[igt-dev] [PATCH i-g-t] tests/gem_render_copy: Use a more elaborate pattern of pixels

Ville Syrjala ville.syrjala at linux.intel.com
Fri Jun 29 16:23:57 UTC 2018


From: Ville Syrjälä <ville.syrjala at linux.intel.com>

Checking whether we can copy solid rectangles isn't particularly
robust. Eg. errors in texture coordinates/interpolation wouldn't
necessarily show up at all because all texels are identical.

Let's switch to a more elaborate pattern that should catch such
errors. And we'll also change the test to not start the copy
from position 0,0 in the texture.

We'll generate the reference image (against which the rendercopy
results are compared) by peforming an identical copy using the
cpu.

Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
---
 tests/gem_render_copy.c | 234 ++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 189 insertions(+), 45 deletions(-)

diff --git a/tests/gem_render_copy.c b/tests/gem_render_copy.c
index a036a9247e93..08a3cebf3bd7 100644
--- a/tests/gem_render_copy.c
+++ b/tests/gem_render_copy.c
@@ -52,16 +52,11 @@ IGT_TEST_DESCRIPTION("Basic test for the render_copy() function.");
 #define WIDTH 512
 #define STRIDE (WIDTH*4)
 #define HEIGHT 512
-#define SIZE (HEIGHT*STRIDE)
-
-#define SRC_COLOR	0xffff00ff
-#define DST_COLOR	0xfff0ff00
 
 typedef struct {
 	int drm_fd;
 	uint32_t devid;
 	drm_intel_bufmgr *bufmgr;
-	uint32_t linear[WIDTH * HEIGHT];
 } data_t;
 static int opt_dump_png = false;
 static int check_all_pixels = false;
@@ -83,36 +78,187 @@ static void scratch_buf_write_to_png(struct igt_buf *buf, const char *filename)
 	drm_intel_bo_unmap(buf->bo);
 }
 
+static void scratch_buf_draw_pattern(data_t *data, struct igt_buf *buf,
+				     int x, int y, int w, int h,
+				     int cx, int cy, int cw, int ch,
+				     bool use_alternate_colors)
+{
+	cairo_surface_t *surface;
+	cairo_pattern_t *pat;
+	cairo_t *cr;
+	void *map;
+
+	gem_set_domain(data->drm_fd, buf->bo->handle,
+		       I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
+
+	map = gem_mmap__cpu(data->drm_fd, buf->bo->handle, 0,
+			    buf->bo->size, PROT_READ | PROT_WRITE);
+
+	surface = cairo_image_surface_create_for_data(map,
+						      CAIRO_FORMAT_RGB24,
+						      igt_buf_width(buf),
+						      igt_buf_height(buf),
+						      buf->stride);
+
+	cr = cairo_create(surface);
+
+	cairo_rectangle(cr, cx, cy, cw, ch);
+	cairo_clip(cr);
+
+	pat = cairo_pattern_create_mesh();
+	cairo_mesh_pattern_begin_patch(pat);
+	cairo_mesh_pattern_move_to(pat, x,   y);
+	cairo_mesh_pattern_line_to(pat, x+w, y);
+	cairo_mesh_pattern_line_to(pat, x+w, y+h);
+	cairo_mesh_pattern_line_to(pat, x,   y+h);
+	if (use_alternate_colors) {
+		cairo_mesh_pattern_set_corner_color_rgb(pat, 0, 0.0, 1.0, 1.0);
+		cairo_mesh_pattern_set_corner_color_rgb(pat, 1, 1.0, 0.0, 1.0);
+		cairo_mesh_pattern_set_corner_color_rgb(pat, 2, 1.0, 1.0, 0.0);
+		cairo_mesh_pattern_set_corner_color_rgb(pat, 3, 0.0, 0.0, 0.0);
+	} else {
+		cairo_mesh_pattern_set_corner_color_rgb(pat, 0, 1.0, 0.0, 0.0);
+		cairo_mesh_pattern_set_corner_color_rgb(pat, 1, 0.0, 1.0, 0.0);
+		cairo_mesh_pattern_set_corner_color_rgb(pat, 2, 0.0, 0.0, 1.0);
+		cairo_mesh_pattern_set_corner_color_rgb(pat, 3, 1.0, 1.0, 1.0);
+	}
+	cairo_mesh_pattern_end_patch(pat);
+
+	cairo_rectangle(cr, x, y, w, h);
+	cairo_set_source(cr, pat);
+	cairo_fill(cr);
+	cairo_pattern_destroy(pat);
+
+	cairo_destroy(cr);
+
+	cairo_surface_destroy(surface);
+
+	munmap(map, buf->bo->size);
+
+	gem_set_domain(data->drm_fd, buf->bo->handle,
+		       I915_GEM_DOMAIN_GTT, 0);
+}
+
+static void
+scratch_buf_copy(data_t *data,
+		 struct igt_buf *src, int sx, int sy, int w, int h,
+		 struct igt_buf *dst, int dx, int dy)
+{
+	int width = igt_buf_width(dst);
+	int height  = igt_buf_height(dst);
+	uint32_t *linear_dst, *linear_src;
+
+	igt_assert_eq(igt_buf_width(dst), igt_buf_width(src));
+	igt_assert_eq(igt_buf_height(dst), igt_buf_height(src));
+	igt_assert_eq(dst->bo->size, src->bo->size);
+
+	linear_dst = malloc(dst->bo->size);
+	linear_src = malloc(src->bo->size);
+
+	gem_read(data->drm_fd, dst->bo->handle, 0,
+		 linear_dst, dst->bo->size);
+	gem_read(data->drm_fd, src->bo->handle, 0,
+		 linear_src, src->bo->size);
+
+	w = min(w, min(width - sx, width - dx));
+	w = min(h, min(height - sy, height - dy));
+
+	for (int y = 0; y < h; y++) {
+		for (int x = 0; x < w; x++) {
+			linear_dst[(dy+y) * width + (dx+x)] =
+				linear_src[(sy+y) * width + (sx+x)];
+		}
+	}
+
+	gem_write(data->drm_fd, dst->bo->handle, 0,
+		  linear_dst, dst->bo->size);
+
+	free(linear_dst);
+	free(linear_src);
+}
+
 static void scratch_buf_init(data_t *data, struct igt_buf *buf,
-			     int width, int height, int stride, uint32_t color)
+			     int width, int height, int stride)
 {
 	drm_intel_bo *bo;
-	int i;
+	int size = height * stride;
 
-	bo = drm_intel_bo_alloc(data->bufmgr, "", SIZE, 4096);
-	for (i = 0; i < width * height; i++)
-		data->linear[i] = color;
-	gem_write(data->drm_fd, bo->handle, 0, data->linear,
-		  sizeof(data->linear));
+	bo = drm_intel_bo_alloc(data->bufmgr, "", size, 4096);
 
 	buf->bo = bo;
 	buf->stride = stride;
 	buf->tiling = I915_TILING_NONE;
-	buf->size = SIZE;
+	buf->size = size;
+
+	igt_assert(igt_buf_width(buf) == width);
+	igt_assert(igt_buf_height(buf) == height);
 }
 
 static void
-scratch_buf_check(data_t *data, struct igt_buf *buf, int x, int y,
-		  uint32_t color)
+scratch_buf_check(data_t *data,
+		  struct igt_buf *buf,
+		  struct igt_buf *ref,
+		  int x, int y)
 {
-	uint32_t val;
+	int width = igt_buf_width(buf);
+	uint32_t buf_val, ref_val;
+	uint32_t *linear;
+
+	igt_assert_eq(igt_buf_width(buf), igt_buf_width(ref));
+	igt_assert_eq(igt_buf_height(buf), igt_buf_height(ref));
+	igt_assert_eq(buf->bo->size, ref->bo->size);
+
+	linear = malloc(buf->bo->size);
 
 	gem_read(data->drm_fd, buf->bo->handle, 0,
-		 data->linear, sizeof(data->linear));
-	val = data->linear[y * WIDTH + x];
-	igt_assert_f(val == color,
+		 linear, buf->bo->size);
+	buf_val = linear[y * width + x];
+
+	gem_read(data->drm_fd, ref->bo->handle, 0,
+		 linear, ref->bo->size);
+	ref_val = linear[y * width + x];
+
+	igt_assert_f(buf_val == ref_val,
 		     "Expected 0x%08x, found 0x%08x at (%d,%d)\n",
-		     color, val, x, y);
+		     ref_val, buf_val, x, y);
+
+	free(linear);
+}
+
+static void
+scratch_buf_check_all(data_t *data,
+		      struct igt_buf *buf,
+		      struct igt_buf *ref)
+{
+	int width = igt_buf_width(buf);
+	int height  = igt_buf_height(buf);
+	uint32_t *linear_buf, *linear_ref;
+
+	igt_assert_eq(igt_buf_width(buf), igt_buf_width(ref));
+	igt_assert_eq(igt_buf_height(buf), igt_buf_height(ref));
+	igt_assert_eq(buf->bo->size, ref->bo->size);
+
+	linear_buf = malloc(buf->bo->size);
+	linear_ref = malloc(ref->bo->size);
+
+	gem_read(data->drm_fd, buf->bo->handle, 0,
+		 linear_buf, buf->bo->size);
+	gem_read(data->drm_fd, ref->bo->handle, 0,
+		 linear_ref, ref->bo->size);
+
+	for (int y = 0; y < height; y++) {
+		for (int x = 0; x < width; x++) {
+			uint32_t buf_val = linear_buf[y * width + x];
+			uint32_t ref_val = linear_ref[y * width + x];
+
+			igt_assert_f(buf_val == ref_val,
+				     "Expected 0x%08x, found 0x%08x at (%d,%d)\n",
+				     ref_val, buf_val, x, y);
+		}
+	}
+
+	free(linear_ref);
+	free(linear_buf);
 }
 
 static int opt_handler(int opt, int opt_index, void *data)
@@ -132,7 +278,7 @@ int main(int argc, char **argv)
 {
 	data_t data = {0, };
 	struct intel_batchbuffer *batch = NULL;
-	struct igt_buf src, dst;
+	struct igt_buf src, dst, ref;
 	igt_render_copyfunc_t render_copy = NULL;
 	int opt_dump_aub = igt_aub_dump_enabled();
 
@@ -154,15 +300,28 @@ int main(int argc, char **argv)
 		igt_assert(batch);
 	}
 
-	scratch_buf_init(&data, &src, WIDTH, HEIGHT, STRIDE, SRC_COLOR);
-	scratch_buf_init(&data, &dst, WIDTH, HEIGHT, STRIDE, DST_COLOR);
+	scratch_buf_init(&data, &src, WIDTH, HEIGHT, STRIDE);
+	scratch_buf_init(&data, &dst, WIDTH, HEIGHT, STRIDE);
+	scratch_buf_init(&data, &ref, WIDTH, HEIGHT, STRIDE);
+
+	scratch_buf_draw_pattern(&data, &src,
+				 0, 0, WIDTH, HEIGHT,
+				 0, 0, WIDTH, HEIGHT, true);
+	scratch_buf_draw_pattern(&data, &dst,
+				 0, 0, WIDTH, HEIGHT,
+				 0, 0, WIDTH, HEIGHT, false);
 
-	scratch_buf_check(&data, &src, WIDTH / 2, HEIGHT / 2, SRC_COLOR);
-	scratch_buf_check(&data, &dst, WIDTH / 2, HEIGHT / 2, DST_COLOR);
+	scratch_buf_copy(&data,
+			 &dst, 0, 0, WIDTH, HEIGHT,
+			 &ref, 0, 0);
+	scratch_buf_copy(&data,
+			 &src, WIDTH/4, WIDTH/4, WIDTH/2, HEIGHT/2,
+			 &ref, WIDTH/2, WIDTH/2);
 
 	if (opt_dump_png) {
 		scratch_buf_write_to_png(&src, "source.png");
 		scratch_buf_write_to_png(&dst, "destination.png");
+		scratch_buf_write_to_png(&ref, "reference.png");
 	}
 
 	if (opt_dump_aub) {
@@ -180,8 +339,8 @@ int main(int argc, char **argv)
 	 *	  -------
 	 */
 	render_copy(batch, NULL,
-		    &src, 0, 0, WIDTH, HEIGHT,
-		    &dst, WIDTH / 2, HEIGHT / 2);
+		    &src, WIDTH/4, HEIGHT/4, WIDTH/2, HEIGHT/2,
+		    &dst, WIDTH/2, HEIGHT/2);
 
 	if (opt_dump_png)
 		scratch_buf_write_to_png(&dst, "result.png");
@@ -193,25 +352,10 @@ int main(int argc, char **argv)
 			STRIDE, 0);
 		drm_intel_bufmgr_gem_set_aub_dump(data.bufmgr, false);
 	} else if (check_all_pixels) {
-		uint32_t val;
-		int i, j;
-		gem_read(data.drm_fd, dst.bo->handle, 0,
-			 data.linear, sizeof(data.linear));
-		for (i = 0; i < WIDTH; i++) {
-			for (j = 0; j < HEIGHT; j++) {
-				uint32_t color = DST_COLOR;
-				val = data.linear[j * WIDTH + i];
-				if (j >= HEIGHT/2 && i >= WIDTH/2)
-					color = SRC_COLOR;
-
-				igt_assert_f(val == color,
-					     "Expected 0x%08x, found 0x%08x at (%d,%d)\n",
-					     color, val, i, j);
-			}
-		}
+		scratch_buf_check_all(&data, &dst, &ref);
 	} else {
-		scratch_buf_check(&data, &dst, 10, 10, DST_COLOR);
-		scratch_buf_check(&data, &dst, WIDTH - 10, HEIGHT - 10, SRC_COLOR);
+		scratch_buf_check(&data, &dst, &ref, 10, 10);
+		scratch_buf_check(&data, &dst, &ref, WIDTH - 10, HEIGHT - 10);
 	}
 
 	igt_exit();
-- 
2.16.4



More information about the igt-dev mailing list