[PATCH 21/27] glamor: Improve the performance of PushPixels by, well, pushing pixels.

Markus Wick markus at selfnet.de
Wed Mar 12 13:20:41 PDT 2014


I didn't find any issues in this patch, but I don't see the point:
Do we really want to convert a pixmap with 1 bit per pixel into a list 
of enabled pixels on cpu?
Isn't it as easy to upload this pixmap as texture and do everything else 
in the pixel shader?
In this way, we won't have to care about the location of the bitmap.

Am 2014-03-11 22:30, schrieb Eric Anholt:
> Otherwise, mi will fall back to GetSpans()ing the bitmap, walking the
> bitmap, computing spans to be filled, and calling FillSpans().
> 
> Improves x11perf -f8text by 759.373% +/- 3.33096% (n=166)
> 
> Signed-off-by: Eric Anholt <eric at anholt.net>
> ---
>  glamor/glamor_glyphblt.c | 115 
> +++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 115 insertions(+)
> 
> diff --git a/glamor/glamor_glyphblt.c b/glamor/glamor_glyphblt.c
> index 6f754ce..0a99a95 100644
> --- a/glamor/glamor_glyphblt.c
> +++ b/glamor/glamor_glyphblt.c
> @@ -91,15 +91,130 @@ glamor_poly_glyph_blt_nf(DrawablePtr pDrawable, 
> GCPtr pGC,
>  }
> 
>  static Bool
> +glamor_push_pixels_points(GCPtr gc, PixmapPtr bitmap,
> +                          DrawablePtr drawable, int w, int h, int x, 
> int y)
> +{
> +    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;
> +    uint8_t *bitmap_data = bitmap->devPrivate.ptr;
> +    int bitmap_stride = bitmap->devKind;
> +    int off_x, off_y;
> +    int yy, xx;
> +    GLfloat xscale, yscale;
> +    float color[4];
> +    unsigned long fg_pixel = gc->fgPixel;
> +    float *points, *next_point;
> +    int num_points = 0;
> +    char *vbo_offset;
> +    RegionPtr clip;
> +
> +    if (w * h > MAXINT / (2 * sizeof(float)))
> +        return FALSE;
> +
> +    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);
> +
> +    points = glamor_get_vbo_space(screen, w * h * sizeof(float) * 2,
> +                                  &vbo_offset);
> +    next_point = points;
> +
> +    clip = fbGetCompositeClip(gc);
> +
> +    /* Note that because fb sets miTranslate in the GC, our incoming X
> +     * and Y are in screen coordinate space (same for spans, but not
> +     * other operations).
> +     */
> +    for (yy = 0; yy < h; yy++) {
> +        uint8_t *bitmap_row = bitmap_data + yy * bitmap_stride;
> +        for (xx = 0; xx < w; xx++) {
> +            if (bitmap_row[xx / 8] & (1 << xx % 8) &&
> +                RegionContainsPoint(clip,
> +                                    x + xx,
> +                                    y + yy,
> +                                    NULL)) {
> +                next_point[0] = v_from_x_coord_x(xscale, x + xx + 
> off_x + 0.5);
> +                if (glamor_priv->yInverted)
> +                    next_point[1] = v_from_x_coord_y_inverted(yscale,
> y + yy + off_y + 0.5);
> +                else
> +                    next_point[1] = v_from_x_coord_y(yscale, y + yy +
> off_y + 0.5);
> +
> +                next_point += 2;
> +                num_points++;
> +            }
> +        }
> +    }
> +    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
> +                          GL_FALSE, 2 * sizeof(float),
> +                          vbo_offset);
> +    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
> +
> +    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_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
>                      DrawablePtr pDrawable, int w, int h, int x, int y,
>                      Bool fallback)
>  {
> +    glamor_pixmap_private *pixmap_priv;
> +
>      if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable)
>          && glamor_ddx_fallback_check_pixmap(&pBitmap->drawable)
>          && glamor_ddx_fallback_check_gc(pGC))
>          return FALSE;
> 
> +    pixmap_priv = glamor_get_pixmap_private(pBitmap);
> +    if (pixmap_priv->type == GLAMOR_MEMORY) {
> +        if (glamor_push_pixels_points(pGC, pBitmap, pDrawable, w, h, 
> x, y))
> +            return TRUE;
> +    }
> +
>      miPushPixels(pGC, pBitmap, pDrawable, w, h, x, y);
>      return TRUE;
>  }


More information about the xorg-devel mailing list