[PATCH 1/2] glamor: Fix bad rendering of glyphs after an a1 glyph upload.

Eric Anholt eric at anholt.net
Wed Jul 1 14:56:39 PDT 2015


Fixes regressions since my "don't make an FBO for the glyph atlas"
change.  The a1 upload was a fallback, as I expected.  However,
fallback reads use glReadPixels() because there's no
glGetTexSubImage2D() to match glTexSubImage2D().  We were just binding
the 0 FBO value, so the glReadPixels() would throw a GL error instead
of getting any data.  After the fallback was done we'd write back the
undefined data to the atlas, blowing away the entire rest of the atlas
because we didn't specify any bounds on our prepare.

To fix the fallbacks to actually work, we'd need a prepare path that
allocates some memory memory do a full glGetTexImage() into, then
memcpy out of that.  Instead, just dodge the general fallback by
implementing the specific upload we need to do here, which should also
be *much* faster at uploading a1 glyphs since it's not
readpixels/texsubimaging back and forth.

Signed-off-by: Eric Anholt <eric at anholt.net>
---
 glamor/glamor_composite_glyphs.c | 67 ++++++++++++++++++++++------------------
 1 file changed, 37 insertions(+), 30 deletions(-)

diff --git a/glamor/glamor_composite_glyphs.c b/glamor/glamor_composite_glyphs.c
index 1f0d75e..f5a54c9 100644
--- a/glamor/glamor_composite_glyphs.c
+++ b/glamor/glamor_composite_glyphs.c
@@ -64,45 +64,52 @@ glamor_copy_glyph(PixmapPtr     glyph_pixmap,
         .x2 = glyph_draw->width,
         .y2 = glyph_draw->height,
     };
+    void *data = glyph_pixmap->devPrivate.ptr;
+    uint32_t stride = glyph_pixmap->devKind;
 
-    if (glyph_pixmap->drawable.bitsPerPixel == atlas_draw->bitsPerPixel) {
-        glamor_upload_boxes((PixmapPtr) atlas_draw,
-                            &box, 1,
-                            0, 0,
-                            x, y,
-                            glyph_pixmap->devPrivate.ptr,
-                            glyph_pixmap->devKind);
-    } else {
-        GCPtr scratch_gc = GetScratchGC(atlas_draw->depth, atlas_draw->pScreen);
-        ChangeGCVal changes[2];
-        if (!scratch_gc)
-            return;
-
+    if (glyph_pixmap->drawable.bitsPerPixel != atlas_draw->bitsPerPixel) {
         /* If we're dealing with 1-bit glyphs, we upload them to
          * the cache as normal 8-bit alpha, since that's what GL
          * can handle.
          */
+        uint32_t temp_stride = ALIGN(glyph_draw->width, 4);
+        uint16_t temp_x, temp_y;
+        uint8_t *temp_data;
+
         assert(glyph_draw->depth == 1);
         assert(atlas_draw->depth == 8);
 
-        changes[0].val = 0xff;
-        changes[1].val = 0x00;
-        if (ChangeGC(NullClient, scratch_gc,
-                     GCForeground|GCBackground, changes) != Success)
-            goto bail_gc;
-        ValidateGC(atlas_draw, scratch_gc);
-
-        (*scratch_gc->ops->CopyPlane)(glyph_draw,
-                                      atlas_draw,
-                                      scratch_gc,
-                                      0, 0,
-                                      glyph_draw->width,
-                                      glyph_draw->height,
-                                      x, y, 0x1);
-
-    bail_gc:
-        FreeScratchGC(scratch_gc);
+        temp_data = malloc(glyph_draw->height * temp_stride);
+        if (!data) {
+            LogMessage(X_WARNING,
+                       "glamor%d: Failed allocate glyph temp\n",
+                       atlas_draw->pScreen->myNum);
+            return;
+        }
+
+        for (temp_y = 0; temp_y < glyph_draw->height; temp_y++) {
+            uint8_t *glyph_row = &((uint8_t *)data)[temp_y * stride];
+            uint8_t *temp_row = &temp_data[temp_y * temp_stride];
+            for (temp_x = 0; temp_x < glyph_draw->width; temp_x++) {
+                if (glyph_row[temp_x / 8] & (1 << (temp_x % 8)))
+                    temp_row[temp_x] = 0xff;
+                else
+                    temp_row[temp_x] = 0x00;
+            }
+        }
+
+        data = temp_data;
+        stride = temp_stride;
     }
+
+    glamor_upload_boxes((PixmapPtr) atlas_draw,
+                        &box, 1,
+                        0, 0,
+                        x, y,
+                        data, stride);
+
+    if (data != glyph_pixmap->devPrivate.ptr)
+        free(data);
 }
 
 static Bool
-- 
2.1.4



More information about the xorg-devel mailing list