summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-09-20 01:02:39 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2009-09-20 01:15:41 +0100
commit57fc09cef28bad2e3e8455b93ef2927118f8a3a3 (patch)
treeebf8bbf5ead34d112a6a315f81f6405184df8eff
parent33f98e4056706f4c30bb4327677ac49e82058231 (diff)
Avoid fallbacks for a1 src/mask
Carl Worth did the hard work in identifying that the regression in cairo between X.org 1.6 and 1.7 was caused by cairo sending an a1 mask to the server in 1.7 whereas in 1.6 cairo used local fallbacks (as the source was using RepeatPad, which triggers cairo's 'buggy_pad_reflect' fallback for X.org 1.6). This was causing the driver to do a fallback to handle the a1 mask instead, which due to the GPU pipeline stall is much more expensive than the equivalent fallback in cairo. Reference: cairo's performance downgrades 4X with server master than server-1.6. https://bugs.freedesktop.org/show_bug.cgi?id=23184 The fix is a relatively simple extension of the current uxa_picture_from_pixman_image() to use CompositePicture() instead of CopyArea() when we need to convert to a new format. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--uxa/uxa-render.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/uxa/uxa-render.c b/uxa/uxa-render.c
index e071fc40..8eee6a69 100644
--- a/uxa/uxa-render.c
+++ b/uxa/uxa-render.c
@@ -315,6 +315,68 @@ uxa_try_driver_solid_fill(PicturePtr pSrc,
return 1;
}
+/* In order to avoid fallbacks when using an a1 source/mask,
+ * for example with non-antialiased trapezoids, we need to
+ * expand the bitmap into an a8 Picture. We do so by using the generic
+ * composition routines, which while may not be perfect is far faster
+ * than causing a fallback.
+ */
+static PicturePtr
+uxa_picture_from_a1_pixman_image (ScreenPtr pScreen,
+ pixman_image_t *image)
+{
+ PicturePtr pPicture;
+ PicturePtr pSrc;
+ PixmapPtr pPixmap;
+ int width, height;
+ int error;
+
+ width = pixman_image_get_width (image);
+ height = pixman_image_get_height (image);
+
+ pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 8,
+ UXA_CREATE_PIXMAP_FOR_MAP);
+ if (!pPixmap)
+ return 0;
+
+ pPicture = CreatePicture (0, &pPixmap->drawable,
+ PictureMatchFormat (pScreen, 8, PICT_a8),
+ 0, 0, serverClient, &error);
+ (*pScreen->DestroyPixmap) (pPixmap);
+ if (!pPicture)
+ return 0;
+
+ ValidatePicture (pPicture);
+
+ pPixmap = GetScratchPixmapHeader(pScreen, width, height, 1,
+ BitsPerPixel (1),
+ pixman_image_get_stride (image),
+ pixman_image_get_data (image));
+ if (!pPixmap) {
+ FreePicture (pPicture, 0);
+ return 0;
+ }
+
+ pSrc = CreatePicture (0, &pPixmap->drawable,
+ PictureMatchFormat (pScreen, 1, PICT_a1),
+ 0, 0, serverClient, &error);
+ FreeScratchPixmapHeader (pPixmap);
+ if (!pPicture) {
+ FreePicture (pPicture, 0);
+ return 0;
+ }
+
+ CompositePicture (PictOpSrc, pSrc, NULL, pPicture,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ width, height);
+
+ FreePicture (pSrc, 0);
+
+ return pPicture;
+}
+
static PicturePtr
uxa_picture_from_pixman_image (ScreenPtr pScreen,
pixman_image_t *image,
@@ -326,6 +388,9 @@ uxa_picture_from_pixman_image (ScreenPtr pScreen,
int width, height, depth;
int error;
+ if (format == PICT_a1)
+ return uxa_picture_from_a1_pixman_image (pScreen, image);
+
width = pixman_image_get_width (image);
height = pixman_image_get_height (image);
depth = pixman_image_get_depth (image);
@@ -339,6 +404,9 @@ uxa_picture_from_pixman_image (ScreenPtr pScreen,
PictureMatchFormat (pScreen, depth, format),
0, 0, serverClient, &error);
(*pScreen->DestroyPixmap) (pPixmap);
+ if (!pPicture)
+ return 0;
+
ValidatePicture (pPicture);
pPixmap = GetScratchPixmapHeader(pScreen, width, height, depth,