All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] i-g-t: kms testcase for NV12 feature
@ 2015-05-02  3:11 Chandra Konduru
  2015-05-02  3:11 ` [PATCH 1/2] i-g-t: Prep work for adding NV12 testcase Chandra Konduru
  2015-05-02  3:11 ` [PATCH 2/2] i-g-t: Adding display " Chandra Konduru
  0 siblings, 2 replies; 8+ messages in thread
From: Chandra Konduru @ 2015-05-02  3:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: thomas.wood

From: chandra konduru <chandra.konduru@intel.com>

This patch series adds necessary prep work for NV12 support to
igt lib and actual testcase to test NV12 feature. Refer to
individual patch header and comments in code for details.

chandra konduru (2):
  i-g-t: Prep work for adding NV12 testcase
  i-g-t: Adding display NV12 testcase

 lib/igt_fb.c            | 316 +++++++++++++++++++++++++++--
 lib/igt_fb.h            |   9 +-
 lib/intel_batchbuffer.c |  16 +-
 lib/intel_batchbuffer.h |   3 +-
 lib/intel_reg.h         |   1 +
 lib/ioctl_wrappers.c    |  10 +-
 lib/ioctl_wrappers.h    |   2 +-
 tests/.gitignore        |   1 +
 tests/Android.mk        |   1 +
 tests/Makefile.sources  |   1 +
 tests/kms_nv12.c        | 529 ++++++++++++++++++++++++++++++++++++++++++++++++
 tests/kms_render.c      |   4 +-
 12 files changed, 866 insertions(+), 27 deletions(-)
 create mode 100644 tests/kms_nv12.c

-- 
1.9.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/2] i-g-t: Prep work for adding NV12 testcase
  2015-05-02  3:11 [PATCH 0/2] i-g-t: kms testcase for NV12 feature Chandra Konduru
@ 2015-05-02  3:11 ` Chandra Konduru
  2015-05-12 15:47   ` Thomas Wood
  2015-05-02  3:11 ` [PATCH 2/2] i-g-t: Adding display " Chandra Konduru
  1 sibling, 1 reply; 8+ messages in thread
From: Chandra Konduru @ 2015-05-02  3:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: thomas.wood

From: chandra konduru <chandra.konduru@intel.com>

This patch adds necessary prep work for nv12 testcase:
  - updated fb allocation functions to handle NV12 format
  - igt helper function to return png image size
  - igt helper function to calculate start of uv in a given NV12 buffer
  - igt helper function to map buffer for host access
  - populates fb->...[4] parameters for NV12
  - igt helper function to convert RGB data to NV12
  - updated drm_format to bpp to handle NV12
  - updated fast copy blit function to deal NV12 subplanes
  - made an update to kms_render testcase due to above changes

Signed-off-by: chandra konduru <chandra.konduru@intel.com>
---
 lib/igt_fb.c            | 316 +++++++++++++++++++++++++++++++++++++++++++++---
 lib/igt_fb.h            |   9 +-
 lib/intel_batchbuffer.c |  16 ++-
 lib/intel_batchbuffer.h |   3 +-
 lib/intel_reg.h         |   1 +
 lib/ioctl_wrappers.c    |  10 +-
 lib/ioctl_wrappers.h    |   2 +-
 tests/kms_render.c      |   4 +-
 8 files changed, 334 insertions(+), 27 deletions(-)

diff --git a/lib/igt_fb.c b/lib/igt_fb.c
index cc4b8ee..dedee9e 100644
--- a/lib/igt_fb.c
+++ b/lib/igt_fb.c
@@ -74,7 +74,7 @@ static struct format_desc_struct {
 
 
 /* helpers to create nice-looking framebuffers */
-static int create_bo_for_fb(int fd, int width, int height, int bpp,
+static int create_bo_for_fb(int fd, int width, int height, int bpp, int bpp2,
 			    uint64_t tiling, unsigned bo_size,
 			    uint32_t *gem_handle_ret,
 			    unsigned *size_ret,
@@ -99,13 +99,17 @@ static int create_bo_for_fb(int fd, int width, int height, int bpp,
 		for (stride = 512; stride < v; stride *= 2)
 			;
 
-		v = stride * height;
+		/* planar formats height is 1.5x */
+		v = stride * (bpp2 ? (height * 3) / 2 : height);
+
 		for (size = 1024*1024; size < v; size *= 2)
 			;
 	} else {
 		/* Scan-out has a 64 byte alignment restriction */
 		stride = (width * (bpp / 8) + 63) & ~63;
-		size = stride * height;
+
+		/* planar formats height is 1.5x */
+		size = stride * (bpp2 ? (height * 3) / 2 : height);
 	}
 
 	if (bo_size == 0)
@@ -393,6 +397,75 @@ void igt_paint_image(cairo_t *cr, const char *filename,
 }
 
 /**
+ * igt_get_image_size:
+ * @filename: filename of the png image
+ * @width: width of the image
+ * @height: height of the image
+ *
+ * This function returns @width and @height of the png image in @filename,
+ * which is loaded from the package data directory.
+ */
+void
+igt_get_image_size(const char *filename, int *width, int *height)
+{
+	cairo_surface_t *image;
+	FILE* f;
+
+	f = igt_fopen_data(filename);
+
+	image = cairo_image_surface_create_from_png_stream(&stdio_read_func, f);
+	igt_assert(cairo_surface_status(image) == CAIRO_STATUS_SUCCESS);
+
+	*width = cairo_image_surface_get_width(image);
+	*height = cairo_image_surface_get_height(image);
+
+	cairo_surface_destroy(image);
+
+	fclose(f);
+}
+
+
+/**
+ * igt_fb_calc_uv:
+ * @fb: pointer to an #igt_fb structure
+ *
+ * This function calculates UV offset in bytes and UV starting line number
+ * for requested NV12 @fb.
+ */
+void
+igt_fb_calc_uv(struct igt_fb *fb)
+{
+	if (fb->drm_format != DRM_FORMAT_NV12)
+		return;
+
+	switch (fb->tiling) {
+	case LOCAL_DRM_FORMAT_MOD_NONE:
+		fb->uv_y_start = fb->height;
+		break;
+	case LOCAL_I915_FORMAT_MOD_X_TILED:
+		fb->uv_y_start = fb->height;
+		break;
+	case LOCAL_I915_FORMAT_MOD_Y_TILED:
+		fb->uv_y_start = fb->height;
+		break;
+	case LOCAL_I915_FORMAT_MOD_Yf_TILED:
+		/* tile-Yf requires uv to start on a new tile row */
+		if (fb->height % 64)
+			fb->uv_y_start = (fb->height + 63) & ~63;
+		else
+			fb->uv_y_start = fb->height;
+		break;
+	default:
+		igt_assert(0);
+	}
+
+	fb->uv_offset = fb->uv_y_start * fb->stride;
+
+	/* assert that fb has enough lines to hold y and uv sub-planes */
+	igt_assert(fb->size / fb->stride >= fb->uv_y_start + fb->height / 2);
+}
+
+/**
  * igt_create_fb_with_bo_size:
  * @fd: open i915 drm file descriptor
  * @width: width of the framebuffer in pixel
@@ -418,24 +491,32 @@ igt_create_fb_with_bo_size(int fd, int width, int height,
 			   struct igt_fb *fb, unsigned bo_size)
 {
 	uint32_t fb_id;
-	int bpp;
+	int bpp, bpp2;
 
 	memset(fb, 0, sizeof(*fb));
 
-	bpp = igt_drm_format_to_bpp(format);
+	bpp = igt_drm_format_to_bpp(format, 0);
+	bpp2 = igt_drm_format_to_bpp(format, 1);
 
-	igt_debug("%s(width=%d, height=%d, format=0x%x [bpp=%d], tiling=0x%"PRIx64", size=%d\n",
-		  __func__, width, height, format, bpp, tiling, bo_size);
-	do_or_die(create_bo_for_fb(fd, width, height, bpp, tiling, bo_size,
+	igt_debug("%s(width=%d, height=%d, format=0x%x [bpp=%d, %d], tiling=0x%"PRIx64", size=%d\n",
+		  __func__, width, height, format, bpp, bpp2, tiling, bo_size);
+	do_or_die(create_bo_for_fb(fd, width, height, bpp, bpp2, tiling, bo_size,
 				   &fb->gem_handle, &fb->size, &fb->stride));
 
 	igt_debug("%s(handle=%d, pitch=%d)\n",
 		  __func__, fb->gem_handle, fb->stride);
 
+	fb->width = width;
+	fb->height = height;
+	fb->tiling = tiling;
+	fb->drm_format = format;
+
+	igt_fb_calc_uv(fb);
+
 	if (tiling != LOCAL_DRM_FORMAT_MOD_NONE &&
 	    tiling != LOCAL_I915_FORMAT_MOD_X_TILED) {
 		do_or_die(__kms_addfb(fd, fb->gem_handle, width, height,
-				      fb->stride, format, tiling,
+				      fb->stride, format, tiling, fb->uv_offset,
 				      LOCAL_DRM_MODE_FB_MODIFIERS, &fb_id));
 	} else {
 		uint32_t handles[4];
@@ -449,21 +530,213 @@ igt_create_fb_with_bo_size(int fd, int width, int height,
 		handles[0] = fb->gem_handle;
 		pitches[0] = fb->stride;
 
+		if (format == DRM_FORMAT_NV12) {
+			handles[1] = fb->gem_handle;
+			pitches[1] = fb->stride;
+			offsets[1] = fb->uv_offset;
+		}
+
 		do_or_die(drmModeAddFB2(fd, width, height, format,
 					handles, pitches, offsets,
 					&fb_id, 0));
 	}
 
-	fb->width = width;
-	fb->height = height;
-	fb->tiling = tiling;
-	fb->drm_format = format;
 	fb->fb_id = fb_id;
 
 	return fb_id;
 }
 
 /**
+ * igt_fb_gem_mmap:
+ * @fd: open i915 drm file descriptor
+ * @fb: pointer to an #igt_fb structure
+ *
+ * This function memory maps gem buffer for cpu access and saves mmap pointer
+ * in @fb.
+ */
+void
+igt_fb_gem_mmap(int fd, struct igt_fb *fb)
+{
+	if (!fb->mmap_gtt)
+		fb->mmap_gtt = gem_mmap__gtt(fd, fb->gem_handle, fb->size,
+			PROT_READ | PROT_WRITE);
+	igt_assert(fb->mmap_gtt);
+}
+
+/**
+ * igt_fb_csc_xrgb_to_nv12:
+ * @fd: open i915 drm file descriptor
+ * @width: width of the framebuffer to be converted
+ * @height: height of the framebuffer to be converted
+ * @dst: pointer to an #igt_fb structure holding destination framebuffer
+ * @src: pointer to an #igt_fb structure holding source framebuffer
+ *
+ * This function converts source framebuffer into destination framebuffer
+ * format. It also mmaps the underlying gem buffer if it isn't mmaped
+ * before.
+ *
+ * For now:
+ *    - it expects both src and dst fbs are same size and tiling
+ */
+void
+igt_fb_csc_xrgb_to_nv12(int fd, struct igt_fb *dst_fb, struct igt_fb *src_fb)
+{
+	unsigned char *nv12;
+	unsigned char *xrgb;
+	unsigned char y, v, u;
+	float yf, vf, uf;
+	unsigned char r, g, b;
+	int i, j;
+	int xrgb_pos;
+	int y_pos;
+	int uv_pos;
+	int uv_base;
+	unsigned int obj_tiling;
+	struct igt_fb *temp_src_fb, *temp_dst_fb;
+	struct igt_fb fb1, fb2;
+	int temp_src_id, temp_dst_id;
+
+	igt_assert(dst_fb);
+	igt_assert(src_fb);
+	igt_assert(dst_fb->width == src_fb->width);
+	igt_assert(dst_fb->height == src_fb->height);
+	igt_assert(src_fb->tiling == dst_fb->tiling);
+
+	igt_assert(src_fb->drm_format == DRM_FORMAT_XRGB8888);
+	igt_assert(dst_fb->drm_format == DRM_FORMAT_NV12);
+
+	/*
+	 * Steps: Not the best approach but gets job done for igt
+	 *     (1) create linear temp_src, temp_dst
+	 *     (2) fast blit src --> temp src
+	 *     (3) gem map temp_src, temp_dst
+	 *     (4) host conversion & copy from temp src --> temp dst
+	 *     (5) fast blit temp dst --> dst
+	 *     (6) free temp fbs
+	 *
+	 * For Linear/X:
+	 *     perform 3 & 4 only
+	 * For Y/Yf:
+	 *     perform all steps
+	 */
+
+	if (src_fb->tiling == LOCAL_I915_FORMAT_MOD_Y_TILED ||
+		src_fb->tiling == LOCAL_I915_FORMAT_MOD_Yf_TILED) {
+
+		temp_src_fb = &fb1;
+		temp_dst_fb = &fb2;
+
+		/* (1) create linear temp_src, temp_dst */
+		temp_src_id = igt_create_fb(fd,
+			src_fb->width, src_fb->height,
+			src_fb->drm_format,
+			LOCAL_DRM_FORMAT_MOD_NONE,
+			temp_src_fb);
+		igt_assert(temp_src_id);
+
+		temp_dst_id = igt_create_fb(fd,
+			dst_fb->width, dst_fb->height,
+			dst_fb->drm_format,
+			LOCAL_DRM_FORMAT_MOD_NONE,
+			temp_dst_fb);
+		igt_assert(temp_dst_id);
+
+		if (src_fb->tiling == LOCAL_I915_FORMAT_MOD_Y_TILED)
+			obj_tiling = I915_TILING_Y;
+		else
+			obj_tiling = I915_TILING_Yf;
+
+		/* (2) fast blit src --> temp src */
+		igt_blitter_fast_copy__raw(fd,
+			src_fb->gem_handle,
+			src_fb->stride,
+			obj_tiling,
+			0, 0,
+			temp_src_fb->width, temp_src_fb->height,
+			igt_drm_format_to_bpp(temp_src_fb->drm_format, 0),
+			temp_src_fb->gem_handle,
+			temp_src_fb->stride,
+			I915_TILING_NONE,
+			0, 0);
+	} else {
+		temp_src_fb = src_fb;
+		temp_dst_fb = dst_fb;
+	}
+
+	/* (3) gem map temp_src, temp_dst */
+	igt_fb_gem_mmap(fd, temp_src_fb);
+	igt_fb_gem_mmap(fd, temp_dst_fb);
+
+	/* (4) host conversion & copy from temp src --> temp dst */
+	xrgb = (unsigned char *) temp_src_fb->mmap_gtt;
+	nv12 = (unsigned char *) temp_dst_fb->mmap_gtt;
+	uv_base = temp_dst_fb->stride * temp_dst_fb->height;
+
+	for (i = 0; i < temp_src_fb->height; i++) {
+		xrgb_pos = i * temp_src_fb->stride;
+		y_pos = i * temp_dst_fb->stride;
+		uv_pos = temp_dst_fb->stride * i / 2;
+		for (j = 0; j < temp_src_fb->width; j++) {
+			b = xrgb[xrgb_pos++];
+			g = xrgb[xrgb_pos++];
+			r = xrgb[xrgb_pos++];
+			xrgb_pos++;
+
+			/* use floats for intermediate calcs, to get better results */
+			yf =  (0.257 * r) + (0.504 * g) + (0.098 * b) + 16;
+			uf = -(0.148 * r) - (0.291 * g) + (0.439 * b) + 128;
+			vf =  (0.439 * r) - (0.368 * g) - (0.071 * b) + 128;
+
+			y = (unsigned char) yf;
+			u = (unsigned char) uf;
+			v = (unsigned char) vf;
+
+			nv12[y_pos++] = y;
+
+			if (!(j % 2) && !(i % 2)) {
+				nv12[uv_base + uv_pos++] = u;
+				nv12[uv_base + uv_pos++] = v;
+			}
+		}
+	}
+
+	/* (5) fast blit temp dst --> dst */
+	if (dst_fb->tiling == LOCAL_I915_FORMAT_MOD_Y_TILED ||
+		dst_fb->tiling == LOCAL_I915_FORMAT_MOD_Yf_TILED) {
+
+		/* blit y-plane */
+		igt_blitter_fast_copy__raw(fd,
+			temp_dst_fb->gem_handle,
+			temp_dst_fb->stride,
+			I915_TILING_NONE,
+			0, 0,
+			dst_fb->width, dst_fb->height,
+			igt_drm_format_to_bpp(dst_fb->drm_format, 0),
+			dst_fb->gem_handle,
+			dst_fb->stride,
+			obj_tiling,
+			0, 0);
+
+		/* blit uv-plane */
+		igt_blitter_fast_copy__raw(fd,
+			temp_dst_fb->gem_handle,
+			temp_dst_fb->stride,
+			I915_TILING_NONE,
+			0, temp_dst_fb->uv_y_start,
+			dst_fb->width, dst_fb->height,
+			igt_drm_format_to_bpp(dst_fb->drm_format, 1),
+			dst_fb->gem_handle,
+			dst_fb->stride,
+			obj_tiling,
+			0, dst_fb->uv_y_start);
+
+		/* (6) free temp fbs */
+		igt_remove_fb(fd, temp_src_fb);
+		igt_remove_fb(fd, temp_dst_fb);
+	}
+}
+
+/**
  * igt_create_fb:
  * @fd: open i915 drm file descriptor
  * @width: width of the framebuffer in pixel
@@ -686,6 +959,7 @@ static void destroy_cairo_surface__blit(void *arg)
 				   I915_TILING_NONE,
 				   0, 0, /* src_x, src_y */
 				   fb->width, fb->height,
+				   0,
 				   fb->gem_handle,
 				   fb->stride,
 				   obj_tiling,
@@ -712,8 +986,8 @@ static void create_cairo_surface__blit(int fd, struct igt_fb *fb)
 	 * cairo). This linear bo will be then blitted to its final
 	 * destination, tiling it at the same time.
 	 */
-	bpp = igt_drm_format_to_bpp(fb->drm_format);
-	ret = create_bo_for_fb(fd, fb->width, fb->height, bpp,
+	bpp = igt_drm_format_to_bpp(fb->drm_format, 0);
+	ret = create_bo_for_fb(fd, fb->width, fb->height, bpp, 0,
 				LOCAL_DRM_FORMAT_MOD_NONE, 0,
 				&blit->linear.handle,
 				&blit->linear.size,
@@ -734,6 +1008,7 @@ static void create_cairo_surface__blit(int fd, struct igt_fb *fb)
 				   obj_tiling,
 				   0, 0, /* src_x, src_y */
 				   fb->width, fb->height,
+				   bpp,
 				   blit->linear.handle,
 				   blit->linear.stride,
 				   I915_TILING_NONE,
@@ -893,15 +1168,24 @@ uint32_t igt_bpp_depth_to_drm_format(int bpp, int depth)
 /**
  * igt_drm_format_to_bpp:
  * @drm_format: drm fourcc pixel format code
+ * @plane: plane id
  *
  * Returns:
  * The bits per pixel for the given drm fourcc pixel format code. Fails hard if
  * no match was found.
  */
-uint32_t igt_drm_format_to_bpp(uint32_t drm_format)
+uint32_t igt_drm_format_to_bpp(uint32_t drm_format, int plane)
 {
 	struct format_desc_struct *f;
 
+	if (drm_format == DRM_FORMAT_NV12 && plane == 0)
+		return 8;
+	if (drm_format == DRM_FORMAT_NV12 && plane == 1)
+		return 16;
+
+	if (plane)
+		return 0;
+
 	for_each_format(f)
 		if (f->drm_id == drm_format)
 			return f->bpp;
diff --git a/lib/igt_fb.h b/lib/igt_fb.h
index a07acd2..9e227e8 100644
--- a/lib/igt_fb.h
+++ b/lib/igt_fb.h
@@ -54,10 +54,13 @@ struct igt_fb {
 	uint64_t tiling;
 	unsigned size;
 	cairo_surface_t *cairo_surface;
+	void *mmap_gtt;
 	uint32_t src_x;
 	uint32_t src_y;
 	uint32_t src_w;
 	uint32_t src_h;
+	uint32_t uv_y_start;
+	uint32_t uv_offset;
 };
 
 enum igt_text_align {
@@ -82,6 +85,9 @@ unsigned int igt_create_color_fb(int fd, int width, int height,
 unsigned int igt_create_stereo_fb(int drm_fd, drmModeModeInfo *mode,
 				  uint32_t format, uint64_t tiling);
 void igt_remove_fb(int fd, struct igt_fb *fb);
+void igt_fb_gem_mmap(int fd, struct igt_fb *fb);
+void igt_fb_csc_xrgb_to_nv12(int fd, struct igt_fb *dst, struct igt_fb *src);
+void igt_fb_calc_uv(struct igt_fb *fb);
 
 /* cairo-based painting */
 cairo_t *igt_get_cairo_ctx(int fd, struct igt_fb *fb);
@@ -98,10 +104,11 @@ void igt_write_fb_to_png(int fd, struct igt_fb *fb, const char *filename);
 int igt_cairo_printf_line(cairo_t *cr, enum igt_text_align align,
 			       double yspacing, const char *fmt, ...)
 			       __attribute__((format (printf, 4, 5)));
+void igt_get_image_size(const char *filename, int *width, int *height);
 
 /* helpers to handle drm fourcc codes */
 uint32_t igt_bpp_depth_to_drm_format(int bpp, int depth);
-uint32_t igt_drm_format_to_bpp(uint32_t drm_format);
+uint32_t igt_drm_format_to_bpp(uint32_t drm_format, int plane);
 const char *igt_format_str(uint32_t drm_format);
 void igt_get_all_formats(const uint32_t **formats, int *format_count);
 
diff --git a/lib/intel_batchbuffer.c b/lib/intel_batchbuffer.c
index 8b68e52..a2cd6ab 100644
--- a/lib/intel_batchbuffer.c
+++ b/lib/intel_batchbuffer.c
@@ -518,7 +518,7 @@ static uint32_t fast_copy_dword0(unsigned int src_tiling,
 }
 
 static uint32_t fast_copy_dword1(unsigned int src_tiling,
-				 unsigned int dst_tiling)
+				 unsigned int dst_tiling, uint32_t color_depth)
 {
 	uint32_t dword1 = 0;
 
@@ -527,7 +527,10 @@ static uint32_t fast_copy_dword1(unsigned int src_tiling,
 	if (dst_tiling == I915_TILING_Yf)
 		dword1 |= XY_FAST_COPY_DST_TILING_Yf;
 
-	dword1 |= XY_FAST_COPY_COLOR_DEPTH_32;
+	if (color_depth == 8)
+		dword1 |= XY_FAST_COPY_COLOR_DEPTH_8;
+	else
+		dword1 |= XY_FAST_COPY_COLOR_DEPTH_32;
 
 	return dword1;
 }
@@ -585,6 +588,7 @@ static void exec_blit(int fd,
  * @src_y: Y coordinate of the source region to copy
  * @width: Width of the region to copy
  * @height: Height of the region to copy
+ * @color_depth: Color depth of the buffer
  * @dst_handle: GEM handle of the source buffer
  * @dst_stride: Stride (in bytes) of the destination buffer
  * @dst_tiling: Tiling mode of the destination buffer
@@ -602,6 +606,7 @@ void igt_blitter_fast_copy__raw(int fd,
 
 				/* size */
 				unsigned int width, unsigned int height,
+				uint32_t color_depth,
 
 				/* dst */
 				uint32_t dst_handle,
@@ -620,7 +625,7 @@ void igt_blitter_fast_copy__raw(int fd,
 	src_pitch = fast_copy_pitch(src_stride, src_tiling);
 	dst_pitch = fast_copy_pitch(dst_stride, dst_tiling);
 	dword0 = fast_copy_dword0(src_tiling, dst_tiling);
-	dword1 = fast_copy_dword1(src_tiling, dst_tiling);
+	dword1 = fast_copy_dword1(src_tiling, dst_tiling, color_depth);
 
 #define CHECK_RANGE(x)	((x) >= 0 && (x) < (1 << 15))
 	assert(CHECK_RANGE(src_x) && CHECK_RANGE(src_y) &&
@@ -670,6 +675,7 @@ void igt_blitter_fast_copy__raw(int fd,
  * @src_y: source pixel y-coordination
  * @width: width of the copied rectangle
  * @height: height of the copied rectangle
+ * @color_depth: Color depth of the buffer
  * @dst: destination i-g-t buffer object
  * @dst_x: destination pixel x-coordination
  * @dst_y: destination pixel y-coordination
@@ -680,7 +686,7 @@ void igt_blitter_fast_copy__raw(int fd,
  */
 void igt_blitter_fast_copy(struct intel_batchbuffer *batch,
 			   struct igt_buf *src, unsigned src_x, unsigned src_y,
-			   unsigned width, unsigned height,
+			   unsigned width, unsigned height, uint32_t color_depth,
 			   struct igt_buf *dst, unsigned dst_x, unsigned dst_y)
 {
 	uint32_t src_pitch, dst_pitch;
@@ -689,7 +695,7 @@ void igt_blitter_fast_copy(struct intel_batchbuffer *batch,
 	src_pitch = fast_copy_pitch(src->stride, src->tiling);
 	dst_pitch = fast_copy_pitch(dst->stride, src->tiling);
 	dword0 = fast_copy_dword0(src->tiling, dst->tiling);
-	dword1 = fast_copy_dword1(src->tiling, dst->tiling);
+	dword1 = fast_copy_dword1(src->tiling, dst->tiling, color_depth);
 
 #define CHECK_RANGE(x)	((x) >= 0 && (x) < (1 << 15))
 	assert(CHECK_RANGE(src_x) && CHECK_RANGE(src_y) &&
diff --git a/lib/intel_batchbuffer.h b/lib/intel_batchbuffer.h
index 62c8396..0e0feed 100644
--- a/lib/intel_batchbuffer.h
+++ b/lib/intel_batchbuffer.h
@@ -226,7 +226,7 @@ unsigned igt_buf_height(struct igt_buf *buf);
 
 void igt_blitter_fast_copy(struct intel_batchbuffer *batch,
 			  struct igt_buf *src, unsigned src_x, unsigned src_y,
-			  unsigned width, unsigned height,
+			  unsigned width, unsigned height, uint32_t color_depth,
 			  struct igt_buf *dst, unsigned dst_x, unsigned dst_y);
 
 void igt_blitter_fast_copy__raw(int fd,
@@ -238,6 +238,7 @@ void igt_blitter_fast_copy__raw(int fd,
 
 				/* size */
 				unsigned int width, unsigned int height,
+				uint32_t color_depth,
 
 				/* dst */
 				uint32_t dst_handle,
diff --git a/lib/intel_reg.h b/lib/intel_reg.h
index 0ffa803..9f3de7a 100644
--- a/lib/intel_reg.h
+++ b/lib/intel_reg.h
@@ -2530,6 +2530,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 /* dword 1 */
 #define   XY_FAST_COPY_SRC_TILING_Yf			(1 <<  31)
 #define   XY_FAST_COPY_DST_TILING_Yf			(1 <<  30)
+#define   XY_FAST_COPY_COLOR_DEPTH_8 			(0  << 24)
 #define   XY_FAST_COPY_COLOR_DEPTH_32			(3  << 24)
 
 #define MI_STORE_DWORD_IMM		((0x20<<23)|2)
diff --git a/lib/ioctl_wrappers.c b/lib/ioctl_wrappers.c
index a269d0f..93717a0 100644
--- a/lib/ioctl_wrappers.c
+++ b/lib/ioctl_wrappers.c
@@ -54,6 +54,7 @@
 #include "intel_chipset.h"
 #include "intel_io.h"
 #include "igt_debugfs.h"
+#include "igt_fb.h"
 #include "config.h"
 
 #include "ioctl_wrappers.h"
@@ -1221,7 +1222,7 @@ void igt_require_fb_modifiers(int fd)
 
 int __kms_addfb(int fd, uint32_t handle, uint32_t width, uint32_t height,
 		uint32_t stride, uint32_t pixel_format, uint64_t modifier,
-		uint32_t flags, uint32_t *buf_id)
+		uint32_t uv_offset, uint32_t flags, uint32_t *buf_id)
 {
 	struct local_drm_mode_fb_cmd2 f;
 	int ret;
@@ -1238,6 +1239,13 @@ int __kms_addfb(int fd, uint32_t handle, uint32_t width, uint32_t height,
 	f.pitches[0] = stride;
 	f.modifier[0] = modifier;
 
+	if (pixel_format == DRM_FORMAT_NV12) {
+		f.handles[1] = handle;
+		f.pitches[1] = stride;
+		f.offsets[1] = uv_offset;
+		f.modifier[1] = modifier;
+	}
+
 	ret = drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f);
 
 	*buf_id = f.fb_id;
diff --git a/lib/ioctl_wrappers.h b/lib/ioctl_wrappers.h
index bc5d4bd..3d93a5e 100644
--- a/lib/ioctl_wrappers.h
+++ b/lib/ioctl_wrappers.h
@@ -175,6 +175,6 @@ void igt_require_fb_modifiers(int fd);
  */
 int __kms_addfb(int fd, uint32_t handle, uint32_t width, uint32_t height,
 		uint32_t stride, uint32_t pixel_format, uint64_t modifier,
-		uint32_t flags, uint32_t *buf_id);
+		uint32_t uv_offset, uint32_t flags, uint32_t *buf_id);
 
 #endif /* IOCTL_WRAPPERS_H */
diff --git a/tests/kms_render.c b/tests/kms_render.c
index 1759eaa..4a7aaec 100644
--- a/tests/kms_render.c
+++ b/tests/kms_render.c
@@ -78,8 +78,8 @@ static void gpu_blit(struct igt_fb *dst_fb, struct igt_fb *src_fb)
 
 	igt_assert(dst_fb->drm_format == src_fb->drm_format);
 	igt_assert(src_fb->drm_format == DRM_FORMAT_RGB565 ||
-	       igt_drm_format_to_bpp(src_fb->drm_format) != 16);
-	bpp = igt_drm_format_to_bpp(src_fb->drm_format);
+	       igt_drm_format_to_bpp(src_fb->drm_format, 0) != 16);
+	bpp = igt_drm_format_to_bpp(src_fb->drm_format, 0);
 	dst_bo = gem_handle_to_libdrm_bo(bufmgr, drm_fd, "destination",
 					 dst_fb->gem_handle);
 	igt_assert(dst_bo);
-- 
1.9.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/2] i-g-t: Adding display NV12 testcase
  2015-05-02  3:11 [PATCH 0/2] i-g-t: kms testcase for NV12 feature Chandra Konduru
  2015-05-02  3:11 ` [PATCH 1/2] i-g-t: Prep work for adding NV12 testcase Chandra Konduru
@ 2015-05-02  3:11 ` Chandra Konduru
  2015-05-07  6:48   ` Daniel Vetter
  2015-05-09  4:32   ` [PATCH] " Chandra Konduru
  1 sibling, 2 replies; 8+ messages in thread
From: Chandra Konduru @ 2015-05-02  3:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: thomas.wood

From: chandra konduru <chandra.konduru@intel.com>

This patch adds kms_nv12 test case. It covers testing NV12 in
all supported linear/tile-X/tile-Y/tile-Yf tile formats in
0 and 180 orientations. For each tiling format, it tests
various combinations of planes and scaling.

It has some very preliminary crc support and it is bit flaky.
Though I have seen once-in-a-while crc check failures, most of the
time they pass, so enabled by-default. If they cause headaches
they can be disabled as needed.

Signed-off-by: chandra konduru <chandra.konduru@intel.com>
---
 tests/.gitignore       |   1 +
 tests/Android.mk       |   1 +
 tests/Makefile.sources |   1 +
 tests/kms_nv12.c       | 529 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 532 insertions(+)
 create mode 100644 tests/kms_nv12.c

diff --git a/tests/.gitignore b/tests/.gitignore
index 796e330..35c0e6e 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -147,6 +147,7 @@ kms_vblank
 kms_crtc_background_color
 kms_plane_scaling
 kms_panel_fitting
+kms_nv12
 pm_lpsp
 pm_rc6_residency
 pm_rpm
diff --git a/tests/Android.mk b/tests/Android.mk
index fac9931..c0c6383 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -81,6 +81,7 @@ else
     kms_pwrite_crc \
     kms_pipe_b_c_ivb \
     kms_legacy_colorkey
+	kms_nv12 \
     IGT_LOCAL_CFLAGS += -DANDROID_HAS_CAIRO=0
 endif
 
diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index 4cbc50d..b68224e 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -78,6 +78,7 @@ TESTS_progs_M = \
 	kms_crtc_background_color \
 	kms_plane_scaling \
 	kms_panel_fitting \
+	kms_nv12 \
 	pm_lpsp \
 	pm_rpm \
 	pm_rps \
diff --git a/tests/kms_nv12.c b/tests/kms_nv12.c
new file mode 100644
index 0000000..e88c934
--- /dev/null
+++ b/tests/kms_nv12.c
@@ -0,0 +1,529 @@
+/*
+ * Copyright © 2013,2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include <math.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include "drmtest.h"
+#include "igt_debugfs.h"
+#include "igt_kms.h"
+#include "igt_core.h"
+#include "intel_chipset.h"
+#include "ioctl_wrappers.h"
+
+IGT_TEST_DESCRIPTION("Test display NV12 support");
+
+uint32_t devid;
+typedef struct {
+	int drm_fd;
+	igt_display_t display;
+	igt_crc_t crc1;
+	igt_crc_t crc2;
+	igt_pipe_crc_t *pipe_crc;
+	int num_scalers;
+
+	struct igt_fb fb1;
+	struct igt_fb fb1_nv12;
+	struct igt_fb fb2;
+	struct igt_fb fb2_nv12;
+	struct igt_fb fb3;
+	struct igt_fb fb3_nv12;
+	int fb_id1;
+	int fb_id1_nv12;
+	int fb_id2;
+	int fb_id2_nv12;
+	int fb_id3;
+	int fb_id3_nv12;
+
+	igt_plane_t *plane1;
+	igt_plane_t *plane2;
+	igt_plane_t *plane3;
+
+	uint64_t tiled;
+	int rotation;
+	int crc;
+} data_t;
+
+#define IMG_FILE  "1080p-left.png"
+#define SOLID_COLOR      0xFFFFFF       /* BGR 8bpc */
+
+static void
+paint_pattern(data_t *d, struct igt_fb *fb, uint16_t w, uint16_t h)
+{
+	cairo_t *cr;
+
+	cr = igt_get_cairo_ctx(d->drm_fd, fb);
+	igt_paint_test_pattern(cr, w, h);
+	cairo_destroy(cr);
+}
+
+static void
+paint_image(data_t *d, struct igt_fb *fb, uint16_t w, uint16_t h)
+{
+	cairo_t *cr;
+
+	cr = igt_get_cairo_ctx(d->drm_fd, fb);
+	igt_paint_image(cr, IMG_FILE, 0, 0, w, h);
+	cairo_destroy(cr);
+}
+
+static void
+paint_solid_color(data_t *d, struct igt_fb *fb, uint16_t w, uint16_t h,
+	uint32_t color)
+{
+	cairo_t *cr;
+	double r, g, b;
+
+	cr = igt_get_cairo_ctx(d->drm_fd, fb);
+
+	/* Paint with solid color */
+	r = (double) (color & 0xFF) / 255.0;
+	g = (double) ((color & 0xFF00) >> 8) / 255.0;
+	b = (double) ((color & 0xFF0000) >> 16) / 255.0;
+	igt_paint_color(cr, 0, 0, w, h, r, g, b);
+
+	cairo_destroy(cr);
+}
+
+static void prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe,
+			igt_plane_t *plane, drmModeModeInfo *mode, enum igt_commit_style s)
+{
+	igt_display_t *display = &data->display;
+
+	igt_output_set_pipe(output, pipe);
+
+	/* create the pipe_crc object for this pipe */
+	igt_pipe_crc_free(data->pipe_crc);
+	data->pipe_crc = igt_pipe_crc_new(pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
+
+	/* before allocating, free if any older fb */
+	if (data->fb_id1) {
+		igt_remove_fb(data->drm_fd, &data->fb1);
+		data->fb_id1 = 0;
+	}
+
+	/* allocate fb for plane 1 */
+	data->fb_id1 = igt_create_fb(data->drm_fd,
+			mode->hdisplay, mode->vdisplay,
+			DRM_FORMAT_XRGB8888,
+			LOCAL_I915_FORMAT_MOD_X_TILED, /* tiled */
+			&data->fb1);
+	igt_assert(data->fb_id1);
+
+	paint_pattern(data, &data->fb1, mode->hdisplay, mode->vdisplay);
+
+	/*
+	 * We always set the primary plane to actually enable the pipe as
+	 * there's no way (that works) to light up a pipe with only a sprite
+	 * plane enabled at the moment.
+	 */
+	if (!plane->is_primary) {
+		igt_plane_t *primary;
+
+		primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
+		igt_plane_set_fb(primary, &data->fb1);
+	}
+
+	igt_plane_set_fb(plane, &data->fb1);
+	if (s == COMMIT_LEGACY) {
+		int ret;
+		ret = drmModeSetCrtc(data->drm_fd,
+				output->config.crtc->crtc_id,
+				data->fb_id1,
+				plane->pan_x, plane->pan_y,
+				&output->id,
+				1,
+				mode);
+		igt_assert(ret == 0);
+	} else {
+		igt_display_commit2(display, s);
+	}
+}
+
+static void cleanup_crtc(data_t *data, igt_output_t *output, igt_plane_t *plane)
+{
+	igt_display_t *display = &data->display;
+
+	igt_pipe_crc_free(data->pipe_crc);
+	data->pipe_crc = NULL;
+
+	if (data->fb_id1) {
+		igt_remove_fb(data->drm_fd, &data->fb1);
+		data->fb_id1 = 0;
+	}
+	if (data->fb_id2) {
+		igt_remove_fb(data->drm_fd, &data->fb2);
+		data->fb_id2 = 0;
+	}
+	if (data->fb_id3) {
+		igt_remove_fb(data->drm_fd, &data->fb3);
+		data->fb_id3 = 0;
+	}
+
+	if (data->fb_id1_nv12) {
+		igt_remove_fb(data->drm_fd, &data->fb1_nv12);
+		data->fb_id1_nv12 = 0;
+	}
+
+	if (data->fb_id2_nv12) {
+		igt_remove_fb(data->drm_fd, &data->fb2_nv12);
+		data->fb_id2_nv12 = 0;
+	}
+
+	if (data->fb_id3_nv12) {
+		igt_remove_fb(data->drm_fd, &data->fb3_nv12);
+		data->fb_id3_nv12 = 0;
+	}
+
+	if (!plane->is_primary) {
+		igt_plane_t *primary;
+
+		primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
+		igt_plane_set_fb(primary, NULL);
+	}
+
+	igt_plane_set_fb(plane, NULL);
+	igt_output_set_pipe(output, PIPE_ANY);
+
+	igt_display_commit2(display, COMMIT_UNIVERSAL);
+}
+
+static void test_nv12_plane(data_t *d)
+{
+	igt_display_t *display = &d->display;
+	igt_output_t *output;
+	enum pipe pipe;
+	int valid_tests = 0;
+	int img_width;
+	int img_height;
+
+	igt_require(d->display.has_universal_planes);
+	igt_require(d->num_scalers);
+
+	for_each_connected_output(display, output) {
+		drmModeModeInfo *mode;
+		mode = igt_output_get_mode(output);
+		pipe = output->config.pipe;
+
+		igt_output_set_pipe(output, pipe);
+
+		/* get planes */
+		d->plane1 = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
+		d->plane2 = igt_output_get_plane(output, IGT_PLANE_2);
+		d->plane3 = igt_output_get_plane(output, IGT_PLANE_3);
+
+		/* set required rotation */
+		igt_plane_set_rotation(d->plane1, d->rotation);
+		igt_plane_set_rotation(d->plane2, d->rotation);
+		igt_plane_set_rotation(d->plane3, d->rotation);
+
+		/* Set up display with plane 1 */
+		prepare_crtc(d, output, pipe, d->plane1, mode, COMMIT_LEGACY);
+
+		/* allocate fb2, fb2_nv12, fb1_nv12 with image size */
+		igt_get_image_size(IMG_FILE, &img_width, &img_height);
+
+		/* fb2 is in RGB format */
+		d->fb_id2 = igt_create_fb(d->drm_fd,
+				img_width, img_height,
+				DRM_FORMAT_XRGB8888,
+				d->tiled, /* tiled */
+				&d->fb2);
+		igt_assert(d->fb_id2);
+
+		/* fb1_nv12 is in NV12 format */
+		d->fb_id1_nv12 = igt_create_fb(d->drm_fd,
+				img_width, img_height,
+				DRM_FORMAT_NV12,
+				d->tiled, /* tiled */
+				&d->fb1_nv12);
+		igt_assert(d->fb_id1_nv12);
+
+		/* fb2_nv12 is in NV12 format */
+		d->fb_id2_nv12 = igt_create_fb(d->drm_fd,
+				img_width, img_height,
+				DRM_FORMAT_NV12,
+				d->tiled,
+				&d->fb2_nv12);
+		igt_assert(d->fb_id2_nv12);
+
+		/* fb3 is in RGB */
+		d->fb_id3 = igt_create_fb(d->drm_fd,
+				mode->hdisplay, mode->vdisplay,
+				DRM_FORMAT_ARGB8888,
+				d->tiled, /* tiled */
+				&d->fb3);
+		igt_assert(d->fb_id3);
+
+		if (d->crc) {
+			/*
+			 * CRC test:
+			 * 1st CRC: plane 1: RGB FS, plane 2: RGB 19x10  --> CRC1
+			 * 2nd CRC: plane 1: RGB FS, plane 2: NV12 19x10 --> CRC2
+			 * make sure CRC1 == CRC2
+			 *
+			 * For CRCs to work, cannot use any image/data because
+			 * chrome-upsampling can fail CRC comparison.
+			 * Though it is a very basic, solid color is expected to work
+			 */
+			paint_solid_color(d, &d->fb2, d->fb2.width, d->fb2.height,
+				SOLID_COLOR);
+
+			/* Setup to capture CRC1 when plane 2 is in RGB mode */
+			igt_plane_set_fb(d->plane2, &d->fb2);
+			igt_fb_set_position(&d->fb2, d->plane2, 0, 0);
+			igt_fb_set_size(&d->fb2, d->plane2, d->fb2.width, d->fb2.height);
+			igt_plane_set_position(d->plane2, 0, 0);
+			igt_plane_set_size(d->plane2, d->fb2.width, d->fb2.height);
+			igt_display_commit2(display, COMMIT_UNIVERSAL);
+			igt_pipe_crc_collect_crc(d->pipe_crc, &d->crc1);
+
+			/* Setup to capture CRC2 when plane 2 is in NV12 mode */
+			igt_fb_csc_xrgb_to_nv12(d->drm_fd, &d->fb2_nv12, &d->fb2);
+			igt_plane_set_fb(d->plane2, &d->fb2_nv12);
+			igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
+			igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
+				d->fb2_nv12.height);
+			igt_plane_set_position(d->plane2, 0, 0);
+			igt_plane_set_size(d->plane2, d->fb2_nv12.width,d->fb2_nv12.height);
+			igt_display_commit2(display, COMMIT_UNIVERSAL);
+			igt_pipe_crc_collect_crc(d->pipe_crc, &d->crc2);
+
+			igt_assert_crc_equal(&d->crc1, &d->crc2);
+		}
+
+		/*
+		 * Non-CRC tests:
+		 * Mimicing some not exactly but closer to some real usage
+		 */
+
+		/* set up data for fb2: both fb1_nv12, fb2_nv12 uses this */
+		paint_image(d, &d->fb2, img_width, img_height);
+
+		/* set up data in fb1_nv12: fb2 RGB-> fb1_nv12 */
+		igt_fb_csc_xrgb_to_nv12(d->drm_fd, &d->fb1_nv12, &d->fb2);
+
+		/* set up data in fb2_nv12: fb2 RGB-> fb2_nv12 */
+		igt_fb_csc_xrgb_to_nv12(d->drm_fd, &d->fb2_nv12, &d->fb2);
+
+		/* set up data in fb3 */
+		paint_pattern(d, &d->fb3, d->fb3.width, d->fb3.height);
+
+		/* Set up fb2_nv12->plane2 mapping. */
+		igt_plane_set_fb(d->plane2, &d->fb2_nv12);
+		/* 2nd plane nv12 windowed - no scaling */
+		igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
+		igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
+			d->fb2_nv12.height);
+		igt_plane_set_position(d->plane2, 0, 0);
+		igt_plane_set_size(d->plane2, d->fb2_nv12.width, d->fb2_nv12.height);
+		igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+		/* Change primary plane to nv12 full screen: scaling + NV12 */
+		igt_plane_set_fb(d->plane1, &d->fb1_nv12);
+		igt_fb_set_position(&d->fb1_nv12, d->plane1, 0, 0);
+		igt_fb_set_size(&d->fb1_nv12, d->plane1, d->fb1_nv12.width,
+			d->fb1_nv12.height);
+		igt_plane_set_position(d->plane1, 0, 0);
+		igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay);
+		igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+		/* Set up fb3->plane3 mapping. */
+		igt_plane_set_fb(d->plane3, &d->fb3);
+
+		/* 3rd plane full screen - no scaling. */
+		igt_fb_set_position(&d->fb3, d->plane3, 0, 0);
+		igt_fb_set_size(&d->fb3, d->plane3, d->fb3.width, d->fb3.height);
+		igt_plane_set_position(d->plane3, 0, 0);
+		igt_plane_set_size(d->plane3, d->fb3.width, d->fb3.height);
+		igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+		/* 2nd plane nv12 up scaling */
+		igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
+		igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
+			d->fb2_nv12.height);
+		igt_plane_set_position(d->plane2, 100, 100);
+		igt_plane_set_size(d->plane2, mode->hdisplay-200, mode->vdisplay-200);
+		igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+		/* 2nd plane nv12 down scaling */
+		igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
+		igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
+			d->fb2_nv12.height);
+		igt_plane_set_position(d->plane2, 1024, 0);
+		igt_plane_set_size(d->plane2, d->fb2_nv12.width * 2/3,
+			d->fb2_nv12.height * 2/3);
+		igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+		/* Back to single plane mode  - rgb & no scaling */
+		igt_plane_set_fb(d->plane1, &d->fb1);
+		igt_plane_set_fb(d->plane2, NULL);
+		igt_plane_set_fb(d->plane3, NULL);
+		igt_fb_set_position(&d->fb1, d->plane1, 0, 0);
+		igt_fb_set_size(&d->fb1, d->plane1, mode->hdisplay, mode->vdisplay);
+		igt_plane_set_position(d->plane1, 0, 0);
+		igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay);
+		igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+		/* single plane mode  - rgb & scaling */
+		igt_plane_set_fb(d->plane1, &d->fb1);
+		igt_fb_set_position(&d->fb1, d->plane1, 0, 0);
+		igt_fb_set_size(&d->fb1, d->plane1, d->fb1.width/2, d->fb1.height/2);
+		igt_plane_set_position(d->plane1, 0, 0);
+		igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay);
+		igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+		/* single plane mode  - nv12 & scaling */
+		igt_plane_set_fb(d->plane1, &d->fb1_nv12);
+		igt_fb_set_position(&d->fb1_nv12, d->plane1, 0, 0);
+		igt_fb_set_size(&d->fb1_nv12, d->plane1, d->fb1_nv12.width,
+			d->fb1_nv12.height);
+		igt_plane_set_position(d->plane1, 0, 0);
+		igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay);
+		igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+		valid_tests++;
+
+		cleanup_crtc(d, output, d->plane1);
+	}
+	igt_require_f(valid_tests, "no valid crtc/connector combinations found\n");
+}
+
+static void test_nv12_unsupported_plane(data_t *d)
+{
+	igt_display_t *display = &d->display;
+	igt_output_t *output;
+	enum pipe pipe;
+	int valid_tests = 0;
+
+	igt_require(d->display.has_universal_planes);
+	igt_require(d->num_scalers);
+
+	for_each_connected_output(display, output) {
+		drmModeModeInfo *mode;
+		mode = igt_output_get_mode(output);
+		pipe = output->config.pipe;
+
+		igt_output_set_pipe(output, pipe);
+
+		/* Set up display with plane 1 */
+		d->plane1 = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
+		prepare_crtc(d, output, pipe, d->plane1, mode, COMMIT_LEGACY);
+
+		d->fb_id3_nv12 = igt_create_fb(d->drm_fd,
+				1920, 1080,
+				DRM_FORMAT_NV12,
+				d->tiled,
+				&d->fb3_nv12);
+		igt_assert(d->fb_id3_nv12);
+
+		/* Set up fb3_nv12->plane3 mapping. */
+		d->plane2 = igt_output_get_plane(output, IGT_PLANE_3);
+		igt_plane_set_fb(d->plane3, &d->fb3_nv12);
+
+		/* 3rd plane nv12 windowed - no scaling */
+		igt_fb_set_position(&d->fb3_nv12, d->plane3, 0, 0);
+		igt_fb_set_size(&d->fb3_nv12, d->plane3, d->fb3_nv12.width,
+			d->fb3_nv12.height);
+		igt_plane_set_position(d->plane3, 0, 0);
+		igt_plane_set_size(d->plane3, d->fb3_nv12.width, d->fb3_nv12.height);
+
+		/* Should fail because NV12 is not supported on plane 3 */
+		igt_assert(igt_display_try_commit2(display, COMMIT_UNIVERSAL)
+			== -EINVAL);
+
+		valid_tests++;
+
+		igt_plane_set_fb(d->plane3, NULL);
+		cleanup_crtc(d, output, d->plane1);
+	}
+	igt_require_f(valid_tests, "no valid crtc/connector combinations found\n");
+}
+
+igt_main
+{
+	data_t data = {};
+
+	igt_skip_on_simulation();
+
+	igt_fixture {
+		data.drm_fd = drm_open_any();
+
+		kmstest_set_vt_graphics_mode();
+
+		igt_require_pipe_crc();
+
+		igt_display_init(&data.display, data.drm_fd);
+	}
+	devid = intel_get_drm_devid(data.drm_fd);
+
+	data.num_scalers = intel_gen(devid) >= 9 ? 2 : 0;
+
+	data.crc = 1;
+	data.rotation = IGT_ROTATION_0;
+	igt_subtest_f("nv12-plane-linear") {
+		data.tiled = LOCAL_DRM_FORMAT_MOD_NONE;
+		test_nv12_plane(&data);
+	}
+	igt_subtest_f("nv12-plane-tile-x") {
+		data.tiled = LOCAL_I915_FORMAT_MOD_X_TILED;
+		test_nv12_plane(&data);
+	}
+	igt_subtest_f("nv12-plane-tile-y") {
+		data.tiled = LOCAL_I915_FORMAT_MOD_Y_TILED;
+		test_nv12_plane(&data);
+	}
+	igt_subtest_f("nv12-plane-tile-yf") {
+		data.tiled = LOCAL_I915_FORMAT_MOD_Yf_TILED;
+		test_nv12_plane(&data);
+	}
+
+	data.rotation = IGT_ROTATION_180;
+	igt_subtest_f("nv12-plane-linear-rot-180") {
+		data.tiled = LOCAL_DRM_FORMAT_MOD_NONE;
+		test_nv12_plane(&data);
+	}
+	igt_subtest_f("nv12-plane-tile-x-rot-180") {
+		data.tiled = LOCAL_I915_FORMAT_MOD_X_TILED;
+		test_nv12_plane(&data);
+	}
+	igt_subtest_f("nv12-plane-tile-y-rot-180") {
+		data.tiled = LOCAL_I915_FORMAT_MOD_Y_TILED;
+		test_nv12_plane(&data);
+	}
+	igt_subtest_f("nv12-plane-tile-yf-rot-180") {
+		data.tiled = LOCAL_I915_FORMAT_MOD_Yf_TILED;
+		test_nv12_plane(&data);
+	}
+
+	igt_subtest_f("nv12-on-unsupported-plane") {
+		data.tiled = LOCAL_DRM_FORMAT_MOD_NONE;
+		test_nv12_unsupported_plane(&data);
+	}
+
+	igt_fixture {
+		igt_display_fini(&data.display);
+	}
+}
-- 
1.9.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] i-g-t: Adding display NV12 testcase
  2015-05-02  3:11 ` [PATCH 2/2] i-g-t: Adding display " Chandra Konduru
@ 2015-05-07  6:48   ` Daniel Vetter
  2015-05-09  4:32   ` [PATCH] " Chandra Konduru
  1 sibling, 0 replies; 8+ messages in thread
From: Daniel Vetter @ 2015-05-07  6:48 UTC (permalink / raw)
  To: Chandra Konduru; +Cc: intel-gfx, thomas.wood

On Fri, May 01, 2015 at 08:11:39PM -0700, Chandra Konduru wrote:
> From: chandra konduru <chandra.konduru@intel.com>
> 
> This patch adds kms_nv12 test case. It covers testing NV12 in
> all supported linear/tile-X/tile-Y/tile-Yf tile formats in
> 0 and 180 orientations. For each tiling format, it tests
> various combinations of planes and scaling.
> 
> It has some very preliminary crc support and it is bit flaky.
> Though I have seen once-in-a-while crc check failures, most of the
> time they pass, so enabled by-default. If they cause headaches
> they can be disabled as needed.

Sporadic crc failures are probably watermark issues. Have you seen
underruns reported?
-Daniel

> 
> Signed-off-by: chandra konduru <chandra.konduru@intel.com>
> ---
>  tests/.gitignore       |   1 +
>  tests/Android.mk       |   1 +
>  tests/Makefile.sources |   1 +
>  tests/kms_nv12.c       | 529 +++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 532 insertions(+)
>  create mode 100644 tests/kms_nv12.c
> 
> diff --git a/tests/.gitignore b/tests/.gitignore
> index 796e330..35c0e6e 100644
> --- a/tests/.gitignore
> +++ b/tests/.gitignore
> @@ -147,6 +147,7 @@ kms_vblank
>  kms_crtc_background_color
>  kms_plane_scaling
>  kms_panel_fitting
> +kms_nv12
>  pm_lpsp
>  pm_rc6_residency
>  pm_rpm
> diff --git a/tests/Android.mk b/tests/Android.mk
> index fac9931..c0c6383 100644
> --- a/tests/Android.mk
> +++ b/tests/Android.mk
> @@ -81,6 +81,7 @@ else
>      kms_pwrite_crc \
>      kms_pipe_b_c_ivb \
>      kms_legacy_colorkey
> +	kms_nv12 \
>      IGT_LOCAL_CFLAGS += -DANDROID_HAS_CAIRO=0
>  endif
>  
> diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> index 4cbc50d..b68224e 100644
> --- a/tests/Makefile.sources
> +++ b/tests/Makefile.sources
> @@ -78,6 +78,7 @@ TESTS_progs_M = \
>  	kms_crtc_background_color \
>  	kms_plane_scaling \
>  	kms_panel_fitting \
> +	kms_nv12 \
>  	pm_lpsp \
>  	pm_rpm \
>  	pm_rps \
> diff --git a/tests/kms_nv12.c b/tests/kms_nv12.c
> new file mode 100644
> index 0000000..e88c934
> --- /dev/null
> +++ b/tests/kms_nv12.c
> @@ -0,0 +1,529 @@
> +/*
> + * Copyright © 2013,2014 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + *
> + */
> +
> +#include <math.h>
> +#include <fcntl.h>
> +#include <sys/stat.h>
> +
> +#include "drmtest.h"
> +#include "igt_debugfs.h"
> +#include "igt_kms.h"
> +#include "igt_core.h"
> +#include "intel_chipset.h"
> +#include "ioctl_wrappers.h"
> +
> +IGT_TEST_DESCRIPTION("Test display NV12 support");
> +
> +uint32_t devid;
> +typedef struct {
> +	int drm_fd;
> +	igt_display_t display;
> +	igt_crc_t crc1;
> +	igt_crc_t crc2;
> +	igt_pipe_crc_t *pipe_crc;
> +	int num_scalers;
> +
> +	struct igt_fb fb1;
> +	struct igt_fb fb1_nv12;
> +	struct igt_fb fb2;
> +	struct igt_fb fb2_nv12;
> +	struct igt_fb fb3;
> +	struct igt_fb fb3_nv12;
> +	int fb_id1;
> +	int fb_id1_nv12;
> +	int fb_id2;
> +	int fb_id2_nv12;
> +	int fb_id3;
> +	int fb_id3_nv12;
> +
> +	igt_plane_t *plane1;
> +	igt_plane_t *plane2;
> +	igt_plane_t *plane3;
> +
> +	uint64_t tiled;
> +	int rotation;
> +	int crc;
> +} data_t;
> +
> +#define IMG_FILE  "1080p-left.png"
> +#define SOLID_COLOR      0xFFFFFF       /* BGR 8bpc */
> +
> +static void
> +paint_pattern(data_t *d, struct igt_fb *fb, uint16_t w, uint16_t h)
> +{
> +	cairo_t *cr;
> +
> +	cr = igt_get_cairo_ctx(d->drm_fd, fb);
> +	igt_paint_test_pattern(cr, w, h);
> +	cairo_destroy(cr);
> +}
> +
> +static void
> +paint_image(data_t *d, struct igt_fb *fb, uint16_t w, uint16_t h)
> +{
> +	cairo_t *cr;
> +
> +	cr = igt_get_cairo_ctx(d->drm_fd, fb);
> +	igt_paint_image(cr, IMG_FILE, 0, 0, w, h);
> +	cairo_destroy(cr);
> +}
> +
> +static void
> +paint_solid_color(data_t *d, struct igt_fb *fb, uint16_t w, uint16_t h,
> +	uint32_t color)
> +{
> +	cairo_t *cr;
> +	double r, g, b;
> +
> +	cr = igt_get_cairo_ctx(d->drm_fd, fb);
> +
> +	/* Paint with solid color */
> +	r = (double) (color & 0xFF) / 255.0;
> +	g = (double) ((color & 0xFF00) >> 8) / 255.0;
> +	b = (double) ((color & 0xFF0000) >> 16) / 255.0;
> +	igt_paint_color(cr, 0, 0, w, h, r, g, b);
> +
> +	cairo_destroy(cr);
> +}
> +
> +static void prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe,
> +			igt_plane_t *plane, drmModeModeInfo *mode, enum igt_commit_style s)
> +{
> +	igt_display_t *display = &data->display;
> +
> +	igt_output_set_pipe(output, pipe);
> +
> +	/* create the pipe_crc object for this pipe */
> +	igt_pipe_crc_free(data->pipe_crc);
> +	data->pipe_crc = igt_pipe_crc_new(pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
> +
> +	/* before allocating, free if any older fb */
> +	if (data->fb_id1) {
> +		igt_remove_fb(data->drm_fd, &data->fb1);
> +		data->fb_id1 = 0;
> +	}
> +
> +	/* allocate fb for plane 1 */
> +	data->fb_id1 = igt_create_fb(data->drm_fd,
> +			mode->hdisplay, mode->vdisplay,
> +			DRM_FORMAT_XRGB8888,
> +			LOCAL_I915_FORMAT_MOD_X_TILED, /* tiled */
> +			&data->fb1);
> +	igt_assert(data->fb_id1);
> +
> +	paint_pattern(data, &data->fb1, mode->hdisplay, mode->vdisplay);
> +
> +	/*
> +	 * We always set the primary plane to actually enable the pipe as
> +	 * there's no way (that works) to light up a pipe with only a sprite
> +	 * plane enabled at the moment.
> +	 */
> +	if (!plane->is_primary) {
> +		igt_plane_t *primary;
> +
> +		primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
> +		igt_plane_set_fb(primary, &data->fb1);
> +	}
> +
> +	igt_plane_set_fb(plane, &data->fb1);
> +	if (s == COMMIT_LEGACY) {
> +		int ret;
> +		ret = drmModeSetCrtc(data->drm_fd,
> +				output->config.crtc->crtc_id,
> +				data->fb_id1,
> +				plane->pan_x, plane->pan_y,
> +				&output->id,
> +				1,
> +				mode);
> +		igt_assert(ret == 0);
> +	} else {
> +		igt_display_commit2(display, s);
> +	}
> +}
> +
> +static void cleanup_crtc(data_t *data, igt_output_t *output, igt_plane_t *plane)
> +{
> +	igt_display_t *display = &data->display;
> +
> +	igt_pipe_crc_free(data->pipe_crc);
> +	data->pipe_crc = NULL;
> +
> +	if (data->fb_id1) {
> +		igt_remove_fb(data->drm_fd, &data->fb1);
> +		data->fb_id1 = 0;
> +	}
> +	if (data->fb_id2) {
> +		igt_remove_fb(data->drm_fd, &data->fb2);
> +		data->fb_id2 = 0;
> +	}
> +	if (data->fb_id3) {
> +		igt_remove_fb(data->drm_fd, &data->fb3);
> +		data->fb_id3 = 0;
> +	}
> +
> +	if (data->fb_id1_nv12) {
> +		igt_remove_fb(data->drm_fd, &data->fb1_nv12);
> +		data->fb_id1_nv12 = 0;
> +	}
> +
> +	if (data->fb_id2_nv12) {
> +		igt_remove_fb(data->drm_fd, &data->fb2_nv12);
> +		data->fb_id2_nv12 = 0;
> +	}
> +
> +	if (data->fb_id3_nv12) {
> +		igt_remove_fb(data->drm_fd, &data->fb3_nv12);
> +		data->fb_id3_nv12 = 0;
> +	}
> +
> +	if (!plane->is_primary) {
> +		igt_plane_t *primary;
> +
> +		primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
> +		igt_plane_set_fb(primary, NULL);
> +	}
> +
> +	igt_plane_set_fb(plane, NULL);
> +	igt_output_set_pipe(output, PIPE_ANY);
> +
> +	igt_display_commit2(display, COMMIT_UNIVERSAL);
> +}
> +
> +static void test_nv12_plane(data_t *d)
> +{
> +	igt_display_t *display = &d->display;
> +	igt_output_t *output;
> +	enum pipe pipe;
> +	int valid_tests = 0;
> +	int img_width;
> +	int img_height;
> +
> +	igt_require(d->display.has_universal_planes);
> +	igt_require(d->num_scalers);
> +
> +	for_each_connected_output(display, output) {
> +		drmModeModeInfo *mode;
> +		mode = igt_output_get_mode(output);
> +		pipe = output->config.pipe;
> +
> +		igt_output_set_pipe(output, pipe);
> +
> +		/* get planes */
> +		d->plane1 = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
> +		d->plane2 = igt_output_get_plane(output, IGT_PLANE_2);
> +		d->plane3 = igt_output_get_plane(output, IGT_PLANE_3);
> +
> +		/* set required rotation */
> +		igt_plane_set_rotation(d->plane1, d->rotation);
> +		igt_plane_set_rotation(d->plane2, d->rotation);
> +		igt_plane_set_rotation(d->plane3, d->rotation);
> +
> +		/* Set up display with plane 1 */
> +		prepare_crtc(d, output, pipe, d->plane1, mode, COMMIT_LEGACY);
> +
> +		/* allocate fb2, fb2_nv12, fb1_nv12 with image size */
> +		igt_get_image_size(IMG_FILE, &img_width, &img_height);
> +
> +		/* fb2 is in RGB format */
> +		d->fb_id2 = igt_create_fb(d->drm_fd,
> +				img_width, img_height,
> +				DRM_FORMAT_XRGB8888,
> +				d->tiled, /* tiled */
> +				&d->fb2);
> +		igt_assert(d->fb_id2);
> +
> +		/* fb1_nv12 is in NV12 format */
> +		d->fb_id1_nv12 = igt_create_fb(d->drm_fd,
> +				img_width, img_height,
> +				DRM_FORMAT_NV12,
> +				d->tiled, /* tiled */
> +				&d->fb1_nv12);
> +		igt_assert(d->fb_id1_nv12);
> +
> +		/* fb2_nv12 is in NV12 format */
> +		d->fb_id2_nv12 = igt_create_fb(d->drm_fd,
> +				img_width, img_height,
> +				DRM_FORMAT_NV12,
> +				d->tiled,
> +				&d->fb2_nv12);
> +		igt_assert(d->fb_id2_nv12);
> +
> +		/* fb3 is in RGB */
> +		d->fb_id3 = igt_create_fb(d->drm_fd,
> +				mode->hdisplay, mode->vdisplay,
> +				DRM_FORMAT_ARGB8888,
> +				d->tiled, /* tiled */
> +				&d->fb3);
> +		igt_assert(d->fb_id3);
> +
> +		if (d->crc) {
> +			/*
> +			 * CRC test:
> +			 * 1st CRC: plane 1: RGB FS, plane 2: RGB 19x10  --> CRC1
> +			 * 2nd CRC: plane 1: RGB FS, plane 2: NV12 19x10 --> CRC2
> +			 * make sure CRC1 == CRC2
> +			 *
> +			 * For CRCs to work, cannot use any image/data because
> +			 * chrome-upsampling can fail CRC comparison.
> +			 * Though it is a very basic, solid color is expected to work
> +			 */
> +			paint_solid_color(d, &d->fb2, d->fb2.width, d->fb2.height,
> +				SOLID_COLOR);
> +
> +			/* Setup to capture CRC1 when plane 2 is in RGB mode */
> +			igt_plane_set_fb(d->plane2, &d->fb2);
> +			igt_fb_set_position(&d->fb2, d->plane2, 0, 0);
> +			igt_fb_set_size(&d->fb2, d->plane2, d->fb2.width, d->fb2.height);
> +			igt_plane_set_position(d->plane2, 0, 0);
> +			igt_plane_set_size(d->plane2, d->fb2.width, d->fb2.height);
> +			igt_display_commit2(display, COMMIT_UNIVERSAL);
> +			igt_pipe_crc_collect_crc(d->pipe_crc, &d->crc1);
> +
> +			/* Setup to capture CRC2 when plane 2 is in NV12 mode */
> +			igt_fb_csc_xrgb_to_nv12(d->drm_fd, &d->fb2_nv12, &d->fb2);
> +			igt_plane_set_fb(d->plane2, &d->fb2_nv12);
> +			igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
> +			igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
> +				d->fb2_nv12.height);
> +			igt_plane_set_position(d->plane2, 0, 0);
> +			igt_plane_set_size(d->plane2, d->fb2_nv12.width,d->fb2_nv12.height);
> +			igt_display_commit2(display, COMMIT_UNIVERSAL);
> +			igt_pipe_crc_collect_crc(d->pipe_crc, &d->crc2);
> +
> +			igt_assert_crc_equal(&d->crc1, &d->crc2);
> +		}
> +
> +		/*
> +		 * Non-CRC tests:
> +		 * Mimicing some not exactly but closer to some real usage
> +		 */
> +
> +		/* set up data for fb2: both fb1_nv12, fb2_nv12 uses this */
> +		paint_image(d, &d->fb2, img_width, img_height);
> +
> +		/* set up data in fb1_nv12: fb2 RGB-> fb1_nv12 */
> +		igt_fb_csc_xrgb_to_nv12(d->drm_fd, &d->fb1_nv12, &d->fb2);
> +
> +		/* set up data in fb2_nv12: fb2 RGB-> fb2_nv12 */
> +		igt_fb_csc_xrgb_to_nv12(d->drm_fd, &d->fb2_nv12, &d->fb2);
> +
> +		/* set up data in fb3 */
> +		paint_pattern(d, &d->fb3, d->fb3.width, d->fb3.height);
> +
> +		/* Set up fb2_nv12->plane2 mapping. */
> +		igt_plane_set_fb(d->plane2, &d->fb2_nv12);
> +		/* 2nd plane nv12 windowed - no scaling */
> +		igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
> +		igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
> +			d->fb2_nv12.height);
> +		igt_plane_set_position(d->plane2, 0, 0);
> +		igt_plane_set_size(d->plane2, d->fb2_nv12.width, d->fb2_nv12.height);
> +		igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +		/* Change primary plane to nv12 full screen: scaling + NV12 */
> +		igt_plane_set_fb(d->plane1, &d->fb1_nv12);
> +		igt_fb_set_position(&d->fb1_nv12, d->plane1, 0, 0);
> +		igt_fb_set_size(&d->fb1_nv12, d->plane1, d->fb1_nv12.width,
> +			d->fb1_nv12.height);
> +		igt_plane_set_position(d->plane1, 0, 0);
> +		igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay);
> +		igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +		/* Set up fb3->plane3 mapping. */
> +		igt_plane_set_fb(d->plane3, &d->fb3);
> +
> +		/* 3rd plane full screen - no scaling. */
> +		igt_fb_set_position(&d->fb3, d->plane3, 0, 0);
> +		igt_fb_set_size(&d->fb3, d->plane3, d->fb3.width, d->fb3.height);
> +		igt_plane_set_position(d->plane3, 0, 0);
> +		igt_plane_set_size(d->plane3, d->fb3.width, d->fb3.height);
> +		igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +		/* 2nd plane nv12 up scaling */
> +		igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
> +		igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
> +			d->fb2_nv12.height);
> +		igt_plane_set_position(d->plane2, 100, 100);
> +		igt_plane_set_size(d->plane2, mode->hdisplay-200, mode->vdisplay-200);
> +		igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +		/* 2nd plane nv12 down scaling */
> +		igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
> +		igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
> +			d->fb2_nv12.height);
> +		igt_plane_set_position(d->plane2, 1024, 0);
> +		igt_plane_set_size(d->plane2, d->fb2_nv12.width * 2/3,
> +			d->fb2_nv12.height * 2/3);
> +		igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +		/* Back to single plane mode  - rgb & no scaling */
> +		igt_plane_set_fb(d->plane1, &d->fb1);
> +		igt_plane_set_fb(d->plane2, NULL);
> +		igt_plane_set_fb(d->plane3, NULL);
> +		igt_fb_set_position(&d->fb1, d->plane1, 0, 0);
> +		igt_fb_set_size(&d->fb1, d->plane1, mode->hdisplay, mode->vdisplay);
> +		igt_plane_set_position(d->plane1, 0, 0);
> +		igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay);
> +		igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +		/* single plane mode  - rgb & scaling */
> +		igt_plane_set_fb(d->plane1, &d->fb1);
> +		igt_fb_set_position(&d->fb1, d->plane1, 0, 0);
> +		igt_fb_set_size(&d->fb1, d->plane1, d->fb1.width/2, d->fb1.height/2);
> +		igt_plane_set_position(d->plane1, 0, 0);
> +		igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay);
> +		igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +		/* single plane mode  - nv12 & scaling */
> +		igt_plane_set_fb(d->plane1, &d->fb1_nv12);
> +		igt_fb_set_position(&d->fb1_nv12, d->plane1, 0, 0);
> +		igt_fb_set_size(&d->fb1_nv12, d->plane1, d->fb1_nv12.width,
> +			d->fb1_nv12.height);
> +		igt_plane_set_position(d->plane1, 0, 0);
> +		igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay);
> +		igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +		valid_tests++;
> +
> +		cleanup_crtc(d, output, d->plane1);
> +	}
> +	igt_require_f(valid_tests, "no valid crtc/connector combinations found\n");
> +}
> +
> +static void test_nv12_unsupported_plane(data_t *d)
> +{
> +	igt_display_t *display = &d->display;
> +	igt_output_t *output;
> +	enum pipe pipe;
> +	int valid_tests = 0;
> +
> +	igt_require(d->display.has_universal_planes);
> +	igt_require(d->num_scalers);
> +
> +	for_each_connected_output(display, output) {
> +		drmModeModeInfo *mode;
> +		mode = igt_output_get_mode(output);
> +		pipe = output->config.pipe;
> +
> +		igt_output_set_pipe(output, pipe);
> +
> +		/* Set up display with plane 1 */
> +		d->plane1 = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
> +		prepare_crtc(d, output, pipe, d->plane1, mode, COMMIT_LEGACY);
> +
> +		d->fb_id3_nv12 = igt_create_fb(d->drm_fd,
> +				1920, 1080,
> +				DRM_FORMAT_NV12,
> +				d->tiled,
> +				&d->fb3_nv12);
> +		igt_assert(d->fb_id3_nv12);
> +
> +		/* Set up fb3_nv12->plane3 mapping. */
> +		d->plane2 = igt_output_get_plane(output, IGT_PLANE_3);
> +		igt_plane_set_fb(d->plane3, &d->fb3_nv12);
> +
> +		/* 3rd plane nv12 windowed - no scaling */
> +		igt_fb_set_position(&d->fb3_nv12, d->plane3, 0, 0);
> +		igt_fb_set_size(&d->fb3_nv12, d->plane3, d->fb3_nv12.width,
> +			d->fb3_nv12.height);
> +		igt_plane_set_position(d->plane3, 0, 0);
> +		igt_plane_set_size(d->plane3, d->fb3_nv12.width, d->fb3_nv12.height);
> +
> +		/* Should fail because NV12 is not supported on plane 3 */
> +		igt_assert(igt_display_try_commit2(display, COMMIT_UNIVERSAL)
> +			== -EINVAL);
> +
> +		valid_tests++;
> +
> +		igt_plane_set_fb(d->plane3, NULL);
> +		cleanup_crtc(d, output, d->plane1);
> +	}
> +	igt_require_f(valid_tests, "no valid crtc/connector combinations found\n");
> +}
> +
> +igt_main
> +{
> +	data_t data = {};
> +
> +	igt_skip_on_simulation();
> +
> +	igt_fixture {
> +		data.drm_fd = drm_open_any();
> +
> +		kmstest_set_vt_graphics_mode();
> +
> +		igt_require_pipe_crc();
> +
> +		igt_display_init(&data.display, data.drm_fd);
> +	}
> +	devid = intel_get_drm_devid(data.drm_fd);
> +
> +	data.num_scalers = intel_gen(devid) >= 9 ? 2 : 0;
> +
> +	data.crc = 1;
> +	data.rotation = IGT_ROTATION_0;
> +	igt_subtest_f("nv12-plane-linear") {
> +		data.tiled = LOCAL_DRM_FORMAT_MOD_NONE;
> +		test_nv12_plane(&data);
> +	}
> +	igt_subtest_f("nv12-plane-tile-x") {
> +		data.tiled = LOCAL_I915_FORMAT_MOD_X_TILED;
> +		test_nv12_plane(&data);
> +	}
> +	igt_subtest_f("nv12-plane-tile-y") {
> +		data.tiled = LOCAL_I915_FORMAT_MOD_Y_TILED;
> +		test_nv12_plane(&data);
> +	}
> +	igt_subtest_f("nv12-plane-tile-yf") {
> +		data.tiled = LOCAL_I915_FORMAT_MOD_Yf_TILED;
> +		test_nv12_plane(&data);
> +	}
> +
> +	data.rotation = IGT_ROTATION_180;
> +	igt_subtest_f("nv12-plane-linear-rot-180") {
> +		data.tiled = LOCAL_DRM_FORMAT_MOD_NONE;
> +		test_nv12_plane(&data);
> +	}
> +	igt_subtest_f("nv12-plane-tile-x-rot-180") {
> +		data.tiled = LOCAL_I915_FORMAT_MOD_X_TILED;
> +		test_nv12_plane(&data);
> +	}
> +	igt_subtest_f("nv12-plane-tile-y-rot-180") {
> +		data.tiled = LOCAL_I915_FORMAT_MOD_Y_TILED;
> +		test_nv12_plane(&data);
> +	}
> +	igt_subtest_f("nv12-plane-tile-yf-rot-180") {
> +		data.tiled = LOCAL_I915_FORMAT_MOD_Yf_TILED;
> +		test_nv12_plane(&data);
> +	}
> +
> +	igt_subtest_f("nv12-on-unsupported-plane") {
> +		data.tiled = LOCAL_DRM_FORMAT_MOD_NONE;
> +		test_nv12_unsupported_plane(&data);
> +	}
> +
> +	igt_fixture {
> +		igt_display_fini(&data.display);
> +	}
> +}
> -- 
> 1.9.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH] i-g-t: Adding display NV12 testcase
  2015-05-02  3:11 ` [PATCH 2/2] i-g-t: Adding display " Chandra Konduru
  2015-05-07  6:48   ` Daniel Vetter
@ 2015-05-09  4:32   ` Chandra Konduru
  2015-05-11 12:12     ` Tvrtko Ursulin
  2015-05-12 15:55     ` Thomas Wood
  1 sibling, 2 replies; 8+ messages in thread
From: Chandra Konduru @ 2015-05-09  4:32 UTC (permalink / raw)
  To: intel-gfx; +Cc: daniel.vetter

From: chandra konduru <chandra.konduru@intel.com>

This patch adds kms_nv12 test case. It covers testing NV12 in
all supported linear/tile-X/tile-Y/tile-Yf tile formats in
0 and 180 orientations. For each tiling format, it tests
various combinations of planes and scaling.

v2:
-Added 90/270 tests (me)
-took out crc test as it isn't adding much value due to chroma upsampling (me)

Signed-off-by: chandra konduru <chandra.konduru@intel.com>
---
 tests/.gitignore       |   1 +
 tests/Android.mk       |   1 +
 tests/Makefile.sources |   1 +
 tests/kms_nv12.c       | 619 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 622 insertions(+)
 create mode 100644 tests/kms_nv12.c

diff --git a/tests/.gitignore b/tests/.gitignore
index 86795c0..b03647a 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -149,6 +149,7 @@ kms_vblank
 kms_crtc_background_color
 kms_plane_scaling
 kms_panel_fitting
+kms_nv12
 pm_lpsp
 pm_rc6_residency
 pm_rpm
diff --git a/tests/Android.mk b/tests/Android.mk
index fac9931..c0c6383 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -81,6 +81,7 @@ else
     kms_pwrite_crc \
     kms_pipe_b_c_ivb \
     kms_legacy_colorkey
+	kms_nv12 \
     IGT_LOCAL_CFLAGS += -DANDROID_HAS_CAIRO=0
 endif
 
diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index 12f27f9..32c1b25 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -79,6 +79,7 @@ TESTS_progs_M = \
 	kms_crtc_background_color \
 	kms_plane_scaling \
 	kms_panel_fitting \
+	kms_nv12 \
 	pm_lpsp \
 	pm_rpm \
 	pm_rps \
diff --git a/tests/kms_nv12.c b/tests/kms_nv12.c
new file mode 100644
index 0000000..616cf6e
--- /dev/null
+++ b/tests/kms_nv12.c
@@ -0,0 +1,619 @@
+/*
+ * Copyright © 2013,2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include <math.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include "drmtest.h"
+#include "igt_debugfs.h"
+#include "igt_kms.h"
+#include "igt_core.h"
+#include "intel_chipset.h"
+#include "ioctl_wrappers.h"
+
+IGT_TEST_DESCRIPTION("Test display NV12 support");
+
+uint32_t devid;
+typedef struct {
+	int drm_fd;
+	igt_display_t display;
+	int num_scalers;
+
+	struct igt_fb fb1;
+	struct igt_fb fb1_nv12;
+	struct igt_fb fb2;
+	struct igt_fb fb2_nv12;
+	struct igt_fb fb3;
+	struct igt_fb fb3_nv12;
+	int fb_id1;
+	int fb_id1_nv12;
+	int fb_id2;
+	int fb_id2_nv12;
+	int fb_id3;
+	int fb_id3_nv12;
+
+	igt_plane_t *plane1;
+	igt_plane_t *plane2;
+	igt_plane_t *plane3;
+
+	uint64_t tiled;
+	int rotation;
+} data_t;
+
+typedef struct {
+	int width;
+	int height;
+} res_t;
+
+#define IMG_FILE  "1080p-left.png"
+
+static void
+paint_pattern(data_t *d, struct igt_fb *fb, uint16_t w, uint16_t h)
+{
+	cairo_t *cr;
+
+	cr = igt_get_cairo_ctx(d->drm_fd, fb);
+	igt_paint_test_pattern(cr, w, h);
+	cairo_destroy(cr);
+}
+
+static void
+paint_image(data_t *d, struct igt_fb *fb, uint16_t w, uint16_t h)
+{
+	cairo_t *cr;
+
+	cr = igt_get_cairo_ctx(d->drm_fd, fb);
+	igt_paint_image(cr, IMG_FILE, 0, 0, w, h);
+	cairo_destroy(cr);
+}
+
+static void prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe,
+			igt_plane_t *plane, drmModeModeInfo *mode, enum igt_commit_style s)
+{
+	igt_display_t *display = &data->display;
+
+	igt_output_set_pipe(output, pipe);
+
+	/* before allocating, free if any older fb */
+	if (data->fb_id1) {
+		igt_remove_fb(data->drm_fd, &data->fb1);
+		data->fb_id1 = 0;
+	}
+
+	/* allocate fb for plane 1 */
+	data->fb_id1 = igt_create_fb(data->drm_fd,
+			mode->hdisplay, mode->vdisplay,
+			DRM_FORMAT_XRGB8888,
+			data->tiled, /* tiled */
+			&data->fb1);
+	igt_assert(data->fb_id1);
+
+	paint_pattern(data, &data->fb1, mode->hdisplay, mode->vdisplay);
+
+	/*
+	 * We always set the primary plane to actually enable the pipe as
+	 * there's no way (that works) to light up a pipe with only a sprite
+	 * plane enabled at the moment.
+	 */
+	if (!plane->is_primary) {
+		igt_plane_t *primary;
+
+		primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
+		igt_plane_set_fb(primary, &data->fb1);
+	}
+
+	igt_plane_set_fb(plane, &data->fb1);
+	if (s == COMMIT_LEGACY) {
+		int ret;
+		ret = drmModeSetCrtc(data->drm_fd,
+				output->config.crtc->crtc_id,
+				data->fb_id1,
+				plane->pan_x, plane->pan_y,
+				&output->id,
+				1,
+				mode);
+		igt_assert(ret == 0);
+	} else {
+		igt_display_commit2(display, s);
+	}
+}
+
+static void cleanup_crtc(data_t *data, igt_output_t *output, igt_plane_t *plane)
+{
+	igt_display_t *display = &data->display;
+
+	if (data->fb_id1) {
+		igt_remove_fb(data->drm_fd, &data->fb1);
+		data->fb_id1 = 0;
+	}
+	if (data->fb_id2) {
+		igt_remove_fb(data->drm_fd, &data->fb2);
+		data->fb_id2 = 0;
+	}
+	if (data->fb_id3) {
+		igt_remove_fb(data->drm_fd, &data->fb3);
+		data->fb_id3 = 0;
+	}
+
+	if (data->fb_id1_nv12) {
+		igt_remove_fb(data->drm_fd, &data->fb1_nv12);
+		data->fb_id1_nv12 = 0;
+	}
+
+	if (data->fb_id2_nv12) {
+		igt_remove_fb(data->drm_fd, &data->fb2_nv12);
+		data->fb_id2_nv12 = 0;
+	}
+
+	if (data->fb_id3_nv12) {
+		igt_remove_fb(data->drm_fd, &data->fb3_nv12);
+		data->fb_id3_nv12 = 0;
+	}
+
+	if (!plane->is_primary) {
+		igt_plane_t *primary;
+
+		primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
+		igt_plane_set_fb(primary, NULL);
+	}
+
+	igt_plane_set_fb(plane, NULL);
+	igt_output_set_pipe(output, PIPE_ANY);
+
+	igt_display_commit2(display, COMMIT_UNIVERSAL);
+}
+
+static void test_nv12_plane(data_t *d)
+{
+	igt_display_t *display = &d->display;
+	igt_output_t *output;
+	enum pipe pipe;
+	int valid_tests = 0;
+	int img_width;
+	int img_height;
+
+	igt_require(d->display.has_universal_planes);
+	igt_require(d->num_scalers);
+
+	for_each_connected_output(display, output) {
+		drmModeModeInfo *mode;
+		mode = igt_output_get_mode(output);
+		pipe = output->config.pipe;
+
+		igt_output_set_pipe(output, pipe);
+
+		/* get planes */
+		d->plane1 = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
+		d->plane2 = igt_output_get_plane(output, IGT_PLANE_2);
+		d->plane3 = igt_output_get_plane(output, IGT_PLANE_3);
+
+		/* set required rotation */
+		igt_plane_set_rotation(d->plane1, d->rotation);
+		igt_plane_set_rotation(d->plane2, d->rotation);
+		igt_plane_set_rotation(d->plane3, d->rotation);
+
+		/* Set up display with plane 1 */
+		prepare_crtc(d, output, pipe, d->plane1, mode, COMMIT_LEGACY);
+
+		/* allocate fb2, fb2_nv12, fb1_nv12 with image size */
+		igt_get_image_size(IMG_FILE, &img_width, &img_height);
+
+		/* fb2 is in RGB format */
+		d->fb_id2 = igt_create_fb(d->drm_fd,
+				img_width, img_height,
+				DRM_FORMAT_XRGB8888,
+				d->tiled, /* tiled */
+				&d->fb2);
+		igt_assert(d->fb_id2);
+
+		/* fb1_nv12 is in NV12 format */
+		d->fb_id1_nv12 = igt_create_fb(d->drm_fd,
+				img_width, img_height,
+				DRM_FORMAT_NV12,
+				d->tiled, /* tiled */
+				&d->fb1_nv12);
+		igt_assert(d->fb_id1_nv12);
+
+		/* fb2_nv12 is in NV12 format */
+		d->fb_id2_nv12 = igt_create_fb(d->drm_fd,
+				img_width, img_height,
+				DRM_FORMAT_NV12,
+				d->tiled,
+				&d->fb2_nv12);
+		igt_assert(d->fb_id2_nv12);
+
+		/* fb3 is in RGB */
+		d->fb_id3 = igt_create_fb(d->drm_fd,
+				mode->hdisplay, mode->vdisplay,
+				DRM_FORMAT_ARGB8888,
+				d->tiled, /* tiled */
+				&d->fb3);
+		igt_assert(d->fb_id3);
+
+		/*
+		 * Mimicing some not exactly but closer to some real usage
+		 */
+
+		/* set up data for fb2: both fb1_nv12, fb2_nv12 uses this */
+		paint_image(d, &d->fb2, img_width, img_height);
+
+		/* set up data in fb1_nv12: fb2 RGB-> fb1_nv12 */
+		igt_fb_csc_xrgb_to_nv12(d->drm_fd, &d->fb1_nv12, &d->fb2);
+
+		/* set up data in fb2_nv12: fb2 RGB-> fb2_nv12 */
+		igt_fb_csc_xrgb_to_nv12(d->drm_fd, &d->fb2_nv12, &d->fb2);
+
+		/* set up data in fb3 */
+		paint_pattern(d, &d->fb3, d->fb3.width, d->fb3.height);
+
+		/* Set up fb2_nv12->plane2 mapping. */
+		igt_plane_set_fb(d->plane2, &d->fb2_nv12);
+		/* 2nd plane nv12 windowed - no scaling */
+		igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
+		igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
+			d->fb2_nv12.height);
+		igt_plane_set_position(d->plane2, 0, 0);
+		igt_plane_set_size(d->plane2, d->fb2_nv12.width, d->fb2_nv12.height);
+		igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+		/* Change primary plane to nv12 full screen: scaling + NV12 */
+		igt_plane_set_fb(d->plane1, &d->fb1_nv12);
+		igt_fb_set_position(&d->fb1_nv12, d->plane1, 0, 0);
+		igt_fb_set_size(&d->fb1_nv12, d->plane1, d->fb1_nv12.width,
+			d->fb1_nv12.height);
+		igt_plane_set_position(d->plane1, 0, 0);
+		igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay);
+		igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+		/* Set up fb3->plane3 mapping. */
+		igt_plane_set_fb(d->plane3, &d->fb3);
+
+		/* 3rd plane full screen - no scaling. */
+		igt_fb_set_position(&d->fb3, d->plane3, 0, 0);
+		igt_fb_set_size(&d->fb3, d->plane3, d->fb3.width, d->fb3.height);
+		igt_plane_set_position(d->plane3, 0, 0);
+		igt_plane_set_size(d->plane3, d->fb3.width, d->fb3.height);
+		igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+		/* 2nd plane nv12 up scaling */
+		igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
+		igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
+			d->fb2_nv12.height);
+		igt_plane_set_position(d->plane2, 100, 100);
+		igt_plane_set_size(d->plane2, mode->hdisplay-200, mode->vdisplay-200);
+		igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+		/* 2nd plane nv12 down scaling */
+		igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
+		igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
+			d->fb2_nv12.height);
+		igt_plane_set_position(d->plane2, 1024, 0);
+		igt_plane_set_size(d->plane2, d->fb2_nv12.width * 2/3,
+			d->fb2_nv12.height * 2/3);
+		igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+		/* Back to single plane mode  - rgb & no scaling */
+		igt_plane_set_fb(d->plane1, &d->fb1);
+		igt_plane_set_fb(d->plane2, NULL);
+		igt_plane_set_fb(d->plane3, NULL);
+		igt_fb_set_position(&d->fb1, d->plane1, 0, 0);
+		igt_fb_set_size(&d->fb1, d->plane1, mode->hdisplay, mode->vdisplay);
+		igt_plane_set_position(d->plane1, 0, 0);
+		igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay);
+		igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+		/* single plane mode  - rgb & scaling */
+		igt_plane_set_fb(d->plane1, &d->fb1);
+		igt_fb_set_position(&d->fb1, d->plane1, 0, 0);
+		igt_fb_set_size(&d->fb1, d->plane1, d->fb1.width/2, d->fb1.height/2);
+		igt_plane_set_position(d->plane1, 0, 0);
+		igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay);
+		igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+		/* single plane mode  - nv12 & scaling */
+		igt_plane_set_fb(d->plane1, &d->fb1_nv12);
+		igt_fb_set_position(&d->fb1_nv12, d->plane1, 0, 0);
+		igt_fb_set_size(&d->fb1_nv12, d->plane1, d->fb1_nv12.width,
+			d->fb1_nv12.height);
+		igt_plane_set_position(d->plane1, 0, 0);
+		igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay);
+		igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+		valid_tests++;
+
+		cleanup_crtc(d, output, d->plane1);
+	}
+	igt_require_f(valid_tests, "no valid crtc/connector combinations found\n");
+}
+
+static void test_nv12_plane_rotation_90_or_270(data_t *d)
+{
+	igt_display_t *display = &d->display;
+	igt_output_t *output;
+	enum pipe pipe;
+	int valid_tests = 0;
+	int i;
+
+	/*
+	 * There are two key scenarios:
+	 * 1) Flip landscape buffer onto portrait display
+	 * 2) Flip portrait buffer onto landscape display
+	 *
+	 * Due to availability of landscape display, going with #2.
+	 */
+	res_t nv12_res_list[] = {
+		{480, 720},
+		{720, 1280},
+		{1080, 1920},
+	};
+
+	igt_require(d->display.has_universal_planes);
+	igt_require(d->num_scalers);
+
+	for_each_connected_output(display, output) {
+		drmModeModeInfo *mode;
+		mode = igt_output_get_mode(output);
+		pipe = output->config.pipe;
+
+		igt_output_set_pipe(output, pipe);
+
+		/* get planes */
+		d->plane1 = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
+		d->plane2 = igt_output_get_plane(output, IGT_PLANE_2);
+
+		for (i = 0; i < sizeof(nv12_res_list)/sizeof(res_t); i++) {
+			/* Set up display with plane 1 */
+			igt_plane_set_rotation(d->plane1, IGT_ROTATION_0);
+			prepare_crtc(d, output, pipe, d->plane1, mode, COMMIT_LEGACY);
+
+			/* fb2 is in RGB format */
+			d->fb_id2 = igt_create_fb(d->drm_fd,
+					nv12_res_list[i].width, nv12_res_list[i].height,
+					DRM_FORMAT_XRGB8888,
+					d->tiled,
+					&d->fb2);
+			igt_assert(d->fb_id2);
+
+			/* fb1_nv12 is in NV12 format */
+			d->fb_id1_nv12 = igt_create_fb(d->drm_fd,
+					nv12_res_list[i].width, nv12_res_list[i].height,
+					DRM_FORMAT_NV12,
+					d->tiled,
+					&d->fb1_nv12);
+			igt_assert(d->fb_id1_nv12);
+
+			/* fb2_nv12 is in NV12 format */
+			d->fb_id2_nv12 = igt_create_fb(d->drm_fd,
+					nv12_res_list[i].width, nv12_res_list[i].height,
+					DRM_FORMAT_NV12,
+					d->tiled,
+					&d->fb2_nv12);
+			igt_assert(d->fb_id2_nv12);
+
+			/* set up data in fb1_nv12: fb2 PATTERN RGB-> fb1_nv12 */
+			paint_pattern(d, &d->fb2, d->fb2.width, d->fb2.height);
+			igt_fb_csc_xrgb_to_nv12(d->drm_fd, &d->fb1_nv12, &d->fb2);
+
+			/* set up data in fb2_nv12: fb2 PATTERN RGB-> fb2_nv12 */
+			paint_pattern(d, &d->fb2, d->fb2.width, d->fb2.height);
+			igt_fb_csc_xrgb_to_nv12(d->drm_fd, &d->fb2_nv12, &d->fb2);
+
+			/* set required rotation */
+			igt_plane_set_rotation(d->plane1, d->rotation);
+			igt_plane_set_rotation(d->plane2, d->rotation);
+
+			/* Change primary plane to nv12 full screen: scaling + NV12 */
+			igt_plane_set_fb(d->plane1, &d->fb1_nv12);
+			igt_fb_set_position(&d->fb1_nv12, d->plane1, 0, 0);
+			igt_fb_set_size(&d->fb1_nv12, d->plane1, d->fb1_nv12.width,
+				d->fb1_nv12.height);
+			igt_plane_set_position(d->plane1, 0, 0);
+			igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay);
+			igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+			/* 2nd plane nv12 windowed */
+			igt_plane_set_fb(d->plane2, &d->fb2_nv12);
+			igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
+			igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
+				d->fb2_nv12.height);
+			igt_plane_set_position(d->plane2, 0, 0);
+			igt_plane_set_size(d->plane2, d->fb2_nv12.height,d->fb2_nv12.width);
+			igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+			/* 2nd plane nv12 up scaling */
+			igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
+			igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
+				d->fb2_nv12.height);
+			igt_plane_set_position(d->plane2, 100, 100);
+			igt_plane_set_size(d->plane2, mode->hdisplay-200, mode->vdisplay-200);
+			igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+			/* 2nd plane nv12 down scaling */
+			igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
+			igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
+				d->fb2_nv12.height);
+			igt_plane_set_position(d->plane2, 100, 100);
+			igt_plane_set_size(d->plane2, d->fb2_nv12.height * 2/3,
+				d->fb2_nv12.width * 2/3);
+			igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+			/* 2nd plane nv12 down scaling - pan into FB */
+			igt_fb_set_position(&d->fb2_nv12, d->plane2, 100, 100);
+			igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width-100,
+				d->fb2_nv12.height-100);
+			igt_plane_set_position(d->plane2, 100, 100);
+			igt_plane_set_size(d->plane2, (d->fb2_nv12.height-100) * 2/3,
+				(d->fb2_nv12.width-100) * 2/3);
+			igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+			igt_remove_fb(d->drm_fd, &d->fb2);
+			igt_remove_fb(d->drm_fd, &d->fb2_nv12);
+			igt_remove_fb(d->drm_fd, &d->fb1_nv12);
+			d->fb_id2 = 0;
+			d->fb_id2_nv12 = 0;
+			d->fb_id1_nv12 = 0;
+		}
+
+		valid_tests++;
+
+		cleanup_crtc(d, output, d->plane1);
+	}
+	igt_require_f(valid_tests, "no valid crtc/connector combinations found\n");
+}
+
+static void test_nv12_unsupported_plane(data_t *d)
+{
+	igt_display_t *display = &d->display;
+	igt_output_t *output;
+	enum pipe pipe;
+	int valid_tests = 0;
+
+	igt_require(d->display.has_universal_planes);
+	igt_require(d->num_scalers);
+
+	for_each_connected_output(display, output) {
+		drmModeModeInfo *mode;
+		mode = igt_output_get_mode(output);
+		pipe = output->config.pipe;
+
+		igt_output_set_pipe(output, pipe);
+
+		/* Set up display with plane 1 */
+		d->plane1 = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
+		prepare_crtc(d, output, pipe, d->plane1, mode, COMMIT_LEGACY);
+
+		d->fb_id3_nv12 = igt_create_fb(d->drm_fd,
+				1920, 1080,
+				DRM_FORMAT_NV12,
+				d->tiled,
+				&d->fb3_nv12);
+		igt_assert(d->fb_id3_nv12);
+
+		/* Set up fb3_nv12->plane3 mapping. */
+		d->plane2 = igt_output_get_plane(output, IGT_PLANE_3);
+		igt_plane_set_fb(d->plane3, &d->fb3_nv12);
+
+		/* 3rd plane nv12 windowed - no scaling */
+		igt_fb_set_position(&d->fb3_nv12, d->plane3, 0, 0);
+		igt_fb_set_size(&d->fb3_nv12, d->plane3, d->fb3_nv12.width,
+			d->fb3_nv12.height);
+		igt_plane_set_position(d->plane3, 0, 0);
+		igt_plane_set_size(d->plane3, d->fb3_nv12.width, d->fb3_nv12.height);
+
+		/* Should fail because NV12 is not supported on plane 3 */
+		igt_assert(igt_display_try_commit2(display, COMMIT_UNIVERSAL)
+			== -EINVAL);
+
+		valid_tests++;
+
+		igt_plane_set_fb(d->plane3, NULL);
+		cleanup_crtc(d, output, d->plane1);
+	}
+	igt_require_f(valid_tests, "no valid crtc/connector combinations found\n");
+}
+
+igt_main
+{
+	data_t data = {};
+	igt_skip_on_simulation();
+
+	igt_fixture {
+		data.drm_fd = drm_open_any();
+
+		kmstest_set_vt_graphics_mode();
+
+		igt_display_init(&data.display, data.drm_fd);
+	}
+	devid = intel_get_drm_devid(data.drm_fd);
+
+	data.num_scalers = intel_gen(devid) >= 9 ? 2 : 0;
+
+	igt_assert(intel_gen(devid) >= 9);
+
+	data.rotation = IGT_ROTATION_0;
+	igt_subtest_f("nv12-plane-linear") {
+		data.tiled = LOCAL_DRM_FORMAT_MOD_NONE;
+		test_nv12_plane(&data);
+	}
+	igt_subtest_f("nv12-plane-tile-x") {
+		data.tiled = LOCAL_I915_FORMAT_MOD_X_TILED;
+		test_nv12_plane(&data);
+	}
+	igt_subtest_f("nv12-plane-tile-y") {
+		data.tiled = LOCAL_I915_FORMAT_MOD_Y_TILED;
+		test_nv12_plane(&data);
+	}
+	igt_subtest_f("nv12-plane-tile-yf") {
+		data.tiled = LOCAL_I915_FORMAT_MOD_Yf_TILED;
+		test_nv12_plane(&data);
+	}
+
+	data.rotation = IGT_ROTATION_180;
+	igt_subtest_f("nv12-plane-linear-rot-180") {
+		data.tiled = LOCAL_DRM_FORMAT_MOD_NONE;
+		test_nv12_plane(&data);
+	}
+	igt_subtest_f("nv12-plane-tile-x-rot-180") {
+		data.tiled = LOCAL_I915_FORMAT_MOD_X_TILED;
+		test_nv12_plane(&data);
+	}
+	igt_subtest_f("nv12-plane-tile-y-rot-180") {
+		data.tiled = LOCAL_I915_FORMAT_MOD_Y_TILED;
+		test_nv12_plane(&data);
+	}
+	igt_subtest_f("nv12-plane-tile-yf-rot-180") {
+		data.tiled = LOCAL_I915_FORMAT_MOD_Yf_TILED;
+		test_nv12_plane(&data);
+	}
+
+	data.rotation = IGT_ROTATION_90;
+	igt_subtest_f("nv12-plane-tile-y-rot-90") {
+		data.tiled = LOCAL_I915_FORMAT_MOD_Y_TILED;
+		test_nv12_plane_rotation_90_or_270(&data);
+	}
+	igt_subtest_f("nv12-plane-tile-yf-rot-90") {
+		data.tiled = LOCAL_I915_FORMAT_MOD_Yf_TILED;
+		test_nv12_plane_rotation_90_or_270(&data);
+	}
+
+	data.rotation = IGT_ROTATION_270;
+	igt_subtest_f("nv12-plane-tile-y-rot-270") {
+		data.tiled = LOCAL_I915_FORMAT_MOD_Y_TILED;
+		test_nv12_plane_rotation_90_or_270(&data);
+	}
+	igt_subtest_f("nv12-plane-tile-yf-rot-270") {
+		data.tiled = LOCAL_I915_FORMAT_MOD_Yf_TILED;
+		test_nv12_plane_rotation_90_or_270(&data);
+	}
+
+	igt_subtest_f("nv12-on-unsupported-plane") {
+		data.tiled = LOCAL_DRM_FORMAT_MOD_NONE;
+		test_nv12_unsupported_plane(&data);
+	}
+
+	igt_fixture {
+		igt_display_fini(&data.display);
+	}
+}
-- 
1.9.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH] i-g-t: Adding display NV12 testcase
  2015-05-09  4:32   ` [PATCH] " Chandra Konduru
@ 2015-05-11 12:12     ` Tvrtko Ursulin
  2015-05-12 15:55     ` Thomas Wood
  1 sibling, 0 replies; 8+ messages in thread
From: Tvrtko Ursulin @ 2015-05-11 12:12 UTC (permalink / raw)
  To: Chandra Konduru, intel-gfx; +Cc: daniel.vetter


Hi,

On 05/09/2015 05:32 AM, Chandra Konduru wrote:
> From: chandra konduru <chandra.konduru@intel.com>
>
> This patch adds kms_nv12 test case. It covers testing NV12 in
> all supported linear/tile-X/tile-Y/tile-Yf tile formats in
> 0 and 180 orientations. For each tiling format, it tests
> various combinations of planes and scaling.
>
> v2:
> -Added 90/270 tests (me)
> -took out crc test as it isn't adding much value due to chroma upsampling (me)
>
> Signed-off-by: chandra konduru <chandra.konduru@intel.com>
> ---
>   tests/.gitignore       |   1 +
>   tests/Android.mk       |   1 +
>   tests/Makefile.sources |   1 +
>   tests/kms_nv12.c       | 619 +++++++++++++++++++++++++++++++++++++++++++++++++
>   4 files changed, 622 insertions(+)
>   create mode 100644 tests/kms_nv12.c

[snip]

> +igt_main
> +{
> +	data_t data = {};
> +	igt_skip_on_simulation();
> +
> +	igt_fixture {
> +		data.drm_fd = drm_open_any();
> +
> +		kmstest_set_vt_graphics_mode();
> +
> +		igt_display_init(&data.display, data.drm_fd);
> +	}
> +	devid = intel_get_drm_devid(data.drm_fd);
> +
> +	data.num_scalers = intel_gen(devid) >= 9 ? 2 : 0;
> +
> +	igt_assert(intel_gen(devid) >= 9);

Not reviewing as such, but notice --list-subtest is broken unless you 
move the above three lines into the fixture.

After that I ran:

> +	data.rotation = IGT_ROTATION_90;
> +	igt_subtest_f("nv12-plane-tile-y-rot-90") {
> +		data.tiled = LOCAL_I915_FORMAT_MOD_Y_TILED;
> +		test_nv12_plane_rotation_90_or_270(&data);
> +	}
> +	igt_subtest_f("nv12-plane-tile-yf-rot-90") {
> +		data.tiled = LOCAL_I915_FORMAT_MOD_Yf_TILED;
> +		test_nv12_plane_rotation_90_or_270(&data);
> +	}

And both succeeded! :)

Your + mine patch series rebased on top of today's nightly.

Regards,

Tvrtko
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] i-g-t: Prep work for adding NV12 testcase
  2015-05-02  3:11 ` [PATCH 1/2] i-g-t: Prep work for adding NV12 testcase Chandra Konduru
@ 2015-05-12 15:47   ` Thomas Wood
  0 siblings, 0 replies; 8+ messages in thread
From: Thomas Wood @ 2015-05-12 15:47 UTC (permalink / raw)
  To: Chandra Konduru; +Cc: Intel Graphics Development

On 2 May 2015 at 04:11, Chandra Konduru <chandra.konduru@intel.com> wrote:
> From: chandra konduru <chandra.konduru@intel.com>
>
> This patch adds necessary prep work for nv12 testcase:
>   - updated fb allocation functions to handle NV12 format
>   - igt helper function to return png image size
>   - igt helper function to calculate start of uv in a given NV12 buffer
>   - igt helper function to map buffer for host access
>   - populates fb->...[4] parameters for NV12
>   - igt helper function to convert RGB data to NV12
>   - updated drm_format to bpp to handle NV12
>   - updated fast copy blit function to deal NV12 subplanes
>   - made an update to kms_render testcase due to above changes

Could you split these changes into seperate patches? The
igt_get_image_size function would be especially useful separately as
you have suggest that it should be used to fix kms_plane_scaling image
loading issue.


>
> Signed-off-by: chandra konduru <chandra.konduru@intel.com>
> ---
>  lib/igt_fb.c            | 316 +++++++++++++++++++++++++++++++++++++++++++++---
>  lib/igt_fb.h            |   9 +-
>  lib/intel_batchbuffer.c |  16 ++-
>  lib/intel_batchbuffer.h |   3 +-
>  lib/intel_reg.h         |   1 +
>  lib/ioctl_wrappers.c    |  10 +-
>  lib/ioctl_wrappers.h    |   2 +-
>  tests/kms_render.c      |   4 +-
>  8 files changed, 334 insertions(+), 27 deletions(-)
>
> diff --git a/lib/igt_fb.c b/lib/igt_fb.c
> index cc4b8ee..dedee9e 100644
> --- a/lib/igt_fb.c
> +++ b/lib/igt_fb.c
> @@ -74,7 +74,7 @@ static struct format_desc_struct {
>
>
>  /* helpers to create nice-looking framebuffers */
> -static int create_bo_for_fb(int fd, int width, int height, int bpp,
> +static int create_bo_for_fb(int fd, int width, int height, int bpp, int bpp2,
>                             uint64_t tiling, unsigned bo_size,
>                             uint32_t *gem_handle_ret,
>                             unsigned *size_ret,
> @@ -99,13 +99,17 @@ static int create_bo_for_fb(int fd, int width, int height, int bpp,
>                 for (stride = 512; stride < v; stride *= 2)
>                         ;
>
> -               v = stride * height;
> +               /* planar formats height is 1.5x */
> +               v = stride * (bpp2 ? (height * 3) / 2 : height);
> +
>                 for (size = 1024*1024; size < v; size *= 2)
>                         ;
>         } else {
>                 /* Scan-out has a 64 byte alignment restriction */
>                 stride = (width * (bpp / 8) + 63) & ~63;
> -               size = stride * height;
> +
> +               /* planar formats height is 1.5x */
> +               size = stride * (bpp2 ? (height * 3) / 2 : height);
>         }
>
>         if (bo_size == 0)
> @@ -393,6 +397,75 @@ void igt_paint_image(cairo_t *cr, const char *filename,
>  }
>
>  /**
> + * igt_get_image_size:
> + * @filename: filename of the png image
> + * @width: width of the image
> + * @height: height of the image
> + *
> + * This function returns @width and @height of the png image in @filename,
> + * which is loaded from the package data directory.
> + */
> +void
> +igt_get_image_size(const char *filename, int *width, int *height)
> +{
> +       cairo_surface_t *image;
> +       FILE* f;
> +
> +       f = igt_fopen_data(filename);
> +
> +       image = cairo_image_surface_create_from_png_stream(&stdio_read_func, f);
> +       igt_assert(cairo_surface_status(image) == CAIRO_STATUS_SUCCESS);
> +
> +       *width = cairo_image_surface_get_width(image);
> +       *height = cairo_image_surface_get_height(image);
> +
> +       cairo_surface_destroy(image);
> +
> +       fclose(f);
> +}
> +
> +
> +/**
> + * igt_fb_calc_uv:
> + * @fb: pointer to an #igt_fb structure
> + *
> + * This function calculates UV offset in bytes and UV starting line number
> + * for requested NV12 @fb.
> + */
> +void
> +igt_fb_calc_uv(struct igt_fb *fb)
> +{
> +       if (fb->drm_format != DRM_FORMAT_NV12)
> +               return;
> +
> +       switch (fb->tiling) {
> +       case LOCAL_DRM_FORMAT_MOD_NONE:
> +               fb->uv_y_start = fb->height;
> +               break;
> +       case LOCAL_I915_FORMAT_MOD_X_TILED:
> +               fb->uv_y_start = fb->height;
> +               break;
> +       case LOCAL_I915_FORMAT_MOD_Y_TILED:
> +               fb->uv_y_start = fb->height;
> +               break;
> +       case LOCAL_I915_FORMAT_MOD_Yf_TILED:
> +               /* tile-Yf requires uv to start on a new tile row */
> +               if (fb->height % 64)
> +                       fb->uv_y_start = (fb->height + 63) & ~63;
> +               else
> +                       fb->uv_y_start = fb->height;
> +               break;
> +       default:
> +               igt_assert(0);
> +       }
> +
> +       fb->uv_offset = fb->uv_y_start * fb->stride;
> +
> +       /* assert that fb has enough lines to hold y and uv sub-planes */
> +       igt_assert(fb->size / fb->stride >= fb->uv_y_start + fb->height / 2);
> +}
> +
> +/**
>   * igt_create_fb_with_bo_size:
>   * @fd: open i915 drm file descriptor
>   * @width: width of the framebuffer in pixel
> @@ -418,24 +491,32 @@ igt_create_fb_with_bo_size(int fd, int width, int height,
>                            struct igt_fb *fb, unsigned bo_size)
>  {
>         uint32_t fb_id;
> -       int bpp;
> +       int bpp, bpp2;
>
>         memset(fb, 0, sizeof(*fb));
>
> -       bpp = igt_drm_format_to_bpp(format);
> +       bpp = igt_drm_format_to_bpp(format, 0);
> +       bpp2 = igt_drm_format_to_bpp(format, 1);
>
> -       igt_debug("%s(width=%d, height=%d, format=0x%x [bpp=%d], tiling=0x%"PRIx64", size=%d\n",
> -                 __func__, width, height, format, bpp, tiling, bo_size);
> -       do_or_die(create_bo_for_fb(fd, width, height, bpp, tiling, bo_size,
> +       igt_debug("%s(width=%d, height=%d, format=0x%x [bpp=%d, %d], tiling=0x%"PRIx64", size=%d\n",
> +                 __func__, width, height, format, bpp, bpp2, tiling, bo_size);
> +       do_or_die(create_bo_for_fb(fd, width, height, bpp, bpp2, tiling, bo_size,
>                                    &fb->gem_handle, &fb->size, &fb->stride));
>
>         igt_debug("%s(handle=%d, pitch=%d)\n",
>                   __func__, fb->gem_handle, fb->stride);
>
> +       fb->width = width;
> +       fb->height = height;
> +       fb->tiling = tiling;
> +       fb->drm_format = format;
> +
> +       igt_fb_calc_uv(fb);
> +
>         if (tiling != LOCAL_DRM_FORMAT_MOD_NONE &&
>             tiling != LOCAL_I915_FORMAT_MOD_X_TILED) {
>                 do_or_die(__kms_addfb(fd, fb->gem_handle, width, height,
> -                                     fb->stride, format, tiling,
> +                                     fb->stride, format, tiling, fb->uv_offset,
>                                       LOCAL_DRM_MODE_FB_MODIFIERS, &fb_id));
>         } else {
>                 uint32_t handles[4];
> @@ -449,21 +530,213 @@ igt_create_fb_with_bo_size(int fd, int width, int height,
>                 handles[0] = fb->gem_handle;
>                 pitches[0] = fb->stride;
>
> +               if (format == DRM_FORMAT_NV12) {
> +                       handles[1] = fb->gem_handle;
> +                       pitches[1] = fb->stride;
> +                       offsets[1] = fb->uv_offset;
> +               }
> +
>                 do_or_die(drmModeAddFB2(fd, width, height, format,
>                                         handles, pitches, offsets,
>                                         &fb_id, 0));
>         }
>
> -       fb->width = width;
> -       fb->height = height;
> -       fb->tiling = tiling;
> -       fb->drm_format = format;
>         fb->fb_id = fb_id;
>
>         return fb_id;
>  }
>
>  /**
> + * igt_fb_gem_mmap:
> + * @fd: open i915 drm file descriptor
> + * @fb: pointer to an #igt_fb structure
> + *
> + * This function memory maps gem buffer for cpu access and saves mmap pointer
> + * in @fb.
> + */
> +void
> +igt_fb_gem_mmap(int fd, struct igt_fb *fb)
> +{
> +       if (!fb->mmap_gtt)
> +               fb->mmap_gtt = gem_mmap__gtt(fd, fb->gem_handle, fb->size,
> +                       PROT_READ | PROT_WRITE);
> +       igt_assert(fb->mmap_gtt);
> +}
> +
> +/**
> + * igt_fb_csc_xrgb_to_nv12:
> + * @fd: open i915 drm file descriptor
> + * @width: width of the framebuffer to be converted
> + * @height: height of the framebuffer to be converted
> + * @dst: pointer to an #igt_fb structure holding destination framebuffer
> + * @src: pointer to an #igt_fb structure holding source framebuffer
> + *
> + * This function converts source framebuffer into destination framebuffer
> + * format. It also mmaps the underlying gem buffer if it isn't mmaped
> + * before.
> + *
> + * For now:
> + *    - it expects both src and dst fbs are same size and tiling
> + */
> +void
> +igt_fb_csc_xrgb_to_nv12(int fd, struct igt_fb *dst_fb, struct igt_fb *src_fb)
> +{
> +       unsigned char *nv12;
> +       unsigned char *xrgb;
> +       unsigned char y, v, u;
> +       float yf, vf, uf;
> +       unsigned char r, g, b;
> +       int i, j;
> +       int xrgb_pos;
> +       int y_pos;
> +       int uv_pos;
> +       int uv_base;
> +       unsigned int obj_tiling;
> +       struct igt_fb *temp_src_fb, *temp_dst_fb;
> +       struct igt_fb fb1, fb2;
> +       int temp_src_id, temp_dst_id;
> +
> +       igt_assert(dst_fb);
> +       igt_assert(src_fb);
> +       igt_assert(dst_fb->width == src_fb->width);
> +       igt_assert(dst_fb->height == src_fb->height);
> +       igt_assert(src_fb->tiling == dst_fb->tiling);
> +
> +       igt_assert(src_fb->drm_format == DRM_FORMAT_XRGB8888);
> +       igt_assert(dst_fb->drm_format == DRM_FORMAT_NV12);
> +
> +       /*
> +        * Steps: Not the best approach but gets job done for igt
> +        *     (1) create linear temp_src, temp_dst
> +        *     (2) fast blit src --> temp src
> +        *     (3) gem map temp_src, temp_dst
> +        *     (4) host conversion & copy from temp src --> temp dst
> +        *     (5) fast blit temp dst --> dst
> +        *     (6) free temp fbs
> +        *
> +        * For Linear/X:
> +        *     perform 3 & 4 only
> +        * For Y/Yf:
> +        *     perform all steps
> +        */
> +
> +       if (src_fb->tiling == LOCAL_I915_FORMAT_MOD_Y_TILED ||
> +               src_fb->tiling == LOCAL_I915_FORMAT_MOD_Yf_TILED) {
> +
> +               temp_src_fb = &fb1;
> +               temp_dst_fb = &fb2;
> +
> +               /* (1) create linear temp_src, temp_dst */
> +               temp_src_id = igt_create_fb(fd,
> +                       src_fb->width, src_fb->height,
> +                       src_fb->drm_format,
> +                       LOCAL_DRM_FORMAT_MOD_NONE,
> +                       temp_src_fb);
> +               igt_assert(temp_src_id);
> +
> +               temp_dst_id = igt_create_fb(fd,
> +                       dst_fb->width, dst_fb->height,
> +                       dst_fb->drm_format,
> +                       LOCAL_DRM_FORMAT_MOD_NONE,
> +                       temp_dst_fb);
> +               igt_assert(temp_dst_id);
> +
> +               if (src_fb->tiling == LOCAL_I915_FORMAT_MOD_Y_TILED)
> +                       obj_tiling = I915_TILING_Y;
> +               else
> +                       obj_tiling = I915_TILING_Yf;
> +
> +               /* (2) fast blit src --> temp src */
> +               igt_blitter_fast_copy__raw(fd,
> +                       src_fb->gem_handle,
> +                       src_fb->stride,
> +                       obj_tiling,
> +                       0, 0,
> +                       temp_src_fb->width, temp_src_fb->height,
> +                       igt_drm_format_to_bpp(temp_src_fb->drm_format, 0),
> +                       temp_src_fb->gem_handle,
> +                       temp_src_fb->stride,
> +                       I915_TILING_NONE,
> +                       0, 0);
> +       } else {
> +               temp_src_fb = src_fb;
> +               temp_dst_fb = dst_fb;
> +       }
> +
> +       /* (3) gem map temp_src, temp_dst */
> +       igt_fb_gem_mmap(fd, temp_src_fb);
> +       igt_fb_gem_mmap(fd, temp_dst_fb);
> +
> +       /* (4) host conversion & copy from temp src --> temp dst */
> +       xrgb = (unsigned char *) temp_src_fb->mmap_gtt;
> +       nv12 = (unsigned char *) temp_dst_fb->mmap_gtt;
> +       uv_base = temp_dst_fb->stride * temp_dst_fb->height;
> +
> +       for (i = 0; i < temp_src_fb->height; i++) {
> +               xrgb_pos = i * temp_src_fb->stride;
> +               y_pos = i * temp_dst_fb->stride;
> +               uv_pos = temp_dst_fb->stride * i / 2;
> +               for (j = 0; j < temp_src_fb->width; j++) {
> +                       b = xrgb[xrgb_pos++];
> +                       g = xrgb[xrgb_pos++];
> +                       r = xrgb[xrgb_pos++];
> +                       xrgb_pos++;
> +
> +                       /* use floats for intermediate calcs, to get better results */
> +                       yf =  (0.257 * r) + (0.504 * g) + (0.098 * b) + 16;
> +                       uf = -(0.148 * r) - (0.291 * g) + (0.439 * b) + 128;
> +                       vf =  (0.439 * r) - (0.368 * g) - (0.071 * b) + 128;
> +
> +                       y = (unsigned char) yf;
> +                       u = (unsigned char) uf;
> +                       v = (unsigned char) vf;
> +
> +                       nv12[y_pos++] = y;
> +
> +                       if (!(j % 2) && !(i % 2)) {
> +                               nv12[uv_base + uv_pos++] = u;
> +                               nv12[uv_base + uv_pos++] = v;
> +                       }
> +               }
> +       }
> +
> +       /* (5) fast blit temp dst --> dst */
> +       if (dst_fb->tiling == LOCAL_I915_FORMAT_MOD_Y_TILED ||
> +               dst_fb->tiling == LOCAL_I915_FORMAT_MOD_Yf_TILED) {
> +
> +               /* blit y-plane */
> +               igt_blitter_fast_copy__raw(fd,
> +                       temp_dst_fb->gem_handle,
> +                       temp_dst_fb->stride,
> +                       I915_TILING_NONE,
> +                       0, 0,
> +                       dst_fb->width, dst_fb->height,
> +                       igt_drm_format_to_bpp(dst_fb->drm_format, 0),
> +                       dst_fb->gem_handle,
> +                       dst_fb->stride,
> +                       obj_tiling,
> +                       0, 0);
> +
> +               /* blit uv-plane */
> +               igt_blitter_fast_copy__raw(fd,
> +                       temp_dst_fb->gem_handle,
> +                       temp_dst_fb->stride,
> +                       I915_TILING_NONE,
> +                       0, temp_dst_fb->uv_y_start,
> +                       dst_fb->width, dst_fb->height,
> +                       igt_drm_format_to_bpp(dst_fb->drm_format, 1),
> +                       dst_fb->gem_handle,
> +                       dst_fb->stride,
> +                       obj_tiling,
> +                       0, dst_fb->uv_y_start);
> +
> +               /* (6) free temp fbs */
> +               igt_remove_fb(fd, temp_src_fb);
> +               igt_remove_fb(fd, temp_dst_fb);
> +       }
> +}
> +
> +/**
>   * igt_create_fb:
>   * @fd: open i915 drm file descriptor
>   * @width: width of the framebuffer in pixel
> @@ -686,6 +959,7 @@ static void destroy_cairo_surface__blit(void *arg)
>                                    I915_TILING_NONE,
>                                    0, 0, /* src_x, src_y */
>                                    fb->width, fb->height,
> +                                  0,
>                                    fb->gem_handle,
>                                    fb->stride,
>                                    obj_tiling,
> @@ -712,8 +986,8 @@ static void create_cairo_surface__blit(int fd, struct igt_fb *fb)
>          * cairo). This linear bo will be then blitted to its final
>          * destination, tiling it at the same time.
>          */
> -       bpp = igt_drm_format_to_bpp(fb->drm_format);
> -       ret = create_bo_for_fb(fd, fb->width, fb->height, bpp,
> +       bpp = igt_drm_format_to_bpp(fb->drm_format, 0);
> +       ret = create_bo_for_fb(fd, fb->width, fb->height, bpp, 0,
>                                 LOCAL_DRM_FORMAT_MOD_NONE, 0,
>                                 &blit->linear.handle,
>                                 &blit->linear.size,
> @@ -734,6 +1008,7 @@ static void create_cairo_surface__blit(int fd, struct igt_fb *fb)
>                                    obj_tiling,
>                                    0, 0, /* src_x, src_y */
>                                    fb->width, fb->height,
> +                                  bpp,
>                                    blit->linear.handle,
>                                    blit->linear.stride,
>                                    I915_TILING_NONE,
> @@ -893,15 +1168,24 @@ uint32_t igt_bpp_depth_to_drm_format(int bpp, int depth)
>  /**
>   * igt_drm_format_to_bpp:
>   * @drm_format: drm fourcc pixel format code
> + * @plane: plane id
>   *
>   * Returns:
>   * The bits per pixel for the given drm fourcc pixel format code. Fails hard if
>   * no match was found.
>   */
> -uint32_t igt_drm_format_to_bpp(uint32_t drm_format)
> +uint32_t igt_drm_format_to_bpp(uint32_t drm_format, int plane)
>  {
>         struct format_desc_struct *f;
>
> +       if (drm_format == DRM_FORMAT_NV12 && plane == 0)
> +               return 8;
> +       if (drm_format == DRM_FORMAT_NV12 && plane == 1)
> +               return 16;
> +
> +       if (plane)
> +               return 0;
> +
>         for_each_format(f)
>                 if (f->drm_id == drm_format)
>                         return f->bpp;
> diff --git a/lib/igt_fb.h b/lib/igt_fb.h
> index a07acd2..9e227e8 100644
> --- a/lib/igt_fb.h
> +++ b/lib/igt_fb.h
> @@ -54,10 +54,13 @@ struct igt_fb {
>         uint64_t tiling;
>         unsigned size;
>         cairo_surface_t *cairo_surface;
> +       void *mmap_gtt;
>         uint32_t src_x;
>         uint32_t src_y;
>         uint32_t src_w;
>         uint32_t src_h;
> +       uint32_t uv_y_start;
> +       uint32_t uv_offset;
>  };
>
>  enum igt_text_align {
> @@ -82,6 +85,9 @@ unsigned int igt_create_color_fb(int fd, int width, int height,
>  unsigned int igt_create_stereo_fb(int drm_fd, drmModeModeInfo *mode,
>                                   uint32_t format, uint64_t tiling);
>  void igt_remove_fb(int fd, struct igt_fb *fb);
> +void igt_fb_gem_mmap(int fd, struct igt_fb *fb);
> +void igt_fb_csc_xrgb_to_nv12(int fd, struct igt_fb *dst, struct igt_fb *src);
> +void igt_fb_calc_uv(struct igt_fb *fb);
>
>  /* cairo-based painting */
>  cairo_t *igt_get_cairo_ctx(int fd, struct igt_fb *fb);
> @@ -98,10 +104,11 @@ void igt_write_fb_to_png(int fd, struct igt_fb *fb, const char *filename);
>  int igt_cairo_printf_line(cairo_t *cr, enum igt_text_align align,
>                                double yspacing, const char *fmt, ...)
>                                __attribute__((format (printf, 4, 5)));
> +void igt_get_image_size(const char *filename, int *width, int *height);
>
>  /* helpers to handle drm fourcc codes */
>  uint32_t igt_bpp_depth_to_drm_format(int bpp, int depth);
> -uint32_t igt_drm_format_to_bpp(uint32_t drm_format);
> +uint32_t igt_drm_format_to_bpp(uint32_t drm_format, int plane);
>  const char *igt_format_str(uint32_t drm_format);
>  void igt_get_all_formats(const uint32_t **formats, int *format_count);
>
> diff --git a/lib/intel_batchbuffer.c b/lib/intel_batchbuffer.c
> index 8b68e52..a2cd6ab 100644
> --- a/lib/intel_batchbuffer.c
> +++ b/lib/intel_batchbuffer.c
> @@ -518,7 +518,7 @@ static uint32_t fast_copy_dword0(unsigned int src_tiling,
>  }
>
>  static uint32_t fast_copy_dword1(unsigned int src_tiling,
> -                                unsigned int dst_tiling)
> +                                unsigned int dst_tiling, uint32_t color_depth)
>  {
>         uint32_t dword1 = 0;
>
> @@ -527,7 +527,10 @@ static uint32_t fast_copy_dword1(unsigned int src_tiling,
>         if (dst_tiling == I915_TILING_Yf)
>                 dword1 |= XY_FAST_COPY_DST_TILING_Yf;
>
> -       dword1 |= XY_FAST_COPY_COLOR_DEPTH_32;
> +       if (color_depth == 8)
> +               dword1 |= XY_FAST_COPY_COLOR_DEPTH_8;
> +       else
> +               dword1 |= XY_FAST_COPY_COLOR_DEPTH_32;
>
>         return dword1;
>  }
> @@ -585,6 +588,7 @@ static void exec_blit(int fd,
>   * @src_y: Y coordinate of the source region to copy
>   * @width: Width of the region to copy
>   * @height: Height of the region to copy
> + * @color_depth: Color depth of the buffer
>   * @dst_handle: GEM handle of the source buffer
>   * @dst_stride: Stride (in bytes) of the destination buffer
>   * @dst_tiling: Tiling mode of the destination buffer
> @@ -602,6 +606,7 @@ void igt_blitter_fast_copy__raw(int fd,
>
>                                 /* size */
>                                 unsigned int width, unsigned int height,
> +                               uint32_t color_depth,
>
>                                 /* dst */
>                                 uint32_t dst_handle,
> @@ -620,7 +625,7 @@ void igt_blitter_fast_copy__raw(int fd,
>         src_pitch = fast_copy_pitch(src_stride, src_tiling);
>         dst_pitch = fast_copy_pitch(dst_stride, dst_tiling);
>         dword0 = fast_copy_dword0(src_tiling, dst_tiling);
> -       dword1 = fast_copy_dword1(src_tiling, dst_tiling);
> +       dword1 = fast_copy_dword1(src_tiling, dst_tiling, color_depth);
>
>  #define CHECK_RANGE(x) ((x) >= 0 && (x) < (1 << 15))
>         assert(CHECK_RANGE(src_x) && CHECK_RANGE(src_y) &&
> @@ -670,6 +675,7 @@ void igt_blitter_fast_copy__raw(int fd,
>   * @src_y: source pixel y-coordination
>   * @width: width of the copied rectangle
>   * @height: height of the copied rectangle
> + * @color_depth: Color depth of the buffer
>   * @dst: destination i-g-t buffer object
>   * @dst_x: destination pixel x-coordination
>   * @dst_y: destination pixel y-coordination
> @@ -680,7 +686,7 @@ void igt_blitter_fast_copy__raw(int fd,
>   */
>  void igt_blitter_fast_copy(struct intel_batchbuffer *batch,
>                            struct igt_buf *src, unsigned src_x, unsigned src_y,
> -                          unsigned width, unsigned height,
> +                          unsigned width, unsigned height, uint32_t color_depth,
>                            struct igt_buf *dst, unsigned dst_x, unsigned dst_y)
>  {
>         uint32_t src_pitch, dst_pitch;
> @@ -689,7 +695,7 @@ void igt_blitter_fast_copy(struct intel_batchbuffer *batch,
>         src_pitch = fast_copy_pitch(src->stride, src->tiling);
>         dst_pitch = fast_copy_pitch(dst->stride, src->tiling);
>         dword0 = fast_copy_dword0(src->tiling, dst->tiling);
> -       dword1 = fast_copy_dword1(src->tiling, dst->tiling);
> +       dword1 = fast_copy_dword1(src->tiling, dst->tiling, color_depth);
>
>  #define CHECK_RANGE(x) ((x) >= 0 && (x) < (1 << 15))
>         assert(CHECK_RANGE(src_x) && CHECK_RANGE(src_y) &&
> diff --git a/lib/intel_batchbuffer.h b/lib/intel_batchbuffer.h
> index 62c8396..0e0feed 100644
> --- a/lib/intel_batchbuffer.h
> +++ b/lib/intel_batchbuffer.h
> @@ -226,7 +226,7 @@ unsigned igt_buf_height(struct igt_buf *buf);
>
>  void igt_blitter_fast_copy(struct intel_batchbuffer *batch,
>                           struct igt_buf *src, unsigned src_x, unsigned src_y,
> -                         unsigned width, unsigned height,
> +                         unsigned width, unsigned height, uint32_t color_depth,
>                           struct igt_buf *dst, unsigned dst_x, unsigned dst_y);
>
>  void igt_blitter_fast_copy__raw(int fd,
> @@ -238,6 +238,7 @@ void igt_blitter_fast_copy__raw(int fd,
>
>                                 /* size */
>                                 unsigned int width, unsigned int height,
> +                               uint32_t color_depth,
>
>                                 /* dst */
>                                 uint32_t dst_handle,
> diff --git a/lib/intel_reg.h b/lib/intel_reg.h
> index 0ffa803..9f3de7a 100644
> --- a/lib/intel_reg.h
> +++ b/lib/intel_reg.h
> @@ -2530,6 +2530,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
>  /* dword 1 */
>  #define   XY_FAST_COPY_SRC_TILING_Yf                   (1 <<  31)
>  #define   XY_FAST_COPY_DST_TILING_Yf                   (1 <<  30)
> +#define   XY_FAST_COPY_COLOR_DEPTH_8                   (0  << 24)
>  #define   XY_FAST_COPY_COLOR_DEPTH_32                  (3  << 24)
>
>  #define MI_STORE_DWORD_IMM             ((0x20<<23)|2)
> diff --git a/lib/ioctl_wrappers.c b/lib/ioctl_wrappers.c
> index a269d0f..93717a0 100644
> --- a/lib/ioctl_wrappers.c
> +++ b/lib/ioctl_wrappers.c
> @@ -54,6 +54,7 @@
>  #include "intel_chipset.h"
>  #include "intel_io.h"
>  #include "igt_debugfs.h"
> +#include "igt_fb.h"
>  #include "config.h"
>
>  #include "ioctl_wrappers.h"
> @@ -1221,7 +1222,7 @@ void igt_require_fb_modifiers(int fd)
>
>  int __kms_addfb(int fd, uint32_t handle, uint32_t width, uint32_t height,
>                 uint32_t stride, uint32_t pixel_format, uint64_t modifier,
> -               uint32_t flags, uint32_t *buf_id)
> +               uint32_t uv_offset, uint32_t flags, uint32_t *buf_id)
>  {
>         struct local_drm_mode_fb_cmd2 f;
>         int ret;
> @@ -1238,6 +1239,13 @@ int __kms_addfb(int fd, uint32_t handle, uint32_t width, uint32_t height,
>         f.pitches[0] = stride;
>         f.modifier[0] = modifier;
>
> +       if (pixel_format == DRM_FORMAT_NV12) {
> +               f.handles[1] = handle;
> +               f.pitches[1] = stride;
> +               f.offsets[1] = uv_offset;
> +               f.modifier[1] = modifier;
> +       }
> +
>         ret = drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f);
>
>         *buf_id = f.fb_id;
> diff --git a/lib/ioctl_wrappers.h b/lib/ioctl_wrappers.h
> index bc5d4bd..3d93a5e 100644
> --- a/lib/ioctl_wrappers.h
> +++ b/lib/ioctl_wrappers.h
> @@ -175,6 +175,6 @@ void igt_require_fb_modifiers(int fd);
>   */
>  int __kms_addfb(int fd, uint32_t handle, uint32_t width, uint32_t height,
>                 uint32_t stride, uint32_t pixel_format, uint64_t modifier,
> -               uint32_t flags, uint32_t *buf_id);
> +               uint32_t uv_offset, uint32_t flags, uint32_t *buf_id);
>
>  #endif /* IOCTL_WRAPPERS_H */
> diff --git a/tests/kms_render.c b/tests/kms_render.c
> index 1759eaa..4a7aaec 100644
> --- a/tests/kms_render.c
> +++ b/tests/kms_render.c
> @@ -78,8 +78,8 @@ static void gpu_blit(struct igt_fb *dst_fb, struct igt_fb *src_fb)
>
>         igt_assert(dst_fb->drm_format == src_fb->drm_format);
>         igt_assert(src_fb->drm_format == DRM_FORMAT_RGB565 ||
> -              igt_drm_format_to_bpp(src_fb->drm_format) != 16);
> -       bpp = igt_drm_format_to_bpp(src_fb->drm_format);
> +              igt_drm_format_to_bpp(src_fb->drm_format, 0) != 16);
> +       bpp = igt_drm_format_to_bpp(src_fb->drm_format, 0);
>         dst_bo = gem_handle_to_libdrm_bo(bufmgr, drm_fd, "destination",
>                                          dst_fb->gem_handle);
>         igt_assert(dst_bo);
> --
> 1.9.1
>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] i-g-t: Adding display NV12 testcase
  2015-05-09  4:32   ` [PATCH] " Chandra Konduru
  2015-05-11 12:12     ` Tvrtko Ursulin
@ 2015-05-12 15:55     ` Thomas Wood
  1 sibling, 0 replies; 8+ messages in thread
From: Thomas Wood @ 2015-05-12 15:55 UTC (permalink / raw)
  To: Chandra Konduru; +Cc: Daniel Vetter, Intel Graphics Development

On 9 May 2015 at 05:32, Chandra Konduru <chandra.konduru@intel.com> wrote:
> From: chandra konduru <chandra.konduru@intel.com>
>
> This patch adds kms_nv12 test case. It covers testing NV12 in
> all supported linear/tile-X/tile-Y/tile-Yf tile formats in
> 0 and 180 orientations. For each tiling format, it tests
> various combinations of planes and scaling.
>
> v2:
> -Added 90/270 tests (me)
> -took out crc test as it isn't adding much value due to chroma upsampling (me)
>
> Signed-off-by: chandra konduru <chandra.konduru@intel.com>
> ---
>  tests/.gitignore       |   1 +
>  tests/Android.mk       |   1 +
>  tests/Makefile.sources |   1 +
>  tests/kms_nv12.c       | 619 +++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 622 insertions(+)
>  create mode 100644 tests/kms_nv12.c
>
> diff --git a/tests/.gitignore b/tests/.gitignore
> index 86795c0..b03647a 100644
> --- a/tests/.gitignore
> +++ b/tests/.gitignore
> @@ -149,6 +149,7 @@ kms_vblank
>  kms_crtc_background_color
>  kms_plane_scaling
>  kms_panel_fitting
> +kms_nv12
>  pm_lpsp
>  pm_rc6_residency
>  pm_rpm
> diff --git a/tests/Android.mk b/tests/Android.mk
> index fac9931..c0c6383 100644
> --- a/tests/Android.mk
> +++ b/tests/Android.mk
> @@ -81,6 +81,7 @@ else
>      kms_pwrite_crc \
>      kms_pipe_b_c_ivb \
>      kms_legacy_colorkey
> +       kms_nv12 \
>      IGT_LOCAL_CFLAGS += -DANDROID_HAS_CAIRO=0
>  endif
>
> diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> index 12f27f9..32c1b25 100644
> --- a/tests/Makefile.sources
> +++ b/tests/Makefile.sources
> @@ -79,6 +79,7 @@ TESTS_progs_M = \
>         kms_crtc_background_color \
>         kms_plane_scaling \
>         kms_panel_fitting \
> +       kms_nv12 \
>         pm_lpsp \
>         pm_rpm \
>         pm_rps \
> diff --git a/tests/kms_nv12.c b/tests/kms_nv12.c
> new file mode 100644
> index 0000000..616cf6e
> --- /dev/null
> +++ b/tests/kms_nv12.c
> @@ -0,0 +1,619 @@
> +/*
> + * Copyright © 2013,2014 Intel Corporation

and 2015?

> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + *
> + */
> +
> +#include <math.h>
> +#include <fcntl.h>
> +#include <sys/stat.h>
> +
> +#include "drmtest.h"
> +#include "igt_debugfs.h"
> +#include "igt_kms.h"
> +#include "igt_core.h"
> +#include "intel_chipset.h"
> +#include "ioctl_wrappers.h"
> +
> +IGT_TEST_DESCRIPTION("Test display NV12 support");
> +
> +uint32_t devid;
> +typedef struct {
> +       int drm_fd;
> +       igt_display_t display;
> +       int num_scalers;
> +
> +       struct igt_fb fb1;
> +       struct igt_fb fb1_nv12;
> +       struct igt_fb fb2;
> +       struct igt_fb fb2_nv12;
> +       struct igt_fb fb3;
> +       struct igt_fb fb3_nv12;
> +       int fb_id1;
> +       int fb_id1_nv12;
> +       int fb_id2;
> +       int fb_id2_nv12;
> +       int fb_id3;
> +       int fb_id3_nv12;
> +
> +       igt_plane_t *plane1;
> +       igt_plane_t *plane2;
> +       igt_plane_t *plane3;
> +
> +       uint64_t tiled;
> +       int rotation;
> +} data_t;
> +
> +typedef struct {
> +       int width;
> +       int height;
> +} res_t;
> +
> +#define IMG_FILE  "1080p-left.png"
> +
> +static void
> +paint_pattern(data_t *d, struct igt_fb *fb, uint16_t w, uint16_t h)
> +{
> +       cairo_t *cr;
> +
> +       cr = igt_get_cairo_ctx(d->drm_fd, fb);
> +       igt_paint_test_pattern(cr, w, h);
> +       cairo_destroy(cr);
> +}
> +
> +static void
> +paint_image(data_t *d, struct igt_fb *fb, uint16_t w, uint16_t h)
> +{
> +       cairo_t *cr;
> +
> +       cr = igt_get_cairo_ctx(d->drm_fd, fb);
> +       igt_paint_image(cr, IMG_FILE, 0, 0, w, h);
> +       cairo_destroy(cr);
> +}
> +
> +static void prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe,
> +                       igt_plane_t *plane, drmModeModeInfo *mode, enum igt_commit_style s)
> +{
> +       igt_display_t *display = &data->display;
> +
> +       igt_output_set_pipe(output, pipe);
> +
> +       /* before allocating, free if any older fb */
> +       if (data->fb_id1) {
> +               igt_remove_fb(data->drm_fd, &data->fb1);
> +               data->fb_id1 = 0;
> +       }
> +
> +       /* allocate fb for plane 1 */
> +       data->fb_id1 = igt_create_fb(data->drm_fd,
> +                       mode->hdisplay, mode->vdisplay,
> +                       DRM_FORMAT_XRGB8888,
> +                       data->tiled, /* tiled */
> +                       &data->fb1);
> +       igt_assert(data->fb_id1);
> +
> +       paint_pattern(data, &data->fb1, mode->hdisplay, mode->vdisplay);
> +
> +       /*
> +        * We always set the primary plane to actually enable the pipe as
> +        * there's no way (that works) to light up a pipe with only a sprite
> +        * plane enabled at the moment.
> +        */
> +       if (!plane->is_primary) {
> +               igt_plane_t *primary;
> +
> +               primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
> +               igt_plane_set_fb(primary, &data->fb1);
> +       }
> +
> +       igt_plane_set_fb(plane, &data->fb1);
> +       if (s == COMMIT_LEGACY) {
> +               int ret;
> +               ret = drmModeSetCrtc(data->drm_fd,
> +                               output->config.crtc->crtc_id,
> +                               data->fb_id1,
> +                               plane->pan_x, plane->pan_y,
> +                               &output->id,
> +                               1,
> +                               mode);
> +               igt_assert(ret == 0);

This could be igt_assert_eq(ret, 0).


> +       } else {
> +               igt_display_commit2(display, s);
> +       }
> +}
> +
> +static void cleanup_crtc(data_t *data, igt_output_t *output, igt_plane_t *plane)
> +{
> +       igt_display_t *display = &data->display;
> +
> +       if (data->fb_id1) {
> +               igt_remove_fb(data->drm_fd, &data->fb1);
> +               data->fb_id1 = 0;
> +       }
> +       if (data->fb_id2) {
> +               igt_remove_fb(data->drm_fd, &data->fb2);
> +               data->fb_id2 = 0;
> +       }
> +       if (data->fb_id3) {
> +               igt_remove_fb(data->drm_fd, &data->fb3);
> +               data->fb_id3 = 0;
> +       }
> +
> +       if (data->fb_id1_nv12) {
> +               igt_remove_fb(data->drm_fd, &data->fb1_nv12);
> +               data->fb_id1_nv12 = 0;
> +       }
> +
> +       if (data->fb_id2_nv12) {
> +               igt_remove_fb(data->drm_fd, &data->fb2_nv12);
> +               data->fb_id2_nv12 = 0;
> +       }
> +
> +       if (data->fb_id3_nv12) {
> +               igt_remove_fb(data->drm_fd, &data->fb3_nv12);
> +               data->fb_id3_nv12 = 0;
> +       }
> +
> +       if (!plane->is_primary) {
> +               igt_plane_t *primary;
> +
> +               primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
> +               igt_plane_set_fb(primary, NULL);
> +       }
> +
> +       igt_plane_set_fb(plane, NULL);
> +       igt_output_set_pipe(output, PIPE_ANY);
> +
> +       igt_display_commit2(display, COMMIT_UNIVERSAL);
> +}
> +
> +static void test_nv12_plane(data_t *d)
> +{
> +       igt_display_t *display = &d->display;
> +       igt_output_t *output;
> +       enum pipe pipe;
> +       int valid_tests = 0;
> +       int img_width;
> +       int img_height;
> +
> +       igt_require(d->display.has_universal_planes);
> +       igt_require(d->num_scalers);
> +
> +       for_each_connected_output(display, output) {
> +               drmModeModeInfo *mode;
> +               mode = igt_output_get_mode(output);
> +               pipe = output->config.pipe;
> +
> +               igt_output_set_pipe(output, pipe);
> +
> +               /* get planes */
> +               d->plane1 = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
> +               d->plane2 = igt_output_get_plane(output, IGT_PLANE_2);
> +               d->plane3 = igt_output_get_plane(output, IGT_PLANE_3);
> +
> +               /* set required rotation */
> +               igt_plane_set_rotation(d->plane1, d->rotation);
> +               igt_plane_set_rotation(d->plane2, d->rotation);
> +               igt_plane_set_rotation(d->plane3, d->rotation);
> +
> +               /* Set up display with plane 1 */
> +               prepare_crtc(d, output, pipe, d->plane1, mode, COMMIT_LEGACY);
> +
> +               /* allocate fb2, fb2_nv12, fb1_nv12 with image size */
> +               igt_get_image_size(IMG_FILE, &img_width, &img_height);

This only needs to be done once, so it can be moved out of the for loop.

> +
> +               /* fb2 is in RGB format */
> +               d->fb_id2 = igt_create_fb(d->drm_fd,
> +                               img_width, img_height,
> +                               DRM_FORMAT_XRGB8888,
> +                               d->tiled, /* tiled */
> +                               &d->fb2);
> +               igt_assert(d->fb_id2);
> +
> +               /* fb1_nv12 is in NV12 format */
> +               d->fb_id1_nv12 = igt_create_fb(d->drm_fd,
> +                               img_width, img_height,
> +                               DRM_FORMAT_NV12,
> +                               d->tiled, /* tiled */
> +                               &d->fb1_nv12);
> +               igt_assert(d->fb_id1_nv12);
> +
> +               /* fb2_nv12 is in NV12 format */
> +               d->fb_id2_nv12 = igt_create_fb(d->drm_fd,
> +                               img_width, img_height,
> +                               DRM_FORMAT_NV12,
> +                               d->tiled,
> +                               &d->fb2_nv12);
> +               igt_assert(d->fb_id2_nv12);
> +
> +               /* fb3 is in RGB */
> +               d->fb_id3 = igt_create_fb(d->drm_fd,
> +                               mode->hdisplay, mode->vdisplay,
> +                               DRM_FORMAT_ARGB8888,
> +                               d->tiled, /* tiled */
> +                               &d->fb3);
> +               igt_assert(d->fb_id3);
> +
> +               /*
> +                * Mimicing some not exactly but closer to some real usage

Mimicking?

> +                */
> +
> +               /* set up data for fb2: both fb1_nv12, fb2_nv12 uses this */
> +               paint_image(d, &d->fb2, img_width, img_height);
> +
> +               /* set up data in fb1_nv12: fb2 RGB-> fb1_nv12 */
> +               igt_fb_csc_xrgb_to_nv12(d->drm_fd, &d->fb1_nv12, &d->fb2);
> +
> +               /* set up data in fb2_nv12: fb2 RGB-> fb2_nv12 */
> +               igt_fb_csc_xrgb_to_nv12(d->drm_fd, &d->fb2_nv12, &d->fb2);
> +
> +               /* set up data in fb3 */
> +               paint_pattern(d, &d->fb3, d->fb3.width, d->fb3.height);
> +
> +               /* Set up fb2_nv12->plane2 mapping. */
> +               igt_plane_set_fb(d->plane2, &d->fb2_nv12);
> +               /* 2nd plane nv12 windowed - no scaling */
> +               igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
> +               igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
> +                       d->fb2_nv12.height);
> +               igt_plane_set_position(d->plane2, 0, 0);
> +               igt_plane_set_size(d->plane2, d->fb2_nv12.width, d->fb2_nv12.height);
> +               igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +               /* Change primary plane to nv12 full screen: scaling + NV12 */
> +               igt_plane_set_fb(d->plane1, &d->fb1_nv12);
> +               igt_fb_set_position(&d->fb1_nv12, d->plane1, 0, 0);
> +               igt_fb_set_size(&d->fb1_nv12, d->plane1, d->fb1_nv12.width,
> +                       d->fb1_nv12.height);
> +               igt_plane_set_position(d->plane1, 0, 0);
> +               igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay);
> +               igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +               /* Set up fb3->plane3 mapping. */
> +               igt_plane_set_fb(d->plane3, &d->fb3);
> +
> +               /* 3rd plane full screen - no scaling. */
> +               igt_fb_set_position(&d->fb3, d->plane3, 0, 0);
> +               igt_fb_set_size(&d->fb3, d->plane3, d->fb3.width, d->fb3.height);
> +               igt_plane_set_position(d->plane3, 0, 0);
> +               igt_plane_set_size(d->plane3, d->fb3.width, d->fb3.height);
> +               igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +               /* 2nd plane nv12 up scaling */
> +               igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
> +               igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
> +                       d->fb2_nv12.height);
> +               igt_plane_set_position(d->plane2, 100, 100);
> +               igt_plane_set_size(d->plane2, mode->hdisplay-200, mode->vdisplay-200);
> +               igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +               /* 2nd plane nv12 down scaling */
> +               igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
> +               igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
> +                       d->fb2_nv12.height);
> +               igt_plane_set_position(d->plane2, 1024, 0);
> +               igt_plane_set_size(d->plane2, d->fb2_nv12.width * 2/3,
> +                       d->fb2_nv12.height * 2/3);
> +               igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +               /* Back to single plane mode  - rgb & no scaling */
> +               igt_plane_set_fb(d->plane1, &d->fb1);
> +               igt_plane_set_fb(d->plane2, NULL);
> +               igt_plane_set_fb(d->plane3, NULL);
> +               igt_fb_set_position(&d->fb1, d->plane1, 0, 0);
> +               igt_fb_set_size(&d->fb1, d->plane1, mode->hdisplay, mode->vdisplay);
> +               igt_plane_set_position(d->plane1, 0, 0);
> +               igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay);
> +               igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +               /* single plane mode  - rgb & scaling */
> +               igt_plane_set_fb(d->plane1, &d->fb1);
> +               igt_fb_set_position(&d->fb1, d->plane1, 0, 0);
> +               igt_fb_set_size(&d->fb1, d->plane1, d->fb1.width/2, d->fb1.height/2);
> +               igt_plane_set_position(d->plane1, 0, 0);
> +               igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay);
> +               igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +               /* single plane mode  - nv12 & scaling */
> +               igt_plane_set_fb(d->plane1, &d->fb1_nv12);
> +               igt_fb_set_position(&d->fb1_nv12, d->plane1, 0, 0);
> +               igt_fb_set_size(&d->fb1_nv12, d->plane1, d->fb1_nv12.width,
> +                       d->fb1_nv12.height);
> +               igt_plane_set_position(d->plane1, 0, 0);
> +               igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay);
> +               igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +               valid_tests++;
> +
> +               cleanup_crtc(d, output, d->plane1);
> +       }
> +       igt_require_f(valid_tests, "no valid crtc/connector combinations found\n");
> +}
> +
> +static void test_nv12_plane_rotation_90_or_270(data_t *d)
> +{
> +       igt_display_t *display = &d->display;
> +       igt_output_t *output;
> +       enum pipe pipe;
> +       int valid_tests = 0;
> +       int i;
> +
> +       /*
> +        * There are two key scenarios:
> +        * 1) Flip landscape buffer onto portrait display
> +        * 2) Flip portrait buffer onto landscape display
> +        *
> +        * Due to availability of landscape display, going with #2.
> +        */
> +       res_t nv12_res_list[] = {
> +               {480, 720},
> +               {720, 1280},
> +               {1080, 1920},
> +       };
> +
> +       igt_require(d->display.has_universal_planes);
> +       igt_require(d->num_scalers);
> +
> +       for_each_connected_output(display, output) {
> +               drmModeModeInfo *mode;
> +               mode = igt_output_get_mode(output);
> +               pipe = output->config.pipe;
> +
> +               igt_output_set_pipe(output, pipe);
> +
> +               /* get planes */
> +               d->plane1 = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
> +               d->plane2 = igt_output_get_plane(output, IGT_PLANE_2);
> +
> +               for (i = 0; i < sizeof(nv12_res_list)/sizeof(res_t); i++) {
> +                       /* Set up display with plane 1 */
> +                       igt_plane_set_rotation(d->plane1, IGT_ROTATION_0);
> +                       prepare_crtc(d, output, pipe, d->plane1, mode, COMMIT_LEGACY);
> +
> +                       /* fb2 is in RGB format */
> +                       d->fb_id2 = igt_create_fb(d->drm_fd,
> +                                       nv12_res_list[i].width, nv12_res_list[i].height,
> +                                       DRM_FORMAT_XRGB8888,
> +                                       d->tiled,
> +                                       &d->fb2);
> +                       igt_assert(d->fb_id2);
> +
> +                       /* fb1_nv12 is in NV12 format */
> +                       d->fb_id1_nv12 = igt_create_fb(d->drm_fd,
> +                                       nv12_res_list[i].width, nv12_res_list[i].height,
> +                                       DRM_FORMAT_NV12,
> +                                       d->tiled,
> +                                       &d->fb1_nv12);
> +                       igt_assert(d->fb_id1_nv12);
> +
> +                       /* fb2_nv12 is in NV12 format */
> +                       d->fb_id2_nv12 = igt_create_fb(d->drm_fd,
> +                                       nv12_res_list[i].width, nv12_res_list[i].height,
> +                                       DRM_FORMAT_NV12,
> +                                       d->tiled,
> +                                       &d->fb2_nv12);
> +                       igt_assert(d->fb_id2_nv12);
> +
> +                       /* set up data in fb1_nv12: fb2 PATTERN RGB-> fb1_nv12 */
> +                       paint_pattern(d, &d->fb2, d->fb2.width, d->fb2.height);
> +                       igt_fb_csc_xrgb_to_nv12(d->drm_fd, &d->fb1_nv12, &d->fb2);
> +
> +                       /* set up data in fb2_nv12: fb2 PATTERN RGB-> fb2_nv12 */
> +                       paint_pattern(d, &d->fb2, d->fb2.width, d->fb2.height);
> +                       igt_fb_csc_xrgb_to_nv12(d->drm_fd, &d->fb2_nv12, &d->fb2);
> +
> +                       /* set required rotation */
> +                       igt_plane_set_rotation(d->plane1, d->rotation);
> +                       igt_plane_set_rotation(d->plane2, d->rotation);
> +
> +                       /* Change primary plane to nv12 full screen: scaling + NV12 */
> +                       igt_plane_set_fb(d->plane1, &d->fb1_nv12);
> +                       igt_fb_set_position(&d->fb1_nv12, d->plane1, 0, 0);
> +                       igt_fb_set_size(&d->fb1_nv12, d->plane1, d->fb1_nv12.width,
> +                               d->fb1_nv12.height);
> +                       igt_plane_set_position(d->plane1, 0, 0);
> +                       igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay);
> +                       igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +                       /* 2nd plane nv12 windowed */
> +                       igt_plane_set_fb(d->plane2, &d->fb2_nv12);
> +                       igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
> +                       igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
> +                               d->fb2_nv12.height);
> +                       igt_plane_set_position(d->plane2, 0, 0);
> +                       igt_plane_set_size(d->plane2, d->fb2_nv12.height,d->fb2_nv12.width);
> +                       igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +                       /* 2nd plane nv12 up scaling */
> +                       igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
> +                       igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
> +                               d->fb2_nv12.height);
> +                       igt_plane_set_position(d->plane2, 100, 100);
> +                       igt_plane_set_size(d->plane2, mode->hdisplay-200, mode->vdisplay-200);
> +                       igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +                       /* 2nd plane nv12 down scaling */
> +                       igt_fb_set_position(&d->fb2_nv12, d->plane2, 0, 0);
> +                       igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width,
> +                               d->fb2_nv12.height);
> +                       igt_plane_set_position(d->plane2, 100, 100);
> +                       igt_plane_set_size(d->plane2, d->fb2_nv12.height * 2/3,
> +                               d->fb2_nv12.width * 2/3);
> +                       igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +                       /* 2nd plane nv12 down scaling - pan into FB */
> +                       igt_fb_set_position(&d->fb2_nv12, d->plane2, 100, 100);
> +                       igt_fb_set_size(&d->fb2_nv12, d->plane2, d->fb2_nv12.width-100,
> +                               d->fb2_nv12.height-100);
> +                       igt_plane_set_position(d->plane2, 100, 100);
> +                       igt_plane_set_size(d->plane2, (d->fb2_nv12.height-100) * 2/3,
> +                               (d->fb2_nv12.width-100) * 2/3);
> +                       igt_display_commit2(display, COMMIT_UNIVERSAL);
> +
> +                       igt_remove_fb(d->drm_fd, &d->fb2);
> +                       igt_remove_fb(d->drm_fd, &d->fb2_nv12);
> +                       igt_remove_fb(d->drm_fd, &d->fb1_nv12);
> +                       d->fb_id2 = 0;
> +                       d->fb_id2_nv12 = 0;
> +                       d->fb_id1_nv12 = 0;
> +               }
> +
> +               valid_tests++;
> +
> +               cleanup_crtc(d, output, d->plane1);
> +       }
> +       igt_require_f(valid_tests, "no valid crtc/connector combinations found\n");
> +}
> +
> +static void test_nv12_unsupported_plane(data_t *d)
> +{
> +       igt_display_t *display = &d->display;
> +       igt_output_t *output;
> +       enum pipe pipe;
> +       int valid_tests = 0;
> +
> +       igt_require(d->display.has_universal_planes);
> +       igt_require(d->num_scalers);
> +
> +       for_each_connected_output(display, output) {
> +               drmModeModeInfo *mode;
> +               mode = igt_output_get_mode(output);
> +               pipe = output->config.pipe;
> +
> +               igt_output_set_pipe(output, pipe);
> +
> +               /* Set up display with plane 1 */
> +               d->plane1 = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
> +               prepare_crtc(d, output, pipe, d->plane1, mode, COMMIT_LEGACY);
> +
> +               d->fb_id3_nv12 = igt_create_fb(d->drm_fd,
> +                               1920, 1080,
> +                               DRM_FORMAT_NV12,
> +                               d->tiled,
> +                               &d->fb3_nv12);
> +               igt_assert(d->fb_id3_nv12);
> +
> +               /* Set up fb3_nv12->plane3 mapping. */
> +               d->plane2 = igt_output_get_plane(output, IGT_PLANE_3);
> +               igt_plane_set_fb(d->plane3, &d->fb3_nv12);
> +
> +               /* 3rd plane nv12 windowed - no scaling */
> +               igt_fb_set_position(&d->fb3_nv12, d->plane3, 0, 0);
> +               igt_fb_set_size(&d->fb3_nv12, d->plane3, d->fb3_nv12.width,
> +                       d->fb3_nv12.height);
> +               igt_plane_set_position(d->plane3, 0, 0);
> +               igt_plane_set_size(d->plane3, d->fb3_nv12.width, d->fb3_nv12.height);
> +
> +               /* Should fail because NV12 is not supported on plane 3 */
> +               igt_assert(igt_display_try_commit2(display, COMMIT_UNIVERSAL)
> +                       == -EINVAL);

This could also use igt_assert_eq.


> +
> +               valid_tests++;
> +
> +               igt_plane_set_fb(d->plane3, NULL);
> +               cleanup_crtc(d, output, d->plane1);
> +       }
> +       igt_require_f(valid_tests, "no valid crtc/connector combinations found\n");
> +}
> +
> +igt_main
> +{
> +       data_t data = {};
> +       igt_skip_on_simulation();
> +
> +       igt_fixture {
> +               data.drm_fd = drm_open_any();
> +
> +               kmstest_set_vt_graphics_mode();
> +
> +               igt_display_init(&data.display, data.drm_fd);
> +       }
> +       devid = intel_get_drm_devid(data.drm_fd);
> +
> +       data.num_scalers = intel_gen(devid) >= 9 ? 2 : 0;
> +
> +       igt_assert(intel_gen(devid) >= 9);

As Tvrtko mentioned, these lines need to be moved into the igt_fixture block.


> +
> +       data.rotation = IGT_ROTATION_0;
> +       igt_subtest_f("nv12-plane-linear") {

There is no format string here, so igt_subtest would be sufficient.


> +               data.tiled = LOCAL_DRM_FORMAT_MOD_NONE;
> +               test_nv12_plane(&data);
> +       }
> +       igt_subtest_f("nv12-plane-tile-x") {
> +               data.tiled = LOCAL_I915_FORMAT_MOD_X_TILED;
> +               test_nv12_plane(&data);
> +       }
> +       igt_subtest_f("nv12-plane-tile-y") {
> +               data.tiled = LOCAL_I915_FORMAT_MOD_Y_TILED;
> +               test_nv12_plane(&data);
> +       }
> +       igt_subtest_f("nv12-plane-tile-yf") {
> +               data.tiled = LOCAL_I915_FORMAT_MOD_Yf_TILED;
> +               test_nv12_plane(&data);
> +       }
> +
> +       data.rotation = IGT_ROTATION_180;
> +       igt_subtest_f("nv12-plane-linear-rot-180") {
> +               data.tiled = LOCAL_DRM_FORMAT_MOD_NONE;
> +               test_nv12_plane(&data);
> +       }
> +       igt_subtest_f("nv12-plane-tile-x-rot-180") {
> +               data.tiled = LOCAL_I915_FORMAT_MOD_X_TILED;
> +               test_nv12_plane(&data);
> +       }
> +       igt_subtest_f("nv12-plane-tile-y-rot-180") {
> +               data.tiled = LOCAL_I915_FORMAT_MOD_Y_TILED;
> +               test_nv12_plane(&data);
> +       }
> +       igt_subtest_f("nv12-plane-tile-yf-rot-180") {
> +               data.tiled = LOCAL_I915_FORMAT_MOD_Yf_TILED;
> +               test_nv12_plane(&data);
> +       }
> +
> +       data.rotation = IGT_ROTATION_90;
> +       igt_subtest_f("nv12-plane-tile-y-rot-90") {
> +               data.tiled = LOCAL_I915_FORMAT_MOD_Y_TILED;
> +               test_nv12_plane_rotation_90_or_270(&data);
> +       }
> +       igt_subtest_f("nv12-plane-tile-yf-rot-90") {
> +               data.tiled = LOCAL_I915_FORMAT_MOD_Yf_TILED;
> +               test_nv12_plane_rotation_90_or_270(&data);
> +       }
> +
> +       data.rotation = IGT_ROTATION_270;
> +       igt_subtest_f("nv12-plane-tile-y-rot-270") {
> +               data.tiled = LOCAL_I915_FORMAT_MOD_Y_TILED;
> +               test_nv12_plane_rotation_90_or_270(&data);
> +       }
> +       igt_subtest_f("nv12-plane-tile-yf-rot-270") {
> +               data.tiled = LOCAL_I915_FORMAT_MOD_Yf_TILED;
> +               test_nv12_plane_rotation_90_or_270(&data);
> +       }
> +
> +       igt_subtest_f("nv12-on-unsupported-plane") {
> +               data.tiled = LOCAL_DRM_FORMAT_MOD_NONE;
> +               test_nv12_unsupported_plane(&data);
> +       }
> +
> +       igt_fixture {
> +               igt_display_fini(&data.display);
> +       }
> +}
> --
> 1.9.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2015-05-12 15:55 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-02  3:11 [PATCH 0/2] i-g-t: kms testcase for NV12 feature Chandra Konduru
2015-05-02  3:11 ` [PATCH 1/2] i-g-t: Prep work for adding NV12 testcase Chandra Konduru
2015-05-12 15:47   ` Thomas Wood
2015-05-02  3:11 ` [PATCH 2/2] i-g-t: Adding display " Chandra Konduru
2015-05-07  6:48   ` Daniel Vetter
2015-05-09  4:32   ` [PATCH] " Chandra Konduru
2015-05-11 12:12     ` Tvrtko Ursulin
2015-05-12 15:55     ` Thomas Wood

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.