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