d37f6b8e447dc56f115909485dca7e3470b79e13
[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 <cutils/properties.h>
31 #include <errno.h>
32 #include <dirent.h>
33 #include <dlfcn.h>
34 #include <fcntl.h>
35 #include <xf86drm.h>
36 #include <stdbool.h>
37 #include <stdio.h>
38 #include <sync/sync.h>
39 #include <sys/types.h>
40
41 #include "loader.h"
42 #include "egl_dri2.h"
43 #include "egl_dri2_fallbacks.h"
44
45 #ifdef HAVE_DRM_GRALLOC
46 #include <gralloc_drm_handle.h>
47 #include "gralloc_drm.h"
48 #endif /* HAVE_DRM_GRALLOC */
49
50 #define ALIGN(val, align) (((val) + (align) - 1) & ~((align) - 1))
51
52 enum chroma_order {
53 YCbCr,
54 YCrCb,
55 };
56
57 struct droid_yuv_format {
58 /* Lookup keys */
59 int native; /* HAL_PIXEL_FORMAT_ */
60 enum chroma_order chroma_order; /* chroma order is {Cb, Cr} or {Cr, Cb} */
61 int chroma_step; /* Distance in bytes between subsequent chroma pixels. */
62
63 /* Result */
64 int fourcc; /* __DRI_IMAGE_FOURCC_ */
65 };
66
67 /* The following table is used to look up a DRI image FourCC based
68 * on native format and information contained in android_ycbcr struct. */
69 static const struct droid_yuv_format droid_yuv_formats[] = {
70 /* Native format, YCrCb, Chroma step, DRI image FourCC */
71 { HAL_PIXEL_FORMAT_YCbCr_420_888, YCbCr, 2, __DRI_IMAGE_FOURCC_NV12 },
72 { HAL_PIXEL_FORMAT_YCbCr_420_888, YCbCr, 1, __DRI_IMAGE_FOURCC_YUV420 },
73 { HAL_PIXEL_FORMAT_YCbCr_420_888, YCrCb, 1, __DRI_IMAGE_FOURCC_YVU420 },
74 { HAL_PIXEL_FORMAT_YV12, YCrCb, 1, __DRI_IMAGE_FOURCC_YVU420 },
75 /* HACK: See droid_create_image_from_prime_fds() and
76 * https://issuetracker.google.com/32077885. */
77 { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 2, __DRI_IMAGE_FOURCC_NV12 },
78 { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 1, __DRI_IMAGE_FOURCC_YUV420 },
79 { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, __DRI_IMAGE_FOURCC_YVU420 },
80 { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, __DRI_IMAGE_FOURCC_AYUV },
81 { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, __DRI_IMAGE_FOURCC_XYUV8888 },
82 };
83
84 static int
85 get_fourcc_yuv(int native, enum chroma_order chroma_order, int chroma_step)
86 {
87 for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i)
88 if (droid_yuv_formats[i].native == native &&
89 droid_yuv_formats[i].chroma_order == chroma_order &&
90 droid_yuv_formats[i].chroma_step == chroma_step)
91 return droid_yuv_formats[i].fourcc;
92
93 return -1;
94 }
95
96 static bool
97 is_yuv(int native)
98 {
99 for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i)
100 if (droid_yuv_formats[i].native == native)
101 return true;
102
103 return false;
104 }
105
106 static int
107 get_format_bpp(int native)
108 {
109 int bpp;
110
111 switch (native) {
112 case HAL_PIXEL_FORMAT_RGBA_8888:
113 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
114 /*
115 * HACK: Hardcode this to RGBX_8888 as per cros_gralloc hack.
116 * TODO: Remove this once https://issuetracker.google.com/32077885 is fixed.
117 */
118 case HAL_PIXEL_FORMAT_RGBX_8888:
119 case HAL_PIXEL_FORMAT_BGRA_8888:
120 bpp = 4;
121 break;
122 case HAL_PIXEL_FORMAT_RGB_565:
123 bpp = 2;
124 break;
125 default:
126 bpp = 0;
127 break;
128 }
129
130 return bpp;
131 }
132
133 /* createImageFromFds requires fourcc format */
134 static int get_fourcc(int native)
135 {
136 switch (native) {
137 case HAL_PIXEL_FORMAT_RGB_565: return __DRI_IMAGE_FOURCC_RGB565;
138 case HAL_PIXEL_FORMAT_BGRA_8888: return __DRI_IMAGE_FOURCC_ARGB8888;
139 case HAL_PIXEL_FORMAT_RGBA_8888: return __DRI_IMAGE_FOURCC_ABGR8888;
140 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
141 /*
142 * HACK: Hardcode this to RGBX_8888 as per cros_gralloc hack.
143 * TODO: Remove this once https://issuetracker.google.com/32077885 is fixed.
144 */
145 case HAL_PIXEL_FORMAT_RGBX_8888: return __DRI_IMAGE_FOURCC_XBGR8888;
146 default:
147 _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", native);
148 }
149 return -1;
150 }
151
152 static int get_format(int format)
153 {
154 switch (format) {
155 case HAL_PIXEL_FORMAT_BGRA_8888: return __DRI_IMAGE_FORMAT_ARGB8888;
156 case HAL_PIXEL_FORMAT_RGB_565: return __DRI_IMAGE_FORMAT_RGB565;
157 case HAL_PIXEL_FORMAT_RGBA_8888: return __DRI_IMAGE_FORMAT_ABGR8888;
158 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
159 /*
160 * HACK: Hardcode this to RGBX_8888 as per cros_gralloc hack.
161 * TODO: Revert this once https://issuetracker.google.com/32077885 is fixed.
162 */
163 case HAL_PIXEL_FORMAT_RGBX_8888: return __DRI_IMAGE_FORMAT_XBGR8888;
164 default:
165 _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", format);
166 }
167 return -1;
168 }
169
170 /* returns # of fds, and by reference the actual fds */
171 static unsigned
172 get_native_buffer_fds(struct ANativeWindowBuffer *buf, int fds[3])
173 {
174 native_handle_t *handle = (native_handle_t *)buf->handle;
175
176 if (!handle)
177 return 0;
178
179 /*
180 * Various gralloc implementations exist, but the dma-buf fd tends
181 * to be first. Access it directly to avoid a dependency on specific
182 * gralloc versions.
183 */
184 for (int i = 0; i < handle->numFds; i++)
185 fds[i] = handle->data[i];
186
187 return handle->numFds;
188 }
189
190 #ifdef HAVE_DRM_GRALLOC
191 static int
192 get_native_buffer_name(struct ANativeWindowBuffer *buf)
193 {
194 return gralloc_drm_get_gem_handle(buf->handle);
195 }
196 #endif /* HAVE_DRM_GRALLOC */
197
198 static EGLBoolean
199 droid_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf)
200 {
201 int fence_fd;
202
203 if (dri2_surf->window->dequeueBuffer(dri2_surf->window, &dri2_surf->buffer,
204 &fence_fd))
205 return EGL_FALSE;
206
207 /* If access to the buffer is controlled by a sync fence, then block on the
208 * fence.
209 *
210 * It may be more performant to postpone blocking until there is an
211 * immediate need to write to the buffer. But doing so would require adding
212 * hooks to the DRI2 loader.
213 *
214 * From the ANativeWindow::dequeueBuffer documentation:
215 *
216 * The libsync fence file descriptor returned in the int pointed to by
217 * the fenceFd argument will refer to the fence that must signal
218 * before the dequeued buffer may be written to. A value of -1
219 * indicates that the caller may access the buffer immediately without
220 * waiting on a fence. If a valid file descriptor is returned (i.e.
221 * any value except -1) then the caller is responsible for closing the
222 * file descriptor.
223 */
224 if (fence_fd >= 0) {
225 /* From the SYNC_IOC_WAIT documentation in <linux/sync.h>:
226 *
227 * Waits indefinitely if timeout < 0.
228 */
229 int timeout = -1;
230 sync_wait(fence_fd, timeout);
231 close(fence_fd);
232 }
233
234 dri2_surf->buffer->common.incRef(&dri2_surf->buffer->common);
235
236 /* Record all the buffers created by ANativeWindow and update back buffer
237 * for updating buffer's age in swap_buffers.
238 */
239 EGLBoolean updated = EGL_FALSE;
240 for (int i = 0; i < dri2_surf->color_buffers_count; i++) {
241 if (!dri2_surf->color_buffers[i].buffer) {
242 dri2_surf->color_buffers[i].buffer = dri2_surf->buffer;
243 }
244 if (dri2_surf->color_buffers[i].buffer == dri2_surf->buffer) {
245 dri2_surf->back = &dri2_surf->color_buffers[i];
246 updated = EGL_TRUE;
247 break;
248 }
249 }
250
251 if (!updated) {
252 /* In case of all the buffers were recreated by ANativeWindow, reset
253 * the color_buffers
254 */
255 for (int i = 0; i < dri2_surf->color_buffers_count; i++) {
256 dri2_surf->color_buffers[i].buffer = NULL;
257 dri2_surf->color_buffers[i].age = 0;
258 }
259 dri2_surf->color_buffers[0].buffer = dri2_surf->buffer;
260 dri2_surf->back = &dri2_surf->color_buffers[0];
261 }
262
263 return EGL_TRUE;
264 }
265
266 static EGLBoolean
267 droid_window_enqueue_buffer(_EGLDisplay *disp, struct dri2_egl_surface *dri2_surf)
268 {
269 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
270
271 /* To avoid blocking other EGL calls, release the display mutex before
272 * we enter droid_window_enqueue_buffer() and re-acquire the mutex upon
273 * return.
274 */
275 mtx_unlock(&disp->Mutex);
276
277 /* Queue the buffer with stored out fence fd. The ANativeWindow or buffer
278 * consumer may choose to wait for the fence to signal before accessing
279 * it. If fence fd value is -1, buffer can be accessed by consumer
280 * immediately. Consumer or application shouldn't rely on timestamp
281 * associated with fence if the fence fd is -1.
282 *
283 * Ownership of fd is transferred to consumer after queueBuffer and the
284 * consumer is responsible for closing it. Caller must not use the fd
285 * after passing it to queueBuffer.
286 */
287 int fence_fd = dri2_surf->out_fence_fd;
288 dri2_surf->out_fence_fd = -1;
289 dri2_surf->window->queueBuffer(dri2_surf->window, dri2_surf->buffer,
290 fence_fd);
291
292 dri2_surf->buffer->common.decRef(&dri2_surf->buffer->common);
293 dri2_surf->buffer = NULL;
294 dri2_surf->back = NULL;
295
296 mtx_lock(&disp->Mutex);
297
298 if (dri2_surf->dri_image_back) {
299 dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
300 dri2_surf->dri_image_back = NULL;
301 }
302
303 return EGL_TRUE;
304 }
305
306 static void
307 droid_window_cancel_buffer(struct dri2_egl_surface *dri2_surf)
308 {
309 int ret;
310 int fence_fd = dri2_surf->out_fence_fd;
311
312 dri2_surf->out_fence_fd = -1;
313 ret = dri2_surf->window->cancelBuffer(dri2_surf->window,
314 dri2_surf->buffer, fence_fd);
315 if (ret < 0) {
316 _eglLog(_EGL_WARNING, "ANativeWindow::cancelBuffer failed");
317 dri2_surf->base.Lost = EGL_TRUE;
318 }
319 }
320
321 static bool
322 droid_set_shared_buffer_mode(_EGLDisplay *disp, _EGLSurface *surf, bool mode)
323 {
324 #if ANDROID_API_LEVEL >= 24
325 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
326 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
327 struct ANativeWindow *window = dri2_surf->window;
328
329 assert(surf->Type == EGL_WINDOW_BIT);
330 assert(_eglSurfaceHasMutableRenderBuffer(&dri2_surf->base));
331
332 _eglLog(_EGL_DEBUG, "%s: mode=%d", __func__, mode);
333
334 if (native_window_set_shared_buffer_mode(window, mode)) {
335 _eglLog(_EGL_WARNING, "failed native_window_set_shared_buffer_mode"
336 "(window=%p, mode=%d)", window, mode);
337 return false;
338 }
339
340 return true;
341 #else
342 _eglLog(_EGL_FATAL, "%s:%d: internal error: unreachable", __FILE__, __LINE__);
343 return false;
344 #endif
345 }
346
347 static _EGLSurface *
348 droid_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
349 _EGLConfig *conf, void *native_window,
350 const EGLint *attrib_list)
351 {
352 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
353 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
354 struct dri2_egl_surface *dri2_surf;
355 struct ANativeWindow *window = native_window;
356 const __DRIconfig *config;
357
358 dri2_surf = calloc(1, sizeof *dri2_surf);
359 if (!dri2_surf) {
360 _eglError(EGL_BAD_ALLOC, "droid_create_surface");
361 return NULL;
362 }
363
364 if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list,
365 true, native_window))
366 goto cleanup_surface;
367
368 if (type == EGL_WINDOW_BIT) {
369 int format;
370 int buffer_count;
371
372 if (window->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
373 _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");
374 goto cleanup_surface;
375 }
376 if (window->query(window, NATIVE_WINDOW_FORMAT, &format)) {
377 _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");
378 goto cleanup_surface;
379 }
380
381 /* Query ANativeWindow for MIN_UNDEQUEUED_BUFFER, set buffer count
382 * and allocate color_buffers.
383 */
384 if (window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
385 &buffer_count)) {
386 _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");
387 goto cleanup_surface;
388 }
389 if (native_window_set_buffer_count(window, buffer_count+1)) {
390 _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");
391 goto cleanup_surface;
392 }
393 dri2_surf->color_buffers = calloc(buffer_count+1,
394 sizeof(*dri2_surf->color_buffers));
395 if (!dri2_surf->color_buffers) {
396 _eglError(EGL_BAD_ALLOC, "droid_create_surface");
397 goto cleanup_surface;
398 }
399 dri2_surf->color_buffers_count = buffer_count+1;
400
401 if (format != dri2_conf->base.NativeVisualID) {
402 _eglLog(_EGL_WARNING, "Native format mismatch: 0x%x != 0x%x",
403 format, dri2_conf->base.NativeVisualID);
404 }
405
406 window->query(window, NATIVE_WINDOW_WIDTH, &dri2_surf->base.Width);
407 window->query(window, NATIVE_WINDOW_HEIGHT, &dri2_surf->base.Height);
408 }
409
410 config = dri2_get_dri_config(dri2_conf, type,
411 dri2_surf->base.GLColorspace);
412 if (!config) {
413 _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration");
414 goto cleanup_surface;
415 }
416
417 if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf))
418 goto cleanup_surface;
419
420 if (window) {
421 window->common.incRef(&window->common);
422 dri2_surf->window = window;
423 }
424
425 return &dri2_surf->base;
426
427 cleanup_surface:
428 if (dri2_surf->color_buffers_count)
429 free(dri2_surf->color_buffers);
430 free(dri2_surf);
431
432 return NULL;
433 }
434
435 static _EGLSurface *
436 droid_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
437 _EGLConfig *conf, void *native_window,
438 const EGLint *attrib_list)
439 {
440 return droid_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
441 native_window, attrib_list);
442 }
443
444 static _EGLSurface *
445 droid_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
446 _EGLConfig *conf, const EGLint *attrib_list)
447 {
448 return droid_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
449 NULL, attrib_list);
450 }
451
452 static EGLBoolean
453 droid_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
454 {
455 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
456 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
457
458 dri2_egl_surface_free_local_buffers(dri2_surf);
459
460 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
461 if (dri2_surf->buffer)
462 droid_window_cancel_buffer(dri2_surf);
463
464 dri2_surf->window->common.decRef(&dri2_surf->window->common);
465 }
466
467 if (dri2_surf->dri_image_back) {
468 _eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_back", __func__, __LINE__);
469 dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
470 dri2_surf->dri_image_back = NULL;
471 }
472
473 if (dri2_surf->dri_image_front) {
474 _eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_front", __func__, __LINE__);
475 dri2_dpy->image->destroyImage(dri2_surf->dri_image_front);
476 dri2_surf->dri_image_front = NULL;
477 }
478
479 dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
480
481 dri2_fini_surface(surf);
482 free(dri2_surf->color_buffers);
483 free(dri2_surf);
484
485 return EGL_TRUE;
486 }
487
488 static EGLBoolean
489 droid_swap_interval(_EGLDriver *drv, _EGLDisplay *disp,
490 _EGLSurface *surf, EGLint interval)
491 {
492 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
493 struct ANativeWindow *window = dri2_surf->window;
494
495 if (window->setSwapInterval(window, interval))
496 return EGL_FALSE;
497
498 surf->SwapInterval = interval;
499 return EGL_TRUE;
500 }
501
502 static int
503 update_buffers(struct dri2_egl_surface *dri2_surf)
504 {
505 if (dri2_surf->base.Lost)
506 return -1;
507
508 if (dri2_surf->base.Type != EGL_WINDOW_BIT)
509 return 0;
510
511 /* try to dequeue the next back buffer */
512 if (!dri2_surf->buffer && !droid_window_dequeue_buffer(dri2_surf)) {
513 _eglLog(_EGL_WARNING, "Could not dequeue buffer from native window");
514 dri2_surf->base.Lost = EGL_TRUE;
515 return -1;
516 }
517
518 /* free outdated buffers and update the surface size */
519 if (dri2_surf->base.Width != dri2_surf->buffer->width ||
520 dri2_surf->base.Height != dri2_surf->buffer->height) {
521 dri2_egl_surface_free_local_buffers(dri2_surf);
522 dri2_surf->base.Width = dri2_surf->buffer->width;
523 dri2_surf->base.Height = dri2_surf->buffer->height;
524 }
525
526 return 0;
527 }
528
529 static int
530 get_front_bo(struct dri2_egl_surface *dri2_surf, unsigned int format)
531 {
532 struct dri2_egl_display *dri2_dpy =
533 dri2_egl_display(dri2_surf->base.Resource.Display);
534
535 if (dri2_surf->dri_image_front)
536 return 0;
537
538 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
539 /* According current EGL spec, front buffer rendering
540 * for window surface is not supported now.
541 * and mesa doesn't have the implementation of this case.
542 * Add warning message, but not treat it as error.
543 */
544 _eglLog(_EGL_DEBUG, "DRI driver requested unsupported front buffer for window surface");
545 } else if (dri2_surf->base.Type == EGL_PBUFFER_BIT) {
546 dri2_surf->dri_image_front =
547 dri2_dpy->image->createImage(dri2_dpy->dri_screen,
548 dri2_surf->base.Width,
549 dri2_surf->base.Height,
550 format,
551 0,
552 dri2_surf);
553 if (!dri2_surf->dri_image_front) {
554 _eglLog(_EGL_WARNING, "dri2_image_front allocation failed");
555 return -1;
556 }
557 }
558
559 return 0;
560 }
561
562 static int
563 get_back_bo(struct dri2_egl_surface *dri2_surf)
564 {
565 struct dri2_egl_display *dri2_dpy =
566 dri2_egl_display(dri2_surf->base.Resource.Display);
567 int fourcc, pitch;
568 int offset = 0, fds[3];
569 unsigned num_fds;
570
571 if (dri2_surf->dri_image_back)
572 return 0;
573
574 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
575 if (!dri2_surf->buffer) {
576 _eglLog(_EGL_WARNING, "Could not get native buffer");
577 return -1;
578 }
579
580 num_fds = get_native_buffer_fds(dri2_surf->buffer, fds);
581 if (num_fds == 0) {
582 _eglLog(_EGL_WARNING, "Could not get native buffer FD");
583 return -1;
584 }
585
586 fourcc = get_fourcc(dri2_surf->buffer->format);
587
588 pitch = dri2_surf->buffer->stride *
589 get_format_bpp(dri2_surf->buffer->format);
590
591 if (fourcc == -1 || pitch == 0) {
592 _eglLog(_EGL_WARNING, "Invalid buffer fourcc(%x) or pitch(%d)",
593 fourcc, pitch);
594 return -1;
595 }
596
597 dri2_surf->dri_image_back =
598 dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
599 dri2_surf->base.Width,
600 dri2_surf->base.Height,
601 fourcc,
602 fds,
603 num_fds,
604 &pitch,
605 &offset,
606 dri2_surf);
607 if (!dri2_surf->dri_image_back) {
608 _eglLog(_EGL_WARNING, "failed to create DRI image from FD");
609 return -1;
610 }
611 } else if (dri2_surf->base.Type == EGL_PBUFFER_BIT) {
612 /* The EGL 1.5 spec states that pbuffers are single-buffered. Specifically,
613 * the spec states that they have a back buffer but no front buffer, in
614 * contrast to pixmaps, which have a front buffer but no back buffer.
615 *
616 * Single-buffered surfaces with no front buffer confuse Mesa; so we deviate
617 * from the spec, following the precedent of Mesa's EGL X11 platform. The
618 * X11 platform correctly assigns pbuffers to single-buffered configs, but
619 * assigns the pbuffer a front buffer instead of a back buffer.
620 *
621 * Pbuffers in the X11 platform mostly work today, so let's just copy its
622 * behavior instead of trying to fix (and hence potentially breaking) the
623 * world.
624 */
625 _eglLog(_EGL_DEBUG, "DRI driver requested unsupported back buffer for pbuffer surface");
626 }
627
628 return 0;
629 }
630
631 /* Some drivers will pass multiple bits in buffer_mask.
632 * For such case, will go through all the bits, and
633 * will not return error when unsupported buffer is requested, only
634 * return error when the allocation for supported buffer failed.
635 */
636 static int
637 droid_image_get_buffers(__DRIdrawable *driDrawable,
638 unsigned int format,
639 uint32_t *stamp,
640 void *loaderPrivate,
641 uint32_t buffer_mask,
642 struct __DRIimageList *images)
643 {
644 struct dri2_egl_surface *dri2_surf = loaderPrivate;
645
646 images->image_mask = 0;
647 images->front = NULL;
648 images->back = NULL;
649
650 if (update_buffers(dri2_surf) < 0)
651 return 0;
652
653 if (_eglSurfaceInSharedBufferMode(&dri2_surf->base)) {
654 if (get_back_bo(dri2_surf) < 0)
655 return 0;
656
657 /* We have dri_image_back because this is a window surface and
658 * get_back_bo() succeeded.
659 */
660 assert(dri2_surf->dri_image_back);
661 images->back = dri2_surf->dri_image_back;
662 images->image_mask |= __DRI_IMAGE_BUFFER_SHARED;
663
664 /* There exists no accompanying back nor front buffer. */
665 return 1;
666 }
667
668 if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
669 if (get_front_bo(dri2_surf, format) < 0)
670 return 0;
671
672 if (dri2_surf->dri_image_front) {
673 images->front = dri2_surf->dri_image_front;
674 images->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
675 }
676 }
677
678 if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) {
679 if (get_back_bo(dri2_surf) < 0)
680 return 0;
681
682 if (dri2_surf->dri_image_back) {
683 images->back = dri2_surf->dri_image_back;
684 images->image_mask |= __DRI_IMAGE_BUFFER_BACK;
685 }
686 }
687
688 return 1;
689 }
690
691 static EGLint
692 droid_query_buffer_age(_EGLDriver *drv,
693 _EGLDisplay *disp, _EGLSurface *surface)
694 {
695 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
696
697 if (update_buffers(dri2_surf) < 0) {
698 _eglError(EGL_BAD_ALLOC, "droid_query_buffer_age");
699 return -1;
700 }
701
702 return dri2_surf->back ? dri2_surf->back->age : 0;
703 }
704
705 static EGLBoolean
706 droid_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
707 {
708 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
709 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
710 const bool has_mutable_rb = _eglSurfaceHasMutableRenderBuffer(draw);
711
712 /* From the EGL_KHR_mutable_render_buffer spec (v12):
713 *
714 * If surface is a single-buffered window, pixmap, or pbuffer surface
715 * for which there is no pending change to the EGL_RENDER_BUFFER
716 * attribute, eglSwapBuffers has no effect.
717 */
718 if (has_mutable_rb &&
719 draw->RequestedRenderBuffer == EGL_SINGLE_BUFFER &&
720 draw->ActiveRenderBuffer == EGL_SINGLE_BUFFER) {
721 _eglLog(_EGL_DEBUG, "%s: remain in shared buffer mode", __func__);
722 return EGL_TRUE;
723 }
724
725 for (int i = 0; i < dri2_surf->color_buffers_count; i++) {
726 if (dri2_surf->color_buffers[i].age > 0)
727 dri2_surf->color_buffers[i].age++;
728 }
729
730 /* "XXX: we don't use get_back_bo() since it causes regressions in
731 * several dEQP tests.
732 */
733 if (dri2_surf->back)
734 dri2_surf->back->age = 1;
735
736 dri2_flush_drawable_for_swapbuffers(disp, draw);
737
738 /* dri2_surf->buffer can be null even when no error has occured. For
739 * example, if the user has called no GL rendering commands since the
740 * previous eglSwapBuffers, then the driver may have not triggered
741 * a callback to ANativeWindow::dequeueBuffer, in which case
742 * dri2_surf->buffer remains null.
743 */
744 if (dri2_surf->buffer)
745 droid_window_enqueue_buffer(disp, dri2_surf);
746
747 dri2_dpy->flush->invalidate(dri2_surf->dri_drawable);
748
749 /* Update the shared buffer mode */
750 if (has_mutable_rb &&
751 draw->ActiveRenderBuffer != draw->RequestedRenderBuffer) {
752 bool mode = (draw->RequestedRenderBuffer == EGL_SINGLE_BUFFER);
753 _eglLog(_EGL_DEBUG, "%s: change to shared buffer mode %d",
754 __func__, mode);
755
756 if (!droid_set_shared_buffer_mode(disp, draw, mode))
757 return EGL_FALSE;
758 draw->ActiveRenderBuffer = draw->RequestedRenderBuffer;
759 }
760
761 return EGL_TRUE;
762 }
763
764 #if ANDROID_API_LEVEL >= 23
765 static EGLBoolean
766 droid_set_damage_region(_EGLDriver *drv,
767 _EGLDisplay *disp,
768 _EGLSurface *draw, const EGLint* rects, EGLint n_rects)
769 {
770 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
771 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
772 android_native_rect_t* droid_rects = NULL;
773 int ret;
774
775 if (n_rects == 0)
776 return EGL_TRUE;
777
778 droid_rects = malloc(n_rects * sizeof(android_native_rect_t));
779 if (droid_rects == NULL)
780 return _eglError(EGL_BAD_ALLOC, "eglSetDamageRegionKHR");
781
782 for (EGLint num_drects = 0; num_drects < n_rects; num_drects++) {
783 EGLint i = num_drects * 4;
784 droid_rects[num_drects].left = rects[i];
785 droid_rects[num_drects].bottom = rects[i + 1];
786 droid_rects[num_drects].right = rects[i] + rects[i + 2];
787 droid_rects[num_drects].top = rects[i + 1] + rects[i + 3];
788 }
789
790 /*
791 * XXX/TODO: Need to check for other return values
792 */
793
794 ret = native_window_set_surface_damage(dri2_surf->window, droid_rects, n_rects);
795 free(droid_rects);
796
797 return ret == 0 ? EGL_TRUE : EGL_FALSE;
798 }
799 #endif
800
801 static _EGLImage *
802 droid_create_image_from_prime_fds_yuv(_EGLDisplay *disp, _EGLContext *ctx,
803 struct ANativeWindowBuffer *buf,
804 int num_fds, int fds[3])
805 {
806 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
807 struct android_ycbcr ycbcr;
808 size_t offsets[3];
809 size_t pitches[3];
810 enum chroma_order chroma_order;
811 int fourcc;
812 int ret;
813
814 if (!dri2_dpy->gralloc->lock_ycbcr) {
815 _eglLog(_EGL_WARNING, "Gralloc does not support lock_ycbcr");
816 return NULL;
817 }
818
819 memset(&ycbcr, 0, sizeof(ycbcr));
820 ret = dri2_dpy->gralloc->lock_ycbcr(dri2_dpy->gralloc, buf->handle,
821 0, 0, 0, 0, 0, &ycbcr);
822 if (ret) {
823 /* HACK: See droid_create_image_from_prime_fds() and
824 * https://issuetracker.google.com/32077885.*/
825 if (buf->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)
826 return NULL;
827
828 _eglLog(_EGL_WARNING, "gralloc->lock_ycbcr failed: %d", ret);
829 return NULL;
830 }
831 dri2_dpy->gralloc->unlock(dri2_dpy->gralloc, buf->handle);
832
833 /* When lock_ycbcr's usage argument contains no SW_READ/WRITE flags
834 * it will return the .y/.cb/.cr pointers based on a NULL pointer,
835 * so they can be interpreted as offsets. */
836 offsets[0] = (size_t)ycbcr.y;
837 /* We assume here that all the planes are located in one DMA-buf. */
838 if ((size_t)ycbcr.cr < (size_t)ycbcr.cb) {
839 chroma_order = YCrCb;
840 offsets[1] = (size_t)ycbcr.cr;
841 offsets[2] = (size_t)ycbcr.cb;
842 } else {
843 chroma_order = YCbCr;
844 offsets[1] = (size_t)ycbcr.cb;
845 offsets[2] = (size_t)ycbcr.cr;
846 }
847
848 /* .ystride is the line length (in bytes) of the Y plane,
849 * .cstride is the line length (in bytes) of any of the remaining
850 * Cb/Cr/CbCr planes, assumed to be the same for Cb and Cr for fully
851 * planar formats. */
852 pitches[0] = ycbcr.ystride;
853 pitches[1] = pitches[2] = ycbcr.cstride;
854
855 /* .chroma_step is the byte distance between the same chroma channel
856 * values of subsequent pixels, assumed to be the same for Cb and Cr. */
857 fourcc = get_fourcc_yuv(buf->format, chroma_order, ycbcr.chroma_step);
858 if (fourcc == -1) {
859 _eglLog(_EGL_WARNING, "unsupported YUV format, native = %x, chroma_order = %s, chroma_step = %d",
860 buf->format, chroma_order == YCbCr ? "YCbCr" : "YCrCb", ycbcr.chroma_step);
861 return NULL;
862 }
863
864 /*
865 * Since this is EGL_NATIVE_BUFFER_ANDROID don't assume that
866 * the single-fd case cannot happen. So handle eithe single
867 * fd or fd-per-plane case:
868 */
869 if (num_fds == 1) {
870 fds[2] = fds[1] = fds[0];
871 } else {
872 int expected_planes = (ycbcr.chroma_step == 2) ? 2 : 3;
873 assert(num_fds == expected_planes);
874 }
875
876 if (ycbcr.chroma_step == 2) {
877 /* Semi-planar Y + CbCr or Y + CrCb format. */
878 const EGLint attr_list_2plane[] = {
879 EGL_WIDTH, buf->width,
880 EGL_HEIGHT, buf->height,
881 EGL_LINUX_DRM_FOURCC_EXT, fourcc,
882 EGL_DMA_BUF_PLANE0_FD_EXT, fds[0],
883 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0],
884 EGL_DMA_BUF_PLANE0_OFFSET_EXT, offsets[0],
885 EGL_DMA_BUF_PLANE1_FD_EXT, fds[1],
886 EGL_DMA_BUF_PLANE1_PITCH_EXT, pitches[1],
887 EGL_DMA_BUF_PLANE1_OFFSET_EXT, offsets[1],
888 EGL_NONE, 0
889 };
890
891 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list_2plane);
892 } else {
893 /* Fully planar Y + Cb + Cr or Y + Cr + Cb format. */
894 const EGLint attr_list_3plane[] = {
895 EGL_WIDTH, buf->width,
896 EGL_HEIGHT, buf->height,
897 EGL_LINUX_DRM_FOURCC_EXT, fourcc,
898 EGL_DMA_BUF_PLANE0_FD_EXT, fds[0],
899 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0],
900 EGL_DMA_BUF_PLANE0_OFFSET_EXT, offsets[0],
901 EGL_DMA_BUF_PLANE1_FD_EXT, fds[1],
902 EGL_DMA_BUF_PLANE1_PITCH_EXT, pitches[1],
903 EGL_DMA_BUF_PLANE1_OFFSET_EXT, offsets[1],
904 EGL_DMA_BUF_PLANE2_FD_EXT, fds[2],
905 EGL_DMA_BUF_PLANE2_PITCH_EXT, pitches[2],
906 EGL_DMA_BUF_PLANE2_OFFSET_EXT, offsets[2],
907 EGL_NONE, 0
908 };
909
910 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list_3plane);
911 }
912 }
913
914 static _EGLImage *
915 droid_create_image_from_prime_fds(_EGLDisplay *disp, _EGLContext *ctx,
916 struct ANativeWindowBuffer *buf, int num_fds, int fds[3])
917 {
918 unsigned int pitch;
919
920 if (is_yuv(buf->format)) {
921 _EGLImage *image;
922
923 image = droid_create_image_from_prime_fds_yuv(disp, ctx, buf, num_fds, fds);
924 /*
925 * HACK: https://issuetracker.google.com/32077885
926 * There is no API available to properly query the IMPLEMENTATION_DEFINED
927 * format. As a workaround we rely here on gralloc allocating either
928 * an arbitrary YCbCr 4:2:0 or RGBX_8888, with the latter being recognized
929 * by lock_ycbcr failing.
930 */
931 if (image || buf->format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)
932 return image;
933 }
934
935 /*
936 * Non-YUV formats could *also* have multiple planes, such as ancillary
937 * color compression state buffer, but the rest of the code isn't ready
938 * yet to deal with modifiers:
939 */
940 assert(num_fds == 1);
941
942 const int fourcc = get_fourcc(buf->format);
943 if (fourcc == -1) {
944 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
945 return NULL;
946 }
947
948 pitch = buf->stride * get_format_bpp(buf->format);
949 if (pitch == 0) {
950 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
951 return NULL;
952 }
953
954 const EGLint attr_list[] = {
955 EGL_WIDTH, buf->width,
956 EGL_HEIGHT, buf->height,
957 EGL_LINUX_DRM_FOURCC_EXT, fourcc,
958 EGL_DMA_BUF_PLANE0_FD_EXT, fds[0],
959 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitch,
960 EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
961 EGL_NONE, 0
962 };
963
964 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list);
965 }
966
967 #ifdef HAVE_DRM_GRALLOC
968 static _EGLImage *
969 droid_create_image_from_name(_EGLDisplay *disp, _EGLContext *ctx,
970 struct ANativeWindowBuffer *buf)
971 {
972 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
973 struct dri2_egl_image *dri2_img;
974 int name;
975 int format;
976
977 name = get_native_buffer_name(buf);
978 if (!name) {
979 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
980 return NULL;
981 }
982
983 format = get_format(buf->format);
984 if (format == -1)
985 return NULL;
986
987 dri2_img = calloc(1, sizeof(*dri2_img));
988 if (!dri2_img) {
989 _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm");
990 return NULL;
991 }
992
993 _eglInitImage(&dri2_img->base, disp);
994
995 dri2_img->dri_image =
996 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
997 buf->width,
998 buf->height,
999 format,
1000 name,
1001 buf->stride,
1002 dri2_img);
1003 if (!dri2_img->dri_image) {
1004 free(dri2_img);
1005 _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm");
1006 return NULL;
1007 }
1008
1009 return &dri2_img->base;
1010 }
1011 #endif /* HAVE_DRM_GRALLOC */
1012
1013 static EGLBoolean
1014 droid_query_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
1015 EGLint attribute, EGLint *value)
1016 {
1017 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1018 switch (attribute) {
1019 case EGL_WIDTH:
1020 if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->window) {
1021 dri2_surf->window->query(dri2_surf->window,
1022 NATIVE_WINDOW_DEFAULT_WIDTH, value);
1023 return EGL_TRUE;
1024 }
1025 break;
1026 case EGL_HEIGHT:
1027 if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->window) {
1028 dri2_surf->window->query(dri2_surf->window,
1029 NATIVE_WINDOW_DEFAULT_HEIGHT, value);
1030 return EGL_TRUE;
1031 }
1032 break;
1033 default:
1034 break;
1035 }
1036 return _eglQuerySurface(drv, disp, surf, attribute, value);
1037 }
1038
1039 static _EGLImage *
1040 dri2_create_image_android_native_buffer(_EGLDisplay *disp,
1041 _EGLContext *ctx,
1042 struct ANativeWindowBuffer *buf)
1043 {
1044 int fds[3];
1045 unsigned num_fds;
1046
1047 if (ctx != NULL) {
1048 /* From the EGL_ANDROID_image_native_buffer spec:
1049 *
1050 * * If <target> is EGL_NATIVE_BUFFER_ANDROID and <ctx> is not
1051 * EGL_NO_CONTEXT, the error EGL_BAD_CONTEXT is generated.
1052 */
1053 _eglError(EGL_BAD_CONTEXT, "eglCreateEGLImageKHR: for "
1054 "EGL_NATIVE_BUFFER_ANDROID, the context must be "
1055 "EGL_NO_CONTEXT");
1056 return NULL;
1057 }
1058
1059 if (!buf || buf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC ||
1060 buf->common.version != sizeof(*buf)) {
1061 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
1062 return NULL;
1063 }
1064
1065 num_fds = get_native_buffer_fds(buf, fds);
1066 if (num_fds > 0)
1067 return droid_create_image_from_prime_fds(disp, ctx, buf, num_fds, fds);
1068
1069 #ifdef HAVE_DRM_GRALLOC
1070 return droid_create_image_from_name(disp, ctx, buf);
1071 #else
1072 return NULL;
1073 #endif
1074 }
1075
1076 static _EGLImage *
1077 droid_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
1078 _EGLContext *ctx, EGLenum target,
1079 EGLClientBuffer buffer, const EGLint *attr_list)
1080 {
1081 switch (target) {
1082 case EGL_NATIVE_BUFFER_ANDROID:
1083 return dri2_create_image_android_native_buffer(disp, ctx,
1084 (struct ANativeWindowBuffer *) buffer);
1085 default:
1086 return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
1087 }
1088 }
1089
1090 static void
1091 droid_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
1092 {
1093 }
1094
1095 #ifdef HAVE_DRM_GRALLOC
1096 static int
1097 droid_get_buffers_parse_attachments(struct dri2_egl_surface *dri2_surf,
1098 unsigned int *attachments, int count)
1099 {
1100 int num_buffers = 0;
1101
1102 /* fill dri2_surf->buffers */
1103 for (int i = 0; i < count * 2; i += 2) {
1104 __DRIbuffer *buf, *local;
1105
1106 assert(num_buffers < ARRAY_SIZE(dri2_surf->buffers));
1107 buf = &dri2_surf->buffers[num_buffers];
1108
1109 switch (attachments[i]) {
1110 case __DRI_BUFFER_BACK_LEFT:
1111 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
1112 buf->attachment = attachments[i];
1113 buf->name = get_native_buffer_name(dri2_surf->buffer);
1114 buf->cpp = get_format_bpp(dri2_surf->buffer->format);
1115 buf->pitch = dri2_surf->buffer->stride * buf->cpp;
1116 buf->flags = 0;
1117
1118 if (buf->name)
1119 num_buffers++;
1120
1121 break;
1122 }
1123 /* fall through for pbuffers */
1124 case __DRI_BUFFER_DEPTH:
1125 case __DRI_BUFFER_STENCIL:
1126 case __DRI_BUFFER_ACCUM:
1127 case __DRI_BUFFER_DEPTH_STENCIL:
1128 case __DRI_BUFFER_HIZ:
1129 local = dri2_egl_surface_alloc_local_buffer(dri2_surf,
1130 attachments[i], attachments[i + 1]);
1131
1132 if (local) {
1133 *buf = *local;
1134 num_buffers++;
1135 }
1136 break;
1137 case __DRI_BUFFER_FRONT_LEFT:
1138 case __DRI_BUFFER_FRONT_RIGHT:
1139 case __DRI_BUFFER_FAKE_FRONT_LEFT:
1140 case __DRI_BUFFER_FAKE_FRONT_RIGHT:
1141 case __DRI_BUFFER_BACK_RIGHT:
1142 default:
1143 /* no front or right buffers */
1144 break;
1145 }
1146 }
1147
1148 return num_buffers;
1149 }
1150
1151 static __DRIbuffer *
1152 droid_get_buffers_with_format(__DRIdrawable * driDrawable,
1153 int *width, int *height,
1154 unsigned int *attachments, int count,
1155 int *out_count, void *loaderPrivate)
1156 {
1157 struct dri2_egl_surface *dri2_surf = loaderPrivate;
1158
1159 if (update_buffers(dri2_surf) < 0)
1160 return NULL;
1161
1162 *out_count = droid_get_buffers_parse_attachments(dri2_surf, attachments, count);
1163
1164 if (width)
1165 *width = dri2_surf->base.Width;
1166 if (height)
1167 *height = dri2_surf->base.Height;
1168
1169 return dri2_surf->buffers;
1170 }
1171 #endif /* HAVE_DRM_GRALLOC */
1172
1173 static unsigned
1174 droid_get_capability(void *loaderPrivate, enum dri_loader_cap cap)
1175 {
1176 /* Note: loaderPrivate is _EGLDisplay* */
1177 switch (cap) {
1178 case DRI_LOADER_CAP_RGBA_ORDERING:
1179 return 1;
1180 default:
1181 return 0;
1182 }
1183 }
1184
1185 static EGLBoolean
1186 droid_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *disp)
1187 {
1188 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1189 static const struct {
1190 int format;
1191 unsigned int rgba_masks[4];
1192 } visuals[] = {
1193 { HAL_PIXEL_FORMAT_RGBA_8888, { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 } },
1194 { HAL_PIXEL_FORMAT_RGBX_8888, { 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 } },
1195 { HAL_PIXEL_FORMAT_RGB_565, { 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 } },
1196 { HAL_PIXEL_FORMAT_BGRA_8888, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 } },
1197 };
1198
1199 unsigned int format_count[ARRAY_SIZE(visuals)] = { 0 };
1200 int config_count = 0;
1201
1202 /* The nesting of loops is significant here. Also significant is the order
1203 * of the HAL pixel formats. Many Android apps (such as Google's official
1204 * NDK GLES2 example app), and even portions the core framework code (such
1205 * as SystemServiceManager in Nougat), incorrectly choose their EGLConfig.
1206 * They neglect to match the EGLConfig's EGL_NATIVE_VISUAL_ID against the
1207 * window's native format, and instead choose the first EGLConfig whose
1208 * channel sizes match those of the native window format while ignoring the
1209 * channel *ordering*.
1210 *
1211 * We can detect such buggy clients in logcat when they call
1212 * eglCreateSurface, by detecting the mismatch between the EGLConfig's
1213 * format and the window's format.
1214 *
1215 * As a workaround, we generate EGLConfigs such that all EGLConfigs for HAL
1216 * pixel format i precede those for HAL pixel format i+1. In my
1217 * (chadversary) testing on Android Nougat, this was good enough to pacify
1218 * the buggy clients.
1219 */
1220 for (int i = 0; i < ARRAY_SIZE(visuals); i++) {
1221 for (int j = 0; dri2_dpy->driver_configs[j]; j++) {
1222 const EGLint surface_type = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
1223
1224 const EGLint config_attrs[] = {
1225 EGL_NATIVE_VISUAL_ID, visuals[i].format,
1226 EGL_NATIVE_VISUAL_TYPE, visuals[i].format,
1227 EGL_FRAMEBUFFER_TARGET_ANDROID, EGL_TRUE,
1228 EGL_RECORDABLE_ANDROID, EGL_TRUE,
1229 EGL_NONE
1230 };
1231
1232 struct dri2_egl_config *dri2_conf =
1233 dri2_add_config(disp, dri2_dpy->driver_configs[j],
1234 config_count + 1, surface_type, config_attrs,
1235 visuals[i].rgba_masks);
1236 if (dri2_conf) {
1237 if (dri2_conf->base.ConfigID == config_count + 1)
1238 config_count++;
1239 format_count[i]++;
1240 }
1241 }
1242 }
1243
1244 for (int i = 0; i < ARRAY_SIZE(format_count); i++) {
1245 if (!format_count[i]) {
1246 _eglLog(_EGL_DEBUG, "No DRI config supports native format 0x%x",
1247 visuals[i].format);
1248 }
1249 }
1250
1251 return (config_count != 0);
1252 }
1253
1254 static const struct dri2_egl_display_vtbl droid_display_vtbl = {
1255 .authenticate = NULL,
1256 .create_window_surface = droid_create_window_surface,
1257 .create_pixmap_surface = dri2_fallback_create_pixmap_surface,
1258 .create_pbuffer_surface = droid_create_pbuffer_surface,
1259 .destroy_surface = droid_destroy_surface,
1260 .create_image = droid_create_image_khr,
1261 .swap_buffers = droid_swap_buffers,
1262 .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage, /* Android implements the function */
1263 .swap_buffers_region = dri2_fallback_swap_buffers_region,
1264 .swap_interval = droid_swap_interval,
1265 #if ANDROID_API_LEVEL >= 23
1266 .set_damage_region = droid_set_damage_region,
1267 #else
1268 .set_damage_region = dri2_fallback_set_damage_region,
1269 #endif
1270 .post_sub_buffer = dri2_fallback_post_sub_buffer,
1271 .copy_buffers = dri2_fallback_copy_buffers,
1272 .query_buffer_age = droid_query_buffer_age,
1273 .query_surface = droid_query_surface,
1274 .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
1275 .get_sync_values = dri2_fallback_get_sync_values,
1276 .get_dri_drawable = dri2_surface_get_dri_drawable,
1277 .set_shared_buffer_mode = droid_set_shared_buffer_mode,
1278 };
1279
1280 #ifdef HAVE_DRM_GRALLOC
1281 static const __DRIdri2LoaderExtension droid_dri2_loader_extension = {
1282 .base = { __DRI_DRI2_LOADER, 4 },
1283
1284 .getBuffers = NULL,
1285 .flushFrontBuffer = droid_flush_front_buffer,
1286 .getBuffersWithFormat = droid_get_buffers_with_format,
1287 .getCapability = droid_get_capability,
1288 };
1289
1290 static const __DRIextension *droid_dri2_loader_extensions[] = {
1291 &droid_dri2_loader_extension.base,
1292 &image_lookup_extension.base,
1293 &use_invalidate.base,
1294 /* No __DRI_MUTABLE_RENDER_BUFFER_LOADER because it requires
1295 * __DRI_IMAGE_LOADER.
1296 */
1297 NULL,
1298 };
1299 #endif /* HAVE_DRM_GRALLOC */
1300
1301 static const __DRIimageLoaderExtension droid_image_loader_extension = {
1302 .base = { __DRI_IMAGE_LOADER, 2 },
1303
1304 .getBuffers = droid_image_get_buffers,
1305 .flushFrontBuffer = droid_flush_front_buffer,
1306 .getCapability = droid_get_capability,
1307 };
1308
1309 static void
1310 droid_display_shared_buffer(__DRIdrawable *driDrawable, int fence_fd,
1311 void *loaderPrivate)
1312 {
1313 struct dri2_egl_surface *dri2_surf = loaderPrivate;
1314 struct ANativeWindowBuffer *old_buffer UNUSED = dri2_surf->buffer;
1315
1316 if (!_eglSurfaceInSharedBufferMode(&dri2_surf->base)) {
1317 _eglLog(_EGL_WARNING, "%s: internal error: buffer is not shared",
1318 __func__);
1319 return;
1320 }
1321
1322 if (fence_fd >= 0) {
1323 /* The driver's fence is more recent than the surface's out fence, if it
1324 * exists at all. So use the driver's fence.
1325 */
1326 if (dri2_surf->out_fence_fd >= 0) {
1327 close(dri2_surf->out_fence_fd);
1328 dri2_surf->out_fence_fd = -1;
1329 }
1330 } else if (dri2_surf->out_fence_fd >= 0) {
1331 fence_fd = dri2_surf->out_fence_fd;
1332 dri2_surf->out_fence_fd = -1;
1333 }
1334
1335 if (dri2_surf->window->queueBuffer(dri2_surf->window, dri2_surf->buffer,
1336 fence_fd)) {
1337 _eglLog(_EGL_WARNING, "%s: ANativeWindow::queueBuffer failed", __func__);
1338 close(fence_fd);
1339 return;
1340 }
1341
1342 fence_fd = -1;
1343
1344 if (dri2_surf->window->dequeueBuffer(dri2_surf->window, &dri2_surf->buffer,
1345 &fence_fd)) {
1346 /* Tear down the surface because it no longer has a back buffer. */
1347 struct dri2_egl_display *dri2_dpy =
1348 dri2_egl_display(dri2_surf->base.Resource.Display);
1349
1350 _eglLog(_EGL_WARNING, "%s: ANativeWindow::dequeueBuffer failed", __func__);
1351
1352 dri2_surf->base.Lost = true;
1353 dri2_surf->buffer = NULL;
1354 dri2_surf->back = NULL;
1355
1356 if (dri2_surf->dri_image_back) {
1357 dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
1358 dri2_surf->dri_image_back = NULL;
1359 }
1360
1361 dri2_dpy->flush->invalidate(dri2_surf->dri_drawable);
1362 return;
1363 }
1364
1365 if (fence_fd < 0)
1366 return;
1367
1368 /* Access to the buffer is controlled by a sync fence. Block on it.
1369 *
1370 * Ideally, we would submit the fence to the driver, and the driver would
1371 * postpone command execution until it signalled. But DRI lacks API for
1372 * that (as of 2018-04-11).
1373 *
1374 * SYNC_IOC_WAIT waits forever if timeout < 0
1375 */
1376 sync_wait(fence_fd, -1);
1377 close(fence_fd);
1378 }
1379
1380 static const __DRImutableRenderBufferLoaderExtension droid_mutable_render_buffer_extension = {
1381 .base = { __DRI_MUTABLE_RENDER_BUFFER_LOADER, 1 },
1382 .displaySharedBuffer = droid_display_shared_buffer,
1383 };
1384
1385 static const __DRIextension *droid_image_loader_extensions[] = {
1386 &droid_image_loader_extension.base,
1387 &image_lookup_extension.base,
1388 &use_invalidate.base,
1389 &droid_mutable_render_buffer_extension.base,
1390 NULL,
1391 };
1392
1393 static EGLBoolean
1394 droid_load_driver(_EGLDisplay *disp, bool swrast)
1395 {
1396 struct dri2_egl_display *dri2_dpy = disp->DriverData;
1397 const char *err;
1398
1399 dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
1400 if (dri2_dpy->driver_name == NULL)
1401 return false;
1402
1403 #ifdef HAVE_DRM_GRALLOC
1404 /* Handle control nodes using __DRI_DRI2_LOADER extension and GEM names
1405 * for backwards compatibility with drm_gralloc. (Do not use on new
1406 * systems.) */
1407 dri2_dpy->loader_extensions = droid_dri2_loader_extensions;
1408 if (!dri2_load_driver(disp)) {
1409 err = "DRI2: failed to load driver";
1410 goto error;
1411 }
1412 #else
1413 if (swrast) {
1414 /* Use kms swrast only with vgem / virtio_gpu.
1415 * virtio-gpu fallbacks to software rendering when 3D features
1416 * are unavailable since 6c5ab.
1417 */
1418 if (strcmp(dri2_dpy->driver_name, "vgem") == 0 ||
1419 strcmp(dri2_dpy->driver_name, "virtio_gpu") == 0) {
1420 free(dri2_dpy->driver_name);
1421 dri2_dpy->driver_name = strdup("kms_swrast");
1422 } else {
1423 err = "DRI3: failed to find software capable driver";
1424 goto error;
1425 }
1426 }
1427
1428 dri2_dpy->loader_extensions = droid_image_loader_extensions;
1429 if (!dri2_load_driver_dri3(disp)) {
1430 err = "DRI3: failed to load driver";
1431 goto error;
1432 }
1433 #endif
1434
1435 return true;
1436
1437 error:
1438 free(dri2_dpy->driver_name);
1439 dri2_dpy->driver_name = NULL;
1440 return false;
1441 }
1442
1443 static void
1444 droid_unload_driver(_EGLDisplay *disp)
1445 {
1446 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1447
1448 dlclose(dri2_dpy->driver);
1449 dri2_dpy->driver = NULL;
1450 free(dri2_dpy->driver_name);
1451 dri2_dpy->driver_name = NULL;
1452 }
1453
1454 static int
1455 droid_filter_device(_EGLDisplay *disp, int fd, const char *vendor)
1456 {
1457 drmVersionPtr ver = drmGetVersion(fd);
1458 if (!ver)
1459 return -1;
1460
1461 if (strcmp(vendor, ver->name) != 0) {
1462 drmFreeVersion(ver);
1463 return -1;
1464 }
1465
1466 drmFreeVersion(ver);
1467 return 0;
1468 }
1469
1470 static EGLBoolean
1471 droid_probe_device(_EGLDisplay *disp, bool swrast)
1472 {
1473 /* Check that the device is supported, by attempting to:
1474 * - load the dri module
1475 * - and, create a screen
1476 */
1477 if (!droid_load_driver(disp, swrast))
1478 return EGL_FALSE;
1479
1480 if (!dri2_create_screen(disp)) {
1481 _eglLog(_EGL_WARNING, "DRI2: failed to create screen");
1482 droid_unload_driver(disp);
1483 return EGL_FALSE;
1484 }
1485 return EGL_TRUE;
1486 }
1487
1488 #ifdef HAVE_DRM_GRALLOC
1489 static EGLBoolean
1490 droid_open_device(_EGLDisplay *disp, bool swrast)
1491 {
1492 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1493 int fd = -1, err = -EINVAL;
1494
1495 if (swrast)
1496 return EGL_FALSE;
1497
1498 if (dri2_dpy->gralloc->perform)
1499 err = dri2_dpy->gralloc->perform(dri2_dpy->gralloc,
1500 GRALLOC_MODULE_PERFORM_GET_DRM_FD,
1501 &fd);
1502 if (err || fd < 0) {
1503 _eglLog(_EGL_WARNING, "fail to get drm fd");
1504 return EGL_FALSE;
1505 }
1506
1507 dri2_dpy->fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1508 if (dri2_dpy->fd < 0)
1509 return EGL_FALSE;
1510
1511 if (drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER)
1512 return EGL_FALSE;
1513
1514 return droid_probe_device(disp, swrast);
1515 }
1516 #else
1517 static EGLBoolean
1518 droid_open_device(_EGLDisplay *disp, bool swrast)
1519 {
1520 #define MAX_DRM_DEVICES 64
1521 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1522 drmDevicePtr device, devices[MAX_DRM_DEVICES] = { NULL };
1523 int num_devices;
1524
1525 char *vendor_name = NULL;
1526 char vendor_buf[PROPERTY_VALUE_MAX];
1527
1528 #ifdef EGL_FORCE_RENDERNODE
1529 const unsigned node_type = DRM_NODE_RENDER;
1530 #else
1531 const unsigned node_type = swrast ? DRM_NODE_PRIMARY : DRM_NODE_RENDER;
1532 #endif
1533
1534 if (property_get("drm.gpu.vendor_name", vendor_buf, NULL) > 0)
1535 vendor_name = vendor_buf;
1536
1537 num_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices));
1538 if (num_devices < 0)
1539 return EGL_FALSE;
1540
1541 for (int i = 0; i < num_devices; i++) {
1542 device = devices[i];
1543
1544 if (!(device->available_nodes & (1 << node_type)))
1545 continue;
1546
1547 dri2_dpy->fd = loader_open_device(device->nodes[node_type]);
1548 if (dri2_dpy->fd < 0) {
1549 _eglLog(_EGL_WARNING, "%s() Failed to open DRM device %s",
1550 __func__, device->nodes[node_type]);
1551 continue;
1552 }
1553
1554 /* If a vendor is explicitly provided, we use only that.
1555 * Otherwise we fall-back the first device that is supported.
1556 */
1557 if (vendor_name) {
1558 if (droid_filter_device(disp, dri2_dpy->fd, vendor_name)) {
1559 /* Device does not match - try next device */
1560 close(dri2_dpy->fd);
1561 dri2_dpy->fd = -1;
1562 continue;
1563 }
1564 /* If the requested device matches - use it. Regardless if
1565 * init fails, do not fall-back to any other device.
1566 */
1567 if (!droid_probe_device(disp, false)) {
1568 close(dri2_dpy->fd);
1569 dri2_dpy->fd = -1;
1570 }
1571
1572 break;
1573 }
1574 if (droid_probe_device(disp, swrast))
1575 break;
1576
1577 /* No explicit request - attempt the next device */
1578 close(dri2_dpy->fd);
1579 dri2_dpy->fd = -1;
1580 }
1581 drmFreeDevices(devices, num_devices);
1582
1583 if (dri2_dpy->fd < 0) {
1584 _eglLog(_EGL_WARNING, "Failed to open %s DRM device",
1585 vendor_name ? "desired": "any");
1586 return EGL_FALSE;
1587 }
1588
1589 return EGL_TRUE;
1590 #undef MAX_DRM_DEVICES
1591 }
1592
1593 #endif
1594
1595 EGLBoolean
1596 dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *disp)
1597 {
1598 _EGLDevice *dev;
1599 bool device_opened = false;
1600 struct dri2_egl_display *dri2_dpy;
1601 const char *err;
1602 int ret;
1603
1604 dri2_dpy = calloc(1, sizeof(*dri2_dpy));
1605 if (!dri2_dpy)
1606 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
1607
1608 dri2_dpy->fd = -1;
1609 ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
1610 (const hw_module_t **)&dri2_dpy->gralloc);
1611 if (ret) {
1612 err = "DRI2: failed to get gralloc module";
1613 goto cleanup;
1614 }
1615
1616 disp->DriverData = (void *) dri2_dpy;
1617 if (!disp->Options.ForceSoftware)
1618 device_opened = droid_open_device(disp, false);
1619 if (!device_opened)
1620 device_opened = droid_open_device(disp, true);
1621
1622 if (!device_opened) {
1623 err = "DRI2: failed to open device";
1624 goto cleanup;
1625 }
1626
1627 dev = _eglAddDevice(dri2_dpy->fd, false);
1628 if (!dev) {
1629 err = "DRI2: failed to find EGLDevice";
1630 goto cleanup;
1631 }
1632
1633 disp->Device = dev;
1634
1635 if (!dri2_setup_extensions(disp)) {
1636 err = "DRI2: failed to setup extensions";
1637 goto cleanup;
1638 }
1639
1640 dri2_setup_screen(disp);
1641
1642 /* We set the maximum swap interval as 1 for Android platform, since it is
1643 * the maximum value supported by Android according to the value of
1644 * ANativeWindow::maxSwapInterval.
1645 */
1646 dri2_setup_swap_interval(disp, 1);
1647
1648 disp->Extensions.ANDROID_framebuffer_target = EGL_TRUE;
1649 disp->Extensions.ANDROID_image_native_buffer = EGL_TRUE;
1650 disp->Extensions.ANDROID_recordable = EGL_TRUE;
1651 disp->Extensions.EXT_buffer_age = EGL_TRUE;
1652 #if ANDROID_API_LEVEL >= 23
1653 disp->Extensions.KHR_partial_update = EGL_TRUE;
1654 #endif
1655 disp->Extensions.KHR_image = EGL_TRUE;
1656 #if ANDROID_API_LEVEL >= 24
1657 if (dri2_dpy->mutable_render_buffer &&
1658 dri2_dpy->loader_extensions == droid_image_loader_extensions) {
1659 disp->Extensions.KHR_mutable_render_buffer = EGL_TRUE;
1660 }
1661 #endif
1662
1663 /* Create configs *after* enabling extensions because presence of DRI
1664 * driver extensions can affect the capabilities of EGLConfigs.
1665 */
1666 if (!droid_add_configs_for_visuals(drv, disp)) {
1667 err = "DRI2: failed to add configs";
1668 goto cleanup;
1669 }
1670
1671 /* Fill vtbl last to prevent accidentally calling virtual function during
1672 * initialization.
1673 */
1674 dri2_dpy->vtbl = &droid_display_vtbl;
1675
1676 return EGL_TRUE;
1677
1678 cleanup:
1679 dri2_display_destroy(disp);
1680 return _eglError(EGL_NOT_INITIALIZED, err);
1681 }