diff --git a/uxa/uxa-priv.h b/uxa/uxa-priv.h index 35961aa5..c1f3688c 100644 --- a/uxa/uxa-priv.h +++ b/uxa/uxa-priv.h @@ -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; /* 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 @@ -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); diff --git a/uxa/uxa.c b/uxa/uxa.c index 4bf8c774..d6ad5a63 100644 --- a/uxa/uxa.c +++ b/uxa/uxa.c @@ -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); /*