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>
This commit is contained in:
Chris Wilson 2009-12-07 21:27:56 +00:00
parent cd475bad23
commit c1afc831c8
3 changed files with 120 additions and 0 deletions

View File

@ -135,6 +135,13 @@ typedef struct {
#define UXA_NUM_GLYPH_CACHES 4
typedef struct {
uint32_t color;
PicturePtr picture;
} uxa_solid_cache_t;
#define UXA_NUM_SOLID_CACHE 16
typedef void (*EnableDisableFBAccessProcPtr) (int, Bool);
typedef struct {
uxa_driver_t *info;
@ -162,6 +169,10 @@ typedef struct {
unsigned offScreenCounter;
uxa_glyph_cache_t glyphCaches[UXA_NUM_GLYPH_CACHES];
PicturePtr solid_clear, solid_black, solid_white;
uxa_solid_cache_t solid_cache[UXA_NUM_SOLID_CACHE];
int solid_cache_size;
} uxa_screen_t;
/*

View File

@ -453,6 +453,93 @@ uxa_picture_from_pixman_image(ScreenPtr pScreen,
return pPicture;
}
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,
@ -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);

View File

@ -361,6 +361,16 @@ static Bool uxa_close_screen(int i, ScreenPtr pScreen)
#ifdef RENDER
PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
#endif
int n;
if (uxa_screen->solid_clear)
FreePicture(uxa_screen->solid_clear, 0);
if (uxa_screen->solid_black)
FreePicture(uxa_screen->solid_black, 0);
if (uxa_screen->solid_white)
FreePicture(uxa_screen->solid_white, 0);
for (n = 0; n < uxa_screen->solid_cache_size; n++)
FreePicture(uxa_screen->solid_cache[n].picture, 0);
uxa_glyphs_fini(pScreen);
@ -467,6 +477,11 @@ Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver)
dixSetPrivate(&screen->devPrivates, &uxa_screen_index, uxa_screen);
uxa_screen->solid_cache_size = 0;
uxa_screen->solid_clear = 0;
uxa_screen->solid_black = 0;
uxa_screen->solid_white = 0;
// exaDDXDriverInit(screen);
/*