diff options
author | Keith Packard <keithp@keithp.com> | 2014-04-01 21:15:46 -0700 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2014-04-03 13:07:52 -0700 |
commit | 3411e8c538476443cafbb70082ef7457932e4a38 (patch) | |
tree | 0995278e12fc6540558c401e3f33e15269a3c1d5 /glamor | |
parent | 0a6d31161811c422799d6f065ea2842d42707530 (diff) |
glamor: Add glamor_program based poly_fill_rect
This accelerates poly_fill_rect using GPU-based geometry computation
Improves x11perf -rect100 by 41.5127% +/- 7.63888% (n=10)
Improves x11perf -rect10 by 3745.72% +/- 94.7503% (n=6)
v2: Rebase on skipping the prepare rewrite for now, and fix the GLSL
1.20 and GLES2 cases (changes by anholt).
Signed-off-by: Keith Packard <keithp@keithp.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'glamor')
-rw-r--r-- | glamor/Makefile.am | 2 | ||||
-rw-r--r-- | glamor/glamor_polyfillrect.c | 123 | ||||
-rw-r--r-- | glamor/glamor_priv.h | 12 | ||||
-rw-r--r-- | glamor/glamor_rects.c | 189 |
4 files changed, 198 insertions, 128 deletions
diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 4be9f3486..dccd923c5 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -14,13 +14,13 @@ libglamor_la_SOURCES = \ glamor_fill.c \ glamor_glx.c \ glamor_glyphs.c \ - glamor_polyfillrect.c \ glamor_polylines.c \ glamor_putimage.c \ glamor_segment.c \ glamor_render.c \ glamor_gradient.c \ glamor_program.c \ + glamor_rects.c \ glamor_spans.c \ glamor_transfer.c \ glamor_transfer.h \ diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c deleted file mode 100644 index 1e361a44f..000000000 --- a/glamor/glamor_polyfillrect.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright © 2009 Intel Corporation - * Copyright © 1998 Keith Packard - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * Authors: - * Eric Anholt <eric@anholt.net> - * - */ - -#include "glamor_priv.h" - -/** @file glamor_fillspans.c - * - * GC PolyFillRect implementation, taken straight from fb_fill.c - */ - -static Bool -_glamor_poly_fill_rect(DrawablePtr drawable, - GCPtr gc, int nrect, xRectangle *prect, Bool fallback) -{ - int fullX1, fullX2, fullY1, fullY2; - int xorg, yorg; - int n; - register BoxPtr pbox; - RegionPtr pClip = fbGetCompositeClip(gc); - Bool ret = FALSE; - - xorg = drawable->x; - yorg = drawable->y; - - while (nrect--) { - fullX1 = prect->x + xorg; - fullY1 = prect->y + yorg; - fullX2 = fullX1 + (int) prect->width; - fullY2 = fullY1 + (int) prect->height; - - n = REGION_NUM_RECTS(pClip); - pbox = REGION_RECTS(pClip); - /* - * clip the rectangle to each box in the clip region - * this is logically equivalent to calling Intersect(), - * but rectangles may overlap each other here. - */ - while (n--) { - int x1 = fullX1; - int x2 = fullX2; - int y1 = fullY1; - int y2 = fullY2; - - if (pbox->x1 > x1) - x1 = pbox->x1; - if (pbox->x2 < x2) - x2 = pbox->x2; - if (pbox->y1 > y1) - y1 = pbox->y1; - if (pbox->y2 < y2) - y2 = pbox->y2; - - pbox++; - if (x1 >= x2 || y1 >= y2) - continue; - if (!glamor_fill(drawable, gc, x1, y1, x2 - x1, y2 - y1, fallback)) { - nrect++; - goto fail; - } - } - prect++; - } - ret = TRUE; - goto done; - - fail: - - if (!fallback && glamor_ddx_fallback_check_pixmap(drawable) - && glamor_ddx_fallback_check_gc(gc)) - goto done; - - glamor_fallback(" to %p (%c)\n", - drawable, glamor_get_drawable_location(drawable)); - if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) && - glamor_prepare_access_gc(gc)) { - fbPolyFillRect(drawable, gc, nrect, prect); - } - glamor_finish_access_gc(gc); - glamor_finish_access(drawable); - ret = TRUE; - - done: - return ret; -} - -void -glamor_poly_fill_rect(DrawablePtr drawable, - GCPtr gc, int nrect, xRectangle *prect) -{ - _glamor_poly_fill_rect(drawable, gc, nrect, prect, TRUE); -} - -Bool -glamor_poly_fill_rect_nf(DrawablePtr drawable, - GCPtr gc, int nrect, xRectangle *prect) -{ - return _glamor_poly_fill_rect(drawable, gc, nrect, prect, FALSE); -} diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 430ca59b8..74bb7896a 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -227,6 +227,9 @@ typedef struct glamor_screen_private { /* glamor spans shaders */ glamor_program_fill fill_spans_program; + /* glamor rect shaders */ + glamor_program_fill poly_fill_rect_program; + /* vertext/elment_index buffer object for render */ GLuint vbo, ebo; /** Next offset within the VBO that glamor_get_vbo_space() will use. */ @@ -691,10 +694,6 @@ void glamor_glyphs(CARD8 op, INT16 xSrc, INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr *glyphs); -/* glamor_polyfillrect.c */ -void glamor_poly_fill_rect(DrawablePtr drawable, - GCPtr gc, int nrect, xRectangle *prect); - /* glamor_polylines.c */ void glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, DDXPointPtr points); @@ -971,6 +970,11 @@ void glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, DDXPointPtr points, int *widths, int numPoints, int sorted); +/* glamor_rects.c */ +void +glamor_poly_fill_rect(DrawablePtr drawable, + GCPtr gc, int nrect, xRectangle *prect); + /* glamor_glyphblt.c */ void glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, diff --git a/glamor/glamor_rects.c b/glamor/glamor_rects.c new file mode 100644 index 000000000..7731edec4 --- /dev/null +++ b/glamor/glamor_rects.c @@ -0,0 +1,189 @@ +/* + * Copyright © 2014 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "glamor_priv.h" +#include "glamor_program.h" +#include "glamor_transform.h" + +static const glamor_facet glamor_facet_polyfillrect_130 = { + .name = "poly_fill_rect", + .version = 130, + .vs_vars = "attribute vec4 primitive;\n", + .vs_exec = (" vec2 pos = primitive.zw * vec2(gl_VertexID&1, (gl_VertexID&2)>>1);\n" + GLAMOR_POS(gl_Position, (primitive.xy + pos))), +}; + +static const glamor_facet glamor_facet_polyfillrect_120 = { + .name = "poly_fill_rect", + .vs_vars = "attribute vec2 primitive;\n", + .vs_exec = (" vec2 pos = vec2(0,0);\n" + GLAMOR_POS(gl_Position, primitive.xy)), +}; + +static Bool +glamor_poly_fill_rect_gl(DrawablePtr drawable, + GCPtr gc, int nrect, xRectangle *prect) +{ + 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; + glamor_program *prog; + int off_x, off_y; + GLshort *v; + char *vbo_offset; + int box_x, box_y; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + goto bail; + + glamor_get_context(glamor_priv); + + if (glamor_priv->glsl_version >= 130) { + prog = glamor_use_program_fill(pixmap, gc, + &glamor_priv->poly_fill_rect_program, + &glamor_facet_polyfillrect_130); + + if (!prog) + goto bail_ctx; + + /* Set up the vertex buffers for the points */ + + v = glamor_get_vbo_space(drawable->pScreen, nrect * sizeof (xRectangle), &vbo_offset); + + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1); + glVertexAttribPointer(GLAMOR_VERTEX_POS, 4, GL_SHORT, GL_FALSE, + 4 * sizeof (short), vbo_offset); + + memcpy(v, prect, nrect * sizeof (xRectangle)); + + glamor_put_vbo_space(screen); + } else { + int n; + + prog = glamor_use_program_fill(pixmap, gc, + &glamor_priv->poly_fill_rect_program, + &glamor_facet_polyfillrect_120); + + if (!prog) + goto bail_ctx; + + /* Set up the vertex buffers for the points */ + + v = glamor_get_vbo_space(drawable->pScreen, nrect * 8 * sizeof (short), &vbo_offset); + + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE, + 2 * sizeof (short), vbo_offset); + + for (n = 0; n < nrect; n++) { + v[0] = prect->x; v[1] = prect->y; + v[2] = prect->x; v[3] = prect->y + prect->height; + v[4] = prect->x + prect->width; v[5] = prect->y + prect->height; + v[6] = prect->x + prect->width; v[7] = prect->y; + prect++; + v += 8; + } + + glamor_put_vbo_space(screen); + } + + glEnable(GL_SCISSOR_TEST); + + glamor_pixmap_loop(pixmap_priv, box_x, box_y) { + int nbox = RegionNumRects(gc->pCompositeClip); + BoxPtr box = RegionRects(gc->pCompositeClip); + + glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, FALSE, prog->matrix_uniform, &off_x, &off_y); + + while (nbox--) { + glScissor(box->x1 + off_x, + box->y1 + off_y, + box->x2 - box->x1, + box->y2 - box->y1); + box++; + if (glamor_priv->glsl_version >= 130) + glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nrect); + else { + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + glDrawArrays(GL_QUADS, 0, nrect * 4); + } else { + int i; + for (i = 0; i < nrect; i++) { + glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4); + } + } + } + } + } + + glDisable(GL_SCISSOR_TEST); + glDisable(GL_COLOR_LOGIC_OP); + if (glamor_priv->glsl_version >= 130) + glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0); + glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + + glamor_put_context(glamor_priv); + return TRUE; +bail_ctx: + glDisable(GL_COLOR_LOGIC_OP); + glamor_put_context(glamor_priv); +bail: + return FALSE; +} + +static void +glamor_poly_fill_rect_bail(DrawablePtr drawable, + GCPtr gc, int nrect, xRectangle *prect) +{ + glamor_fallback("to %p (%c)\n", drawable, + glamor_get_drawable_location(drawable)); + if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) && + glamor_prepare_access_gc(gc)) { + fbPolyFillRect(drawable, gc, nrect, prect); + } + glamor_finish_access_gc(gc); + glamor_finish_access(drawable); +} + +void +glamor_poly_fill_rect(DrawablePtr drawable, + GCPtr gc, int nrect, xRectangle *prect) +{ + if (glamor_poly_fill_rect_gl(drawable, gc, nrect, prect)) + return; + glamor_poly_fill_rect_bail(drawable, gc, nrect, prect); +} + +Bool +glamor_poly_fill_rect_nf(DrawablePtr drawable, + GCPtr gc, int nrect, xRectangle *prect) +{ + if (glamor_poly_fill_rect_gl(drawable, gc, nrect, prect)) + return TRUE; + if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc)) + return FALSE; + glamor_poly_fill_rect_bail(drawable, gc, nrect, prect); + return TRUE; +} |