egl: android: factor out back buffer handling code
[mesa.git] / src / egl / drivers / dri2 / platform_android.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
5 * Copyright (C) 2010-2011 LunarG Inc.
6 *
7 * Based on platform_x11, which has
8 *
9 * Copyright © 2011 Intel Corporation
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included
19 * in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 * DEALINGS IN THE SOFTWARE.
28 */
29
30 #include <errno.h>
31 #include <dlfcn.h>
32 #include <xf86drm.h>
33
34 #if ANDROID_VERSION >= 0x402
35 #include <sync/sync.h>
36 #endif
37
38 #include "loader.h"
39 #include "egl_dri2.h"
40 #include "egl_dri2_fallbacks.h"
41 #include "gralloc_drm.h"
42
43 static int
44 get_format_bpp(int native)
45 {
46 int bpp;
47
48 switch (native) {
49 case HAL_PIXEL_FORMAT_RGBA_8888:
50 case HAL_PIXEL_FORMAT_RGBX_8888:
51 case HAL_PIXEL_FORMAT_BGRA_8888:
52 bpp = 4;
53 break;
54 case HAL_PIXEL_FORMAT_RGB_888:
55 bpp = 3;
56 break;
57 case HAL_PIXEL_FORMAT_RGB_565:
58 bpp = 2;
59 break;
60 default:
61 bpp = 0;
62 break;
63 }
64
65 return bpp;
66 }
67
68 static int get_format(int format)
69 {
70 switch (format) {
71 case HAL_PIXEL_FORMAT_BGRA_8888: return __DRI_IMAGE_FORMAT_ARGB8888;
72 case HAL_PIXEL_FORMAT_RGB_565: return __DRI_IMAGE_FORMAT_RGB565;
73 case HAL_PIXEL_FORMAT_RGBA_8888: return __DRI_IMAGE_FORMAT_ABGR8888;
74 case HAL_PIXEL_FORMAT_RGBX_8888: return __DRI_IMAGE_FORMAT_XBGR8888;
75 case HAL_PIXEL_FORMAT_RGB_888:
76 /* unsupported */
77 default:
78 _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", format);
79 }
80 return -1;
81 }
82 static int
83 get_native_buffer_name(struct ANativeWindowBuffer *buf)
84 {
85 return gralloc_drm_get_gem_handle(buf->handle);
86 }
87
88 static EGLBoolean
89 droid_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf)
90 {
91 #if ANDROID_VERSION >= 0x0402
92 int fence_fd;
93
94 if (dri2_surf->window->dequeueBuffer(dri2_surf->window, &dri2_surf->buffer,
95 &fence_fd))
96 return EGL_FALSE;
97
98 /* If access to the buffer is controlled by a sync fence, then block on the
99 * fence.
100 *
101 * It may be more performant to postpone blocking until there is an
102 * immediate need to write to the buffer. But doing so would require adding
103 * hooks to the DRI2 loader.
104 *
105 * From the ANativeWindow::dequeueBuffer documentation:
106 *
107 * The libsync fence file descriptor returned in the int pointed to by
108 * the fenceFd argument will refer to the fence that must signal
109 * before the dequeued buffer may be written to. A value of -1
110 * indicates that the caller may access the buffer immediately without
111 * waiting on a fence. If a valid file descriptor is returned (i.e.
112 * any value except -1) then the caller is responsible for closing the
113 * file descriptor.
114 */
115 if (fence_fd >= 0) {
116 /* From the SYNC_IOC_WAIT documentation in <linux/sync.h>:
117 *
118 * Waits indefinitely if timeout < 0.
119 */
120 int timeout = -1;
121 sync_wait(fence_fd, timeout);
122 close(fence_fd);
123 }
124
125 dri2_surf->buffer->common.incRef(&dri2_surf->buffer->common);
126 #else
127 if (dri2_surf->window->dequeueBuffer(dri2_surf->window, &dri2_surf->buffer))
128 return EGL_FALSE;
129
130 dri2_surf->buffer->common.incRef(&dri2_surf->buffer->common);
131 dri2_surf->window->lockBuffer(dri2_surf->window, dri2_surf->buffer);
132 #endif
133
134 return EGL_TRUE;
135 }
136
137 static EGLBoolean
138 droid_window_enqueue_buffer(struct dri2_egl_surface *dri2_surf)
139 {
140 #if ANDROID_VERSION >= 0x0402
141 /* Queue the buffer without a sync fence. This informs the ANativeWindow
142 * that it may access the buffer immediately.
143 *
144 * From ANativeWindow::dequeueBuffer:
145 *
146 * The fenceFd argument specifies a libsync fence file descriptor for
147 * a fence that must signal before the buffer can be accessed. If
148 * the buffer can be accessed immediately then a value of -1 should
149 * be used. The caller must not use the file descriptor after it
150 * is passed to queueBuffer, and the ANativeWindow implementation
151 * is responsible for closing it.
152 */
153 int fence_fd = -1;
154 dri2_surf->window->queueBuffer(dri2_surf->window, dri2_surf->buffer,
155 fence_fd);
156 #else
157 dri2_surf->window->queueBuffer(dri2_surf->window, dri2_surf->buffer);
158 #endif
159
160 dri2_surf->buffer->common.decRef(&dri2_surf->buffer->common);
161 dri2_surf->buffer = NULL;
162
163 return EGL_TRUE;
164 }
165
166 static void
167 droid_window_cancel_buffer(struct dri2_egl_surface *dri2_surf)
168 {
169 /* no cancel buffer? */
170 droid_window_enqueue_buffer(dri2_surf);
171 }
172
173 static __DRIbuffer *
174 droid_alloc_local_buffer(struct dri2_egl_surface *dri2_surf,
175 unsigned int att, unsigned int format)
176 {
177 struct dri2_egl_display *dri2_dpy =
178 dri2_egl_display(dri2_surf->base.Resource.Display);
179
180 if (att >= ARRAY_SIZE(dri2_surf->local_buffers))
181 return NULL;
182
183 if (!dri2_surf->local_buffers[att]) {
184 dri2_surf->local_buffers[att] =
185 dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, att, format,
186 dri2_surf->base.Width, dri2_surf->base.Height);
187 }
188
189 return dri2_surf->local_buffers[att];
190 }
191
192 static void
193 droid_free_local_buffers(struct dri2_egl_surface *dri2_surf)
194 {
195 struct dri2_egl_display *dri2_dpy =
196 dri2_egl_display(dri2_surf->base.Resource.Display);
197 int i;
198
199 for (i = 0; i < ARRAY_SIZE(dri2_surf->local_buffers); i++) {
200 if (dri2_surf->local_buffers[i]) {
201 dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
202 dri2_surf->local_buffers[i]);
203 dri2_surf->local_buffers[i] = NULL;
204 }
205 }
206 }
207
208 static _EGLSurface *
209 droid_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
210 _EGLConfig *conf, void *native_window,
211 const EGLint *attrib_list)
212 {
213 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
214 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
215 struct dri2_egl_surface *dri2_surf;
216 struct ANativeWindow *window = native_window;
217 const __DRIconfig *config;
218
219 dri2_surf = calloc(1, sizeof *dri2_surf);
220 if (!dri2_surf) {
221 _eglError(EGL_BAD_ALLOC, "droid_create_surface");
222 return NULL;
223 }
224
225 if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
226 goto cleanup_surface;
227
228 if (type == EGL_WINDOW_BIT) {
229 int format;
230
231 if (!window || window->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
232 _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");
233 goto cleanup_surface;
234 }
235 if (window->query(window, NATIVE_WINDOW_FORMAT, &format)) {
236 _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");
237 goto cleanup_surface;
238 }
239
240 if (format != dri2_conf->base.NativeVisualID) {
241 _eglLog(_EGL_WARNING, "Native format mismatch: 0x%x != 0x%x",
242 format, dri2_conf->base.NativeVisualID);
243 }
244
245 window->query(window, NATIVE_WINDOW_WIDTH, &dri2_surf->base.Width);
246 window->query(window, NATIVE_WINDOW_HEIGHT, &dri2_surf->base.Height);
247 }
248
249 config = dri2_get_dri_config(dri2_conf, EGL_WINDOW_BIT,
250 dri2_surf->base.GLColorspace);
251
252 dri2_surf->dri_drawable =
253 (*dri2_dpy->dri2->createNewDrawable)(dri2_dpy->dri_screen, config,
254 dri2_surf);
255 if (dri2_surf->dri_drawable == NULL) {
256 _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
257 goto cleanup_surface;
258 }
259
260 if (window) {
261 window->common.incRef(&window->common);
262 dri2_surf->window = window;
263 }
264
265 return &dri2_surf->base;
266
267 cleanup_surface:
268 free(dri2_surf);
269
270 return NULL;
271 }
272
273 static _EGLSurface *
274 droid_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
275 _EGLConfig *conf, void *native_window,
276 const EGLint *attrib_list)
277 {
278 return droid_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
279 native_window, attrib_list);
280 }
281
282 static _EGLSurface *
283 droid_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
284 _EGLConfig *conf, const EGLint *attrib_list)
285 {
286 return droid_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
287 NULL, attrib_list);
288 }
289
290 static EGLBoolean
291 droid_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
292 {
293 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
294 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
295
296 if (!_eglPutSurface(surf))
297 return EGL_TRUE;
298
299 droid_free_local_buffers(dri2_surf);
300
301 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
302 if (dri2_surf->buffer)
303 droid_window_cancel_buffer(dri2_surf);
304
305 dri2_surf->window->common.decRef(&dri2_surf->window->common);
306 }
307
308 (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
309
310 free(dri2_surf);
311
312 return EGL_TRUE;
313 }
314
315 static int
316 update_buffers(struct dri2_egl_surface *dri2_surf)
317 {
318 if (dri2_surf->base.Type != EGL_WINDOW_BIT)
319 return 0;
320
321 /* try to dequeue the next back buffer */
322 if (!dri2_surf->buffer && !droid_window_dequeue_buffer(dri2_surf))
323 return -1;
324
325 /* free outdated buffers and update the surface size */
326 if (dri2_surf->base.Width != dri2_surf->buffer->width ||
327 dri2_surf->base.Height != dri2_surf->buffer->height) {
328 droid_free_local_buffers(dri2_surf);
329 dri2_surf->base.Width = dri2_surf->buffer->width;
330 dri2_surf->base.Height = dri2_surf->buffer->height;
331 }
332
333 return 0;
334 }
335
336 static EGLBoolean
337 droid_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
338 {
339 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
340 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
341 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
342 _EGLContext *ctx;
343
344 if (dri2_surf->base.Type != EGL_WINDOW_BIT)
345 return EGL_TRUE;
346
347 if (dri2_drv->glFlush) {
348 ctx = _eglGetCurrentContext();
349 if (ctx && ctx->DrawSurface == &dri2_surf->base)
350 dri2_drv->glFlush();
351 }
352
353 dri2_flush_drawable_for_swapbuffers(disp, draw);
354
355 if (dri2_surf->buffer)
356 droid_window_enqueue_buffer(dri2_surf);
357
358 (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
359
360 return EGL_TRUE;
361 }
362
363 static _EGLImage *
364 dri2_create_image_android_native_buffer(_EGLDisplay *disp, _EGLContext *ctx,
365 struct ANativeWindowBuffer *buf)
366 {
367 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
368 struct dri2_egl_image *dri2_img;
369 int name;
370
371 if (ctx != NULL) {
372 /* From the EGL_ANDROID_image_native_buffer spec:
373 *
374 * * If <target> is EGL_NATIVE_BUFFER_ANDROID and <ctx> is not
375 * EGL_NO_CONTEXT, the error EGL_BAD_CONTEXT is generated.
376 */
377 _eglError(EGL_BAD_CONTEXT, "eglCreateEGLImageKHR: for "
378 "EGL_NATIVE_BUFFER_ANDROID, the context must be "
379 "EGL_NO_CONTEXT");
380 return NULL;
381 }
382
383 if (!buf || buf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC ||
384 buf->common.version != sizeof(*buf)) {
385 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
386 return NULL;
387 }
388
389 name = get_native_buffer_name(buf);
390 if (!name) {
391 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
392 return NULL;
393 }
394
395 dri2_img = calloc(1, sizeof(*dri2_img));
396 if (!dri2_img) {
397 _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm");
398 return NULL;
399 }
400
401 if (!_eglInitImage(&dri2_img->base, disp)) {
402 free(dri2_img);
403 return NULL;
404 }
405
406 dri2_img->dri_image =
407 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
408 buf->width,
409 buf->height,
410 get_format(buf->format),
411 name,
412 buf->stride,
413 dri2_img);
414 if (!dri2_img->dri_image) {
415 free(dri2_img);
416 _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm");
417 return NULL;
418 }
419
420 return &dri2_img->base;
421 }
422
423 static _EGLImage *
424 droid_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
425 _EGLContext *ctx, EGLenum target,
426 EGLClientBuffer buffer, const EGLint *attr_list)
427 {
428 switch (target) {
429 case EGL_NATIVE_BUFFER_ANDROID:
430 return dri2_create_image_android_native_buffer(disp, ctx,
431 (struct ANativeWindowBuffer *) buffer);
432 default:
433 return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
434 }
435 }
436
437 static void
438 droid_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
439 {
440 }
441
442 static int
443 droid_get_buffers_parse_attachments(struct dri2_egl_surface *dri2_surf,
444 unsigned int *attachments, int count)
445 {
446 int num_buffers = 0, i;
447
448 /* fill dri2_surf->buffers */
449 for (i = 0; i < count * 2; i += 2) {
450 __DRIbuffer *buf, *local;
451
452 assert(num_buffers < ARRAY_SIZE(dri2_surf->buffers));
453 buf = &dri2_surf->buffers[num_buffers];
454
455 switch (attachments[i]) {
456 case __DRI_BUFFER_BACK_LEFT:
457 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
458 buf->attachment = attachments[i];
459 buf->name = get_native_buffer_name(dri2_surf->buffer);
460 buf->cpp = get_format_bpp(dri2_surf->buffer->format);
461 buf->pitch = dri2_surf->buffer->stride * buf->cpp;
462 buf->flags = 0;
463
464 if (buf->name)
465 num_buffers++;
466
467 break;
468 }
469 /* fall through for pbuffers */
470 case __DRI_BUFFER_DEPTH:
471 case __DRI_BUFFER_STENCIL:
472 case __DRI_BUFFER_ACCUM:
473 case __DRI_BUFFER_DEPTH_STENCIL:
474 case __DRI_BUFFER_HIZ:
475 local = droid_alloc_local_buffer(dri2_surf,
476 attachments[i], attachments[i + 1]);
477
478 if (local) {
479 *buf = *local;
480 num_buffers++;
481 }
482 break;
483 case __DRI_BUFFER_FRONT_LEFT:
484 case __DRI_BUFFER_FRONT_RIGHT:
485 case __DRI_BUFFER_FAKE_FRONT_LEFT:
486 case __DRI_BUFFER_FAKE_FRONT_RIGHT:
487 case __DRI_BUFFER_BACK_RIGHT:
488 default:
489 /* no front or right buffers */
490 break;
491 }
492 }
493
494 return num_buffers;
495 }
496
497 static __DRIbuffer *
498 droid_get_buffers_with_format(__DRIdrawable * driDrawable,
499 int *width, int *height,
500 unsigned int *attachments, int count,
501 int *out_count, void *loaderPrivate)
502 {
503 struct dri2_egl_surface *dri2_surf = loaderPrivate;
504 struct dri2_egl_display *dri2_dpy =
505 dri2_egl_display(dri2_surf->base.Resource.Display);
506 int i;
507
508 if (update_buffers(dri2_surf) < 0)
509 return NULL;
510
511 dri2_surf->buffer_count =
512 droid_get_buffers_parse_attachments(dri2_surf, attachments, count);
513
514 if (width)
515 *width = dri2_surf->base.Width;
516 if (height)
517 *height = dri2_surf->base.Height;
518
519 *out_count = dri2_surf->buffer_count;
520
521 return dri2_surf->buffers;
522 }
523
524 static EGLBoolean
525 droid_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *dpy)
526 {
527 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
528 const struct {
529 int format;
530 unsigned int rgba_masks[4];
531 } visuals[] = {
532 { HAL_PIXEL_FORMAT_RGBA_8888, { 0xff, 0xff00, 0xff0000, 0xff000000 } },
533 { HAL_PIXEL_FORMAT_RGBX_8888, { 0xff, 0xff00, 0xff0000, 0x0 } },
534 { HAL_PIXEL_FORMAT_RGB_888, { 0xff, 0xff00, 0xff0000, 0x0 } },
535 { HAL_PIXEL_FORMAT_RGB_565, { 0xf800, 0x7e0, 0x1f, 0x0 } },
536 { HAL_PIXEL_FORMAT_BGRA_8888, { 0xff0000, 0xff00, 0xff, 0xff000000 } },
537 { 0, { 0, 0, 0, 0 } }
538 };
539 EGLint config_attrs[] = {
540 EGL_NATIVE_VISUAL_ID, 0,
541 EGL_NATIVE_VISUAL_TYPE, 0,
542 EGL_FRAMEBUFFER_TARGET_ANDROID, EGL_TRUE,
543 EGL_RECORDABLE_ANDROID, EGL_TRUE,
544 EGL_NONE
545 };
546 int count, i, j;
547
548 count = 0;
549 for (i = 0; visuals[i].format; i++) {
550 int format_count = 0;
551
552 config_attrs[1] = visuals[i].format;
553 config_attrs[3] = visuals[i].format;
554
555 for (j = 0; dri2_dpy->driver_configs[j]; j++) {
556 const EGLint surface_type = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
557 struct dri2_egl_config *dri2_conf;
558 unsigned int double_buffered = 0;
559
560 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[j],
561 __DRI_ATTRIB_DOUBLE_BUFFER, &double_buffered);
562
563 /* support only double buffered configs */
564 if (!double_buffered)
565 continue;
566
567 dri2_conf = dri2_add_config(dpy, dri2_dpy->driver_configs[j],
568 count + 1, surface_type, config_attrs, visuals[i].rgba_masks);
569 if (dri2_conf) {
570 count++;
571 format_count++;
572 }
573 }
574
575 if (!format_count) {
576 _eglLog(_EGL_DEBUG, "No DRI config supports native format 0x%x",
577 visuals[i].format);
578 }
579 }
580
581 /* post-process configs */
582 for (i = 0; i < dpy->Configs->Size; i++) {
583 struct dri2_egl_config *dri2_conf = dri2_egl_config(dpy->Configs->Elements[i]);
584
585 /* there is no front buffer so no OpenGL */
586 dri2_conf->base.RenderableType &= ~EGL_OPENGL_BIT;
587 dri2_conf->base.Conformant &= ~EGL_OPENGL_BIT;
588 }
589
590 return (count != 0);
591 }
592
593 static int
594 droid_open_device(void)
595 {
596 const hw_module_t *mod;
597 int fd = -1, err;
598
599 err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mod);
600 if (!err) {
601 const gralloc_module_t *gr = (gralloc_module_t *) mod;
602
603 err = -EINVAL;
604 if (gr->perform)
605 err = gr->perform(gr, GRALLOC_MODULE_PERFORM_GET_DRM_FD, &fd);
606 }
607 if (err || fd < 0) {
608 _eglLog(_EGL_WARNING, "fail to get drm fd");
609 fd = -1;
610 }
611
612 return (fd >= 0) ? dup(fd) : -1;
613 }
614
615 /* support versions < JellyBean */
616 #ifndef ALOGW
617 #define ALOGW LOGW
618 #endif
619 #ifndef ALOGD
620 #define ALOGD LOGD
621 #endif
622 #ifndef ALOGI
623 #define ALOGI LOGI
624 #endif
625
626 static void
627 droid_log(EGLint level, const char *msg)
628 {
629 switch (level) {
630 case _EGL_DEBUG:
631 ALOGD("%s", msg);
632 break;
633 case _EGL_INFO:
634 ALOGI("%s", msg);
635 break;
636 case _EGL_WARNING:
637 ALOGW("%s", msg);
638 break;
639 case _EGL_FATAL:
640 LOG_FATAL("%s", msg);
641 break;
642 default:
643 break;
644 }
645 }
646
647 static struct dri2_egl_display_vtbl droid_display_vtbl = {
648 .authenticate = NULL,
649 .create_window_surface = droid_create_window_surface,
650 .create_pixmap_surface = dri2_fallback_create_pixmap_surface,
651 .create_pbuffer_surface = droid_create_pbuffer_surface,
652 .destroy_surface = droid_destroy_surface,
653 .create_image = droid_create_image_khr,
654 .swap_interval = dri2_fallback_swap_interval,
655 .swap_buffers = droid_swap_buffers,
656 .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage,
657 .swap_buffers_region = dri2_fallback_swap_buffers_region,
658 .post_sub_buffer = dri2_fallback_post_sub_buffer,
659 .copy_buffers = dri2_fallback_copy_buffers,
660 .query_buffer_age = dri2_fallback_query_buffer_age,
661 .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
662 .get_sync_values = dri2_fallback_get_sync_values,
663 .get_dri_drawable = dri2_surface_get_dri_drawable,
664 };
665
666 EGLBoolean
667 dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *dpy)
668 {
669 struct dri2_egl_display *dri2_dpy;
670 const char *err;
671
672 _eglSetLogProc(droid_log);
673
674 loader_set_logger(_eglLog);
675
676 dri2_dpy = calloc(1, sizeof(*dri2_dpy));
677 if (!dri2_dpy)
678 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
679
680 dpy->DriverData = (void *) dri2_dpy;
681
682 dri2_dpy->fd = droid_open_device();
683 if (dri2_dpy->fd < 0) {
684 err = "DRI2: failed to open device";
685 goto cleanup_display;
686 }
687
688 dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd, 0);
689 if (dri2_dpy->driver_name == NULL) {
690 err = "DRI2: failed to get driver name";
691 goto cleanup_device;
692 }
693
694 if (!dri2_load_driver(dpy)) {
695 err = "DRI2: failed to load driver";
696 goto cleanup_driver_name;
697 }
698
699 dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER;
700
701 dri2_dpy->extensions[0] = &image_lookup_extension.base;
702 dri2_dpy->extensions[1] = &use_invalidate.base;
703
704 /* render nodes cannot use Gem names, and thus do not support
705 * the __DRI_DRI2_LOADER extension */
706 if (!dri2_dpy->is_render_node) {
707 dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER;
708 dri2_dpy->dri2_loader_extension.base.version = 3;
709 dri2_dpy->dri2_loader_extension.getBuffers = NULL;
710 dri2_dpy->dri2_loader_extension.flushFrontBuffer = droid_flush_front_buffer;
711 dri2_dpy->dri2_loader_extension.getBuffersWithFormat =
712 droid_get_buffers_with_format;
713 dri2_dpy->extensions[2] = &dri2_dpy->dri2_loader_extension.base;
714 dri2_dpy->extensions[3] = NULL;
715 } else
716 dri2_dpy->extensions[2] = NULL;
717
718
719 if (!dri2_create_screen(dpy)) {
720 err = "DRI2: failed to create screen";
721 goto cleanup_driver;
722 }
723
724 if (!droid_add_configs_for_visuals(drv, dpy)) {
725 err = "DRI2: failed to add configs";
726 goto cleanup_screen;
727 }
728
729 dpy->Extensions.ANDROID_framebuffer_target = EGL_TRUE;
730 dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE;
731 dpy->Extensions.ANDROID_recordable = EGL_TRUE;
732 dpy->Extensions.KHR_image_base = EGL_TRUE;
733
734 /* Fill vtbl last to prevent accidentally calling virtual function during
735 * initialization.
736 */
737 dri2_dpy->vtbl = &droid_display_vtbl;
738
739 return EGL_TRUE;
740
741 cleanup_screen:
742 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
743 cleanup_driver:
744 dlclose(dri2_dpy->driver);
745 cleanup_driver_name:
746 free(dri2_dpy->driver_name);
747 cleanup_device:
748 close(dri2_dpy->fd);
749 cleanup_display:
750 free(dri2_dpy);
751
752 return _eglError(EGL_NOT_INITIALIZED, err);
753 }