Split glyph cache for antialiasing

Glenn Wurster gwurster at scs.carleton.ca
Wed Jan 19 13:25:37 CST 2005


This is the first of three patches, and the next attempt at getting
antialiasing disabled when we should not be using it.

This patch splits the caching of antialiased and non-antialiased
glyphs, and will allow us to use each as required.

Authors:
  * Glenn Wurster (gwurster at scs.carleton.ca)

Changelog:
  * Split caching of antialiased and non-antialiased glyphs.

Index: dlls/x11drv/xrender.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/xrender.c,v
retrieving revision 1.54
diff -u -r1.54 xrender.c
--- dlls/x11drv/xrender.c	3 Jan 2005 14:56:42 -0000	1.54
+++ dlls/x11drv/xrender.c	13 Jan 2005 03:08:28 -0000
@@ -67,18 +67,23 @@
 
 #define INITIAL_REALIZED_BUF_SIZE 128
 
-typedef enum { AA_None, AA_Grey, AA_RGB, AA_BGR, AA_VRGB, AA_VBGR } AA_Type;
+typedef enum { AA_None = 0, AA_Grey, AA_RGB, AA_BGR, AA_VRGB, AA_VBGR, AA_MAXVALUE } AA_Type;
 
 typedef struct
 {
-    LFANDSIZE lfsz;
-    AA_Type aa;
     GlyphSet glyphset;
     XRenderPictFormat *font_format;
     int nrealized;
     BOOL *realized;
     void **bitmaps;
     XGlyphInfo *gis;
+} gsCacheEntryFormat;
+
+typedef struct
+{
+    LFANDSIZE lfsz;
+    AA_Type aa_default;
+    gsCacheEntryFormat * format[AA_MAXVALUE];
     UINT count;
     INT next;
 } gsCacheEntry;
@@ -292,26 +297,39 @@
 
 static void FreeEntry(int entry)
 {
-    int i;
+    int i, format;
+  
+    for(format = 0; format < AA_MAXVALUE; format++) {
+        gsCacheEntryFormat * formatEntry;
 
-    if(glyphsetCache[entry].glyphset) {
-	wine_tsx11_lock();
-	pXRenderFreeGlyphSet(gdi_display, glyphsetCache[entry].glyphset);
-	wine_tsx11_unlock();
-	glyphsetCache[entry].glyphset = 0;
-    }
-    if(glyphsetCache[entry].nrealized) {
-	HeapFree(GetProcessHeap(), 0, glyphsetCache[entry].realized);
-	glyphsetCache[entry].realized = NULL;
-	if(glyphsetCache[entry].bitmaps) {
-	    for(i = 0; i < glyphsetCache[entry].nrealized; i++)
-                HeapFree(GetProcessHeap(), 0, glyphsetCache[entry].bitmaps[i]);
-	    HeapFree(GetProcessHeap(), 0, glyphsetCache[entry].bitmaps);
-	    glyphsetCache[entry].bitmaps = NULL;
-	    HeapFree(GetProcessHeap(), 0, glyphsetCache[entry].gis);
-	    glyphsetCache[entry].gis = NULL;
-	}
-	glyphsetCache[entry].nrealized = 0;
+        if( !glyphsetCache[entry].format[format] )
+            continue;
+
+        formatEntry = glyphsetCache[entry].format[format];
+
+        if(formatEntry->glyphset) {
+            wine_tsx11_lock();
+            pXRenderFreeGlyphSet(gdi_display, formatEntry->glyphset);
+            wine_tsx11_unlock();
+            formatEntry->glyphset = 0;
+        }
+        if(formatEntry->nrealized) {
+            HeapFree(GetProcessHeap(), 0, formatEntry->realized);
+            formatEntry->realized = NULL;
+            if(formatEntry->bitmaps) {
+                for(i = 0; i < formatEntry->nrealized; i++)
+                    if(formatEntry->bitmaps[i])
+                        HeapFree(GetProcessHeap(), 0, formatEntry->bitmaps[i]);
+                HeapFree(GetProcessHeap(), 0, formatEntry->bitmaps);
+                formatEntry->bitmaps = NULL;
+                HeapFree(GetProcessHeap(), 0, formatEntry->gis);
+                formatEntry->gis = NULL;
+            }
+            formatEntry->nrealized = 0;
+        }
+
+        HeapFree(GetProcessHeap(), 0, formatEntry);
+        glyphsetCache[entry].format[format] = NULL;
     }
 }
 
@@ -385,6 +403,7 @@
 static int GetCacheEntry(LFANDSIZE *plfsz)
 {
     int ret;
+    int format;
     gsCacheEntry *entry;
 
     if((ret = LookupEntry(plfsz)) != -1) return ret;
@@ -392,15 +411,15 @@
     ret = AllocEntry();
     entry = glyphsetCache + ret;
     entry->lfsz = *plfsz;
-    assert(entry->nrealized == 0);
+    for( format = 0; format < AA_MAXVALUE; format++ ) {
+        assert( !entry->format[format] );
+    }
 
     if(antialias)
-        entry->aa = AA_Grey;
+        entry->aa_default = AA_Grey;
     else
-        entry->aa = AA_None;
+        entry->aa_default = AA_None;
 
-    entry->font_format = NULL;
-    entry->glyphset = 0;
     return ret;
 }
 
@@ -527,7 +546,7 @@
  *
  * Helper to ExtTextOut.  Must be called inside xrender_cs
  */
-static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, int glyph)
+static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, int glyph, AA_Type format)
 {
     unsigned int buflen;
     char *buf;
@@ -535,52 +554,61 @@
     GLYPHMETRICS gm;
     XGlyphInfo gi;
     gsCacheEntry *entry = glyphsetCache + physDev->xrender->cache_index;
+    gsCacheEntryFormat *formatEntry;
     UINT ggo_format = GGO_GLYPH_INDEX;
     XRenderPictFormat pf;
 
-    if(entry->nrealized <= glyph) {
-        entry->nrealized = (glyph / 128 + 1) * 128;
+    /* If there is nothing for the current type, we create the entry. */
+    if( !entry->format[format] ) {
+        entry->format[format] = HeapAlloc(GetProcessHeap(),
+                                          HEAP_ZERO_MEMORY,
+                                          sizeof(gsCacheEntryFormat));
+    }
+    formatEntry = entry->format[format];
 
-	if (entry->realized)
-	    entry->realized = HeapReAlloc(GetProcessHeap(),
+    if(formatEntry->nrealized <= glyph) {
+        formatEntry->nrealized = (glyph / 128 + 1) * 128;
+
+	if (formatEntry->realized)
+	    formatEntry->realized = HeapReAlloc(GetProcessHeap(),
 				      HEAP_ZERO_MEMORY,
-				      entry->realized,
-				      entry->nrealized * sizeof(BOOL));
+				      formatEntry->realized,
+				      formatEntry->nrealized * sizeof(BOOL));
 	else
-	    entry->realized = HeapAlloc(GetProcessHeap(),
+	    formatEntry->realized = HeapAlloc(GetProcessHeap(),
 				      HEAP_ZERO_MEMORY,
-				      entry->nrealized * sizeof(BOOL));
+				      formatEntry->nrealized * sizeof(BOOL));
 
 	if(!X11DRV_XRender_Installed) {
-	  if (entry->bitmaps)
-	    entry->bitmaps = HeapReAlloc(GetProcessHeap(),
+	  if (formatEntry->bitmaps)
+	    formatEntry->bitmaps = HeapReAlloc(GetProcessHeap(),
 				      HEAP_ZERO_MEMORY,
-				      entry->bitmaps,
-				      entry->nrealized * sizeof(entry->bitmaps[0]));
+				      formatEntry->bitmaps,
+				      formatEntry->nrealized * sizeof(formatEntry->bitmaps[0]));
 	  else
-	    entry->bitmaps = HeapAlloc(GetProcessHeap(),
+	    formatEntry->bitmaps = HeapAlloc(GetProcessHeap(),
 				      HEAP_ZERO_MEMORY,
-				      entry->nrealized * sizeof(entry->bitmaps[0]));
+				      formatEntry->nrealized * sizeof(formatEntry->bitmaps[0]));
 
-	  if (entry->gis)
-	    entry->gis = HeapReAlloc(GetProcessHeap(),
+	  if (formatEntry->gis)
+	    formatEntry->gis = HeapReAlloc(GetProcessHeap(),
 				   HEAP_ZERO_MEMORY,
-				   entry->gis,
-				   entry->nrealized * sizeof(entry->gis[0]));
+				   formatEntry->gis,
+				   formatEntry->nrealized * sizeof(formatEntry->gis[0]));
 	  else
-	    entry->gis = HeapAlloc(GetProcessHeap(),
+	    formatEntry->gis = HeapAlloc(GetProcessHeap(),
 				   HEAP_ZERO_MEMORY,
-				   entry->nrealized * sizeof(entry->gis[0]));
+				   formatEntry->nrealized * sizeof(formatEntry->gis[0]));
 	}
     }
 
-    switch(entry->aa) {
+    switch(format) {
     case AA_Grey:
 	ggo_format |= WINE_GGO_GRAY16_BITMAP;
 	break;
 
     default:
-        ERR("aa = %d - not implemented\n", entry->aa);
+        ERR("aa = %d - not implemented\n", format);
     case AA_None:
         ggo_format |= GGO_BITMAP;
 	break;
@@ -589,8 +617,9 @@
     buflen = GetGlyphOutlineW(physDev->hdc, glyph, ggo_format, &gm, 0, NULL,
 			      NULL);
     if(buflen == GDI_ERROR) {
-        if(entry->aa != AA_None) {
-            entry->aa = AA_None;
+        if(format != AA_None) {
+            format = AA_None;
+            entry->aa_default = AA_None;
             ggo_format &= ~WINE_GGO_GRAY16_BITMAP;
             ggo_format |= GGO_BITMAP;
             buflen = GetGlyphOutlineW(physDev->hdc, glyph, ggo_format, &gm, 0, NULL,
@@ -603,15 +632,15 @@
         TRACE("Turning off antialiasing for this monochrome font\n");
     }
 
-    if(entry->glyphset == 0 && X11DRV_XRender_Installed) {
-        switch(entry->aa) {
+    if(formatEntry->glyphset == 0 && X11DRV_XRender_Installed) {
+        switch(format) {
 	case AA_Grey:
 	    pf.depth = 8;
 	    pf.direct.alphaMask = 0xff;
 	    break;
 
 	default:
-	    ERR("aa = %d - not implemented\n", entry->aa);
+	    ERR("aa = %d - not implemented\n", format);
 	case AA_None:
 	    pf.depth = 1;
 	    pf.direct.alphaMask = 1;
@@ -622,21 +651,21 @@
 	pf.direct.alpha = 0;
 
 	wine_tsx11_lock();
-	entry->font_format = pXRenderFindFormat(gdi_display,
+	formatEntry->font_format = pXRenderFindFormat(gdi_display,
 						PictFormatType |
 						PictFormatDepth |
 						PictFormatAlpha |
 						PictFormatAlphaMask,
 						&pf, 0);
 
-	entry->glyphset = pXRenderCreateGlyphSet(gdi_display, entry->font_format);
+	formatEntry->glyphset = pXRenderCreateGlyphSet(gdi_display, formatEntry->font_format);
 	wine_tsx11_unlock();
     }
 
 
     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buflen);
     GetGlyphOutlineW(physDev->hdc, glyph, ggo_format, &gm, buflen, buf, NULL);
-    entry->realized[glyph] = TRUE;
+    formatEntry->realized[glyph] = TRUE;
 
     TRACE("buflen = %d. Got metrics: %dx%d adv=%d,%d origin=%ld,%ld\n",
 	  buflen,
@@ -655,7 +684,7 @@
 	char output[300];
 	unsigned char *line;
 
-	if(entry->aa == AA_None) {
+	if(format == AA_None) {
 	    pitch = ((gi.width + 31) / 32) * 4;
 	    for(i = 0; i < gi.height; i++) {
 	        line = buf + i * pitch;
@@ -685,8 +714,8 @@
 	}
     }
 
-    if(entry->glyphset) {
-        if(entry->aa == AA_None && BitmapBitOrder(gdi_display) != MSBFirst) {
+    if(formatEntry->glyphset) {
+        if(format == AA_None && BitmapBitOrder(gdi_display) != MSBFirst) {
 	    unsigned char *byte = buf, c;
 	    int i = buflen;
 
@@ -703,13 +732,13 @@
 	}
 	gid = glyph;
         wine_tsx11_lock();
-	pXRenderAddGlyphs(gdi_display, entry->glyphset, &gid, &gi, 1,
+	pXRenderAddGlyphs(gdi_display, formatEntry->glyphset, &gid, &gi, 1,
 			  buf, buflen);
 	wine_tsx11_unlock();
 	HeapFree(GetProcessHeap(), 0, buf);
     } else {
-        entry->bitmaps[glyph] = buf;
-	memcpy(&entry->gis[glyph], &gi, sizeof(gi));
+        formatEntry->bitmaps[glyph] = buf;
+	memcpy(&formatEntry->gis[glyph], &gi, sizeof(gi));
     }
     return TRUE;
 }
@@ -977,6 +1006,7 @@
     const WORD *glyphs;
     POINT pt;
     gsCacheEntry *entry;
+    gsCacheEntryFormat *formatEntry;
     BOOL retv = FALSE;
     HDC hdc = physDev->hdc;
     int textPixel, backgroundPixel;
@@ -1277,13 +1307,17 @@
 
     EnterCriticalSection(&xrender_cs);
     entry = glyphsetCache + physDev->xrender->cache_index;
+    formatEntry = entry->format[entry->aa_default];
 
     for(idx = 0; idx < count; idx++) {
-        if(glyphs[idx] >= entry->nrealized || entry->realized[glyphs[idx]] == FALSE) {
-	    UploadGlyph(physDev, glyphs[idx]);
+        if( !formatEntry ) {
+	    UploadGlyph(physDev, glyphs[idx], entry->aa_default);
+            formatEntry = entry->format[entry->aa_default];
+        } else if( glyphs[idx] >= formatEntry->nrealized || formatEntry->realized[glyphs[idx]] == FALSE) {
+	    UploadGlyph(physDev, glyphs[idx], entry->aa_default);
 	}
     }
-
+    assert(formatEntry);
 
     TRACE("Writing %s at %ld,%ld\n", debugstr_wn(wstr,count),
           physDev->org.x + x, physDev->org.y + y);
@@ -1294,7 +1328,7 @@
 	    pXRenderCompositeString16(gdi_display, render_op,
 				      physDev->xrender->tile_pict,
 				      physDev->xrender->pict,
-				      entry->font_format, entry->glyphset,
+				      formatEntry->font_format, formatEntry->glyphset,
 				      0, 0, physDev->org.x + x, physDev->org.y + y,
 				      glyphs, count);
 
@@ -1304,7 +1338,7 @@
 	        pXRenderCompositeString16(gdi_display, render_op,
 					  physDev->xrender->tile_pict,
 					  physDev->xrender->pict,
-					  entry->font_format, entry->glyphset,
+					  formatEntry->font_format, formatEntry->glyphset,
 					  0, 0, physDev->org.x + x + xoff,
 					  physDev->org.y + y + yoff,
 					  glyphs + idx, 1);
@@ -1320,36 +1354,36 @@
         wine_tsx11_lock();
 	XSetForeground( gdi_display, physDev->gc, textPixel );
 
-	if(entry->aa == AA_None) {
+	if(entry->aa_default == AA_None) {
 	    for(idx = 0; idx < count; idx++) {
 	        SharpGlyphMono(physDev, physDev->org.x + x + xoff,
 			       physDev->org.y + y + yoff,
-			       entry->bitmaps[glyphs[idx]],
-			       &entry->gis[glyphs[idx]]);
+			       formatEntry->bitmaps[glyphs[idx]],
+			       &formatEntry->gis[glyphs[idx]]);
 		if(deltas) {
 		    offset += X11DRV_XWStoDS(physDev, deltas[idx]);
 		    xoff = offset * cosEsc;
 		    yoff = offset * -sinEsc;
 
 		} else {
-		    xoff += entry->gis[glyphs[idx]].xOff;
-		    yoff += entry->gis[glyphs[idx]].yOff;
+		    xoff += formatEntry->gis[glyphs[idx]].xOff;
+		    yoff += formatEntry->gis[glyphs[idx]].yOff;
 		}
 	    }
 	} else if(physDev->depth == 1) {
 	    for(idx = 0; idx < count; idx++) {
 	        SharpGlyphGray(physDev, physDev->org.x + x + xoff,
 			       physDev->org.y + y + yoff,
-			       entry->bitmaps[glyphs[idx]],
-			       &entry->gis[glyphs[idx]]);
+			       formatEntry->bitmaps[glyphs[idx]],
+			       &formatEntry->gis[glyphs[idx]]);
 		if(deltas) {
 		    offset += X11DRV_XWStoDS(physDev, deltas[idx]);
 		    xoff = offset * cosEsc;
 		    yoff = offset * -sinEsc;
 
 		} else {
-		    xoff += entry->gis[glyphs[idx]].xOff;
-		    yoff += entry->gis[glyphs[idx]].yOff;
+		    xoff += formatEntry->gis[glyphs[idx]].xOff;
+		    yoff += formatEntry->gis[glyphs[idx]].yOff;
 		}
 		    
 	    }
@@ -1368,21 +1402,21 @@
 	    TRACE("drawable %dx%d\n", w, h);
 
 	    for(idx = 0; idx < count; idx++) {
-	        if(extents.left > cur.x - entry->gis[glyphs[idx]].x)
-		    extents.left = cur.x - entry->gis[glyphs[idx]].x;
-		if(extents.top > cur.y - entry->gis[glyphs[idx]].y)
-		    extents.top = cur.y - entry->gis[glyphs[idx]].y;
-		if(extents.right < cur.x - entry->gis[glyphs[idx]].x + entry->gis[glyphs[idx]].width)
-		    extents.right = cur.x - entry->gis[glyphs[idx]].x + entry->gis[glyphs[idx]].width;
-		if(extents.bottom < cur.y - entry->gis[glyphs[idx]].y + entry->gis[glyphs[idx]].height)
-		    extents.bottom = cur.y - entry->gis[glyphs[idx]].y + entry->gis[glyphs[idx]].height;
+	        if(extents.left > cur.x - formatEntry->gis[glyphs[idx]].x)
+		    extents.left = cur.x - formatEntry->gis[glyphs[idx]].x;
+		if(extents.top > cur.y - formatEntry->gis[glyphs[idx]].y)
+		    extents.top = cur.y - formatEntry->gis[glyphs[idx]].y;
+		if(extents.right < cur.x - formatEntry->gis[glyphs[idx]].x + formatEntry->gis[glyphs[idx]].width)
+		    extents.right = cur.x - formatEntry->gis[glyphs[idx]].x + formatEntry->gis[glyphs[idx]].width;
+		if(extents.bottom < cur.y - formatEntry->gis[glyphs[idx]].y + formatEntry->gis[glyphs[idx]].height)
+		    extents.bottom = cur.y - formatEntry->gis[glyphs[idx]].y + formatEntry->gis[glyphs[idx]].height;
 		if(deltas) {
 		    offset += X11DRV_XWStoDS(physDev, deltas[idx]);
 		    cur.x = offset * cosEsc;
 		    cur.y = offset * -sinEsc;
 		} else {
-		    cur.x += entry->gis[glyphs[idx]].xOff;
-		    cur.y += entry->gis[glyphs[idx]].yOff;
+		    cur.x += formatEntry->gis[glyphs[idx]].xOff;
+		    cur.y += formatEntry->gis[glyphs[idx]].yOff;
 		}
 	    }
 	    TRACE("glyph extents %ld,%ld - %ld,%ld drawable x,y %ld,%ld\n", extents.left, extents.top,
@@ -1450,16 +1484,16 @@
 	    for(idx = 0; idx < count; idx++) {
 	        SmoothGlyphGray(image, xoff + image_off_x - extents.left,
 				yoff + image_off_y - extents.top,
-				entry->bitmaps[glyphs[idx]],
-				&entry->gis[glyphs[idx]],
+				formatEntry->bitmaps[glyphs[idx]],
+				&formatEntry->gis[glyphs[idx]],
 				physDev->textPixel);
 		if(deltas) {
 		    offset += X11DRV_XWStoDS(physDev, deltas[idx]);
 		    xoff = offset * cosEsc;
 		    yoff = offset * -sinEsc;
 		} else {
-		    xoff += entry->gis[glyphs[idx]].xOff;
-		    yoff += entry->gis[glyphs[idx]].yOff;
+		    xoff += formatEntry->gis[glyphs[idx]].xOff;
+		    yoff += formatEntry->gis[glyphs[idx]].yOff;
 		}
 		    
 	    }



More information about the wine-patches mailing list