blob: cf953860532eee2da97ac954b3135354e392497b [file] [log] [blame]
Gurchetan Singh0d714272017-01-26 11:58:49 -08001/*
2 * Copyright 2017 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
Haixia Shifc476462015-04-22 16:25:04 -07006
Gurchetan Singh0d714272017-01-26 11:58:49 -08007/*
8 * This file performs some sanity checks on the DRM atomic API. To run a test, please run the
9 * following command:
10 *
11 * atomictest <testname>
12 *
13 * To get a list of possible tests, run:
14 *
15 * atomictest
16 */
Haixia Shifc476462015-04-22 16:25:04 -070017
Gurchetan Singhe6afe0a2017-06-02 18:02:03 -070018#include <getopt.h>
19
Gurchetan Singh0d714272017-01-26 11:58:49 -080020#include "bs_drm.h"
Haixia Shifc476462015-04-22 16:25:04 -070021
Dongseong Hwang9093afe2017-03-20 19:16:28 -070022#define CHECK(cond) \
23 do { \
24 if (!(cond)) { \
25 bs_debug_error("check %s failed", #cond); \
26 return -1; \
27 } \
Gurchetan Singh0d714272017-01-26 11:58:49 -080028 } while (0)
29
Dongseong Hwang9093afe2017-03-20 19:16:28 -070030#define CHECK_RESULT(ret) \
31 do { \
32 if ((ret) < 0) { \
33 bs_debug_error("failed with error: %d", ret); \
34 return -1; \
35 } \
Gurchetan Singh0d714272017-01-26 11:58:49 -080036 } while (0)
37
38#define CURSOR_SIZE 64
39
40static const uint32_t yuv_formats[] = {
Gurchetan Singh07a45152017-04-27 18:08:18 -070041 DRM_FORMAT_NV12, DRM_FORMAT_UYVY, DRM_FORMAT_YUYV, DRM_FORMAT_YVU420,
Gurchetan Singh0d714272017-01-26 11:58:49 -080042};
43
44static struct gbm_device *gbm = NULL;
45
46static void page_flip_handler(int fd, unsigned int sequence, unsigned int tv_sec,
47 unsigned int tv_usec, void *user_data)
Haixia Shifc476462015-04-22 16:25:04 -070048{
Gurchetan Singh0d714272017-01-26 11:58:49 -080049 // Nothing to do.
Haixia Shifc476462015-04-22 16:25:04 -070050}
51
Gurchetan Singh0d714272017-01-26 11:58:49 -080052struct atomictest_property {
53 uint32_t pid;
54 uint32_t value;
55};
Haixia Shifc476462015-04-22 16:25:04 -070056
Gurchetan Singh0d714272017-01-26 11:58:49 -080057struct atomictest_plane {
58 drmModePlane drm_plane;
59 struct gbm_bo *bo;
Haixia Shifc476462015-04-22 16:25:04 -070060
Gurchetan Singh0d714272017-01-26 11:58:49 -080061 uint32_t format_idx;
62
63 /* Properties. */
64 struct atomictest_property crtc_id;
65 struct atomictest_property crtc_x;
66 struct atomictest_property crtc_y;
67 struct atomictest_property crtc_w;
68 struct atomictest_property crtc_h;
69 struct atomictest_property fb_id;
70 struct atomictest_property src_x;
71 struct atomictest_property src_y;
72 struct atomictest_property src_w;
73 struct atomictest_property src_h;
74 struct atomictest_property type;
75 struct atomictest_property zpos;
76};
77
78struct atomictest_connector {
79 uint32_t connector_id;
80 struct atomictest_property crtc_id;
81 struct atomictest_property edid;
82 struct atomictest_property dpms;
83};
84
85struct atomictest_crtc {
86 uint32_t crtc_id;
87 uint32_t width;
88 uint32_t height;
89 uint32_t *primary_idx;
90 uint32_t *cursor_idx;
91 uint32_t *overlay_idx;
92 uint32_t num_primary;
93 uint32_t num_cursor;
94 uint32_t num_overlay;
95
96 struct atomictest_plane *planes;
97 struct atomictest_property mode_id;
98 struct atomictest_property active;
99};
100
101struct atomictest_mode {
102 uint32_t height;
103 uint32_t width;
104 uint32_t id;
105};
106
107struct atomictest_context {
108 int fd;
109 uint32_t num_crtcs;
110 uint32_t num_connectors;
111 uint32_t num_modes;
112
113 struct atomictest_connector *connectors;
114 struct atomictest_crtc *crtcs;
115 struct atomictest_mode *modes;
Dominik Behre0f1c182016-01-25 14:38:22 -0800116 drmModeAtomicReqPtr pset;
Gurchetan Singh0d714272017-01-26 11:58:49 -0800117 drmEventContext drm_event_ctx;
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700118
119 struct bs_mapper *mapper;
Gurchetan Singh0d714272017-01-26 11:58:49 -0800120};
Haixia Shifc476462015-04-22 16:25:04 -0700121
Gurchetan Singhd61875a2017-06-02 17:03:19 -0700122typedef int (*test_function)(struct atomictest_context *ctx, struct atomictest_crtc *crtc);
123
124struct atomictest_testcase {
Gurchetan Singh0d714272017-01-26 11:58:49 -0800125 const char *name;
Gurchetan Singhd61875a2017-06-02 17:03:19 -0700126 test_function test_func;
Gurchetan Singh0d714272017-01-26 11:58:49 -0800127};
Haixia Shifc476462015-04-22 16:25:04 -0700128
Gurchetan Singhc3b543e2017-10-17 09:28:47 -0700129// clang-format off
130enum draw_format_type {
131 DRAW_NONE = 0,
132 DRAW_STRIPE = 1,
133 DRAW_ELLIPSE = 2,
134 DRAW_CURSOR = 3,
Gurchetan Singhe07faed2017-10-18 16:32:34 -0700135 DRAW_LINES = 4,
Gurchetan Singhc3b543e2017-10-17 09:28:47 -0700136};
137// clang-format on
138
Gurchetan Singh0d714272017-01-26 11:58:49 -0800139static int32_t get_format_idx(struct atomictest_plane *plane, uint32_t format)
140{
141 for (int32_t i = 0; i < plane->drm_plane.count_formats; i++)
142 if (plane->drm_plane.formats[i] == format)
143 return i;
144 return -1;
145}
146
147static void copy_drm_plane(drmModePlane *dest, drmModePlane *src)
148{
149 memcpy(dest, src, sizeof(drmModePlane));
150 dest->formats = calloc(src->count_formats, sizeof(uint32_t));
151 dest->format_modifiers =
152 calloc(src->count_format_modifiers, sizeof(struct drm_format_modifier));
153 memcpy(dest->formats, src->formats, src->count_formats * sizeof(uint32_t));
154 memcpy(dest->format_modifiers, src->format_modifiers,
155 src->count_format_modifiers * sizeof(struct drm_format_modifier));
156}
157
158static struct atomictest_plane *get_plane(struct atomictest_crtc *crtc, uint32_t idx, uint64_t type)
159{
160 uint32_t index;
161 switch (type) {
162 case DRM_PLANE_TYPE_OVERLAY:
163 index = crtc->overlay_idx[idx];
164 break;
165 case DRM_PLANE_TYPE_PRIMARY:
166 index = crtc->primary_idx[idx];
167 break;
168 case DRM_PLANE_TYPE_CURSOR:
169 index = crtc->cursor_idx[idx];
170 break;
171 default:
172 bs_debug_error("invalid plane type returned");
173 return NULL;
Haixia Shifc476462015-04-22 16:25:04 -0700174 }
175
Gurchetan Singh0d714272017-01-26 11:58:49 -0800176 return &crtc->planes[index];
177}
Haixia Shifc476462015-04-22 16:25:04 -0700178
Gurchetan Singhc3b543e2017-10-17 09:28:47 -0700179static int draw_to_plane(struct bs_mapper *mapper, struct atomictest_plane *plane,
180 enum draw_format_type pattern)
Gurchetan Singh0d714272017-01-26 11:58:49 -0800181{
Gurchetan Singhc3b543e2017-10-17 09:28:47 -0700182 struct gbm_bo *bo = plane->bo;
Gurchetan Singha676f1b2017-10-16 18:33:29 -0700183 uint32_t format = gbm_bo_get_format(bo);
184 const struct bs_draw_format *draw_format = bs_get_draw_format(format);
Gurchetan Singhc3b543e2017-10-17 09:28:47 -0700185
186 if (draw_format && pattern) {
187 switch (pattern) {
188 case DRAW_STRIPE:
189 CHECK(bs_draw_stripe(mapper, bo, draw_format));
190 break;
191 case DRAW_ELLIPSE:
192 CHECK(bs_draw_ellipse(mapper, bo, draw_format, 0));
193 break;
194 case DRAW_CURSOR:
195 CHECK(bs_draw_cursor(mapper, bo, draw_format));
196 break;
Gurchetan Singhe07faed2017-10-18 16:32:34 -0700197 case DRAW_LINES:
198 CHECK(bs_draw_lines(mapper, bo, draw_format));
199 break;
Gurchetan Singhc3b543e2017-10-17 09:28:47 -0700200 default:
201 bs_debug_error("invalid draw type");
202 return -1;
203 }
204 } else {
205 // DRM_FORMAT_RGB565 --> red, DRM_FORMAT_BGR565 --> blue,
206 // everything else --> something
207 void *map_data;
208 uint16_t value = 0xF800;
209 void *addr = bs_mapper_map(mapper, bo, 0, &map_data);
210 uint32_t num_shorts = gbm_bo_get_plane_size(bo, 0) / sizeof(uint16_t);
211 uint16_t *pixel = (uint16_t *)addr;
212
213 CHECK(addr);
214 for (uint32_t i = 0; i < num_shorts; i++)
215 pixel[i] = value;
216
217 bs_mapper_unmap(mapper, bo, map_data);
218 }
219
220 return 0;
Gurchetan Singh0d714272017-01-26 11:58:49 -0800221}
222
223static int get_prop(int fd, drmModeObjectPropertiesPtr props, const char *name,
224 struct atomictest_property *bs_prop)
225{
226 /* Property ID should always be > 0. */
227 bs_prop->pid = 0;
228 drmModePropertyPtr prop;
229 for (uint32_t i = 0; i < props->count_props; i++) {
230 if (bs_prop->pid)
231 break;
232
233 prop = drmModeGetProperty(fd, props->props[i]);
234 if (prop) {
235 if (!strcmp(prop->name, name)) {
236 bs_prop->pid = prop->prop_id;
237 bs_prop->value = props->prop_values[i];
238 }
239 drmModeFreeProperty(prop);
240 }
241 }
242
243 return (bs_prop->pid == 0) ? -1 : 0;
244}
245
246static int get_connector_props(int fd, struct atomictest_connector *connector,
247 drmModeObjectPropertiesPtr props)
248{
Gurchetan Singh476ce542017-06-02 09:06:01 -0700249 CHECK_RESULT(get_prop(fd, props, "CRTC_ID", &connector->crtc_id));
Gurchetan Singh0d714272017-01-26 11:58:49 -0800250 CHECK_RESULT(get_prop(fd, props, "EDID", &connector->edid));
251 CHECK_RESULT(get_prop(fd, props, "DPMS", &connector->dpms));
252 return 0;
253}
254
255static int get_crtc_props(int fd, struct atomictest_crtc *crtc, drmModeObjectPropertiesPtr props)
256{
257 CHECK_RESULT(get_prop(fd, props, "MODE_ID", &crtc->mode_id));
258 CHECK_RESULT(get_prop(fd, props, "ACTIVE", &crtc->active));
259 return 0;
260}
261
262static int get_plane_props(int fd, struct atomictest_plane *plane, drmModeObjectPropertiesPtr props)
263{
264 CHECK_RESULT(get_prop(fd, props, "CRTC_ID", &plane->crtc_id));
265 CHECK_RESULT(get_prop(fd, props, "FB_ID", &plane->fb_id));
266 CHECK_RESULT(get_prop(fd, props, "CRTC_X", &plane->crtc_x));
267 CHECK_RESULT(get_prop(fd, props, "CRTC_Y", &plane->crtc_y));
268 CHECK_RESULT(get_prop(fd, props, "CRTC_W", &plane->crtc_w));
269 CHECK_RESULT(get_prop(fd, props, "CRTC_H", &plane->crtc_h));
270 CHECK_RESULT(get_prop(fd, props, "SRC_X", &plane->src_x));
271 CHECK_RESULT(get_prop(fd, props, "SRC_Y", &plane->src_y));
272 CHECK_RESULT(get_prop(fd, props, "SRC_W", &plane->src_w));
273 CHECK_RESULT(get_prop(fd, props, "SRC_H", &plane->src_h));
274 CHECK_RESULT(get_prop(fd, props, "type", &plane->type));
275 return 0;
276}
277
278int set_connector_props(struct atomictest_connector *conn, drmModeAtomicReqPtr pset)
279{
280 uint32_t id = conn->connector_id;
Gurchetan Singh0d714272017-01-26 11:58:49 -0800281 CHECK_RESULT(drmModeAtomicAddProperty(pset, id, conn->crtc_id.pid, conn->crtc_id.value));
282 return 0;
283}
284
285int set_crtc_props(struct atomictest_crtc *crtc, drmModeAtomicReqPtr pset)
286{
287 uint32_t id = crtc->crtc_id;
288 CHECK_RESULT(drmModeAtomicAddProperty(pset, id, crtc->mode_id.pid, crtc->mode_id.value));
289 CHECK_RESULT(drmModeAtomicAddProperty(pset, id, crtc->active.pid, crtc->active.value));
290 return 0;
291}
292
293int set_plane_props(struct atomictest_plane *plane, drmModeAtomicReqPtr pset)
294{
295 uint32_t id = plane->drm_plane.plane_id;
296 CHECK_RESULT(drmModeAtomicAddProperty(pset, id, plane->crtc_id.pid, plane->crtc_id.value));
297 CHECK_RESULT(drmModeAtomicAddProperty(pset, id, plane->fb_id.pid, plane->fb_id.value));
298 CHECK_RESULT(drmModeAtomicAddProperty(pset, id, plane->crtc_x.pid, plane->crtc_x.value));
299 CHECK_RESULT(drmModeAtomicAddProperty(pset, id, plane->crtc_y.pid, plane->crtc_y.value));
300 CHECK_RESULT(drmModeAtomicAddProperty(pset, id, plane->crtc_w.pid, plane->crtc_w.value));
301 CHECK_RESULT(drmModeAtomicAddProperty(pset, id, plane->crtc_h.pid, plane->crtc_h.value));
302 CHECK_RESULT(drmModeAtomicAddProperty(pset, id, plane->src_x.pid, plane->src_x.value));
303 CHECK_RESULT(drmModeAtomicAddProperty(pset, id, plane->src_y.pid, plane->src_y.value));
304 CHECK_RESULT(drmModeAtomicAddProperty(pset, id, plane->src_w.pid, plane->src_w.value));
305 CHECK_RESULT(drmModeAtomicAddProperty(pset, id, plane->src_h.pid, plane->src_h.value));
306 return 0;
307}
308
309static int remove_plane_fb(struct atomictest_context *ctx, struct atomictest_plane *plane)
310{
311 if (plane->bo && plane->fb_id.value) {
312 CHECK_RESULT(drmModeRmFB(ctx->fd, plane->fb_id.value));
313 gbm_bo_destroy(plane->bo);
314 plane->bo = NULL;
315 plane->fb_id.value = 0;
316 }
317
318 return 0;
319}
320
321static int add_plane_fb(struct atomictest_context *ctx, struct atomictest_plane *plane)
322{
323 if (plane->format_idx < plane->drm_plane.count_formats) {
324 CHECK_RESULT(remove_plane_fb(ctx, plane));
325 uint32_t flags = (plane->type.value == DRM_PLANE_TYPE_CURSOR) ? GBM_BO_USE_CURSOR
326 : GBM_BO_USE_SCANOUT;
327 /* TODO(gsingh): add create with modifiers option. */
328 plane->bo = gbm_bo_create(gbm, plane->crtc_w.value, plane->crtc_h.value,
329 plane->drm_plane.formats[plane->format_idx], flags);
330
331 CHECK(plane->bo);
332 plane->fb_id.value = bs_drm_fb_create_gbm(plane->bo);
333 CHECK(plane->fb_id.value);
334 CHECK_RESULT(set_plane_props(plane, ctx->pset));
335 }
336
337 return 0;
338}
339
340static int init_plane(struct atomictest_context *ctx, struct atomictest_plane *plane,
341 uint32_t format, uint32_t x, uint32_t y, uint32_t w, uint32_t h,
342 uint32_t zpos, uint32_t crtc_id)
343{
344 int32_t idx = get_format_idx(plane, format);
345 if (idx < 0)
346 return -EINVAL;
347
348 plane->format_idx = idx;
349 plane->crtc_x.value = x;
350 plane->crtc_y.value = y;
351 plane->crtc_w.value = w;
352 plane->crtc_h.value = h;
353 plane->src_w.value = plane->crtc_w.value << 16;
354 plane->src_h.value = plane->crtc_h.value << 16;
355 plane->zpos.value = zpos;
356 plane->crtc_id.value = crtc_id;
357
358 CHECK_RESULT(add_plane_fb(ctx, plane));
359 return 0;
360}
361
362static int disable_plane(struct atomictest_context *ctx, struct atomictest_plane *plane)
363{
364 plane->format_idx = 0;
365 plane->crtc_x.value = 0;
366 plane->crtc_y.value = 0;
367 plane->crtc_w.value = 0;
368 plane->crtc_h.value = 0;
369 plane->src_w.value = 0;
370 plane->src_h.value = 0;
371 plane->zpos.value = 0;
372 plane->crtc_id.value = 0;
373
374 CHECK_RESULT(remove_plane_fb(ctx, plane));
375 CHECK_RESULT(set_plane_props(plane, ctx->pset));
376 return 0;
377}
378
379static int move_plane(struct atomictest_context *ctx, struct atomictest_crtc *crtc,
380 struct atomictest_plane *plane, uint32_t dx, uint32_t dy)
381{
382 if (plane->crtc_x.value < (crtc->width - plane->crtc_w.value) &&
383 plane->crtc_y.value < (crtc->height - plane->crtc_h.value)) {
384 plane->crtc_x.value += dx;
385 plane->crtc_y.value += dy;
386 CHECK_RESULT(set_plane_props(plane, ctx->pset));
387 return 0;
388 }
389
390 return -1;
391}
392
393static int commit(struct atomictest_context *ctx)
394{
395 int ret;
396 fd_set fds;
397 FD_ZERO(&fds);
398 FD_SET(ctx->fd, &fds);
399
400 ret = drmModeAtomicCommit(ctx->fd, ctx->pset,
401 DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
402 CHECK_RESULT(ret);
403 do {
404 ret = select(ctx->fd + 1, &fds, NULL, NULL, NULL);
405 } while (ret == -1 && errno == EINTR);
406
407 CHECK_RESULT(ret);
408 if (FD_ISSET(ctx->fd, &fds))
409 drmHandleEvent(ctx->fd, &ctx->drm_event_ctx);
410
411 return 0;
412}
413
Gurchetan Singh1f4e15e2017-10-16 14:04:19 -0700414static int pageflip_formats(struct atomictest_context *ctx, struct atomictest_crtc *crtc,
415 struct atomictest_plane *plane)
Gurchetan Singh0d714272017-01-26 11:58:49 -0800416{
Gurchetan Singh1f4e15e2017-10-16 14:04:19 -0700417 uint32_t flags;
418 for (uint32_t i = 0; i < plane->drm_plane.count_formats; i++) {
419 flags = (plane->type.value == DRM_PLANE_TYPE_CURSOR) ? GBM_BO_USE_CURSOR
420 : GBM_BO_USE_SCANOUT;
421 if (!gbm_device_is_format_supported(gbm, plane->drm_plane.formats[i], flags))
Shirish Scd098332017-09-26 16:31:07 +0530422 continue;
423
Gurchetan Singh1f4e15e2017-10-16 14:04:19 -0700424 CHECK_RESULT(init_plane(ctx, plane, plane->drm_plane.formats[i], 0, 0, crtc->width,
425 crtc->height, 0, crtc->crtc_id));
Gurchetan Singhc3b543e2017-10-17 09:28:47 -0700426 CHECK_RESULT(draw_to_plane(ctx->mapper, plane, DRAW_ELLIPSE));
Gurchetan Singh0d714272017-01-26 11:58:49 -0800427 CHECK_RESULT(commit(ctx));
428 usleep(1e6);
Gurchetan Singh1f4e15e2017-10-16 14:04:19 -0700429
430 // disable, but don't commit, since we can't have an active CRTC without any planes.
431 CHECK_RESULT(disable_plane(ctx, plane));
Gurchetan Singh0d714272017-01-26 11:58:49 -0800432 }
433
434 return 0;
435}
436
Gurchetan Singhb60e7652017-06-02 12:54:34 -0700437static uint32_t get_connection(struct atomictest_crtc *crtc, uint32_t crtc_index)
438{
439 uint32_t connector_id = 0;
440 uint32_t crtc_mask = 1u << crtc_index;
441 struct bs_drm_pipe pipe = { 0 };
442 struct bs_drm_pipe_plumber *plumber = bs_drm_pipe_plumber_new();
443 bs_drm_pipe_plumber_crtc_mask(plumber, crtc_mask);
444 if (bs_drm_pipe_plumber_make(plumber, &pipe))
445 connector_id = pipe.connector_id;
446
447 bs_drm_pipe_plumber_destroy(&plumber);
448 return connector_id;
449}
450
451static int enable_crtc(struct atomictest_context *ctx, struct atomictest_crtc *crtc)
Gurchetan Singh0d714272017-01-26 11:58:49 -0800452{
453 drmModeAtomicSetCursor(ctx->pset, 0);
454
Gurchetan Singhb60e7652017-06-02 12:54:34 -0700455 for (uint32_t i = 0; i < ctx->num_connectors; i++) {
456 ctx->connectors[i].crtc_id.value = 0;
457 set_connector_props(&ctx->connectors[i], ctx->pset);
Gurchetan Singh0d714272017-01-26 11:58:49 -0800458 }
459
Gurchetan Singhb60e7652017-06-02 12:54:34 -0700460 for (uint32_t i = 0; i < ctx->num_crtcs; i++) {
461 if (&ctx->crtcs[i] == crtc) {
462 uint32_t connector_id = get_connection(crtc, i);
463 CHECK(connector_id);
464 for (uint32_t j = 0; j < ctx->num_connectors; j++) {
465 if (connector_id == ctx->connectors[j].connector_id) {
466 ctx->connectors[j].crtc_id.value = crtc->crtc_id;
467 set_connector_props(&ctx->connectors[j], ctx->pset);
468 break;
469 }
470 }
471
472 break;
473 }
Gurchetan Singh0d714272017-01-26 11:58:49 -0800474 }
475
476 int ret = -EINVAL;
477 int cursor = drmModeAtomicGetCursor(ctx->pset);
478
479 for (uint32_t i = 0; i < ctx->num_modes; i++) {
480 struct atomictest_mode *mode = &ctx->modes[i];
481 drmModeAtomicSetCursor(ctx->pset, cursor);
482
483 crtc->mode_id.value = mode->id;
484 crtc->active.value = 1;
485 crtc->width = mode->width;
486 crtc->height = mode->height;
487
488 set_crtc_props(crtc, ctx->pset);
489 ret = drmModeAtomicCommit(ctx->fd, ctx->pset,
490 DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET,
491 NULL);
492 if (!ret)
493 return 0;
494 }
495
496 bs_debug_error("[CRTC:%d]: failed to find mode", crtc->crtc_id);
497 return ret;
498}
499
Gurchetan Singhb60e7652017-06-02 12:54:34 -0700500static int disable_crtc(struct atomictest_context *ctx, struct atomictest_crtc *crtc)
501{
502 for (uint32_t i = 0; i < ctx->num_connectors; i++) {
503 ctx->connectors[i].crtc_id.value = 0;
504 set_connector_props(&ctx->connectors[i], ctx->pset);
505 }
506
507 crtc->mode_id.value = 0;
508 crtc->active.value = 0;
509 set_crtc_props(crtc, ctx->pset);
510 int ret = drmModeAtomicCommit(ctx->fd, ctx->pset, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
511 CHECK_RESULT(ret);
512 return ret;
513}
514
Gurchetan Singhbcfaf082017-06-02 12:58:10 -0700515static struct atomictest_context *new_context(uint32_t num_connectors, uint32_t num_crtcs,
516 uint32_t num_planes)
517{
518 struct atomictest_context *ctx = calloc(1, sizeof(*ctx));
519
520 ctx->mapper = bs_mapper_gem_new();
521 if (ctx->mapper == NULL) {
522 bs_debug_error("failed to create mapper object");
523 free(ctx);
524 return NULL;
525 }
526
527 ctx->connectors = calloc(num_connectors, sizeof(*ctx->connectors));
528 ctx->crtcs = calloc(num_crtcs, sizeof(*ctx->crtcs));
529 for (uint32_t i = 0; i < num_crtcs; i++) {
530 ctx->crtcs[i].planes = calloc(num_planes, sizeof(*ctx->crtcs[i].planes));
531 ctx->crtcs[i].overlay_idx = calloc(num_planes, sizeof(uint32_t));
532 ctx->crtcs[i].primary_idx = calloc(num_planes, sizeof(uint32_t));
533 ctx->crtcs[i].cursor_idx = calloc(num_planes, sizeof(uint32_t));
534 }
535
536 ctx->num_connectors = num_connectors;
537 ctx->num_crtcs = num_crtcs;
538 ctx->num_modes = 0;
539 ctx->modes = NULL;
540 ctx->pset = drmModeAtomicAlloc();
541 ctx->drm_event_ctx.version = DRM_EVENT_CONTEXT_VERSION;
542 ctx->drm_event_ctx.page_flip_handler = page_flip_handler;
543
544 return ctx;
545}
546
Gurchetan Singh0d714272017-01-26 11:58:49 -0800547static void free_context(struct atomictest_context *ctx)
548{
549 for (uint32_t i = 0; i < ctx->num_crtcs; i++) {
550 uint32_t num_planes = ctx->crtcs[i].num_primary + ctx->crtcs[i].num_cursor +
551 ctx->crtcs[i].num_overlay;
552
553 for (uint32_t j = 0; j < num_planes; j++) {
554 remove_plane_fb(ctx, &ctx->crtcs[i].planes[j]);
555 free(ctx->crtcs[i].planes[j].drm_plane.formats);
556 free(ctx->crtcs[i].planes[j].drm_plane.format_modifiers);
Haixia Shifc476462015-04-22 16:25:04 -0700557 }
558
Gurchetan Singh0d714272017-01-26 11:58:49 -0800559 free(ctx->crtcs[i].planes);
560 free(ctx->crtcs[i].overlay_idx);
561 free(ctx->crtcs[i].cursor_idx);
562 free(ctx->crtcs[i].primary_idx);
563 }
564
565 drmModeAtomicFree(ctx->pset);
566 free(ctx->modes);
567 free(ctx->crtcs);
568 free(ctx->connectors);
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700569 bs_mapper_destroy(ctx->mapper);
Gurchetan Singh0d714272017-01-26 11:58:49 -0800570 free(ctx);
571}
572
Gurchetan Singh83df8832017-06-02 14:06:48 -0700573static struct atomictest_context *query_kms(int fd)
Gurchetan Singh0d714272017-01-26 11:58:49 -0800574{
575 drmModeRes *res = drmModeGetResources(fd);
576 if (res == NULL) {
577 bs_debug_error("failed to get drm resources");
578 return false;
579 }
580
581 drmModePlaneRes *plane_res = drmModeGetPlaneResources(fd);
582 if (plane_res == NULL) {
583 bs_debug_error("failed to get plane resources");
584 drmModeFreeResources(res);
585 return NULL;
586 }
587
588 struct atomictest_context *ctx =
589 new_context(res->count_connectors, res->count_crtcs, plane_res->count_planes);
590 if (ctx == NULL) {
591 bs_debug_error("failed to allocate atomic context");
592 drmModeFreePlaneResources(plane_res);
593 drmModeFreeResources(res);
594 return NULL;
595 }
596
Gurchetan Singh0d714272017-01-26 11:58:49 -0800597 ctx->fd = fd;
598 drmModeObjectPropertiesPtr props = NULL;
599
600 for (uint32_t conn_index = 0; conn_index < res->count_connectors; conn_index++) {
601 uint32_t conn_id = res->connectors[conn_index];
602 ctx->connectors[conn_index].connector_id = conn_id;
603 props = drmModeObjectGetProperties(fd, conn_id, DRM_MODE_OBJECT_CONNECTOR);
604 get_connector_props(fd, &ctx->connectors[conn_index], props);
605
606 drmModeConnector *connector = drmModeGetConnector(fd, conn_id);
607 for (uint32_t mode_index = 0; mode_index < connector->count_modes; mode_index++) {
Dongseong Hwang326d08f2017-06-13 14:42:31 -0700608 ctx->modes =
609 realloc(ctx->modes, (ctx->num_modes + 1) * sizeof(*ctx->modes));
Gurchetan Singh0d714272017-01-26 11:58:49 -0800610 drmModeCreatePropertyBlob(fd, &connector->modes[mode_index],
611 sizeof(drmModeModeInfo),
612 &ctx->modes[ctx->num_modes].id);
613 ctx->modes[ctx->num_modes].width = connector->modes[mode_index].hdisplay;
614 ctx->modes[ctx->num_modes].height = connector->modes[mode_index].vdisplay;
615 ctx->num_modes++;
Haixia Shifc476462015-04-22 16:25:04 -0700616 }
617
Gurchetan Singh0d714272017-01-26 11:58:49 -0800618 drmModeFreeConnector(connector);
619 drmModeFreeObjectProperties(props);
620 props = NULL;
Haixia Shifc476462015-04-22 16:25:04 -0700621 }
622
Gurchetan Singh0d714272017-01-26 11:58:49 -0800623 uint32_t crtc_index;
624 for (crtc_index = 0; crtc_index < res->count_crtcs; crtc_index++) {
625 ctx->crtcs[crtc_index].crtc_id = res->crtcs[crtc_index];
626 props =
627 drmModeObjectGetProperties(fd, res->crtcs[crtc_index], DRM_MODE_OBJECT_CRTC);
628 get_crtc_props(fd, &ctx->crtcs[crtc_index], props);
629
630 drmModeFreeObjectProperties(props);
631 props = NULL;
Haixia Shifc476462015-04-22 16:25:04 -0700632 }
633
Gurchetan Singh0d714272017-01-26 11:58:49 -0800634 uint32_t overlay_idx, primary_idx, cursor_idx, idx;
Haixia Shifc476462015-04-22 16:25:04 -0700635
Gurchetan Singh0d714272017-01-26 11:58:49 -0800636 for (uint32_t plane_index = 0; plane_index < plane_res->count_planes; plane_index++) {
Kristian H. Kristensenfe6e6fa2017-05-01 15:12:20 -0700637 drmModePlane *plane = drmModeGetPlane2(fd, plane_res->planes[plane_index]);
Gurchetan Singh0d714272017-01-26 11:58:49 -0800638 if (plane == NULL) {
639 bs_debug_error("failed to get plane id %u", plane_res->planes[plane_index]);
640 continue;
641 }
Haixia Shifc476462015-04-22 16:25:04 -0700642
Gurchetan Singh0d714272017-01-26 11:58:49 -0800643 uint32_t crtc_mask = 0;
644
645 drmModeObjectPropertiesPtr props = drmModeObjectGetProperties(
646 fd, plane_res->planes[plane_index], DRM_MODE_OBJECT_PLANE);
647
648 for (crtc_index = 0; crtc_index < res->count_crtcs; crtc_index++) {
649 crtc_mask = (1 << crtc_index);
650 if (plane->possible_crtcs & crtc_mask) {
651 struct atomictest_crtc *crtc = &ctx->crtcs[crtc_index];
652 cursor_idx = crtc->num_cursor;
653 primary_idx = crtc->num_primary;
654 overlay_idx = crtc->num_overlay;
655 idx = cursor_idx + primary_idx + overlay_idx;
656 copy_drm_plane(&crtc->planes[idx].drm_plane, plane);
657 get_plane_props(fd, &crtc->planes[idx], props);
658 switch (crtc->planes[idx].type.value) {
659 case DRM_PLANE_TYPE_OVERLAY:
660 crtc->overlay_idx[overlay_idx] = idx;
661 crtc->num_overlay++;
662 break;
663 case DRM_PLANE_TYPE_PRIMARY:
664 crtc->primary_idx[primary_idx] = idx;
665 crtc->num_primary++;
666 break;
667 case DRM_PLANE_TYPE_CURSOR:
668 crtc->cursor_idx[cursor_idx] = idx;
669 crtc->num_cursor++;
670 break;
671 default:
672 bs_debug_error("invalid plane type returned");
673 return NULL;
674 }
Haixia Shifc476462015-04-22 16:25:04 -0700675 }
676 }
677
Gurchetan Singh0d714272017-01-26 11:58:49 -0800678 drmModeFreePlane(plane);
679 drmModeFreeObjectProperties(props);
680 props = NULL;
Haixia Shifc476462015-04-22 16:25:04 -0700681 }
682
Gurchetan Singh0d714272017-01-26 11:58:49 -0800683 drmModeFreePlaneResources(plane_res);
684 drmModeFreeResources(res);
685 return ctx;
686}
Haixia Shifc476462015-04-22 16:25:04 -0700687
Gurchetan Singh0d714272017-01-26 11:58:49 -0800688static int test_multiple_planes(struct atomictest_context *ctx, struct atomictest_crtc *crtc)
689{
690 struct atomictest_plane *primary, *overlay, *cursor;
691 for (uint32_t i = 0; i < crtc->num_primary; i++) {
692 bool has_video = false;
693 uint32_t x, y;
694 for (uint32_t j = 0; j < crtc->num_overlay; j++) {
695 overlay = get_plane(crtc, j, DRM_PLANE_TYPE_OVERLAY);
696 x = crtc->width >> (j + 2);
697 y = crtc->height >> (j + 2);
Dongseong Hwang326d08f2017-06-13 14:42:31 -0700698 // drmModeAddFB2 requires the height and width are even for sub-sampled YUV
699 // formats.
700 x = BS_ALIGN(x, 2);
701 y = BS_ALIGN(y, 2);
Gurchetan Singh0d714272017-01-26 11:58:49 -0800702 bool added_video = false;
703 if (!has_video) {
704 uint32_t k = 0;
705 for (k = 0; k < BS_ARRAY_LEN(yuv_formats); k++) {
706 if (!init_plane(ctx, overlay, yuv_formats[k], x, y, x, y, j,
707 crtc->crtc_id)) {
708 has_video = true;
709 added_video = true;
710 break;
711 }
712 }
713
Gurchetan Singhc3b543e2017-10-17 09:28:47 -0700714 if (added_video)
715 CHECK_RESULT(
716 draw_to_plane(ctx->mapper, overlay, DRAW_STRIPE));
Gurchetan Singh0d714272017-01-26 11:58:49 -0800717 }
718
719 if (!added_video) {
720 added_video = true;
721 CHECK_RESULT(init_plane(ctx, overlay, DRM_FORMAT_XRGB8888, x, y, x,
722 y, i, crtc->crtc_id));
Gurchetan Singhe07faed2017-10-18 16:32:34 -0700723 CHECK_RESULT(draw_to_plane(ctx->mapper, overlay, DRAW_LINES));
Gurchetan Singh0d714272017-01-26 11:58:49 -0800724 }
725 }
726
727 for (uint32_t j = 0; j < crtc->num_cursor; j++) {
728 x = crtc->width >> (j + 2);
729 y = crtc->height >> (j + 2);
730 cursor = get_plane(crtc, j, DRM_PLANE_TYPE_CURSOR);
Dongseong Hwangd0a45fc2017-04-12 17:10:11 -0700731 CHECK_RESULT(init_plane(ctx, cursor, DRM_FORMAT_ARGB8888, x, y, CURSOR_SIZE,
Gurchetan Singh0d714272017-01-26 11:58:49 -0800732 CURSOR_SIZE, crtc->num_overlay + j, crtc->crtc_id));
Gurchetan Singhc3b543e2017-10-17 09:28:47 -0700733 CHECK_RESULT(draw_to_plane(ctx->mapper, cursor, DRAW_CURSOR));
Gurchetan Singh0d714272017-01-26 11:58:49 -0800734 }
735
736 primary = get_plane(crtc, i, DRM_PLANE_TYPE_PRIMARY);
737 CHECK_RESULT(init_plane(ctx, primary, DRM_FORMAT_XRGB8888, 0, 0, crtc->width,
738 crtc->height, 0, crtc->crtc_id));
Gurchetan Singhc3b543e2017-10-17 09:28:47 -0700739 CHECK_RESULT(draw_to_plane(ctx->mapper, primary, DRAW_ELLIPSE));
Gurchetan Singh0d714272017-01-26 11:58:49 -0800740
741 uint32_t num_planes = crtc->num_primary + crtc->num_cursor + crtc->num_overlay;
742 int done = 0;
743 struct atomictest_plane *plane;
744 while (!done) {
745 done = 1;
746 for (uint32_t j = 0; j < num_planes; j++) {
747 plane = &crtc->planes[j];
748 if (plane->type.value != DRM_PLANE_TYPE_PRIMARY)
749 done &= move_plane(ctx, crtc, plane, 20, 20);
750 }
751
752 CHECK_RESULT(commit(ctx));
753 usleep(1e6 / 60);
754 }
755
756 CHECK_RESULT(commit(ctx));
757 usleep(1e6);
758
759 /* Disable primary plane and verify overlays show up. */
760 CHECK_RESULT(disable_plane(ctx, primary));
761 CHECK_RESULT(commit(ctx));
762 usleep(1e6);
763 }
764
765 return 0;
766}
767
768static int test_video_overlay(struct atomictest_context *ctx, struct atomictest_crtc *crtc)
769{
770 struct atomictest_plane *overlay;
771 for (uint32_t i = 0; i < crtc->num_overlay; i++) {
772 overlay = get_plane(crtc, i, DRM_PLANE_TYPE_OVERLAY);
773 for (uint32_t j = 0; j < BS_ARRAY_LEN(yuv_formats); j++) {
774 if (init_plane(ctx, overlay, yuv_formats[j], 0, 0, 800, 800, 0,
775 crtc->crtc_id))
776 continue;
777
Gurchetan Singhc3b543e2017-10-17 09:28:47 -0700778 CHECK_RESULT(draw_to_plane(ctx->mapper, overlay, DRAW_STRIPE));
Gurchetan Singh0d714272017-01-26 11:58:49 -0800779 while (!move_plane(ctx, crtc, overlay, 20, 20)) {
780 CHECK_RESULT(commit(ctx));
781 usleep(1e6 / 60);
782 }
783 }
784 }
785
786 return 0;
787}
788
789static int test_fullscreen_video(struct atomictest_context *ctx, struct atomictest_crtc *crtc)
790{
791 struct atomictest_plane *primary;
792 for (uint32_t i = 0; i < crtc->num_primary; i++) {
793 primary = get_plane(crtc, i, DRM_PLANE_TYPE_PRIMARY);
794 for (uint32_t j = 0; j < BS_ARRAY_LEN(yuv_formats); j++) {
795 if (init_plane(ctx, primary, yuv_formats[j], 0, 0, crtc->width,
796 crtc->height, 0, crtc->crtc_id))
797 continue;
Dongseong Hwangd0a45fc2017-04-12 17:10:11 -0700798
Gurchetan Singhc3b543e2017-10-17 09:28:47 -0700799 CHECK_RESULT(draw_to_plane(ctx->mapper, primary, DRAW_STRIPE));
Gurchetan Singh0d714272017-01-26 11:58:49 -0800800 CHECK_RESULT(commit(ctx));
801 usleep(1e6);
802 }
803 }
804
805 return 0;
806}
807
808static int test_disable_primary(struct atomictest_context *ctx, struct atomictest_crtc *crtc)
809{
Gurchetan Singh0d714272017-01-26 11:58:49 -0800810 struct atomictest_plane *primary, *overlay;
811 for (uint32_t i = 0; i < crtc->num_primary; i++) {
812 for (uint32_t j = 0; j < crtc->num_overlay; j++) {
813 overlay = get_plane(crtc, j, DRM_PLANE_TYPE_OVERLAY);
814 uint32_t x = crtc->width >> (j + 2);
815 uint32_t y = crtc->height >> (j + 2);
816 CHECK_RESULT(init_plane(ctx, overlay, DRM_FORMAT_XRGB8888, x, y, x, y, i,
817 crtc->crtc_id));
Gurchetan Singhe07faed2017-10-18 16:32:34 -0700818 CHECK_RESULT(draw_to_plane(ctx->mapper, overlay, DRAW_LINES));
Gurchetan Singh0d714272017-01-26 11:58:49 -0800819 }
820
Gurchetan Singh0d714272017-01-26 11:58:49 -0800821 primary = get_plane(crtc, i, DRM_PLANE_TYPE_PRIMARY);
822 CHECK_RESULT(init_plane(ctx, primary, DRM_FORMAT_XRGB8888, 0, 0, crtc->width,
823 crtc->height, 0, crtc->crtc_id));
Gurchetan Singhc3b543e2017-10-17 09:28:47 -0700824 CHECK_RESULT(draw_to_plane(ctx->mapper, primary, DRAW_ELLIPSE));
Gurchetan Singh0d714272017-01-26 11:58:49 -0800825 CHECK_RESULT(commit(ctx));
826 usleep(1e6);
827
828 /* Disable primary plane. */
829 disable_plane(ctx, primary);
830 CHECK_RESULT(commit(ctx));
831 usleep(1e6);
Gurchetan Singh0d714272017-01-26 11:58:49 -0800832 }
833
834 return 0;
835}
836
837static int test_overlay_pageflip(struct atomictest_context *ctx, struct atomictest_crtc *crtc)
838{
839 struct atomictest_plane *overlay;
Gurchetan Singh0d714272017-01-26 11:58:49 -0800840 for (uint32_t i = 0; i < crtc->num_overlay; i++) {
841 overlay = get_plane(crtc, i, DRM_PLANE_TYPE_OVERLAY);
Gurchetan Singh1f4e15e2017-10-16 14:04:19 -0700842 CHECK_RESULT(pageflip_formats(ctx, crtc, overlay));
Gurchetan Singh0d714272017-01-26 11:58:49 -0800843 }
844
845 return 0;
846}
847
848static int test_primary_pageflip(struct atomictest_context *ctx, struct atomictest_crtc *crtc)
849{
Gurchetan Singh0d714272017-01-26 11:58:49 -0800850 struct atomictest_plane *primary;
Gurchetan Singh0d714272017-01-26 11:58:49 -0800851 for (uint32_t i = 0; i < crtc->num_primary; i++) {
852 primary = get_plane(crtc, i, DRM_PLANE_TYPE_PRIMARY);
Gurchetan Singh1f4e15e2017-10-16 14:04:19 -0700853 CHECK_RESULT(pageflip_formats(ctx, crtc, primary));
Gurchetan Singh0d714272017-01-26 11:58:49 -0800854 }
855
856 return 0;
857}
858
Gurchetan Singhd61875a2017-06-02 17:03:19 -0700859static const struct atomictest_testcase cases[] = {
Gurchetan Singh0d714272017-01-26 11:58:49 -0800860 { "disable_primary", test_disable_primary },
861 { "fullscreen_video", test_fullscreen_video },
862 { "multiple_planes", test_multiple_planes },
863 { "overlay_pageflip", test_overlay_pageflip },
864 { "primary_pageflip", test_primary_pageflip },
865 { "video_overlay", test_video_overlay },
866};
867
Gurchetan Singhd61875a2017-06-02 17:03:19 -0700868static int run_testcase(struct atomictest_context *ctx, struct atomictest_crtc *crtc,
869 test_function func)
870{
871 int cursor = drmModeAtomicGetCursor(ctx->pset);
872 uint32_t num_planes = crtc->num_primary + crtc->num_cursor + crtc->num_overlay;
873
874 int ret = func(ctx, crtc);
875
876 for (uint32_t i = 0; i < num_planes; i++)
877 disable_plane(ctx, &crtc->planes[i]);
878
Azhar Shaikh013037e2017-08-08 13:47:02 -0700879 drmModeAtomicSetCursor(ctx->pset, cursor);
880
Gurchetan Singhd61875a2017-06-02 17:03:19 -0700881 CHECK_RESULT(commit(ctx));
882 usleep(1e6 / 60);
883
Gurchetan Singhd61875a2017-06-02 17:03:19 -0700884 return ret;
885}
886
Gurchetan Singhe6afe0a2017-06-02 18:02:03 -0700887static int run_atomictest(const char *name, uint32_t crtc_mask)
Gurchetan Singhd61875a2017-06-02 17:03:19 -0700888{
889 int ret = 0;
890 uint32_t num_run = 0;
891 int fd = bs_drm_open_main_display();
892 CHECK_RESULT(fd);
893
894 gbm = gbm_create_device(fd);
895 if (!gbm) {
896 bs_debug_error("failed to create gbm device");
897 ret = -1;
898 goto destroy_fd;
899 }
900
901 ret = drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
902 if (ret) {
903 bs_debug_error("failed to enable DRM_CLIENT_CAP_UNIVERSAL_PLANES");
904 ret = -1;
905 goto destroy_gbm_device;
906 }
907
908 ret = drmSetClientCap(fd, DRM_CLIENT_CAP_ATOMIC, 1);
909 if (ret) {
910 bs_debug_error("failed to enable DRM_CLIENT_CAP_ATOMIC");
911 ret = -1;
912 goto destroy_gbm_device;
913 }
914
915 struct atomictest_context *ctx = query_kms(fd);
916 if (!ctx) {
917 bs_debug_error("querying atomictest failed.");
918 ret = -1;
919 goto destroy_gbm_device;
920 }
921
922 struct atomictest_crtc *crtc;
923 for (uint32_t crtc_index = 0; crtc_index < ctx->num_crtcs; crtc_index++) {
924 crtc = &ctx->crtcs[crtc_index];
Gurchetan Singhe6afe0a2017-06-02 18:02:03 -0700925 if (!((1 << crtc_index) & crtc_mask))
926 continue;
927
Gurchetan Singhd61875a2017-06-02 17:03:19 -0700928 for (uint32_t i = 0; i < BS_ARRAY_LEN(cases); i++) {
929 if (strcmp(cases[i].name, name) && strcmp("all", name))
930 continue;
931
932 num_run++;
933 ret = enable_crtc(ctx, crtc);
934 if (ret)
935 goto out;
936
937 ret = run_testcase(ctx, crtc, cases[i].test_func);
938 if (ret)
939 goto out;
940
941 ret = disable_crtc(ctx, crtc);
942 if (ret)
943 goto out;
944 }
945 }
946
947 ret = (num_run == 0);
948
949out:
950 free_context(ctx);
951destroy_gbm_device:
952 gbm_device_destroy(gbm);
953destroy_fd:
954 close(fd);
955
956 return ret;
957}
958
Gurchetan Singhe6afe0a2017-06-02 18:02:03 -0700959static const struct option longopts[] = {
960 { "crtc", required_argument, NULL, 'c' },
961 { "test_name", required_argument, NULL, 't' },
Gurchetan Singh3008ce62017-10-17 10:51:36 -0700962 { "help", no_argument, NULL, 'h' },
Gurchetan Singhe6afe0a2017-06-02 18:02:03 -0700963 { 0, 0, 0, 0 },
964};
965
Gurchetan Singh0d714272017-01-26 11:58:49 -0800966static void print_help(const char *argv0)
967{
Gurchetan Singhe6afe0a2017-06-02 18:02:03 -0700968 printf("usage: %s -t <test_name> -c <crtc_index>\n", argv0);
Gurchetan Singh0d714272017-01-26 11:58:49 -0800969 printf("A valid name test is one the following:\n");
Gurchetan Singhd61875a2017-06-02 17:03:19 -0700970 for (uint32_t i = 0; i < BS_ARRAY_LEN(cases); i++)
971 printf("%s\n", cases[i].name);
972 printf("all\n");
Gurchetan Singh0d714272017-01-26 11:58:49 -0800973}
974
975int main(int argc, char **argv)
976{
Gurchetan Singhe6afe0a2017-06-02 18:02:03 -0700977 int c;
978 char *name = NULL;
979 int32_t crtc_idx = -1;
980 uint32_t crtc_mask = ~0;
Gurchetan Singh3008ce62017-10-17 10:51:36 -0700981 while ((c = getopt_long(argc, argv, "c:t:h", longopts, NULL)) != -1) {
Gurchetan Singhe6afe0a2017-06-02 18:02:03 -0700982 switch (c) {
983 case 'c':
984 if (sscanf(optarg, "%d", &crtc_idx) != 1)
985 goto print;
986 break;
987 case 't':
988 if (name) {
989 free(name);
990 name = NULL;
991 }
992
993 name = strdup(optarg);
994 break;
Gurchetan Singh3008ce62017-10-17 10:51:36 -0700995 case 'h':
996 goto print;
Gurchetan Singhe6afe0a2017-06-02 18:02:03 -0700997 default:
998 goto print;
Gurchetan Singh0d714272017-01-26 11:58:49 -0800999 }
1000 }
1001
Gurchetan Singhafcea5b2017-06-09 15:28:20 -07001002 if (!name)
1003 goto print;
1004
Gurchetan Singhe6afe0a2017-06-02 18:02:03 -07001005 if (crtc_idx >= 0)
1006 crtc_mask = 1 << crtc_idx;
1007
1008 int ret = run_atomictest(name, crtc_mask);
Gurchetan Singhafcea5b2017-06-09 15:28:20 -07001009 if (ret == 0)
Gurchetan Singhe6afe0a2017-06-02 18:02:03 -07001010 printf("[ PASSED ] atomictest.%s\n", name);
Gurchetan Singhafcea5b2017-06-09 15:28:20 -07001011 else if (ret < 0)
Gurchetan Singhe6afe0a2017-06-02 18:02:03 -07001012 printf("[ FAILED ] atomictest.%s\n", name);
Gurchetan Singhafcea5b2017-06-09 15:28:20 -07001013
1014 free(name);
1015
1016 if (ret > 0)
1017 goto print;
1018
1019 return ret;
Gurchetan Singhe6afe0a2017-06-02 18:02:03 -07001020
1021print:
Gurchetan Singh0d714272017-01-26 11:58:49 -08001022 print_help(argv[0]);
Gurchetan Singhe6afe0a2017-06-02 18:02:03 -07001023 return 0;
Gurchetan Singh0d714272017-01-26 11:58:49 -08001024}