[PATCH 05/16] glamor: Add glamor_program based fill/set/get spans

Eric Anholt eric at anholt.net
Wed Apr 2 13:53:35 PDT 2014


Keith Packard <keithp at keithp.com> writes:

> This accelerates spans operations using GPU-based geometry computation
>
> Signed-off-by: Keith Packard <keithp at keithp.com>

> +static Bool
> +glamor_fill_spans_gl(DrawablePtr drawable,
> +                     GCPtr gc,
> +                     int n, DDXPointPtr points, int *widths, int sorted)
> +{
> +    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 c;
> +    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->fill_spans_program,
> +                                       &glamor_facet_fillspans_130);
> +
> +        if (!prog)
> +            goto bail_ctx;
> +
> +        /* Set up the vertex buffers for the points */
> +
> +        v = glamor_get_vbo_space(drawable->pScreen, n * (4 * sizeof (GLshort)), &vbo_offset);
> +
> +        glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
> +        glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1);
> +        glVertexAttribPointer(GLAMOR_VERTEX_POS, 3, GL_SHORT, GL_FALSE,
> +                              4 * sizeof (GLshort), vbo_offset);
> +
> +        for (c = 0; c < n; c++) {
> +            v[0] = points->x;
> +            v[1] = points->y;
> +            v[2] = *widths++;
> +            points++;
> +            v += 4;
> +        }
> +
> +        glamor_put_vbo_space(screen);
> +    } else {
> +        prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->fill_spans_program,
> +                                       &glamor_facet_fillspans_120);
> +
> +        if (!prog)
> +            goto bail_ctx;
> +
> +        /* Set up the vertex buffers for the points */
> +
> +        v = glamor_get_vbo_space(drawable->pScreen, n * 8 * sizeof (short), &vbo_offset);
> +
> +        glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
> +        glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE,
> +                              2 * sizeof (short), vbo_offset);
> +
> +        for (c = 0; c < n; c++) {
> +            v[0] = points->x;           v[1] = points->y;
> +            v[2] = points->x;           v[3] = points->y + 1;
> +            v[4] = points->x + *widths; v[5] = points->y + 1;
> +            v[6] = points->x + *widths; v[7] = points->y;
> +
> +            widths++;
> +            points++;
> +            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, FALSE, 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, n);
> +            else
> +                glDrawArrays(GL_QUADS, 0, 4 * n);

QUADS aren't available in ES.  You've got the index buffer bound, so you
could just use glDrawElememts(GL_TRIANGLES, 6 * n) with some checking to
make sure you don't overflow the size of the IB.  Or, just loop doing a
glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4), which would still be better
than the previous fill code.

Here's what I squashed in to fix it:

diff --git a/glamor/glamor_spans.c b/glamor/glamor_spans.c
index f529de6..98842cd 100644
--- a/glamor/glamor_spans.c
+++ b/glamor/glamor_spans.c
@@ -23,7 +23,6 @@
 #include "glamor_priv.h"
 #include "glamor_transform.h"
 #include "glamor_transfer.h"
-#include "glamor_prepare.h"
 
 glamor_program  fill_spans_progs[4];
 
@@ -134,14 +133,23 @@ glamor_fill_spans_gl(DrawablePtr drawable,
             box++;
             if (glamor_priv->glsl_version >= 130)
                 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, n);
-            else
-                glDrawArrays(GL_QUADS, 0, 4 * n);
+            else {
+                if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+                    glDrawArrays(GL_QUADS, 0, 4 * n);
+                } else {
+                    int i;
+                    for (i = 0; i < n; i++) {
+                        glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4);
+                    }
+                }
+            }
         }
     }
 
     glDisable(GL_SCISSOR_TEST);
     glDisable(GL_COLOR_LOGIC_OP);
-    glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0);
+    if (glamor_priv->glsl_version >= 130)
+        glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0);
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
 
     glamor_put_context(glamor_priv);

-wellipse500 goes from about 4k/sec before your patch, to ~8k/sec in the
fallback loop, to ~100k/sec in desktop mode.

> +static Bool
> +glamor_set_spans_gl(DrawablePtr drawable, GCPtr gc, char *src,
> +                    DDXPointPtr points, int *widths, int numPoints, int sorted)
> +{
> +    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;
> +    int box_x, box_y;
> +    int n;
> +    char *s;
> +    GLenum type;
> +    GLenum format;
> +    int off_x, off_y;
> +
> +    pixmap_priv = glamor_get_pixmap_private(pixmap);
> +    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
> +        goto bail;
> +
> +    if (gc->alu != GXcopy)
> +        goto bail;
> +
> +    if (!glamor_pm_is_solid(&pixmap->drawable, gc->planemask))
> +        goto bail;
> +
> +    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
> +    glamor_format_for_pixmap(pixmap, &format, &type);
> +
> +    glamor_get_context(glamor_priv);
> +
> +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
> +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

These glTexParameteri()s are unnecessary.

I'm dropping commits to clean up things like this in
glamor-extra-after-keithp of my tree, as I review.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.x.org/archives/xorg-devel/attachments/20140402/2206cbba/attachment.sig>


More information about the xorg-devel mailing list