Skip to content

Commit

Permalink
xinerama: Implement graphics exposures for window->pixmap copies (v4)
Browse files Browse the repository at this point in the history
This code is using GetImage to accumulate a logical view of the window
image (since the windows will be clipped to their containing screen),
and then PutImage to load that back into the pixmap.  What it wasn't
doing was constructing a region for the obscured areas of the window and
emitting graphics exposures for same.

v2: Fix coordinate translation when the source is the root window
v3: Create sourceBox with the right coordinates initially instead of
translating (Keith Packard)
v4: Clamp the region to 15 bits to avoid overflow (Keith Packard)

Signed-off-by: Adam Jackson <ajax@redhat.com>
  • Loading branch information
nwnk committed Mar 15, 2017
1 parent f1f865e commit e337de2
Showing 1 changed file with 60 additions and 10 deletions.
70 changes: 60 additions & 10 deletions Xext/panoramiXprocs.c
Expand Up @@ -1050,7 +1050,7 @@ PanoramiXClearToBackground(ClientPtr client)
int
PanoramiXCopyArea(ClientPtr client)
{
int j, result, srcx, srcy, dstx, dsty;
int j, result, srcx, srcy, dstx, dsty, width, height;
PanoramiXRes *gc, *src, *dst;
Bool srcIsRoot = FALSE;
Bool dstIsRoot = FALSE;
Expand Down Expand Up @@ -1091,6 +1091,8 @@ PanoramiXCopyArea(ClientPtr client)
srcy = stuff->srcY;
dstx = stuff->dstX;
dsty = stuff->dstY;
width = stuff->width;
height = stuff->height;
if ((dst->type == XRT_PIXMAP) && (src->type == XRT_WINDOW)) {
DrawablePtr drawables[MAXSCREENS];
DrawablePtr pDst;
Expand All @@ -1105,13 +1107,12 @@ PanoramiXCopyArea(ClientPtr client)
return rc;
}

pitch = PixmapBytePad(stuff->width, drawables[0]->depth);
if (!(data = calloc(stuff->height, pitch)))
pitch = PixmapBytePad(width, drawables[0]->depth);
if (!(data = calloc(height, pitch)))
return BadAlloc;

XineramaGetImageData(drawables, srcx, srcy,
stuff->width, stuff->height, ZPixmap, ~0, data,
pitch, srcIsRoot);
XineramaGetImageData(drawables, srcx, srcy, width, height, ZPixmap, ~0,
data, pitch, srcIsRoot);

FOR_NSCREENS_BACKWARD(j) {
stuff->gc = gc->info[j].id;
Expand All @@ -1123,14 +1124,63 @@ PanoramiXCopyArea(ClientPtr client)
}

(*pGC->ops->PutImage) (pDst, pGC, pDst->depth, dstx, dsty,
stuff->width, stuff->height,
0, ZPixmap, data);

width, height, 0, ZPixmap, data);
if (dstShared)
break;
}

free(data);

if (pGC->graphicsExposures) {
RegionRec rgn;
int dx, dy;
BoxRec sourceBox;

dx = drawables[0]->x;
dy = drawables[0]->y;
if (srcIsRoot) {
dx += screenInfo.screens[0]->x;
dy += screenInfo.screens[0]->y;
}

sourceBox.x1 = min(srcx + dx, 0);
sourceBox.y1 = min(srcy + dy, 0);
sourceBox.x2 = max(sourceBox.x1 + width, 32767);
sourceBox.y2 = max(sourceBox.y1 + height, 32767);

RegionInit(&rgn, &sourceBox, 1);

/* subtract the (screen-space) clips of the source drawables */
FOR_NSCREENS(j) {
ScreenPtr screen = screenInfo.screens[j];
RegionPtr sd;

if (pGC->subWindowMode == IncludeInferiors)
sd = NotClippedByChildren((WindowPtr)drawables[j]);
else
sd = &((WindowPtr)drawables[j])->clipList;

if (srcIsRoot)
RegionTranslate(&rgn, -screen->x, -screen->y);

RegionSubtract(&rgn, &rgn, sd);

if (srcIsRoot)
RegionTranslate(&rgn, screen->x, screen->y);

if (pGC->subWindowMode == IncludeInferiors)
RegionDestroy(sd);
}

/* -dx/-dy to get back to dest-relative, plus request offsets */
RegionTranslate(&rgn, -dx + dstx, -dy + dsty);

/* intersect with gc clip; just one screen is fine because pixmap */
RegionIntersect(&rgn, &rgn, pGC->pCompositeClip);

/* and expose */
SendGraphicsExpose(client, &rgn, dst->info[0].id, X_CopyArea, 0);
RegionUninit(&rgn);
}
}
else {
DrawablePtr pDst = NULL, pSrc = NULL;
Expand Down

0 comments on commit e337de2

Please sign in to comment.