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