blob: 2230be8e4beb20715441f21453a4a7f7f870eb95 [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
Lauri Peltonen95226da2014-12-18 16:39:54 -080027static const char * get_gl_error(void)
Haixia Shie04ddfd2014-11-11 19:14:32 -080028{
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
Lauri Peltonen95226da2014-12-18 16:39:54 -080047static const char * get_egl_error(void)
Haixia Shie04ddfd2014-11-11 19:14:32 -080048{
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
Lauri Peltonen95226da2014-12-18 16:39:54 -0800123static bool setup_drm(struct context * ctx)
Haixia Shie04ddfd2014-11-11 19:14:32 -0800124{
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
Lauri Peltonen95226da2014-12-18 16:39:54 -0800197static float f(int i)
198{
Haixia Shie04ddfd2014-11-11 19:14:32 -0800199 int a = i % 40;
200 int b = (i / 40) % 6;
201 switch (b) {
202 case 0:
203 case 1:
204 return 0.0f;
205 case 3:
206 case 4:
207 return 1.0f;
208 case 2:
209 return (a / 40.0f);
210 case 5:
211 return 1.0f - (a / 40.0f);
212 default:
213 return 0.0f;
214 }
215}
216
Haixia Shi4652b8c2014-11-19 17:55:38 -0800217static void page_flip_handler(int fd, unsigned int frame, unsigned int sec,
218 unsigned int usec, void *data)
219{
220 int *waiting_for_flip = data;
221 *waiting_for_flip = 0;
222}
223
Lauri Peltonen95226da2014-12-18 16:39:54 -0800224static void draw(struct context * ctx)
Haixia Shie04ddfd2014-11-11 19:14:32 -0800225{
226 int i;
227 const GLchar *vertexShaderStr =
228 "attribute vec4 vPosition;\n"
229 "attribute vec4 vColor;\n"
230 "varying vec4 vFillColor;\n"
231 "void main() {\n"
232 " gl_Position = vPosition;\n"
233 " vFillColor = vColor;\n"
234 "}\n";
235 const GLchar *fragmentShaderStr =
236 "precision mediump float;\n"
237 "varying vec4 vFillColor;\n"
238 "void main() {\n"
239 " gl_FragColor = vFillColor;\n"
240 "}\n";
241 GLint vertexShader, fragmentShader, program, status;
242
243 vertexShader = glCreateShader(GL_VERTEX_SHADER);
244 if (!vertexShader) {
245 fprintf(stderr, "Failed to create vertex shader. Error=0x%x\n", glGetError());
246 return;
247 }
248 glShaderSource(vertexShader, 1, &vertexShaderStr, NULL);
249 glCompileShader(vertexShader);
250 glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
251 if (!status) {
252 fprintf(stderr, "Failed to compile vertex shader. Error=0x%x\n", glGetError());
253 return;
254 }
255
256 fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
257 if (!fragmentShader) {
258 fprintf(stderr, "Failed to create fragment shader. Error=0x%x\n", glGetError());
259 return;
260 }
261 glShaderSource(fragmentShader, 1, &fragmentShaderStr, NULL);
262 glCompileShader(fragmentShader);
263 glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
264 if (!status) {
265 fprintf(stderr, "Failed to compile fragment shader. Error=0x%x\n", glGetError());
266 return;
267 }
268
269
270 program = glCreateProgram();
271 if (!program) {
272 fprintf(stderr, "Failed to create program.\n");
273 return;
274 }
275 glAttachShader(program, vertexShader);
276 glAttachShader(program, fragmentShader);
277 glBindAttribLocation(program, 0, "vPosition");
278 glBindAttribLocation(program, 1, "vColor");
279 glLinkProgram(program);
280 glGetShaderiv(program, GL_LINK_STATUS, &status);
281 if (!status) {
282 fprintf(stderr, "Failed to link program.\n");
283 return;
284 }
285
Haixia Shi4652b8c2014-11-19 17:55:38 -0800286 int fb_idx = 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800287 for (i = 0; i <= 500; i++) {
Haixia Shi4652b8c2014-11-19 17:55:38 -0800288 int waiting_for_flip = 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800289 GLfloat verts[] = {
290 0.0f, -0.5f, 0.0f,
291 -0.5f, 0.5f, 0.0f,
292 0.5f, 0.5f, 0.0f
293 };
294 GLfloat colors[] = {
295 1.0f, 0.0f, 0.0f, 1.0f,
296 0.0f, 1.0f, 0.0f, 1.0f,
297 0.0f, 0.0f, 1.0f, 1.0f
298 };
299
Haixia Shi4652b8c2014-11-19 17:55:38 -0800300 glBindFramebuffer(GL_FRAMEBUFFER, ctx->gl_fb[fb_idx]);
301 glViewport(0, 0,(GLint) ctx->mode->hdisplay,
302 (GLint) ctx->mode->vdisplay);
303
Haixia Shie04ddfd2014-11-11 19:14:32 -0800304 glClearColor(f(i), f(i + 80), f(i + 160), 0.0f);
305 glClear(GL_COLOR_BUFFER_BIT);
306
307 glUseProgram(program);
308 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, verts);
309 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, colors);
310 glEnableVertexAttribArray(0);
311 glEnableVertexAttribArray(1);
312 glDrawArrays(GL_TRIANGLES, 0, 3);
313
314 usleep(1e6 / 120); /* 120 Hz */
315 glFinish();
Haixia Shibc4d0a02014-12-01 14:25:54 -0800316 drmModePageFlip(ctx->drm_card_fd, ctx->encoder->crtc_id,
Haixia Shi4652b8c2014-11-19 17:55:38 -0800317 ctx->drm_fb_id[fb_idx],
318 DRM_MODE_PAGE_FLIP_EVENT,
319 &waiting_for_flip);
320
321 while (waiting_for_flip) {
322 drmEventContext evctx = {
323 .version = DRM_EVENT_CONTEXT_VERSION,
324 .page_flip_handler = page_flip_handler,
325 };
326
327 fd_set fds;
328 FD_ZERO(&fds);
329 FD_SET(0, &fds);
Haixia Shibc4d0a02014-12-01 14:25:54 -0800330 FD_SET(ctx->drm_card_fd, &fds);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800331
Haixia Shibc4d0a02014-12-01 14:25:54 -0800332 int ret = select(ctx->drm_card_fd + 1, &fds, NULL, NULL, NULL);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800333 if (ret < 0) {
334 fprintf(stderr, "select err: %s\n", strerror(errno));
335 return;
336 } else if (ret == 0) {
337 fprintf(stderr, "select timeout\n");
338 return;
339 } else if (FD_ISSET(0, &fds)) {
340 fprintf(stderr, "user interrupted\n");
341 return;
342 }
Haixia Shibc4d0a02014-12-01 14:25:54 -0800343 drmHandleEvent(ctx->drm_card_fd, &evctx);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800344 }
345 fb_idx = fb_idx ^ 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800346 }
347
348 glDeleteProgram(program);
349}
350
351int main(int argc, char ** argv)
352{
353 int ret = 0;
354 struct context ctx;
355 EGLint egl_major, egl_minor;
Lauri Peltonen763ca462014-12-17 12:22:21 -0800356 const char * egl_extensions;
357 const char * gl_extensions;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800358 uint32_t bo_handle;
359 uint32_t bo_stride;
360 int drm_prime_fd;
361 EGLint num_configs;
362 EGLConfig egl_config;
Haixia Shi4652b8c2014-11-19 17:55:38 -0800363 size_t i;
Lauri Peltonen71cdf952014-12-17 12:13:24 -0800364 char* drm_card_path = "/dev/dri/card0";
Lauri Peltonen763ca462014-12-17 12:22:21 -0800365 PFNEGLCREATEIMAGEKHRPROC pfeglCreateImageKHR;
366 PFNEGLDESTROYIMAGEKHRPROC pfeglDestroyImageKHR;
367 PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC pfglEGLImageTargetRenderbufferStorageOES;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800368
369 const EGLint config_attribs[] = {
370 EGL_RED_SIZE, 1,
371 EGL_GREEN_SIZE, 1,
372 EGL_BLUE_SIZE, 1,
373 EGL_DEPTH_SIZE, 1,
374 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
Haixia Shicfff8b12015-05-26 11:55:39 -0700375 EGL_SURFACE_TYPE, EGL_DONT_CARE,
Haixia Shie04ddfd2014-11-11 19:14:32 -0800376 EGL_NONE
377 };
378 const EGLint context_attribs[] = {
379 EGL_CONTEXT_CLIENT_VERSION, 2,
380 EGL_NONE
381 };
382
Lauri Peltonen71cdf952014-12-17 12:13:24 -0800383 if (argc >= 2)
Haixia Shibc4d0a02014-12-01 14:25:54 -0800384 drm_card_path = argv[1];
Haixia Shie04ddfd2014-11-11 19:14:32 -0800385
Haixia Shibc4d0a02014-12-01 14:25:54 -0800386 ctx.drm_card_fd = open(drm_card_path, O_RDWR);
387 if (ctx.drm_card_fd < 0) {
388 fprintf(stderr, "failed to open %s\n", drm_card_path);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800389 ret = 1;
390 goto fail;
391 }
392
Haixia Shibc4d0a02014-12-01 14:25:54 -0800393 ctx.drm_gbm = gbm_create_device(ctx.drm_card_fd);
394 if (!ctx.drm_gbm) {
395 fprintf(stderr, "failed to create gbm device on %s\n", drm_card_path);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800396 ret = 1;
Haixia Shibc4d0a02014-12-01 14:25:54 -0800397 goto close_drm_card;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800398 }
399
Lauri Peltonen71cdf952014-12-17 12:13:24 -0800400 ctx.egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800401 if (ctx.egl_display == EGL_NO_DISPLAY) {
402 fprintf(stderr, "failed to get egl display\n");
403 ret = 1;
Lauri Peltonen71cdf952014-12-17 12:13:24 -0800404 goto destroy_drm_gbm;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800405 }
406
407 if (!eglInitialize(ctx.egl_display, &egl_major, &egl_minor)) {
408 fprintf(stderr, "failed to initialize egl: %s\n",
409 get_egl_error());
410 ret = 1;
411 goto terminate_display;
412 }
413
414 fprintf(stderr, "EGL %d.%d\n", egl_major, egl_minor);
415 fprintf(stderr, "EGL %s\n",
416 eglQueryString(ctx.egl_display, EGL_VERSION));
417
Lauri Peltonen763ca462014-12-17 12:22:21 -0800418 egl_extensions = eglQueryString(ctx.egl_display, EGL_EXTENSIONS);
419 fprintf(stderr, "EGL Extensions: %s\n", egl_extensions);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800420
421 if (!setup_drm(&ctx)) {
422 fprintf(stderr, "failed to setup drm resources\n");
423 ret = 1;
424 goto terminate_display;
425 }
426
427 fprintf(stderr, "display size: %dx%d\n",
428 ctx.mode->hdisplay, ctx.mode->vdisplay);
429
430 if (!eglChooseConfig(ctx.egl_display, config_attribs, NULL, 0,
431 &num_configs)) {
432 fprintf(stderr, "eglChooseConfig() failed with error: %x\n", eglGetError());
433 goto free_drm;
434 }
435 if (!eglChooseConfig(ctx.egl_display, config_attribs, &egl_config, 1,
436 &num_configs)) {
437 fprintf(stderr, "eglChooseConfig() failed with error: %x\n", eglGetError());
438 goto free_drm;
439 }
440
441 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
442 fprintf(stderr, "failed to bind OpenGL ES: %s\n",
443 get_egl_error());
444 ret = 1;
445 goto free_drm;
446 }
447
448 ctx.egl_ctx = eglCreateContext(ctx.egl_display,
Lauri Peltonen44af28d2014-12-17 12:19:54 -0800449 egl_config,
Haixia Shie04ddfd2014-11-11 19:14:32 -0800450 EGL_NO_CONTEXT /* No shared context */,
451 context_attribs);
452 if (ctx.egl_ctx == EGL_NO_CONTEXT) {
453 fprintf(stderr, "failed to create OpenGL ES Context: %s\n",
454 get_egl_error());
455 ret = 1;
456 goto free_drm;
457 }
458
459 if (!eglMakeCurrent(ctx.egl_display,
460 EGL_NO_SURFACE /* No default draw surface */,
461 EGL_NO_SURFACE /* No default draw read */,
462 ctx.egl_ctx)) {
463 fprintf(stderr, "failed to make the OpenGL ES Context current: %s\n",
464 get_egl_error());
465 ret = 1;
466 goto destroy_context;
467 }
468
Lauri Peltonen763ca462014-12-17 12:22:21 -0800469 gl_extensions = (const char *)glGetString(GL_EXTENSIONS);
470 fprintf(stderr, "GL extensions: %s\n", gl_extensions);
471
472 if (!has_extension("EGL_EXT_image_dma_buf_import", egl_extensions)) {
473 fprintf(stderr, "EGL_EXT_image_dma_buf_import extension not supported\n");
474 ret = 1;
475 goto destroy_context;
476 }
477
478 if (!has_extension("GL_OES_EGL_image", gl_extensions)) {
479 fprintf(stderr, "GL_OES_EGL_image extension not supported\n");
480 ret = 1;
481 goto destroy_context;
482 }
483
484 pfeglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");
485 pfeglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR");
486 pfglEGLImageTargetRenderbufferStorageOES = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)eglGetProcAddress("glEGLImageTargetRenderbufferStorageOES");
487 if (!pfeglCreateImageKHR || !pfeglDestroyImageKHR || !pfglEGLImageTargetRenderbufferStorageOES) {
488 fprintf(stderr, "eglGetProcAddress returned NULL for a required extension entry point\n");
489 ret = 1;
490 goto destroy_context;
491 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800492
Haixia Shi4652b8c2014-11-19 17:55:38 -0800493 glGenFramebuffers(BUFFERS, ctx.gl_fb);
494 glGenRenderbuffers(BUFFERS, ctx.gl_rb);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800495
Haixia Shi4652b8c2014-11-19 17:55:38 -0800496 for (i = 0; i < BUFFERS; ++i) {
Haixia Shibc4d0a02014-12-01 14:25:54 -0800497 ctx.gbm_buffer[i] = gbm_bo_create(ctx.drm_gbm,
Haixia Shi4652b8c2014-11-19 17:55:38 -0800498 ctx.mode->hdisplay, ctx.mode->vdisplay, GBM_BO_FORMAT_XRGB8888,
499 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
500
501 if (!ctx.gbm_buffer[i]) {
502 fprintf(stderr, "failed to create buffer object\n");
503 ret = 1;
504 goto free_buffers;
505 }
506
507 bo_handle = gbm_bo_get_handle(ctx.gbm_buffer[i]).u32;
508 bo_stride = gbm_bo_get_stride(ctx.gbm_buffer[i]);
509
Zach Reizner0feb1f12015-01-09 13:38:57 -0800510 drm_prime_fd = gbm_bo_get_fd(ctx.gbm_buffer[i]);
511
512 if (drm_prime_fd < 0) {
Haixia Shi4652b8c2014-11-19 17:55:38 -0800513 fprintf(stderr, "failed to turn handle into fd\n");
514 ret = 1;
515 goto free_buffers;
516 }
517
518 const EGLint khr_image_attrs[] = {
519 EGL_WIDTH, ctx.mode->hdisplay,
520 EGL_HEIGHT, ctx.mode->vdisplay,
521 EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_XRGB8888,
522 EGL_DMA_BUF_PLANE0_FD_EXT, drm_prime_fd,
523 EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
524 EGL_DMA_BUF_PLANE0_PITCH_EXT, bo_stride,
525 EGL_NONE
526 };
527
Lauri Peltonen763ca462014-12-17 12:22:21 -0800528 ctx.egl_image[i] = pfeglCreateImageKHR(ctx.egl_display, EGL_NO_CONTEXT,
Haixia Shi4652b8c2014-11-19 17:55:38 -0800529 EGL_LINUX_DMA_BUF_EXT, NULL, khr_image_attrs);
530 if (ctx.egl_image[i] == EGL_NO_IMAGE_KHR) {
531 fprintf(stderr, "failed to create egl image: %s\n",
532 get_egl_error());
533 ret = 1;
534 goto free_buffers;
535 }
536
537 glBindRenderbuffer(GL_RENDERBUFFER, ctx.gl_rb[i]);
538 glBindFramebuffer(GL_FRAMEBUFFER, ctx.gl_fb[i]);
Lauri Peltonen763ca462014-12-17 12:22:21 -0800539 pfglEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, ctx.egl_image[i]);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800540 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
541 GL_RENDERBUFFER, ctx.gl_rb[i]);
542
543 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) !=
544 GL_FRAMEBUFFER_COMPLETE) {
545 fprintf(stderr, "failed to create framebuffer: %s\n", get_gl_error());
546 ret = 1;
547 goto free_buffers;
548 }
549
Haixia Shibc4d0a02014-12-01 14:25:54 -0800550 ret = drmModeAddFB(ctx.drm_card_fd, ctx.mode->hdisplay, ctx.mode->vdisplay,
Haixia Shi4652b8c2014-11-19 17:55:38 -0800551 24, 32, bo_stride, bo_handle, &ctx.drm_fb_id[i]);
552
553 if (ret) {
554 fprintf(stderr, "failed to add fb\n");
555 ret = 1;
556 goto free_buffers;
557 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800558 }
559
Haixia Shibc4d0a02014-12-01 14:25:54 -0800560 if (drmModeSetCrtc(ctx.drm_card_fd, ctx.encoder->crtc_id, ctx.drm_fb_id[0],
Haixia Shie04ddfd2014-11-11 19:14:32 -0800561 0, 0, &ctx.connector->connector_id, 1, ctx.mode)) {
562 fprintf(stderr, "failed to set CRTC\n");
563 ret = 1;
Haixia Shi4652b8c2014-11-19 17:55:38 -0800564 goto free_buffers;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800565 }
566
567 draw(&ctx);
568
Haixia Shi4652b8c2014-11-19 17:55:38 -0800569free_buffers:
Haixia Shie04ddfd2014-11-11 19:14:32 -0800570 glBindRenderbuffer(GL_RENDERBUFFER, 0);
571 glBindFramebuffer(GL_FRAMEBUFFER, 0);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800572 for (i = 0; i < BUFFERS; ++i) {
573 if (ctx.drm_fb_id[i])
Haixia Shibc4d0a02014-12-01 14:25:54 -0800574 drmModeRmFB(ctx.drm_card_fd, ctx.drm_fb_id[i]);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800575 if (ctx.egl_image[i])
Lauri Peltonen763ca462014-12-17 12:22:21 -0800576 pfeglDestroyImageKHR(ctx.egl_display, ctx.egl_image[i]);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800577 if (ctx.gl_fb[i])
578 glDeleteFramebuffers(1, &ctx.gl_fb[i]);
579 if (ctx.gl_rb[i])
580 glDeleteRenderbuffers(1, &ctx.gl_rb[i]);
581 if (ctx.gbm_buffer[i])
582 gbm_bo_destroy(ctx.gbm_buffer[i]);
583 }
Haixia Shie04ddfd2014-11-11 19:14:32 -0800584destroy_context:
585 eglDestroyContext(ctx.egl_display, ctx.egl_ctx);
586free_drm:
587 drmModeFreeConnector(ctx.connector);
588 drmModeFreeEncoder(ctx.encoder);
589terminate_display:
590 eglTerminate(ctx.egl_display);
Haixia Shibc4d0a02014-12-01 14:25:54 -0800591destroy_drm_gbm:
592 gbm_device_destroy(ctx.drm_gbm);
593close_drm_card:
594 close(ctx.drm_card_fd);
Haixia Shie04ddfd2014-11-11 19:14:32 -0800595fail:
596 return ret;
597}