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