Message ID | 1348771328-3655-2-git-send-email-damien.lespiau@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Sep 27, 2012 at 3:42 PM, Damien Lespiau <damien.lespiau@gmail.com> wrote: > 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]); Typo here: set_3d_modes(&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 > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com> Tested-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
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();