[PATCH] xinerama: Implement graphics exposures for window->pixmap copies

Adam Jackson ajax at redhat.com
Wed Sep 24 14:43:27 PDT 2014


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.

This special case for window->pixmap copies (and corresponding lack of
graphics exposures) appears to date back to cvs revision 3.15 of this
file in xfree86, which makes it almost exactly fifteen years old.  It's
possible that we could do better now, since Composite would mean that
for redirected windows we would in fact have consistent window contents
on every screen.  Would be slightly ugly to have Xinerama know about
Composite at the dispatch level, but then this is Xinerama we're talking
about, nothing's pretty here.

Signed-off-by: Adam Jackson <ajax at redhat.com>
---
 Xext/panoramiXprocs.c | 63 +++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 53 insertions(+), 10 deletions(-)

diff --git a/Xext/panoramiXprocs.c b/Xext/panoramiXprocs.c
index 83a2e08..fdf68a7 100644
--- a/Xext/panoramiXprocs.c
+++ b/Xext/panoramiXprocs.c
@@ -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;
@@ -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;
@@ -1105,13 +1107,12 @@ PanoramiXCopyArea(ClientPtr client)
                 return rc;
         }
 
-        pitch = PixmapBytePad(stuff->width, drawables[0]->depth);
-        if (!(data = calloc(1, stuff->height * pitch)))
+        pitch = PixmapBytePad(width, drawables[0]->depth);
+        if (!(data = calloc(1, 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;
@@ -1123,14 +1124,56 @@ 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;
+
+            /* create region for source box */
+            BoxRec sourceBox = { srcx, srcy, srcx + width, srcy + height };
+            RegionInit(&rgn, &sourceBox, 1);
+
+            dx = drawables[0]->x;
+            dy = drawables[0]->y;
+            if (srcIsRoot) {
+                dx += screenInfo.screens[0]->x;
+                dy += screenInfo.screens[0]->y;
+            }
+
+            /* translate from source-relative to screen */
+            RegionTranslate(&rgn, dx, dy);
+
+            /* subtract the (screen-space) clips of the source drawables */
+            FOR_NSCREENS(j) {
+                RegionPtr sd;
+
+                if (pGC->subWindowMode == IncludeInferiors)
+                    sd = NotClippedByChildren((WindowPtr)drawables[j]);
+                else
+                    sd = &((WindowPtr)drawables[j])->clipList;
+
+                RegionSubtract(&rgn, &rgn, sd);
+
+                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 */
+            pGC->pScreen->SendGraphicsExpose(client, &rgn, dst->info[0].id,
+                                             X_CopyArea, 0);
+            RegionUninit(&rgn);
+        }
     }
     else {
         DrawablePtr pDst = NULL, pSrc = NULL;
-- 
1.9.3



More information about the xorg-devel mailing list