blob: a059ff7dd206ade02f1ba4e3019c0d7a541d2b87 [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
Haixia Shie04ddfd2014-11-11 19:14:32 -08007#include <errno.h>
8#include <fcntl.h>
9#include <stdbool.h>
10#include <stdio.h>
11#include <string.h>
12#include <sys/types.h>
13#include <unistd.h>
14
15#define EGL_EGLEXT_PROTOTYPES
16#define GL_GLEXT_PROTOTYPES
17
18#include <gbm.h>
19#include <EGL/egl.h>
20#include <EGL/eglext.h>
21#include <drm_fourcc.h>
22#include <GLES2/gl2.h>
23#include <GLES2/gl2ext.h>
24#include <xf86drm.h>
25#include <xf86drmMode.h>
26
27const char * get_gl_error()
28{
29 switch (glGetError()) {
30 case GL_NO_ERROR:
Haixia Shi4652b8c2014-11-19 17:55:38 -080031 return "GL_NO_ERROR";
Haixia Shie04ddfd2014-11-11 19:14:32 -080032 case GL_INVALID_ENUM:
Haixia Shi4652b8c2014-11-19 17:55:38 -080033 return "GL_INVALID_ENUM";
Haixia Shie04ddfd2014-11-11 19:14:32 -080034 case GL_INVALID_VALUE:
Haixia Shi4652b8c2014-11-19 17:55:38 -080035 return "GL_INVALID_VALUE";
Haixia Shie04ddfd2014-11-11 19:14:32 -080036 case GL_INVALID_OPERATION:
Haixia Shi4652b8c2014-11-19 17:55:38 -080037 return "GL_INVALID_OPERATION";
Haixia Shie04ddfd2014-11-11 19:14:32 -080038 case GL_INVALID_FRAMEBUFFER_OPERATION:
Haixia Shi4652b8c2014-11-19 17:55:38 -080039 return "GL_INVALID_FRAMEBUFFER_OPERATION";
Haixia Shie04ddfd2014-11-11 19:14:32 -080040 case GL_OUT_OF_MEMORY:
Haixia Shi4652b8c2014-11-19 17:55:38 -080041 return "GL_OUT_OF_MEMORY";
Haixia Shie04ddfd2014-11-11 19:14:32 -080042 default:
43 return "Unknown error";
44 }
45}
46
47const char * get_egl_error()
48{
49 switch (eglGetError()) {
50 case EGL_SUCCESS:
Haixia Shi4652b8c2014-11-19 17:55:38 -080051 return "EGL_SUCCESS";
Haixia Shie04ddfd2014-11-11 19:14:32 -080052 case EGL_NOT_INITIALIZED:
Haixia Shi4652b8c2014-11-19 17:55:38 -080053 return "EGL_NOT_INITIALIZED";
Haixia Shie04ddfd2014-11-11 19:14:32 -080054 case EGL_BAD_ACCESS:
Haixia Shi4652b8c2014-11-19 17:55:38 -080055 return "EGL_BAD_ACCESS";
Haixia Shie04ddfd2014-11-11 19:14:32 -080056 case EGL_BAD_ALLOC:
Haixia Shi4652b8c2014-11-19 17:55:38 -080057 return "EGL_BAD_ALLOC";
Haixia Shie04ddfd2014-11-11 19:14:32 -080058 case EGL_BAD_ATTRIBUTE:
Haixia Shi4652b8c2014-11-19 17:55:38 -080059 return "EGL_BAD_ATTRIBUTE";
Haixia Shie04ddfd2014-11-11 19:14:32 -080060 case EGL_BAD_CONTEXT:
Haixia Shi4652b8c2014-11-19 17:55:38 -080061 return "EGL_BAD_CONTEXT";
Haixia Shie04ddfd2014-11-11 19:14:32 -080062 case EGL_BAD_CONFIG:
Haixia Shi4652b8c2014-11-19 17:55:38 -080063 return "EGL_BAD_CONFIG";
Haixia Shie04ddfd2014-11-11 19:14:32 -080064 case EGL_BAD_CURRENT_SURFACE:
Haixia Shi4652b8c2014-11-19 17:55:38 -080065 return "EGL_BAD_CURRENT_SURFACE";
Haixia Shie04ddfd2014-11-11 19:14:32 -080066 case EGL_BAD_DISPLAY:
Haixia Shi4652b8c2014-11-19 17:55:38 -080067 return "EGL_BAD_DISPLAY";
Haixia Shie04ddfd2014-11-11 19:14:32 -080068 case EGL_BAD_SURFACE:
Haixia Shi4652b8c2014-11-19 17:55:38 -080069 return "EGL_BAD_SURFACE";
Haixia Shie04ddfd2014-11-11 19:14:32 -080070 case EGL_BAD_MATCH:
Haixia Shi4652b8c2014-11-19 17:55:38 -080071 return "EGL_BAD_MATCH";
Haixia Shie04ddfd2014-11-11 19:14:32 -080072 case EGL_BAD_PARAMETER:
Haixia Shi4652b8c2014-11-19 17:55:38 -080073 return "EGL_BAD_PARAMETER";
Haixia Shie04ddfd2014-11-11 19:14:32 -080074 case EGL_BAD_NATIVE_PIXMAP:
Haixia Shi4652b8c2014-11-19 17:55:38 -080075 return "EGL_BAD_NATIVE_PIXMAP";
Haixia Shie04ddfd2014-11-11 19:14:32 -080076 case EGL_BAD_NATIVE_WINDOW:
Haixia Shi4652b8c2014-11-19 17:55:38 -080077 return "EGL_BAD_NATIVE_WINDOW";
Haixia Shie04ddfd2014-11-11 19:14:32 -080078 case EGL_CONTEXT_LOST:
Haixia Shi4652b8c2014-11-19 17:55:38 -080079 return "EGL_CONTEXT_LOST";
Haixia Shie04ddfd2014-11-11 19:14:32 -080080 default:
81 return "Unknown error";
82 }
83}
84
Haixia Shi4652b8c2014-11-19 17:55:38 -080085#define BUFFERS 2
86
Haixia Shie04ddfd2014-11-11 19:14:32 -080087struct context {
Haixia Shibc4d0a02014-12-01 14:25:54 -080088 int drm_card_fd;
Haixia Shibc4d0a02014-12-01 14:25:54 -080089 struct gbm_device *drm_gbm;
Haixia Shie04ddfd2014-11-11 19:14:32 -080090
91 EGLDisplay egl_display;
92 EGLContext egl_ctx;
Haixia Shie04ddfd2014-11-11 19:14:32 -080093
94 drmModeConnector * connector;
95 drmModeEncoder * encoder;
96 drmModeModeInfo * mode;
Haixia Shie04ddfd2014-11-11 19:14:32 -080097
Haixia Shi4652b8c2014-11-19 17:55:38 -080098 struct gbm_bo * gbm_buffer[BUFFERS];
99 EGLImageKHR egl_image[BUFFERS];
100 uint32_t drm_fb_id[BUFFERS];
101 unsigned gl_fb[BUFFERS];
102 unsigned gl_rb[BUFFERS];
Haixia Shie04ddfd2014-11-11 19:14:32 -0800103
104};
105
106bool setup_drm(struct context * ctx)
107{
Haixia Shibc4d0a02014-12-01 14:25:54 -0800108 int fd = ctx->drm_card_fd;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800109 drmModeRes *resources = NULL;
110 drmModeConnector *connector = NULL;
111 drmModeEncoder *encoder = NULL;
112 int i, j;
113
114 resources = drmModeGetResources(fd);
115 if (!resources) {
116 fprintf(stderr, "drmModeGetResources failed\n");
117 return false;
118 }
119
120 for (i = 0; i < resources->count_connectors; i++) {
121 connector = drmModeGetConnector(fd, resources->connectors[i]);
122 if (connector == NULL)
123 continue;
124
125 if (connector->connection == DRM_MODE_CONNECTED &&
126 connector->count_modes > 0)
127 break;
128
129 drmModeFreeConnector(connector);
130 }
131
132 if (i == resources->count_connectors) {
133 fprintf(stderr, "no currently active connector found\n");
134 return false;
135 }
136
137 for (i = 0; i < resources->count_encoders; i++) {
138 encoder = drmModeGetEncoder(fd, resources->encoders[i]);
139
140 if (encoder == NULL)
141 continue;
142
143 for (j = 0; j < connector->count_encoders; j++) {
144 if (encoder->encoder_id == connector->encoders[j])
145 break;
146 }
147
148 if (j == connector->count_encoders) {
149 drmModeFreeEncoder(encoder);
150 continue;
151 }
152
153 break;
154 }
155
156 if (i == resources->count_encoders) {
157 fprintf(stderr, "no supported encoder found\n");
158 return false;
159 }
160
161 for (i = 0; i < resources->count_crtcs; i++) {
162 if (encoder->possible_crtcs & (1 << i)) {
163 encoder->crtc_id = resources->crtcs[i];
164 break;
165 }
166 }
167
168 if (i == resources->count_crtcs) {
169 fprintf(stderr, "no possible crtc found\n");
170 return false;
171 }
172
173 ctx->connector = connector;
174 ctx->encoder = encoder;
175 ctx->mode = &connector->modes[0];
176
177 return true;
178}
179
180float f(int i) {
181 int a = i % 40;
182 int b = (i / 40) % 6;
183 switch (b) {
184 case 0:
185 case 1:
186 return 0.0f;
187 case 3:
188 case 4:
189 return 1.0f;
190 case 2:
191 return (a / 40.0f);
192 case 5:
193 return 1.0f - (a / 40.0f);
194 default:
195 return 0.0f;
196 }
197}
198
Haixia Shi4652b8c2014-11-19 17:55:38 -0800199static void page_flip_handler(int fd, unsigned int frame, unsigned int sec,
200 unsigned int usec, void *data)
201{
202 int *waiting_for_flip = data;
203 *waiting_for_flip = 0;
204}
205
Haixia Shie04ddfd2014-11-11 19:14:32 -0800206void draw(struct context * ctx)
207{
208 int i;
209 const GLchar *vertexShaderStr =
210 "attribute vec4 vPosition;\n"
211 "attribute vec4 vColor;\n"
212 "varying vec4 vFillColor;\n"
213 "void main() {\n"
214 " gl_Position = vPosition;\n"
215 " vFillColor = vColor;\n"
216 "}\n";
217 const GLchar *fragmentShaderStr =
218 "precision mediump float;\n"
219 "varying vec4 vFillColor;\n"
220 "void main() {\n"
221 " gl_FragColor = vFillColor;\n"
222 "}\n";
223 GLint vertexShader, fragmentShader, program, status;
224
225 vertexShader = glCreateShader(GL_VERTEX_SHADER);
226 if (!vertexShader) {
227 fprintf(stderr, "Failed to create vertex shader. Error=0x%x\n", glGetError());
228 return;
229 }
230 glShaderSource(vertexShader, 1, &vertexShaderStr, NULL);
231 glCompileShader(vertexShader);
232 glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
233 if (!status) {
234 fprintf(stderr, "Failed to compile vertex shader. Error=0x%x\n", glGetError());
235 return;
236 }
237
238 fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
239 if (!fragmentShader) {
240 fprintf(stderr, "Failed to create fragment shader. Error=0x%x\n", glGetError());
241 return;
242 }
243 glShaderSource(fragmentShader, 1, &fragmentShaderStr, NULL);
244 glCompileShader(fragmentShader);
245 glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
246 if (!status) {
247 fprintf(stderr, "Failed to compile fragment shader. Error=0x%x\n", glGetError());
248 return;
249 }
250
251
252 program = glCreateProgram();
253 if (!program) {
254 fprintf(stderr, "Failed to create program.\n");
255 return;
256 }
257 glAttachShader(program, vertexShader);
258 glAttachShader(program, fragmentShader);
259 glBindAttribLocation(program, 0, "vPosition");
260 glBindAttribLocation(program, 1, "vColor");
261 glLinkProgram(program);
262 glGetShaderiv(program, GL_LINK_STATUS, &status);
263 if (!status) {
264 fprintf(stderr, "Failed to link program.\n");
265 return;
266 }
267
Haixia Shi4652b8c2014-11-19 17:55:38 -0800268 int fb_idx = 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800269 for (i = 0; i <= 500; i++) {
Haixia Shi4652b8c2014-11-19 17:55:38 -0800270 int waiting_for_flip = 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800271 GLfloat verts[] = {
272 0.0f, -0.5f, 0.0f,
273 -0.5f, 0.5f, 0.0f,
274 0.5f, 0.5f, 0.0f
275 };
276 GLfloat colors[] = {
277 1.0f, 0.0f, 0.0f, 1.0f,
278 0.0f, 1.0f, 0.0f, 1.0f,
279 0.0f, 0.0f, 1.0f, 1.0f
280 };
281
Haixia Shi4652b8c2014-11-19 17:55:38 -0800282 glBindFramebuffer(GL_FRAMEBUFFER, ctx->gl_fb[fb_idx]);
283 glViewport(0, 0,(GLint) ctx->mode->hdisplay,
284 (GLint) ctx->mode->vdisplay);
285
Haixia Shie04ddfd2014-11-11 19:14:32 -0800286 glClearColor(f(i), f(i + 80), f(i + 160), 0.0f);
287 glClear(GL_COLOR_BUFFER_BIT);
288
289 glUseProgram(program);
290 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, verts);
291 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, colors);
292 glEnableVertexAttribArray(0);
293 glEnableVertexAttribArray(1);
294 glDrawArrays(GL_TRIANGLES, 0, 3);
295
296 usleep(1e6 / 120); /* 120 Hz */
297 glFinish();
Haixia Shibc4d0a02014-12-01 14:25:54 -0800298 drmModePageFlip(ctx->drm_card_fd, ctx->encoder->crtc_id,
Haixia Shi4652b8c2014-11-19 17:55:38 -0800299 ctx->drm_fb_id[fb_idx],
300 DRM_MODE_PAGE_FLIP_EVENT,
301 &waiting_for_flip);
302
303 while (waiting_for_flip) {
304 drmEventContext evctx = {
305 .version = DRM_EVENT_CONTEXT_VERSION,
306 .page_flip_handler = page_flip_handler,
307 };
308
309 fd_set fds;
310 FD_ZERO(&fds);
311 FD_SET(0, &fds);
Haixia Shibc4d0a02014-12-01 14:25:54 -0800312 FD_SET(ctx->drm_card_fd, &fds);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800313
Haixia Shibc4d0a02014-12-01 14:25:54 -0800314 int ret = select(ctx->drm_card_fd + 1, &fds, NULL, NULL, NULL);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800315 if (ret < 0) {
316 fprintf(stderr, "select err: %s\n", strerror(errno));
317 return;
318 } else if (ret == 0) {
319 fprintf(stderr, "select timeout\n");
320 return;
321 } else if (FD_ISSET(0, &fds)) {
322 fprintf(stderr, "user interrupted\n");
323 return;
324 }
Haixia Shibc4d0a02014-12-01 14:25:54 -0800325 drmHandleEvent(ctx->drm_card_fd, &evctx);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800326 }
327 fb_idx = fb_idx ^ 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800328 }
329
330 glDeleteProgram(program);
331}
332
333int main(int argc, char ** argv)
334{
335 int ret = 0;
336 struct context ctx;
337 EGLint egl_major, egl_minor;
338 const char * extensions;
339 uint32_t bo_handle;
340 uint32_t bo_stride;
341 int drm_prime_fd;
342 EGLint num_configs;
343 EGLConfig egl_config;
Haixia Shi4652b8c2014-11-19 17:55:38 -0800344 size_t i;
Lauri Peltonen71cdf952014-12-17 12:13:24 -0800345 char* drm_card_path = "/dev/dri/card0";
Haixia Shie04ddfd2014-11-11 19:14:32 -0800346
347 const EGLint config_attribs[] = {
348 EGL_RED_SIZE, 1,
349 EGL_GREEN_SIZE, 1,
350 EGL_BLUE_SIZE, 1,
351 EGL_DEPTH_SIZE, 1,
352 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
353 EGL_NONE
354 };
355 const EGLint context_attribs[] = {
356 EGL_CONTEXT_CLIENT_VERSION, 2,
357 EGL_NONE
358 };
359
Lauri Peltonen71cdf952014-12-17 12:13:24 -0800360 if (argc >= 2)
Haixia Shibc4d0a02014-12-01 14:25:54 -0800361 drm_card_path = argv[1];
Haixia Shie04ddfd2014-11-11 19:14:32 -0800362
Haixia Shibc4d0a02014-12-01 14:25:54 -0800363 ctx.drm_card_fd = open(drm_card_path, O_RDWR);
364 if (ctx.drm_card_fd < 0) {
365 fprintf(stderr, "failed to open %s\n", drm_card_path);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800366 ret = 1;
367 goto fail;
368 }
369
Haixia Shibc4d0a02014-12-01 14:25:54 -0800370 ctx.drm_gbm = gbm_create_device(ctx.drm_card_fd);
371 if (!ctx.drm_gbm) {
372 fprintf(stderr, "failed to create gbm device on %s\n", drm_card_path);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800373 ret = 1;
Haixia Shibc4d0a02014-12-01 14:25:54 -0800374 goto close_drm_card;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800375 }
376
Lauri Peltonen71cdf952014-12-17 12:13:24 -0800377 ctx.egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800378 if (ctx.egl_display == EGL_NO_DISPLAY) {
379 fprintf(stderr, "failed to get egl display\n");
380 ret = 1;
Lauri Peltonen71cdf952014-12-17 12:13:24 -0800381 goto destroy_drm_gbm;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800382 }
383
384 if (!eglInitialize(ctx.egl_display, &egl_major, &egl_minor)) {
385 fprintf(stderr, "failed to initialize egl: %s\n",
386 get_egl_error());
387 ret = 1;
388 goto terminate_display;
389 }
390
391 fprintf(stderr, "EGL %d.%d\n", egl_major, egl_minor);
392 fprintf(stderr, "EGL %s\n",
393 eglQueryString(ctx.egl_display, EGL_VERSION));
394
395 extensions = eglQueryString(ctx.egl_display, EGL_EXTENSIONS);
396 fprintf(stderr, "EGL Extensions: %s\n", extensions);
397
398 if (!setup_drm(&ctx)) {
399 fprintf(stderr, "failed to setup drm resources\n");
400 ret = 1;
401 goto terminate_display;
402 }
403
404 fprintf(stderr, "display size: %dx%d\n",
405 ctx.mode->hdisplay, ctx.mode->vdisplay);
406
407 if (!eglChooseConfig(ctx.egl_display, config_attribs, NULL, 0,
408 &num_configs)) {
409 fprintf(stderr, "eglChooseConfig() failed with error: %x\n", eglGetError());
410 goto free_drm;
411 }
412 if (!eglChooseConfig(ctx.egl_display, config_attribs, &egl_config, 1,
413 &num_configs)) {
414 fprintf(stderr, "eglChooseConfig() failed with error: %x\n", eglGetError());
415 goto free_drm;
416 }
417
418 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
419 fprintf(stderr, "failed to bind OpenGL ES: %s\n",
420 get_egl_error());
421 ret = 1;
422 goto free_drm;
423 }
424
425 ctx.egl_ctx = eglCreateContext(ctx.egl_display,
Lauri Peltonen44af28d2014-12-17 12:19:54 -0800426 egl_config,
Haixia Shie04ddfd2014-11-11 19:14:32 -0800427 EGL_NO_CONTEXT /* No shared context */,
428 context_attribs);
429 if (ctx.egl_ctx == EGL_NO_CONTEXT) {
430 fprintf(stderr, "failed to create OpenGL ES Context: %s\n",
431 get_egl_error());
432 ret = 1;
433 goto free_drm;
434 }
435
436 if (!eglMakeCurrent(ctx.egl_display,
437 EGL_NO_SURFACE /* No default draw surface */,
438 EGL_NO_SURFACE /* No default draw read */,
439 ctx.egl_ctx)) {
440 fprintf(stderr, "failed to make the OpenGL ES Context current: %s\n",
441 get_egl_error());
442 ret = 1;
443 goto destroy_context;
444 }
445
446 fprintf(stderr, "GL extensions: %s\n", glGetString(GL_EXTENSIONS));
447
Haixia Shi4652b8c2014-11-19 17:55:38 -0800448 glGenFramebuffers(BUFFERS, ctx.gl_fb);
449 glGenRenderbuffers(BUFFERS, ctx.gl_rb);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800450
Haixia Shi4652b8c2014-11-19 17:55:38 -0800451 for (i = 0; i < BUFFERS; ++i) {
Haixia Shibc4d0a02014-12-01 14:25:54 -0800452 ctx.gbm_buffer[i] = gbm_bo_create(ctx.drm_gbm,
Haixia Shi4652b8c2014-11-19 17:55:38 -0800453 ctx.mode->hdisplay, ctx.mode->vdisplay, GBM_BO_FORMAT_XRGB8888,
454 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
455
456 if (!ctx.gbm_buffer[i]) {
457 fprintf(stderr, "failed to create buffer object\n");
458 ret = 1;
459 goto free_buffers;
460 }
461
462 bo_handle = gbm_bo_get_handle(ctx.gbm_buffer[i]).u32;
463 bo_stride = gbm_bo_get_stride(ctx.gbm_buffer[i]);
464
Zach Reizner0feb1f12015-01-09 13:38:57 -0800465 drm_prime_fd = gbm_bo_get_fd(ctx.gbm_buffer[i]);
466
467 if (drm_prime_fd < 0) {
Haixia Shi4652b8c2014-11-19 17:55:38 -0800468 fprintf(stderr, "failed to turn handle into fd\n");
469 ret = 1;
470 goto free_buffers;
471 }
472
473 const EGLint khr_image_attrs[] = {
474 EGL_WIDTH, ctx.mode->hdisplay,
475 EGL_HEIGHT, ctx.mode->vdisplay,
476 EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_XRGB8888,
477 EGL_DMA_BUF_PLANE0_FD_EXT, drm_prime_fd,
478 EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
479 EGL_DMA_BUF_PLANE0_PITCH_EXT, bo_stride,
480 EGL_NONE
481 };
482
483 ctx.egl_image[i] = eglCreateImageKHR(ctx.egl_display, EGL_NO_CONTEXT,
484 EGL_LINUX_DMA_BUF_EXT, NULL, khr_image_attrs);
485 if (ctx.egl_image[i] == EGL_NO_IMAGE_KHR) {
486 fprintf(stderr, "failed to create egl image: %s\n",
487 get_egl_error());
488 ret = 1;
489 goto free_buffers;
490 }
491
492 glBindRenderbuffer(GL_RENDERBUFFER, ctx.gl_rb[i]);
493 glBindFramebuffer(GL_FRAMEBUFFER, ctx.gl_fb[i]);
494 glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, ctx.egl_image[i]);
495 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
496 GL_RENDERBUFFER, ctx.gl_rb[i]);
497
498 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) !=
499 GL_FRAMEBUFFER_COMPLETE) {
500 fprintf(stderr, "failed to create framebuffer: %s\n", get_gl_error());
501 ret = 1;
502 goto free_buffers;
503 }
504
Haixia Shibc4d0a02014-12-01 14:25:54 -0800505 ret = drmModeAddFB(ctx.drm_card_fd, ctx.mode->hdisplay, ctx.mode->vdisplay,
Haixia Shi4652b8c2014-11-19 17:55:38 -0800506 24, 32, bo_stride, bo_handle, &ctx.drm_fb_id[i]);
507
508 if (ret) {
509 fprintf(stderr, "failed to add fb\n");
510 ret = 1;
511 goto free_buffers;
512 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800513 }
514
Haixia Shibc4d0a02014-12-01 14:25:54 -0800515 if (drmModeSetCrtc(ctx.drm_card_fd, ctx.encoder->crtc_id, ctx.drm_fb_id[0],
Haixia Shie04ddfd2014-11-11 19:14:32 -0800516 0, 0, &ctx.connector->connector_id, 1, ctx.mode)) {
517 fprintf(stderr, "failed to set CRTC\n");
518 ret = 1;
Haixia Shi4652b8c2014-11-19 17:55:38 -0800519 goto free_buffers;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800520 }
521
522 draw(&ctx);
523
Haixia Shi4652b8c2014-11-19 17:55:38 -0800524free_buffers:
Haixia Shie04ddfd2014-11-11 19:14:32 -0800525 glBindRenderbuffer(GL_RENDERBUFFER, 0);
526 glBindFramebuffer(GL_FRAMEBUFFER, 0);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800527 for (i = 0; i < BUFFERS; ++i) {
528 if (ctx.drm_fb_id[i])
Haixia Shibc4d0a02014-12-01 14:25:54 -0800529 drmModeRmFB(ctx.drm_card_fd, ctx.drm_fb_id[i]);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800530 if (ctx.egl_image[i])
531 eglDestroyImageKHR(ctx.egl_display, ctx.egl_image[i]);
532 if (ctx.gl_fb[i])
533 glDeleteFramebuffers(1, &ctx.gl_fb[i]);
534 if (ctx.gl_rb[i])
535 glDeleteRenderbuffers(1, &ctx.gl_rb[i]);
536 if (ctx.gbm_buffer[i])
537 gbm_bo_destroy(ctx.gbm_buffer[i]);
538 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800539destroy_context:
540 eglDestroyContext(ctx.egl_display, ctx.egl_ctx);
541free_drm:
542 drmModeFreeConnector(ctx.connector);
543 drmModeFreeEncoder(ctx.encoder);
544terminate_display:
545 eglTerminate(ctx.egl_display);
Haixia Shibc4d0a02014-12-01 14:25:54 -0800546destroy_drm_gbm:
547 gbm_device_destroy(ctx.drm_gbm);
548close_drm_card:
549 close(ctx.drm_card_fd);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800550fail:
551 return ret;
552}