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