• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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