blob: aa8be712a32d5423c0ac8d056c60c7b3a44bff12 [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
Zach Reizner4dfdf602016-03-01 13:06:30 -080011static GLuint solid_shader_create()
Haixia Shie04ddfd2014-11-11 19:14:32 -080012{
Zach Reizner4dfdf602016-03-01 13:06:30 -080013 const GLchar *vert =
Zach Reizner38f0fd92016-02-18 14:28:02 -080014 "attribute vec4 vPosition;\n"
15 "attribute vec4 vColor;\n"
16 "varying vec4 vFillColor;\n"
17 "void main() {\n"
18 " gl_Position = vPosition;\n"
19 " vFillColor = vColor;\n"
20 "}\n";
Haixia Shie04ddfd2014-11-11 19:14:32 -080021
Zach Reizner4dfdf602016-03-01 13:06:30 -080022 const GLchar *frag =
Zach Reizner38f0fd92016-02-18 14:28:02 -080023 "precision mediump float;\n"
24 "varying vec4 vFillColor;\n"
25 "void main() {\n"
26 " gl_FragColor = vFillColor;\n"
27 "}\n";
Lauri Peltonen763ca462014-12-17 12:22:21 -080028
Zach Reizner4dfdf602016-03-01 13:06:30 -080029 struct bs_gl_program_create_binding bindings[] = {
30 { 0, "vPosition" }, { 1, "vColor" }, { 0, NULL },
31 };
Haixia Shie04ddfd2014-11-11 19:14:32 -080032
Zach Reizner4dfdf602016-03-01 13:06:30 -080033 return bs_gl_program_create_vert_frag_bind(vert, frag, bindings);
Haixia Shie04ddfd2014-11-11 19:14:32 -080034}
35
Lauri Peltonen95226da2014-12-18 16:39:54 -080036static float f(int i)
37{
Haixia Shie04ddfd2014-11-11 19:14:32 -080038 int a = i % 40;
39 int b = (i / 40) % 6;
40 switch (b) {
Zach Reizner38f0fd92016-02-18 14:28:02 -080041 case 0:
42 case 1:
43 return 0.0f;
44 case 3:
45 case 4:
46 return 1.0f;
47 case 2:
48 return (a / 40.0f);
49 case 5:
50 return 1.0f - (a / 40.0f);
51 default:
52 return 0.0f;
Haixia Shie04ddfd2014-11-11 19:14:32 -080053 }
54}
55
Zach Reizner38f0fd92016-02-18 14:28:02 -080056static void page_flip_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec,
57 void *data)
Haixia Shi4652b8c2014-11-19 17:55:38 -080058{
59 int *waiting_for_flip = data;
60 *waiting_for_flip = 0;
61}
62
Daniele Castagna8a63a602016-10-10 18:43:29 -040063static const struct option longopts[] = {
64 { "test-page-flip-format-change", no_argument, NULL, 'f' },
65 { "help", no_argument, NULL, 'h' },
66 { 0, 0, 0, 0 },
67};
68
69static void print_help(const char *argv0)
70{
71 // clang-format off
72 printf("usage: %s [OPTIONS] [drm_device_path]\n", argv0);
73 printf(" -f, --test-page-flip-format-change test page flips alternating RGB and BGR fbs\n");
74 printf(" -h, --help show help\n");
75 printf("\n");
76 printf("\n");
77 // clang-format on
78}
79
Zach Reizner38f0fd92016-02-18 14:28:02 -080080int main(int argc, char **argv)
Haixia Shie04ddfd2014-11-11 19:14:32 -080081{
Zach Reizner38f0fd92016-02-18 14:28:02 -080082 int fd = -1;
Daniele Castagna8a63a602016-10-10 18:43:29 -040083 bool test_page_flip_format_change = false;
84 bool help_flag = false;
85
86 int c = -1;
87 while ((c = getopt_long(argc, argv, "fh", longopts, NULL)) != -1) {
88 switch (c) {
89 case 'f':
90 test_page_flip_format_change = true;
91 break;
92 case 'h':
93 help_flag = true;
94 break;
95 }
96 }
97
98 if (help_flag) {
99 print_help(*argv);
100 }
101
102 if (optind < argc) {
103 fd = open(argv[optind], O_RDWR);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800104 if (fd < 0) {
Daniele Castagna8a63a602016-10-10 18:43:29 -0400105 bs_debug_error("failed to open card %s", argv[optind]);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800106 return 1;
107 }
Zach Reiznerbf26be82016-09-15 16:06:21 -0700108 } else {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800109 fd = bs_drm_open_main_display();
110 if (fd < 0) {
111 bs_debug_error("failed to open card for display");
112 return 1;
113 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800114 }
115
Zach Reizner38f0fd92016-02-18 14:28:02 -0800116 struct gbm_device *gbm = gbm_create_device(fd);
117 if (!gbm) {
118 bs_debug_error("failed to create gbm");
119 return 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800120 }
121
Zach Reizner4dfdf602016-03-01 13:06:30 -0800122 struct bs_drm_pipe pipe = { 0 };
Zach Reizner38f0fd92016-02-18 14:28:02 -0800123 if (!bs_drm_pipe_make(fd, &pipe)) {
124 bs_debug_error("failed to make pipe");
125 return 1;
126 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800127
Zach Reizner38f0fd92016-02-18 14:28:02 -0800128 drmModeConnector *connector = drmModeGetConnector(fd, pipe.connector_id);
129 assert(connector);
130 drmModeModeInfo *mode = &connector->modes[0];
131
132 struct bs_egl *egl = bs_egl_new();
133 if (!bs_egl_setup(egl)) {
134 bs_debug_error("failed to setup egl context");
135 return 1;
136 }
137
138 struct gbm_bo *bos[2];
139 uint32_t ids[2];
140 struct bs_egl_fb *egl_fbs[2];
Haixia Shife4e2ff2016-10-17 14:28:55 -0700141 EGLImageKHR egl_images[2];
Zach Reizner38f0fd92016-02-18 14:28:02 -0800142 for (size_t fb_index = 0; fb_index < 2; fb_index++) {
Daniele Castagna8a63a602016-10-10 18:43:29 -0400143 uint32_t format = GBM_FORMAT_XRGB8888;
144 if (test_page_flip_format_change && fb_index) {
Gurchetan Singh43380142017-03-09 10:45:01 -0800145 format = GBM_FORMAT_XBGR8888;
Daniele Castagna8a63a602016-10-10 18:43:29 -0400146 }
147
Gurchetan Singh43380142017-03-09 10:45:01 -0800148 bos[fb_index] = gbm_bo_create(gbm, mode->hdisplay, mode->vdisplay, format,
149 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800150 if (bos[fb_index] == NULL) {
151 bs_debug_error("failed to allocate framebuffer");
152 return 1;
153 }
154
155 ids[fb_index] = bs_drm_fb_create_gbm(bos[fb_index]);
156 if (ids[fb_index] == 0) {
157 bs_debug_error("failed to create framebuffer id");
158 return 1;
159 }
160
161 EGLImageKHR egl_image = bs_egl_image_create_gbm(egl, bos[fb_index]);
162 if (egl_image == EGL_NO_IMAGE_KHR) {
163 bs_debug_error("failed to create EGLImageKHR from framebuffer");
164 return 1;
165 }
166
167 egl_fbs[fb_index] = bs_egl_fb_new(egl, egl_image);
168 if (!egl_fbs[fb_index]) {
169 bs_debug_error("failed to create framebuffer from EGLImageKHR");
170 return 1;
171 }
Haixia Shife4e2ff2016-10-17 14:28:55 -0700172 egl_images[fb_index] = egl_image;
Zach Reizner38f0fd92016-02-18 14:28:02 -0800173 }
174
175 int ret = drmModeSetCrtc(fd, pipe.crtc_id, ids[0], 0 /* x */, 0 /* y */, &pipe.connector_id,
176 1 /* connector count */, mode);
177 if (ret) {
178 bs_debug_error("failed to set CRTC");
179 return 1;
180 }
181
182 GLuint program = solid_shader_create();
Haixia Shie04ddfd2014-11-11 19:14:32 -0800183 if (!program) {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800184 bs_debug_error("failed to create solid shader");
185 return 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800186 }
187
Haixia Shi4652b8c2014-11-19 17:55:38 -0800188 int fb_idx = 1;
Zach Reizner38f0fd92016-02-18 14:28:02 -0800189 for (int i = 0; i <= 500; i++) {
Haixia Shi4652b8c2014-11-19 17:55:38 -0800190 int waiting_for_flip = 1;
Zach Reizner38f0fd92016-02-18 14:28:02 -0800191 // clang-format off
Haixia Shie04ddfd2014-11-11 19:14:32 -0800192 GLfloat verts[] = {
193 0.0f, -0.5f, 0.0f,
194 -0.5f, 0.5f, 0.0f,
195 0.5f, 0.5f, 0.0f
196 };
197 GLfloat colors[] = {
198 1.0f, 0.0f, 0.0f, 1.0f,
199 0.0f, 1.0f, 0.0f, 1.0f,
200 0.0f, 0.0f, 1.0f, 1.0f
201 };
Zach Reizner38f0fd92016-02-18 14:28:02 -0800202 // clang-format on
Haixia Shie04ddfd2014-11-11 19:14:32 -0800203
Zach Reizner38f0fd92016-02-18 14:28:02 -0800204 glBindFramebuffer(GL_FRAMEBUFFER, bs_egl_fb_name(egl_fbs[fb_idx]));
205 glViewport(0, 0, (GLint)mode->hdisplay, (GLint)mode->vdisplay);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800206
Haixia Shie04ddfd2014-11-11 19:14:32 -0800207 glClearColor(f(i), f(i + 80), f(i + 160), 0.0f);
208 glClear(GL_COLOR_BUFFER_BIT);
209
210 glUseProgram(program);
211 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, verts);
212 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, colors);
213 glEnableVertexAttribArray(0);
214 glEnableVertexAttribArray(1);
215 glDrawArrays(GL_TRIANGLES, 0, 3);
216
217 usleep(1e6 / 120); /* 120 Hz */
218 glFinish();
Haixia Shife4e2ff2016-10-17 14:28:55 -0700219
220 if (!bs_egl_image_flush_external(egl, egl_images[fb_idx])) {
221 bs_debug_error("failed to call image_flush_external");
222 return 1;
223 }
224
Zach Reizner38f0fd92016-02-18 14:28:02 -0800225 ret = drmModePageFlip(fd, pipe.crtc_id, ids[fb_idx], DRM_MODE_PAGE_FLIP_EVENT,
226 &waiting_for_flip);
227 if (ret) {
228 bs_debug_error("failed page flip: %d", ret);
229 return 1;
230 }
Haixia Shi4652b8c2014-11-19 17:55:38 -0800231
232 while (waiting_for_flip) {
233 drmEventContext evctx = {
Zach Reizner4dfdf602016-03-01 13:06:30 -0800234 .version = DRM_EVENT_CONTEXT_VERSION,
235 .page_flip_handler = page_flip_handler,
Haixia Shi4652b8c2014-11-19 17:55:38 -0800236 };
237
238 fd_set fds;
239 FD_ZERO(&fds);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800240 FD_SET(fd, &fds);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800241
Zach Reizner38f0fd92016-02-18 14:28:02 -0800242 ret = select(fd + 1, &fds, NULL, NULL, NULL);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800243 if (ret < 0) {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800244 bs_debug_error("select err: %s", strerror(errno));
245 return 1;
Zach Reiznerbf26be82016-09-15 16:06:21 -0700246 } else if (ret == 0) {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800247 bs_debug_error("select timeout");
248 return 1;
249 }
Zach Reizner38f0fd92016-02-18 14:28:02 -0800250 ret = drmHandleEvent(fd, &evctx);
251 if (ret) {
252 bs_debug_error("failed to wait for page flip: %d", ret);
253 return 1;
254 }
Haixia Shi4652b8c2014-11-19 17:55:38 -0800255 }
256 fb_idx = fb_idx ^ 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800257 }
258
Zach Reizner38f0fd92016-02-18 14:28:02 -0800259 return 0;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800260}