egl: add EGL_BAD_MATCH error case for surfaceless and android
[mesa.git] / src / egl / drivers / dri2 / platform_android.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
5 * Copyright (C) 2010-2011 LunarG Inc.
6 *
7 * Based on platform_x11, which has
8 *
9 * Copyright © 2011 Intel Corporation
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included
19 * in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 * DEALINGS IN THE SOFTWARE.
28 */
29
30 #include <errno.h>
31 #include <dlfcn.h>
32 #include <fcntl.h>
33 #include <xf86drm.h>
34 #include <stdbool.h>
35 #include <sync/sync.h>
36
37 #include "loader.h"
38 #include "egl_dri2.h"
39 #include "egl_dri2_fallbacks.h"
40 #include "gralloc_drm.h"
41
42 #define ALIGN(val, align) (((val) + (align) - 1) & ~((align) - 1))
43
44 struct droid_yuv_format {
45 /* Lookup keys */
46 int native; /* HAL_PIXEL_FORMAT_ */
47 int is_ycrcb; /* 0 if chroma order is {Cb, Cr}, 1 if {Cr, Cb} */
48 int chroma_step; /* Distance in bytes between subsequent chroma pixels. */
49
50 /* Result */
51 int fourcc; /* __DRI_IMAGE_FOURCC_ */
52 };
53
54 /* The following table is used to look up a DRI image FourCC based
55 * on native format and information contained in android_ycbcr struct. */
56 static const struct droid_yuv_format droid_yuv_formats[] = {
57 /* Native format, YCrCb, Chroma step, DRI image FourCC */
58 { HAL_PIXEL_FORMAT_YCbCr_420_888, 0, 2, __DRI_IMAGE_FOURCC_NV12 },
59 { HAL_PIXEL_FORMAT_YCbCr_420_888, 0, 1, __DRI_IMAGE_FOURCC_YUV420 },
60 { HAL_PIXEL_FORMAT_YCbCr_420_888, 1, 1, __DRI_IMAGE_FOURCC_YVU420 },
61 { HAL_PIXEL_FORMAT_YV12, 1, 1, __DRI_IMAGE_FOURCC_YVU420 },
62 /* HACK: See droid_create_image_from_prime_fd() and
63 * https://issuetracker.google.com/32077885. */
64 { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 0, 2, __DRI_IMAGE_FOURCC_NV12 },
65 { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 0, 1, __DRI_IMAGE_FOURCC_YUV420 },
66 { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 1, 1, __DRI_IMAGE_FOURCC_YVU420 },
67 };
68
69 static int
70 get_fourcc_yuv(int native, int is_ycrcb, int chroma_step)
71 {
72 for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i)
73 if (droid_yuv_formats[i].native == native &&
74 droid_yuv_formats[i].is_ycrcb == is_ycrcb &&
75 droid_yuv_formats[i].chroma_step == chroma_step)
76 return droid_yuv_formats[i].fourcc;
77
78 return -1;
79 }
80
81 static bool
82 is_yuv(int native)
83 {
84 for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i)
85 if (droid_yuv_formats[i].native == native)
86 return true;
87
88 return false;
89 }
90
91 static int
92 get_format_bpp(int native)
93 {
94 int bpp;
95
96 switch (native) {
97 case HAL_PIXEL_FORMAT_RGBA_8888:
98 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
99 /*
100 * HACK: Hardcode this to RGBX_8888 as per cros_gralloc hack.
101 * TODO: Remove this once https://issuetracker.google.com/32077885 is fixed.
102 */
103 case HAL_PIXEL_FORMAT_RGBX_8888:
104 case HAL_PIXEL_FORMAT_BGRA_8888:
105 bpp = 4;
106 break;
107 case HAL_PIXEL_FORMAT_RGB_565:
108 bpp = 2;
109 break;
110 default:
111 bpp = 0;
112 break;
113 }
114
115 return bpp;
116 }
117
118 /* createImageFromFds requires fourcc format */
119 static int get_fourcc(int native)
120 {
121 switch (native) {
122 case HAL_PIXEL_FORMAT_RGB_565: return __DRI_IMAGE_FOURCC_RGB565;
123 case HAL_PIXEL_FORMAT_BGRA_8888: return __DRI_IMAGE_FOURCC_ARGB8888;
124 case HAL_PIXEL_FORMAT_RGBA_8888: return __DRI_IMAGE_FOURCC_ABGR8888;
125 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
126 /*
127 * HACK: Hardcode this to RGBX_8888 as per cros_gralloc hack.
128 * TODO: Remove this once https://issuetracker.google.com/32077885 is fixed.
129 */
130 case HAL_PIXEL_FORMAT_RGBX_8888: return __DRI_IMAGE_FOURCC_XBGR8888;
131 default:
132 _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", native);
133 }
134 return -1;
135 }
136
137 static int get_format(int format)
138 {
139 switch (format) {
140 case HAL_PIXEL_FORMAT_BGRA_8888: return __DRI_IMAGE_FORMAT_ARGB8888;
141 case HAL_PIXEL_FORMAT_RGB_565: return __DRI_IMAGE_FORMAT_RGB565;
142 case HAL_PIXEL_FORMAT_RGBA_8888: return __DRI_IMAGE_FORMAT_ABGR8888;
143 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
144 /*
145 * HACK: Hardcode this to RGBX_8888 as per cros_gralloc hack.
146 * TODO: Revert this once https://issuetracker.google.com/32077885 is fixed.
147 */
148 case HAL_PIXEL_FORMAT_RGBX_8888: return __DRI_IMAGE_FORMAT_XBGR8888;
149 default:
150 _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", format);
151 }
152 return -1;
153 }
154
155 static int
156 get_native_buffer_fd(struct ANativeWindowBuffer *buf)
157 {
158 native_handle_t *handle = (native_handle_t *)buf->handle;
159 /*
160 * Various gralloc implementations exist, but the dma-buf fd tends
161 * to be first. Access it directly to avoid a dependency on specific
162 * gralloc versions.
163 */
164 return (handle && handle->numFds) ? handle->data[0] : -1;
165 }
166
167 static int
168 get_native_buffer_name(struct ANativeWindowBuffer *buf)
169 {
170 return gralloc_drm_get_gem_handle(buf->handle);
171 }
172
173 static EGLBoolean
174 droid_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf)
175 {
176 int fence_fd;
177
178 if (dri2_surf->window->dequeueBuffer(dri2_surf->window, &dri2_surf->buffer,
179 &fence_fd))
180 return EGL_FALSE;
181
182 /* If access to the buffer is controlled by a sync fence, then block on the
183 * fence.
184 *
185 * It may be more performant to postpone blocking until there is an
186 * immediate need to write to the buffer. But doing so would require adding
187 * hooks to the DRI2 loader.
188 *
189 * From the ANativeWindow::dequeueBuffer documentation:
190 *
191 * The libsync fence file descriptor returned in the int pointed to by
192 * the fenceFd argument will refer to the fence that must signal
193 * before the dequeued buffer may be written to. A value of -1
194 * indicates that the caller may access the buffer immediately without
195 * waiting on a fence. If a valid file descriptor is returned (i.e.
196 * any value except -1) then the caller is responsible for closing the
197 * file descriptor.
198 */
199 if (fence_fd >= 0) {
200 /* From the SYNC_IOC_WAIT documentation in <linux/sync.h>:
201 *
202 * Waits indefinitely if timeout < 0.
203 */
204 int timeout = -1;
205 sync_wait(fence_fd, timeout);
206 close(fence_fd);
207 }
208
209 dri2_surf->buffer->common.incRef(&dri2_surf->buffer->common);
210
211 /* Record all the buffers created by ANativeWindow and update back buffer
212 * for updating buffer's age in swap_buffers.
213 */
214 EGLBoolean updated = EGL_FALSE;
215 for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
216 if (!dri2_surf->color_buffers[i].buffer) {
217 dri2_surf->color_buffers[i].buffer = dri2_surf->buffer;
218 }
219 if (dri2_surf->color_buffers[i].buffer == dri2_surf->buffer) {
220 dri2_surf->back = &dri2_surf->color_buffers[i];
221 updated = EGL_TRUE;
222 break;
223 }
224 }
225
226 if (!updated) {
227 /* In case of all the buffers were recreated by ANativeWindow, reset
228 * the color_buffers
229 */
230 for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
231 dri2_surf->color_buffers[i].buffer = NULL;
232 dri2_surf->color_buffers[i].age = 0;
233 }
234 dri2_surf->color_buffers[0].buffer = dri2_surf->buffer;
235 dri2_surf->back = &dri2_surf->color_buffers[0];
236 }
237
238 return EGL_TRUE;
239 }
240
241 static EGLBoolean
242 droid_window_enqueue_buffer(_EGLDisplay *disp, struct dri2_egl_surface *dri2_surf)
243 {
244 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
245
246 /* To avoid blocking other EGL calls, release the display mutex before
247 * we enter droid_window_enqueue_buffer() and re-acquire the mutex upon
248 * return.
249 */
250 mtx_unlock(&disp->Mutex);
251
252 /* Queue the buffer with stored out fence fd. The ANativeWindow or buffer
253 * consumer may choose to wait for the fence to signal before accessing
254 * it. If fence fd value is -1, buffer can be accessed by consumer
255 * immediately. Consumer or application shouldn't rely on timestamp
256 * associated with fence if the fence fd is -1.
257 *
258 * Ownership of fd is transferred to consumer after queueBuffer and the
259 * consumer is responsible for closing it. Caller must not use the fd
260 * after passing it to queueBuffer.
261 */
262 int fence_fd = dri2_surf->out_fence_fd;
263 dri2_surf->out_fence_fd = -1;
264 dri2_surf->window->queueBuffer(dri2_surf->window, dri2_surf->buffer,
265 fence_fd);
266
267 dri2_surf->buffer->common.decRef(&dri2_surf->buffer->common);
268 dri2_surf->buffer = NULL;
269 dri2_surf->back = NULL;
270
271 mtx_lock(&disp->Mutex);
272
273 if (dri2_surf->dri_image_back) {
274 dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
275 dri2_surf->dri_image_back = NULL;
276 }
277
278 return EGL_TRUE;
279 }
280
281 static void
282 droid_window_cancel_buffer(struct dri2_egl_surface *dri2_surf)
283 {
284 int ret;
285 int fence_fd = dri2_surf->out_fence_fd;
286
287 dri2_surf->out_fence_fd = -1;
288 ret = dri2_surf->window->cancelBuffer(dri2_surf->window,
289 dri2_surf->buffer, fence_fd);
290 if (ret < 0) {
291 _eglLog(_EGL_WARNING, "ANativeWindow::cancelBuffer failed");
292 dri2_surf->base.Lost = EGL_TRUE;
293 }
294 }
295
296 static _EGLSurface *
297 droid_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
298 _EGLConfig *conf, void *native_window,
299 const EGLint *attrib_list)
300 {
301 __DRIcreateNewDrawableFunc createNewDrawable;
302 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
303 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
304 struct dri2_egl_surface *dri2_surf;
305 struct ANativeWindow *window = native_window;
306 const __DRIconfig *config;
307
308 dri2_surf = calloc(1, sizeof *dri2_surf);
309 if (!dri2_surf) {
310 _eglError(EGL_BAD_ALLOC, "droid_create_surface");
311 return NULL;
312 }
313
314 if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list, true))
315 goto cleanup_surface;
316
317 if (type == EGL_WINDOW_BIT) {
318 int format;
319
320 if (window->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
321 _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");
322 goto cleanup_surface;
323 }
324 if (window->query(window, NATIVE_WINDOW_FORMAT, &format)) {
325 _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");
326 goto cleanup_surface;
327 }
328
329 if (format != dri2_conf->base.NativeVisualID) {
330 _eglLog(_EGL_WARNING, "Native format mismatch: 0x%x != 0x%x",
331 format, dri2_conf->base.NativeVisualID);
332 }
333
334 window->query(window, NATIVE_WINDOW_WIDTH, &dri2_surf->base.Width);
335 window->query(window, NATIVE_WINDOW_HEIGHT, &dri2_surf->base.Height);
336 }
337
338 config = dri2_get_dri_config(dri2_conf, type,
339 dri2_surf->base.GLColorspace);
340 if (!config) {
341 _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration");
342 goto cleanup_surface;
343 }
344
345 if (dri2_dpy->image_driver)
346 createNewDrawable = dri2_dpy->image_driver->createNewDrawable;
347 else
348 createNewDrawable = dri2_dpy->dri2->createNewDrawable;
349
350 dri2_surf->dri_drawable = (*createNewDrawable)(dri2_dpy->dri_screen, config,
351 dri2_surf);
352 if (dri2_surf->dri_drawable == NULL) {
353 _eglError(EGL_BAD_ALLOC, "createNewDrawable");
354 goto cleanup_surface;
355 }
356
357 if (window) {
358 window->common.incRef(&window->common);
359 dri2_surf->window = window;
360 }
361
362 return &dri2_surf->base;
363
364 cleanup_surface:
365 free(dri2_surf);
366
367 return NULL;
368 }
369
370 static _EGLSurface *
371 droid_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
372 _EGLConfig *conf, void *native_window,
373 const EGLint *attrib_list)
374 {
375 return droid_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
376 native_window, attrib_list);
377 }
378
379 static _EGLSurface *
380 droid_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
381 _EGLConfig *conf, const EGLint *attrib_list)
382 {
383 return droid_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
384 NULL, attrib_list);
385 }
386
387 static EGLBoolean
388 droid_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
389 {
390 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
391 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
392
393 dri2_egl_surface_free_local_buffers(dri2_surf);
394
395 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
396 if (dri2_surf->buffer)
397 droid_window_cancel_buffer(dri2_surf);
398
399 dri2_surf->window->common.decRef(&dri2_surf->window->common);
400 }
401
402 if (dri2_surf->dri_image_back) {
403 _eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_back", __func__, __LINE__);
404 dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
405 dri2_surf->dri_image_back = NULL;
406 }
407
408 if (dri2_surf->dri_image_front) {
409 _eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_front", __func__, __LINE__);
410 dri2_dpy->image->destroyImage(dri2_surf->dri_image_front);
411 dri2_surf->dri_image_front = NULL;
412 }
413
414 dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
415
416 dri2_fini_surface(surf);
417 free(dri2_surf);
418
419 return EGL_TRUE;
420 }
421
422 static EGLBoolean
423 droid_swap_interval(_EGLDriver *drv, _EGLDisplay *dpy,
424 _EGLSurface *surf, EGLint interval)
425 {
426 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
427 struct ANativeWindow *window = dri2_surf->window;
428
429 if (window->setSwapInterval(window, interval))
430 return EGL_FALSE;
431
432 surf->SwapInterval = interval;
433 return EGL_TRUE;
434 }
435
436 static int
437 update_buffers(struct dri2_egl_surface *dri2_surf)
438 {
439 if (dri2_surf->base.Lost)
440 return -1;
441
442 if (dri2_surf->base.Type != EGL_WINDOW_BIT)
443 return 0;
444
445 /* try to dequeue the next back buffer */
446 if (!dri2_surf->buffer && !droid_window_dequeue_buffer(dri2_surf)) {
447 _eglLog(_EGL_WARNING, "Could not dequeue buffer from native window");
448 dri2_surf->base.Lost = EGL_TRUE;
449 return -1;
450 }
451
452 /* free outdated buffers and update the surface size */
453 if (dri2_surf->base.Width != dri2_surf->buffer->width ||
454 dri2_surf->base.Height != dri2_surf->buffer->height) {
455 dri2_egl_surface_free_local_buffers(dri2_surf);
456 dri2_surf->base.Width = dri2_surf->buffer->width;
457 dri2_surf->base.Height = dri2_surf->buffer->height;
458 }
459
460 return 0;
461 }
462
463 static int
464 get_front_bo(struct dri2_egl_surface *dri2_surf, unsigned int format)
465 {
466 struct dri2_egl_display *dri2_dpy =
467 dri2_egl_display(dri2_surf->base.Resource.Display);
468
469 if (dri2_surf->dri_image_front)
470 return 0;
471
472 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
473 /* According current EGL spec, front buffer rendering
474 * for window surface is not supported now.
475 * and mesa doesn't have the implementation of this case.
476 * Add warning message, but not treat it as error.
477 */
478 _eglLog(_EGL_DEBUG, "DRI driver requested unsupported front buffer for window surface");
479 } else if (dri2_surf->base.Type == EGL_PBUFFER_BIT) {
480 dri2_surf->dri_image_front =
481 dri2_dpy->image->createImage(dri2_dpy->dri_screen,
482 dri2_surf->base.Width,
483 dri2_surf->base.Height,
484 format,
485 0,
486 dri2_surf);
487 if (!dri2_surf->dri_image_front) {
488 _eglLog(_EGL_WARNING, "dri2_image_front allocation failed");
489 return -1;
490 }
491 }
492
493 return 0;
494 }
495
496 static int
497 get_back_bo(struct dri2_egl_surface *dri2_surf)
498 {
499 struct dri2_egl_display *dri2_dpy =
500 dri2_egl_display(dri2_surf->base.Resource.Display);
501 int fourcc, pitch;
502 int offset = 0, fd;
503
504 if (dri2_surf->dri_image_back)
505 return 0;
506
507 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
508 if (!dri2_surf->buffer) {
509 _eglLog(_EGL_WARNING, "Could not get native buffer");
510 return -1;
511 }
512
513 fd = get_native_buffer_fd(dri2_surf->buffer);
514 if (fd < 0) {
515 _eglLog(_EGL_WARNING, "Could not get native buffer FD");
516 return -1;
517 }
518
519 fourcc = get_fourcc(dri2_surf->buffer->format);
520
521 pitch = dri2_surf->buffer->stride *
522 get_format_bpp(dri2_surf->buffer->format);
523
524 if (fourcc == -1 || pitch == 0) {
525 _eglLog(_EGL_WARNING, "Invalid buffer fourcc(%x) or pitch(%d)",
526 fourcc, pitch);
527 return -1;
528 }
529
530 dri2_surf->dri_image_back =
531 dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
532 dri2_surf->base.Width,
533 dri2_surf->base.Height,
534 fourcc,
535 &fd,
536 1,
537 &pitch,
538 &offset,
539 dri2_surf);
540 if (!dri2_surf->dri_image_back) {
541 _eglLog(_EGL_WARNING, "failed to create DRI image from FD");
542 return -1;
543 }
544 } else if (dri2_surf->base.Type == EGL_PBUFFER_BIT) {
545 /* The EGL 1.5 spec states that pbuffers are single-buffered. Specifically,
546 * the spec states that they have a back buffer but no front buffer, in
547 * contrast to pixmaps, which have a front buffer but no back buffer.
548 *
549 * Single-buffered surfaces with no front buffer confuse Mesa; so we deviate
550 * from the spec, following the precedent of Mesa's EGL X11 platform. The
551 * X11 platform correctly assigns pbuffers to single-buffered configs, but
552 * assigns the pbuffer a front buffer instead of a back buffer.
553 *
554 * Pbuffers in the X11 platform mostly work today, so let's just copy its
555 * behavior instead of trying to fix (and hence potentially breaking) the
556 * world.
557 */
558 _eglLog(_EGL_DEBUG, "DRI driver requested unsupported back buffer for pbuffer surface");
559 }
560
561 return 0;
562 }
563
564 /* Some drivers will pass multiple bits in buffer_mask.
565 * For such case, will go through all the bits, and
566 * will not return error when unsupported buffer is requested, only
567 * return error when the allocation for supported buffer failed.
568 */
569 static int
570 droid_image_get_buffers(__DRIdrawable *driDrawable,
571 unsigned int format,
572 uint32_t *stamp,
573 void *loaderPrivate,
574 uint32_t buffer_mask,
575 struct __DRIimageList *images)
576 {
577 struct dri2_egl_surface *dri2_surf = loaderPrivate;
578
579 images->image_mask = 0;
580 images->front = NULL;
581 images->back = NULL;
582
583 if (update_buffers(dri2_surf) < 0)
584 return 0;
585
586 if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
587 if (get_front_bo(dri2_surf, format) < 0)
588 return 0;
589
590 if (dri2_surf->dri_image_front) {
591 images->front = dri2_surf->dri_image_front;
592 images->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
593 }
594 }
595
596 if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) {
597 if (get_back_bo(dri2_surf) < 0)
598 return 0;
599
600 if (dri2_surf->dri_image_back) {
601 images->back = dri2_surf->dri_image_back;
602 images->image_mask |= __DRI_IMAGE_BUFFER_BACK;
603 }
604 }
605
606 return 1;
607 }
608
609 static EGLint
610 droid_query_buffer_age(_EGLDriver *drv,
611 _EGLDisplay *disp, _EGLSurface *surface)
612 {
613 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
614
615 if (update_buffers(dri2_surf) < 0) {
616 _eglError(EGL_BAD_ALLOC, "droid_query_buffer_age");
617 return -1;
618 }
619
620 return dri2_surf->back ? dri2_surf->back->age : 0;
621 }
622
623 static EGLBoolean
624 droid_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
625 {
626 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
627 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
628
629 if (dri2_surf->base.Type != EGL_WINDOW_BIT)
630 return EGL_TRUE;
631
632 for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
633 if (dri2_surf->color_buffers[i].age > 0)
634 dri2_surf->color_buffers[i].age++;
635 }
636
637 /* "XXX: we don't use get_back_bo() since it causes regressions in
638 * several dEQP tests.
639 */
640 if (dri2_surf->back)
641 dri2_surf->back->age = 1;
642
643 dri2_flush_drawable_for_swapbuffers(disp, draw);
644
645 /* dri2_surf->buffer can be null even when no error has occured. For
646 * example, if the user has called no GL rendering commands since the
647 * previous eglSwapBuffers, then the driver may have not triggered
648 * a callback to ANativeWindow::dequeueBuffer, in which case
649 * dri2_surf->buffer remains null.
650 */
651 if (dri2_surf->buffer)
652 droid_window_enqueue_buffer(disp, dri2_surf);
653
654 dri2_dpy->flush->invalidate(dri2_surf->dri_drawable);
655
656 return EGL_TRUE;
657 }
658
659 #if ANDROID_API_LEVEL >= 23
660 static EGLBoolean
661 droid_set_damage_region(_EGLDriver *drv,
662 _EGLDisplay *disp,
663 _EGLSurface *draw, const EGLint* rects, EGLint n_rects)
664 {
665 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
666 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
667 android_native_rect_t* droid_rects = NULL;
668 int ret;
669
670 if (n_rects == 0)
671 return EGL_TRUE;
672
673 droid_rects = malloc(n_rects * sizeof(android_native_rect_t));
674 if (droid_rects == NULL)
675 return _eglError(EGL_BAD_ALLOC, "eglSetDamageRegionKHR");
676
677 for (EGLint num_drects = 0; num_drects < n_rects; num_drects++) {
678 EGLint i = num_drects * 4;
679 droid_rects[num_drects].left = rects[i];
680 droid_rects[num_drects].bottom = rects[i + 1];
681 droid_rects[num_drects].right = rects[i] + rects[i + 2];
682 droid_rects[num_drects].top = rects[i + 1] + rects[i + 3];
683 }
684
685 /*
686 * XXX/TODO: Need to check for other return values
687 */
688
689 ret = native_window_set_surface_damage(dri2_surf->window, droid_rects, n_rects);
690 free(droid_rects);
691
692 return ret == 0 ? EGL_TRUE : EGL_FALSE;
693 }
694 #endif
695
696 static _EGLImage *
697 droid_create_image_from_prime_fd_yuv(_EGLDisplay *disp, _EGLContext *ctx,
698 struct ANativeWindowBuffer *buf, int fd)
699 {
700 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
701 struct android_ycbcr ycbcr;
702 size_t offsets[3];
703 size_t pitches[3];
704 int is_ycrcb;
705 int fourcc;
706 int ret;
707
708 if (!dri2_dpy->gralloc->lock_ycbcr) {
709 _eglLog(_EGL_WARNING, "Gralloc does not support lock_ycbcr");
710 return NULL;
711 }
712
713 memset(&ycbcr, 0, sizeof(ycbcr));
714 ret = dri2_dpy->gralloc->lock_ycbcr(dri2_dpy->gralloc, buf->handle,
715 0, 0, 0, 0, 0, &ycbcr);
716 if (ret) {
717 /* HACK: See droid_create_image_from_prime_fd() and
718 * https://issuetracker.google.com/32077885.*/
719 if (buf->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)
720 return NULL;
721
722 _eglLog(_EGL_WARNING, "gralloc->lock_ycbcr failed: %d", ret);
723 return NULL;
724 }
725 dri2_dpy->gralloc->unlock(dri2_dpy->gralloc, buf->handle);
726
727 /* When lock_ycbcr's usage argument contains no SW_READ/WRITE flags
728 * it will return the .y/.cb/.cr pointers based on a NULL pointer,
729 * so they can be interpreted as offsets. */
730 offsets[0] = (size_t)ycbcr.y;
731 /* We assume here that all the planes are located in one DMA-buf. */
732 is_ycrcb = (size_t)ycbcr.cr < (size_t)ycbcr.cb;
733 if (is_ycrcb) {
734 offsets[1] = (size_t)ycbcr.cr;
735 offsets[2] = (size_t)ycbcr.cb;
736 } else {
737 offsets[1] = (size_t)ycbcr.cb;
738 offsets[2] = (size_t)ycbcr.cr;
739 }
740
741 /* .ystride is the line length (in bytes) of the Y plane,
742 * .cstride is the line length (in bytes) of any of the remaining
743 * Cb/Cr/CbCr planes, assumed to be the same for Cb and Cr for fully
744 * planar formats. */
745 pitches[0] = ycbcr.ystride;
746 pitches[1] = pitches[2] = ycbcr.cstride;
747
748 /* .chroma_step is the byte distance between the same chroma channel
749 * values of subsequent pixels, assumed to be the same for Cb and Cr. */
750 fourcc = get_fourcc_yuv(buf->format, is_ycrcb, ycbcr.chroma_step);
751 if (fourcc == -1) {
752 _eglLog(_EGL_WARNING, "unsupported YUV format, native = %x, is_ycrcb = %d, chroma_step = %d",
753 buf->format, is_ycrcb, ycbcr.chroma_step);
754 return NULL;
755 }
756
757 if (ycbcr.chroma_step == 2) {
758 /* Semi-planar Y + CbCr or Y + CrCb format. */
759 const EGLint attr_list_2plane[] = {
760 EGL_WIDTH, buf->width,
761 EGL_HEIGHT, buf->height,
762 EGL_LINUX_DRM_FOURCC_EXT, fourcc,
763 EGL_DMA_BUF_PLANE0_FD_EXT, fd,
764 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0],
765 EGL_DMA_BUF_PLANE0_OFFSET_EXT, offsets[0],
766 EGL_DMA_BUF_PLANE1_FD_EXT, fd,
767 EGL_DMA_BUF_PLANE1_PITCH_EXT, pitches[1],
768 EGL_DMA_BUF_PLANE1_OFFSET_EXT, offsets[1],
769 EGL_NONE, 0
770 };
771
772 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list_2plane);
773 } else {
774 /* Fully planar Y + Cb + Cr or Y + Cr + Cb format. */
775 const EGLint attr_list_3plane[] = {
776 EGL_WIDTH, buf->width,
777 EGL_HEIGHT, buf->height,
778 EGL_LINUX_DRM_FOURCC_EXT, fourcc,
779 EGL_DMA_BUF_PLANE0_FD_EXT, fd,
780 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0],
781 EGL_DMA_BUF_PLANE0_OFFSET_EXT, offsets[0],
782 EGL_DMA_BUF_PLANE1_FD_EXT, fd,
783 EGL_DMA_BUF_PLANE1_PITCH_EXT, pitches[1],
784 EGL_DMA_BUF_PLANE1_OFFSET_EXT, offsets[1],
785 EGL_DMA_BUF_PLANE2_FD_EXT, fd,
786 EGL_DMA_BUF_PLANE2_PITCH_EXT, pitches[2],
787 EGL_DMA_BUF_PLANE2_OFFSET_EXT, offsets[2],
788 EGL_NONE, 0
789 };
790
791 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list_3plane);
792 }
793 }
794
795 static _EGLImage *
796 droid_create_image_from_prime_fd(_EGLDisplay *disp, _EGLContext *ctx,
797 struct ANativeWindowBuffer *buf, int fd)
798 {
799 unsigned int pitch;
800
801 if (is_yuv(buf->format)) {
802 _EGLImage *image;
803
804 image = droid_create_image_from_prime_fd_yuv(disp, ctx, buf, fd);
805 /*
806 * HACK: https://issuetracker.google.com/32077885
807 * There is no API available to properly query the IMPLEMENTATION_DEFINED
808 * format. As a workaround we rely here on gralloc allocating either
809 * an arbitrary YCbCr 4:2:0 or RGBX_8888, with the latter being recognized
810 * by lock_ycbcr failing.
811 */
812 if (image || buf->format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)
813 return image;
814 }
815
816 const int fourcc = get_fourcc(buf->format);
817 if (fourcc == -1) {
818 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
819 return NULL;
820 }
821
822 pitch = buf->stride * get_format_bpp(buf->format);
823 if (pitch == 0) {
824 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
825 return NULL;
826 }
827
828 const EGLint attr_list[] = {
829 EGL_WIDTH, buf->width,
830 EGL_HEIGHT, buf->height,
831 EGL_LINUX_DRM_FOURCC_EXT, fourcc,
832 EGL_DMA_BUF_PLANE0_FD_EXT, fd,
833 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitch,
834 EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
835 EGL_NONE, 0
836 };
837
838 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list);
839 }
840
841 static _EGLImage *
842 droid_create_image_from_name(_EGLDisplay *disp, _EGLContext *ctx,
843 struct ANativeWindowBuffer *buf)
844 {
845 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
846 struct dri2_egl_image *dri2_img;
847 int name;
848 int format;
849
850 name = get_native_buffer_name(buf);
851 if (!name) {
852 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
853 return NULL;
854 }
855
856 format = get_format(buf->format);
857 if (format == -1)
858 return NULL;
859
860 dri2_img = calloc(1, sizeof(*dri2_img));
861 if (!dri2_img) {
862 _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm");
863 return NULL;
864 }
865
866 _eglInitImage(&dri2_img->base, disp);
867
868 dri2_img->dri_image =
869 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
870 buf->width,
871 buf->height,
872 format,
873 name,
874 buf->stride,
875 dri2_img);
876 if (!dri2_img->dri_image) {
877 free(dri2_img);
878 _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm");
879 return NULL;
880 }
881
882 return &dri2_img->base;
883 }
884
885 static EGLBoolean
886 droid_query_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
887 EGLint attribute, EGLint *value)
888 {
889 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
890 switch (attribute) {
891 case EGL_WIDTH:
892 if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->window) {
893 dri2_surf->window->query(dri2_surf->window,
894 NATIVE_WINDOW_DEFAULT_WIDTH, value);
895 return EGL_TRUE;
896 }
897 break;
898 case EGL_HEIGHT:
899 if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->window) {
900 dri2_surf->window->query(dri2_surf->window,
901 NATIVE_WINDOW_DEFAULT_HEIGHT, value);
902 return EGL_TRUE;
903 }
904 break;
905 default:
906 break;
907 }
908 return _eglQuerySurface(drv, dpy, surf, attribute, value);
909 }
910
911 static _EGLImage *
912 dri2_create_image_android_native_buffer(_EGLDisplay *disp,
913 _EGLContext *ctx,
914 struct ANativeWindowBuffer *buf)
915 {
916 int fd;
917
918 if (ctx != NULL) {
919 /* From the EGL_ANDROID_image_native_buffer spec:
920 *
921 * * If <target> is EGL_NATIVE_BUFFER_ANDROID and <ctx> is not
922 * EGL_NO_CONTEXT, the error EGL_BAD_CONTEXT is generated.
923 */
924 _eglError(EGL_BAD_CONTEXT, "eglCreateEGLImageKHR: for "
925 "EGL_NATIVE_BUFFER_ANDROID, the context must be "
926 "EGL_NO_CONTEXT");
927 return NULL;
928 }
929
930 if (!buf || buf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC ||
931 buf->common.version != sizeof(*buf)) {
932 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
933 return NULL;
934 }
935
936 fd = get_native_buffer_fd(buf);
937 if (fd >= 0)
938 return droid_create_image_from_prime_fd(disp, ctx, buf, fd);
939
940 return droid_create_image_from_name(disp, ctx, buf);
941 }
942
943 static _EGLImage *
944 droid_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
945 _EGLContext *ctx, EGLenum target,
946 EGLClientBuffer buffer, const EGLint *attr_list)
947 {
948 switch (target) {
949 case EGL_NATIVE_BUFFER_ANDROID:
950 return dri2_create_image_android_native_buffer(disp, ctx,
951 (struct ANativeWindowBuffer *) buffer);
952 default:
953 return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
954 }
955 }
956
957 static void
958 droid_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
959 {
960 }
961
962 static int
963 droid_get_buffers_parse_attachments(struct dri2_egl_surface *dri2_surf,
964 unsigned int *attachments, int count)
965 {
966 int num_buffers = 0;
967
968 /* fill dri2_surf->buffers */
969 for (int i = 0; i < count * 2; i += 2) {
970 __DRIbuffer *buf, *local;
971
972 assert(num_buffers < ARRAY_SIZE(dri2_surf->buffers));
973 buf = &dri2_surf->buffers[num_buffers];
974
975 switch (attachments[i]) {
976 case __DRI_BUFFER_BACK_LEFT:
977 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
978 buf->attachment = attachments[i];
979 buf->name = get_native_buffer_name(dri2_surf->buffer);
980 buf->cpp = get_format_bpp(dri2_surf->buffer->format);
981 buf->pitch = dri2_surf->buffer->stride * buf->cpp;
982 buf->flags = 0;
983
984 if (buf->name)
985 num_buffers++;
986
987 break;
988 }
989 /* fall through for pbuffers */
990 case __DRI_BUFFER_DEPTH:
991 case __DRI_BUFFER_STENCIL:
992 case __DRI_BUFFER_ACCUM:
993 case __DRI_BUFFER_DEPTH_STENCIL:
994 case __DRI_BUFFER_HIZ:
995 local = dri2_egl_surface_alloc_local_buffer(dri2_surf,
996 attachments[i], attachments[i + 1]);
997
998 if (local) {
999 *buf = *local;
1000 num_buffers++;
1001 }
1002 break;
1003 case __DRI_BUFFER_FRONT_LEFT:
1004 case __DRI_BUFFER_FRONT_RIGHT:
1005 case __DRI_BUFFER_FAKE_FRONT_LEFT:
1006 case __DRI_BUFFER_FAKE_FRONT_RIGHT:
1007 case __DRI_BUFFER_BACK_RIGHT:
1008 default:
1009 /* no front or right buffers */
1010 break;
1011 }
1012 }
1013
1014 return num_buffers;
1015 }
1016
1017 static __DRIbuffer *
1018 droid_get_buffers_with_format(__DRIdrawable * driDrawable,
1019 int *width, int *height,
1020 unsigned int *attachments, int count,
1021 int *out_count, void *loaderPrivate)
1022 {
1023 struct dri2_egl_surface *dri2_surf = loaderPrivate;
1024
1025 if (update_buffers(dri2_surf) < 0)
1026 return NULL;
1027
1028 *out_count = droid_get_buffers_parse_attachments(dri2_surf, attachments, count);
1029
1030 if (width)
1031 *width = dri2_surf->base.Width;
1032 if (height)
1033 *height = dri2_surf->base.Height;
1034
1035 return dri2_surf->buffers;
1036 }
1037
1038 static unsigned
1039 droid_get_capability(void *loaderPrivate, enum dri_loader_cap cap)
1040 {
1041 /* Note: loaderPrivate is _EGLDisplay* */
1042 switch (cap) {
1043 case DRI_LOADER_CAP_RGBA_ORDERING:
1044 return 1;
1045 default:
1046 return 0;
1047 }
1048 }
1049
1050 static EGLBoolean
1051 droid_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *dpy)
1052 {
1053 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1054 static const struct {
1055 int format;
1056 unsigned int rgba_masks[4];
1057 } visuals[] = {
1058 { HAL_PIXEL_FORMAT_RGBA_8888, { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 } },
1059 { HAL_PIXEL_FORMAT_RGBX_8888, { 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 } },
1060 { HAL_PIXEL_FORMAT_RGB_565, { 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 } },
1061 { HAL_PIXEL_FORMAT_BGRA_8888, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 } },
1062 };
1063
1064 unsigned int format_count[ARRAY_SIZE(visuals)] = { 0 };
1065 int config_count = 0;
1066
1067 /* The nesting of loops is significant here. Also significant is the order
1068 * of the HAL pixel formats. Many Android apps (such as Google's official
1069 * NDK GLES2 example app), and even portions the core framework code (such
1070 * as SystemServiceManager in Nougat), incorrectly choose their EGLConfig.
1071 * They neglect to match the EGLConfig's EGL_NATIVE_VISUAL_ID against the
1072 * window's native format, and instead choose the first EGLConfig whose
1073 * channel sizes match those of the native window format while ignoring the
1074 * channel *ordering*.
1075 *
1076 * We can detect such buggy clients in logcat when they call
1077 * eglCreateSurface, by detecting the mismatch between the EGLConfig's
1078 * format and the window's format.
1079 *
1080 * As a workaround, we generate EGLConfigs such that all EGLConfigs for HAL
1081 * pixel format i precede those for HAL pixel format i+1. In my
1082 * (chadversary) testing on Android Nougat, this was good enough to pacify
1083 * the buggy clients.
1084 */
1085 for (int i = 0; i < ARRAY_SIZE(visuals); i++) {
1086 for (int j = 0; dri2_dpy->driver_configs[j]; j++) {
1087 const EGLint surface_type = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
1088
1089 const EGLint config_attrs[] = {
1090 EGL_NATIVE_VISUAL_ID, visuals[i].format,
1091 EGL_NATIVE_VISUAL_TYPE, visuals[i].format,
1092 EGL_FRAMEBUFFER_TARGET_ANDROID, EGL_TRUE,
1093 EGL_RECORDABLE_ANDROID, EGL_TRUE,
1094 EGL_NONE
1095 };
1096
1097 struct dri2_egl_config *dri2_conf =
1098 dri2_add_config(dpy, dri2_dpy->driver_configs[j],
1099 config_count + 1, surface_type, config_attrs,
1100 visuals[i].rgba_masks);
1101 if (dri2_conf) {
1102 if (dri2_conf->base.ConfigID == config_count + 1)
1103 config_count++;
1104 format_count[i]++;
1105 }
1106 }
1107 }
1108
1109 for (int i = 0; i < ARRAY_SIZE(format_count); i++) {
1110 if (!format_count[i]) {
1111 _eglLog(_EGL_DEBUG, "No DRI config supports native format 0x%x",
1112 visuals[i].format);
1113 }
1114 }
1115
1116 return (config_count != 0);
1117 }
1118
1119 static int
1120 droid_open_device(struct dri2_egl_display *dri2_dpy)
1121 {
1122 int fd = -1, err = -EINVAL;
1123
1124 if (dri2_dpy->gralloc->perform)
1125 err = dri2_dpy->gralloc->perform(dri2_dpy->gralloc,
1126 GRALLOC_MODULE_PERFORM_GET_DRM_FD,
1127 &fd);
1128 if (err || fd < 0) {
1129 _eglLog(_EGL_WARNING, "fail to get drm fd");
1130 fd = -1;
1131 }
1132
1133 return (fd >= 0) ? fcntl(fd, F_DUPFD_CLOEXEC, 3) : -1;
1134 }
1135
1136 static const struct dri2_egl_display_vtbl droid_display_vtbl = {
1137 .authenticate = NULL,
1138 .create_window_surface = droid_create_window_surface,
1139 .create_pixmap_surface = dri2_fallback_create_pixmap_surface,
1140 .create_pbuffer_surface = droid_create_pbuffer_surface,
1141 .destroy_surface = droid_destroy_surface,
1142 .create_image = droid_create_image_khr,
1143 .swap_buffers = droid_swap_buffers,
1144 .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage, /* Android implements the function */
1145 .swap_buffers_region = dri2_fallback_swap_buffers_region,
1146 .swap_interval = droid_swap_interval,
1147 #if ANDROID_API_LEVEL >= 23
1148 .set_damage_region = droid_set_damage_region,
1149 #else
1150 .set_damage_region = dri2_fallback_set_damage_region,
1151 #endif
1152 .post_sub_buffer = dri2_fallback_post_sub_buffer,
1153 .copy_buffers = dri2_fallback_copy_buffers,
1154 .query_buffer_age = droid_query_buffer_age,
1155 .query_surface = droid_query_surface,
1156 .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
1157 .get_sync_values = dri2_fallback_get_sync_values,
1158 .get_dri_drawable = dri2_surface_get_dri_drawable,
1159 };
1160
1161 static const __DRIdri2LoaderExtension droid_dri2_loader_extension = {
1162 .base = { __DRI_DRI2_LOADER, 4 },
1163
1164 .getBuffers = NULL,
1165 .flushFrontBuffer = droid_flush_front_buffer,
1166 .getBuffersWithFormat = droid_get_buffers_with_format,
1167 .getCapability = droid_get_capability,
1168 };
1169
1170 static const __DRIimageLoaderExtension droid_image_loader_extension = {
1171 .base = { __DRI_IMAGE_LOADER, 2 },
1172
1173 .getBuffers = droid_image_get_buffers,
1174 .flushFrontBuffer = droid_flush_front_buffer,
1175 .getCapability = droid_get_capability,
1176 };
1177
1178 static const __DRIextension *droid_dri2_loader_extensions[] = {
1179 &droid_dri2_loader_extension.base,
1180 &image_lookup_extension.base,
1181 &use_invalidate.base,
1182 NULL,
1183 };
1184
1185 static const __DRIextension *droid_image_loader_extensions[] = {
1186 &droid_image_loader_extension.base,
1187 &image_lookup_extension.base,
1188 &use_invalidate.base,
1189 NULL,
1190 };
1191
1192 EGLBoolean
1193 dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *disp)
1194 {
1195 struct dri2_egl_display *dri2_dpy;
1196 const char *err;
1197 int ret;
1198
1199 /* Not supported yet */
1200 if (disp->Options.ForceSoftware)
1201 return EGL_FALSE;
1202
1203 loader_set_logger(_eglLog);
1204
1205 dri2_dpy = calloc(1, sizeof(*dri2_dpy));
1206 if (!dri2_dpy)
1207 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
1208
1209 dri2_dpy->fd = -1;
1210 ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
1211 (const hw_module_t **)&dri2_dpy->gralloc);
1212 if (ret) {
1213 err = "DRI2: failed to get gralloc module";
1214 goto cleanup;
1215 }
1216
1217 disp->DriverData = (void *) dri2_dpy;
1218
1219 dri2_dpy->fd = droid_open_device(dri2_dpy);
1220 if (dri2_dpy->fd < 0) {
1221 err = "DRI2: failed to open device";
1222 goto cleanup;
1223 }
1224
1225 dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
1226 if (dri2_dpy->driver_name == NULL) {
1227 err = "DRI2: failed to get driver name";
1228 goto cleanup;
1229 }
1230
1231 dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER;
1232
1233 /* render nodes cannot use Gem names, and thus do not support
1234 * the __DRI_DRI2_LOADER extension */
1235 if (!dri2_dpy->is_render_node) {
1236 dri2_dpy->loader_extensions = droid_dri2_loader_extensions;
1237 if (!dri2_load_driver(disp)) {
1238 err = "DRI2: failed to load driver";
1239 goto cleanup;
1240 }
1241 } else {
1242 dri2_dpy->loader_extensions = droid_image_loader_extensions;
1243 if (!dri2_load_driver_dri3(disp)) {
1244 err = "DRI3: failed to load driver";
1245 goto cleanup;
1246 }
1247 }
1248
1249 if (!dri2_create_screen(disp)) {
1250 err = "DRI2: failed to create screen";
1251 goto cleanup;
1252 }
1253
1254 if (!dri2_setup_extensions(disp)) {
1255 err = "DRI2: failed to setup extensions";
1256 goto cleanup;
1257 }
1258
1259 dri2_setup_screen(disp);
1260
1261 /* We set the maximum swap interval as 1 for Android platform, since it is
1262 * the maximum value supported by Android according to the value of
1263 * ANativeWindow::maxSwapInterval.
1264 */
1265 dri2_setup_swap_interval(disp, 1);
1266
1267 if (!droid_add_configs_for_visuals(drv, disp)) {
1268 err = "DRI2: failed to add configs";
1269 goto cleanup;
1270 }
1271
1272 disp->Extensions.ANDROID_framebuffer_target = EGL_TRUE;
1273 disp->Extensions.ANDROID_image_native_buffer = EGL_TRUE;
1274 disp->Extensions.ANDROID_recordable = EGL_TRUE;
1275 disp->Extensions.EXT_buffer_age = EGL_TRUE;
1276 #if ANDROID_API_LEVEL >= 23
1277 disp->Extensions.KHR_partial_update = EGL_TRUE;
1278 #endif
1279 disp->Extensions.KHR_image = EGL_TRUE;
1280
1281 /* Fill vtbl last to prevent accidentally calling virtual function during
1282 * initialization.
1283 */
1284 dri2_dpy->vtbl = &droid_display_vtbl;
1285
1286 return EGL_TRUE;
1287
1288 cleanup:
1289 dri2_display_destroy(disp);
1290 return _eglError(EGL_NOT_INITIALIZED, err);
1291 }