Please remove the 2011BRB_Reviewed tag from the commit log.  That's just a 
bugzilla whitespace keyword that I've been adding to bugs as I've been 
reviewing the bugs.  I use it to keep track of what I've screened and what I 
haven't, and it should have no bearing on the actual commit.

On Nov 10, 2011, at 7:35 AM, Arvind Umrao wrote:

> The following changes since commit 072ff17136b7c2d795d261870025c3061886b4c8:
> 
>  Xext: XCopyArea does not work in Xinerama mode.#25113 (2011-11-10 20:47:50 
> +0530)
> 
> are available in the git repository at:
>  git://github.com/akumrao/xserver.git master
> 
> Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=25113
> 
> XCopyArea() does not work in Xinerama mode. XCopyArea does not copy areas of 
> the screen across physical displays. XcopyArea works fine when source and 
> destination image are in same screen, but Xcopy does not work, when we Xcopy 
> image from one screen to the other in Xinerama mode. The solution is to use 
> internal Xcopy  instead of regular Xcopy. I mean use GetImage & PutImage 
> Instead of regular Xcopy.
> 
> *1) Internal Xcopy*
> In Internal Xcopy temporary buffer is allocated and Xineramadata is copied. 
> GetImage reads the image(Xineramadata) from all intersection boxes and 
> Putimage copies the image to the screen.
> 
> *2) Regular xcopy*
> Regular xcopy calls the regular copyimage. Regular copyimage will be much 
> faster when hardware acceleration is on.
> 
> Code changes are well commented. Code changes will execute only when xinerama 
> is on and xcopy happens across screen. This bug was first reported for Xsun. 
> Two years back, code changes was reviewed and intergrated to Oracle/Sun local 
> Xserer repository.
> 
> *Testing*
> a)I have tested it with Nvidia Quadro FX 1700 on x86 machine.You can find the 
> test case in bugzilla. If you wish I can email some more test cases for 
> stress testing.
> b)I have tested my fixes using two XVR2500 frame buffer on SPARC Ultra 45 
> with Xinerama on. You can find the test case in bugzilla. If you wish I can 
> email some more test cases, for stress testing.
> c)Also I have tested my fixes on Sunray with Xinerama on
> 
> Reviewed-by: Dave Airlie <airl...@redhat.com>
> 2011BRB_Reviewed: Jeremy Huddleston <jerem...@freedesktop.org>
> Signed-off-by: Arvind Umrao <arvind.um...@oracle.com>
> ---
> Xext/panoramiXprocs.c |  215 +++++++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 215 insertions(+), 0 deletions(-)
> 
> diff --git a/Xext/panoramiXprocs.c b/Xext/panoramiXprocs.c
> index 9ea4611..f8296e4 100644
> --- a/Xext/panoramiXprocs.c
> +++ b/Xext/panoramiXprocs.c
> @@ -1074,6 +1074,221 @@ int PanoramiXCopyArea(ClientPtr client)
>       }
> 
>       free(data);
> +} else if (src->type == XRT_WINDOW) {
> +        /*
> +         * If destination image coordinate not lie in same screen of
> +         * source image, then call Internal Copy instead of regular
> +         * XCopy. I mean use GetImage & PutImage, instead of regular XCopy
> +         */
> +        DrawablePtr pDst = NULL, pSrc = NULL;
> +        GCPtr pGC = NULL;
> +        RegionPtr pRgn[MAXSCREENS];
> +        int rc;
> +        DrawablePtr drawables[MAXSCREENS];
> +        char *data = NULL;
> +        size_t data_size;
> +        int pitch;
> +        RegionRec overlap, imageReg;
> +        BoxRec imageBox;
> +        int cross_screen = 0, rsrcFlag = 0;
> +        int rsrcx = 0, rsrcy = 0, rsrcx2 = stuff->width, rsrcy2 = 
> stuff->height;
> +
> +        memset(pRgn, 0, sizeof(RegionPtr) * MAXSCREENS);
> +
> +        /*
> +         * Execute only when Xinerama is on and having two or more screens.
> +         * Two cases when source and dest. image will not lie in same screen.
> +         * a) Right and bottom coordinates of destination image crosses the
> +         * other screen.
> +         * b) Top and left coordinates of destination image cross the other
> +         * screen.
> +         * Also check coordinates validity. Source and destination should
> +         * not be same.
> +         */
> +        if (PanoramiXNumScreens > 1)
> +            FOR_NSCREENS_BACKWARD(j) {
> +            rc = dixLookupDrawable(drawables + j, src->info[j].id, client, 0,
> +                    DixGetAttrAccess);
> +            if (rc != Success)
> +                return rc;
> +            if (!((drawables[j]->width + drawables[j]->x) < 0 ||
> +                    (drawables[j]->height + drawables[j]->y) < 0 ||
> +                    ((stuff->srcX + drawables[j]->x + stuff->width) < 0 &&
> +                    (stuff->dstX + drawables[j]->x + stuff->width) < 0) ||
> +                    ((stuff->srcY + drawables[j]->y + stuff->height) < 0 &&
> +                    (stuff->dstY + drawables[j]->y + stuff->height) < 0) ||
> +                    ((drawables[j]->x + stuff->srcX) > 
> drawables[j]->pScreen->width &&
> +                    (drawables[j]->x + stuff->dstX) > 
> drawables[j]->pScreen->width) ||
> +                    ((drawables[j]->y + stuff->srcY) > 
> drawables[j]->pScreen->height &&
> +                    (drawables[j]->y + stuff->dstY) > 
> drawables[j]->pScreen->height))) {
> +                if (!(stuff->srcX == stuff->dstX && (stuff->srcY + 
> drawables[j]->y) > 0 &&
> +                        (stuff->srcY + drawables[j]->y + stuff->height) < 
> drawables[j]->pScreen->height) &&
> +                        !(stuff->srcY == stuff->dstY && (stuff->srcX + 
> drawables[j]->x) > 0 &&
> +                        (stuff->srcX + drawables[j]->x + stuff->width) < 
> drawables[j]->pScreen->width))
> +                    cross_screen++;
> +            }
> +        }
> +        /*
> +         * cross_screen > 1, signifies that there are more than one screens 
> and
> +         * source and destination image are not in the same screen.
> +         */
> +
> +        FOR_NSCREENS_BACKWARD(j) {
> +            stuff->dstDrawable = dst->info[j].id;
> +            stuff->srcDrawable = src->info[j].id;
> +            stuff->gc = gc->info[j].id;
> +            if (srcIsRoot) {
> +                stuff->srcX = srcx - screenInfo.screens[j]->x;
> +                stuff->srcY = srcy - screenInfo.screens[j]->y;
> +            }
> +            if (dstIsRoot) {
> +                stuff->dstX = dstx - screenInfo.screens[j]->x;
> +                stuff->dstY = dsty - screenInfo.screens[j]->y;
> +            }
> +
> +            VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, 
> DixWriteAccess);
> +
> +            if (stuff->dstDrawable != stuff->srcDrawable) {
> +                rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0,
> +                        DixReadAccess);
> +                if (rc != Success)
> +                    return rc;
> +
> +                if ((pDst->pScreen != pSrc->pScreen) ||
> +                        (pDst->depth != pSrc->depth)) {
> +                    client->errorValue = stuff->dstDrawable;
> +                    return (BadMatch);
> +                }
> +            } else
> +                pSrc = pDst;
> +
> +            pRgn[j] = (*pGC->ops->CopyArea)(pSrc, pDst, pGC,
> +                    stuff->srcX, stuff->srcY,
> +                    stuff->width, stuff->height,
> +                    stuff->dstX, stuff->dstY);
> +            /*
> +             * If source and destination are not in same screen, instead of
> +             * regular copy, use GetImage and PutImage
> +             */
> +
> +            if (cross_screen > 1 && pRgn[j] && RegionNotEmpty(pRgn[j])) {
> +                imageBox.x1 = stuff->srcX > 0 ? dstx : dstx - stuff->srcX;
> +                imageBox.y1 = stuff->srcY > 0 ? dsty : dsty - stuff->srcY;
> +                if (stuff->srcX + stuff->width > drawables[j]->width)
> +                    imageBox.x2 = dstx - stuff->srcX + drawables[j]->width;
> +                else
> +                    imageBox.x2 = dstx + stuff->width;
> +                if (stuff->srcY + stuff->height > drawables[j]->height)
> +                    imageBox.y2 = dsty - stuff->srcY + drawables[j]->height;
> +                else
> +                    imageBox.y2 = dsty + stuff->height;
> +
> +                RegionInit(&imageReg, &imageBox, 1);
> +                RegionInit(&overlap, NullBox, 1);
> +                RegionIntersect(&overlap, &imageReg, pRgn[j]);
> +
> +                /* First initialize rsrcx & rsrcy to some very big number, 
> impossible screen width.
> +                 * There could be case when source image overlaps with two 
> or more screens of Xinerama.
> +                 * So calculates the area of overlapping source image.
> +                 * RegionNumRects will return number of xinerama screens 
> when source image overlaps and
> +                 * returns one when there is no overlap. Suppose 
> screen1(0,0,100,100), screen2(100,0,200,100)
> +                 * & source image(80,0,130,50) then rsrcx2-rsrcx is 20 for 
> screen1 and 30 for screen2.
> +                 */
> +                if (RegionNotEmpty(&overlap)) {
> +                    int i;
> +                    if (!rsrcFlag) {
> +                        rsrcx = rsrcy = MAXINT;
> +                        rsrcx2 = rsrcy2 = 0;
> +                        rsrcFlag = 1;
> +                    }
> +
> +                    for (i = 0; i < RegionNumRects(&overlap); i++) {
> +                        BoxPtr rects = RegionRects(&overlap);
> +                        if (rsrcx > (rects[i].x1 - dstx))
> +                            rsrcx = rects[i].x1 - dstx;
> +                        if (rsrcy > (rects[i].y1 - dsty))
> +                            rsrcy = rects[i].y1 - dsty;
> +                        if (rsrcx2 < (rects[i].x2 - dstx))
> +                            rsrcx2 = rects[i].x2 - dstx;
> +                        if (rsrcy2 < (rects[i].y2 - dsty))
> +                            rsrcy2 = rects[i].y2 - dsty;
> +                    }
> +
> +                    RegionUninit(&overlap);
> +                    RegionUninit(&imageReg);
> +                }
> +            }
> +        }
> +
> +        if (cross_screen > 1) {
> +            pitch = PixmapBytePad(stuff->width, drawables[0]->depth);
> +            data_size = stuff->height * pitch;
> +            if (!(data = calloc(1, data_size)))
> +                return BadAlloc;
> +
> +            /* Data which is not copied by regular XCopy, for that temporary
> +             * buffer is allocatted and Xinerama data is copied. GetImage 
> reads
> +             * the image(Xineramadata) from all the intersection boxes.
> +             * When image overlaps between two or more screens, we can 
> visualize
> +             * the portion of image in intersection boxes.
> +             */
> +
> +            XineramaGetImageData(drawables, srcx + rsrcx, srcy + rsrcy,
> +                    rsrcx2 - rsrcx, rsrcy2 - rsrcy, ZPixmap,
> +                    ~0, data, pitch, srcIsRoot);
> +
> +            FOR_NSCREENS_BACKWARD(j) {
> +                stuff->dstDrawable = dst->info[j].id;
> +                stuff->srcDrawable = src->info[j].id;
> +                stuff->gc = gc->info[j].id;
> +                if (srcIsRoot) {
> +                    stuff->srcX = srcx - screenInfo.screens[j]->x;
> +                    stuff->srcY = srcy - screenInfo.screens[j]->y;
> +                }
> +                if (dstIsRoot) {
> +                    stuff->dstX = dstx - screenInfo.screens[j]->x;
> +                    stuff->dstY = dsty - screenInfo.screens[j]->y;
> +                }
> +
> +                VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, 
> DixWriteAccess);
> +
> +                if (stuff->dstDrawable != stuff->srcDrawable) {
> +                    rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, 
> client, 0,
> +                            DixReadAccess);
> +                    if (rc != Success) {
> +                        free(data);
> +                        return rc;
> +                    }
> +
> +                    if ((pDst->pScreen != pSrc->pScreen) ||
> +                            (pDst->depth != pSrc->depth)) {
> +                        client->errorValue = stuff->dstDrawable;
> +                        free(data);
> +                        return (BadMatch);
> +                    }
> +                } else
> +                    pSrc = pDst;
> +
> +                if (pRgn[j] && REGION_NOTEMPTY(pDst->pScreen, pRgn[j])) {
> +
> +                    if (drawables[0]->depth != pDst->depth) {
> +                        client->errorValue = stuff->dstDrawable;
> +                        free(data);
> +                        return (BadMatch);
> +                    }
> +
> +                    /*
> +                     * Copy the buffered Xinerama data to screen
> +                     */
> +
> +                    (*pGC->ops->PutImage) (pDst, pGC, pDst->depth, dstx + 
> rsrcx, dsty + rsrcy,
> +                            rsrcx2 - rsrcx, rsrcy2 - rsrcy, 0, ZPixmap, 
> data);
> +                }
> +            }
> +
> +            free(data);
> +        }
> +
>     } else {
>       DrawablePtr pDst = NULL, pSrc = NULL;
>       GCPtr pGC = NULL;
> -- 
> 1.7.3.2
> 
> _______________________________________________
> xorg-devel@lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel
> 



_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to