gbm: Add buffer handling and visuals for fp16 formats
[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 static _EGLImage *
765 droid_create_image_from_prime_fds_yuv(_EGLDisplay *disp, _EGLContext *ctx,
766 struct ANativeWindowBuffer *buf,
767 int num_fds, int fds[3])
768 {
769 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
770 struct android_ycbcr ycbcr;
771 size_t offsets[3];
772 size_t pitches[3];
773 enum chroma_order chroma_order;
774 int fourcc;
775 int ret;
776
777 if (!dri2_dpy->gralloc->lock_ycbcr) {
778 _eglLog(_EGL_WARNING, "Gralloc does not support lock_ycbcr");
779 return NULL;
780 }
781
782 memset(&ycbcr, 0, sizeof(ycbcr));
783 ret = dri2_dpy->gralloc->lock_ycbcr(dri2_dpy->gralloc, buf->handle,
784 0, 0, 0, 0, 0, &ycbcr);
785 if (ret) {
786 /* HACK: See droid_create_image_from_prime_fds() and
787 * https://issuetracker.google.com/32077885.*/
788 if (buf->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)
789 return NULL;
790
791 _eglLog(_EGL_WARNING, "gralloc->lock_ycbcr failed: %d", ret);
792 return NULL;
793 }
794 dri2_dpy->gralloc->unlock(dri2_dpy->gralloc, buf->handle);
795
796 /* When lock_ycbcr's usage argument contains no SW_READ/WRITE flags
797 * it will return the .y/.cb/.cr pointers based on a NULL pointer,
798 * so they can be interpreted as offsets. */
799 offsets[0] = (size_t)ycbcr.y;
800 /* We assume here that all the planes are located in one DMA-buf. */
801 if ((size_t)ycbcr.cr < (size_t)ycbcr.cb) {
802 chroma_order = YCrCb;
803 offsets[1] = (size_t)ycbcr.cr;
804 offsets[2] = (size_t)ycbcr.cb;
805 } else {
806 chroma_order = YCbCr;
807 offsets[1] = (size_t)ycbcr.cb;
808 offsets[2] = (size_t)ycbcr.cr;
809 }
810
811 /* .ystride is the line length (in bytes) of the Y plane,
812 * .cstride is the line length (in bytes) of any of the remaining
813 * Cb/Cr/CbCr planes, assumed to be the same for Cb and Cr for fully
814 * planar formats. */
815 pitches[0] = ycbcr.ystride;
816 pitches[1] = pitches[2] = ycbcr.cstride;
817
818 /* .chroma_step is the byte distance between the same chroma channel
819 * values of subsequent pixels, assumed to be the same for Cb and Cr. */
820 fourcc = get_fourcc_yuv(buf->format, chroma_order, ycbcr.chroma_step);
821 if (fourcc == -1) {
822 _eglLog(_EGL_WARNING, "unsupported YUV format, native = %x, chroma_order = %s, chroma_step = %d",
823 buf->format, chroma_order == YCbCr ? "YCbCr" : "YCrCb", ycbcr.chroma_step);
824 return NULL;
825 }
826
827 /*
828 * Since this is EGL_NATIVE_BUFFER_ANDROID don't assume that
829 * the single-fd case cannot happen. So handle eithe single
830 * fd or fd-per-plane case:
831 */
832 if (num_fds == 1) {
833 fds[2] = fds[1] = fds[0];
834 } else {
835 int expected_planes = (ycbcr.chroma_step == 2) ? 2 : 3;
836 assert(num_fds == expected_planes);
837 }
838
839 if (ycbcr.chroma_step == 2) {
840 /* Semi-planar Y + CbCr or Y + CrCb format. */
841 const EGLint attr_list_2plane[] = {
842 EGL_WIDTH, buf->width,
843 EGL_HEIGHT, buf->height,
844 EGL_LINUX_DRM_FOURCC_EXT, fourcc,
845 EGL_DMA_BUF_PLANE0_FD_EXT, fds[0],
846 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0],
847 EGL_DMA_BUF_PLANE0_OFFSET_EXT, offsets[0],
848 EGL_DMA_BUF_PLANE1_FD_EXT, fds[1],
849 EGL_DMA_BUF_PLANE1_PITCH_EXT, pitches[1],
850 EGL_DMA_BUF_PLANE1_OFFSET_EXT, offsets[1],
851 EGL_NONE, 0
852 };
853
854 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list_2plane);
855 } else {
856 /* Fully planar Y + Cb + Cr or Y + Cr + Cb format. */
857 const EGLint attr_list_3plane[] = {
858 EGL_WIDTH, buf->width,
859 EGL_HEIGHT, buf->height,
860 EGL_LINUX_DRM_FOURCC_EXT, fourcc,
861 EGL_DMA_BUF_PLANE0_FD_EXT, fds[0],
862 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0],
863 EGL_DMA_BUF_PLANE0_OFFSET_EXT, offsets[0],
864 EGL_DMA_BUF_PLANE1_FD_EXT, fds[1],
865 EGL_DMA_BUF_PLANE1_PITCH_EXT, pitches[1],
866 EGL_DMA_BUF_PLANE1_OFFSET_EXT, offsets[1],
867 EGL_DMA_BUF_PLANE2_FD_EXT, fds[2],
868 EGL_DMA_BUF_PLANE2_PITCH_EXT, pitches[2],
869 EGL_DMA_BUF_PLANE2_OFFSET_EXT, offsets[2],
870 EGL_NONE, 0
871 };
872
873 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list_3plane);
874 }
875 }
876
877 static _EGLImage *
878 droid_create_image_from_prime_fds(_EGLDisplay *disp, _EGLContext *ctx,
879 struct ANativeWindowBuffer *buf, int num_fds, int fds[3])
880 {
881 unsigned int pitch;
882
883 if (is_yuv(buf->format)) {
884 _EGLImage *image;
885
886 image = droid_create_image_from_prime_fds_yuv(disp, ctx, buf, num_fds, fds);
887 /*
888 * HACK: https://issuetracker.google.com/32077885
889 * There is no API available to properly query the IMPLEMENTATION_DEFINED
890 * format. As a workaround we rely here on gralloc allocating either
891 * an arbitrary YCbCr 4:2:0 or RGBX_8888, with the latter being recognized
892 * by lock_ycbcr failing.
893 */
894 if (image || buf->format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)
895 return image;
896 }
897
898 /*
899 * Non-YUV formats could *also* have multiple planes, such as ancillary
900 * color compression state buffer, but the rest of the code isn't ready
901 * yet to deal with modifiers:
902 */
903 assert(num_fds == 1);
904
905 const int fourcc = get_fourcc(buf->format);
906 if (fourcc == -1) {
907 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
908 return NULL;
909 }
910
911 pitch = buf->stride * get_format_bpp(buf->format);
912 if (pitch == 0) {
913 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
914 return NULL;
915 }
916
917 const EGLint attr_list[] = {
918 EGL_WIDTH, buf->width,
919 EGL_HEIGHT, buf->height,
920 EGL_LINUX_DRM_FOURCC_EXT, fourcc,
921 EGL_DMA_BUF_PLANE0_FD_EXT, fds[0],
922 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitch,
923 EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
924 EGL_NONE, 0
925 };
926
927 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list);
928 }
929
930 #ifdef HAVE_DRM_GRALLOC
931 static _EGLImage *
932 droid_create_image_from_name(_EGLDisplay *disp, _EGLContext *ctx,
933 struct ANativeWindowBuffer *buf)
934 {
935 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
936 struct dri2_egl_image *dri2_img;
937 int name;
938 int format;
939
940 name = get_native_buffer_name(buf);
941 if (!name) {
942 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
943 return NULL;
944 }
945
946 format = get_format(buf->format);
947 if (format == -1)
948 return NULL;
949
950 dri2_img = calloc(1, sizeof(*dri2_img));
951 if (!dri2_img) {
952 _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm");
953 return NULL;
954 }
955
956 _eglInitImage(&dri2_img->base, disp);
957
958 dri2_img->dri_image =
959 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
960 buf->width,
961 buf->height,
962 format,
963 name,
964 buf->stride,
965 dri2_img);
966 if (!dri2_img->dri_image) {
967 free(dri2_img);
968 _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm");
969 return NULL;
970 }
971
972 return &dri2_img->base;
973 }
974 #endif /* HAVE_DRM_GRALLOC */
975
976 static EGLBoolean
977 droid_query_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
978 EGLint attribute, EGLint *value)
979 {
980 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
981 switch (attribute) {
982 case EGL_WIDTH:
983 if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->window) {
984 dri2_surf->window->query(dri2_surf->window,
985 NATIVE_WINDOW_DEFAULT_WIDTH, value);
986 return EGL_TRUE;
987 }
988 break;
989 case EGL_HEIGHT:
990 if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->window) {
991 dri2_surf->window->query(dri2_surf->window,
992 NATIVE_WINDOW_DEFAULT_HEIGHT, value);
993 return EGL_TRUE;
994 }
995 break;
996 default:
997 break;
998 }
999 return _eglQuerySurface(drv, disp, surf, attribute, value);
1000 }
1001
1002 static _EGLImage *
1003 dri2_create_image_android_native_buffer(_EGLDisplay *disp,
1004 _EGLContext *ctx,
1005 struct ANativeWindowBuffer *buf)
1006 {
1007 int fds[3];
1008 unsigned num_fds;
1009
1010 if (ctx != NULL) {
1011 /* From the EGL_ANDROID_image_native_buffer spec:
1012 *
1013 * * If <target> is EGL_NATIVE_BUFFER_ANDROID and <ctx> is not
1014 * EGL_NO_CONTEXT, the error EGL_BAD_CONTEXT is generated.
1015 */
1016 _eglError(EGL_BAD_CONTEXT, "eglCreateEGLImageKHR: for "
1017 "EGL_NATIVE_BUFFER_ANDROID, the context must be "
1018 "EGL_NO_CONTEXT");
1019 return NULL;
1020 }
1021
1022 if (!buf || buf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC ||
1023 buf->common.version != sizeof(*buf)) {
1024 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
1025 return NULL;
1026 }
1027
1028 num_fds = get_native_buffer_fds(buf, fds);
1029 if (num_fds > 0)
1030 return droid_create_image_from_prime_fds(disp, ctx, buf, num_fds, fds);
1031
1032 #ifdef HAVE_DRM_GRALLOC
1033 return droid_create_image_from_name(disp, ctx, buf);
1034 #else
1035 return NULL;
1036 #endif
1037 }
1038
1039 static _EGLImage *
1040 droid_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
1041 _EGLContext *ctx, EGLenum target,
1042 EGLClientBuffer buffer, const EGLint *attr_list)
1043 {
1044 switch (target) {
1045 case EGL_NATIVE_BUFFER_ANDROID:
1046 return dri2_create_image_android_native_buffer(disp, ctx,
1047 (struct ANativeWindowBuffer *) buffer);
1048 default:
1049 return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
1050 }
1051 }
1052
1053 static void
1054 droid_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
1055 {
1056 }
1057
1058 #ifdef HAVE_DRM_GRALLOC
1059 static int
1060 droid_get_buffers_parse_attachments(struct dri2_egl_surface *dri2_surf,
1061 unsigned int *attachments, int count)
1062 {
1063 int num_buffers = 0;
1064
1065 /* fill dri2_surf->buffers */
1066 for (int i = 0; i < count * 2; i += 2) {
1067 __DRIbuffer *buf, *local;
1068
1069 assert(num_buffers < ARRAY_SIZE(dri2_surf->buffers));
1070 buf = &dri2_surf->buffers[num_buffers];
1071
1072 switch (attachments[i]) {
1073 case __DRI_BUFFER_BACK_LEFT:
1074 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
1075 buf->attachment = attachments[i];
1076 buf->name = get_native_buffer_name(dri2_surf->buffer);
1077 buf->cpp = get_format_bpp(dri2_surf->buffer->format);
1078 buf->pitch = dri2_surf->buffer->stride * buf->cpp;
1079 buf->flags = 0;
1080
1081 if (buf->name)
1082 num_buffers++;
1083
1084 break;
1085 }
1086 /* fall through for pbuffers */
1087 case __DRI_BUFFER_DEPTH:
1088 case __DRI_BUFFER_STENCIL:
1089 case __DRI_BUFFER_ACCUM:
1090 case __DRI_BUFFER_DEPTH_STENCIL:
1091 case __DRI_BUFFER_HIZ:
1092 local = dri2_egl_surface_alloc_local_buffer(dri2_surf,
1093 attachments[i], attachments[i + 1]);
1094
1095 if (local) {
1096 *buf = *local;
1097 num_buffers++;
1098 }
1099 break;
1100 case __DRI_BUFFER_FRONT_LEFT:
1101 case __DRI_BUFFER_FRONT_RIGHT:
1102 case __DRI_BUFFER_FAKE_FRONT_LEFT:
1103 case __DRI_BUFFER_FAKE_FRONT_RIGHT:
1104 case __DRI_BUFFER_BACK_RIGHT:
1105 default:
1106 /* no front or right buffers */
1107 break;
1108 }
1109 }
1110
1111 return num_buffers;
1112 }
1113
1114 static __DRIbuffer *
1115 droid_get_buffers_with_format(__DRIdrawable * driDrawable,
1116 int *width, int *height,
1117 unsigned int *attachments, int count,
1118 int *out_count, void *loaderPrivate)
1119 {
1120 struct dri2_egl_surface *dri2_surf = loaderPrivate;
1121
1122 if (update_buffers(dri2_surf) < 0)
1123 return NULL;
1124
1125 *out_count = droid_get_buffers_parse_attachments(dri2_surf, attachments, count);
1126
1127 if (width)
1128 *width = dri2_surf->base.Width;
1129 if (height)
1130 *height = dri2_surf->base.Height;
1131
1132 return dri2_surf->buffers;
1133 }
1134 #endif /* HAVE_DRM_GRALLOC */
1135
1136 static unsigned
1137 droid_get_capability(void *loaderPrivate, enum dri_loader_cap cap)
1138 {
1139 /* Note: loaderPrivate is _EGLDisplay* */
1140 switch (cap) {
1141 case DRI_LOADER_CAP_RGBA_ORDERING:
1142 return 1;
1143 default:
1144 return 0;
1145 }
1146 }
1147
1148 static EGLBoolean
1149 droid_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *disp)
1150 {
1151 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1152 static const struct {
1153 int format;
1154 int rgba_shifts[4];
1155 unsigned int rgba_sizes[4];
1156 } visuals[] = {
1157 { HAL_PIXEL_FORMAT_RGBA_8888, { 0, 8, 16, 24 }, { 8, 8, 8, 8 } },
1158 { HAL_PIXEL_FORMAT_RGBX_8888, { 0, 8, 16, -1 }, { 8, 8, 8, 0 } },
1159 { HAL_PIXEL_FORMAT_RGB_565, { 11, 5, 0, -1 }, { 5, 6, 5, 0 } },
1160 { HAL_PIXEL_FORMAT_BGRA_8888, { 16, 8, 0, 24 }, { 8, 8, 8, 8 } },
1161 };
1162
1163 unsigned int format_count[ARRAY_SIZE(visuals)] = { 0 };
1164 int config_count = 0;
1165
1166 /* The nesting of loops is significant here. Also significant is the order
1167 * of the HAL pixel formats. Many Android apps (such as Google's official
1168 * NDK GLES2 example app), and even portions the core framework code (such
1169 * as SystemServiceManager in Nougat), incorrectly choose their EGLConfig.
1170 * They neglect to match the EGLConfig's EGL_NATIVE_VISUAL_ID against the
1171 * window's native format, and instead choose the first EGLConfig whose
1172 * channel sizes match those of the native window format while ignoring the
1173 * channel *ordering*.
1174 *
1175 * We can detect such buggy clients in logcat when they call
1176 * eglCreateSurface, by detecting the mismatch between the EGLConfig's
1177 * format and the window's format.
1178 *
1179 * As a workaround, we generate EGLConfigs such that all EGLConfigs for HAL
1180 * pixel format i precede those for HAL pixel format i+1. In my
1181 * (chadversary) testing on Android Nougat, this was good enough to pacify
1182 * the buggy clients.
1183 */
1184 for (int i = 0; i < ARRAY_SIZE(visuals); i++) {
1185 for (int j = 0; dri2_dpy->driver_configs[j]; j++) {
1186 const EGLint surface_type = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
1187
1188 const EGLint config_attrs[] = {
1189 EGL_NATIVE_VISUAL_ID, visuals[i].format,
1190 EGL_NATIVE_VISUAL_TYPE, visuals[i].format,
1191 EGL_FRAMEBUFFER_TARGET_ANDROID, EGL_TRUE,
1192 EGL_RECORDABLE_ANDROID, EGL_TRUE,
1193 EGL_NONE
1194 };
1195
1196 struct dri2_egl_config *dri2_conf =
1197 dri2_add_config(disp, dri2_dpy->driver_configs[j],
1198 config_count + 1, surface_type, config_attrs,
1199 visuals[i].rgba_shifts, visuals[i].rgba_sizes);
1200 if (dri2_conf) {
1201 if (dri2_conf->base.ConfigID == config_count + 1)
1202 config_count++;
1203 format_count[i]++;
1204 }
1205 }
1206 }
1207
1208 for (int i = 0; i < ARRAY_SIZE(format_count); i++) {
1209 if (!format_count[i]) {
1210 _eglLog(_EGL_DEBUG, "No DRI config supports native format 0x%x",
1211 visuals[i].format);
1212 }
1213 }
1214
1215 return (config_count != 0);
1216 }
1217
1218 static const struct dri2_egl_display_vtbl droid_display_vtbl = {
1219 .authenticate = NULL,
1220 .create_window_surface = droid_create_window_surface,
1221 .create_pixmap_surface = dri2_fallback_create_pixmap_surface,
1222 .create_pbuffer_surface = droid_create_pbuffer_surface,
1223 .destroy_surface = droid_destroy_surface,
1224 .create_image = droid_create_image_khr,
1225 .swap_buffers = droid_swap_buffers,
1226 .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage, /* Android implements the function */
1227 .swap_buffers_region = dri2_fallback_swap_buffers_region,
1228 .swap_interval = droid_swap_interval,
1229 .post_sub_buffer = dri2_fallback_post_sub_buffer,
1230 .copy_buffers = dri2_fallback_copy_buffers,
1231 .query_buffer_age = droid_query_buffer_age,
1232 .query_surface = droid_query_surface,
1233 .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
1234 .get_sync_values = dri2_fallback_get_sync_values,
1235 .get_dri_drawable = dri2_surface_get_dri_drawable,
1236 .set_shared_buffer_mode = droid_set_shared_buffer_mode,
1237 };
1238
1239 #ifdef HAVE_DRM_GRALLOC
1240 static const __DRIdri2LoaderExtension droid_dri2_loader_extension = {
1241 .base = { __DRI_DRI2_LOADER, 4 },
1242
1243 .getBuffers = NULL,
1244 .flushFrontBuffer = droid_flush_front_buffer,
1245 .getBuffersWithFormat = droid_get_buffers_with_format,
1246 .getCapability = droid_get_capability,
1247 };
1248
1249 static const __DRIextension *droid_dri2_loader_extensions[] = {
1250 &droid_dri2_loader_extension.base,
1251 &image_lookup_extension.base,
1252 &use_invalidate.base,
1253 /* No __DRI_MUTABLE_RENDER_BUFFER_LOADER because it requires
1254 * __DRI_IMAGE_LOADER.
1255 */
1256 NULL,
1257 };
1258 #endif /* HAVE_DRM_GRALLOC */
1259
1260 static const __DRIimageLoaderExtension droid_image_loader_extension = {
1261 .base = { __DRI_IMAGE_LOADER, 2 },
1262
1263 .getBuffers = droid_image_get_buffers,
1264 .flushFrontBuffer = droid_flush_front_buffer,
1265 .getCapability = droid_get_capability,
1266 };
1267
1268 static void
1269 droid_display_shared_buffer(__DRIdrawable *driDrawable, int fence_fd,
1270 void *loaderPrivate)
1271 {
1272 struct dri2_egl_surface *dri2_surf = loaderPrivate;
1273 struct ANativeWindowBuffer *old_buffer UNUSED = dri2_surf->buffer;
1274
1275 if (!_eglSurfaceInSharedBufferMode(&dri2_surf->base)) {
1276 _eglLog(_EGL_WARNING, "%s: internal error: buffer is not shared",
1277 __func__);
1278 return;
1279 }
1280
1281 if (fence_fd >= 0) {
1282 /* The driver's fence is more recent than the surface's out fence, if it
1283 * exists at all. So use the driver's fence.
1284 */
1285 if (dri2_surf->out_fence_fd >= 0) {
1286 close(dri2_surf->out_fence_fd);
1287 dri2_surf->out_fence_fd = -1;
1288 }
1289 } else if (dri2_surf->out_fence_fd >= 0) {
1290 fence_fd = dri2_surf->out_fence_fd;
1291 dri2_surf->out_fence_fd = -1;
1292 }
1293
1294 if (dri2_surf->window->queueBuffer(dri2_surf->window, dri2_surf->buffer,
1295 fence_fd)) {
1296 _eglLog(_EGL_WARNING, "%s: ANativeWindow::queueBuffer failed", __func__);
1297 close(fence_fd);
1298 return;
1299 }
1300
1301 fence_fd = -1;
1302
1303 if (dri2_surf->window->dequeueBuffer(dri2_surf->window, &dri2_surf->buffer,
1304 &fence_fd)) {
1305 /* Tear down the surface because it no longer has a back buffer. */
1306 struct dri2_egl_display *dri2_dpy =
1307 dri2_egl_display(dri2_surf->base.Resource.Display);
1308
1309 _eglLog(_EGL_WARNING, "%s: ANativeWindow::dequeueBuffer failed", __func__);
1310
1311 dri2_surf->base.Lost = true;
1312 dri2_surf->buffer = NULL;
1313 dri2_surf->back = NULL;
1314
1315 if (dri2_surf->dri_image_back) {
1316 dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
1317 dri2_surf->dri_image_back = NULL;
1318 }
1319
1320 dri2_dpy->flush->invalidate(dri2_surf->dri_drawable);
1321 return;
1322 }
1323
1324 if (fence_fd < 0)
1325 return;
1326
1327 /* Access to the buffer is controlled by a sync fence. Block on it.
1328 *
1329 * Ideally, we would submit the fence to the driver, and the driver would
1330 * postpone command execution until it signalled. But DRI lacks API for
1331 * that (as of 2018-04-11).
1332 *
1333 * SYNC_IOC_WAIT waits forever if timeout < 0
1334 */
1335 sync_wait(fence_fd, -1);
1336 close(fence_fd);
1337 }
1338
1339 static const __DRImutableRenderBufferLoaderExtension droid_mutable_render_buffer_extension = {
1340 .base = { __DRI_MUTABLE_RENDER_BUFFER_LOADER, 1 },
1341 .displaySharedBuffer = droid_display_shared_buffer,
1342 };
1343
1344 static const __DRIextension *droid_image_loader_extensions[] = {
1345 &droid_image_loader_extension.base,
1346 &image_lookup_extension.base,
1347 &use_invalidate.base,
1348 &droid_mutable_render_buffer_extension.base,
1349 NULL,
1350 };
1351
1352 static EGLBoolean
1353 droid_load_driver(_EGLDisplay *disp, bool swrast)
1354 {
1355 struct dri2_egl_display *dri2_dpy = disp->DriverData;
1356 const char *err;
1357
1358 dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
1359 if (dri2_dpy->driver_name == NULL)
1360 return false;
1361
1362 #ifdef HAVE_DRM_GRALLOC
1363 /* Handle control nodes using __DRI_DRI2_LOADER extension and GEM names
1364 * for backwards compatibility with drm_gralloc. (Do not use on new
1365 * systems.) */
1366 dri2_dpy->loader_extensions = droid_dri2_loader_extensions;
1367 if (!dri2_load_driver(disp)) {
1368 err = "DRI2: failed to load driver";
1369 goto error;
1370 }
1371 #else
1372 if (swrast) {
1373 /* Use kms swrast only with vgem / virtio_gpu.
1374 * virtio-gpu fallbacks to software rendering when 3D features
1375 * are unavailable since 6c5ab.
1376 */
1377 if (strcmp(dri2_dpy->driver_name, "vgem") == 0 ||
1378 strcmp(dri2_dpy->driver_name, "virtio_gpu") == 0) {
1379 free(dri2_dpy->driver_name);
1380 dri2_dpy->driver_name = strdup("kms_swrast");
1381 } else {
1382 err = "DRI3: failed to find software capable driver";
1383 goto error;
1384 }
1385 }
1386
1387 dri2_dpy->loader_extensions = droid_image_loader_extensions;
1388 if (!dri2_load_driver_dri3(disp)) {
1389 err = "DRI3: failed to load driver";
1390 goto error;
1391 }
1392 #endif
1393
1394 return true;
1395
1396 error:
1397 free(dri2_dpy->driver_name);
1398 dri2_dpy->driver_name = NULL;
1399 return false;
1400 }
1401
1402 static void
1403 droid_unload_driver(_EGLDisplay *disp)
1404 {
1405 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1406
1407 dlclose(dri2_dpy->driver);
1408 dri2_dpy->driver = NULL;
1409 free(dri2_dpy->driver_name);
1410 dri2_dpy->driver_name = NULL;
1411 }
1412
1413 static int
1414 droid_filter_device(_EGLDisplay *disp, int fd, const char *vendor)
1415 {
1416 drmVersionPtr ver = drmGetVersion(fd);
1417 if (!ver)
1418 return -1;
1419
1420 if (strcmp(vendor, ver->name) != 0) {
1421 drmFreeVersion(ver);
1422 return -1;
1423 }
1424
1425 drmFreeVersion(ver);
1426 return 0;
1427 }
1428
1429 static EGLBoolean
1430 droid_probe_device(_EGLDisplay *disp, bool swrast)
1431 {
1432 /* Check that the device is supported, by attempting to:
1433 * - load the dri module
1434 * - and, create a screen
1435 */
1436 if (!droid_load_driver(disp, swrast))
1437 return EGL_FALSE;
1438
1439 if (!dri2_create_screen(disp)) {
1440 _eglLog(_EGL_WARNING, "DRI2: failed to create screen");
1441 droid_unload_driver(disp);
1442 return EGL_FALSE;
1443 }
1444 return EGL_TRUE;
1445 }
1446
1447 #ifdef HAVE_DRM_GRALLOC
1448 static EGLBoolean
1449 droid_open_device(_EGLDisplay *disp, bool swrast)
1450 {
1451 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1452 int fd = -1, err = -EINVAL;
1453
1454 if (swrast)
1455 return EGL_FALSE;
1456
1457 if (dri2_dpy->gralloc->perform)
1458 err = dri2_dpy->gralloc->perform(dri2_dpy->gralloc,
1459 GRALLOC_MODULE_PERFORM_GET_DRM_FD,
1460 &fd);
1461 if (err || fd < 0) {
1462 _eglLog(_EGL_WARNING, "fail to get drm fd");
1463 return EGL_FALSE;
1464 }
1465
1466 dri2_dpy->fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1467 if (dri2_dpy->fd < 0)
1468 return EGL_FALSE;
1469
1470 if (drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER)
1471 return EGL_FALSE;
1472
1473 return droid_probe_device(disp, swrast);
1474 }
1475 #else
1476 static EGLBoolean
1477 droid_open_device(_EGLDisplay *disp, bool swrast)
1478 {
1479 #define MAX_DRM_DEVICES 64
1480 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1481 drmDevicePtr device, devices[MAX_DRM_DEVICES] = { NULL };
1482 int num_devices;
1483
1484 char *vendor_name = NULL;
1485 char vendor_buf[PROPERTY_VALUE_MAX];
1486
1487 #ifdef EGL_FORCE_RENDERNODE
1488 const unsigned node_type = DRM_NODE_RENDER;
1489 #else
1490 const unsigned node_type = swrast ? DRM_NODE_PRIMARY : DRM_NODE_RENDER;
1491 #endif
1492
1493 if (property_get("drm.gpu.vendor_name", vendor_buf, NULL) > 0)
1494 vendor_name = vendor_buf;
1495
1496 num_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices));
1497 if (num_devices < 0)
1498 return EGL_FALSE;
1499
1500 for (int i = 0; i < num_devices; i++) {
1501 device = devices[i];
1502
1503 if (!(device->available_nodes & (1 << node_type)))
1504 continue;
1505
1506 dri2_dpy->fd = loader_open_device(device->nodes[node_type]);
1507 if (dri2_dpy->fd < 0) {
1508 _eglLog(_EGL_WARNING, "%s() Failed to open DRM device %s",
1509 __func__, device->nodes[node_type]);
1510 continue;
1511 }
1512
1513 /* If a vendor is explicitly provided, we use only that.
1514 * Otherwise we fall-back the first device that is supported.
1515 */
1516 if (vendor_name) {
1517 if (droid_filter_device(disp, dri2_dpy->fd, vendor_name)) {
1518 /* Device does not match - try next device */
1519 close(dri2_dpy->fd);
1520 dri2_dpy->fd = -1;
1521 continue;
1522 }
1523 /* If the requested device matches - use it. Regardless if
1524 * init fails, do not fall-back to any other device.
1525 */
1526 if (!droid_probe_device(disp, false)) {
1527 close(dri2_dpy->fd);
1528 dri2_dpy->fd = -1;
1529 }
1530
1531 break;
1532 }
1533 if (droid_probe_device(disp, swrast))
1534 break;
1535
1536 /* No explicit request - attempt the next device */
1537 close(dri2_dpy->fd);
1538 dri2_dpy->fd = -1;
1539 }
1540 drmFreeDevices(devices, num_devices);
1541
1542 if (dri2_dpy->fd < 0) {
1543 _eglLog(_EGL_WARNING, "Failed to open %s DRM device",
1544 vendor_name ? "desired": "any");
1545 return EGL_FALSE;
1546 }
1547
1548 return EGL_TRUE;
1549 #undef MAX_DRM_DEVICES
1550 }
1551
1552 #endif
1553
1554 EGLBoolean
1555 dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *disp)
1556 {
1557 _EGLDevice *dev;
1558 bool device_opened = false;
1559 struct dri2_egl_display *dri2_dpy;
1560 const char *err;
1561 int ret;
1562
1563 dri2_dpy = calloc(1, sizeof(*dri2_dpy));
1564 if (!dri2_dpy)
1565 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
1566
1567 dri2_dpy->fd = -1;
1568 ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
1569 (const hw_module_t **)&dri2_dpy->gralloc);
1570 if (ret) {
1571 err = "DRI2: failed to get gralloc module";
1572 goto cleanup;
1573 }
1574
1575 disp->DriverData = (void *) dri2_dpy;
1576 if (!disp->Options.ForceSoftware)
1577 device_opened = droid_open_device(disp, false);
1578 if (!device_opened)
1579 device_opened = droid_open_device(disp, true);
1580
1581 if (!device_opened) {
1582 err = "DRI2: failed to open device";
1583 goto cleanup;
1584 }
1585
1586 dev = _eglAddDevice(dri2_dpy->fd, false);
1587 if (!dev) {
1588 err = "DRI2: failed to find EGLDevice";
1589 goto cleanup;
1590 }
1591
1592 disp->Device = dev;
1593
1594 if (!dri2_setup_extensions(disp)) {
1595 err = "DRI2: failed to setup extensions";
1596 goto cleanup;
1597 }
1598
1599 dri2_setup_screen(disp);
1600
1601 /* We set the maximum swap interval as 1 for Android platform, since it is
1602 * the maximum value supported by Android according to the value of
1603 * ANativeWindow::maxSwapInterval.
1604 */
1605 dri2_setup_swap_interval(disp, 1);
1606
1607 disp->Extensions.ANDROID_framebuffer_target = EGL_TRUE;
1608 disp->Extensions.ANDROID_image_native_buffer = EGL_TRUE;
1609 disp->Extensions.ANDROID_recordable = EGL_TRUE;
1610 disp->Extensions.EXT_buffer_age = EGL_TRUE;
1611 disp->Extensions.KHR_image = EGL_TRUE;
1612 #if ANDROID_API_LEVEL >= 24
1613 if (dri2_dpy->mutable_render_buffer &&
1614 dri2_dpy->loader_extensions == droid_image_loader_extensions) {
1615 disp->Extensions.KHR_mutable_render_buffer = EGL_TRUE;
1616 }
1617 #endif
1618
1619 /* Create configs *after* enabling extensions because presence of DRI
1620 * driver extensions can affect the capabilities of EGLConfigs.
1621 */
1622 if (!droid_add_configs_for_visuals(drv, disp)) {
1623 err = "DRI2: failed to add configs";
1624 goto cleanup;
1625 }
1626
1627 /* Fill vtbl last to prevent accidentally calling virtual function during
1628 * initialization.
1629 */
1630 dri2_dpy->vtbl = &droid_display_vtbl;
1631
1632 return EGL_TRUE;
1633
1634 cleanup:
1635 dri2_display_destroy(disp);
1636 return _eglError(EGL_NOT_INITIALIZED, err);
1637 }