blob: 0763bac507f402ffd00508d45b8c9001cb21789d [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,
30};
31
32static const struct option longopts[] = {
33 { "format", required_argument, NULL, 'f' },
34 { "modifier", required_argument, NULL, 'm' },
35 { "test-page-flip-format-change", required_argument, NULL, 'p' },
36 { "banding", no_argument, NULL, 'b' },
37 { "help", no_argument, NULL, 'h' },
38 { 0, 0, 0, 0 },
Daniele Castagna72729122017-10-18 17:09:36 -040039};
40
41const size_t allowed_formats_length = BS_ARRAY_LEN(allowed_formats);
42
Zach Reizner4dfdf602016-03-01 13:06:30 -080043static GLuint solid_shader_create()
Haixia Shie04ddfd2014-11-11 19:14:32 -080044{
Zach Reizner4dfdf602016-03-01 13:06:30 -080045 const GLchar *vert =
Zach Reizner38f0fd92016-02-18 14:28:02 -080046 "attribute vec4 vPosition;\n"
47 "attribute vec4 vColor;\n"
48 "varying vec4 vFillColor;\n"
49 "void main() {\n"
50 " gl_Position = vPosition;\n"
51 " vFillColor = vColor;\n"
52 "}\n";
Haixia Shie04ddfd2014-11-11 19:14:32 -080053
Zach Reizner4dfdf602016-03-01 13:06:30 -080054 const GLchar *frag =
Zach Reizner38f0fd92016-02-18 14:28:02 -080055 "precision mediump float;\n"
56 "varying vec4 vFillColor;\n"
57 "void main() {\n"
58 " gl_FragColor = vFillColor;\n"
59 "}\n";
Lauri Peltonen763ca462014-12-17 12:22:21 -080060
Zach Reizner4dfdf602016-03-01 13:06:30 -080061 struct bs_gl_program_create_binding bindings[] = {
Mark Yacoub97d267a2019-07-17 14:44:08 -040062 { 0, "vPosition" },
63 { 1, "vColor" },
64 { 0, NULL },
Zach Reizner4dfdf602016-03-01 13:06:30 -080065 };
Haixia Shie04ddfd2014-11-11 19:14:32 -080066
Zach Reizner4dfdf602016-03-01 13:06:30 -080067 return bs_gl_program_create_vert_frag_bind(vert, frag, bindings);
Haixia Shie04ddfd2014-11-11 19:14:32 -080068}
69
Lauri Peltonen95226da2014-12-18 16:39:54 -080070static float f(int i)
71{
Haixia Shie04ddfd2014-11-11 19:14:32 -080072 int a = i % 40;
73 int b = (i / 40) % 6;
74 switch (b) {
Zach Reizner38f0fd92016-02-18 14:28:02 -080075 case 0:
76 case 1:
77 return 0.0f;
78 case 3:
79 case 4:
80 return 1.0f;
81 case 2:
82 return (a / 40.0f);
83 case 5:
84 return 1.0f - (a / 40.0f);
85 default:
86 return 0.0f;
Haixia Shie04ddfd2014-11-11 19:14:32 -080087 }
88}
89
Daniele Castagna72729122017-10-18 17:09:36 -040090static uint32_t find_format(char *fourcc)
91{
92 if (!fourcc || strlen(fourcc) < 4)
93 return 0;
94
95 uint32_t format = fourcc_code(fourcc[0], fourcc[1], fourcc[2], fourcc[3]);
96 for (int i = 0; i < allowed_formats_length; i++) {
97 if (allowed_formats[i] == format)
98 return format;
99 }
100
101 return 0;
102}
103
Mark Yacoub97d267a2019-07-17 14:44:08 -0400104static void print_help(const char *argv0, int drm_device_fd)
Daniele Castagna8a63a602016-10-10 18:43:29 -0400105{
Daniele Castagna72729122017-10-18 17:09:36 -0400106 char allowed_formats_string[allowed_formats_length * 6];
107 int i;
108 for (i = 0; i < allowed_formats_length; i++) {
109 uint32_t format = allowed_formats[i];
110 sprintf(allowed_formats_string + i * 6, "%.4s, ", (char *)&format);
111 }
112
113 allowed_formats_string[i * 6 - 2] = 0;
114
Daniele Castagna8a63a602016-10-10 18:43:29 -0400115 // clang-format off
116 printf("usage: %s [OPTIONS] [drm_device_path]\n", argv0);
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800117 printf(" -f, --format <format> defines the fb format.\n");
118 printf(" -m, --modifier <modifier> pass modifiers.\n");
119 printf(" -p, --test-page-flip-format-change <format> test page flips alternating formats.\n");
Miguel Casasab04f3e2019-03-21 14:40:37 -0400120 printf(" -b, --banding show a pattern that makes banding easy to spot if present.\n");
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800121 printf(" -h, --help show help\n");
Daniele Castagna8a63a602016-10-10 18:43:29 -0400122 printf("\n");
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800123 printf(" <format> must be one of [ %s ].\n", allowed_formats_string);
124 printf(" <modifier> must be one of ");
Mark Yacoub97d267a2019-07-17 14:44:08 -0400125 bs_print_supported_modifiers(drm_device_fd);
Daniele Castagna72729122017-10-18 17:09:36 -0400126 printf("\n");
Daniele Castagna8a63a602016-10-10 18:43:29 -0400127 printf("\n");
128 // clang-format on
129}
130
Mark Yacoub97d267a2019-07-17 14:44:08 -0400131static bool draw_gl(drmModeModeInfo *mode, int fb_idx, int color_idx, GLuint program,
132 bool banding_pattern)
133{
134 // clang-format off
135 const GLfloat triangle_vertices[] = {
136 0.0f, -0.5f, 0.0f,
137 -0.5f, 0.5f, 0.0f,
138 0.5f, 0.5f, 0.0f
139 };
140 const GLfloat triangle_colors[] = {
141 1.0f, 0.0f, 0.0f, 1.0f,
142 0.0f, 1.0f, 0.0f, 1.0f,
143 0.0f, 0.0f, 1.0f, 1.0f
144 };
145 const GLfloat square_vertices[] = {
146 -1.0f, -1.0f, 0.0f,
147 1.0f, -1.0f, 0.0f,
148 -1.0f, 1.0f, 0.0f,
149 1.0f, 1.0f, 0.0f,
150 };
151 const GLfloat square_colors[] = {
152 0.05f, 0.05f, 0.05f, 1.0f,
153 0.05f, 0.05f, 0.05f, 1.0f,
154 0.45f, 0.45f, 0.45f, 1.0f,
155 0.45f, 0.45f, 0.45f, 1.0f,
156 };
157
158 glBindFramebuffer(GL_FRAMEBUFFER, bs_egl_fb_name(egl_fbs[fb_idx]));
159 glViewport(0, 0, (GLint)mode->hdisplay, (GLint)mode->vdisplay);
160
161 glClearColor(f(color_idx), f(color_idx + 80), f(color_idx + 160), 0.0f);
162 glClear(GL_COLOR_BUFFER_BIT);
163
164 glUseProgram(program);
165 if (banding_pattern) {
166 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, square_vertices);
167 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, square_colors);
168 } else {
169 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, triangle_vertices);
170 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, triangle_colors);
171 }
172 glEnableVertexAttribArray(0);
173 glEnableVertexAttribArray(1);
174 glDrawArrays(GL_TRIANGLES, 0, 3);
175
176 usleep(1e6 / 120 /* 120 Hz */);
177 glFinish();
178
179 if (!bs_egl_image_flush_external(egl, egl_images[fb_idx])) {
180 bs_debug_error("failed to call image_flush_external");
181 return false;
182 }
183
184 return true;
185}
186
187bool check_if_fd_valid(fd)
188{
189 if (fd < 0) {
190 bs_debug_error("fd is not valid.");
191 return false;
192 }
193 if (fcntl(fd, F_GETFD, 0) < 0) {
194 bs_debug_error("Unable to return the fd flags.");
195 return false;
196 }
197 return true;
198}
199
200static int test_atomic(int drm_device_fd, drmModeModeInfo *mode, GLuint program,
201 bool banding_pattern)
202{
203 uint32_t connector_id = drm_pipe.connector_id;
204 uint32_t crtc_id = drm_pipe.crtc_id;
205 uint32_t plane_id = bs_get_plane_id(drm_device_fd, crtc_id);
206 if (plane_id < 1) {
207 bs_debug_error("failed to get Plane ID.");
208 return -1;
209 }
210
211 uint32_t mode_blob_id = 0;
212 drmModeCreatePropertyBlob(drm_device_fd, mode, sizeof(drmModeModeInfo), &mode_blob_id);
213 assert(mode_blob_id);
214
215 int res = drmSetClientCap(drm_device_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
216 assert(!res);
217
218 uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_ALLOW_MODESET;
219 drmModeAtomicReqPtr atomic_req = drmModeAtomicAlloc();
220 int cursor = drmModeAtomicGetCursor(atomic_req);
221
222 const drm_property_value_t connector_props[] = { { "CRTC_ID", crtc_id } };
223 for (size_t i = 0; i < BS_ARRAY_LEN(connector_props); ++i) {
224 uint32_t prop =
225 bs_drm_find_property_id(drm_device_fd, connector_id, DRM_MODE_OBJECT_CONNECTOR,
226 connector_props[i].property_name);
227 drmModeAtomicAddProperty(atomic_req, connector_id, prop, connector_props[i].value);
228 }
229
230 int out_fence_fd = -1;
231 const drm_property_value_t crtc_props[] = { { "OUT_FENCE_PTR", (uint64_t)&out_fence_fd },
232 { "MODE_ID", mode_blob_id },
233 { "ACTIVE", 1 } };
234 for (size_t i = 0; i < BS_ARRAY_LEN(crtc_props); ++i) {
235 uint32_t prop = bs_drm_find_property_id(
236 drm_device_fd, crtc_id, DRM_MODE_OBJECT_CRTC, crtc_props[i].property_name);
237 drmModeAtomicAddProperty(atomic_req, crtc_id, prop, crtc_props[i].value);
238 }
239
240 const drm_property_value_t plane_props[] = {
241 { "CRTC_ID", crtc_id },
242 { "CRTC_X", 0 },
243 { "CRTC_Y", 0 },
244 { "CRTC_W", mode->hdisplay },
245 { "CRTC_H", mode->vdisplay },
246 { "SRC_X", 0 },
247 { "SRC_Y", 0 },
248 { "SRC_W", mode->hdisplay << 16 },
249 { "SRC_H", mode->vdisplay << 16 },
250 };
251 for (size_t i = 0; i < BS_ARRAY_LEN(plane_props); ++i) {
252 uint32_t prop = bs_drm_find_property_id(
253 drm_device_fd, plane_id, DRM_MODE_OBJECT_PLANE, plane_props[i].property_name);
254 drmModeAtomicAddProperty(atomic_req, plane_id, prop, plane_props[i].value);
255 }
256
257 uint32_t fb_propery_id =
258 bs_drm_find_property_id(drm_device_fd, plane_id, DRM_MODE_OBJECT_PLANE, "FB_ID");
259
260 fd_set fds;
261 FD_ZERO(&fds);
262 FD_SET(drm_device_fd, &fds);
263
264 for (int i = 0; i <= 500; i++) {
265 int fb_idx = i % 2;
266 if (!draw_gl(mode, fb_idx, i, program, banding_pattern))
267 return false;
268
269 drmModeAtomicAddProperty(atomic_req, plane_id, fb_propery_id, ids[fb_idx]);
270 res = drmModeAtomicCommit(drm_device_fd, atomic_req, flags, NULL);
271 assert(!res);
272
273 flags = DRM_MODE_PAGE_FLIP_EVENT;
274 drmModeAtomicSetCursor(atomic_req, cursor);
275 drmModeAtomicFree(atomic_req);
276 atomic_req = drmModeAtomicAlloc();
277
278 check_if_fd_valid(out_fence_fd);
279
280 select(drm_device_fd + 1, &fds, NULL, NULL, NULL);
281 char buffer[1024];
282 int len = read(drm_device_fd, buffer, sizeof(buffer));
283 assert(len > 0);
284 }
285
286 drmModeDestroyPropertyBlob(drm_device_fd, mode_blob_id);
287 return true;
288}
289
290static void page_flip_handler(int drm_device_fd, unsigned int frame, unsigned int sec,
291 unsigned int usec, void *data)
292{
293 int *waiting_for_flip = data;
294 *waiting_for_flip = 0;
295}
296
297static bool test_non_atomic(int drm_device_fd, drmModeModeInfo *mode, GLuint program,
298 bool banding_pattern)
299{
300 int ret = drmModeSetCrtc(drm_device_fd, drm_pipe.crtc_id, ids[0], 0 /* x */, 0 /* y */,
301 &drm_pipe.connector_id, 1 /* connector count */, mode);
302 if (ret) {
303 bs_debug_error("failed to set CRTC");
304 return false;
305 }
306
307 // NOTE: Loop starts from 1 as `fb_idx` should not be 0. ids[0] is used in drmModeSetCrtc
308 // which gets locked on some devices, so we have to draw to another buffer (ids[1]) and
309 // commit it first to release [0].
310 for (int i = 1; i <= 500; i++) {
311 int waiting_for_flip = 1;
312 int fb_idx = i % 2;
313 if (!draw_gl(mode, i % 2, i, program, banding_pattern))
314 return false;
315
316 int ret = drmModePageFlip(drm_device_fd, drm_pipe.crtc_id, ids[fb_idx],
317 DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip);
318 if (ret) {
319 bs_debug_error("failed page flip: %d", ret);
320 return false;
321 }
322
323 while (waiting_for_flip) {
324 drmEventContext evctx = {
325 .version = DRM_EVENT_CONTEXT_VERSION,
326 .page_flip_handler = page_flip_handler,
327 };
328
329 fd_set fds;
330 FD_ZERO(&fds);
331 FD_SET(drm_device_fd, &fds);
332
333 ret = select(drm_device_fd + 1, &fds, NULL, NULL, NULL);
334 if (ret < 0) {
335 bs_debug_error("select err: %s", strerror(errno));
336 return false;
337 } else if (ret == 0) {
338 bs_debug_error("select timeout");
339 return false;
340 }
341 ret = drmHandleEvent(drm_device_fd, &evctx);
342 if (ret) {
343 bs_debug_error("failed to wait for page flip: %d", ret);
344 return false;
345 }
346 }
347 }
348 return true;
349}
350
Zach Reizner38f0fd92016-02-18 14:28:02 -0800351int main(int argc, char **argv)
Haixia Shie04ddfd2014-11-11 19:14:32 -0800352{
Daniele Castagna8a63a602016-10-10 18:43:29 -0400353 bool help_flag = false;
Daniele Castagna72729122017-10-18 17:09:36 -0400354 uint32_t format = GBM_FORMAT_XRGB8888;
Daniele Castagna95d027f2017-11-01 21:56:58 -0400355 uint32_t test_page_flip_format_change = 0;
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800356 uint64_t modifier = DRM_FORMAT_MOD_INVALID;
Miguel Casasab04f3e2019-03-21 14:40:37 -0400357 bool banding_pattern = false;
Daniele Castagna8a63a602016-10-10 18:43:29 -0400358
359 int c = -1;
Mark Yacoub97d267a2019-07-17 14:44:08 -0400360 while ((c = getopt_long(argc, argv, "m:hp:f:bl", longopts, NULL)) != -1) {
Daniele Castagna8a63a602016-10-10 18:43:29 -0400361 switch (c) {
Daniele Castagna72729122017-10-18 17:09:36 -0400362 case 'p':
363 test_page_flip_format_change = find_format(optarg);
364 if (!test_page_flip_format_change)
365 help_flag = true;
366 break;
Daniele Castagna8a63a602016-10-10 18:43:29 -0400367 case 'f':
Daniele Castagna72729122017-10-18 17:09:36 -0400368 format = find_format(optarg);
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800369 if (!format) {
370 bs_debug_error("unsupported format: %s", optarg);
Daniele Castagna72729122017-10-18 17:09:36 -0400371 help_flag = true;
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800372 }
373 break;
374 case 'm':
375 modifier = bs_string_to_modifier(optarg);
376 if (modifier == -1) {
377 bs_debug_error("unsupported modifier: %s", optarg);
378 help_flag = true;
379 }
Daniele Castagna8a63a602016-10-10 18:43:29 -0400380 break;
Miguel Casasab04f3e2019-03-21 14:40:37 -0400381 case 'b':
382 banding_pattern = true;
383 break;
Daniele Castagna8a63a602016-10-10 18:43:29 -0400384 case 'h':
385 help_flag = true;
386 break;
387 }
388 }
389
Mark Yacoub97d267a2019-07-17 14:44:08 -0400390 int drm_device_fd = -1;
Daniele Castagna8a63a602016-10-10 18:43:29 -0400391 if (optind < argc) {
Mark Yacoub97d267a2019-07-17 14:44:08 -0400392 drm_device_fd = open(argv[optind], O_RDWR);
393 if (drm_device_fd < 0) {
Daniele Castagna8a63a602016-10-10 18:43:29 -0400394 bs_debug_error("failed to open card %s", argv[optind]);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800395 return 1;
396 }
Zach Reiznerbf26be82016-09-15 16:06:21 -0700397 } else {
Mark Yacoub97d267a2019-07-17 14:44:08 -0400398 drm_device_fd = bs_drm_open_main_display();
399 if (drm_device_fd < 0) {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800400 bs_debug_error("failed to open card for display");
401 return 1;
402 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800403 }
404
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800405 if (help_flag) {
Mark Yacoub97d267a2019-07-17 14:44:08 -0400406 print_help(*argv, drm_device_fd);
407 close(drm_device_fd);
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800408 return 1;
409 }
410
Mark Yacoub97d267a2019-07-17 14:44:08 -0400411 struct gbm_device *gbm = gbm_create_device(drm_device_fd);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800412 if (!gbm) {
413 bs_debug_error("failed to create gbm");
414 return 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800415 }
416
Mark Yacoub97d267a2019-07-17 14:44:08 -0400417 if (!bs_drm_pipe_make(drm_device_fd, &drm_pipe)) {
418 bs_debug_error("failed to make drm_pipe");
Zach Reizner38f0fd92016-02-18 14:28:02 -0800419 return 1;
420 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800421
Mark Yacoub97d267a2019-07-17 14:44:08 -0400422 drmModeConnector *connector = drmModeGetConnector(drm_device_fd, drm_pipe.connector_id);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800423 assert(connector);
424 drmModeModeInfo *mode = &connector->modes[0];
425
Mark Yacoub97d267a2019-07-17 14:44:08 -0400426 egl = bs_egl_new();
Zach Reizner38f0fd92016-02-18 14:28:02 -0800427 if (!bs_egl_setup(egl)) {
428 bs_debug_error("failed to setup egl context");
429 return 1;
430 }
431
Gurchetan Singh10008e62017-03-09 11:14:38 -0800432 struct gbm_bo *bos[NUM_BUFFERS];
Gurchetan Singh10008e62017-03-09 11:14:38 -0800433 for (size_t fb_index = 0; fb_index < NUM_BUFFERS; fb_index++) {
Daniele Castagna8a63a602016-10-10 18:43:29 -0400434 if (test_page_flip_format_change && fb_index) {
Daniele Castagna72729122017-10-18 17:09:36 -0400435 format = test_page_flip_format_change;
Daniele Castagna8a63a602016-10-10 18:43:29 -0400436 }
437
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800438 if (modifier != DRM_FORMAT_MOD_INVALID) {
439 bos[fb_index] = gbm_bo_create_with_modifiers(
440 gbm, mode->hdisplay, mode->vdisplay, format, &modifier, 1);
441 } else {
442 bos[fb_index] = gbm_bo_create(gbm, mode->hdisplay, mode->vdisplay, format,
443 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
444 }
445
Zach Reizner38f0fd92016-02-18 14:28:02 -0800446 if (bos[fb_index] == NULL) {
447 bs_debug_error("failed to allocate framebuffer");
448 return 1;
449 }
450
451 ids[fb_index] = bs_drm_fb_create_gbm(bos[fb_index]);
452 if (ids[fb_index] == 0) {
453 bs_debug_error("failed to create framebuffer id");
454 return 1;
455 }
456
457 EGLImageKHR egl_image = bs_egl_image_create_gbm(egl, bos[fb_index]);
458 if (egl_image == EGL_NO_IMAGE_KHR) {
459 bs_debug_error("failed to create EGLImageKHR from framebuffer");
460 return 1;
461 }
462
463 egl_fbs[fb_index] = bs_egl_fb_new(egl, egl_image);
464 if (!egl_fbs[fb_index]) {
465 bs_debug_error("failed to create framebuffer from EGLImageKHR");
466 return 1;
467 }
Haixia Shife4e2ff2016-10-17 14:28:55 -0700468 egl_images[fb_index] = egl_image;
Zach Reizner38f0fd92016-02-18 14:28:02 -0800469 }
470
Zach Reizner38f0fd92016-02-18 14:28:02 -0800471 GLuint program = solid_shader_create();
Haixia Shie04ddfd2014-11-11 19:14:32 -0800472 if (!program) {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800473 bs_debug_error("failed to create solid shader");
474 return 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800475 }
476
Mark Yacoub97d267a2019-07-17 14:44:08 -0400477 struct drm_set_client_cap cap = { DRM_CLIENT_CAP_ATOMIC, 1 };
478 bool has_atomic_capabilities = !drmIoctl(drm_device_fd, DRM_IOCTL_SET_CLIENT_CAP, &cap);
479 if (has_atomic_capabilities) {
480 if (!test_atomic(drm_device_fd, mode, program, banding_pattern))
Haixia Shife4e2ff2016-10-17 14:28:55 -0700481 return 1;
Mark Yacoub97d267a2019-07-17 14:44:08 -0400482 } else {
483 printf("Running Legacy API. Atomic API is not supported.\n");
484 if (!test_non_atomic(drm_device_fd, mode, program, banding_pattern))
Zach Reizner38f0fd92016-02-18 14:28:02 -0800485 return 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800486 }
487
Gurchetan Singh10008e62017-03-09 11:14:38 -0800488 for (size_t fb_index = 0; fb_index < NUM_BUFFERS; fb_index++) {
489 bs_egl_fb_destroy(&egl_fbs[fb_index]);
490 bs_egl_image_destroy(egl, &egl_images[fb_index]);
Mark Yacoub97d267a2019-07-17 14:44:08 -0400491 drmModeRmFB(drm_device_fd, ids[fb_index]);
Gurchetan Singh10008e62017-03-09 11:14:38 -0800492 gbm_bo_destroy(bos[fb_index]);
493 }
494
495 bs_egl_destroy(&egl);
496 gbm_device_destroy(gbm);
Mark Yacoub97d267a2019-07-17 14:44:08 -0400497 close(drm_device_fd);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800498 return 0;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800499}