1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2010 Intel Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18bf215546Sopenharmony_ci * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19bf215546Sopenharmony_ci * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20bf215546Sopenharmony_ci * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE.
23bf215546Sopenharmony_ci *
24bf215546Sopenharmony_ci * Authors:
25bf215546Sopenharmony_ci *    Kristian Høgsberg <krh@bitplanet.net>
26bf215546Sopenharmony_ci */
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include <stdbool.h>
29bf215546Sopenharmony_ci#include <stdint.h>
30bf215546Sopenharmony_ci#include <stdbool.h>
31bf215546Sopenharmony_ci#include <stdlib.h>
32bf215546Sopenharmony_ci#include <string.h>
33bf215546Sopenharmony_ci#include <stdio.h>
34bf215546Sopenharmony_ci#include <limits.h>
35bf215546Sopenharmony_ci#include <dlfcn.h>
36bf215546Sopenharmony_ci#include <fcntl.h>
37bf215546Sopenharmony_ci#include <errno.h>
38bf215546Sopenharmony_ci#include <unistd.h>
39bf215546Sopenharmony_ci#include <c11/threads.h>
40bf215546Sopenharmony_ci#include <time.h>
41bf215546Sopenharmony_ci#ifdef HAVE_LIBDRM
42bf215546Sopenharmony_ci#include <xf86drm.h>
43bf215546Sopenharmony_ci#include "drm-uapi/drm_fourcc.h"
44bf215546Sopenharmony_ci#endif
45bf215546Sopenharmony_ci#include <GL/gl.h>
46bf215546Sopenharmony_ci#include <GL/internal/dri_interface.h>
47bf215546Sopenharmony_ci#include <sys/types.h>
48bf215546Sopenharmony_ci#include <sys/stat.h>
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_ci#ifdef HAVE_WAYLAND_PLATFORM
51bf215546Sopenharmony_ci#include <wayland-client.h>
52bf215546Sopenharmony_ci#include "wayland-drm.h"
53bf215546Sopenharmony_ci#include "wayland-drm-client-protocol.h"
54bf215546Sopenharmony_ci#include "linux-dmabuf-unstable-v1-client-protocol.h"
55bf215546Sopenharmony_ci#endif
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ci#ifdef HAVE_X11_PLATFORM
58bf215546Sopenharmony_ci#include "X11/Xlibint.h"
59bf215546Sopenharmony_ci#endif
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci#include "egldefines.h"
62bf215546Sopenharmony_ci#include "egl_dri2.h"
63bf215546Sopenharmony_ci#include "GL/mesa_glinterop.h"
64bf215546Sopenharmony_ci#include "loader/loader.h"
65bf215546Sopenharmony_ci#include "util/libsync.h"
66bf215546Sopenharmony_ci#include "util/os_file.h"
67bf215546Sopenharmony_ci#include "util/u_atomic.h"
68bf215546Sopenharmony_ci#include "util/u_vector.h"
69bf215546Sopenharmony_ci#include "mapi/glapi/glapi.h"
70bf215546Sopenharmony_ci#include "util/bitscan.h"
71bf215546Sopenharmony_ci#include "util/driconf.h"
72bf215546Sopenharmony_ci#include "util/u_math.h"
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_ci#include "ohos_log.h"
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci#define NUM_ATTRIBS 12
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_cistatic const struct dri2_pbuffer_visual {
79bf215546Sopenharmony_ci   const char *format_name;
80bf215546Sopenharmony_ci   unsigned int dri_image_format;
81bf215546Sopenharmony_ci   int rgba_shifts[4];
82bf215546Sopenharmony_ci   unsigned int rgba_sizes[4];
83bf215546Sopenharmony_ci} dri2_pbuffer_visuals[] = {
84bf215546Sopenharmony_ci   {
85bf215546Sopenharmony_ci      "ABGR16F",
86bf215546Sopenharmony_ci      __DRI_IMAGE_FORMAT_ABGR16161616F,
87bf215546Sopenharmony_ci      { 0, 16, 32, 48 },
88bf215546Sopenharmony_ci      { 16, 16, 16, 16 }
89bf215546Sopenharmony_ci   },
90bf215546Sopenharmony_ci   {
91bf215546Sopenharmony_ci      "XBGR16F",
92bf215546Sopenharmony_ci      __DRI_IMAGE_FORMAT_XBGR16161616F,
93bf215546Sopenharmony_ci      { 0, 16, 32, -1 },
94bf215546Sopenharmony_ci      { 16, 16, 16, 0 }
95bf215546Sopenharmony_ci   },
96bf215546Sopenharmony_ci   {
97bf215546Sopenharmony_ci      "A2RGB10",
98bf215546Sopenharmony_ci      __DRI_IMAGE_FORMAT_ARGB2101010,
99bf215546Sopenharmony_ci      { 20, 10, 0, 30 },
100bf215546Sopenharmony_ci      { 10, 10, 10, 2 }
101bf215546Sopenharmony_ci   },
102bf215546Sopenharmony_ci   {
103bf215546Sopenharmony_ci      "X2RGB10",
104bf215546Sopenharmony_ci      __DRI_IMAGE_FORMAT_XRGB2101010,
105bf215546Sopenharmony_ci      { 20, 10, 0, -1 },
106bf215546Sopenharmony_ci      { 10, 10, 10, 0 }
107bf215546Sopenharmony_ci   },
108bf215546Sopenharmony_ci   {
109bf215546Sopenharmony_ci      "ARGB8888",
110bf215546Sopenharmony_ci      __DRI_IMAGE_FORMAT_ARGB8888,
111bf215546Sopenharmony_ci      { 16, 8, 0, 24 },
112bf215546Sopenharmony_ci      { 8, 8, 8, 8 }
113bf215546Sopenharmony_ci   },
114bf215546Sopenharmony_ci   {
115bf215546Sopenharmony_ci      "RGB888",
116bf215546Sopenharmony_ci      __DRI_IMAGE_FORMAT_XRGB8888,
117bf215546Sopenharmony_ci      { 16, 8, 0, -1 },
118bf215546Sopenharmony_ci      { 8, 8, 8, 0 }
119bf215546Sopenharmony_ci   },
120bf215546Sopenharmony_ci   {
121bf215546Sopenharmony_ci      "RGB565",
122bf215546Sopenharmony_ci      __DRI_IMAGE_FORMAT_RGB565,
123bf215546Sopenharmony_ci      { 11, 5, 0, -1 },
124bf215546Sopenharmony_ci      { 5, 6, 5, 0 }
125bf215546Sopenharmony_ci   },
126bf215546Sopenharmony_ci};
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_cistatic void
129bf215546Sopenharmony_cidri_set_background_context(void *loaderPrivate)
130bf215546Sopenharmony_ci{
131bf215546Sopenharmony_ci   _EGLContext *ctx = _eglGetCurrentContext();
132bf215546Sopenharmony_ci   _EGLThreadInfo *t = _eglGetCurrentThread();
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci   _eglBindContextToThread(ctx, t);
135bf215546Sopenharmony_ci}
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_cistatic void
138bf215546Sopenharmony_cidri2_gl_flush()
139bf215546Sopenharmony_ci{
140bf215546Sopenharmony_ci   static void (*glFlush)(void);
141bf215546Sopenharmony_ci   static mtx_t glFlushMutex = _MTX_INITIALIZER_NP;
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci   mtx_lock(&glFlushMutex);
144bf215546Sopenharmony_ci   if (!glFlush)
145bf215546Sopenharmony_ci      glFlush = _glapi_get_proc_address("glFlush");
146bf215546Sopenharmony_ci   mtx_unlock(&glFlushMutex);
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_ci   /* if glFlush is not available things are horribly broken */
149bf215546Sopenharmony_ci   if (!glFlush) {
150bf215546Sopenharmony_ci      _eglLog(_EGL_WARNING, "DRI2: failed to find glFlush entry point");
151bf215546Sopenharmony_ci      return;
152bf215546Sopenharmony_ci   }
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci   glFlush();
155bf215546Sopenharmony_ci}
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_cistatic GLboolean
158bf215546Sopenharmony_cidri_is_thread_safe(void *loaderPrivate)
159bf215546Sopenharmony_ci{
160bf215546Sopenharmony_ci   struct dri2_egl_surface *dri2_surf = loaderPrivate;
161bf215546Sopenharmony_ci   UNUSED _EGLDisplay *display =  dri2_surf->base.Resource.Display;
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_ci#ifdef HAVE_X11_PLATFORM
164bf215546Sopenharmony_ci   Display *xdpy = (Display*)display->PlatformDisplay;
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci   /* Check Xlib is running in thread safe mode when running on EGL/X11-xlib
167bf215546Sopenharmony_ci    * platform
168bf215546Sopenharmony_ci    *
169bf215546Sopenharmony_ci    * 'lock_fns' is the XLockDisplay function pointer of the X11 display 'dpy'.
170bf215546Sopenharmony_ci    * It wll be NULL if XInitThreads wasn't called.
171bf215546Sopenharmony_ci    */
172bf215546Sopenharmony_ci   if (display->Platform == _EGL_PLATFORM_X11 && xdpy && !xdpy->lock_fns)
173bf215546Sopenharmony_ci      return false;
174bf215546Sopenharmony_ci#endif
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci   return true;
177bf215546Sopenharmony_ci}
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ciconst __DRIbackgroundCallableExtension background_callable_extension = {
180bf215546Sopenharmony_ci   .base = { __DRI_BACKGROUND_CALLABLE, 2 },
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci   .setBackgroundContext = dri_set_background_context,
183bf215546Sopenharmony_ci   .isThreadSafe         = dri_is_thread_safe,
184bf215546Sopenharmony_ci};
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ciconst __DRIuseInvalidateExtension use_invalidate = {
187bf215546Sopenharmony_ci   .base = { __DRI_USE_INVALIDATE, 1 }
188bf215546Sopenharmony_ci};
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_cistatic void
191bf215546Sopenharmony_cidri2_get_pbuffer_drawable_info(__DRIdrawable * draw,
192bf215546Sopenharmony_ci                               int *x, int *y, int *w, int *h,
193bf215546Sopenharmony_ci                               void *loaderPrivate)
194bf215546Sopenharmony_ci{
195bf215546Sopenharmony_ci   struct dri2_egl_surface *dri2_surf = loaderPrivate;
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci   *x = *y = 0;
198bf215546Sopenharmony_ci   *w = dri2_surf->base.Width;
199bf215546Sopenharmony_ci   *h = dri2_surf->base.Height;
200bf215546Sopenharmony_ci}
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_cistatic int
203bf215546Sopenharmony_cidri2_get_bytes_per_pixel(struct dri2_egl_surface *dri2_surf)
204bf215546Sopenharmony_ci{
205bf215546Sopenharmony_ci   const int depth = dri2_surf->base.Config->BufferSize;
206bf215546Sopenharmony_ci   return depth ? util_next_power_of_two(depth / 8) : 0;
207bf215546Sopenharmony_ci}
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_cistatic void
210bf215546Sopenharmony_cidri2_put_image(__DRIdrawable * draw, int op,
211bf215546Sopenharmony_ci               int x, int y, int w, int h,
212bf215546Sopenharmony_ci               char *data, void *loaderPrivate)
213bf215546Sopenharmony_ci{
214bf215546Sopenharmony_ci   struct dri2_egl_surface *dri2_surf = loaderPrivate;
215bf215546Sopenharmony_ci   const int bpp = dri2_get_bytes_per_pixel(dri2_surf);
216bf215546Sopenharmony_ci   const int width = dri2_surf->base.Width;
217bf215546Sopenharmony_ci   const int height = dri2_surf->base.Height;
218bf215546Sopenharmony_ci   const int dst_stride = width*bpp;
219bf215546Sopenharmony_ci   const int src_stride = w*bpp;
220bf215546Sopenharmony_ci   const int x_offset = x*bpp;
221bf215546Sopenharmony_ci   int copy_width = src_stride;
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci   if (!dri2_surf->swrast_device_buffer)
224bf215546Sopenharmony_ci      dri2_surf->swrast_device_buffer = malloc(height*dst_stride);
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci   if (dri2_surf->swrast_device_buffer) {
227bf215546Sopenharmony_ci      const char *src = data;
228bf215546Sopenharmony_ci      char *dst = dri2_surf->swrast_device_buffer;
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci      dst += x_offset;
231bf215546Sopenharmony_ci      dst += y*dst_stride;
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_ci      /* Drivers are allowed to submit OOB PutImage requests, so clip here. */
234bf215546Sopenharmony_ci      if (copy_width > dst_stride - x_offset)
235bf215546Sopenharmony_ci         copy_width = dst_stride - x_offset;
236bf215546Sopenharmony_ci      if (h > height - y)
237bf215546Sopenharmony_ci         h = height - y;
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci      for (; 0 < h; --h) {
240bf215546Sopenharmony_ci         memcpy(dst, src, copy_width);
241bf215546Sopenharmony_ci         dst += dst_stride;
242bf215546Sopenharmony_ci         src += src_stride;
243bf215546Sopenharmony_ci      }
244bf215546Sopenharmony_ci   }
245bf215546Sopenharmony_ci}
246bf215546Sopenharmony_ci
247bf215546Sopenharmony_cistatic void
248bf215546Sopenharmony_cidri2_get_image(__DRIdrawable * read,
249bf215546Sopenharmony_ci               int x, int y, int w, int h,
250bf215546Sopenharmony_ci               char *data, void *loaderPrivate)
251bf215546Sopenharmony_ci{
252bf215546Sopenharmony_ci   struct dri2_egl_surface *dri2_surf = loaderPrivate;
253bf215546Sopenharmony_ci   const int bpp = dri2_get_bytes_per_pixel(dri2_surf);
254bf215546Sopenharmony_ci   const int width = dri2_surf->base.Width;
255bf215546Sopenharmony_ci   const int height = dri2_surf->base.Height;
256bf215546Sopenharmony_ci   const int src_stride = width*bpp;
257bf215546Sopenharmony_ci   const int dst_stride = w*bpp;
258bf215546Sopenharmony_ci   const int x_offset = x*bpp;
259bf215546Sopenharmony_ci   int copy_width = dst_stride;
260bf215546Sopenharmony_ci   const char *src = dri2_surf->swrast_device_buffer;
261bf215546Sopenharmony_ci   char *dst = data;
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_ci   if (!src) {
264bf215546Sopenharmony_ci      memset(data, 0, copy_width * h);
265bf215546Sopenharmony_ci      return;
266bf215546Sopenharmony_ci   }
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_ci   src += x_offset;
269bf215546Sopenharmony_ci   src += y*src_stride;
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_ci   /* Drivers are allowed to submit OOB GetImage requests, so clip here. */
272bf215546Sopenharmony_ci   if (copy_width > src_stride - x_offset)
273bf215546Sopenharmony_ci      copy_width = src_stride - x_offset;
274bf215546Sopenharmony_ci   if (h > height - y)
275bf215546Sopenharmony_ci      h = height - y;
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci   for (; 0 < h; --h) {
278bf215546Sopenharmony_ci      memcpy(dst, src, copy_width);
279bf215546Sopenharmony_ci      src += src_stride;
280bf215546Sopenharmony_ci      dst += dst_stride;
281bf215546Sopenharmony_ci   }
282bf215546Sopenharmony_ci
283bf215546Sopenharmony_ci}
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_ci/* HACK: technically we should have swrast_null, instead of these.
286bf215546Sopenharmony_ci */
287bf215546Sopenharmony_ciconst __DRIswrastLoaderExtension swrast_pbuffer_loader_extension = {
288bf215546Sopenharmony_ci   .base            = { __DRI_SWRAST_LOADER, 1 },
289bf215546Sopenharmony_ci   .getDrawableInfo = dri2_get_pbuffer_drawable_info,
290bf215546Sopenharmony_ci   .putImage        = dri2_put_image,
291bf215546Sopenharmony_ci   .getImage        = dri2_get_image,
292bf215546Sopenharmony_ci};
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_cistatic const EGLint dri2_to_egl_attribute_map[__DRI_ATTRIB_MAX] = {
295bf215546Sopenharmony_ci   [__DRI_ATTRIB_BUFFER_SIZE ]          = EGL_BUFFER_SIZE,
296bf215546Sopenharmony_ci   [__DRI_ATTRIB_LEVEL]                 = EGL_LEVEL,
297bf215546Sopenharmony_ci   [__DRI_ATTRIB_LUMINANCE_SIZE]        = EGL_LUMINANCE_SIZE,
298bf215546Sopenharmony_ci   [__DRI_ATTRIB_DEPTH_SIZE]            = EGL_DEPTH_SIZE,
299bf215546Sopenharmony_ci   [__DRI_ATTRIB_STENCIL_SIZE]          = EGL_STENCIL_SIZE,
300bf215546Sopenharmony_ci   [__DRI_ATTRIB_SAMPLE_BUFFERS]        = EGL_SAMPLE_BUFFERS,
301bf215546Sopenharmony_ci   [__DRI_ATTRIB_SAMPLES]               = EGL_SAMPLES,
302bf215546Sopenharmony_ci   [__DRI_ATTRIB_MAX_PBUFFER_WIDTH]     = EGL_MAX_PBUFFER_WIDTH,
303bf215546Sopenharmony_ci   [__DRI_ATTRIB_MAX_PBUFFER_HEIGHT]    = EGL_MAX_PBUFFER_HEIGHT,
304bf215546Sopenharmony_ci   [__DRI_ATTRIB_MAX_PBUFFER_PIXELS]    = EGL_MAX_PBUFFER_PIXELS,
305bf215546Sopenharmony_ci   [__DRI_ATTRIB_MAX_SWAP_INTERVAL]     = EGL_MAX_SWAP_INTERVAL,
306bf215546Sopenharmony_ci   [__DRI_ATTRIB_MIN_SWAP_INTERVAL]     = EGL_MIN_SWAP_INTERVAL,
307bf215546Sopenharmony_ci   [__DRI_ATTRIB_YINVERTED]             = EGL_Y_INVERTED_NOK,
308bf215546Sopenharmony_ci};
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_ciconst __DRIconfig *
311bf215546Sopenharmony_cidri2_get_dri_config(struct dri2_egl_config *conf, EGLint surface_type,
312bf215546Sopenharmony_ci                    EGLenum colorspace)
313bf215546Sopenharmony_ci{
314bf215546Sopenharmony_ci   const bool double_buffer = surface_type == EGL_WINDOW_BIT;
315bf215546Sopenharmony_ci   const bool srgb = colorspace == EGL_GL_COLORSPACE_SRGB_KHR;
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci   return conf->dri_config[double_buffer][srgb];
318bf215546Sopenharmony_ci}
319bf215546Sopenharmony_ci
320bf215546Sopenharmony_cistatic EGLBoolean
321bf215546Sopenharmony_cidri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria)
322bf215546Sopenharmony_ci{
323bf215546Sopenharmony_ci   if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0)
324bf215546Sopenharmony_ci      return EGL_FALSE;
325bf215546Sopenharmony_ci
326bf215546Sopenharmony_ci   if (!_eglMatchConfig(conf, criteria))
327bf215546Sopenharmony_ci      return EGL_FALSE;
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ci   return EGL_TRUE;
330bf215546Sopenharmony_ci}
331bf215546Sopenharmony_ci
332bf215546Sopenharmony_civoid
333bf215546Sopenharmony_cidri2_get_shifts_and_sizes(const __DRIcoreExtension *core,
334bf215546Sopenharmony_ci                          const __DRIconfig *config, int *shifts,
335bf215546Sopenharmony_ci		          unsigned int *sizes)
336bf215546Sopenharmony_ci{
337bf215546Sopenharmony_ci   unsigned int mask;
338bf215546Sopenharmony_ci
339bf215546Sopenharmony_ci   if (core->getConfigAttrib(config, __DRI_ATTRIB_RED_SHIFT, (unsigned int *)&shifts[0])) {
340bf215546Sopenharmony_ci      core->getConfigAttrib(config, __DRI_ATTRIB_GREEN_SHIFT, (unsigned int *)&shifts[1]);
341bf215546Sopenharmony_ci      core->getConfigAttrib(config, __DRI_ATTRIB_BLUE_SHIFT, (unsigned int *)&shifts[2]);
342bf215546Sopenharmony_ci      core->getConfigAttrib(config, __DRI_ATTRIB_ALPHA_SHIFT, (unsigned int *)&shifts[3]);
343bf215546Sopenharmony_ci   } else {
344bf215546Sopenharmony_ci      /* Driver isn't exposing shifts, so convert masks to shifts */
345bf215546Sopenharmony_ci      core->getConfigAttrib(config, __DRI_ATTRIB_RED_MASK, &mask);
346bf215546Sopenharmony_ci      shifts[0] = ffs(mask) - 1;
347bf215546Sopenharmony_ci      core->getConfigAttrib(config, __DRI_ATTRIB_GREEN_MASK, &mask);
348bf215546Sopenharmony_ci      shifts[1] = ffs(mask) - 1;
349bf215546Sopenharmony_ci      core->getConfigAttrib(config, __DRI_ATTRIB_BLUE_MASK, &mask);
350bf215546Sopenharmony_ci      shifts[2] = ffs(mask) - 1;
351bf215546Sopenharmony_ci      core->getConfigAttrib(config, __DRI_ATTRIB_ALPHA_MASK, &mask);
352bf215546Sopenharmony_ci      shifts[3] = ffs(mask) - 1;
353bf215546Sopenharmony_ci   }
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ci   core->getConfigAttrib(config, __DRI_ATTRIB_RED_SIZE, &sizes[0]);
356bf215546Sopenharmony_ci   core->getConfigAttrib(config, __DRI_ATTRIB_GREEN_SIZE, &sizes[1]);
357bf215546Sopenharmony_ci   core->getConfigAttrib(config, __DRI_ATTRIB_BLUE_SIZE, &sizes[2]);
358bf215546Sopenharmony_ci   core->getConfigAttrib(config, __DRI_ATTRIB_ALPHA_SIZE, &sizes[3]);
359bf215546Sopenharmony_ci}
360bf215546Sopenharmony_ci
361bf215546Sopenharmony_civoid
362bf215546Sopenharmony_cidri2_get_render_type_float(const __DRIcoreExtension *core,
363bf215546Sopenharmony_ci                           const __DRIconfig *config,
364bf215546Sopenharmony_ci                           bool *is_float)
365bf215546Sopenharmony_ci{
366bf215546Sopenharmony_ci   unsigned int render_type;
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_ci   core->getConfigAttrib(config, __DRI_ATTRIB_RENDER_TYPE, &render_type);
369bf215546Sopenharmony_ci   *is_float = (render_type & __DRI_ATTRIB_FLOAT_BIT) ? true : false;
370bf215546Sopenharmony_ci}
371bf215546Sopenharmony_ci
372bf215546Sopenharmony_ciunsigned int
373bf215546Sopenharmony_cidri2_image_format_for_pbuffer_config(struct dri2_egl_display *dri2_dpy,
374bf215546Sopenharmony_ci                                     const __DRIconfig *config)
375bf215546Sopenharmony_ci{
376bf215546Sopenharmony_ci   int shifts[4];
377bf215546Sopenharmony_ci   unsigned int sizes[4];
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_ci   dri2_get_shifts_and_sizes(dri2_dpy->core, config, shifts, sizes);
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_ci   for (unsigned i = 0; i < ARRAY_SIZE(dri2_pbuffer_visuals); ++i) {
382bf215546Sopenharmony_ci      const struct dri2_pbuffer_visual *visual = &dri2_pbuffer_visuals[i];
383bf215546Sopenharmony_ci
384bf215546Sopenharmony_ci      if (shifts[0] == visual->rgba_shifts[0] &&
385bf215546Sopenharmony_ci          shifts[1] == visual->rgba_shifts[1] &&
386bf215546Sopenharmony_ci          shifts[2] == visual->rgba_shifts[2] &&
387bf215546Sopenharmony_ci          shifts[3] == visual->rgba_shifts[3] &&
388bf215546Sopenharmony_ci          sizes[0] == visual->rgba_sizes[0] &&
389bf215546Sopenharmony_ci          sizes[1] == visual->rgba_sizes[1] &&
390bf215546Sopenharmony_ci          sizes[2] == visual->rgba_sizes[2] &&
391bf215546Sopenharmony_ci          sizes[3] == visual->rgba_sizes[3]) {
392bf215546Sopenharmony_ci         return visual->dri_image_format;
393bf215546Sopenharmony_ci      }
394bf215546Sopenharmony_ci   }
395bf215546Sopenharmony_ci
396bf215546Sopenharmony_ci   return __DRI_IMAGE_FORMAT_NONE;
397bf215546Sopenharmony_ci}
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_cistruct dri2_egl_config *
400bf215546Sopenharmony_cidri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
401bf215546Sopenharmony_ci                EGLint surface_type, const EGLint *attr_list,
402bf215546Sopenharmony_ci                const int *rgba_shifts, const unsigned int *rgba_sizes)
403bf215546Sopenharmony_ci{
404bf215546Sopenharmony_ci   struct dri2_egl_config *conf;
405bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
406bf215546Sopenharmony_ci   _EGLConfig base;
407bf215546Sopenharmony_ci   unsigned int attrib, value, double_buffer;
408bf215546Sopenharmony_ci   bool srgb = false;
409bf215546Sopenharmony_ci   EGLint key, bind_to_texture_rgb, bind_to_texture_rgba;
410bf215546Sopenharmony_ci   int dri_shifts[4] = { -1, -1, -1, -1 };
411bf215546Sopenharmony_ci   unsigned int dri_sizes[4] = { 0, 0, 0, 0 };
412bf215546Sopenharmony_ci   _EGLConfig *matching_config;
413bf215546Sopenharmony_ci   EGLint num_configs = 0;
414bf215546Sopenharmony_ci   EGLint config_id;
415bf215546Sopenharmony_ci
416bf215546Sopenharmony_ci   _eglInitConfig(&base, disp, id);
417bf215546Sopenharmony_ci
418bf215546Sopenharmony_ci   double_buffer = 0;
419bf215546Sopenharmony_ci   bind_to_texture_rgb = 0;
420bf215546Sopenharmony_ci   bind_to_texture_rgba = 0;
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_ci   for (int i = 0; i < __DRI_ATTRIB_MAX; ++i) {
423bf215546Sopenharmony_ci      if (!dri2_dpy->core->indexConfigAttrib(dri_config, i, &attrib, &value))
424bf215546Sopenharmony_ci         break;
425bf215546Sopenharmony_ci
426bf215546Sopenharmony_ci      switch (attrib) {
427bf215546Sopenharmony_ci      case __DRI_ATTRIB_RENDER_TYPE:
428bf215546Sopenharmony_ci         if (value & __DRI_ATTRIB_FLOAT_BIT)
429bf215546Sopenharmony_ci            base.ComponentType = EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT;
430bf215546Sopenharmony_ci         if (value & __DRI_ATTRIB_RGBA_BIT)
431bf215546Sopenharmony_ci            value = EGL_RGB_BUFFER;
432bf215546Sopenharmony_ci         else if (value & __DRI_ATTRIB_LUMINANCE_BIT)
433bf215546Sopenharmony_ci            value = EGL_LUMINANCE_BUFFER;
434bf215546Sopenharmony_ci         else
435bf215546Sopenharmony_ci            return NULL;
436bf215546Sopenharmony_ci         base.ColorBufferType = value;
437bf215546Sopenharmony_ci         break;
438bf215546Sopenharmony_ci
439bf215546Sopenharmony_ci      case __DRI_ATTRIB_CONFIG_CAVEAT:
440bf215546Sopenharmony_ci         if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
441bf215546Sopenharmony_ci            value = EGL_NON_CONFORMANT_CONFIG;
442bf215546Sopenharmony_ci         else if (value & __DRI_ATTRIB_SLOW_BIT)
443bf215546Sopenharmony_ci            value = EGL_SLOW_CONFIG;
444bf215546Sopenharmony_ci         else
445bf215546Sopenharmony_ci            value = EGL_NONE;
446bf215546Sopenharmony_ci         base.ConfigCaveat = value;
447bf215546Sopenharmony_ci         break;
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_ci      case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB:
450bf215546Sopenharmony_ci         bind_to_texture_rgb = value;
451bf215546Sopenharmony_ci         break;
452bf215546Sopenharmony_ci
453bf215546Sopenharmony_ci      case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA:
454bf215546Sopenharmony_ci         bind_to_texture_rgba = value;
455bf215546Sopenharmony_ci         break;
456bf215546Sopenharmony_ci
457bf215546Sopenharmony_ci      case __DRI_ATTRIB_DOUBLE_BUFFER:
458bf215546Sopenharmony_ci         double_buffer = value;
459bf215546Sopenharmony_ci         break;
460bf215546Sopenharmony_ci
461bf215546Sopenharmony_ci      case __DRI_ATTRIB_RED_SIZE:
462bf215546Sopenharmony_ci         dri_sizes[0] = value;
463bf215546Sopenharmony_ci         base.RedSize = value;
464bf215546Sopenharmony_ci         break;
465bf215546Sopenharmony_ci
466bf215546Sopenharmony_ci      case __DRI_ATTRIB_RED_MASK:
467bf215546Sopenharmony_ci         dri_shifts[0] = ffs(value) - 1;
468bf215546Sopenharmony_ci         break;
469bf215546Sopenharmony_ci
470bf215546Sopenharmony_ci      case __DRI_ATTRIB_RED_SHIFT:
471bf215546Sopenharmony_ci         dri_shifts[0] = value;
472bf215546Sopenharmony_ci         break;
473bf215546Sopenharmony_ci
474bf215546Sopenharmony_ci      case __DRI_ATTRIB_GREEN_SIZE:
475bf215546Sopenharmony_ci         dri_sizes[1] = value;
476bf215546Sopenharmony_ci         base.GreenSize = value;
477bf215546Sopenharmony_ci         break;
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_ci      case __DRI_ATTRIB_GREEN_MASK:
480bf215546Sopenharmony_ci         dri_shifts[1] = ffs(value) - 1;
481bf215546Sopenharmony_ci         break;
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_ci      case __DRI_ATTRIB_GREEN_SHIFT:
484bf215546Sopenharmony_ci         dri_shifts[1] = value;
485bf215546Sopenharmony_ci         break;
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_ci      case __DRI_ATTRIB_BLUE_SIZE:
488bf215546Sopenharmony_ci         dri_sizes[2] = value;
489bf215546Sopenharmony_ci         base.BlueSize = value;
490bf215546Sopenharmony_ci         break;
491bf215546Sopenharmony_ci
492bf215546Sopenharmony_ci      case __DRI_ATTRIB_BLUE_MASK:
493bf215546Sopenharmony_ci         dri_shifts[2] = ffs(value) - 1;
494bf215546Sopenharmony_ci         break;
495bf215546Sopenharmony_ci
496bf215546Sopenharmony_ci      case __DRI_ATTRIB_BLUE_SHIFT:
497bf215546Sopenharmony_ci         dri_shifts[2] = value;
498bf215546Sopenharmony_ci         break;
499bf215546Sopenharmony_ci
500bf215546Sopenharmony_ci     case __DRI_ATTRIB_ALPHA_SIZE:
501bf215546Sopenharmony_ci         dri_sizes[3] = value;
502bf215546Sopenharmony_ci         base.AlphaSize = value;
503bf215546Sopenharmony_ci         break;
504bf215546Sopenharmony_ci
505bf215546Sopenharmony_ci      case __DRI_ATTRIB_ALPHA_MASK:
506bf215546Sopenharmony_ci         dri_shifts[3] = ffs(value) - 1;
507bf215546Sopenharmony_ci         break;
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_ci      case __DRI_ATTRIB_ALPHA_SHIFT:
510bf215546Sopenharmony_ci         dri_shifts[3] = value;
511bf215546Sopenharmony_ci         break;
512bf215546Sopenharmony_ci
513bf215546Sopenharmony_ci      case __DRI_ATTRIB_ACCUM_RED_SIZE:
514bf215546Sopenharmony_ci      case __DRI_ATTRIB_ACCUM_GREEN_SIZE:
515bf215546Sopenharmony_ci      case __DRI_ATTRIB_ACCUM_BLUE_SIZE:
516bf215546Sopenharmony_ci      case __DRI_ATTRIB_ACCUM_ALPHA_SIZE:
517bf215546Sopenharmony_ci         /* Don't expose visuals with the accumulation buffer. */
518bf215546Sopenharmony_ci         if (value > 0)
519bf215546Sopenharmony_ci            return NULL;
520bf215546Sopenharmony_ci         break;
521bf215546Sopenharmony_ci
522bf215546Sopenharmony_ci      case __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE:
523bf215546Sopenharmony_ci         srgb = value != 0;
524bf215546Sopenharmony_ci         if (!disp->Extensions.KHR_gl_colorspace && srgb)
525bf215546Sopenharmony_ci            return NULL;
526bf215546Sopenharmony_ci         break;
527bf215546Sopenharmony_ci
528bf215546Sopenharmony_ci      case __DRI_ATTRIB_MAX_PBUFFER_WIDTH:
529bf215546Sopenharmony_ci         base.MaxPbufferWidth = _EGL_MAX_PBUFFER_WIDTH;
530bf215546Sopenharmony_ci         break;
531bf215546Sopenharmony_ci      case __DRI_ATTRIB_MAX_PBUFFER_HEIGHT:
532bf215546Sopenharmony_ci         base.MaxPbufferHeight = _EGL_MAX_PBUFFER_HEIGHT;
533bf215546Sopenharmony_ci         break;
534bf215546Sopenharmony_ci      case __DRI_ATTRIB_MUTABLE_RENDER_BUFFER:
535bf215546Sopenharmony_ci         if (disp->Extensions.KHR_mutable_render_buffer)
536bf215546Sopenharmony_ci            surface_type |= EGL_MUTABLE_RENDER_BUFFER_BIT_KHR;
537bf215546Sopenharmony_ci         break;
538bf215546Sopenharmony_ci      default:
539bf215546Sopenharmony_ci         key = dri2_to_egl_attribute_map[attrib];
540bf215546Sopenharmony_ci         if (key != 0)
541bf215546Sopenharmony_ci            _eglSetConfigKey(&base, key, value);
542bf215546Sopenharmony_ci         break;
543bf215546Sopenharmony_ci      }
544bf215546Sopenharmony_ci   }
545bf215546Sopenharmony_ci
546bf215546Sopenharmony_ci   if (attr_list)
547bf215546Sopenharmony_ci      for (int i = 0; attr_list[i] != EGL_NONE; i += 2)
548bf215546Sopenharmony_ci         _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]);
549bf215546Sopenharmony_ci
550bf215546Sopenharmony_ci   if (rgba_shifts && memcmp(rgba_shifts, dri_shifts, sizeof(dri_shifts)))
551bf215546Sopenharmony_ci      return NULL;
552bf215546Sopenharmony_ci
553bf215546Sopenharmony_ci   if (rgba_sizes && memcmp(rgba_sizes, dri_sizes, sizeof(dri_sizes)))
554bf215546Sopenharmony_ci      return NULL;
555bf215546Sopenharmony_ci
556bf215546Sopenharmony_ci   base.NativeRenderable = EGL_TRUE;
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_ci   base.SurfaceType = surface_type;
559bf215546Sopenharmony_ci   if (surface_type & (EGL_PBUFFER_BIT |
560bf215546Sopenharmony_ci       (disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) {
561bf215546Sopenharmony_ci      base.BindToTextureRGB = bind_to_texture_rgb;
562bf215546Sopenharmony_ci      if (base.AlphaSize > 0)
563bf215546Sopenharmony_ci         base.BindToTextureRGBA = bind_to_texture_rgba;
564bf215546Sopenharmony_ci   }
565bf215546Sopenharmony_ci
566bf215546Sopenharmony_ci   if (double_buffer) {
567bf215546Sopenharmony_ci      surface_type &= ~EGL_PIXMAP_BIT;
568bf215546Sopenharmony_ci   }
569bf215546Sopenharmony_ci
570bf215546Sopenharmony_ci   if (!surface_type)
571bf215546Sopenharmony_ci      return NULL;
572bf215546Sopenharmony_ci
573bf215546Sopenharmony_ci   base.RenderableType = disp->ClientAPIs;
574bf215546Sopenharmony_ci   base.Conformant = disp->ClientAPIs;
575bf215546Sopenharmony_ci
576bf215546Sopenharmony_ci   base.MinSwapInterval = dri2_dpy->min_swap_interval;
577bf215546Sopenharmony_ci   base.MaxSwapInterval = dri2_dpy->max_swap_interval;
578bf215546Sopenharmony_ci
579bf215546Sopenharmony_ci   if (!_eglValidateConfig(&base, EGL_FALSE)) {
580bf215546Sopenharmony_ci      _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id);
581bf215546Sopenharmony_ci      return NULL;
582bf215546Sopenharmony_ci   }
583bf215546Sopenharmony_ci
584bf215546Sopenharmony_ci   config_id = base.ConfigID;
585bf215546Sopenharmony_ci   base.ConfigID    = EGL_DONT_CARE;
586bf215546Sopenharmony_ci   base.SurfaceType = EGL_DONT_CARE;
587bf215546Sopenharmony_ci   num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1,
588bf215546Sopenharmony_ci                                 (_EGLArrayForEach) dri2_match_config, &base);
589bf215546Sopenharmony_ci
590bf215546Sopenharmony_ci   if (num_configs == 1) {
591bf215546Sopenharmony_ci      conf = (struct dri2_egl_config *) matching_config;
592bf215546Sopenharmony_ci
593bf215546Sopenharmony_ci      if (!conf->dri_config[double_buffer][srgb])
594bf215546Sopenharmony_ci         conf->dri_config[double_buffer][srgb] = dri_config;
595bf215546Sopenharmony_ci      else
596bf215546Sopenharmony_ci         /* a similar config type is already added (unlikely) => discard */
597bf215546Sopenharmony_ci         return NULL;
598bf215546Sopenharmony_ci   }
599bf215546Sopenharmony_ci   else if (num_configs == 0) {
600bf215546Sopenharmony_ci      conf = calloc(1, sizeof *conf);
601bf215546Sopenharmony_ci      if (conf == NULL)
602bf215546Sopenharmony_ci         return NULL;
603bf215546Sopenharmony_ci
604bf215546Sopenharmony_ci      conf->dri_config[double_buffer][srgb] = dri_config;
605bf215546Sopenharmony_ci
606bf215546Sopenharmony_ci      memcpy(&conf->base, &base, sizeof base);
607bf215546Sopenharmony_ci      conf->base.SurfaceType = 0;
608bf215546Sopenharmony_ci      conf->base.ConfigID = config_id;
609bf215546Sopenharmony_ci
610bf215546Sopenharmony_ci      _eglLinkConfig(&conf->base);
611bf215546Sopenharmony_ci   }
612bf215546Sopenharmony_ci   else {
613bf215546Sopenharmony_ci      unreachable("duplicates should not be possible");
614bf215546Sopenharmony_ci      return NULL;
615bf215546Sopenharmony_ci   }
616bf215546Sopenharmony_ci
617bf215546Sopenharmony_ci   conf->base.SurfaceType |= surface_type;
618bf215546Sopenharmony_ci
619bf215546Sopenharmony_ci   return conf;
620bf215546Sopenharmony_ci}
621bf215546Sopenharmony_ci
622bf215546Sopenharmony_ciEGLBoolean
623bf215546Sopenharmony_cidri2_add_pbuffer_configs_for_visuals(_EGLDisplay *disp)
624bf215546Sopenharmony_ci{
625bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
626bf215546Sopenharmony_ci   unsigned int format_count[ARRAY_SIZE(dri2_pbuffer_visuals)] = { 0 };
627bf215546Sopenharmony_ci   unsigned int config_count = 0;
628bf215546Sopenharmony_ci
629bf215546Sopenharmony_ci   for (unsigned i = 0; dri2_dpy->driver_configs[i] != NULL; i++) {
630bf215546Sopenharmony_ci      for (unsigned j = 0; j < ARRAY_SIZE(dri2_pbuffer_visuals); j++) {
631bf215546Sopenharmony_ci         struct dri2_egl_config *dri2_conf;
632bf215546Sopenharmony_ci
633bf215546Sopenharmony_ci         dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i],
634bf215546Sopenharmony_ci               config_count + 1, EGL_PBUFFER_BIT, NULL,
635bf215546Sopenharmony_ci               dri2_pbuffer_visuals[j].rgba_shifts, dri2_pbuffer_visuals[j].rgba_sizes);
636bf215546Sopenharmony_ci
637bf215546Sopenharmony_ci         if (dri2_conf) {
638bf215546Sopenharmony_ci            if (dri2_conf->base.ConfigID == config_count + 1)
639bf215546Sopenharmony_ci               config_count++;
640bf215546Sopenharmony_ci            format_count[j]++;
641bf215546Sopenharmony_ci         }
642bf215546Sopenharmony_ci      }
643bf215546Sopenharmony_ci   }
644bf215546Sopenharmony_ci
645bf215546Sopenharmony_ci   for (unsigned i = 0; i < ARRAY_SIZE(format_count); i++) {
646bf215546Sopenharmony_ci      if (!format_count[i]) {
647bf215546Sopenharmony_ci         _eglLog(_EGL_DEBUG, "No DRI config supports native format %s",
648bf215546Sopenharmony_ci               dri2_pbuffer_visuals[i].format_name);
649bf215546Sopenharmony_ci      }
650bf215546Sopenharmony_ci   }
651bf215546Sopenharmony_ci
652bf215546Sopenharmony_ci   return (config_count != 0);
653bf215546Sopenharmony_ci}
654bf215546Sopenharmony_ci
655bf215546Sopenharmony_ciGLboolean
656bf215546Sopenharmony_cidri2_validate_egl_image(void *image, void *data)
657bf215546Sopenharmony_ci{
658bf215546Sopenharmony_ci   _EGLDisplay *disp = data;
659bf215546Sopenharmony_ci   _EGLImage *img;
660bf215546Sopenharmony_ci
661bf215546Sopenharmony_ci   mtx_lock(&disp->Mutex);
662bf215546Sopenharmony_ci   img = _eglLookupImage(image, disp);
663bf215546Sopenharmony_ci   mtx_unlock(&disp->Mutex);
664bf215546Sopenharmony_ci
665bf215546Sopenharmony_ci   if (img == NULL) {
666bf215546Sopenharmony_ci      _eglError(EGL_BAD_PARAMETER, "dri2_validate_egl_image");
667bf215546Sopenharmony_ci      return false;
668bf215546Sopenharmony_ci   }
669bf215546Sopenharmony_ci
670bf215546Sopenharmony_ci   return true;
671bf215546Sopenharmony_ci}
672bf215546Sopenharmony_ci
673bf215546Sopenharmony_ci__DRIimage *
674bf215546Sopenharmony_cidri2_lookup_egl_image_validated(void *image, void *data)
675bf215546Sopenharmony_ci{
676bf215546Sopenharmony_ci   struct dri2_egl_image *dri2_img;
677bf215546Sopenharmony_ci
678bf215546Sopenharmony_ci   (void)data;
679bf215546Sopenharmony_ci
680bf215546Sopenharmony_ci   dri2_img = dri2_egl_image(image);
681bf215546Sopenharmony_ci
682bf215546Sopenharmony_ci   return dri2_img->dri_image;
683bf215546Sopenharmony_ci}
684bf215546Sopenharmony_ci
685bf215546Sopenharmony_ci__DRIimage *
686bf215546Sopenharmony_cidri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
687bf215546Sopenharmony_ci{
688bf215546Sopenharmony_ci   (void) screen;
689bf215546Sopenharmony_ci
690bf215546Sopenharmony_ci   if (!dri2_validate_egl_image(image, data))
691bf215546Sopenharmony_ci      return NULL;
692bf215546Sopenharmony_ci
693bf215546Sopenharmony_ci   return dri2_lookup_egl_image_validated(image, data);
694bf215546Sopenharmony_ci}
695bf215546Sopenharmony_ci
696bf215546Sopenharmony_ciconst __DRIimageLookupExtension image_lookup_extension = {
697bf215546Sopenharmony_ci   .base = { __DRI_IMAGE_LOOKUP, 2 },
698bf215546Sopenharmony_ci
699bf215546Sopenharmony_ci   .lookupEGLImage       = dri2_lookup_egl_image,
700bf215546Sopenharmony_ci   .validateEGLImage     = dri2_validate_egl_image,
701bf215546Sopenharmony_ci   .lookupEGLImageValidated = dri2_lookup_egl_image_validated,
702bf215546Sopenharmony_ci};
703bf215546Sopenharmony_ci
704bf215546Sopenharmony_cistruct dri2_extension_match {
705bf215546Sopenharmony_ci   const char *name;
706bf215546Sopenharmony_ci   int version;
707bf215546Sopenharmony_ci   int offset;
708bf215546Sopenharmony_ci};
709bf215546Sopenharmony_ci
710bf215546Sopenharmony_cistatic const struct dri2_extension_match dri3_driver_extensions[] = {
711bf215546Sopenharmony_ci   { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
712bf215546Sopenharmony_ci   { __DRI_IMAGE_DRIVER, 1, offsetof(struct dri2_egl_display, image_driver) },
713bf215546Sopenharmony_ci   { NULL, 0, 0 }
714bf215546Sopenharmony_ci};
715bf215546Sopenharmony_ci
716bf215546Sopenharmony_cistatic const struct dri2_extension_match dri2_driver_extensions[] = {
717bf215546Sopenharmony_ci   { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
718bf215546Sopenharmony_ci   { __DRI_DRI2, 2, offsetof(struct dri2_egl_display, dri2) },
719bf215546Sopenharmony_ci   { NULL, 0, 0 }
720bf215546Sopenharmony_ci};
721bf215546Sopenharmony_ci
722bf215546Sopenharmony_cistatic const struct dri2_extension_match dri2_core_extensions[] = {
723bf215546Sopenharmony_ci   { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) },
724bf215546Sopenharmony_ci   { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
725bf215546Sopenharmony_ci   { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) },
726bf215546Sopenharmony_ci   { NULL, 0, 0 }
727bf215546Sopenharmony_ci};
728bf215546Sopenharmony_ci
729bf215546Sopenharmony_cistatic const struct dri2_extension_match swrast_driver_extensions[] = {
730bf215546Sopenharmony_ci   { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
731bf215546Sopenharmony_ci   { __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) },
732bf215546Sopenharmony_ci   { NULL, 0, 0 }
733bf215546Sopenharmony_ci};
734bf215546Sopenharmony_ci
735bf215546Sopenharmony_cistatic const struct dri2_extension_match swrast_core_extensions[] = {
736bf215546Sopenharmony_ci   { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
737bf215546Sopenharmony_ci   { NULL, 0, 0 }
738bf215546Sopenharmony_ci};
739bf215546Sopenharmony_ci
740bf215546Sopenharmony_cistatic const struct dri2_extension_match optional_driver_extensions[] = {
741bf215546Sopenharmony_ci   { __DRI_CONFIG_OPTIONS, 1, offsetof(struct dri2_egl_display, configOptions) },
742bf215546Sopenharmony_ci   { NULL, 0, 0 }
743bf215546Sopenharmony_ci};
744bf215546Sopenharmony_ci
745bf215546Sopenharmony_cistatic const struct dri2_extension_match optional_core_extensions[] = {
746bf215546Sopenharmony_ci   { __DRI2_ROBUSTNESS, 1, offsetof(struct dri2_egl_display, robustness) },
747bf215546Sopenharmony_ci   { __DRI2_CONFIG_QUERY, 1, offsetof(struct dri2_egl_display, config) },
748bf215546Sopenharmony_ci   { __DRI2_FENCE, 1, offsetof(struct dri2_egl_display, fence) },
749bf215546Sopenharmony_ci   { __DRI2_BUFFER_DAMAGE, 1, offsetof(struct dri2_egl_display, buffer_damage) },
750bf215546Sopenharmony_ci   { __DRI2_RENDERER_QUERY, 1, offsetof(struct dri2_egl_display, rendererQuery) },
751bf215546Sopenharmony_ci   { __DRI2_INTEROP, 1, offsetof(struct dri2_egl_display, interop) },
752bf215546Sopenharmony_ci   { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) },
753bf215546Sopenharmony_ci   { __DRI2_FLUSH_CONTROL, 1, offsetof(struct dri2_egl_display, flush_control) },
754bf215546Sopenharmony_ci   { __DRI2_BLOB, 1, offsetof(struct dri2_egl_display, blob) },
755bf215546Sopenharmony_ci   { __DRI_MUTABLE_RENDER_BUFFER_DRIVER, 1, offsetof(struct dri2_egl_display, mutable_render_buffer) },
756bf215546Sopenharmony_ci   { __DRI_KOPPER, 1, offsetof(struct dri2_egl_display, kopper) },
757bf215546Sopenharmony_ci   { NULL, 0, 0 }
758bf215546Sopenharmony_ci};
759bf215546Sopenharmony_ci
760bf215546Sopenharmony_cistatic EGLBoolean
761bf215546Sopenharmony_cidri2_bind_extensions(struct dri2_egl_display *dri2_dpy,
762bf215546Sopenharmony_ci                     const struct dri2_extension_match *matches,
763bf215546Sopenharmony_ci                     const __DRIextension **extensions,
764bf215546Sopenharmony_ci                     bool optional)
765bf215546Sopenharmony_ci{
766bf215546Sopenharmony_ci   int ret = EGL_TRUE;
767bf215546Sopenharmony_ci   void *field;
768bf215546Sopenharmony_ci
769bf215546Sopenharmony_ci   for (int i = 0; extensions[i]; i++) {
770bf215546Sopenharmony_ci      _eglLog(_EGL_DEBUG, "found extension `%s'", extensions[i]->name);
771bf215546Sopenharmony_ci      for (int j = 0; matches[j].name; j++) {
772bf215546Sopenharmony_ci         if (strcmp(extensions[i]->name, matches[j].name) == 0 &&
773bf215546Sopenharmony_ci             extensions[i]->version >= matches[j].version) {
774bf215546Sopenharmony_ci            field = ((char *) dri2_dpy + matches[j].offset);
775bf215546Sopenharmony_ci            *(const __DRIextension **) field = extensions[i];
776bf215546Sopenharmony_ci            _eglLog(_EGL_INFO, "found extension %s version %d",
777bf215546Sopenharmony_ci                    extensions[i]->name, extensions[i]->version);
778bf215546Sopenharmony_ci            break;
779bf215546Sopenharmony_ci         }
780bf215546Sopenharmony_ci      }
781bf215546Sopenharmony_ci   }
782bf215546Sopenharmony_ci
783bf215546Sopenharmony_ci   for (int j = 0; matches[j].name; j++) {
784bf215546Sopenharmony_ci      field = ((char *) dri2_dpy + matches[j].offset);
785bf215546Sopenharmony_ci      if (*(const __DRIextension **) field == NULL) {
786bf215546Sopenharmony_ci         if (optional) {
787bf215546Sopenharmony_ci            _eglLog(_EGL_DEBUG, "did not find optional extension %s version %d",
788bf215546Sopenharmony_ci                    matches[j].name, matches[j].version);
789bf215546Sopenharmony_ci         } else {
790bf215546Sopenharmony_ci            _eglLog(_EGL_WARNING, "did not find extension %s version %d",
791bf215546Sopenharmony_ci                    matches[j].name, matches[j].version);
792bf215546Sopenharmony_ci            ret = EGL_FALSE;
793bf215546Sopenharmony_ci         }
794bf215546Sopenharmony_ci      }
795bf215546Sopenharmony_ci   }
796bf215546Sopenharmony_ci
797bf215546Sopenharmony_ci   return ret;
798bf215546Sopenharmony_ci}
799bf215546Sopenharmony_ci
800bf215546Sopenharmony_cistatic const __DRIextension **
801bf215546Sopenharmony_cidri2_open_driver(_EGLDisplay *disp)
802bf215546Sopenharmony_ci{
803bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
804bf215546Sopenharmony_ci   static const char *search_path_vars[] = {
805bf215546Sopenharmony_ci      "LIBGL_DRIVERS_PATH",
806bf215546Sopenharmony_ci      NULL,
807bf215546Sopenharmony_ci   };
808bf215546Sopenharmony_ci
809bf215546Sopenharmony_ci   return loader_open_driver(dri2_dpy->driver_name,
810bf215546Sopenharmony_ci                             &dri2_dpy->driver,
811bf215546Sopenharmony_ci                             search_path_vars);
812bf215546Sopenharmony_ci}
813bf215546Sopenharmony_ci
814bf215546Sopenharmony_cistatic EGLBoolean
815bf215546Sopenharmony_cidri2_load_driver_common(_EGLDisplay *disp,
816bf215546Sopenharmony_ci                        const struct dri2_extension_match *driver_extensions)
817bf215546Sopenharmony_ci{
818bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
819bf215546Sopenharmony_ci   const __DRIextension **extensions;
820bf215546Sopenharmony_ci
821bf215546Sopenharmony_ci   extensions = dri2_open_driver(disp);
822bf215546Sopenharmony_ci   if (!extensions)
823bf215546Sopenharmony_ci      return EGL_FALSE;
824bf215546Sopenharmony_ci
825bf215546Sopenharmony_ci   if (!dri2_bind_extensions(dri2_dpy, driver_extensions, extensions, false)) {
826bf215546Sopenharmony_ci      dlclose(dri2_dpy->driver);
827bf215546Sopenharmony_ci      dri2_dpy->driver = NULL;
828bf215546Sopenharmony_ci      return EGL_FALSE;
829bf215546Sopenharmony_ci   }
830bf215546Sopenharmony_ci   dri2_dpy->driver_extensions = extensions;
831bf215546Sopenharmony_ci
832bf215546Sopenharmony_ci   dri2_bind_extensions(dri2_dpy, optional_driver_extensions, extensions, true);
833bf215546Sopenharmony_ci
834bf215546Sopenharmony_ci   return EGL_TRUE;
835bf215546Sopenharmony_ci}
836bf215546Sopenharmony_ci
837bf215546Sopenharmony_ciEGLBoolean
838bf215546Sopenharmony_cidri2_load_driver(_EGLDisplay *disp)
839bf215546Sopenharmony_ci{
840bf215546Sopenharmony_ci   return dri2_load_driver_common(disp, dri2_driver_extensions);
841bf215546Sopenharmony_ci}
842bf215546Sopenharmony_ci
843bf215546Sopenharmony_ciEGLBoolean
844bf215546Sopenharmony_cidri2_load_driver_dri3(_EGLDisplay *disp)
845bf215546Sopenharmony_ci{
846bf215546Sopenharmony_ci   return dri2_load_driver_common(disp, dri3_driver_extensions);
847bf215546Sopenharmony_ci}
848bf215546Sopenharmony_ci
849bf215546Sopenharmony_ciEGLBoolean
850bf215546Sopenharmony_cidri2_load_driver_swrast(_EGLDisplay *disp)
851bf215546Sopenharmony_ci{
852bf215546Sopenharmony_ci   return dri2_load_driver_common(disp, swrast_driver_extensions);
853bf215546Sopenharmony_ci}
854bf215546Sopenharmony_ci
855bf215546Sopenharmony_cistatic unsigned
856bf215546Sopenharmony_cidri2_renderer_query_integer(struct dri2_egl_display *dri2_dpy, int param)
857bf215546Sopenharmony_ci{
858bf215546Sopenharmony_ci   const __DRI2rendererQueryExtension *rendererQuery = dri2_dpy->rendererQuery;
859bf215546Sopenharmony_ci   unsigned int value = 0;
860bf215546Sopenharmony_ci
861bf215546Sopenharmony_ci   if (!rendererQuery ||
862bf215546Sopenharmony_ci       rendererQuery->queryInteger(dri2_dpy->dri_screen, param, &value) == -1)
863bf215546Sopenharmony_ci      return 0;
864bf215546Sopenharmony_ci
865bf215546Sopenharmony_ci   return value;
866bf215546Sopenharmony_ci}
867bf215546Sopenharmony_ci
868bf215546Sopenharmony_cistatic const char *
869bf215546Sopenharmony_cidri2_query_driver_name(_EGLDisplay *disp)
870bf215546Sopenharmony_ci{
871bf215546Sopenharmony_ci    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
872bf215546Sopenharmony_ci    return dri2_dpy->driver_name;
873bf215546Sopenharmony_ci}
874bf215546Sopenharmony_ci
875bf215546Sopenharmony_cistatic char *
876bf215546Sopenharmony_cidri2_query_driver_config(_EGLDisplay *disp)
877bf215546Sopenharmony_ci{
878bf215546Sopenharmony_ci    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
879bf215546Sopenharmony_ci    const __DRIconfigOptionsExtension *ext = dri2_dpy->configOptions;
880bf215546Sopenharmony_ci
881bf215546Sopenharmony_ci    if (ext->base.version >= 2)
882bf215546Sopenharmony_ci        return ext->getXml(dri2_dpy->driver_name);
883bf215546Sopenharmony_ci
884bf215546Sopenharmony_ci    return strdup(ext->xml);
885bf215546Sopenharmony_ci}
886bf215546Sopenharmony_ci
887bf215546Sopenharmony_ci
888bf215546Sopenharmony_civoid
889bf215546Sopenharmony_cidri2_setup_screen(_EGLDisplay *disp)
890bf215546Sopenharmony_ci{
891bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
892bf215546Sopenharmony_ci   unsigned int api_mask;
893bf215546Sopenharmony_ci
894bf215546Sopenharmony_ci   /*
895bf215546Sopenharmony_ci    * EGL 1.5 specification defines the default value to 1. Moreover,
896bf215546Sopenharmony_ci    * eglSwapInterval() is required to clamp requested value to the supported
897bf215546Sopenharmony_ci    * range. Since the default value is implicitly assumed to be supported,
898bf215546Sopenharmony_ci    * use it as both minimum and maximum for the platforms that do not allow
899bf215546Sopenharmony_ci    * changing the interval. Platforms, which allow it (e.g. x11, wayland)
900bf215546Sopenharmony_ci    * override these values already.
901bf215546Sopenharmony_ci    */
902bf215546Sopenharmony_ci   dri2_dpy->min_swap_interval = 1;
903bf215546Sopenharmony_ci   dri2_dpy->max_swap_interval = 1;
904bf215546Sopenharmony_ci   dri2_dpy->default_swap_interval = 1;
905bf215546Sopenharmony_ci
906bf215546Sopenharmony_ci   if (dri2_dpy->image_driver) {
907bf215546Sopenharmony_ci      api_mask = dri2_dpy->image_driver->getAPIMask(dri2_dpy->dri_screen);
908bf215546Sopenharmony_ci   } else if (dri2_dpy->dri2) {
909bf215546Sopenharmony_ci      api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
910bf215546Sopenharmony_ci   } else {
911bf215546Sopenharmony_ci      assert(dri2_dpy->swrast);
912bf215546Sopenharmony_ci      api_mask = 1 << __DRI_API_OPENGL |
913bf215546Sopenharmony_ci                 1 << __DRI_API_GLES |
914bf215546Sopenharmony_ci                 1 << __DRI_API_GLES2 |
915bf215546Sopenharmony_ci                 1 << __DRI_API_GLES3;
916bf215546Sopenharmony_ci   }
917bf215546Sopenharmony_ci
918bf215546Sopenharmony_ci   disp->ClientAPIs = 0;
919bf215546Sopenharmony_ci   if ((api_mask & (1 <<__DRI_API_OPENGL)) && _eglIsApiValid(EGL_OPENGL_API))
920bf215546Sopenharmony_ci      disp->ClientAPIs |= EGL_OPENGL_BIT;
921bf215546Sopenharmony_ci   if ((api_mask & (1 << __DRI_API_GLES)) && _eglIsApiValid(EGL_OPENGL_ES_API))
922bf215546Sopenharmony_ci      disp->ClientAPIs |= EGL_OPENGL_ES_BIT;
923bf215546Sopenharmony_ci   if ((api_mask & (1 << __DRI_API_GLES2)) && _eglIsApiValid(EGL_OPENGL_ES_API))
924bf215546Sopenharmony_ci      disp->ClientAPIs |= EGL_OPENGL_ES2_BIT;
925bf215546Sopenharmony_ci   if ((api_mask & (1 << __DRI_API_GLES3)) && _eglIsApiValid(EGL_OPENGL_ES_API))
926bf215546Sopenharmony_ci      disp->ClientAPIs |= EGL_OPENGL_ES3_BIT_KHR;
927bf215546Sopenharmony_ci
928bf215546Sopenharmony_ci   assert(dri2_dpy->image_driver || dri2_dpy->dri2 || dri2_dpy->swrast);
929bf215546Sopenharmony_ci   disp->Extensions.KHR_no_config_context = EGL_TRUE;
930bf215546Sopenharmony_ci   disp->Extensions.KHR_surfaceless_context = EGL_TRUE;
931bf215546Sopenharmony_ci
932bf215546Sopenharmony_ci   if (dri2_dpy->configOptions) {
933bf215546Sopenharmony_ci       disp->Extensions.MESA_query_driver = EGL_TRUE;
934bf215546Sopenharmony_ci   }
935bf215546Sopenharmony_ci
936bf215546Sopenharmony_ci   /* Report back to EGL the bitmask of priorities supported */
937bf215546Sopenharmony_ci   disp->Extensions.IMG_context_priority =
938bf215546Sopenharmony_ci      dri2_renderer_query_integer(dri2_dpy,
939bf215546Sopenharmony_ci                                  __DRI2_RENDERER_HAS_CONTEXT_PRIORITY);
940bf215546Sopenharmony_ci
941bf215546Sopenharmony_ci   disp->Extensions.EXT_pixel_format_float = EGL_TRUE;
942bf215546Sopenharmony_ci
943bf215546Sopenharmony_ci   if (dri2_renderer_query_integer(dri2_dpy,
944bf215546Sopenharmony_ci                                   __DRI2_RENDERER_HAS_FRAMEBUFFER_SRGB))
945bf215546Sopenharmony_ci      disp->Extensions.KHR_gl_colorspace = EGL_TRUE;
946bf215546Sopenharmony_ci
947bf215546Sopenharmony_ci   if (dri2_dpy->image_driver ||
948bf215546Sopenharmony_ci       (dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) ||
949bf215546Sopenharmony_ci       (dri2_dpy->swrast && dri2_dpy->swrast->base.version >= 3)) {
950bf215546Sopenharmony_ci      disp->Extensions.KHR_create_context = EGL_TRUE;
951bf215546Sopenharmony_ci
952bf215546Sopenharmony_ci      if (dri2_dpy->robustness)
953bf215546Sopenharmony_ci         disp->Extensions.EXT_create_context_robustness = EGL_TRUE;
954bf215546Sopenharmony_ci   }
955bf215546Sopenharmony_ci
956bf215546Sopenharmony_ci   if (dri2_renderer_query_integer(dri2_dpy,
957bf215546Sopenharmony_ci                                   __DRI2_RENDERER_HAS_NO_ERROR_CONTEXT))
958bf215546Sopenharmony_ci      disp->Extensions.KHR_create_context_no_error = EGL_TRUE;
959bf215546Sopenharmony_ci
960bf215546Sopenharmony_ci   if (dri2_dpy->fence) {
961bf215546Sopenharmony_ci      disp->Extensions.KHR_fence_sync = EGL_TRUE;
962bf215546Sopenharmony_ci      disp->Extensions.KHR_wait_sync = EGL_TRUE;
963bf215546Sopenharmony_ci      if (dri2_dpy->fence->get_fence_from_cl_event)
964bf215546Sopenharmony_ci         disp->Extensions.KHR_cl_event2 = EGL_TRUE;
965bf215546Sopenharmony_ci      if (dri2_dpy->fence->base.version >= 2 &&
966bf215546Sopenharmony_ci          dri2_dpy->fence->get_capabilities) {
967bf215546Sopenharmony_ci         unsigned capabilities =
968bf215546Sopenharmony_ci            dri2_dpy->fence->get_capabilities(dri2_dpy->dri_screen);
969bf215546Sopenharmony_ci         disp->Extensions.ANDROID_native_fence_sync =
970bf215546Sopenharmony_ci            (capabilities & __DRI_FENCE_CAP_NATIVE_FD) != 0;
971bf215546Sopenharmony_ci      }
972bf215546Sopenharmony_ci   }
973bf215546Sopenharmony_ci
974bf215546Sopenharmony_ci   if (dri2_dpy->blob)
975bf215546Sopenharmony_ci      disp->Extensions.ANDROID_blob_cache = EGL_TRUE;
976bf215546Sopenharmony_ci
977bf215546Sopenharmony_ci   disp->Extensions.KHR_reusable_sync = EGL_TRUE;
978bf215546Sopenharmony_ci
979bf215546Sopenharmony_ci   if (dri2_dpy->image) {
980bf215546Sopenharmony_ci      if (dri2_dpy->image->base.version >= 10 &&
981bf215546Sopenharmony_ci          dri2_dpy->image->getCapabilities != NULL) {
982bf215546Sopenharmony_ci         int capabilities;
983bf215546Sopenharmony_ci
984bf215546Sopenharmony_ci         capabilities = dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen);
985bf215546Sopenharmony_ci         disp->Extensions.MESA_drm_image = (capabilities & __DRI_IMAGE_CAP_GLOBAL_NAMES) != 0;
986bf215546Sopenharmony_ci
987bf215546Sopenharmony_ci         if (dri2_dpy->image->base.version >= 11)
988bf215546Sopenharmony_ci            disp->Extensions.MESA_image_dma_buf_export = EGL_TRUE;
989bf215546Sopenharmony_ci      } else {
990bf215546Sopenharmony_ci         disp->Extensions.MESA_drm_image = EGL_TRUE;
991bf215546Sopenharmony_ci         if (dri2_dpy->image->base.version >= 11)
992bf215546Sopenharmony_ci            disp->Extensions.MESA_image_dma_buf_export = EGL_TRUE;
993bf215546Sopenharmony_ci      }
994bf215546Sopenharmony_ci
995bf215546Sopenharmony_ci      disp->Extensions.KHR_image_base = EGL_TRUE;
996bf215546Sopenharmony_ci      disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
997bf215546Sopenharmony_ci      if (dri2_dpy->image->base.version >= 5 &&
998bf215546Sopenharmony_ci          dri2_dpy->image->createImageFromTexture) {
999bf215546Sopenharmony_ci         disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
1000bf215546Sopenharmony_ci         disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE;
1001bf215546Sopenharmony_ci
1002bf215546Sopenharmony_ci         if (dri2_renderer_query_integer(dri2_dpy,
1003bf215546Sopenharmony_ci                                         __DRI2_RENDERER_HAS_TEXTURE_3D))
1004bf215546Sopenharmony_ci             disp->Extensions.KHR_gl_texture_3D_image = EGL_TRUE;
1005bf215546Sopenharmony_ci      }
1006bf215546Sopenharmony_ci#ifdef HAVE_LIBDRM
1007bf215546Sopenharmony_ci      if (dri2_dpy->image->base.version >= 8 &&
1008bf215546Sopenharmony_ci          dri2_dpy->image->createImageFromDmaBufs) {
1009bf215546Sopenharmony_ci         disp->Extensions.EXT_image_dma_buf_import = EGL_TRUE;
1010bf215546Sopenharmony_ci         disp->Extensions.EXT_image_dma_buf_import_modifiers = EGL_TRUE;
1011bf215546Sopenharmony_ci      }
1012bf215546Sopenharmony_ci#endif
1013bf215546Sopenharmony_ci   }
1014bf215546Sopenharmony_ci
1015bf215546Sopenharmony_ci   if (dri2_dpy->flush_control)
1016bf215546Sopenharmony_ci      disp->Extensions.KHR_context_flush_control = EGL_TRUE;
1017bf215546Sopenharmony_ci
1018bf215546Sopenharmony_ci   if (dri2_dpy->buffer_damage && dri2_dpy->buffer_damage->set_damage_region)
1019bf215546Sopenharmony_ci      disp->Extensions.KHR_partial_update = EGL_TRUE;
1020bf215546Sopenharmony_ci
1021bf215546Sopenharmony_ci   disp->Extensions.EXT_protected_surface =
1022bf215546Sopenharmony_ci      dri2_renderer_query_integer(dri2_dpy,
1023bf215546Sopenharmony_ci                                  __DRI2_RENDERER_HAS_PROTECTED_CONTENT);
1024bf215546Sopenharmony_ci}
1025bf215546Sopenharmony_ci
1026bf215546Sopenharmony_civoid
1027bf215546Sopenharmony_cidri2_setup_swap_interval(_EGLDisplay *disp, int max_swap_interval)
1028bf215546Sopenharmony_ci{
1029bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1030bf215546Sopenharmony_ci   GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
1031bf215546Sopenharmony_ci
1032bf215546Sopenharmony_ci   /* Allow driconf to override applications.*/
1033bf215546Sopenharmony_ci   if (dri2_dpy->config)
1034bf215546Sopenharmony_ci      dri2_dpy->config->configQueryi(dri2_dpy->dri_screen,
1035bf215546Sopenharmony_ci                                     "vblank_mode", &vblank_mode);
1036bf215546Sopenharmony_ci   switch (vblank_mode) {
1037bf215546Sopenharmony_ci   case DRI_CONF_VBLANK_NEVER:
1038bf215546Sopenharmony_ci      dri2_dpy->min_swap_interval = 0;
1039bf215546Sopenharmony_ci      dri2_dpy->max_swap_interval = 0;
1040bf215546Sopenharmony_ci      dri2_dpy->default_swap_interval = 0;
1041bf215546Sopenharmony_ci      break;
1042bf215546Sopenharmony_ci   case DRI_CONF_VBLANK_ALWAYS_SYNC:
1043bf215546Sopenharmony_ci      dri2_dpy->min_swap_interval = 1;
1044bf215546Sopenharmony_ci      dri2_dpy->max_swap_interval = max_swap_interval;
1045bf215546Sopenharmony_ci      dri2_dpy->default_swap_interval = 1;
1046bf215546Sopenharmony_ci      break;
1047bf215546Sopenharmony_ci   case DRI_CONF_VBLANK_DEF_INTERVAL_0:
1048bf215546Sopenharmony_ci      dri2_dpy->min_swap_interval = 0;
1049bf215546Sopenharmony_ci      dri2_dpy->max_swap_interval = max_swap_interval;
1050bf215546Sopenharmony_ci      dri2_dpy->default_swap_interval = 0;
1051bf215546Sopenharmony_ci      break;
1052bf215546Sopenharmony_ci   default:
1053bf215546Sopenharmony_ci   case DRI_CONF_VBLANK_DEF_INTERVAL_1:
1054bf215546Sopenharmony_ci      dri2_dpy->min_swap_interval = 0;
1055bf215546Sopenharmony_ci      dri2_dpy->max_swap_interval = max_swap_interval;
1056bf215546Sopenharmony_ci      dri2_dpy->default_swap_interval = 1;
1057bf215546Sopenharmony_ci      break;
1058bf215546Sopenharmony_ci   }
1059bf215546Sopenharmony_ci}
1060bf215546Sopenharmony_ci
1061bf215546Sopenharmony_ci/* All platforms but DRM call this function to create the screen and populate
1062bf215546Sopenharmony_ci * the driver_configs. DRM inherits that information from its display - GBM.
1063bf215546Sopenharmony_ci */
1064bf215546Sopenharmony_ciEGLBoolean
1065bf215546Sopenharmony_cidri2_create_screen(_EGLDisplay *disp)
1066bf215546Sopenharmony_ci{
1067bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1068bf215546Sopenharmony_ci
1069bf215546Sopenharmony_ci   if (dri2_dpy->image_driver) {
1070bf215546Sopenharmony_ci      dri2_dpy->dri_screen =
1071bf215546Sopenharmony_ci         dri2_dpy->image_driver->createNewScreen2(0, dri2_dpy->fd,
1072bf215546Sopenharmony_ci                                                  dri2_dpy->loader_extensions,
1073bf215546Sopenharmony_ci                                                  dri2_dpy->driver_extensions,
1074bf215546Sopenharmony_ci                                                  &dri2_dpy->driver_configs,
1075bf215546Sopenharmony_ci                                                  disp);
1076bf215546Sopenharmony_ci   } else if (dri2_dpy->dri2) {
1077bf215546Sopenharmony_ci      if (dri2_dpy->dri2->base.version >= 4) {
1078bf215546Sopenharmony_ci         dri2_dpy->dri_screen =
1079bf215546Sopenharmony_ci            dri2_dpy->dri2->createNewScreen2(0, dri2_dpy->fd,
1080bf215546Sopenharmony_ci                                             dri2_dpy->loader_extensions,
1081bf215546Sopenharmony_ci                                             dri2_dpy->driver_extensions,
1082bf215546Sopenharmony_ci                                             &dri2_dpy->driver_configs, disp);
1083bf215546Sopenharmony_ci      } else {
1084bf215546Sopenharmony_ci         dri2_dpy->dri_screen =
1085bf215546Sopenharmony_ci            dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd,
1086bf215546Sopenharmony_ci                                            dri2_dpy->loader_extensions,
1087bf215546Sopenharmony_ci                                            &dri2_dpy->driver_configs, disp);
1088bf215546Sopenharmony_ci      }
1089bf215546Sopenharmony_ci   } else {
1090bf215546Sopenharmony_ci      assert(dri2_dpy->swrast);
1091bf215546Sopenharmony_ci      if (dri2_dpy->swrast->base.version >= 4) {
1092bf215546Sopenharmony_ci         dri2_dpy->dri_screen =
1093bf215546Sopenharmony_ci            dri2_dpy->swrast->createNewScreen2(0, dri2_dpy->loader_extensions,
1094bf215546Sopenharmony_ci                                               dri2_dpy->driver_extensions,
1095bf215546Sopenharmony_ci                                               &dri2_dpy->driver_configs, disp);
1096bf215546Sopenharmony_ci      } else {
1097bf215546Sopenharmony_ci         dri2_dpy->dri_screen =
1098bf215546Sopenharmony_ci            dri2_dpy->swrast->createNewScreen(0, dri2_dpy->loader_extensions,
1099bf215546Sopenharmony_ci                                              &dri2_dpy->driver_configs, disp);
1100bf215546Sopenharmony_ci      }
1101bf215546Sopenharmony_ci   }
1102bf215546Sopenharmony_ci
1103bf215546Sopenharmony_ci   if (dri2_dpy->dri_screen == NULL) {
1104bf215546Sopenharmony_ci      _eglLog(_EGL_WARNING, "egl: failed to create dri2 screen");
1105bf215546Sopenharmony_ci      return EGL_FALSE;
1106bf215546Sopenharmony_ci   }
1107bf215546Sopenharmony_ci
1108bf215546Sopenharmony_ci   dri2_dpy->own_dri_screen = true;
1109bf215546Sopenharmony_ci   return EGL_TRUE;
1110bf215546Sopenharmony_ci}
1111bf215546Sopenharmony_ci
1112bf215546Sopenharmony_ciEGLBoolean
1113bf215546Sopenharmony_cidri2_setup_extensions(_EGLDisplay *disp)
1114bf215546Sopenharmony_ci{
1115bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1116bf215546Sopenharmony_ci   const struct dri2_extension_match *mandatory_core_extensions;
1117bf215546Sopenharmony_ci   const __DRIextension **extensions;
1118bf215546Sopenharmony_ci
1119bf215546Sopenharmony_ci   extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
1120bf215546Sopenharmony_ci
1121bf215546Sopenharmony_ci   if (dri2_dpy->image_driver || dri2_dpy->dri2)
1122bf215546Sopenharmony_ci      mandatory_core_extensions = dri2_core_extensions;
1123bf215546Sopenharmony_ci   else
1124bf215546Sopenharmony_ci      mandatory_core_extensions = swrast_core_extensions;
1125bf215546Sopenharmony_ci
1126bf215546Sopenharmony_ci   if (!dri2_bind_extensions(dri2_dpy, mandatory_core_extensions, extensions, false))
1127bf215546Sopenharmony_ci      return EGL_FALSE;
1128bf215546Sopenharmony_ci
1129bf215546Sopenharmony_ci#ifdef HAVE_DRI3_MODIFIERS
1130bf215546Sopenharmony_ci   dri2_dpy->multibuffers_available =
1131bf215546Sopenharmony_ci      (dri2_dpy->dri3_major_version > 1 || (dri2_dpy->dri3_major_version == 1 &&
1132bf215546Sopenharmony_ci                                            dri2_dpy->dri3_minor_version >= 2)) &&
1133bf215546Sopenharmony_ci      (dri2_dpy->present_major_version > 1 || (dri2_dpy->present_major_version == 1 &&
1134bf215546Sopenharmony_ci                                               dri2_dpy->present_minor_version >= 2)) &&
1135bf215546Sopenharmony_ci      (dri2_dpy->image && dri2_dpy->image->base.version >= 15);
1136bf215546Sopenharmony_ci#endif
1137bf215546Sopenharmony_ci
1138bf215546Sopenharmony_ci   dri2_bind_extensions(dri2_dpy, optional_core_extensions, extensions, true);
1139bf215546Sopenharmony_ci   return EGL_TRUE;
1140bf215546Sopenharmony_ci}
1141bf215546Sopenharmony_ci
1142bf215546Sopenharmony_ci/**
1143bf215546Sopenharmony_ci * Called via eglInitialize(), drv->Initialize().
1144bf215546Sopenharmony_ci *
1145bf215546Sopenharmony_ci * This must be guaranteed to be called exactly once, even if eglInitialize is
1146bf215546Sopenharmony_ci * called many times (without a eglTerminate in between).
1147bf215546Sopenharmony_ci */
1148bf215546Sopenharmony_cistatic EGLBoolean
1149bf215546Sopenharmony_cidri2_initialize(_EGLDisplay *disp)
1150bf215546Sopenharmony_ci{
1151bf215546Sopenharmony_ci   EGLBoolean ret = EGL_FALSE;
1152bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1153bf215546Sopenharmony_ci
1154bf215546Sopenharmony_ci   /* In the case where the application calls eglMakeCurrent(context1),
1155bf215546Sopenharmony_ci    * eglTerminate, then eglInitialize again (without a call to eglReleaseThread
1156bf215546Sopenharmony_ci    * or eglMakeCurrent(NULL) before that), dri2_dpy structure is still
1157bf215546Sopenharmony_ci    * initialized, as we need it to be able to free context1 correctly.
1158bf215546Sopenharmony_ci    *
1159bf215546Sopenharmony_ci    * It would probably be safest to forcibly release the display with
1160bf215546Sopenharmony_ci    * dri2_display_release, to make sure the display is reinitialized correctly.
1161bf215546Sopenharmony_ci    * However, the EGL spec states that we need to keep a reference to the
1162bf215546Sopenharmony_ci    * current context (so we cannot call dri2_make_current(NULL)), and therefore
1163bf215546Sopenharmony_ci    * we would leak context1 as we would be missing the old display connection
1164bf215546Sopenharmony_ci    * to free it up correctly.
1165bf215546Sopenharmony_ci    */
1166bf215546Sopenharmony_ci   if (dri2_dpy) {
1167bf215546Sopenharmony_ci      dri2_dpy->ref_count++;
1168bf215546Sopenharmony_ci      return EGL_TRUE;
1169bf215546Sopenharmony_ci   }
1170bf215546Sopenharmony_ci
1171bf215546Sopenharmony_ci   loader_set_logger(_eglLog);
1172bf215546Sopenharmony_ci
1173bf215546Sopenharmony_ci   switch (disp->Platform) {
1174bf215546Sopenharmony_ci   case _EGL_PLATFORM_SURFACELESS:
1175bf215546Sopenharmony_ci      ret = dri2_initialize_surfaceless(disp);
1176bf215546Sopenharmony_ci      break;
1177bf215546Sopenharmony_ci   case _EGL_PLATFORM_DEVICE:
1178bf215546Sopenharmony_ci      ret = dri2_initialize_device(disp);
1179bf215546Sopenharmony_ci      break;
1180bf215546Sopenharmony_ci   case _EGL_PLATFORM_X11:
1181bf215546Sopenharmony_ci   case _EGL_PLATFORM_XCB:
1182bf215546Sopenharmony_ci      ret = dri2_initialize_x11(disp);
1183bf215546Sopenharmony_ci      break;
1184bf215546Sopenharmony_ci   case _EGL_PLATFORM_DRM:
1185bf215546Sopenharmony_ci      ret = dri2_initialize_drm(disp);
1186bf215546Sopenharmony_ci      break;
1187bf215546Sopenharmony_ci   case _EGL_PLATFORM_WAYLAND:
1188bf215546Sopenharmony_ci      ret = dri2_initialize_wayland(disp);
1189bf215546Sopenharmony_ci      break;
1190bf215546Sopenharmony_ci   case _EGL_PLATFORM_ANDROID:
1191bf215546Sopenharmony_ci      ret = dri2_initialize_android(disp);
1192bf215546Sopenharmony_ci      break;
1193bf215546Sopenharmony_ci   case _EGL_PLATFORM_OHOS:
1194bf215546Sopenharmony_ci      // NEED add openharmony init for dri2
1195bf215546Sopenharmony_ci      ret = dri2_initialize_ohos(disp);
1196bf215546Sopenharmony_ci      break;
1197bf215546Sopenharmony_ci   default:
1198bf215546Sopenharmony_ci      unreachable("Callers ensure we cannot get here.");
1199bf215546Sopenharmony_ci      return EGL_FALSE;
1200bf215546Sopenharmony_ci   }
1201bf215546Sopenharmony_ci
1202bf215546Sopenharmony_ci   if (!ret)
1203bf215546Sopenharmony_ci      return EGL_FALSE;
1204bf215546Sopenharmony_ci
1205bf215546Sopenharmony_ci   dri2_dpy = dri2_egl_display(disp);
1206bf215546Sopenharmony_ci   dri2_dpy->ref_count++;
1207bf215546Sopenharmony_ci
1208bf215546Sopenharmony_ci   return EGL_TRUE;
1209bf215546Sopenharmony_ci}
1210bf215546Sopenharmony_ci
1211bf215546Sopenharmony_ci/**
1212bf215546Sopenharmony_ci * Decrement display reference count, and free up display if necessary.
1213bf215546Sopenharmony_ci */
1214bf215546Sopenharmony_cistatic void
1215bf215546Sopenharmony_cidri2_display_release(_EGLDisplay *disp)
1216bf215546Sopenharmony_ci{
1217bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy;
1218bf215546Sopenharmony_ci
1219bf215546Sopenharmony_ci   if (!disp)
1220bf215546Sopenharmony_ci      return;
1221bf215546Sopenharmony_ci
1222bf215546Sopenharmony_ci   dri2_dpy = dri2_egl_display(disp);
1223bf215546Sopenharmony_ci
1224bf215546Sopenharmony_ci   assert(dri2_dpy->ref_count > 0);
1225bf215546Sopenharmony_ci   dri2_dpy->ref_count--;
1226bf215546Sopenharmony_ci
1227bf215546Sopenharmony_ci   if (dri2_dpy->ref_count > 0)
1228bf215546Sopenharmony_ci      return;
1229bf215546Sopenharmony_ci
1230bf215546Sopenharmony_ci   _eglCleanupDisplay(disp);
1231bf215546Sopenharmony_ci   dri2_display_destroy(disp);
1232bf215546Sopenharmony_ci}
1233bf215546Sopenharmony_ci
1234bf215546Sopenharmony_civoid
1235bf215546Sopenharmony_cidri2_display_destroy(_EGLDisplay *disp)
1236bf215546Sopenharmony_ci{
1237bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1238bf215546Sopenharmony_ci
1239bf215546Sopenharmony_ci   if (dri2_dpy->own_dri_screen) {
1240bf215546Sopenharmony_ci      if (dri2_dpy->vtbl && dri2_dpy->vtbl->close_screen_notify)
1241bf215546Sopenharmony_ci         dri2_dpy->vtbl->close_screen_notify(disp);
1242bf215546Sopenharmony_ci      dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
1243bf215546Sopenharmony_ci   }
1244bf215546Sopenharmony_ci   if (dri2_dpy->fd >= 0)
1245bf215546Sopenharmony_ci      close(dri2_dpy->fd);
1246bf215546Sopenharmony_ci
1247bf215546Sopenharmony_ci   /* Don't dlclose the driver when building with the address sanitizer, so you
1248bf215546Sopenharmony_ci    * get good symbols from the leak reports.
1249bf215546Sopenharmony_ci    */
1250bf215546Sopenharmony_ci#if !BUILT_WITH_ASAN || defined(NDEBUG)
1251bf215546Sopenharmony_ci   if (dri2_dpy->driver)
1252bf215546Sopenharmony_ci      dlclose(dri2_dpy->driver);
1253bf215546Sopenharmony_ci#endif
1254bf215546Sopenharmony_ci
1255bf215546Sopenharmony_ci   free(dri2_dpy->driver_name);
1256bf215546Sopenharmony_ci
1257bf215546Sopenharmony_ci#ifdef HAVE_WAYLAND_PLATFORM
1258bf215546Sopenharmony_ci   free(dri2_dpy->device_name);
1259bf215546Sopenharmony_ci#endif
1260bf215546Sopenharmony_ci
1261bf215546Sopenharmony_ci   switch (disp->Platform) {
1262bf215546Sopenharmony_ci   case _EGL_PLATFORM_X11:
1263bf215546Sopenharmony_ci      dri2_teardown_x11(dri2_dpy);
1264bf215546Sopenharmony_ci      break;
1265bf215546Sopenharmony_ci   case _EGL_PLATFORM_DRM:
1266bf215546Sopenharmony_ci      dri2_teardown_drm(dri2_dpy);
1267bf215546Sopenharmony_ci      break;
1268bf215546Sopenharmony_ci   case _EGL_PLATFORM_WAYLAND:
1269bf215546Sopenharmony_ci      dri2_teardown_wayland(dri2_dpy);
1270bf215546Sopenharmony_ci      break;
1271bf215546Sopenharmony_ci   default:
1272bf215546Sopenharmony_ci      /* TODO: add teardown for other platforms */
1273bf215546Sopenharmony_ci      break;
1274bf215546Sopenharmony_ci   }
1275bf215546Sopenharmony_ci
1276bf215546Sopenharmony_ci   /* The drm platform does not create the screen/driver_configs but reuses
1277bf215546Sopenharmony_ci    * the ones from the gbm device. As such the gbm itself is responsible
1278bf215546Sopenharmony_ci    * for the cleanup.
1279bf215546Sopenharmony_ci    */
1280bf215546Sopenharmony_ci   if (disp->Platform != _EGL_PLATFORM_DRM && dri2_dpy->driver_configs) {
1281bf215546Sopenharmony_ci      for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++)
1282bf215546Sopenharmony_ci         free((__DRIconfig *) dri2_dpy->driver_configs[i]);
1283bf215546Sopenharmony_ci      free(dri2_dpy->driver_configs);
1284bf215546Sopenharmony_ci   }
1285bf215546Sopenharmony_ci   free(dri2_dpy);
1286bf215546Sopenharmony_ci   disp->DriverData = NULL;
1287bf215546Sopenharmony_ci}
1288bf215546Sopenharmony_ci
1289bf215546Sopenharmony_ci__DRIbuffer *
1290bf215546Sopenharmony_cidri2_egl_surface_alloc_local_buffer(struct dri2_egl_surface *dri2_surf,
1291bf215546Sopenharmony_ci                                    unsigned int att, unsigned int format)
1292bf215546Sopenharmony_ci{
1293bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy =
1294bf215546Sopenharmony_ci      dri2_egl_display(dri2_surf->base.Resource.Display);
1295bf215546Sopenharmony_ci
1296bf215546Sopenharmony_ci   if (att >= ARRAY_SIZE(dri2_surf->local_buffers))
1297bf215546Sopenharmony_ci      return NULL;
1298bf215546Sopenharmony_ci
1299bf215546Sopenharmony_ci   if (!dri2_surf->local_buffers[att]) {
1300bf215546Sopenharmony_ci      dri2_surf->local_buffers[att] =
1301bf215546Sopenharmony_ci         dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, att, format,
1302bf215546Sopenharmony_ci                                        dri2_surf->base.Width, dri2_surf->base.Height);
1303bf215546Sopenharmony_ci   }
1304bf215546Sopenharmony_ci
1305bf215546Sopenharmony_ci   return dri2_surf->local_buffers[att];
1306bf215546Sopenharmony_ci}
1307bf215546Sopenharmony_ci
1308bf215546Sopenharmony_civoid
1309bf215546Sopenharmony_cidri2_egl_surface_free_local_buffers(struct dri2_egl_surface *dri2_surf)
1310bf215546Sopenharmony_ci{
1311bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy =
1312bf215546Sopenharmony_ci      dri2_egl_display(dri2_surf->base.Resource.Display);
1313bf215546Sopenharmony_ci
1314bf215546Sopenharmony_ci   for (int i = 0; i < ARRAY_SIZE(dri2_surf->local_buffers); i++) {
1315bf215546Sopenharmony_ci      if (dri2_surf->local_buffers[i]) {
1316bf215546Sopenharmony_ci         dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
1317bf215546Sopenharmony_ci                                       dri2_surf->local_buffers[i]);
1318bf215546Sopenharmony_ci         dri2_surf->local_buffers[i] = NULL;
1319bf215546Sopenharmony_ci      }
1320bf215546Sopenharmony_ci   }
1321bf215546Sopenharmony_ci}
1322bf215546Sopenharmony_ci
1323bf215546Sopenharmony_ci/**
1324bf215546Sopenharmony_ci * Called via eglTerminate(), drv->Terminate().
1325bf215546Sopenharmony_ci *
1326bf215546Sopenharmony_ci * This must be guaranteed to be called exactly once, even if eglTerminate is
1327bf215546Sopenharmony_ci * called many times (without a eglInitialize in between).
1328bf215546Sopenharmony_ci */
1329bf215546Sopenharmony_cistatic EGLBoolean
1330bf215546Sopenharmony_cidri2_terminate(_EGLDisplay *disp)
1331bf215546Sopenharmony_ci{
1332bf215546Sopenharmony_ci   /* Release all non-current Context/Surfaces. */
1333bf215546Sopenharmony_ci   _eglReleaseDisplayResources(disp);
1334bf215546Sopenharmony_ci
1335bf215546Sopenharmony_ci   dri2_display_release(disp);
1336bf215546Sopenharmony_ci
1337bf215546Sopenharmony_ci   return EGL_TRUE;
1338bf215546Sopenharmony_ci}
1339bf215546Sopenharmony_ci
1340bf215546Sopenharmony_ci/**
1341bf215546Sopenharmony_ci * Set the error code after a call to
1342bf215546Sopenharmony_ci * dri2_egl_display::dri2::createContextAttribs.
1343bf215546Sopenharmony_ci */
1344bf215546Sopenharmony_cistatic void
1345bf215546Sopenharmony_cidri2_create_context_attribs_error(int dri_error)
1346bf215546Sopenharmony_ci{
1347bf215546Sopenharmony_ci   EGLint egl_error;
1348bf215546Sopenharmony_ci
1349bf215546Sopenharmony_ci   switch (dri_error) {
1350bf215546Sopenharmony_ci   case __DRI_CTX_ERROR_SUCCESS:
1351bf215546Sopenharmony_ci      return;
1352bf215546Sopenharmony_ci
1353bf215546Sopenharmony_ci   case __DRI_CTX_ERROR_NO_MEMORY:
1354bf215546Sopenharmony_ci      egl_error = EGL_BAD_ALLOC;
1355bf215546Sopenharmony_ci      break;
1356bf215546Sopenharmony_ci
1357bf215546Sopenharmony_ci  /* From the EGL_KHR_create_context spec, section "Errors":
1358bf215546Sopenharmony_ci   *
1359bf215546Sopenharmony_ci   *   * If <config> does not support a client API context compatible
1360bf215546Sopenharmony_ci   *     with the requested API major and minor version, [...] context flags,
1361bf215546Sopenharmony_ci   *     and context reset notification behavior (for client API types where
1362bf215546Sopenharmony_ci   *     these attributes are supported), then an EGL_BAD_MATCH error is
1363bf215546Sopenharmony_ci   *     generated.
1364bf215546Sopenharmony_ci   *
1365bf215546Sopenharmony_ci   *   * If an OpenGL ES context is requested and the values for
1366bf215546Sopenharmony_ci   *     attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
1367bf215546Sopenharmony_ci   *     EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
1368bf215546Sopenharmony_ci   *     is not defined, than an EGL_BAD_MATCH error is generated.
1369bf215546Sopenharmony_ci   *
1370bf215546Sopenharmony_ci   *   * If an OpenGL context is requested, the requested version is
1371bf215546Sopenharmony_ci   *     greater than 3.2, and the value for attribute
1372bf215546Sopenharmony_ci   *     EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has any
1373bf215546Sopenharmony_ci   *     bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and
1374bf215546Sopenharmony_ci   *     EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than
1375bf215546Sopenharmony_ci   *     one of these bits set; or if the implementation does not support
1376bf215546Sopenharmony_ci   *     the requested profile, then an EGL_BAD_MATCH error is generated.
1377bf215546Sopenharmony_ci   */
1378bf215546Sopenharmony_ci   case __DRI_CTX_ERROR_BAD_API:
1379bf215546Sopenharmony_ci   case __DRI_CTX_ERROR_BAD_VERSION:
1380bf215546Sopenharmony_ci   case __DRI_CTX_ERROR_BAD_FLAG:
1381bf215546Sopenharmony_ci      egl_error = EGL_BAD_MATCH;
1382bf215546Sopenharmony_ci      break;
1383bf215546Sopenharmony_ci
1384bf215546Sopenharmony_ci  /* From the EGL_KHR_create_context spec, section "Errors":
1385bf215546Sopenharmony_ci   *
1386bf215546Sopenharmony_ci   *   * If an attribute name or attribute value in <attrib_list> is not
1387bf215546Sopenharmony_ci   *     recognized (including unrecognized bits in bitmask attributes),
1388bf215546Sopenharmony_ci   *     then an EGL_BAD_ATTRIBUTE error is generated."
1389bf215546Sopenharmony_ci   */
1390bf215546Sopenharmony_ci   case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE:
1391bf215546Sopenharmony_ci   case __DRI_CTX_ERROR_UNKNOWN_FLAG:
1392bf215546Sopenharmony_ci      egl_error = EGL_BAD_ATTRIBUTE;
1393bf215546Sopenharmony_ci      break;
1394bf215546Sopenharmony_ci
1395bf215546Sopenharmony_ci   default:
1396bf215546Sopenharmony_ci      assert(!"unknown dri_error code");
1397bf215546Sopenharmony_ci      egl_error = EGL_BAD_MATCH;
1398bf215546Sopenharmony_ci      break;
1399bf215546Sopenharmony_ci   }
1400bf215546Sopenharmony_ci
1401bf215546Sopenharmony_ci   _eglError(egl_error, "dri2_create_context");
1402bf215546Sopenharmony_ci}
1403bf215546Sopenharmony_ci
1404bf215546Sopenharmony_cistatic bool
1405bf215546Sopenharmony_cidri2_fill_context_attribs(struct dri2_egl_context *dri2_ctx,
1406bf215546Sopenharmony_ci                          struct dri2_egl_display *dri2_dpy,
1407bf215546Sopenharmony_ci                          uint32_t *ctx_attribs,
1408bf215546Sopenharmony_ci                          unsigned *num_attribs)
1409bf215546Sopenharmony_ci{
1410bf215546Sopenharmony_ci   int pos = 0;
1411bf215546Sopenharmony_ci
1412bf215546Sopenharmony_ci   assert(*num_attribs >= NUM_ATTRIBS);
1413bf215546Sopenharmony_ci
1414bf215546Sopenharmony_ci   ctx_attribs[pos++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
1415bf215546Sopenharmony_ci   ctx_attribs[pos++] = dri2_ctx->base.ClientMajorVersion;
1416bf215546Sopenharmony_ci   ctx_attribs[pos++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
1417bf215546Sopenharmony_ci   ctx_attribs[pos++] = dri2_ctx->base.ClientMinorVersion;
1418bf215546Sopenharmony_ci
1419bf215546Sopenharmony_ci   if (dri2_ctx->base.Flags != 0) {
1420bf215546Sopenharmony_ci      /* If the implementation doesn't support the __DRI2_ROBUSTNESS
1421bf215546Sopenharmony_ci       * extension, don't even try to send it the robust-access flag.
1422bf215546Sopenharmony_ci       * It may explode.  Instead, generate the required EGL error here.
1423bf215546Sopenharmony_ci       */
1424bf215546Sopenharmony_ci      if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0
1425bf215546Sopenharmony_ci            && !dri2_dpy->robustness) {
1426bf215546Sopenharmony_ci         _eglError(EGL_BAD_MATCH, "eglCreateContext");
1427bf215546Sopenharmony_ci         return false;
1428bf215546Sopenharmony_ci      }
1429bf215546Sopenharmony_ci
1430bf215546Sopenharmony_ci      ctx_attribs[pos++] = __DRI_CTX_ATTRIB_FLAGS;
1431bf215546Sopenharmony_ci      ctx_attribs[pos++] = dri2_ctx->base.Flags;
1432bf215546Sopenharmony_ci   }
1433bf215546Sopenharmony_ci
1434bf215546Sopenharmony_ci   if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) {
1435bf215546Sopenharmony_ci      /* If the implementation doesn't support the __DRI2_ROBUSTNESS
1436bf215546Sopenharmony_ci       * extension, don't even try to send it a reset strategy.  It may
1437bf215546Sopenharmony_ci       * explode.  Instead, generate the required EGL error here.
1438bf215546Sopenharmony_ci       */
1439bf215546Sopenharmony_ci      if (!dri2_dpy->robustness) {
1440bf215546Sopenharmony_ci         _eglError(EGL_BAD_CONFIG, "eglCreateContext");
1441bf215546Sopenharmony_ci         return false;
1442bf215546Sopenharmony_ci      }
1443bf215546Sopenharmony_ci
1444bf215546Sopenharmony_ci      ctx_attribs[pos++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
1445bf215546Sopenharmony_ci      ctx_attribs[pos++] = __DRI_CTX_RESET_LOSE_CONTEXT;
1446bf215546Sopenharmony_ci   }
1447bf215546Sopenharmony_ci
1448bf215546Sopenharmony_ci   if (dri2_ctx->base.ContextPriority != EGL_CONTEXT_PRIORITY_MEDIUM_IMG) {
1449bf215546Sopenharmony_ci      unsigned val;
1450bf215546Sopenharmony_ci
1451bf215546Sopenharmony_ci      switch (dri2_ctx->base.ContextPriority) {
1452bf215546Sopenharmony_ci      case EGL_CONTEXT_PRIORITY_HIGH_IMG:
1453bf215546Sopenharmony_ci         val = __DRI_CTX_PRIORITY_HIGH;
1454bf215546Sopenharmony_ci         break;
1455bf215546Sopenharmony_ci      case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
1456bf215546Sopenharmony_ci         val = __DRI_CTX_PRIORITY_MEDIUM;
1457bf215546Sopenharmony_ci         break;
1458bf215546Sopenharmony_ci      case EGL_CONTEXT_PRIORITY_LOW_IMG:
1459bf215546Sopenharmony_ci         val = __DRI_CTX_PRIORITY_LOW;
1460bf215546Sopenharmony_ci         break;
1461bf215546Sopenharmony_ci      default:
1462bf215546Sopenharmony_ci         _eglError(EGL_BAD_CONFIG, "eglCreateContext");
1463bf215546Sopenharmony_ci         return false;
1464bf215546Sopenharmony_ci      }
1465bf215546Sopenharmony_ci
1466bf215546Sopenharmony_ci      ctx_attribs[pos++] = __DRI_CTX_ATTRIB_PRIORITY;
1467bf215546Sopenharmony_ci      ctx_attribs[pos++] = val;
1468bf215546Sopenharmony_ci   }
1469bf215546Sopenharmony_ci
1470bf215546Sopenharmony_ci   if (dri2_ctx->base.ReleaseBehavior == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR) {
1471bf215546Sopenharmony_ci      ctx_attribs[pos++] = __DRI_CTX_ATTRIB_RELEASE_BEHAVIOR;
1472bf215546Sopenharmony_ci      ctx_attribs[pos++] = __DRI_CTX_RELEASE_BEHAVIOR_NONE;
1473bf215546Sopenharmony_ci   }
1474bf215546Sopenharmony_ci
1475bf215546Sopenharmony_ci   if (dri2_ctx->base.NoError) {
1476bf215546Sopenharmony_ci      ctx_attribs[pos++] = __DRI_CTX_ATTRIB_NO_ERROR;
1477bf215546Sopenharmony_ci      ctx_attribs[pos++] = true;
1478bf215546Sopenharmony_ci   }
1479bf215546Sopenharmony_ci
1480bf215546Sopenharmony_ci   *num_attribs = pos;
1481bf215546Sopenharmony_ci
1482bf215546Sopenharmony_ci   return true;
1483bf215546Sopenharmony_ci}
1484bf215546Sopenharmony_ci
1485bf215546Sopenharmony_ci/**
1486bf215546Sopenharmony_ci * Called via eglCreateContext(), drv->CreateContext().
1487bf215546Sopenharmony_ci */
1488bf215546Sopenharmony_cistatic _EGLContext *
1489bf215546Sopenharmony_cidri2_create_context(_EGLDisplay *disp, _EGLConfig *conf,
1490bf215546Sopenharmony_ci                    _EGLContext *share_list, const EGLint *attrib_list)
1491bf215546Sopenharmony_ci{
1492bf215546Sopenharmony_ci   struct dri2_egl_context *dri2_ctx;
1493bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1494bf215546Sopenharmony_ci   struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list);
1495bf215546Sopenharmony_ci   __DRIcontext *shared =
1496bf215546Sopenharmony_ci      dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL;
1497bf215546Sopenharmony_ci   struct dri2_egl_config *dri2_config = dri2_egl_config(conf);
1498bf215546Sopenharmony_ci   const __DRIconfig *dri_config;
1499bf215546Sopenharmony_ci   int api;
1500bf215546Sopenharmony_ci   unsigned error;
1501bf215546Sopenharmony_ci   unsigned num_attribs = NUM_ATTRIBS;
1502bf215546Sopenharmony_ci   uint32_t ctx_attribs[NUM_ATTRIBS];
1503bf215546Sopenharmony_ci
1504bf215546Sopenharmony_ci   dri2_ctx = malloc(sizeof *dri2_ctx);
1505bf215546Sopenharmony_ci   if (!dri2_ctx) {
1506bf215546Sopenharmony_ci      _eglError(EGL_BAD_ALLOC, "eglCreateContext");
1507bf215546Sopenharmony_ci      return NULL;
1508bf215546Sopenharmony_ci   }
1509bf215546Sopenharmony_ci
1510bf215546Sopenharmony_ci   if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list))
1511bf215546Sopenharmony_ci      goto cleanup;
1512bf215546Sopenharmony_ci
1513bf215546Sopenharmony_ci   /* The EGL_EXT_create_context_robustness spec says:
1514bf215546Sopenharmony_ci    *
1515bf215546Sopenharmony_ci    *    "Add to the eglCreateContext context creation errors: [...]
1516bf215546Sopenharmony_ci    *
1517bf215546Sopenharmony_ci    *     * If the reset notification behavior of <share_context> and the
1518bf215546Sopenharmony_ci    *       newly created context are different then an EGL_BAD_MATCH error is
1519bf215546Sopenharmony_ci    *       generated."
1520bf215546Sopenharmony_ci    */
1521bf215546Sopenharmony_ci   if (share_list && share_list->ResetNotificationStrategy !=
1522bf215546Sopenharmony_ci                     dri2_ctx->base.ResetNotificationStrategy) {
1523bf215546Sopenharmony_ci      _eglError(EGL_BAD_MATCH, "eglCreateContext");
1524bf215546Sopenharmony_ci      goto cleanup;
1525bf215546Sopenharmony_ci   }
1526bf215546Sopenharmony_ci
1527bf215546Sopenharmony_ci   /* The EGL_KHR_create_context_no_error spec says:
1528bf215546Sopenharmony_ci    *
1529bf215546Sopenharmony_ci    *    "BAD_MATCH is generated if the value of EGL_CONTEXT_OPENGL_NO_ERROR_KHR
1530bf215546Sopenharmony_ci    *    used to create <share_context> does not match the value of
1531bf215546Sopenharmony_ci    *    EGL_CONTEXT_OPENGL_NO_ERROR_KHR for the context being created."
1532bf215546Sopenharmony_ci    */
1533bf215546Sopenharmony_ci   if (share_list && share_list->NoError != dri2_ctx->base.NoError) {
1534bf215546Sopenharmony_ci      _eglError(EGL_BAD_MATCH, "eglCreateContext");
1535bf215546Sopenharmony_ci      goto cleanup;
1536bf215546Sopenharmony_ci   }
1537bf215546Sopenharmony_ci
1538bf215546Sopenharmony_ci   switch (dri2_ctx->base.ClientAPI) {
1539bf215546Sopenharmony_ci   case EGL_OPENGL_ES_API:
1540bf215546Sopenharmony_ci      switch (dri2_ctx->base.ClientMajorVersion) {
1541bf215546Sopenharmony_ci      case 1:
1542bf215546Sopenharmony_ci         api = __DRI_API_GLES;
1543bf215546Sopenharmony_ci         break;
1544bf215546Sopenharmony_ci      case 2:
1545bf215546Sopenharmony_ci         api = __DRI_API_GLES2;
1546bf215546Sopenharmony_ci         break;
1547bf215546Sopenharmony_ci      case 3:
1548bf215546Sopenharmony_ci         api = __DRI_API_GLES3;
1549bf215546Sopenharmony_ci         break;
1550bf215546Sopenharmony_ci      default:
1551bf215546Sopenharmony_ci         _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
1552bf215546Sopenharmony_ci         free(dri2_ctx);
1553bf215546Sopenharmony_ci         return NULL;
1554bf215546Sopenharmony_ci      }
1555bf215546Sopenharmony_ci      break;
1556bf215546Sopenharmony_ci   case EGL_OPENGL_API:
1557bf215546Sopenharmony_ci      if ((dri2_ctx->base.ClientMajorVersion >= 4
1558bf215546Sopenharmony_ci           || (dri2_ctx->base.ClientMajorVersion == 3
1559bf215546Sopenharmony_ci               && dri2_ctx->base.ClientMinorVersion >= 2))
1560bf215546Sopenharmony_ci          && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
1561bf215546Sopenharmony_ci         api = __DRI_API_OPENGL_CORE;
1562bf215546Sopenharmony_ci      else if (dri2_ctx->base.ClientMajorVersion == 3 &&
1563bf215546Sopenharmony_ci               dri2_ctx->base.ClientMinorVersion == 1)
1564bf215546Sopenharmony_ci         api = __DRI_API_OPENGL_CORE;
1565bf215546Sopenharmony_ci      else
1566bf215546Sopenharmony_ci         api = __DRI_API_OPENGL;
1567bf215546Sopenharmony_ci      break;
1568bf215546Sopenharmony_ci   default:
1569bf215546Sopenharmony_ci      _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
1570bf215546Sopenharmony_ci      free(dri2_ctx);
1571bf215546Sopenharmony_ci      return NULL;
1572bf215546Sopenharmony_ci   }
1573bf215546Sopenharmony_ci
1574bf215546Sopenharmony_ci   if (conf != NULL) {
1575bf215546Sopenharmony_ci      /* The config chosen here isn't necessarily
1576bf215546Sopenharmony_ci       * used for surfaces later.
1577bf215546Sopenharmony_ci       * A pixmap surface will use the single config.
1578bf215546Sopenharmony_ci       * This opportunity depends on disabling the
1579bf215546Sopenharmony_ci       * doubleBufferMode check in
1580bf215546Sopenharmony_ci       * src/mesa/main/context.c:check_compatible()
1581bf215546Sopenharmony_ci       */
1582bf215546Sopenharmony_ci      if (dri2_config->dri_config[1][0])
1583bf215546Sopenharmony_ci         dri_config = dri2_config->dri_config[1][0];
1584bf215546Sopenharmony_ci      else
1585bf215546Sopenharmony_ci         dri_config = dri2_config->dri_config[0][0];
1586bf215546Sopenharmony_ci   }
1587bf215546Sopenharmony_ci   else
1588bf215546Sopenharmony_ci      dri_config = NULL;
1589bf215546Sopenharmony_ci
1590bf215546Sopenharmony_ci   if (!dri2_fill_context_attribs(dri2_ctx, dri2_dpy, ctx_attribs,
1591bf215546Sopenharmony_ci                                  &num_attribs))
1592bf215546Sopenharmony_ci      goto cleanup;
1593bf215546Sopenharmony_ci
1594bf215546Sopenharmony_ci   if (dri2_dpy->image_driver) {
1595bf215546Sopenharmony_ci      dri2_ctx->dri_context =
1596bf215546Sopenharmony_ci         dri2_dpy->image_driver->createContextAttribs(dri2_dpy->dri_screen,
1597bf215546Sopenharmony_ci                                                      api,
1598bf215546Sopenharmony_ci                                                      dri_config,
1599bf215546Sopenharmony_ci                                                      shared,
1600bf215546Sopenharmony_ci                                                      num_attribs / 2,
1601bf215546Sopenharmony_ci                                                      ctx_attribs,
1602bf215546Sopenharmony_ci                                                      & error,
1603bf215546Sopenharmony_ci                                                      dri2_ctx);
1604bf215546Sopenharmony_ci      dri2_create_context_attribs_error(error);
1605bf215546Sopenharmony_ci   } else if (dri2_dpy->dri2) {
1606bf215546Sopenharmony_ci      if (dri2_dpy->dri2->base.version >= 3) {
1607bf215546Sopenharmony_ci         dri2_ctx->dri_context =
1608bf215546Sopenharmony_ci            dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen,
1609bf215546Sopenharmony_ci                                                 api,
1610bf215546Sopenharmony_ci                                                 dri_config,
1611bf215546Sopenharmony_ci                                                 shared,
1612bf215546Sopenharmony_ci                                                 num_attribs / 2,
1613bf215546Sopenharmony_ci                                                 ctx_attribs,
1614bf215546Sopenharmony_ci                                                 & error,
1615bf215546Sopenharmony_ci                                                 dri2_ctx);
1616bf215546Sopenharmony_ci         dri2_create_context_attribs_error(error);
1617bf215546Sopenharmony_ci      } else {
1618bf215546Sopenharmony_ci         dri2_ctx->dri_context =
1619bf215546Sopenharmony_ci            dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
1620bf215546Sopenharmony_ci                                                   api,
1621bf215546Sopenharmony_ci                                                   dri_config,
1622bf215546Sopenharmony_ci                                                   shared,
1623bf215546Sopenharmony_ci                                                   dri2_ctx);
1624bf215546Sopenharmony_ci      }
1625bf215546Sopenharmony_ci   } else {
1626bf215546Sopenharmony_ci      assert(dri2_dpy->swrast);
1627bf215546Sopenharmony_ci      if (dri2_dpy->swrast->base.version >= 3) {
1628bf215546Sopenharmony_ci         dri2_ctx->dri_context =
1629bf215546Sopenharmony_ci            dri2_dpy->swrast->createContextAttribs(dri2_dpy->dri_screen,
1630bf215546Sopenharmony_ci                                                   api,
1631bf215546Sopenharmony_ci                                                   dri_config,
1632bf215546Sopenharmony_ci                                                   shared,
1633bf215546Sopenharmony_ci                                                   num_attribs / 2,
1634bf215546Sopenharmony_ci                                                   ctx_attribs,
1635bf215546Sopenharmony_ci                                                   & error,
1636bf215546Sopenharmony_ci                                                   dri2_ctx);
1637bf215546Sopenharmony_ci         dri2_create_context_attribs_error(error);
1638bf215546Sopenharmony_ci      } else {
1639bf215546Sopenharmony_ci         dri2_ctx->dri_context =
1640bf215546Sopenharmony_ci            dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen,
1641bf215546Sopenharmony_ci                                                     api,
1642bf215546Sopenharmony_ci                                                     dri_config,
1643bf215546Sopenharmony_ci                                                     shared,
1644bf215546Sopenharmony_ci                                                     dri2_ctx);
1645bf215546Sopenharmony_ci      }
1646bf215546Sopenharmony_ci   }
1647bf215546Sopenharmony_ci
1648bf215546Sopenharmony_ci   if (!dri2_ctx->dri_context)
1649bf215546Sopenharmony_ci      goto cleanup;
1650bf215546Sopenharmony_ci
1651bf215546Sopenharmony_ci   return &dri2_ctx->base;
1652bf215546Sopenharmony_ci
1653bf215546Sopenharmony_ci cleanup:
1654bf215546Sopenharmony_ci   free(dri2_ctx);
1655bf215546Sopenharmony_ci   return NULL;
1656bf215546Sopenharmony_ci}
1657bf215546Sopenharmony_ci
1658bf215546Sopenharmony_ci/**
1659bf215546Sopenharmony_ci * Called via eglDestroyContext(), drv->DestroyContext().
1660bf215546Sopenharmony_ci */
1661bf215546Sopenharmony_cistatic EGLBoolean
1662bf215546Sopenharmony_cidri2_destroy_context(_EGLDisplay *disp, _EGLContext *ctx)
1663bf215546Sopenharmony_ci{
1664bf215546Sopenharmony_ci   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1665bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1666bf215546Sopenharmony_ci
1667bf215546Sopenharmony_ci   if (_eglPutContext(ctx)) {
1668bf215546Sopenharmony_ci      dri2_dpy->core->destroyContext(dri2_ctx->dri_context);
1669bf215546Sopenharmony_ci      free(dri2_ctx);
1670bf215546Sopenharmony_ci   }
1671bf215546Sopenharmony_ci
1672bf215546Sopenharmony_ci   return EGL_TRUE;
1673bf215546Sopenharmony_ci}
1674bf215546Sopenharmony_ci
1675bf215546Sopenharmony_ciEGLBoolean
1676bf215546Sopenharmony_cidri2_init_surface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type,
1677bf215546Sopenharmony_ci        _EGLConfig *conf, const EGLint *attrib_list,
1678bf215546Sopenharmony_ci        EGLBoolean enable_out_fence, void *native_surface)
1679bf215546Sopenharmony_ci{
1680bf215546Sopenharmony_ci   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1681bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1682bf215546Sopenharmony_ci
1683bf215546Sopenharmony_ci   dri2_surf->out_fence_fd = -1;
1684bf215546Sopenharmony_ci   dri2_surf->enable_out_fence = false;
1685bf215546Sopenharmony_ci   if (dri2_dpy->fence && dri2_dpy->fence->base.version >= 2 &&
1686bf215546Sopenharmony_ci       dri2_dpy->fence->get_capabilities &&
1687bf215546Sopenharmony_ci       (dri2_dpy->fence->get_capabilities(dri2_dpy->dri_screen) &
1688bf215546Sopenharmony_ci        __DRI_FENCE_CAP_NATIVE_FD)) {
1689bf215546Sopenharmony_ci      dri2_surf->enable_out_fence = enable_out_fence;
1690bf215546Sopenharmony_ci   }
1691bf215546Sopenharmony_ci
1692bf215546Sopenharmony_ci   return _eglInitSurface(surf, disp, type, conf, attrib_list, native_surface);
1693bf215546Sopenharmony_ci}
1694bf215546Sopenharmony_ci
1695bf215546Sopenharmony_cistatic void
1696bf215546Sopenharmony_cidri2_surface_set_out_fence_fd( _EGLSurface *surf, int fence_fd)
1697bf215546Sopenharmony_ci{
1698bf215546Sopenharmony_ci   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1699bf215546Sopenharmony_ci
1700bf215546Sopenharmony_ci   if (dri2_surf->out_fence_fd >= 0)
1701bf215546Sopenharmony_ci      close(dri2_surf->out_fence_fd);
1702bf215546Sopenharmony_ci
1703bf215546Sopenharmony_ci   dri2_surf->out_fence_fd = fence_fd;
1704bf215546Sopenharmony_ci}
1705bf215546Sopenharmony_ci
1706bf215546Sopenharmony_civoid
1707bf215546Sopenharmony_cidri2_fini_surface(_EGLSurface *surf)
1708bf215546Sopenharmony_ci{
1709bf215546Sopenharmony_ci   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1710bf215546Sopenharmony_ci
1711bf215546Sopenharmony_ci   dri2_surface_set_out_fence_fd(surf, -1);
1712bf215546Sopenharmony_ci   dri2_surf->enable_out_fence = false;
1713bf215546Sopenharmony_ci}
1714bf215546Sopenharmony_ci
1715bf215546Sopenharmony_cistatic EGLBoolean
1716bf215546Sopenharmony_cidri2_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
1717bf215546Sopenharmony_ci{
1718bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1719bf215546Sopenharmony_ci
1720bf215546Sopenharmony_ci   if (!_eglPutSurface(surf))
1721bf215546Sopenharmony_ci      return EGL_TRUE;
1722bf215546Sopenharmony_ci
1723bf215546Sopenharmony_ci   return dri2_dpy->vtbl->destroy_surface(disp, surf);
1724bf215546Sopenharmony_ci}
1725bf215546Sopenharmony_ci
1726bf215546Sopenharmony_cistatic void
1727bf215546Sopenharmony_cidri2_surf_update_fence_fd(_EGLContext *ctx,
1728bf215546Sopenharmony_ci                          _EGLDisplay *disp, _EGLSurface *surf)
1729bf215546Sopenharmony_ci{
1730bf215546Sopenharmony_ci   __DRIcontext *dri_ctx = dri2_egl_context(ctx)->dri_context;
1731bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1732bf215546Sopenharmony_ci   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1733bf215546Sopenharmony_ci   int fence_fd = -1;
1734bf215546Sopenharmony_ci   void *fence;
1735bf215546Sopenharmony_ci
1736bf215546Sopenharmony_ci   if (!dri2_surf->enable_out_fence)
1737bf215546Sopenharmony_ci      return;
1738bf215546Sopenharmony_ci
1739bf215546Sopenharmony_ci   fence = dri2_dpy->fence->create_fence_fd(dri_ctx, -1);
1740bf215546Sopenharmony_ci   if (fence) {
1741bf215546Sopenharmony_ci      fence_fd = dri2_dpy->fence->get_fence_fd(dri2_dpy->dri_screen,
1742bf215546Sopenharmony_ci                                               fence);
1743bf215546Sopenharmony_ci      dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, fence);
1744bf215546Sopenharmony_ci   }
1745bf215546Sopenharmony_ci   dri2_surface_set_out_fence_fd(surf, fence_fd);
1746bf215546Sopenharmony_ci}
1747bf215546Sopenharmony_ci
1748bf215546Sopenharmony_ciEGLBoolean
1749bf215546Sopenharmony_cidri2_create_drawable(struct dri2_egl_display *dri2_dpy,
1750bf215546Sopenharmony_ci                     const __DRIconfig *config,
1751bf215546Sopenharmony_ci                     struct dri2_egl_surface *dri2_surf,
1752bf215546Sopenharmony_ci                     void *loaderPrivate)
1753bf215546Sopenharmony_ci{
1754bf215546Sopenharmony_ci   if (dri2_dpy->kopper) {
1755bf215546Sopenharmony_ci      dri2_surf->dri_drawable =
1756bf215546Sopenharmony_ci          dri2_dpy->kopper->createNewDrawable(dri2_dpy->dri_screen, config, loaderPrivate,
1757bf215546Sopenharmony_ci                                              dri2_surf->base.Type == EGL_PBUFFER_BIT ||
1758bf215546Sopenharmony_ci                                              dri2_surf->base.Type == EGL_PIXMAP_BIT);
1759bf215546Sopenharmony_ci   } else {
1760bf215546Sopenharmony_ci      __DRIcreateNewDrawableFunc createNewDrawable;
1761bf215546Sopenharmony_ci      if (dri2_dpy->image_driver)
1762bf215546Sopenharmony_ci         createNewDrawable = dri2_dpy->image_driver->createNewDrawable;
1763bf215546Sopenharmony_ci      else if (dri2_dpy->dri2)
1764bf215546Sopenharmony_ci         createNewDrawable = dri2_dpy->dri2->createNewDrawable;
1765bf215546Sopenharmony_ci      else if (dri2_dpy->swrast)
1766bf215546Sopenharmony_ci         createNewDrawable = dri2_dpy->swrast->createNewDrawable;
1767bf215546Sopenharmony_ci      else
1768bf215546Sopenharmony_ci         return _eglError(EGL_BAD_ALLOC, "no createNewDrawable");
1769bf215546Sopenharmony_ci
1770bf215546Sopenharmony_ci      dri2_surf->dri_drawable = createNewDrawable(dri2_dpy->dri_screen,
1771bf215546Sopenharmony_ci                                                  config, loaderPrivate);
1772bf215546Sopenharmony_ci   }
1773bf215546Sopenharmony_ci   if (dri2_surf->dri_drawable == NULL)
1774bf215546Sopenharmony_ci      return _eglError(EGL_BAD_ALLOC, "createNewDrawable");
1775bf215546Sopenharmony_ci
1776bf215546Sopenharmony_ci   return EGL_TRUE;
1777bf215546Sopenharmony_ci}
1778bf215546Sopenharmony_ci
1779bf215546Sopenharmony_ci/**
1780bf215546Sopenharmony_ci * Called via eglMakeCurrent(), drv->MakeCurrent().
1781bf215546Sopenharmony_ci */
1782bf215546Sopenharmony_cistatic EGLBoolean
1783bf215546Sopenharmony_cidri2_make_current(_EGLDisplay *disp, _EGLSurface *dsurf,
1784bf215546Sopenharmony_ci                  _EGLSurface *rsurf, _EGLContext *ctx)
1785bf215546Sopenharmony_ci{
1786bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1787bf215546Sopenharmony_ci   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1788bf215546Sopenharmony_ci   _EGLDisplay *old_disp = NULL;
1789bf215546Sopenharmony_ci   struct dri2_egl_display *old_dri2_dpy = NULL;
1790bf215546Sopenharmony_ci   _EGLContext *old_ctx;
1791bf215546Sopenharmony_ci   _EGLSurface *old_dsurf, *old_rsurf;
1792bf215546Sopenharmony_ci   _EGLSurface *tmp_dsurf, *tmp_rsurf;
1793bf215546Sopenharmony_ci   __DRIdrawable *ddraw, *rdraw;
1794bf215546Sopenharmony_ci   __DRIcontext *cctx;
1795bf215546Sopenharmony_ci   EGLint egl_error = EGL_SUCCESS;
1796bf215546Sopenharmony_ci
1797bf215546Sopenharmony_ci   if (!dri2_dpy)
1798bf215546Sopenharmony_ci      return _eglError(EGL_NOT_INITIALIZED, "eglMakeCurrent");
1799bf215546Sopenharmony_ci
1800bf215546Sopenharmony_ci   /* make new bindings, set the EGL error otherwise */
1801bf215546Sopenharmony_ci   if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
1802bf215546Sopenharmony_ci      return EGL_FALSE;
1803bf215546Sopenharmony_ci
1804bf215546Sopenharmony_ci   if (old_ctx == ctx && old_dsurf == dsurf && old_rsurf == rsurf) {
1805bf215546Sopenharmony_ci      _eglPutSurface(old_dsurf);
1806bf215546Sopenharmony_ci      _eglPutSurface(old_rsurf);
1807bf215546Sopenharmony_ci      _eglPutContext(old_ctx);
1808bf215546Sopenharmony_ci      return EGL_TRUE;
1809bf215546Sopenharmony_ci   }
1810bf215546Sopenharmony_ci
1811bf215546Sopenharmony_ci   if (old_ctx) {
1812bf215546Sopenharmony_ci      __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context;
1813bf215546Sopenharmony_ci      old_disp = old_ctx->Resource.Display;
1814bf215546Sopenharmony_ci      old_dri2_dpy = dri2_egl_display(old_disp);
1815bf215546Sopenharmony_ci
1816bf215546Sopenharmony_ci      /* Disable shared buffer mode */
1817bf215546Sopenharmony_ci      if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) &&
1818bf215546Sopenharmony_ci          old_dri2_dpy->vtbl->set_shared_buffer_mode) {
1819bf215546Sopenharmony_ci         old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, false);
1820bf215546Sopenharmony_ci      }
1821bf215546Sopenharmony_ci
1822bf215546Sopenharmony_ci      dri2_dpy->core->unbindContext(old_cctx);
1823bf215546Sopenharmony_ci
1824bf215546Sopenharmony_ci      if (old_dsurf)
1825bf215546Sopenharmony_ci         dri2_surf_update_fence_fd(old_ctx, disp, old_dsurf);
1826bf215546Sopenharmony_ci   }
1827bf215546Sopenharmony_ci
1828bf215546Sopenharmony_ci   ddraw = (dsurf) ? dri2_dpy->vtbl->get_dri_drawable(dsurf) : NULL;
1829bf215546Sopenharmony_ci   rdraw = (rsurf) ? dri2_dpy->vtbl->get_dri_drawable(rsurf) : NULL;
1830bf215546Sopenharmony_ci   cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL;
1831bf215546Sopenharmony_ci
1832bf215546Sopenharmony_ci   if (cctx || ddraw || rdraw) {
1833bf215546Sopenharmony_ci      if (!dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
1834bf215546Sopenharmony_ci         _EGLContext *tmp_ctx;
1835bf215546Sopenharmony_ci
1836bf215546Sopenharmony_ci         /* dri2_dpy->core->bindContext failed. We cannot tell for sure why, but
1837bf215546Sopenharmony_ci          * setting the error to EGL_BAD_MATCH is surely better than leaving it
1838bf215546Sopenharmony_ci          * as EGL_SUCCESS.
1839bf215546Sopenharmony_ci          */
1840bf215546Sopenharmony_ci         egl_error = EGL_BAD_MATCH;
1841bf215546Sopenharmony_ci
1842bf215546Sopenharmony_ci         /* undo the previous _eglBindContext */
1843bf215546Sopenharmony_ci         _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &tmp_dsurf, &tmp_rsurf);
1844bf215546Sopenharmony_ci         assert(&dri2_ctx->base == ctx &&
1845bf215546Sopenharmony_ci                tmp_dsurf == dsurf &&
1846bf215546Sopenharmony_ci                tmp_rsurf == rsurf);
1847bf215546Sopenharmony_ci
1848bf215546Sopenharmony_ci         _eglPutSurface(dsurf);
1849bf215546Sopenharmony_ci         _eglPutSurface(rsurf);
1850bf215546Sopenharmony_ci         _eglPutContext(ctx);
1851bf215546Sopenharmony_ci
1852bf215546Sopenharmony_ci         _eglPutSurface(old_dsurf);
1853bf215546Sopenharmony_ci         _eglPutSurface(old_rsurf);
1854bf215546Sopenharmony_ci         _eglPutContext(old_ctx);
1855bf215546Sopenharmony_ci
1856bf215546Sopenharmony_ci         ddraw = (old_dsurf) ? dri2_dpy->vtbl->get_dri_drawable(old_dsurf) : NULL;
1857bf215546Sopenharmony_ci         rdraw = (old_rsurf) ? dri2_dpy->vtbl->get_dri_drawable(old_rsurf) : NULL;
1858bf215546Sopenharmony_ci         cctx = (old_ctx) ? dri2_egl_context(old_ctx)->dri_context : NULL;
1859bf215546Sopenharmony_ci
1860bf215546Sopenharmony_ci         /* undo the previous dri2_dpy->core->unbindContext */
1861bf215546Sopenharmony_ci         if (dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
1862bf215546Sopenharmony_ci            if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) &&
1863bf215546Sopenharmony_ci                old_dri2_dpy->vtbl->set_shared_buffer_mode) {
1864bf215546Sopenharmony_ci               old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, true);
1865bf215546Sopenharmony_ci            }
1866bf215546Sopenharmony_ci
1867bf215546Sopenharmony_ci            return _eglError(egl_error, "eglMakeCurrent");
1868bf215546Sopenharmony_ci         }
1869bf215546Sopenharmony_ci
1870bf215546Sopenharmony_ci         /* We cannot restore the same state as it was before calling
1871bf215546Sopenharmony_ci          * eglMakeCurrent() and the spec isn't clear about what to do. We
1872bf215546Sopenharmony_ci          * can prevent EGL from calling into the DRI driver with no DRI
1873bf215546Sopenharmony_ci          * context bound.
1874bf215546Sopenharmony_ci          */
1875bf215546Sopenharmony_ci         dsurf = rsurf = NULL;
1876bf215546Sopenharmony_ci         ctx = NULL;
1877bf215546Sopenharmony_ci
1878bf215546Sopenharmony_ci         _eglBindContext(ctx, dsurf, rsurf, &tmp_ctx, &tmp_dsurf, &tmp_rsurf);
1879bf215546Sopenharmony_ci         assert(tmp_ctx == old_ctx && tmp_dsurf == old_dsurf &&
1880bf215546Sopenharmony_ci                tmp_rsurf == old_rsurf);
1881bf215546Sopenharmony_ci
1882bf215546Sopenharmony_ci         _eglLog(_EGL_WARNING, "DRI2: failed to rebind the previous context");
1883bf215546Sopenharmony_ci      } else {
1884bf215546Sopenharmony_ci         /* dri2_dpy->core->bindContext succeeded, so take a reference on the
1885bf215546Sopenharmony_ci          * dri2_dpy. This prevents dri2_dpy from being reinitialized when a
1886bf215546Sopenharmony_ci          * EGLDisplay is terminated and then initialized again while a
1887bf215546Sopenharmony_ci          * context is still bound. See dri2_intitialize() for a more in depth
1888bf215546Sopenharmony_ci          * explanation. */
1889bf215546Sopenharmony_ci         dri2_dpy->ref_count++;
1890bf215546Sopenharmony_ci      }
1891bf215546Sopenharmony_ci   }
1892bf215546Sopenharmony_ci
1893bf215546Sopenharmony_ci   dri2_destroy_surface(disp, old_dsurf);
1894bf215546Sopenharmony_ci   dri2_destroy_surface(disp, old_rsurf);
1895bf215546Sopenharmony_ci
1896bf215546Sopenharmony_ci   if (old_ctx) {
1897bf215546Sopenharmony_ci      dri2_destroy_context(disp, old_ctx);
1898bf215546Sopenharmony_ci      dri2_display_release(old_disp);
1899bf215546Sopenharmony_ci   }
1900bf215546Sopenharmony_ci
1901bf215546Sopenharmony_ci   if (egl_error != EGL_SUCCESS)
1902bf215546Sopenharmony_ci      return _eglError(egl_error, "eglMakeCurrent");
1903bf215546Sopenharmony_ci
1904bf215546Sopenharmony_ci   if (dsurf && _eglSurfaceHasMutableRenderBuffer(dsurf) &&
1905bf215546Sopenharmony_ci       dri2_dpy->vtbl->set_shared_buffer_mode) {
1906bf215546Sopenharmony_ci      /* Always update the shared buffer mode. This is obviously needed when
1907bf215546Sopenharmony_ci       * the active EGL_RENDER_BUFFER is EGL_SINGLE_BUFFER. When
1908bf215546Sopenharmony_ci       * EGL_RENDER_BUFFER is EGL_BACK_BUFFER, the update protects us in the
1909bf215546Sopenharmony_ci       * case where external non-EGL API may have changed window's shared
1910bf215546Sopenharmony_ci       * buffer mode since we last saw it.
1911bf215546Sopenharmony_ci       */
1912bf215546Sopenharmony_ci      bool mode = (dsurf->ActiveRenderBuffer == EGL_SINGLE_BUFFER);
1913bf215546Sopenharmony_ci      dri2_dpy->vtbl->set_shared_buffer_mode(disp, dsurf, mode);
1914bf215546Sopenharmony_ci   }
1915bf215546Sopenharmony_ci
1916bf215546Sopenharmony_ci   return EGL_TRUE;
1917bf215546Sopenharmony_ci}
1918bf215546Sopenharmony_ci
1919bf215546Sopenharmony_ci__DRIdrawable *
1920bf215546Sopenharmony_cidri2_surface_get_dri_drawable(_EGLSurface *surf)
1921bf215546Sopenharmony_ci{
1922bf215546Sopenharmony_ci   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1923bf215546Sopenharmony_ci
1924bf215546Sopenharmony_ci   return dri2_surf->dri_drawable;
1925bf215546Sopenharmony_ci}
1926bf215546Sopenharmony_ci
1927bf215546Sopenharmony_ci/*
1928bf215546Sopenharmony_ci * Called from eglGetProcAddress() via drv->GetProcAddress().
1929bf215546Sopenharmony_ci */
1930bf215546Sopenharmony_cistatic _EGLProc
1931bf215546Sopenharmony_cidri2_get_proc_address(const char *procname)
1932bf215546Sopenharmony_ci{
1933bf215546Sopenharmony_ci   DISPLAY_LOGI("procname = %{public}s", procname);
1934bf215546Sopenharmony_ci   return _glapi_get_proc_address(procname);
1935bf215546Sopenharmony_ci}
1936bf215546Sopenharmony_ci
1937bf215546Sopenharmony_cistatic _EGLSurface*
1938bf215546Sopenharmony_cidri2_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
1939bf215546Sopenharmony_ci                           void *native_window, const EGLint *attrib_list)
1940bf215546Sopenharmony_ci{
1941bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1942bf215546Sopenharmony_ci   return dri2_dpy->vtbl->create_window_surface(disp, conf, native_window,
1943bf215546Sopenharmony_ci                                                attrib_list);
1944bf215546Sopenharmony_ci}
1945bf215546Sopenharmony_ci
1946bf215546Sopenharmony_cistatic _EGLSurface*
1947bf215546Sopenharmony_cidri2_create_pixmap_surface(_EGLDisplay *disp, _EGLConfig *conf,
1948bf215546Sopenharmony_ci                           void *native_pixmap, const EGLint *attrib_list)
1949bf215546Sopenharmony_ci{
1950bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1951bf215546Sopenharmony_ci   if (!dri2_dpy->vtbl->create_pixmap_surface)
1952bf215546Sopenharmony_ci      return NULL;
1953bf215546Sopenharmony_ci   return dri2_dpy->vtbl->create_pixmap_surface(disp, conf, native_pixmap,
1954bf215546Sopenharmony_ci                                                attrib_list);
1955bf215546Sopenharmony_ci}
1956bf215546Sopenharmony_ci
1957bf215546Sopenharmony_cistatic _EGLSurface*
1958bf215546Sopenharmony_cidri2_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
1959bf215546Sopenharmony_ci                            const EGLint *attrib_list)
1960bf215546Sopenharmony_ci{
1961bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1962bf215546Sopenharmony_ci   if (!dri2_dpy->vtbl->create_pbuffer_surface)
1963bf215546Sopenharmony_ci      return NULL;
1964bf215546Sopenharmony_ci   return dri2_dpy->vtbl->create_pbuffer_surface(disp, conf, attrib_list);
1965bf215546Sopenharmony_ci}
1966bf215546Sopenharmony_ci
1967bf215546Sopenharmony_cistatic EGLBoolean
1968bf215546Sopenharmony_cidri2_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval)
1969bf215546Sopenharmony_ci{
1970bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1971bf215546Sopenharmony_ci   if (!dri2_dpy->vtbl->swap_interval)
1972bf215546Sopenharmony_ci      return EGL_TRUE;
1973bf215546Sopenharmony_ci   return dri2_dpy->vtbl->swap_interval(disp, surf, interval);
1974bf215546Sopenharmony_ci}
1975bf215546Sopenharmony_ci
1976bf215546Sopenharmony_ci/**
1977bf215546Sopenharmony_ci * Asks the client API to flush any rendering to the drawable so that we can
1978bf215546Sopenharmony_ci * do our swapbuffers.
1979bf215546Sopenharmony_ci */
1980bf215546Sopenharmony_civoid
1981bf215546Sopenharmony_cidri2_flush_drawable_for_swapbuffers(_EGLDisplay *disp, _EGLSurface *draw)
1982bf215546Sopenharmony_ci{
1983bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1984bf215546Sopenharmony_ci   __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(draw);
1985bf215546Sopenharmony_ci
1986bf215546Sopenharmony_ci   if (dri2_dpy->flush) {
1987bf215546Sopenharmony_ci      if (dri2_dpy->flush->base.version >= 4) {
1988bf215546Sopenharmony_ci         /* We know there's a current context because:
1989bf215546Sopenharmony_ci          *
1990bf215546Sopenharmony_ci          *     "If surface is not bound to the calling thread’s current
1991bf215546Sopenharmony_ci          *      context, an EGL_BAD_SURFACE error is generated."
1992bf215546Sopenharmony_ci         */
1993bf215546Sopenharmony_ci         _EGLContext *ctx = _eglGetCurrentContext();
1994bf215546Sopenharmony_ci         struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1995bf215546Sopenharmony_ci
1996bf215546Sopenharmony_ci         /* From the EGL 1.4 spec (page 52):
1997bf215546Sopenharmony_ci          *
1998bf215546Sopenharmony_ci          *     "The contents of ancillary buffers are always undefined
1999bf215546Sopenharmony_ci          *      after calling eglSwapBuffers."
2000bf215546Sopenharmony_ci          */
2001bf215546Sopenharmony_ci         dri2_dpy->flush->flush_with_flags(dri2_ctx->dri_context,
2002bf215546Sopenharmony_ci                                           dri_drawable,
2003bf215546Sopenharmony_ci                                           __DRI2_FLUSH_DRAWABLE |
2004bf215546Sopenharmony_ci                                           __DRI2_FLUSH_INVALIDATE_ANCILLARY,
2005bf215546Sopenharmony_ci                                           __DRI2_THROTTLE_SWAPBUFFER);
2006bf215546Sopenharmony_ci      } else {
2007bf215546Sopenharmony_ci         dri2_dpy->flush->flush(dri_drawable);
2008bf215546Sopenharmony_ci      }
2009bf215546Sopenharmony_ci   }
2010bf215546Sopenharmony_ci}
2011bf215546Sopenharmony_ci
2012bf215546Sopenharmony_cistatic EGLBoolean
2013bf215546Sopenharmony_cidri2_swap_buffers(_EGLDisplay *disp, _EGLSurface *surf)
2014bf215546Sopenharmony_ci{
2015bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2016bf215546Sopenharmony_ci   __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2017bf215546Sopenharmony_ci   _EGLContext *ctx = _eglGetCurrentContext();
2018bf215546Sopenharmony_ci   EGLBoolean ret;
2019bf215546Sopenharmony_ci
2020bf215546Sopenharmony_ci   if (ctx && surf)
2021bf215546Sopenharmony_ci      dri2_surf_update_fence_fd(ctx, disp, surf);
2022bf215546Sopenharmony_ci   ret = dri2_dpy->vtbl->swap_buffers(disp, surf);
2023bf215546Sopenharmony_ci
2024bf215546Sopenharmony_ci   /* SwapBuffers marks the end of the frame; reset the damage region for
2025bf215546Sopenharmony_ci    * use again next time.
2026bf215546Sopenharmony_ci    */
2027bf215546Sopenharmony_ci   if (ret && dri2_dpy->buffer_damage &&
2028bf215546Sopenharmony_ci       dri2_dpy->buffer_damage->set_damage_region)
2029bf215546Sopenharmony_ci      dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL);
2030bf215546Sopenharmony_ci
2031bf215546Sopenharmony_ci   return ret;
2032bf215546Sopenharmony_ci}
2033bf215546Sopenharmony_ci
2034bf215546Sopenharmony_cistatic EGLBoolean
2035bf215546Sopenharmony_cidri2_swap_buffers_with_damage(_EGLDisplay *disp, _EGLSurface *surf,
2036bf215546Sopenharmony_ci                              const EGLint *rects, EGLint n_rects)
2037bf215546Sopenharmony_ci{
2038bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2039bf215546Sopenharmony_ci   __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2040bf215546Sopenharmony_ci   _EGLContext *ctx = _eglGetCurrentContext();
2041bf215546Sopenharmony_ci   EGLBoolean ret;
2042bf215546Sopenharmony_ci
2043bf215546Sopenharmony_ci   if (ctx && surf)
2044bf215546Sopenharmony_ci      dri2_surf_update_fence_fd(ctx, disp, surf);
2045bf215546Sopenharmony_ci   if (dri2_dpy->vtbl->swap_buffers_with_damage)
2046bf215546Sopenharmony_ci      ret = dri2_dpy->vtbl->swap_buffers_with_damage(disp, surf,
2047bf215546Sopenharmony_ci                                                     rects, n_rects);
2048bf215546Sopenharmony_ci   else
2049bf215546Sopenharmony_ci      ret = dri2_dpy->vtbl->swap_buffers(disp, surf);
2050bf215546Sopenharmony_ci
2051bf215546Sopenharmony_ci   /* SwapBuffers marks the end of the frame; reset the damage region for
2052bf215546Sopenharmony_ci    * use again next time.
2053bf215546Sopenharmony_ci    */
2054bf215546Sopenharmony_ci   if (ret && dri2_dpy->buffer_damage &&
2055bf215546Sopenharmony_ci       dri2_dpy->buffer_damage->set_damage_region)
2056bf215546Sopenharmony_ci      dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL);
2057bf215546Sopenharmony_ci
2058bf215546Sopenharmony_ci   return ret;
2059bf215546Sopenharmony_ci}
2060bf215546Sopenharmony_ci
2061bf215546Sopenharmony_cistatic EGLBoolean
2062bf215546Sopenharmony_cidri2_swap_buffers_region(_EGLDisplay *disp, _EGLSurface *surf,
2063bf215546Sopenharmony_ci                         EGLint numRects, const EGLint *rects)
2064bf215546Sopenharmony_ci{
2065bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2066bf215546Sopenharmony_ci   __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2067bf215546Sopenharmony_ci   EGLBoolean ret;
2068bf215546Sopenharmony_ci
2069bf215546Sopenharmony_ci   if (!dri2_dpy->vtbl->swap_buffers_region)
2070bf215546Sopenharmony_ci      return EGL_FALSE;
2071bf215546Sopenharmony_ci   ret = dri2_dpy->vtbl->swap_buffers_region(disp, surf, numRects, rects);
2072bf215546Sopenharmony_ci
2073bf215546Sopenharmony_ci   /* SwapBuffers marks the end of the frame; reset the damage region for
2074bf215546Sopenharmony_ci    * use again next time.
2075bf215546Sopenharmony_ci    */
2076bf215546Sopenharmony_ci   if (ret && dri2_dpy->buffer_damage &&
2077bf215546Sopenharmony_ci       dri2_dpy->buffer_damage->set_damage_region)
2078bf215546Sopenharmony_ci      dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL);
2079bf215546Sopenharmony_ci
2080bf215546Sopenharmony_ci   return ret;
2081bf215546Sopenharmony_ci}
2082bf215546Sopenharmony_ci
2083bf215546Sopenharmony_cistatic EGLBoolean
2084bf215546Sopenharmony_cidri2_set_damage_region(_EGLDisplay *disp, _EGLSurface *surf,
2085bf215546Sopenharmony_ci                       EGLint *rects, EGLint n_rects)
2086bf215546Sopenharmony_ci{
2087bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2088bf215546Sopenharmony_ci   __DRIdrawable *drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2089bf215546Sopenharmony_ci
2090bf215546Sopenharmony_ci   if (!dri2_dpy->buffer_damage || !dri2_dpy->buffer_damage->set_damage_region)
2091bf215546Sopenharmony_ci      return EGL_FALSE;
2092bf215546Sopenharmony_ci
2093bf215546Sopenharmony_ci   dri2_dpy->buffer_damage->set_damage_region(drawable, n_rects, rects);
2094bf215546Sopenharmony_ci   return EGL_TRUE;
2095bf215546Sopenharmony_ci}
2096bf215546Sopenharmony_ci
2097bf215546Sopenharmony_cistatic EGLBoolean
2098bf215546Sopenharmony_cidri2_post_sub_buffer(_EGLDisplay *disp, _EGLSurface *surf,
2099bf215546Sopenharmony_ci                     EGLint x, EGLint y, EGLint width, EGLint height)
2100bf215546Sopenharmony_ci{
2101bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2102bf215546Sopenharmony_ci   if (!dri2_dpy->vtbl->post_sub_buffer)
2103bf215546Sopenharmony_ci      return EGL_FALSE;
2104bf215546Sopenharmony_ci   return dri2_dpy->vtbl->post_sub_buffer(disp, surf, x, y, width, height);
2105bf215546Sopenharmony_ci}
2106bf215546Sopenharmony_ci
2107bf215546Sopenharmony_cistatic EGLBoolean
2108bf215546Sopenharmony_cidri2_copy_buffers(_EGLDisplay *disp, _EGLSurface *surf, void *native_pixmap_target)
2109bf215546Sopenharmony_ci{
2110bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2111bf215546Sopenharmony_ci   if (!dri2_dpy->vtbl->copy_buffers)
2112bf215546Sopenharmony_ci      return _eglError(EGL_BAD_NATIVE_PIXMAP, "no support for native pixmaps");
2113bf215546Sopenharmony_ci   return dri2_dpy->vtbl->copy_buffers(disp, surf, native_pixmap_target);
2114bf215546Sopenharmony_ci}
2115bf215546Sopenharmony_ci
2116bf215546Sopenharmony_cistatic EGLint
2117bf215546Sopenharmony_cidri2_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surf)
2118bf215546Sopenharmony_ci{
2119bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2120bf215546Sopenharmony_ci   if (!dri2_dpy->vtbl->query_buffer_age)
2121bf215546Sopenharmony_ci      return 0;
2122bf215546Sopenharmony_ci   return dri2_dpy->vtbl->query_buffer_age(disp, surf);
2123bf215546Sopenharmony_ci}
2124bf215546Sopenharmony_ci
2125bf215546Sopenharmony_cistatic EGLBoolean
2126bf215546Sopenharmony_cidri2_wait_client(_EGLDisplay *disp, _EGLContext *ctx)
2127bf215546Sopenharmony_ci{
2128bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2129bf215546Sopenharmony_ci   _EGLSurface *surf = ctx->DrawSurface;
2130bf215546Sopenharmony_ci   __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2131bf215546Sopenharmony_ci
2132bf215546Sopenharmony_ci   /* FIXME: If EGL allows frontbuffer rendering for window surfaces,
2133bf215546Sopenharmony_ci    * we need to copy fake to real here.*/
2134bf215546Sopenharmony_ci
2135bf215546Sopenharmony_ci   if (dri2_dpy->flush != NULL)
2136bf215546Sopenharmony_ci      dri2_dpy->flush->flush(dri_drawable);
2137bf215546Sopenharmony_ci
2138bf215546Sopenharmony_ci   return EGL_TRUE;
2139bf215546Sopenharmony_ci}
2140bf215546Sopenharmony_ci
2141bf215546Sopenharmony_cistatic EGLBoolean
2142bf215546Sopenharmony_cidri2_wait_native(EGLint engine)
2143bf215546Sopenharmony_ci{
2144bf215546Sopenharmony_ci   if (engine != EGL_CORE_NATIVE_ENGINE)
2145bf215546Sopenharmony_ci      return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
2146bf215546Sopenharmony_ci   /* glXWaitX(); */
2147bf215546Sopenharmony_ci
2148bf215546Sopenharmony_ci   return EGL_TRUE;
2149bf215546Sopenharmony_ci}
2150bf215546Sopenharmony_ci
2151bf215546Sopenharmony_cistatic EGLBoolean
2152bf215546Sopenharmony_cidri2_bind_tex_image(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
2153bf215546Sopenharmony_ci{
2154bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2155bf215546Sopenharmony_ci   struct dri2_egl_context *dri2_ctx;
2156bf215546Sopenharmony_ci   _EGLContext *ctx;
2157bf215546Sopenharmony_ci   GLint format, target;
2158bf215546Sopenharmony_ci   __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2159bf215546Sopenharmony_ci
2160bf215546Sopenharmony_ci   ctx = _eglGetCurrentContext();
2161bf215546Sopenharmony_ci   dri2_ctx = dri2_egl_context(ctx);
2162bf215546Sopenharmony_ci
2163bf215546Sopenharmony_ci   if (!_eglBindTexImage(disp, surf, buffer))
2164bf215546Sopenharmony_ci      return EGL_FALSE;
2165bf215546Sopenharmony_ci
2166bf215546Sopenharmony_ci   switch (surf->TextureFormat) {
2167bf215546Sopenharmony_ci   case EGL_TEXTURE_RGB:
2168bf215546Sopenharmony_ci      format = __DRI_TEXTURE_FORMAT_RGB;
2169bf215546Sopenharmony_ci      break;
2170bf215546Sopenharmony_ci   case EGL_TEXTURE_RGBA:
2171bf215546Sopenharmony_ci      format = __DRI_TEXTURE_FORMAT_RGBA;
2172bf215546Sopenharmony_ci      break;
2173bf215546Sopenharmony_ci   default:
2174bf215546Sopenharmony_ci      assert(!"Unexpected texture format in dri2_bind_tex_image()");
2175bf215546Sopenharmony_ci      format = __DRI_TEXTURE_FORMAT_RGBA;
2176bf215546Sopenharmony_ci   }
2177bf215546Sopenharmony_ci
2178bf215546Sopenharmony_ci   switch (surf->TextureTarget) {
2179bf215546Sopenharmony_ci   case EGL_TEXTURE_2D:
2180bf215546Sopenharmony_ci      target = GL_TEXTURE_2D;
2181bf215546Sopenharmony_ci      break;
2182bf215546Sopenharmony_ci   default:
2183bf215546Sopenharmony_ci      target = GL_TEXTURE_2D;
2184bf215546Sopenharmony_ci      assert(!"Unexpected texture target in dri2_bind_tex_image()");
2185bf215546Sopenharmony_ci   }
2186bf215546Sopenharmony_ci
2187bf215546Sopenharmony_ci   dri2_dpy->tex_buffer->setTexBuffer2(dri2_ctx->dri_context,
2188bf215546Sopenharmony_ci                                       target, format,
2189bf215546Sopenharmony_ci                                       dri_drawable);
2190bf215546Sopenharmony_ci
2191bf215546Sopenharmony_ci   return EGL_TRUE;
2192bf215546Sopenharmony_ci}
2193bf215546Sopenharmony_ci
2194bf215546Sopenharmony_cistatic EGLBoolean
2195bf215546Sopenharmony_cidri2_release_tex_image(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
2196bf215546Sopenharmony_ci{
2197bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2198bf215546Sopenharmony_ci   struct dri2_egl_context *dri2_ctx;
2199bf215546Sopenharmony_ci   _EGLContext *ctx;
2200bf215546Sopenharmony_ci   GLint  target;
2201bf215546Sopenharmony_ci   __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2202bf215546Sopenharmony_ci
2203bf215546Sopenharmony_ci   ctx = _eglGetCurrentContext();
2204bf215546Sopenharmony_ci   dri2_ctx = dri2_egl_context(ctx);
2205bf215546Sopenharmony_ci
2206bf215546Sopenharmony_ci   if (!_eglReleaseTexImage(disp, surf, buffer))
2207bf215546Sopenharmony_ci      return EGL_FALSE;
2208bf215546Sopenharmony_ci
2209bf215546Sopenharmony_ci   switch (surf->TextureTarget) {
2210bf215546Sopenharmony_ci   case EGL_TEXTURE_2D:
2211bf215546Sopenharmony_ci      target = GL_TEXTURE_2D;
2212bf215546Sopenharmony_ci      break;
2213bf215546Sopenharmony_ci   default:
2214bf215546Sopenharmony_ci      assert(!"missing texture target");
2215bf215546Sopenharmony_ci   }
2216bf215546Sopenharmony_ci
2217bf215546Sopenharmony_ci   if (dri2_dpy->tex_buffer->base.version >= 3 &&
2218bf215546Sopenharmony_ci       dri2_dpy->tex_buffer->releaseTexBuffer != NULL) {
2219bf215546Sopenharmony_ci      dri2_dpy->tex_buffer->releaseTexBuffer(dri2_ctx->dri_context,
2220bf215546Sopenharmony_ci                                             target, dri_drawable);
2221bf215546Sopenharmony_ci   }
2222bf215546Sopenharmony_ci
2223bf215546Sopenharmony_ci   return EGL_TRUE;
2224bf215546Sopenharmony_ci}
2225bf215546Sopenharmony_ci
2226bf215546Sopenharmony_cistatic _EGLImage*
2227bf215546Sopenharmony_cidri2_create_image(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
2228bf215546Sopenharmony_ci                  EGLClientBuffer buffer, const EGLint *attr_list)
2229bf215546Sopenharmony_ci{
2230bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2231bf215546Sopenharmony_ci   return dri2_dpy->vtbl->create_image(disp, ctx, target, buffer,
2232bf215546Sopenharmony_ci                                       attr_list);
2233bf215546Sopenharmony_ci}
2234bf215546Sopenharmony_ci
2235bf215546Sopenharmony_ci_EGLImage *
2236bf215546Sopenharmony_cidri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image)
2237bf215546Sopenharmony_ci{
2238bf215546Sopenharmony_ci   struct dri2_egl_image *dri2_img;
2239bf215546Sopenharmony_ci
2240bf215546Sopenharmony_ci   if (dri_image == NULL) {
2241bf215546Sopenharmony_ci      _eglError(EGL_BAD_ALLOC, "dri2_create_image");
2242bf215546Sopenharmony_ci      return NULL;
2243bf215546Sopenharmony_ci   }
2244bf215546Sopenharmony_ci
2245bf215546Sopenharmony_ci   dri2_img = malloc(sizeof *dri2_img);
2246bf215546Sopenharmony_ci   if (!dri2_img) {
2247bf215546Sopenharmony_ci      _eglError(EGL_BAD_ALLOC, "dri2_create_image");
2248bf215546Sopenharmony_ci      return NULL;
2249bf215546Sopenharmony_ci   }
2250bf215546Sopenharmony_ci
2251bf215546Sopenharmony_ci   _eglInitImage(&dri2_img->base, disp);
2252bf215546Sopenharmony_ci
2253bf215546Sopenharmony_ci   dri2_img->dri_image = dri_image;
2254bf215546Sopenharmony_ci
2255bf215546Sopenharmony_ci   return &dri2_img->base;
2256bf215546Sopenharmony_ci}
2257bf215546Sopenharmony_ci
2258bf215546Sopenharmony_ci/**
2259bf215546Sopenharmony_ci * Translate a DRI Image extension error code into an EGL error code.
2260bf215546Sopenharmony_ci */
2261bf215546Sopenharmony_cistatic EGLint
2262bf215546Sopenharmony_ciegl_error_from_dri_image_error(int dri_error)
2263bf215546Sopenharmony_ci{
2264bf215546Sopenharmony_ci   switch (dri_error) {
2265bf215546Sopenharmony_ci   case __DRI_IMAGE_ERROR_SUCCESS:
2266bf215546Sopenharmony_ci      return EGL_SUCCESS;
2267bf215546Sopenharmony_ci   case __DRI_IMAGE_ERROR_BAD_ALLOC:
2268bf215546Sopenharmony_ci      return EGL_BAD_ALLOC;
2269bf215546Sopenharmony_ci   case __DRI_IMAGE_ERROR_BAD_MATCH:
2270bf215546Sopenharmony_ci      return EGL_BAD_MATCH;
2271bf215546Sopenharmony_ci   case __DRI_IMAGE_ERROR_BAD_PARAMETER:
2272bf215546Sopenharmony_ci      return EGL_BAD_PARAMETER;
2273bf215546Sopenharmony_ci   case __DRI_IMAGE_ERROR_BAD_ACCESS:
2274bf215546Sopenharmony_ci      return EGL_BAD_ACCESS;
2275bf215546Sopenharmony_ci   default:
2276bf215546Sopenharmony_ci      assert(!"unknown dri_error code");
2277bf215546Sopenharmony_ci      return EGL_BAD_ALLOC;
2278bf215546Sopenharmony_ci   }
2279bf215546Sopenharmony_ci}
2280bf215546Sopenharmony_ci
2281bf215546Sopenharmony_cistatic _EGLImage *
2282bf215546Sopenharmony_cidri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
2283bf215546Sopenharmony_ci                                   EGLClientBuffer buffer,
2284bf215546Sopenharmony_ci                                   const EGLint *attr_list)
2285bf215546Sopenharmony_ci{
2286bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2287bf215546Sopenharmony_ci   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
2288bf215546Sopenharmony_ci   GLuint renderbuffer = (GLuint) (uintptr_t) buffer;
2289bf215546Sopenharmony_ci   __DRIimage *dri_image;
2290bf215546Sopenharmony_ci
2291bf215546Sopenharmony_ci   if (renderbuffer == 0) {
2292bf215546Sopenharmony_ci      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2293bf215546Sopenharmony_ci      return EGL_NO_IMAGE_KHR;
2294bf215546Sopenharmony_ci   }
2295bf215546Sopenharmony_ci
2296bf215546Sopenharmony_ci   if (!disp->Extensions.KHR_gl_renderbuffer_image) {
2297bf215546Sopenharmony_ci      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2298bf215546Sopenharmony_ci      return EGL_NO_IMAGE_KHR;
2299bf215546Sopenharmony_ci   }
2300bf215546Sopenharmony_ci
2301bf215546Sopenharmony_ci   if (dri2_dpy->image->base.version >= 17 &&
2302bf215546Sopenharmony_ci       dri2_dpy->image->createImageFromRenderbuffer2) {
2303bf215546Sopenharmony_ci      unsigned error = ~0;
2304bf215546Sopenharmony_ci
2305bf215546Sopenharmony_ci      dri_image = dri2_dpy->image->createImageFromRenderbuffer2(
2306bf215546Sopenharmony_ci               dri2_ctx->dri_context, renderbuffer, NULL, &error);
2307bf215546Sopenharmony_ci
2308bf215546Sopenharmony_ci      assert(!!dri_image == (error == __DRI_IMAGE_ERROR_SUCCESS));
2309bf215546Sopenharmony_ci
2310bf215546Sopenharmony_ci      if (!dri_image) {
2311bf215546Sopenharmony_ci         _eglError(egl_error_from_dri_image_error(error), "dri2_create_image_khr");
2312bf215546Sopenharmony_ci         return EGL_NO_IMAGE_KHR;
2313bf215546Sopenharmony_ci      }
2314bf215546Sopenharmony_ci   } else {
2315bf215546Sopenharmony_ci      dri_image = dri2_dpy->image->createImageFromRenderbuffer(
2316bf215546Sopenharmony_ci               dri2_ctx->dri_context, renderbuffer, NULL);
2317bf215546Sopenharmony_ci      if (!dri_image) {
2318bf215546Sopenharmony_ci         _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
2319bf215546Sopenharmony_ci         return EGL_NO_IMAGE_KHR;
2320bf215546Sopenharmony_ci      }
2321bf215546Sopenharmony_ci   }
2322bf215546Sopenharmony_ci
2323bf215546Sopenharmony_ci   return dri2_create_image_from_dri(disp, dri_image);
2324bf215546Sopenharmony_ci}
2325bf215546Sopenharmony_ci
2326bf215546Sopenharmony_ci#ifdef HAVE_WAYLAND_PLATFORM
2327bf215546Sopenharmony_ci
2328bf215546Sopenharmony_ci/* This structure describes how a wl_buffer maps to one or more
2329bf215546Sopenharmony_ci * __DRIimages.  A wl_drm_buffer stores the wl_drm format code and the
2330bf215546Sopenharmony_ci * offsets and strides of the planes in the buffer.  This table maps a
2331bf215546Sopenharmony_ci * wl_drm format code to a description of the planes in the buffer
2332bf215546Sopenharmony_ci * that lets us create a __DRIimage for each of the planes. */
2333bf215546Sopenharmony_ci
2334bf215546Sopenharmony_cistatic const struct wl_drm_components_descriptor {
2335bf215546Sopenharmony_ci   uint32_t dri_components;
2336bf215546Sopenharmony_ci   EGLint components;
2337bf215546Sopenharmony_ci   int nplanes;
2338bf215546Sopenharmony_ci} wl_drm_components[] = {
2339bf215546Sopenharmony_ci   { __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 },
2340bf215546Sopenharmony_ci   { __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 },
2341bf215546Sopenharmony_ci   { __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 },
2342bf215546Sopenharmony_ci   { __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 },
2343bf215546Sopenharmony_ci   { __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 },
2344bf215546Sopenharmony_ci};
2345bf215546Sopenharmony_ci
2346bf215546Sopenharmony_cistatic _EGLImage *
2347bf215546Sopenharmony_cidri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
2348bf215546Sopenharmony_ci                                    EGLClientBuffer _buffer,
2349bf215546Sopenharmony_ci                                    const EGLint *attr_list)
2350bf215546Sopenharmony_ci{
2351bf215546Sopenharmony_ci   struct wl_drm_buffer *buffer;
2352bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2353bf215546Sopenharmony_ci   const struct wl_drm_components_descriptor *f;
2354bf215546Sopenharmony_ci   __DRIimage *dri_image;
2355bf215546Sopenharmony_ci   _EGLImageAttribs attrs;
2356bf215546Sopenharmony_ci   int32_t plane;
2357bf215546Sopenharmony_ci
2358bf215546Sopenharmony_ci   buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm,
2359bf215546Sopenharmony_ci                                   (struct wl_resource *) _buffer);
2360bf215546Sopenharmony_ci   if (!buffer)
2361bf215546Sopenharmony_ci       return NULL;
2362bf215546Sopenharmony_ci
2363bf215546Sopenharmony_ci   if (!_eglParseImageAttribList(&attrs, disp, attr_list))
2364bf215546Sopenharmony_ci      return NULL;
2365bf215546Sopenharmony_ci
2366bf215546Sopenharmony_ci   plane = attrs.PlaneWL;
2367bf215546Sopenharmony_ci   f = buffer->driver_format;
2368bf215546Sopenharmony_ci   if (plane < 0 || plane >= f->nplanes) {
2369bf215546Sopenharmony_ci      _eglError(EGL_BAD_PARAMETER,
2370bf215546Sopenharmony_ci                "dri2_create_image_wayland_wl_buffer (plane out of bounds)");
2371bf215546Sopenharmony_ci      return NULL;
2372bf215546Sopenharmony_ci   }
2373bf215546Sopenharmony_ci
2374bf215546Sopenharmony_ci   dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL);
2375bf215546Sopenharmony_ci   if (dri_image == NULL && plane == 0)
2376bf215546Sopenharmony_ci      dri_image = dri2_dpy->image->dupImage(buffer->driver_buffer, NULL);
2377bf215546Sopenharmony_ci   if (dri_image == NULL) {
2378bf215546Sopenharmony_ci      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
2379bf215546Sopenharmony_ci      return NULL;
2380bf215546Sopenharmony_ci   }
2381bf215546Sopenharmony_ci
2382bf215546Sopenharmony_ci   return dri2_create_image_from_dri(disp, dri_image);
2383bf215546Sopenharmony_ci}
2384bf215546Sopenharmony_ci#endif
2385bf215546Sopenharmony_ci
2386bf215546Sopenharmony_cistatic EGLBoolean
2387bf215546Sopenharmony_cidri2_get_sync_values_chromium(_EGLDisplay *disp, _EGLSurface *surf,
2388bf215546Sopenharmony_ci                              EGLuint64KHR *ust, EGLuint64KHR *msc,
2389bf215546Sopenharmony_ci                              EGLuint64KHR *sbc)
2390bf215546Sopenharmony_ci{
2391bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2392bf215546Sopenharmony_ci   if (!dri2_dpy->vtbl->get_sync_values)
2393bf215546Sopenharmony_ci      return EGL_FALSE;
2394bf215546Sopenharmony_ci   return dri2_dpy->vtbl->get_sync_values(disp, surf, ust, msc, sbc);
2395bf215546Sopenharmony_ci}
2396bf215546Sopenharmony_ci
2397bf215546Sopenharmony_ci/**
2398bf215546Sopenharmony_ci * Set the error code after a call to
2399bf215546Sopenharmony_ci * dri2_egl_image::dri_image::createImageFromTexture.
2400bf215546Sopenharmony_ci */
2401bf215546Sopenharmony_cistatic void
2402bf215546Sopenharmony_cidri2_create_image_khr_texture_error(int dri_error)
2403bf215546Sopenharmony_ci{
2404bf215546Sopenharmony_ci   EGLint egl_error = egl_error_from_dri_image_error(dri_error);
2405bf215546Sopenharmony_ci
2406bf215546Sopenharmony_ci   if (egl_error != EGL_SUCCESS)
2407bf215546Sopenharmony_ci      _eglError(egl_error, "dri2_create_image_khr_texture");
2408bf215546Sopenharmony_ci}
2409bf215546Sopenharmony_ci
2410bf215546Sopenharmony_cistatic _EGLImage *
2411bf215546Sopenharmony_cidri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
2412bf215546Sopenharmony_ci                                   EGLenum target,
2413bf215546Sopenharmony_ci                                   EGLClientBuffer buffer,
2414bf215546Sopenharmony_ci                                   const EGLint *attr_list)
2415bf215546Sopenharmony_ci{
2416bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2417bf215546Sopenharmony_ci   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
2418bf215546Sopenharmony_ci   struct dri2_egl_image *dri2_img;
2419bf215546Sopenharmony_ci   GLuint texture = (GLuint) (uintptr_t) buffer;
2420bf215546Sopenharmony_ci   _EGLImageAttribs attrs;
2421bf215546Sopenharmony_ci   GLuint depth;
2422bf215546Sopenharmony_ci   GLenum gl_target;
2423bf215546Sopenharmony_ci   unsigned error;
2424bf215546Sopenharmony_ci
2425bf215546Sopenharmony_ci   if (texture == 0) {
2426bf215546Sopenharmony_ci      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2427bf215546Sopenharmony_ci      return EGL_NO_IMAGE_KHR;
2428bf215546Sopenharmony_ci   }
2429bf215546Sopenharmony_ci
2430bf215546Sopenharmony_ci   if (!_eglParseImageAttribList(&attrs, disp, attr_list))
2431bf215546Sopenharmony_ci      return EGL_NO_IMAGE_KHR;
2432bf215546Sopenharmony_ci
2433bf215546Sopenharmony_ci   switch (target) {
2434bf215546Sopenharmony_ci   case EGL_GL_TEXTURE_2D_KHR:
2435bf215546Sopenharmony_ci      if (!disp->Extensions.KHR_gl_texture_2D_image) {
2436bf215546Sopenharmony_ci         _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2437bf215546Sopenharmony_ci         return EGL_NO_IMAGE_KHR;
2438bf215546Sopenharmony_ci      }
2439bf215546Sopenharmony_ci      depth = 0;
2440bf215546Sopenharmony_ci      gl_target = GL_TEXTURE_2D;
2441bf215546Sopenharmony_ci      break;
2442bf215546Sopenharmony_ci   case EGL_GL_TEXTURE_3D_KHR:
2443bf215546Sopenharmony_ci      if (!disp->Extensions.KHR_gl_texture_3D_image) {
2444bf215546Sopenharmony_ci         _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2445bf215546Sopenharmony_ci         return EGL_NO_IMAGE_KHR;
2446bf215546Sopenharmony_ci      }
2447bf215546Sopenharmony_ci
2448bf215546Sopenharmony_ci      depth = attrs.GLTextureZOffset;
2449bf215546Sopenharmony_ci      gl_target = GL_TEXTURE_3D;
2450bf215546Sopenharmony_ci      break;
2451bf215546Sopenharmony_ci   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
2452bf215546Sopenharmony_ci   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
2453bf215546Sopenharmony_ci   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
2454bf215546Sopenharmony_ci   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
2455bf215546Sopenharmony_ci   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
2456bf215546Sopenharmony_ci   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
2457bf215546Sopenharmony_ci      if (!disp->Extensions.KHR_gl_texture_cubemap_image) {
2458bf215546Sopenharmony_ci         _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2459bf215546Sopenharmony_ci         return EGL_NO_IMAGE_KHR;
2460bf215546Sopenharmony_ci      }
2461bf215546Sopenharmony_ci
2462bf215546Sopenharmony_ci      depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
2463bf215546Sopenharmony_ci      gl_target = GL_TEXTURE_CUBE_MAP;
2464bf215546Sopenharmony_ci      break;
2465bf215546Sopenharmony_ci   default:
2466bf215546Sopenharmony_ci      unreachable("Unexpected target in dri2_create_image_khr_texture()");
2467bf215546Sopenharmony_ci      return EGL_NO_IMAGE_KHR;
2468bf215546Sopenharmony_ci   }
2469bf215546Sopenharmony_ci
2470bf215546Sopenharmony_ci   dri2_img = malloc(sizeof *dri2_img);
2471bf215546Sopenharmony_ci   if (!dri2_img) {
2472bf215546Sopenharmony_ci      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
2473bf215546Sopenharmony_ci      return EGL_NO_IMAGE_KHR;
2474bf215546Sopenharmony_ci   }
2475bf215546Sopenharmony_ci
2476bf215546Sopenharmony_ci   _eglInitImage(&dri2_img->base, disp);
2477bf215546Sopenharmony_ci
2478bf215546Sopenharmony_ci   dri2_img->dri_image =
2479bf215546Sopenharmony_ci      dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context,
2480bf215546Sopenharmony_ci                                              gl_target,
2481bf215546Sopenharmony_ci                                              texture,
2482bf215546Sopenharmony_ci                                              depth,
2483bf215546Sopenharmony_ci                                              attrs.GLTextureLevel,
2484bf215546Sopenharmony_ci                                              &error,
2485bf215546Sopenharmony_ci                                              NULL);
2486bf215546Sopenharmony_ci   dri2_create_image_khr_texture_error(error);
2487bf215546Sopenharmony_ci
2488bf215546Sopenharmony_ci   if (!dri2_img->dri_image) {
2489bf215546Sopenharmony_ci      free(dri2_img);
2490bf215546Sopenharmony_ci      return EGL_NO_IMAGE_KHR;
2491bf215546Sopenharmony_ci   }
2492bf215546Sopenharmony_ci   return &dri2_img->base;
2493bf215546Sopenharmony_ci}
2494bf215546Sopenharmony_ci
2495bf215546Sopenharmony_cistatic EGLBoolean
2496bf215546Sopenharmony_cidri2_query_surface(_EGLDisplay *disp, _EGLSurface *surf,
2497bf215546Sopenharmony_ci                   EGLint attribute, EGLint *value)
2498bf215546Sopenharmony_ci{
2499bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2500bf215546Sopenharmony_ci   if (!dri2_dpy->vtbl->query_surface)
2501bf215546Sopenharmony_ci      return _eglQuerySurface(disp, surf, attribute, value);
2502bf215546Sopenharmony_ci   return dri2_dpy->vtbl->query_surface(disp, surf, attribute, value);
2503bf215546Sopenharmony_ci}
2504bf215546Sopenharmony_ci
2505bf215546Sopenharmony_cistatic struct wl_buffer*
2506bf215546Sopenharmony_cidri2_create_wayland_buffer_from_image(_EGLDisplay *disp, _EGLImage *img)
2507bf215546Sopenharmony_ci{
2508bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2509bf215546Sopenharmony_ci   if (!dri2_dpy->vtbl->create_wayland_buffer_from_image)
2510bf215546Sopenharmony_ci      return NULL;
2511bf215546Sopenharmony_ci   return dri2_dpy->vtbl->create_wayland_buffer_from_image(disp, img);
2512bf215546Sopenharmony_ci}
2513bf215546Sopenharmony_ci
2514bf215546Sopenharmony_ci#ifdef HAVE_LIBDRM
2515bf215546Sopenharmony_cistatic _EGLImage *
2516bf215546Sopenharmony_cidri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
2517bf215546Sopenharmony_ci                                  EGLClientBuffer buffer, const EGLint *attr_list)
2518bf215546Sopenharmony_ci{
2519bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2520bf215546Sopenharmony_ci   EGLint format, name, pitch;
2521bf215546Sopenharmony_ci   _EGLImageAttribs attrs;
2522bf215546Sopenharmony_ci   __DRIimage *dri_image;
2523bf215546Sopenharmony_ci
2524bf215546Sopenharmony_ci   name = (EGLint) (uintptr_t) buffer;
2525bf215546Sopenharmony_ci
2526bf215546Sopenharmony_ci   if (!_eglParseImageAttribList(&attrs, disp, attr_list))
2527bf215546Sopenharmony_ci      return NULL;
2528bf215546Sopenharmony_ci
2529bf215546Sopenharmony_ci   if (attrs.Width <= 0 || attrs.Height <= 0 ||
2530bf215546Sopenharmony_ci       attrs.DRMBufferStrideMESA <= 0) {
2531bf215546Sopenharmony_ci      _eglError(EGL_BAD_PARAMETER,
2532bf215546Sopenharmony_ci                "bad width, height or stride");
2533bf215546Sopenharmony_ci      return NULL;
2534bf215546Sopenharmony_ci   }
2535bf215546Sopenharmony_ci
2536bf215546Sopenharmony_ci   switch (attrs.DRMBufferFormatMESA) {
2537bf215546Sopenharmony_ci   case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
2538bf215546Sopenharmony_ci      format = __DRI_IMAGE_FORMAT_ARGB8888;
2539bf215546Sopenharmony_ci      pitch = attrs.DRMBufferStrideMESA;
2540bf215546Sopenharmony_ci      break;
2541bf215546Sopenharmony_ci   default:
2542bf215546Sopenharmony_ci      _eglError(EGL_BAD_PARAMETER,
2543bf215546Sopenharmony_ci                "dri2_create_image_khr: unsupported pixmap depth");
2544bf215546Sopenharmony_ci      return NULL;
2545bf215546Sopenharmony_ci   }
2546bf215546Sopenharmony_ci
2547bf215546Sopenharmony_ci   dri_image =
2548bf215546Sopenharmony_ci      dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
2549bf215546Sopenharmony_ci                                           attrs.Width,
2550bf215546Sopenharmony_ci                                           attrs.Height,
2551bf215546Sopenharmony_ci                                           format,
2552bf215546Sopenharmony_ci                                           name,
2553bf215546Sopenharmony_ci                                           pitch,
2554bf215546Sopenharmony_ci                                           NULL);
2555bf215546Sopenharmony_ci
2556bf215546Sopenharmony_ci   return dri2_create_image_from_dri(disp, dri_image);
2557bf215546Sopenharmony_ci}
2558bf215546Sopenharmony_ci
2559bf215546Sopenharmony_cistatic EGLBoolean
2560bf215546Sopenharmony_cidri2_check_dma_buf_attribs(const _EGLImageAttribs *attrs)
2561bf215546Sopenharmony_ci{
2562bf215546Sopenharmony_ci   /**
2563bf215546Sopenharmony_ci     * The spec says:
2564bf215546Sopenharmony_ci     *
2565bf215546Sopenharmony_ci     * "Required attributes and their values are as follows:
2566bf215546Sopenharmony_ci     *
2567bf215546Sopenharmony_ci     *  * EGL_WIDTH & EGL_HEIGHT: The logical dimensions of the buffer in pixels
2568bf215546Sopenharmony_ci     *
2569bf215546Sopenharmony_ci     *  * EGL_LINUX_DRM_FOURCC_EXT: The pixel format of the buffer, as specified
2570bf215546Sopenharmony_ci     *    by drm_fourcc.h and used as the pixel_format parameter of the
2571bf215546Sopenharmony_ci     *    drm_mode_fb_cmd2 ioctl."
2572bf215546Sopenharmony_ci     *
2573bf215546Sopenharmony_ci     * and
2574bf215546Sopenharmony_ci     *
2575bf215546Sopenharmony_ci     * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is
2576bf215546Sopenharmony_ci     *    incomplete, EGL_BAD_PARAMETER is generated."
2577bf215546Sopenharmony_ci     */
2578bf215546Sopenharmony_ci   if (attrs->Width <= 0 || attrs->Height <= 0 ||
2579bf215546Sopenharmony_ci       !attrs->DMABufFourCC.IsPresent)
2580bf215546Sopenharmony_ci      return _eglError(EGL_BAD_PARAMETER, "attribute(s) missing");
2581bf215546Sopenharmony_ci
2582bf215546Sopenharmony_ci   /**
2583bf215546Sopenharmony_ci    * Also:
2584bf215546Sopenharmony_ci    *
2585bf215546Sopenharmony_ci    * "If <target> is EGL_LINUX_DMA_BUF_EXT and one or more of the values
2586bf215546Sopenharmony_ci    *  specified for a plane's pitch or offset isn't supported by EGL,
2587bf215546Sopenharmony_ci    *  EGL_BAD_ACCESS is generated."
2588bf215546Sopenharmony_ci    */
2589bf215546Sopenharmony_ci   for (unsigned i = 0; i < ARRAY_SIZE(attrs->DMABufPlanePitches); ++i) {
2590bf215546Sopenharmony_ci      if (attrs->DMABufPlanePitches[i].IsPresent &&
2591bf215546Sopenharmony_ci          attrs->DMABufPlanePitches[i].Value <= 0)
2592bf215546Sopenharmony_ci         return _eglError(EGL_BAD_ACCESS, "invalid pitch");
2593bf215546Sopenharmony_ci   }
2594bf215546Sopenharmony_ci
2595bf215546Sopenharmony_ci   /**
2596bf215546Sopenharmony_ci    * If <target> is EGL_LINUX_DMA_BUF_EXT, both or neither of the following
2597bf215546Sopenharmony_ci    * attribute values may be given.
2598bf215546Sopenharmony_ci    *
2599bf215546Sopenharmony_ci    * This is referring to EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT and
2600bf215546Sopenharmony_ci    * EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, and the same for other planes.
2601bf215546Sopenharmony_ci    */
2602bf215546Sopenharmony_ci   for (unsigned i = 0; i < DMA_BUF_MAX_PLANES; ++i) {
2603bf215546Sopenharmony_ci      if (attrs->DMABufPlaneModifiersLo[i].IsPresent !=
2604bf215546Sopenharmony_ci          attrs->DMABufPlaneModifiersHi[i].IsPresent)
2605bf215546Sopenharmony_ci         return _eglError(EGL_BAD_PARAMETER, "modifier attribute lo or hi missing");
2606bf215546Sopenharmony_ci   }
2607bf215546Sopenharmony_ci
2608bf215546Sopenharmony_ci   /* Although the EGL_EXT_image_dma_buf_import_modifiers spec doesn't
2609bf215546Sopenharmony_ci    * mandate it, we only accept the same modifier across all planes. */
2610bf215546Sopenharmony_ci   for (unsigned i = 1; i < DMA_BUF_MAX_PLANES; ++i) {
2611bf215546Sopenharmony_ci      if (attrs->DMABufPlaneFds[i].IsPresent) {
2612bf215546Sopenharmony_ci         if ((attrs->DMABufPlaneModifiersLo[0].IsPresent !=
2613bf215546Sopenharmony_ci               attrs->DMABufPlaneModifiersLo[i].IsPresent) ||
2614bf215546Sopenharmony_ci             (attrs->DMABufPlaneModifiersLo[0].Value !=
2615bf215546Sopenharmony_ci               attrs->DMABufPlaneModifiersLo[i].Value) ||
2616bf215546Sopenharmony_ci             (attrs->DMABufPlaneModifiersHi[0].Value !=
2617bf215546Sopenharmony_ci               attrs->DMABufPlaneModifiersHi[i].Value))
2618bf215546Sopenharmony_ci            return _eglError(EGL_BAD_PARAMETER, "modifier attributes not equal");
2619bf215546Sopenharmony_ci      }
2620bf215546Sopenharmony_ci   }
2621bf215546Sopenharmony_ci
2622bf215546Sopenharmony_ci   return EGL_TRUE;
2623bf215546Sopenharmony_ci}
2624bf215546Sopenharmony_ci
2625bf215546Sopenharmony_ci/* Returns the total number of planes for the format or zero if it isn't a
2626bf215546Sopenharmony_ci * valid fourcc format.
2627bf215546Sopenharmony_ci */
2628bf215546Sopenharmony_cistatic unsigned
2629bf215546Sopenharmony_cidri2_num_fourcc_format_planes(EGLint format)
2630bf215546Sopenharmony_ci{
2631bf215546Sopenharmony_ci   switch (format) {
2632bf215546Sopenharmony_ci   case DRM_FORMAT_R8:
2633bf215546Sopenharmony_ci   case DRM_FORMAT_RG88:
2634bf215546Sopenharmony_ci   case DRM_FORMAT_GR88:
2635bf215546Sopenharmony_ci   case DRM_FORMAT_R16:
2636bf215546Sopenharmony_ci   case DRM_FORMAT_GR1616:
2637bf215546Sopenharmony_ci   case DRM_FORMAT_RGB332:
2638bf215546Sopenharmony_ci   case DRM_FORMAT_BGR233:
2639bf215546Sopenharmony_ci   case DRM_FORMAT_XRGB4444:
2640bf215546Sopenharmony_ci   case DRM_FORMAT_XBGR4444:
2641bf215546Sopenharmony_ci   case DRM_FORMAT_RGBX4444:
2642bf215546Sopenharmony_ci   case DRM_FORMAT_BGRX4444:
2643bf215546Sopenharmony_ci   case DRM_FORMAT_ARGB4444:
2644bf215546Sopenharmony_ci   case DRM_FORMAT_ABGR4444:
2645bf215546Sopenharmony_ci   case DRM_FORMAT_RGBA4444:
2646bf215546Sopenharmony_ci   case DRM_FORMAT_BGRA4444:
2647bf215546Sopenharmony_ci   case DRM_FORMAT_XRGB1555:
2648bf215546Sopenharmony_ci   case DRM_FORMAT_XBGR1555:
2649bf215546Sopenharmony_ci   case DRM_FORMAT_RGBX5551:
2650bf215546Sopenharmony_ci   case DRM_FORMAT_BGRX5551:
2651bf215546Sopenharmony_ci   case DRM_FORMAT_ARGB1555:
2652bf215546Sopenharmony_ci   case DRM_FORMAT_ABGR1555:
2653bf215546Sopenharmony_ci   case DRM_FORMAT_RGBA5551:
2654bf215546Sopenharmony_ci   case DRM_FORMAT_BGRA5551:
2655bf215546Sopenharmony_ci   case DRM_FORMAT_RGB565:
2656bf215546Sopenharmony_ci   case DRM_FORMAT_BGR565:
2657bf215546Sopenharmony_ci   case DRM_FORMAT_RGB888:
2658bf215546Sopenharmony_ci   case DRM_FORMAT_BGR888:
2659bf215546Sopenharmony_ci   case DRM_FORMAT_XRGB8888:
2660bf215546Sopenharmony_ci   case DRM_FORMAT_XBGR8888:
2661bf215546Sopenharmony_ci   case DRM_FORMAT_RGBX8888:
2662bf215546Sopenharmony_ci   case DRM_FORMAT_BGRX8888:
2663bf215546Sopenharmony_ci   case DRM_FORMAT_ARGB8888:
2664bf215546Sopenharmony_ci   case DRM_FORMAT_ABGR8888:
2665bf215546Sopenharmony_ci   case DRM_FORMAT_RGBA8888:
2666bf215546Sopenharmony_ci   case DRM_FORMAT_BGRA8888:
2667bf215546Sopenharmony_ci   case DRM_FORMAT_XRGB2101010:
2668bf215546Sopenharmony_ci   case DRM_FORMAT_XBGR2101010:
2669bf215546Sopenharmony_ci   case DRM_FORMAT_RGBX1010102:
2670bf215546Sopenharmony_ci   case DRM_FORMAT_BGRX1010102:
2671bf215546Sopenharmony_ci   case DRM_FORMAT_ARGB2101010:
2672bf215546Sopenharmony_ci   case DRM_FORMAT_ABGR2101010:
2673bf215546Sopenharmony_ci   case DRM_FORMAT_RGBA1010102:
2674bf215546Sopenharmony_ci   case DRM_FORMAT_BGRA1010102:
2675bf215546Sopenharmony_ci   case DRM_FORMAT_ABGR16161616:
2676bf215546Sopenharmony_ci   case DRM_FORMAT_XBGR16161616:
2677bf215546Sopenharmony_ci   case DRM_FORMAT_XBGR16161616F:
2678bf215546Sopenharmony_ci   case DRM_FORMAT_ABGR16161616F:
2679bf215546Sopenharmony_ci   case DRM_FORMAT_YUYV:
2680bf215546Sopenharmony_ci   case DRM_FORMAT_YVYU:
2681bf215546Sopenharmony_ci   case DRM_FORMAT_UYVY:
2682bf215546Sopenharmony_ci   case DRM_FORMAT_VYUY:
2683bf215546Sopenharmony_ci   case DRM_FORMAT_AYUV:
2684bf215546Sopenharmony_ci   case DRM_FORMAT_XYUV8888:
2685bf215546Sopenharmony_ci   case DRM_FORMAT_Y210:
2686bf215546Sopenharmony_ci   case DRM_FORMAT_Y212:
2687bf215546Sopenharmony_ci   case DRM_FORMAT_Y216:
2688bf215546Sopenharmony_ci   case DRM_FORMAT_Y410:
2689bf215546Sopenharmony_ci   case DRM_FORMAT_Y412:
2690bf215546Sopenharmony_ci   case DRM_FORMAT_Y416:
2691bf215546Sopenharmony_ci      return 1;
2692bf215546Sopenharmony_ci
2693bf215546Sopenharmony_ci   case DRM_FORMAT_NV12:
2694bf215546Sopenharmony_ci   case DRM_FORMAT_NV21:
2695bf215546Sopenharmony_ci   case DRM_FORMAT_NV16:
2696bf215546Sopenharmony_ci   case DRM_FORMAT_NV61:
2697bf215546Sopenharmony_ci   case DRM_FORMAT_P010:
2698bf215546Sopenharmony_ci   case DRM_FORMAT_P012:
2699bf215546Sopenharmony_ci   case DRM_FORMAT_P016:
2700bf215546Sopenharmony_ci      return 2;
2701bf215546Sopenharmony_ci
2702bf215546Sopenharmony_ci   case DRM_FORMAT_YUV410:
2703bf215546Sopenharmony_ci   case DRM_FORMAT_YVU410:
2704bf215546Sopenharmony_ci   case DRM_FORMAT_YUV411:
2705bf215546Sopenharmony_ci   case DRM_FORMAT_YVU411:
2706bf215546Sopenharmony_ci   case DRM_FORMAT_YUV420:
2707bf215546Sopenharmony_ci   case DRM_FORMAT_YVU420:
2708bf215546Sopenharmony_ci   case DRM_FORMAT_YUV422:
2709bf215546Sopenharmony_ci   case DRM_FORMAT_YVU422:
2710bf215546Sopenharmony_ci   case DRM_FORMAT_YUV444:
2711bf215546Sopenharmony_ci   case DRM_FORMAT_YVU444:
2712bf215546Sopenharmony_ci      return 3;
2713bf215546Sopenharmony_ci
2714bf215546Sopenharmony_ci   default:
2715bf215546Sopenharmony_ci      return 0;
2716bf215546Sopenharmony_ci   }
2717bf215546Sopenharmony_ci}
2718bf215546Sopenharmony_ci
2719bf215546Sopenharmony_ci/* Returns the total number of file descriptors. Zero indicates an error. */
2720bf215546Sopenharmony_cistatic unsigned
2721bf215546Sopenharmony_cidri2_check_dma_buf_format(const _EGLImageAttribs *attrs)
2722bf215546Sopenharmony_ci{
2723bf215546Sopenharmony_ci   unsigned plane_n = dri2_num_fourcc_format_planes(attrs->DMABufFourCC.Value);
2724bf215546Sopenharmony_ci   if (plane_n == 0) {
2725bf215546Sopenharmony_ci      _eglError(EGL_BAD_MATCH, "unknown drm fourcc format");
2726bf215546Sopenharmony_ci      return 0;
2727bf215546Sopenharmony_ci   }
2728bf215546Sopenharmony_ci
2729bf215546Sopenharmony_ci   for (unsigned i = plane_n; i < DMA_BUF_MAX_PLANES; i++) {
2730bf215546Sopenharmony_ci      /**
2731bf215546Sopenharmony_ci       * The modifiers extension spec says:
2732bf215546Sopenharmony_ci       *
2733bf215546Sopenharmony_ci       * "Modifiers may modify any attribute of a buffer import, including
2734bf215546Sopenharmony_ci       *  but not limited to adding extra planes to a format which
2735bf215546Sopenharmony_ci       *  otherwise does not have those planes. As an example, a modifier
2736bf215546Sopenharmony_ci       *  may add a plane for an external compression buffer to a
2737bf215546Sopenharmony_ci       *  single-plane format. The exact meaning and effect of any
2738bf215546Sopenharmony_ci       *  modifier is canonically defined by drm_fourcc.h, not as part of
2739bf215546Sopenharmony_ci       *  this extension."
2740bf215546Sopenharmony_ci       */
2741bf215546Sopenharmony_ci      if (attrs->DMABufPlaneModifiersLo[i].IsPresent &&
2742bf215546Sopenharmony_ci          attrs->DMABufPlaneModifiersHi[i].IsPresent) {
2743bf215546Sopenharmony_ci         plane_n = i + 1;
2744bf215546Sopenharmony_ci      }
2745bf215546Sopenharmony_ci   }
2746bf215546Sopenharmony_ci
2747bf215546Sopenharmony_ci   /**
2748bf215546Sopenharmony_ci     * The spec says:
2749bf215546Sopenharmony_ci     *
2750bf215546Sopenharmony_ci     * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is
2751bf215546Sopenharmony_ci     *    incomplete, EGL_BAD_PARAMETER is generated."
2752bf215546Sopenharmony_ci     */
2753bf215546Sopenharmony_ci   for (unsigned i = 0; i < plane_n; ++i) {
2754bf215546Sopenharmony_ci      if (!attrs->DMABufPlaneFds[i].IsPresent ||
2755bf215546Sopenharmony_ci          !attrs->DMABufPlaneOffsets[i].IsPresent ||
2756bf215546Sopenharmony_ci          !attrs->DMABufPlanePitches[i].IsPresent) {
2757bf215546Sopenharmony_ci         _eglError(EGL_BAD_PARAMETER, "plane attribute(s) missing");
2758bf215546Sopenharmony_ci         return 0;
2759bf215546Sopenharmony_ci      }
2760bf215546Sopenharmony_ci   }
2761bf215546Sopenharmony_ci
2762bf215546Sopenharmony_ci   /**
2763bf215546Sopenharmony_ci    * The spec also says:
2764bf215546Sopenharmony_ci    *
2765bf215546Sopenharmony_ci    * "If <target> is EGL_LINUX_DMA_BUF_EXT, and the EGL_LINUX_DRM_FOURCC_EXT
2766bf215546Sopenharmony_ci    *  attribute indicates a single-plane format, EGL_BAD_ATTRIBUTE is
2767bf215546Sopenharmony_ci    *  generated if any of the EGL_DMA_BUF_PLANE1_* or EGL_DMA_BUF_PLANE2_*
2768bf215546Sopenharmony_ci    *  or EGL_DMA_BUF_PLANE3_* attributes are specified."
2769bf215546Sopenharmony_ci    */
2770bf215546Sopenharmony_ci   for (unsigned i = plane_n; i < DMA_BUF_MAX_PLANES; ++i) {
2771bf215546Sopenharmony_ci      if (attrs->DMABufPlaneFds[i].IsPresent ||
2772bf215546Sopenharmony_ci          attrs->DMABufPlaneOffsets[i].IsPresent ||
2773bf215546Sopenharmony_ci          attrs->DMABufPlanePitches[i].IsPresent) {
2774bf215546Sopenharmony_ci         _eglError(EGL_BAD_ATTRIBUTE, "too many plane attributes");
2775bf215546Sopenharmony_ci         return 0;
2776bf215546Sopenharmony_ci      }
2777bf215546Sopenharmony_ci   }
2778bf215546Sopenharmony_ci
2779bf215546Sopenharmony_ci   return plane_n;
2780bf215546Sopenharmony_ci}
2781bf215546Sopenharmony_ci
2782bf215546Sopenharmony_cistatic EGLBoolean
2783bf215546Sopenharmony_cidri2_query_dma_buf_formats(_EGLDisplay *disp, EGLint max,
2784bf215546Sopenharmony_ci                           EGLint *formats, EGLint *count)
2785bf215546Sopenharmony_ci{
2786bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2787bf215546Sopenharmony_ci   if (max < 0 || (max > 0 && formats == NULL))
2788bf215546Sopenharmony_ci      return _eglError(EGL_BAD_PARAMETER, "invalid value for max count of formats");
2789bf215546Sopenharmony_ci
2790bf215546Sopenharmony_ci   if (dri2_dpy->image->base.version < 15 ||
2791bf215546Sopenharmony_ci       dri2_dpy->image->queryDmaBufFormats == NULL)
2792bf215546Sopenharmony_ci      return EGL_FALSE;
2793bf215546Sopenharmony_ci
2794bf215546Sopenharmony_ci   if (!dri2_dpy->image->queryDmaBufFormats(dri2_dpy->dri_screen, max,
2795bf215546Sopenharmony_ci                                            formats, count))
2796bf215546Sopenharmony_ci      return EGL_FALSE;
2797bf215546Sopenharmony_ci
2798bf215546Sopenharmony_ci   if (max > 0) {
2799bf215546Sopenharmony_ci      /* Assert that all of the formats returned are actually fourcc formats.
2800bf215546Sopenharmony_ci       * Some day, if we want the internal interface function to be able to
2801bf215546Sopenharmony_ci       * return the fake fourcc formats defined in dri_interface.h, we'll have
2802bf215546Sopenharmony_ci       * to do something more clever here to pair the list down to just real
2803bf215546Sopenharmony_ci       * fourcc formats so that we don't leak the fake internal ones.
2804bf215546Sopenharmony_ci       */
2805bf215546Sopenharmony_ci      for (int i = 0; i < *count; i++) {
2806bf215546Sopenharmony_ci         assert(dri2_num_fourcc_format_planes(formats[i]) > 0);
2807bf215546Sopenharmony_ci      }
2808bf215546Sopenharmony_ci   }
2809bf215546Sopenharmony_ci
2810bf215546Sopenharmony_ci   return EGL_TRUE;
2811bf215546Sopenharmony_ci}
2812bf215546Sopenharmony_ci
2813bf215546Sopenharmony_cistatic EGLBoolean
2814bf215546Sopenharmony_cidri2_query_dma_buf_modifiers(_EGLDisplay *disp, EGLint format,
2815bf215546Sopenharmony_ci                             EGLint max, EGLuint64KHR *modifiers,
2816bf215546Sopenharmony_ci                             EGLBoolean *external_only, EGLint *count)
2817bf215546Sopenharmony_ci{
2818bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2819bf215546Sopenharmony_ci
2820bf215546Sopenharmony_ci   if (dri2_num_fourcc_format_planes(format) == 0)
2821bf215546Sopenharmony_ci      return _eglError(EGL_BAD_PARAMETER, "invalid fourcc format");
2822bf215546Sopenharmony_ci
2823bf215546Sopenharmony_ci   if (max < 0)
2824bf215546Sopenharmony_ci      return _eglError(EGL_BAD_PARAMETER, "invalid value for max count of formats");
2825bf215546Sopenharmony_ci
2826bf215546Sopenharmony_ci   if (max > 0 && modifiers == NULL)
2827bf215546Sopenharmony_ci      return _eglError(EGL_BAD_PARAMETER, "invalid modifiers array");
2828bf215546Sopenharmony_ci
2829bf215546Sopenharmony_ci   if (dri2_dpy->image->base.version < 15 ||
2830bf215546Sopenharmony_ci       dri2_dpy->image->queryDmaBufModifiers == NULL)
2831bf215546Sopenharmony_ci      return EGL_FALSE;
2832bf215546Sopenharmony_ci
2833bf215546Sopenharmony_ci   if (dri2_dpy->image->queryDmaBufModifiers(dri2_dpy->dri_screen, format,
2834bf215546Sopenharmony_ci                                             max, modifiers,
2835bf215546Sopenharmony_ci                                             (unsigned int *) external_only,
2836bf215546Sopenharmony_ci                                             count) == false)
2837bf215546Sopenharmony_ci      return _eglError(EGL_BAD_PARAMETER, "invalid format");
2838bf215546Sopenharmony_ci
2839bf215546Sopenharmony_ci   return EGL_TRUE;
2840bf215546Sopenharmony_ci}
2841bf215546Sopenharmony_ci
2842bf215546Sopenharmony_ci/**
2843bf215546Sopenharmony_ci * The spec says:
2844bf215546Sopenharmony_ci *
2845bf215546Sopenharmony_ci * "If eglCreateImageKHR is successful for a EGL_LINUX_DMA_BUF_EXT target, the
2846bf215546Sopenharmony_ci *  EGL will take a reference to the dma_buf(s) which it will release at any
2847bf215546Sopenharmony_ci *  time while the EGLDisplay is initialized. It is the responsibility of the
2848bf215546Sopenharmony_ci *  application to close the dma_buf file descriptors."
2849bf215546Sopenharmony_ci *
2850bf215546Sopenharmony_ci * Therefore we must never close or otherwise modify the file descriptors.
2851bf215546Sopenharmony_ci */
2852bf215546Sopenharmony_ci_EGLImage *
2853bf215546Sopenharmony_cidri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
2854bf215546Sopenharmony_ci                          EGLClientBuffer buffer, const EGLint *attr_list)
2855bf215546Sopenharmony_ci{
2856bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2857bf215546Sopenharmony_ci   _EGLImage *res;
2858bf215546Sopenharmony_ci   _EGLImageAttribs attrs;
2859bf215546Sopenharmony_ci   __DRIimage *dri_image;
2860bf215546Sopenharmony_ci   unsigned num_fds;
2861bf215546Sopenharmony_ci   int fds[DMA_BUF_MAX_PLANES];
2862bf215546Sopenharmony_ci   int pitches[DMA_BUF_MAX_PLANES];
2863bf215546Sopenharmony_ci   int offsets[DMA_BUF_MAX_PLANES];
2864bf215546Sopenharmony_ci   uint64_t modifier;
2865bf215546Sopenharmony_ci   bool has_modifier = false;
2866bf215546Sopenharmony_ci   unsigned error;
2867bf215546Sopenharmony_ci
2868bf215546Sopenharmony_ci   /**
2869bf215546Sopenharmony_ci    * The spec says:
2870bf215546Sopenharmony_ci    *
2871bf215546Sopenharmony_ci    * ""* If <target> is EGL_LINUX_DMA_BUF_EXT and <buffer> is not NULL, the
2872bf215546Sopenharmony_ci    *     error EGL_BAD_PARAMETER is generated."
2873bf215546Sopenharmony_ci    */
2874bf215546Sopenharmony_ci   if (buffer != NULL) {
2875bf215546Sopenharmony_ci      _eglError(EGL_BAD_PARAMETER, "buffer not NULL");
2876bf215546Sopenharmony_ci      return NULL;
2877bf215546Sopenharmony_ci   }
2878bf215546Sopenharmony_ci
2879bf215546Sopenharmony_ci   if (!_eglParseImageAttribList(&attrs, disp, attr_list))
2880bf215546Sopenharmony_ci      return NULL;
2881bf215546Sopenharmony_ci
2882bf215546Sopenharmony_ci   if (!dri2_check_dma_buf_attribs(&attrs))
2883bf215546Sopenharmony_ci      return NULL;
2884bf215546Sopenharmony_ci
2885bf215546Sopenharmony_ci   num_fds = dri2_check_dma_buf_format(&attrs);
2886bf215546Sopenharmony_ci   if (!num_fds)
2887bf215546Sopenharmony_ci      return NULL;
2888bf215546Sopenharmony_ci
2889bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_fds; ++i) {
2890bf215546Sopenharmony_ci      fds[i] = attrs.DMABufPlaneFds[i].Value;
2891bf215546Sopenharmony_ci      pitches[i] = attrs.DMABufPlanePitches[i].Value;
2892bf215546Sopenharmony_ci      offsets[i] = attrs.DMABufPlaneOffsets[i].Value;
2893bf215546Sopenharmony_ci   }
2894bf215546Sopenharmony_ci
2895bf215546Sopenharmony_ci   /* dri2_check_dma_buf_attribs ensures that the modifier, if available,
2896bf215546Sopenharmony_ci    * will be present in attrs.DMABufPlaneModifiersLo[0] and
2897bf215546Sopenharmony_ci    * attrs.DMABufPlaneModifiersHi[0] */
2898bf215546Sopenharmony_ci   if (attrs.DMABufPlaneModifiersLo[0].IsPresent) {
2899bf215546Sopenharmony_ci      modifier = combine_u32_into_u64(attrs.DMABufPlaneModifiersHi[0].Value,
2900bf215546Sopenharmony_ci                                      attrs.DMABufPlaneModifiersLo[0].Value);
2901bf215546Sopenharmony_ci      has_modifier = true;
2902bf215546Sopenharmony_ci   }
2903bf215546Sopenharmony_ci
2904bf215546Sopenharmony_ci   if (attrs.ProtectedContent) {
2905bf215546Sopenharmony_ci      if (dri2_dpy->image->base.version < 18 ||
2906bf215546Sopenharmony_ci          dri2_dpy->image->createImageFromDmaBufs3 == NULL) {
2907bf215546Sopenharmony_ci         _eglError(EGL_BAD_MATCH, "unsupported protected_content attribute");
2908bf215546Sopenharmony_ci         return EGL_NO_IMAGE_KHR;
2909bf215546Sopenharmony_ci      }
2910bf215546Sopenharmony_ci      if (!has_modifier)
2911bf215546Sopenharmony_ci         modifier = DRM_FORMAT_MOD_INVALID;
2912bf215546Sopenharmony_ci
2913bf215546Sopenharmony_ci      dri_image =
2914bf215546Sopenharmony_ci         dri2_dpy->image->createImageFromDmaBufs3(dri2_dpy->dri_screen,
2915bf215546Sopenharmony_ci            attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
2916bf215546Sopenharmony_ci            modifier, fds, num_fds, pitches, offsets,
2917bf215546Sopenharmony_ci            attrs.DMABufYuvColorSpaceHint.Value,
2918bf215546Sopenharmony_ci            attrs.DMABufSampleRangeHint.Value,
2919bf215546Sopenharmony_ci            attrs.DMABufChromaHorizontalSiting.Value,
2920bf215546Sopenharmony_ci            attrs.DMABufChromaVerticalSiting.Value,
2921bf215546Sopenharmony_ci            attrs.ProtectedContent ? __DRI_IMAGE_PROTECTED_CONTENT_FLAG : 0,
2922bf215546Sopenharmony_ci            &error,
2923bf215546Sopenharmony_ci            NULL);
2924bf215546Sopenharmony_ci   }
2925bf215546Sopenharmony_ci   else if (has_modifier) {
2926bf215546Sopenharmony_ci      if (dri2_dpy->image->base.version < 15 ||
2927bf215546Sopenharmony_ci          dri2_dpy->image->createImageFromDmaBufs2 == NULL) {
2928bf215546Sopenharmony_ci         _eglError(EGL_BAD_MATCH, "unsupported dma_buf format modifier");
2929bf215546Sopenharmony_ci         return EGL_NO_IMAGE_KHR;
2930bf215546Sopenharmony_ci      }
2931bf215546Sopenharmony_ci      dri_image =
2932bf215546Sopenharmony_ci         dri2_dpy->image->createImageFromDmaBufs2(dri2_dpy->dri_screen,
2933bf215546Sopenharmony_ci            attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
2934bf215546Sopenharmony_ci            modifier, fds, num_fds, pitches, offsets,
2935bf215546Sopenharmony_ci            attrs.DMABufYuvColorSpaceHint.Value,
2936bf215546Sopenharmony_ci            attrs.DMABufSampleRangeHint.Value,
2937bf215546Sopenharmony_ci            attrs.DMABufChromaHorizontalSiting.Value,
2938bf215546Sopenharmony_ci            attrs.DMABufChromaVerticalSiting.Value,
2939bf215546Sopenharmony_ci            &error,
2940bf215546Sopenharmony_ci            NULL);
2941bf215546Sopenharmony_ci   }
2942bf215546Sopenharmony_ci   else {
2943bf215546Sopenharmony_ci      dri_image =
2944bf215546Sopenharmony_ci         dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen,
2945bf215546Sopenharmony_ci            attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
2946bf215546Sopenharmony_ci            fds, num_fds, pitches, offsets,
2947bf215546Sopenharmony_ci            attrs.DMABufYuvColorSpaceHint.Value,
2948bf215546Sopenharmony_ci            attrs.DMABufSampleRangeHint.Value,
2949bf215546Sopenharmony_ci            attrs.DMABufChromaHorizontalSiting.Value,
2950bf215546Sopenharmony_ci            attrs.DMABufChromaVerticalSiting.Value,
2951bf215546Sopenharmony_ci            &error,
2952bf215546Sopenharmony_ci            NULL);
2953bf215546Sopenharmony_ci   }
2954bf215546Sopenharmony_ci   dri2_create_image_khr_texture_error(error);
2955bf215546Sopenharmony_ci
2956bf215546Sopenharmony_ci   if (!dri_image)
2957bf215546Sopenharmony_ci      return EGL_NO_IMAGE_KHR;
2958bf215546Sopenharmony_ci
2959bf215546Sopenharmony_ci   res = dri2_create_image_from_dri(disp, dri_image);
2960bf215546Sopenharmony_ci
2961bf215546Sopenharmony_ci   return res;
2962bf215546Sopenharmony_ci}
2963bf215546Sopenharmony_cistatic _EGLImage *
2964bf215546Sopenharmony_cidri2_create_drm_image_mesa(_EGLDisplay *disp, const EGLint *attr_list)
2965bf215546Sopenharmony_ci{
2966bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2967bf215546Sopenharmony_ci   struct dri2_egl_image *dri2_img;
2968bf215546Sopenharmony_ci   _EGLImageAttribs attrs;
2969bf215546Sopenharmony_ci   unsigned int dri_use, valid_mask;
2970bf215546Sopenharmony_ci   int format;
2971bf215546Sopenharmony_ci
2972bf215546Sopenharmony_ci   if (!attr_list) {
2973bf215546Sopenharmony_ci      _eglError(EGL_BAD_PARAMETER, __func__);
2974bf215546Sopenharmony_ci      return EGL_NO_IMAGE_KHR;
2975bf215546Sopenharmony_ci   }
2976bf215546Sopenharmony_ci
2977bf215546Sopenharmony_ci   if (!_eglParseImageAttribList(&attrs, disp, attr_list))
2978bf215546Sopenharmony_ci      return EGL_NO_IMAGE_KHR;
2979bf215546Sopenharmony_ci
2980bf215546Sopenharmony_ci   if (attrs.Width <= 0 || attrs.Height <= 0) {
2981bf215546Sopenharmony_ci      _eglError(EGL_BAD_PARAMETER, __func__);
2982bf215546Sopenharmony_ci      return EGL_NO_IMAGE_KHR;
2983bf215546Sopenharmony_ci   }
2984bf215546Sopenharmony_ci
2985bf215546Sopenharmony_ci   switch (attrs.DRMBufferFormatMESA) {
2986bf215546Sopenharmony_ci   case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
2987bf215546Sopenharmony_ci      format = __DRI_IMAGE_FORMAT_ARGB8888;
2988bf215546Sopenharmony_ci      break;
2989bf215546Sopenharmony_ci   default:
2990bf215546Sopenharmony_ci      _eglError(EGL_BAD_PARAMETER, __func__);
2991bf215546Sopenharmony_ci      return EGL_NO_IMAGE_KHR;
2992bf215546Sopenharmony_ci   }
2993bf215546Sopenharmony_ci
2994bf215546Sopenharmony_ci   valid_mask =
2995bf215546Sopenharmony_ci      EGL_DRM_BUFFER_USE_SCANOUT_MESA |
2996bf215546Sopenharmony_ci      EGL_DRM_BUFFER_USE_SHARE_MESA |
2997bf215546Sopenharmony_ci      EGL_DRM_BUFFER_USE_CURSOR_MESA;
2998bf215546Sopenharmony_ci   if (attrs.DRMBufferUseMESA & ~valid_mask) {
2999bf215546Sopenharmony_ci      _eglError(EGL_BAD_PARAMETER, __func__);
3000bf215546Sopenharmony_ci      return EGL_NO_IMAGE_KHR;
3001bf215546Sopenharmony_ci   }
3002bf215546Sopenharmony_ci
3003bf215546Sopenharmony_ci   dri_use = 0;
3004bf215546Sopenharmony_ci   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA)
3005bf215546Sopenharmony_ci      dri_use |= __DRI_IMAGE_USE_SHARE;
3006bf215546Sopenharmony_ci   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
3007bf215546Sopenharmony_ci      dri_use |= __DRI_IMAGE_USE_SCANOUT;
3008bf215546Sopenharmony_ci   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA)
3009bf215546Sopenharmony_ci      dri_use |= __DRI_IMAGE_USE_CURSOR;
3010bf215546Sopenharmony_ci
3011bf215546Sopenharmony_ci   dri2_img = malloc(sizeof *dri2_img);
3012bf215546Sopenharmony_ci   if (!dri2_img) {
3013bf215546Sopenharmony_ci      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
3014bf215546Sopenharmony_ci      return EGL_NO_IMAGE_KHR;
3015bf215546Sopenharmony_ci   }
3016bf215546Sopenharmony_ci
3017bf215546Sopenharmony_ci   _eglInitImage(&dri2_img->base, disp);
3018bf215546Sopenharmony_ci
3019bf215546Sopenharmony_ci   dri2_img->dri_image =
3020bf215546Sopenharmony_ci      dri2_dpy->image->createImage(dri2_dpy->dri_screen,
3021bf215546Sopenharmony_ci                                   attrs.Width, attrs.Height,
3022bf215546Sopenharmony_ci                                   format, dri_use, dri2_img);
3023bf215546Sopenharmony_ci   if (dri2_img->dri_image == NULL) {
3024bf215546Sopenharmony_ci      free(dri2_img);
3025bf215546Sopenharmony_ci       _eglError(EGL_BAD_ALLOC, "dri2_create_drm_image_mesa");
3026bf215546Sopenharmony_ci      return EGL_NO_IMAGE_KHR;
3027bf215546Sopenharmony_ci   }
3028bf215546Sopenharmony_ci
3029bf215546Sopenharmony_ci   return &dri2_img->base;
3030bf215546Sopenharmony_ci}
3031bf215546Sopenharmony_ci
3032bf215546Sopenharmony_cistatic EGLBoolean
3033bf215546Sopenharmony_cidri2_export_drm_image_mesa(_EGLDisplay *disp, _EGLImage *img,
3034bf215546Sopenharmony_ci                          EGLint *name, EGLint *handle, EGLint *stride)
3035bf215546Sopenharmony_ci{
3036bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3037bf215546Sopenharmony_ci   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
3038bf215546Sopenharmony_ci
3039bf215546Sopenharmony_ci   if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image,
3040bf215546Sopenharmony_ci                                            __DRI_IMAGE_ATTRIB_NAME, name))
3041bf215546Sopenharmony_ci      return _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa");
3042bf215546Sopenharmony_ci
3043bf215546Sopenharmony_ci   if (handle)
3044bf215546Sopenharmony_ci      dri2_dpy->image->queryImage(dri2_img->dri_image,
3045bf215546Sopenharmony_ci                                  __DRI_IMAGE_ATTRIB_HANDLE, handle);
3046bf215546Sopenharmony_ci
3047bf215546Sopenharmony_ci   if (stride)
3048bf215546Sopenharmony_ci      dri2_dpy->image->queryImage(dri2_img->dri_image,
3049bf215546Sopenharmony_ci                                  __DRI_IMAGE_ATTRIB_STRIDE, stride);
3050bf215546Sopenharmony_ci
3051bf215546Sopenharmony_ci   return EGL_TRUE;
3052bf215546Sopenharmony_ci}
3053bf215546Sopenharmony_ci
3054bf215546Sopenharmony_ci/**
3055bf215546Sopenharmony_ci * Checks if we can support EGL_MESA_image_dma_buf_export on this image.
3056bf215546Sopenharmony_ci
3057bf215546Sopenharmony_ci * The spec provides a boolean return for the driver to reject exporting for
3058bf215546Sopenharmony_ci * basically any reason, but doesn't specify any particular error cases.  For
3059bf215546Sopenharmony_ci * now, we just fail if we don't have a DRM fourcc for the format.
3060bf215546Sopenharmony_ci */
3061bf215546Sopenharmony_cistatic bool
3062bf215546Sopenharmony_cidri2_can_export_dma_buf_image(_EGLDisplay *disp, _EGLImage *img)
3063bf215546Sopenharmony_ci{
3064bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3065bf215546Sopenharmony_ci   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
3066bf215546Sopenharmony_ci   EGLint fourcc;
3067bf215546Sopenharmony_ci
3068bf215546Sopenharmony_ci   if (!dri2_dpy->image->queryImage(dri2_img->dri_image,
3069bf215546Sopenharmony_ci                                    __DRI_IMAGE_ATTRIB_FOURCC, &fourcc)) {
3070bf215546Sopenharmony_ci      return false;
3071bf215546Sopenharmony_ci   }
3072bf215546Sopenharmony_ci
3073bf215546Sopenharmony_ci   return true;
3074bf215546Sopenharmony_ci}
3075bf215546Sopenharmony_ci
3076bf215546Sopenharmony_cistatic EGLBoolean
3077bf215546Sopenharmony_cidri2_export_dma_buf_image_query_mesa(_EGLDisplay *disp, _EGLImage *img,
3078bf215546Sopenharmony_ci                                     EGLint *fourcc, EGLint *nplanes,
3079bf215546Sopenharmony_ci                                     EGLuint64KHR *modifiers)
3080bf215546Sopenharmony_ci{
3081bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3082bf215546Sopenharmony_ci   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
3083bf215546Sopenharmony_ci   int num_planes;
3084bf215546Sopenharmony_ci
3085bf215546Sopenharmony_ci   if (!dri2_can_export_dma_buf_image(disp, img))
3086bf215546Sopenharmony_ci      return EGL_FALSE;
3087bf215546Sopenharmony_ci
3088bf215546Sopenharmony_ci   dri2_dpy->image->queryImage(dri2_img->dri_image,
3089bf215546Sopenharmony_ci                               __DRI_IMAGE_ATTRIB_NUM_PLANES, &num_planes);
3090bf215546Sopenharmony_ci   if (nplanes)
3091bf215546Sopenharmony_ci     *nplanes = num_planes;
3092bf215546Sopenharmony_ci
3093bf215546Sopenharmony_ci   if (fourcc)
3094bf215546Sopenharmony_ci      dri2_dpy->image->queryImage(dri2_img->dri_image,
3095bf215546Sopenharmony_ci                                  __DRI_IMAGE_ATTRIB_FOURCC, fourcc);
3096bf215546Sopenharmony_ci
3097bf215546Sopenharmony_ci   if (modifiers) {
3098bf215546Sopenharmony_ci      int mod_hi, mod_lo;
3099bf215546Sopenharmony_ci      uint64_t modifier = DRM_FORMAT_MOD_INVALID;
3100bf215546Sopenharmony_ci      bool query;
3101bf215546Sopenharmony_ci
3102bf215546Sopenharmony_ci      query = dri2_dpy->image->queryImage(dri2_img->dri_image,
3103bf215546Sopenharmony_ci                                          __DRI_IMAGE_ATTRIB_MODIFIER_UPPER,
3104bf215546Sopenharmony_ci                                          &mod_hi);
3105bf215546Sopenharmony_ci      query &= dri2_dpy->image->queryImage(dri2_img->dri_image,
3106bf215546Sopenharmony_ci                                           __DRI_IMAGE_ATTRIB_MODIFIER_LOWER,
3107bf215546Sopenharmony_ci                                           &mod_lo);
3108bf215546Sopenharmony_ci      if (query)
3109bf215546Sopenharmony_ci         modifier = combine_u32_into_u64 (mod_hi, mod_lo);
3110bf215546Sopenharmony_ci
3111bf215546Sopenharmony_ci      for (int i = 0; i < num_planes; i++)
3112bf215546Sopenharmony_ci        modifiers[i] = modifier;
3113bf215546Sopenharmony_ci   }
3114bf215546Sopenharmony_ci
3115bf215546Sopenharmony_ci   return EGL_TRUE;
3116bf215546Sopenharmony_ci}
3117bf215546Sopenharmony_ci
3118bf215546Sopenharmony_cistatic EGLBoolean
3119bf215546Sopenharmony_cidri2_export_dma_buf_image_mesa(_EGLDisplay *disp, _EGLImage *img,
3120bf215546Sopenharmony_ci                               int *fds, EGLint *strides, EGLint *offsets)
3121bf215546Sopenharmony_ci{
3122bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3123bf215546Sopenharmony_ci   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
3124bf215546Sopenharmony_ci   EGLint nplanes;
3125bf215546Sopenharmony_ci
3126bf215546Sopenharmony_ci   if (!dri2_can_export_dma_buf_image(disp, img))
3127bf215546Sopenharmony_ci      return EGL_FALSE;
3128bf215546Sopenharmony_ci
3129bf215546Sopenharmony_ci   /* EGL_MESA_image_dma_buf_export spec says:
3130bf215546Sopenharmony_ci    *    "If the number of fds is less than the number of planes, then
3131bf215546Sopenharmony_ci    *    subsequent fd slots should contain -1."
3132bf215546Sopenharmony_ci    */
3133bf215546Sopenharmony_ci   if (fds) {
3134bf215546Sopenharmony_ci      /* Query nplanes so that we know how big the given array is. */
3135bf215546Sopenharmony_ci      dri2_dpy->image->queryImage(dri2_img->dri_image,
3136bf215546Sopenharmony_ci                                  __DRI_IMAGE_ATTRIB_NUM_PLANES, &nplanes);
3137bf215546Sopenharmony_ci      memset(fds, -1, nplanes * sizeof(int));
3138bf215546Sopenharmony_ci   }
3139bf215546Sopenharmony_ci
3140bf215546Sopenharmony_ci   /* rework later to provide multiple fds/strides/offsets */
3141bf215546Sopenharmony_ci   if (fds)
3142bf215546Sopenharmony_ci      dri2_dpy->image->queryImage(dri2_img->dri_image,
3143bf215546Sopenharmony_ci                                  __DRI_IMAGE_ATTRIB_FD, fds);
3144bf215546Sopenharmony_ci
3145bf215546Sopenharmony_ci   if (strides)
3146bf215546Sopenharmony_ci      dri2_dpy->image->queryImage(dri2_img->dri_image,
3147bf215546Sopenharmony_ci                                  __DRI_IMAGE_ATTRIB_STRIDE, strides);
3148bf215546Sopenharmony_ci
3149bf215546Sopenharmony_ci   if (offsets) {
3150bf215546Sopenharmony_ci      int img_offset;
3151bf215546Sopenharmony_ci      bool ret = dri2_dpy->image->queryImage(dri2_img->dri_image,
3152bf215546Sopenharmony_ci                     __DRI_IMAGE_ATTRIB_OFFSET, &img_offset);
3153bf215546Sopenharmony_ci      if (ret)
3154bf215546Sopenharmony_ci         offsets[0] = img_offset;
3155bf215546Sopenharmony_ci      else
3156bf215546Sopenharmony_ci         offsets[0] = 0;
3157bf215546Sopenharmony_ci   }
3158bf215546Sopenharmony_ci
3159bf215546Sopenharmony_ci   return EGL_TRUE;
3160bf215546Sopenharmony_ci}
3161bf215546Sopenharmony_ci
3162bf215546Sopenharmony_ci#endif
3163bf215546Sopenharmony_ci
3164bf215546Sopenharmony_ci_EGLImage *
3165bf215546Sopenharmony_cidri2_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
3166bf215546Sopenharmony_ci                      EGLClientBuffer buffer, const EGLint *attr_list)
3167bf215546Sopenharmony_ci{
3168bf215546Sopenharmony_ci   switch (target) {
3169bf215546Sopenharmony_ci   case EGL_GL_TEXTURE_2D_KHR:
3170bf215546Sopenharmony_ci   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
3171bf215546Sopenharmony_ci   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
3172bf215546Sopenharmony_ci   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
3173bf215546Sopenharmony_ci   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
3174bf215546Sopenharmony_ci   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
3175bf215546Sopenharmony_ci   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
3176bf215546Sopenharmony_ci   case EGL_GL_TEXTURE_3D_KHR:
3177bf215546Sopenharmony_ci      return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
3178bf215546Sopenharmony_ci   case EGL_GL_RENDERBUFFER_KHR:
3179bf215546Sopenharmony_ci      return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
3180bf215546Sopenharmony_ci#ifdef HAVE_LIBDRM
3181bf215546Sopenharmony_ci   case EGL_DRM_BUFFER_MESA:
3182bf215546Sopenharmony_ci      return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
3183bf215546Sopenharmony_ci   case EGL_LINUX_DMA_BUF_EXT:
3184bf215546Sopenharmony_ci      return dri2_create_image_dma_buf(disp, ctx, buffer, attr_list);
3185bf215546Sopenharmony_ci#endif
3186bf215546Sopenharmony_ci#ifdef HAVE_WAYLAND_PLATFORM
3187bf215546Sopenharmony_ci   case EGL_WAYLAND_BUFFER_WL:
3188bf215546Sopenharmony_ci      return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
3189bf215546Sopenharmony_ci#endif
3190bf215546Sopenharmony_ci   default:
3191bf215546Sopenharmony_ci      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
3192bf215546Sopenharmony_ci      return EGL_NO_IMAGE_KHR;
3193bf215546Sopenharmony_ci   }
3194bf215546Sopenharmony_ci}
3195bf215546Sopenharmony_ci
3196bf215546Sopenharmony_cistatic EGLBoolean
3197bf215546Sopenharmony_cidri2_destroy_image_khr(_EGLDisplay *disp, _EGLImage *image)
3198bf215546Sopenharmony_ci{
3199bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3200bf215546Sopenharmony_ci   struct dri2_egl_image *dri2_img = dri2_egl_image(image);
3201bf215546Sopenharmony_ci
3202bf215546Sopenharmony_ci   dri2_dpy->image->destroyImage(dri2_img->dri_image);
3203bf215546Sopenharmony_ci   free(dri2_img);
3204bf215546Sopenharmony_ci
3205bf215546Sopenharmony_ci   return EGL_TRUE;
3206bf215546Sopenharmony_ci}
3207bf215546Sopenharmony_ci
3208bf215546Sopenharmony_ci#ifdef HAVE_WAYLAND_PLATFORM
3209bf215546Sopenharmony_ci
3210bf215546Sopenharmony_cistatic void
3211bf215546Sopenharmony_cidri2_wl_reference_buffer(void *user_data, uint32_t name, int fd,
3212bf215546Sopenharmony_ci                         struct wl_drm_buffer *buffer)
3213bf215546Sopenharmony_ci{
3214bf215546Sopenharmony_ci   _EGLDisplay *disp = user_data;
3215bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3216bf215546Sopenharmony_ci   __DRIimage *img;
3217bf215546Sopenharmony_ci   int dri_components = 0;
3218bf215546Sopenharmony_ci
3219bf215546Sopenharmony_ci   if (fd == -1)
3220bf215546Sopenharmony_ci      img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen,
3221bf215546Sopenharmony_ci                                                  buffer->width,
3222bf215546Sopenharmony_ci                                                  buffer->height,
3223bf215546Sopenharmony_ci                                                  buffer->format,
3224bf215546Sopenharmony_ci                                                  (int*)&name, 1,
3225bf215546Sopenharmony_ci                                                  buffer->stride,
3226bf215546Sopenharmony_ci                                                  buffer->offset,
3227bf215546Sopenharmony_ci                                                  NULL);
3228bf215546Sopenharmony_ci   else
3229bf215546Sopenharmony_ci      img = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
3230bf215546Sopenharmony_ci                                                buffer->width,
3231bf215546Sopenharmony_ci                                                buffer->height,
3232bf215546Sopenharmony_ci                                                buffer->format,
3233bf215546Sopenharmony_ci                                                &fd, 1,
3234bf215546Sopenharmony_ci                                                buffer->stride,
3235bf215546Sopenharmony_ci                                                buffer->offset,
3236bf215546Sopenharmony_ci                                                NULL);
3237bf215546Sopenharmony_ci
3238bf215546Sopenharmony_ci   if (img == NULL)
3239bf215546Sopenharmony_ci      return;
3240bf215546Sopenharmony_ci
3241bf215546Sopenharmony_ci   dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components);
3242bf215546Sopenharmony_ci
3243bf215546Sopenharmony_ci   buffer->driver_format = NULL;
3244bf215546Sopenharmony_ci   for (int i = 0; i < ARRAY_SIZE(wl_drm_components); i++)
3245bf215546Sopenharmony_ci      if (wl_drm_components[i].dri_components == dri_components)
3246bf215546Sopenharmony_ci         buffer->driver_format = &wl_drm_components[i];
3247bf215546Sopenharmony_ci
3248bf215546Sopenharmony_ci   if (buffer->driver_format == NULL)
3249bf215546Sopenharmony_ci      dri2_dpy->image->destroyImage(img);
3250bf215546Sopenharmony_ci   else
3251bf215546Sopenharmony_ci      buffer->driver_buffer = img;
3252bf215546Sopenharmony_ci}
3253bf215546Sopenharmony_ci
3254bf215546Sopenharmony_cistatic void
3255bf215546Sopenharmony_cidri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer)
3256bf215546Sopenharmony_ci{
3257bf215546Sopenharmony_ci   _EGLDisplay *disp = user_data;
3258bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3259bf215546Sopenharmony_ci
3260bf215546Sopenharmony_ci   dri2_dpy->image->destroyImage(buffer->driver_buffer);
3261bf215546Sopenharmony_ci}
3262bf215546Sopenharmony_ci
3263bf215546Sopenharmony_cistatic EGLBoolean
3264bf215546Sopenharmony_cidri2_bind_wayland_display_wl(_EGLDisplay *disp, struct wl_display *wl_dpy)
3265bf215546Sopenharmony_ci{
3266bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3267bf215546Sopenharmony_ci   const struct wayland_drm_callbacks wl_drm_callbacks = {
3268bf215546Sopenharmony_ci      .authenticate = (int(*)(void *, uint32_t)) dri2_dpy->vtbl->authenticate,
3269bf215546Sopenharmony_ci      .reference_buffer = dri2_wl_reference_buffer,
3270bf215546Sopenharmony_ci      .release_buffer = dri2_wl_release_buffer,
3271bf215546Sopenharmony_ci      .is_format_supported = dri2_wl_is_format_supported
3272bf215546Sopenharmony_ci   };
3273bf215546Sopenharmony_ci   int flags = 0;
3274bf215546Sopenharmony_ci   char *device_name;
3275bf215546Sopenharmony_ci   uint64_t cap;
3276bf215546Sopenharmony_ci
3277bf215546Sopenharmony_ci   if (dri2_dpy->wl_server_drm)
3278bf215546Sopenharmony_ci           return EGL_FALSE;
3279bf215546Sopenharmony_ci
3280bf215546Sopenharmony_ci   device_name = drmGetRenderDeviceNameFromFd(dri2_dpy->fd);
3281bf215546Sopenharmony_ci   if (!device_name)
3282bf215546Sopenharmony_ci      device_name = strdup(dri2_dpy->device_name);
3283bf215546Sopenharmony_ci   if (!device_name)
3284bf215546Sopenharmony_ci      return EGL_FALSE;
3285bf215546Sopenharmony_ci
3286bf215546Sopenharmony_ci   if (drmGetCap(dri2_dpy->fd, DRM_CAP_PRIME, &cap) == 0 &&
3287bf215546Sopenharmony_ci       cap == (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT) &&
3288bf215546Sopenharmony_ci       dri2_dpy->image->base.version >= 7 &&
3289bf215546Sopenharmony_ci       dri2_dpy->image->createImageFromFds != NULL)
3290bf215546Sopenharmony_ci      flags |= WAYLAND_DRM_PRIME;
3291bf215546Sopenharmony_ci
3292bf215546Sopenharmony_ci   dri2_dpy->wl_server_drm =
3293bf215546Sopenharmony_ci           wayland_drm_init(wl_dpy, device_name,
3294bf215546Sopenharmony_ci                            &wl_drm_callbacks, disp, flags);
3295bf215546Sopenharmony_ci
3296bf215546Sopenharmony_ci   free(device_name);
3297bf215546Sopenharmony_ci
3298bf215546Sopenharmony_ci   if (!dri2_dpy->wl_server_drm)
3299bf215546Sopenharmony_ci           return EGL_FALSE;
3300bf215546Sopenharmony_ci
3301bf215546Sopenharmony_ci#ifdef HAVE_DRM_PLATFORM
3302bf215546Sopenharmony_ci   /* We have to share the wl_drm instance with gbm, so gbm can convert
3303bf215546Sopenharmony_ci    * wl_buffers to gbm bos. */
3304bf215546Sopenharmony_ci   if (dri2_dpy->gbm_dri)
3305bf215546Sopenharmony_ci      dri2_dpy->gbm_dri->wl_drm = dri2_dpy->wl_server_drm;
3306bf215546Sopenharmony_ci#endif
3307bf215546Sopenharmony_ci
3308bf215546Sopenharmony_ci   return EGL_TRUE;
3309bf215546Sopenharmony_ci}
3310bf215546Sopenharmony_ci
3311bf215546Sopenharmony_cistatic EGLBoolean
3312bf215546Sopenharmony_cidri2_unbind_wayland_display_wl(_EGLDisplay *disp, struct wl_display *wl_dpy)
3313bf215546Sopenharmony_ci{
3314bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3315bf215546Sopenharmony_ci
3316bf215546Sopenharmony_ci   if (!dri2_dpy->wl_server_drm)
3317bf215546Sopenharmony_ci           return EGL_FALSE;
3318bf215546Sopenharmony_ci
3319bf215546Sopenharmony_ci   wayland_drm_uninit(dri2_dpy->wl_server_drm);
3320bf215546Sopenharmony_ci   dri2_dpy->wl_server_drm = NULL;
3321bf215546Sopenharmony_ci
3322bf215546Sopenharmony_ci   return EGL_TRUE;
3323bf215546Sopenharmony_ci}
3324bf215546Sopenharmony_ci
3325bf215546Sopenharmony_cistatic EGLBoolean
3326bf215546Sopenharmony_cidri2_query_wayland_buffer_wl(_EGLDisplay *disp, struct wl_resource *buffer_resource,
3327bf215546Sopenharmony_ci                             EGLint attribute, EGLint *value)
3328bf215546Sopenharmony_ci{
3329bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3330bf215546Sopenharmony_ci   struct wl_drm_buffer *buffer;
3331bf215546Sopenharmony_ci   const struct wl_drm_components_descriptor *format;
3332bf215546Sopenharmony_ci
3333bf215546Sopenharmony_ci   buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm, buffer_resource);
3334bf215546Sopenharmony_ci   if (!buffer)
3335bf215546Sopenharmony_ci      return EGL_FALSE;
3336bf215546Sopenharmony_ci
3337bf215546Sopenharmony_ci   format = buffer->driver_format;
3338bf215546Sopenharmony_ci   switch (attribute) {
3339bf215546Sopenharmony_ci   case EGL_TEXTURE_FORMAT:
3340bf215546Sopenharmony_ci      *value = format->components;
3341bf215546Sopenharmony_ci      return EGL_TRUE;
3342bf215546Sopenharmony_ci   case EGL_WIDTH:
3343bf215546Sopenharmony_ci      *value = buffer->width;
3344bf215546Sopenharmony_ci      return EGL_TRUE;
3345bf215546Sopenharmony_ci   case EGL_HEIGHT:
3346bf215546Sopenharmony_ci      *value = buffer->height;
3347bf215546Sopenharmony_ci      return EGL_TRUE;
3348bf215546Sopenharmony_ci   }
3349bf215546Sopenharmony_ci
3350bf215546Sopenharmony_ci   return EGL_FALSE;
3351bf215546Sopenharmony_ci}
3352bf215546Sopenharmony_ci#endif
3353bf215546Sopenharmony_ci
3354bf215546Sopenharmony_cistatic void
3355bf215546Sopenharmony_cidri2_egl_ref_sync(struct dri2_egl_sync *sync)
3356bf215546Sopenharmony_ci{
3357bf215546Sopenharmony_ci   p_atomic_inc(&sync->refcount);
3358bf215546Sopenharmony_ci}
3359bf215546Sopenharmony_ci
3360bf215546Sopenharmony_cistatic void
3361bf215546Sopenharmony_cidri2_egl_unref_sync(struct dri2_egl_display *dri2_dpy,
3362bf215546Sopenharmony_ci                    struct dri2_egl_sync *dri2_sync)
3363bf215546Sopenharmony_ci{
3364bf215546Sopenharmony_ci   if (p_atomic_dec_zero(&dri2_sync->refcount)) {
3365bf215546Sopenharmony_ci      switch (dri2_sync->base.Type) {
3366bf215546Sopenharmony_ci      case EGL_SYNC_REUSABLE_KHR:
3367bf215546Sopenharmony_ci         cnd_destroy(&dri2_sync->cond);
3368bf215546Sopenharmony_ci         break;
3369bf215546Sopenharmony_ci      case EGL_SYNC_NATIVE_FENCE_ANDROID:
3370bf215546Sopenharmony_ci         if (dri2_sync->base.SyncFd != EGL_NO_NATIVE_FENCE_FD_ANDROID)
3371bf215546Sopenharmony_ci            close(dri2_sync->base.SyncFd);
3372bf215546Sopenharmony_ci         break;
3373bf215546Sopenharmony_ci      default:
3374bf215546Sopenharmony_ci         break;
3375bf215546Sopenharmony_ci      }
3376bf215546Sopenharmony_ci
3377bf215546Sopenharmony_ci      if (dri2_sync->fence)
3378bf215546Sopenharmony_ci         dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, dri2_sync->fence);
3379bf215546Sopenharmony_ci
3380bf215546Sopenharmony_ci      free(dri2_sync);
3381bf215546Sopenharmony_ci   }
3382bf215546Sopenharmony_ci}
3383bf215546Sopenharmony_ci
3384bf215546Sopenharmony_cistatic _EGLSync *
3385bf215546Sopenharmony_cidri2_create_sync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list)
3386bf215546Sopenharmony_ci{
3387bf215546Sopenharmony_ci   _EGLContext *ctx = _eglGetCurrentContext();
3388bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3389bf215546Sopenharmony_ci   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3390bf215546Sopenharmony_ci   struct dri2_egl_sync *dri2_sync;
3391bf215546Sopenharmony_ci   EGLint ret;
3392bf215546Sopenharmony_ci   pthread_condattr_t attr;
3393bf215546Sopenharmony_ci
3394bf215546Sopenharmony_ci   dri2_sync = calloc(1, sizeof(struct dri2_egl_sync));
3395bf215546Sopenharmony_ci   if (!dri2_sync) {
3396bf215546Sopenharmony_ci      _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
3397bf215546Sopenharmony_ci      return NULL;
3398bf215546Sopenharmony_ci   }
3399bf215546Sopenharmony_ci
3400bf215546Sopenharmony_ci   if (!_eglInitSync(&dri2_sync->base, disp, type, attrib_list)) {
3401bf215546Sopenharmony_ci      free(dri2_sync);
3402bf215546Sopenharmony_ci      return NULL;
3403bf215546Sopenharmony_ci   }
3404bf215546Sopenharmony_ci
3405bf215546Sopenharmony_ci   switch (type) {
3406bf215546Sopenharmony_ci   case EGL_SYNC_FENCE_KHR:
3407bf215546Sopenharmony_ci      dri2_sync->fence = dri2_dpy->fence->create_fence(dri2_ctx->dri_context);
3408bf215546Sopenharmony_ci      if (!dri2_sync->fence) {
3409bf215546Sopenharmony_ci         /* Why did it fail? DRI doesn't return an error code, so we emit
3410bf215546Sopenharmony_ci          * a generic EGL error that doesn't communicate user error.
3411bf215546Sopenharmony_ci          */
3412bf215546Sopenharmony_ci         _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
3413bf215546Sopenharmony_ci         free(dri2_sync);
3414bf215546Sopenharmony_ci         return NULL;
3415bf215546Sopenharmony_ci      }
3416bf215546Sopenharmony_ci      break;
3417bf215546Sopenharmony_ci
3418bf215546Sopenharmony_ci   case EGL_SYNC_CL_EVENT_KHR:
3419bf215546Sopenharmony_ci      dri2_sync->fence = dri2_dpy->fence->get_fence_from_cl_event(
3420bf215546Sopenharmony_ci                                 dri2_dpy->dri_screen,
3421bf215546Sopenharmony_ci                                 dri2_sync->base.CLEvent);
3422bf215546Sopenharmony_ci      /* this can only happen if the cl_event passed in is invalid. */
3423bf215546Sopenharmony_ci      if (!dri2_sync->fence) {
3424bf215546Sopenharmony_ci         _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
3425bf215546Sopenharmony_ci         free(dri2_sync);
3426bf215546Sopenharmony_ci         return NULL;
3427bf215546Sopenharmony_ci      }
3428bf215546Sopenharmony_ci
3429bf215546Sopenharmony_ci      /* the initial status must be "signaled" if the cl_event is signaled */
3430bf215546Sopenharmony_ci      if (dri2_dpy->fence->client_wait_sync(dri2_ctx->dri_context,
3431bf215546Sopenharmony_ci                                            dri2_sync->fence, 0, 0))
3432bf215546Sopenharmony_ci         dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
3433bf215546Sopenharmony_ci      break;
3434bf215546Sopenharmony_ci
3435bf215546Sopenharmony_ci   case EGL_SYNC_REUSABLE_KHR:
3436bf215546Sopenharmony_ci      /* intialize attr */
3437bf215546Sopenharmony_ci      ret = pthread_condattr_init(&attr);
3438bf215546Sopenharmony_ci
3439bf215546Sopenharmony_ci      if (ret) {
3440bf215546Sopenharmony_ci         _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR");
3441bf215546Sopenharmony_ci         free(dri2_sync);
3442bf215546Sopenharmony_ci         return NULL;
3443bf215546Sopenharmony_ci      }
3444bf215546Sopenharmony_ci
3445bf215546Sopenharmony_ci      /* change clock attribute to CLOCK_MONOTONIC */
3446bf215546Sopenharmony_ci      ret = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
3447bf215546Sopenharmony_ci
3448bf215546Sopenharmony_ci      if (ret) {
3449bf215546Sopenharmony_ci         _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR");
3450bf215546Sopenharmony_ci         free(dri2_sync);
3451bf215546Sopenharmony_ci         return NULL;
3452bf215546Sopenharmony_ci      }
3453bf215546Sopenharmony_ci
3454bf215546Sopenharmony_ci      ret = pthread_cond_init(&dri2_sync->cond, &attr);
3455bf215546Sopenharmony_ci
3456bf215546Sopenharmony_ci      if (ret) {
3457bf215546Sopenharmony_ci         _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR");
3458bf215546Sopenharmony_ci         free(dri2_sync);
3459bf215546Sopenharmony_ci         return NULL;
3460bf215546Sopenharmony_ci      }
3461bf215546Sopenharmony_ci
3462bf215546Sopenharmony_ci      /* initial status of reusable sync must be "unsignaled" */
3463bf215546Sopenharmony_ci      dri2_sync->base.SyncStatus = EGL_UNSIGNALED_KHR;
3464bf215546Sopenharmony_ci      break;
3465bf215546Sopenharmony_ci
3466bf215546Sopenharmony_ci   case EGL_SYNC_NATIVE_FENCE_ANDROID:
3467bf215546Sopenharmony_ci      if (dri2_dpy->fence->create_fence_fd) {
3468bf215546Sopenharmony_ci         dri2_sync->fence = dri2_dpy->fence->create_fence_fd(
3469bf215546Sopenharmony_ci                                    dri2_ctx->dri_context,
3470bf215546Sopenharmony_ci                                    dri2_sync->base.SyncFd);
3471bf215546Sopenharmony_ci      }
3472bf215546Sopenharmony_ci      if (!dri2_sync->fence) {
3473bf215546Sopenharmony_ci         _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
3474bf215546Sopenharmony_ci         free(dri2_sync);
3475bf215546Sopenharmony_ci         return NULL;
3476bf215546Sopenharmony_ci      }
3477bf215546Sopenharmony_ci      break;
3478bf215546Sopenharmony_ci   }
3479bf215546Sopenharmony_ci
3480bf215546Sopenharmony_ci   p_atomic_set(&dri2_sync->refcount, 1);
3481bf215546Sopenharmony_ci   return &dri2_sync->base;
3482bf215546Sopenharmony_ci}
3483bf215546Sopenharmony_ci
3484bf215546Sopenharmony_cistatic EGLBoolean
3485bf215546Sopenharmony_cidri2_destroy_sync(_EGLDisplay *disp, _EGLSync *sync)
3486bf215546Sopenharmony_ci{
3487bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3488bf215546Sopenharmony_ci   struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3489bf215546Sopenharmony_ci   EGLint ret = EGL_TRUE;
3490bf215546Sopenharmony_ci   EGLint err;
3491bf215546Sopenharmony_ci
3492bf215546Sopenharmony_ci   /* if type of sync is EGL_SYNC_REUSABLE_KHR and it is not signaled yet,
3493bf215546Sopenharmony_ci    * then unlock all threads possibly blocked by the reusable sync before
3494bf215546Sopenharmony_ci    * destroying it.
3495bf215546Sopenharmony_ci    */
3496bf215546Sopenharmony_ci   if (dri2_sync->base.Type == EGL_SYNC_REUSABLE_KHR &&
3497bf215546Sopenharmony_ci       dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR) {
3498bf215546Sopenharmony_ci      dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
3499bf215546Sopenharmony_ci      /* unblock all threads currently blocked by sync */
3500bf215546Sopenharmony_ci      err = cnd_broadcast(&dri2_sync->cond);
3501bf215546Sopenharmony_ci
3502bf215546Sopenharmony_ci      if (err) {
3503bf215546Sopenharmony_ci         _eglError(EGL_BAD_ACCESS, "eglDestroySyncKHR");
3504bf215546Sopenharmony_ci         ret = EGL_FALSE;
3505bf215546Sopenharmony_ci      }
3506bf215546Sopenharmony_ci   }
3507bf215546Sopenharmony_ci
3508bf215546Sopenharmony_ci   dri2_egl_unref_sync(dri2_dpy, dri2_sync);
3509bf215546Sopenharmony_ci
3510bf215546Sopenharmony_ci   return ret;
3511bf215546Sopenharmony_ci}
3512bf215546Sopenharmony_ci
3513bf215546Sopenharmony_cistatic EGLint
3514bf215546Sopenharmony_cidri2_dup_native_fence_fd(_EGLDisplay *disp, _EGLSync *sync)
3515bf215546Sopenharmony_ci{
3516bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3517bf215546Sopenharmony_ci   struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3518bf215546Sopenharmony_ci
3519bf215546Sopenharmony_ci   assert(sync->Type == EGL_SYNC_NATIVE_FENCE_ANDROID);
3520bf215546Sopenharmony_ci
3521bf215546Sopenharmony_ci   if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
3522bf215546Sopenharmony_ci      /* try to retrieve the actual native fence fd.. if rendering is
3523bf215546Sopenharmony_ci       * not flushed this will just return -1, aka NO_NATIVE_FENCE_FD:
3524bf215546Sopenharmony_ci       */
3525bf215546Sopenharmony_ci      sync->SyncFd = dri2_dpy->fence->get_fence_fd(dri2_dpy->dri_screen,
3526bf215546Sopenharmony_ci                                                   dri2_sync->fence);
3527bf215546Sopenharmony_ci   }
3528bf215546Sopenharmony_ci
3529bf215546Sopenharmony_ci   if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
3530bf215546Sopenharmony_ci      /* if native fence fd still not created, return an error: */
3531bf215546Sopenharmony_ci      _eglError(EGL_BAD_PARAMETER, "eglDupNativeFenceFDANDROID");
3532bf215546Sopenharmony_ci      return EGL_NO_NATIVE_FENCE_FD_ANDROID;
3533bf215546Sopenharmony_ci   }
3534bf215546Sopenharmony_ci
3535bf215546Sopenharmony_ci   assert(sync_valid_fd(sync->SyncFd));
3536bf215546Sopenharmony_ci
3537bf215546Sopenharmony_ci   return os_dupfd_cloexec(sync->SyncFd);
3538bf215546Sopenharmony_ci}
3539bf215546Sopenharmony_ci
3540bf215546Sopenharmony_cistatic void
3541bf215546Sopenharmony_cidri2_set_blob_cache_funcs(_EGLDisplay *disp,
3542bf215546Sopenharmony_ci                          EGLSetBlobFuncANDROID set,
3543bf215546Sopenharmony_ci                          EGLGetBlobFuncANDROID get)
3544bf215546Sopenharmony_ci{
3545bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3546bf215546Sopenharmony_ci   dri2_dpy->blob->set_cache_funcs(dri2_dpy->dri_screen,
3547bf215546Sopenharmony_ci                                   disp->BlobCacheSet,
3548bf215546Sopenharmony_ci                                   disp->BlobCacheGet);
3549bf215546Sopenharmony_ci}
3550bf215546Sopenharmony_ci
3551bf215546Sopenharmony_cistatic EGLint
3552bf215546Sopenharmony_cidri2_client_wait_sync(_EGLDisplay *disp, _EGLSync *sync,
3553bf215546Sopenharmony_ci                      EGLint flags, EGLTime timeout)
3554bf215546Sopenharmony_ci{
3555bf215546Sopenharmony_ci   _EGLContext *ctx = _eglGetCurrentContext();
3556bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3557bf215546Sopenharmony_ci   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3558bf215546Sopenharmony_ci   struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3559bf215546Sopenharmony_ci   unsigned wait_flags = 0;
3560bf215546Sopenharmony_ci
3561bf215546Sopenharmony_ci   EGLint ret = EGL_CONDITION_SATISFIED_KHR;
3562bf215546Sopenharmony_ci
3563bf215546Sopenharmony_ci   /* The EGL_KHR_fence_sync spec states:
3564bf215546Sopenharmony_ci    *
3565bf215546Sopenharmony_ci    *    "If no context is current for the bound API,
3566bf215546Sopenharmony_ci    *     the EGL_SYNC_FLUSH_COMMANDS_BIT_KHR bit is ignored.
3567bf215546Sopenharmony_ci    */
3568bf215546Sopenharmony_ci   if (dri2_ctx && flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)
3569bf215546Sopenharmony_ci      wait_flags |= __DRI2_FENCE_FLAG_FLUSH_COMMANDS;
3570bf215546Sopenharmony_ci
3571bf215546Sopenharmony_ci   /* the sync object should take a reference while waiting */
3572bf215546Sopenharmony_ci   dri2_egl_ref_sync(dri2_sync);
3573bf215546Sopenharmony_ci
3574bf215546Sopenharmony_ci   switch (sync->Type) {
3575bf215546Sopenharmony_ci   case EGL_SYNC_FENCE_KHR:
3576bf215546Sopenharmony_ci   case EGL_SYNC_NATIVE_FENCE_ANDROID:
3577bf215546Sopenharmony_ci   case EGL_SYNC_CL_EVENT_KHR:
3578bf215546Sopenharmony_ci      if (dri2_dpy->fence->client_wait_sync(dri2_ctx ? dri2_ctx->dri_context : NULL,
3579bf215546Sopenharmony_ci                                         dri2_sync->fence, wait_flags,
3580bf215546Sopenharmony_ci                                         timeout))
3581bf215546Sopenharmony_ci         dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
3582bf215546Sopenharmony_ci      else
3583bf215546Sopenharmony_ci         ret = EGL_TIMEOUT_EXPIRED_KHR;
3584bf215546Sopenharmony_ci      break;
3585bf215546Sopenharmony_ci
3586bf215546Sopenharmony_ci   case EGL_SYNC_REUSABLE_KHR:
3587bf215546Sopenharmony_ci      if (dri2_ctx && dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR &&
3588bf215546Sopenharmony_ci          (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)) {
3589bf215546Sopenharmony_ci         /* flush context if EGL_SYNC_FLUSH_COMMANDS_BIT_KHR is set */
3590bf215546Sopenharmony_ci         dri2_gl_flush();
3591bf215546Sopenharmony_ci      }
3592bf215546Sopenharmony_ci
3593bf215546Sopenharmony_ci      /* if timeout is EGL_FOREVER_KHR, it should wait without any timeout.*/
3594bf215546Sopenharmony_ci      if (timeout == EGL_FOREVER_KHR) {
3595bf215546Sopenharmony_ci         mtx_lock(&dri2_sync->mutex);
3596bf215546Sopenharmony_ci         cnd_wait(&dri2_sync->cond, &dri2_sync->mutex);
3597bf215546Sopenharmony_ci         mtx_unlock(&dri2_sync->mutex);
3598bf215546Sopenharmony_ci      } else {
3599bf215546Sopenharmony_ci         /* if reusable sync has not been yet signaled */
3600bf215546Sopenharmony_ci         if (dri2_sync->base.SyncStatus != EGL_SIGNALED_KHR) {
3601bf215546Sopenharmony_ci            /* timespecs for cnd_timedwait */
3602bf215546Sopenharmony_ci            struct timespec current;
3603bf215546Sopenharmony_ci            struct timespec expire;
3604bf215546Sopenharmony_ci
3605bf215546Sopenharmony_ci            /* We override the clock to monotonic when creating the condition
3606bf215546Sopenharmony_ci             * variable. */
3607bf215546Sopenharmony_ci            clock_gettime(CLOCK_MONOTONIC, &current);
3608bf215546Sopenharmony_ci
3609bf215546Sopenharmony_ci            /* calculating when to expire */
3610bf215546Sopenharmony_ci            expire.tv_nsec = timeout % 1000000000L;
3611bf215546Sopenharmony_ci            expire.tv_sec = timeout / 1000000000L;
3612bf215546Sopenharmony_ci
3613bf215546Sopenharmony_ci            expire.tv_nsec += current.tv_nsec;
3614bf215546Sopenharmony_ci            expire.tv_sec += current.tv_sec;
3615bf215546Sopenharmony_ci
3616bf215546Sopenharmony_ci            /* expire.nsec now is a number between 0 and 1999999998 */
3617bf215546Sopenharmony_ci            if (expire.tv_nsec > 999999999L) {
3618bf215546Sopenharmony_ci               expire.tv_sec++;
3619bf215546Sopenharmony_ci               expire.tv_nsec -= 1000000000L;
3620bf215546Sopenharmony_ci            }
3621bf215546Sopenharmony_ci
3622bf215546Sopenharmony_ci            mtx_lock(&dri2_sync->mutex);
3623bf215546Sopenharmony_ci            ret = cnd_timedwait(&dri2_sync->cond, &dri2_sync->mutex, &expire);
3624bf215546Sopenharmony_ci            mtx_unlock(&dri2_sync->mutex);
3625bf215546Sopenharmony_ci
3626bf215546Sopenharmony_ci            if (ret == thrd_timedout) {
3627bf215546Sopenharmony_ci               if (dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR) {
3628bf215546Sopenharmony_ci                  ret = EGL_TIMEOUT_EXPIRED_KHR;
3629bf215546Sopenharmony_ci               } else {
3630bf215546Sopenharmony_ci                  _eglError(EGL_BAD_ACCESS, "eglClientWaitSyncKHR");
3631bf215546Sopenharmony_ci                  ret = EGL_FALSE;
3632bf215546Sopenharmony_ci               }
3633bf215546Sopenharmony_ci            }
3634bf215546Sopenharmony_ci         }
3635bf215546Sopenharmony_ci      }
3636bf215546Sopenharmony_ci      break;
3637bf215546Sopenharmony_ci  }
3638bf215546Sopenharmony_ci  dri2_egl_unref_sync(dri2_dpy, dri2_sync);
3639bf215546Sopenharmony_ci
3640bf215546Sopenharmony_ci  return ret;
3641bf215546Sopenharmony_ci}
3642bf215546Sopenharmony_ci
3643bf215546Sopenharmony_cistatic EGLBoolean
3644bf215546Sopenharmony_cidri2_signal_sync(_EGLDisplay *disp, _EGLSync *sync, EGLenum mode)
3645bf215546Sopenharmony_ci{
3646bf215546Sopenharmony_ci   struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3647bf215546Sopenharmony_ci   EGLint ret;
3648bf215546Sopenharmony_ci
3649bf215546Sopenharmony_ci   if (sync->Type != EGL_SYNC_REUSABLE_KHR)
3650bf215546Sopenharmony_ci      return _eglError(EGL_BAD_MATCH, "eglSignalSyncKHR");
3651bf215546Sopenharmony_ci
3652bf215546Sopenharmony_ci   if (mode != EGL_SIGNALED_KHR && mode != EGL_UNSIGNALED_KHR)
3653bf215546Sopenharmony_ci      return _eglError(EGL_BAD_ATTRIBUTE, "eglSignalSyncKHR");
3654bf215546Sopenharmony_ci
3655bf215546Sopenharmony_ci   dri2_sync->base.SyncStatus = mode;
3656bf215546Sopenharmony_ci
3657bf215546Sopenharmony_ci   if (mode == EGL_SIGNALED_KHR) {
3658bf215546Sopenharmony_ci      ret = cnd_broadcast(&dri2_sync->cond);
3659bf215546Sopenharmony_ci
3660bf215546Sopenharmony_ci      /* fail to broadcast */
3661bf215546Sopenharmony_ci      if (ret)
3662bf215546Sopenharmony_ci         return _eglError(EGL_BAD_ACCESS, "eglSignalSyncKHR");
3663bf215546Sopenharmony_ci   }
3664bf215546Sopenharmony_ci
3665bf215546Sopenharmony_ci   return EGL_TRUE;
3666bf215546Sopenharmony_ci}
3667bf215546Sopenharmony_ci
3668bf215546Sopenharmony_cistatic EGLint
3669bf215546Sopenharmony_cidri2_server_wait_sync(_EGLDisplay *disp, _EGLSync *sync)
3670bf215546Sopenharmony_ci{
3671bf215546Sopenharmony_ci   _EGLContext *ctx = _eglGetCurrentContext();
3672bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3673bf215546Sopenharmony_ci   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3674bf215546Sopenharmony_ci   struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3675bf215546Sopenharmony_ci
3676bf215546Sopenharmony_ci   dri2_dpy->fence->server_wait_sync(dri2_ctx->dri_context,
3677bf215546Sopenharmony_ci                                     dri2_sync->fence, 0);
3678bf215546Sopenharmony_ci   return EGL_TRUE;
3679bf215546Sopenharmony_ci}
3680bf215546Sopenharmony_ci
3681bf215546Sopenharmony_cistatic int
3682bf215546Sopenharmony_cidri2_interop_query_device_info(_EGLDisplay *disp, _EGLContext *ctx,
3683bf215546Sopenharmony_ci                               struct mesa_glinterop_device_info *out)
3684bf215546Sopenharmony_ci{
3685bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3686bf215546Sopenharmony_ci   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3687bf215546Sopenharmony_ci
3688bf215546Sopenharmony_ci   if (!dri2_dpy->interop)
3689bf215546Sopenharmony_ci      return MESA_GLINTEROP_UNSUPPORTED;
3690bf215546Sopenharmony_ci
3691bf215546Sopenharmony_ci   return dri2_dpy->interop->query_device_info(dri2_ctx->dri_context, out);
3692bf215546Sopenharmony_ci}
3693bf215546Sopenharmony_ci
3694bf215546Sopenharmony_cistatic int
3695bf215546Sopenharmony_cidri2_interop_export_object(_EGLDisplay *disp, _EGLContext *ctx,
3696bf215546Sopenharmony_ci                           struct mesa_glinterop_export_in *in,
3697bf215546Sopenharmony_ci                           struct mesa_glinterop_export_out *out)
3698bf215546Sopenharmony_ci{
3699bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3700bf215546Sopenharmony_ci   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3701bf215546Sopenharmony_ci
3702bf215546Sopenharmony_ci   if (!dri2_dpy->interop)
3703bf215546Sopenharmony_ci      return MESA_GLINTEROP_UNSUPPORTED;
3704bf215546Sopenharmony_ci
3705bf215546Sopenharmony_ci   return dri2_dpy->interop->export_object(dri2_ctx->dri_context, in, out);
3706bf215546Sopenharmony_ci}
3707bf215546Sopenharmony_ci
3708bf215546Sopenharmony_ciconst _EGLDriver _eglDriver = {
3709bf215546Sopenharmony_ci   .Initialize = dri2_initialize,
3710bf215546Sopenharmony_ci   .Terminate = dri2_terminate,
3711bf215546Sopenharmony_ci   .CreateContext = dri2_create_context,
3712bf215546Sopenharmony_ci   .DestroyContext = dri2_destroy_context,
3713bf215546Sopenharmony_ci   .MakeCurrent = dri2_make_current,
3714bf215546Sopenharmony_ci   .CreateWindowSurface = dri2_create_window_surface,
3715bf215546Sopenharmony_ci   .CreatePixmapSurface = dri2_create_pixmap_surface,
3716bf215546Sopenharmony_ci   .CreatePbufferSurface = dri2_create_pbuffer_surface,
3717bf215546Sopenharmony_ci   .DestroySurface = dri2_destroy_surface,
3718bf215546Sopenharmony_ci   .GetProcAddress = dri2_get_proc_address,
3719bf215546Sopenharmony_ci   .WaitClient = dri2_wait_client,
3720bf215546Sopenharmony_ci   .WaitNative = dri2_wait_native,
3721bf215546Sopenharmony_ci   .BindTexImage = dri2_bind_tex_image,
3722bf215546Sopenharmony_ci   .ReleaseTexImage = dri2_release_tex_image,
3723bf215546Sopenharmony_ci   .SwapInterval = dri2_swap_interval,
3724bf215546Sopenharmony_ci   .SwapBuffers = dri2_swap_buffers,
3725bf215546Sopenharmony_ci   .SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage,
3726bf215546Sopenharmony_ci   .SwapBuffersRegionNOK = dri2_swap_buffers_region,
3727bf215546Sopenharmony_ci   .SetDamageRegion = dri2_set_damage_region,
3728bf215546Sopenharmony_ci   .PostSubBufferNV = dri2_post_sub_buffer,
3729bf215546Sopenharmony_ci   .CopyBuffers = dri2_copy_buffers,
3730bf215546Sopenharmony_ci   .QueryBufferAge = dri2_query_buffer_age,
3731bf215546Sopenharmony_ci   .CreateImageKHR = dri2_create_image,
3732bf215546Sopenharmony_ci   .DestroyImageKHR = dri2_destroy_image_khr,
3733bf215546Sopenharmony_ci   .CreateWaylandBufferFromImageWL = dri2_create_wayland_buffer_from_image,
3734bf215546Sopenharmony_ci   .QuerySurface = dri2_query_surface,
3735bf215546Sopenharmony_ci   .QueryDriverName = dri2_query_driver_name,
3736bf215546Sopenharmony_ci   .QueryDriverConfig = dri2_query_driver_config,
3737bf215546Sopenharmony_ci#ifdef HAVE_LIBDRM
3738bf215546Sopenharmony_ci   .CreateDRMImageMESA = dri2_create_drm_image_mesa,
3739bf215546Sopenharmony_ci   .ExportDRMImageMESA = dri2_export_drm_image_mesa,
3740bf215546Sopenharmony_ci   .ExportDMABUFImageQueryMESA = dri2_export_dma_buf_image_query_mesa,
3741bf215546Sopenharmony_ci   .ExportDMABUFImageMESA = dri2_export_dma_buf_image_mesa,
3742bf215546Sopenharmony_ci   .QueryDmaBufFormatsEXT = dri2_query_dma_buf_formats,
3743bf215546Sopenharmony_ci   .QueryDmaBufModifiersEXT = dri2_query_dma_buf_modifiers,
3744bf215546Sopenharmony_ci#endif
3745bf215546Sopenharmony_ci#ifdef HAVE_WAYLAND_PLATFORM
3746bf215546Sopenharmony_ci   .BindWaylandDisplayWL = dri2_bind_wayland_display_wl,
3747bf215546Sopenharmony_ci   .UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl,
3748bf215546Sopenharmony_ci   .QueryWaylandBufferWL = dri2_query_wayland_buffer_wl,
3749bf215546Sopenharmony_ci#endif
3750bf215546Sopenharmony_ci   .GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium,
3751bf215546Sopenharmony_ci   .CreateSyncKHR = dri2_create_sync,
3752bf215546Sopenharmony_ci   .ClientWaitSyncKHR = dri2_client_wait_sync,
3753bf215546Sopenharmony_ci   .SignalSyncKHR = dri2_signal_sync,
3754bf215546Sopenharmony_ci   .WaitSyncKHR = dri2_server_wait_sync,
3755bf215546Sopenharmony_ci   .DestroySyncKHR = dri2_destroy_sync,
3756bf215546Sopenharmony_ci   .GLInteropQueryDeviceInfo = dri2_interop_query_device_info,
3757bf215546Sopenharmony_ci   .GLInteropExportObject = dri2_interop_export_object,
3758bf215546Sopenharmony_ci   .DupNativeFenceFDANDROID = dri2_dup_native_fence_fd,
3759bf215546Sopenharmony_ci   .SetBlobCacheFuncsANDROID = dri2_set_blob_cache_funcs,
3760bf215546Sopenharmony_ci};
3761