[PATCH] Xext: XCopyArea() does not work in Xinerama. Bug#:25113

arvind Umrao Arvind.Umrao at Sun.COM
Thu Dec 3 22:46:03 PST 2009


Let me try my luck again and see if somebody can review my patch.

-Arvind

Arvind Umrao wrote:
> Again request for review of patch attached in this email.
>
> -Arvind
>
> arvind Umrao wrote:
>>
>>
>> From 15b4f89262bd77657d4159e029eab4c599ae0abc Mon Sep 17 00:00:00 2001
>> From: Arvind Umrao <arvind.umrao at sun.com>
>> Date: Mon, 16 Nov 2009 16:49:44 +0530
>> Subject: [PATCH] Xext: XCopyArea() does not work in Xinerama. Bug#:25113
>>
>>
>> XCopyArea() does not work in Xinerama mode. XCopyArea() does not copy 
>> areas of the screen between physical displays.
>>
>> Description of the change:
>> This bug was first reported for Xsun. Two months back I have fixed 
>> Xsun,in Nevada. Xserver team in SUN reviewed my code changes.
>>
>> Xcopy does not work, when we xcopy image from one screen to other in 
>> Xinerama mode. The solution to the problem is use internal xcopy  
>> instead of regular xcopy. Lines of code I have added is to detect if 
>> copied image( destination coordinate) not lies in same  screen of 
>> source image, then call internal xcopy instead of regular xcopy.
>> *1) Internal Xcopy*
>> In Internal Xcopy  temporary buffer is allocated and Xineramadata is 
>> copied .  Size of temporary buffer is same as drawing object(stuff). 
>> GetImage reads the image(Xineramadata) from all intersection boxes. 
>> When image overlaps between two or more screens, we can visualize 
>> portion of image in intersection boxes.
>>
>> *2) Regular xcopy*
>> *Regular xcopy calls the regular copyimage. Regular copyimage will be 
>> much faster, because it does not call  getimage or putimage.*
>>
>>
>> My code changes are well commented.
>>
>> *Testing*
>> a)I have tested my fixes using two XVR2500 frame buffer on SPARC 
>> Ultra 45 with Xinerama on.
>> b)Also I have tested my fixes on Sunray with Xinerama on.
>>
>>
>> X.Org Bug 25113 <http://bugs.freedesktop.org/show_bug.cgi?id=25113>
>>
>>
>> Signed-off-by: Arvind Umrao <arvind.umrao at sun.com>
>> ---
>> Xext/panoramiXprocs.c |  354 
>> +++++++++++++++++++++++++++++++++++++++++++++++++
>> 1 files changed, 354 insertions(+), 0 deletions(-)
>>
>> diff --git a/Xext/panoramiXprocs.c b/Xext/panoramiXprocs.c
>> index 6834efb..7011356 100644
>> --- a/Xext/panoramiXprocs.c
>> +++ b/Xext/panoramiXprocs.c
>> @@ -59,6 +59,144 @@ Equipment Corporation.
>>  */
>> extern XID clientErrorValue;   /* XXX this is a kludge */
>>
>> +/*
>> + * calculate the overlap area of image when image overlaps two 
>> screens of Xinerama
>> + *
>> + * getRgn is used by PanoramiXCopyArea
>> + *
>> + */
>> +
>> +RegionPtr getRgn(DrawablePtr pSrcDrawable,DrawablePtr pDstDrawable,
>> +                  GCPtr pGC,int srcx,int srcy,int width,int 
>> height,int dstx,int dsty)
>> +{
>> +    register ScreenPtr pscr = pGC->pScreen;
>> +    RegionPtr prgnSrcClip;      /* drawable-relative source clip */
>> +    RegionRec rgnSrcRec;
>> +    RegionPtr prgnDstClip;      /* drawable-relative dest clip */
>> +    RegionRec rgnDstRec;
>> +    BoxRec srcBox;              /* unclipped source */
>> +    RegionRec rgnExposed;       /* exposed region, calculated source-
>> +                                   relative, made dst relative to
>> +                                   intersect with visible parts of
>> +                                   dest and send events to client,
>> +                                   and then screen relative to paint
>> +                                   the window background
>> +                                */
>> +    WindowPtr pSrcWin;
>> +    BoxRec expBox;
>> +    Bool extents;
>> +
>> +    /* avoid work if we can */
>> +    if (!pGC->graphicsExposures &&
>> +        (pDstDrawable->type == DRAWABLE_PIXMAP) &&
>> +        ((pSrcDrawable->type == DRAWABLE_PIXMAP) ||
>> +         (((WindowPtr)pSrcDrawable)->backStorage == NULL)))
>> +        return NULL;
>> +
>> +    srcBox.x1 = srcx;
>> +    srcBox.y1 = srcy;
>> +    srcBox.x2 = srcx+width;
>> +    srcBox.y2 = srcy+height;
>> +
>> +    if (pSrcDrawable->type != DRAWABLE_PIXMAP)
>> +    {
>> +        BoxRec TsrcBox;
>> +
>> +        TsrcBox.x1 = srcx + pSrcDrawable->x;
>> +        TsrcBox.y1 = srcy + pSrcDrawable->y;
>> +        TsrcBox.x2 = TsrcBox.x1 + width;
>> +        TsrcBox.y2 = TsrcBox.y1 + height;
>> +        pSrcWin = (WindowPtr) pSrcDrawable;
>> +        if (pGC->subWindowMode == IncludeInferiors)
>> +        {
>> +            prgnSrcClip = NotClippedByChildren (pSrcWin);
>> +            if ((RECT_IN_REGION(pscr, prgnSrcClip, &TsrcBox)) == rgnIN)
>> +            {
>> +                REGION_DESTROY(pscr, prgnSrcClip);
>> +                return NULL;
>> +            }
>> +        }
>> +        else
>> +        {
>> +            if ((RECT_IN_REGION(pscr, &pSrcWin->clipList, &TsrcBox)) 
>> == rgnIN)
>> +                return NULL;
>> +            prgnSrcClip = &rgnSrcRec;
>> +            REGION_INIT(pscr, prgnSrcClip, NullBox, 0);
>> +            REGION_COPY(pscr, prgnSrcClip, &pSrcWin->clipList);
>> +        }
>> +        REGION_TRANSLATE(pscr, prgnSrcClip,
>> +                                -pSrcDrawable->x, -pSrcDrawable->y);
>> +    }
>> +    else
>> +    {
>> +        BoxRec  box;
>> +
>> +        if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) &&
>> +            (srcBox.x2 <= pSrcDrawable->width) &&
>> +            (srcBox.y2 <= pSrcDrawable->height))
>> +            return NULL;
>> +
>> +        box.x1 = 0;
>> +        box.y1 = 0;
>> +        box.x2 = pSrcDrawable->width;
>> +        box.y2 = pSrcDrawable->height;
>> +        prgnSrcClip = &rgnSrcRec;
>> +        REGION_INIT(pscr, prgnSrcClip, &box, 1);
>> +        pSrcWin = (WindowPtr)NULL;
>> +    }
>> +
>> +    if (pDstDrawable == pSrcDrawable)
>> +    {
>> +        prgnDstClip = prgnSrcClip;
>> +    }
>> +    else if (pDstDrawable->type != DRAWABLE_PIXMAP)
>> +    {
>> +        if (pGC->subWindowMode == IncludeInferiors)
>> +        {
>> +            prgnDstClip = 
>> NotClippedByChildren((WindowPtr)pDstDrawable);
>> +        }
>> +        else
>> +        {
>> +            prgnDstClip = &rgnDstRec;
>> +            REGION_INIT(pscr, prgnDstClip, NullBox, 0);
>> +            REGION_COPY(pscr, prgnDstClip,
>> +                                &((WindowPtr)pDstDrawable)->clipList);
>> +        }
>> +        REGION_TRANSLATE(pscr, prgnDstClip,
>> +                                 -pDstDrawable->x, -pDstDrawable->y);
>> +    }
>> +    else
>> +    {
>> +        BoxRec  box;
>> +
>> +        box.x1 = 0;
>> +        box.y1 = 0;
>> +        box.x2 = pDstDrawable->width;
>> +        box.y2 = pDstDrawable->height;
>> +        prgnDstClip = &rgnDstRec;
>> +        REGION_INIT(pscr, prgnDstClip, &box, 1);
>> +    }
>> +
>> +    /* drawable-relative source region */
>> +    REGION_INIT(pscr, &rgnExposed, &srcBox, 1);
>> +
>> +    /* now get the hidden parts of the source box*/
>> +    REGION_SUBTRACT(pscr, &rgnExposed, &rgnExposed, prgnSrcClip);
>> +    /* move them over the destination */
>> +    REGION_TRANSLATE(pscr, &rgnExposed, dstx-srcx, dsty-srcy);
>> +
>> +    /* intersect with visible areas of dest */
>> +    REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, prgnDstClip);
>> +
>> +    {
>> +        /* don't look */
>> +        RegionPtr exposed = REGION_CREATE(pscr, NullBox, 0);
>> +        *exposed = rgnExposed;
>> +        return exposed;
>> +    }
>> +}
>> +
>> +
>> int PanoramiXCreateWindow(ClientPtr client)
>> {
>>     PanoramiXRes *parent, *newWin;
>> @@ -1090,6 +1228,222 @@ int PanoramiXCopyArea(ClientPtr client)
>>     xfree(data);
>>
>>     result = Success;
>> +    } else if (src->type == XRT_WINDOW){
>> +
>> +        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;
>> +    int cross_screen = 0, rsrcFlag = 0;
>> +    int rsrcx = 0, rsrcy = 0, rsrcx2 = stuff->width, rsrcy2 = 
>> stuff->height;
>> +
>> +        bzero(pRgn, sizeof(RegionPtr) * MAXSCREENS);
>> +
>> +    /*
>> +         * Lines of code I have added is to detect if copied image( 
>> destination coordinate)
>> +         * not lies in same  screen of source image, then call 
>> internal xcopy instead of regular xcopy.
>> +         * There are two cases only when destination image will not 
>> lie in same sceen.
>> +         * a) right and bottom coordinates of copied image( 
>> destination coordinate) crosses the other screen.
>> +         * b) top and left coordinates of copied image( destination 
>> coordinate)  cross the other screen.
>> +        */
>> +        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++;
>> +                }
>> +        }
>> +
>> +    /* if not cross screens, don't even bother calculatnge the 
>> overlap */
>> +    if(cross_screen > 1) {
>> +          RegionRec overlap, imageReg;
>> +          BoxRec imageBox;
>> +      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 - panoramiXdataPtr[j].x;
>> +                stuff->srcY = srcy - panoramiXdataPtr[j].y;
>> +            }
>> +            if (dstIsRoot) {
>> +                stuff->dstX = dstx - panoramiXdataPtr[j].x;
>> +                stuff->dstY = dsty - panoramiXdataPtr[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;
>> +
>> +           /*  calculate the overlap area first and get the
>> +       image of the overlap area only */
>> +            pRgn[j] = getRgn(pSrc, pDst, pGC,
>> +                                stuff->srcX, stuff->srcY,
>> +                                stuff->width, stuff->height,
>> +                                stuff->dstX, stuff->dstY);
>> +            if(pRgn[j] && REGION_NOTEMPTY(pDst->pScreen, pRgn[j])) {
>> +                imageBox.x1 = dstx;
>> +                imageBox.y1 = dsty;
>> +                imageBox.x2 = dstx + stuff->width;
>> +                imageBox.y2 = dsty + stuff->height;
>> +
>> +                REGION_INIT(pDst->pScreen, &imageReg, &imageBox, 1);
>> +                REGION_INIT(pDst->pScreen, &overlap, NullBox, 1);
>> +                REGION_INTERSECT(pDst->pScreen, &overlap, &imageReg, 
>> pRgn[j]);
>> +
>> +                if (REGION_NOTEMPTY(pDst->pScreen, &overlap)) {
>> +            int i;
>> +            if(!rsrcFlag) {
>> +            rsrcx = rsrcy = 100000;
>> +            rsrcx2 = rsrcy2 = 0;
>> +            rsrcFlag = 1;
>> +            }
>> +            for (i = 0; i < REGION_NUM_RECTS(&overlap); i++) {
>> +                        BoxPtr rects = REGION_RECTS(&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;
>> +                    }
>> +
>> +                    REGION_UNINIT(pDst->pScreen, &overlap);
>> +                    REGION_UNINIT(pDst->pScreen, &imageReg);
>> +              }
>> +            }
>> +      }
>> +      pitch = PixmapBytePad(stuff->width, drawables[0]->depth);
>> +      data_size = stuff->height * pitch;
>> +      if(!(data =  xcalloc(1,data_size)))
>> +            return BadAlloc;
>> +
>> +        /*  In Internal Xcopy  temporary buffer is allocattated and 
>> Xineramadata is copied .
>> +         *  Size of temporary buffer is same as drawing object(stuff).
>> +         *  GetImage reads the image(Xineramadata) from all 
>> intersection boxes.
>> +         *  When image overlaps between two or more screens, we can 
>> visualize 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 - panoramiXdataPtr[j].x;
>> +        stuff->srcY = srcy - panoramiXdataPtr[j].y;
>> +        }
>> +            if (dstIsRoot){
>> +        stuff->dstX = dstx - panoramiXdataPtr[j].x;
>> +        stuff->dstY = dsty - panoramiXdataPtr[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 (cross_screen > 1 && pRgn[j] && 
>> REGION_NOTEMPTY(pDst->pScreen, pRgn[j])) {
>> +        RegionRec overlap, imageReg;
>> +        BoxRec imageBox;
>> +
>> +        if(drawables[0]->depth != pDst->depth) {
>> +            client->errorValue = stuff->dstDrawable;
>> +                    xfree(data );
>> +            return (BadMatch);
>> +        }
>> +
>> +        imageBox.x1 = dstx;
>> +        imageBox.y1 = dsty;
>> +        imageBox.x2 = dstx + stuff->width;
>> +        imageBox.y2 = dsty + stuff->height;
>> +
>> +        REGION_INIT(pDst->pScreen, &imageReg, &imageBox, 1);
>> +        REGION_INIT(pDst->pScreen, &overlap, NullBox, 1);
>> +        REGION_INTERSECT(pDst->pScreen, &overlap, &imageReg, pRgn[j]);
>> +
>> +        if (REGION_NOTEMPTY(pDst->pScreen, &overlap)) {
>> +            int i;
>> +            PixmapPtr pData;
>> +
>> +                    pData = GetScratchPixmapHeader(pDst->pScreen, 
>> rsrcx2-rsrcx,
>> +                    rsrcy2-rsrcy, pDst->depth, 
>> BitsPerPixel(pDst->depth),
>> +                    PixmapBytePad(rsrcx2-rsrcx, pDst->depth), data);
>> +
>> +            for (i = 0; i < REGION_NUM_RECTS(&overlap); i++) {
>> +            BoxPtr rects = REGION_RECTS(&overlap);
>> +            (*pGC->ops->CopyArea)((DrawablePtr) pData, pDst, pGC,
>> +              rects[i].x1 - dstx - rsrcx,
>> +              rects[i].y1 - dsty - rsrcy,
>> +              rects[i].x2 - rects[i].x1,
>> +              rects[i].y2 - rects[i].y1,
>> +              rects[i].x1, rects[i].y1);
>> +            }
>> +        }
>> +        REGION_UNINIT(pDst->pScreen, &overlap);
>> +        REGION_UNINIT(pDst->pScreen, &imageReg);
>> +        }
>> +    }
>> +
>> +    if(cross_screen > 1)
>> +            xfree(data);
>> +
>> +    result = Success;
>>     } else {
>>     DrawablePtr pDst = NULL, pSrc = NULL;
>>     GCPtr pGC = NULL;
>

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: 0001-Subject-PATCH-Xext-XCopyArea-does-not-work-in.patch
Url: http://lists.x.org/archives/xorg-devel/attachments/20091204/ad8b8c37/attachment.ksh 


More information about the xorg-devel mailing list