All of lore.kernel.org
 help / color / mirror / Atom feed
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: dri-devel@lists.freedesktop.org
Subject: [PATCH 2/7] modetest: Add SMPTE test pattern
Date: Fri, 20 Jul 2012 14:50:42 +0200	[thread overview]
Message-ID: <1342788648-28528-3-git-send-email-laurent.pinchart@ideasonboard.com> (raw)
In-Reply-To: <1342788648-28528-1-git-send-email-laurent.pinchart@ideasonboard.com>

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 tests/modetest/modetest.c |  729 ++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 627 insertions(+), 102 deletions(-)

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index 496aac5..df2b977 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -474,6 +474,10 @@ static void dump_planes(void)
 	return;
 }
 
+/* -----------------------------------------------------------------------------
+ * Connectors and planes
+ */
+
 /*
  * Mode setting with the kernel interfaces is a bit of a chore.
  * First you have to find the connector in question and make sure the
@@ -577,41 +581,471 @@ connector_find_mode(struct connector *c)
 
 }
 
-static struct kms_bo *
-allocate_buffer(struct kms_driver *kms,
-		int width, int height, int *stride)
+/* -----------------------------------------------------------------------------
+ * Formats
+ */
+
+struct color_component {
+	unsigned int length;
+	unsigned int offset;
+};
+
+struct rgb_info {
+	struct color_component red;
+	struct color_component green;
+	struct color_component blue;
+	struct color_component alpha;
+};
+
+enum yuv_order {
+	YUV_YCbCr = 1,
+	YUV_YCrCb = 2,
+	YUV_YC = 4,
+	YUV_CY = 8,
+};
+
+struct yuv_info {
+	enum yuv_order order;
+	unsigned int xsub;
+	unsigned int ysub;
+	unsigned int chroma_stride;
+};
+
+struct format_info {
+	unsigned int format;
+	const char *name;
+	const struct rgb_info rgb;
+	const struct yuv_info yuv;
+};
+
+#define MAKE_RGB_INFO(rl, ro, bl, bo, gl, go, al, ao) \
+	.rgb = { { (rl), (ro) }, { (bl), (bo) }, { (gl), (go) }, { (al), (ao) } }
+
+#define MAKE_YUV_INFO(order, xsub, ysub, chroma_stride) \
+	.yuv = { (order), (xsub), (ysub), (chroma_stride) }
+
+static const struct format_info format_info[] = {
+	{ DRM_FORMAT_YUYV, "YUYV", MAKE_YUV_INFO(YUV_YCbCr | YUV_YC, 2, 2, 2) },
+	{ DRM_FORMAT_NV12, "NV12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 2) },
+	{ DRM_FORMAT_NV21, "NV21", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 2) },
+	{ DRM_FORMAT_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) },
+	{ DRM_FORMAT_XRGB1555, "XR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 0, 0) },
+	{ DRM_FORMAT_XRGB8888, "XR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
+	{ DRM_FORMAT_ARGB1555, "AR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 1, 15) },
+};
+
+unsigned int format_fourcc(const char *name)
 {
-	struct kms_bo *bo;
-	unsigned bo_attribs[] = {
-		KMS_WIDTH,   0,
-		KMS_HEIGHT,  0,
-		KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8,
-		KMS_TERMINATE_PROP_LIST
+	unsigned int i;
+	for (i = 0; i < ARRAY_SIZE(format_info); i++) {
+		if (!strcmp(format_info[i].name, name))
+			return format_info[i].format;
+	}
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Test patterns
+ */
+
+enum fill_pattern {
+	PATTERN_TILES = 0,
+	PATTERN_PLAIN = 1,
+	PATTERN_SMPTE = 2,
+};
+
+struct color_rgb24 {
+	unsigned int value:24;
+} __attribute__((__packed__));
+
+struct color_yuv {
+	unsigned char y;
+	unsigned char u;
+	unsigned char v;
+};
+
+#define MAKE_YUV_601_Y(r, g, b) \
+	((( 66 * (r) + 129 * (g) +  25 * (b) + 128) >> 8) + 16)
+#define MAKE_YUV_601_U(r, g, b) \
+	(((-38 * (r) -  74 * (g) + 112 * (b) + 128) >> 8) + 128)
+#define MAKE_YUV_601_V(r, g, b) \
+	(((112 * (r) -  94 * (g) -  18 * (b) + 128) >> 8) + 128)
+
+#define MAKE_YUV_601(r, g, b) \
+	{ .y = MAKE_YUV_601_Y(r, g, b), \
+	  .u = MAKE_YUV_601_U(r, g, b), \
+	  .v = MAKE_YUV_601_V(r, g, b) }
+
+#define MAKE_RGBA(rgb, r, g, b, a) \
+	((((r) >> (8 - (rgb)->red.length)) << (rgb)->red.offset) | \
+	 (((g) >> (8 - (rgb)->green.length)) << (rgb)->green.offset) | \
+	 (((b) >> (8 - (rgb)->blue.length)) << (rgb)->blue.offset) | \
+	 (((a) >> (8 - (rgb)->alpha.length)) << (rgb)->alpha.offset))
+
+static void
+fill_smpte_yuv_planar(const struct yuv_info *yuv,
+		      unsigned char *y_mem, unsigned char *u_mem,
+		      unsigned char *v_mem, unsigned int width,
+		      unsigned int height, unsigned int stride)
+{
+	const struct color_yuv colors_top[] = {
+		MAKE_YUV_601(191, 192, 192),	/* grey */
+		MAKE_YUV_601(192, 192, 0),	/* yellow */
+		MAKE_YUV_601(0, 192, 192),	/* cyan */
+		MAKE_YUV_601(0, 192, 0),	/* green */
+		MAKE_YUV_601(192, 0, 192),	/* magenta */
+		MAKE_YUV_601(192, 0, 0),	/* red */
+		MAKE_YUV_601(0, 0, 192),	/* blue */
 	};
-	int ret;
+	const struct color_yuv colors_middle[] = {
+		MAKE_YUV_601(0, 0, 192),	/* blue */
+		MAKE_YUV_601(19, 19, 19),	/* black */
+		MAKE_YUV_601(192, 0, 192),	/* magenta */
+		MAKE_YUV_601(19, 19, 19),	/* black */
+		MAKE_YUV_601(0, 192, 192),	/* cyan */
+		MAKE_YUV_601(19, 19, 19),	/* black */
+		MAKE_YUV_601(192, 192, 192),	/* grey */
+	};
+	const struct color_yuv colors_bottom[] = {
+		MAKE_YUV_601(0, 33, 76),	/* in-phase */
+		MAKE_YUV_601(255, 255, 255),	/* super white */
+		MAKE_YUV_601(50, 0, 106),	/* quadrature */
+		MAKE_YUV_601(19, 19, 19),	/* black */
+		MAKE_YUV_601(9, 9, 9),		/* 3.5% */
+		MAKE_YUV_601(19, 19, 19),	/* 7.5% */
+		MAKE_YUV_601(29, 29, 29),	/* 11.5% */
+		MAKE_YUV_601(19, 19, 19),	/* black */
+	};
+	unsigned int cs = yuv->chroma_stride;
+	unsigned int xsub = yuv->xsub;
+	unsigned int ysub = yuv->ysub;
+	unsigned int x;
+	unsigned int y;
+
+	/* Luma */
+	for (y = 0; y < height * 6 / 9; ++y) {
+		for (x = 0; x < width; ++x)
+			y_mem[x] = colors_top[x * 7 / width].y;
+		y_mem += stride;
+	}
 
-	bo_attribs[1] = width;
-	bo_attribs[3] = height;
+	for (; y < height * 7 / 9; ++y) {
+		for (x = 0; x < width; ++x)
+			y_mem[x] = colors_middle[x * 7 / width].y;
+		y_mem += stride;
+	}
 
-	ret = kms_bo_create(kms, bo_attribs, &bo);
-	if (ret) {
-		fprintf(stderr, "failed to alloc buffer: %s\n",
-			strerror(-ret));
-		return NULL;
+	for (; y < height; ++y) {
+		for (x = 0; x < width * 5 / 7; ++x)
+			y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
+		for (; x < width * 6 / 7; ++x)
+			y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3
+						 / (width / 7) + 4].y;
+		for (; x < width; ++x)
+			y_mem[x] = colors_bottom[7].y;
+		y_mem += stride;
 	}
 
-	ret = kms_bo_get_prop(bo, KMS_PITCH, stride);
-	if (ret) {
-		fprintf(stderr, "failed to retreive buffer stride: %s\n",
-			strerror(-ret));
-		kms_bo_destroy(&bo);
-		return NULL;
+	/* Chroma */
+	for (y = 0; y < height / ysub * 6 / 9; ++y) {
+		for (x = 0; x < width; x += xsub) {
+			u_mem[x*cs/xsub] = colors_top[x * 7 / width].u;
+			v_mem[x*cs/xsub] = colors_top[x * 7 / width].v;
+		}
+		u_mem += stride * cs / xsub;
+		v_mem += stride * cs / xsub;
 	}
 
-	return bo;
+	for (; y < height / ysub * 7 / 9; ++y) {
+		for (x = 0; x < width; x += xsub) {
+			u_mem[x*cs/xsub] = colors_middle[x * 7 / width].u;
+			v_mem[x*cs/xsub] = colors_middle[x * 7 / width].v;
+		}
+		u_mem += stride * cs / xsub;
+		v_mem += stride * cs / xsub;
+	}
+
+	for (; y < height / ysub; ++y) {
+		for (x = 0; x < width * 5 / 7; x += xsub) {
+			u_mem[x*cs/xsub] =
+				colors_bottom[x * 4 / (width * 5 / 7)].u;
+			v_mem[x*cs/xsub] =
+				colors_bottom[x * 4 / (width * 5 / 7)].v;
+		}
+		for (; x < width * 6 / 7; x += xsub) {
+			u_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
+							 3 / (width / 7) + 4].u;
+			v_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
+							 3 / (width / 7) + 4].v;
+		}
+		for (; x < width; x += xsub) {
+			u_mem[x*cs/xsub] = colors_bottom[7].u;
+			v_mem[x*cs/xsub] = colors_bottom[7].v;
+		}
+		u_mem += stride * cs / xsub;
+		v_mem += stride * cs / xsub;
+	}
+}
+
+static void
+fill_smpte_yuv_packed(const struct yuv_info *yuv, unsigned char *mem,
+		      unsigned int width, unsigned int height,
+		      unsigned int stride)
+{
+	const struct color_yuv colors_top[] = {
+		MAKE_YUV_601(191, 192, 192),	/* grey */
+		MAKE_YUV_601(192, 192, 0),	/* yellow */
+		MAKE_YUV_601(0, 192, 192),	/* cyan */
+		MAKE_YUV_601(0, 192, 0),	/* green */
+		MAKE_YUV_601(192, 0, 192),	/* magenta */
+		MAKE_YUV_601(192, 0, 0),	/* red */
+		MAKE_YUV_601(0, 0, 192),	/* blue */
+	};
+	const struct color_yuv colors_middle[] = {
+		MAKE_YUV_601(0, 0, 192),	/* blue */
+		MAKE_YUV_601(19, 19, 19),	/* black */
+		MAKE_YUV_601(192, 0, 192),	/* magenta */
+		MAKE_YUV_601(19, 19, 19),	/* black */
+		MAKE_YUV_601(0, 192, 192),	/* cyan */
+		MAKE_YUV_601(19, 19, 19),	/* black */
+		MAKE_YUV_601(192, 192, 192),	/* grey */
+	};
+	const struct color_yuv colors_bottom[] = {
+		MAKE_YUV_601(0, 33, 76),	/* in-phase */
+		MAKE_YUV_601(255, 255, 255),	/* super white */
+		MAKE_YUV_601(50, 0, 106),	/* quadrature */
+		MAKE_YUV_601(19, 19, 19),	/* black */
+		MAKE_YUV_601(9, 9, 9),		/* 3.5% */
+		MAKE_YUV_601(19, 19, 19),	/* 7.5% */
+		MAKE_YUV_601(29, 29, 29),	/* 11.5% */
+		MAKE_YUV_601(19, 19, 19),	/* black */
+	};
+	unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
+	unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
+	unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
+	unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
+	unsigned int x;
+	unsigned int y;
+
+	/* Luma */
+	for (y = 0; y < height * 6 / 9; ++y) {
+		for (x = 0; x < width; ++x)
+			y_mem[2*x] = colors_top[x * 7 / width].y;
+		y_mem += stride * 2;
+	}
+
+	for (; y < height * 7 / 9; ++y) {
+		for (x = 0; x < width; ++x)
+			y_mem[2*x] = colors_middle[x * 7 / width].y;
+		y_mem += stride * 2;
+	}
+
+	for (; y < height; ++y) {
+		for (x = 0; x < width * 5 / 7; ++x)
+			y_mem[2*x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
+		for (; x < width * 6 / 7; ++x)
+			y_mem[2*x] = colors_bottom[(x - width * 5 / 7) * 3
+						   / (width / 7) + 4].y;
+		for (; x < width; ++x)
+			y_mem[2*x] = colors_bottom[7].y;
+		y_mem += stride * 2;
+	}
+
+	/* Chroma */
+	for (y = 0; y < height * 6 / 9; ++y) {
+		for (x = 0; x < width; x += 2) {
+			c_mem[2*x+u] = colors_top[x * 7 / width].u;
+			c_mem[2*x+v] = colors_top[x * 7 / width].v;
+		}
+		c_mem += stride * 2;
+	}
+
+	for (; y < height * 7 / 9; ++y) {
+		for (x = 0; x < width; x += 2) {
+			c_mem[2*x+u] = colors_middle[x * 7 / width].u;
+			c_mem[2*x+v] = colors_middle[x * 7 / width].v;
+		}
+		c_mem += stride * 2;
+	}
+
+	for (; y < height; ++y) {
+		for (x = 0; x < width * 5 / 7; x += 2) {
+			c_mem[2*x+u] = colors_bottom[x * 4 / (width * 5 / 7)].u;
+			c_mem[2*x+v] = colors_bottom[x * 4 / (width * 5 / 7)].v;
+		}
+		for (; x < width * 6 / 7; x += 2) {
+			c_mem[2*x+u] = colors_bottom[(x - width * 5 / 7) *
+						     3 / (width / 7) + 4].u;
+			c_mem[2*x+v] = colors_bottom[(x - width * 5 / 7) *
+						     3 / (width / 7) + 4].v;
+		}
+		for (; x < width; x += 2) {
+			c_mem[2*x+u] = colors_bottom[7].u;
+			c_mem[2*x+v] = colors_bottom[7].v;
+		}
+		c_mem += stride * 2;
+	}
+}
+
+static void
+fill_smpte_rgb16(const struct rgb_info *rgb, unsigned char *mem,
+		 unsigned int width, unsigned int height, unsigned int stride)
+{
+	const uint16_t colors_top[] = {
+		MAKE_RGBA(rgb, 192, 192, 192, 255),	/* grey */
+		MAKE_RGBA(rgb, 192, 192, 0, 255),	/* yellow */
+		MAKE_RGBA(rgb, 0, 192, 192, 255),	/* cyan */
+		MAKE_RGBA(rgb, 0, 192, 0, 255),		/* green */
+		MAKE_RGBA(rgb, 192, 0, 192, 255),	/* magenta */
+		MAKE_RGBA(rgb, 192, 0, 0, 255),		/* red */
+		MAKE_RGBA(rgb, 0, 0, 192, 255),		/* blue */
+	};
+	const uint16_t colors_middle[] = {
+		MAKE_RGBA(rgb, 0, 0, 192, 255),		/* blue */
+		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
+		MAKE_RGBA(rgb, 192, 0, 192, 255),	/* magenta */
+		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
+		MAKE_RGBA(rgb, 0, 192, 192, 255),	/* cyan */
+		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
+		MAKE_RGBA(rgb, 192, 192, 192, 255),	/* grey */
+	};
+	const uint16_t colors_bottom[] = {
+		MAKE_RGBA(rgb, 0, 33, 76, 255),		/* in-phase */
+		MAKE_RGBA(rgb, 255, 255, 255, 255),	/* super white */
+		MAKE_RGBA(rgb, 50, 0, 106, 255),	/* quadrature */
+		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
+		MAKE_RGBA(rgb, 9, 9, 9, 255),		/* 3.5% */
+		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* 7.5% */
+		MAKE_RGBA(rgb, 29, 29, 29, 255),	/* 11.5% */
+		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
+	};
+	unsigned int x;
+	unsigned int y;
+
+	for (y = 0; y < height * 6 / 9; ++y) {
+		for (x = 0; x < width; ++x)
+			((uint16_t *)mem)[x] = colors_top[x * 7 / width];
+		mem += stride;
+	}
+
+	for (; y < height * 7 / 9; ++y) {
+		for (x = 0; x < width; ++x)
+			((uint16_t *)mem)[x] = colors_middle[x * 7 / width];
+		mem += stride;
+	}
+
+	for (; y < height; ++y) {
+		for (x = 0; x < width * 5 / 7; ++x)
+			((uint16_t *)mem)[x] =
+				colors_bottom[x * 4 / (width * 5 / 7)];
+		for (; x < width * 6 / 7; ++x)
+			((uint16_t *)mem)[x] =
+				colors_bottom[(x - width * 5 / 7) * 3
+					      / (width / 7) + 4];
+		for (; x < width; ++x)
+			((uint16_t *)mem)[x] = colors_bottom[7];
+		mem += stride;
+	}
 }
 
 static void
+fill_smpte_rgb32(const struct rgb_info *rgb, unsigned char *mem,
+		 unsigned int width, unsigned int height, unsigned int stride)
+{
+	const uint32_t colors_top[] = {
+		MAKE_RGBA(rgb, 192, 192, 192, 255),	/* grey */
+		MAKE_RGBA(rgb, 192, 192, 0, 255),	/* yellow */
+		MAKE_RGBA(rgb, 0, 192, 192, 255),	/* cyan */
+		MAKE_RGBA(rgb, 0, 192, 0, 255),		/* green */
+		MAKE_RGBA(rgb, 192, 0, 192, 255),	/* magenta */
+		MAKE_RGBA(rgb, 192, 0, 0, 255),		/* red */
+		MAKE_RGBA(rgb, 0, 0, 192, 255),		/* blue */
+	};
+	const uint32_t colors_middle[] = {
+		MAKE_RGBA(rgb, 0, 0, 192, 255),		/* blue */
+		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
+		MAKE_RGBA(rgb, 192, 0, 192, 255),	/* magenta */
+		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
+		MAKE_RGBA(rgb, 0, 192, 192, 255),	/* cyan */
+		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
+		MAKE_RGBA(rgb, 192, 192, 192, 255),	/* grey */
+	};
+	const uint32_t colors_bottom[] = {
+		MAKE_RGBA(rgb, 0, 33, 76, 255),		/* in-phase */
+		MAKE_RGBA(rgb, 255, 255, 255, 255),	/* super white */
+		MAKE_RGBA(rgb, 50, 0, 106, 255),	/* quadrature */
+		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
+		MAKE_RGBA(rgb, 9, 9, 9, 255),		/* 3.5% */
+		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* 7.5% */
+		MAKE_RGBA(rgb, 29, 29, 29, 255),	/* 11.5% */
+		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
+	};
+	unsigned int x;
+	unsigned int y;
+
+	for (y = 0; y < height * 6 / 9; ++y) {
+		for (x = 0; x < width; ++x)
+			((uint32_t *)mem)[x] = colors_top[x * 7 / width];
+		mem += stride;
+	}
+
+	for (; y < height * 7 / 9; ++y) {
+		for (x = 0; x < width; ++x)
+			((uint32_t *)mem)[x] = colors_middle[x * 7 / width];
+		mem += stride;
+	}
+
+	for (; y < height; ++y) {
+		for (x = 0; x < width * 5 / 7; ++x)
+			((uint32_t *)mem)[x] =
+				colors_bottom[x * 4 / (width * 5 / 7)];
+		for (; x < width * 6 / 7; ++x)
+			((uint32_t *)mem)[x] =
+				colors_bottom[(x - width * 5 / 7) * 3
+					      / (width / 7) + 4];
+		for (; x < width; ++x)
+			((uint32_t *)mem)[x] = colors_bottom[7];
+		mem += stride;
+	}
+}
+
+static void
+fill_smpte(const struct format_info *info, void *planes[3], unsigned int width,
+	   unsigned int height, unsigned int stride)
+{
+	unsigned char *u, *v;
+
+	switch (info->format) {
+	case DRM_FORMAT_YUYV:
+		return fill_smpte_yuv_packed(&info->yuv, planes[0], width,
+					     height, stride);
+
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV21:
+		u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
+		v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
+		return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v,
+					     width, height, stride);
+	case DRM_FORMAT_YVU420:
+		return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1],
+					     planes[2], width, height, stride);
+
+	case DRM_FORMAT_ARGB1555:
+	case DRM_FORMAT_XRGB1555:
+		return fill_smpte_rgb16(&info->rgb, planes[0],
+					width, height, stride);
+	case DRM_FORMAT_XRGB8888:
+		return fill_smpte_rgb32(&info->rgb, planes[0],
+					width, height, stride);
+	}
+}
+
+/* swap these for big endian.. */
+#define RED   2
+#define GREEN 1
+#define BLUE  0
+
+static void
 make_pwetty(void *data, int width, int height, int stride)
 {
 #ifdef HAVE_CAIRO
@@ -657,55 +1091,23 @@ make_pwetty(void *data, int width, int height, int stride)
 #endif
 }
 
-/* -----------------------------------------------------------------------------
- * Buffers management
- */
-
-/* swap these for big endian.. */
-#define RED   2
-#define GREEN 1
-#define BLUE  0
-
-struct format_name {
-	unsigned int format;
-	const char *name;
-};
-
-static const struct format_name format_names[] = {
-	{ DRM_FORMAT_YUYV, "YUYV" },
-	{ DRM_FORMAT_NV12, "NV12" },
-	{ DRM_FORMAT_YVU420, "YV12" },
-	{ DRM_FORMAT_XRGB1555, "XR15" },
-	{ DRM_FORMAT_XRGB8888, "XR24" },
-	{ DRM_FORMAT_ARGB1555, "AR15" },
-};
-
-unsigned int format_fourcc(const char *name)
-{
-	unsigned int i;
-	for (i = 0; i < ARRAY_SIZE(format_names); i++) {
-		if (!strcmp(format_names[i].name, name))
-			return format_names[i].format;
-	}
-	return 0;
-}
-
 static void
-fill420(unsigned char *y, unsigned char *u, unsigned char *v,
-		int cs /*chroma pixel stride */,
-		int n, int width, int height, int stride)
+fill_tiles_yuv_planar(const struct yuv_info *yuv,
+		      unsigned char *y_mem, unsigned char *u_mem,
+		      unsigned char *v_mem, unsigned int width,
+		      unsigned int height, unsigned int stride)
 {
-	int i, j;
+	unsigned int cs = yuv->chroma_stride;
+	unsigned int i, j;
 
-	/* paint the buffer with colored tiles, in blocks of 2x2 */
 	for (j = 0; j < height; j+=2) {
-		unsigned char *y1p = y + j * stride;
+		unsigned char *y1p = y_mem + j * stride;
 		unsigned char *y2p = y1p + stride;
-		unsigned char *up = u + (j/2) * stride * cs / 2;
-		unsigned char *vp = v + (j/2) * stride * cs / 2;
+		unsigned char *up = u_mem + (j/2) * stride * cs / 2;
+		unsigned char *vp = v_mem + (j/2) * stride * cs / 2;
 
 		for (i = 0; i < width; i+=2) {
-			div_t d = div(n+i+j, width);
+			div_t d = div(i+j, width);
 			uint32_t rgb = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6);
 			unsigned char *rgbp = (unsigned char *)&rgb;
 			unsigned char y = (0.299 * rgbp[RED]) + (0.587 * rgbp[GREEN]) + (0.114 * rgbp[BLUE]);
@@ -722,14 +1124,16 @@ fill420(unsigned char *y, unsigned char *u, unsigned char *v,
 }
 
 static void
-fill422(unsigned char *virtual, int n, int width, int height, int stride)
+fill_tiles_yuv_packed(const struct yuv_info *yuv, unsigned char *mem,
+		      unsigned int width, unsigned int height,
+		      unsigned int stride)
 {
-	int i, j;
-	/* paint the buffer with colored tiles */
+	unsigned int i, j;
+
 	for (j = 0; j < height; j++) {
-		uint8_t *ptr = (uint8_t*)((char*)virtual + j * stride);
+		uint8_t *ptr = (uint8_t*)((char*)mem + j * stride);
 		for (i = 0; i < width; i++) {
-			div_t d = div(n+i+j, width);
+			div_t d = div(i+j, width);
 			uint32_t rgb = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6);
 			unsigned char *rgbp = (unsigned char *)&rgb;
 			unsigned char y = (0.299 * rgbp[RED]) + (0.587 * rgbp[GREEN]) + (0.114 * rgbp[BLUE]);
@@ -743,14 +1147,15 @@ fill422(unsigned char *virtual, int n, int width, int height, int stride)
 }
 
 static void
-fill1555(unsigned char *virtual, int n, int width, int height, int stride)
+fill_tiles_rgb16(const struct rgb_info *rgb, unsigned char *mem,
+		 unsigned int width, unsigned int height, unsigned int stride)
 {
-	int i, j;
-	/* paint the buffer with colored tiles */
+	unsigned int i, j;
+
 	for (j = 0; j < height; j++) {
-		uint16_t *ptr = (uint16_t*)((char*)virtual + j * stride);
+		uint16_t *ptr = (uint16_t*)((char*)mem + j * stride);
 		for (i = 0; i < width; i++) {
-			div_t d = div(n+i+j, width);
+			div_t d = div(i+j, width);
 			uint32_t rgb = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6);
 			unsigned char *rgbp = (unsigned char *)&rgb;
 
@@ -763,12 +1168,13 @@ fill1555(unsigned char *virtual, int n, int width, int height, int stride)
 }
 
 static void
-fill8888(unsigned char *virtual, int width, int height, int stride)
+fill_tiles_rgb32(const struct rgb_info *rgb, unsigned char *mem,
+		 unsigned int width, unsigned int height, unsigned int stride)
 {
-	int i, j;
-	/* paint the buffer with colored tiles */
+	unsigned int i, j;
+
 	for (j = 0; j < height; j++) {
-		uint32_t *ptr = (uint32_t*)((char*)virtual + j * stride);
+		uint32_t *ptr = (uint32_t*)((char*)mem + j * stride);
 		for (i = 0; i < width; i++) {
 			div_t d = div(i, width);
 			ptr[i] =
@@ -777,22 +1183,139 @@ fill8888(unsigned char *virtual, int width, int height, int stride)
 		}
 	}
 
-	make_pwetty(virtual, width, height, stride);
+	make_pwetty(mem, width, height, stride);
+}
+
+static void
+fill_tiles(const struct format_info *info, void *planes[3], unsigned int width,
+	   unsigned int height, unsigned int stride)
+{
+	unsigned char *u, *v;
+
+	switch (info->format) {
+	case DRM_FORMAT_YUYV:
+		return fill_tiles_yuv_packed(&info->yuv, planes[0],
+					     width, height, stride);
+
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV21:
+		u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
+		v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
+		return fill_tiles_yuv_planar(&info->yuv, planes[0], u, v,
+					     width, height, stride);
+	case DRM_FORMAT_YVU420:
+		return fill_tiles_yuv_planar(&info->yuv, planes[0], planes[1],
+					     planes[2], width, height, stride);
+
+	case DRM_FORMAT_ARGB1555:
+	case DRM_FORMAT_XRGB1555:
+		return fill_tiles_rgb16(&info->rgb, planes[0],
+					width, height, stride);
+	case DRM_FORMAT_XRGB8888:
+		return fill_tiles_rgb32(&info->rgb, planes[0],
+					width, height, stride);
+	}
+}
+
+static void
+fill_plain(const struct format_info *info, void *planes[3], unsigned int width,
+	   unsigned int height, unsigned int stride)
+{
+	memset(planes[0], 0x77, stride * height);
 }
 
+/*
+ * fill_pattern - Fill a buffer with a test pattern
+ * @format: Pixel format
+ * @pattern: Test pattern
+ * @buffer: Buffer memory
+ * @width: Width in pixels
+ * @height: Height in pixels
+ * @stride: Line stride (pitch) in bytes
+ *
+ * Fill the buffer with the test pattern specified by the pattern parameter.
+ * Supported formats vary depending on the selected pattern.
+ */
 static void
-fill_grey(unsigned char *virtual, int width, int height, int stride)
+fill_pattern(unsigned int format, enum fill_pattern pattern,
+	     void *planes[3],
+	     unsigned int width, unsigned int height, unsigned int stride)
+{
+	const struct format_info *info = NULL;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(format_info); ++i) {
+		if (format_info[i].format == format) {
+			info = &format_info[i];
+			break;
+		}
+	}
+
+	if (info == NULL)
+		return;
+
+	switch (pattern) {
+	case PATTERN_TILES:
+		return fill_tiles(info, planes, width, height, stride);
+
+	case PATTERN_SMPTE:
+		return fill_smpte(info, planes, width, height, stride);
+
+	case PATTERN_PLAIN:
+		return fill_plain(info, planes, width, height, stride);
+
+	default:
+		printf("Error: unsupported test pattern %u.\n", pattern);
+		break;
+	}
+}
+
+/* -----------------------------------------------------------------------------
+ * Buffers management
+ */
+
+static struct kms_bo *
+allocate_buffer(struct kms_driver *kms,
+		int width, int height, int *stride)
 {
-	memset(virtual, 0x77, stride * height);
+	struct kms_bo *bo;
+	unsigned bo_attribs[] = {
+		KMS_WIDTH,   0,
+		KMS_HEIGHT,  0,
+		KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8,
+		KMS_TERMINATE_PROP_LIST
+	};
+	int ret;
+
+	bo_attribs[1] = width;
+	bo_attribs[3] = height;
+
+	ret = kms_bo_create(kms, bo_attribs, &bo);
+	if (ret) {
+		fprintf(stderr, "failed to alloc buffer: %s\n",
+			strerror(-ret));
+		return NULL;
+	}
+
+	ret = kms_bo_get_prop(bo, KMS_PITCH, stride);
+	if (ret) {
+		fprintf(stderr, "failed to retreive buffer stride: %s\n",
+			strerror(-ret));
+		kms_bo_destroy(&bo);
+		return NULL;
+	}
+
+	return bo;
 }
 
 static struct kms_bo *
 create_test_buffer(struct kms_driver *kms, unsigned int format,
 		   int width, int height, int handles[4],
-		   int pitches[4], int offsets[4], int grey)
+		   int pitches[4], int offsets[4], enum fill_pattern pattern)
 {
 	struct kms_bo *bo;
 	int ret, stride;
+	void *planes[3];
 	void *virtual;
 
 	bo = allocate_buffer(kms, width, height, &pitches[0]);
@@ -816,10 +1339,11 @@ create_test_buffer(struct kms_driver *kms, unsigned int format,
 		offsets[0] = 0;
 		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
 
-		fill422(virtual, 0, width, height, pitches[0]);
+		planes[0] = virtual;
 		break;
 
 	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV21:
 		pitches[0] = width;
 		offsets[0] = 0;
 		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
@@ -827,8 +1351,8 @@ create_test_buffer(struct kms_driver *kms, unsigned int format,
 		offsets[1] = width * height;
 		kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]);
 
-		fill420(virtual, virtual+offsets[1], virtual+offsets[1]+1,
-				2, 0, width, height, pitches[0]);
+		planes[0] = virtual;
+		planes[1] = virtual + offsets[1];
 		break;
 
 	case DRM_FORMAT_YVU420:
@@ -842,38 +1366,39 @@ create_test_buffer(struct kms_driver *kms, unsigned int format,
 		offsets[2] = offsets[1] + (width * height) / 4;
 		kms_bo_get_prop(bo, KMS_HANDLE, &handles[2]);
 
-		fill420(virtual, virtual+offsets[1], virtual+offsets[2],
-				1, 0, width, height, pitches[0]);
+		planes[0] = virtual;
+		planes[1] = virtual + offsets[1];
+		planes[2] = virtual + offsets[2];
 		break;
 
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_ARGB1555:
 	case DRM_FORMAT_XRGB1555:
 		pitches[0] = width * 2;
 		offsets[0] = 0;
 		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
 
-		fill1555(virtual, 0, width, height, pitches[0]);
+		planes[0] = virtual;
 		break;
 
-	case DRM_FORMAT_XRGB8888:
-		pitches[0] = width * 4;
+	case DRM_FORMAT_RGB888:
+		pitches[0] = width * 3;
 		offsets[0] = 0;
 		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
 
-		if (grey)
-			fill_grey(virtual, width, height, pitches[0]);
-		else
-			fill8888(virtual, width, height, pitches[0]);
+		planes[0] = virtual;
 		break;
 
-	case DRM_FORMAT_ARGB1555:
-		pitches[0] = width * 2;
+	case DRM_FORMAT_XRGB8888:
+		pitches[0] = width * 4;
 		offsets[0] = 0;
 		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
 
-		fill1555(virtual, 0, width, height, pitches[0]);
+		planes[0] = virtual;
 		break;
 	}
 
+	fill_pattern(format, pattern, planes, width, height, pitches[0]);
 	kms_bo_unmap(bo);
 
 	return bo;
@@ -959,7 +1484,7 @@ set_plane(struct kms_driver *kms, struct connector *c, struct plane *p)
 	}
 
 	plane_bo = create_test_buffer(kms, format, p->w, p->h, handles,
-				      pitches, offsets, 0);
+				      pitches, offsets, PATTERN_TILES);
 	if (plane_bo == NULL)
 		return -1;
 
@@ -1018,7 +1543,7 @@ set_mode(struct connector *c, int count, struct plane *p, int plane_count,
 	}
 
 	bo = create_test_buffer(kms, DRM_FORMAT_XRGB8888, width, height, handles,
-				pitches, offsets, 0);
+				pitches, offsets, PATTERN_SMPTE);
 	if (bo == NULL)
 		return;
 
@@ -1061,7 +1586,7 @@ set_mode(struct connector *c, int count, struct plane *p, int plane_count,
 		return;
 	
 	other_bo = create_test_buffer(kms, DRM_FORMAT_XRGB8888, width, height, handles,
-				      pitches, offsets, 1);
+				      pitches, offsets, PATTERN_PLAIN);
 	if (other_bo == NULL)
 		return;
 
-- 
1.7.8.6

  parent reply	other threads:[~2012-07-20 12:50 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-07-20 12:50 [PATCH 0/7] modetest cleanup and enhancements Laurent Pinchart
2012-07-20 12:50 ` [PATCH 1/7] modetest: Unify buffer allocation Laurent Pinchart
2012-07-20 12:50 ` Laurent Pinchart [this message]
2012-07-20 12:50 ` [PATCH 3/3] modetest: Add support for ARGB888, BGRA888 and BGRX888 formats Laurent Pinchart
2012-07-20 12:50 ` [PATCH 3/7] modetest: Add test pattern support for missing packed YUV formats Laurent Pinchart
2012-07-20 12:50 ` [PATCH 4/7] modetest: Add test pattern support for missing planar " Laurent Pinchart
2012-07-20 12:50 ` [PATCH 5/7] modetest: Add test pattern support for missing RGB formats Laurent Pinchart
2012-07-20 12:50 ` [PATCH 6/7] modetest: Move connector and plane parsing to separate functions Laurent Pinchart
2012-07-20 12:50 ` [PATCH 7/7] modetest: Make frame buffer format configurable on the command line Laurent Pinchart
2012-07-20 13:43 ` [PATCH 0/7] modetest cleanup and enhancements Rob Clark
2012-07-20 14:37   ` [PATCH] modeset: Split buffer allocation to a separate file Laurent Pinchart
2012-07-20 15:34     ` Rob Clark
2012-07-20 17:38       ` Laurent Pinchart
2012-07-23 16:40         ` Rob Clark

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1342788648-28528-3-git-send-email-laurent.pinchart@ideasonboard.com \
    --to=laurent.pinchart@ideasonboard.com \
    --cc=dri-devel@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.