[PATCH 21/27] glamor: Improve the performance of PushPixels by, well, pushing pixels.
Eric Anholt
eric at anholt.net
Tue Mar 11 14:30:35 PDT 2014
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;
}
--
1.9.0
More information about the xorg-devel
mailing list