xf86-video-intel: uxa/uxa.c uxa/uxa-priv.h uxa/uxa-render.c

Chris Wilson ickle at kemper.freedesktop.org
Mon Dec 7 13:59:14 PST 2009


 uxa/uxa-priv.h   |   11 ++++++
 uxa/uxa-render.c |   94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 uxa/uxa.c        |   15 ++++++++
 3 files changed, 120 insertions(+)

New commits:
commit c1afc831c8fe4cbececee7dfa23506a6746c2425
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Dec 7 21:27:56 2009 +0000

    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 at chris-wilson.co.uk>

diff --git a/uxa/uxa-priv.h b/uxa/uxa-priv.h
index 35961aa..c1f3688 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 abd0bf5..525f75b 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);
diff --git a/uxa/uxa.c b/uxa/uxa.c
index 4bf8c77..d6ad5a6 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);
 
 	/*


More information about the xorg-commit mailing list