[igt-dev] [PATCH i-g-t v2] tests/gem_render_copy: Use a more elaborate pattern of pixels
Ville Syrjala
ville.syrjala at linux.intel.com
Tue Jul 3 12:30:22 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.
v2: Use gtt mmap instead of pread/pwrite (Chris)
Offset the dst coordinates by -1,-1 to make sure
the copy doesn't go past the intended region
Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
---
tests/gem_render_copy.c | 248 +++++++++++++++++++++++++++++++++++++++---------
1 file changed, 202 insertions(+), 46 deletions(-)
diff --git a/tests/gem_render_copy.c b/tests/gem_render_copy.c
index a036a9247e93..2efec0783585 100644
--- a/tests/gem_render_copy.c
+++ b/tests/gem_render_copy.c
@@ -30,6 +30,7 @@
*/
#include "igt.h"
+#include "igt_x86.h"
#include <stdbool.h>
#include <unistd.h>
#include <cairo.h>
@@ -52,16 +53,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 +79,198 @@ static void scratch_buf_write_to_png(struct igt_buf *buf, const char *filename)
drm_intel_bo_unmap(buf->bo);
}
+static void *linear_copy(data_t *data, struct igt_buf *buf)
+{
+ void *map, *linear;
+
+ igt_assert_eq(posix_memalign(&linear, 16, buf->bo->size), 0);
+
+ gem_set_domain(data->drm_fd, buf->bo->handle,
+ I915_GEM_DOMAIN_GTT, 0);
+
+ map = gem_mmap__gtt(data->drm_fd, buf->bo->handle,
+ buf->bo->size, PROT_READ);
+
+ igt_memcpy_from_wc(linear, map, buf->bo->size);
+
+ munmap(map, buf->bo->size);
+
+ return linear;
+}
+
+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, *linear;
+
+ linear = linear_copy(data, buf);
+
+ surface = cairo_image_surface_create_for_data(linear,
+ 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);
+
+ gem_set_domain(data->drm_fd, buf->bo->handle,
+ I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+
+ map = gem_mmap__gtt(data->drm_fd, buf->bo->handle,
+ buf->bo->size, PROT_READ | PROT_WRITE);
+
+ memcpy(map, linear, buf->bo->size);
+
+ munmap(map, buf->bo->size);
+
+ free(linear);
+}
+
+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);
+
+ gem_set_domain(data->drm_fd, dst->bo->handle,
+ I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+ gem_set_domain(data->drm_fd, src->bo->handle,
+ I915_GEM_DOMAIN_GTT, 0);
+
+ linear_dst = gem_mmap__gtt(data->drm_fd, dst->bo->handle,
+ dst->bo->size, PROT_WRITE);
+ linear_src = gem_mmap__gtt(data->drm_fd, src->bo->handle,
+ src->bo->size, PROT_READ);
+
+ w = min(w, min(width - sx, width - dx));
+ w = min(h, min(height - sy, height - dy));
+
+ for (int y = 0; y < h; y++) {
+ igt_memcpy_from_wc(&linear_dst[(dy+y) * width + dx],
+ &linear_src[(sy+y) * width + sx],
+ w * 4);
+ }
+
+ munmap(linear_dst, dst->bo->size);
+ munmap(linear_src, src->bo->size);
+}
+
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 = linear_copy(data, buf);
+ buf_val = linear[y * width + x];
+ free(linear);
+
+ linear = linear_copy(data, ref);
+ ref_val = linear[y * width + x];
+ free(linear);
- 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,
+ 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);
+}
+
+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 = linear_copy(data, buf);
+ linear_ref = linear_copy(data, ref);
+
+ 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 +290,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 +312,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-1, WIDTH/2-1);
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 +351,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-1, HEIGHT/2-1);
if (opt_dump_png)
scratch_buf_write_to_png(&dst, "result.png");
@@ -193,25 +364,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