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