blob: a153f5b4d8195b3e768880db65c0c4366aca8755 [file] [log] [blame]
Zach Reiznerd847a7e2016-04-28 16:48:32 -07001/*
2 * Copyright 2015 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 */
6
7#include <ctype.h>
Zach Reiznerfa0547a2016-05-11 18:43:40 -07008#include <getopt.h>
9#include <math.h>
Zach Reiznerd847a7e2016-04-28 16:48:32 -070010
11#include "bs_drm.h"
12
Zach Reiznerfa0547a2016-05-11 18:43:40 -070013#define MAX_TEST_PLANES 4
14
15static int64_t ns_since(struct timespec *since)
16{
17 struct timespec now;
18 clock_gettime(CLOCK_MONOTONIC, &now);
19
20 return (int64_t)(now.tv_sec - since->tv_sec) * 1000000000 + (int64_t)now.tv_nsec -
21 (int64_t)since->tv_nsec;
22}
Zach Reiznerd847a7e2016-04-28 16:48:32 -070023
24static drmModeModeInfoPtr find_best_mode(int mode_count, drmModeModeInfoPtr modes)
25{
26 if (mode_count <= 0 || modes == NULL)
27 return NULL;
28
29 for (int m = 0; m < mode_count; m++)
30 if (modes[m].type & DRM_MODE_TYPE_PREFERRED)
31 return &modes[m];
32
33 return &modes[0];
34}
35
36static bool is_format_supported(uint32_t format_count, uint32_t *formats, uint32_t format)
37{
38 for (uint32_t i = 0; i < format_count; i++)
39 if (formats[i] == format)
40 return true;
41 return false;
42}
43
Zach Reiznerfa0547a2016-05-11 18:43:40 -070044static bool find_overlay_planes(int fd, uint32_t crtc_id, size_t plane_count, uint32_t *formats,
45 uint32_t *plane_ids)
Zach Reiznerd847a7e2016-04-28 16:48:32 -070046{
47 drmModeRes *res = drmModeGetResources(fd);
48 if (res == NULL) {
49 bs_debug_error("failed to get drm resources");
Zach Reiznerfa0547a2016-05-11 18:43:40 -070050 return false;
Zach Reiznerd847a7e2016-04-28 16:48:32 -070051 }
52
53 uint32_t crtc_mask = 0;
54 for (int crtc_index = 0; crtc_index < res->count_crtcs; crtc_index++) {
55 if (res->crtcs[crtc_index] == crtc_id) {
56 crtc_mask = (1 << crtc_index);
57 break;
58 }
59 }
60 if (crtc_mask == 0) {
61 bs_debug_error("invalid crtc id %u", crtc_id);
62 drmModeFreeResources(res);
Zach Reiznerfa0547a2016-05-11 18:43:40 -070063 return false;
Zach Reiznerd847a7e2016-04-28 16:48:32 -070064 }
65
66 drmModePlaneRes *plane_res = drmModeGetPlaneResources(fd);
67 if (plane_res == NULL) {
68 bs_debug_error("failed to get plane resources");
69 drmModeFreeResources(res);
Zach Reiznerfa0547a2016-05-11 18:43:40 -070070 return false;
Zach Reiznerd847a7e2016-04-28 16:48:32 -070071 }
72
Zach Reiznerfa0547a2016-05-11 18:43:40 -070073 for (size_t out_index = 0; out_index < plane_count; out_index++)
74 plane_ids[out_index] = 0;
75
76 size_t remaining_out = plane_count;
77 for (uint32_t plane_index = 0; remaining_out > 0 && plane_index < plane_res->count_planes;
Zach Reiznerd847a7e2016-04-28 16:48:32 -070078 plane_index++) {
79 drmModePlane *plane = drmModeGetPlane(fd, plane_res->planes[plane_index]);
80 if (plane == NULL) {
81 bs_debug_error("failed to get plane id %u", plane_res->planes[plane_index]);
82 continue;
83 }
84
Zach Reiznerfa0547a2016-05-11 18:43:40 -070085 size_t out_index;
86 for (out_index = 0; out_index < plane_count; out_index++) {
87 if (plane_ids[out_index] == 0 &&
88 is_format_supported(plane->count_formats, plane->formats,
89 formats[out_index]))
90 break;
91 }
92
93 if ((plane->possible_crtcs & crtc_mask) == 0 || out_index == plane_count) {
Zach Reiznerd847a7e2016-04-28 16:48:32 -070094 drmModeFreePlane(plane);
95 continue;
96 }
97
98 drmModeObjectPropertiesPtr props =
99 drmModeObjectGetProperties(fd, plane->plane_id, DRM_MODE_OBJECT_PLANE);
100 for (uint32_t prop_index = 0; prop_index < props->count_props; ++prop_index) {
101 drmModePropertyPtr prop = drmModeGetProperty(fd, props->props[prop_index]);
102 if (strcmp(prop->name, "type")) {
103 drmModeFreeProperty(prop);
104 continue;
105 }
106
107 uint64_t desired_value = 0;
108 bool has_value = false;
109 for (int enum_index = 0; enum_index < prop->count_enums; enum_index++) {
110 struct drm_mode_property_enum *penum = &prop->enums[enum_index];
111 if (!strcmp(penum->name, "Overlay")) {
112 desired_value = penum->value;
113 has_value = true;
114 break;
115 }
116 }
117 drmModeFreeProperty(prop);
118
Zach Reiznerfa0547a2016-05-11 18:43:40 -0700119 if (has_value && desired_value == props->prop_values[prop_index]) {
120 plane_ids[out_index] = plane->plane_id;
121 remaining_out--;
122 }
Zach Reiznerd847a7e2016-04-28 16:48:32 -0700123
124 break;
125 }
Zach Reiznerfa0547a2016-05-11 18:43:40 -0700126
Zach Reiznerd847a7e2016-04-28 16:48:32 -0700127 drmModeFreeObjectProperties(props);
Zach Reiznerd847a7e2016-04-28 16:48:32 -0700128 drmModeFreePlane(plane);
129 }
130
131 drmModeFreePlaneResources(plane_res);
132 drmModeFreeResources(res);
133
Zach Reiznerfa0547a2016-05-11 18:43:40 -0700134 return remaining_out == 0;
Zach Reiznerd847a7e2016-04-28 16:48:32 -0700135}
136
Zach Reiznerfa0547a2016-05-11 18:43:40 -0700137struct test_plane {
Gurchetan Singh61208942017-01-27 13:31:19 -0800138 const struct bs_draw_format *format;
Zach Reiznerd847a7e2016-04-28 16:48:32 -0700139
Zach Reiznerfa0547a2016-05-11 18:43:40 -0700140 bool has_bo_size;
141 uint32_t bo_w;
142 uint32_t bo_h;
143
144 bool has_dst_position;
145 int32_t dst_x;
146 int32_t dst_y;
147
148 int32_t dst_center_x;
149 int32_t dst_center_y;
150
151 int32_t dst_vx;
152 int32_t dst_vy;
153
154 bool has_dst_size;
155 uint32_t dst_w;
156 uint32_t dst_h;
157
158 uint32_t dst_min_w;
159 uint32_t dst_max_w;
160 uint32_t dst_min_h;
161 uint32_t dst_max_h;
162
163 bool has_dst_scale;
164 uint32_t dst_downscale_factor;
165 uint32_t dst_upscale_factor;
166
167 int32_t src_x;
168 int32_t src_y;
169
170 int32_t src_vx;
171 int32_t src_vy;
172
173 bool has_src_size;
174 uint32_t src_w;
175 uint32_t src_h;
176
177 struct gbm_bo *bo;
178 uint32_t fb_id;
179};
180
181static bool update_test_plane(int step, int32_t max_x, int32_t max_y, struct test_plane *tp)
182{
183 bool needs_set = (step == 0);
184 if (tp->has_dst_scale) {
185 float scale_factor = (sinf(step / 120.0f) / 2.0f + 0.5f);
186 scale_factor = powf(scale_factor, 4);
187 tp->dst_w = tp->dst_min_w + scale_factor * (tp->dst_max_w - tp->dst_min_w);
188 tp->dst_h = tp->dst_min_h + scale_factor * (tp->dst_max_h - tp->dst_min_h);
189 needs_set = true;
190 }
191
192 if (tp->dst_vx != 0) {
193 tp->dst_center_x += tp->dst_vx;
194 if (tp->dst_center_x > max_x || tp->dst_center_x < 0) {
195 tp->dst_vx = -tp->dst_vx;
196 tp->dst_x += tp->dst_vx * 2;
197 }
198 needs_set = true;
199 }
200 tp->dst_x = tp->dst_center_x - tp->dst_w / 2;
201
202 if (tp->dst_vy != 0) {
203 tp->dst_center_y += tp->dst_vy;
204 if (tp->dst_center_y > max_y || tp->dst_center_y < 0) {
205 tp->dst_vy = -tp->dst_vy;
206 tp->dst_y += tp->dst_vy * 2;
207 }
208 needs_set = true;
209 }
210 tp->dst_y = tp->dst_center_y - tp->dst_h / 2;
211
212 if (tp->src_vx != 0) {
213 tp->src_x += tp->src_vx;
214 if (tp->src_x + tp->src_w > gbm_bo_get_width(tp->bo) || tp->src_x < 0) {
215 tp->src_vx = -tp->src_vx;
216 tp->src_x += tp->src_vx * 2;
217 }
218 needs_set = true;
219 }
220
221 if (tp->src_vy != 0) {
222 tp->src_y += tp->src_vy;
223 if (tp->src_y + tp->src_h > gbm_bo_get_height(tp->bo) || tp->src_y < 0) {
224 tp->src_vy = -tp->src_vy;
225 tp->src_y += tp->src_vy * 2;
226 }
227 needs_set = true;
228 }
229
230 return needs_set;
231}
232
Gurchetan Singh61208942017-01-27 13:31:19 -0800233static bool parse_format(const char *str, const struct bs_draw_format **format)
Zach Reiznerfa0547a2016-05-11 18:43:40 -0700234{
235 if (strlen(str) == 4) {
Gurchetan Singh61208942017-01-27 13:31:19 -0800236 const struct bs_draw_format *bs_draw_format = bs_get_draw_format(*(uint32_t *)str);
237 if (bs_draw_format) {
238 *format = bs_draw_format;
Zach Reiznerfa0547a2016-05-11 18:43:40 -0700239 return true;
240 }
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700241 } else {
Gurchetan Singh61208942017-01-27 13:31:19 -0800242 const struct bs_draw_format *bs_draw_format = bs_get_draw_format_from_name(str);
243 if (bs_draw_format) {
244 *format = bs_draw_format;
245 return true;
Zach Reiznerd847a7e2016-04-28 16:48:32 -0700246 }
247 }
248
Zach Reiznerfa0547a2016-05-11 18:43:40 -0700249 printf("plane format %s is not recognized\n", str);
250 return false;
251}
252
253static bool parse_size(const char *str, uint32_t *w, uint32_t *h)
254{
255 if (sscanf(str, "%ux%u", w, h) == 2)
256 return true;
257
258 printf("unrecognized size format \"%s\"\n", str);
259
260 return false;
261}
262
263static bool parse_scale(const char *str, uint32_t *down, uint32_t *up)
264{
265 if (sscanf(str, "%u/%u", down, up) == 2)
266 return true;
267
268 printf("unrecognized scale format \"%s\"\n", str);
269
270 return false;
271}
272
273static bool parse_rect(const char *str, int32_t *x, int32_t *y, uint32_t *w, uint32_t *h,
274 bool *has_position, bool *has_size)
275{
276 if (sscanf(str, "%d,%d,%u,%u", x, y, w, h) == 4) {
277 if (has_position)
278 *has_position = true;
279 if (has_size)
280 *has_size = true;
281 return true;
282 }
283
284 if (sscanf(str, "%d,%d", x, y) == 2) {
285 if (has_position)
286 *has_position = true;
287 if (has_size)
288 *has_size = false;
289 return true;
290 }
291
292 if (sscanf(str, "%ux%u", w, h) == 2) {
293 if (has_position)
294 *has_position = false;
295 if (has_size)
296 *has_size = true;
297 return true;
298 }
299
300 printf("unrecognized rectangle format \"%s\"\n", str);
301
302 return false;
303}
304
305static const struct option longopts[] = {
306 { "plane", no_argument, NULL, 'p' },
307 { "format", required_argument, NULL, 'f' },
308 { "size", required_argument, NULL, 'z' },
309 { "scale", required_argument, NULL, 'c' },
310 { "translate", no_argument, NULL, 't' },
311 { "src", required_argument, NULL, 's' },
312 { "dst", required_argument, NULL, 'd' },
313 { "help", no_argument, NULL, 'h' },
314 { 0, 0, 0, 0 },
315};
316
317static void print_help(const char *argv0)
318{
319 // clang-format off
320 printf("usage: %s [OPTIONS]\n", argv0);
321 printf(" -p, --plane indicates that subsequent parameters are for a new plane\n");
322 printf(" -f, --format FOURCC format of source buffer (defaults to NV12)\n");
323 printf(" -z, --size WIDTHxHEIGHT size of the source buffer (defaults to screen size)\n");
324 printf(" -c, --scale DOWN/UP scale plane over time between (1/DOWN)x and UPx\n");
325 printf(" -t, --translate translate plane over time\n");
326 printf(" -s, --src RECT source rectangle (defaults to full buffer)\n");
327 printf(" -d, --dst RECT destination rectangle (defaults to buffer size centered in screen)\n");
328 printf(" -h, --help show help\n");
329 printf("\n");
330 printf("The format of RECT arguments is X,Y or X,Y,WIDTH,HEIGHT or WIDTHxHEIGHT.\n");
331 printf("To test more than one plane, separate plane arguments with -p. For example:\n");
332 printf(" %s --format NV12 --size 400x400 -p --format XR24 --size 100x100 --translate\n", argv0);
333 printf("\n");
334 // clang-format on
335}
336
337int main(int argc, char **argv)
338{
339 int ret = 0;
340 bool help_flag = false;
341 size_t test_planes_count = 1;
342 struct test_plane test_planes[MAX_TEST_PLANES] = { { 0 } };
343 uint32_t test_planes_formats[MAX_TEST_PLANES] = { 0 };
344 uint32_t test_planes_ids[MAX_TEST_PLANES] = { 0 };
345
346 int c;
347 while ((c = getopt_long(argc, argv, "pf:z:c:ts:d:h", longopts, NULL)) != -1) {
348 struct test_plane *current_plane = &test_planes[test_planes_count - 1];
349 switch (c) {
350 case 'p':
351 test_planes_count++;
352 if (test_planes_count > MAX_TEST_PLANES) {
353 printf("only %d planes are allowed\n", MAX_TEST_PLANES);
354 return 1;
355 }
356 break;
357 case 'f':
358 if (!parse_format(optarg, &current_plane->format))
359 return 1;
360 break;
361 case 'z':
362 if (!parse_size(optarg, &current_plane->bo_w, &current_plane->bo_h))
363 return 1;
364 current_plane->has_bo_size = true;
365 break;
366 case 'c':
367 if (!parse_scale(optarg, &current_plane->dst_downscale_factor,
368 &current_plane->dst_upscale_factor))
369 return 1;
370 current_plane->has_dst_scale = true;
371 break;
372 case 't':
373 current_plane->dst_vx = 7;
374 current_plane->dst_vy = 7;
375 break;
376 case 's':
377 if (!parse_rect(optarg, &current_plane->src_x,
378 &current_plane->src_y, &current_plane->src_w,
379 &current_plane->src_h, NULL,
380 &current_plane->has_src_size))
381 return 1;
382 break;
383 case 'd':
384 if (!parse_rect(optarg, &current_plane->dst_x,
385 &current_plane->dst_y, &current_plane->dst_w,
386 &current_plane->dst_h,
387 &current_plane->has_dst_position,
388 &current_plane->has_dst_size))
389 return 1;
390 break;
391 case '?':
392 ret = 1;
393 case 'h':
394 help_flag = true;
395 break;
396 }
397 }
398
399 if (help_flag)
400 print_help(argv[0]);
401
402 if (ret)
403 return ret;
Zach Reiznerd847a7e2016-04-28 16:48:32 -0700404
405 drmModeConnector *connector;
406 struct bs_drm_pipe pipe = { 0 };
407 struct bs_drm_pipe_plumber *plumber = bs_drm_pipe_plumber_new();
408 bs_drm_pipe_plumber_connector_ranks(plumber, bs_drm_connectors_internal_rank);
409 bs_drm_pipe_plumber_connector_ptr(plumber, &connector);
410 if (!bs_drm_pipe_plumber_make(plumber, &pipe)) {
411 bs_debug_error("failed to make pipe");
412 return 1;
413 }
414 bs_drm_pipe_plumber_destroy(&plumber);
415
416 drmModeModeInfo *mode_ptr = find_best_mode(connector->count_modes, connector->modes);
417 if (!mode_ptr) {
418 bs_debug_error("failed to find preferred mode");
419 return 1;
420 }
421 drmModeModeInfo mode = *mode_ptr;
422 drmModeFreeConnector(connector);
423 printf("Using mode %s\n", mode.name);
424
Zach Reiznerfa0547a2016-05-11 18:43:40 -0700425 printf("Using CRTC:%u ENCODER:%u CONNECTOR:%u\n", pipe.crtc_id, pipe.encoder_id,
426 pipe.connector_id);
Zach Reiznerd847a7e2016-04-28 16:48:32 -0700427
428 struct gbm_device *gbm = gbm_create_device(pipe.fd);
429 if (!gbm) {
430 bs_debug_error("failed to create gbm");
431 return 1;
432 }
433
434 struct gbm_bo *bg_bo = gbm_bo_create(gbm, mode.hdisplay, mode.vdisplay, GBM_FORMAT_XRGB8888,
435 GBM_BO_USE_SCANOUT | GBM_BO_USE_LINEAR);
436 if (!bg_bo) {
437 bs_debug_error("failed to create background buffer ojbect");
438 return 1;
439 }
440
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700441 struct bs_mapper *mapper = bs_mapper_dma_buf_new();
442 if (mapper == NULL) {
443 bs_debug_error("failed to create mapper object");
444 return 1;
445 }
446
447 void *map_data;
448 void *bo_ptr = bs_mapper_map(mapper, bg_bo, 0, &map_data);
449 if (bo_ptr == MAP_FAILED) {
Zach Reiznerd847a7e2016-04-28 16:48:32 -0700450 bs_debug_error("failed to mmap background buffer object");
451 return 1;
452 }
453 memset(bo_ptr, 0xff, gbm_bo_get_height(bg_bo) * gbm_bo_get_stride(bg_bo));
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700454 bs_mapper_unmap(mapper, bg_bo, map_data);
Zach Reiznerd847a7e2016-04-28 16:48:32 -0700455
Zach Reiznerd847a7e2016-04-28 16:48:32 -0700456 uint32_t crtc_fb_id = bs_drm_fb_create_gbm(bg_bo);
457 if (!crtc_fb_id) {
458 bs_debug_error("failed to create frame buffer for buffer object");
459 return 1;
460 }
461
Zach Reiznerfa0547a2016-05-11 18:43:40 -0700462 for (size_t test_plane_index = 0; test_plane_index < test_planes_count;
463 test_plane_index++) {
464 struct test_plane *tp = &test_planes[test_plane_index];
465
466 if (!tp->format)
Gurchetan Singh61208942017-01-27 13:31:19 -0800467 tp->format = bs_get_draw_format(GBM_FORMAT_NV12);
Zach Reiznerfa0547a2016-05-11 18:43:40 -0700468
Gurchetan Singh61208942017-01-27 13:31:19 -0800469 test_planes_formats[test_plane_index] = bs_get_pixel_format(tp->format);
Zach Reiznerfa0547a2016-05-11 18:43:40 -0700470
471 if (!tp->has_bo_size) {
472 tp->bo_w = mode.hdisplay;
473 tp->bo_h = mode.vdisplay;
474 }
475
476 if (!tp->has_src_size) {
477 tp->src_w = tp->bo_w;
478 tp->src_h = tp->bo_h;
479 }
480
481 if (!tp->has_dst_size) {
482 tp->dst_w = tp->bo_w;
483 tp->dst_h = tp->bo_h;
484 }
485
486 if (tp->has_dst_position) {
487 tp->dst_center_x = tp->dst_x + mode.hdisplay / 2;
488 tp->dst_center_y = tp->dst_y + mode.vdisplay / 2;
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700489 } else {
Zach Reiznerfa0547a2016-05-11 18:43:40 -0700490 tp->dst_center_x = mode.hdisplay / 2;
491 tp->dst_center_y = mode.vdisplay / 2;
492 tp->dst_x = tp->dst_center_x - tp->dst_w / 2;
493 tp->dst_y = tp->dst_center_y - tp->dst_h / 2;
494 }
495
496 if (tp->has_dst_scale) {
497 tp->dst_min_w = tp->dst_w / tp->dst_downscale_factor;
498 tp->dst_max_w = tp->dst_w * tp->dst_upscale_factor;
499 tp->dst_min_h = tp->dst_h / tp->dst_downscale_factor;
500 tp->dst_max_h = tp->dst_h * tp->dst_upscale_factor;
501 }
502
Gurchetan Singh61208942017-01-27 13:31:19 -0800503 printf("Creating buffer %ux%u %s\n", tp->bo_w, tp->bo_h,
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700504 bs_get_format_name(tp->format));
Gurchetan Singh61208942017-01-27 13:31:19 -0800505 tp->bo = gbm_bo_create(gbm, tp->bo_w, tp->bo_h, bs_get_pixel_format(tp->format),
Zach Reiznerfa0547a2016-05-11 18:43:40 -0700506 GBM_BO_USE_SCANOUT | GBM_BO_USE_LINEAR);
507 if (!tp->bo) {
508 bs_debug_error("failed to create buffer object");
509 return 1;
510 }
511
512 tp->fb_id = bs_drm_fb_create_gbm(tp->bo);
513 if (!tp->fb_id) {
514 bs_debug_error("failed to create plane frame buffer for buffer object");
515 return 1;
516 }
517
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700518 if (!bs_draw_pattern(mapper, tp->bo, tp->format)) {
Zach Reiznerfa0547a2016-05-11 18:43:40 -0700519 bs_debug_error("failed to draw pattern to buffer object");
520 return 1;
521 }
522 }
523
524 if (!find_overlay_planes(pipe.fd, pipe.crtc_id, test_planes_count, test_planes_formats,
525 test_planes_ids)) {
526 bs_debug_error("failed to find overlay planes for given formats");
Zach Reiznerd847a7e2016-04-28 16:48:32 -0700527 return 1;
528 }
529
Zach Reiznerfa0547a2016-05-11 18:43:40 -0700530 ret = drmModeSetCrtc(pipe.fd, pipe.crtc_id, crtc_fb_id, 0, 0, &pipe.connector_id, 1, &mode);
Zach Reiznerd847a7e2016-04-28 16:48:32 -0700531 if (ret < 0) {
532 bs_debug_error("Could not set mode on CRTC %d %s", pipe.crtc_id, strerror(errno));
533 return 1;
534 }
535
Zach Reiznerfa0547a2016-05-11 18:43:40 -0700536 struct timespec start;
537 clock_gettime(CLOCK_MONOTONIC, &start);
538 const int64_t ten_seconds_in_ns = 10000000000;
539 for (int i = 0; ns_since(&start) < ten_seconds_in_ns; i++) {
540 for (size_t test_plane_index = 0; test_plane_index < test_planes_count;
541 test_plane_index++) {
542 struct test_plane *current_plane = &test_planes[test_plane_index];
Zach Reiznerd847a7e2016-04-28 16:48:32 -0700543
Zach Reiznerfa0547a2016-05-11 18:43:40 -0700544 bool needs_set =
545 update_test_plane(i, mode.hdisplay, mode.vdisplay, current_plane);
546 if (!needs_set)
547 continue;
548
549 ret = drmModeSetPlane(
550 pipe.fd, test_planes_ids[test_plane_index], pipe.crtc_id,
551 current_plane->fb_id, 0 /* flags */, current_plane->dst_x,
552 current_plane->dst_y, current_plane->dst_w, current_plane->dst_h,
553 current_plane->src_x << 16, current_plane->src_y << 16,
554 current_plane->src_w << 16, current_plane->src_h << 16);
555
556 if (ret) {
557 bs_debug_error(
558 "failed to set plane "
559 "%d:\ndst[x,y,w,h]=%d,%d,%u,%u\nsrc[x,y,w,h]=%d,%d,%u,%u",
560 ret, current_plane->dst_x, current_plane->dst_y,
561 current_plane->dst_w, current_plane->dst_h,
562 current_plane->src_x, current_plane->src_y,
563 current_plane->src_w, current_plane->src_h);
564 return 1;
565 }
566 }
567
568 usleep(1000000 / 60);
Zach Reiznerd847a7e2016-04-28 16:48:32 -0700569 }
570
Zach Reiznerd847a7e2016-04-28 16:48:32 -0700571 ret = drmModeSetCrtc(pipe.fd, pipe.crtc_id, 0, 0, 0, NULL, 0, NULL);
572 if (ret < 0) {
573 bs_debug_error("Could not disable CRTC %d %s", pipe.crtc_id, strerror(errno));
574 return 1;
575 }
576
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700577 bs_mapper_destroy(mapper);
Zach Reiznerfa0547a2016-05-11 18:43:40 -0700578 for (size_t test_plane_index = 0; test_plane_index < test_planes_count;
579 test_plane_index++) {
580 struct test_plane *current_plane = &test_planes[test_plane_index];
581 drmModeRmFB(pipe.fd, current_plane->fb_id);
582 gbm_bo_destroy(current_plane->bo);
583 }
Zach Reiznerd847a7e2016-04-28 16:48:32 -0700584 drmModeRmFB(pipe.fd, crtc_fb_id);
Zach Reiznerd847a7e2016-04-28 16:48:32 -0700585 gbm_bo_destroy(bg_bo);
586 gbm_device_destroy(gbm);
587 close(pipe.fd);
588
589 return 0;
590}