blob: da7fe7374be46d0a1bcc11378b0d44f587d299d7 [file] [log] [blame]
Haixia Shi4652b8c2014-11-19 17:55:38 -08001/*
2 * Copyright 2014 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
Daniele Castagna8a63a602016-10-10 18:43:29 -04007#include <getopt.h>
8
Mark Yacoub97d267a2019-07-17 14:44:08 -04009#include "bs_drm.h"
10
Gurchetan Singh10008e62017-03-09 11:14:38 -080011#define NUM_BUFFERS 2
12
Mark Yacoub97d267a2019-07-17 14:44:08 -040013typedef struct drm_property_value {
14 char property_name[15];
15 uint64_t value;
16} drm_property_value_t;
17
18struct bs_drm_pipe drm_pipe = { 0 };
19
20struct bs_egl_fb *egl_fbs[NUM_BUFFERS];
21EGLImageKHR egl_images[NUM_BUFFERS];
22struct bs_egl *egl = NULL;
23uint32_t ids[NUM_BUFFERS];
24
Daniele Castagna72729122017-10-18 17:09:36 -040025static uint32_t allowed_formats[] = {
Mark Yacoub97d267a2019-07-17 14:44:08 -040026 GBM_FORMAT_XRGB8888,
27 GBM_FORMAT_XBGR8888,
28 GBM_FORMAT_XRGB2101010,
29 GBM_FORMAT_XBGR2101010,
Miguel Casascb821462019-11-19 13:52:22 -050030 GBM_FORMAT_ARGB2101010,
31 GBM_FORMAT_ABGR2101010,
Mark Yacoub97d267a2019-07-17 14:44:08 -040032};
33
34static const struct option longopts[] = {
35 { "format", required_argument, NULL, 'f' },
36 { "modifier", required_argument, NULL, 'm' },
37 { "test-page-flip-format-change", required_argument, NULL, 'p' },
38 { "banding", no_argument, NULL, 'b' },
39 { "help", no_argument, NULL, 'h' },
40 { 0, 0, 0, 0 },
Daniele Castagna72729122017-10-18 17:09:36 -040041};
42
43const size_t allowed_formats_length = BS_ARRAY_LEN(allowed_formats);
44
Zach Reizner4dfdf602016-03-01 13:06:30 -080045static GLuint solid_shader_create()
Haixia Shie04ddfd2014-11-11 19:14:32 -080046{
Zach Reizner4dfdf602016-03-01 13:06:30 -080047 const GLchar *vert =
Zach Reizner38f0fd92016-02-18 14:28:02 -080048 "attribute vec4 vPosition;\n"
49 "attribute vec4 vColor;\n"
50 "varying vec4 vFillColor;\n"
51 "void main() {\n"
52 " gl_Position = vPosition;\n"
53 " vFillColor = vColor;\n"
54 "}\n";
Haixia Shie04ddfd2014-11-11 19:14:32 -080055
Zach Reizner4dfdf602016-03-01 13:06:30 -080056 const GLchar *frag =
Zach Reizner38f0fd92016-02-18 14:28:02 -080057 "precision mediump float;\n"
58 "varying vec4 vFillColor;\n"
59 "void main() {\n"
60 " gl_FragColor = vFillColor;\n"
61 "}\n";
Lauri Peltonen763ca462014-12-17 12:22:21 -080062
Zach Reizner4dfdf602016-03-01 13:06:30 -080063 struct bs_gl_program_create_binding bindings[] = {
Mark Yacoub97d267a2019-07-17 14:44:08 -040064 { 0, "vPosition" },
65 { 1, "vColor" },
66 { 0, NULL },
Zach Reizner4dfdf602016-03-01 13:06:30 -080067 };
Haixia Shie04ddfd2014-11-11 19:14:32 -080068
Zach Reizner4dfdf602016-03-01 13:06:30 -080069 return bs_gl_program_create_vert_frag_bind(vert, frag, bindings);
Haixia Shie04ddfd2014-11-11 19:14:32 -080070}
71
Lauri Peltonen95226da2014-12-18 16:39:54 -080072static float f(int i)
73{
Haixia Shie04ddfd2014-11-11 19:14:32 -080074 int a = i % 40;
75 int b = (i / 40) % 6;
76 switch (b) {
Zach Reizner38f0fd92016-02-18 14:28:02 -080077 case 0:
78 case 1:
79 return 0.0f;
80 case 3:
81 case 4:
82 return 1.0f;
83 case 2:
84 return (a / 40.0f);
85 case 5:
86 return 1.0f - (a / 40.0f);
87 default:
88 return 0.0f;
Haixia Shie04ddfd2014-11-11 19:14:32 -080089 }
90}
91
Daniele Castagna72729122017-10-18 17:09:36 -040092static uint32_t find_format(char *fourcc)
93{
94 if (!fourcc || strlen(fourcc) < 4)
95 return 0;
96
97 uint32_t format = fourcc_code(fourcc[0], fourcc[1], fourcc[2], fourcc[3]);
98 for (int i = 0; i < allowed_formats_length; i++) {
99 if (allowed_formats[i] == format)
100 return format;
101 }
102
103 return 0;
104}
105
Mark Yacoub97d267a2019-07-17 14:44:08 -0400106static void print_help(const char *argv0, int drm_device_fd)
Daniele Castagna8a63a602016-10-10 18:43:29 -0400107{
Daniele Castagna72729122017-10-18 17:09:36 -0400108 char allowed_formats_string[allowed_formats_length * 6];
109 int i;
110 for (i = 0; i < allowed_formats_length; i++) {
111 uint32_t format = allowed_formats[i];
112 sprintf(allowed_formats_string + i * 6, "%.4s, ", (char *)&format);
113 }
114
115 allowed_formats_string[i * 6 - 2] = 0;
116
Daniele Castagna8a63a602016-10-10 18:43:29 -0400117 // clang-format off
118 printf("usage: %s [OPTIONS] [drm_device_path]\n", argv0);
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800119 printf(" -f, --format <format> defines the fb format.\n");
120 printf(" -m, --modifier <modifier> pass modifiers.\n");
121 printf(" -p, --test-page-flip-format-change <format> test page flips alternating formats.\n");
Miguel Casasab04f3e2019-03-21 14:40:37 -0400122 printf(" -b, --banding show a pattern that makes banding easy to spot if present.\n");
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800123 printf(" -h, --help show help\n");
Daniele Castagna8a63a602016-10-10 18:43:29 -0400124 printf("\n");
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800125 printf(" <format> must be one of [ %s ].\n", allowed_formats_string);
126 printf(" <modifier> must be one of ");
Mark Yacoub97d267a2019-07-17 14:44:08 -0400127 bs_print_supported_modifiers(drm_device_fd);
Daniele Castagna72729122017-10-18 17:09:36 -0400128 printf("\n");
Daniele Castagna8a63a602016-10-10 18:43:29 -0400129 printf("\n");
130 // clang-format on
131}
132
Mark Yacoub97d267a2019-07-17 14:44:08 -0400133static bool draw_gl(drmModeModeInfo *mode, int fb_idx, int color_idx, GLuint program,
134 bool banding_pattern)
135{
136 // clang-format off
137 const GLfloat triangle_vertices[] = {
138 0.0f, -0.5f, 0.0f,
139 -0.5f, 0.5f, 0.0f,
140 0.5f, 0.5f, 0.0f
141 };
142 const GLfloat triangle_colors[] = {
143 1.0f, 0.0f, 0.0f, 1.0f,
144 0.0f, 1.0f, 0.0f, 1.0f,
145 0.0f, 0.0f, 1.0f, 1.0f
146 };
147 const GLfloat square_vertices[] = {
148 -1.0f, -1.0f, 0.0f,
149 1.0f, -1.0f, 0.0f,
150 -1.0f, 1.0f, 0.0f,
151 1.0f, 1.0f, 0.0f,
152 };
153 const GLfloat square_colors[] = {
154 0.05f, 0.05f, 0.05f, 1.0f,
155 0.05f, 0.05f, 0.05f, 1.0f,
156 0.45f, 0.45f, 0.45f, 1.0f,
157 0.45f, 0.45f, 0.45f, 1.0f,
158 };
159
160 glBindFramebuffer(GL_FRAMEBUFFER, bs_egl_fb_name(egl_fbs[fb_idx]));
161 glViewport(0, 0, (GLint)mode->hdisplay, (GLint)mode->vdisplay);
162
163 glClearColor(f(color_idx), f(color_idx + 80), f(color_idx + 160), 0.0f);
164 glClear(GL_COLOR_BUFFER_BIT);
165
166 glUseProgram(program);
167 if (banding_pattern) {
168 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, square_vertices);
169 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, square_colors);
170 } else {
171 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, triangle_vertices);
172 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, triangle_colors);
173 }
174 glEnableVertexAttribArray(0);
175 glEnableVertexAttribArray(1);
176 glDrawArrays(GL_TRIANGLES, 0, 3);
177
178 usleep(1e6 / 120 /* 120 Hz */);
179 glFinish();
180
181 if (!bs_egl_image_flush_external(egl, egl_images[fb_idx])) {
182 bs_debug_error("failed to call image_flush_external");
183 return false;
184 }
185
186 return true;
187}
188
189bool check_if_fd_valid(fd)
190{
191 if (fd < 0) {
192 bs_debug_error("fd is not valid.");
193 return false;
194 }
195 if (fcntl(fd, F_GETFD, 0) < 0) {
196 bs_debug_error("Unable to return the fd flags.");
197 return false;
198 }
199 return true;
200}
201
202static int test_atomic(int drm_device_fd, drmModeModeInfo *mode, GLuint program,
203 bool banding_pattern)
204{
205 uint32_t connector_id = drm_pipe.connector_id;
206 uint32_t crtc_id = drm_pipe.crtc_id;
207 uint32_t plane_id = bs_get_plane_id(drm_device_fd, crtc_id);
208 if (plane_id < 1) {
209 bs_debug_error("failed to get Plane ID.");
210 return -1;
211 }
212
213 uint32_t mode_blob_id = 0;
214 drmModeCreatePropertyBlob(drm_device_fd, mode, sizeof(drmModeModeInfo), &mode_blob_id);
215 assert(mode_blob_id);
216
217 int res = drmSetClientCap(drm_device_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
218 assert(!res);
219
220 uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_ALLOW_MODESET;
221 drmModeAtomicReqPtr atomic_req = drmModeAtomicAlloc();
222 int cursor = drmModeAtomicGetCursor(atomic_req);
223
224 const drm_property_value_t connector_props[] = { { "CRTC_ID", crtc_id } };
225 for (size_t i = 0; i < BS_ARRAY_LEN(connector_props); ++i) {
226 uint32_t prop =
227 bs_drm_find_property_id(drm_device_fd, connector_id, DRM_MODE_OBJECT_CONNECTOR,
228 connector_props[i].property_name);
229 drmModeAtomicAddProperty(atomic_req, connector_id, prop, connector_props[i].value);
230 }
231
232 int out_fence_fd = -1;
233 const drm_property_value_t crtc_props[] = { { "OUT_FENCE_PTR", (uint64_t)&out_fence_fd },
234 { "MODE_ID", mode_blob_id },
235 { "ACTIVE", 1 } };
236 for (size_t i = 0; i < BS_ARRAY_LEN(crtc_props); ++i) {
237 uint32_t prop = bs_drm_find_property_id(
238 drm_device_fd, crtc_id, DRM_MODE_OBJECT_CRTC, crtc_props[i].property_name);
239 drmModeAtomicAddProperty(atomic_req, crtc_id, prop, crtc_props[i].value);
240 }
241
242 const drm_property_value_t plane_props[] = {
243 { "CRTC_ID", crtc_id },
244 { "CRTC_X", 0 },
245 { "CRTC_Y", 0 },
246 { "CRTC_W", mode->hdisplay },
247 { "CRTC_H", mode->vdisplay },
248 { "SRC_X", 0 },
249 { "SRC_Y", 0 },
250 { "SRC_W", mode->hdisplay << 16 },
251 { "SRC_H", mode->vdisplay << 16 },
252 };
253 for (size_t i = 0; i < BS_ARRAY_LEN(plane_props); ++i) {
254 uint32_t prop = bs_drm_find_property_id(
255 drm_device_fd, plane_id, DRM_MODE_OBJECT_PLANE, plane_props[i].property_name);
256 drmModeAtomicAddProperty(atomic_req, plane_id, prop, plane_props[i].value);
257 }
258
259 uint32_t fb_propery_id =
260 bs_drm_find_property_id(drm_device_fd, plane_id, DRM_MODE_OBJECT_PLANE, "FB_ID");
261
262 fd_set fds;
263 FD_ZERO(&fds);
264 FD_SET(drm_device_fd, &fds);
265
266 for (int i = 0; i <= 500; i++) {
267 int fb_idx = i % 2;
268 if (!draw_gl(mode, fb_idx, i, program, banding_pattern))
269 return false;
270
271 drmModeAtomicAddProperty(atomic_req, plane_id, fb_propery_id, ids[fb_idx]);
272 res = drmModeAtomicCommit(drm_device_fd, atomic_req, flags, NULL);
273 assert(!res);
274
275 flags = DRM_MODE_PAGE_FLIP_EVENT;
276 drmModeAtomicSetCursor(atomic_req, cursor);
277 drmModeAtomicFree(atomic_req);
278 atomic_req = drmModeAtomicAlloc();
279
280 check_if_fd_valid(out_fence_fd);
281
282 select(drm_device_fd + 1, &fds, NULL, NULL, NULL);
283 char buffer[1024];
284 int len = read(drm_device_fd, buffer, sizeof(buffer));
285 assert(len > 0);
286 }
287
288 drmModeDestroyPropertyBlob(drm_device_fd, mode_blob_id);
289 return true;
290}
291
292static void page_flip_handler(int drm_device_fd, unsigned int frame, unsigned int sec,
293 unsigned int usec, void *data)
294{
295 int *waiting_for_flip = data;
296 *waiting_for_flip = 0;
297}
298
299static bool test_non_atomic(int drm_device_fd, drmModeModeInfo *mode, GLuint program,
300 bool banding_pattern)
301{
302 int ret = drmModeSetCrtc(drm_device_fd, drm_pipe.crtc_id, ids[0], 0 /* x */, 0 /* y */,
303 &drm_pipe.connector_id, 1 /* connector count */, mode);
304 if (ret) {
305 bs_debug_error("failed to set CRTC");
306 return false;
307 }
308
309 // NOTE: Loop starts from 1 as `fb_idx` should not be 0. ids[0] is used in drmModeSetCrtc
310 // which gets locked on some devices, so we have to draw to another buffer (ids[1]) and
311 // commit it first to release [0].
312 for (int i = 1; i <= 500; i++) {
313 int waiting_for_flip = 1;
314 int fb_idx = i % 2;
315 if (!draw_gl(mode, i % 2, i, program, banding_pattern))
316 return false;
317
318 int ret = drmModePageFlip(drm_device_fd, drm_pipe.crtc_id, ids[fb_idx],
319 DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip);
320 if (ret) {
321 bs_debug_error("failed page flip: %d", ret);
322 return false;
323 }
324
325 while (waiting_for_flip) {
326 drmEventContext evctx = {
327 .version = DRM_EVENT_CONTEXT_VERSION,
328 .page_flip_handler = page_flip_handler,
329 };
330
331 fd_set fds;
332 FD_ZERO(&fds);
333 FD_SET(drm_device_fd, &fds);
334
335 ret = select(drm_device_fd + 1, &fds, NULL, NULL, NULL);
336 if (ret < 0) {
337 bs_debug_error("select err: %s", strerror(errno));
338 return false;
339 } else if (ret == 0) {
340 bs_debug_error("select timeout");
341 return false;
342 }
343 ret = drmHandleEvent(drm_device_fd, &evctx);
344 if (ret) {
345 bs_debug_error("failed to wait for page flip: %d", ret);
346 return false;
347 }
348 }
349 }
350 return true;
351}
352
Zach Reizner38f0fd92016-02-18 14:28:02 -0800353int main(int argc, char **argv)
Haixia Shie04ddfd2014-11-11 19:14:32 -0800354{
Daniele Castagna8a63a602016-10-10 18:43:29 -0400355 bool help_flag = false;
Daniele Castagna72729122017-10-18 17:09:36 -0400356 uint32_t format = GBM_FORMAT_XRGB8888;
Daniele Castagna95d027f2017-11-01 21:56:58 -0400357 uint32_t test_page_flip_format_change = 0;
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800358 uint64_t modifier = DRM_FORMAT_MOD_INVALID;
Miguel Casasab04f3e2019-03-21 14:40:37 -0400359 bool banding_pattern = false;
Daniele Castagna8a63a602016-10-10 18:43:29 -0400360
361 int c = -1;
Mark Yacoub97d267a2019-07-17 14:44:08 -0400362 while ((c = getopt_long(argc, argv, "m:hp:f:bl", longopts, NULL)) != -1) {
Daniele Castagna8a63a602016-10-10 18:43:29 -0400363 switch (c) {
Daniele Castagna72729122017-10-18 17:09:36 -0400364 case 'p':
365 test_page_flip_format_change = find_format(optarg);
366 if (!test_page_flip_format_change)
367 help_flag = true;
368 break;
Daniele Castagna8a63a602016-10-10 18:43:29 -0400369 case 'f':
Daniele Castagna72729122017-10-18 17:09:36 -0400370 format = find_format(optarg);
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800371 if (!format) {
372 bs_debug_error("unsupported format: %s", optarg);
Daniele Castagna72729122017-10-18 17:09:36 -0400373 help_flag = true;
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800374 }
375 break;
376 case 'm':
377 modifier = bs_string_to_modifier(optarg);
378 if (modifier == -1) {
379 bs_debug_error("unsupported modifier: %s", optarg);
380 help_flag = true;
381 }
Daniele Castagna8a63a602016-10-10 18:43:29 -0400382 break;
Miguel Casasab04f3e2019-03-21 14:40:37 -0400383 case 'b':
384 banding_pattern = true;
385 break;
Daniele Castagna8a63a602016-10-10 18:43:29 -0400386 case 'h':
387 help_flag = true;
388 break;
389 }
390 }
391
Mark Yacoub97d267a2019-07-17 14:44:08 -0400392 int drm_device_fd = -1;
Daniele Castagna8a63a602016-10-10 18:43:29 -0400393 if (optind < argc) {
Mark Yacoub97d267a2019-07-17 14:44:08 -0400394 drm_device_fd = open(argv[optind], O_RDWR);
395 if (drm_device_fd < 0) {
Daniele Castagna8a63a602016-10-10 18:43:29 -0400396 bs_debug_error("failed to open card %s", argv[optind]);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800397 return 1;
398 }
Zach Reiznerbf26be82016-09-15 16:06:21 -0700399 } else {
Mark Yacoub97d267a2019-07-17 14:44:08 -0400400 drm_device_fd = bs_drm_open_main_display();
401 if (drm_device_fd < 0) {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800402 bs_debug_error("failed to open card for display");
403 return 1;
404 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800405 }
406
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800407 if (help_flag) {
Mark Yacoub97d267a2019-07-17 14:44:08 -0400408 print_help(*argv, drm_device_fd);
409 close(drm_device_fd);
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800410 return 1;
411 }
412
Mark Yacoub97d267a2019-07-17 14:44:08 -0400413 struct gbm_device *gbm = gbm_create_device(drm_device_fd);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800414 if (!gbm) {
415 bs_debug_error("failed to create gbm");
416 return 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800417 }
418
Mark Yacoub97d267a2019-07-17 14:44:08 -0400419 if (!bs_drm_pipe_make(drm_device_fd, &drm_pipe)) {
420 bs_debug_error("failed to make drm_pipe");
Zach Reizner38f0fd92016-02-18 14:28:02 -0800421 return 1;
422 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800423
Mark Yacoub97d267a2019-07-17 14:44:08 -0400424 drmModeConnector *connector = drmModeGetConnector(drm_device_fd, drm_pipe.connector_id);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800425 assert(connector);
426 drmModeModeInfo *mode = &connector->modes[0];
427
Mark Yacoub97d267a2019-07-17 14:44:08 -0400428 egl = bs_egl_new();
Zach Reizner38f0fd92016-02-18 14:28:02 -0800429 if (!bs_egl_setup(egl)) {
430 bs_debug_error("failed to setup egl context");
431 return 1;
432 }
433
Gurchetan Singh10008e62017-03-09 11:14:38 -0800434 struct gbm_bo *bos[NUM_BUFFERS];
Gurchetan Singh10008e62017-03-09 11:14:38 -0800435 for (size_t fb_index = 0; fb_index < NUM_BUFFERS; fb_index++) {
Daniele Castagna8a63a602016-10-10 18:43:29 -0400436 if (test_page_flip_format_change && fb_index) {
Daniele Castagna72729122017-10-18 17:09:36 -0400437 format = test_page_flip_format_change;
Daniele Castagna8a63a602016-10-10 18:43:29 -0400438 }
439
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800440 if (modifier != DRM_FORMAT_MOD_INVALID) {
441 bos[fb_index] = gbm_bo_create_with_modifiers(
442 gbm, mode->hdisplay, mode->vdisplay, format, &modifier, 1);
443 } else {
444 bos[fb_index] = gbm_bo_create(gbm, mode->hdisplay, mode->vdisplay, format,
445 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
446 }
447
Zach Reizner38f0fd92016-02-18 14:28:02 -0800448 if (bos[fb_index] == NULL) {
Miguel Casascb821462019-11-19 13:52:22 -0500449 bs_debug_error("failed to allocate BO %s modifiers",
450 (modifier != DRM_FORMAT_MOD_INVALID ? "with" : "without"));
Zach Reizner38f0fd92016-02-18 14:28:02 -0800451 return 1;
452 }
453
454 ids[fb_index] = bs_drm_fb_create_gbm(bos[fb_index]);
455 if (ids[fb_index] == 0) {
456 bs_debug_error("failed to create framebuffer id");
457 return 1;
458 }
459
460 EGLImageKHR egl_image = bs_egl_image_create_gbm(egl, bos[fb_index]);
461 if (egl_image == EGL_NO_IMAGE_KHR) {
462 bs_debug_error("failed to create EGLImageKHR from framebuffer");
463 return 1;
464 }
465
466 egl_fbs[fb_index] = bs_egl_fb_new(egl, egl_image);
467 if (!egl_fbs[fb_index]) {
468 bs_debug_error("failed to create framebuffer from EGLImageKHR");
469 return 1;
470 }
Haixia Shife4e2ff2016-10-17 14:28:55 -0700471 egl_images[fb_index] = egl_image;
Zach Reizner38f0fd92016-02-18 14:28:02 -0800472 }
473
Zach Reizner38f0fd92016-02-18 14:28:02 -0800474 GLuint program = solid_shader_create();
Haixia Shie04ddfd2014-11-11 19:14:32 -0800475 if (!program) {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800476 bs_debug_error("failed to create solid shader");
477 return 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800478 }
479
Mark Yacoub97d267a2019-07-17 14:44:08 -0400480 struct drm_set_client_cap cap = { DRM_CLIENT_CAP_ATOMIC, 1 };
481 bool has_atomic_capabilities = !drmIoctl(drm_device_fd, DRM_IOCTL_SET_CLIENT_CAP, &cap);
482 if (has_atomic_capabilities) {
483 if (!test_atomic(drm_device_fd, mode, program, banding_pattern))
Haixia Shife4e2ff2016-10-17 14:28:55 -0700484 return 1;
Mark Yacoub97d267a2019-07-17 14:44:08 -0400485 } else {
486 printf("Running Legacy API. Atomic API is not supported.\n");
487 if (!test_non_atomic(drm_device_fd, mode, program, banding_pattern))
Zach Reizner38f0fd92016-02-18 14:28:02 -0800488 return 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800489 }
490
Gurchetan Singh10008e62017-03-09 11:14:38 -0800491 for (size_t fb_index = 0; fb_index < NUM_BUFFERS; fb_index++) {
492 bs_egl_fb_destroy(&egl_fbs[fb_index]);
493 bs_egl_image_destroy(egl, &egl_images[fb_index]);
Mark Yacoub97d267a2019-07-17 14:44:08 -0400494 drmModeRmFB(drm_device_fd, ids[fb_index]);
Gurchetan Singh10008e62017-03-09 11:14:38 -0800495 gbm_bo_destroy(bos[fb_index]);
496 }
497
498 bs_egl_destroy(&egl);
499 gbm_device_destroy(gbm);
Mark Yacoub97d267a2019-07-17 14:44:08 -0400500 close(drm_device_fd);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800501 return 0;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800502}