[PATCH xserver 1/3] glamor: Accelerate PutImage for XYBitmap format

Keith Packard keithp at keithp.com
Sat Oct 1 05:44:00 UTC 2016


Upload the bitmap and use a program like TE Text program to draw it,
avoiding fallbacks for this case.

Signed-off-by: Keith Packard <keithp at keithp.com>
---
 glamor/glamor_image.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++---
 glamor/glamor_priv.h  |   3 +
 2 files changed, 176 insertions(+), 10 deletions(-)

diff --git a/glamor/glamor_image.c b/glamor/glamor_image.c
index 3158749..798277b 100644
--- a/glamor/glamor_image.c
+++ b/glamor/glamor_image.c
@@ -29,8 +29,8 @@
  */
 
 static Bool
-glamor_put_image_gl(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
-                    int w, int h, int leftPad, int format, char *bits)
+glamor_put_image_zpixmap_gl(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
+                            int w, int h, char *bits)
 {
     ScreenPtr screen = drawable->pScreen;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
@@ -52,12 +52,6 @@ glamor_put_image_gl(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
     if (!glamor_pm_is_solid(gc->depth, gc->planemask))
         goto bail;
 
-    if (format == XYPixmap && drawable->depth == 1 && leftPad == 0)
-        format = ZPixmap;
-
-    if (format != ZPixmap)
-        goto bail;
-
     x += drawable->x;
     y += drawable->y;
     box.x1 = x;
@@ -84,6 +78,165 @@ bail:
     return FALSE;
 }
 
+static const char vs_vars_put_bitmap[] =
+    "attribute vec4 primitive;\n"
+    "attribute vec2 source;\n"
+    "varying vec2 image_pos;\n";
+
+static const char vs_exec_put_bitmap[] =
+    "       vec2 pos = primitive.zw * vec2(gl_VertexID&1, (gl_VertexID&2)>>1);\n"
+    GLAMOR_POS(gl_Position, (primitive.xy + pos))
+    "       image_pos = source + pos;\n";
+
+static const char fs_vars_put_bitmap[] =
+    "varying vec2 image_pos;\n";
+
+static Bool
+glamor_put_bitmap_use(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
+{
+    if (!glamor_set_solid(pixmap, gc, TRUE, prog->fg_uniform))
+        return FALSE;
+    glamor_set_color(pixmap, gc->bgPixel, prog->bg_uniform);
+    return TRUE;
+}
+
+static const char fs_exec_put_bitmap[] =
+    "       ivec2 itile_texture = ivec2(image_pos);\n"
+    "       uint x = uint(itile_texture.x & 7);\n"
+    "       itile_texture.x >>= 3;\n"
+    "       uint texel = texelFetch(font, itile_texture, 0).x;\n"
+    "       uint bit = (texel >> x) & uint(1);\n"
+    "       if (bit == uint(0))\n"
+    "               gl_FragColor = bg;\n"
+    "       else\n"
+    "               gl_FragColor = fg;\n";
+
+const glamor_facet glamor_facet_put_bitmap = {
+    .name = "put_bitmap",
+    .version = 130,
+    .vs_vars = vs_vars_put_bitmap,
+    .vs_exec = vs_exec_put_bitmap,
+    .fs_vars = fs_vars_put_bitmap,
+    .fs_exec = fs_exec_put_bitmap,
+    .locations = glamor_program_location_fg | glamor_program_location_bg | glamor_program_location_font,
+    .source_name = "source",
+    .use = glamor_put_bitmap_use,
+};
+
+/*
+ * Use a program like the terminal emulator text program to fetch single
+ * bits from the source image and expand them to full pixel values.
+ */
+static Bool
+glamor_put_image_xybitmap_gl(DrawablePtr drawable, GCPtr gc, int x, int y,
+                             int w, int h, int leftPad, char *bits)
+{
+    ScreenPtr screen = drawable->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
+    uint32_t byte_stride = BitmapBytePad(w + leftPad);
+    GLuint texture_id;
+    glamor_program *prog;
+    char *vbo_offset;
+    GLshort *v;
+    int box_index;
+    int off_x, off_y;
+    Bool ret = FALSE;
+
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+        return FALSE;
+
+    glamor_make_current(glamor_priv);
+
+    prog = &glamor_priv->put_bitmap_prog;
+
+    if (prog->failed)
+        goto bail;
+
+    if (!prog->prog) {
+        if (!glamor_build_program(screen, prog, &glamor_facet_put_bitmap, NULL, NULL, NULL))
+            goto bail;
+    }
+
+    if (!glamor_use_program(pixmap, gc, prog, NULL))
+        goto bail;
+
+    glGenTextures(1, &texture_id);
+    glActiveTexture(GL_TEXTURE1);
+    glBindTexture(GL_TEXTURE_2D, texture_id);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    glamor_priv->suppress_gl_out_of_memory_logging = true;
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, byte_stride, h,
+                 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, bits);
+    glamor_priv->suppress_gl_out_of_memory_logging = false;
+    if (glGetError() == GL_OUT_OF_MEMORY)
+        goto bail;
+
+    glUniform1i(prog->font_uniform, 1);
+
+    /* Set up the vertex buffers for the font and destination */
+
+    v = glamor_get_vbo_space(drawable->pScreen, (6 * sizeof (GLshort)), &vbo_offset);
+
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1);
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 4, GL_SHORT, GL_FALSE,
+                          6 * sizeof (GLshort), vbo_offset);
+
+    glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 1);
+    glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_SHORT, GL_FALSE,
+                          6 * sizeof (GLshort), vbo_offset + 4 * sizeof (GLshort));
+
+    v[0] = x;
+    v[1] = y;
+    v[2] = w;
+    v[3] = h;
+    v[4] = leftPad;
+    v[5] = 0;
+
+    glamor_put_vbo_space(drawable->pScreen);
+    glEnable(GL_SCISSOR_TEST);
+
+    glamor_pixmap_loop(pixmap_priv, box_index) {
+        BoxPtr box = RegionRects(gc->pCompositeClip);
+        int nbox = RegionNumRects(gc->pCompositeClip);
+
+        glamor_set_destination_drawable(drawable, box_index, TRUE, FALSE,
+                                        prog->matrix_uniform,
+                                        &off_x, &off_y);
+
+        /* Run over the clip list, drawing the glyphs
+         * in each box
+         */
+
+        while (nbox--) {
+            glScissor(box->x1 + off_x,
+                      box->y1 + off_y,
+                      box->x2 - box->x1,
+                      box->y2 - box->y1);
+            box++;
+            glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
+        }
+    }
+    glDisable(GL_SCISSOR_TEST);
+
+    glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 0);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+
+    ret = TRUE;
+bail:
+    glDeleteTextures(1, &texture_id);
+    return ret;
+}
+
 static void
 glamor_put_image_bail(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
                       int w, int h, int leftPad, int format, char *bits)
@@ -97,8 +250,18 @@ void
 glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
                  int w, int h, int leftPad, int format, char *bits)
 {
-    if (glamor_put_image_gl(drawable, gc, depth, x, y, w, h, leftPad, format, bits))
-        return;
+    switch (format) {
+    case ZPixmap:
+        if (glamor_put_image_zpixmap_gl(drawable, gc, depth, x, y, w, h, bits))
+            return;
+        break;
+    case XYPixmap:
+        break;
+    case XYBitmap:
+        if (glamor_put_image_xybitmap_gl(drawable, gc, x, y, w, h, leftPad, bits))
+            return;
+        break;
+    }
     glamor_put_image_bail(drawable, gc, depth, x, y, w, h, leftPad, format, bits);
 }
 
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 27f9552..bcbb7a7 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -227,6 +227,9 @@ typedef struct glamor_screen_private {
     glamor_program      copy_area_prog;
     glamor_program      copy_plane_prog;
 
+    /* glamor image shaders */
+    glamor_program      put_bitmap_prog;
+
     /* glamor line shader */
     glamor_program_fill poly_line_program;
 
-- 
2.9.3



More information about the xorg-devel mailing list