[PATCH 22/27] glamor: Improve the performance of PolyGlyphBlt.

Markus Wick markus at selfnet.de
Wed Mar 12 13:55:01 PDT 2014


Are we able to add cached textures to CharInfoPtr? If not, then this 
would be the ideal use case for texture_arrays ;)
Again, using GL_POINTS and check for every bit on CPU isn't the way to 
go.

Am 2014-03-11 22:30, schrieb Eric Anholt:
> Using the same idea as the previous PushPixels code, just make points
> for each point in the glyph.  This is an advantage over the pushpixels
> fallback because we can batch the BO mappings and draw calls across
> glyphs.
> 
> Improves performance of x11perf -f8text by 773.389% +/- 3.50754% 
> (n=10).
> 
> Signed-off-by: Eric Anholt <eric at anholt.net>
> ---
>  glamor/glamor_glyphblt.c | 138 
> +++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 138 insertions(+)
> 
> diff --git a/glamor/glamor_glyphblt.c b/glamor/glamor_glyphblt.c
> index 0a99a95..5d785a0 100644
> --- a/glamor/glamor_glyphblt.c
> +++ b/glamor/glamor_glyphblt.c
> @@ -27,6 +27,141 @@
>   */
> 
>  #include "glamor_priv.h"
> +#include <dixfontstr.h>
> +
> +static Bool
> +glamor_poly_glyph_blt_pixels(DrawablePtr drawable, GCPtr gc,
> +                             int x, int y, unsigned int nglyph,
> +                             CharInfoPtr *ppci)
> +{
> +    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;
> +    int off_x, off_y;
> +    GLfloat xscale, yscale;
> +    float color[4];
> +    unsigned long fg_pixel = gc->fgPixel;
> +    char *vbo_offset;
> +    RegionPtr clip;
> +    int num_points, max_points;
> +    float *points = NULL;
> +
> +    x += drawable->x;
> +    y += drawable->y;
> +
> +    if (gc->fillStyle != FillSolid) {
> +        glamor_fallback("gc fillstyle not solid\n");
> +        return FALSE;
> +    }
> +
> +    pixmap_priv = glamor_get_pixmap_private(pixmap);
> +    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
> +        return FALSE;
> +
> +    glamor_get_context(glamor_priv);
> +    if (!glamor_set_alu(screen, gc->alu)) {
> +        if (gc->alu == GXclear)
> +            fg_pixel = 0;
> +        else {
> +            glamor_fallback("unsupported alu %x\n", gc->alu);
> +            glamor_put_context(glamor_priv);
> +            return FALSE;
> +        }
> +    }
> +
> +    if (!glamor_set_planemask(pixmap, gc->planemask)) {
> +        glamor_fallback("Failed to set planemask in %s.\n", 
> __FUNCTION__);
> +        glamor_put_context(glamor_priv);
> +        return FALSE;
> +    }
> +
> +    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
> +
> +    glamor_set_destination_pixmap_priv_nc(pixmap_priv);
> +    pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
> +
> +    glUseProgram(glamor_priv->solid_prog);
> +
> +    glamor_get_rgba_from_pixel(fg_pixel,
> +                               &color[0], &color[1], &color[2], 
> &color[3],
> +                               format_for_pixmap(pixmap));
> +    glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color);
> +
> +    clip = fbGetCompositeClip(gc);
> +
> +    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
> +
> +    max_points = 500;
> +    num_points = 0;
> +    while (nglyph--) {
> +        CharInfoPtr charinfo = *ppci++;
> +        int w = GLYPHWIDTHPIXELS(charinfo);
> +        int h = GLYPHHEIGHTPIXELS(charinfo);
> +        uint8_t *glyphbits = FONTGLYPHBITS(NULL, charinfo);
> +
> +        if (w && h) {
> +            int glyph_x = x + charinfo->metrics.leftSideBearing;
> +            int glyph_y = y - charinfo->metrics.ascent;
> +            int glyph_stride = GLYPHWIDTHBYTESPADDED(charinfo);
> +            int xx, yy;
> +
> +            for (yy = 0; yy < h; yy++) {
> +                uint8_t *glyph_row = glyphbits + glyph_stride * yy;
> +                for (xx = 0; xx < w; xx++) {
> +                    int pt_x_i = glyph_x + xx;
> +                    int pt_y_i = glyph_y + yy;
> +                    float pt_x_f, pt_y_f;
> +                    if (!(glyph_row[xx / 8] & (1 << xx % 8)))
> +                        continue;
> +
> +                    if (!RegionContainsPoint(clip, pt_x_i, pt_y_i, 
> NULL))
> +                        continue;
> +
> +                    if (!num_points) {
> +                        points = glamor_get_vbo_space(screen,
> +                                                      max_points * 2
> * sizeof(float),
> +                                                      &vbo_offset);
> +
> +                        glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, 
> GL_FLOAT,
> +                                              GL_FALSE, 2 * 
> sizeof(float),
> +                                              vbo_offset);
> +                    }
> +
> +                    pt_x_f = v_from_x_coord_x(xscale, pt_x_i + off_x + 
> 0.5);
> +                    if (glamor_priv->yInverted)
> +                        pt_y_f = v_from_x_coord_y_inverted(yscale,
> pt_y_i + off_y + 0.5);
> +                    else
> +                        pt_y_f = v_from_x_coord_y(yscale, pt_y_i +
> off_y + 0.5);
> +
> +                    points[num_points * 2 + 0] = pt_x_f;
> +                    points[num_points * 2 + 1] = pt_y_f;
> +                    num_points++;
> +
> +                    if (num_points == max_points) {
> +                        glamor_put_vbo_space(screen);
> +                        glDrawArrays(GL_POINTS, 0, num_points);
> +                        num_points = 0;
> +                    }
> +                }
> +            }
> +        }
> +
> +        x += charinfo->metrics.characterWidth;
> +    }
> +
> +    if (num_points) {
> +        glamor_put_vbo_space(screen);
> +        glDrawArrays(GL_POINTS, 0, num_points);
> +    }
> +
> +    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
> +    glUseProgram(0);
> +
> +    glamor_put_context(glamor_priv);
> +
> +    return TRUE;
> +}
> 
>  static Bool
>  _glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
> @@ -64,6 +199,9 @@ _glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr 
> pGC,
>                         int x, int y, unsigned int nglyph,
>                         CharInfoPtr *ppci, void *pglyphBase, Bool 
> fallback)
>  {
> +    if (glamor_poly_glyph_blt_pixels(pDrawable, pGC, x, y, nglyph, 
> ppci))
> +        return TRUE;
> +
>      if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable)
>          && glamor_ddx_fallback_check_gc(pGC))
>          return FALSE;


More information about the xorg-devel mailing list