xf86-video-intel: 4 commits - src/sna/sna_accel.c src/sna/sna_io.c src/uxa/uxa-accel.c test/DrawSegments.c test/.gitignore test/Makefile.am

Chris Wilson ickle at kemper.freedesktop.org
Tue Sep 16 12:29:25 PDT 2014


 src/sna/sna_accel.c |    2 
 src/sna/sna_io.c    |    4 
 src/uxa/uxa-accel.c |   64 ++++++++-----
 test/.gitignore     |    1 
 test/DrawSegments.c |  249 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 test/Makefile.am    |    1 
 6 files changed, 296 insertions(+), 25 deletions(-)

New commits:
commit 2a4855a633f42d90e11f5c51342c514c2dc24307
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Sep 16 20:26:28 2014 +0100

    sna: Constify argument to box_from_seg()
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index e5382a2..ab43831 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -9955,7 +9955,7 @@ out:
 	RegionUninit(&data.region);
 }
 
-static inline void box_from_seg(BoxPtr b, xSegment *seg, GCPtr gc)
+static inline void box_from_seg(BoxPtr b, const xSegment *seg, GCPtr gc)
 {
 	if (seg->x1 == seg->x2) {
 		if (seg->y1 > seg->y2) {
commit 1cc9762b08a127a2475a44da71ca07cb294562f2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Sep 16 12:14:31 2014 +0100

    uxa: Fix conversion of Segments into Rectangles
    
    The trick is to make sure we consider the CapLast setting in the
    direction the line is being drawn and adjust the inked pixels
    accordingly.
    
    Testcase: DrawSegments/hv0
    Reported-by: Russell King
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/uxa/uxa-accel.c b/src/uxa/uxa-accel.c
index 757b276..9e7879b 100644
--- a/src/uxa/uxa-accel.c
+++ b/src/uxa/uxa-accel.c
@@ -675,6 +675,43 @@ uxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
 	free(prect);
 }
 
+static BoxRec box_from_seg(const xSegment *seg, GCPtr gc)
+{
+	BoxRec b;
+
+	if (seg->x1 == seg->x2) {
+		if (seg->y1 > seg->y2) {
+			b.y2 = seg->y1 + 1;
+			b.y1 = seg->y2 + 1;
+			if (gc->capStyle != CapNotLast)
+				b.y1--;
+		} else {
+			b.y1 = seg->y1;
+			b.y2 = seg->y2;
+			if (gc->capStyle != CapNotLast)
+				b.y2++;
+		}
+		b.x1 = seg->x1;
+		b.x2 = seg->x1 + 1;
+	} else {
+		if (seg->x1 > seg->x2) {
+			b.x2 = seg->x1 + 1;
+			b.x1 = seg->x2 + 1;
+			if (gc->capStyle != CapNotLast)
+				b.x1--;
+		} else {
+			b.x1 = seg->x1;
+			b.x2 = seg->x2;
+			if (gc->capStyle != CapNotLast)
+				b.x2++;
+		}
+		b.y1 = seg->y1;
+		b.y2 = seg->y1 + 1;
+	}
+
+	return b;
+}
+
 /**
  * uxa_poly_segment() checks if it can accelerate the lines as a group of
  * horizontal or vertical lines (rectangles), and uses existing rectangle fill
@@ -718,28 +755,11 @@ uxa_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSeg)
 	if (!prect)
 		return;
 	for (i = 0; i < nseg; i++) {
-		if (pSeg[i].x1 < pSeg[i].x2) {
-			prect[i].x = pSeg[i].x1;
-			prect[i].width = pSeg[i].x2 - pSeg[i].x1 + 1;
-		} else {
-			prect[i].x = pSeg[i].x2;
-			prect[i].width = pSeg[i].x1 - pSeg[i].x2 + 1;
-		}
-		if (pSeg[i].y1 < pSeg[i].y2) {
-			prect[i].y = pSeg[i].y1;
-			prect[i].height = pSeg[i].y2 - pSeg[i].y1 + 1;
-		} else {
-			prect[i].y = pSeg[i].y2;
-			prect[i].height = pSeg[i].y1 - pSeg[i].y2 + 1;
-		}
-
-		/* don't paint last pixel */
-		if (pGC->capStyle == CapNotLast) {
-			if (prect[i].width == 1)
-				prect[i].height--;
-			else
-				prect[i].width--;
-		}
+		BoxRec b = box_from_seg(&pSeg[i], pGC);
+		prect[i].x = b.x1;
+		prect[i].y = b.y1;
+		prect[i].width  = b.x2 - b.x1;
+		prect[i].height = b.y2 - b.y1;
 	}
 	pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect);
 	free(prect);
commit db157b42aaa7880d98fed3e7493a19471e86e534
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Sep 16 11:56:07 2014 +0100

    test: Add DrawSegments
    
    Compare fb/ddx for many DrawSegments operations.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/.gitignore b/test/.gitignore
index d036ead..3b18297 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -6,6 +6,7 @@ basic-lines
 basic-stress
 basic-stippledrect
 basic-tiledrect
+DrawSegments
 cursor-test
 render-fill
 render-trapezoid
diff --git a/test/DrawSegments.c b/test/DrawSegments.c
new file mode 100644
index 0000000..d310af9
--- /dev/null
+++ b/test/DrawSegments.c
@@ -0,0 +1,249 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <X11/Xutil.h> /* for XDestroyImage */
+#include <pixman.h> /* for pixman blt functions */
+
+#include "test.h"
+
+static const XPoint points[]= {
+	/* top */
+	{ 0, 0},
+	{ 1, 0},
+	{ 2, 0},
+	{ 3, 0},
+	{ 4, 0},
+	{ 5, 0},
+	{ 6, 0},
+	{ 7, 0},
+	{ 8, 0},
+	/* right */
+	{ 8, 1},
+	{ 8, 2},
+	{ 8, 3},
+	{ 8, 4},
+	{ 8, 5},
+	{ 8, 6},
+	{ 8, 7},
+	{ 8, 8},
+	/* bottom */
+	{ 7, 8},
+	{ 6, 8},
+	{ 5, 8},
+	{ 4, 8},
+	{ 3, 8},
+	{ 2, 8},
+	{ 1, 8},
+	{ 0, 8},
+	/* left */
+	{ 0, 7},
+	{ 0, 6},
+	{ 0, 5},
+	{ 0, 4},
+	{ 0, 3},
+	{ 0, 2},
+	{ 0, 1},
+	{ 0, 0} /* and origin again for luck */
+};
+#define NUM_POINTS (sizeof(points)/sizeof(points[0]))
+
+static void clear(struct test_display *dpy, struct test_target *tt)
+{
+	XRenderColor render_color = {0};
+	XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, &render_color,
+			     0, 0, tt->width, tt->height);
+}
+
+static void draw(struct test_display *dpy, struct test_target *tt,
+		 int alu, int width, int style, int cap,
+		 XSegment *seg, int nseg)
+{
+	XGCValues val;
+	GC gc;
+
+	val.function = alu;
+	val.foreground = WhitePixel(dpy->dpy, 0);
+	val.line_width = width;
+	val.line_style = style;
+	val.cap_style = cap;
+
+	gc = XCreateGC(dpy->dpy, tt->draw,
+		       GCForeground |
+		       GCFunction |
+		       GCLineWidth |
+		       GCLineStyle |
+		       GCCapStyle,
+		       &val);
+	XDrawSegments(dpy->dpy, tt->draw, gc, seg, nseg);
+	XFreeGC(dpy->dpy, gc);
+}
+
+static void hv0(struct test *t, enum target target)
+{
+	char buf[1024];
+	struct test_target out, ref;
+	int a, alu, cap;
+	XSegment seg[(NUM_POINTS+1)*8];
+	int n, x, y, nseg;
+
+	printf("Testing drawing of zero-width line segments (%s): ",
+	       test_target_name(target));
+	fflush(stdout);
+
+	test_target_create_render(&t->out, target, &out);
+	test_target_create_render(&t->ref, target, &ref);
+
+	y = x = n = 0;
+	for (a = 0; a <= NUM_POINTS; a++) {
+		seg[n].x1 = a + 64;
+		seg[n].y1 = y + 64;
+		seg[n].x2 = NUM_POINTS + 64;
+		seg[n].y2 = y + 64;
+		n++; y++;
+
+		seg[n].x1 = NUM_POINTS - a + 64;
+		seg[n].y1 = y + 64;
+		seg[n].x2 = 0 + 64;
+		seg[n].y2 = y + 64;
+		n++; y++;
+
+		seg[n].x2 = a + 64;
+		seg[n].y2 = y + 64;
+		seg[n].x1 = NUM_POINTS + 64;
+		seg[n].y1 = y + 64;
+		n++; y++;
+
+		seg[n].x2 = NUM_POINTS - a + 64;
+		seg[n].y2 = y + 64;
+		seg[n].x1 = 0 + 64;
+		seg[n].y1 = y + 64;
+		n++; y++;
+
+
+		seg[n].y1 = a + 64;
+		seg[n].x1 = x + 64;
+		seg[n].y2 = NUM_POINTS + 64;
+		seg[n].x2 = x + 64;
+		n++; x++;
+
+		seg[n].y1 = NUM_POINTS - a + 64;
+		seg[n].x1 = x + 64;
+		seg[n].y2 = 0 + 64;
+		seg[n].x2 = x + 64;
+		n++; x++;
+
+		seg[n].y2 = a + 64;
+		seg[n].x2 = x + 64;
+		seg[n].y1 = NUM_POINTS + 64;
+		seg[n].x1 = x + 64;
+		n++; x++;
+
+		seg[n].y2 = NUM_POINTS - a + 64;
+		seg[n].x2 = x + 64;
+		seg[n].y1 = 0 + 64;
+		seg[n].x1 = x + 64;
+		n++; x++;
+	}
+
+	for (alu = 0; alu < 16; alu++) {
+		for (cap = CapNotLast; cap <= CapProjecting; cap++) {
+			for (nseg = 0; nseg < n; nseg++) {
+				sprintf(buf,
+					"cap=%d, alu=%d, nseg=%d",
+					cap, alu, nseg);
+
+				clear(&t->out, &out);
+				clear(&t->ref, &ref);
+
+				draw(&t->out, &out, alu, 0, LineSolid, cap,
+				     seg, nseg);
+				draw(&t->ref, &ref, alu, 0, LineSolid, cap,
+				     seg, nseg);
+
+				test_compare(t,
+					     out.draw, out.format,
+					     ref.draw, ref.format,
+					     0, 0, out.width, out.height,
+					     buf);
+			}
+		}
+	}
+
+	test_target_destroy_render(&t->out, &out);
+	test_target_destroy_render(&t->ref, &ref);
+
+	printf("\n");
+}
+
+static void general(struct test *t, enum target target)
+{
+	char buf[1024];
+	struct test_target out, ref;
+	int a, b, alu, lw, style, cap;
+	XSegment seg[NUM_POINTS*NUM_POINTS];
+	int n = 0;
+
+	printf("Testing drawing of general line segments (%s): ",
+	       test_target_name(target));
+	fflush(stdout);
+
+	test_target_create_render(&t->out, target, &out);
+	test_target_create_render(&t->ref, target, &ref);
+
+	style = LineSolid;
+
+	for (a = 0; a < NUM_POINTS; a++) {
+		for (b = 0; b < NUM_POINTS; b++) {
+			seg[n].x1 = points[a].x + 64;
+			seg[n].y1 = points[a].y + 64;
+			seg[n].x2 = points[b].x + 64;
+			seg[n].y2 = points[b].y + 64;
+			n++;
+		}
+	}
+
+	for (alu = 0; alu < 16; alu++) {
+		for (cap = CapNotLast; cap <= CapProjecting; cap++) {
+			for (lw = 0; lw <= 4; lw++) {
+				sprintf(buf,
+					"width=%d, cap=%d, alu=%d",
+					lw, cap, alu);
+
+				clear(&t->out, &out);
+				clear(&t->ref, &ref);
+
+				draw(&t->out, &out, alu, lw, style, cap,
+					  seg, n);
+				draw(&t->ref, &ref, alu, lw, style, cap,
+					  seg, n);
+
+				test_compare(t,
+					     out.draw, out.format,
+					     ref.draw, ref.format,
+					     0, 0, out.width, out.height,
+					     buf);
+			}
+		}
+	}
+
+	test_target_destroy_render(&t->out, &out);
+	test_target_destroy_render(&t->ref, &ref);
+
+	printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+	struct test test;
+	enum target t;
+
+	test_init(&test, argc, argv);
+
+	for (t = TARGET_FIRST; t <= TARGET_LAST; t++) {
+		hv0(&test, t);
+		general(&test, t);
+	}
+
+	return 0;
+}
diff --git a/test/Makefile.am b/test/Makefile.am
index f9906d4..66ed8eb 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -9,6 +9,7 @@ stress_TESTS = \
 	basic-putimage \
 	basic-lines \
 	basic-stress \
+	DrawSegments \
 	cursor-test \
 	render-fill \
 	render-trapezoid \
commit e453f276daa33a66a665e446a071d27e56ff15fe
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Sep 15 12:08:59 2014 +0100

    sna/io: Initialise return code to catch early segfaults
    
    In case we are ever given an invalid buffer that we then attempt to read
    past the end.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_io.c b/src/sna/sna_io.c
index 3ce3ded..0181838 100644
--- a/src/sna/sna_io.c
+++ b/src/sna/sna_io.c
@@ -1771,6 +1771,7 @@ indirect_replace(struct sna *sna,
 	if (!src_bo)
 		return false;
 
+	ret = false;
 	if (sigtrap_get() == 0) {
 		memcpy_blt(src, ptr, pixmap->drawable.bitsPerPixel,
 			   stride, src_bo->pitch,
@@ -1788,8 +1789,7 @@ indirect_replace(struct sna *sna,
 					     &pixmap->drawable, bo, 0, 0,
 					     &box, 1, 0);
 		sigtrap_put();
-	} else
-		ret = false;
+	}
 
 	kgem_bo_destroy(kgem, src_bo);
 


More information about the xorg-commit mailing list