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

Reply via email to