blob: c31bd2a914752194dfdfe85cf7935f9fa4f0fc7d [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
Dominik Behr515ead52019-06-03 15:23:01 -070034
Mark Yacoub97d267a2019-07-17 14:44:08 -040035static const struct option longopts[] = {
36 { "format", required_argument, NULL, 'f' },
37 { "modifier", required_argument, NULL, 'm' },
38 { "test-page-flip-format-change", required_argument, NULL, 'p' },
39 { "banding", no_argument, NULL, 'b' },
40 { "help", no_argument, NULL, 'h' },
Dominik Behr515ead52019-06-03 15:23:01 -070041 { "display", required_argument, NULL, 'd' },
42 { "renderer", required_argument, NULL, 'r' },
Mark Yacoub97d267a2019-07-17 14:44:08 -040043 { 0, 0, 0, 0 },
Daniele Castagna72729122017-10-18 17:09:36 -040044};
45
46const size_t allowed_formats_length = BS_ARRAY_LEN(allowed_formats);
47
Zach Reizner4dfdf602016-03-01 13:06:30 -080048static GLuint solid_shader_create()
Haixia Shie04ddfd2014-11-11 19:14:32 -080049{
Zach Reizner4dfdf602016-03-01 13:06:30 -080050 const GLchar *vert =
Zach Reizner38f0fd92016-02-18 14:28:02 -080051 "attribute vec4 vPosition;\n"
52 "attribute vec4 vColor;\n"
53 "varying vec4 vFillColor;\n"
54 "void main() {\n"
55 " gl_Position = vPosition;\n"
56 " vFillColor = vColor;\n"
57 "}\n";
Haixia Shie04ddfd2014-11-11 19:14:32 -080058
Zach Reizner4dfdf602016-03-01 13:06:30 -080059 const GLchar *frag =
Zach Reizner38f0fd92016-02-18 14:28:02 -080060 "precision mediump float;\n"
61 "varying vec4 vFillColor;\n"
62 "void main() {\n"
63 " gl_FragColor = vFillColor;\n"
64 "}\n";
Lauri Peltonen763ca462014-12-17 12:22:21 -080065
Zach Reizner4dfdf602016-03-01 13:06:30 -080066 struct bs_gl_program_create_binding bindings[] = {
Mark Yacoub97d267a2019-07-17 14:44:08 -040067 { 0, "vPosition" },
68 { 1, "vColor" },
69 { 0, NULL },
Zach Reizner4dfdf602016-03-01 13:06:30 -080070 };
Haixia Shie04ddfd2014-11-11 19:14:32 -080071
Zach Reizner4dfdf602016-03-01 13:06:30 -080072 return bs_gl_program_create_vert_frag_bind(vert, frag, bindings);
Haixia Shie04ddfd2014-11-11 19:14:32 -080073}
74
Lauri Peltonen95226da2014-12-18 16:39:54 -080075static float f(int i)
76{
Haixia Shie04ddfd2014-11-11 19:14:32 -080077 int a = i % 40;
78 int b = (i / 40) % 6;
79 switch (b) {
Zach Reizner38f0fd92016-02-18 14:28:02 -080080 case 0:
81 case 1:
82 return 0.0f;
83 case 3:
84 case 4:
85 return 1.0f;
86 case 2:
87 return (a / 40.0f);
88 case 5:
89 return 1.0f - (a / 40.0f);
90 default:
91 return 0.0f;
Haixia Shie04ddfd2014-11-11 19:14:32 -080092 }
93}
94
Daniele Castagna72729122017-10-18 17:09:36 -040095static uint32_t find_format(char *fourcc)
96{
97 if (!fourcc || strlen(fourcc) < 4)
98 return 0;
99
100 uint32_t format = fourcc_code(fourcc[0], fourcc[1], fourcc[2], fourcc[3]);
101 for (int i = 0; i < allowed_formats_length; i++) {
102 if (allowed_formats[i] == format)
103 return format;
104 }
105
106 return 0;
107}
108
Mark Yacoub97d267a2019-07-17 14:44:08 -0400109static void print_help(const char *argv0, int drm_device_fd)
Daniele Castagna8a63a602016-10-10 18:43:29 -0400110{
Daniele Castagna72729122017-10-18 17:09:36 -0400111 char allowed_formats_string[allowed_formats_length * 6];
112 int i;
113 for (i = 0; i < allowed_formats_length; i++) {
114 uint32_t format = allowed_formats[i];
115 sprintf(allowed_formats_string + i * 6, "%.4s, ", (char *)&format);
116 }
117
118 allowed_formats_string[i * 6 - 2] = 0;
119
Daniele Castagna8a63a602016-10-10 18:43:29 -0400120 // clang-format off
121 printf("usage: %s [OPTIONS] [drm_device_path]\n", argv0);
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800122 printf(" -f, --format <format> defines the fb format.\n");
123 printf(" -m, --modifier <modifier> pass modifiers.\n");
124 printf(" -p, --test-page-flip-format-change <format> test page flips alternating formats.\n");
Miguel Casasab04f3e2019-03-21 14:40:37 -0400125 printf(" -b, --banding show a pattern that makes banding easy to spot if present.\n");
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800126 printf(" -h, --help show help\n");
Dominik Behr515ead52019-06-03 15:23:01 -0700127 printf(" -d, --display <drm_driver_name> dri driver name for display.\n");
128 printf(" -r, --renderer <drm_driver_name> dri driver name for renderer.\n");
Daniele Castagna8a63a602016-10-10 18:43:29 -0400129 printf("\n");
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800130 printf(" <format> must be one of [ %s ].\n", allowed_formats_string);
131 printf(" <modifier> must be one of ");
Mark Yacoub97d267a2019-07-17 14:44:08 -0400132 bs_print_supported_modifiers(drm_device_fd);
Daniele Castagna72729122017-10-18 17:09:36 -0400133 printf("\n");
Daniele Castagna8a63a602016-10-10 18:43:29 -0400134 printf("\n");
135 // clang-format on
136}
137
Mark Yacoub97d267a2019-07-17 14:44:08 -0400138static bool draw_gl(drmModeModeInfo *mode, int fb_idx, int color_idx, GLuint program,
139 bool banding_pattern)
140{
141 // clang-format off
142 const GLfloat triangle_vertices[] = {
143 0.0f, -0.5f, 0.0f,
144 -0.5f, 0.5f, 0.0f,
145 0.5f, 0.5f, 0.0f
146 };
147 const GLfloat triangle_colors[] = {
148 1.0f, 0.0f, 0.0f, 1.0f,
149 0.0f, 1.0f, 0.0f, 1.0f,
150 0.0f, 0.0f, 1.0f, 1.0f
151 };
152 const GLfloat square_vertices[] = {
153 -1.0f, -1.0f, 0.0f,
154 1.0f, -1.0f, 0.0f,
155 -1.0f, 1.0f, 0.0f,
156 1.0f, 1.0f, 0.0f,
157 };
158 const GLfloat square_colors[] = {
159 0.05f, 0.05f, 0.05f, 1.0f,
160 0.05f, 0.05f, 0.05f, 1.0f,
161 0.45f, 0.45f, 0.45f, 1.0f,
162 0.45f, 0.45f, 0.45f, 1.0f,
163 };
164
165 glBindFramebuffer(GL_FRAMEBUFFER, bs_egl_fb_name(egl_fbs[fb_idx]));
166 glViewport(0, 0, (GLint)mode->hdisplay, (GLint)mode->vdisplay);
167
168 glClearColor(f(color_idx), f(color_idx + 80), f(color_idx + 160), 0.0f);
169 glClear(GL_COLOR_BUFFER_BIT);
170
171 glUseProgram(program);
172 if (banding_pattern) {
173 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, square_vertices);
174 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, square_colors);
175 } else {
176 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, triangle_vertices);
177 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, triangle_colors);
178 }
179 glEnableVertexAttribArray(0);
180 glEnableVertexAttribArray(1);
181 glDrawArrays(GL_TRIANGLES, 0, 3);
182
183 usleep(1e6 / 120 /* 120 Hz */);
184 glFinish();
185
186 if (!bs_egl_image_flush_external(egl, egl_images[fb_idx])) {
187 bs_debug_error("failed to call image_flush_external");
188 return false;
189 }
190
191 return true;
192}
193
Gurchetan Singh97e724d2020-08-24 10:54:15 -0700194bool check_if_fd_valid(int fd)
Mark Yacoub97d267a2019-07-17 14:44:08 -0400195{
196 if (fd < 0) {
197 bs_debug_error("fd is not valid.");
198 return false;
199 }
200 if (fcntl(fd, F_GETFD, 0) < 0) {
201 bs_debug_error("Unable to return the fd flags.");
202 return false;
203 }
204 return true;
205}
206
207static int test_atomic(int drm_device_fd, drmModeModeInfo *mode, GLuint program,
208 bool banding_pattern)
209{
210 uint32_t connector_id = drm_pipe.connector_id;
211 uint32_t crtc_id = drm_pipe.crtc_id;
212 uint32_t plane_id = bs_get_plane_id(drm_device_fd, crtc_id);
213 if (plane_id < 1) {
214 bs_debug_error("failed to get Plane ID.");
215 return -1;
216 }
217
218 uint32_t mode_blob_id = 0;
219 drmModeCreatePropertyBlob(drm_device_fd, mode, sizeof(drmModeModeInfo), &mode_blob_id);
220 assert(mode_blob_id);
221
222 int res = drmSetClientCap(drm_device_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
223 assert(!res);
224
225 uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_ALLOW_MODESET;
226 drmModeAtomicReqPtr atomic_req = drmModeAtomicAlloc();
227 int cursor = drmModeAtomicGetCursor(atomic_req);
228
229 const drm_property_value_t connector_props[] = { { "CRTC_ID", crtc_id } };
230 for (size_t i = 0; i < BS_ARRAY_LEN(connector_props); ++i) {
231 uint32_t prop =
232 bs_drm_find_property_id(drm_device_fd, connector_id, DRM_MODE_OBJECT_CONNECTOR,
233 connector_props[i].property_name);
234 drmModeAtomicAddProperty(atomic_req, connector_id, prop, connector_props[i].value);
235 }
236
237 int out_fence_fd = -1;
238 const drm_property_value_t crtc_props[] = { { "OUT_FENCE_PTR", (uint64_t)&out_fence_fd },
239 { "MODE_ID", mode_blob_id },
240 { "ACTIVE", 1 } };
241 for (size_t i = 0; i < BS_ARRAY_LEN(crtc_props); ++i) {
242 uint32_t prop = bs_drm_find_property_id(
243 drm_device_fd, crtc_id, DRM_MODE_OBJECT_CRTC, crtc_props[i].property_name);
244 drmModeAtomicAddProperty(atomic_req, crtc_id, prop, crtc_props[i].value);
245 }
246
247 const drm_property_value_t plane_props[] = {
248 { "CRTC_ID", crtc_id },
249 { "CRTC_X", 0 },
250 { "CRTC_Y", 0 },
251 { "CRTC_W", mode->hdisplay },
252 { "CRTC_H", mode->vdisplay },
253 { "SRC_X", 0 },
254 { "SRC_Y", 0 },
255 { "SRC_W", mode->hdisplay << 16 },
256 { "SRC_H", mode->vdisplay << 16 },
257 };
258 for (size_t i = 0; i < BS_ARRAY_LEN(plane_props); ++i) {
259 uint32_t prop = bs_drm_find_property_id(
260 drm_device_fd, plane_id, DRM_MODE_OBJECT_PLANE, plane_props[i].property_name);
261 drmModeAtomicAddProperty(atomic_req, plane_id, prop, plane_props[i].value);
262 }
263
264 uint32_t fb_propery_id =
265 bs_drm_find_property_id(drm_device_fd, plane_id, DRM_MODE_OBJECT_PLANE, "FB_ID");
266
267 fd_set fds;
268 FD_ZERO(&fds);
269 FD_SET(drm_device_fd, &fds);
270
271 for (int i = 0; i <= 500; i++) {
272 int fb_idx = i % 2;
273 if (!draw_gl(mode, fb_idx, i, program, banding_pattern))
274 return false;
275
276 drmModeAtomicAddProperty(atomic_req, plane_id, fb_propery_id, ids[fb_idx]);
277 res = drmModeAtomicCommit(drm_device_fd, atomic_req, flags, NULL);
278 assert(!res);
279
280 flags = DRM_MODE_PAGE_FLIP_EVENT;
281 drmModeAtomicSetCursor(atomic_req, cursor);
282 drmModeAtomicFree(atomic_req);
283 atomic_req = drmModeAtomicAlloc();
284
285 check_if_fd_valid(out_fence_fd);
286
287 select(drm_device_fd + 1, &fds, NULL, NULL, NULL);
288 char buffer[1024];
289 int len = read(drm_device_fd, buffer, sizeof(buffer));
290 assert(len > 0);
291 }
292
293 drmModeDestroyPropertyBlob(drm_device_fd, mode_blob_id);
294 return true;
295}
296
297static void page_flip_handler(int drm_device_fd, unsigned int frame, unsigned int sec,
298 unsigned int usec, void *data)
299{
300 int *waiting_for_flip = data;
301 *waiting_for_flip = 0;
302}
303
304static bool test_non_atomic(int drm_device_fd, drmModeModeInfo *mode, GLuint program,
305 bool banding_pattern)
306{
307 int ret = drmModeSetCrtc(drm_device_fd, drm_pipe.crtc_id, ids[0], 0 /* x */, 0 /* y */,
308 &drm_pipe.connector_id, 1 /* connector count */, mode);
309 if (ret) {
310 bs_debug_error("failed to set CRTC");
311 return false;
312 }
313
314 // NOTE: Loop starts from 1 as `fb_idx` should not be 0. ids[0] is used in drmModeSetCrtc
315 // which gets locked on some devices, so we have to draw to another buffer (ids[1]) and
316 // commit it first to release [0].
317 for (int i = 1; i <= 500; i++) {
318 int waiting_for_flip = 1;
319 int fb_idx = i % 2;
320 if (!draw_gl(mode, i % 2, i, program, banding_pattern))
321 return false;
322
323 int ret = drmModePageFlip(drm_device_fd, drm_pipe.crtc_id, ids[fb_idx],
324 DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip);
325 if (ret) {
326 bs_debug_error("failed page flip: %d", ret);
327 return false;
328 }
329
330 while (waiting_for_flip) {
331 drmEventContext evctx = {
332 .version = DRM_EVENT_CONTEXT_VERSION,
333 .page_flip_handler = page_flip_handler,
334 };
335
336 fd_set fds;
337 FD_ZERO(&fds);
338 FD_SET(drm_device_fd, &fds);
339
340 ret = select(drm_device_fd + 1, &fds, NULL, NULL, NULL);
341 if (ret < 0) {
342 bs_debug_error("select err: %s", strerror(errno));
343 return false;
344 } else if (ret == 0) {
345 bs_debug_error("select timeout");
346 return false;
347 }
348 ret = drmHandleEvent(drm_device_fd, &evctx);
349 if (ret) {
350 bs_debug_error("failed to wait for page flip: %d", ret);
351 return false;
352 }
353 }
354 }
355 return true;
356}
357
Dominik Behr515ead52019-06-03 15:23:01 -0700358struct check_driver_data {
359 char *driver;
360 int fd;
361};
362
363static bool check_driver(void *user, int fd)
364{
365 struct check_driver_data *data = (struct check_driver_data *)user;
366 drmVersionPtr version;
367
368 version = drmGetVersion(fd);
369 if (!version)
370 return false;
371
372 if (strcmp(data->driver, version->name) != 0) {
373 drmFreeVersion(version);
374 return false;
375 }
376
377 drmFreeVersion(version);
378 data->fd = dup(fd);
379 return true;
380}
381
Zach Reizner38f0fd92016-02-18 14:28:02 -0800382int main(int argc, char **argv)
Haixia Shie04ddfd2014-11-11 19:14:32 -0800383{
Daniele Castagna8a63a602016-10-10 18:43:29 -0400384 bool help_flag = false;
Daniele Castagna72729122017-10-18 17:09:36 -0400385 uint32_t format = GBM_FORMAT_XRGB8888;
Daniele Castagna95d027f2017-11-01 21:56:58 -0400386 uint32_t test_page_flip_format_change = 0;
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800387 uint64_t modifier = DRM_FORMAT_MOD_INVALID;
Miguel Casasab04f3e2019-03-21 14:40:37 -0400388 bool banding_pattern = false;
Dominik Behr515ead52019-06-03 15:23:01 -0700389 char *display_driver = NULL;
390 char *render_driver = NULL;
Daniele Castagna8a63a602016-10-10 18:43:29 -0400391
392 int c = -1;
Dominik Behr515ead52019-06-03 15:23:01 -0700393 while ((c = getopt_long(argc, argv, "m:hp:f:bld:r:", longopts, NULL)) != -1) {
Daniele Castagna8a63a602016-10-10 18:43:29 -0400394 switch (c) {
Daniele Castagna72729122017-10-18 17:09:36 -0400395 case 'p':
396 test_page_flip_format_change = find_format(optarg);
397 if (!test_page_flip_format_change)
398 help_flag = true;
399 break;
Daniele Castagna8a63a602016-10-10 18:43:29 -0400400 case 'f':
Daniele Castagna72729122017-10-18 17:09:36 -0400401 format = find_format(optarg);
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800402 if (!format) {
403 bs_debug_error("unsupported format: %s", optarg);
Daniele Castagna72729122017-10-18 17:09:36 -0400404 help_flag = true;
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800405 }
406 break;
407 case 'm':
408 modifier = bs_string_to_modifier(optarg);
409 if (modifier == -1) {
410 bs_debug_error("unsupported modifier: %s", optarg);
411 help_flag = true;
412 }
Daniele Castagna8a63a602016-10-10 18:43:29 -0400413 break;
Miguel Casasab04f3e2019-03-21 14:40:37 -0400414 case 'b':
415 banding_pattern = true;
416 break;
Daniele Castagna8a63a602016-10-10 18:43:29 -0400417 case 'h':
418 help_flag = true;
419 break;
Dominik Behr515ead52019-06-03 15:23:01 -0700420 case 'd':
421 if (display_driver) {
422 free(display_driver);
423 display_driver = NULL;
424 }
425 display_driver = strdup(optarg);
426 break;
427 case 'r':
428 if (render_driver) {
429 free(render_driver);
430 render_driver = NULL;
431 }
432 render_driver = strdup(optarg);
433 break;
Daniele Castagna8a63a602016-10-10 18:43:29 -0400434 }
435 }
436
Mark Yacoub97d267a2019-07-17 14:44:08 -0400437 int drm_device_fd = -1;
Daniele Castagna8a63a602016-10-10 18:43:29 -0400438 if (optind < argc) {
Mark Yacoub97d267a2019-07-17 14:44:08 -0400439 drm_device_fd = open(argv[optind], O_RDWR);
440 if (drm_device_fd < 0) {
Daniele Castagna8a63a602016-10-10 18:43:29 -0400441 bs_debug_error("failed to open card %s", argv[optind]);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800442 return 1;
443 }
Zach Reiznerbf26be82016-09-15 16:06:21 -0700444 } else {
Dominik Behr515ead52019-06-03 15:23:01 -0700445 if (display_driver) {
446 struct check_driver_data data;
447 data.driver = display_driver;
448 data.fd = -1;
449 bs_open_enumerate("/dev/dri/card%u", 0, DRM_MAX_MINOR,
450 check_driver, (void *)&data);
451 drm_device_fd = data.fd;
452 } else {
453 drm_device_fd = bs_drm_open_main_display();
454 }
Mark Yacoub97d267a2019-07-17 14:44:08 -0400455 if (drm_device_fd < 0) {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800456 bs_debug_error("failed to open card for display");
457 return 1;
458 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800459 }
460
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800461 if (help_flag) {
Mark Yacoub97d267a2019-07-17 14:44:08 -0400462 print_help(*argv, drm_device_fd);
463 close(drm_device_fd);
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800464 return 1;
465 }
466
Mark Yacoub97d267a2019-07-17 14:44:08 -0400467 struct gbm_device *gbm = gbm_create_device(drm_device_fd);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800468 if (!gbm) {
469 bs_debug_error("failed to create gbm");
470 return 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800471 }
472
Mark Yacoub97d267a2019-07-17 14:44:08 -0400473 if (!bs_drm_pipe_make(drm_device_fd, &drm_pipe)) {
474 bs_debug_error("failed to make drm_pipe");
Zach Reizner38f0fd92016-02-18 14:28:02 -0800475 return 1;
476 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800477
Mark Yacoub97d267a2019-07-17 14:44:08 -0400478 drmModeConnector *connector = drmModeGetConnector(drm_device_fd, drm_pipe.connector_id);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800479 assert(connector);
480 drmModeModeInfo *mode = &connector->modes[0];
481
Mark Yacoub97d267a2019-07-17 14:44:08 -0400482 egl = bs_egl_new();
Dominik Behr515ead52019-06-03 15:23:01 -0700483 if (!bs_egl_setup(egl, render_driver)) {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800484 bs_debug_error("failed to setup egl context");
485 return 1;
486 }
487
Gurchetan Singh10008e62017-03-09 11:14:38 -0800488 struct gbm_bo *bos[NUM_BUFFERS];
Gurchetan Singh10008e62017-03-09 11:14:38 -0800489 for (size_t fb_index = 0; fb_index < NUM_BUFFERS; fb_index++) {
Daniele Castagna8a63a602016-10-10 18:43:29 -0400490 if (test_page_flip_format_change && fb_index) {
Daniele Castagna72729122017-10-18 17:09:36 -0400491 format = test_page_flip_format_change;
Daniele Castagna8a63a602016-10-10 18:43:29 -0400492 }
493
Fritz Koenig01ee3d42018-11-07 10:42:17 -0800494 if (modifier != DRM_FORMAT_MOD_INVALID) {
495 bos[fb_index] = gbm_bo_create_with_modifiers(
496 gbm, mode->hdisplay, mode->vdisplay, format, &modifier, 1);
497 } else {
498 bos[fb_index] = gbm_bo_create(gbm, mode->hdisplay, mode->vdisplay, format,
499 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
500 }
501
Zach Reizner38f0fd92016-02-18 14:28:02 -0800502 if (bos[fb_index] == NULL) {
Miguel Casascb821462019-11-19 13:52:22 -0500503 bs_debug_error("failed to allocate BO %s modifiers",
504 (modifier != DRM_FORMAT_MOD_INVALID ? "with" : "without"));
Zach Reizner38f0fd92016-02-18 14:28:02 -0800505 return 1;
506 }
507
508 ids[fb_index] = bs_drm_fb_create_gbm(bos[fb_index]);
509 if (ids[fb_index] == 0) {
510 bs_debug_error("failed to create framebuffer id");
511 return 1;
512 }
513
514 EGLImageKHR egl_image = bs_egl_image_create_gbm(egl, bos[fb_index]);
515 if (egl_image == EGL_NO_IMAGE_KHR) {
516 bs_debug_error("failed to create EGLImageKHR from framebuffer");
517 return 1;
518 }
519
520 egl_fbs[fb_index] = bs_egl_fb_new(egl, egl_image);
521 if (!egl_fbs[fb_index]) {
522 bs_debug_error("failed to create framebuffer from EGLImageKHR");
523 return 1;
524 }
Haixia Shife4e2ff2016-10-17 14:28:55 -0700525 egl_images[fb_index] = egl_image;
Zach Reizner38f0fd92016-02-18 14:28:02 -0800526 }
527
Zach Reizner38f0fd92016-02-18 14:28:02 -0800528 GLuint program = solid_shader_create();
Haixia Shie04ddfd2014-11-11 19:14:32 -0800529 if (!program) {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800530 bs_debug_error("failed to create solid shader");
531 return 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800532 }
533
Mark Yacoub97d267a2019-07-17 14:44:08 -0400534 struct drm_set_client_cap cap = { DRM_CLIENT_CAP_ATOMIC, 1 };
535 bool has_atomic_capabilities = !drmIoctl(drm_device_fd, DRM_IOCTL_SET_CLIENT_CAP, &cap);
536 if (has_atomic_capabilities) {
537 if (!test_atomic(drm_device_fd, mode, program, banding_pattern))
Haixia Shife4e2ff2016-10-17 14:28:55 -0700538 return 1;
Mark Yacoub97d267a2019-07-17 14:44:08 -0400539 } else {
540 printf("Running Legacy API. Atomic API is not supported.\n");
541 if (!test_non_atomic(drm_device_fd, mode, program, banding_pattern))
Zach Reizner38f0fd92016-02-18 14:28:02 -0800542 return 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800543 }
544
Gurchetan Singh10008e62017-03-09 11:14:38 -0800545 for (size_t fb_index = 0; fb_index < NUM_BUFFERS; fb_index++) {
546 bs_egl_fb_destroy(&egl_fbs[fb_index]);
547 bs_egl_image_destroy(egl, &egl_images[fb_index]);
Mark Yacoub97d267a2019-07-17 14:44:08 -0400548 drmModeRmFB(drm_device_fd, ids[fb_index]);
Gurchetan Singh10008e62017-03-09 11:14:38 -0800549 gbm_bo_destroy(bos[fb_index]);
550 }
551
552 bs_egl_destroy(&egl);
553 gbm_device_destroy(gbm);
Mark Yacoub97d267a2019-07-17 14:44:08 -0400554 close(drm_device_fd);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800555 return 0;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800556}