summaryrefslogtreecommitdiff
path: root/uxa/uxa-render.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-12-07 21:27:56 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2009-12-07 21:37:31 +0000
commitc1afc831c8fe4cbececee7dfa23506a6746c2425 (patch)
treed15f586c68af3150aa6c09a45954daba9d88521d /uxa/uxa-render.c
parentcd475bad23c02130d11c49882c11261c9f0d4ef1 (diff)
uxa: Cache solid fills.
Maintain a small cache of pixmaps to hold SolidFill pictures. Currently we create a pixmap the size of the damaged region and fill that using pixman before downloading it to the GPU and compositing. Needless to say this is extremely expensive compared to simply emitting the solid colour. To mitigate this cost, we maintain a small cache of 1x1R pictures which is recognised by the driver as being a solid, but at the very least is maintained as a GPU ready pixmap. This gives a good boost to cairo-xcb (which uses solid fills) on a gm45: Before: gnome-terminal-vim: 41.9s After: gnome-terminal-vim: 31.7s Compare with using a cache of 1x1R pixmaps in cairo-xcb: gnome-terminal-vim: 31.6s Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'uxa/uxa-render.c')
-rw-r--r--uxa/uxa-render.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/uxa/uxa-render.c b/uxa/uxa-render.c
index abd0bf5a..525f75bb 100644
--- a/uxa/uxa-render.c
+++ b/uxa/uxa-render.c
@@ -454,6 +454,93 @@ uxa_picture_from_pixman_image(ScreenPtr pScreen,
}
static PicturePtr
+uxa_create_solid(ScreenPtr screen, uint32_t color)
+{
+ PixmapPtr pixmap;
+ PicturePtr picture;
+ uint32_t repeat = RepeatNormal;
+ int error = 0;
+
+ pixmap = (*screen->CreatePixmap)(screen, 1, 1, 32,
+ UXA_CREATE_PIXMAP_FOR_MAP);
+ if (!pixmap)
+ return 0;
+
+ if (!uxa_prepare_access((DrawablePtr)pixmap, UXA_ACCESS_RW)) {
+ (*screen->DestroyPixmap)(pixmap);
+ return 0;
+ }
+ *((uint32_t *)pixmap->devPrivate.ptr) = color;
+ uxa_finish_access((DrawablePtr)pixmap);
+
+ picture = CreatePicture(0, &pixmap->drawable,
+ PictureMatchFormat(screen, 32, PICT_a8r8g8b8),
+ CPRepeat, &repeat, serverClient, &error);
+ (*screen->DestroyPixmap)(pixmap);
+
+ return picture;
+}
+
+static PicturePtr
+uxa_acquire_solid(ScreenPtr screen, SourcePict *source)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ PictSolidFill *solid = &source->solidFill;
+ PicturePtr picture;
+ int i;
+
+ if ((solid->color >> 24) == 0) {
+ if (!uxa_screen->solid_clear) {
+ uxa_screen->solid_clear = uxa_create_solid(screen, 0);
+ if (!uxa_screen->solid_clear)
+ return 0;
+ }
+ picture = uxa_screen->solid_clear;
+ goto DONE;
+ } else if (solid->color == 0xff000000) {
+ if (!uxa_screen->solid_black) {
+ uxa_screen->solid_black = uxa_create_solid(screen, 0xff000000);
+ if (!uxa_screen->solid_black)
+ return 0;
+ }
+ picture = uxa_screen->solid_black;
+ goto DONE;
+ } else if (solid->color == 0xffffffff) {
+ if (!uxa_screen->solid_white) {
+ uxa_screen->solid_white = uxa_create_solid(screen, 0xffffffff);
+ if (!uxa_screen->solid_white)
+ return 0;
+ }
+ picture = uxa_screen->solid_white;
+ goto DONE;
+ }
+
+ for (i = 0; i < uxa_screen->solid_cache_size; i++) {
+ if (uxa_screen->solid_cache[i].color == solid->color) {
+ picture = uxa_screen->solid_cache[i].picture;
+ goto DONE;
+ }
+ }
+
+ picture = uxa_create_solid(screen, solid->color);
+ if (!picture)
+ return 0;
+
+ if (uxa_screen->solid_cache_size == UXA_NUM_SOLID_CACHE) {
+ i = rand() % UXA_NUM_SOLID_CACHE;
+ FreePicture(uxa_screen->solid_cache[i].picture, 0);
+ } else
+ uxa_screen->solid_cache_size++;
+
+ uxa_screen->solid_cache[i].picture = picture;
+ uxa_screen->solid_cache[i].color = solid->color;
+
+DONE:
+ picture->refcnt++;
+ return picture;
+}
+
+static PicturePtr
uxa_acquire_pattern(ScreenPtr pScreen,
PicturePtr pSrc,
pixman_format_code_t format,
@@ -461,9 +548,16 @@ uxa_acquire_pattern(ScreenPtr pScreen,
{
PicturePtr pDst;
+ if (pSrc->pSourcePict) {
+ SourcePict *source = pSrc->pSourcePict;
+ if (source->type == SourcePictTypeSolidFill)
+ return uxa_acquire_solid (pScreen, source);
+ }
+
pDst = uxa_picture_for_pixman_format(pScreen, format, width, height);
if (!pDst)
return 0;
+
if (uxa_prepare_access(pDst->pDrawable, UXA_ACCESS_RW)) {
fbComposite(PictOpSrc, pSrc, NULL, pDst,
x, y, 0, 0, 0, 0, width, height);