[PATCH xserver] glamor: Paint first and last pixel of lines
Max Staudt
mstaudt at suse.de
Tue Feb 7 15:50:00 UTC 2017
OpenGL implementations are allowed to be imprecise in drawing line caps.
This patch expands on the original workaround in dc9fa908.
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=99705
Signed-off-by: Max Staudt <mstaudt at suse.de>
---
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
More information about the xorg-devel
mailing list