[PATCH 05/13] glamor: Add glamor_program based 0-width dashed lines

Keith Packard keithp at keithp.com
Mon May 5 15:02:12 PDT 2014


This makes sure the pixelization for dashed lines matches non-dashed
lines, while also speeding them up.

v2: Switch to glamor_make_current

v3: Create dash pattern pixmap without GLAMOR_CREATE_FBO_NO_FBO

Signed-off-by: Keith Packard <keithp at keithp.com>

fixup for dash
---
 glamor/Makefile.am      |   1 +
 glamor/glamor.c         |  11 +-
 glamor/glamor_core.c    |  26 +++-
 glamor/glamor_dash.c    | 368 ++++++++++++++++++++++++++++++++++++++++++++++++
 glamor/glamor_lines.c   |  32 +++--
 glamor/glamor_priv.h    |  29 +++-
 glamor/glamor_program.c |   7 +
 glamor/glamor_program.h |   3 +
 glamor/glamor_segs.c    |  33 +++--
 9 files changed, 490 insertions(+), 20 deletions(-)
 create mode 100644 glamor/glamor_dash.c

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index 8fd6ec1..9dd06eb 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -9,6 +9,7 @@ libglamor_la_SOURCES = \
 	glamor_context.h \
 	glamor_copy.c \
 	glamor_core.c \
+	glamor_dash.c \
 	glamor_debug.h \
 	glamor_fill.c \
 	glamor_font.c \
diff --git a/glamor/glamor.c b/glamor/glamor.c
index 3468b51..1ae0382 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -37,6 +37,7 @@
 
 DevPrivateKeyRec glamor_screen_private_key;
 DevPrivateKeyRec glamor_pixmap_private_key;
+DevPrivateKeyRec glamor_gc_private_key;
 
 /**
  * glamor_get_drawable_pixmap() returns a backing pixmap for a given drawable.
@@ -346,7 +347,15 @@ glamor_init(ScreenPtr screen, unsigned int flags)
         LogMessage(X_WARNING,
                    "glamor%d: Failed to allocate pixmap private\n",
                    screen->myNum);
-        goto fail;;
+        goto fail;
+    }
+
+    if (!dixRegisterPrivateKey(&glamor_gc_private_key, PRIVATE_GC,
+                               sizeof (glamor_gc_private))) {
+        LogMessage(X_WARNING,
+                   "glamor%d: Failed to allocate gc private\n",
+                   screen->myNum);
+        goto fail;
     }
 
     if (epoxy_is_desktop_gl())
diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c
index ffb6eba..9d941d7 100644
--- a/glamor/glamor_core.c
+++ b/glamor/glamor_core.c
@@ -409,14 +409,35 @@ glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable)
         fbValidateGC(gc, changes, drawable);
     }
 
+    if (changes & GCDashList) {
+        glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
+
+        if (gc_priv->dash) {
+            glamor_destroy_pixmap(gc_priv->dash);
+            gc_priv->dash = NULL;
+        }
+    }
+
     gc->ops = &glamor_gc_ops;
 }
 
+static void
+glamor_destroy_gc(GCPtr gc)
+{
+    glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
+
+    if (gc_priv->dash) {
+        glamor_destroy_pixmap(gc_priv->dash);
+        gc_priv->dash = NULL;
+    }
+    miDestroyGC(gc);
+}
+
 static GCFuncs glamor_gc_funcs = {
     glamor_validate_gc,
     miChangeGC,
     miCopyGC,
-    miDestroyGC,
+    glamor_destroy_gc,
     miChangeClip,
     miDestroyClip,
     miCopyClip
@@ -429,6 +450,9 @@ static GCFuncs glamor_gc_funcs = {
 int
 glamor_create_gc(GCPtr gc)
 {
+    glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
+
+    gc_priv->dash = NULL;
     if (!fbCreateGC(gc))
         return FALSE;
 
diff --git a/glamor/glamor_dash.c b/glamor/glamor_dash.c
new file mode 100644
index 0000000..59565be
--- /dev/null
+++ b/glamor/glamor_dash.c
@@ -0,0 +1,368 @@
+/*
+ * 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"
+#include "glamor_transfer.h"
+#include "glamor_prepare.h"
+
+static const char dash_vs_vars[] =
+    "attribute vec3 primitive;\n"
+    "varying float dash_offset;\n";
+
+static const char dash_vs_exec[] =
+    "       dash_offset = primitive.z / dash_length;\n"
+    GLAMOR_POS(gl_Position, primitive.xy);
+
+static const char dash_fs_vars[] =
+    "varying float dash_offset;\n";
+
+static const char on_off_fs_exec[] =
+    "       float pattern = texture2D(dash, vec2(dash_offset, 0.5)).w;\n"
+    "       if (pattern == 0.0)\n"
+    "               discard;\n";
+
+/* XXX deal with stippled double dashed lines once we have stippling support */
+static const char double_fs_exec[] =
+    "       float pattern = texture2D(dash, vec2(dash_offset, 0.5)).w;\n"
+    "       if (pattern == 0.0)\n"
+    "               gl_FragColor = bg;\n"
+    "       else\n"
+    "               gl_FragColor = fg;\n";
+
+
+static const glamor_facet glamor_facet_on_off_dash_lines = {
+    .version = 130,
+    .name = "poly_lines_on_off_dash",
+    .vs_vars = dash_vs_vars,
+    .vs_exec = dash_vs_exec,
+    .fs_vars = dash_fs_vars,
+    .fs_exec = on_off_fs_exec,
+    .locations = glamor_program_location_dash,
+};
+
+static const glamor_facet glamor_facet_double_dash_lines = {
+    .version = 130,
+    .name = "poly_lines_double_dash",
+    .vs_vars = dash_vs_vars,
+    .vs_exec = dash_vs_exec,
+    .fs_vars = dash_fs_vars,
+    .fs_exec = double_fs_exec,
+    .locations = glamor_program_location_dash|glamor_program_location_fg|glamor_program_location_bg,
+};
+
+static PixmapPtr
+glamor_get_dash_pixmap(GCPtr gc)
+{
+    glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
+    ScreenPtr   screen = gc->pScreen;
+    PixmapPtr   pixmap;
+    int         offset;
+    int         d;
+    uint32_t    pixel;
+    GCPtr       scratch_gc;
+
+    if (gc_priv->dash)
+        return gc_priv->dash;
+
+    offset = 0;
+    for (d = 0; d < gc->numInDashList; d++)
+        offset += gc->dash[d];
+
+    pixmap = glamor_create_pixmap(screen, offset, 1, 8, 0);
+    if (!pixmap)
+        goto bail;
+
+    scratch_gc = GetScratchGC(8, screen);
+    if (!scratch_gc)
+        goto bail_pixmap;
+
+    pixel = 0xffffffff;
+    offset = 0;
+    for (d = 0; d < gc->numInDashList; d++) {
+        xRectangle      rect;
+        ChangeGCVal     changes;
+
+        changes.val = pixel;
+        (void) ChangeGC(NullClient, scratch_gc,
+                        GCForeground, &changes);
+        ValidateGC(&pixmap->drawable, scratch_gc);
+        rect.x = offset;
+        rect.y = 0;
+        rect.width = gc->dash[d];
+        rect.height = 1;
+        scratch_gc->ops->PolyFillRect (&pixmap->drawable, scratch_gc, 1, &rect);
+        offset += gc->dash[d];
+        pixel = ~pixel;
+    }
+    FreeScratchGC(scratch_gc);
+
+    gc_priv->dash = pixmap;
+    return pixmap;
+
+bail_pixmap:
+    glamor_destroy_pixmap(pixmap);
+bail:
+    return NULL;
+}
+
+static glamor_program *
+glamor_dash_setup(DrawablePtr drawable, GCPtr gc)
+{
+    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_get_pixmap_private(pixmap);
+    PixmapPtr dash_pixmap;
+    glamor_pixmap_private *dash_priv;
+    glamor_program *prog;
+
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+        goto bail;
+
+    if (gc->lineWidth != 0)
+        goto bail;
+
+    dash_pixmap = glamor_get_dash_pixmap(gc);
+    dash_priv = glamor_get_pixmap_private(pixmap);
+
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dash_priv))
+        goto bail;
+
+    glamor_make_current(glamor_priv);
+
+    switch (gc->lineStyle) {
+    case LineOnOffDash:
+        prog = glamor_use_program_fill(pixmap, gc,
+                                       &glamor_priv->on_off_dash_line_progs,
+                                       &glamor_facet_on_off_dash_lines);
+        if (!prog)
+            goto bail_ctx;
+        break;
+    case LineDoubleDash:
+        if (gc->fillStyle != FillSolid)
+            goto bail_ctx;
+
+        prog = &glamor_priv->double_dash_line_prog;
+
+        if (!prog->prog) {
+            if (!glamor_build_program(screen, prog,
+                                      &glamor_facet_double_dash_lines,
+                                      NULL))
+                goto bail_ctx;
+        }
+
+        if (!glamor_use_program(pixmap, gc, prog, NULL))
+            goto bail_ctx;
+
+        glamor_set_color(pixmap, gc->fgPixel, prog->fg_uniform);
+        glamor_set_color(pixmap, gc->bgPixel, prog->bg_uniform);
+        break;
+
+    default:
+        goto bail_ctx;
+    }
+
+
+    /* Set the dash pattern as texture 1 */
+
+    glActiveTexture(GL_TEXTURE1);
+    glBindTexture(GL_TEXTURE_2D, dash_priv->base.fbo->tex);
+    glUniform1i(prog->dash_uniform, 1);
+    glUniform1f(prog->dash_length_uniform, dash_pixmap->drawable.width);
+
+    return prog;
+
+bail_ctx:
+    glDisable(GL_COLOR_LOGIC_OP);
+bail:
+    return NULL;
+}
+
+static void
+glamor_dash_loop(DrawablePtr drawable, GCPtr gc, glamor_program *prog, int n, GLenum mode)
+{
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
+    int box_x, box_y;
+    int off_x, off_y;
+
+    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, TRUE, 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++;
+            glDrawArrays(mode, 0, n);
+        }
+    }
+
+    glDisable(GL_SCISSOR_TEST);
+    glDisable(GL_COLOR_LOGIC_OP);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+}
+
+static int
+glamor_line_length(short x1, short y1, short x2, short y2)
+{
+    int dx = abs(x2 - x1);
+    int dy = abs(y2 - y1);
+    if (dx > dy)
+        return dx;
+    return dy;
+}
+
+Bool
+glamor_poly_lines_dash_gl(DrawablePtr drawable, GCPtr gc,
+                          int mode, int n, DDXPointPtr points)
+{
+    ScreenPtr screen = drawable->pScreen;
+    glamor_program *prog;
+    short *v;
+    char *vbo_offset;
+    int add_last;
+    int dash_pos;
+    int prev_x, prev_y;
+    int i;
+
+    if (n < 2)
+        return TRUE;
+
+    if (!(prog = glamor_dash_setup(drawable, gc)))
+        return FALSE;
+
+    add_last = 0;
+    if (gc->capStyle != CapNotLast)
+        add_last = 1;
+
+    /* Set up the vertex buffers for the points */
+
+    v = glamor_get_vbo_space(drawable->pScreen, (n + add_last) * 4 * sizeof (short), &vbo_offset);
+
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 3, GL_SHORT, GL_FALSE,
+                          4 * sizeof (short), vbo_offset);
+
+    if (mode == CoordModePrevious) {
+        DDXPointRec here = { 0, 0 };
+
+        for (i = 0; i < n; i++) {
+            here.x += points[i].x;
+            points[i].x = here.x;
+            here.y += points[i].y;
+            points[i].y = here.y;
+        }
+    }
+
+    dash_pos = gc->dashOffset;
+    prev_x = prev_y = 0;
+    for (i = 0; i < n; i++) {
+        if (i)
+            dash_pos += glamor_line_length(prev_x, prev_y,
+                                           points[i].x, points[i].y);
+        v[0] = prev_x = points[i].x;
+        v[1] = prev_y = points[i].y;
+        v[2] = dash_pos;
+        v += 4;
+    }
+
+    if (add_last) {
+        v[0] = v[-4] + 1;
+        v[1] = v[-3];
+        v[2] = dash_pos + 1;
+    }
+
+    glamor_put_vbo_space(screen);
+
+    glamor_dash_loop(drawable, gc, prog, n + add_last, GL_LINE_STRIP);
+
+    return TRUE;
+}
+
+static short *
+glamor_add_segment(short *v, short x1, short y1, short x2, short y2, int dash_start)
+{
+    v[0] = x1;
+    v[1] = y1;
+    v[2] = dash_start;
+
+    v[4] = x2;
+    v[5] = y2;
+    v[6] = dash_start + glamor_line_length(x1, y1,
+                                           x2, y2);
+    return v + 8;
+}
+
+Bool
+glamor_poly_segment_dash_gl(DrawablePtr drawable, GCPtr gc,
+                            int nseg, xSegment *segs)
+{
+    ScreenPtr screen = drawable->pScreen;
+    glamor_program *prog;
+    short *v;
+    char *vbo_offset;
+    int dash_start = gc->dashOffset;
+    int add_last;
+    int i;
+
+    if (!(prog = glamor_dash_setup(drawable, gc)))
+        return FALSE;
+
+    add_last = 0;
+    if (gc->capStyle != CapNotLast)
+        add_last = 1;
+
+    /* Set up the vertex buffers for the points */
+
+    v = glamor_get_vbo_space(drawable->pScreen, (nseg<<add_last) * 8 * sizeof (short), &vbo_offset);
+
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 3, GL_SHORT, GL_FALSE,
+                          4 * sizeof (short), vbo_offset);
+
+    for (i = 0; i < nseg; i++) {
+        v = glamor_add_segment(v,
+                               segs[i].x1, segs[i].y1,
+                               segs[i].x2, segs[i].y2,
+                               dash_start);
+        if (add_last)
+            v = glamor_add_segment(v,
+                                   segs[i].x2, segs[i].y2,
+                                   segs[i].x2 + 1, segs[i].y2,
+                                   v[-8 + 6]);
+    }
+
+    glamor_put_vbo_space(screen);
+
+    glamor_dash_loop(drawable, gc, prog, nseg << (1 + add_last), GL_LINES);
+
+    return TRUE;
+}
diff --git a/glamor/glamor_lines.c b/glamor/glamor_lines.c
index 3f021a6..f577936 100644
--- a/glamor/glamor_lines.c
+++ b/glamor/glamor_lines.c
@@ -33,8 +33,8 @@ static const glamor_facet glamor_facet_poly_lines = {
 };
 
 static Bool
-glamor_poly_lines_gl(DrawablePtr drawable, GCPtr gc,
-                     int mode, int n, DDXPointPtr points)
+glamor_poly_lines_solid_gl(DrawablePtr drawable, GCPtr gc,
+                           int mode, int n, DDXPointPtr points)
 {
     ScreenPtr screen = drawable->pScreen;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
@@ -51,12 +51,6 @@ glamor_poly_lines_gl(DrawablePtr drawable, GCPtr gc,
     if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
         goto bail;
 
-    if (gc->lineWidth != 0)
-        goto bail;
-
-    if (gc->lineStyle != LineSolid)
-        goto bail;
-
     add_last = 0;
     if (gc->capStyle != CapNotLast)
         add_last = 1;
@@ -130,6 +124,28 @@ bail:
     return FALSE;
 }
 
+static Bool
+glamor_poly_lines_gl(DrawablePtr drawable, GCPtr gc,
+                     int mode, int n, DDXPointPtr points)
+{
+    if (gc->lineWidth != 0)
+        return FALSE;
+
+    switch (gc->lineStyle) {
+    case LineSolid:
+        return glamor_poly_lines_solid_gl(drawable, gc, mode, n, points);
+    case LineOnOffDash:
+        return glamor_poly_lines_dash_gl(drawable, gc, mode, n, points);
+    case LineDoubleDash:
+        if (gc->fillStyle == FillTiled)
+            return glamor_poly_lines_solid_gl(drawable, gc, mode, n, points);
+        else
+            return glamor_poly_lines_dash_gl(drawable, gc, mode, n, points);
+    default:
+        return FALSE;
+    }
+}
+
 static void
 glamor_poly_lines_bail(DrawablePtr drawable, GCPtr gc,
                        int mode, int n, DDXPointPtr points)
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 59fb32d..e438f7f 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -250,6 +250,10 @@ typedef struct glamor_screen_private {
     /* glamor segment shaders */
     glamor_program_fill poly_segment_program;
 
+    /*  glamor dash line shader */
+    glamor_program_fill on_off_dash_line_progs;
+    glamor_program      double_dash_line_prog;
+
     /* vertext/elment_index buffer object for render */
     GLuint vbo, ebo;
     /** Next offset within the VBO that glamor_get_vbo_space() will use. */
@@ -562,6 +566,13 @@ typedef enum glamor_pixmap_status {
     GLAMOR_UPLOAD_FAILED
 } glamor_pixmap_status_t;
 
+/* GC private structure. Currently holds only any computed dash pixmap */
+
+typedef struct {
+    PixmapPtr   dash;
+} glamor_gc_private;
+
+extern DevPrivateKeyRec glamor_gc_private_key;
 extern DevPrivateKeyRec glamor_screen_private_key;
 extern DevPrivateKeyRec glamor_pixmap_private_key;
 
@@ -594,6 +605,12 @@ glamor_get_pixmap_private(PixmapPtr pixmap)
 
 void glamor_set_pixmap_private(PixmapPtr pixmap, glamor_pixmap_private *priv);
 
+static inline glamor_gc_private *
+glamor_get_gc_private(GCPtr gc)
+{
+    return dixLookupPrivate(&gc->devPrivates, &glamor_gc_private_key);
+}
+
 /**
  * Returns TRUE if the given planemask covers all the significant bits in the
  * pixel values for pDrawable.
@@ -979,7 +996,17 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
 void
 glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
                  unsigned int format, unsigned long planeMask, char *d);
-/*  glamor_lines.c */
+
+/* glamor_dash.c */
+Bool
+glamor_poly_lines_dash_gl(DrawablePtr drawable, GCPtr gc,
+                          int mode, int n, DDXPointPtr points);
+
+Bool
+glamor_poly_segment_dash_gl(DrawablePtr drawable, GCPtr gc,
+                            int nseg, xSegment *segs);
+
+/* glamor_lines.c */
 void
 glamor_poly_lines(DrawablePtr drawable, GCPtr gc,
                   int mode, int n, DDXPointPtr points);
diff --git a/glamor/glamor_program.c b/glamor/glamor_program.c
index a9371f3..0e3e94d 100644
--- a/glamor/glamor_program.c
+++ b/glamor/glamor_program.c
@@ -122,6 +122,11 @@ static glamor_location_var location_vars[] = {
         .fs_vars = ("uniform uvec4 bitplane;\n"
                     "uniform uvec4 bitmul;\n"),
     },
+    {
+        .location = glamor_program_location_dash,
+        .vs_vars = "uniform float dash_length;\n",
+        .fs_vars = "uniform sampler2D dash;\n",
+    },
 };
 
 #define NUM_LOCATION_VARS       (sizeof location_vars / sizeof location_vars[0])
@@ -326,6 +331,8 @@ glamor_build_program(ScreenPtr          screen,
     prog->font_uniform = glamor_get_uniform(prog, glamor_program_location_font, "font");
     prog->bitplane_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitplane");
     prog->bitmul_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitmul");
+    prog->dash_uniform = glamor_get_uniform(prog, glamor_program_location_dash, "dash");
+    prog->dash_length_uniform = glamor_get_uniform(prog, glamor_program_location_dash, "dash_length");
 
     if (glGetError() != GL_NO_ERROR)
         goto fail;
diff --git a/glamor/glamor_program.h b/glamor/glamor_program.h
index 118f978..56ba03a 100644
--- a/glamor/glamor_program.h
+++ b/glamor/glamor_program.h
@@ -30,6 +30,7 @@ typedef enum {
     glamor_program_location_fill = 4,
     glamor_program_location_font = 8,
     glamor_program_location_bitplane = 16,
+    glamor_program_location_dash = 32,
 } glamor_program_location;
 
 typedef enum {
@@ -64,6 +65,8 @@ struct _glamor_program {
     GLint                       font_uniform;
     GLint                       bitplane_uniform;
     GLint                       bitmul_uniform;
+    GLint                       dash_uniform;
+    GLint                       dash_length_uniform;
     glamor_program_location     locations;
     glamor_program_flag         flags;
     glamor_use                  prim_use;
diff --git a/glamor/glamor_segs.c b/glamor/glamor_segs.c
index 98ef9a0..01129a2 100644
--- a/glamor/glamor_segs.c
+++ b/glamor/glamor_segs.c
@@ -33,8 +33,8 @@ static const glamor_facet glamor_facet_poly_segment = {
 };
 
 static Bool
-glamor_poly_segment_gl(DrawablePtr drawable, GCPtr gc,
-                       int nseg, xSegment *segs)
+glamor_poly_segment_solid_gl(DrawablePtr drawable, GCPtr gc,
+                             int nseg, xSegment *segs)
 {
     ScreenPtr screen = drawable->pScreen;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
@@ -51,12 +51,6 @@ glamor_poly_segment_gl(DrawablePtr drawable, GCPtr gc,
     if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
         goto bail;
 
-    if (gc->lineWidth != 0)
-        goto bail;
-
-    if (gc->lineStyle != LineSolid)
-        goto bail;
-
     add_last = 0;
     if (gc->capStyle != CapNotLast)
         add_last = 1;
@@ -122,6 +116,28 @@ bail:
     return FALSE;
 }
 
+static Bool
+glamor_poly_segment_gl(DrawablePtr drawable, GCPtr gc,
+                       int nseg, xSegment *segs)
+{
+    if (gc->lineWidth != 0)
+        return FALSE;
+
+    switch (gc->lineStyle) {
+    case LineSolid:
+        return glamor_poly_segment_solid_gl(drawable, gc, nseg, segs);
+    case LineOnOffDash:
+        return glamor_poly_segment_dash_gl(drawable, gc, nseg, segs);
+    case LineDoubleDash:
+        if (gc->fillStyle == FillTiled)
+            return glamor_poly_segment_solid_gl(drawable, gc, nseg, segs);
+        else
+            return glamor_poly_segment_dash_gl(drawable, gc, nseg, segs);
+    default:
+        return FALSE;
+    }
+}
+
 static void
 glamor_poly_segment_bail(DrawablePtr drawable, GCPtr gc,
                          int nseg, xSegment *segs)
@@ -140,7 +156,6 @@ glamor_poly_segment_bail(DrawablePtr drawable, GCPtr gc,
         miPolySegment(drawable, gc, nseg, segs);
 }
 
-
 void
 glamor_poly_segment(DrawablePtr drawable, GCPtr gc,
                     int nseg, xSegment *segs)
-- 
2.0.0.rc0



More information about the xorg-devel mailing list