summaryrefslogtreecommitdiff
path: root/glamor
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2014-01-05 21:54:48 +0800
committerEric Anholt <eric@anholt.net>2014-03-17 14:30:56 -0700
commitb885a639144cdadcb0dae8249a168db158770604 (patch)
tree16e29b889d7106bb8b6fcc3493c4cfed1da2b39c /glamor
parentab68982dcc53d29d5e3c5ea092bd91dab09e54c9 (diff)
glamor: Improve the performance of PushPixels by, well, pushing pixels.
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@anholt.net> Reviewed-by: Markus Wick <markus@selfnet.de>
Diffstat (limited to 'glamor')
-rw-r--r--glamor/glamor_glyphblt.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/glamor/glamor_glyphblt.c b/glamor/glamor_glyphblt.c
index 6f754ce2b..0a99a951c 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;
}