[Glamor] [PATCH 26/34] glamor: Improve the performance of PushPixels by, well, pushing pixels.

Alex Deucher alexdeucher at gmail.com
Fri Feb 28 10:02:21 PST 2014


From: Eric Anholt <eric at anholt.net>

Otherwise, mi will fall back to GetSpans()ing the bitmap, walking the
bitmap, computing spans to be filled, and calling FillSpans().

Improves x11perf -f23text16 by 49.8918% +/- 7.81351% (n=4).

Ported from Eric's xserver glamor tree.

Signed-off-by: Eric Anholt <eric at anholt.net>
Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
---
 src/glamor_glyphblt.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 117 insertions(+)

diff --git a/src/glamor_glyphblt.c b/src/glamor_glyphblt.c
index b55327c..35be282 100644
--- a/src/glamor_glyphblt.c
+++ b/src/glamor_glyphblt.c
@@ -89,15 +89,132 @@ 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;
+	glamor_gl_dispatch *dispatch;
+
+	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;
+
+	dispatch = glamor_get_dispatch(glamor_priv);
+	if (!glamor_set_alu(dispatch, gc->alu)) {
+	    if (gc->alu == GXclear)
+		fg_pixel = 0;
+	    else {
+		glamor_fallback("unsupported alu %x\n", gc->alu);
+		glamor_put_dispatch(glamor_priv);
+		return FALSE;
+	    }
+	}
+
+	if (!glamor_set_planemask(pixmap, gc->planemask)) {
+	    glamor_fallback("Failed to set planemask in %s.\n", __FUNCTION__);
+	    glamor_put_dispatch(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);
+
+	dispatch->glUseProgram(glamor_priv->solid_prog);
+
+	glamor_get_rgba_from_pixel(fg_pixel,
+				   &color[0], &color[1], &color[2], &color[3],
+				   format_for_pixmap(pixmap));
+	dispatch->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++;
+		}
+	    }
+	}
+	glamor_put_vbo_space(screen);
+
+	dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
+					GL_FALSE, 2 * sizeof(float),
+					vbo_offset);
+	dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+
+	dispatch->glDrawArrays(GL_POINTS, 0, num_points);
+
+	dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+	dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0);
+	dispatch->glUseProgram(0);
+
+	glamor_put_dispatch(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.8.3.1



More information about the Glamor mailing list