All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] modetest cleanup and enhancements
@ 2012-07-20 12:50 Laurent Pinchart
  2012-07-20 12:50 ` [PATCH 1/7] modetest: Unify buffer allocation Laurent Pinchart
                   ` (8 more replies)
  0 siblings, 9 replies; 14+ messages in thread
From: Laurent Pinchart @ 2012-07-20 12:50 UTC (permalink / raw)
  To: dri-devel

Hi everybody,

I've enhanced the modetest utility to test various features of the SH Mobile
LCDC DRM driver. Here are the corresponding patches. They mostly touch buffer
allocation cleanup (1/7), adding test patterns for different formats (2/7 to
5/7) and making frame buffer format configurable on the command line (6/7 and
7/7).

Laurent Pinchart (7):
  modetest: Unify buffer allocation
  modetest: Add SMPTE test pattern
  modetest: Add test pattern support for missing packed YUV formats
  modetest: Add test pattern support for missing planar YUV formats
  modetest: Add test pattern support for missing RGB formats
  modetest: Move connector and plane parsing to separate functions
  modetest: Make frame buffer format configurable on the command line

 tests/modetest/modetest.c | 1254 +++++++++++++++++++++++++++++++++++----------
 1 files changed, 988 insertions(+), 266 deletions(-)

-- 
Regards,

Laurent Pinchart

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

* [PATCH 1/7] modetest: Unify buffer allocation
  2012-07-20 12:50 [PATCH 0/7] modetest cleanup and enhancements Laurent Pinchart
@ 2012-07-20 12:50 ` Laurent Pinchart
  2012-07-20 12:50 ` [PATCH 2/7] modetest: Add SMPTE test pattern Laurent Pinchart
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2012-07-20 12:50 UTC (permalink / raw)
  To: dri-devel

Merge the create_test_buffer() and create_grey_buffer() functions into a
single buffer allocation function that takes the pixel format and fill
pattern as parameters.

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

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index ec3121e..496aac5 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -657,112 +657,39 @@ make_pwetty(void *data, int width, int height, int stride)
 #endif
 }
 
-static int
-create_test_buffer(struct kms_driver *kms,
-		   int width, int height, int *stride_out,
-		   struct kms_bo **bo_out)
-{
-	struct kms_bo *bo;
-	int ret, i, j, stride;
-	void *virtual;
-
-	bo = allocate_buffer(kms, width, height, &stride);
-	if (!bo)
-		return -1;
-
-	ret = kms_bo_map(bo, &virtual);
-	if (ret) {
-		fprintf(stderr, "failed to map buffer: %s\n",
-			strerror(-ret));
-		kms_bo_destroy(&bo);
-		return -1;
-	}
-
-	/* paint the buffer with colored tiles */
-	for (j = 0; j < height; j++) {
-		uint32_t *fb_ptr = (uint32_t*)((char*)virtual + j * stride);
-		for (i = 0; i < width; i++) {
-			div_t d = div(i, width);
-			fb_ptr[i] =
-				0x00130502 * (d.quot >> 6) +
-				0x000a1120 * (d.rem >> 6);
-		}
-	}
+/* -----------------------------------------------------------------------------
+ * Buffers management
+ */
 
-	make_pwetty(virtual, width, height, stride);
+/* swap these for big endian.. */
+#define RED   2
+#define GREEN 1
+#define BLUE  0
 
-	kms_bo_unmap(bo);
+struct format_name {
+	unsigned int format;
+	const char *name;
+};
 
-	*bo_out = bo;
-	*stride_out = stride;
-	return 0;
-}
+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" },
+};
 
-static int
-create_grey_buffer(struct kms_driver *kms,
-		   int width, int height, int *stride_out,
-		   struct kms_bo **bo_out)
+unsigned int format_fourcc(const char *name)
 {
-	struct kms_bo *bo;
-	int size, ret, stride;
-	void *virtual;
-
-	bo = allocate_buffer(kms, width, height, &stride);
-	if (!bo)
-		return -1;
-
-	ret = kms_bo_map(bo, &virtual);
-	if (ret) {
-		fprintf(stderr, "failed to map buffer: %s\n",
-			strerror(-ret));
-		kms_bo_destroy(&bo);
-		return -1;
+	unsigned int i;
+	for (i = 0; i < ARRAY_SIZE(format_names); i++) {
+		if (!strcmp(format_names[i].name, name))
+			return format_names[i].format;
 	}
-
-	size = stride * height;
-	memset(virtual, 0x77, size);
-	kms_bo_unmap(bo);
-
-	*bo_out = bo;
-	*stride_out = stride;
-
 	return 0;
 }
 
-void
-page_flip_handler(int fd, unsigned int frame,
-		  unsigned int sec, unsigned int usec, void *data)
-{
-	struct connector *c;
-	unsigned int new_fb_id;
-	struct timeval end;
-	double t;
-
-	c = data;
-	if (c->current_fb_id == c->fb_id[0])
-		new_fb_id = c->fb_id[1];
-	else
-		new_fb_id = c->fb_id[0];
-			
-	drmModePageFlip(fd, c->crtc, new_fb_id,
-			DRM_MODE_PAGE_FLIP_EVENT, c);
-	c->current_fb_id = new_fb_id;
-	c->swap_count++;
-	if (c->swap_count == 60) {
-		gettimeofday(&end, NULL);
-		t = end.tv_sec + end.tv_usec * 1e-6 -
-			(c->start.tv_sec + c->start.tv_usec * 1e-6);
-		fprintf(stderr, "freq: %.02fHz\n", c->swap_count / t);
-		c->swap_count = 0;
-		c->start = end;
-	}
-}
-
-/* swap these for big endian.. */
-#define RED   2
-#define GREEN 1
-#define BLUE  0
-
 static void
 fill420(unsigned char *y, unsigned char *u, unsigned char *v,
 		int cs /*chroma pixel stride */,
@@ -835,6 +762,154 @@ fill1555(unsigned char *virtual, int n, int width, int height, int stride)
 	}
 }
 
+static void
+fill8888(unsigned char *virtual, int width, int height, int stride)
+{
+	int i, j;
+	/* paint the buffer with colored tiles */
+	for (j = 0; j < height; j++) {
+		uint32_t *ptr = (uint32_t*)((char*)virtual + j * stride);
+		for (i = 0; i < width; i++) {
+			div_t d = div(i, width);
+			ptr[i] =
+				0x00130502 * (d.quot >> 6) +
+				0x000a1120 * (d.rem >> 6);
+		}
+	}
+
+	make_pwetty(virtual, width, height, stride);
+}
+
+static void
+fill_grey(unsigned char *virtual, int width, int height, int stride)
+{
+	memset(virtual, 0x77, stride * height);
+}
+
+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)
+{
+	struct kms_bo *bo;
+	int ret, stride;
+	void *virtual;
+
+	bo = allocate_buffer(kms, width, height, &pitches[0]);
+	if (!bo)
+		return NULL;
+
+	ret = kms_bo_map(bo, &virtual);
+	if (ret) {
+		fprintf(stderr, "failed to map buffer: %s\n",
+			strerror(-ret));
+		kms_bo_destroy(&bo);
+		return NULL;
+	}
+
+	/* just testing a limited # of formats to test single
+	 * and multi-planar path.. would be nice to add more..
+	 */
+	switch (format) {
+	case DRM_FORMAT_YUYV:
+		pitches[0] = width * 2;
+		offsets[0] = 0;
+		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
+
+		fill422(virtual, 0, width, height, pitches[0]);
+		break;
+
+	case DRM_FORMAT_NV12:
+		pitches[0] = width;
+		offsets[0] = 0;
+		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
+		pitches[1] = width;
+		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]);
+		break;
+
+	case DRM_FORMAT_YVU420:
+		pitches[0] = width;
+		offsets[0] = 0;
+		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
+		pitches[1] = width / 2;
+		offsets[1] = width * height;
+		kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]);
+		pitches[2] = width / 2;
+		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]);
+		break;
+
+	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]);
+		break;
+
+	case DRM_FORMAT_XRGB8888:
+		pitches[0] = width * 4;
+		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]);
+		break;
+
+	case DRM_FORMAT_ARGB1555:
+		pitches[0] = width * 2;
+		offsets[0] = 0;
+		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
+
+		fill1555(virtual, 0, width, height, pitches[0]);
+		break;
+	}
+
+	kms_bo_unmap(bo);
+
+	return bo;
+}
+
+/* -------------------------------------------------------------------------- */
+
+void
+page_flip_handler(int fd, unsigned int frame,
+		  unsigned int sec, unsigned int usec, void *data)
+{
+	struct connector *c;
+	unsigned int new_fb_id;
+	struct timeval end;
+	double t;
+
+	c = data;
+	if (c->current_fb_id == c->fb_id[0])
+		new_fb_id = c->fb_id[1];
+	else
+		new_fb_id = c->fb_id[0];
+
+	drmModePageFlip(fd, c->crtc, new_fb_id,
+			DRM_MODE_PAGE_FLIP_EVENT, c);
+	c->current_fb_id = new_fb_id;
+	c->swap_count++;
+	if (c->swap_count == 60) {
+		gettimeofday(&end, NULL);
+		t = end.tv_sec + end.tv_usec * 1e-6 -
+			(c->start.tv_sec + c->start.tv_usec * 1e-6);
+		fprintf(stderr, "freq: %.02fHz\n", c->swap_count / t);
+		c->swap_count = 0;
+		c->start = end;
+	}
+}
+
 static int
 set_plane(struct kms_driver *kms, struct connector *c, struct plane *p)
 {
@@ -847,6 +922,12 @@ set_plane(struct kms_driver *kms, struct connector *c, struct plane *p)
 	int ret, crtc_x, crtc_y, crtc_w, crtc_h;
 	unsigned int i;
 
+	format = format_fourcc(p->format_str);
+	if (format == 0) {
+		fprintf(stderr, "Unknown format: %s\n", p->format_str);
+		return -1;
+	}
+
 	/* find an unused plane which can be connected to our crtc */
 	plane_resources = drmModeGetPlaneResources(fd);
 	if (!plane_resources) {
@@ -877,92 +958,10 @@ set_plane(struct kms_driver *kms, struct connector *c, struct plane *p)
 		return -1;
 	}
 
-	if (!strcmp(p->format_str, "XR24")) {
-		if (create_test_buffer(kms, p->w, p->h, &pitches[0], &plane_bo))
-			return -1;
-		kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]);
-		format = DRM_FORMAT_XRGB8888;
-	} else {
-		void *virtual;
-
-		/* TODO: this always allocates a buffer for 32bpp RGB.. but for
-		 * YUV formats, we don't use all of it..  since 4bytes/pixel is
-		 * worst case, so live with it for now and just don't use all
-		 * the buffer:
-		 */
-		plane_bo = allocate_buffer(kms, p->w, p->h, &pitches[0]);
-		if (!plane_bo)
-			return -1;
-
-		ret = kms_bo_map(plane_bo, &virtual);
-		if (ret) {
-			fprintf(stderr, "failed to map buffer: %s\n",
-				strerror(-ret));
-			kms_bo_destroy(&plane_bo);
-			return -1;
-		}
-
-		/* just testing a limited # of formats to test single
-		 * and multi-planar path.. would be nice to add more..
-		 */
-		if (!strcmp(p->format_str, "YUYV")) {
-			pitches[0] = p->w * 2;
-			offsets[0] = 0;
-			kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]);
-
-			fill422(virtual, 0, p->w, p->h, pitches[0]);
-
-			format = DRM_FORMAT_YUYV;
-		} else if (!strcmp(p->format_str, "NV12")) {
-			pitches[0] = p->w;
-			offsets[0] = 0;
-			kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]);
-			pitches[1] = p->w;
-			offsets[1] = p->w * p->h;
-			kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[1]);
-
-			fill420(virtual, virtual+offsets[1], virtual+offsets[1]+1,
-					2, 0, p->w, p->h, pitches[0]);
-
-			format = DRM_FORMAT_NV12;
-		} else if (!strcmp(p->format_str, "YV12")) {
-			pitches[0] = p->w;
-			offsets[0] = 0;
-			kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]);
-			pitches[1] = p->w / 2;
-			offsets[1] = p->w * p->h;
-			kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[1]);
-			pitches[2] = p->w / 2;
-			offsets[2] = offsets[1] + (p->w * p->h) / 4;
-			kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[2]);
-
-			fill420(virtual, virtual+offsets[1], virtual+offsets[2],
-					1, 0, p->w, p->h, pitches[0]);
-
-			format = DRM_FORMAT_YVU420;
-		} else if (!strcmp(p->format_str, "XR15")) {
-			pitches[0] = p->w * 2;
-			offsets[0] = 0;
-			kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]);
-
-			fill1555(virtual, 0, p->w, p->h, pitches[0]);
-
-			format = DRM_FORMAT_XRGB1555;
-		} else if (!strcmp(p->format_str, "AR15")) {
-			pitches[0] = p->w * 2;
-			offsets[0] = 0;
-			kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]);
-
-			fill1555(virtual, 0, p->w, p->h, pitches[0]);
-
-			format = DRM_FORMAT_ARGB1555;
-		} else {
-			fprintf(stderr, "Unknown format: %s\n", p->format_str);
-			return -1;
-		}
-
-		kms_bo_unmap(plane_bo);
-	}
+	plane_bo = create_test_buffer(kms, format, p->w, p->h, handles,
+				      pitches, offsets, 0);
+	if (plane_bo == NULL)
+		return -1;
 
 	/* just use single plane format for now.. */
 	if (drmModeAddFB2(fd, p->w, p->h, format,
@@ -996,8 +995,8 @@ set_mode(struct connector *c, int count, struct plane *p, int plane_count,
 	struct kms_driver *kms;
 	struct kms_bo *bo, *other_bo;
 	unsigned int fb_id, other_fb_id;
-	int i, j, ret, width, height, x, stride;
-	unsigned handle;
+	int i, j, ret, width, height, x;
+	uint32_t handles[4], pitches[4], offsets[4] = {0}; /* we only use [0] */
 	drmEventContext evctx;
 
 	width = 0;
@@ -1018,11 +1017,12 @@ set_mode(struct connector *c, int count, struct plane *p, int plane_count,
 		return;
 	}
 
-	if (create_test_buffer(kms, width, height, &stride, &bo))
+	bo = create_test_buffer(kms, DRM_FORMAT_XRGB8888, width, height, handles,
+				pitches, offsets, 0);
+	if (bo == NULL)
 		return;
 
-	kms_bo_get_prop(bo, KMS_HANDLE, &handle);
-	ret = drmModeAddFB(fd, width, height, 24, 32, stride, handle, &fb_id);
+	ret = drmModeAddFB(fd, width, height, 24, 32, pitches[0], handles[0], &fb_id);
 	if (ret) {
 		fprintf(stderr, "failed to add fb (%ux%u): %s\n",
 			width, height, strerror(errno));
@@ -1060,11 +1060,12 @@ set_mode(struct connector *c, int count, struct plane *p, int plane_count,
 	if (!page_flip)
 		return;
 	
-	if (create_grey_buffer(kms, width, height, &stride, &other_bo))
+	other_bo = create_test_buffer(kms, DRM_FORMAT_XRGB8888, width, height, handles,
+				      pitches, offsets, 1);
+	if (other_bo == NULL)
 		return;
 
-	kms_bo_get_prop(other_bo, KMS_HANDLE, &handle);
-	ret = drmModeAddFB(fd, width, height, 32, 32, stride, handle,
+	ret = drmModeAddFB(fd, width, height, 32, 32, pitches[0], handles[0],
 			   &other_fb_id);
 	if (ret) {
 		fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
-- 
1.7.8.6

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

* [PATCH 2/7] modetest: Add SMPTE test pattern
  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
  2012-07-20 12:50 ` [PATCH 3/3] modetest: Add support for ARGB888, BGRA888 and BGRX888 formats Laurent Pinchart
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2012-07-20 12:50 UTC (permalink / raw)
  To: dri-devel

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

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

* [PATCH 3/3] modetest: Add support for ARGB888, BGRA888 and BGRX888 formats
  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 ` [PATCH 2/7] modetest: Add SMPTE test pattern Laurent Pinchart
@ 2012-07-20 12:50 ` Laurent Pinchart
  2012-07-20 12:50 ` [PATCH 3/7] modetest: Add test pattern support for missing packed YUV formats Laurent Pinchart
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2012-07-20 12:50 UTC (permalink / raw)
  To: dri-devel

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

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index b70fb10..2a04459 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -629,6 +629,9 @@ static const struct format_info format_info[] = {
 	{ DRM_FORMAT_XRGB1555, "XR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 0, 0) },
 	{ DRM_FORMAT_RGB888, "RG24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
 	{ DRM_FORMAT_XRGB8888, "XR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
+	{ DRM_FORMAT_BGRX8888, "BX24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 0, 0) },
+	{ DRM_FORMAT_ARGB8888, "AR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 8, 24) },
+	{ DRM_FORMAT_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, 0) },
 };
 
 unsigned int format_fourcc(const char *name)
@@ -915,35 +918,36 @@ fill_smpte_rgb24(const struct rgb_info *rgb, void *mem,
 
 static void
 fill_smpte_rgb32(const struct rgb_info *rgb, void *mem,
-		 unsigned int width, unsigned int height, unsigned int stride)
+		 unsigned int width, unsigned int height, unsigned int stride,
+		 uint8_t alpha)
 {
 	const uint32_t colors_top[] = {
-		MAKE_RGBA(rgb, 192, 192, 192, 0),	/* grey */
-		MAKE_RGBA(rgb, 192, 192, 0, 0),		/* yellow */
-		MAKE_RGBA(rgb, 0, 192, 192, 0),		/* cyan */
-		MAKE_RGBA(rgb, 0, 192, 0, 0),		/* green */
-		MAKE_RGBA(rgb, 192, 0, 192, 0),		/* magenta */
-		MAKE_RGBA(rgb, 192, 0, 0, 0),		/* red */
-		MAKE_RGBA(rgb, 0, 0, 192, 0),		/* blue */
+		MAKE_RGBA(rgb, 192, 192, 192, alpha),	/* grey */
+		MAKE_RGBA(rgb, 192, 192, 0, alpha),	/* yellow */
+		MAKE_RGBA(rgb, 0, 192, 192, alpha),	/* cyan */
+		MAKE_RGBA(rgb, 0, 192, 0, alpha),	/* green */
+		MAKE_RGBA(rgb, 192, 0, 192, alpha),	/* magenta */
+		MAKE_RGBA(rgb, 192, 0, 0, alpha),	/* red */
+		MAKE_RGBA(rgb, 0, 0, 192, alpha),	/* blue */
 	};
 	const uint32_t colors_middle[] = {
-		MAKE_RGBA(rgb, 0, 0, 192, 0),		/* blue */
-		MAKE_RGBA(rgb, 19, 19, 19, 0),		/* black */
-		MAKE_RGBA(rgb, 192, 0, 192, 0),		/* magenta */
-		MAKE_RGBA(rgb, 19, 19, 19, 0),		/* black */
-		MAKE_RGBA(rgb, 0, 192, 192, 0),		/* cyan */
-		MAKE_RGBA(rgb, 19, 19, 19, 0),		/* black */
-		MAKE_RGBA(rgb, 192, 192, 192, 0),	/* grey */
+		MAKE_RGBA(rgb, 0, 0, 192, alpha),	/* blue */
+		MAKE_RGBA(rgb, 19, 19, 19, alpha),	/* black */
+		MAKE_RGBA(rgb, 192, 0, 192, alpha),	/* magenta */
+		MAKE_RGBA(rgb, 19, 19, 19, alpha),	/* black */
+		MAKE_RGBA(rgb, 0, 192, 192, alpha),	/* cyan */
+		MAKE_RGBA(rgb, 19, 19, 19, alpha),	/* black */
+		MAKE_RGBA(rgb, 192, 192, 192, alpha),	/* grey */
 	};
 	const uint32_t colors_bottom[] = {
-		MAKE_RGBA(rgb, 0, 33, 76, 0),		/* in-phase */
-		MAKE_RGBA(rgb, 255, 255, 255, 0),	/* super white */
-		MAKE_RGBA(rgb, 50, 0, 106, 0),		/* quadrature */
-		MAKE_RGBA(rgb, 19, 19, 19, 0),		/* black */
-		MAKE_RGBA(rgb, 9, 9, 9, 0),		/* 3.5% */
-		MAKE_RGBA(rgb, 19, 19, 19, 0),		/* 7.5% */
-		MAKE_RGBA(rgb, 29, 29, 29, 0),		/* 11.5% */
-		MAKE_RGBA(rgb, 19, 19, 19, 0),		/* black */
+		MAKE_RGBA(rgb, 0, 33, 76, alpha),	/* in-phase */
+		MAKE_RGBA(rgb, 255, 255, 255, alpha),	/* super white */
+		MAKE_RGBA(rgb, 50, 0, 106, alpha),	/* quadrature */
+		MAKE_RGBA(rgb, 19, 19, 19, alpha),	/* black */
+		MAKE_RGBA(rgb, 9, 9, 9, alpha),		/* 3.5% */
+		MAKE_RGBA(rgb, 19, 19, 19, alpha),	/* 7.5% */
+		MAKE_RGBA(rgb, 29, 29, 29, alpha),	/* 11.5% */
+		MAKE_RGBA(rgb, 19, 19, 19, alpha),	/* black */
 	};
 	unsigned int x;
 	unsigned int y;
@@ -992,10 +996,12 @@ fill_smpte(const struct format_info *info, void *planes[3], unsigned int width,
 	case DRM_FORMAT_BGR888:
 		return fill_smpte_rgb24(&info->rgb, planes[0],
 					width, height, stride);
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_BGRA8888:
 	case DRM_FORMAT_XRGB8888:
 	case DRM_FORMAT_BGRX8888:
 		return fill_smpte_rgb32(&info->rgb, planes[0],
-					width, height, stride);
+					width, height, stride, 255);
 	}
 }
 
@@ -1085,9 +1091,9 @@ fill_tile_xrgb8888(unsigned char *virtual, int width, int height, int stride)
 		uint32_t *ptr = (uint32_t*)((char*)virtual + j * stride);
 		for (i = 0; i < width; i++) {
 			div_t d = div(i, width);
-			ptr[i] =
-				0x00130502 * (d.quot >> 6) +
-				0x000a1120 * (d.rem >> 6);
+			ptr[i] = 0xff000000
+			       | (0x00130502 * (d.quot >> 6) +
+			          0x000a1120 * (d.rem >> 6));
 		}
 	}
 
@@ -1116,6 +1122,7 @@ fill_tiles(const struct format_info *info, void *planes[3], unsigned int width,
 	case DRM_FORMAT_ARGB1555:
 	case DRM_FORMAT_XRGB1555:
 		return fill_tiles_xrgb1555(planes[0], width, height, stride);
+	case DRM_FORMAT_ARGB8888:
 	case DRM_FORMAT_XRGB8888:
 		return fill_tile_xrgb8888(planes[0], width, height, stride);
 	}
@@ -1293,7 +1300,10 @@ create_test_buffer(struct kms_driver *kms, unsigned int format,
 		planes[0] = virtual;
 		break;
 
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_BGRA8888:
 	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_BGRX8888:
 		pitches[0] = width * 4;
 		offsets[0] = 0;
 		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
-- 
1.7.3.4

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

* [PATCH 3/7] modetest: Add test pattern support for missing packed YUV formats
  2012-07-20 12:50 [PATCH 0/7] modetest cleanup and enhancements Laurent Pinchart
                   ` (2 preceding siblings ...)
  2012-07-20 12:50 ` [PATCH 3/3] modetest: Add support for ARGB888, BGRA888 and BGRX888 formats Laurent Pinchart
@ 2012-07-20 12:50 ` Laurent Pinchart
  2012-07-20 12:50 ` [PATCH 4/7] modetest: Add test pattern support for missing planar " Laurent Pinchart
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2012-07-20 12:50 UTC (permalink / raw)
  To: dri-devel

Implement tiles and SMPTE test pattern generation for the UYVY, VYUY and
YVYU formats.

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

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index df2b977..f1dfe98 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -625,10 +625,17 @@ struct format_info {
 	.yuv = { (order), (xsub), (ysub), (chroma_stride) }
 
 static const struct format_info format_info[] = {
+	/* YUV packed */
+	{ DRM_FORMAT_UYVY, "UYVY", MAKE_YUV_INFO(YUV_YCbCr | YUV_CY, 2, 2, 2) },
+	{ DRM_FORMAT_VYUY, "VYUY", MAKE_YUV_INFO(YUV_YCrCb | YUV_CY, 2, 2, 2) },
 	{ DRM_FORMAT_YUYV, "YUYV", MAKE_YUV_INFO(YUV_YCbCr | YUV_YC, 2, 2, 2) },
+	{ DRM_FORMAT_YVYU, "YVYU", MAKE_YUV_INFO(YUV_YCrCb | YUV_YC, 2, 2, 2) },
+	/* YUV semi-planar */
 	{ DRM_FORMAT_NV12, "NV12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 2) },
 	{ DRM_FORMAT_NV21, "NV21", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 2) },
+	/* YUV planar */
 	{ DRM_FORMAT_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) },
+	/* RGB */
 	{ 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) },
@@ -1016,7 +1023,10 @@ fill_smpte(const struct format_info *info, void *planes[3], unsigned int width,
 	unsigned char *u, *v;
 
 	switch (info->format) {
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_VYUY:
 	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
 		return fill_smpte_yuv_packed(&info->yuv, planes[0], width,
 					     height, stride);
 
@@ -1026,6 +1036,7 @@ fill_smpte(const struct format_info *info, void *planes[3], unsigned int width,
 		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);
@@ -1128,21 +1139,30 @@ fill_tiles_yuv_packed(const struct yuv_info *yuv, unsigned char *mem,
 		      unsigned int width, unsigned int height,
 		      unsigned int stride)
 {
-	unsigned int i, j;
-
-	for (j = 0; j < height; j++) {
-		uint8_t *ptr = (uint8_t*)((char*)mem + j * stride);
-		for (i = 0; i < width; i++) {
-			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]);
+	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;
 
-			*(ptr++) = y;
-			*(ptr++) = (rgbp[BLUE] - y) * 0.565 + 128;
-			*(ptr++) = y;
-			*(ptr++) = (rgbp[RED] - y) * 0.713 + 128;
+	for (y = 0; y < height; ++y) {
+		for (x = 0; x < width; x += 2) {
+			div_t d = div(x+y, width);
+			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
+				       + 0x000a1120 * (d.rem >> 6);
+			struct color_yuv color =
+				MAKE_YUV_601((rgb32 >> 16) & 0xff,
+					     (rgb32 >> 8) & 0xff, rgb32 & 0xff);
+
+			y_mem[2*x] = color.y;
+			c_mem[2*x+u] = color.u;
+			y_mem[2*x+2] = color.y;
+			c_mem[2*x+v] = color.v;
 		}
+
+		y_mem += stride;
+		c_mem += stride;
 	}
 }
 
@@ -1193,7 +1213,10 @@ fill_tiles(const struct format_info *info, void *planes[3], unsigned int width,
 	unsigned char *u, *v;
 
 	switch (info->format) {
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_VYUY:
 	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
 		return fill_tiles_yuv_packed(&info->yuv, planes[0],
 					     width, height, stride);
 
@@ -1203,6 +1226,7 @@ fill_tiles(const struct format_info *info, void *planes[3], unsigned int width,
 		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);
@@ -1334,7 +1358,10 @@ create_test_buffer(struct kms_driver *kms, unsigned int format,
 	 * and multi-planar path.. would be nice to add more..
 	 */
 	switch (format) {
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_VYUY:
 	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
 		pitches[0] = width * 2;
 		offsets[0] = 0;
 		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
-- 
1.7.8.6

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

* [PATCH 4/7] modetest: Add test pattern support for missing planar YUV formats
  2012-07-20 12:50 [PATCH 0/7] modetest cleanup and enhancements Laurent Pinchart
                   ` (3 preceding siblings ...)
  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 ` Laurent Pinchart
  2012-07-20 12:50 ` [PATCH 5/7] modetest: Add test pattern support for missing RGB formats Laurent Pinchart
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2012-07-20 12:50 UTC (permalink / raw)
  To: dri-devel

Implement tiles and SMPTE test pattern generation for the NV12, NV21,
NV16 and NV61 formats.

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

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index f1dfe98..bdb74ae 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -633,6 +633,8 @@ static const struct format_info format_info[] = {
 	/* YUV semi-planar */
 	{ 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_NV16, "NV16", MAKE_YUV_INFO(YUV_YCbCr, 2, 1, 2) },
+	{ DRM_FORMAT_NV61, "NV61", MAKE_YUV_INFO(YUV_YCrCb, 2, 1, 2) },
 	/* YUV planar */
 	{ DRM_FORMAT_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) },
 	/* RGB */
@@ -1032,6 +1034,8 @@ fill_smpte(const struct format_info *info, void *planes[3], unsigned int width,
 
 	case DRM_FORMAT_NV12:
 	case DRM_FORMAT_NV21:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV61:
 		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,
@@ -1109,27 +1113,29 @@ fill_tiles_yuv_planar(const struct yuv_info *yuv,
 		      unsigned int height, unsigned int stride)
 {
 	unsigned int cs = yuv->chroma_stride;
-	unsigned int i, j;
-
-	for (j = 0; j < height; j+=2) {
-		unsigned char *y1p = y_mem + j * stride;
-		unsigned char *y2p = y1p + stride;
-		unsigned char *up = u_mem + (j/2) * stride * cs / 2;
-		unsigned char *vp = v_mem + (j/2) * stride * cs / 2;
+	unsigned int xsub = yuv->xsub;
+	unsigned int ysub = yuv->ysub;
+	unsigned int x;
+	unsigned int y;
 
-		for (i = 0; i < width; i+=2) {
-			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]);
+	for (y = 0; y < height; ++y) {
+		for (x = 0; x < width; ++x) {
+			div_t d = div(x+y, width);
+			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
+				       + 0x000a1120 * (d.rem >> 6);
+			struct color_yuv color =
+				MAKE_YUV_601((rgb32 >> 16) & 0xff,
+					     (rgb32 >> 8) & 0xff, rgb32 & 0xff);
 
-			*(y2p++) = *(y1p++) = y;
-			*(y2p++) = *(y1p++) = y;
+			y_mem[x] = color.y;
+			u_mem[x/xsub*cs] = color.u;
+			v_mem[x/xsub*cs] = color.v;
+		}
 
-			*up = (rgbp[BLUE] - y) * 0.565 + 128;
-			*vp = (rgbp[RED] - y) * 0.713 + 128;
-			up += cs;
-			vp += cs;
+		y_mem += stride;
+		if ((y + 1) % ysub == 0) {
+			u_mem += stride * cs / xsub;
+			v_mem += stride * cs / xsub;
 		}
 	}
 }
@@ -1222,6 +1228,8 @@ fill_tiles(const struct format_info *info, void *planes[3], unsigned int width,
 
 	case DRM_FORMAT_NV12:
 	case DRM_FORMAT_NV21:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV61:
 		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,
@@ -1371,6 +1379,8 @@ create_test_buffer(struct kms_driver *kms, unsigned int format,
 
 	case DRM_FORMAT_NV12:
 	case DRM_FORMAT_NV21:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV61:
 		pitches[0] = width;
 		offsets[0] = 0;
 		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
-- 
1.7.8.6

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

* [PATCH 5/7] modetest: Add test pattern support for missing RGB formats
  2012-07-20 12:50 [PATCH 0/7] modetest cleanup and enhancements Laurent Pinchart
                   ` (4 preceding siblings ...)
  2012-07-20 12:50 ` [PATCH 4/7] modetest: Add test pattern support for missing planar " Laurent Pinchart
@ 2012-07-20 12:50 ` Laurent Pinchart
  2012-07-20 12:50 ` [PATCH 6/7] modetest: Move connector and plane parsing to separate functions Laurent Pinchart
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2012-07-20 12:50 UTC (permalink / raw)
  To: dri-devel

Implement tiles and SMPTE test pattern generation for the RGB565,
BGR888, RGB888, ARGB8888, BGRA8888 and BGRX8888 formats.

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

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index bdb74ae..2b3ffbc 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -637,10 +637,18 @@ static const struct format_info format_info[] = {
 	{ DRM_FORMAT_NV61, "NV61", MAKE_YUV_INFO(YUV_YCrCb, 2, 1, 2) },
 	/* YUV planar */
 	{ DRM_FORMAT_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) },
-	/* RGB */
+	/* RGB16 */
+	{ DRM_FORMAT_ARGB1555, "AR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 1, 15) },
 	{ DRM_FORMAT_XRGB1555, "XR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 0, 0) },
+	{ DRM_FORMAT_RGB565, "RG16", MAKE_RGB_INFO(5, 11, 6, 5, 5, 0, 0, 0) },
+	/* RGB24 */
+	{ DRM_FORMAT_BGR888, "BG24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) },
+	{ DRM_FORMAT_RGB888, "RG24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
+	/* RGB32 */
+	{ DRM_FORMAT_ARGB8888, "AR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 8, 24) },
+	{ DRM_FORMAT_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, 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) },
+	{ DRM_FORMAT_BGRX8888, "BX24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 0, 0) },
 };
 
 unsigned int format_fourcc(const char *name)
@@ -691,6 +699,9 @@ struct color_yuv {
 	 (((b) >> (8 - (rgb)->blue.length)) << (rgb)->blue.offset) | \
 	 (((a) >> (8 - (rgb)->alpha.length)) << (rgb)->alpha.offset))
 
+#define MAKE_RGB24(rgb, r, g, b) \
+	{ .value = MAKE_RGBA(rgb, r, g, b, 0) }
+
 static void
 fill_smpte_yuv_planar(const struct yuv_info *yuv,
 		      unsigned char *y_mem, unsigned char *u_mem,
@@ -958,6 +969,69 @@ fill_smpte_rgb16(const struct rgb_info *rgb, unsigned char *mem,
 }
 
 static void
+fill_smpte_rgb24(const struct rgb_info *rgb, void *mem,
+		 unsigned int width, unsigned int height, unsigned int stride)
+{
+	const struct color_rgb24 colors_top[] = {
+		MAKE_RGB24(rgb, 192, 192, 192),	/* grey */
+		MAKE_RGB24(rgb, 192, 192, 0),	/* yellow */
+		MAKE_RGB24(rgb, 0, 192, 192),	/* cyan */
+		MAKE_RGB24(rgb, 0, 192, 0),	/* green */
+		MAKE_RGB24(rgb, 192, 0, 192),	/* magenta */
+		MAKE_RGB24(rgb, 192, 0, 0),	/* red */
+		MAKE_RGB24(rgb, 0, 0, 192),	/* blue */
+	};
+	const struct color_rgb24 colors_middle[] = {
+		MAKE_RGB24(rgb, 0, 0, 192),	/* blue */
+		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
+		MAKE_RGB24(rgb, 192, 0, 192),	/* magenta */
+		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
+		MAKE_RGB24(rgb, 0, 192, 192),	/* cyan */
+		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
+		MAKE_RGB24(rgb, 192, 192, 192),	/* grey */
+	};
+	const struct color_rgb24 colors_bottom[] = {
+		MAKE_RGB24(rgb, 0, 33, 76),	/* in-phase */
+		MAKE_RGB24(rgb, 255, 255, 255),	/* super white */
+		MAKE_RGB24(rgb, 50, 0, 106),	/* quadrature */
+		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
+		MAKE_RGB24(rgb, 9, 9, 9),	/* 3.5% */
+		MAKE_RGB24(rgb, 19, 19, 19),	/* 7.5% */
+		MAKE_RGB24(rgb, 29, 29, 29),	/* 11.5% */
+		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
+	};
+	unsigned int x;
+	unsigned int y;
+
+	for (y = 0; y < height * 6 / 9; ++y) {
+		for (x = 0; x < width; ++x)
+			((struct color_rgb24 *)mem)[x] =
+				colors_top[x * 7 / width];
+		mem += stride;
+	}
+
+	for (; y < height * 7 / 9; ++y) {
+		for (x = 0; x < width; ++x)
+			((struct color_rgb24 *)mem)[x] =
+				colors_middle[x * 7 / width];
+		mem += stride;
+	}
+
+	for (; y < height; ++y) {
+		for (x = 0; x < width * 5 / 7; ++x)
+			((struct color_rgb24 *)mem)[x] =
+				colors_bottom[x * 4 / (width * 5 / 7)];
+		for (; x < width * 6 / 7; ++x)
+			((struct color_rgb24 *)mem)[x] =
+				colors_bottom[(x - width * 5 / 7) * 3
+					      / (width / 7) + 4];
+		for (; x < width; ++x)
+			((struct color_rgb24 *)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)
 {
@@ -1045,11 +1119,19 @@ fill_smpte(const struct format_info *info, void *planes[3], unsigned int width,
 		return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1],
 					     planes[2], width, height, stride);
 
+	case DRM_FORMAT_RGB565:
 	case DRM_FORMAT_ARGB1555:
 	case DRM_FORMAT_XRGB1555:
 		return fill_smpte_rgb16(&info->rgb, planes[0],
 					width, height, stride);
+	case DRM_FORMAT_BGR888:
+	case DRM_FORMAT_RGB888:
+		return fill_smpte_rgb24(&info->rgb, planes[0],
+					width, height, stride);
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_BGRA8888:
 	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_BGRX8888:
 		return fill_smpte_rgb32(&info->rgb, planes[0],
 					width, height, stride);
 	}
@@ -1176,20 +1258,42 @@ static void
 fill_tiles_rgb16(const struct rgb_info *rgb, unsigned char *mem,
 		 unsigned int width, unsigned int height, unsigned int stride)
 {
-	unsigned int i, j;
+	unsigned int x, y;
 
-	for (j = 0; j < height; j++) {
-		uint16_t *ptr = (uint16_t*)((char*)mem + j * stride);
-		for (i = 0; i < width; i++) {
-			div_t d = div(i+j, width);
-			uint32_t rgb = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6);
-			unsigned char *rgbp = (unsigned char *)&rgb;
-
-			*(ptr++) = 0x8000 |
-					(rgbp[RED] >> 3) << 10 |
-					(rgbp[GREEN] >> 3) << 5 |
-					(rgbp[BLUE] >> 3);
+	for (y = 0; y < height; ++y) {
+		for (x = 0; x < width; ++x) {
+			div_t d = div(x+y, width);
+			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
+				       + 0x000a1120 * (d.rem >> 6);
+			uint16_t color =
+				MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
+					  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
+					  255);
+
+			((uint16_t *)mem)[x] = color;
 		}
+		mem += stride;
+	}
+}
+
+static void
+fill_tiles_rgb24(const struct rgb_info *rgb, unsigned char *mem,
+		 unsigned int width, unsigned int height, unsigned int stride)
+{
+	unsigned int x, y;
+
+	for (y = 0; y < height; ++y) {
+		for (x = 0; x < width; ++x) {
+			div_t d = div(x+y, width);
+			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
+				       + 0x000a1120 * (d.rem >> 6);
+			struct color_rgb24 color =
+				MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff,
+					   (rgb32 >> 8) & 0xff, rgb32 & 0xff);
+
+			((struct color_rgb24 *)mem)[x] = color;
+		}
+		mem += stride;
 	}
 }
 
@@ -1197,19 +1301,25 @@ static void
 fill_tiles_rgb32(const struct rgb_info *rgb, unsigned char *mem,
 		 unsigned int width, unsigned int height, unsigned int stride)
 {
-	unsigned int i, j;
+	unsigned char *mem_base = mem;
+	unsigned int x, y;
 
-	for (j = 0; j < height; j++) {
-		uint32_t *ptr = (uint32_t*)((char*)mem + j * stride);
-		for (i = 0; i < width; i++) {
-			div_t d = div(i, width);
-			ptr[i] =
-				0x00130502 * (d.quot >> 6) +
-				0x000a1120 * (d.rem >> 6);
+	for (y = 0; y < height; ++y) {
+		for (x = 0; x < width; ++x) {
+			div_t d = div(x+y, width);
+			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
+				       + 0x000a1120 * (d.rem >> 6);
+			uint32_t color =
+				MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
+					  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
+					  255);
+
+			((uint32_t *)mem)[x] = color;
 		}
+		mem += stride;
 	}
 
-	make_pwetty(mem, width, height, stride);
+	make_pwetty(mem_base, width, height, stride);
 }
 
 static void
@@ -1239,11 +1349,19 @@ fill_tiles(const struct format_info *info, void *planes[3], unsigned int width,
 		return fill_tiles_yuv_planar(&info->yuv, planes[0], planes[1],
 					     planes[2], width, height, stride);
 
+	case DRM_FORMAT_RGB565:
 	case DRM_FORMAT_ARGB1555:
 	case DRM_FORMAT_XRGB1555:
 		return fill_tiles_rgb16(&info->rgb, planes[0],
 					width, height, stride);
+	case DRM_FORMAT_BGR888:
+	case DRM_FORMAT_RGB888:
+		return fill_tiles_rgb24(&info->rgb, planes[0],
+					width, height, stride);
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_BGRA8888:
 	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_BGRX8888:
 		return fill_tiles_rgb32(&info->rgb, planes[0],
 					width, height, stride);
 	}
@@ -1418,6 +1536,7 @@ create_test_buffer(struct kms_driver *kms, unsigned int format,
 		planes[0] = virtual;
 		break;
 
+	case DRM_FORMAT_BGR888:
 	case DRM_FORMAT_RGB888:
 		pitches[0] = width * 3;
 		offsets[0] = 0;
@@ -1426,7 +1545,10 @@ create_test_buffer(struct kms_driver *kms, unsigned int format,
 		planes[0] = virtual;
 		break;
 
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_BGRA8888:
 	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_BGRX8888:
 		pitches[0] = width * 4;
 		offsets[0] = 0;
 		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
-- 
1.7.8.6

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

* [PATCH 6/7] modetest: Move connector and plane parsing to separate functions
  2012-07-20 12:50 [PATCH 0/7] modetest cleanup and enhancements Laurent Pinchart
                   ` (5 preceding siblings ...)
  2012-07-20 12:50 ` [PATCH 5/7] modetest: Add test pattern support for missing RGB formats Laurent Pinchart
@ 2012-07-20 12:50 ` 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
  8 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2012-07-20 12:50 UTC (permalink / raw)
  To: dri-devel

This will make it easier to add additional parameters to the connector
and plane arguments.

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

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index 2b3ffbc..3e0af17 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -503,6 +503,7 @@ struct plane {
 	uint32_t w, h;
 	unsigned int fb_id;
 	char format_str[5]; /* need to leave room for terminating \0 */
+	unsigned int fourcc;
 };
 
 static void
@@ -1602,16 +1603,10 @@ set_plane(struct kms_driver *kms, struct connector *c, struct plane *p)
 	uint32_t handles[4], pitches[4], offsets[4] = {0}; /* we only use [0] */
 	uint32_t plane_id = 0;
 	struct kms_bo *plane_bo;
-	uint32_t plane_flags = 0, format;
+	uint32_t plane_flags = 0;
 	int ret, crtc_x, crtc_y, crtc_w, crtc_h;
 	unsigned int i;
 
-	format = format_fourcc(p->format_str);
-	if (format == 0) {
-		fprintf(stderr, "Unknown format: %s\n", p->format_str);
-		return -1;
-	}
-
 	/* find an unused plane which can be connected to our crtc */
 	plane_resources = drmModeGetPlaneResources(fd);
 	if (!plane_resources) {
@@ -1642,13 +1637,13 @@ set_plane(struct kms_driver *kms, struct connector *c, struct plane *p)
 		return -1;
 	}
 
-	plane_bo = create_test_buffer(kms, format, p->w, p->h, handles,
+	plane_bo = create_test_buffer(kms, p->fourcc, p->w, p->h, handles,
 				      pitches, offsets, PATTERN_TILES);
 	if (plane_bo == NULL)
 		return -1;
 
 	/* just use single plane format for now.. */
-	if (drmModeAddFB2(fd, p->w, p->h, format,
+	if (drmModeAddFB2(fd, p->w, p->h, p->fourcc,
 			handles, pitches, offsets, &p->fb_id, plane_flags)) {
 		fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
 		return -1;
@@ -1825,6 +1820,36 @@ extern char *optarg;
 extern int optind, opterr, optopt;
 static char optstr[] = "ecpmfs:P:v";
 
+static int parse_connector(struct connector *c, const char *arg)
+{
+	c->crtc = -1;
+
+	if (sscanf(arg, "%d:%64s", &c->id, &c->mode_str) == 2)
+		return 0;
+
+	if (sscanf(arg, "%d@%d:%64s", &c->id, &c->crtc, &c->mode_str) == 3)
+		return 0;
+
+	return -1;
+}
+
+static int parse_plane(struct plane *p, const char *arg)
+{
+	strcpy(p->format_str, "XR24");
+
+	if (sscanf(arg, "%d:%dx%d@%4s", &p->con_id, &p->w, &p->h, &p->format_str) != 4 &&
+	    sscanf(arg, "%d:%dx%d", &p->con_id, &p->w, &p->h) != 3)
+		return -1;
+
+	p->fourcc = format_fourcc(p->format_str);
+	if (p->fourcc == 0) {
+		fprintf(stderr, "unknown format %s\n", p->format_str);
+		return -1;
+	}
+
+	return 0;
+}
+
 void usage(char *name)
 {
 	fprintf(stderr, "usage: %s [-ecpmf]\n", name);
@@ -1899,28 +1924,12 @@ int main(int argc, char **argv)
 			test_vsync = 1;
 			break;
 		case 's':
-			con_args[count].crtc = -1;
-			if (sscanf(optarg, "%d:%64s",
-				   &con_args[count].id,
-				   con_args[count].mode_str) != 2 &&
-			    sscanf(optarg, "%d@%d:%64s",
-				   &con_args[count].id,
-				   &con_args[count].crtc,
-				   con_args[count].mode_str) != 3)
+			if (parse_connector(&con_args[count], optarg) < 0)
 				usage(argv[0]);
 			count++;				      
 			break;
 		case 'P':
-			strcpy(plane_args[plane_count].format_str, "XR24");
-			if (sscanf(optarg, "%d:%dx%d@%4s",
-					&plane_args[plane_count].con_id,
-					&plane_args[plane_count].w,
-					&plane_args[plane_count].h,
-					plane_args[plane_count].format_str) != 4 &&
-				sscanf(optarg, "%d:%dx%d",
-					&plane_args[plane_count].con_id,
-					&plane_args[plane_count].w,
-					&plane_args[plane_count].h) != 3)
+			if (parse_plane(&plane_args[plane_count], optarg) < 0)
 				usage(argv[0]);
 			plane_count++;
 			break;
-- 
1.7.8.6

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

* [PATCH 7/7] modetest: Make frame buffer format configurable on the command line
  2012-07-20 12:50 [PATCH 0/7] modetest cleanup and enhancements Laurent Pinchart
                   ` (6 preceding siblings ...)
  2012-07-20 12:50 ` [PATCH 6/7] modetest: Move connector and plane parsing to separate functions Laurent Pinchart
@ 2012-07-20 12:50 ` Laurent Pinchart
  2012-07-20 13:43 ` [PATCH 0/7] modetest cleanup and enhancements Rob Clark
  8 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2012-07-20 12:50 UTC (permalink / raw)
  To: dri-devel

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

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index 3e0af17..3ed39b7 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -488,6 +488,8 @@ static void dump_planes(void)
 struct connector {
 	uint32_t id;
 	char mode_str[64];
+	char format_str[5];
+	unsigned int fourcc;
 	drmModeModeInfo *mode;
 	drmModeEncoder *encoder;
 	int crtc;
@@ -1696,12 +1698,13 @@ set_mode(struct connector *c, int count, struct plane *p, int plane_count,
 		return;
 	}
 
-	bo = create_test_buffer(kms, DRM_FORMAT_XRGB8888, width, height, handles,
+	bo = create_test_buffer(kms, c->fourcc, width, height, handles,
 				pitches, offsets, PATTERN_SMPTE);
 	if (bo == NULL)
 		return;
 
-	ret = drmModeAddFB(fd, width, height, 24, 32, pitches[0], handles[0], &fb_id);
+	ret = drmModeAddFB2(fd, width, height, c->fourcc,
+			    handles, pitches, offsets, &fb_id, 0);
 	if (ret) {
 		fprintf(stderr, "failed to add fb (%ux%u): %s\n",
 			width, height, strerror(errno));
@@ -1713,8 +1716,8 @@ set_mode(struct connector *c, int count, struct plane *p, int plane_count,
 		if (c[i].mode == NULL)
 			continue;
 
-		printf("setting mode %s on connector %d, crtc %d\n",
-		       c[i].mode_str, c[i].id, c[i].crtc);
+		printf("setting mode %s@%s on connector %d, crtc %d\n",
+		       c[i].mode_str, c[i].format_str, c[i].id, c[i].crtc);
 
 		ret = drmModeSetCrtc(fd, c[i].crtc, fb_id, x, 0,
 				     &c[i].id, 1, c[i].mode);
@@ -1739,13 +1742,13 @@ set_mode(struct connector *c, int count, struct plane *p, int plane_count,
 	if (!page_flip)
 		return;
 	
-	other_bo = create_test_buffer(kms, DRM_FORMAT_XRGB8888, width, height, handles,
+	other_bo = create_test_buffer(kms, c->fourcc, width, height, handles,
 				      pitches, offsets, PATTERN_PLAIN);
 	if (other_bo == NULL)
 		return;
 
-	ret = drmModeAddFB(fd, width, height, 32, 32, pitches[0], handles[0],
-			   &other_fb_id);
+	ret = drmModeAddFB2(fd, width, height, c->fourcc, handles, pitches, offsets,
+			    &other_fb_id, 0);
 	if (ret) {
 		fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
 		return;
@@ -1820,17 +1823,44 @@ extern char *optarg;
 extern int optind, opterr, optopt;
 static char optstr[] = "ecpmfs:P:v";
 
+#define min(a, b)	((a) < (b) ? (a) : (b))
+
 static int parse_connector(struct connector *c, const char *arg)
 {
+	unsigned int len;
+	const char *p;
+	char *endp;
+
 	c->crtc = -1;
+	strcpy(c->format_str, "XR24");
 
-	if (sscanf(arg, "%d:%64s", &c->id, &c->mode_str) == 2)
-		return 0;
+	c->id = strtoul(arg, &endp, 10);
+	if (*endp == '@') {
+		arg = endp + 1;
+		c->crtc = strtoul(arg, &endp, 10);
+	}
+	if (*endp != ':')
+		return -1;
 
-	if (sscanf(arg, "%d@%d:%64s", &c->id, &c->crtc, &c->mode_str) == 3)
-		return 0;
+	arg = endp + 1;
 
-	return -1;
+	p = strchrnul(arg, '@');
+	len = min(sizeof c->mode_str - 1, p - arg);
+	strncpy(c->mode_str, arg, len);
+	c->mode_str[len] = '\0';
+
+	if (*p == '@') {
+		strncpy(c->format_str, p + 1, 4);
+		c->format_str[4] = '\0';
+
+		c->fourcc = format_fourcc(p + 1);
+		if (c->fourcc == 0)  {
+			fprintf(stderr, "unknown format %s\n", c->format_str);
+			return -1;
+		}
+	}
+
+	return 0;
 }
 
 static int parse_plane(struct plane *p, const char *arg)
@@ -1859,10 +1889,8 @@ void usage(char *name)
 	fprintf(stderr, "\t-m\tlist modes\n");
 	fprintf(stderr, "\t-f\tlist framebuffers\n");
 	fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
-	fprintf(stderr, "\t-s <connector_id>:<mode>\tset a mode\n");
-	fprintf(stderr, "\t-s <connector_id>@<crtc_id>:<mode>\tset a mode\n");
-	fprintf(stderr, "\t-P <connector_id>:<w>x<h>\tset a plane\n");
-	fprintf(stderr, "\t-P <connector_id>:<w>x<h>@<format>\tset a plane\n");
+	fprintf(stderr, "\t-s <connector_id>[@<crtc_id>]:<mode>[@<format>]\tset a mode\n");
+	fprintf(stderr, "\t-P <connector_id>:<w>x<h>[@<format>]\tset a plane\n");
 	fprintf(stderr, "\n\tDefault is to dump all info.\n");
 	exit(0);
 }
-- 
1.7.8.6

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

* Re: [PATCH 0/7] modetest cleanup and enhancements
  2012-07-20 12:50 [PATCH 0/7] modetest cleanup and enhancements Laurent Pinchart
                   ` (7 preceding siblings ...)
  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 ` Rob Clark
  2012-07-20 14:37   ` [PATCH] modeset: Split buffer allocation to a separate file Laurent Pinchart
  8 siblings, 1 reply; 14+ messages in thread
From: Rob Clark @ 2012-07-20 13:43 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel

On Fri, Jul 20, 2012 at 7:50 AM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> Hi everybody,
>
> I've enhanced the modetest utility to test various features of the SH Mobile
> LCDC DRM driver. Here are the corresponding patches. They mostly touch buffer
> allocation cleanup (1/7), adding test patterns for different formats (2/7 to
> 5/7) and making frame buffer format configurable on the command line (6/7 and
> 7/7).

Cool, thanks.. although one small comment, maybe modetest is getting
big enough that it might be a good idea to split the allocation and
test pattern stuff into a separate file?  It is useful to point people
at modetest when they want to know about how to use kms, so perhaps
splitting the mode from buffer stuff is not such a bad idea.

BR,
-R

> Laurent Pinchart (7):
>   modetest: Unify buffer allocation
>   modetest: Add SMPTE test pattern
>   modetest: Add test pattern support for missing packed YUV formats
>   modetest: Add test pattern support for missing planar YUV formats
>   modetest: Add test pattern support for missing RGB formats
>   modetest: Move connector and plane parsing to separate functions
>   modetest: Make frame buffer format configurable on the command line
>
>  tests/modetest/modetest.c | 1254 +++++++++++++++++++++++++++++++++++----------
>  1 files changed, 988 insertions(+), 266 deletions(-)
>
> --
> Regards,
>
> Laurent Pinchart
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH] modeset: Split buffer allocation to a separate file
  2012-07-20 13:43 ` [PATCH 0/7] modetest cleanup and enhancements Rob Clark
@ 2012-07-20 14:37   ` Laurent Pinchart
  2012-07-20 15:34     ` Rob Clark
  0 siblings, 1 reply; 14+ messages in thread
From: Laurent Pinchart @ 2012-07-20 14:37 UTC (permalink / raw)
  To: dri-devel; +Cc: Rob Clark

As the modeset test application is often referred to as an example of
the KMS API usage, move test pattern generation and buffer allocation to
a separate file to keep it simple and clear.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 tests/modetest/Makefile.am |    2 +-
 tests/modetest/buffers.c   | 1021 ++++++++++++++++++++++++++++++++++++++++++++
 tests/modetest/buffers.h   |   45 ++
 tests/modetest/modetest.c  |  987 +------------------------------------------
 4 files changed, 1068 insertions(+), 987 deletions(-)
 create mode 100644 tests/modetest/buffers.c
 create mode 100644 tests/modetest/buffers.h

Hi Rob,

Something like this ?

diff --git a/tests/modetest/Makefile.am b/tests/modetest/Makefile.am
index 2191242..35754a2 100644
--- a/tests/modetest/Makefile.am
+++ b/tests/modetest/Makefile.am
@@ -8,7 +8,7 @@ noinst_PROGRAMS = \
 	modetest
 
 modetest_SOURCES = \
-	modetest.c
+	buffers.c modetest.c
 modetest_LDADD = \
 	$(top_builddir)/libdrm.la \
 	$(top_builddir)/libkms/libkms.la \
diff --git a/tests/modetest/buffers.c b/tests/modetest/buffers.c
new file mode 100644
index 0000000..5086381
--- /dev/null
+++ b/tests/modetest/buffers.c
@@ -0,0 +1,1021 @@
+/*
+ * DRM based mode setting test program
+ * Copyright 2008 Tungsten Graphics
+ *   Jakob Bornecrantz <jakob@tungstengraphics.com>
+ * Copyright 2008 Intel Corporation
+ *   Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * 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 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 "config.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "drm_fourcc.h"
+#include "libkms.h"
+
+#include "buffers.h"
+
+#ifdef HAVE_CAIRO
+#include <math.h>
+#include <cairo.h>
+#endif
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+/* -----------------------------------------------------------------------------
+ * 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[] = {
+	/* YUV packed */
+	{ DRM_FORMAT_UYVY, "UYVY", MAKE_YUV_INFO(YUV_YCbCr | YUV_CY, 2, 2, 2) },
+	{ DRM_FORMAT_VYUY, "VYUY", MAKE_YUV_INFO(YUV_YCrCb | YUV_CY, 2, 2, 2) },
+	{ DRM_FORMAT_YUYV, "YUYV", MAKE_YUV_INFO(YUV_YCbCr | YUV_YC, 2, 2, 2) },
+	{ DRM_FORMAT_YVYU, "YVYU", MAKE_YUV_INFO(YUV_YCrCb | YUV_YC, 2, 2, 2) },
+	/* YUV semi-planar */
+	{ 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_NV16, "NV16", MAKE_YUV_INFO(YUV_YCbCr, 2, 1, 2) },
+	{ DRM_FORMAT_NV61, "NV61", MAKE_YUV_INFO(YUV_YCrCb, 2, 1, 2) },
+	/* YUV planar */
+	{ DRM_FORMAT_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) },
+	/* RGB16 */
+	{ DRM_FORMAT_ARGB1555, "AR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 1, 15) },
+	{ DRM_FORMAT_XRGB1555, "XR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 0, 0) },
+	{ DRM_FORMAT_RGB565, "RG16", MAKE_RGB_INFO(5, 11, 6, 5, 5, 0, 0, 0) },
+	/* RGB24 */
+	{ DRM_FORMAT_BGR888, "BG24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) },
+	{ DRM_FORMAT_RGB888, "RG24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
+	/* RGB32 */
+	{ DRM_FORMAT_ARGB8888, "AR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 8, 24) },
+	{ DRM_FORMAT_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, 0) },
+	{ DRM_FORMAT_XRGB8888, "XR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
+	{ DRM_FORMAT_BGRX8888, "BX24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 0, 0) },
+};
+
+unsigned int format_fourcc(const char *name)
+{
+	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
+ */
+
+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))
+
+#define MAKE_RGB24(rgb, r, g, b) \
+	{ .value = MAKE_RGBA(rgb, r, g, b, 0) }
+
+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 */
+	};
+	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;
+	}
+
+	for (; y < height * 7 / 9; ++y) {
+		for (x = 0; x < width; ++x)
+			y_mem[x] = colors_middle[x * 7 / width].y;
+		y_mem += stride;
+	}
+
+	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;
+	}
+
+	/* 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;
+	}
+
+	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_rgb24(const struct rgb_info *rgb, void *mem,
+		 unsigned int width, unsigned int height, unsigned int stride)
+{
+	const struct color_rgb24 colors_top[] = {
+		MAKE_RGB24(rgb, 192, 192, 192),	/* grey */
+		MAKE_RGB24(rgb, 192, 192, 0),	/* yellow */
+		MAKE_RGB24(rgb, 0, 192, 192),	/* cyan */
+		MAKE_RGB24(rgb, 0, 192, 0),	/* green */
+		MAKE_RGB24(rgb, 192, 0, 192),	/* magenta */
+		MAKE_RGB24(rgb, 192, 0, 0),	/* red */
+		MAKE_RGB24(rgb, 0, 0, 192),	/* blue */
+	};
+	const struct color_rgb24 colors_middle[] = {
+		MAKE_RGB24(rgb, 0, 0, 192),	/* blue */
+		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
+		MAKE_RGB24(rgb, 192, 0, 192),	/* magenta */
+		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
+		MAKE_RGB24(rgb, 0, 192, 192),	/* cyan */
+		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
+		MAKE_RGB24(rgb, 192, 192, 192),	/* grey */
+	};
+	const struct color_rgb24 colors_bottom[] = {
+		MAKE_RGB24(rgb, 0, 33, 76),	/* in-phase */
+		MAKE_RGB24(rgb, 255, 255, 255),	/* super white */
+		MAKE_RGB24(rgb, 50, 0, 106),	/* quadrature */
+		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
+		MAKE_RGB24(rgb, 9, 9, 9),	/* 3.5% */
+		MAKE_RGB24(rgb, 19, 19, 19),	/* 7.5% */
+		MAKE_RGB24(rgb, 29, 29, 29),	/* 11.5% */
+		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
+	};
+	unsigned int x;
+	unsigned int y;
+
+	for (y = 0; y < height * 6 / 9; ++y) {
+		for (x = 0; x < width; ++x)
+			((struct color_rgb24 *)mem)[x] =
+				colors_top[x * 7 / width];
+		mem += stride;
+	}
+
+	for (; y < height * 7 / 9; ++y) {
+		for (x = 0; x < width; ++x)
+			((struct color_rgb24 *)mem)[x] =
+				colors_middle[x * 7 / width];
+		mem += stride;
+	}
+
+	for (; y < height; ++y) {
+		for (x = 0; x < width * 5 / 7; ++x)
+			((struct color_rgb24 *)mem)[x] =
+				colors_bottom[x * 4 / (width * 5 / 7)];
+		for (; x < width * 6 / 7; ++x)
+			((struct color_rgb24 *)mem)[x] =
+				colors_bottom[(x - width * 5 / 7) * 3
+					      / (width / 7) + 4];
+		for (; x < width; ++x)
+			((struct color_rgb24 *)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_UYVY:
+	case DRM_FORMAT_VYUY:
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
+		return fill_smpte_yuv_packed(&info->yuv, planes[0], width,
+					     height, stride);
+
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV21:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV61:
+		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_RGB565:
+	case DRM_FORMAT_ARGB1555:
+	case DRM_FORMAT_XRGB1555:
+		return fill_smpte_rgb16(&info->rgb, planes[0],
+					width, height, stride);
+	case DRM_FORMAT_BGR888:
+	case DRM_FORMAT_RGB888:
+		return fill_smpte_rgb24(&info->rgb, planes[0],
+					width, height, stride);
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_BGRA8888:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_BGRX8888:
+		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
+	cairo_surface_t *surface;
+	cairo_t *cr;
+	int x, y;
+
+	surface = cairo_image_surface_create_for_data(data,
+						      CAIRO_FORMAT_ARGB32,
+						      width, height,
+						      stride);
+	cr = cairo_create(surface);
+	cairo_surface_destroy(surface);
+
+	cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
+	for (x = 0; x < width; x += 250)
+		for (y = 0; y < height; y += 250) {
+			char buf[64];
+
+			cairo_move_to(cr, x, y - 20);
+			cairo_line_to(cr, x, y + 20);
+			cairo_move_to(cr, x - 20, y);
+			cairo_line_to(cr, x + 20, y);
+			cairo_new_sub_path(cr);
+			cairo_arc(cr, x, y, 10, 0, M_PI * 2);
+			cairo_set_line_width(cr, 4);
+			cairo_set_source_rgb(cr, 0, 0, 0);
+			cairo_stroke_preserve(cr);
+			cairo_set_source_rgb(cr, 1, 1, 1);
+			cairo_set_line_width(cr, 2);
+			cairo_stroke(cr);
+
+			snprintf(buf, sizeof buf, "%d, %d", x, y);
+			cairo_move_to(cr, x + 20, y + 20);
+			cairo_text_path(cr, buf);
+			cairo_set_source_rgb(cr, 0, 0, 0);
+			cairo_stroke_preserve(cr);
+			cairo_set_source_rgb(cr, 1, 1, 1);
+			cairo_fill(cr);
+		}
+
+	cairo_destroy(cr);
+#endif
+}
+
+static void
+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)
+{
+	unsigned int cs = yuv->chroma_stride;
+	unsigned int xsub = yuv->xsub;
+	unsigned int ysub = yuv->ysub;
+	unsigned int x;
+	unsigned int y;
+
+	for (y = 0; y < height; ++y) {
+		for (x = 0; x < width; ++x) {
+			div_t d = div(x+y, width);
+			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
+				       + 0x000a1120 * (d.rem >> 6);
+			struct color_yuv color =
+				MAKE_YUV_601((rgb32 >> 16) & 0xff,
+					     (rgb32 >> 8) & 0xff, rgb32 & 0xff);
+
+			y_mem[x] = color.y;
+			u_mem[x/xsub*cs] = color.u;
+			v_mem[x/xsub*cs] = color.v;
+		}
+
+		y_mem += stride;
+		if ((y + 1) % ysub == 0) {
+			u_mem += stride * cs / xsub;
+			v_mem += stride * cs / xsub;
+		}
+	}
+}
+
+static void
+fill_tiles_yuv_packed(const struct yuv_info *yuv, unsigned char *mem,
+		      unsigned int width, unsigned int height,
+		      unsigned int stride)
+{
+	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;
+
+	for (y = 0; y < height; ++y) {
+		for (x = 0; x < width; x += 2) {
+			div_t d = div(x+y, width);
+			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
+				       + 0x000a1120 * (d.rem >> 6);
+			struct color_yuv color =
+				MAKE_YUV_601((rgb32 >> 16) & 0xff,
+					     (rgb32 >> 8) & 0xff, rgb32 & 0xff);
+
+			y_mem[2*x] = color.y;
+			c_mem[2*x+u] = color.u;
+			y_mem[2*x+2] = color.y;
+			c_mem[2*x+v] = color.v;
+		}
+
+		y_mem += stride;
+		c_mem += stride;
+	}
+}
+
+static void
+fill_tiles_rgb16(const struct rgb_info *rgb, unsigned char *mem,
+		 unsigned int width, unsigned int height, unsigned int stride)
+{
+	unsigned int x, y;
+
+	for (y = 0; y < height; ++y) {
+		for (x = 0; x < width; ++x) {
+			div_t d = div(x+y, width);
+			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
+				       + 0x000a1120 * (d.rem >> 6);
+			uint16_t color =
+				MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
+					  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
+					  255);
+
+			((uint16_t *)mem)[x] = color;
+		}
+		mem += stride;
+	}
+}
+
+static void
+fill_tiles_rgb24(const struct rgb_info *rgb, unsigned char *mem,
+		 unsigned int width, unsigned int height, unsigned int stride)
+{
+	unsigned int x, y;
+
+	for (y = 0; y < height; ++y) {
+		for (x = 0; x < width; ++x) {
+			div_t d = div(x+y, width);
+			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
+				       + 0x000a1120 * (d.rem >> 6);
+			struct color_rgb24 color =
+				MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff,
+					   (rgb32 >> 8) & 0xff, rgb32 & 0xff);
+
+			((struct color_rgb24 *)mem)[x] = color;
+		}
+		mem += stride;
+	}
+}
+
+static void
+fill_tiles_rgb32(const struct rgb_info *rgb, unsigned char *mem,
+		 unsigned int width, unsigned int height, unsigned int stride)
+{
+	unsigned char *mem_base = mem;
+	unsigned int x, y;
+
+	for (y = 0; y < height; ++y) {
+		for (x = 0; x < width; ++x) {
+			div_t d = div(x+y, width);
+			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
+				       + 0x000a1120 * (d.rem >> 6);
+			uint32_t color =
+				MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
+					  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
+					  255);
+
+			((uint32_t *)mem)[x] = color;
+		}
+		mem += stride;
+	}
+
+	make_pwetty(mem_base, 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_UYVY:
+	case DRM_FORMAT_VYUY:
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
+		return fill_tiles_yuv_packed(&info->yuv, planes[0],
+					     width, height, stride);
+
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV21:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV61:
+		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_RGB565:
+	case DRM_FORMAT_ARGB1555:
+	case DRM_FORMAT_XRGB1555:
+		return fill_tiles_rgb16(&info->rgb, planes[0],
+					width, height, stride);
+	case DRM_FORMAT_BGR888:
+	case DRM_FORMAT_RGB888:
+		return fill_tiles_rgb24(&info->rgb, planes[0],
+					width, height, stride);
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_BGRA8888:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_BGRX8888:
+		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_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)
+{
+	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;
+}
+
+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], enum fill_pattern pattern)
+{
+	struct kms_bo *bo;
+	int ret, stride;
+	void *planes[3];
+	void *virtual;
+
+	bo = allocate_buffer(kms, width, height, &pitches[0]);
+	if (!bo)
+		return NULL;
+
+	ret = kms_bo_map(bo, &virtual);
+	if (ret) {
+		fprintf(stderr, "failed to map buffer: %s\n",
+			strerror(-ret));
+		kms_bo_destroy(&bo);
+		return NULL;
+	}
+
+	/* just testing a limited # of formats to test single
+	 * and multi-planar path.. would be nice to add more..
+	 */
+	switch (format) {
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_VYUY:
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
+		pitches[0] = width * 2;
+		offsets[0] = 0;
+		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
+
+		planes[0] = virtual;
+		break;
+
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV21:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV61:
+		pitches[0] = width;
+		offsets[0] = 0;
+		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
+		pitches[1] = width;
+		offsets[1] = width * height;
+		kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]);
+
+		planes[0] = virtual;
+		planes[1] = virtual + offsets[1];
+		break;
+
+	case DRM_FORMAT_YVU420:
+		pitches[0] = width;
+		offsets[0] = 0;
+		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
+		pitches[1] = width / 2;
+		offsets[1] = width * height;
+		kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]);
+		pitches[2] = width / 2;
+		offsets[2] = offsets[1] + (width * height) / 4;
+		kms_bo_get_prop(bo, KMS_HANDLE, &handles[2]);
+
+		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]);
+
+		planes[0] = virtual;
+		break;
+
+	case DRM_FORMAT_BGR888:
+	case DRM_FORMAT_RGB888:
+		pitches[0] = width * 3;
+		offsets[0] = 0;
+		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
+
+		planes[0] = virtual;
+		break;
+
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_BGRA8888:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_BGRX8888:
+		pitches[0] = width * 4;
+		offsets[0] = 0;
+		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
+
+		planes[0] = virtual;
+		break;
+	}
+
+	fill_pattern(format, pattern, planes, width, height, pitches[0]);
+	kms_bo_unmap(bo);
+
+	return bo;
+}
diff --git a/tests/modetest/buffers.h b/tests/modetest/buffers.h
new file mode 100644
index 0000000..2b15ce5
--- /dev/null
+++ b/tests/modetest/buffers.h
@@ -0,0 +1,45 @@
+/*
+ * DRM based mode setting test program
+ * Copyright 2008 Tungsten Graphics
+ *   Jakob Bornecrantz <jakob@tungstengraphics.com>
+ * Copyright 2008 Intel Corporation
+ *   Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * 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 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.
+ */
+
+#ifndef __BUFFERS_H__
+#define __BUFFERS_H__
+
+struct kms_bo;
+struct kms_driver;
+
+enum fill_pattern {
+	PATTERN_TILES = 0,
+	PATTERN_PLAIN = 1,
+	PATTERN_SMPTE = 2,
+};
+
+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], enum fill_pattern pattern);
+
+unsigned int format_fourcc(const char *name);
+
+#endif
diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index 3ed39b7..3e74008 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -55,10 +55,7 @@
 #include "drm_fourcc.h"
 #include "libkms.h"
 
-#ifdef HAVE_CAIRO
-#include <math.h>
-#include <cairo.h>
-#endif
+#include "buffers.h"
 
 drmModeRes *resources;
 int fd, modes;
@@ -584,988 +581,6 @@ connector_find_mode(struct connector *c)
 
 }
 
-/* -----------------------------------------------------------------------------
- * 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[] = {
-	/* YUV packed */
-	{ DRM_FORMAT_UYVY, "UYVY", MAKE_YUV_INFO(YUV_YCbCr | YUV_CY, 2, 2, 2) },
-	{ DRM_FORMAT_VYUY, "VYUY", MAKE_YUV_INFO(YUV_YCrCb | YUV_CY, 2, 2, 2) },
-	{ DRM_FORMAT_YUYV, "YUYV", MAKE_YUV_INFO(YUV_YCbCr | YUV_YC, 2, 2, 2) },
-	{ DRM_FORMAT_YVYU, "YVYU", MAKE_YUV_INFO(YUV_YCrCb | YUV_YC, 2, 2, 2) },
-	/* YUV semi-planar */
-	{ 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_NV16, "NV16", MAKE_YUV_INFO(YUV_YCbCr, 2, 1, 2) },
-	{ DRM_FORMAT_NV61, "NV61", MAKE_YUV_INFO(YUV_YCrCb, 2, 1, 2) },
-	/* YUV planar */
-	{ DRM_FORMAT_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) },
-	/* RGB16 */
-	{ DRM_FORMAT_ARGB1555, "AR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 1, 15) },
-	{ DRM_FORMAT_XRGB1555, "XR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 0, 0) },
-	{ DRM_FORMAT_RGB565, "RG16", MAKE_RGB_INFO(5, 11, 6, 5, 5, 0, 0, 0) },
-	/* RGB24 */
-	{ DRM_FORMAT_BGR888, "BG24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) },
-	{ DRM_FORMAT_RGB888, "RG24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
-	/* RGB32 */
-	{ DRM_FORMAT_ARGB8888, "AR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 8, 24) },
-	{ DRM_FORMAT_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, 0) },
-	{ DRM_FORMAT_XRGB8888, "XR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
-	{ DRM_FORMAT_BGRX8888, "BX24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 0, 0) },
-};
-
-unsigned int format_fourcc(const char *name)
-{
-	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))
-
-#define MAKE_RGB24(rgb, r, g, b) \
-	{ .value = MAKE_RGBA(rgb, r, g, b, 0) }
-
-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 */
-	};
-	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;
-	}
-
-	for (; y < height * 7 / 9; ++y) {
-		for (x = 0; x < width; ++x)
-			y_mem[x] = colors_middle[x * 7 / width].y;
-		y_mem += stride;
-	}
-
-	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;
-	}
-
-	/* 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;
-	}
-
-	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_rgb24(const struct rgb_info *rgb, void *mem,
-		 unsigned int width, unsigned int height, unsigned int stride)
-{
-	const struct color_rgb24 colors_top[] = {
-		MAKE_RGB24(rgb, 192, 192, 192),	/* grey */
-		MAKE_RGB24(rgb, 192, 192, 0),	/* yellow */
-		MAKE_RGB24(rgb, 0, 192, 192),	/* cyan */
-		MAKE_RGB24(rgb, 0, 192, 0),	/* green */
-		MAKE_RGB24(rgb, 192, 0, 192),	/* magenta */
-		MAKE_RGB24(rgb, 192, 0, 0),	/* red */
-		MAKE_RGB24(rgb, 0, 0, 192),	/* blue */
-	};
-	const struct color_rgb24 colors_middle[] = {
-		MAKE_RGB24(rgb, 0, 0, 192),	/* blue */
-		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
-		MAKE_RGB24(rgb, 192, 0, 192),	/* magenta */
-		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
-		MAKE_RGB24(rgb, 0, 192, 192),	/* cyan */
-		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
-		MAKE_RGB24(rgb, 192, 192, 192),	/* grey */
-	};
-	const struct color_rgb24 colors_bottom[] = {
-		MAKE_RGB24(rgb, 0, 33, 76),	/* in-phase */
-		MAKE_RGB24(rgb, 255, 255, 255),	/* super white */
-		MAKE_RGB24(rgb, 50, 0, 106),	/* quadrature */
-		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
-		MAKE_RGB24(rgb, 9, 9, 9),	/* 3.5% */
-		MAKE_RGB24(rgb, 19, 19, 19),	/* 7.5% */
-		MAKE_RGB24(rgb, 29, 29, 29),	/* 11.5% */
-		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
-	};
-	unsigned int x;
-	unsigned int y;
-
-	for (y = 0; y < height * 6 / 9; ++y) {
-		for (x = 0; x < width; ++x)
-			((struct color_rgb24 *)mem)[x] =
-				colors_top[x * 7 / width];
-		mem += stride;
-	}
-
-	for (; y < height * 7 / 9; ++y) {
-		for (x = 0; x < width; ++x)
-			((struct color_rgb24 *)mem)[x] =
-				colors_middle[x * 7 / width];
-		mem += stride;
-	}
-
-	for (; y < height; ++y) {
-		for (x = 0; x < width * 5 / 7; ++x)
-			((struct color_rgb24 *)mem)[x] =
-				colors_bottom[x * 4 / (width * 5 / 7)];
-		for (; x < width * 6 / 7; ++x)
-			((struct color_rgb24 *)mem)[x] =
-				colors_bottom[(x - width * 5 / 7) * 3
-					      / (width / 7) + 4];
-		for (; x < width; ++x)
-			((struct color_rgb24 *)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_UYVY:
-	case DRM_FORMAT_VYUY:
-	case DRM_FORMAT_YUYV:
-	case DRM_FORMAT_YVYU:
-		return fill_smpte_yuv_packed(&info->yuv, planes[0], width,
-					     height, stride);
-
-	case DRM_FORMAT_NV12:
-	case DRM_FORMAT_NV21:
-	case DRM_FORMAT_NV16:
-	case DRM_FORMAT_NV61:
-		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_RGB565:
-	case DRM_FORMAT_ARGB1555:
-	case DRM_FORMAT_XRGB1555:
-		return fill_smpte_rgb16(&info->rgb, planes[0],
-					width, height, stride);
-	case DRM_FORMAT_BGR888:
-	case DRM_FORMAT_RGB888:
-		return fill_smpte_rgb24(&info->rgb, planes[0],
-					width, height, stride);
-	case DRM_FORMAT_ARGB8888:
-	case DRM_FORMAT_BGRA8888:
-	case DRM_FORMAT_XRGB8888:
-	case DRM_FORMAT_BGRX8888:
-		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
-	cairo_surface_t *surface;
-	cairo_t *cr;
-	int x, y;
-
-	surface = cairo_image_surface_create_for_data(data,
-						      CAIRO_FORMAT_ARGB32,
-						      width, height,
-						      stride);
-	cr = cairo_create(surface);
-	cairo_surface_destroy(surface);
-
-	cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
-	for (x = 0; x < width; x += 250)
-		for (y = 0; y < height; y += 250) {
-			char buf[64];
-
-			cairo_move_to(cr, x, y - 20);
-			cairo_line_to(cr, x, y + 20);
-			cairo_move_to(cr, x - 20, y);
-			cairo_line_to(cr, x + 20, y);
-			cairo_new_sub_path(cr);
-			cairo_arc(cr, x, y, 10, 0, M_PI * 2);
-			cairo_set_line_width(cr, 4);
-			cairo_set_source_rgb(cr, 0, 0, 0);
-			cairo_stroke_preserve(cr);
-			cairo_set_source_rgb(cr, 1, 1, 1);
-			cairo_set_line_width(cr, 2);
-			cairo_stroke(cr);
-
-			snprintf(buf, sizeof buf, "%d, %d", x, y);
-			cairo_move_to(cr, x + 20, y + 20);
-			cairo_text_path(cr, buf);
-			cairo_set_source_rgb(cr, 0, 0, 0);
-			cairo_stroke_preserve(cr);
-			cairo_set_source_rgb(cr, 1, 1, 1);
-			cairo_fill(cr);
-		}
-
-	cairo_destroy(cr);
-#endif
-}
-
-static void
-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)
-{
-	unsigned int cs = yuv->chroma_stride;
-	unsigned int xsub = yuv->xsub;
-	unsigned int ysub = yuv->ysub;
-	unsigned int x;
-	unsigned int y;
-
-	for (y = 0; y < height; ++y) {
-		for (x = 0; x < width; ++x) {
-			div_t d = div(x+y, width);
-			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
-				       + 0x000a1120 * (d.rem >> 6);
-			struct color_yuv color =
-				MAKE_YUV_601((rgb32 >> 16) & 0xff,
-					     (rgb32 >> 8) & 0xff, rgb32 & 0xff);
-
-			y_mem[x] = color.y;
-			u_mem[x/xsub*cs] = color.u;
-			v_mem[x/xsub*cs] = color.v;
-		}
-
-		y_mem += stride;
-		if ((y + 1) % ysub == 0) {
-			u_mem += stride * cs / xsub;
-			v_mem += stride * cs / xsub;
-		}
-	}
-}
-
-static void
-fill_tiles_yuv_packed(const struct yuv_info *yuv, unsigned char *mem,
-		      unsigned int width, unsigned int height,
-		      unsigned int stride)
-{
-	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;
-
-	for (y = 0; y < height; ++y) {
-		for (x = 0; x < width; x += 2) {
-			div_t d = div(x+y, width);
-			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
-				       + 0x000a1120 * (d.rem >> 6);
-			struct color_yuv color =
-				MAKE_YUV_601((rgb32 >> 16) & 0xff,
-					     (rgb32 >> 8) & 0xff, rgb32 & 0xff);
-
-			y_mem[2*x] = color.y;
-			c_mem[2*x+u] = color.u;
-			y_mem[2*x+2] = color.y;
-			c_mem[2*x+v] = color.v;
-		}
-
-		y_mem += stride;
-		c_mem += stride;
-	}
-}
-
-static void
-fill_tiles_rgb16(const struct rgb_info *rgb, unsigned char *mem,
-		 unsigned int width, unsigned int height, unsigned int stride)
-{
-	unsigned int x, y;
-
-	for (y = 0; y < height; ++y) {
-		for (x = 0; x < width; ++x) {
-			div_t d = div(x+y, width);
-			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
-				       + 0x000a1120 * (d.rem >> 6);
-			uint16_t color =
-				MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
-					  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
-					  255);
-
-			((uint16_t *)mem)[x] = color;
-		}
-		mem += stride;
-	}
-}
-
-static void
-fill_tiles_rgb24(const struct rgb_info *rgb, unsigned char *mem,
-		 unsigned int width, unsigned int height, unsigned int stride)
-{
-	unsigned int x, y;
-
-	for (y = 0; y < height; ++y) {
-		for (x = 0; x < width; ++x) {
-			div_t d = div(x+y, width);
-			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
-				       + 0x000a1120 * (d.rem >> 6);
-			struct color_rgb24 color =
-				MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff,
-					   (rgb32 >> 8) & 0xff, rgb32 & 0xff);
-
-			((struct color_rgb24 *)mem)[x] = color;
-		}
-		mem += stride;
-	}
-}
-
-static void
-fill_tiles_rgb32(const struct rgb_info *rgb, unsigned char *mem,
-		 unsigned int width, unsigned int height, unsigned int stride)
-{
-	unsigned char *mem_base = mem;
-	unsigned int x, y;
-
-	for (y = 0; y < height; ++y) {
-		for (x = 0; x < width; ++x) {
-			div_t d = div(x+y, width);
-			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
-				       + 0x000a1120 * (d.rem >> 6);
-			uint32_t color =
-				MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
-					  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
-					  255);
-
-			((uint32_t *)mem)[x] = color;
-		}
-		mem += stride;
-	}
-
-	make_pwetty(mem_base, 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_UYVY:
-	case DRM_FORMAT_VYUY:
-	case DRM_FORMAT_YUYV:
-	case DRM_FORMAT_YVYU:
-		return fill_tiles_yuv_packed(&info->yuv, planes[0],
-					     width, height, stride);
-
-	case DRM_FORMAT_NV12:
-	case DRM_FORMAT_NV21:
-	case DRM_FORMAT_NV16:
-	case DRM_FORMAT_NV61:
-		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_RGB565:
-	case DRM_FORMAT_ARGB1555:
-	case DRM_FORMAT_XRGB1555:
-		return fill_tiles_rgb16(&info->rgb, planes[0],
-					width, height, stride);
-	case DRM_FORMAT_BGR888:
-	case DRM_FORMAT_RGB888:
-		return fill_tiles_rgb24(&info->rgb, planes[0],
-					width, height, stride);
-	case DRM_FORMAT_ARGB8888:
-	case DRM_FORMAT_BGRA8888:
-	case DRM_FORMAT_XRGB8888:
-	case DRM_FORMAT_BGRX8888:
-		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_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)
-{
-	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], enum fill_pattern pattern)
-{
-	struct kms_bo *bo;
-	int ret, stride;
-	void *planes[3];
-	void *virtual;
-
-	bo = allocate_buffer(kms, width, height, &pitches[0]);
-	if (!bo)
-		return NULL;
-
-	ret = kms_bo_map(bo, &virtual);
-	if (ret) {
-		fprintf(stderr, "failed to map buffer: %s\n",
-			strerror(-ret));
-		kms_bo_destroy(&bo);
-		return NULL;
-	}
-
-	/* just testing a limited # of formats to test single
-	 * and multi-planar path.. would be nice to add more..
-	 */
-	switch (format) {
-	case DRM_FORMAT_UYVY:
-	case DRM_FORMAT_VYUY:
-	case DRM_FORMAT_YUYV:
-	case DRM_FORMAT_YVYU:
-		pitches[0] = width * 2;
-		offsets[0] = 0;
-		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
-
-		planes[0] = virtual;
-		break;
-
-	case DRM_FORMAT_NV12:
-	case DRM_FORMAT_NV21:
-	case DRM_FORMAT_NV16:
-	case DRM_FORMAT_NV61:
-		pitches[0] = width;
-		offsets[0] = 0;
-		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
-		pitches[1] = width;
-		offsets[1] = width * height;
-		kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]);
-
-		planes[0] = virtual;
-		planes[1] = virtual + offsets[1];
-		break;
-
-	case DRM_FORMAT_YVU420:
-		pitches[0] = width;
-		offsets[0] = 0;
-		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
-		pitches[1] = width / 2;
-		offsets[1] = width * height;
-		kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]);
-		pitches[2] = width / 2;
-		offsets[2] = offsets[1] + (width * height) / 4;
-		kms_bo_get_prop(bo, KMS_HANDLE, &handles[2]);
-
-		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]);
-
-		planes[0] = virtual;
-		break;
-
-	case DRM_FORMAT_BGR888:
-	case DRM_FORMAT_RGB888:
-		pitches[0] = width * 3;
-		offsets[0] = 0;
-		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
-
-		planes[0] = virtual;
-		break;
-
-	case DRM_FORMAT_ARGB8888:
-	case DRM_FORMAT_BGRA8888:
-	case DRM_FORMAT_XRGB8888:
-	case DRM_FORMAT_BGRX8888:
-		pitches[0] = width * 4;
-		offsets[0] = 0;
-		kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
-
-		planes[0] = virtual;
-		break;
-	}
-
-	fill_pattern(format, pattern, planes, width, height, pitches[0]);
-	kms_bo_unmap(bo);
-
-	return bo;
-}
-
 /* -------------------------------------------------------------------------- */
 
 void
-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH] modeset: Split buffer allocation to a separate file
  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
  0 siblings, 1 reply; 14+ messages in thread
From: Rob Clark @ 2012-07-20 15:34 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel

thanks!  I've pushed to a branch on my github tree, in case you want
to double check that I'm not missing anything:

  git://github.com/robclark/libdrm.git  modetest branch

will do some sanity testing a bit later, and if that looks ok and no
one objects, I can push to fd.o

BR,
-R

On Fri, Jul 20, 2012 at 9:37 AM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> As the modeset test application is often referred to as an example of
> the KMS API usage, move test pattern generation and buffer allocation to
> a separate file to keep it simple and clear.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  tests/modetest/Makefile.am |    2 +-
>  tests/modetest/buffers.c   | 1021 ++++++++++++++++++++++++++++++++++++++++++++
>  tests/modetest/buffers.h   |   45 ++
>  tests/modetest/modetest.c  |  987 +------------------------------------------
>  4 files changed, 1068 insertions(+), 987 deletions(-)
>  create mode 100644 tests/modetest/buffers.c
>  create mode 100644 tests/modetest/buffers.h
>
> Hi Rob,
>
> Something like this ?
>
> diff --git a/tests/modetest/Makefile.am b/tests/modetest/Makefile.am
> index 2191242..35754a2 100644
> --- a/tests/modetest/Makefile.am
> +++ b/tests/modetest/Makefile.am
> @@ -8,7 +8,7 @@ noinst_PROGRAMS = \
>         modetest
>
>  modetest_SOURCES = \
> -       modetest.c
> +       buffers.c modetest.c
>  modetest_LDADD = \
>         $(top_builddir)/libdrm.la \
>         $(top_builddir)/libkms/libkms.la \
> diff --git a/tests/modetest/buffers.c b/tests/modetest/buffers.c
> new file mode 100644
> index 0000000..5086381
> --- /dev/null
> +++ b/tests/modetest/buffers.c
> @@ -0,0 +1,1021 @@
> +/*
> + * DRM based mode setting test program
> + * Copyright 2008 Tungsten Graphics
> + *   Jakob Bornecrantz <jakob@tungstengraphics.com>
> + * Copyright 2008 Intel Corporation
> + *   Jesse Barnes <jesse.barnes@intel.com>
> + *
> + * 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 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 "config.h"
> +
> +#include <assert.h>
> +#include <errno.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <stdint.h>
> +#include <string.h>
> +
> +#include "drm_fourcc.h"
> +#include "libkms.h"
> +
> +#include "buffers.h"
> +
> +#ifdef HAVE_CAIRO
> +#include <math.h>
> +#include <cairo.h>
> +#endif
> +
> +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
> +
> +/* -----------------------------------------------------------------------------
> + * 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[] = {
> +       /* YUV packed */
> +       { DRM_FORMAT_UYVY, "UYVY", MAKE_YUV_INFO(YUV_YCbCr | YUV_CY, 2, 2, 2) },
> +       { DRM_FORMAT_VYUY, "VYUY", MAKE_YUV_INFO(YUV_YCrCb | YUV_CY, 2, 2, 2) },
> +       { DRM_FORMAT_YUYV, "YUYV", MAKE_YUV_INFO(YUV_YCbCr | YUV_YC, 2, 2, 2) },
> +       { DRM_FORMAT_YVYU, "YVYU", MAKE_YUV_INFO(YUV_YCrCb | YUV_YC, 2, 2, 2) },
> +       /* YUV semi-planar */
> +       { 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_NV16, "NV16", MAKE_YUV_INFO(YUV_YCbCr, 2, 1, 2) },
> +       { DRM_FORMAT_NV61, "NV61", MAKE_YUV_INFO(YUV_YCrCb, 2, 1, 2) },
> +       /* YUV planar */
> +       { DRM_FORMAT_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) },
> +       /* RGB16 */
> +       { DRM_FORMAT_ARGB1555, "AR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 1, 15) },
> +       { DRM_FORMAT_XRGB1555, "XR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 0, 0) },
> +       { DRM_FORMAT_RGB565, "RG16", MAKE_RGB_INFO(5, 11, 6, 5, 5, 0, 0, 0) },
> +       /* RGB24 */
> +       { DRM_FORMAT_BGR888, "BG24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) },
> +       { DRM_FORMAT_RGB888, "RG24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
> +       /* RGB32 */
> +       { DRM_FORMAT_ARGB8888, "AR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 8, 24) },
> +       { DRM_FORMAT_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, 0) },
> +       { DRM_FORMAT_XRGB8888, "XR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
> +       { DRM_FORMAT_BGRX8888, "BX24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 0, 0) },
> +};
> +
> +unsigned int format_fourcc(const char *name)
> +{
> +       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
> + */
> +
> +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))
> +
> +#define MAKE_RGB24(rgb, r, g, b) \
> +       { .value = MAKE_RGBA(rgb, r, g, b, 0) }
> +
> +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 */
> +       };
> +       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;
> +       }
> +
> +       for (; y < height * 7 / 9; ++y) {
> +               for (x = 0; x < width; ++x)
> +                       y_mem[x] = colors_middle[x * 7 / width].y;
> +               y_mem += stride;
> +       }
> +
> +       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;
> +       }
> +
> +       /* 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;
> +       }
> +
> +       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_rgb24(const struct rgb_info *rgb, void *mem,
> +                unsigned int width, unsigned int height, unsigned int stride)
> +{
> +       const struct color_rgb24 colors_top[] = {
> +               MAKE_RGB24(rgb, 192, 192, 192), /* grey */
> +               MAKE_RGB24(rgb, 192, 192, 0),   /* yellow */
> +               MAKE_RGB24(rgb, 0, 192, 192),   /* cyan */
> +               MAKE_RGB24(rgb, 0, 192, 0),     /* green */
> +               MAKE_RGB24(rgb, 192, 0, 192),   /* magenta */
> +               MAKE_RGB24(rgb, 192, 0, 0),     /* red */
> +               MAKE_RGB24(rgb, 0, 0, 192),     /* blue */
> +       };
> +       const struct color_rgb24 colors_middle[] = {
> +               MAKE_RGB24(rgb, 0, 0, 192),     /* blue */
> +               MAKE_RGB24(rgb, 19, 19, 19),    /* black */
> +               MAKE_RGB24(rgb, 192, 0, 192),   /* magenta */
> +               MAKE_RGB24(rgb, 19, 19, 19),    /* black */
> +               MAKE_RGB24(rgb, 0, 192, 192),   /* cyan */
> +               MAKE_RGB24(rgb, 19, 19, 19),    /* black */
> +               MAKE_RGB24(rgb, 192, 192, 192), /* grey */
> +       };
> +       const struct color_rgb24 colors_bottom[] = {
> +               MAKE_RGB24(rgb, 0, 33, 76),     /* in-phase */
> +               MAKE_RGB24(rgb, 255, 255, 255), /* super white */
> +               MAKE_RGB24(rgb, 50, 0, 106),    /* quadrature */
> +               MAKE_RGB24(rgb, 19, 19, 19),    /* black */
> +               MAKE_RGB24(rgb, 9, 9, 9),       /* 3.5% */
> +               MAKE_RGB24(rgb, 19, 19, 19),    /* 7.5% */
> +               MAKE_RGB24(rgb, 29, 29, 29),    /* 11.5% */
> +               MAKE_RGB24(rgb, 19, 19, 19),    /* black */
> +       };
> +       unsigned int x;
> +       unsigned int y;
> +
> +       for (y = 0; y < height * 6 / 9; ++y) {
> +               for (x = 0; x < width; ++x)
> +                       ((struct color_rgb24 *)mem)[x] =
> +                               colors_top[x * 7 / width];
> +               mem += stride;
> +       }
> +
> +       for (; y < height * 7 / 9; ++y) {
> +               for (x = 0; x < width; ++x)
> +                       ((struct color_rgb24 *)mem)[x] =
> +                               colors_middle[x * 7 / width];
> +               mem += stride;
> +       }
> +
> +       for (; y < height; ++y) {
> +               for (x = 0; x < width * 5 / 7; ++x)
> +                       ((struct color_rgb24 *)mem)[x] =
> +                               colors_bottom[x * 4 / (width * 5 / 7)];
> +               for (; x < width * 6 / 7; ++x)
> +                       ((struct color_rgb24 *)mem)[x] =
> +                               colors_bottom[(x - width * 5 / 7) * 3
> +                                             / (width / 7) + 4];
> +               for (; x < width; ++x)
> +                       ((struct color_rgb24 *)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_UYVY:
> +       case DRM_FORMAT_VYUY:
> +       case DRM_FORMAT_YUYV:
> +       case DRM_FORMAT_YVYU:
> +               return fill_smpte_yuv_packed(&info->yuv, planes[0], width,
> +                                            height, stride);
> +
> +       case DRM_FORMAT_NV12:
> +       case DRM_FORMAT_NV21:
> +       case DRM_FORMAT_NV16:
> +       case DRM_FORMAT_NV61:
> +               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_RGB565:
> +       case DRM_FORMAT_ARGB1555:
> +       case DRM_FORMAT_XRGB1555:
> +               return fill_smpte_rgb16(&info->rgb, planes[0],
> +                                       width, height, stride);
> +       case DRM_FORMAT_BGR888:
> +       case DRM_FORMAT_RGB888:
> +               return fill_smpte_rgb24(&info->rgb, planes[0],
> +                                       width, height, stride);
> +       case DRM_FORMAT_ARGB8888:
> +       case DRM_FORMAT_BGRA8888:
> +       case DRM_FORMAT_XRGB8888:
> +       case DRM_FORMAT_BGRX8888:
> +               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
> +       cairo_surface_t *surface;
> +       cairo_t *cr;
> +       int x, y;
> +
> +       surface = cairo_image_surface_create_for_data(data,
> +                                                     CAIRO_FORMAT_ARGB32,
> +                                                     width, height,
> +                                                     stride);
> +       cr = cairo_create(surface);
> +       cairo_surface_destroy(surface);
> +
> +       cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
> +       for (x = 0; x < width; x += 250)
> +               for (y = 0; y < height; y += 250) {
> +                       char buf[64];
> +
> +                       cairo_move_to(cr, x, y - 20);
> +                       cairo_line_to(cr, x, y + 20);
> +                       cairo_move_to(cr, x - 20, y);
> +                       cairo_line_to(cr, x + 20, y);
> +                       cairo_new_sub_path(cr);
> +                       cairo_arc(cr, x, y, 10, 0, M_PI * 2);
> +                       cairo_set_line_width(cr, 4);
> +                       cairo_set_source_rgb(cr, 0, 0, 0);
> +                       cairo_stroke_preserve(cr);
> +                       cairo_set_source_rgb(cr, 1, 1, 1);
> +                       cairo_set_line_width(cr, 2);
> +                       cairo_stroke(cr);
> +
> +                       snprintf(buf, sizeof buf, "%d, %d", x, y);
> +                       cairo_move_to(cr, x + 20, y + 20);
> +                       cairo_text_path(cr, buf);
> +                       cairo_set_source_rgb(cr, 0, 0, 0);
> +                       cairo_stroke_preserve(cr);
> +                       cairo_set_source_rgb(cr, 1, 1, 1);
> +                       cairo_fill(cr);
> +               }
> +
> +       cairo_destroy(cr);
> +#endif
> +}
> +
> +static void
> +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)
> +{
> +       unsigned int cs = yuv->chroma_stride;
> +       unsigned int xsub = yuv->xsub;
> +       unsigned int ysub = yuv->ysub;
> +       unsigned int x;
> +       unsigned int y;
> +
> +       for (y = 0; y < height; ++y) {
> +               for (x = 0; x < width; ++x) {
> +                       div_t d = div(x+y, width);
> +                       uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
> +                                      + 0x000a1120 * (d.rem >> 6);
> +                       struct color_yuv color =
> +                               MAKE_YUV_601((rgb32 >> 16) & 0xff,
> +                                            (rgb32 >> 8) & 0xff, rgb32 & 0xff);
> +
> +                       y_mem[x] = color.y;
> +                       u_mem[x/xsub*cs] = color.u;
> +                       v_mem[x/xsub*cs] = color.v;
> +               }
> +
> +               y_mem += stride;
> +               if ((y + 1) % ysub == 0) {
> +                       u_mem += stride * cs / xsub;
> +                       v_mem += stride * cs / xsub;
> +               }
> +       }
> +}
> +
> +static void
> +fill_tiles_yuv_packed(const struct yuv_info *yuv, unsigned char *mem,
> +                     unsigned int width, unsigned int height,
> +                     unsigned int stride)
> +{
> +       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;
> +
> +       for (y = 0; y < height; ++y) {
> +               for (x = 0; x < width; x += 2) {
> +                       div_t d = div(x+y, width);
> +                       uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
> +                                      + 0x000a1120 * (d.rem >> 6);
> +                       struct color_yuv color =
> +                               MAKE_YUV_601((rgb32 >> 16) & 0xff,
> +                                            (rgb32 >> 8) & 0xff, rgb32 & 0xff);
> +
> +                       y_mem[2*x] = color.y;
> +                       c_mem[2*x+u] = color.u;
> +                       y_mem[2*x+2] = color.y;
> +                       c_mem[2*x+v] = color.v;
> +               }
> +
> +               y_mem += stride;
> +               c_mem += stride;
> +       }
> +}
> +
> +static void
> +fill_tiles_rgb16(const struct rgb_info *rgb, unsigned char *mem,
> +                unsigned int width, unsigned int height, unsigned int stride)
> +{
> +       unsigned int x, y;
> +
> +       for (y = 0; y < height; ++y) {
> +               for (x = 0; x < width; ++x) {
> +                       div_t d = div(x+y, width);
> +                       uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
> +                                      + 0x000a1120 * (d.rem >> 6);
> +                       uint16_t color =
> +                               MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
> +                                         (rgb32 >> 8) & 0xff, rgb32 & 0xff,
> +                                         255);
> +
> +                       ((uint16_t *)mem)[x] = color;
> +               }
> +               mem += stride;
> +       }
> +}
> +
> +static void
> +fill_tiles_rgb24(const struct rgb_info *rgb, unsigned char *mem,
> +                unsigned int width, unsigned int height, unsigned int stride)
> +{
> +       unsigned int x, y;
> +
> +       for (y = 0; y < height; ++y) {
> +               for (x = 0; x < width; ++x) {
> +                       div_t d = div(x+y, width);
> +                       uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
> +                                      + 0x000a1120 * (d.rem >> 6);
> +                       struct color_rgb24 color =
> +                               MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff,
> +                                          (rgb32 >> 8) & 0xff, rgb32 & 0xff);
> +
> +                       ((struct color_rgb24 *)mem)[x] = color;
> +               }
> +               mem += stride;
> +       }
> +}
> +
> +static void
> +fill_tiles_rgb32(const struct rgb_info *rgb, unsigned char *mem,
> +                unsigned int width, unsigned int height, unsigned int stride)
> +{
> +       unsigned char *mem_base = mem;
> +       unsigned int x, y;
> +
> +       for (y = 0; y < height; ++y) {
> +               for (x = 0; x < width; ++x) {
> +                       div_t d = div(x+y, width);
> +                       uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
> +                                      + 0x000a1120 * (d.rem >> 6);
> +                       uint32_t color =
> +                               MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
> +                                         (rgb32 >> 8) & 0xff, rgb32 & 0xff,
> +                                         255);
> +
> +                       ((uint32_t *)mem)[x] = color;
> +               }
> +               mem += stride;
> +       }
> +
> +       make_pwetty(mem_base, 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_UYVY:
> +       case DRM_FORMAT_VYUY:
> +       case DRM_FORMAT_YUYV:
> +       case DRM_FORMAT_YVYU:
> +               return fill_tiles_yuv_packed(&info->yuv, planes[0],
> +                                            width, height, stride);
> +
> +       case DRM_FORMAT_NV12:
> +       case DRM_FORMAT_NV21:
> +       case DRM_FORMAT_NV16:
> +       case DRM_FORMAT_NV61:
> +               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_RGB565:
> +       case DRM_FORMAT_ARGB1555:
> +       case DRM_FORMAT_XRGB1555:
> +               return fill_tiles_rgb16(&info->rgb, planes[0],
> +                                       width, height, stride);
> +       case DRM_FORMAT_BGR888:
> +       case DRM_FORMAT_RGB888:
> +               return fill_tiles_rgb24(&info->rgb, planes[0],
> +                                       width, height, stride);
> +       case DRM_FORMAT_ARGB8888:
> +       case DRM_FORMAT_BGRA8888:
> +       case DRM_FORMAT_XRGB8888:
> +       case DRM_FORMAT_BGRX8888:
> +               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_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)
> +{
> +       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;
> +}
> +
> +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], enum fill_pattern pattern)
> +{
> +       struct kms_bo *bo;
> +       int ret, stride;
> +       void *planes[3];
> +       void *virtual;
> +
> +       bo = allocate_buffer(kms, width, height, &pitches[0]);
> +       if (!bo)
> +               return NULL;
> +
> +       ret = kms_bo_map(bo, &virtual);
> +       if (ret) {
> +               fprintf(stderr, "failed to map buffer: %s\n",
> +                       strerror(-ret));
> +               kms_bo_destroy(&bo);
> +               return NULL;
> +       }
> +
> +       /* just testing a limited # of formats to test single
> +        * and multi-planar path.. would be nice to add more..
> +        */
> +       switch (format) {
> +       case DRM_FORMAT_UYVY:
> +       case DRM_FORMAT_VYUY:
> +       case DRM_FORMAT_YUYV:
> +       case DRM_FORMAT_YVYU:
> +               pitches[0] = width * 2;
> +               offsets[0] = 0;
> +               kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
> +
> +               planes[0] = virtual;
> +               break;
> +
> +       case DRM_FORMAT_NV12:
> +       case DRM_FORMAT_NV21:
> +       case DRM_FORMAT_NV16:
> +       case DRM_FORMAT_NV61:
> +               pitches[0] = width;
> +               offsets[0] = 0;
> +               kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
> +               pitches[1] = width;
> +               offsets[1] = width * height;
> +               kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]);
> +
> +               planes[0] = virtual;
> +               planes[1] = virtual + offsets[1];
> +               break;
> +
> +       case DRM_FORMAT_YVU420:
> +               pitches[0] = width;
> +               offsets[0] = 0;
> +               kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
> +               pitches[1] = width / 2;
> +               offsets[1] = width * height;
> +               kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]);
> +               pitches[2] = width / 2;
> +               offsets[2] = offsets[1] + (width * height) / 4;
> +               kms_bo_get_prop(bo, KMS_HANDLE, &handles[2]);
> +
> +               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]);
> +
> +               planes[0] = virtual;
> +               break;
> +
> +       case DRM_FORMAT_BGR888:
> +       case DRM_FORMAT_RGB888:
> +               pitches[0] = width * 3;
> +               offsets[0] = 0;
> +               kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
> +
> +               planes[0] = virtual;
> +               break;
> +
> +       case DRM_FORMAT_ARGB8888:
> +       case DRM_FORMAT_BGRA8888:
> +       case DRM_FORMAT_XRGB8888:
> +       case DRM_FORMAT_BGRX8888:
> +               pitches[0] = width * 4;
> +               offsets[0] = 0;
> +               kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
> +
> +               planes[0] = virtual;
> +               break;
> +       }
> +
> +       fill_pattern(format, pattern, planes, width, height, pitches[0]);
> +       kms_bo_unmap(bo);
> +
> +       return bo;
> +}
> diff --git a/tests/modetest/buffers.h b/tests/modetest/buffers.h
> new file mode 100644
> index 0000000..2b15ce5
> --- /dev/null
> +++ b/tests/modetest/buffers.h
> @@ -0,0 +1,45 @@
> +/*
> + * DRM based mode setting test program
> + * Copyright 2008 Tungsten Graphics
> + *   Jakob Bornecrantz <jakob@tungstengraphics.com>
> + * Copyright 2008 Intel Corporation
> + *   Jesse Barnes <jesse.barnes@intel.com>
> + *
> + * 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 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.
> + */
> +
> +#ifndef __BUFFERS_H__
> +#define __BUFFERS_H__
> +
> +struct kms_bo;
> +struct kms_driver;
> +
> +enum fill_pattern {
> +       PATTERN_TILES = 0,
> +       PATTERN_PLAIN = 1,
> +       PATTERN_SMPTE = 2,
> +};
> +
> +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], enum fill_pattern pattern);
> +
> +unsigned int format_fourcc(const char *name);
> +
> +#endif
> diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
> index 3ed39b7..3e74008 100644
> --- a/tests/modetest/modetest.c
> +++ b/tests/modetest/modetest.c
> @@ -55,10 +55,7 @@
>  #include "drm_fourcc.h"
>  #include "libkms.h"
>
> -#ifdef HAVE_CAIRO
> -#include <math.h>
> -#include <cairo.h>
> -#endif
> +#include "buffers.h"
>
>  drmModeRes *resources;
>  int fd, modes;
> @@ -584,988 +581,6 @@ connector_find_mode(struct connector *c)
>
>  }
>
> -/* -----------------------------------------------------------------------------
> - * 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[] = {
> -       /* YUV packed */
> -       { DRM_FORMAT_UYVY, "UYVY", MAKE_YUV_INFO(YUV_YCbCr | YUV_CY, 2, 2, 2) },
> -       { DRM_FORMAT_VYUY, "VYUY", MAKE_YUV_INFO(YUV_YCrCb | YUV_CY, 2, 2, 2) },
> -       { DRM_FORMAT_YUYV, "YUYV", MAKE_YUV_INFO(YUV_YCbCr | YUV_YC, 2, 2, 2) },
> -       { DRM_FORMAT_YVYU, "YVYU", MAKE_YUV_INFO(YUV_YCrCb | YUV_YC, 2, 2, 2) },
> -       /* YUV semi-planar */
> -       { 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_NV16, "NV16", MAKE_YUV_INFO(YUV_YCbCr, 2, 1, 2) },
> -       { DRM_FORMAT_NV61, "NV61", MAKE_YUV_INFO(YUV_YCrCb, 2, 1, 2) },
> -       /* YUV planar */
> -       { DRM_FORMAT_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) },
> -       /* RGB16 */
> -       { DRM_FORMAT_ARGB1555, "AR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 1, 15) },
> -       { DRM_FORMAT_XRGB1555, "XR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 0, 0) },
> -       { DRM_FORMAT_RGB565, "RG16", MAKE_RGB_INFO(5, 11, 6, 5, 5, 0, 0, 0) },
> -       /* RGB24 */
> -       { DRM_FORMAT_BGR888, "BG24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) },
> -       { DRM_FORMAT_RGB888, "RG24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
> -       /* RGB32 */
> -       { DRM_FORMAT_ARGB8888, "AR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 8, 24) },
> -       { DRM_FORMAT_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, 0) },
> -       { DRM_FORMAT_XRGB8888, "XR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
> -       { DRM_FORMAT_BGRX8888, "BX24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 0, 0) },
> -};
> -
> -unsigned int format_fourcc(const char *name)
> -{
> -       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))
> -
> -#define MAKE_RGB24(rgb, r, g, b) \
> -       { .value = MAKE_RGBA(rgb, r, g, b, 0) }
> -
> -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 */
> -       };
> -       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;
> -       }
> -
> -       for (; y < height * 7 / 9; ++y) {
> -               for (x = 0; x < width; ++x)
> -                       y_mem[x] = colors_middle[x * 7 / width].y;
> -               y_mem += stride;
> -       }
> -
> -       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;
> -       }
> -
> -       /* 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;
> -       }
> -
> -       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_rgb24(const struct rgb_info *rgb, void *mem,
> -                unsigned int width, unsigned int height, unsigned int stride)
> -{
> -       const struct color_rgb24 colors_top[] = {
> -               MAKE_RGB24(rgb, 192, 192, 192), /* grey */
> -               MAKE_RGB24(rgb, 192, 192, 0),   /* yellow */
> -               MAKE_RGB24(rgb, 0, 192, 192),   /* cyan */
> -               MAKE_RGB24(rgb, 0, 192, 0),     /* green */
> -               MAKE_RGB24(rgb, 192, 0, 192),   /* magenta */
> -               MAKE_RGB24(rgb, 192, 0, 0),     /* red */
> -               MAKE_RGB24(rgb, 0, 0, 192),     /* blue */
> -       };
> -       const struct color_rgb24 colors_middle[] = {
> -               MAKE_RGB24(rgb, 0, 0, 192),     /* blue */
> -               MAKE_RGB24(rgb, 19, 19, 19),    /* black */
> -               MAKE_RGB24(rgb, 192, 0, 192),   /* magenta */
> -               MAKE_RGB24(rgb, 19, 19, 19),    /* black */
> -               MAKE_RGB24(rgb, 0, 192, 192),   /* cyan */
> -               MAKE_RGB24(rgb, 19, 19, 19),    /* black */
> -               MAKE_RGB24(rgb, 192, 192, 192), /* grey */
> -       };
> -       const struct color_rgb24 colors_bottom[] = {
> -               MAKE_RGB24(rgb, 0, 33, 76),     /* in-phase */
> -               MAKE_RGB24(rgb, 255, 255, 255), /* super white */
> -               MAKE_RGB24(rgb, 50, 0, 106),    /* quadrature */
> -               MAKE_RGB24(rgb, 19, 19, 19),    /* black */
> -               MAKE_RGB24(rgb, 9, 9, 9),       /* 3.5% */
> -               MAKE_RGB24(rgb, 19, 19, 19),    /* 7.5% */
> -               MAKE_RGB24(rgb, 29, 29, 29),    /* 11.5% */
> -               MAKE_RGB24(rgb, 19, 19, 19),    /* black */
> -       };
> -       unsigned int x;
> -       unsigned int y;
> -
> -       for (y = 0; y < height * 6 / 9; ++y) {
> -               for (x = 0; x < width; ++x)
> -                       ((struct color_rgb24 *)mem)[x] =
> -                               colors_top[x * 7 / width];
> -               mem += stride;
> -       }
> -
> -       for (; y < height * 7 / 9; ++y) {
> -               for (x = 0; x < width; ++x)
> -                       ((struct color_rgb24 *)mem)[x] =
> -                               colors_middle[x * 7 / width];
> -               mem += stride;
> -       }
> -
> -       for (; y < height; ++y) {
> -               for (x = 0; x < width * 5 / 7; ++x)
> -                       ((struct color_rgb24 *)mem)[x] =
> -                               colors_bottom[x * 4 / (width * 5 / 7)];
> -               for (; x < width * 6 / 7; ++x)
> -                       ((struct color_rgb24 *)mem)[x] =
> -                               colors_bottom[(x - width * 5 / 7) * 3
> -                                             / (width / 7) + 4];
> -               for (; x < width; ++x)
> -                       ((struct color_rgb24 *)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_UYVY:
> -       case DRM_FORMAT_VYUY:
> -       case DRM_FORMAT_YUYV:
> -       case DRM_FORMAT_YVYU:
> -               return fill_smpte_yuv_packed(&info->yuv, planes[0], width,
> -                                            height, stride);
> -
> -       case DRM_FORMAT_NV12:
> -       case DRM_FORMAT_NV21:
> -       case DRM_FORMAT_NV16:
> -       case DRM_FORMAT_NV61:
> -               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_RGB565:
> -       case DRM_FORMAT_ARGB1555:
> -       case DRM_FORMAT_XRGB1555:
> -               return fill_smpte_rgb16(&info->rgb, planes[0],
> -                                       width, height, stride);
> -       case DRM_FORMAT_BGR888:
> -       case DRM_FORMAT_RGB888:
> -               return fill_smpte_rgb24(&info->rgb, planes[0],
> -                                       width, height, stride);
> -       case DRM_FORMAT_ARGB8888:
> -       case DRM_FORMAT_BGRA8888:
> -       case DRM_FORMAT_XRGB8888:
> -       case DRM_FORMAT_BGRX8888:
> -               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
> -       cairo_surface_t *surface;
> -       cairo_t *cr;
> -       int x, y;
> -
> -       surface = cairo_image_surface_create_for_data(data,
> -                                                     CAIRO_FORMAT_ARGB32,
> -                                                     width, height,
> -                                                     stride);
> -       cr = cairo_create(surface);
> -       cairo_surface_destroy(surface);
> -
> -       cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
> -       for (x = 0; x < width; x += 250)
> -               for (y = 0; y < height; y += 250) {
> -                       char buf[64];
> -
> -                       cairo_move_to(cr, x, y - 20);
> -                       cairo_line_to(cr, x, y + 20);
> -                       cairo_move_to(cr, x - 20, y);
> -                       cairo_line_to(cr, x + 20, y);
> -                       cairo_new_sub_path(cr);
> -                       cairo_arc(cr, x, y, 10, 0, M_PI * 2);
> -                       cairo_set_line_width(cr, 4);
> -                       cairo_set_source_rgb(cr, 0, 0, 0);
> -                       cairo_stroke_preserve(cr);
> -                       cairo_set_source_rgb(cr, 1, 1, 1);
> -                       cairo_set_line_width(cr, 2);
> -                       cairo_stroke(cr);
> -
> -                       snprintf(buf, sizeof buf, "%d, %d", x, y);
> -                       cairo_move_to(cr, x + 20, y + 20);
> -                       cairo_text_path(cr, buf);
> -                       cairo_set_source_rgb(cr, 0, 0, 0);
> -                       cairo_stroke_preserve(cr);
> -                       cairo_set_source_rgb(cr, 1, 1, 1);
> -                       cairo_fill(cr);
> -               }
> -
> -       cairo_destroy(cr);
> -#endif
> -}
> -
> -static void
> -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)
> -{
> -       unsigned int cs = yuv->chroma_stride;
> -       unsigned int xsub = yuv->xsub;
> -       unsigned int ysub = yuv->ysub;
> -       unsigned int x;
> -       unsigned int y;
> -
> -       for (y = 0; y < height; ++y) {
> -               for (x = 0; x < width; ++x) {
> -                       div_t d = div(x+y, width);
> -                       uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
> -                                      + 0x000a1120 * (d.rem >> 6);
> -                       struct color_yuv color =
> -                               MAKE_YUV_601((rgb32 >> 16) & 0xff,
> -                                            (rgb32 >> 8) & 0xff, rgb32 & 0xff);
> -
> -                       y_mem[x] = color.y;
> -                       u_mem[x/xsub*cs] = color.u;
> -                       v_mem[x/xsub*cs] = color.v;
> -               }
> -
> -               y_mem += stride;
> -               if ((y + 1) % ysub == 0) {
> -                       u_mem += stride * cs / xsub;
> -                       v_mem += stride * cs / xsub;
> -               }
> -       }
> -}
> -
> -static void
> -fill_tiles_yuv_packed(const struct yuv_info *yuv, unsigned char *mem,
> -                     unsigned int width, unsigned int height,
> -                     unsigned int stride)
> -{
> -       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;
> -
> -       for (y = 0; y < height; ++y) {
> -               for (x = 0; x < width; x += 2) {
> -                       div_t d = div(x+y, width);
> -                       uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
> -                                      + 0x000a1120 * (d.rem >> 6);
> -                       struct color_yuv color =
> -                               MAKE_YUV_601((rgb32 >> 16) & 0xff,
> -                                            (rgb32 >> 8) & 0xff, rgb32 & 0xff);
> -
> -                       y_mem[2*x] = color.y;
> -                       c_mem[2*x+u] = color.u;
> -                       y_mem[2*x+2] = color.y;
> -                       c_mem[2*x+v] = color.v;
> -               }
> -
> -               y_mem += stride;
> -               c_mem += stride;
> -       }
> -}
> -
> -static void
> -fill_tiles_rgb16(const struct rgb_info *rgb, unsigned char *mem,
> -                unsigned int width, unsigned int height, unsigned int stride)
> -{
> -       unsigned int x, y;
> -
> -       for (y = 0; y < height; ++y) {
> -               for (x = 0; x < width; ++x) {
> -                       div_t d = div(x+y, width);
> -                       uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
> -                                      + 0x000a1120 * (d.rem >> 6);
> -                       uint16_t color =
> -                               MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
> -                                         (rgb32 >> 8) & 0xff, rgb32 & 0xff,
> -                                         255);
> -
> -                       ((uint16_t *)mem)[x] = color;
> -               }
> -               mem += stride;
> -       }
> -}
> -
> -static void
> -fill_tiles_rgb24(const struct rgb_info *rgb, unsigned char *mem,
> -                unsigned int width, unsigned int height, unsigned int stride)
> -{
> -       unsigned int x, y;
> -
> -       for (y = 0; y < height; ++y) {
> -               for (x = 0; x < width; ++x) {
> -                       div_t d = div(x+y, width);
> -                       uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
> -                                      + 0x000a1120 * (d.rem >> 6);
> -                       struct color_rgb24 color =
> -                               MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff,
> -                                          (rgb32 >> 8) & 0xff, rgb32 & 0xff);
> -
> -                       ((struct color_rgb24 *)mem)[x] = color;
> -               }
> -               mem += stride;
> -       }
> -}
> -
> -static void
> -fill_tiles_rgb32(const struct rgb_info *rgb, unsigned char *mem,
> -                unsigned int width, unsigned int height, unsigned int stride)
> -{
> -       unsigned char *mem_base = mem;
> -       unsigned int x, y;
> -
> -       for (y = 0; y < height; ++y) {
> -               for (x = 0; x < width; ++x) {
> -                       div_t d = div(x+y, width);
> -                       uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
> -                                      + 0x000a1120 * (d.rem >> 6);
> -                       uint32_t color =
> -                               MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
> -                                         (rgb32 >> 8) & 0xff, rgb32 & 0xff,
> -                                         255);
> -
> -                       ((uint32_t *)mem)[x] = color;
> -               }
> -               mem += stride;
> -       }
> -
> -       make_pwetty(mem_base, 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_UYVY:
> -       case DRM_FORMAT_VYUY:
> -       case DRM_FORMAT_YUYV:
> -       case DRM_FORMAT_YVYU:
> -               return fill_tiles_yuv_packed(&info->yuv, planes[0],
> -                                            width, height, stride);
> -
> -       case DRM_FORMAT_NV12:
> -       case DRM_FORMAT_NV21:
> -       case DRM_FORMAT_NV16:
> -       case DRM_FORMAT_NV61:
> -               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_RGB565:
> -       case DRM_FORMAT_ARGB1555:
> -       case DRM_FORMAT_XRGB1555:
> -               return fill_tiles_rgb16(&info->rgb, planes[0],
> -                                       width, height, stride);
> -       case DRM_FORMAT_BGR888:
> -       case DRM_FORMAT_RGB888:
> -               return fill_tiles_rgb24(&info->rgb, planes[0],
> -                                       width, height, stride);
> -       case DRM_FORMAT_ARGB8888:
> -       case DRM_FORMAT_BGRA8888:
> -       case DRM_FORMAT_XRGB8888:
> -       case DRM_FORMAT_BGRX8888:
> -               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_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)
> -{
> -       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], enum fill_pattern pattern)
> -{
> -       struct kms_bo *bo;
> -       int ret, stride;
> -       void *planes[3];
> -       void *virtual;
> -
> -       bo = allocate_buffer(kms, width, height, &pitches[0]);
> -       if (!bo)
> -               return NULL;
> -
> -       ret = kms_bo_map(bo, &virtual);
> -       if (ret) {
> -               fprintf(stderr, "failed to map buffer: %s\n",
> -                       strerror(-ret));
> -               kms_bo_destroy(&bo);
> -               return NULL;
> -       }
> -
> -       /* just testing a limited # of formats to test single
> -        * and multi-planar path.. would be nice to add more..
> -        */
> -       switch (format) {
> -       case DRM_FORMAT_UYVY:
> -       case DRM_FORMAT_VYUY:
> -       case DRM_FORMAT_YUYV:
> -       case DRM_FORMAT_YVYU:
> -               pitches[0] = width * 2;
> -               offsets[0] = 0;
> -               kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
> -
> -               planes[0] = virtual;
> -               break;
> -
> -       case DRM_FORMAT_NV12:
> -       case DRM_FORMAT_NV21:
> -       case DRM_FORMAT_NV16:
> -       case DRM_FORMAT_NV61:
> -               pitches[0] = width;
> -               offsets[0] = 0;
> -               kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
> -               pitches[1] = width;
> -               offsets[1] = width * height;
> -               kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]);
> -
> -               planes[0] = virtual;
> -               planes[1] = virtual + offsets[1];
> -               break;
> -
> -       case DRM_FORMAT_YVU420:
> -               pitches[0] = width;
> -               offsets[0] = 0;
> -               kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
> -               pitches[1] = width / 2;
> -               offsets[1] = width * height;
> -               kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]);
> -               pitches[2] = width / 2;
> -               offsets[2] = offsets[1] + (width * height) / 4;
> -               kms_bo_get_prop(bo, KMS_HANDLE, &handles[2]);
> -
> -               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]);
> -
> -               planes[0] = virtual;
> -               break;
> -
> -       case DRM_FORMAT_BGR888:
> -       case DRM_FORMAT_RGB888:
> -               pitches[0] = width * 3;
> -               offsets[0] = 0;
> -               kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
> -
> -               planes[0] = virtual;
> -               break;
> -
> -       case DRM_FORMAT_ARGB8888:
> -       case DRM_FORMAT_BGRA8888:
> -       case DRM_FORMAT_XRGB8888:
> -       case DRM_FORMAT_BGRX8888:
> -               pitches[0] = width * 4;
> -               offsets[0] = 0;
> -               kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
> -
> -               planes[0] = virtual;
> -               break;
> -       }
> -
> -       fill_pattern(format, pattern, planes, width, height, pitches[0]);
> -       kms_bo_unmap(bo);
> -
> -       return bo;
> -}
> -
>  /* -------------------------------------------------------------------------- */
>
>  void
> --
> Regards,
>
> Laurent Pinchart
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH] modeset: Split buffer allocation to a separate file
  2012-07-20 15:34     ` Rob Clark
@ 2012-07-20 17:38       ` Laurent Pinchart
  2012-07-23 16:40         ` Rob Clark
  0 siblings, 1 reply; 14+ messages in thread
From: Laurent Pinchart @ 2012-07-20 17:38 UTC (permalink / raw)
  To: Rob Clark; +Cc: dri-devel

Hi Rob,


On Friday 20 July 2012 10:34:46 Rob Clark wrote:
> thanks!  I've pushed to a branch on my github tree, in case you want
> to double check that I'm not missing anything:
> 
>   git://github.com/robclark/libdrm.git  modetest branch
> 
> will do some sanity testing a bit later, and if that looks ok and no
> one objects, I can push to fd.o

It looks good to me, thank you.

I've tested the NV12, NV21, NV16, NV61, RGB565, RGB888 and ARGB888 formats, as 
that's what my hardware supports. The other formats haven't been tested.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH] modeset: Split buffer allocation to a separate file
  2012-07-20 17:38       ` Laurent Pinchart
@ 2012-07-23 16:40         ` Rob Clark
  0 siblings, 0 replies; 14+ messages in thread
From: Rob Clark @ 2012-07-23 16:40 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel

On Fri, Jul 20, 2012 at 12:38 PM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> Hi Rob,
>
>
> On Friday 20 July 2012 10:34:46 Rob Clark wrote:
>> thanks!  I've pushed to a branch on my github tree, in case you want
>> to double check that I'm not missing anything:
>>
>>   git://github.com/robclark/libdrm.git  modetest branch
>>
>> will do some sanity testing a bit later, and if that looks ok and no
>> one objects, I can push to fd.o
>
> It looks good to me, thank you.
>
> I've tested the NV12, NV21, NV16, NV61, RGB565, RGB888 and ARGB888 formats, as
> that's what my hardware supports. The other formats haven't been tested.


Ok, I made one small fix for potentially uninitialized variable, and
pushed.  Thanks

BR,
-R


> --
> Regards,
>
> Laurent Pinchart
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

end of thread, other threads:[~2012-07-23 16:40 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [PATCH 2/7] modetest: Add SMPTE test pattern Laurent Pinchart
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

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.