All of lore.kernel.org
 help / color / mirror / Atom feed
From: Damien Lespiau <damien.lespiau@gmail.com>
To: intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org
Subject: [PATCH 2/2] tests/testdisplay: Test the stereo 3D modes
Date: Thu, 27 Sep 2012 19:42:08 +0100	[thread overview]
Message-ID: <1348771328-3655-2-git-send-email-damien.lespiau@gmail.com> (raw)
In-Reply-To: <1348771328-3655-1-git-send-email-damien.lespiau@gmail.com>

From: Damien Lespiau <damien.lespiau@intel.com>

Now that modes have flags to describe which 3d formats the sink
supports, it's time to test them.

The new test cycles through the supported 3D formats and paint 3D
stereoscopic images taken from publicly available samples:
  http://www.quantumdata.com/apps/3D/sample_BMP.asp

Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
---
 tests/testdisplay.c | 226 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 221 insertions(+), 5 deletions(-)

diff --git a/tests/testdisplay.c b/tests/testdisplay.c
index c52bb2f..e179c83 100644
--- a/tests/testdisplay.c
+++ b/tests/testdisplay.c
@@ -52,6 +52,7 @@
 #include <errno.h>
 #include <math.h>
 #include <stdint.h>
+#include <strings.h>
 #include <unistd.h>
 #include <sys/poll.h>
 #include <sys/time.h>
@@ -68,7 +69,7 @@
 drmModeRes *resources;
 int drm_fd, modes;
 int dump_info = 0, test_all_modes =0, test_preferred_mode = 0, force_mode = 0,
-	test_plane, enable_tiling;
+	test_plane, test_3d_modes, enable_tiling;
 int sleep_between_modes = 5;
 uint32_t depth = 24, stride, bpp;
 int qr_code = 0;
@@ -153,8 +154,51 @@ struct connector {
 	drmModeConnector *connector;
 	int crtc;
 	int pipe;
+
+	/* stereo 3d */
+	int s3d_format;
+	char s3d_image[32];
 };
 
+static bool connector_expose_3d(uint32_t connector_id, bool enable)
+{
+	drmModeConnector *connector;
+	drmModePropertyRes *property;
+	bool status = false;
+	int i;
+
+	connector = drmModeGetConnector(drm_fd, connector_id);
+	if (connector->count_props == 0)
+		return false;
+
+	for (i = 0; i < connector->count_props; i++) {
+		property = drmModeGetProperty(drm_fd, connector->props[i]);
+		if (!property)
+			continue;
+
+		if (strcmp(property->name, "expose 3D modes") == 0) {
+			if (drmModeConnectorSetProperty(drm_fd,
+							connector_id,
+							property->prop_id,
+							enable))
+				fprintf(stderr, "failed to set the \"expose 3D "
+					"modes\" property on connector %d: %s\n",
+					connector_id, strerror(errno));
+			else
+				status = true;
+			drmModeFreeProperty(property);
+			goto out;
+		}
+
+		drmModeFreeProperty(property);
+		property = NULL;
+	}
+
+out:
+	drmModeFreeConnector(connector);
+	return status;
+}
+
 static void dump_connectors_fd(int drmfd)
 {
 	int i, j;
@@ -172,11 +216,13 @@ static void dump_connectors_fd(int drmfd)
 	for (i = 0; i < mode_resources->count_connectors; i++) {
 		drmModeConnector *connector;
 
+		connector_expose_3d(mode_resources->connectors[i], TRUE);
+
 		connector = drmModeGetConnector(drmfd, mode_resources->connectors[i]);
 		if (!connector) {
 			fprintf(stderr, "could not get connector %i: %s\n",
 				mode_resources->connectors[i], strerror(errno));
-			continue;
+			goto next;
 		}
 
 		printf("%d\t%d\t%s\t%s\t%dx%d\t\t%d\n",
@@ -188,7 +234,7 @@ static void dump_connectors_fd(int drmfd)
 		       connector->count_modes);
 
 		if (!connector->count_modes)
-			continue;
+			goto next;
 
 		printf("  modes:\n");
 		printf("  name refresh (Hz) hdisp hss hse htot vdisp "
@@ -197,6 +243,9 @@ static void dump_connectors_fd(int drmfd)
 			kmstest_dump_mode(&connector->modes[j]);
 
 		drmModeFreeConnector(connector);
+
+next:
+		connector_expose_3d(mode_resources->connectors[i], FALSE);
 	}
 	printf("\n");
 
@@ -554,6 +603,154 @@ set_mode(struct connector *c)
 	drmModeFreeConnector(c->connector);
 }
 
+static void
+paint_3d_image(cairo_t *cr, int l_width, int l_height, void *priv)
+{
+	struct connector *c = priv;
+	cairo_surface_t *image;
+
+	image = cairo_image_surface_create_from_png(c->s3d_image);
+
+	cairo_set_source_surface(cr, image, 0, 0);
+	cairo_paint(cr);
+
+	cairo_surface_destroy(image);
+}
+
+static void adjust_3d_timings(drmModeModeInfo *mode, unsigned int format)
+{
+	uint16_t vdisplay, vactive_space;
+
+	/* just set the 3D format we are setting (this is not used by the
+	 * kernel, it's just for kmstest_dump_mode()) */
+	mode->flags &= ~DRM_MODE_FLAG_3D_MASK;
+	mode->flags |= format;
+
+	switch (format) {
+	case DRM_MODE_FLAG_3D_TOP_BOTTOM:
+	case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF:
+		return;
+	case DRM_MODE_FLAG_3D_FRAME_PACKING:
+		vactive_space = mode->vtotal - mode->vdisplay;
+		vdisplay = mode->vdisplay;
+
+		mode->vdisplay += vdisplay + vactive_space;
+		mode->vsync_start += vdisplay + vactive_space;
+		mode->vsync_end += vdisplay + vactive_space;
+		mode->vtotal += vdisplay + vactive_space;
+		mode->clock = (mode->vtotal * mode->htotal * mode->vrefresh) /
+			      1000;
+		return;
+	default:
+		assert(0);
+	}
+}
+
+static const char *s3d_format_str(unsigned int format)
+{
+	switch(format) {
+	case DRM_MODE_FLAG_3D_TOP_BOTTOM:
+		return "TB";
+	case DRM_MODE_FLAG_3D_FRAME_PACKING:
+		return "FP";
+	}
+
+	return "Unknown format";
+}
+
+static void do_set_3d_format(struct connector *c, unsigned int format)
+{
+	uint32_t fb_id;
+	struct kmstest_fb fb_info;
+
+	snprintf(c->s3d_image, sizeof(c->s3d_image), "%d%s.png",
+		 c->mode.vdisplay, s3d_format_str(format));
+
+	adjust_3d_timings(&c->mode, format);
+	width = c->mode.hdisplay;
+	height = c->mode.vdisplay;
+
+	fb_id = kmstest_create_fb(drm_fd, width, height, bpp, depth,
+				  enable_tiling, &fb_info,
+				  paint_3d_image, c);
+
+	fb_ptr = gem_mmap(drm_fd, fb_info.gem_handle,
+			  fb_info.size, PROT_READ | PROT_WRITE);
+	assert(fb_ptr);
+
+	gem_close(drm_fd, fb_info.gem_handle);
+
+	kmstest_dump_mode(&c->mode);
+
+	if (drmModeSetCrtc(drm_fd, c->crtc, fb_id, 0, 0,
+			   &c->id, 1, &c->mode)) {
+		fprintf(stderr, "failed to set mode (%dx%d@%dHz): %s\n",
+			width, height, c->mode.vrefresh,
+			strerror(errno));
+	}
+}
+
+static void
+set_3d_modes(struct connector *c)
+{
+	int i;
+
+	if (depth <= 8)
+		bpp = 8;
+	else if (depth > 8 && depth <= 16)
+		bpp = 16;
+	else if (depth > 16 && depth <= 32)
+		bpp = 32;
+
+	connector_find_preferred_mode(c);
+	if (!c->mode_valid)
+		return;
+
+	for (i = 0; i < c->connector->count_modes; i++) {
+		unsigned int s3d_formats, format;
+
+		c->mode = c->connector->modes[i];
+
+		if (!c->mode_valid)
+			continue;
+
+		if (c->mode.flags & DRM_MODE_FLAG_INTERLACE)
+			continue;
+
+		s3d_formats = c->mode.flags & DRM_MODE_FLAG_3D_MASK;
+		if (!s3d_formats)
+			continue;
+
+		do {
+			format = 1 << (ffs(s3d_formats) - 1);
+
+			/* Modify the mode flags to specify which 3D format is
+			 * being set.
+			 *
+			 * XXX: One would need to also clear the upper bits of
+			 * flags in case extra modes/flags are added
+			 */
+			c->mode.flags &= ~DRM_MODE_FLAG_3D_MASK;
+			c->mode.flags |= format;
+
+			do_set_3d_format(c, format);
+
+			if (qr_code){
+				set_single();
+				pause();
+			} else if (sleep_between_modes) {
+				sleep(sleep_between_modes);
+			}
+
+			s3d_formats &= ~(format);
+		} while (s3d_formats);
+
+	}
+
+	drmModeFreeEncoder(c->encoder);
+	drmModeFreeConnector(c->connector);
+}
+
 /*
  * Re-probe outputs and light up as many as possible.
  *
@@ -592,11 +789,26 @@ int update_display(void)
 			set_mode(&connectors[c]);
 		}
 	}
+
+	if (test_all_modes || test_3d_modes) {
+		/* Find connectors that can expose 3D modes */
+		for (c = 0; c < resources->count_connectors; c++) {
+			connectors[c].id = resources->connectors[c];
+
+			if (!connector_expose_3d(connectors[c].id, TRUE))
+				continue;
+
+			set_3d_mods(&connectors[c]);
+
+			connector_expose_3d(connectors[c].id, FALSE);
+		}
+	}
+
 	drmModeFreeResources(resources);
 	return 1;
 }
 
-static char optstr[] = "hiaf:s:d:p:mrt";
+static char optstr[] = "3hiaf:s:d:p:mrt";
 
 static void __attribute__((noreturn)) usage(char *name)
 {
@@ -607,6 +819,7 @@ static void __attribute__((noreturn)) usage(char *name)
 	fprintf(stderr, "\t-d\t<depth>\tbit depth of scanout buffer\n");
 	fprintf(stderr, "\t-p\t<planew,h>,<crtcx,y>,<crtcw,h> test overlay plane\n");
 	fprintf(stderr, "\t-m\ttest the preferred mode\n");
+	fprintf(stderr, "\t-3\ttest all 3D modes\n");
 	fprintf(stderr, "\t-t\tuse a tiled framebuffer\n");
 	fprintf(stderr, "\t-r\tprint a QR code on the screen whose content is \"pass\" for the automatic test\n");
 	fprintf(stderr, "\t-f\t<clock MHz>,<hdisp>,<hsync-start>,<hsync-end>,<htotal>,\n");
@@ -663,6 +876,9 @@ int main(int argc, char **argv)
 	opterr = 0;
 	while ((c = getopt(argc, argv, optstr)) != -1) {
 		switch (c) {
+		case '3':
+			test_3d_modes = 1;
+			break;
 		case 'i':
 			dump_info = 1;
 			break;
@@ -710,7 +926,7 @@ int main(int argc, char **argv)
 		}
 	}
 	if (!test_all_modes && !force_mode && !dump_info &&
-	    !test_preferred_mode)
+	    !test_preferred_mode && !test_3d_modes)
 		test_all_modes = 1;
 
 	drm_fd = drm_open_any();
-- 
1.7.11.4

  reply	other threads:[~2012-09-27 18:42 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-27 18:42 [PATCH 1/2] lib: Dump information about the supported 3D stereo formats Damien Lespiau
2012-09-27 18:42 ` Damien Lespiau [this message]
2012-09-29  0:43   ` [PATCH 2/2] tests/testdisplay: Test the stereo 3D modes Rodrigo Vivi
2012-09-29  0:45 ` [PATCH 1/2] lib: Dump information about the supported 3D stereo formats Rodrigo Vivi
  -- strict thread matches above, loose matches on Subject: below --
2012-09-12 18:07 [PATCH 2/2] tests/testdisplay: Test the stereo 3D modes Lespiau, Damien
2012-09-12 17:48 [PATCH 1/2] lib: Dump information about the supported 3D stereo formats Damien Lespiau
2012-09-12 17:48 ` [PATCH 2/2] tests/testdisplay: Test the stereo 3D modes Damien Lespiau
2012-09-14 16:35   ` Kristian Høgsberg

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=1348771328-3655-2-git-send-email-damien.lespiau@gmail.com \
    --to=damien.lespiau@gmail.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

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

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.