Upload the bitmap and use a program like TE Text program to draw it, avoiding fallbacks for this case.
Signed-off-by: Keith Packard <kei...@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 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: https://lists.x.org/mailman/listinfo/xorg-devel