[igt-dev] [PATCH i-g-t 6/7] tests/kms_ccs: Generate compressed surfaces with rendercopy

Dhinakaran Pandiyan dhinakaran.pandiyan at intel.com
Thu Feb 21 14:41:08 UTC 2019


lib/igt_fb.c now has capability to make use of rendercopy, which means
we do not have to handwrite compressed buffers.

Cc: Clinton Taylor <clinton.a.taylor at intel.com>
Cc: Ville Syrjälä <ville.syrjala at linux.intel.com>
Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan at intel.com>
---
 tests/kms_ccs.c | 202 ++++++++++++------------------------------------
 1 file changed, 49 insertions(+), 153 deletions(-)

diff --git a/tests/kms_ccs.c b/tests/kms_ccs.c
index 42596a45..8cbf100f 100644
--- a/tests/kms_ccs.c
+++ b/tests/kms_ccs.c
@@ -60,13 +60,14 @@ typedef struct {
 	igt_pipe_crc_t *pipe_crc;
 } data_t;
 
-#define RED			0x00ff0000
-#define COMPRESSED_RED		0x0ff0000f
-#define GREEN			0x0000ff00
-#define COMPRESSED_GREEN	0x000ff00f
-
-#define CCS_UNCOMPRESSED	0x0
-#define CCS_COMPRESSED		0x55
+const struct {
+	double r;
+	double g;
+	double b;
+} colors[2] = {
+	{1.0, 0.0, 0.0},
+	{0.0, 1.0, 0.0}
+};
 
 /*
  * Limit maximum used sprite plane width so this test will not mistakenly
@@ -192,104 +193,32 @@ static bool plane_has_format_with_ccs(data_t *data, igt_plane_t *plane, uint32_t
 	return false;
 }
 
-static void render_fb(data_t *data, uint32_t gem_handle, unsigned int size,
-		      enum test_fb_flags fb_flags,
-		      int height, unsigned int stride)
+static void addfb_init(struct igt_fb *fb, struct drm_mode_fb_cmd2 *f)
 {
-	uint32_t *ptr;
-	unsigned int half_height, half_size;
-	uint32_t uncompressed_color = data->plane ? GREEN : RED;
-	uint32_t compressed_color =
-		data->plane ? COMPRESSED_GREEN : COMPRESSED_RED;
-	uint32_t bad_color = RED;
 	int i;
 
-	ptr = gem_mmap__cpu(data->drm_fd, gem_handle, 0, size,
-			    PROT_READ | PROT_WRITE);
+	f->width = fb->width;
+	f->height = fb->height;
+	f->pixel_format = fb->drm_format;
+	f->flags = LOCAL_DRM_MODE_FB_MODIFIERS;
 
-	if (fb_flags & FB_COMPRESSED) {
-		/* In the compressed case, we want the top half of the
-		 * surface to be uncompressed and the bottom half to be
-		 * compressed.
-		 *
-		 * We need to cut the surface on a CCS cache-line boundary,
-		 * otherwise, we're going to be in trouble when we try to
-		 * generate CCS data for the surface.  A cache line in the
-		 * CCS is 16x16 cache-line-pairs in the main surface.  16
-		 * cache lines is 64 rows high.
-		 */
-		half_height = ALIGN(height, 128) / 2;
-		half_size = half_height * stride;
-		for (i = 0; i < size / 4; i++) {
-			if (i < half_size / 4)
-				ptr[i] = uncompressed_color;
-			else
-				ptr[i] = compressed_color;
-		}
-	} else {
-		/* When we're displaying the primary plane underneath a
-		 * sprite plane, cut out a 128 x 128 area (less than the sprite)
-		 * plane size which we paint red, so we know easily if it's
-		 * bad.
-		 */
-		for (i = 0; i < size / 4; i++) {
-			if ((fb_flags & FB_HAS_PLANE) &&
-			    (i / (stride / 4)) < 128 &&
-			    (i % (stride / 4)) < 128) {
-				ptr[i] = bad_color;
-			} else {
-				ptr[i] = uncompressed_color;
-			}
-		}
+	for (i = 0; i < fb->num_planes; i++) {
+		f->handles[i] = fb->gem_handle;
+		f->modifier[i] = fb->modifier;
+		f->pitches[i] = fb->strides[i];
+		f->offsets[i] = fb->offsets[i];
 	}
-
-	munmap(ptr, size);
-}
-
-static unsigned int
-y_tile_y_pos(unsigned int offset, unsigned int stride)
-{
-	unsigned int y_tiles, y;
-	y_tiles = (offset / 4096) / (stride / 128);
-	y = y_tiles * 32 + ((offset & 0x1f0) >> 4);
-	return y;
-}
-
-static void render_ccs(data_t *data, uint32_t gem_handle,
-		       uint32_t offset, uint32_t size,
-		       int height, unsigned int ccs_stride)
-{
-	unsigned int half_height, ccs_half_height;
-	uint8_t *ptr;
-	int i;
-
-	half_height = ALIGN(height, 128) / 2;
-	ccs_half_height = half_height / 16;
-
-	ptr = gem_mmap__cpu(data->drm_fd, gem_handle, offset, size,
-			    PROT_READ | PROT_WRITE);
-
-	for (i = 0; i < size; i++) {
-		if (y_tile_y_pos(i, ccs_stride) < ccs_half_height)
-			ptr[i] = CCS_UNCOMPRESSED;
-		else
-			ptr[i] = CCS_COMPRESSED;
-	}
-
-	munmap(ptr, size);
 }
 
 static void generate_fb(data_t *data, struct igt_fb *fb,
 			int width, int height,
 			enum test_fb_flags fb_flags)
 {
-	struct local_drm_mode_fb_cmd2 f = {};
-	unsigned int size[2];
+	struct drm_mode_fb_cmd2 f = {0};
+	uint32_t format;
 	uint64_t modifier;
+	cairo_t *cr;
 	int ret;
-	uint32_t ccs_handle;
-
-	memset(fb, 0, sizeof(*fb));
 
 	/* Use either compressed or Y-tiled to test. However, given the lack of
 	 * available bandwidth, we use linear for the primary plane when
@@ -303,74 +232,52 @@ static void generate_fb(data_t *data, struct igt_fb *fb,
 	else
 		modifier = 0;
 
-	f.flags = LOCAL_DRM_MODE_FB_MODIFIERS;
-	f.width = width;
-	f.height = height;
-
 	if (data->flags & TEST_BAD_PIXEL_FORMAT)
-		f.pixel_format = DRM_FORMAT_RGB565;
+		format = DRM_FORMAT_RGB565;
 	else
-		f.pixel_format = DRM_FORMAT_XRGB8888;
+		format = DRM_FORMAT_XRGB8888;
 
-	f.pitches[0] = ALIGN(width * 4, 128);
-	f.modifier[0] = modifier;
-	f.offsets[0] = 0;
-	size[0] = f.pitches[0] * ALIGN(height, 32);
+	igt_create_bo_for_fb(data->drm_fd, width, height, format, modifier, fb);
+	igt_assert(fb->gem_handle > 0);
 
-	if (fb_flags & FB_COMPRESSED) {
-		/* From the Sky Lake PRM, Vol 12, "Color Control Surface":
-		 *
-		 *    "The compression state of the cache-line pair is
-		 *    specified by 2 bits in the CCS.  Each CCS cache-line
-		 *    represents an area on the main surface of 16x16 sets
-		 *    of 128 byte Y-tiled cache-line-pairs. CCS is always Y
-		 *    tiled."
-		 *
-		 * A "cache-line-pair" for a Y-tiled surface is two
-		 * horizontally adjacent cache lines.  When operating in
-		 * bytes and rows, this gives us a scale-down factor of
-		 * 32x16.  Since the main surface has a 32-bit format, we
-		 * need to multiply width by 4 to get bytes.
-		 */
-		int ccs_width = ALIGN(width * 4, 32) / 32;
-		int ccs_height = ALIGN(height, 16) / 16;
-		int ccs_pitches = ALIGN(ccs_width * 1, 128);
-		int ccs_offsets = size[0];
+	addfb_init(fb, &f);
 
+	if (fb_flags & FB_COMPRESSED) {
 		if (fb_flags & FB_MISALIGN_AUX_STRIDE) {
 			igt_skip_on_f(width <= 1024,
 				      "FB already has the smallest possible stride\n");
-			ccs_pitches -= 64;
+			f.pitches[1] -= 64;
 		}
-		else if (fb_flags & FB_SMALL_AUX_STRIDE) {
+
+		if (fb_flags & FB_SMALL_AUX_STRIDE) {
 			igt_skip_on_f(width <= 1024,
 				      "FB already has the smallest possible stride\n");
-			ccs_pitches = ALIGN(ccs_width/2, 128);
+			f.pitches[1] = ALIGN(f.pitches[1]/2, 128);
 		}
 
-		size[1] = ccs_pitches * ALIGN(ccs_height, 32);
-
-		f.handles[0] = gem_create(data->drm_fd, size[0] + size[1]);
-		if (data->flags & TEST_BAD_CCS_HANDLE) {
-			/* Put the CCS buffer on a different BO. */
-			ccs_handle = gem_create(data->drm_fd, size[0] + size[1]);
-		} else
-			ccs_handle = f.handles[0];
+		if (fb_flags & FB_ZERO_AUX_STRIDE)
+			f.pitches[1] = 0;
 
-		if (!(data->flags & TEST_NO_AUX_BUFFER)) {
-			f.modifier[1] = modifier;
-			f.handles[1] = ccs_handle;
-			f.offsets[1] = ccs_offsets;
-			f.pitches[1] = (fb_flags & FB_ZERO_AUX_STRIDE)? 0:ccs_pitches;
+		/* Put the CCS buffer on a different BO. */
+		if (data->flags & TEST_BAD_CCS_HANDLE)
+			f.handles[1] = gem_create(data->drm_fd, fb->size);
 
-			render_ccs(data, f.handles[1], f.offsets[1], size[1],
-				   height, ccs_pitches);
+		if (data->flags & TEST_NO_AUX_BUFFER) {
+			f.handles[1] = 0;
+			f.modifier[1] = 0;
+			f.pitches[1] = 0;
+			f.offsets[1] = 0;
 		}
-	} else {
-		f.handles[0] = gem_create(data->drm_fd, size[0]);
 	}
 
-	render_fb(data, f.handles[0], size[0], fb_flags, height, f.pitches[0]);
+	if (!(data->flags & TEST_BAD_PIXEL_FORMAT)) {
+		int c = !!data->plane;
+
+		cr = igt_get_cairo_ctx(data->drm_fd, fb);
+		igt_paint_color(cr, 0, 0, width, height,
+				colors[c].r, colors[c].g, colors[c].b);
+		igt_put_cairo_ctx(data->drm_fd, fb, cr);
+	}
 
 	ret = drmIoctl(data->drm_fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f);
 	if (data->flags & TEST_FAIL_ON_ADDFB2) {
@@ -381,17 +288,6 @@ static void generate_fb(data_t *data, struct igt_fb *fb,
 		igt_assert_eq(ret, 0);
 
 	fb->fb_id = f.fb_id;
-	fb->fd = data->drm_fd;
-	fb->gem_handle = f.handles[0];
-	fb->is_dumb = false;
-	fb->drm_format = f.pixel_format;
-	fb->width = f.width;
-	fb->height = f.height;
-	fb->strides[0] = f.pitches[0];
-	fb->modifier = f.modifier[0];
-	fb->size = size[0];
-	fb->cairo_surface = NULL;
-	fb->domain = 0;
 }
 
 static bool try_config(data_t *data, enum test_fb_flags fb_flags,
-- 
2.17.1



More information about the igt-dev mailing list