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