summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhigang Gong <zhigang.gong@linux.intel.com>2012-06-15 08:46:24 +0800
committerZhigang Gong <zhigang.gong@linux.intel.com>2012-06-15 09:25:53 +0800
commit741a065f55fc78d624ef9c423d8c36d8d06a95c3 (patch)
tree8d6371201fbc51c30f5c22cee94e930933bc8f8c
parent996194140ce10b8c8b2b1cf8774c857fed4a6f24 (diff)
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>
-rw-r--r--src/glamor_glyphs.c226
1 files changed, 139 insertions, 87 deletions
diff --git a/src/glamor_glyphs.c b/src/glamor_glyphs.c
index dd3b4c6..362e46f 100644
--- a/src/glamor_glyphs.c
+++ b/src/glamor_glyphs.c
@@ -226,6 +226,7 @@ glamor_glyph_cache_upload_glyph(ScreenPtr screen,
PixmapPtr pGlyphPixmap = (PixmapPtr) pGlyphPicture->pDrawable;
PixmapPtr pCachePixmap = (PixmapPtr) cache->picture->pDrawable;
PixmapPtr scratch;
+ BoxRec box;
GCPtr gc;
gc = GetScratchGC(pCachePixmap->drawable.depth, screen);
@@ -236,54 +237,51 @@ glamor_glyph_cache_upload_glyph(ScreenPtr screen,
scratch = pGlyphPixmap;
if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth) {
+
scratch = glamor_create_pixmap(screen,
glyph->info.width,
glyph->info.height,
pCachePixmap->
drawable.depth, 0);
if (scratch) {
- if (pGlyphPixmap->drawable.depth !=
- pCachePixmap->drawable.depth) {
- PicturePtr picture;
- int error;
-
- picture =
- CreatePicture(0,
- &scratch->drawable,
- PictureMatchFormat
- (screen,
- pCachePixmap->
- drawable.depth,
- cache->picture->format),
- 0, NULL, serverClient,
- &error);
- if (picture) {
- ValidatePicture(picture);
- glamor_composite(PictOpSrc,
- pGlyphPicture,
- NULL, picture,
- 0, 0, 0, 0, 0,
- 0,
- glyph->info.width,
- glyph->info.height);
- FreePicture(picture, 0);
- }
- } else {
- glamor_copy_area(&pGlyphPixmap->drawable,
- &scratch->drawable,
- gc, 0, 0,
- glyph->info.width,
- glyph->info.height, 0, 0);
+ PicturePtr picture;
+ int error;
+
+ picture =
+ CreatePicture(0,
+ &scratch->drawable,
+ PictureMatchFormat
+ (screen,
+ pCachePixmap->
+ drawable.depth,
+ cache->picture->format),
+ 0, NULL, serverClient,
+ &error);
+ if (picture) {
+ ValidatePicture(picture);
+ glamor_composite(PictOpSrc,
+ pGlyphPicture,
+ NULL, picture,
+ 0, 0, 0, 0, 0,
+ 0,
+ glyph->info.width,
+ glyph->info.height);
+ FreePicture(picture, 0);
}
} else {
scratch = pGlyphPixmap;
}
}
- (*gc->ops->CopyArea)(&scratch->drawable, &pCachePixmap->drawable, gc,
- 0, 0, glyph->info.width, glyph->info.height, x,
- y);
-
+ box.x1 = x;
+ box.y1 = 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)
screen->DestroyPixmap(scratch);
@@ -550,11 +548,13 @@ glamor_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x,
*out_y = priv->y;
return cache->picture;
}
+typedef void (*glyphs_flush)(void * arg);
static glamor_glyph_cache_result_t
glamor_buffer_glyph(ScreenPtr screen,
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_get_screen_private(screen);
@@ -573,11 +573,18 @@ glamor_buffer_glyph(ScreenPtr screen,
&glamor_screen->glyphCaches[PICT_FORMAT_RGB
(glyph_picture->format) != 0];
- if (buffer->source && buffer->source != cache->picture)
- return GLAMOR_GLYPH_NEED_FLUSH;
+ if (buffer->source
+ && buffer->source != cache->picture
+ && glyphs_flush) {
+ (*glyphs_flush)(flush_arg);
+ glyphs_flush = NULL;
+ }
- if (buffer->count == GLYPH_BUFFER_SIZE)
- return GLAMOR_GLYPH_NEED_FLUSH;
+ if (buffer->count == GLYPH_BUFFER_SIZE
+ && glyphs_flush) {
+ (*glyphs_flush)(flush_arg);
+ glyphs_flush = NULL;
+ }
priv = glamor_glyph_get_private(glyph);
@@ -588,6 +595,8 @@ glamor_buffer_glyph(ScreenPtr screen,
if (buffer->source == NULL)
buffer->source = priv->cache->picture;
} else {
+ if (glyphs_flush)
+ (*glyphs_flush)(flush_arg);
source = glamor_glyph_cache(screen, glyph, &x, &y);
if (source != NULL) {
rect = &buffer->rects[buffer->count++];
@@ -597,8 +606,10 @@ glamor_buffer_glyph(ScreenPtr screen,
buffer->source = source;
} else {
source = GlyphPicture(glyph)[screen->myNum];
- if (buffer->source && buffer->source != source)
- return GLAMOR_GLYPH_NEED_FLUSH;
+ if (buffer->source
+ && buffer->source != source
+ && glyphs_flush)
+ (*glyphs_flush)(flush_arg);
buffer->source = source;
rect = &buffer->rects[buffer->count++];
@@ -617,16 +628,22 @@ glamor_buffer_glyph(ScreenPtr screen,
return GLAMOR_GLYPH_SUCCESS;
}
+struct glyphs_flush_mask_arg {
+ PicturePtr mask;
+ glamor_glyph_buffer_t *buffer;
+};
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
- glamor_composite_glyph_rects(PictOpAdd, buffer->source, NULL, mask,
- buffer->count, buffer->rects);
+ glamor_composite_glyph_rects(PictOpAdd, arg->buffer->source,
+ NULL, arg->mask,
+ arg->buffer->count,
+ arg->buffer->rects);
#endif
- buffer->count = 0;
- buffer->source = NULL;
+ arg->buffer->count = 0;
+ arg->buffer->source = NULL;
}
static void
@@ -651,7 +668,7 @@ glamor_glyphs_via_mask(CARD8 op,
XID component_alpha;
glamor_glyph_buffer_t buffer;
xRectangle fill_rect;
-
+ struct glyphs_flush_mask_arg arg;
GCPtr gc;
glamor_glyph_extents(nlist, list, glyphs, &extents);
@@ -704,18 +721,21 @@ glamor_glyphs_via_mask(CARD8 op,
n = list->len;
while (n--) {
glyph = *glyphs++;
-
if (glyph->info.width > 0
- && glyph->info.height > 0
- && glamor_buffer_glyph(screen, &buffer,
- glyph, x,
- y) ==
- GLAMOR_GLYPH_NEED_FLUSH) {
-
- glamor_glyphs_flush_mask(mask, &buffer);
+ && glyph->info.height > 0) {
+ glyphs_flush flush_func;
+ if (buffer.count) {
+ arg.mask = mask;
+ arg.buffer = &buffer;
+ flush_func = (glyphs_flush)glamor_glyphs_flush_mask;
+ }
+ else
+ flush_func = NULL;
glamor_buffer_glyph(screen, &buffer,
- glyph, x, y);
+ glyph, x, y,
+ flush_func,
+ (void*)&arg);
}
x += glyph->info.xOff;
@@ -724,8 +744,11 @@ glamor_glyphs_via_mask(CARD8 op,
list++;
}
- if (buffer.count)
- glamor_glyphs_flush_mask(mask, &buffer);
+ if (buffer.count) {
+ arg.mask = mask;
+ arg.buffer = &buffer;
+ glamor_glyphs_flush_mask(&arg);
+ }
x = extents.x1;
y = extents.y1;
@@ -739,27 +762,36 @@ glamor_glyphs_via_mask(CARD8 op,
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
-glamor_glyphs_flush_dst(CARD8 op,
- PicturePtr src,
- PicturePtr dst,
- glamor_glyph_buffer_t * buffer,
- INT16 x_src, INT16 y_src, INT16 x_dst, INT16 y_dst)
+glamor_glyphs_flush_dst(struct glyphs_flush_dst_arg * arg)
{
int i;
- glamor_composite_rect_t *rect = &buffer->rects[0];
- for (i = 0; i < buffer->count; i++, rect++) {
+ glamor_composite_rect_t *rect = &arg->buffer->rects[0];
+ for (i = 0; i < arg->buffer->count; i++, rect++) {
rect->x_mask = rect->x_src;
rect->y_mask = rect->y_src;
- rect->x_src = x_src + rect->x_dst - x_dst;
- rect->y_src = y_src + rect->y_dst - y_dst;
+ rect->x_src = arg->x_src + rect->x_dst - arg->x_dst;
+ rect->y_src = arg->y_src + rect->y_dst - arg->y_dst;
}
- glamor_composite_glyph_rects(op, src, buffer->source, dst,
- buffer->count, &buffer->rects[0]);
+ glamor_composite_glyph_rects(arg->op, arg->src,
+ arg->buffer->source, arg->dst,
+ arg->buffer->count,
+ &arg->buffer->rects[0]);
- buffer->count = 0;
- buffer->source = NULL;
+ arg->buffer->count = 0;
+ arg->buffer->source = NULL;
}
static void
@@ -776,6 +808,7 @@ glamor_glyphs_to_dst(CARD8 op,
int n;
GlyphPtr glyph;
glamor_glyph_buffer_t buffer;
+ struct glyphs_flush_dst_arg arg;
buffer.count = 0;
buffer.source = NULL;
@@ -787,17 +820,28 @@ glamor_glyphs_to_dst(CARD8 op,
glyph = *glyphs++;
if (glyph->info.width > 0
- && glyph->info.height > 0
- && glamor_buffer_glyph(screen, &buffer,
- glyph, x,
- y) ==
- GLAMOR_GLYPH_NEED_FLUSH) {
- glamor_glyphs_flush_dst(op, src, dst,
- &buffer, x_src,
- y_src, x_dst,
- y_dst);
- glamor_buffer_glyph(screen, &buffer,
- glyph, x, y);
+ && glyph->info.height > 0) {
+ glyphs_flush flush_func;
+
+ if (buffer.count) {
+ arg.op = op;
+ 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;
+ 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;
@@ -806,9 +850,17 @@ glamor_glyphs_to_dst(CARD8 op,
list++;
}
- if (buffer.count)
- glamor_glyphs_flush_dst(op, src, dst, &buffer,
- x_src, y_src, x_dst, y_dst);
+ if (buffer.count) {
+ arg.op = op;
+ 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