[PATCH] glamor/glyphs: Fix rendering regressions

Chris Wilson chris at chris-wilson.co.uk
Mon May 18 07:28:15 PDT 2015


commit b0d2e010316d710eb4052963de3a1e2dc7ba356e
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Oct 10 09:25:51 2014 +0200

    glamor: Replace CompositeGlyphs code [v2]

introduced a number of regressions in both ignoring the effect of
applying the user requested mask on the glyphs (for example to correctly
render overlapping glyphs and to apply quantisation effects, e.g. mixing
different filters) along with incorrectly computing the glyph source
coordinates.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Keith Packard <keithp at keithp.com>
---
 glamor/glamor_composite_glyphs.c | 130 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 122 insertions(+), 8 deletions(-)

diff --git a/glamor/glamor_composite_glyphs.c b/glamor/glamor_composite_glyphs.c
index 39ed854..3a21eed 100644
--- a/glamor/glamor_composite_glyphs.c
+++ b/glamor/glamor_composite_glyphs.c
@@ -316,6 +316,54 @@ glamor_atlas_for_glyph(glamor_screen_private *glamor_priv, DrawablePtr drawable)
         return glamor_priv->glyph_atlas_a;
 }
 
+static void
+GlyphExtents(int nlist, GlyphListPtr list, GlyphPtr * glyphs, BoxPtr extents)
+{
+    int x1, x2, y1, y2;
+    int n;
+    GlyphPtr glyph;
+    int x, y;
+
+    x = 0;
+    y = 0;
+    extents->x1 = MAXSHORT;
+    extents->x2 = MINSHORT;
+    extents->y1 = MAXSHORT;
+    extents->y2 = MINSHORT;
+    while (nlist--) {
+        x += list->xOff;
+        y += list->yOff;
+        n = list->len;
+        list++;
+        while (n--) {
+            glyph = *glyphs++;
+            x1 = x - glyph->info.x;
+            if (x1 < MINSHORT)
+                x1 = MINSHORT;
+            y1 = y - glyph->info.y;
+            if (y1 < MINSHORT)
+                y1 = MINSHORT;
+            x2 = x1 + glyph->info.width;
+            if (x2 > MAXSHORT)
+                x2 = MAXSHORT;
+            y2 = y1 + glyph->info.height;
+            if (y2 > MAXSHORT)
+                y2 = MAXSHORT;
+            if (x1 < extents->x1)
+                extents->x1 = x1;
+            if (x2 > extents->x2)
+                extents->x2 = x2;
+            if (y1 < extents->y1)
+                extents->y1 = y1;
+            if (y2 > extents->y2)
+                extents->y2 = y2;
+            x += glyph->info.xOff;
+            y += glyph->info.yOff;
+        }
+    }
+}
+
+#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
 void
 glamor_composite_glyphs(CARD8 op,
                         PicturePtr src,
@@ -329,6 +377,8 @@ glamor_composite_glyphs(CARD8 op,
     GLshort *v = NULL;
     DrawablePtr drawable = dst->pDrawable;
     ScreenPtr screen = drawable->pScreen;
+    PicturePtr mask = NULL;
+    PicturePtr glyph_dst, glyph_src;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     glamor_program *prog = NULL;
     PicturePtr glyph_pict = NULL;
@@ -341,6 +391,57 @@ glamor_composite_glyphs(CARD8 op,
     int glyph_max_dim = glamor_priv->glyph_max_dim;
     int nglyph = 0;
     int screen_num = screen->myNum;
+    CARD32 glyph_op;
+    BoxRec extents;
+
+    if (glyph_format) {
+	    xRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff };
+	    CARD32 component_alpha;
+	    PixmapPtr pixmap;
+	    int error;
+
+	    GlyphExtents(nlist, list, glyphs, &extents);
+	    pixmap = screen->CreatePixmap(screen,
+					  extents.x2 - extents.x1,
+					  extents.y2 - extents.y1,
+					  glyph_format->depth,
+					  CREATE_PIXMAP_USAGE_SCRATCH);
+	    if (!pixmap)
+		    return;
+
+	    component_alpha = NeedsComponent(glyph_format->format);
+	    mask = CreatePicture(0, &pixmap->drawable,
+				 glyph_format,
+				 CPComponentAlpha, &component_alpha,
+				 serverClient, &error);
+	    screen->DestroyPixmap(pixmap);
+	    if (!mask)
+		    return;
+
+	    glyph_src = CreateSolidPicture(0, &white, &error);
+
+	    ValidatePicture(glyph_src);
+	    ValidatePicture(mask);
+
+	    glamor_composite(PictOpClear, glyph_src, NULL, mask,
+			     0, 0,
+			     0, 0,
+			     0, 0,
+			     extents.x2 - extents.x1,
+			     extents.y2 - extents.y1);
+
+	    glyph_dst = mask;
+	    x += -extents.x1;
+	    y += -extents.y1;
+	    glyph_op = PictOpAdd;
+    } else {
+	    glyph_dst = dst;
+	    glyph_src = src;
+	    glyph_op = op;
+    }
+
+    x_src += list->xOff;
+    y_src += list->yOff;
 
     for (n = 0; n < nlist; n++)
         nglyph += list[n].len;
@@ -373,12 +474,13 @@ glamor_composite_glyphs(CARD8 op,
                                 (glyph_pix_priv != 0 && glyph_pix_priv->type != GLAMOR_MEMORY)))
                 {
                     if (glyphs_queued) {
-                        glamor_glyphs_flush(op, src, dst, prog, glyph_atlas, glyphs_queued);
+                        glamor_glyphs_flush(glyph_op, glyph_src, glyph_dst,
+					    prog, glyph_atlas, glyphs_queued);
                         glyphs_queued = 0;
                     }
                 bail_one:
-                    glamor_composite(op, src, glyph_pict, dst,
-                                     x_src + (x - glyph->info.x), (y - glyph->info.y),
+                    glamor_composite(glyph_op, glyph_src, glyph_pict, glyph_dst,
+                                     x_src + (x - glyph->info.x), y_src + (y - glyph->info.y),
                                      0, 0,
                                      x - glyph->info.x, y - glyph->info.y,
                                      glyph_draw->width, glyph_draw->height);
@@ -390,7 +492,7 @@ glamor_composite_glyphs(CARD8 op,
                      */
                     if (_X_UNLIKELY(next_atlas != glyph_atlas)) {
                         if (glyphs_queued) {
-                            glamor_glyphs_flush(op, src, dst, prog, glyph_atlas, glyphs_queued);
+                            glamor_glyphs_flush(glyph_op, glyph_src, glyph_dst, prog, glyph_atlas, glyphs_queued);
                             glyphs_queued = 0;
                         }
                         glyph_atlas = next_atlas;
@@ -401,7 +503,8 @@ glamor_composite_glyphs(CARD8 op,
                     if (_X_UNLIKELY(glyph_priv->serial != glyph_atlas->serial)) {
                         if (!glamor_glyph_can_add(glyph_atlas, glyph_atlas_dim, glyph_draw)) {
                             if (glyphs_queued) {
-                                glamor_glyphs_flush(op, src, dst, prog, glyph_atlas, glyphs_queued);
+                                glamor_glyphs_flush(glyph_op, glyph_src, glyph_dst,
+						    prog, glyph_atlas, glyphs_queued);
                                 glyphs_queued = 0;
                             }
                             if (glyph_atlas->atlas) {
@@ -418,12 +521,12 @@ glamor_composite_glyphs(CARD8 op,
                      */
                     if (_X_UNLIKELY(glyphs_queued == 0)) {
                         if (glamor_glyph_use_130(glamor_priv))
-                            prog = glamor_setup_program_render(op, src, glyph_pict, dst,
+                            prog = glamor_setup_program_render(glyph_op, glyph_src, glyph_pict, glyph_dst,
                                                                glyphs_program,
                                                                &glamor_facet_composite_glyphs_130,
                                                                glamor_priv->glyph_defines);
                         else
-                            prog = glamor_setup_program_render(op, src, glyph_pict, dst,
+                            prog = glamor_setup_program_render(glyph_op, glyph_src, glyph_pict, glyph_dst,
                                                                glyphs_program,
                                                                &glamor_facet_composite_glyphs_120,
                                                                glamor_priv->glyph_defines);
@@ -478,7 +581,18 @@ glamor_composite_glyphs(CARD8 op,
     }
 
     if (glyphs_queued)
-        glamor_glyphs_flush(op, src, dst, prog, glyph_atlas, glyphs_queued);
+        glamor_glyphs_flush(glyph_op, glyph_src, glyph_dst,
+			    prog, glyph_atlas, glyphs_queued);
+
+    if (mask) {
+	    glamor_composite(op, src, mask, dst,
+			     x_src + extents.x1, y_src + extents.y1,
+			     0, 0,
+			     extents.x1, extents.y1,
+			     extents.x2 - extents.x1, extents.y2 - extents.y1);
+	    FreePicture(mask, 0);
+	    FreePicture(glyph_src, 0);
+    }
 
     return;
 }
-- 
2.1.4



More information about the xorg-devel mailing list