blob: 6cd273e1ffbf6aa6da7149c33b20fcd18321b8cb [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
Zach Reizner38f0fd92016-02-18 14:28:02 -08009GLuint shader_create(GLenum type, const GLchar *src)
Haixia Shie04ddfd2014-11-11 19:14:32 -080010{
Zach Reizner38f0fd92016-02-18 14:28:02 -080011 GLuint shader = glCreateShader(type);
12 if (!shader) {
13 bs_debug_error("failed to create shader");
14 return 0;
Haixia Shie04ddfd2014-11-11 19:14:32 -080015 }
Zach Reizner38f0fd92016-02-18 14:28:02 -080016
17 glShaderSource(shader, 1, &src, NULL);
18 glCompileShader(shader);
19
20 GLint status;
21 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
22 if (status == GL_FALSE) {
23 GLint log_len = 0;
24 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_len);
25 char *shader_log = calloc(log_len, sizeof(char));
26 assert(shader_log);
27 glGetShaderInfoLog(shader, log_len, NULL, shader_log);
28 bs_debug_error("failed to compile shader: %s", shader_log);
29 free(shader_log);
30 glDeleteShader(shader);
31 return 0;
32 }
33
34 return shader;
Haixia Shie04ddfd2014-11-11 19:14:32 -080035}
36
Zach Reizner38f0fd92016-02-18 14:28:02 -080037GLuint solid_shader_create()
Haixia Shie04ddfd2014-11-11 19:14:32 -080038{
Zach Reizner38f0fd92016-02-18 14:28:02 -080039 const GLchar *vertex_shader_str =
40 "attribute vec4 vPosition;\n"
41 "attribute vec4 vColor;\n"
42 "varying vec4 vFillColor;\n"
43 "void main() {\n"
44 " gl_Position = vPosition;\n"
45 " vFillColor = vColor;\n"
46 "}\n";
Haixia Shie04ddfd2014-11-11 19:14:32 -080047
Zach Reizner38f0fd92016-02-18 14:28:02 -080048 const GLchar *fragment_shader_str =
49 "precision mediump float;\n"
50 "varying vec4 vFillColor;\n"
51 "void main() {\n"
52 " gl_FragColor = vFillColor;\n"
53 "}\n";
Lauri Peltonen763ca462014-12-17 12:22:21 -080054
Zach Reizner38f0fd92016-02-18 14:28:02 -080055 GLuint program = glCreateProgram();
56 if (!program) {
57 bs_debug_error("failed to create program");
58 return 0;
Haixia Shie04ddfd2014-11-11 19:14:32 -080059 }
60
Zach Reizner38f0fd92016-02-18 14:28:02 -080061 GLuint vert_shader = shader_create(GL_VERTEX_SHADER, vertex_shader_str);
62 if (!vert_shader) {
63 bs_debug_error("failed to create vertex shader");
64 glDeleteProgram(program);
65 return 0;
Haixia Shie04ddfd2014-11-11 19:14:32 -080066 }
67
Zach Reizner38f0fd92016-02-18 14:28:02 -080068 GLuint frag_shader = shader_create(GL_FRAGMENT_SHADER, fragment_shader_str);
69 if (!frag_shader) {
70 bs_debug_error("failed to create fragment shader");
71 glDeleteShader(vert_shader);
72 glDeleteProgram(program);
73 return 0;
Haixia Shie04ddfd2014-11-11 19:14:32 -080074 }
75
Zach Reizner38f0fd92016-02-18 14:28:02 -080076 glAttachShader(program, vert_shader);
77 glAttachShader(program, frag_shader);
78 glBindAttribLocation(program, 0, "vPosition");
79 glBindAttribLocation(program, 1, "vColor");
80 glLinkProgram(program);
81 glDetachShader(program, vert_shader);
82 glDetachShader(program, frag_shader);
83 glDeleteShader(vert_shader);
84 glDeleteShader(frag_shader);
Haixia Shie04ddfd2014-11-11 19:14:32 -080085
Zach Reizner38f0fd92016-02-18 14:28:02 -080086 GLint status;
87 glGetProgramiv(program, GL_LINK_STATUS, &status);
88 if (!status) {
89 GLint log_len = 0;
90 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_len);
91 char *program_log = calloc(log_len, sizeof(char));
92 assert(program_log);
93 glGetProgramInfoLog(program, log_len, NULL, program_log);
94 bs_debug_error("failed to link program: %s", program_log);
95 free(program_log);
96 glDeleteProgram(program);
97 return 0;
Haixia Shie04ddfd2014-11-11 19:14:32 -080098 }
99
Zach Reizner38f0fd92016-02-18 14:28:02 -0800100 return program;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800101}
102
Lauri Peltonen95226da2014-12-18 16:39:54 -0800103static float f(int i)
104{
Haixia Shie04ddfd2014-11-11 19:14:32 -0800105 int a = i % 40;
106 int b = (i / 40) % 6;
107 switch (b) {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800108 case 0:
109 case 1:
110 return 0.0f;
111 case 3:
112 case 4:
113 return 1.0f;
114 case 2:
115 return (a / 40.0f);
116 case 5:
117 return 1.0f - (a / 40.0f);
118 default:
119 return 0.0f;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800120 }
121}
122
Zach Reizner38f0fd92016-02-18 14:28:02 -0800123static void page_flip_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec,
124 void *data)
Haixia Shi4652b8c2014-11-19 17:55:38 -0800125{
126 int *waiting_for_flip = data;
127 *waiting_for_flip = 0;
128}
129
Zach Reizner38f0fd92016-02-18 14:28:02 -0800130int main(int argc, char **argv)
Haixia Shie04ddfd2014-11-11 19:14:32 -0800131{
Zach Reizner38f0fd92016-02-18 14:28:02 -0800132 int fd = -1;
133 if (argc >= 2) {
134 fd = open(argv[1], O_RDWR);
135 if (fd < 0) {
136 bs_debug_error("failed to open card %s", argv[1]);
137 return 1;
138 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800139 }
Zach Reizner38f0fd92016-02-18 14:28:02 -0800140 else {
141 fd = bs_drm_open_main_display();
142 if (fd < 0) {
143 bs_debug_error("failed to open card for display");
144 return 1;
145 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800146 }
147
Zach Reizner38f0fd92016-02-18 14:28:02 -0800148 struct gbm_device *gbm = gbm_create_device(fd);
149 if (!gbm) {
150 bs_debug_error("failed to create gbm");
151 return 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800152 }
153
Zach Reizner38f0fd92016-02-18 14:28:02 -0800154 struct bs_drm_pipe pipe = {0};
155 if (!bs_drm_pipe_make(fd, &pipe)) {
156 bs_debug_error("failed to make pipe");
157 return 1;
158 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800159
Zach Reizner38f0fd92016-02-18 14:28:02 -0800160 drmModeConnector *connector = drmModeGetConnector(fd, pipe.connector_id);
161 assert(connector);
162 drmModeModeInfo *mode = &connector->modes[0];
163
164 struct bs_egl *egl = bs_egl_new();
165 if (!bs_egl_setup(egl)) {
166 bs_debug_error("failed to setup egl context");
167 return 1;
168 }
169
170 struct gbm_bo *bos[2];
171 uint32_t ids[2];
172 struct bs_egl_fb *egl_fbs[2];
173 for (size_t fb_index = 0; fb_index < 2; fb_index++) {
174 bos[fb_index] =
175 gbm_bo_create(gbm, mode->hdisplay, mode->vdisplay, GBM_FORMAT_XRGB8888,
176 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
177 if (bos[fb_index] == NULL) {
178 bs_debug_error("failed to allocate framebuffer");
179 return 1;
180 }
181
182 ids[fb_index] = bs_drm_fb_create_gbm(bos[fb_index]);
183 if (ids[fb_index] == 0) {
184 bs_debug_error("failed to create framebuffer id");
185 return 1;
186 }
187
188 EGLImageKHR egl_image = bs_egl_image_create_gbm(egl, bos[fb_index]);
189 if (egl_image == EGL_NO_IMAGE_KHR) {
190 bs_debug_error("failed to create EGLImageKHR from framebuffer");
191 return 1;
192 }
193
194 egl_fbs[fb_index] = bs_egl_fb_new(egl, egl_image);
195 if (!egl_fbs[fb_index]) {
196 bs_debug_error("failed to create framebuffer from EGLImageKHR");
197 return 1;
198 }
199 }
200
201 int ret = drmModeSetCrtc(fd, pipe.crtc_id, ids[0], 0 /* x */, 0 /* y */, &pipe.connector_id,
202 1 /* connector count */, mode);
203 if (ret) {
204 bs_debug_error("failed to set CRTC");
205 return 1;
206 }
207
208 GLuint program = solid_shader_create();
Haixia Shie04ddfd2014-11-11 19:14:32 -0800209 if (!program) {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800210 bs_debug_error("failed to create solid shader");
211 return 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800212 }
213
Haixia Shi4652b8c2014-11-19 17:55:38 -0800214 int fb_idx = 1;
Zach Reizner38f0fd92016-02-18 14:28:02 -0800215 for (int i = 0; i <= 500; i++) {
Haixia Shi4652b8c2014-11-19 17:55:38 -0800216 int waiting_for_flip = 1;
Zach Reizner38f0fd92016-02-18 14:28:02 -0800217 // clang-format off
Haixia Shie04ddfd2014-11-11 19:14:32 -0800218 GLfloat verts[] = {
219 0.0f, -0.5f, 0.0f,
220 -0.5f, 0.5f, 0.0f,
221 0.5f, 0.5f, 0.0f
222 };
223 GLfloat colors[] = {
224 1.0f, 0.0f, 0.0f, 1.0f,
225 0.0f, 1.0f, 0.0f, 1.0f,
226 0.0f, 0.0f, 1.0f, 1.0f
227 };
Zach Reizner38f0fd92016-02-18 14:28:02 -0800228 // clang-format on
Haixia Shie04ddfd2014-11-11 19:14:32 -0800229
Zach Reizner38f0fd92016-02-18 14:28:02 -0800230 glBindFramebuffer(GL_FRAMEBUFFER, bs_egl_fb_name(egl_fbs[fb_idx]));
231 glViewport(0, 0, (GLint)mode->hdisplay, (GLint)mode->vdisplay);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800232
Haixia Shie04ddfd2014-11-11 19:14:32 -0800233 glClearColor(f(i), f(i + 80), f(i + 160), 0.0f);
234 glClear(GL_COLOR_BUFFER_BIT);
235
236 glUseProgram(program);
237 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, verts);
238 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, colors);
239 glEnableVertexAttribArray(0);
240 glEnableVertexAttribArray(1);
241 glDrawArrays(GL_TRIANGLES, 0, 3);
242
243 usleep(1e6 / 120); /* 120 Hz */
244 glFinish();
Zach Reizner38f0fd92016-02-18 14:28:02 -0800245 ret = drmModePageFlip(fd, pipe.crtc_id, ids[fb_idx], DRM_MODE_PAGE_FLIP_EVENT,
246 &waiting_for_flip);
247 if (ret) {
248 bs_debug_error("failed page flip: %d", ret);
249 return 1;
250 }
Haixia Shi4652b8c2014-11-19 17:55:38 -0800251
252 while (waiting_for_flip) {
253 drmEventContext evctx = {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800254 .version = DRM_EVENT_CONTEXT_VERSION,
255 .page_flip_handler = page_flip_handler,
Haixia Shi4652b8c2014-11-19 17:55:38 -0800256 };
257
258 fd_set fds;
259 FD_ZERO(&fds);
260 FD_SET(0, &fds);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800261 FD_SET(fd, &fds);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800262
Zach Reizner38f0fd92016-02-18 14:28:02 -0800263 ret = select(fd + 1, &fds, NULL, NULL, NULL);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800264 if (ret < 0) {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800265 bs_debug_error("select err: %s", strerror(errno));
266 return 1;
Haixia Shi4652b8c2014-11-19 17:55:38 -0800267 }
Zach Reizner38f0fd92016-02-18 14:28:02 -0800268 else if (ret == 0) {
269 bs_debug_error("select timeout");
270 return 1;
271 }
272 else if (FD_ISSET(0, &fds)) {
273 bs_debug_error("user interrupted");
274 return 1;
275 }
276 ret = drmHandleEvent(fd, &evctx);
277 if (ret) {
278 bs_debug_error("failed to wait for page flip: %d", ret);
279 return 1;
280 }
Haixia Shi4652b8c2014-11-19 17:55:38 -0800281 }
282 fb_idx = fb_idx ^ 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800283 }
284
Zach Reizner38f0fd92016-02-18 14:28:02 -0800285 return 0;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800286}