[PATCH] composite: Don't bother copying the pixmap for ForgetGravity windows (v3)

Jasper St. Pierre jstpierre at mecheye.net
Wed Nov 18 15:06:55 PST 2015


If a window has ForgetGravity in its bitGravity, that very likely
means it will repaint on the ConfigureNotify / Expose event, and thus
we don't have to copy the old pixmap into the new pixmap, we can simply
leave it blank.

Preventing this copy is super simple to do and a big win on small
devices where these blits can be expensive.

A better approach would be to actually obey BitGravity correctly rather
than assume NorthWestGravity always, but this is a big speedup for the
common case.

v2: Check all subwindows to make sure they are also ForgetGravity
v3: Destroy old pixmap before creating the new one

Cc: Adam Jackson <ajax at redhat.com>
Signed-off-by: Jasper St. Pierre <jstpierre at mecheye.net>
---
 composite/compalloc.c | 113 ++++++++++++++++++++++++++++++--------------------
 1 file changed, 67 insertions(+), 46 deletions(-)

diff --git a/composite/compalloc.c b/composite/compalloc.c
index 8daded0..06b54e9 100644
--- a/composite/compalloc.c
+++ b/composite/compalloc.c
@@ -526,6 +526,21 @@ compUnredirectOneSubwindow(WindowPtr pParent, WindowPtr pWin)
     return Success;
 }
 
+static Bool
+needsPixmapCopy(WindowPtr pWin)
+{
+    WindowPtr pChild;
+
+    if (pWin->bitGravity != ForgetGravity)
+        return TRUE;
+
+    for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
+        if (needsPixmapCopy(pChild))
+            return TRUE;
+
+    return FALSE;
+}
+
 static PixmapPtr
 compNewPixmap(WindowPtr pWin, int x, int y, int w, int h)
 {
@@ -542,54 +557,56 @@ compNewPixmap(WindowPtr pWin, int x, int y, int w, int h)
     pPixmap->screen_x = x;
     pPixmap->screen_y = y;
 
-    if (pParent->drawable.depth == pWin->drawable.depth) {
-        GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen);
-
-        if (pGC) {
-            ChangeGCVal val;
-
-            val.val = IncludeInferiors;
-            ChangeGC(NullClient, pGC, GCSubwindowMode, &val);
-            ValidateGC(&pPixmap->drawable, pGC);
-            (*pGC->ops->CopyArea) (&pParent->drawable,
-                                   &pPixmap->drawable,
-                                   pGC,
-                                   x - pParent->drawable.x,
-                                   y - pParent->drawable.y, w, h, 0, 0);
-            FreeScratchGC(pGC);
+    if (needsPixmapCopy(pWin)) {
+        if (pParent->drawable.depth == pWin->drawable.depth) {
+            GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen);
+
+            if (pGC) {
+                ChangeGCVal val;
+
+                val.val = IncludeInferiors;
+                ChangeGC(NullClient, pGC, GCSubwindowMode, &val);
+                ValidateGC(&pPixmap->drawable, pGC);
+                (*pGC->ops->CopyArea) (&pParent->drawable,
+                                       &pPixmap->drawable,
+                                       pGC,
+                                       x - pParent->drawable.x,
+                                       y - pParent->drawable.y, w, h, 0, 0);
+                FreeScratchGC(pGC);
+            }
         }
-    }
-    else {
-        PictFormatPtr pSrcFormat = PictureWindowFormat(pParent);
-        PictFormatPtr pDstFormat = PictureWindowFormat(pWin);
-        XID inferiors = IncludeInferiors;
-        int error;
-
-        PicturePtr pSrcPicture = CreatePicture(None,
-                                               &pParent->drawable,
-                                               pSrcFormat,
-                                               CPSubwindowMode,
-                                               &inferiors,
-                                               serverClient, &error);
-
-        PicturePtr pDstPicture = CreatePicture(None,
-                                               &pPixmap->drawable,
-                                               pDstFormat,
-                                               0, 0,
-                                               serverClient, &error);
-
-        if (pSrcPicture && pDstPicture) {
-            CompositePicture(PictOpSrc,
-                             pSrcPicture,
-                             NULL,
-                             pDstPicture,
-                             x - pParent->drawable.x,
-                             y - pParent->drawable.y, 0, 0, 0, 0, w, h);
+        else {
+            PictFormatPtr pSrcFormat = PictureWindowFormat(pParent);
+            PictFormatPtr pDstFormat = PictureWindowFormat(pWin);
+            XID inferiors = IncludeInferiors;
+            int error;
+
+            PicturePtr pSrcPicture = CreatePicture(None,
+                                                   &pParent->drawable,
+                                                   pSrcFormat,
+                                                   CPSubwindowMode,
+                                                   &inferiors,
+                                                   serverClient, &error);
+
+            PicturePtr pDstPicture = CreatePicture(None,
+                                                   &pPixmap->drawable,
+                                                   pDstFormat,
+                                                   0, 0,
+                                                   serverClient, &error);
+
+            if (pSrcPicture && pDstPicture) {
+                CompositePicture(PictOpSrc,
+                                 pSrcPicture,
+                                 NULL,
+                                 pDstPicture,
+                                 x - pParent->drawable.x,
+                                 y - pParent->drawable.y, 0, 0, 0, 0, w, h);
+            }
+            if (pSrcPicture)
+                FreePicture(pSrcPicture, 0);
+            if (pDstPicture)
+                FreePicture(pDstPicture, 0);
         }
-        if (pSrcPicture)
-            FreePicture(pSrcPicture, 0);
-        if (pDstPicture)
-            FreePicture(pDstPicture, 0);
     }
     return pPixmap;
 }
@@ -678,6 +695,10 @@ compReallocPixmap(WindowPtr pWin, int draw_x, int draw_y,
     pix_w = w + (bw << 1);
     pix_h = h + (bw << 1);
     if (pix_w != pOld->drawable.width || pix_h != pOld->drawable.height) {
+        if (!needsPixmapCopy(pWin)) {
+            pScreen->DestroyPixmap(pOld);
+            pOld = None;
+        }
         pNew = compNewPixmap(pWin, pix_x, pix_y, pix_w, pix_h);
         if (!pNew)
             return FALSE;
-- 
2.4.3



More information about the xorg-devel mailing list