Store the cache entry indices and not the ptrs.

Protect cache with a critical section.
This commit is contained in:
Huw D M Davies 2002-06-22 01:01:34 +00:00 committed by Alexandre Julliard
parent 75de8fe16c
commit 998ae970e5
1 changed files with 87 additions and 50 deletions

View File

@ -64,7 +64,7 @@ typedef struct
struct tagXRENDERINFO struct tagXRENDERINFO
{ {
gsCacheEntry *cacheEntry; int cache_index;
Picture pict; Picture pict;
Picture tile_pict; Picture tile_pict;
Pixmap tile_xpm; Pixmap tile_xpm;
@ -110,6 +110,9 @@ MAKE_FUNCPTR(XRenderSetPictureClipRectangles)
MAKE_FUNCPTR(XRenderQueryExtension) MAKE_FUNCPTR(XRenderQueryExtension)
#undef MAKE_FUNCPTR #undef MAKE_FUNCPTR
static CRITICAL_SECTION xrender_cs = CRITICAL_SECTION_INIT("xrender_cs");
/*********************************************************************** /***********************************************************************
* X11DRV_XRender_Init * X11DRV_XRender_Init
* *
@ -203,12 +206,14 @@ static void walk_cache(void)
{ {
int i; int i;
EnterCriticalSection(&xrender_cs);
for(i=mru; i >= 0; i = glyphsetCache[i].next) for(i=mru; i >= 0; i = glyphsetCache[i].next)
TRACE("item %d\n", i); TRACE("item %d\n", i);
LeaveCriticalSection(&xrender_cs);
} }
#endif #endif
static gsCacheEntry *LookupEntry(LFANDSIZE *plfsz) static int LookupEntry(LFANDSIZE *plfsz)
{ {
int i, prev_i = -1; int i, prev_i = -1;
@ -227,15 +232,15 @@ static gsCacheEntry *LookupEntry(LFANDSIZE *plfsz)
mru = i; mru = i;
} }
TRACE("found font in cache %d\n", i); TRACE("found font in cache %d\n", i);
return glyphsetCache + i; return i;
} }
prev_i = i; prev_i = i;
} }
TRACE("font not in cache\n"); TRACE("font not in cache\n");
return NULL; return -1;
} }
static gsCacheEntry *AllocEntry(void) static int AllocEntry(void)
{ {
int best = -1, prev_best = -1, i, prev_i = -1; int best = -1, prev_best = -1, i, prev_i = -1;
@ -249,7 +254,7 @@ static gsCacheEntry *AllocEntry(void)
mru = best; mru = best;
TRACE("empty space at %d, next lastfree = %d\n", mru, lastfree); TRACE("empty space at %d, next lastfree = %d\n", mru, lastfree);
return glyphsetCache + mru; return mru;
} }
for(i = mru; i >= 0; i = glyphsetCache[i].next) { for(i = mru; i >= 0; i = glyphsetCache[i].next) {
@ -279,7 +284,7 @@ static gsCacheEntry *AllocEntry(void)
} else { } else {
assert(mru == best); assert(mru == best);
} }
return glyphsetCache + mru; return mru;
} }
TRACE("Growing cache\n"); TRACE("Growing cache\n");
@ -300,22 +305,24 @@ static gsCacheEntry *AllocEntry(void)
glyphsetCache[best].next = mru; glyphsetCache[best].next = mru;
mru = best; mru = best;
TRACE("new free cache slot at %d\n", mru); TRACE("new free cache slot at %d\n", mru);
return glyphsetCache + mru; return mru;
} }
static gsCacheEntry *GetCacheEntry(LFANDSIZE *plfsz) static int GetCacheEntry(LFANDSIZE *plfsz)
{ {
XRenderPictFormat pf; XRenderPictFormat pf;
gsCacheEntry *ret; int ret;
gsCacheEntry *entry;
if((ret = LookupEntry(plfsz)) != NULL) return ret; if((ret = LookupEntry(plfsz)) != -1) return ret;
ret = AllocEntry(); ret = AllocEntry();
ret->lfsz = *plfsz; entry = glyphsetCache + ret;
assert(ret->nrealized == 0); entry->lfsz = *plfsz;
assert(entry->nrealized == 0);
if(antialias && abs(plfsz->lf.lfHeight) > 16) { if(antialias && abs(plfsz->lf.lfHeight * plfsz->xform.eM22) > 16) {
pf.depth = 8; pf.depth = 8;
pf.direct.alphaMask = 0xff; pf.direct.alphaMask = 0xff;
} else { } else {
@ -326,23 +333,24 @@ static gsCacheEntry *GetCacheEntry(LFANDSIZE *plfsz)
pf.direct.alpha = 0; pf.direct.alpha = 0;
wine_tsx11_lock(); wine_tsx11_lock();
ret->font_format = pXRenderFindFormat(gdi_display, entry->font_format = pXRenderFindFormat(gdi_display,
PictFormatType | PictFormatType |
PictFormatDepth | PictFormatDepth |
PictFormatAlpha | PictFormatAlpha |
PictFormatAlphaMask, PictFormatAlphaMask,
&pf, 0); &pf, 0);
ret->glyphset = pXRenderCreateGlyphSet(gdi_display, ret->font_format); entry->glyphset = pXRenderCreateGlyphSet(gdi_display, entry->font_format);
wine_tsx11_unlock(); wine_tsx11_unlock();
return ret; return ret;
} }
static void dec_ref_cache(gsCacheEntry *entry) static void dec_ref_cache(int index)
{ {
TRACE("dec'ing entry %d to %d\n", entry - glyphsetCache, entry->count - 1); assert(index >= 0);
assert(entry->count > 0); TRACE("dec'ing entry %d to %d\n", index, glyphsetCache[index].count - 1);
entry->count--; assert(glyphsetCache[index].count > 0);
glyphsetCache[index].count--;
} }
static void lfsz_calc_hash(LFANDSIZE *plfsz) static void lfsz_calc_hash(LFANDSIZE *plfsz)
@ -371,8 +379,10 @@ static void lfsz_calc_hash(LFANDSIZE *plfsz)
void X11DRV_XRender_Finalize(void) void X11DRV_XRender_Finalize(void)
{ {
FIXME("Free cached glyphsets\n"); FIXME("Free cached glyphsets\n");
#if 0
if (xrender_handle) wine_dlclose(xrender_handle, NULL, 0); if (xrender_handle) wine_dlclose(xrender_handle, NULL, 0);
xrender_handle = NULL; xrender_handle = NULL;
#endif
} }
@ -390,13 +400,16 @@ BOOL X11DRV_XRender_SelectFont(X11DRV_PDEVICE *physDev, HFONT hfont)
lfsz.xform = physDev->dc->xformWorld2Vport; lfsz.xform = physDev->dc->xformWorld2Vport;
lfsz_calc_hash(&lfsz); lfsz_calc_hash(&lfsz);
if(!physDev->xrender) EnterCriticalSection(&xrender_cs);
if(!physDev->xrender) {
physDev->xrender = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, physDev->xrender = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(*physDev->xrender)); sizeof(*physDev->xrender));
physDev->xrender->cache_index = -1;
else if(physDev->xrender->cacheEntry) }
dec_ref_cache(physDev->xrender->cacheEntry); else if(physDev->xrender->cache_index != -1)
physDev->xrender->cacheEntry = GetCacheEntry(&lfsz); dec_ref_cache(physDev->xrender->cache_index);
physDev->xrender->cache_index = GetCacheEntry(&lfsz);
LeaveCriticalSection(&xrender_cs);
return 0; return 0;
} }
@ -418,8 +431,10 @@ void X11DRV_XRender_DeleteDC(X11DRV_PDEVICE *physDev)
} }
wine_tsx11_unlock(); wine_tsx11_unlock();
if(physDev->xrender->cacheEntry) EnterCriticalSection(&xrender_cs);
dec_ref_cache(physDev->xrender->cacheEntry); if(physDev->xrender->cache_index != -1)
dec_ref_cache(physDev->xrender->cache_index);
LeaveCriticalSection(&xrender_cs);
HeapFree(GetProcessHeap(), 0, physDev->xrender); HeapFree(GetProcessHeap(), 0, physDev->xrender);
physDev->xrender = NULL; physDev->xrender = NULL;
@ -445,6 +460,11 @@ void X11DRV_XRender_UpdateDrawable(X11DRV_PDEVICE *physDev)
return; return;
} }
/************************************************************************
* UploadGlyph
*
* 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)
{ {
int buflen; int buflen;
@ -452,7 +472,7 @@ static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, int glyph)
Glyph gid; Glyph gid;
GLYPHMETRICS gm; GLYPHMETRICS gm;
XGlyphInfo gi; XGlyphInfo gi;
gsCacheEntry *entry = physDev->xrender->cacheEntry; gsCacheEntry *entry = glyphsetCache + physDev->xrender->cache_index;
UINT ggo_format = GGO_GLYPH_INDEX; UINT ggo_format = GGO_GLYPH_INDEX;
BOOL aa; BOOL aa;
@ -463,7 +483,6 @@ static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, int glyph)
entry->realized, entry->realized,
entry->nrealized * sizeof(BOOL)); entry->nrealized * sizeof(BOOL));
} }
entry->realized[glyph] = TRUE;
if(entry->font_format->depth == 8) { if(entry->font_format->depth == 8) {
aa = TRUE; aa = TRUE;
@ -475,8 +494,12 @@ 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) {
return FALSE; LeaveCriticalSection(&xrender_cs);
return FALSE;
}
entry->realized[glyph] = TRUE;
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);
@ -572,6 +595,9 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
LOGFONTW lf; LOGFONTW lf;
int render_op = PictOpOver; int render_op = PictOpOver;
WORD *glyphs; WORD *glyphs;
POINT pt;
gsCacheEntry *entry;
BOOL retv = FALSE;
HDC hdc = physDev->hdc; HDC hdc = physDev->hdc;
DC *dc = physDev->dc; DC *dc = physDev->dc;
@ -617,10 +643,7 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
rc = *lprect; rc = *lprect;
} }
rc.left = INTERNAL_XWPTODP(dc, rc.left, rc.top); LPtoDP(physDev->hdc, (POINT*)&rc, 2);
rc.top = INTERNAL_YWPTODP(dc, rc.left, rc.top);
rc.right = INTERNAL_XWPTODP(dc, rc.right, rc.bottom);
rc.bottom = INTERNAL_YWPTODP(dc, rc.right, rc.bottom);
if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;} if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;} if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
@ -642,12 +665,15 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
} }
if(count == 0) { if(count == 0) {
X11DRV_UnlockDIBSection( physDev, TRUE ); retv = TRUE;
return TRUE; goto done;
} }
x = INTERNAL_XWPTODP( dc, x, y ); pt.x = x;
y = INTERNAL_YWPTODP( dc, x, y ); pt.y = y;
LPtoDP(physDev->hdc, &pt, 1);
x = pt.x;
y = pt.y;
TRACE("real x,y %d,%d\n", x, y); TRACE("real x,y %d,%d\n", x, y);
@ -673,8 +699,11 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
switch( dc->textAlign & (TA_LEFT | TA_RIGHT | TA_CENTER) ) { switch( dc->textAlign & (TA_LEFT | TA_RIGHT | TA_CENTER) ) {
case TA_LEFT: case TA_LEFT:
if (dc->textAlign & TA_UPDATECP) { if (dc->textAlign & TA_UPDATECP) {
dc->CursPosX = INTERNAL_XDPTOWP( dc, x + xwidth, y - ywidth ); pt.x = x + xwidth;
dc->CursPosY = INTERNAL_YDPTOWP( dc, x + xwidth, y - ywidth ); pt.y = y - ywidth;
DPtoLP(physDev->hdc, &pt, 1);
dc->CursPosX = pt.x;
dc->CursPosY = pt.y;
} }
break; break;
@ -687,8 +716,11 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
x -= xwidth; x -= xwidth;
y += ywidth; y += ywidth;
if (dc->textAlign & TA_UPDATECP) { if (dc->textAlign & TA_UPDATECP) {
dc->CursPosX = INTERNAL_XDPTOWP( dc, x + xwidth, y - ywidth ); pt.x = x;
dc->CursPosY = INTERNAL_YDPTOWP( dc, x + xwidth, y - ywidth ); pt.y = y;
DPtoLP(physDev->hdc, &pt, 1);
dc->CursPosX = pt.x;
dc->CursPosY = pt.y;
} }
break; break;
} }
@ -802,9 +834,11 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
if((dc->bitsPerPixel == 1) && ((dc->textColor & 0xffffff) == 0)) if((dc->bitsPerPixel == 1) && ((dc->textColor & 0xffffff) == 0))
render_op = PictOpOutReverse; /* This gives us 'black' text */ render_op = PictOpOutReverse; /* This gives us 'black' text */
EnterCriticalSection(&xrender_cs);
entry = glyphsetCache + physDev->xrender->cache_index;
for(idx = 0; idx < count; idx++) { for(idx = 0; idx < count; idx++) {
if(glyphs[idx] >= physDev->xrender->cacheEntry->nrealized || if(glyphs[idx] >= entry->nrealized || entry->realized[glyphs[idx]] == FALSE) {
physDev->xrender->cacheEntry->realized[glyphs[idx]] == FALSE) {
UploadGlyph(physDev, glyphs[idx]); UploadGlyph(physDev, glyphs[idx]);
} }
} }
@ -818,8 +852,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,
physDev->xrender->cacheEntry->font_format, entry->font_format, entry->glyphset,
physDev->xrender->cacheEntry->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);
@ -829,8 +862,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,
physDev->xrender->cacheEntry->font_format, entry->font_format, entry->glyphset,
physDev->xrender->cacheEntry->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);
@ -840,6 +872,8 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
} }
} }
LeaveCriticalSection(&xrender_cs);
if(physDev->xrender->pict) { if(physDev->xrender->pict) {
pXRenderFreePicture(gdi_display, physDev->xrender->pict); pXRenderFreePicture(gdi_display, physDev->xrender->pict);
} }
@ -849,9 +883,12 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
if (flags & ETO_CLIPPED) if (flags & ETO_CLIPPED)
RestoreVisRgn16( hdc ); RestoreVisRgn16( hdc );
retv = TRUE;
done:
X11DRV_UnlockDIBSection( physDev, TRUE ); X11DRV_UnlockDIBSection( physDev, TRUE );
if(glyphs != wstr) HeapFree(GetProcessHeap(), 0, glyphs); if(glyphs != wstr) HeapFree(GetProcessHeap(), 0, glyphs);
return TRUE; return retv;
} }
#else /* HAVE_X11_EXTENSIONS_XRENDER_H */ #else /* HAVE_X11_EXTENSIONS_XRENDER_H */