glamor_glyphs: Before get upload to cache flush is needed.

When we can't get a cache hit and have to evict one cache
entry to upload new picture, we need to flush the previous
buffer. Otherwise, we may get corrupt glyphs rendering result.

This is the reason why user-font-proxy may fail sometimes.

Signed-off-by: Zhigang Gong <zhigang.gong@linux.intel.com>
This commit is contained in:
Zhigang Gong 2012-06-15 08:46:24 +08:00 committed by Eric Anholt
parent 016995334e
commit 8656ddbbe7

View File

@ -226,6 +226,7 @@ glamor_glyph_cache_upload_glyph(ScreenPtr screen,
PixmapPtr pGlyphPixmap = (PixmapPtr) pGlyphPicture->pDrawable; PixmapPtr pGlyphPixmap = (PixmapPtr) pGlyphPicture->pDrawable;
PixmapPtr pCachePixmap = (PixmapPtr) cache->picture->pDrawable; PixmapPtr pCachePixmap = (PixmapPtr) cache->picture->pDrawable;
PixmapPtr scratch; PixmapPtr scratch;
BoxRec box;
GCPtr gc; GCPtr gc;
gc = GetScratchGC(pCachePixmap->drawable.depth, screen); gc = GetScratchGC(pCachePixmap->drawable.depth, screen);
@ -236,54 +237,51 @@ glamor_glyph_cache_upload_glyph(ScreenPtr screen,
scratch = pGlyphPixmap; scratch = pGlyphPixmap;
if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth) { if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth) {
scratch = glamor_create_pixmap(screen, scratch = glamor_create_pixmap(screen,
glyph->info.width, glyph->info.width,
glyph->info.height, glyph->info.height,
pCachePixmap-> pCachePixmap->
drawable.depth, 0); drawable.depth, 0);
if (scratch) { if (scratch) {
if (pGlyphPixmap->drawable.depth != PicturePtr picture;
pCachePixmap->drawable.depth) { int error;
PicturePtr picture;
int error;
picture = picture =
CreatePicture(0, CreatePicture(0,
&scratch->drawable, &scratch->drawable,
PictureMatchFormat PictureMatchFormat
(screen, (screen,
pCachePixmap-> pCachePixmap->
drawable.depth, drawable.depth,
cache->picture->format), cache->picture->format),
0, NULL, serverClient, 0, NULL, serverClient,
&error); &error);
if (picture) { if (picture) {
ValidatePicture(picture); ValidatePicture(picture);
glamor_composite(PictOpSrc, glamor_composite(PictOpSrc,
pGlyphPicture, pGlyphPicture,
NULL, picture, NULL, picture,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
glyph->info.width, glyph->info.width,
glyph->info.height); glyph->info.height);
FreePicture(picture, 0); FreePicture(picture, 0);
}
} else {
glamor_copy_area(&pGlyphPixmap->drawable,
&scratch->drawable,
gc, 0, 0,
glyph->info.width,
glyph->info.height, 0, 0);
} }
} else { } else {
scratch = pGlyphPixmap; scratch = pGlyphPixmap;
} }
} }
(*gc->ops->CopyArea)(&scratch->drawable, &pCachePixmap->drawable, gc, box.x1 = x;
0, 0, glyph->info.width, glyph->info.height, x, box.y1 = y;
y); box.x2 = x + glyph->info.width;
box.y2 = y + glyph->info.height;
glamor_copy_n_to_n_nf(&scratch->drawable,
&pCachePixmap->drawable, NULL,
&box, 1,
-x, -y,
FALSE, FALSE, 0, NULL);
if (scratch != pGlyphPixmap) if (scratch != pGlyphPixmap)
screen->DestroyPixmap(scratch); screen->DestroyPixmap(scratch);
@ -550,11 +548,13 @@ glamor_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x,
*out_y = priv->y; *out_y = priv->y;
return cache->picture; return cache->picture;
} }
typedef void (*glyphs_flush)(void * arg);
static glamor_glyph_cache_result_t static glamor_glyph_cache_result_t
glamor_buffer_glyph(ScreenPtr screen, glamor_buffer_glyph(ScreenPtr screen,
glamor_glyph_buffer_t * buffer, glamor_glyph_buffer_t * buffer,
GlyphPtr glyph, int x_glyph, int y_glyph) GlyphPtr glyph, int x_glyph, int y_glyph,
glyphs_flush glyphs_flush, void *flush_arg)
{ {
glamor_screen_private *glamor_screen = glamor_screen_private *glamor_screen =
glamor_get_screen_private(screen); glamor_get_screen_private(screen);
@ -573,11 +573,18 @@ glamor_buffer_glyph(ScreenPtr screen,
&glamor_screen->glyphCaches[PICT_FORMAT_RGB &glamor_screen->glyphCaches[PICT_FORMAT_RGB
(glyph_picture->format) != 0]; (glyph_picture->format) != 0];
if (buffer->source && buffer->source != cache->picture) if (buffer->source
return GLAMOR_GLYPH_NEED_FLUSH; && buffer->source != cache->picture
&& glyphs_flush) {
(*glyphs_flush)(flush_arg);
glyphs_flush = NULL;
}
if (buffer->count == GLYPH_BUFFER_SIZE) if (buffer->count == GLYPH_BUFFER_SIZE
return GLAMOR_GLYPH_NEED_FLUSH; && glyphs_flush) {
(*glyphs_flush)(flush_arg);
glyphs_flush = NULL;
}
priv = glamor_glyph_get_private(glyph); priv = glamor_glyph_get_private(glyph);
@ -588,6 +595,8 @@ glamor_buffer_glyph(ScreenPtr screen,
if (buffer->source == NULL) if (buffer->source == NULL)
buffer->source = priv->cache->picture; buffer->source = priv->cache->picture;
} else { } else {
if (glyphs_flush)
(*glyphs_flush)(flush_arg);
source = glamor_glyph_cache(screen, glyph, &x, &y); source = glamor_glyph_cache(screen, glyph, &x, &y);
if (source != NULL) { if (source != NULL) {
rect = &buffer->rects[buffer->count++]; rect = &buffer->rects[buffer->count++];
@ -597,8 +606,10 @@ glamor_buffer_glyph(ScreenPtr screen,
buffer->source = source; buffer->source = source;
} else { } else {
source = GlyphPicture(glyph)[screen->myNum]; source = GlyphPicture(glyph)[screen->myNum];
if (buffer->source && buffer->source != source) if (buffer->source
return GLAMOR_GLYPH_NEED_FLUSH; && buffer->source != source
&& glyphs_flush)
(*glyphs_flush)(flush_arg);
buffer->source = source; buffer->source = source;
rect = &buffer->rects[buffer->count++]; rect = &buffer->rects[buffer->count++];
@ -617,16 +628,22 @@ glamor_buffer_glyph(ScreenPtr screen,
return GLAMOR_GLYPH_SUCCESS; return GLAMOR_GLYPH_SUCCESS;
} }
struct glyphs_flush_mask_arg {
PicturePtr mask;
glamor_glyph_buffer_t *buffer;
};
static void static void
glamor_glyphs_flush_mask(PicturePtr mask, glamor_glyph_buffer_t * buffer) glamor_glyphs_flush_mask(struct glyphs_flush_mask_arg *arg)
{ {
#ifdef RENDER #ifdef RENDER
glamor_composite_glyph_rects(PictOpAdd, buffer->source, NULL, mask, glamor_composite_glyph_rects(PictOpAdd, arg->buffer->source,
buffer->count, buffer->rects); NULL, arg->mask,
arg->buffer->count,
arg->buffer->rects);
#endif #endif
buffer->count = 0; arg->buffer->count = 0;
buffer->source = NULL; arg->buffer->source = NULL;
} }
static void static void
@ -651,7 +668,7 @@ glamor_glyphs_via_mask(CARD8 op,
XID component_alpha; XID component_alpha;
glamor_glyph_buffer_t buffer; glamor_glyph_buffer_t buffer;
xRectangle fill_rect; xRectangle fill_rect;
struct glyphs_flush_mask_arg arg;
GCPtr gc; GCPtr gc;
glamor_glyph_extents(nlist, list, glyphs, &extents); glamor_glyph_extents(nlist, list, glyphs, &extents);
@ -704,18 +721,21 @@ glamor_glyphs_via_mask(CARD8 op,
n = list->len; n = list->len;
while (n--) { while (n--) {
glyph = *glyphs++; glyph = *glyphs++;
if (glyph->info.width > 0 if (glyph->info.width > 0
&& glyph->info.height > 0 && glyph->info.height > 0) {
&& glamor_buffer_glyph(screen, &buffer, glyphs_flush flush_func;
glyph, x, if (buffer.count) {
y) == arg.mask = mask;
GLAMOR_GLYPH_NEED_FLUSH) { arg.buffer = &buffer;
flush_func = (glyphs_flush)glamor_glyphs_flush_mask;
glamor_glyphs_flush_mask(mask, &buffer); }
else
flush_func = NULL;
glamor_buffer_glyph(screen, &buffer, glamor_buffer_glyph(screen, &buffer,
glyph, x, y); glyph, x, y,
flush_func,
(void*)&arg);
} }
x += glyph->info.xOff; x += glyph->info.xOff;
@ -724,8 +744,11 @@ glamor_glyphs_via_mask(CARD8 op,
list++; list++;
} }
if (buffer.count) if (buffer.count) {
glamor_glyphs_flush_mask(mask, &buffer); arg.mask = mask;
arg.buffer = &buffer;
glamor_glyphs_flush_mask(&arg);
}
x = extents.x1; x = extents.x1;
y = extents.y1; y = extents.y1;
@ -739,27 +762,36 @@ glamor_glyphs_via_mask(CARD8 op,
screen->DestroyPixmap(mask_pixmap); screen->DestroyPixmap(mask_pixmap);
} }
struct glyphs_flush_dst_arg {
CARD8 op;
PicturePtr src;
PicturePtr dst;
glamor_glyph_buffer_t * buffer;
INT16 x_src;
INT16 y_src;
INT16 x_dst;
INT16 y_dst;
};
static void static void
glamor_glyphs_flush_dst(CARD8 op, glamor_glyphs_flush_dst(struct glyphs_flush_dst_arg * arg)
PicturePtr src,
PicturePtr dst,
glamor_glyph_buffer_t * buffer,
INT16 x_src, INT16 y_src, INT16 x_dst, INT16 y_dst)
{ {
int i; int i;
glamor_composite_rect_t *rect = &buffer->rects[0]; glamor_composite_rect_t *rect = &arg->buffer->rects[0];
for (i = 0; i < buffer->count; i++, rect++) { for (i = 0; i < arg->buffer->count; i++, rect++) {
rect->x_mask = rect->x_src; rect->x_mask = rect->x_src;
rect->y_mask = rect->y_src; rect->y_mask = rect->y_src;
rect->x_src = x_src + rect->x_dst - x_dst; rect->x_src = arg->x_src + rect->x_dst - arg->x_dst;
rect->y_src = y_src + rect->y_dst - y_dst; rect->y_src = arg->y_src + rect->y_dst - arg->y_dst;
} }
glamor_composite_glyph_rects(op, src, buffer->source, dst, glamor_composite_glyph_rects(arg->op, arg->src,
buffer->count, &buffer->rects[0]); arg->buffer->source, arg->dst,
arg->buffer->count,
&arg->buffer->rects[0]);
buffer->count = 0; arg->buffer->count = 0;
buffer->source = NULL; arg->buffer->source = NULL;
} }
static void static void
@ -776,6 +808,7 @@ glamor_glyphs_to_dst(CARD8 op,
int n; int n;
GlyphPtr glyph; GlyphPtr glyph;
glamor_glyph_buffer_t buffer; glamor_glyph_buffer_t buffer;
struct glyphs_flush_dst_arg arg;
buffer.count = 0; buffer.count = 0;
buffer.source = NULL; buffer.source = NULL;
@ -787,17 +820,28 @@ glamor_glyphs_to_dst(CARD8 op,
glyph = *glyphs++; glyph = *glyphs++;
if (glyph->info.width > 0 if (glyph->info.width > 0
&& glyph->info.height > 0 && glyph->info.height > 0) {
&& glamor_buffer_glyph(screen, &buffer, glyphs_flush flush_func;
glyph, x,
y) == if (buffer.count) {
GLAMOR_GLYPH_NEED_FLUSH) { arg.op = op;
glamor_glyphs_flush_dst(op, src, dst, arg.src = src;
&buffer, x_src, arg.dst = dst;
y_src, x_dst, arg.buffer = &buffer;
y_dst); arg.x_src = x_src;
glamor_buffer_glyph(screen, &buffer, arg.y_src = y_src;
glyph, x, y); arg.x_dst = x_dst;
arg.y_dst = y_dst;
flush_func = (glyphs_flush)glamor_glyphs_flush_dst;
} else
flush_func = NULL;
glamor_buffer_glyph(screen,
&buffer,
glyph, x, y,
flush_func,
(void*)&arg);
} }
x += glyph->info.xOff; x += glyph->info.xOff;
@ -806,9 +850,17 @@ glamor_glyphs_to_dst(CARD8 op,
list++; list++;
} }
if (buffer.count) if (buffer.count) {
glamor_glyphs_flush_dst(op, src, dst, &buffer, arg.op = op;
x_src, y_src, x_dst, y_dst); arg.src = src;
arg.dst = dst;
arg.buffer = &buffer;
arg.x_src = x_src;
arg.y_src = y_src;
arg.x_dst = x_dst;
arg.y_dst = y_dst;
glamor_glyphs_flush_dst(&arg);
}
} }
static Bool static Bool