[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