From patchwork Thu Sep 27 18:42:08 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Lespiau X-Patchwork-Id: 1515551 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork1.kernel.org (Postfix) with ESMTP id F01BD3FC71 for ; Thu, 27 Sep 2012 18:50:40 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id F23CCA086B for ; Thu, 27 Sep 2012 11:50:40 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-wi0-f171.google.com (mail-wi0-f171.google.com [209.85.212.171]) by gabe.freedesktop.org (Postfix) with ESMTP id 31E8A9E85C; Thu, 27 Sep 2012 11:42:15 -0700 (PDT) Received: by wibhj13 with SMTP id hj13so3085865wib.12 for ; Thu, 27 Sep 2012 11:42:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id:x-mailer:in-reply-to:references; bh=rhbSJS8PQ4TLyIFN/v29f5H6hhpIg7Y01nauVqp9rA4=; b=hfvDtV8PuWDklH4jEAxIDDqN4kGXS9QrSxe2g+8ZKfOeKa7WPejcI4y0nhp0BREv3p D0W+DHh916xkPJJXCkZsxWijwh6yrfCtUrGb/KIpfxn8n5K60spK0rxAhn0GFevXrPAB CidExRvxDh9T+0aEGlbhypwhPcnkgog3bU2TGqzhRtWoKFQp74ySmx1mUz0zjGIYZ3Ja OI8W13v5xtQFR77U3iriq+mtN/7NsKkPRmN/HhFs2J6tFCTAUm46NeYpJmaLmfV7XkXw SErnptT6pXrne1FRWQTvOAMHWJ0WDy2eUMONAZvgEhc2VSLxx8bqDDXWGWu9sTI8bRxj WbgQ== Received: by 10.216.53.193 with SMTP id g43mr1796385wec.67.1348771334080; Thu, 27 Sep 2012 11:42:14 -0700 (PDT) Received: from localhost.localdomain ([83.217.123.106]) by mx.google.com with ESMTPS id cn6sm5435409wib.9.2012.09.27.11.42.12 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 27 Sep 2012 11:42:13 -0700 (PDT) From: Damien Lespiau 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 Message-Id: <1348771328-3655-2-git-send-email-damien.lespiau@gmail.com> X-Mailer: git-send-email 1.7.11.4 In-Reply-To: <1348771328-3655-1-git-send-email-damien.lespiau@gmail.com> References: <1348771328-3655-1-git-send-email-damien.lespiau@gmail.com> X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org From: Damien Lespiau 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 Reviewed-by: Rodrigo Vivi Tested-by: Rodrigo Vivi --- 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 #include #include +#include #include #include #include @@ -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\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-f\t,,,,,\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();