EGL/android: pbuffer implementation
[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 <fcntl.h>
33 #include <xf86drm.h>
34
35 #if ANDROID_VERSION >= 0x402
36 #include <sync/sync.h>
37 #endif
38
39 #include "loader.h"
40 #include "egl_dri2.h"
41 #include "egl_dri2_fallbacks.h"
42 #include "gralloc_drm.h"
43
44 #define ALIGN(val, align) (((val) + (align) - 1) & ~((align) - 1))
45
46 static int
47 get_format_bpp(int native)
48 {
49 int bpp;
50
51 switch (native) {
52 case HAL_PIXEL_FORMAT_RGBA_8888:
53 case HAL_PIXEL_FORMAT_RGBX_8888:
54 case HAL_PIXEL_FORMAT_BGRA_8888:
55 bpp = 4;
56 break;
57 case HAL_PIXEL_FORMAT_RGB_888:
58 bpp = 3;
59 break;
60 case HAL_PIXEL_FORMAT_RGB_565:
61 bpp = 2;
62 break;
63 case HAL_PIXEL_FORMAT_YV12:
64 bpp = 1;
65 break;
66 default:
67 bpp = 0;
68 break;
69 }
70
71 return bpp;
72 }
73
74 /* createImageFromFds requires fourcc format */
75 static int get_fourcc(int native)
76 {
77 switch (native) {
78 case HAL_PIXEL_FORMAT_RGB_565: return __DRI_IMAGE_FOURCC_RGB565;
79 case HAL_PIXEL_FORMAT_BGRA_8888: return __DRI_IMAGE_FOURCC_ARGB8888;
80 case HAL_PIXEL_FORMAT_RGBA_8888: return __DRI_IMAGE_FOURCC_ABGR8888;
81 case HAL_PIXEL_FORMAT_RGBX_8888: return __DRI_IMAGE_FOURCC_XBGR8888;
82 case HAL_PIXEL_FORMAT_YV12: return __DRI_IMAGE_FOURCC_YVU420;
83 default:
84 _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", native);
85 }
86 return -1;
87 }
88
89 static int get_format(int format)
90 {
91 switch (format) {
92 case HAL_PIXEL_FORMAT_BGRA_8888: return __DRI_IMAGE_FORMAT_ARGB8888;
93 case HAL_PIXEL_FORMAT_RGB_565: return __DRI_IMAGE_FORMAT_RGB565;
94 case HAL_PIXEL_FORMAT_RGBA_8888: return __DRI_IMAGE_FORMAT_ABGR8888;
95 case HAL_PIXEL_FORMAT_RGBX_8888: return __DRI_IMAGE_FORMAT_XBGR8888;
96 case HAL_PIXEL_FORMAT_RGB_888:
97 /* unsupported */
98 default:
99 _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", format);
100 }
101 return -1;
102 }
103
104 static int
105 get_native_buffer_fd(struct ANativeWindowBuffer *buf)
106 {
107 native_handle_t *handle = (native_handle_t *)buf->handle;
108 /*
109 * Various gralloc implementations exist, but the dma-buf fd tends
110 * to be first. Access it directly to avoid a dependency on specific
111 * gralloc versions.
112 */
113 return (handle && handle->numFds) ? handle->data[0] : -1;
114 }
115
116 static int
117 get_native_buffer_name(struct ANativeWindowBuffer *buf)
118 {
119 return gralloc_drm_get_gem_handle(buf->handle);
120 }
121
122 static EGLBoolean
123 droid_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf)
124 {
125 #if ANDROID_VERSION >= 0x0402
126 int fence_fd;
127
128 if (dri2_surf->window->dequeueBuffer(dri2_surf->window, &dri2_surf->buffer,
129 &fence_fd))
130 return EGL_FALSE;
131
132 /* If access to the buffer is controlled by a sync fence, then block on the
133 * fence.
134 *
135 * It may be more performant to postpone blocking until there is an
136 * immediate need to write to the buffer. But doing so would require adding
137 * hooks to the DRI2 loader.
138 *
139 * From the ANativeWindow::dequeueBuffer documentation:
140 *
141 * The libsync fence file descriptor returned in the int pointed to by
142 * the fenceFd argument will refer to the fence that must signal
143 * before the dequeued buffer may be written to. A value of -1
144 * indicates that the caller may access the buffer immediately without
145 * waiting on a fence. If a valid file descriptor is returned (i.e.
146 * any value except -1) then the caller is responsible for closing the
147 * file descriptor.
148 */
149 if (fence_fd >= 0) {
150 /* From the SYNC_IOC_WAIT documentation in <linux/sync.h>:
151 *
152 * Waits indefinitely if timeout < 0.
153 */
154 int timeout = -1;
155 sync_wait(fence_fd, timeout);
156 close(fence_fd);
157 }
158
159 dri2_surf->buffer->common.incRef(&dri2_surf->buffer->common);
160 #else
161 if (dri2_surf->window->dequeueBuffer(dri2_surf->window, &dri2_surf->buffer))
162 return EGL_FALSE;
163
164 dri2_surf->buffer->common.incRef(&dri2_surf->buffer->common);
165 dri2_surf->window->lockBuffer(dri2_surf->window, dri2_surf->buffer);
166 #endif
167
168 return EGL_TRUE;
169 }
170
171 static EGLBoolean
172 droid_window_enqueue_buffer(_EGLDisplay *disp, struct dri2_egl_surface *dri2_surf)
173 {
174 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
175
176 /* To avoid blocking other EGL calls, release the display mutex before
177 * we enter droid_window_enqueue_buffer() and re-acquire the mutex upon
178 * return.
179 */
180 mtx_unlock(&disp->Mutex);
181
182 #if ANDROID_VERSION >= 0x0402
183 /* Queue the buffer without a sync fence. This informs the ANativeWindow
184 * that it may access the buffer immediately.
185 *
186 * From ANativeWindow::dequeueBuffer:
187 *
188 * The fenceFd argument specifies a libsync fence file descriptor for
189 * a fence that must signal before the buffer can be accessed. If
190 * the buffer can be accessed immediately then a value of -1 should
191 * be used. The caller must not use the file descriptor after it
192 * is passed to queueBuffer, and the ANativeWindow implementation
193 * is responsible for closing it.
194 */
195 int fence_fd = -1;
196 dri2_surf->window->queueBuffer(dri2_surf->window, dri2_surf->buffer,
197 fence_fd);
198 #else
199 dri2_surf->window->queueBuffer(dri2_surf->window, dri2_surf->buffer);
200 #endif
201
202 dri2_surf->buffer->common.decRef(&dri2_surf->buffer->common);
203 dri2_surf->buffer = NULL;
204
205 mtx_lock(&disp->Mutex);
206
207 if (dri2_surf->dri_image_back) {
208 dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
209 dri2_surf->dri_image_back = NULL;
210 }
211
212 return EGL_TRUE;
213 }
214
215 static void
216 droid_window_cancel_buffer(_EGLDisplay *disp, struct dri2_egl_surface *dri2_surf)
217 {
218 /* no cancel buffer? */
219 droid_window_enqueue_buffer(disp, dri2_surf);
220 }
221
222 static __DRIbuffer *
223 droid_alloc_local_buffer(struct dri2_egl_surface *dri2_surf,
224 unsigned int att, unsigned int format)
225 {
226 struct dri2_egl_display *dri2_dpy =
227 dri2_egl_display(dri2_surf->base.Resource.Display);
228
229 if (att >= ARRAY_SIZE(dri2_surf->local_buffers))
230 return NULL;
231
232 if (!dri2_surf->local_buffers[att]) {
233 dri2_surf->local_buffers[att] =
234 dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, att, format,
235 dri2_surf->base.Width, dri2_surf->base.Height);
236 }
237
238 return dri2_surf->local_buffers[att];
239 }
240
241 static void
242 droid_free_local_buffers(struct dri2_egl_surface *dri2_surf)
243 {
244 struct dri2_egl_display *dri2_dpy =
245 dri2_egl_display(dri2_surf->base.Resource.Display);
246 int i;
247
248 for (i = 0; i < ARRAY_SIZE(dri2_surf->local_buffers); i++) {
249 if (dri2_surf->local_buffers[i]) {
250 dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
251 dri2_surf->local_buffers[i]);
252 dri2_surf->local_buffers[i] = NULL;
253 }
254 }
255 }
256
257 static _EGLSurface *
258 droid_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
259 _EGLConfig *conf, void *native_window,
260 const EGLint *attrib_list)
261 {
262 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
263 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
264 struct dri2_egl_surface *dri2_surf;
265 struct ANativeWindow *window = native_window;
266 const __DRIconfig *config;
267
268 dri2_surf = calloc(1, sizeof *dri2_surf);
269 if (!dri2_surf) {
270 _eglError(EGL_BAD_ALLOC, "droid_create_surface");
271 return NULL;
272 }
273
274 if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
275 goto cleanup_surface;
276
277 if (type == EGL_WINDOW_BIT) {
278 int format;
279
280 if (!window || window->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
281 _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");
282 goto cleanup_surface;
283 }
284 if (window->query(window, NATIVE_WINDOW_FORMAT, &format)) {
285 _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");
286 goto cleanup_surface;
287 }
288
289 if (format != dri2_conf->base.NativeVisualID) {
290 _eglLog(_EGL_WARNING, "Native format mismatch: 0x%x != 0x%x",
291 format, dri2_conf->base.NativeVisualID);
292 }
293
294 window->query(window, NATIVE_WINDOW_WIDTH, &dri2_surf->base.Width);
295 window->query(window, NATIVE_WINDOW_HEIGHT, &dri2_surf->base.Height);
296 }
297
298 config = dri2_get_dri_config(dri2_conf, type,
299 dri2_surf->base.GLColorspace);
300 if (!config)
301 goto cleanup_surface;
302
303 dri2_surf->dri_drawable =
304 (*dri2_dpy->dri2->createNewDrawable)(dri2_dpy->dri_screen, config,
305 dri2_surf);
306 if (dri2_surf->dri_drawable == NULL) {
307 _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
308 goto cleanup_surface;
309 }
310
311 if (window) {
312 window->common.incRef(&window->common);
313 dri2_surf->window = window;
314 }
315
316 return &dri2_surf->base;
317
318 cleanup_surface:
319 free(dri2_surf);
320
321 return NULL;
322 }
323
324 static _EGLSurface *
325 droid_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
326 _EGLConfig *conf, void *native_window,
327 const EGLint *attrib_list)
328 {
329 return droid_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
330 native_window, attrib_list);
331 }
332
333 static _EGLSurface *
334 droid_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
335 _EGLConfig *conf, const EGLint *attrib_list)
336 {
337 return droid_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
338 NULL, attrib_list);
339 }
340
341 static EGLBoolean
342 droid_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
343 {
344 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
345 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
346
347 droid_free_local_buffers(dri2_surf);
348
349 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
350 if (dri2_surf->buffer)
351 droid_window_cancel_buffer(disp, dri2_surf);
352
353 dri2_surf->window->common.decRef(&dri2_surf->window->common);
354 }
355
356 if (dri2_surf->dri_image_back) {
357 _eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_back", __func__, __LINE__);
358 dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
359 dri2_surf->dri_image_back = NULL;
360 }
361
362 if (dri2_surf->dri_image_front) {
363 _eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_front", __func__, __LINE__);
364 dri2_dpy->image->destroyImage(dri2_surf->dri_image_front);
365 dri2_surf->dri_image_front = NULL;
366 }
367
368 (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
369
370 free(dri2_surf);
371
372 return EGL_TRUE;
373 }
374
375 static int
376 update_buffers(struct dri2_egl_surface *dri2_surf)
377 {
378 if (dri2_surf->base.Type != EGL_WINDOW_BIT)
379 return 0;
380
381 /* try to dequeue the next back buffer */
382 if (!dri2_surf->buffer && !droid_window_dequeue_buffer(dri2_surf)) {
383 _eglLog(_EGL_WARNING, "Could not dequeue buffer from native window");
384 return -1;
385 }
386
387 /* free outdated buffers and update the surface size */
388 if (dri2_surf->base.Width != dri2_surf->buffer->width ||
389 dri2_surf->base.Height != dri2_surf->buffer->height) {
390 droid_free_local_buffers(dri2_surf);
391 dri2_surf->base.Width = dri2_surf->buffer->width;
392 dri2_surf->base.Height = dri2_surf->buffer->height;
393 }
394
395 return 0;
396 }
397
398 static int
399 get_back_bo(struct dri2_egl_surface *dri2_surf)
400 {
401 struct dri2_egl_display *dri2_dpy =
402 dri2_egl_display(dri2_surf->base.Resource.Display);
403 int fourcc, pitch;
404 int offset = 0, fd;
405
406 if (dri2_surf->dri_image_back)
407 return 0;
408
409 if (!dri2_surf->buffer)
410 return -1;
411
412 fd = get_native_buffer_fd(dri2_surf->buffer);
413 if (fd < 0) {
414 _eglLog(_EGL_WARNING, "Could not get native buffer FD");
415 return -1;
416 }
417
418 fourcc = get_fourcc(dri2_surf->buffer->format);
419
420 pitch = dri2_surf->buffer->stride *
421 get_format_bpp(dri2_surf->buffer->format);
422
423 if (fourcc == -1 || pitch == 0) {
424 _eglLog(_EGL_WARNING, "Invalid buffer fourcc(%x) or pitch(%d)",
425 fourcc, pitch);
426 return -1;
427 }
428
429 dri2_surf->dri_image_back =
430 dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
431 dri2_surf->base.Width,
432 dri2_surf->base.Height,
433 fourcc,
434 &fd,
435 1,
436 &pitch,
437 &offset,
438 dri2_surf);
439 if (!dri2_surf->dri_image_back)
440 return -1;
441
442 return 0;
443 }
444
445 static int
446 droid_image_get_buffers(__DRIdrawable *driDrawable,
447 unsigned int format,
448 uint32_t *stamp,
449 void *loaderPrivate,
450 uint32_t buffer_mask,
451 struct __DRIimageList *images)
452 {
453 struct dri2_egl_surface *dri2_surf = loaderPrivate;
454 struct dri2_egl_display *dri2_dpy =
455 dri2_egl_display(dri2_surf->base.Resource.Display);
456
457 images->image_mask = 0;
458 images->front = NULL;
459 images->back = NULL;
460
461 if (update_buffers(dri2_surf) < 0)
462 return 0;
463
464 if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
465 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
466 /* According current EGL spec,
467 * front buffer rendering for window surface is not supported now */
468 _eglLog(_EGL_WARNING,
469 "%s:%d front buffer rendering for window surface is not supported!",
470 __func__, __LINE__);
471 return 0;
472 }
473
474 /* The EGL 1.5 spec states that pbuffers are single-buffered. Specifically,
475 * the spec states that they have a back buffer but no front buffer, in
476 * contrast to pixmaps, which have a front buffer but no back buffer.
477 *
478 * Single-buffered surfaces with no front buffer confuse Mesa; so we deviate
479 * from the spec, following the precedent of Mesa's EGL X11 platform. The
480 * X11 platform correctly assigns pbuffers to single-buffered configs, but
481 * assigns the pbuffer a front buffer instead of a back buffer.
482 *
483 * Pbuffers in the X11 platform mostly work today, so let's just copy its
484 * behavior instead of trying to fix (and hence potentially breaking) the
485 * world.
486 */
487 if (!dri2_surf->dri_image_front &&
488 dri2_surf->base.Type == EGL_PBUFFER_BIT) {
489 dri2_surf->dri_image_front =
490 dri2_dpy->image->createImage(dri2_dpy->dri_screen,
491 dri2_surf->base.Width,
492 dri2_surf->base.Height,
493 format,
494 0,
495 dri2_surf);
496 }
497
498 if (!dri2_surf->dri_image_front) {
499 _eglLog(_EGL_WARNING,
500 "%s:%d dri2_image front buffer allocation failed!",
501 __func__, __LINE__);
502 return 0;
503 }
504
505 images->front = dri2_surf->dri_image_front;
506 images->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
507 }
508
509 if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) {
510 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
511 if (get_back_bo(dri2_surf) < 0)
512 return 0;
513 }
514
515 if (!dri2_surf->dri_image_back) {
516 _eglLog(_EGL_WARNING,
517 "%s:%d dri2_image back buffer allocation failed!",
518 __func__, __LINE__);
519 return 0;
520 }
521
522 images->back = dri2_surf->dri_image_back;
523 images->image_mask |= __DRI_IMAGE_BUFFER_BACK;
524 }
525
526 return 1;
527 }
528
529 static EGLBoolean
530 droid_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
531 {
532 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
533 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
534
535 if (dri2_surf->base.Type != EGL_WINDOW_BIT)
536 return EGL_TRUE;
537
538 dri2_flush_drawable_for_swapbuffers(disp, draw);
539
540 if (dri2_surf->buffer)
541 droid_window_enqueue_buffer(disp, dri2_surf);
542
543 (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
544
545 return EGL_TRUE;
546 }
547
548 static _EGLImage *
549 droid_create_image_from_prime_fd(_EGLDisplay *disp, _EGLContext *ctx,
550 struct ANativeWindowBuffer *buf, int fd)
551 {
552 unsigned int offsets[3] = { 0, 0, 0 };
553 unsigned int pitches[3] = { 0, 0, 0 };
554
555 const int fourcc = get_fourcc(buf->format);
556 if (fourcc == -1) {
557 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
558 return NULL;
559 }
560
561 pitches[0] = buf->stride * get_format_bpp(buf->format);
562 if (pitches[0] == 0) {
563 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
564 return NULL;
565 }
566
567 switch (buf->format) {
568 case HAL_PIXEL_FORMAT_YV12:
569 /* Y plane is assumed to be at offset 0. */
570 /* Cr plane is located after Y plane */
571 offsets[1] = offsets[0] + pitches[0] * buf->height;
572 pitches[1] = ALIGN(pitches[0] / 2, 16);
573 /* Cb plane is located after Cr plane */
574 offsets[2] = offsets[1] + pitches[1] * buf->height / 2;
575 pitches[2] = pitches[1];
576
577 const EGLint attr_list_yv12[] = {
578 EGL_WIDTH, buf->width,
579 EGL_HEIGHT, buf->height,
580 EGL_LINUX_DRM_FOURCC_EXT, fourcc,
581 EGL_DMA_BUF_PLANE0_FD_EXT, fd,
582 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0],
583 EGL_DMA_BUF_PLANE0_OFFSET_EXT, offsets[0],
584 EGL_DMA_BUF_PLANE1_FD_EXT, fd,
585 EGL_DMA_BUF_PLANE1_PITCH_EXT, pitches[1],
586 EGL_DMA_BUF_PLANE1_OFFSET_EXT, offsets[1],
587 EGL_DMA_BUF_PLANE2_FD_EXT, fd,
588 EGL_DMA_BUF_PLANE2_PITCH_EXT, pitches[2],
589 EGL_DMA_BUF_PLANE2_OFFSET_EXT, offsets[2],
590 EGL_NONE, 0
591 };
592
593 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list_yv12);
594 }
595
596 const EGLint attr_list[] = {
597 EGL_WIDTH, buf->width,
598 EGL_HEIGHT, buf->height,
599 EGL_LINUX_DRM_FOURCC_EXT, fourcc,
600 EGL_DMA_BUF_PLANE0_FD_EXT, fd,
601 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0],
602 EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
603 EGL_NONE, 0
604 };
605
606 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list);
607 }
608
609 static _EGLImage *
610 droid_create_image_from_name(_EGLDisplay *disp, _EGLContext *ctx,
611 struct ANativeWindowBuffer *buf)
612 {
613 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
614 struct dri2_egl_image *dri2_img;
615 int name;
616 int format;
617
618 name = get_native_buffer_name(buf);
619 if (!name) {
620 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
621 return NULL;
622 }
623
624 format = get_format(buf->format);
625 if (format == -1)
626 return NULL;
627
628 dri2_img = calloc(1, sizeof(*dri2_img));
629 if (!dri2_img) {
630 _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm");
631 return NULL;
632 }
633
634 if (!_eglInitImage(&dri2_img->base, disp)) {
635 free(dri2_img);
636 return NULL;
637 }
638
639 dri2_img->dri_image =
640 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
641 buf->width,
642 buf->height,
643 format,
644 name,
645 buf->stride,
646 dri2_img);
647 if (!dri2_img->dri_image) {
648 free(dri2_img);
649 _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm");
650 return NULL;
651 }
652
653 return &dri2_img->base;
654 }
655
656 static EGLBoolean
657 droid_query_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
658 EGLint attribute, EGLint *value)
659 {
660 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
661 switch (attribute) {
662 case EGL_WIDTH:
663 if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->window) {
664 dri2_surf->window->query(dri2_surf->window,
665 NATIVE_WINDOW_DEFAULT_WIDTH, value);
666 return EGL_TRUE;
667 }
668 break;
669 case EGL_HEIGHT:
670 if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->window) {
671 dri2_surf->window->query(dri2_surf->window,
672 NATIVE_WINDOW_DEFAULT_HEIGHT, value);
673 return EGL_TRUE;
674 }
675 break;
676 default:
677 break;
678 }
679 return _eglQuerySurface(drv, dpy, surf, attribute, value);
680 }
681
682 static _EGLImage *
683 dri2_create_image_android_native_buffer(_EGLDisplay *disp,
684 _EGLContext *ctx,
685 struct ANativeWindowBuffer *buf)
686 {
687 int fd;
688
689 if (ctx != NULL) {
690 /* From the EGL_ANDROID_image_native_buffer spec:
691 *
692 * * If <target> is EGL_NATIVE_BUFFER_ANDROID and <ctx> is not
693 * EGL_NO_CONTEXT, the error EGL_BAD_CONTEXT is generated.
694 */
695 _eglError(EGL_BAD_CONTEXT, "eglCreateEGLImageKHR: for "
696 "EGL_NATIVE_BUFFER_ANDROID, the context must be "
697 "EGL_NO_CONTEXT");
698 return NULL;
699 }
700
701 if (!buf || buf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC ||
702 buf->common.version != sizeof(*buf)) {
703 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
704 return NULL;
705 }
706
707 fd = get_native_buffer_fd(buf);
708 if (fd >= 0)
709 return droid_create_image_from_prime_fd(disp, ctx, buf, fd);
710
711 return droid_create_image_from_name(disp, ctx, buf);
712 }
713
714 static _EGLImage *
715 droid_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
716 _EGLContext *ctx, EGLenum target,
717 EGLClientBuffer buffer, const EGLint *attr_list)
718 {
719 switch (target) {
720 case EGL_NATIVE_BUFFER_ANDROID:
721 return dri2_create_image_android_native_buffer(disp, ctx,
722 (struct ANativeWindowBuffer *) buffer);
723 default:
724 return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
725 }
726 }
727
728 static void
729 droid_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
730 {
731 }
732
733 static int
734 droid_get_buffers_parse_attachments(struct dri2_egl_surface *dri2_surf,
735 unsigned int *attachments, int count)
736 {
737 int num_buffers = 0, i;
738
739 /* fill dri2_surf->buffers */
740 for (i = 0; i < count * 2; i += 2) {
741 __DRIbuffer *buf, *local;
742
743 assert(num_buffers < ARRAY_SIZE(dri2_surf->buffers));
744 buf = &dri2_surf->buffers[num_buffers];
745
746 switch (attachments[i]) {
747 case __DRI_BUFFER_BACK_LEFT:
748 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
749 buf->attachment = attachments[i];
750 buf->name = get_native_buffer_name(dri2_surf->buffer);
751 buf->cpp = get_format_bpp(dri2_surf->buffer->format);
752 buf->pitch = dri2_surf->buffer->stride * buf->cpp;
753 buf->flags = 0;
754
755 if (buf->name)
756 num_buffers++;
757
758 break;
759 }
760 /* fall through for pbuffers */
761 case __DRI_BUFFER_DEPTH:
762 case __DRI_BUFFER_STENCIL:
763 case __DRI_BUFFER_ACCUM:
764 case __DRI_BUFFER_DEPTH_STENCIL:
765 case __DRI_BUFFER_HIZ:
766 local = droid_alloc_local_buffer(dri2_surf,
767 attachments[i], attachments[i + 1]);
768
769 if (local) {
770 *buf = *local;
771 num_buffers++;
772 }
773 break;
774 case __DRI_BUFFER_FRONT_LEFT:
775 case __DRI_BUFFER_FRONT_RIGHT:
776 case __DRI_BUFFER_FAKE_FRONT_LEFT:
777 case __DRI_BUFFER_FAKE_FRONT_RIGHT:
778 case __DRI_BUFFER_BACK_RIGHT:
779 default:
780 /* no front or right buffers */
781 break;
782 }
783 }
784
785 return num_buffers;
786 }
787
788 static __DRIbuffer *
789 droid_get_buffers_with_format(__DRIdrawable * driDrawable,
790 int *width, int *height,
791 unsigned int *attachments, int count,
792 int *out_count, void *loaderPrivate)
793 {
794 struct dri2_egl_surface *dri2_surf = loaderPrivate;
795
796 if (update_buffers(dri2_surf) < 0)
797 return NULL;
798
799 dri2_surf->buffer_count =
800 droid_get_buffers_parse_attachments(dri2_surf, attachments, count);
801
802 if (width)
803 *width = dri2_surf->base.Width;
804 if (height)
805 *height = dri2_surf->base.Height;
806
807 *out_count = dri2_surf->buffer_count;
808
809 return dri2_surf->buffers;
810 }
811
812 static EGLBoolean
813 droid_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *dpy)
814 {
815 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
816 static const struct {
817 int format;
818 unsigned int rgba_masks[4];
819 } visuals[] = {
820 { HAL_PIXEL_FORMAT_RGBA_8888, { 0xff, 0xff00, 0xff0000, 0xff000000 } },
821 { HAL_PIXEL_FORMAT_RGBX_8888, { 0xff, 0xff00, 0xff0000, 0x0 } },
822 { HAL_PIXEL_FORMAT_RGB_888, { 0xff, 0xff00, 0xff0000, 0x0 } },
823 { HAL_PIXEL_FORMAT_RGB_565, { 0xf800, 0x7e0, 0x1f, 0x0 } },
824 { HAL_PIXEL_FORMAT_BGRA_8888, { 0xff0000, 0xff00, 0xff, 0xff000000 } },
825 };
826 EGLint config_attrs[] = {
827 EGL_NATIVE_VISUAL_ID, 0,
828 EGL_NATIVE_VISUAL_TYPE, 0,
829 EGL_FRAMEBUFFER_TARGET_ANDROID, EGL_TRUE,
830 EGL_RECORDABLE_ANDROID, EGL_TRUE,
831 EGL_NONE
832 };
833 unsigned int format_count[ARRAY_SIZE(visuals)] = { 0 };
834 int count, i, j;
835
836 count = 0;
837 for (i = 0; dri2_dpy->driver_configs[i]; i++) {
838 const EGLint surface_type = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
839 struct dri2_egl_config *dri2_conf;
840
841 for (j = 0; j < ARRAY_SIZE(visuals); j++) {
842 config_attrs[1] = visuals[j].format;
843 config_attrs[3] = visuals[j].format;
844
845 dri2_conf = dri2_add_config(dpy, dri2_dpy->driver_configs[i],
846 count + 1, surface_type, config_attrs, visuals[j].rgba_masks);
847 if (dri2_conf) {
848 count++;
849 format_count[j]++;
850 }
851 }
852 }
853
854 for (i = 0; i < ARRAY_SIZE(format_count); i++) {
855 if (!format_count[i]) {
856 _eglLog(_EGL_DEBUG, "No DRI config supports native format 0x%x",
857 visuals[i].format);
858 }
859 }
860
861 return (count != 0);
862 }
863
864 static int
865 droid_open_device(void)
866 {
867 const hw_module_t *mod;
868 int fd = -1, err;
869
870 err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mod);
871 if (!err) {
872 const gralloc_module_t *gr = (gralloc_module_t *) mod;
873
874 err = -EINVAL;
875 if (gr->perform)
876 err = gr->perform(gr, GRALLOC_MODULE_PERFORM_GET_DRM_FD, &fd);
877 }
878 if (err || fd < 0) {
879 _eglLog(_EGL_WARNING, "fail to get drm fd");
880 fd = -1;
881 }
882
883 return (fd >= 0) ? fcntl(fd, F_DUPFD_CLOEXEC, 3) : -1;
884 }
885
886 /* support versions < JellyBean */
887 #ifndef ALOGW
888 #define ALOGW LOGW
889 #endif
890 #ifndef ALOGD
891 #define ALOGD LOGD
892 #endif
893 #ifndef ALOGI
894 #define ALOGI LOGI
895 #endif
896
897 static void
898 droid_log(EGLint level, const char *msg)
899 {
900 switch (level) {
901 case _EGL_DEBUG:
902 ALOGD("%s", msg);
903 break;
904 case _EGL_INFO:
905 ALOGI("%s", msg);
906 break;
907 case _EGL_WARNING:
908 ALOGW("%s", msg);
909 break;
910 case _EGL_FATAL:
911 LOG_FATAL("%s", msg);
912 break;
913 default:
914 break;
915 }
916 }
917
918 static struct dri2_egl_display_vtbl droid_display_vtbl = {
919 .authenticate = NULL,
920 .create_window_surface = droid_create_window_surface,
921 .create_pixmap_surface = dri2_fallback_create_pixmap_surface,
922 .create_pbuffer_surface = droid_create_pbuffer_surface,
923 .destroy_surface = droid_destroy_surface,
924 .create_image = droid_create_image_khr,
925 .swap_interval = dri2_fallback_swap_interval,
926 .swap_buffers = droid_swap_buffers,
927 .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage,
928 .swap_buffers_region = dri2_fallback_swap_buffers_region,
929 .post_sub_buffer = dri2_fallback_post_sub_buffer,
930 .copy_buffers = dri2_fallback_copy_buffers,
931 .query_buffer_age = dri2_fallback_query_buffer_age,
932 .query_surface = droid_query_surface,
933 .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
934 .get_sync_values = dri2_fallback_get_sync_values,
935 .get_dri_drawable = dri2_surface_get_dri_drawable,
936 };
937
938 static const __DRIdri2LoaderExtension droid_dri2_loader_extension = {
939 .base = { __DRI_DRI2_LOADER, 3 },
940
941 .getBuffers = NULL,
942 .flushFrontBuffer = droid_flush_front_buffer,
943 .getBuffersWithFormat = droid_get_buffers_with_format,
944 };
945
946 static const __DRIimageLoaderExtension droid_image_loader_extension = {
947 .base = { __DRI_IMAGE_LOADER, 1 },
948
949 .getBuffers = droid_image_get_buffers,
950 .flushFrontBuffer = droid_flush_front_buffer,
951 };
952
953 static const __DRIextension *droid_dri2_loader_extensions[] = {
954 &droid_dri2_loader_extension.base,
955 &image_lookup_extension.base,
956 &use_invalidate.base,
957 NULL,
958 };
959
960 static const __DRIextension *droid_image_loader_extensions[] = {
961 &droid_image_loader_extension.base,
962 &image_lookup_extension.base,
963 &use_invalidate.base,
964 NULL,
965 };
966
967 EGLBoolean
968 dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *dpy)
969 {
970 struct dri2_egl_display *dri2_dpy;
971 const char *err;
972
973 _eglSetLogProc(droid_log);
974
975 loader_set_logger(_eglLog);
976
977 dri2_dpy = calloc(1, sizeof(*dri2_dpy));
978 if (!dri2_dpy)
979 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
980
981 dpy->DriverData = (void *) dri2_dpy;
982
983 dri2_dpy->fd = droid_open_device();
984 if (dri2_dpy->fd < 0) {
985 err = "DRI2: failed to open device";
986 goto cleanup_display;
987 }
988
989 dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
990 if (dri2_dpy->driver_name == NULL) {
991 err = "DRI2: failed to get driver name";
992 goto cleanup_device;
993 }
994
995 if (!dri2_load_driver(dpy)) {
996 err = "DRI2: failed to load driver";
997 goto cleanup_driver_name;
998 }
999
1000 dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER;
1001
1002 /* render nodes cannot use Gem names, and thus do not support
1003 * the __DRI_DRI2_LOADER extension */
1004 if (!dri2_dpy->is_render_node)
1005 dri2_dpy->loader_extensions = droid_dri2_loader_extensions;
1006 else
1007 dri2_dpy->loader_extensions = droid_image_loader_extensions;
1008
1009 if (!dri2_create_screen(dpy)) {
1010 err = "DRI2: failed to create screen";
1011 goto cleanup_driver;
1012 }
1013
1014 if (!droid_add_configs_for_visuals(drv, dpy)) {
1015 err = "DRI2: failed to add configs";
1016 goto cleanup_screen;
1017 }
1018
1019 dpy->Extensions.ANDROID_framebuffer_target = EGL_TRUE;
1020 dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE;
1021 dpy->Extensions.ANDROID_recordable = EGL_TRUE;
1022
1023 /* Fill vtbl last to prevent accidentally calling virtual function during
1024 * initialization.
1025 */
1026 dri2_dpy->vtbl = &droid_display_vtbl;
1027
1028 return EGL_TRUE;
1029
1030 cleanup_screen:
1031 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
1032 cleanup_driver:
1033 dlclose(dri2_dpy->driver);
1034 cleanup_driver_name:
1035 free(dri2_dpy->driver_name);
1036 cleanup_device:
1037 close(dri2_dpy->fd);
1038 cleanup_display:
1039 free(dri2_dpy);
1040 dpy->DriverData = NULL;
1041
1042 return _eglError(EGL_NOT_INITIALIZED, err);
1043 }