kmscube: add command-line selection of video mode
The mode of type "DRM_MODE_TYPE_PREFERED" can be miss-configured,
making kmscube not working.
Plus, user could need to test the other available video modes at
the connector.
Add a command line flag to specify the video mode. If the mode is
not present, print an informative message and fall-back to the
default behaviour (preferred mode or highest resolution mode).
Signed-off-by: Antonio Borneo <antonio.borneo@st.com>
Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
Antonio Borneo authored 5 years ago
Antonio Borneo committed 4 years ago
336 | 336 | return ret; |
337 | 337 | } |
338 | 338 | |
339 | const struct drm * init_drm_atomic(const char *device) | |
339 | const struct drm * init_drm_atomic(const char *device, const char *mode_str, unsigned int vrefresh) | |
340 | 340 | { |
341 | 341 | uint32_t plane_id; |
342 | 342 | int ret; |
343 | 343 | |
344 | ret = init_drm(&drm, device); | |
344 | ret = init_drm(&drm, device, mode_str, vrefresh); | |
345 | 345 | if (ret) |
346 | 346 | return NULL; |
347 | 347 |
159 | 159 | return -1; |
160 | 160 | } |
161 | 161 | |
162 | int init_drm(struct drm *drm, const char *device) | |
162 | int init_drm(struct drm *drm, const char *device, const char *mode_str, unsigned int vrefresh) | |
163 | 163 | { |
164 | 164 | drmModeRes *resources; |
165 | 165 | drmModeConnector *connector = NULL; |
198 | 198 | return -1; |
199 | 199 | } |
200 | 200 | |
201 | /* find user requested mode: */ | |
202 | if (mode_str && *mode_str) { | |
203 | for (i = 0; i < connector->count_modes; i++) { | |
204 | drmModeModeInfo *current_mode = &connector->modes[i]; | |
205 | ||
206 | if (strcmp(current_mode->name, mode_str) == 0) { | |
207 | if (vrefresh == 0 || current_mode->vrefresh == vrefresh) { | |
208 | drm->mode = current_mode; | |
209 | break; | |
210 | } | |
211 | } | |
212 | } | |
213 | if (!drm->mode) | |
214 | printf("requested mode not found, using default mode!\n"); | |
215 | } | |
216 | ||
201 | 217 | /* find preferred mode or the highest resolution mode: */ |
202 | for (i = 0, area = 0; i < connector->count_modes; i++) { | |
203 | drmModeModeInfo *current_mode = &connector->modes[i]; | |
204 | ||
205 | if (current_mode->type & DRM_MODE_TYPE_PREFERRED) { | |
206 | drm->mode = current_mode; | |
207 | break; | |
208 | } | |
209 | ||
210 | int current_area = current_mode->hdisplay * current_mode->vdisplay; | |
211 | if (current_area > area) { | |
212 | drm->mode = current_mode; | |
213 | area = current_area; | |
218 | if (!drm->mode) { | |
219 | for (i = 0, area = 0; i < connector->count_modes; i++) { | |
220 | drmModeModeInfo *current_mode = &connector->modes[i]; | |
221 | ||
222 | if (current_mode->type & DRM_MODE_TYPE_PREFERRED) { | |
223 | drm->mode = current_mode; | |
224 | break; | |
225 | } | |
226 | ||
227 | int current_area = current_mode->hdisplay * current_mode->vdisplay; | |
228 | if (current_area > area) { | |
229 | drm->mode = current_mode; | |
230 | area = current_area; | |
231 | } | |
214 | 232 | } |
215 | 233 | } |
216 | 234 |
72 | 72 | |
73 | 73 | struct drm_fb * drm_fb_get_from_bo(struct gbm_bo *bo); |
74 | 74 | |
75 | int init_drm(struct drm *drm, const char *device); | |
76 | const struct drm * init_drm_legacy(const char *device); | |
77 | const struct drm * init_drm_atomic(const char *device); | |
75 | int init_drm(struct drm *drm, const char *device, const char *mode_str, unsigned int vrefresh); | |
76 | const struct drm * init_drm_legacy(const char *device, const char *mode_str, unsigned int vrefresh); | |
77 | const struct drm * init_drm_atomic(const char *device, const char *mode_str, unsigned int vrefresh); | |
78 | 78 | |
79 | 79 | #endif /* _DRM_COMMON_H */ |
121 | 121 | return 0; |
122 | 122 | } |
123 | 123 | |
124 | const struct drm * init_drm_legacy(const char *device) | |
124 | const struct drm * init_drm_legacy(const char *device, const char *mode_str, unsigned int vrefresh) | |
125 | 125 | { |
126 | 126 | int ret; |
127 | 127 | |
128 | ret = init_drm(&drm, device); | |
128 | ret = init_drm(&drm, device, mode_str, vrefresh); | |
129 | 129 | if (ret) |
130 | 130 | return NULL; |
131 | 131 |
40 | 40 | static const struct gbm *gbm; |
41 | 41 | static const struct drm *drm; |
42 | 42 | |
43 | static const char *shortopts = "AD:M:m:V:"; | |
43 | static const char *shortopts = "AD:M:m:V:v:"; | |
44 | 44 | |
45 | 45 | static const struct option longopts[] = { |
46 | 46 | {"atomic", no_argument, 0, 'A'}, |
49 | 49 | {"modifier", required_argument, 0, 'm'}, |
50 | 50 | {"samples", required_argument, 0, 's'}, |
51 | 51 | {"video", required_argument, 0, 'V'}, |
52 | {"vmode", required_argument, 0, 'v'}, | |
52 | 53 | {0, 0, 0, 0} |
53 | 54 | }; |
54 | 55 | |
55 | 56 | static void usage(const char *name) |
56 | 57 | { |
57 | printf("Usage: %s [-ADMmV]\n" | |
58 | printf("Usage: %s [-ADMmVv]\n" | |
58 | 59 | "\n" |
59 | 60 | "options:\n" |
60 | 61 | " -A, --atomic use atomic modesetting and fencing\n" |
66 | 67 | " nv12-1img - yuv textured (single nv12 texture)\n" |
67 | 68 | " -m, --modifier=MODIFIER hardcode the selected modifier\n" |
68 | 69 | " -s, --samples=N use MSAA\n" |
69 | " -V, --video=FILE video textured cube\n", | |
70 | " -V, --video=FILE video textured cube\n" | |
71 | " -v, --vmode=VMODE specify the video mode in the format\n" | |
72 | " <mode>[-<vrefresh>]\n", | |
70 | 73 | name); |
71 | 74 | } |
72 | 75 | |
74 | 77 | { |
75 | 78 | const char *device = "/dev/dri/card0"; |
76 | 79 | const char *video = NULL; |
80 | char mode_str[DRM_DISPLAY_MODE_LEN] = ""; | |
81 | char *p; | |
77 | 82 | enum mode mode = SMOOTH; |
78 | 83 | uint64_t modifier = DRM_FORMAT_MOD_LINEAR; |
79 | 84 | int samples = 0; |
80 | 85 | int atomic = 0; |
81 | 86 | int opt; |
87 | unsigned int len; | |
88 | unsigned int vrefresh = 0; | |
82 | 89 | |
83 | 90 | #ifdef HAVE_GST |
84 | 91 | gst_init(&argc, &argv); |
118 | 125 | mode = VIDEO; |
119 | 126 | video = optarg; |
120 | 127 | break; |
128 | case 'v': | |
129 | p = strchr(optarg, '-'); | |
130 | if (p == NULL) { | |
131 | len = strlen(optarg); | |
132 | } else { | |
133 | vrefresh = strtoul(p + 1, NULL, 0); | |
134 | len = p - optarg; | |
135 | } | |
136 | if (len > sizeof(mode_str) - 1) | |
137 | len = sizeof(mode_str) - 1; | |
138 | strncpy(mode_str, optarg, len); | |
139 | mode_str[len] = '\0'; | |
140 | break; | |
121 | 141 | default: |
122 | 142 | usage(argv[0]); |
123 | 143 | return -1; |
125 | 145 | } |
126 | 146 | |
127 | 147 | if (atomic) |
128 | drm = init_drm_atomic(device); | |
148 | drm = init_drm_atomic(device, mode_str, vrefresh); | |
129 | 149 | else |
130 | drm = init_drm_legacy(device); | |
150 | drm = init_drm_legacy(device, mode_str, vrefresh); | |
131 | 151 | if (!drm) { |
132 | 152 | printf("failed to initialize %s DRM\n", atomic ? "atomic" : "legacy"); |
133 | 153 | return -1; |