[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