[PATCH] Bug #25136: Fix a severe performance regression caused by fb reading back the screen.

Aaron Plattner aplattner at nvidia.com
Wed Nov 18 18:53:18 PST 2009


Commit e9aa61e9f0d663d5b34a397b943b4d1df44e873d added code to copy the source
whenever fb is using a window as the source picture, in case the composite tries
to read portions of the window that lie outside its backing pixmap.  However, it
does this all the time and it always reads back the entire window.

KDE sometimes maps a 32-bit 1x1 InputOutput window, which compNewPixmap tries to
fill with a RENDER Composite operation using the root window as a parent.  This
triggers the copy-back described above for the entire contents of the screen.

This copy is not necessary when the window is fully contained within its backing
storage, which is trivially true of the root window.

Signed-off-by: Aaron Plattner <aplattner at nvidia.com>
---
This patch speeds up a simple test app that maps a 1x1 ARGB window from 11
seconds to 0.005 seconds.

This patch needs to be applied after
http://cvs.fedora.redhat.com/viewvc/rpms/xorg-x11-server/F-12/xserver-1.7.1-window-pictures.patch?revision=1.4&view=markup
or the server will still be subject to the corruption and crash bugs that
e9aa61e introduced.

 fb/fbpict.c |   27 ++++++++++++++++++++++++++-
 1 files changed, 26 insertions(+), 1 deletions(-)

diff --git a/fb/fbpict.c b/fb/fbpict.c
index 5c96427..5799e37 100644
--- a/fb/fbpict.c
+++ b/fb/fbpict.c
@@ -317,6 +317,27 @@ destroy_drawable (pixman_image_t *image, void *data)
     pScreen->DestroyPixmap ((PixmapPtr)pDrawable);
 }
 
+/*
+ * Returns TRUE when the specified window is fully contained within its bounding
+ * pixmap.
+ */
+static Bool
+window_is_fully_contained(WindowPtr pWin)
+{
+    PixmapPtr pBoundingPix = (*pWin->drawable.pScreen->GetWindowPixmap)(pWin);
+    int x = pWin->drawable.x, y = pWin->drawable.y;
+
+#ifdef COMPOSITE
+    /* Translate from screen coordinates to pixmap coordinates */
+    x -= pBoundingPix->screen_x;
+    y -= pBoundingPix->screen_y;
+#endif
+
+    return x >= 0 && y >= 0 &&
+	   x + pWin->drawable.width <= pBoundingPix->drawable.width &&
+	   y + pWin->drawable.height <= pBoundingPix->drawable.height;
+}
+
 static pixman_image_t *
 create_bits_picture (PicturePtr pict,
 		     Bool	has_clip,
@@ -328,7 +349,11 @@ create_bits_picture (PicturePtr pict,
     pixman_image_t *image;
     DrawablePtr drawable;
 
-    if (is_src && pict->pDrawable->type == DRAWABLE_WINDOW)
+    /* Copy the source window if part of it lies outside its bounding pixmap to
+     * avoid reading outside that pixmap's bounds, since Pixman doesn't clip the
+     * source image per pixel */
+    if (is_src && pict->pDrawable->type == DRAWABLE_WINDOW &&
+	    !window_is_fully_contained((WindowPtr)pict->pDrawable))
 	drawable = copy_drawable (pict->pDrawable);
     else
 	drawable = pict->pDrawable;
-- 
1.6.3.3



More information about the xorg-devel mailing list