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