[PATCH 2/2] tests/testdisplay: Test the stereo 3D modes

Rodrigo Vivi rodrigo.vivi at gmail.com
Fri Sep 28 17:43:52 PDT 2012


On Thu, Sep 27, 2012 at 3:42 PM, Damien Lespiau
<damien.lespiau at gmail.com> wrote:
> From: Damien Lespiau <damien.lespiau at 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 at 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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


Reviewed-by: Rodrigo Vivi <rodrigo.vivi at gmail.com>
Tested-by: Rodrigo Vivi <rodrigo.vivi at gmail.com>

-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br


More information about the dri-devel mailing list