blob: 2722ae5c514fd688e3eefab0f8acbc477bb72dbe [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;
89 int egl_card_fd;
90 struct gbm_device *drm_gbm;
91 struct gbm_device *egl_gbm;
Haixia Shie04ddfd2014-11-11 19:14:32 -080092
93 EGLDisplay egl_display;
94 EGLContext egl_ctx;
Haixia Shie04ddfd2014-11-11 19:14:32 -080095
96 drmModeConnector * connector;
97 drmModeEncoder * encoder;
98 drmModeModeInfo * mode;
Haixia Shie04ddfd2014-11-11 19:14:32 -080099
Haixia Shi4652b8c2014-11-19 17:55:38 -0800100 struct gbm_bo * gbm_buffer[BUFFERS];
101 EGLImageKHR egl_image[BUFFERS];
102 uint32_t drm_fb_id[BUFFERS];
103 unsigned gl_fb[BUFFERS];
104 unsigned gl_rb[BUFFERS];
Haixia Shie04ddfd2014-11-11 19:14:32 -0800105
106};
107
108bool setup_drm(struct context * ctx)
109{
Haixia Shibc4d0a02014-12-01 14:25:54 -0800110 int fd = ctx->drm_card_fd;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800111 drmModeRes *resources = NULL;
112 drmModeConnector *connector = NULL;
113 drmModeEncoder *encoder = NULL;
114 int i, j;
115
116 resources = drmModeGetResources(fd);
117 if (!resources) {
118 fprintf(stderr, "drmModeGetResources failed\n");
119 return false;
120 }
121
122 for (i = 0; i < resources->count_connectors; i++) {
123 connector = drmModeGetConnector(fd, resources->connectors[i]);
124 if (connector == NULL)
125 continue;
126
127 if (connector->connection == DRM_MODE_CONNECTED &&
128 connector->count_modes > 0)
129 break;
130
131 drmModeFreeConnector(connector);
132 }
133
134 if (i == resources->count_connectors) {
135 fprintf(stderr, "no currently active connector found\n");
136 return false;
137 }
138
139 for (i = 0; i < resources->count_encoders; i++) {
140 encoder = drmModeGetEncoder(fd, resources->encoders[i]);
141
142 if (encoder == NULL)
143 continue;
144
145 for (j = 0; j < connector->count_encoders; j++) {
146 if (encoder->encoder_id == connector->encoders[j])
147 break;
148 }
149
150 if (j == connector->count_encoders) {
151 drmModeFreeEncoder(encoder);
152 continue;
153 }
154
155 break;
156 }
157
158 if (i == resources->count_encoders) {
159 fprintf(stderr, "no supported encoder found\n");
160 return false;
161 }
162
163 for (i = 0; i < resources->count_crtcs; i++) {
164 if (encoder->possible_crtcs & (1 << i)) {
165 encoder->crtc_id = resources->crtcs[i];
166 break;
167 }
168 }
169
170 if (i == resources->count_crtcs) {
171 fprintf(stderr, "no possible crtc found\n");
172 return false;
173 }
174
175 ctx->connector = connector;
176 ctx->encoder = encoder;
177 ctx->mode = &connector->modes[0];
178
179 return true;
180}
181
182float f(int i) {
183 int a = i % 40;
184 int b = (i / 40) % 6;
185 switch (b) {
186 case 0:
187 case 1:
188 return 0.0f;
189 case 3:
190 case 4:
191 return 1.0f;
192 case 2:
193 return (a / 40.0f);
194 case 5:
195 return 1.0f - (a / 40.0f);
196 default:
197 return 0.0f;
198 }
199}
200
Haixia Shi4652b8c2014-11-19 17:55:38 -0800201static void page_flip_handler(int fd, unsigned int frame, unsigned int sec,
202 unsigned int usec, void *data)
203{
204 int *waiting_for_flip = data;
205 *waiting_for_flip = 0;
206}
207
Haixia Shie04ddfd2014-11-11 19:14:32 -0800208void draw(struct context * ctx)
209{
210 int i;
211 const GLchar *vertexShaderStr =
212 "attribute vec4 vPosition;\n"
213 "attribute vec4 vColor;\n"
214 "varying vec4 vFillColor;\n"
215 "void main() {\n"
216 " gl_Position = vPosition;\n"
217 " vFillColor = vColor;\n"
218 "}\n";
219 const GLchar *fragmentShaderStr =
220 "precision mediump float;\n"
221 "varying vec4 vFillColor;\n"
222 "void main() {\n"
223 " gl_FragColor = vFillColor;\n"
224 "}\n";
225 GLint vertexShader, fragmentShader, program, status;
226
227 vertexShader = glCreateShader(GL_VERTEX_SHADER);
228 if (!vertexShader) {
229 fprintf(stderr, "Failed to create vertex shader. Error=0x%x\n", glGetError());
230 return;
231 }
232 glShaderSource(vertexShader, 1, &vertexShaderStr, NULL);
233 glCompileShader(vertexShader);
234 glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
235 if (!status) {
236 fprintf(stderr, "Failed to compile vertex shader. Error=0x%x\n", glGetError());
237 return;
238 }
239
240 fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
241 if (!fragmentShader) {
242 fprintf(stderr, "Failed to create fragment shader. Error=0x%x\n", glGetError());
243 return;
244 }
245 glShaderSource(fragmentShader, 1, &fragmentShaderStr, NULL);
246 glCompileShader(fragmentShader);
247 glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
248 if (!status) {
249 fprintf(stderr, "Failed to compile fragment shader. Error=0x%x\n", glGetError());
250 return;
251 }
252
253
254 program = glCreateProgram();
255 if (!program) {
256 fprintf(stderr, "Failed to create program.\n");
257 return;
258 }
259 glAttachShader(program, vertexShader);
260 glAttachShader(program, fragmentShader);
261 glBindAttribLocation(program, 0, "vPosition");
262 glBindAttribLocation(program, 1, "vColor");
263 glLinkProgram(program);
264 glGetShaderiv(program, GL_LINK_STATUS, &status);
265 if (!status) {
266 fprintf(stderr, "Failed to link program.\n");
267 return;
268 }
269
Haixia Shi4652b8c2014-11-19 17:55:38 -0800270 int fb_idx = 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800271 for (i = 0; i <= 500; i++) {
Haixia Shi4652b8c2014-11-19 17:55:38 -0800272 int waiting_for_flip = 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800273 GLfloat verts[] = {
274 0.0f, -0.5f, 0.0f,
275 -0.5f, 0.5f, 0.0f,
276 0.5f, 0.5f, 0.0f
277 };
278 GLfloat colors[] = {
279 1.0f, 0.0f, 0.0f, 1.0f,
280 0.0f, 1.0f, 0.0f, 1.0f,
281 0.0f, 0.0f, 1.0f, 1.0f
282 };
283
Haixia Shi4652b8c2014-11-19 17:55:38 -0800284 glBindFramebuffer(GL_FRAMEBUFFER, ctx->gl_fb[fb_idx]);
285 glViewport(0, 0,(GLint) ctx->mode->hdisplay,
286 (GLint) ctx->mode->vdisplay);
287
Haixia Shie04ddfd2014-11-11 19:14:32 -0800288 glClearColor(f(i), f(i + 80), f(i + 160), 0.0f);
289 glClear(GL_COLOR_BUFFER_BIT);
290
291 glUseProgram(program);
292 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, verts);
293 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, colors);
294 glEnableVertexAttribArray(0);
295 glEnableVertexAttribArray(1);
296 glDrawArrays(GL_TRIANGLES, 0, 3);
297
298 usleep(1e6 / 120); /* 120 Hz */
299 glFinish();
Haixia Shibc4d0a02014-12-01 14:25:54 -0800300 drmModePageFlip(ctx->drm_card_fd, ctx->encoder->crtc_id,
Haixia Shi4652b8c2014-11-19 17:55:38 -0800301 ctx->drm_fb_id[fb_idx],
302 DRM_MODE_PAGE_FLIP_EVENT,
303 &waiting_for_flip);
304
305 while (waiting_for_flip) {
306 drmEventContext evctx = {
307 .version = DRM_EVENT_CONTEXT_VERSION,
308 .page_flip_handler = page_flip_handler,
309 };
310
311 fd_set fds;
312 FD_ZERO(&fds);
313 FD_SET(0, &fds);
Haixia Shibc4d0a02014-12-01 14:25:54 -0800314 FD_SET(ctx->drm_card_fd, &fds);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800315
Haixia Shibc4d0a02014-12-01 14:25:54 -0800316 int ret = select(ctx->drm_card_fd + 1, &fds, NULL, NULL, NULL);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800317 if (ret < 0) {
318 fprintf(stderr, "select err: %s\n", strerror(errno));
319 return;
320 } else if (ret == 0) {
321 fprintf(stderr, "select timeout\n");
322 return;
323 } else if (FD_ISSET(0, &fds)) {
324 fprintf(stderr, "user interrupted\n");
325 return;
326 }
Haixia Shibc4d0a02014-12-01 14:25:54 -0800327 drmHandleEvent(ctx->drm_card_fd, &evctx);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800328 }
329 fb_idx = fb_idx ^ 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800330 }
331
332 glDeleteProgram(program);
333}
334
335int main(int argc, char ** argv)
336{
337 int ret = 0;
338 struct context ctx;
339 EGLint egl_major, egl_minor;
340 const char * extensions;
341 uint32_t bo_handle;
342 uint32_t bo_stride;
343 int drm_prime_fd;
344 EGLint num_configs;
345 EGLConfig egl_config;
Haixia Shi4652b8c2014-11-19 17:55:38 -0800346 size_t i;
Haixia Shibc4d0a02014-12-01 14:25:54 -0800347 char* egl_card_path = "/dev/dri/card0";
348 char* drm_card_path = "/dev/dri/card1";
349 bool single_card = false;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800350
351 const EGLint config_attribs[] = {
352 EGL_RED_SIZE, 1,
353 EGL_GREEN_SIZE, 1,
354 EGL_BLUE_SIZE, 1,
355 EGL_DEPTH_SIZE, 1,
356 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
357 EGL_NONE
358 };
359 const EGLint context_attribs[] = {
360 EGL_CONTEXT_CLIENT_VERSION, 2,
361 EGL_NONE
362 };
363
Haixia Shibc4d0a02014-12-01 14:25:54 -0800364 if (argc >= 2) {
365 drm_card_path = argv[1];
366 if (strcmp(egl_card_path, drm_card_path) == 0) {
367 single_card = true;
368 }
369 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800370
Haixia Shibc4d0a02014-12-01 14:25:54 -0800371 ctx.drm_card_fd = open(drm_card_path, O_RDWR);
372 if (ctx.drm_card_fd < 0) {
373 fprintf(stderr, "failed to open %s\n", drm_card_path);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800374 ret = 1;
375 goto fail;
376 }
377
Haixia Shibc4d0a02014-12-01 14:25:54 -0800378 ctx.drm_gbm = gbm_create_device(ctx.drm_card_fd);
379 if (!ctx.drm_gbm) {
380 fprintf(stderr, "failed to create gbm device on %s\n", drm_card_path);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800381 ret = 1;
Haixia Shibc4d0a02014-12-01 14:25:54 -0800382 goto close_drm_card;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800383 }
384
Haixia Shibc4d0a02014-12-01 14:25:54 -0800385 if (single_card) {
386 ctx.egl_card_fd = ctx.drm_card_fd;
387 ctx.egl_gbm = ctx.drm_gbm;
388 } else {
389 ctx.egl_card_fd = open(egl_card_path, O_RDWR);
390 if (ctx.egl_card_fd < 0) {
391 fprintf(stderr, "failed to open %s\n", egl_card_path);
392 ret = 1;
393 goto destroy_drm_gbm;
394 }
395
396 ctx.egl_gbm = gbm_create_device(ctx.egl_card_fd);
397 if (!ctx.egl_gbm) {
398 fprintf(stderr, "failed to create gbm device on %s\n", egl_card_path);
399 ret = 1;
400 goto close_egl_card;
401 }
402 }
403
404 ctx.egl_display = eglGetDisplay((EGLNativeDisplayType)(intptr_t)ctx.egl_card_fd);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800405 if (ctx.egl_display == EGL_NO_DISPLAY) {
406 fprintf(stderr, "failed to get egl display\n");
407 ret = 1;
Haixia Shibc4d0a02014-12-01 14:25:54 -0800408 goto destroy_egl_gbm;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800409 }
410
411 if (!eglInitialize(ctx.egl_display, &egl_major, &egl_minor)) {
412 fprintf(stderr, "failed to initialize egl: %s\n",
413 get_egl_error());
414 ret = 1;
415 goto terminate_display;
416 }
417
418 fprintf(stderr, "EGL %d.%d\n", egl_major, egl_minor);
419 fprintf(stderr, "EGL %s\n",
420 eglQueryString(ctx.egl_display, EGL_VERSION));
421
422 extensions = eglQueryString(ctx.egl_display, EGL_EXTENSIONS);
423 fprintf(stderr, "EGL Extensions: %s\n", extensions);
424
425 if (!setup_drm(&ctx)) {
426 fprintf(stderr, "failed to setup drm resources\n");
427 ret = 1;
428 goto terminate_display;
429 }
430
431 fprintf(stderr, "display size: %dx%d\n",
432 ctx.mode->hdisplay, ctx.mode->vdisplay);
433
434 if (!eglChooseConfig(ctx.egl_display, config_attribs, NULL, 0,
435 &num_configs)) {
436 fprintf(stderr, "eglChooseConfig() failed with error: %x\n", eglGetError());
437 goto free_drm;
438 }
439 if (!eglChooseConfig(ctx.egl_display, config_attribs, &egl_config, 1,
440 &num_configs)) {
441 fprintf(stderr, "eglChooseConfig() failed with error: %x\n", eglGetError());
442 goto free_drm;
443 }
444
445 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
446 fprintf(stderr, "failed to bind OpenGL ES: %s\n",
447 get_egl_error());
448 ret = 1;
449 goto free_drm;
450 }
451
452 ctx.egl_ctx = eglCreateContext(ctx.egl_display,
453 NULL /* No framebuffer */,
454 EGL_NO_CONTEXT /* No shared context */,
455 context_attribs);
456 if (ctx.egl_ctx == EGL_NO_CONTEXT) {
457 fprintf(stderr, "failed to create OpenGL ES Context: %s\n",
458 get_egl_error());
459 ret = 1;
460 goto free_drm;
461 }
462
463 if (!eglMakeCurrent(ctx.egl_display,
464 EGL_NO_SURFACE /* No default draw surface */,
465 EGL_NO_SURFACE /* No default draw read */,
466 ctx.egl_ctx)) {
467 fprintf(stderr, "failed to make the OpenGL ES Context current: %s\n",
468 get_egl_error());
469 ret = 1;
470 goto destroy_context;
471 }
472
473 fprintf(stderr, "GL extensions: %s\n", glGetString(GL_EXTENSIONS));
474
Haixia Shi4652b8c2014-11-19 17:55:38 -0800475 glGenFramebuffers(BUFFERS, ctx.gl_fb);
476 glGenRenderbuffers(BUFFERS, ctx.gl_rb);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800477
Haixia Shi4652b8c2014-11-19 17:55:38 -0800478 for (i = 0; i < BUFFERS; ++i) {
Haixia Shibc4d0a02014-12-01 14:25:54 -0800479 ctx.gbm_buffer[i] = gbm_bo_create(ctx.drm_gbm,
Haixia Shi4652b8c2014-11-19 17:55:38 -0800480 ctx.mode->hdisplay, ctx.mode->vdisplay, GBM_BO_FORMAT_XRGB8888,
481 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
482
483 if (!ctx.gbm_buffer[i]) {
484 fprintf(stderr, "failed to create buffer object\n");
485 ret = 1;
486 goto free_buffers;
487 }
488
489 bo_handle = gbm_bo_get_handle(ctx.gbm_buffer[i]).u32;
490 bo_stride = gbm_bo_get_stride(ctx.gbm_buffer[i]);
491
Haixia Shibc4d0a02014-12-01 14:25:54 -0800492 if (drmPrimeHandleToFD(ctx.drm_card_fd, bo_handle, DRM_CLOEXEC,
Haixia Shi4652b8c2014-11-19 17:55:38 -0800493 &drm_prime_fd)) {
494 fprintf(stderr, "failed to turn handle into fd\n");
495 ret = 1;
496 goto free_buffers;
497 }
498
499 const EGLint khr_image_attrs[] = {
500 EGL_WIDTH, ctx.mode->hdisplay,
501 EGL_HEIGHT, ctx.mode->vdisplay,
502 EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_XRGB8888,
503 EGL_DMA_BUF_PLANE0_FD_EXT, drm_prime_fd,
504 EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
505 EGL_DMA_BUF_PLANE0_PITCH_EXT, bo_stride,
506 EGL_NONE
507 };
508
509 ctx.egl_image[i] = eglCreateImageKHR(ctx.egl_display, EGL_NO_CONTEXT,
510 EGL_LINUX_DMA_BUF_EXT, NULL, khr_image_attrs);
511 if (ctx.egl_image[i] == EGL_NO_IMAGE_KHR) {
512 fprintf(stderr, "failed to create egl image: %s\n",
513 get_egl_error());
514 ret = 1;
515 goto free_buffers;
516 }
517
518 glBindRenderbuffer(GL_RENDERBUFFER, ctx.gl_rb[i]);
519 glBindFramebuffer(GL_FRAMEBUFFER, ctx.gl_fb[i]);
520 glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, ctx.egl_image[i]);
521 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
522 GL_RENDERBUFFER, ctx.gl_rb[i]);
523
524 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) !=
525 GL_FRAMEBUFFER_COMPLETE) {
526 fprintf(stderr, "failed to create framebuffer: %s\n", get_gl_error());
527 ret = 1;
528 goto free_buffers;
529 }
530
Haixia Shibc4d0a02014-12-01 14:25:54 -0800531 ret = drmModeAddFB(ctx.drm_card_fd, ctx.mode->hdisplay, ctx.mode->vdisplay,
Haixia Shi4652b8c2014-11-19 17:55:38 -0800532 24, 32, bo_stride, bo_handle, &ctx.drm_fb_id[i]);
533
534 if (ret) {
535 fprintf(stderr, "failed to add fb\n");
536 ret = 1;
537 goto free_buffers;
538 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800539 }
540
Haixia Shibc4d0a02014-12-01 14:25:54 -0800541 if (drmModeSetCrtc(ctx.drm_card_fd, ctx.encoder->crtc_id, ctx.drm_fb_id[0],
Haixia Shie04ddfd2014-11-11 19:14:32 -0800542 0, 0, &ctx.connector->connector_id, 1, ctx.mode)) {
543 fprintf(stderr, "failed to set CRTC\n");
544 ret = 1;
Haixia Shi4652b8c2014-11-19 17:55:38 -0800545 goto free_buffers;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800546 }
547
548 draw(&ctx);
549
Haixia Shi4652b8c2014-11-19 17:55:38 -0800550free_buffers:
Haixia Shie04ddfd2014-11-11 19:14:32 -0800551 glBindRenderbuffer(GL_RENDERBUFFER, 0);
552 glBindFramebuffer(GL_FRAMEBUFFER, 0);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800553 for (i = 0; i < BUFFERS; ++i) {
554 if (ctx.drm_fb_id[i])
Haixia Shibc4d0a02014-12-01 14:25:54 -0800555 drmModeRmFB(ctx.drm_card_fd, ctx.drm_fb_id[i]);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800556 if (ctx.egl_image[i])
557 eglDestroyImageKHR(ctx.egl_display, ctx.egl_image[i]);
558 if (ctx.gl_fb[i])
559 glDeleteFramebuffers(1, &ctx.gl_fb[i]);
560 if (ctx.gl_rb[i])
561 glDeleteRenderbuffers(1, &ctx.gl_rb[i]);
562 if (ctx.gbm_buffer[i])
563 gbm_bo_destroy(ctx.gbm_buffer[i]);
564 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800565destroy_context:
566 eglDestroyContext(ctx.egl_display, ctx.egl_ctx);
567free_drm:
568 drmModeFreeConnector(ctx.connector);
569 drmModeFreeEncoder(ctx.encoder);
570terminate_display:
571 eglTerminate(ctx.egl_display);
Haixia Shibc4d0a02014-12-01 14:25:54 -0800572destroy_egl_gbm:
573 if (!single_card)
574 gbm_device_destroy(ctx.egl_gbm);
575close_egl_card:
576 if (!single_card)
577 close(ctx.egl_card_fd);
578destroy_drm_gbm:
579 gbm_device_destroy(ctx.drm_gbm);
580close_drm_card:
581 close(ctx.drm_card_fd);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800582fail:
583 return ret;
584}