From b2bed1b6f452e0592161a4220543ca952549a24e Mon Sep 17 00:00:00 2001 From: Max Staudt Date: Tue, 7 Feb 2017 13:47:35 +0100 Subject: [PATCH] glamor: Paint first and last pixel of lines OpenGL implementations are allowed to be imprecise in drawing line caps. This patch expands on the original workaround in dc9fa908. References: fdo#99705 boo#1021803 Signed-off-by: Max Staudt --- glamor/glamor_lines.c | 21 +++++++++------------ glamor/glamor_segs.c | 43 ++++++++++++++++++++++++------------------- 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/glamor/glamor_lines.c b/glamor/glamor_lines.c index ca3cccf..47f8ed2 100644 --- a/glamor/glamor_lines.c +++ b/glamor/glamor_lines.c @@ -45,7 +45,6 @@ glamor_poly_lines_gl(DrawablePtr drawable, GCPtr gc, DDXPointPtr v; char *vbo_offset; int box_x, box_y; - int add_last; pixmap_priv = glamor_get_pixmap_private(pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) @@ -57,10 +56,6 @@ glamor_poly_lines_gl(DrawablePtr drawable, GCPtr gc, if (gc->lineStyle != LineSolid) goto bail; - add_last = 0; - if (gc->capStyle != CapNotLast) - add_last = 1; - if (n < 2) return TRUE; @@ -76,7 +71,7 @@ glamor_poly_lines_gl(DrawablePtr drawable, GCPtr gc, /* Set up the vertex buffers for the points */ v = glamor_get_vbo_space(drawable->pScreen, - (n + add_last) * sizeof (DDXPointRec), + n * sizeof (DDXPointRec), &vbo_offset); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); @@ -96,11 +91,6 @@ glamor_poly_lines_gl(DrawablePtr drawable, GCPtr gc, memcpy(v, points, n * sizeof (DDXPointRec)); } - if (add_last) { - v[n].x = v[n-1].x + 1; - v[n].y = v[n-1].y; - } - glamor_put_vbo_space(screen); glEnable(GL_SCISSOR_TEST); @@ -118,7 +108,14 @@ glamor_poly_lines_gl(DrawablePtr drawable, GCPtr gc, box->x2 - box->x1, box->y2 - box->y1); box++; - glDrawArrays(GL_LINE_STRIP, 0, n + add_last); + glDrawArrays(GL_LINE_STRIP, 0, n); + + /* Draw the first and last pixels, as implementations are + * allowed to be inaccurate there. */ + if (gc->capStyle == CapNotLast) + glDrawArrays(GL_POINTS, 0, n-1); + else + glDrawArrays(GL_POINTS, 0, n); } } diff --git a/glamor/glamor_segs.c b/glamor/glamor_segs.c index 0168d05..b571b10 100644 --- a/glamor/glamor_segs.c +++ b/glamor/glamor_segs.c @@ -45,7 +45,6 @@ glamor_poly_segment_gl(DrawablePtr drawable, GCPtr gc, xSegment *v; char *vbo_offset; int box_x, box_y; - int add_last; pixmap_priv = glamor_get_pixmap_private(pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) @@ -57,10 +56,6 @@ glamor_poly_segment_gl(DrawablePtr drawable, GCPtr gc, if (gc->lineStyle != LineSolid) goto bail; - add_last = 0; - if (gc->capStyle != CapNotLast) - add_last = 1; - glamor_make_current(glamor_priv); prog = glamor_use_program_fill(pixmap, gc, @@ -71,27 +66,25 @@ glamor_poly_segment_gl(DrawablePtr drawable, GCPtr gc, goto bail_ctx; /* Set up the vertex buffers for the points */ - + /* We need 1.5 times the space in case of CapNotLast, + * so let's just always allocate 2 times the space. */ v = glamor_get_vbo_space(drawable->pScreen, - (nseg << add_last) * sizeof (xSegment), + nseg * sizeof (xSegment) * 2, &vbo_offset); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE, sizeof(DDXPointRec), vbo_offset); - if (add_last) { - int i, j; - for (i = 0, j=0; i < nseg; i++) { - v[j++] = segs[i]; - v[j].x1 = segs[i].x2; - v[j].y1 = segs[i].y2; - v[j].x2 = segs[i].x2+1; - v[j].y2 = segs[i].y2; - j++; + memcpy(v, segs, nseg * sizeof (xSegment)); + + /* In case of CapNotLast, copy the line starting points for later */ + if (gc->capStyle != CapNotLast) { + int i; + for (i = 0; i < nseg; i++) { + v[2*nseg + i] = v[2*i]; } - } else - memcpy(v, segs, nseg * sizeof (xSegment)); + } glamor_put_vbo_space(screen); @@ -110,7 +103,19 @@ glamor_poly_segment_gl(DrawablePtr drawable, GCPtr gc, box->x2 - box->x1, box->y2 - box->y1); box++; - glDrawArrays(GL_LINES, 0, nseg << (1 + add_last)); + glDrawArrays(GL_LINES, 0, nseg * 2); + + /* Draw the first and last pixel of each line, as OpenGL + * implementations are allowed to be inaccurate there. + * Since we're drawing all line ends, we can just reuse + * the array of all line starts and ends. */ + if (gc->capStyle != CapNotLast) { + glDrawArrays(GL_POINTS, 0, nseg * 2); + } else { + /* With CapNotLast, we only want to draw the starting points. + * That's why we copied them earlier. */ + glDrawArrays(GL_POINTS, nseg, nseg); + } } } -- 2.10.2