diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2009-09-20 01:02:39 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2009-09-20 01:15:41 +0100 |
commit | 57fc09cef28bad2e3e8455b93ef2927118f8a3a3 (patch) | |
tree | ebf8bbf5ead34d112a6a315f81f6405184df8eff /uxa | |
parent | 33f98e4056706f4c30bb4327677ac49e82058231 (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>
Diffstat (limited to 'uxa')
-rw-r--r-- | uxa/uxa-render.c | 68 |
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, |