summaryrefslogtreecommitdiff
path: root/uxa/uxa-glyphs.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-05-12 12:01:46 +0100
committerOwain G. Ainsworth <oga@openbsd.org>2010-05-17 20:27:27 +0100
commitc2b087a66104dbd7bae6b4afd53c8d9ad6b6ecb6 (patch)
tree3b6838e570d20c810b44bd005dfd5d6451c6dd19 /uxa/uxa-glyphs.c
parent390a3c653b707e1fb1b2ad141a871bcd82cbc610 (diff)
uxa: Avoid glyph ping-pong with !offscreen destination
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> (cherry picked from commit 6c27f6e4f76b97df71094acf25083b2922966b42) Signed-off-by: Owain G. Ainsworth <oga@openbsd.org>
Diffstat (limited to 'uxa/uxa-glyphs.c')
-rw-r--r--uxa/uxa-glyphs.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/uxa/uxa-glyphs.c b/uxa/uxa-glyphs.c
index 5c233216..8c53a885 100644
--- a/uxa/uxa-glyphs.c
+++ b/uxa/uxa-glyphs.c
@@ -735,6 +735,120 @@ uxa_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs)
return FALSE;
}
+static void
+uxa_check_glyphs(CARD8 op,
+ PicturePtr src,
+ PicturePtr dst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
+{
+ int screen = dst->pDrawable->pScreen->myNum;
+ pixman_image_t *image;
+ PixmapPtr scratch;
+ PicturePtr mask;
+ int width = 0, height = 0;
+ int x, y, n;
+ int xDst = list->xOff, yDst = list->yOff;
+ BoxRec extents = { 0, 0, 0, 0 };
+
+ if (maskFormat) {
+ pixman_format_code_t format;
+ CARD32 component_alpha;
+ int error;
+
+ uxa_glyph_extents(nlist, list, glyphs, &extents);
+ if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
+ return;
+
+ width = extents.x2 - extents.x1;
+ height = extents.y2 - extents.y1;
+
+ format = maskFormat->format |
+ (BitsPerPixel(maskFormat->depth) << 24);
+ image =
+ pixman_image_create_bits(format, width, height, NULL, 0);
+ if (!image)
+ return;
+
+ scratch = GetScratchPixmapHeader(dst->pDrawable->pScreen, width, height,
+ PIXMAN_FORMAT_DEPTH(format),
+ PIXMAN_FORMAT_BPP(format),
+ pixman_image_get_stride(image),
+ pixman_image_get_data(image));
+
+ if (!scratch) {
+ pixman_image_unref(image);
+ return;
+ }
+
+ component_alpha = NeedsComponent(maskFormat->format);
+ mask = CreatePicture(0, &scratch->drawable,
+ maskFormat, CPComponentAlpha,
+ &component_alpha, serverClient, &error);
+ if (!mask) {
+ FreeScratchPixmapHeader(scratch);
+ pixman_image_unref(image);
+ return;
+ }
+
+ x = -extents.x1;
+ y = -extents.y1;
+ } else {
+ mask = dst;
+ x = 0;
+ y = 0;
+ }
+
+ while (nlist--) {
+ x += list->xOff;
+ y += list->yOff;
+ n = list->len;
+ while (n--) {
+ GlyphPtr glyph = *glyphs++;
+ PicturePtr g = GlyphPicture(glyph)[screen];
+ if (g) {
+ if (maskFormat) {
+ CompositePicture(PictOpAdd, g, NULL, mask,
+ 0, 0,
+ 0, 0,
+ x - glyph->info.x,
+ y - glyph->info.y,
+ glyph->info.width,
+ glyph->info.height);
+ } else {
+ CompositePicture(op, src, g, dst,
+ xSrc + (x - glyph->info.x) - xDst,
+ ySrc + (y - glyph->info.y) - yDst,
+ 0, 0,
+ x - glyph->info.x,
+ y - glyph->info.y,
+ glyph->info.width,
+ glyph->info.height);
+ }
+ }
+
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ }
+ list++;
+ }
+
+ if (maskFormat) {
+ x = extents.x1;
+ y = extents.y1;
+ CompositePicture(op, src, mask, dst,
+ xSrc + x - xDst,
+ ySrc + y - yDst,
+ 0, 0,
+ x, y,
+ width, height);
+ FreePicture(mask, 0);
+ FreeScratchPixmapHeader(scratch);
+ pixman_image_unref(image);
+ }
+}
+
void
uxa_glyphs(CARD8 op,
PicturePtr pSrc,
@@ -757,6 +871,11 @@ uxa_glyphs(CARD8 op,
CARD32 component_alpha;
uxa_glyph_buffer_t buffer;
+ if (!uxa_drawable_is_offscreen(pDst->pDrawable)) {
+ uxa_check_glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
+ return;
+ }
+
/* If we don't have a mask format but all the glyphs have the same format
* and don't intersect, use the glyph format as mask format for the full
* benefits of the glyph cache.