Split caching of antialiased and non-antialiased glyphs.

This commit is contained in:
Glenn Wurster 2005-01-24 19:08:02 +00:00 committed by Alexandre Julliard
parent c173f6a756
commit c3f8226ed1

View File

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