commit b0d2e010316d710eb4052963de3a1e2dc7ba356e
Author: Keith Packard <kei...@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 <ch...@chris-wilson.co.uk>
Cc: Keith Packard <kei...@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

_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to