blob: 93a03c3682ce2a18472e66c2e6d51cb44857a006 [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
Lauri Peltonen763ca462014-12-17 12:22:21 -080085static bool has_extension(const char *extension, const char *extensions)
86{
87 const char *start, *where, *terminator;
88 start = extensions;
89 for (;;) {
90 where = (char *)strstr((const char *)start, extension);
91 if (!where)
92 break;
93 terminator = where + strlen(extension);
94 if (where == start || *(where - 1) == ' ')
95 if (*terminator == ' ' || *terminator == '\0')
96 return true;
97 start = terminator;
98 }
99 return false;
100}
101
Haixia Shi4652b8c2014-11-19 17:55:38 -0800102#define BUFFERS 2
103
Haixia Shie04ddfd2014-11-11 19:14:32 -0800104struct context {
Haixia Shibc4d0a02014-12-01 14:25:54 -0800105 int drm_card_fd;
Haixia Shibc4d0a02014-12-01 14:25:54 -0800106 struct gbm_device *drm_gbm;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800107
108 EGLDisplay egl_display;
109 EGLContext egl_ctx;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800110
111 drmModeConnector * connector;
112 drmModeEncoder * encoder;
113 drmModeModeInfo * mode;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800114
Haixia Shi4652b8c2014-11-19 17:55:38 -0800115 struct gbm_bo * gbm_buffer[BUFFERS];
116 EGLImageKHR egl_image[BUFFERS];
117 uint32_t drm_fb_id[BUFFERS];
118 unsigned gl_fb[BUFFERS];
119 unsigned gl_rb[BUFFERS];
Haixia Shie04ddfd2014-11-11 19:14:32 -0800120
121};
122
123bool setup_drm(struct context * ctx)
124{
Haixia Shibc4d0a02014-12-01 14:25:54 -0800125 int fd = ctx->drm_card_fd;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800126 drmModeRes *resources = NULL;
127 drmModeConnector *connector = NULL;
128 drmModeEncoder *encoder = NULL;
129 int i, j;
130
131 resources = drmModeGetResources(fd);
132 if (!resources) {
133 fprintf(stderr, "drmModeGetResources failed\n");
134 return false;
135 }
136
137 for (i = 0; i < resources->count_connectors; i++) {
138 connector = drmModeGetConnector(fd, resources->connectors[i]);
139 if (connector == NULL)
140 continue;
141
142 if (connector->connection == DRM_MODE_CONNECTED &&
143 connector->count_modes > 0)
144 break;
145
146 drmModeFreeConnector(connector);
147 }
148
149 if (i == resources->count_connectors) {
150 fprintf(stderr, "no currently active connector found\n");
151 return false;
152 }
153
154 for (i = 0; i < resources->count_encoders; i++) {
155 encoder = drmModeGetEncoder(fd, resources->encoders[i]);
156
157 if (encoder == NULL)
158 continue;
159
160 for (j = 0; j < connector->count_encoders; j++) {
161 if (encoder->encoder_id == connector->encoders[j])
162 break;
163 }
164
165 if (j == connector->count_encoders) {
166 drmModeFreeEncoder(encoder);
167 continue;
168 }
169
170 break;
171 }
172
173 if (i == resources->count_encoders) {
174 fprintf(stderr, "no supported encoder found\n");
175 return false;
176 }
177
178 for (i = 0; i < resources->count_crtcs; i++) {
179 if (encoder->possible_crtcs & (1 << i)) {
180 encoder->crtc_id = resources->crtcs[i];
181 break;
182 }
183 }
184
185 if (i == resources->count_crtcs) {
186 fprintf(stderr, "no possible crtc found\n");
187 return false;
188 }
189
190 ctx->connector = connector;
191 ctx->encoder = encoder;
192 ctx->mode = &connector->modes[0];
193
194 return true;
195}
196
197float f(int i) {
198 int a = i % 40;
199 int b = (i / 40) % 6;
200 switch (b) {
201 case 0:
202 case 1:
203 return 0.0f;
204 case 3:
205 case 4:
206 return 1.0f;
207 case 2:
208 return (a / 40.0f);
209 case 5:
210 return 1.0f - (a / 40.0f);
211 default:
212 return 0.0f;
213 }
214}
215
Haixia Shi4652b8c2014-11-19 17:55:38 -0800216static void page_flip_handler(int fd, unsigned int frame, unsigned int sec,
217 unsigned int usec, void *data)
218{
219 int *waiting_for_flip = data;
220 *waiting_for_flip = 0;
221}
222
Haixia Shie04ddfd2014-11-11 19:14:32 -0800223void draw(struct context * ctx)
224{
225 int i;
226 const GLchar *vertexShaderStr =
227 "attribute vec4 vPosition;\n"
228 "attribute vec4 vColor;\n"
229 "varying vec4 vFillColor;\n"
230 "void main() {\n"
231 " gl_Position = vPosition;\n"
232 " vFillColor = vColor;\n"
233 "}\n";
234 const GLchar *fragmentShaderStr =
235 "precision mediump float;\n"
236 "varying vec4 vFillColor;\n"
237 "void main() {\n"
238 " gl_FragColor = vFillColor;\n"
239 "}\n";
240 GLint vertexShader, fragmentShader, program, status;
241
242 vertexShader = glCreateShader(GL_VERTEX_SHADER);
243 if (!vertexShader) {
244 fprintf(stderr, "Failed to create vertex shader. Error=0x%x\n", glGetError());
245 return;
246 }
247 glShaderSource(vertexShader, 1, &vertexShaderStr, NULL);
248 glCompileShader(vertexShader);
249 glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
250 if (!status) {
251 fprintf(stderr, "Failed to compile vertex shader. Error=0x%x\n", glGetError());
252 return;
253 }
254
255 fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
256 if (!fragmentShader) {
257 fprintf(stderr, "Failed to create fragment shader. Error=0x%x\n", glGetError());
258 return;
259 }
260 glShaderSource(fragmentShader, 1, &fragmentShaderStr, NULL);
261 glCompileShader(fragmentShader);
262 glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
263 if (!status) {
264 fprintf(stderr, "Failed to compile fragment shader. Error=0x%x\n", glGetError());
265 return;
266 }
267
268
269 program = glCreateProgram();
270 if (!program) {
271 fprintf(stderr, "Failed to create program.\n");
272 return;
273 }
274 glAttachShader(program, vertexShader);
275 glAttachShader(program, fragmentShader);
276 glBindAttribLocation(program, 0, "vPosition");
277 glBindAttribLocation(program, 1, "vColor");
278 glLinkProgram(program);
279 glGetShaderiv(program, GL_LINK_STATUS, &status);
280 if (!status) {
281 fprintf(stderr, "Failed to link program.\n");
282 return;
283 }
284
Haixia Shi4652b8c2014-11-19 17:55:38 -0800285 int fb_idx = 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800286 for (i = 0; i <= 500; i++) {
Haixia Shi4652b8c2014-11-19 17:55:38 -0800287 int waiting_for_flip = 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800288 GLfloat verts[] = {
289 0.0f, -0.5f, 0.0f,
290 -0.5f, 0.5f, 0.0f,
291 0.5f, 0.5f, 0.0f
292 };
293 GLfloat colors[] = {
294 1.0f, 0.0f, 0.0f, 1.0f,
295 0.0f, 1.0f, 0.0f, 1.0f,
296 0.0f, 0.0f, 1.0f, 1.0f
297 };
298
Haixia Shi4652b8c2014-11-19 17:55:38 -0800299 glBindFramebuffer(GL_FRAMEBUFFER, ctx->gl_fb[fb_idx]);
300 glViewport(0, 0,(GLint) ctx->mode->hdisplay,
301 (GLint) ctx->mode->vdisplay);
302
Haixia Shie04ddfd2014-11-11 19:14:32 -0800303 glClearColor(f(i), f(i + 80), f(i + 160), 0.0f);
304 glClear(GL_COLOR_BUFFER_BIT);
305
306 glUseProgram(program);
307 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, verts);
308 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, colors);
309 glEnableVertexAttribArray(0);
310 glEnableVertexAttribArray(1);
311 glDrawArrays(GL_TRIANGLES, 0, 3);
312
313 usleep(1e6 / 120); /* 120 Hz */
314 glFinish();
Haixia Shibc4d0a02014-12-01 14:25:54 -0800315 drmModePageFlip(ctx->drm_card_fd, ctx->encoder->crtc_id,
Haixia Shi4652b8c2014-11-19 17:55:38 -0800316 ctx->drm_fb_id[fb_idx],
317 DRM_MODE_PAGE_FLIP_EVENT,
318 &waiting_for_flip);
319
320 while (waiting_for_flip) {
321 drmEventContext evctx = {
322 .version = DRM_EVENT_CONTEXT_VERSION,
323 .page_flip_handler = page_flip_handler,
324 };
325
326 fd_set fds;
327 FD_ZERO(&fds);
328 FD_SET(0, &fds);
Haixia Shibc4d0a02014-12-01 14:25:54 -0800329 FD_SET(ctx->drm_card_fd, &fds);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800330
Haixia Shibc4d0a02014-12-01 14:25:54 -0800331 int ret = select(ctx->drm_card_fd + 1, &fds, NULL, NULL, NULL);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800332 if (ret < 0) {
333 fprintf(stderr, "select err: %s\n", strerror(errno));
334 return;
335 } else if (ret == 0) {
336 fprintf(stderr, "select timeout\n");
337 return;
338 } else if (FD_ISSET(0, &fds)) {
339 fprintf(stderr, "user interrupted\n");
340 return;
341 }
Haixia Shibc4d0a02014-12-01 14:25:54 -0800342 drmHandleEvent(ctx->drm_card_fd, &evctx);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800343 }
344 fb_idx = fb_idx ^ 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800345 }
346
347 glDeleteProgram(program);
348}
349
350int main(int argc, char ** argv)
351{
352 int ret = 0;
353 struct context ctx;
354 EGLint egl_major, egl_minor;
Lauri Peltonen763ca462014-12-17 12:22:21 -0800355 const char * egl_extensions;
356 const char * gl_extensions;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800357 uint32_t bo_handle;
358 uint32_t bo_stride;
359 int drm_prime_fd;
360 EGLint num_configs;
361 EGLConfig egl_config;
Haixia Shi4652b8c2014-11-19 17:55:38 -0800362 size_t i;
Lauri Peltonen71cdf952014-12-17 12:13:24 -0800363 char* drm_card_path = "/dev/dri/card0";
Lauri Peltonen763ca462014-12-17 12:22:21 -0800364 PFNEGLCREATEIMAGEKHRPROC pfeglCreateImageKHR;
365 PFNEGLDESTROYIMAGEKHRPROC pfeglDestroyImageKHR;
366 PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC pfglEGLImageTargetRenderbufferStorageOES;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800367
368 const EGLint config_attribs[] = {
369 EGL_RED_SIZE, 1,
370 EGL_GREEN_SIZE, 1,
371 EGL_BLUE_SIZE, 1,
372 EGL_DEPTH_SIZE, 1,
373 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
374 EGL_NONE
375 };
376 const EGLint context_attribs[] = {
377 EGL_CONTEXT_CLIENT_VERSION, 2,
378 EGL_NONE
379 };
380
Lauri Peltonen71cdf952014-12-17 12:13:24 -0800381 if (argc >= 2)
Haixia Shibc4d0a02014-12-01 14:25:54 -0800382 drm_card_path = argv[1];
Haixia Shie04ddfd2014-11-11 19:14:32 -0800383
Haixia Shibc4d0a02014-12-01 14:25:54 -0800384 ctx.drm_card_fd = open(drm_card_path, O_RDWR);
385 if (ctx.drm_card_fd < 0) {
386 fprintf(stderr, "failed to open %s\n", drm_card_path);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800387 ret = 1;
388 goto fail;
389 }
390
Haixia Shibc4d0a02014-12-01 14:25:54 -0800391 ctx.drm_gbm = gbm_create_device(ctx.drm_card_fd);
392 if (!ctx.drm_gbm) {
393 fprintf(stderr, "failed to create gbm device on %s\n", drm_card_path);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800394 ret = 1;
Haixia Shibc4d0a02014-12-01 14:25:54 -0800395 goto close_drm_card;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800396 }
397
Lauri Peltonen71cdf952014-12-17 12:13:24 -0800398 ctx.egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800399 if (ctx.egl_display == EGL_NO_DISPLAY) {
400 fprintf(stderr, "failed to get egl display\n");
401 ret = 1;
Lauri Peltonen71cdf952014-12-17 12:13:24 -0800402 goto destroy_drm_gbm;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800403 }
404
405 if (!eglInitialize(ctx.egl_display, &egl_major, &egl_minor)) {
406 fprintf(stderr, "failed to initialize egl: %s\n",
407 get_egl_error());
408 ret = 1;
409 goto terminate_display;
410 }
411
412 fprintf(stderr, "EGL %d.%d\n", egl_major, egl_minor);
413 fprintf(stderr, "EGL %s\n",
414 eglQueryString(ctx.egl_display, EGL_VERSION));
415
Lauri Peltonen763ca462014-12-17 12:22:21 -0800416 egl_extensions = eglQueryString(ctx.egl_display, EGL_EXTENSIONS);
417 fprintf(stderr, "EGL Extensions: %s\n", egl_extensions);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800418
419 if (!setup_drm(&ctx)) {
420 fprintf(stderr, "failed to setup drm resources\n");
421 ret = 1;
422 goto terminate_display;
423 }
424
425 fprintf(stderr, "display size: %dx%d\n",
426 ctx.mode->hdisplay, ctx.mode->vdisplay);
427
428 if (!eglChooseConfig(ctx.egl_display, config_attribs, NULL, 0,
429 &num_configs)) {
430 fprintf(stderr, "eglChooseConfig() failed with error: %x\n", eglGetError());
431 goto free_drm;
432 }
433 if (!eglChooseConfig(ctx.egl_display, config_attribs, &egl_config, 1,
434 &num_configs)) {
435 fprintf(stderr, "eglChooseConfig() failed with error: %x\n", eglGetError());
436 goto free_drm;
437 }
438
439 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
440 fprintf(stderr, "failed to bind OpenGL ES: %s\n",
441 get_egl_error());
442 ret = 1;
443 goto free_drm;
444 }
445
446 ctx.egl_ctx = eglCreateContext(ctx.egl_display,
Lauri Peltonen44af28d2014-12-17 12:19:54 -0800447 egl_config,
Haixia Shie04ddfd2014-11-11 19:14:32 -0800448 EGL_NO_CONTEXT /* No shared context */,
449 context_attribs);
450 if (ctx.egl_ctx == EGL_NO_CONTEXT) {
451 fprintf(stderr, "failed to create OpenGL ES Context: %s\n",
452 get_egl_error());
453 ret = 1;
454 goto free_drm;
455 }
456
457 if (!eglMakeCurrent(ctx.egl_display,
458 EGL_NO_SURFACE /* No default draw surface */,
459 EGL_NO_SURFACE /* No default draw read */,
460 ctx.egl_ctx)) {
461 fprintf(stderr, "failed to make the OpenGL ES Context current: %s\n",
462 get_egl_error());
463 ret = 1;
464 goto destroy_context;
465 }
466
Lauri Peltonen763ca462014-12-17 12:22:21 -0800467 gl_extensions = (const char *)glGetString(GL_EXTENSIONS);
468 fprintf(stderr, "GL extensions: %s\n", gl_extensions);
469
470 if (!has_extension("EGL_EXT_image_dma_buf_import", egl_extensions)) {
471 fprintf(stderr, "EGL_EXT_image_dma_buf_import extension not supported\n");
472 ret = 1;
473 goto destroy_context;
474 }
475
476 if (!has_extension("GL_OES_EGL_image", gl_extensions)) {
477 fprintf(stderr, "GL_OES_EGL_image extension not supported\n");
478 ret = 1;
479 goto destroy_context;
480 }
481
482 pfeglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");
483 pfeglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR");
484 pfglEGLImageTargetRenderbufferStorageOES = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)eglGetProcAddress("glEGLImageTargetRenderbufferStorageOES");
485 if (!pfeglCreateImageKHR || !pfeglDestroyImageKHR || !pfglEGLImageTargetRenderbufferStorageOES) {
486 fprintf(stderr, "eglGetProcAddress returned NULL for a required extension entry point\n");
487 ret = 1;
488 goto destroy_context;
489 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800490
Haixia Shi4652b8c2014-11-19 17:55:38 -0800491 glGenFramebuffers(BUFFERS, ctx.gl_fb);
492 glGenRenderbuffers(BUFFERS, ctx.gl_rb);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800493
Haixia Shi4652b8c2014-11-19 17:55:38 -0800494 for (i = 0; i < BUFFERS; ++i) {
Haixia Shibc4d0a02014-12-01 14:25:54 -0800495 ctx.gbm_buffer[i] = gbm_bo_create(ctx.drm_gbm,
Haixia Shi4652b8c2014-11-19 17:55:38 -0800496 ctx.mode->hdisplay, ctx.mode->vdisplay, GBM_BO_FORMAT_XRGB8888,
497 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
498
499 if (!ctx.gbm_buffer[i]) {
500 fprintf(stderr, "failed to create buffer object\n");
501 ret = 1;
502 goto free_buffers;
503 }
504
505 bo_handle = gbm_bo_get_handle(ctx.gbm_buffer[i]).u32;
506 bo_stride = gbm_bo_get_stride(ctx.gbm_buffer[i]);
507
Zach Reizner0feb1f12015-01-09 13:38:57 -0800508 drm_prime_fd = gbm_bo_get_fd(ctx.gbm_buffer[i]);
509
510 if (drm_prime_fd < 0) {
Haixia Shi4652b8c2014-11-19 17:55:38 -0800511 fprintf(stderr, "failed to turn handle into fd\n");
512 ret = 1;
513 goto free_buffers;
514 }
515
516 const EGLint khr_image_attrs[] = {
517 EGL_WIDTH, ctx.mode->hdisplay,
518 EGL_HEIGHT, ctx.mode->vdisplay,
519 EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_XRGB8888,
520 EGL_DMA_BUF_PLANE0_FD_EXT, drm_prime_fd,
521 EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
522 EGL_DMA_BUF_PLANE0_PITCH_EXT, bo_stride,
523 EGL_NONE
524 };
525
Lauri Peltonen763ca462014-12-17 12:22:21 -0800526 ctx.egl_image[i] = pfeglCreateImageKHR(ctx.egl_display, EGL_NO_CONTEXT,
Haixia Shi4652b8c2014-11-19 17:55:38 -0800527 EGL_LINUX_DMA_BUF_EXT, NULL, khr_image_attrs);
528 if (ctx.egl_image[i] == EGL_NO_IMAGE_KHR) {
529 fprintf(stderr, "failed to create egl image: %s\n",
530 get_egl_error());
531 ret = 1;
532 goto free_buffers;
533 }
534
535 glBindRenderbuffer(GL_RENDERBUFFER, ctx.gl_rb[i]);
536 glBindFramebuffer(GL_FRAMEBUFFER, ctx.gl_fb[i]);
Lauri Peltonen763ca462014-12-17 12:22:21 -0800537 pfglEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, ctx.egl_image[i]);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800538 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
539 GL_RENDERBUFFER, ctx.gl_rb[i]);
540
541 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) !=
542 GL_FRAMEBUFFER_COMPLETE) {
543 fprintf(stderr, "failed to create framebuffer: %s\n", get_gl_error());
544 ret = 1;
545 goto free_buffers;
546 }
547
Haixia Shibc4d0a02014-12-01 14:25:54 -0800548 ret = drmModeAddFB(ctx.drm_card_fd, ctx.mode->hdisplay, ctx.mode->vdisplay,
Haixia Shi4652b8c2014-11-19 17:55:38 -0800549 24, 32, bo_stride, bo_handle, &ctx.drm_fb_id[i]);
550
551 if (ret) {
552 fprintf(stderr, "failed to add fb\n");
553 ret = 1;
554 goto free_buffers;
555 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800556 }
557
Haixia Shibc4d0a02014-12-01 14:25:54 -0800558 if (drmModeSetCrtc(ctx.drm_card_fd, ctx.encoder->crtc_id, ctx.drm_fb_id[0],
Haixia Shie04ddfd2014-11-11 19:14:32 -0800559 0, 0, &ctx.connector->connector_id, 1, ctx.mode)) {
560 fprintf(stderr, "failed to set CRTC\n");
561 ret = 1;
Haixia Shi4652b8c2014-11-19 17:55:38 -0800562 goto free_buffers;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800563 }
564
565 draw(&ctx);
566
Haixia Shi4652b8c2014-11-19 17:55:38 -0800567free_buffers:
Haixia Shie04ddfd2014-11-11 19:14:32 -0800568 glBindRenderbuffer(GL_RENDERBUFFER, 0);
569 glBindFramebuffer(GL_FRAMEBUFFER, 0);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800570 for (i = 0; i < BUFFERS; ++i) {
571 if (ctx.drm_fb_id[i])
Haixia Shibc4d0a02014-12-01 14:25:54 -0800572 drmModeRmFB(ctx.drm_card_fd, ctx.drm_fb_id[i]);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800573 if (ctx.egl_image[i])
Lauri Peltonen763ca462014-12-17 12:22:21 -0800574 pfeglDestroyImageKHR(ctx.egl_display, ctx.egl_image[i]);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800575 if (ctx.gl_fb[i])
576 glDeleteFramebuffers(1, &ctx.gl_fb[i]);
577 if (ctx.gl_rb[i])
578 glDeleteRenderbuffers(1, &ctx.gl_rb[i]);
579 if (ctx.gbm_buffer[i])
580 gbm_bo_destroy(ctx.gbm_buffer[i]);
581 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800582destroy_context:
583 eglDestroyContext(ctx.egl_display, ctx.egl_ctx);
584free_drm:
585 drmModeFreeConnector(ctx.connector);
586 drmModeFreeEncoder(ctx.encoder);
587terminate_display:
588 eglTerminate(ctx.egl_display);
Haixia Shibc4d0a02014-12-01 14:25:54 -0800589destroy_drm_gbm:
590 gbm_device_destroy(ctx.drm_gbm);
591close_drm_card:
592 close(ctx.drm_card_fd);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800593fail:
594 return ret;
595}