From 2c4e865ca50fab95eed2c32bd48d1c13ac4237ba Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 28 Feb 2014 13:02:21 -0500 Subject: 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 -f23text16 by 49.8918% +/- 7.81351% (n=4). Ported from Eric's xserver glamor tree. Signed-off-by: Eric Anholt Signed-off-by: Alex Deucher --- 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 @@ -88,16 +88,133 @@ glamor_poly_glyph_blt_nf(DrawablePtr pDrawable, GCPtr pGC, return _glamor_poly_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase, FALSE); } +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; } -- cgit v1.2.3