From: Michel Dänzer <[email protected]> Inspired by the corresponding intel driver change by Chris Wilson.
Signed-off-by: Michel Dänzer <[email protected]> --- exa/exa.c | 3 + exa/exa_glyphs.c | 219 ++++++++++++++++++------------------------------------ exa/exa_priv.h | 20 ++--- 3 files changed, 82 insertions(+), 160 deletions(-) diff --git a/exa/exa.c b/exa/exa.c index a4e294a..b6df33c 100644 --- a/exa/exa.c +++ b/exa/exa.c @@ -799,6 +799,8 @@ exaCloseScreen(int i, ScreenPtr pScreen) unwrap(pExaScr, ps, Composite); if (pExaScr->SavedGlyphs) unwrap(pExaScr, ps, Glyphs); + if (pExaScr->SavedUnrealizeGlyph) + unwrap(pExaScr, ps, UnrealizeGlyph); unwrap(pExaScr, ps, Trapezoids); unwrap(pExaScr, ps, Triangles); unwrap(pExaScr, ps, AddTraps); @@ -960,6 +962,7 @@ exaDriverInit (ScreenPtr pScreen, wrap(pExaScr, ps, Composite, exaComposite); if (pScreenInfo->PrepareComposite) { wrap(pExaScr, ps, Glyphs, exaGlyphs); + wrap(pExaScr, ps, UnrealizeGlyph, exaUnrealizeGlyph); } else { wrap(pExaScr, ps, Glyphs, ExaCheckGlyphs); } diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c index 5711ca7..3918122 100644 --- a/exa/exa_glyphs.c +++ b/exa/exa_glyphs.c @@ -56,6 +56,13 @@ #define DBG_GLYPH_CACHE(a) #endif +struct exaGlyph { + ExaGlyphCachePtr cache; + int pos; +}; + +static DevPrivateKeyRec exaGlyphKey; + /* Width of the pixmaps we use for the caches; this should be less than * max texture size of the driver; this may need to actually come from * the driver. @@ -63,7 +70,6 @@ #define CACHE_COLUMNS (1024 / 32) #define CACHE_SIZE 256 -#define HASH_SIZE 557 /* Maximum number of glyphs we buffer on the stack before flushing * rendering to the mask or destination surface. @@ -88,6 +94,9 @@ exaGlyphsInit(ScreenPtr pScreen) ExaScreenPriv(pScreen); int i = 0; + if (!dixRegisterPrivateKey(&exaGlyphKey, PRIVATE_GLYPH, 0)) + FatalError("Failed to register EXA glyph private key"); + memset(pExaScr->glyphCaches, 0, sizeof(pExaScr->glyphCaches)); pExaScr->glyphCaches[i].format = PICT_a8; @@ -124,12 +133,8 @@ exaUnrealizeGlyphCaches(ScreenPtr pScreen, cache->picture = NULL; } - free(cache->hashEntries); - cache->hashEntries = NULL; - - free(cache->glyphs); - cache->glyphs = NULL; - cache->glyphCount = 0; + free(cache->ppGlyph); + cache->ppGlyph = NULL; } } @@ -199,23 +204,17 @@ exaRealizeGlyphCaches(ScreenPtr pScreen, /* And store the picture in all the caches for the format */ for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) { ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i]; - int j; if (cache->format != format) continue; cache->picture = pPicture; cache->picture->refcnt++; - cache->hashEntries = malloc(sizeof(int) * HASH_SIZE); - cache->glyphs = malloc(sizeof(ExaCachedGlyphRec) * CACHE_SIZE); - cache->glyphCount = 0; + cache->ppGlyph = calloc(CACHE_SIZE, sizeof(struct exaGlyph*)); - if (!cache->hashEntries || !cache->glyphs) + if (!cache->ppGlyph) goto bail; - for (j = 0; j < HASH_SIZE; j++) - cache->hashEntries[j] = -1; - cache->evictionPosition = 0; } @@ -229,6 +228,23 @@ bail: } void +exaUnrealizeGlyph(ScreenPtr screen, GlyphPtr pGlyph) +{ + struct exaGlyph *priv; + + /* Use Lookup in case we have not attached to this glyph. */ + priv = dixLookupPrivate(&pGlyph->devPrivates, &exaGlyphKey); + if (priv == NULL) + return; + + if (priv->cache) + priv->cache->ppGlyph[priv->pos] = NULL; + + dixSetPrivate(&pGlyph->devPrivates, &exaGlyphKey, NULL); + free(priv); +} + +void exaGlyphsFini (ScreenPtr pScreen) { ExaScreenPriv(pScreen); @@ -242,104 +258,6 @@ exaGlyphsFini (ScreenPtr pScreen) } } -static int -exaGlyphCacheHashLookup(ExaGlyphCachePtr cache, - GlyphPtr pGlyph) -{ - int slot; - - slot = (*(CARD32 *) pGlyph->sha1) % HASH_SIZE; - - while (TRUE) { /* hash table can never be full */ - int entryPos = cache->hashEntries[slot]; - if (entryPos == -1) - return -1; - - if (memcmp(pGlyph->sha1, cache->glyphs[entryPos].sha1, sizeof(pGlyph->sha1)) == 0){ - return entryPos; - } - - slot--; - if (slot < 0) - slot = HASH_SIZE - 1; - } -} - -static void -exaGlyphCacheHashInsert(ExaGlyphCachePtr cache, - GlyphPtr pGlyph, - int pos) -{ - int slot; - - memcpy(cache->glyphs[pos].sha1, pGlyph->sha1, sizeof(pGlyph->sha1)); - - slot = (*(CARD32 *) pGlyph->sha1) % HASH_SIZE; - - while (TRUE) { /* hash table can never be full */ - if (cache->hashEntries[slot] == -1) { - cache->hashEntries[slot] = pos; - return; - } - - slot--; - if (slot < 0) - slot = HASH_SIZE - 1; - } -} - -static void -exaGlyphCacheHashRemove(ExaGlyphCachePtr cache, - int pos) -{ - int slot; - int emptiedSlot = -1; - - slot = (*(CARD32 *) cache->glyphs[pos].sha1) % HASH_SIZE; - - while (TRUE) { /* hash table can never be full */ - int entryPos = cache->hashEntries[slot]; - - if (entryPos == -1) - return; - - if (entryPos == pos) { - cache->hashEntries[slot] = -1; - emptiedSlot = slot; - } else if (emptiedSlot != -1) { - /* See if we can move this entry into the emptied slot, we can't - * do that if if entry would have hashed between the current position - * and the emptied slot. (taking wrapping into account). Bad positions - * are: - * - * | XXXXXXXXXX | - * i j - * - * |XXX XXXX| - * j i - * - * i - slot, j - emptiedSlot - * - * (Knuth 6.4R) - */ - - int entrySlot = (*(CARD32 *) cache->glyphs[entryPos].sha1) % HASH_SIZE; - - if (!((entrySlot >= slot && entrySlot < emptiedSlot) || - (emptiedSlot < slot && (entrySlot < emptiedSlot || entrySlot >= slot)))) - { - cache->hashEntries[emptiedSlot] = entryPos; - cache->hashEntries[slot] = -1; - emptiedSlot = slot; - } - } - - slot--; - if (slot < 0) - slot = HASH_SIZE - 1; - } -} - #define CACHE_X(pos) (((pos) & (CACHE_COLUMNS - 1)) * cache->glyphWidth) #define CACHE_Y(pos) (cache->yOffset + ((pos) / CACHE_COLUMNS) * cache->glyphHeight) @@ -439,67 +357,74 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen, INT16 yDst) { ExaCompositeRectPtr rect; - int pos; + struct exaGlyph *priv; + int pos = -1; int x, y; if (buffer->mask && buffer->mask != cache->picture) return ExaGlyphNeedFlush; - if (!cache->picture) { - if (!exaRealizeGlyphCaches(pScreen, cache->format)) - return ExaGlyphFail; - } + if (!cache->picture && !exaRealizeGlyphCaches(pScreen, cache->format)) + return ExaGlyphFail; DBG_GLYPH_CACHE(("(%d,%d,%s): buffering glyph %lx\n", cache->glyphWidth, cache->glyphHeight, cache->format == PICT_a8 ? "A" : "ARGB", (long)*(CARD32 *) pGlyph->sha1)); - - pos = exaGlyphCacheHashLookup(cache, pGlyph); + + priv = dixGetPrivate(&pGlyph->devPrivates, &exaGlyphKey); + if (!priv) { + priv = malloc(sizeof(*priv)); + if (!priv) + return ExaGlyphFail; + + priv->cache = NULL; + priv->pos = pos; + dixSetPrivate(&pGlyph->devPrivates, &exaGlyphKey, priv); + } else if (priv->cache == cache) + pos = priv->pos; + if (pos != -1) { DBG_GLYPH_CACHE((" found existing glyph at %d\n", pos)); x = CACHE_X(pos); y = CACHE_Y(pos); } else { - if (cache->glyphCount < CACHE_SIZE) { - /* Space remaining; we fill from the start */ - pos = cache->glyphCount; - x = CACHE_X(pos); - y = CACHE_Y(pos); - cache->glyphCount++; - DBG_GLYPH_CACHE((" storing glyph in free space at %d\n", pos)); + int i; - exaGlyphCacheHashInsert(cache, pGlyph, pos); + pos = cache->evictionPosition; - } else { + /* Find first empty slot before eviction position, if any */ + for (i = 0; i < CACHE_SIZE && cache->ppGlyph[pos]; i++) + pos = (pos - 1) & (CACHE_SIZE - 1); + + x = CACHE_X(pos); + y = CACHE_Y(pos); + + if (cache->ppGlyph[pos]) { /* Need to evict an entry. We have to see if any glyphs * already in the output buffer were at this position in * the cache */ - pos = cache->evictionPosition; - x = CACHE_X(pos); - y = CACHE_Y(pos); DBG_GLYPH_CACHE((" evicting glyph at %d\n", pos)); - if (buffer->count) { - int i; - - for (i = 0; i < buffer->count; i++) { - if (pSrc ? - (buffer->rects[i].xMask == x && buffer->rects[i].yMask == y) : - (buffer->rects[i].xSrc == x && buffer->rects[i].ySrc == y)) { - DBG_GLYPH_CACHE((" must flush buffer\n")); - return ExaGlyphNeedFlush; - } + + for (i = 0; i < buffer->count; i++) { + if (pSrc ? + (buffer->rects[i].xMask == x && buffer->rects[i].yMask == y) : + (buffer->rects[i].xSrc == x && buffer->rects[i].ySrc == y)) { + DBG_GLYPH_CACHE((" must flush buffer\n")); + return ExaGlyphNeedFlush; } } - - /* OK, we're all set, swap in the new glyph */ - exaGlyphCacheHashRemove(cache, pos); - exaGlyphCacheHashInsert(cache, pGlyph, pos); + cache->ppGlyph[pos]->cache = NULL; + cache->ppGlyph[pos]->pos = -1; /* And pick a new eviction position */ - cache->evictionPosition = (pos + 1) & (CACHE_SIZE - 1); + cache->evictionPosition = (cache->evictionPosition + 1) & (CACHE_SIZE - 1); } + priv->cache = cache; + priv->pos = pos; + cache->ppGlyph[pos] = priv; + exaGlyphCacheUploadGlyph(pScreen, cache, x, y, pGlyph); } diff --git a/exa/exa_priv.h b/exa/exa_priv.h index 7d2ea2c..251aad9 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -105,9 +105,7 @@ enum ExaMigrationHeuristic { ExaMigrationSmart }; -typedef struct { - unsigned char sha1[20]; -} ExaCachedGlyphRec, *ExaCachedGlyphPtr; +struct exaGlyph; typedef struct { /* The identity of the cache, statically configured at initialization */ @@ -115,16 +113,7 @@ typedef struct { int glyphWidth; int glyphHeight; - /* Hash table mapping from glyph sha1 to position in the glyph; we use - * open addressing with a hash table size determined based on size and large - * enough so that we always have a good amount of free space, so we can - * use linear probing. (Linear probing is preferrable to double hashing - * here because it allows us to easily remove entries.) - */ - int *hashEntries; - - ExaCachedGlyphPtr glyphs; - int glyphCount; /* Current number of glyphs */ + struct exaGlyph **ppGlyph; PicturePtr picture; /* Where the glyphs of the cache are stored */ int yOffset; /* y location within the picture where the cache starts */ @@ -164,6 +153,7 @@ typedef struct { CompositeProcPtr SavedComposite; TrianglesProcPtr SavedTriangles; GlyphsProcPtr SavedGlyphs; + UnrealizeGlyphProcPtr SavedUnrealizeGlyph; TrapezoidsProcPtr SavedTrapezoids; AddTrapsProcPtr SavedAddTraps; void (*do_migration) (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel); @@ -696,6 +686,10 @@ exaGlyphs (CARD8 op, GlyphListPtr list, GlyphPtr *glyphs); +void +exaUnrealizeGlyph(ScreenPtr pScreen, + GlyphPtr pGlyph); + /* exa_migration_classic.c */ void exaCopyDirtyToSys (ExaMigrationPtr migrate); -- 1.7.5.1 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
