From patchwork Fri Sep 6 19:08:50 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Lespiau, Damien" X-Patchwork-Id: 2855041 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 31AEEBF43F for ; Fri, 6 Sep 2013 19:19:10 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BFD6720319 for ; Fri, 6 Sep 2013 19:19:09 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 70CBC20318 for ; Fri, 6 Sep 2013 19:19:08 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 516A3E653A for ; Fri, 6 Sep 2013 12:19:08 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by gabe.freedesktop.org (Postfix) with ESMTP id D8398E63FD for ; Fri, 6 Sep 2013 12:09:37 -0700 (PDT) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga101.jf.intel.com with ESMTP; 06 Sep 2013 12:09:37 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.90,856,1371106800"; d="scan'208";a="374565021" Received: from unknown (HELO strange.amr.corp.intel.com) ([10.255.14.105]) by orsmga001.jf.intel.com with ESMTP; 06 Sep 2013 12:09:14 -0700 From: Damien Lespiau To: intel-gfx@lists.freedesktop.org Date: Fri, 6 Sep 2013 20:08:50 +0100 Message-Id: <1378494530-3600-13-git-send-email-damien.lespiau@intel.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1378494530-3600-1-git-send-email-damien.lespiau@intel.com> References: <1378494530-3600-1-git-send-email-damien.lespiau@intel.com> Subject: [Intel-gfx] [PATCH i-g-t 12/12] testdisplay: Test the stereo 3D modes X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org X-Spam-Status: No, score=-6.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- tests/testdisplay.c | 255 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 252 insertions(+), 3 deletions(-) diff --git a/tests/testdisplay.c b/tests/testdisplay.c index df3b4d4..a8b39fe 100644 --- a/tests/testdisplay.c +++ b/tests/testdisplay.c @@ -54,10 +54,13 @@ #include #include #include +#include #include #include #include #include +#include +#include #include "i915_drm.h" #include "drmtest.h" @@ -69,7 +72,7 @@ drmModeRes *resources; int drm_fd, modes; int test_all_modes = 0, test_preferred_mode = 0, force_mode = 0, test_plane, - enable_tiling; + test_3d_modes, enable_tiling; int sleep_between_modes = 5; uint32_t depth = 24, stride, bpp; int qr_code = 0; @@ -362,6 +365,9 @@ set_mode(struct connector *c) if (test_all_modes) c->mode = c->connector->modes[j]; + /* set_mode() only tests 2D modes */ + c->mode.flags &= ~DRMTEST_MODE_FLAG_3D_MASK; + if (!c->mode_valid) continue; @@ -404,6 +410,223 @@ set_mode(struct connector *c) drmModeFreeConnector(c->connector); } +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 &= ~DRMTEST_MODE_FLAG_3D_MASK; + mode->flags |= format; + + switch (format) { + case DRM_MODE_FLAG_3D_TOP_AND_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); + } +} + +struct box { + int x, y, width, height; +}; + +struct s3d_fb_layout { + int fb_width, fb_height; + struct box left, right; +}; + +static void box_init(struct box *box, int x, int y, int bwidth, int bheight) +{ + box->x = x; + box->y = y; + box->width = bwidth; + box->height = bheight; +} + +static void box_print(const char * prefix, struct box *box) +{ + printf("%s: %d, %d, %d, %d\n", prefix, + box->x, box->y, box->width, box->height); +} + +static void s3d_fb_layout_from_mode(struct s3d_fb_layout *layout, + drmModeModeInfo *mode) +{ + unsigned int format = mode->flags & DRMTEST_MODE_FLAG_3D_MASK; + const int hdisplay = mode->hdisplay, vdisplay = mode->vdisplay; + int middle; + + switch (format) { + case DRM_MODE_FLAG_3D_TOP_AND_BOTTOM: + layout->fb_width = hdisplay; + layout->fb_height = vdisplay; + + middle = vdisplay / 2; + box_init(&layout->left, 0, 0, hdisplay, middle); + box_init(&layout->right, + 0, middle, hdisplay, vdisplay - middle); + break; + case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF: + layout->fb_width = hdisplay; + layout->fb_height = vdisplay; + + middle = hdisplay / 2; + box_init(&layout->left, 0, 0, middle, vdisplay); + box_init(&layout->right, + middle, 0, hdisplay - middle, vdisplay); + break; + case DRM_MODE_FLAG_3D_FRAME_PACKING: + { + int vactive_space = mode->vtotal - vdisplay; + + layout->fb_width = hdisplay; + layout->fb_height = 2 * vdisplay + vactive_space; + + box_init(&layout->left, + 0, 0, hdisplay, vdisplay); + box_init(&layout->right, + 0, vdisplay + vactive_space, hdisplay, vdisplay); + break; + } + default: + assert(0); + } +} + +static const char *s3d_mode_str(unsigned format) +{ + switch (format) { + case DRM_MODE_FLAG_3D_TOP_AND_BOTTOM: + return "TB"; + case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF: + return "SbSH"; + case DRM_MODE_FLAG_3D_FRAME_PACKING: + return "FP"; + default: + assert(0); + } +} + +static uint32_t create_s3d_fb(drmModeModeInfo *mode, struct kmstest_fb *fb) +{ + struct s3d_fb_layout layout; + cairo_t *cr; + uint32_t fb_id; + + s3d_fb_layout_from_mode(&layout, mode); + box_print("left: ", &layout.left); + box_print("right: ", &layout.right); + fb_id = kmstest_create_fb(drm_fd, layout.fb_width, layout.fb_height, + bpp, depth, enable_tiling, fb); + cr = kmstest_get_cairo_ctx(drm_fd, fb); + + kmstest_paint_image(cr, IGT_DATADIR"/1080p-left.png", + layout.left.x, layout.left.y, + layout.left.width, layout.left.height); + kmstest_paint_image(cr, IGT_DATADIR"/1080p-right.png", + layout.right.x, layout.right.y, + layout.right.width, layout.right.height); + +#if 0 /* Comment this out if you want to see what the composited fb looks + like */ + { + char buffer[64]; + + snprintf(buffer, sizeof(buffer), "%dx%d@%dHz-%s.png", + mode->hdisplay, + mode->vdisplay, + mode->vrefresh, + s3d_mode_str(mode->flags & DRMTEST_MODE_FLAG_3D_MASK)); + + kmstest_write_fb(drm_fd, fb, buffer); + } +#endif + + return fb_id; +} + +static void do_set_3d_format(struct connector *c, unsigned int format) +{ + uint32_t fb_id; + struct kmstest_fb fb_info; + + fb_id = create_s3d_fb(&c->mode, &fb_info); + adjust_3d_timings(&c->mode, format); + + 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_mode(struct connector *c) +{ + int i; + + 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; + + s3d_formats = c->mode.flags & DRMTEST_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 &= ~DRMTEST_MODE_FLAG_3D_MASK; + c->mode.flags |= format; + + do_set_3d_format(c, format); + + /* + * The mode may have been adjusted for this format, + * reset it to its origin timings + */ + c->mode = c->connector->modes[i]; + + 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. * @@ -458,12 +681,29 @@ int update_display(void) } } + if (test_3d_modes) { + for (c = 0; c < resources->count_connectors; c++) { + struct connector *connector = &connectors[c]; + + connector->id = resources->connectors[c]; + + connector_find_preferred_mode(connector->id, + -1UL, + specified_mode_num, + connector); + if (!connector->mode_valid) + continue; + + set_3d_mode(connector); + } + } + free(connectors); drmModeFreeResources(resources); return 1; } -static char optstr[] = "hiaf:s:d:p:mrto:"; +static char optstr[] = "3hiaf:s:d:p:mrto:"; static void __attribute__((noreturn)) usage(char *name) { @@ -474,6 +714,7 @@ static void __attribute__((noreturn)) usage(char *name) fprintf(stderr, "\t-d\t\tbit depth of scanout buffer\n"); fprintf(stderr, "\t-p\t,, 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-o\t,\tonly test specified mode on the specified display\n"); @@ -536,6 +777,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': opt_dump_info = true; break; @@ -594,11 +838,16 @@ int main(int argc, char **argv) bpp = 32; if (!test_all_modes && !force_mode && !test_preferred_mode && - specified_mode_num == -1) + specified_mode_num == -1 && !test_3d_modes) test_all_modes = 1; drm_fd = drm_open_any(); + if (test_3d_modes && drmSetCap(drm_fd, DRM_CAP_STEREO_3D, 1) < 0) { + fprintf(stderr, "DRM_CAP_STEREO_3D isn't supported\n"); + goto out_close; + } + if (opt_dump_info) { dump_info(); goto out_close;