all: include config.h only when available and use its defines
[platform/upstream/libdrm.git] / tests / modetest / modetest.c
index f96b930..92efb82 100644 (file)
@@ -37,7 +37,9 @@
  * TODO: use cairo to write the mode info on the selected output once
  *       the mode has been programmed, along with possible test patterns.
  */
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #include <assert.h>
 #include <ctype.h>
@@ -58,6 +60,7 @@
 #include "libkms.h"
 
 #include "buffers.h"
+#include "cursor.h"
 
 struct crtc {
        drmModeCrtc *crtc;
@@ -693,6 +696,7 @@ struct pipe_arg {
        uint32_t crtc_id;
        char mode_str[64];
        char format_str[5];
+       unsigned int vrefresh;
        unsigned int fourcc;
        drmModeModeInfo *mode;
        struct crtc *crtc;
@@ -707,13 +711,15 @@ struct plane_arg {
        bool has_position;
        int32_t x, y;
        uint32_t w, h;
+       double scale;
        unsigned int fb_id;
        char format_str[5]; /* need to leave room for terminating \0 */
        unsigned int fourcc;
 };
 
 static drmModeModeInfo *
-connector_find_mode(struct device *dev, uint32_t con_id, const char *mode_str)
+connector_find_mode(struct device *dev, uint32_t con_id, const char *mode_str,
+        const unsigned int vrefresh)
 {
        drmModeConnector *connector;
        drmModeModeInfo *mode;
@@ -725,8 +731,16 @@ connector_find_mode(struct device *dev, uint32_t con_id, const char *mode_str)
 
        for (i = 0; i < connector->count_modes; i++) {
                mode = &connector->modes[i];
-               if (!strcmp(mode->name, mode_str))
-                       return mode;
+               if (!strcmp(mode->name, mode_str)) {
+                       /* If the vertical refresh frequency is not specified then return the
+                        * first mode that match with the name. Else, return the mode that match
+                        * the name and the specified vertical refresh frequency.
+                        */
+                       if (vrefresh == 0)
+                               return mode;
+                       else if (mode->vrefresh == vrefresh)
+                               return mode;
+               }
        }
 
        return NULL;
@@ -781,14 +795,14 @@ static struct crtc *pipe_find_crtc(struct device *dev, struct pipe_arg *pipe)
 
 static int pipe_find_crtc_and_mode(struct device *dev, struct pipe_arg *pipe)
 {
-       drmModeModeInfo *mode;
+       drmModeModeInfo *mode = NULL;
        int i;
 
        pipe->mode = NULL;
 
        for (i = 0; i < (int)pipe->num_cons; i++) {
                mode = connector_find_mode(dev, pipe->con_ids[i],
-                                          pipe->mode_str);
+                                          pipe->mode_str, pipe->vrefresh);
                if (mode == NULL) {
                        fprintf(stderr,
                                "failed to find mode \"%s\" for connector %u\n",
@@ -838,8 +852,8 @@ struct property_arg {
 
 static void set_property(struct device *dev, struct property_arg *p)
 {
-       drmModeObjectProperties *props;
-       drmModePropertyRes **props_info;
+       drmModeObjectProperties *props = NULL;
+       drmModePropertyRes **props_info = NULL;
        const char *obj_type;
        int ret;
        int i;
@@ -988,16 +1002,16 @@ static int set_plane(struct device *dev, struct plane_arg *p)
                return -1;
        }
 
+       crtc_w = p->w * p->scale;
+       crtc_h = p->h * p->scale;
        if (!p->has_position) {
                /* Default to the middle of the screen */
-               crtc_x = (crtc->mode->hdisplay - p->w) / 2;
-               crtc_y = (crtc->mode->vdisplay - p->h) / 2;
+               crtc_x = (crtc->mode->hdisplay - crtc_w) / 2;
+               crtc_y = (crtc->mode->vdisplay - crtc_h) / 2;
        } else {
                crtc_x = p->x;
                crtc_y = p->y;
        }
-       crtc_w = p->w;
-       crtc_h = p->h;
 
        /* note src coords (last 4 args) are in Q16 format */
        if (drmModeSetPlane(dev->fd, plane_id, crtc->crtc->crtc_id, p->fb_id,
@@ -1058,8 +1072,8 @@ static void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int co
                if (pipe->mode == NULL)
                        continue;
 
-               printf("setting mode %s@%s on connectors ",
-                      pipe->mode_str, pipe->format_str);
+               printf("setting mode %s-%dHz@%s on connectors ",
+                      pipe->mode_str, pipe->mode->vrefresh, pipe->format_str);
                for (j = 0; j < pipe->num_cons; ++j)
                        printf("%u, ", pipe->con_ids[j]);
                printf("crtc %d\n", pipe->crtc->crtc->crtc_id);
@@ -1093,6 +1107,46 @@ static void set_planes(struct device *dev, struct plane_arg *p, unsigned int cou
                        return;
 }
 
+static void set_cursors(struct device *dev, struct pipe_arg *pipes, unsigned int count)
+{
+       uint32_t handles[4], pitches[4], offsets[4] = {0}; /* we only use [0] */
+       struct kms_bo *bo;
+       unsigned int i;
+       int ret;
+
+       /* maybe make cursor width/height configurable some day */
+       uint32_t cw = 64;
+       uint32_t ch = 64;
+
+       /* create cursor bo.. just using PATTERN_PLAIN as it has
+        * translucent alpha
+        */
+       bo = create_test_buffer(dev->kms, DRM_FORMAT_ARGB8888,
+                       cw, ch, handles, pitches, offsets, PATTERN_PLAIN);
+       if (bo == NULL)
+               return;
+
+       for (i = 0; i < count; i++) {
+               struct pipe_arg *pipe = &pipes[i];
+               ret = cursor_init(dev->fd, handles[0],
+                               pipe->crtc->crtc->crtc_id,
+                               pipe->mode->hdisplay, pipe->mode->vdisplay,
+                               cw, ch);
+               if (ret) {
+                       fprintf(stderr, "failed to init cursor for CRTC[%u]\n",
+                                       pipe->crtc_id);
+                       return;
+               }
+       }
+
+       cursor_start();
+}
+
+static void clear_cursors(struct device *dev)
+{
+       cursor_stop();
+}
+
 static void test_page_flip(struct device *dev, struct pipe_arg *pipes, unsigned int count)
 {
        uint32_t handles[4], pitches[4], offsets[4] = {0}; /* we only use [0] */
@@ -1191,6 +1245,7 @@ static int parse_connector(struct pipe_arg *pipe, const char *arg)
        const char *p;
        char *endp;
 
+       pipe->vrefresh = 0;
        pipe->crtc_id = (uint32_t)-1;
        strcpy(pipe->format_str, "XR24");
 
@@ -1225,11 +1280,19 @@ static int parse_connector(struct pipe_arg *pipe, const char *arg)
 
        arg = endp + 1;
 
-       p = strchrnul(arg, '@');
+       /* Search for the vertical refresh or the format. */
+       p = strpbrk(arg, "-@");
+       if (p == NULL)
+               p = arg + strlen(arg);
        len = min(sizeof pipe->mode_str - 1, (unsigned int)(p - arg));
        strncpy(pipe->mode_str, arg, len);
        pipe->mode_str[len] = '\0';
 
+       if (*p == '-') {
+               pipe->vrefresh = strtoul(p + 1, &endp, 10);
+               p = endp;
+       }
+
        if (*p == '@') {
                strncpy(pipe->format_str, p + 1, 4);
                pipe->format_str[4] = '\0';
@@ -1271,6 +1334,15 @@ static int parse_plane(struct plane_arg *plane, const char *p)
                plane->has_position = true;
        }
 
+       if (*end == '*') {
+               p = end + 1;
+               plane->scale = strtod(p, &end);
+               if (plane->scale <= 0.0)
+                       return -EINVAL;
+       } else {
+               plane->scale = 1.0;
+       }
+
        if (*end == '@') {
                p = end + 1;
                if (strlen(p) != 4)
@@ -1303,7 +1375,7 @@ static int parse_property(struct property_arg *p, const char *arg)
 
 static void usage(char *name)
 {
-       fprintf(stderr, "usage: %s [-cdefMmPpsvw]\n", name);
+       fprintf(stderr, "usage: %s [-cDdefMPpsCvw]\n", name);
 
        fprintf(stderr, "\n Query options:\n\n");
        fprintf(stderr, "\t-c\tlist connectors\n");
@@ -1312,14 +1384,16 @@ static void usage(char *name)
        fprintf(stderr, "\t-p\tlist CRTCs and planes (pipes)\n");
 
        fprintf(stderr, "\n Test options:\n\n");
-       fprintf(stderr, "\t-P <crtc_id>:<w>x<h>[+<x>+<y>][@<format>]\tset a plane\n");
-       fprintf(stderr, "\t-s <connector_id>[,<connector_id>][@<crtc_id>]:<mode>[@<format>]\tset a mode\n");
+       fprintf(stderr, "\t-P <crtc_id>:<w>x<h>[+<x>+<y>][*<scale>][@<format>]\tset a plane\n");
+       fprintf(stderr, "\t-s <connector_id>[,<connector_id>][@<crtc_id>]:<mode>[-<vrefresh>][@<format>]\tset a mode\n");
+       fprintf(stderr, "\t-C\ttest hw cursor\n");
        fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
        fprintf(stderr, "\t-w <obj_id>:<prop_name>:<value>\tset property\n");
 
        fprintf(stderr, "\n Generic options:\n\n");
        fprintf(stderr, "\t-d\tdrop master after mode set\n");
        fprintf(stderr, "\t-M module\tuse the given driver\n");
+       fprintf(stderr, "\t-D device\tuse the given device\n");
 
        fprintf(stderr, "\n\tDefault is to dump all info.\n");
        exit(0);
@@ -1346,7 +1420,13 @@ static int page_flipping_supported(void)
 #endif
 }
 
-static char optstr[] = "cdefM:P:ps:vw:";
+static int cursor_supported(void)
+{
+       /*FIXME: generic ioctl needed? */
+       return 1;
+}
+
+static char optstr[] = "cdD:efM:P:ps:Cvw:";
 
 int main(int argc, char **argv)
 {
@@ -1356,7 +1436,9 @@ int main(int argc, char **argv)
        int encoders = 0, connectors = 0, crtcs = 0, planes = 0, framebuffers = 0;
        int drop_master = 0;
        int test_vsync = 0;
-       const char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", "tilcdc" };
+       int test_cursor = 0;
+       const char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", "tilcdc", "msm" };
+       char *device = NULL;
        char *module = NULL;
        unsigned int i;
        int count = 0, plane_count = 0;
@@ -1377,6 +1459,10 @@ int main(int argc, char **argv)
                case 'c':
                        connectors = 1;
                        break;
+               case 'D':
+                       device = optarg;
+                       args--;
+                       break;
                case 'd':
                        drop_master = 1;
                        break;
@@ -1421,6 +1507,9 @@ int main(int argc, char **argv)
 
                        count++;                                      
                        break;
+               case 'C':
+                       test_cursor = 1;
+                       break;
                case 'v':
                        test_vsync = 1;
                        break;
@@ -1447,7 +1536,7 @@ int main(int argc, char **argv)
                encoders = connectors = crtcs = planes = framebuffers = 1;
 
        if (module) {
-               dev.fd = drmOpen(module, NULL);
+               dev.fd = drmOpen(module, device);
                if (dev.fd < 0) {
                        fprintf(stderr, "failed to open device '%s'.\n", module);
                        return 1;
@@ -1455,7 +1544,7 @@ int main(int argc, char **argv)
        } else {
                for (i = 0; i < ARRAY_SIZE(modules); i++) {
                        printf("trying to open device '%s'...", modules[i]);
-                       dev.fd = drmOpen(modules[i], NULL);
+                       dev.fd = drmOpen(modules[i], device);
                        if (dev.fd < 0) {
                                printf("failed.\n");
                        } else {
@@ -1480,6 +1569,11 @@ int main(int argc, char **argv)
                return -1;
        }
 
+       if (test_cursor && !cursor_supported()) {
+               fprintf(stderr, "hw cursor not supported by drm.\n");
+               return -1;
+       }
+
        dev.resources = get_resources(&dev);
        if (!dev.resources) {
                drmClose(dev.fd);
@@ -1511,16 +1605,22 @@ int main(int argc, char **argv)
                if (plane_count)
                        set_planes(&dev, plane_args, plane_count);
 
+               if (test_cursor)
+                       set_cursors(&dev, pipe_args, count);
+
                if (test_vsync)
                        test_page_flip(&dev, pipe_args, count);
 
                if (drop_master)
                        drmDropMaster(dev.fd);
 
+               getchar();
+
+               if (test_cursor)
+                       clear_cursors(&dev);
+
                kms_bo_destroy(&dev.mode.bo);
                kms_destroy(&dev.kms);
-
-               getchar();
        }
 
        free_resources(dev.resources);