blob: c2e0e1ff2df2ba9bad27b4c96ed9914f4e0ad04b [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
Zach Reizner38f0fd92016-02-18 14:28:02 -08007#include "bs_drm.h"
Haixia Shie04ddfd2014-11-11 19:14:32 -08008
Daniele Castagna8a63a602016-10-10 18:43:29 -04009#include <getopt.h>
10
Gurchetan Singh10008e62017-03-09 11:14:38 -080011#define NUM_BUFFERS 2
12
Zach Reizner4dfdf602016-03-01 13:06:30 -080013static GLuint solid_shader_create()
Haixia Shie04ddfd2014-11-11 19:14:32 -080014{
Zach Reizner4dfdf602016-03-01 13:06:30 -080015 const GLchar *vert =
Zach Reizner38f0fd92016-02-18 14:28:02 -080016 "attribute vec4 vPosition;\n"
17 "attribute vec4 vColor;\n"
18 "varying vec4 vFillColor;\n"
19 "void main() {\n"
20 " gl_Position = vPosition;\n"
21 " vFillColor = vColor;\n"
22 "}\n";
Haixia Shie04ddfd2014-11-11 19:14:32 -080023
Zach Reizner4dfdf602016-03-01 13:06:30 -080024 const GLchar *frag =
Zach Reizner38f0fd92016-02-18 14:28:02 -080025 "precision mediump float;\n"
26 "varying vec4 vFillColor;\n"
27 "void main() {\n"
28 " gl_FragColor = vFillColor;\n"
29 "}\n";
Lauri Peltonen763ca462014-12-17 12:22:21 -080030
Zach Reizner4dfdf602016-03-01 13:06:30 -080031 struct bs_gl_program_create_binding bindings[] = {
32 { 0, "vPosition" }, { 1, "vColor" }, { 0, NULL },
33 };
Haixia Shie04ddfd2014-11-11 19:14:32 -080034
Zach Reizner4dfdf602016-03-01 13:06:30 -080035 return bs_gl_program_create_vert_frag_bind(vert, frag, bindings);
Haixia Shie04ddfd2014-11-11 19:14:32 -080036}
37
Lauri Peltonen95226da2014-12-18 16:39:54 -080038static float f(int i)
39{
Haixia Shie04ddfd2014-11-11 19:14:32 -080040 int a = i % 40;
41 int b = (i / 40) % 6;
42 switch (b) {
Zach Reizner38f0fd92016-02-18 14:28:02 -080043 case 0:
44 case 1:
45 return 0.0f;
46 case 3:
47 case 4:
48 return 1.0f;
49 case 2:
50 return (a / 40.0f);
51 case 5:
52 return 1.0f - (a / 40.0f);
53 default:
54 return 0.0f;
Haixia Shie04ddfd2014-11-11 19:14:32 -080055 }
56}
57
Zach Reizner38f0fd92016-02-18 14:28:02 -080058static void page_flip_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec,
59 void *data)
Haixia Shi4652b8c2014-11-19 17:55:38 -080060{
61 int *waiting_for_flip = data;
62 *waiting_for_flip = 0;
63}
64
Daniele Castagna8a63a602016-10-10 18:43:29 -040065static const struct option longopts[] = {
66 { "test-page-flip-format-change", no_argument, NULL, 'f' },
67 { "help", no_argument, NULL, 'h' },
68 { 0, 0, 0, 0 },
69};
70
71static void print_help(const char *argv0)
72{
73 // clang-format off
74 printf("usage: %s [OPTIONS] [drm_device_path]\n", argv0);
75 printf(" -f, --test-page-flip-format-change test page flips alternating RGB and BGR fbs\n");
76 printf(" -h, --help show help\n");
77 printf("\n");
78 printf("\n");
79 // clang-format on
80}
81
Zach Reizner38f0fd92016-02-18 14:28:02 -080082int main(int argc, char **argv)
Haixia Shie04ddfd2014-11-11 19:14:32 -080083{
Zach Reizner38f0fd92016-02-18 14:28:02 -080084 int fd = -1;
Daniele Castagna8a63a602016-10-10 18:43:29 -040085 bool test_page_flip_format_change = false;
86 bool help_flag = false;
87
88 int c = -1;
89 while ((c = getopt_long(argc, argv, "fh", longopts, NULL)) != -1) {
90 switch (c) {
91 case 'f':
92 test_page_flip_format_change = true;
93 break;
94 case 'h':
95 help_flag = true;
96 break;
97 }
98 }
99
100 if (help_flag) {
101 print_help(*argv);
102 }
103
104 if (optind < argc) {
105 fd = open(argv[optind], O_RDWR);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800106 if (fd < 0) {
Daniele Castagna8a63a602016-10-10 18:43:29 -0400107 bs_debug_error("failed to open card %s", argv[optind]);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800108 return 1;
109 }
Zach Reiznerbf26be82016-09-15 16:06:21 -0700110 } else {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800111 fd = bs_drm_open_main_display();
112 if (fd < 0) {
113 bs_debug_error("failed to open card for display");
114 return 1;
115 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800116 }
117
Zach Reizner38f0fd92016-02-18 14:28:02 -0800118 struct gbm_device *gbm = gbm_create_device(fd);
119 if (!gbm) {
120 bs_debug_error("failed to create gbm");
121 return 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800122 }
123
Zach Reizner4dfdf602016-03-01 13:06:30 -0800124 struct bs_drm_pipe pipe = { 0 };
Zach Reizner38f0fd92016-02-18 14:28:02 -0800125 if (!bs_drm_pipe_make(fd, &pipe)) {
126 bs_debug_error("failed to make pipe");
127 return 1;
128 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800129
Zach Reizner38f0fd92016-02-18 14:28:02 -0800130 drmModeConnector *connector = drmModeGetConnector(fd, pipe.connector_id);
131 assert(connector);
132 drmModeModeInfo *mode = &connector->modes[0];
133
134 struct bs_egl *egl = bs_egl_new();
135 if (!bs_egl_setup(egl)) {
136 bs_debug_error("failed to setup egl context");
137 return 1;
138 }
139
Gurchetan Singh10008e62017-03-09 11:14:38 -0800140 struct gbm_bo *bos[NUM_BUFFERS];
141 uint32_t ids[NUM_BUFFERS];
142 struct bs_egl_fb *egl_fbs[NUM_BUFFERS];
143 EGLImageKHR egl_images[NUM_BUFFERS];
144 for (size_t fb_index = 0; fb_index < NUM_BUFFERS; fb_index++) {
Daniele Castagna8a63a602016-10-10 18:43:29 -0400145 uint32_t format = GBM_FORMAT_XRGB8888;
146 if (test_page_flip_format_change && fb_index) {
Gurchetan Singh43380142017-03-09 10:45:01 -0800147 format = GBM_FORMAT_XBGR8888;
Daniele Castagna8a63a602016-10-10 18:43:29 -0400148 }
149
Gurchetan Singh43380142017-03-09 10:45:01 -0800150 bos[fb_index] = gbm_bo_create(gbm, mode->hdisplay, mode->vdisplay, format,
151 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800152 if (bos[fb_index] == NULL) {
153 bs_debug_error("failed to allocate framebuffer");
154 return 1;
155 }
156
157 ids[fb_index] = bs_drm_fb_create_gbm(bos[fb_index]);
158 if (ids[fb_index] == 0) {
159 bs_debug_error("failed to create framebuffer id");
160 return 1;
161 }
162
163 EGLImageKHR egl_image = bs_egl_image_create_gbm(egl, bos[fb_index]);
164 if (egl_image == EGL_NO_IMAGE_KHR) {
165 bs_debug_error("failed to create EGLImageKHR from framebuffer");
166 return 1;
167 }
168
169 egl_fbs[fb_index] = bs_egl_fb_new(egl, egl_image);
170 if (!egl_fbs[fb_index]) {
171 bs_debug_error("failed to create framebuffer from EGLImageKHR");
172 return 1;
173 }
Haixia Shife4e2ff2016-10-17 14:28:55 -0700174 egl_images[fb_index] = egl_image;
Zach Reizner38f0fd92016-02-18 14:28:02 -0800175 }
176
177 int ret = drmModeSetCrtc(fd, pipe.crtc_id, ids[0], 0 /* x */, 0 /* y */, &pipe.connector_id,
178 1 /* connector count */, mode);
179 if (ret) {
180 bs_debug_error("failed to set CRTC");
181 return 1;
182 }
183
184 GLuint program = solid_shader_create();
Haixia Shie04ddfd2014-11-11 19:14:32 -0800185 if (!program) {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800186 bs_debug_error("failed to create solid shader");
187 return 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800188 }
189
Haixia Shi4652b8c2014-11-19 17:55:38 -0800190 int fb_idx = 1;
Zach Reizner38f0fd92016-02-18 14:28:02 -0800191 for (int i = 0; i <= 500; i++) {
Haixia Shi4652b8c2014-11-19 17:55:38 -0800192 int waiting_for_flip = 1;
Zach Reizner38f0fd92016-02-18 14:28:02 -0800193 // clang-format off
Haixia Shie04ddfd2014-11-11 19:14:32 -0800194 GLfloat verts[] = {
195 0.0f, -0.5f, 0.0f,
196 -0.5f, 0.5f, 0.0f,
197 0.5f, 0.5f, 0.0f
198 };
199 GLfloat colors[] = {
200 1.0f, 0.0f, 0.0f, 1.0f,
201 0.0f, 1.0f, 0.0f, 1.0f,
202 0.0f, 0.0f, 1.0f, 1.0f
203 };
Zach Reizner38f0fd92016-02-18 14:28:02 -0800204 // clang-format on
Haixia Shie04ddfd2014-11-11 19:14:32 -0800205
Zach Reizner38f0fd92016-02-18 14:28:02 -0800206 glBindFramebuffer(GL_FRAMEBUFFER, bs_egl_fb_name(egl_fbs[fb_idx]));
207 glViewport(0, 0, (GLint)mode->hdisplay, (GLint)mode->vdisplay);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800208
Haixia Shie04ddfd2014-11-11 19:14:32 -0800209 glClearColor(f(i), f(i + 80), f(i + 160), 0.0f);
210 glClear(GL_COLOR_BUFFER_BIT);
211
212 glUseProgram(program);
213 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, verts);
214 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, colors);
215 glEnableVertexAttribArray(0);
216 glEnableVertexAttribArray(1);
217 glDrawArrays(GL_TRIANGLES, 0, 3);
218
219 usleep(1e6 / 120); /* 120 Hz */
220 glFinish();
Haixia Shife4e2ff2016-10-17 14:28:55 -0700221
222 if (!bs_egl_image_flush_external(egl, egl_images[fb_idx])) {
223 bs_debug_error("failed to call image_flush_external");
224 return 1;
225 }
226
Zach Reizner38f0fd92016-02-18 14:28:02 -0800227 ret = drmModePageFlip(fd, pipe.crtc_id, ids[fb_idx], DRM_MODE_PAGE_FLIP_EVENT,
228 &waiting_for_flip);
229 if (ret) {
230 bs_debug_error("failed page flip: %d", ret);
231 return 1;
232 }
Haixia Shi4652b8c2014-11-19 17:55:38 -0800233
234 while (waiting_for_flip) {
235 drmEventContext evctx = {
Zach Reizner4dfdf602016-03-01 13:06:30 -0800236 .version = DRM_EVENT_CONTEXT_VERSION,
237 .page_flip_handler = page_flip_handler,
Haixia Shi4652b8c2014-11-19 17:55:38 -0800238 };
239
240 fd_set fds;
241 FD_ZERO(&fds);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800242 FD_SET(fd, &fds);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800243
Zach Reizner38f0fd92016-02-18 14:28:02 -0800244 ret = select(fd + 1, &fds, NULL, NULL, NULL);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800245 if (ret < 0) {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800246 bs_debug_error("select err: %s", strerror(errno));
247 return 1;
Zach Reiznerbf26be82016-09-15 16:06:21 -0700248 } else if (ret == 0) {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800249 bs_debug_error("select timeout");
250 return 1;
251 }
Zach Reizner38f0fd92016-02-18 14:28:02 -0800252 ret = drmHandleEvent(fd, &evctx);
253 if (ret) {
254 bs_debug_error("failed to wait for page flip: %d", ret);
255 return 1;
256 }
Haixia Shi4652b8c2014-11-19 17:55:38 -0800257 }
258 fb_idx = fb_idx ^ 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800259 }
260
Gurchetan Singh10008e62017-03-09 11:14:38 -0800261 for (size_t fb_index = 0; fb_index < NUM_BUFFERS; fb_index++) {
262 bs_egl_fb_destroy(&egl_fbs[fb_index]);
263 bs_egl_image_destroy(egl, &egl_images[fb_index]);
264 drmModeRmFB(fd, ids[fb_idx]);
265 gbm_bo_destroy(bos[fb_index]);
266 }
267
268 bs_egl_destroy(&egl);
269 gbm_device_destroy(gbm);
270 close(fd);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800271 return 0;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800272}