Alexandre Julliard : gdi32: Add a level of pointers to the glyph cache to avoid the need for locking individual glyphs .

Alexandre Julliard julliard at winehq.org
Tue Dec 11 14:41:14 CST 2012


Module: wine
Branch: master
Commit: a3cf48afada1ab525ed5c60cea8dcbf64f94c0b2
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a3cf48afada1ab525ed5c60cea8dcbf64f94c0b2

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Dec 10 21:42:18 2012 +0100

gdi32: Add a level of pointers to the glyph cache to avoid the need for locking individual glyphs.

---

 dlls/gdi32/dibdrv/graphics.c |   65 +++++++++++++++++++++++------------------
 1 files changed, 36 insertions(+), 29 deletions(-)

diff --git a/dlls/gdi32/dibdrv/graphics.c b/dlls/gdi32/dibdrv/graphics.c
index aadd9b5..bb4ec81 100644
--- a/dlls/gdi32/dibdrv/graphics.c
+++ b/dlls/gdi32/dibdrv/graphics.c
@@ -40,6 +40,9 @@ enum glyph_type
     GLYPH_NBTYPES
 };
 
+#define GLYPH_CACHE_PAGE_SIZE  0x100
+#define GLYPH_CACHE_PAGES      (0x10000 / GLYPH_CACHE_PAGE_SIZE)
+
 struct cached_font
 {
     struct list           entry;
@@ -48,8 +51,7 @@ struct cached_font
     LOGFONTW              lf;
     XFORM                 xform;
     UINT                  aa_flags;
-    UINT                  nb_glyphs[GLYPH_NBTYPES];
-    struct cached_glyph **glyphs[GLYPH_NBTYPES];
+    struct cached_glyph **glyphs[GLYPH_NBTYPES][GLYPH_CACHE_PAGES];
 };
 
 static struct list font_cache = LIST_INIT( font_cache );
@@ -494,7 +496,7 @@ static int font_cache_cmp( const struct cached_font *p1, const struct cached_fon
 static struct cached_font *add_cached_font( HDC hdc, HFONT hfont, UINT aa_flags )
 {
     struct cached_font font, *ptr, *last_unused = NULL;
-    UINT i = 0, j;
+    UINT i = 0, j, k;
 
     GetObjectW( hfont, sizeof(font.lf), &font.lf );
     GetTransform( hdc, 0x204, &font.xform );
@@ -530,8 +532,13 @@ static struct cached_font *add_cached_font( HDC hdc, HFONT hfont, UINT aa_flags
         ptr = last_unused;
         for (i = 0; i < GLYPH_NBTYPES; i++)
         {
-            for (j = 0; j < ptr->nb_glyphs[i]; j++) HeapFree( GetProcessHeap(), 0, ptr->glyphs[i][j] );
-            HeapFree( GetProcessHeap(), 0, ptr->glyphs[i] );
+            for (j = 0; j < GLYPH_CACHE_PAGES; j++)
+            {
+                if (!ptr->glyphs[i][j]) continue;
+                for (k = 0; k < GLYPH_CACHE_PAGE_SIZE; k++)
+                    HeapFree( GetProcessHeap(), 0, ptr->glyphs[i][j][k] );
+                HeapFree( GetProcessHeap(), 0, ptr->glyphs[i][j] );
+            }
         }
         list_remove( &ptr->entry );
     }
@@ -543,11 +550,7 @@ static struct cached_font *add_cached_font( HDC hdc, HFONT hfont, UINT aa_flags
 
     *ptr = font;
     ptr->ref = 1;
-    for (i = 0; i < GLYPH_NBTYPES; i++)
-    {
-        ptr->glyphs[i] = NULL;
-        ptr->nb_glyphs[i] = 0;
-    }
+    memset( ptr->glyphs, 0, sizeof(ptr->glyphs) );
 done:
     list_add_head( &font_cache, &ptr->entry );
     LeaveCriticalSection( &font_cache_cs );
@@ -560,33 +563,40 @@ void release_cached_font( struct cached_font *font )
     if (font) InterlockedDecrement( &font->ref );
 }
 
-static void add_cached_glyph( struct cached_font *font, UINT index, UINT flags, struct cached_glyph *glyph )
+static struct cached_glyph *add_cached_glyph( struct cached_font *font, UINT index, UINT flags,
+                                              struct cached_glyph *glyph )
 {
+    struct cached_glyph *ret;
     enum glyph_type type = (flags & ETO_GLYPH_INDEX) ? GLYPH_INDEX : GLYPH_WCHAR;
+    UINT page = index / GLYPH_CACHE_PAGE_SIZE;
+    UINT entry = index % GLYPH_CACHE_PAGE_SIZE;
 
-    if (index >= font->nb_glyphs[type])
+    if (!font->glyphs[type][page])
     {
-        UINT new_count = (index + 128) & ~127;
-        struct cached_glyph **new;
+        struct cached_glyph **ptr;
 
-        if (font->glyphs[type])
-            new = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
-                               font->glyphs[type], new_count * sizeof(*new) );
-        else
-            new = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*new) );
-        if (!new) return;
-        font->glyphs[type] = new;
-        font->nb_glyphs[type] = new_count;
+        ptr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, GLYPH_CACHE_PAGE_SIZE * sizeof(*ptr) );
+        if (!ptr)
+        {
+            HeapFree( GetProcessHeap(), 0, glyph );
+            return NULL;
+        }
+        if (InterlockedCompareExchangePointer( (void **)&font->glyphs[type][page], ptr, NULL ))
+            HeapFree( GetProcessHeap(), 0, ptr );
     }
-    font->glyphs[type][index] = glyph;
+    ret = InterlockedCompareExchangePointer( (void **)&font->glyphs[type][page][entry], glyph, NULL );
+    if (!ret) ret = glyph;
+    else HeapFree( GetProcessHeap(), 0, glyph );
+    return ret;
 }
 
 static struct cached_glyph *get_cached_glyph( struct cached_font *font, UINT index, UINT flags )
 {
     enum glyph_type type = (flags & ETO_GLYPH_INDEX) ? GLYPH_INDEX : GLYPH_WCHAR;
+    UINT page = index / GLYPH_CACHE_PAGE_SIZE;
 
-    if (index < font->nb_glyphs[type]) return font->glyphs[type][index];
-    return NULL;
+    if (!font->glyphs[type][page]) return NULL;
+    return font->glyphs[type][page][index % GLYPH_CACHE_PAGE_SIZE];
 }
 
 /**********************************************************************
@@ -733,8 +743,7 @@ static struct cached_glyph *cache_glyph_bitmap( HDC hdc, struct cached_font *fon
 
 done:
     glyph->metrics = metrics;
-    add_cached_glyph( font, index, flags, glyph );
-    return glyph;
+    return add_cached_glyph( font, index, flags, glyph );
 }
 
 static void render_string( HDC hdc, dib_info *dib, struct cached_font *font, INT x, INT y,
@@ -758,7 +767,6 @@ static void render_string( HDC hdc, dib_info *dib, struct cached_font *font, INT
     if (glyph_dib.bit_count == 8)
         get_aa_ranges( dib->funcs->pixel_to_colorref( dib, text_color ), ranges );
 
-    EnterCriticalSection( &font_cache_cs );
     for (i = 0; i < count; i++)
     {
         if (!(glyph = get_cached_glyph( font, str[i], flags )) &&
@@ -789,7 +797,6 @@ static void render_string( HDC hdc, dib_info *dib, struct cached_font *font, INT
             y += glyph->metrics.gmCellIncY;
         }
     }
-    LeaveCriticalSection( &font_cache_cs );
 }
 
 BOOL render_aa_text_bitmapinfo( HDC hdc, BITMAPINFO *info, struct gdi_image_bits *bits,




More information about the wine-cvs mailing list