egl: handle NULL loaderPrivate in dri_is_thread_safe
[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    default:
1211       unreachable("Callers ensure we cannot get here.");
1212       return EGL_FALSE;
1213    }
1214
1215    if (!ret)
1216       return EGL_FALSE;
1217
1218    dri2_dpy = dri2_egl_display(disp);
1219    p_atomic_inc(&dri2_dpy->ref_count);
1220
1221    mtx_init(&dri2_dpy->lock, mtx_plain);
1222
1223    return EGL_TRUE;
1224 }
1225
1226 /**
1227  * Decrement display reference count, and free up display if necessary.
1228  */
1229 static void
1230 dri2_display_release(_EGLDisplay *disp)
1231 {
1232    struct dri2_egl_display *dri2_dpy;
1233
1234    if (!disp)
1235       return;
1236
1237    dri2_dpy = dri2_egl_display(disp);
1238
1239    assert(dri2_dpy->ref_count > 0);
1240
1241    if (!p_atomic_dec_zero(&dri2_dpy->ref_count))
1242       return;
1243
1244    _eglCleanupDisplay(disp);
1245    dri2_display_destroy(disp);
1246 }
1247
1248 void
1249 dri2_display_destroy(_EGLDisplay *disp)
1250 {
1251    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1252
1253    if (dri2_dpy->own_dri_screen) {
1254       if (dri2_dpy->vtbl && dri2_dpy->vtbl->close_screen_notify)
1255          dri2_dpy->vtbl->close_screen_notify(disp);
1256       dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
1257    }
1258    if (dri2_dpy->fd >= 0)
1259       close(dri2_dpy->fd);
1260
1261    /* Don't dlclose the driver when building with the address sanitizer, so you
1262     * get good symbols from the leak reports.
1263     */
1264 #if !BUILT_WITH_ASAN || defined(NDEBUG)
1265    if (dri2_dpy->driver)
1266       dlclose(dri2_dpy->driver);
1267 #endif
1268
1269    free(dri2_dpy->driver_name);
1270
1271 #ifdef HAVE_WAYLAND_PLATFORM
1272    free(dri2_dpy->device_name);
1273 #endif
1274
1275    switch (disp->Platform) {
1276    case _EGL_PLATFORM_X11:
1277       dri2_teardown_x11(dri2_dpy);
1278       break;
1279    case _EGL_PLATFORM_DRM:
1280       dri2_teardown_drm(dri2_dpy);
1281       break;
1282    case _EGL_PLATFORM_WAYLAND:
1283       dri2_teardown_wayland(dri2_dpy);
1284       break;
1285    default:
1286       /* TODO: add teardown for other platforms */
1287       break;
1288    }
1289
1290    /* The drm platform does not create the screen/driver_configs but reuses
1291     * the ones from the gbm device. As such the gbm itself is responsible
1292     * for the cleanup.
1293     */
1294    if (disp->Platform != _EGL_PLATFORM_DRM && dri2_dpy->driver_configs) {
1295       for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++)
1296          free((__DRIconfig *) dri2_dpy->driver_configs[i]);
1297       free(dri2_dpy->driver_configs);
1298    }
1299    free(dri2_dpy);
1300    disp->DriverData = NULL;
1301 }
1302
1303 __DRIbuffer *
1304 dri2_egl_surface_alloc_local_buffer(struct dri2_egl_surface *dri2_surf,
1305                                     unsigned int att, unsigned int format)
1306 {
1307    struct dri2_egl_display *dri2_dpy =
1308       dri2_egl_display(dri2_surf->base.Resource.Display);
1309
1310    if (att >= ARRAY_SIZE(dri2_surf->local_buffers))
1311       return NULL;
1312
1313    if (!dri2_surf->local_buffers[att]) {
1314       dri2_surf->local_buffers[att] =
1315          dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, att, format,
1316                                         dri2_surf->base.Width, dri2_surf->base.Height);
1317    }
1318
1319    return dri2_surf->local_buffers[att];
1320 }
1321
1322 void
1323 dri2_egl_surface_free_local_buffers(struct dri2_egl_surface *dri2_surf)
1324 {
1325    struct dri2_egl_display *dri2_dpy =
1326       dri2_egl_display(dri2_surf->base.Resource.Display);
1327
1328    for (int i = 0; i < ARRAY_SIZE(dri2_surf->local_buffers); i++) {
1329       if (dri2_surf->local_buffers[i]) {
1330          dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
1331                                        dri2_surf->local_buffers[i]);
1332          dri2_surf->local_buffers[i] = NULL;
1333       }
1334    }
1335 }
1336
1337 /**
1338  * Called via eglTerminate(), drv->Terminate().
1339  *
1340  * This must be guaranteed to be called exactly once, even if eglTerminate is
1341  * called many times (without a eglInitialize in between).
1342  */
1343 static EGLBoolean
1344 dri2_terminate(_EGLDisplay *disp)
1345 {
1346    /* Release all non-current Context/Surfaces. */
1347    _eglReleaseDisplayResources(disp);
1348
1349    dri2_display_release(disp);
1350
1351    return EGL_TRUE;
1352 }
1353
1354 /**
1355  * Set the error code after a call to
1356  * dri2_egl_display::dri2::createContextAttribs.
1357  */
1358 static void
1359 dri2_create_context_attribs_error(int dri_error)
1360 {
1361    EGLint egl_error;
1362
1363    switch (dri_error) {
1364    case __DRI_CTX_ERROR_SUCCESS:
1365       return;
1366
1367    case __DRI_CTX_ERROR_NO_MEMORY:
1368       egl_error = EGL_BAD_ALLOC;
1369       break;
1370
1371   /* From the EGL_KHR_create_context spec, section "Errors":
1372    *
1373    *   * If <config> does not support a client API context compatible
1374    *     with the requested API major and minor version, [...] context flags,
1375    *     and context reset notification behavior (for client API types where
1376    *     these attributes are supported), then an EGL_BAD_MATCH error is
1377    *     generated.
1378    *
1379    *   * If an OpenGL ES context is requested and the values for
1380    *     attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
1381    *     EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
1382    *     is not defined, than an EGL_BAD_MATCH error is generated.
1383    *
1384    *   * If an OpenGL context is requested, the requested version is
1385    *     greater than 3.2, and the value for attribute
1386    *     EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has any
1387    *     bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and
1388    *     EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than
1389    *     one of these bits set; or if the implementation does not support
1390    *     the requested profile, then an EGL_BAD_MATCH error is generated.
1391    */
1392    case __DRI_CTX_ERROR_BAD_API:
1393    case __DRI_CTX_ERROR_BAD_VERSION:
1394    case __DRI_CTX_ERROR_BAD_FLAG:
1395       egl_error = EGL_BAD_MATCH;
1396       break;
1397
1398   /* From the EGL_KHR_create_context spec, section "Errors":
1399    *
1400    *   * If an attribute name or attribute value in <attrib_list> is not
1401    *     recognized (including unrecognized bits in bitmask attributes),
1402    *     then an EGL_BAD_ATTRIBUTE error is generated."
1403    */
1404    case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE:
1405    case __DRI_CTX_ERROR_UNKNOWN_FLAG:
1406       egl_error = EGL_BAD_ATTRIBUTE;
1407       break;
1408
1409    default:
1410       assert(!"unknown dri_error code");
1411       egl_error = EGL_BAD_MATCH;
1412       break;
1413    }
1414
1415    _eglError(egl_error, "dri2_create_context");
1416 }
1417
1418 static bool
1419 dri2_fill_context_attribs(struct dri2_egl_context *dri2_ctx,
1420                           struct dri2_egl_display *dri2_dpy,
1421                           uint32_t *ctx_attribs,
1422                           unsigned *num_attribs)
1423 {
1424    int pos = 0;
1425
1426    assert(*num_attribs >= NUM_ATTRIBS);
1427
1428    ctx_attribs[pos++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
1429    ctx_attribs[pos++] = dri2_ctx->base.ClientMajorVersion;
1430    ctx_attribs[pos++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
1431    ctx_attribs[pos++] = dri2_ctx->base.ClientMinorVersion;
1432
1433    if (dri2_ctx->base.Flags != 0) {
1434       /* If the implementation doesn't support the __DRI2_ROBUSTNESS
1435        * extension, don't even try to send it the robust-access flag.
1436        * It may explode.  Instead, generate the required EGL error here.
1437        */
1438       if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0
1439             && !dri2_dpy->robustness) {
1440          _eglError(EGL_BAD_MATCH, "eglCreateContext");
1441          return false;
1442       }
1443
1444       ctx_attribs[pos++] = __DRI_CTX_ATTRIB_FLAGS;
1445       ctx_attribs[pos++] = dri2_ctx->base.Flags;
1446    }
1447
1448    if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) {
1449       /* If the implementation doesn't support the __DRI2_ROBUSTNESS
1450        * extension, don't even try to send it a reset strategy.  It may
1451        * explode.  Instead, generate the required EGL error here.
1452        */
1453       if (!dri2_dpy->robustness) {
1454          _eglError(EGL_BAD_CONFIG, "eglCreateContext");
1455          return false;
1456       }
1457
1458       ctx_attribs[pos++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
1459       ctx_attribs[pos++] = __DRI_CTX_RESET_LOSE_CONTEXT;
1460    }
1461
1462    if (dri2_ctx->base.ContextPriority != EGL_CONTEXT_PRIORITY_MEDIUM_IMG) {
1463       unsigned val;
1464
1465       switch (dri2_ctx->base.ContextPriority) {
1466       case EGL_CONTEXT_PRIORITY_HIGH_IMG:
1467          val = __DRI_CTX_PRIORITY_HIGH;
1468          break;
1469       case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
1470          val = __DRI_CTX_PRIORITY_MEDIUM;
1471          break;
1472       case EGL_CONTEXT_PRIORITY_LOW_IMG:
1473          val = __DRI_CTX_PRIORITY_LOW;
1474          break;
1475       default:
1476          _eglError(EGL_BAD_CONFIG, "eglCreateContext");
1477          return false;
1478       }
1479
1480       ctx_attribs[pos++] = __DRI_CTX_ATTRIB_PRIORITY;
1481       ctx_attribs[pos++] = val;
1482    }
1483
1484    if (dri2_ctx->base.ReleaseBehavior == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR) {
1485       ctx_attribs[pos++] = __DRI_CTX_ATTRIB_RELEASE_BEHAVIOR;
1486       ctx_attribs[pos++] = __DRI_CTX_RELEASE_BEHAVIOR_NONE;
1487    }
1488
1489    if (dri2_ctx->base.NoError) {
1490       ctx_attribs[pos++] = __DRI_CTX_ATTRIB_NO_ERROR;
1491       ctx_attribs[pos++] = true;
1492    }
1493
1494    if (dri2_ctx->base.Protected) {
1495       ctx_attribs[pos++] = __DRI_CTX_ATTRIB_PROTECTED;
1496       ctx_attribs[pos++] = true;
1497    }
1498
1499    *num_attribs = pos;
1500
1501    return true;
1502 }
1503
1504 /**
1505  * Called via eglCreateContext(), drv->CreateContext().
1506  */
1507 static _EGLContext *
1508 dri2_create_context(_EGLDisplay *disp, _EGLConfig *conf,
1509                     _EGLContext *share_list, const EGLint *attrib_list)
1510 {
1511    struct dri2_egl_context *dri2_ctx;
1512    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
1513    struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list);
1514    __DRIcontext *shared =
1515       dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL;
1516    struct dri2_egl_config *dri2_config = dri2_egl_config(conf);
1517    const __DRIconfig *dri_config;
1518    int api;
1519    unsigned error;
1520    unsigned num_attribs = NUM_ATTRIBS;
1521    uint32_t ctx_attribs[NUM_ATTRIBS];
1522
1523    dri2_ctx = malloc(sizeof *dri2_ctx);
1524    if (!dri2_ctx) {
1525       dri2_egl_error_unlock(dri2_dpy, EGL_BAD_ALLOC, "eglCreateContext");
1526       return NULL;
1527    }
1528
1529    if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list))
1530       goto cleanup;
1531
1532    /* The EGL_EXT_create_context_robustness spec says:
1533     *
1534     *    "Add to the eglCreateContext context creation errors: [...]
1535     *
1536     *     * If the reset notification behavior of <share_context> and the
1537     *       newly created context are different then an EGL_BAD_MATCH error is
1538     *       generated."
1539     */
1540    if (share_list && share_list->ResetNotificationStrategy !=
1541                      dri2_ctx->base.ResetNotificationStrategy) {
1542       _eglError(EGL_BAD_MATCH, "eglCreateContext");
1543       goto cleanup;
1544    }
1545
1546    /* The EGL_KHR_create_context_no_error spec says:
1547     *
1548     *    "BAD_MATCH is generated if the value of EGL_CONTEXT_OPENGL_NO_ERROR_KHR
1549     *    used to create <share_context> does not match the value of
1550     *    EGL_CONTEXT_OPENGL_NO_ERROR_KHR for the context being created."
1551     */
1552    if (share_list && share_list->NoError != dri2_ctx->base.NoError) {
1553       _eglError(EGL_BAD_MATCH, "eglCreateContext");
1554       goto cleanup;
1555    }
1556
1557    switch (dri2_ctx->base.ClientAPI) {
1558    case EGL_OPENGL_ES_API:
1559       switch (dri2_ctx->base.ClientMajorVersion) {
1560       case 1:
1561          api = __DRI_API_GLES;
1562          break;
1563       case 2:
1564          api = __DRI_API_GLES2;
1565          break;
1566       case 3:
1567          api = __DRI_API_GLES3;
1568          break;
1569       default:
1570          _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
1571          goto cleanup;
1572       }
1573       break;
1574    case EGL_OPENGL_API:
1575       if ((dri2_ctx->base.ClientMajorVersion >= 4
1576            || (dri2_ctx->base.ClientMajorVersion == 3
1577                && dri2_ctx->base.ClientMinorVersion >= 2))
1578           && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
1579          api = __DRI_API_OPENGL_CORE;
1580       else if (dri2_ctx->base.ClientMajorVersion == 3 &&
1581                dri2_ctx->base.ClientMinorVersion == 1)
1582          api = __DRI_API_OPENGL_CORE;
1583       else
1584          api = __DRI_API_OPENGL;
1585       break;
1586    default:
1587       _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
1588       goto cleanup;
1589    }
1590
1591    if (conf != NULL) {
1592       /* The config chosen here isn't necessarily
1593        * used for surfaces later.
1594        * A pixmap surface will use the single config.
1595        * This opportunity depends on disabling the
1596        * doubleBufferMode check in
1597        * src/mesa/main/context.c:check_compatible()
1598        */
1599       if (dri2_config->dri_config[1][0])
1600          dri_config = dri2_config->dri_config[1][0];
1601       else
1602          dri_config = dri2_config->dri_config[0][0];
1603    }
1604    else
1605       dri_config = NULL;
1606
1607    if (!dri2_fill_context_attribs(dri2_ctx, dri2_dpy, ctx_attribs,
1608                                   &num_attribs))
1609       goto cleanup;
1610
1611    if (dri2_dpy->image_driver) {
1612       dri2_ctx->dri_context =
1613          dri2_dpy->image_driver->createContextAttribs(dri2_dpy->dri_screen,
1614                                                       api,
1615                                                       dri_config,
1616                                                       shared,
1617                                                       num_attribs / 2,
1618                                                       ctx_attribs,
1619                                                       & error,
1620                                                       dri2_ctx);
1621       dri2_create_context_attribs_error(error);
1622    } else if (dri2_dpy->dri2) {
1623       if (dri2_dpy->dri2->base.version >= 3) {
1624          dri2_ctx->dri_context =
1625             dri2_dpy->dri2->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 {
1635          dri2_ctx->dri_context =
1636             dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
1637                                                    api,
1638                                                    dri_config,
1639                                                    shared,
1640                                                    dri2_ctx);
1641       }
1642    } else {
1643       assert(dri2_dpy->swrast);
1644       if (dri2_dpy->swrast->base.version >= 3) {
1645          dri2_ctx->dri_context =
1646             dri2_dpy->swrast->createContextAttribs(dri2_dpy->dri_screen,
1647                                                    api,
1648                                                    dri_config,
1649                                                    shared,
1650                                                    num_attribs / 2,
1651                                                    ctx_attribs,
1652                                                    & error,
1653                                                    dri2_ctx);
1654          dri2_create_context_attribs_error(error);
1655       } else {
1656          dri2_ctx->dri_context =
1657             dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen,
1658                                                      api,
1659                                                      dri_config,
1660                                                      shared,
1661                                                      dri2_ctx);
1662       }
1663    }
1664
1665    if (!dri2_ctx->dri_context)
1666       goto cleanup;
1667
1668    mtx_unlock(&dri2_dpy->lock);
1669
1670    return &dri2_ctx->base;
1671
1672  cleanup:
1673    mtx_unlock(&dri2_dpy->lock);
1674    free(dri2_ctx);
1675    return NULL;
1676 }
1677
1678 /**
1679  * Called via eglDestroyContext(), drv->DestroyContext().
1680  */
1681 static EGLBoolean
1682 dri2_destroy_context(_EGLDisplay *disp, _EGLContext *ctx)
1683 {
1684    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1685    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1686
1687    if (_eglPutContext(ctx)) {
1688       dri2_dpy->core->destroyContext(dri2_ctx->dri_context);
1689       free(dri2_ctx);
1690    }
1691
1692    return EGL_TRUE;
1693 }
1694
1695 EGLBoolean
1696 dri2_init_surface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type,
1697         _EGLConfig *conf, const EGLint *attrib_list,
1698         EGLBoolean enable_out_fence, void *native_surface)
1699 {
1700    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1701    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1702
1703    dri2_surf->out_fence_fd = -1;
1704    dri2_surf->enable_out_fence = false;
1705    if (dri2_dpy->fence && dri2_dpy->fence->base.version >= 2 &&
1706        dri2_dpy->fence->get_capabilities &&
1707        (dri2_dpy->fence->get_capabilities(dri2_dpy->dri_screen) &
1708         __DRI_FENCE_CAP_NATIVE_FD)) {
1709       dri2_surf->enable_out_fence = enable_out_fence;
1710    }
1711
1712    return _eglInitSurface(surf, disp, type, conf, attrib_list, native_surface);
1713 }
1714
1715 static void
1716 dri2_surface_set_out_fence_fd( _EGLSurface *surf, int fence_fd)
1717 {
1718    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1719
1720    if (dri2_surf->out_fence_fd >= 0)
1721       close(dri2_surf->out_fence_fd);
1722
1723    dri2_surf->out_fence_fd = fence_fd;
1724 }
1725
1726 void
1727 dri2_fini_surface(_EGLSurface *surf)
1728 {
1729    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1730
1731    dri2_surface_set_out_fence_fd(surf, -1);
1732    dri2_surf->enable_out_fence = false;
1733 }
1734
1735 static EGLBoolean
1736 dri2_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
1737 {
1738    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1739    EGLBoolean ret = EGL_TRUE;
1740
1741    if (_eglPutSurface(surf))
1742       ret = dri2_dpy->vtbl->destroy_surface(disp, surf);
1743
1744    return ret;
1745 }
1746
1747 static void
1748 dri2_surf_update_fence_fd(_EGLContext *ctx,
1749                           _EGLDisplay *disp, _EGLSurface *surf)
1750 {
1751    __DRIcontext *dri_ctx = dri2_egl_context(ctx)->dri_context;
1752    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1753    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1754    int fence_fd = -1;
1755    void *fence;
1756
1757    if (!dri2_surf->enable_out_fence)
1758       return;
1759
1760    fence = dri2_dpy->fence->create_fence_fd(dri_ctx, -1);
1761    if (fence) {
1762       fence_fd = dri2_dpy->fence->get_fence_fd(dri2_dpy->dri_screen,
1763                                                fence);
1764       dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, fence);
1765    }
1766    dri2_surface_set_out_fence_fd(surf, fence_fd);
1767 }
1768
1769 EGLBoolean
1770 dri2_create_drawable(struct dri2_egl_display *dri2_dpy,
1771                      const __DRIconfig *config,
1772                      struct dri2_egl_surface *dri2_surf,
1773                      void *loaderPrivate)
1774 {
1775    if (dri2_dpy->kopper) {
1776       dri2_surf->dri_drawable =
1777           dri2_dpy->kopper->createNewDrawable(dri2_dpy->dri_screen, config, loaderPrivate,
1778                                               dri2_surf->base.Type == EGL_PBUFFER_BIT ||
1779                                               dri2_surf->base.Type == EGL_PIXMAP_BIT);
1780    } else {
1781       __DRIcreateNewDrawableFunc createNewDrawable;
1782       if (dri2_dpy->image_driver)
1783          createNewDrawable = dri2_dpy->image_driver->createNewDrawable;
1784       else if (dri2_dpy->dri2)
1785          createNewDrawable = dri2_dpy->dri2->createNewDrawable;
1786       else if (dri2_dpy->swrast)
1787          createNewDrawable = dri2_dpy->swrast->createNewDrawable;
1788       else
1789          return _eglError(EGL_BAD_ALLOC, "no createNewDrawable");
1790
1791       dri2_surf->dri_drawable = createNewDrawable(dri2_dpy->dri_screen,
1792                                                   config, loaderPrivate);
1793    }
1794    if (dri2_surf->dri_drawable == NULL)
1795       return _eglError(EGL_BAD_ALLOC, "createNewDrawable");
1796
1797    return EGL_TRUE;
1798 }
1799
1800 /**
1801  * Called via eglMakeCurrent(), drv->MakeCurrent().
1802  */
1803 static EGLBoolean
1804 dri2_make_current(_EGLDisplay *disp, _EGLSurface *dsurf,
1805                   _EGLSurface *rsurf, _EGLContext *ctx)
1806 {
1807    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1808    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1809    _EGLDisplay *old_disp = NULL;
1810    struct dri2_egl_display *old_dri2_dpy = NULL;
1811    _EGLContext *old_ctx;
1812    _EGLSurface *old_dsurf, *old_rsurf;
1813    _EGLSurface *tmp_dsurf, *tmp_rsurf;
1814    __DRIdrawable *ddraw, *rdraw;
1815    __DRIcontext *cctx;
1816    EGLint egl_error = EGL_SUCCESS;
1817
1818    if (!dri2_dpy)
1819       return _eglError(EGL_NOT_INITIALIZED, "eglMakeCurrent");
1820
1821    /* make new bindings, set the EGL error otherwise */
1822    if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
1823       return EGL_FALSE;
1824
1825    if (old_ctx == ctx && old_dsurf == dsurf && old_rsurf == rsurf) {
1826       _eglPutSurface(old_dsurf);
1827       _eglPutSurface(old_rsurf);
1828       _eglPutContext(old_ctx);
1829       return EGL_TRUE;
1830    }
1831
1832    if (old_ctx) {
1833       __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context;
1834       old_disp = old_ctx->Resource.Display;
1835       old_dri2_dpy = dri2_egl_display(old_disp);
1836
1837       /* Disable shared buffer mode */
1838       if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) &&
1839           old_dri2_dpy->vtbl->set_shared_buffer_mode) {
1840          old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, false);
1841       }
1842
1843       old_dri2_dpy->core->unbindContext(old_cctx);
1844
1845       if (old_dsurf)
1846          dri2_surf_update_fence_fd(old_ctx, old_disp, old_dsurf);
1847    }
1848
1849    ddraw = (dsurf) ? dri2_dpy->vtbl->get_dri_drawable(dsurf) : NULL;
1850    rdraw = (rsurf) ? dri2_dpy->vtbl->get_dri_drawable(rsurf) : NULL;
1851    cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL;
1852
1853    if (cctx) {
1854       if (!dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
1855          _EGLContext *tmp_ctx;
1856
1857          /* dri2_dpy->core->bindContext failed. We cannot tell for sure why, but
1858           * setting the error to EGL_BAD_MATCH is surely better than leaving it
1859           * as EGL_SUCCESS.
1860           */
1861          egl_error = EGL_BAD_MATCH;
1862
1863          /* undo the previous _eglBindContext */
1864          _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &tmp_dsurf, &tmp_rsurf);
1865          assert(&dri2_ctx->base == ctx &&
1866                 tmp_dsurf == dsurf &&
1867                 tmp_rsurf == rsurf);
1868
1869          _eglPutSurface(dsurf);
1870          _eglPutSurface(rsurf);
1871          _eglPutContext(ctx);
1872
1873          _eglPutSurface(old_dsurf);
1874          _eglPutSurface(old_rsurf);
1875          _eglPutContext(old_ctx);
1876
1877          ddraw = (old_dsurf) ? dri2_dpy->vtbl->get_dri_drawable(old_dsurf) : NULL;
1878          rdraw = (old_rsurf) ? dri2_dpy->vtbl->get_dri_drawable(old_rsurf) : NULL;
1879          cctx = (old_ctx) ? dri2_egl_context(old_ctx)->dri_context : NULL;
1880
1881          /* undo the previous dri2_dpy->core->unbindContext */
1882          if (dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
1883             if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) &&
1884                 old_dri2_dpy->vtbl->set_shared_buffer_mode) {
1885                old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, true);
1886             }
1887
1888             return _eglError(egl_error, "eglMakeCurrent");
1889          }
1890
1891          /* We cannot restore the same state as it was before calling
1892           * eglMakeCurrent() and the spec isn't clear about what to do. We
1893           * can prevent EGL from calling into the DRI driver with no DRI
1894           * context bound.
1895           */
1896          dsurf = rsurf = NULL;
1897          ctx = NULL;
1898
1899          _eglBindContext(ctx, dsurf, rsurf, &tmp_ctx, &tmp_dsurf, &tmp_rsurf);
1900          assert(tmp_ctx == old_ctx && tmp_dsurf == old_dsurf &&
1901                 tmp_rsurf == old_rsurf);
1902
1903          _eglLog(_EGL_WARNING, "DRI2: failed to rebind the previous context");
1904       } else {
1905          /* dri2_dpy->core->bindContext succeeded, so take a reference on the
1906           * dri2_dpy. This prevents dri2_dpy from being reinitialized when a
1907           * EGLDisplay is terminated and then initialized again while a
1908           * context is still bound. See dri2_initialize() for a more in depth
1909           * explanation. */
1910          p_atomic_inc(&dri2_dpy->ref_count);
1911       }
1912    }
1913
1914    dri2_destroy_surface(disp, old_dsurf);
1915    dri2_destroy_surface(disp, old_rsurf);
1916
1917    if (old_ctx) {
1918       dri2_destroy_context(disp, old_ctx);
1919       dri2_display_release(old_disp);
1920    }
1921
1922    if (egl_error != EGL_SUCCESS)
1923       return _eglError(egl_error, "eglMakeCurrent");
1924
1925    if (dsurf && _eglSurfaceHasMutableRenderBuffer(dsurf) &&
1926        dri2_dpy->vtbl->set_shared_buffer_mode) {
1927       /* Always update the shared buffer mode. This is obviously needed when
1928        * the active EGL_RENDER_BUFFER is EGL_SINGLE_BUFFER. When
1929        * EGL_RENDER_BUFFER is EGL_BACK_BUFFER, the update protects us in the
1930        * case where external non-EGL API may have changed window's shared
1931        * buffer mode since we last saw it.
1932        */
1933       bool mode = (dsurf->ActiveRenderBuffer == EGL_SINGLE_BUFFER);
1934       dri2_dpy->vtbl->set_shared_buffer_mode(disp, dsurf, mode);
1935    }
1936
1937    return EGL_TRUE;
1938 }
1939
1940 __DRIdrawable *
1941 dri2_surface_get_dri_drawable(_EGLSurface *surf)
1942 {
1943    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1944
1945    return dri2_surf->dri_drawable;
1946 }
1947
1948 /*
1949  * Called from eglGetProcAddress() via drv->GetProcAddress().
1950  */
1951 static _EGLProc
1952 dri2_get_proc_address(const char *procname)
1953 {
1954    return _glapi_get_proc_address(procname);
1955 }
1956
1957 static _EGLSurface*
1958 dri2_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
1959                            void *native_window, const EGLint *attrib_list)
1960 {
1961    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
1962    _EGLSurface *ret =
1963          dri2_dpy->vtbl->create_window_surface(disp, conf, native_window,
1964                                                attrib_list);
1965    mtx_unlock(&dri2_dpy->lock);
1966    return ret;
1967 }
1968
1969 static _EGLSurface*
1970 dri2_create_pixmap_surface(_EGLDisplay *disp, _EGLConfig *conf,
1971                            void *native_pixmap, const EGLint *attrib_list)
1972 {
1973    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
1974    _EGLSurface *ret = NULL;
1975
1976    if (dri2_dpy->vtbl->create_pixmap_surface)
1977       ret = dri2_dpy->vtbl->create_pixmap_surface(disp, conf, native_pixmap,
1978                                                   attrib_list);
1979
1980    mtx_unlock(&dri2_dpy->lock);
1981
1982    return ret;
1983 }
1984
1985 static _EGLSurface*
1986 dri2_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
1987                             const EGLint *attrib_list)
1988 {
1989    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
1990    _EGLSurface *ret = NULL;
1991
1992    if (dri2_dpy->vtbl->create_pbuffer_surface)
1993       ret = dri2_dpy->vtbl->create_pbuffer_surface(disp, conf, attrib_list);
1994
1995    mtx_unlock(&dri2_dpy->lock);
1996
1997    return ret;
1998 }
1999
2000 static EGLBoolean
2001 dri2_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval)
2002 {
2003    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
2004    EGLBoolean ret = EGL_TRUE;
2005
2006    if (dri2_dpy->vtbl->swap_interval)
2007       ret = dri2_dpy->vtbl->swap_interval(disp, surf, interval);
2008
2009    mtx_unlock(&dri2_dpy->lock);
2010
2011    return ret;
2012 }
2013
2014 /**
2015  * Asks the client API to flush any rendering to the drawable so that we can
2016  * do our swapbuffers.
2017  */
2018 void
2019 dri2_flush_drawable_for_swapbuffers(_EGLDisplay *disp, _EGLSurface *draw)
2020 {
2021    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2022    __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(draw);
2023
2024    if (dri2_dpy->flush) {
2025       if (dri2_dpy->flush->base.version >= 4) {
2026          /* We know there's a current context because:
2027           *
2028           *     "If surface is not bound to the calling thread’s current
2029           *      context, an EGL_BAD_SURFACE error is generated."
2030          */
2031          _EGLContext *ctx = _eglGetCurrentContext();
2032          struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
2033
2034          /* From the EGL 1.4 spec (page 52):
2035           *
2036           *     "The contents of ancillary buffers are always undefined
2037           *      after calling eglSwapBuffers."
2038           */
2039          dri2_dpy->flush->flush_with_flags(dri2_ctx->dri_context,
2040                                            dri_drawable,
2041                                            __DRI2_FLUSH_DRAWABLE |
2042                                            __DRI2_FLUSH_INVALIDATE_ANCILLARY,
2043                                            __DRI2_THROTTLE_SWAPBUFFER);
2044       } else {
2045          dri2_dpy->flush->flush(dri_drawable);
2046       }
2047    }
2048 }
2049
2050 static EGLBoolean
2051 dri2_swap_buffers(_EGLDisplay *disp, _EGLSurface *surf)
2052 {
2053    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2054    __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2055    _EGLContext *ctx = _eglGetCurrentContext();
2056    EGLBoolean ret;
2057
2058    if (ctx && surf)
2059       dri2_surf_update_fence_fd(ctx, disp, surf);
2060    ret = dri2_dpy->vtbl->swap_buffers(disp, surf);
2061
2062    /* SwapBuffers marks the end of the frame; reset the damage region for
2063     * use again next time.
2064     */
2065    if (ret && dri2_dpy->buffer_damage &&
2066        dri2_dpy->buffer_damage->set_damage_region)
2067       dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL);
2068
2069    return ret;
2070 }
2071
2072 static EGLBoolean
2073 dri2_swap_buffers_with_damage(_EGLDisplay *disp, _EGLSurface *surf,
2074                               const EGLint *rects, EGLint n_rects)
2075 {
2076    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2077    __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2078    _EGLContext *ctx = _eglGetCurrentContext();
2079    EGLBoolean ret;
2080
2081    if (ctx && surf)
2082       dri2_surf_update_fence_fd(ctx, disp, surf);
2083    if (dri2_dpy->vtbl->swap_buffers_with_damage)
2084       ret = dri2_dpy->vtbl->swap_buffers_with_damage(disp, surf,
2085                                                      rects, n_rects);
2086    else
2087       ret = dri2_dpy->vtbl->swap_buffers(disp, surf);
2088
2089    /* SwapBuffers marks the end of the frame; reset the damage region for
2090     * use again next time.
2091     */
2092    if (ret && dri2_dpy->buffer_damage &&
2093        dri2_dpy->buffer_damage->set_damage_region)
2094       dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL);
2095
2096    return ret;
2097 }
2098
2099 static EGLBoolean
2100 dri2_swap_buffers_region(_EGLDisplay *disp, _EGLSurface *surf,
2101                          EGLint numRects, const EGLint *rects)
2102 {
2103    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2104    __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2105    EGLBoolean ret;
2106
2107    if (!dri2_dpy->vtbl->swap_buffers_region)
2108       return EGL_FALSE;
2109    ret = dri2_dpy->vtbl->swap_buffers_region(disp, surf, numRects, rects);
2110
2111    /* SwapBuffers marks the end of the frame; reset the damage region for
2112     * use again next time.
2113     */
2114    if (ret && dri2_dpy->buffer_damage &&
2115        dri2_dpy->buffer_damage->set_damage_region)
2116       dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL);
2117
2118    return ret;
2119 }
2120
2121 static EGLBoolean
2122 dri2_set_damage_region(_EGLDisplay *disp, _EGLSurface *surf,
2123                        EGLint *rects, EGLint n_rects)
2124 {
2125    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
2126    __DRIdrawable *drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2127
2128    if (!dri2_dpy->buffer_damage || !dri2_dpy->buffer_damage->set_damage_region) {
2129       mtx_unlock(&dri2_dpy->lock);
2130       return EGL_FALSE;
2131    }
2132
2133    dri2_dpy->buffer_damage->set_damage_region(drawable, n_rects, rects);
2134    mtx_unlock(&dri2_dpy->lock);
2135    return EGL_TRUE;
2136 }
2137
2138 static EGLBoolean
2139 dri2_post_sub_buffer(_EGLDisplay *disp, _EGLSurface *surf,
2140                      EGLint x, EGLint y, EGLint width, EGLint height)
2141 {
2142    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
2143    EGLBoolean ret = EGL_FALSE;
2144
2145    if (dri2_dpy->vtbl->post_sub_buffer)
2146       ret = dri2_dpy->vtbl->post_sub_buffer(disp, surf, x, y, width, height);
2147
2148    mtx_unlock(&dri2_dpy->lock);
2149
2150    return ret;
2151 }
2152
2153 static EGLBoolean
2154 dri2_copy_buffers(_EGLDisplay *disp, _EGLSurface *surf, void *native_pixmap_target)
2155 {
2156    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
2157    if (!dri2_dpy->vtbl->copy_buffers)
2158       return dri2_egl_error_unlock(dri2_dpy, EGL_BAD_NATIVE_PIXMAP, "no support for native pixmaps");
2159    EGLBoolean ret = dri2_dpy->vtbl->copy_buffers(disp, surf, native_pixmap_target);
2160    mtx_unlock(&dri2_dpy->lock);
2161    return ret;
2162 }
2163
2164 static EGLint
2165 dri2_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surf)
2166 {
2167    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2168    if (!dri2_dpy->vtbl->query_buffer_age)
2169       return 0;
2170    return dri2_dpy->vtbl->query_buffer_age(disp, surf);
2171 }
2172
2173 static EGLBoolean
2174 dri2_wait_client(_EGLDisplay *disp, _EGLContext *ctx)
2175 {
2176    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2177    _EGLSurface *surf = ctx->DrawSurface;
2178    __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2179
2180    /* FIXME: If EGL allows frontbuffer rendering for window surfaces,
2181     * we need to copy fake to real here.*/
2182
2183    if (dri2_dpy->flush != NULL)
2184       dri2_dpy->flush->flush(dri_drawable);
2185
2186    return EGL_TRUE;
2187 }
2188
2189 static EGLBoolean
2190 dri2_wait_native(EGLint engine)
2191 {
2192    if (engine != EGL_CORE_NATIVE_ENGINE)
2193       return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
2194    /* glXWaitX(); */
2195
2196    return EGL_TRUE;
2197 }
2198
2199 static EGLBoolean
2200 dri2_bind_tex_image(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
2201 {
2202    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
2203    struct dri2_egl_context *dri2_ctx;
2204    _EGLContext *ctx;
2205    GLint format, target;
2206    __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2207
2208    ctx = _eglGetCurrentContext();
2209    dri2_ctx = dri2_egl_context(ctx);
2210
2211    if (!_eglBindTexImage(disp, surf, buffer)) {
2212       mtx_unlock(&dri2_dpy->lock);
2213       return EGL_FALSE;
2214    }
2215
2216    switch (surf->TextureFormat) {
2217    case EGL_TEXTURE_RGB:
2218       format = __DRI_TEXTURE_FORMAT_RGB;
2219       break;
2220    case EGL_TEXTURE_RGBA:
2221       format = __DRI_TEXTURE_FORMAT_RGBA;
2222       break;
2223    default:
2224       assert(!"Unexpected texture format in dri2_bind_tex_image()");
2225       format = __DRI_TEXTURE_FORMAT_RGBA;
2226    }
2227
2228    switch (surf->TextureTarget) {
2229    case EGL_TEXTURE_2D:
2230       target = GL_TEXTURE_2D;
2231       break;
2232    default:
2233       target = GL_TEXTURE_2D;
2234       assert(!"Unexpected texture target in dri2_bind_tex_image()");
2235    }
2236
2237    dri2_dpy->tex_buffer->setTexBuffer2(dri2_ctx->dri_context,
2238                                        target, format,
2239                                        dri_drawable);
2240
2241    mtx_unlock(&dri2_dpy->lock);
2242
2243    return EGL_TRUE;
2244 }
2245
2246 static EGLBoolean
2247 dri2_release_tex_image(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
2248 {
2249    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
2250    struct dri2_egl_context *dri2_ctx;
2251    _EGLContext *ctx;
2252    GLint  target;
2253    __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2254
2255    ctx = _eglGetCurrentContext();
2256    dri2_ctx = dri2_egl_context(ctx);
2257
2258    if (!_eglReleaseTexImage(disp, surf, buffer)) {
2259       mtx_unlock(&dri2_dpy->lock);
2260       return EGL_FALSE;
2261    }
2262
2263    switch (surf->TextureTarget) {
2264    case EGL_TEXTURE_2D:
2265       target = GL_TEXTURE_2D;
2266       break;
2267    default:
2268       assert(!"missing texture target");
2269    }
2270
2271    if (dri2_dpy->tex_buffer->base.version >= 3 &&
2272        dri2_dpy->tex_buffer->releaseTexBuffer != NULL) {
2273       dri2_dpy->tex_buffer->releaseTexBuffer(dri2_ctx->dri_context,
2274                                              target, dri_drawable);
2275    }
2276
2277    mtx_unlock(&dri2_dpy->lock);
2278
2279    return EGL_TRUE;
2280 }
2281
2282 static _EGLImage*
2283 dri2_create_image(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
2284                   EGLClientBuffer buffer, const EGLint *attr_list)
2285 {
2286    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
2287    _EGLImage *ret = dri2_dpy->vtbl->create_image(disp, ctx, target, buffer,
2288                                                  attr_list);
2289    mtx_unlock(&dri2_dpy->lock);
2290    return ret;
2291 }
2292
2293 _EGLImage *
2294 dri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image)
2295 {
2296    struct dri2_egl_image *dri2_img;
2297
2298    if (dri_image == NULL) {
2299       _eglError(EGL_BAD_ALLOC, "dri2_create_image");
2300       return NULL;
2301    }
2302
2303    dri2_img = malloc(sizeof *dri2_img);
2304    if (!dri2_img) {
2305       _eglError(EGL_BAD_ALLOC, "dri2_create_image");
2306       return NULL;
2307    }
2308
2309    _eglInitImage(&dri2_img->base, disp);
2310
2311    dri2_img->dri_image = dri_image;
2312
2313    return &dri2_img->base;
2314 }
2315
2316 /**
2317  * Translate a DRI Image extension error code into an EGL error code.
2318  */
2319 static EGLint
2320 egl_error_from_dri_image_error(int dri_error)
2321 {
2322    switch (dri_error) {
2323    case __DRI_IMAGE_ERROR_SUCCESS:
2324       return EGL_SUCCESS;
2325    case __DRI_IMAGE_ERROR_BAD_ALLOC:
2326       return EGL_BAD_ALLOC;
2327    case __DRI_IMAGE_ERROR_BAD_MATCH:
2328       return EGL_BAD_MATCH;
2329    case __DRI_IMAGE_ERROR_BAD_PARAMETER:
2330       return EGL_BAD_PARAMETER;
2331    case __DRI_IMAGE_ERROR_BAD_ACCESS:
2332       return EGL_BAD_ACCESS;
2333    default:
2334       assert(!"unknown dri_error code");
2335       return EGL_BAD_ALLOC;
2336    }
2337 }
2338
2339 static _EGLImage *
2340 dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
2341                                    EGLClientBuffer buffer,
2342                                    const EGLint *attr_list)
2343 {
2344    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2345    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
2346    GLuint renderbuffer = (GLuint) (uintptr_t) buffer;
2347    __DRIimage *dri_image;
2348
2349    if (renderbuffer == 0) {
2350       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2351       return EGL_NO_IMAGE_KHR;
2352    }
2353
2354    if (!disp->Extensions.KHR_gl_renderbuffer_image) {
2355       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2356       return EGL_NO_IMAGE_KHR;
2357    }
2358
2359    if (dri2_dpy->image->base.version >= 17 &&
2360        dri2_dpy->image->createImageFromRenderbuffer2) {
2361       unsigned error = ~0;
2362
2363       dri_image = dri2_dpy->image->createImageFromRenderbuffer2(
2364                dri2_ctx->dri_context, renderbuffer, NULL, &error);
2365
2366       assert(!!dri_image == (error == __DRI_IMAGE_ERROR_SUCCESS));
2367
2368       if (!dri_image) {
2369          _eglError(egl_error_from_dri_image_error(error), "dri2_create_image_khr");
2370          return EGL_NO_IMAGE_KHR;
2371       }
2372    } else {
2373       dri_image = dri2_dpy->image->createImageFromRenderbuffer(
2374                dri2_ctx->dri_context, renderbuffer, NULL);
2375       if (!dri_image) {
2376          _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
2377          return EGL_NO_IMAGE_KHR;
2378       }
2379    }
2380
2381    return dri2_create_image_from_dri(disp, dri_image);
2382 }
2383
2384 #ifdef HAVE_WAYLAND_PLATFORM
2385
2386 /* This structure describes how a wl_buffer maps to one or more
2387  * __DRIimages.  A wl_drm_buffer stores the wl_drm format code and the
2388  * offsets and strides of the planes in the buffer.  This table maps a
2389  * wl_drm format code to a description of the planes in the buffer
2390  * that lets us create a __DRIimage for each of the planes. */
2391
2392 static const struct wl_drm_components_descriptor {
2393    uint32_t dri_components;
2394    EGLint components;
2395    int nplanes;
2396 } wl_drm_components[] = {
2397    { __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 },
2398    { __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 },
2399    { __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 },
2400    { __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 },
2401    { __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 },
2402 };
2403
2404 static _EGLImage *
2405 dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
2406                                     EGLClientBuffer _buffer,
2407                                     const EGLint *attr_list)
2408 {
2409    struct wl_drm_buffer *buffer;
2410    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2411    const struct wl_drm_components_descriptor *f;
2412    __DRIimage *dri_image;
2413    _EGLImageAttribs attrs;
2414    int32_t plane;
2415
2416    buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm,
2417                                    (struct wl_resource *) _buffer);
2418    if (!buffer)
2419        return NULL;
2420
2421    if (!_eglParseImageAttribList(&attrs, disp, attr_list))
2422       return NULL;
2423
2424    plane = attrs.PlaneWL;
2425    f = buffer->driver_format;
2426    if (plane < 0 || plane >= f->nplanes) {
2427       _eglError(EGL_BAD_PARAMETER,
2428                 "dri2_create_image_wayland_wl_buffer (plane out of bounds)");
2429       return NULL;
2430    }
2431
2432    dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL);
2433    if (dri_image == NULL && plane == 0)
2434       dri_image = dri2_dpy->image->dupImage(buffer->driver_buffer, NULL);
2435    if (dri_image == NULL) {
2436       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
2437       return NULL;
2438    }
2439
2440    return dri2_create_image_from_dri(disp, dri_image);
2441 }
2442 #endif
2443
2444 static EGLBoolean
2445 dri2_get_sync_values_chromium(_EGLDisplay *disp, _EGLSurface *surf,
2446                               EGLuint64KHR *ust, EGLuint64KHR *msc,
2447                               EGLuint64KHR *sbc)
2448 {
2449    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2450    EGLBoolean ret = EGL_FALSE;
2451
2452    if (dri2_dpy->vtbl->get_sync_values)
2453       ret = dri2_dpy->vtbl->get_sync_values(disp, surf, ust, msc, sbc);
2454
2455    mtx_unlock(&dri2_dpy->lock);
2456
2457    return ret;
2458 }
2459
2460 static EGLBoolean
2461 dri2_get_msc_rate_angle(_EGLDisplay *disp, _EGLSurface *surf,
2462                         EGLint *numerator, EGLint *denominator)
2463 {
2464    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2465    if (!dri2_dpy->vtbl->get_msc_rate)
2466       return EGL_FALSE;
2467    return dri2_dpy->vtbl->get_msc_rate(disp, surf, numerator, denominator);
2468 }
2469
2470 /**
2471  * Set the error code after a call to
2472  * dri2_egl_image::dri_image::createImageFromTexture.
2473  */
2474 static void
2475 dri2_create_image_khr_texture_error(int dri_error)
2476 {
2477    EGLint egl_error = egl_error_from_dri_image_error(dri_error);
2478
2479    if (egl_error != EGL_SUCCESS)
2480       _eglError(egl_error, "dri2_create_image_khr_texture");
2481 }
2482
2483 static _EGLImage *
2484 dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
2485                                    EGLenum target,
2486                                    EGLClientBuffer buffer,
2487                                    const EGLint *attr_list)
2488 {
2489    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2490    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
2491    struct dri2_egl_image *dri2_img;
2492    GLuint texture = (GLuint) (uintptr_t) buffer;
2493    _EGLImageAttribs attrs;
2494    GLuint depth;
2495    GLenum gl_target;
2496    unsigned error;
2497
2498    if (texture == 0) {
2499       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2500       return EGL_NO_IMAGE_KHR;
2501    }
2502
2503    if (!_eglParseImageAttribList(&attrs, disp, attr_list))
2504       return EGL_NO_IMAGE_KHR;
2505
2506    switch (target) {
2507    case EGL_GL_TEXTURE_2D_KHR:
2508       if (!disp->Extensions.KHR_gl_texture_2D_image) {
2509          _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2510          return EGL_NO_IMAGE_KHR;
2511       }
2512       depth = 0;
2513       gl_target = GL_TEXTURE_2D;
2514       break;
2515    case EGL_GL_TEXTURE_3D_KHR:
2516       if (!disp->Extensions.KHR_gl_texture_3D_image) {
2517          _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2518          return EGL_NO_IMAGE_KHR;
2519       }
2520
2521       depth = attrs.GLTextureZOffset;
2522       gl_target = GL_TEXTURE_3D;
2523       break;
2524    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
2525    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
2526    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
2527    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
2528    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
2529    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
2530       if (!disp->Extensions.KHR_gl_texture_cubemap_image) {
2531          _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2532          return EGL_NO_IMAGE_KHR;
2533       }
2534
2535       depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
2536       gl_target = GL_TEXTURE_CUBE_MAP;
2537       break;
2538    default:
2539       unreachable("Unexpected target in dri2_create_image_khr_texture()");
2540       return EGL_NO_IMAGE_KHR;
2541    }
2542
2543    dri2_img = malloc(sizeof *dri2_img);
2544    if (!dri2_img) {
2545       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
2546       return EGL_NO_IMAGE_KHR;
2547    }
2548
2549    _eglInitImage(&dri2_img->base, disp);
2550
2551    dri2_img->dri_image =
2552       dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context,
2553                                               gl_target,
2554                                               texture,
2555                                               depth,
2556                                               attrs.GLTextureLevel,
2557                                               &error,
2558                                               NULL);
2559    dri2_create_image_khr_texture_error(error);
2560
2561    if (!dri2_img->dri_image) {
2562       free(dri2_img);
2563       return EGL_NO_IMAGE_KHR;
2564    }
2565    return &dri2_img->base;
2566 }
2567
2568 static EGLBoolean
2569 dri2_query_surface(_EGLDisplay *disp, _EGLSurface *surf,
2570                    EGLint attribute, EGLint *value)
2571 {
2572    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2573    EGLBoolean ret;
2574
2575    if (!dri2_dpy->vtbl->query_surface) {
2576       ret = _eglQuerySurface(disp, surf, attribute, value);
2577    } else {
2578       ret = dri2_dpy->vtbl->query_surface(disp, surf, attribute, value);
2579    }
2580
2581    mtx_unlock(&dri2_dpy->lock);
2582
2583    return ret;
2584 }
2585
2586 static struct wl_buffer*
2587 dri2_create_wayland_buffer_from_image(_EGLDisplay *disp, _EGLImage *img)
2588 {
2589    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
2590    struct wl_buffer *ret = NULL;
2591
2592    if (dri2_dpy->vtbl->create_wayland_buffer_from_image)
2593       ret = dri2_dpy->vtbl->create_wayland_buffer_from_image(disp, img);
2594
2595    mtx_unlock(&dri2_dpy->lock);
2596
2597    return ret;
2598 }
2599
2600 #ifdef HAVE_LIBDRM
2601 static _EGLImage *
2602 dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
2603                                   EGLClientBuffer buffer, const EGLint *attr_list)
2604 {
2605    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2606    EGLint format, name, pitch;
2607    _EGLImageAttribs attrs;
2608    __DRIimage *dri_image;
2609
2610    name = (EGLint) (uintptr_t) buffer;
2611
2612    if (!_eglParseImageAttribList(&attrs, disp, attr_list))
2613       return NULL;
2614
2615    if (attrs.Width <= 0 || attrs.Height <= 0 ||
2616        attrs.DRMBufferStrideMESA <= 0) {
2617       _eglError(EGL_BAD_PARAMETER,
2618                 "bad width, height or stride");
2619       return NULL;
2620    }
2621
2622    switch (attrs.DRMBufferFormatMESA) {
2623    case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
2624       format = __DRI_IMAGE_FORMAT_ARGB8888;
2625       pitch = attrs.DRMBufferStrideMESA;
2626       break;
2627    default:
2628       _eglError(EGL_BAD_PARAMETER,
2629                 "dri2_create_image_khr: unsupported pixmap depth");
2630       return NULL;
2631    }
2632
2633    dri_image =
2634       dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
2635                                            attrs.Width,
2636                                            attrs.Height,
2637                                            format,
2638                                            name,
2639                                            pitch,
2640                                            NULL);
2641
2642    return dri2_create_image_from_dri(disp, dri_image);
2643 }
2644
2645 static EGLBoolean
2646 dri2_check_dma_buf_attribs(const _EGLImageAttribs *attrs)
2647 {
2648    /**
2649      * The spec says:
2650      *
2651      * "Required attributes and their values are as follows:
2652      *
2653      *  * EGL_WIDTH & EGL_HEIGHT: The logical dimensions of the buffer in pixels
2654      *
2655      *  * EGL_LINUX_DRM_FOURCC_EXT: The pixel format of the buffer, as specified
2656      *    by drm_fourcc.h and used as the pixel_format parameter of the
2657      *    drm_mode_fb_cmd2 ioctl."
2658      *
2659      * and
2660      *
2661      * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is
2662      *    incomplete, EGL_BAD_PARAMETER is generated."
2663      */
2664    if (attrs->Width <= 0 || attrs->Height <= 0 ||
2665        !attrs->DMABufFourCC.IsPresent)
2666       return _eglError(EGL_BAD_PARAMETER, "attribute(s) missing");
2667
2668    /**
2669     * Also:
2670     *
2671     * "If <target> is EGL_LINUX_DMA_BUF_EXT and one or more of the values
2672     *  specified for a plane's pitch or offset isn't supported by EGL,
2673     *  EGL_BAD_ACCESS is generated."
2674     */
2675    for (unsigned i = 0; i < ARRAY_SIZE(attrs->DMABufPlanePitches); ++i) {
2676       if (attrs->DMABufPlanePitches[i].IsPresent &&
2677           attrs->DMABufPlanePitches[i].Value <= 0)
2678          return _eglError(EGL_BAD_ACCESS, "invalid pitch");
2679    }
2680
2681    /**
2682     * If <target> is EGL_LINUX_DMA_BUF_EXT, both or neither of the following
2683     * attribute values may be given.
2684     *
2685     * This is referring to EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT and
2686     * EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, and the same for other planes.
2687     */
2688    for (unsigned i = 0; i < DMA_BUF_MAX_PLANES; ++i) {
2689       if (attrs->DMABufPlaneModifiersLo[i].IsPresent !=
2690           attrs->DMABufPlaneModifiersHi[i].IsPresent)
2691          return _eglError(EGL_BAD_PARAMETER, "modifier attribute lo or hi missing");
2692    }
2693
2694    /* Although the EGL_EXT_image_dma_buf_import_modifiers spec doesn't
2695     * mandate it, we only accept the same modifier across all planes. */
2696    for (unsigned i = 1; i < DMA_BUF_MAX_PLANES; ++i) {
2697       if (attrs->DMABufPlaneFds[i].IsPresent) {
2698          if ((attrs->DMABufPlaneModifiersLo[0].IsPresent !=
2699                attrs->DMABufPlaneModifiersLo[i].IsPresent) ||
2700              (attrs->DMABufPlaneModifiersLo[0].Value !=
2701                attrs->DMABufPlaneModifiersLo[i].Value) ||
2702              (attrs->DMABufPlaneModifiersHi[0].Value !=
2703                attrs->DMABufPlaneModifiersHi[i].Value))
2704             return _eglError(EGL_BAD_PARAMETER, "modifier attributes not equal");
2705       }
2706    }
2707
2708    return EGL_TRUE;
2709 }
2710
2711 /* Returns the total number of planes for the format or zero if it isn't a
2712  * valid fourcc format.
2713  */
2714 static unsigned
2715 dri2_num_fourcc_format_planes(EGLint format)
2716 {
2717    switch (format) {
2718    case DRM_FORMAT_R8:
2719    case DRM_FORMAT_RG88:
2720    case DRM_FORMAT_GR88:
2721    case DRM_FORMAT_R16:
2722    case DRM_FORMAT_GR1616:
2723    case DRM_FORMAT_RGB332:
2724    case DRM_FORMAT_BGR233:
2725    case DRM_FORMAT_XRGB4444:
2726    case DRM_FORMAT_XBGR4444:
2727    case DRM_FORMAT_RGBX4444:
2728    case DRM_FORMAT_BGRX4444:
2729    case DRM_FORMAT_ARGB4444:
2730    case DRM_FORMAT_ABGR4444:
2731    case DRM_FORMAT_RGBA4444:
2732    case DRM_FORMAT_BGRA4444:
2733    case DRM_FORMAT_XRGB1555:
2734    case DRM_FORMAT_XBGR1555:
2735    case DRM_FORMAT_RGBX5551:
2736    case DRM_FORMAT_BGRX5551:
2737    case DRM_FORMAT_ARGB1555:
2738    case DRM_FORMAT_ABGR1555:
2739    case DRM_FORMAT_RGBA5551:
2740    case DRM_FORMAT_BGRA5551:
2741    case DRM_FORMAT_RGB565:
2742    case DRM_FORMAT_BGR565:
2743    case DRM_FORMAT_RGB888:
2744    case DRM_FORMAT_BGR888:
2745    case DRM_FORMAT_XRGB8888:
2746    case DRM_FORMAT_XBGR8888:
2747    case DRM_FORMAT_RGBX8888:
2748    case DRM_FORMAT_BGRX8888:
2749    case DRM_FORMAT_ARGB8888:
2750    case DRM_FORMAT_ABGR8888:
2751    case DRM_FORMAT_RGBA8888:
2752    case DRM_FORMAT_BGRA8888:
2753    case DRM_FORMAT_XRGB2101010:
2754    case DRM_FORMAT_XBGR2101010:
2755    case DRM_FORMAT_RGBX1010102:
2756    case DRM_FORMAT_BGRX1010102:
2757    case DRM_FORMAT_ARGB2101010:
2758    case DRM_FORMAT_ABGR2101010:
2759    case DRM_FORMAT_RGBA1010102:
2760    case DRM_FORMAT_BGRA1010102:
2761    case DRM_FORMAT_ABGR16161616:
2762    case DRM_FORMAT_XBGR16161616:
2763    case DRM_FORMAT_XBGR16161616F:
2764    case DRM_FORMAT_ABGR16161616F:
2765    case DRM_FORMAT_YUYV:
2766    case DRM_FORMAT_YVYU:
2767    case DRM_FORMAT_UYVY:
2768    case DRM_FORMAT_VYUY:
2769    case DRM_FORMAT_AYUV:
2770    case DRM_FORMAT_XYUV8888:
2771    case DRM_FORMAT_Y210:
2772    case DRM_FORMAT_Y212:
2773    case DRM_FORMAT_Y216:
2774    case DRM_FORMAT_Y410:
2775    case DRM_FORMAT_Y412:
2776    case DRM_FORMAT_Y416:
2777       return 1;
2778
2779    case DRM_FORMAT_NV12:
2780    case DRM_FORMAT_NV21:
2781    case DRM_FORMAT_NV16:
2782    case DRM_FORMAT_NV61:
2783    case DRM_FORMAT_P010:
2784    case DRM_FORMAT_P012:
2785    case DRM_FORMAT_P016:
2786       return 2;
2787
2788    case DRM_FORMAT_YUV410:
2789    case DRM_FORMAT_YVU410:
2790    case DRM_FORMAT_YUV411:
2791    case DRM_FORMAT_YVU411:
2792    case DRM_FORMAT_YUV420:
2793    case DRM_FORMAT_YVU420:
2794    case DRM_FORMAT_YUV422:
2795    case DRM_FORMAT_YVU422:
2796    case DRM_FORMAT_YUV444:
2797    case DRM_FORMAT_YVU444:
2798       return 3;
2799
2800    default:
2801       return 0;
2802    }
2803 }
2804
2805 /* Returns the total number of file descriptors. Zero indicates an error. */
2806 static unsigned
2807 dri2_check_dma_buf_format(const _EGLImageAttribs *attrs)
2808 {
2809    unsigned plane_n = dri2_num_fourcc_format_planes(attrs->DMABufFourCC.Value);
2810    if (plane_n == 0) {
2811       _eglError(EGL_BAD_MATCH, "unknown drm fourcc format");
2812       return 0;
2813    }
2814
2815    for (unsigned i = plane_n; i < DMA_BUF_MAX_PLANES; i++) {
2816       /**
2817        * The modifiers extension spec says:
2818        *
2819        * "Modifiers may modify any attribute of a buffer import, including
2820        *  but not limited to adding extra planes to a format which
2821        *  otherwise does not have those planes. As an example, a modifier
2822        *  may add a plane for an external compression buffer to a
2823        *  single-plane format. The exact meaning and effect of any
2824        *  modifier is canonically defined by drm_fourcc.h, not as part of
2825        *  this extension."
2826        */
2827       if (attrs->DMABufPlaneModifiersLo[i].IsPresent &&
2828           attrs->DMABufPlaneModifiersHi[i].IsPresent) {
2829          plane_n = i + 1;
2830       }
2831    }
2832
2833    /**
2834      * The spec says:
2835      *
2836      * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is
2837      *    incomplete, EGL_BAD_PARAMETER is generated."
2838      */
2839    for (unsigned i = 0; i < plane_n; ++i) {
2840       if (!attrs->DMABufPlaneFds[i].IsPresent ||
2841           !attrs->DMABufPlaneOffsets[i].IsPresent ||
2842           !attrs->DMABufPlanePitches[i].IsPresent) {
2843          _eglError(EGL_BAD_PARAMETER, "plane attribute(s) missing");
2844          return 0;
2845       }
2846    }
2847
2848    /**
2849     * The spec also says:
2850     *
2851     * "If <target> is EGL_LINUX_DMA_BUF_EXT, and the EGL_LINUX_DRM_FOURCC_EXT
2852     *  attribute indicates a single-plane format, EGL_BAD_ATTRIBUTE is
2853     *  generated if any of the EGL_DMA_BUF_PLANE1_* or EGL_DMA_BUF_PLANE2_*
2854     *  or EGL_DMA_BUF_PLANE3_* attributes are specified."
2855     */
2856    for (unsigned i = plane_n; i < DMA_BUF_MAX_PLANES; ++i) {
2857       if (attrs->DMABufPlaneFds[i].IsPresent ||
2858           attrs->DMABufPlaneOffsets[i].IsPresent ||
2859           attrs->DMABufPlanePitches[i].IsPresent) {
2860          _eglError(EGL_BAD_ATTRIBUTE, "too many plane attributes");
2861          return 0;
2862       }
2863    }
2864
2865    return plane_n;
2866 }
2867
2868 static EGLBoolean
2869 dri2_query_dma_buf_formats(_EGLDisplay *disp, EGLint max,
2870                            EGLint *formats, EGLint *count)
2871 {
2872    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
2873    if (max < 0 || (max > 0 && formats == NULL)) {
2874       _eglError(EGL_BAD_PARAMETER, "invalid value for max count of formats");
2875       goto fail;
2876    }
2877
2878    if (dri2_dpy->image->base.version < 15 ||
2879        dri2_dpy->image->queryDmaBufFormats == NULL)
2880       goto fail;
2881
2882    if (!dri2_dpy->image->queryDmaBufFormats(dri2_dpy->dri_screen, max,
2883                                             formats, count))
2884       goto fail;
2885
2886    if (max > 0) {
2887       /* Assert that all of the formats returned are actually fourcc formats.
2888        * Some day, if we want the internal interface function to be able to
2889        * return the fake fourcc formats defined in dri_interface.h, we'll have
2890        * to do something more clever here to pair the list down to just real
2891        * fourcc formats so that we don't leak the fake internal ones.
2892        */
2893       for (int i = 0; i < *count; i++) {
2894          assert(dri2_num_fourcc_format_planes(formats[i]) > 0);
2895       }
2896    }
2897
2898    mtx_unlock(&dri2_dpy->lock);
2899
2900    return EGL_TRUE;
2901
2902 fail:
2903    mtx_unlock(&dri2_dpy->lock);
2904    return EGL_FALSE;
2905 }
2906
2907 static EGLBoolean
2908 dri2_query_dma_buf_modifiers(_EGLDisplay *disp, EGLint format,
2909                              EGLint max, EGLuint64KHR *modifiers,
2910                              EGLBoolean *external_only, EGLint *count)
2911 {
2912    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
2913
2914    if (dri2_num_fourcc_format_planes(format) == 0)
2915       return dri2_egl_error_unlock(dri2_dpy, EGL_BAD_PARAMETER, "invalid fourcc format");
2916
2917    if (max < 0)
2918       return dri2_egl_error_unlock(dri2_dpy, EGL_BAD_PARAMETER, "invalid value for max count of formats");
2919
2920    if (max > 0 && modifiers == NULL)
2921       return dri2_egl_error_unlock(dri2_dpy, EGL_BAD_PARAMETER, "invalid modifiers array");
2922
2923    if (dri2_dpy->image->base.version < 15 ||
2924        dri2_dpy->image->queryDmaBufModifiers == NULL) {
2925       mtx_unlock(&dri2_dpy->lock);
2926       return EGL_FALSE;
2927    }
2928
2929    if (dri2_dpy->image->queryDmaBufModifiers(dri2_dpy->dri_screen, format,
2930                                              max, modifiers,
2931                                              (unsigned int *) external_only,
2932                                              count) == false)
2933       return dri2_egl_error_unlock(dri2_dpy, EGL_BAD_PARAMETER, "invalid format");
2934
2935    mtx_unlock(&dri2_dpy->lock);
2936
2937    return EGL_TRUE;
2938 }
2939
2940 /**
2941  * The spec says:
2942  *
2943  * "If eglCreateImageKHR is successful for a EGL_LINUX_DMA_BUF_EXT target, the
2944  *  EGL will take a reference to the dma_buf(s) which it will release at any
2945  *  time while the EGLDisplay is initialized. It is the responsibility of the
2946  *  application to close the dma_buf file descriptors."
2947  *
2948  * Therefore we must never close or otherwise modify the file descriptors.
2949  */
2950 _EGLImage *
2951 dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
2952                           EGLClientBuffer buffer, const EGLint *attr_list)
2953 {
2954    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2955    _EGLImage *res;
2956    _EGLImageAttribs attrs;
2957    __DRIimage *dri_image;
2958    unsigned num_fds;
2959    int fds[DMA_BUF_MAX_PLANES];
2960    int pitches[DMA_BUF_MAX_PLANES];
2961    int offsets[DMA_BUF_MAX_PLANES];
2962    uint64_t modifier;
2963    bool has_modifier = false;
2964    unsigned error;
2965    EGLint egl_error;
2966
2967    /**
2968     * The spec says:
2969     *
2970     * ""* If <target> is EGL_LINUX_DMA_BUF_EXT and <buffer> is not NULL, the
2971     *     error EGL_BAD_PARAMETER is generated."
2972     */
2973    if (buffer != NULL) {
2974       _eglError(EGL_BAD_PARAMETER, "buffer not NULL");
2975       return NULL;
2976    }
2977
2978    if (!_eglParseImageAttribList(&attrs, disp, attr_list))
2979       return NULL;
2980
2981    if (!dri2_check_dma_buf_attribs(&attrs))
2982       return NULL;
2983
2984    num_fds = dri2_check_dma_buf_format(&attrs);
2985    if (!num_fds)
2986       return NULL;
2987
2988    for (unsigned i = 0; i < num_fds; ++i) {
2989       fds[i] = attrs.DMABufPlaneFds[i].Value;
2990       pitches[i] = attrs.DMABufPlanePitches[i].Value;
2991       offsets[i] = attrs.DMABufPlaneOffsets[i].Value;
2992    }
2993
2994    /* dri2_check_dma_buf_attribs ensures that the modifier, if available,
2995     * will be present in attrs.DMABufPlaneModifiersLo[0] and
2996     * attrs.DMABufPlaneModifiersHi[0] */
2997    if (attrs.DMABufPlaneModifiersLo[0].IsPresent) {
2998       modifier = combine_u32_into_u64(attrs.DMABufPlaneModifiersHi[0].Value,
2999                                       attrs.DMABufPlaneModifiersLo[0].Value);
3000       has_modifier = true;
3001    }
3002
3003    if (attrs.ProtectedContent) {
3004       if (dri2_dpy->image->base.version < 18 ||
3005           dri2_dpy->image->createImageFromDmaBufs3 == NULL) {
3006          _eglError(EGL_BAD_MATCH, "unsupported protected_content attribute");
3007          return EGL_NO_IMAGE_KHR;
3008       }
3009       if (!has_modifier)
3010          modifier = DRM_FORMAT_MOD_INVALID;
3011
3012       dri_image =
3013          dri2_dpy->image->createImageFromDmaBufs3(dri2_dpy->dri_screen,
3014             attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
3015             modifier, fds, num_fds, pitches, offsets,
3016             attrs.DMABufYuvColorSpaceHint.Value,
3017             attrs.DMABufSampleRangeHint.Value,
3018             attrs.DMABufChromaHorizontalSiting.Value,
3019             attrs.DMABufChromaVerticalSiting.Value,
3020             attrs.ProtectedContent ? __DRI_IMAGE_PROTECTED_CONTENT_FLAG : 0,
3021             &error,
3022             NULL);
3023    }
3024    else if (has_modifier) {
3025       if (dri2_dpy->image->base.version < 15 ||
3026           dri2_dpy->image->createImageFromDmaBufs2 == NULL) {
3027          _eglError(EGL_BAD_MATCH, "unsupported dma_buf format modifier");
3028          return EGL_NO_IMAGE_KHR;
3029       }
3030       dri_image =
3031          dri2_dpy->image->createImageFromDmaBufs2(dri2_dpy->dri_screen,
3032             attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
3033             modifier, fds, num_fds, pitches, offsets,
3034             attrs.DMABufYuvColorSpaceHint.Value,
3035             attrs.DMABufSampleRangeHint.Value,
3036             attrs.DMABufChromaHorizontalSiting.Value,
3037             attrs.DMABufChromaVerticalSiting.Value,
3038             &error,
3039             NULL);
3040    }
3041    else {
3042       dri_image =
3043          dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen,
3044             attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
3045             fds, num_fds, pitches, offsets,
3046             attrs.DMABufYuvColorSpaceHint.Value,
3047             attrs.DMABufSampleRangeHint.Value,
3048             attrs.DMABufChromaHorizontalSiting.Value,
3049             attrs.DMABufChromaVerticalSiting.Value,
3050             &error,
3051             NULL);
3052    }
3053
3054    egl_error = egl_error_from_dri_image_error(error);
3055    if (egl_error != EGL_SUCCESS)
3056       _eglError(egl_error, "createImageFromDmaBufs failed");
3057
3058    if (!dri_image)
3059       return EGL_NO_IMAGE_KHR;
3060
3061    res = dri2_create_image_from_dri(disp, dri_image);
3062
3063    return res;
3064 }
3065 static _EGLImage *
3066 dri2_create_drm_image_mesa(_EGLDisplay *disp, const EGLint *attr_list)
3067 {
3068    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
3069    struct dri2_egl_image *dri2_img;
3070    _EGLImageAttribs attrs;
3071    unsigned int dri_use, valid_mask;
3072    int format;
3073
3074    if (!attr_list) {
3075       _eglError(EGL_BAD_PARAMETER, __func__);
3076       goto fail;
3077    }
3078
3079    if (!_eglParseImageAttribList(&attrs, disp, attr_list))
3080       goto fail;
3081
3082    if (attrs.Width <= 0 || attrs.Height <= 0) {
3083       _eglError(EGL_BAD_PARAMETER, __func__);
3084       goto fail;
3085    }
3086
3087    switch (attrs.DRMBufferFormatMESA) {
3088    case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
3089       format = __DRI_IMAGE_FORMAT_ARGB8888;
3090       break;
3091    default:
3092       _eglError(EGL_BAD_PARAMETER, __func__);
3093       goto fail;
3094    }
3095
3096    valid_mask =
3097       EGL_DRM_BUFFER_USE_SCANOUT_MESA |
3098       EGL_DRM_BUFFER_USE_SHARE_MESA |
3099       EGL_DRM_BUFFER_USE_CURSOR_MESA;
3100    if (attrs.DRMBufferUseMESA & ~valid_mask) {
3101       _eglError(EGL_BAD_PARAMETER, __func__);
3102       goto fail;
3103    }
3104
3105    dri_use = 0;
3106    if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA)
3107       dri_use |= __DRI_IMAGE_USE_SHARE;
3108    if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
3109       dri_use |= __DRI_IMAGE_USE_SCANOUT;
3110    if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA)
3111       dri_use |= __DRI_IMAGE_USE_CURSOR;
3112
3113    dri2_img = malloc(sizeof *dri2_img);
3114    if (!dri2_img) {
3115       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
3116       goto fail;
3117    }
3118
3119    _eglInitImage(&dri2_img->base, disp);
3120
3121    dri2_img->dri_image =
3122       dri2_dpy->image->createImage(dri2_dpy->dri_screen,
3123                                    attrs.Width, attrs.Height,
3124                                    format, dri_use, dri2_img);
3125    if (dri2_img->dri_image == NULL) {
3126       free(dri2_img);
3127       _eglError(EGL_BAD_ALLOC, "dri2_create_drm_image_mesa");
3128       goto fail;
3129    }
3130
3131    mtx_unlock(&dri2_dpy->lock);
3132
3133    return &dri2_img->base;
3134
3135 fail:
3136    mtx_unlock(&dri2_dpy->lock);
3137    return EGL_NO_IMAGE_KHR;
3138 }
3139
3140 static EGLBoolean
3141 dri2_export_drm_image_mesa(_EGLDisplay *disp, _EGLImage *img,
3142                           EGLint *name, EGLint *handle, EGLint *stride)
3143 {
3144    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
3145    struct dri2_egl_image *dri2_img = dri2_egl_image(img);
3146
3147    if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image,
3148                                             __DRI_IMAGE_ATTRIB_NAME, name))
3149       return _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa");
3150
3151    if (handle)
3152       dri2_dpy->image->queryImage(dri2_img->dri_image,
3153                                   __DRI_IMAGE_ATTRIB_HANDLE, handle);
3154
3155    if (stride)
3156       dri2_dpy->image->queryImage(dri2_img->dri_image,
3157                                   __DRI_IMAGE_ATTRIB_STRIDE, stride);
3158
3159    mtx_unlock(&dri2_dpy->lock);
3160
3161    return EGL_TRUE;
3162 }
3163
3164 /**
3165  * Checks if we can support EGL_MESA_image_dma_buf_export on this image.
3166
3167  * The spec provides a boolean return for the driver to reject exporting for
3168  * basically any reason, but doesn't specify any particular error cases.  For
3169  * now, we just fail if we don't have a DRM fourcc for the format.
3170  */
3171 static bool
3172 dri2_can_export_dma_buf_image(_EGLDisplay *disp, _EGLImage *img)
3173 {
3174    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3175    struct dri2_egl_image *dri2_img = dri2_egl_image(img);
3176    EGLint fourcc;
3177
3178    if (!dri2_dpy->image->queryImage(dri2_img->dri_image,
3179                                     __DRI_IMAGE_ATTRIB_FOURCC, &fourcc)) {
3180       return false;
3181    }
3182
3183    return true;
3184 }
3185
3186 static EGLBoolean
3187 dri2_export_dma_buf_image_query_mesa(_EGLDisplay *disp, _EGLImage *img,
3188                                      EGLint *fourcc, EGLint *nplanes,
3189                                      EGLuint64KHR *modifiers)
3190 {
3191    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
3192    struct dri2_egl_image *dri2_img = dri2_egl_image(img);
3193    int num_planes;
3194
3195    if (!dri2_can_export_dma_buf_image(disp, img)) {
3196       mtx_unlock(&dri2_dpy->lock);
3197       return EGL_FALSE;
3198    }
3199
3200    dri2_dpy->image->queryImage(dri2_img->dri_image,
3201                                __DRI_IMAGE_ATTRIB_NUM_PLANES, &num_planes);
3202    if (nplanes)
3203      *nplanes = num_planes;
3204
3205    if (fourcc)
3206       dri2_dpy->image->queryImage(dri2_img->dri_image,
3207                                   __DRI_IMAGE_ATTRIB_FOURCC, fourcc);
3208
3209    if (modifiers) {
3210       int mod_hi, mod_lo;
3211       uint64_t modifier = DRM_FORMAT_MOD_INVALID;
3212       bool query;
3213
3214       query = dri2_dpy->image->queryImage(dri2_img->dri_image,
3215                                           __DRI_IMAGE_ATTRIB_MODIFIER_UPPER,
3216                                           &mod_hi);
3217       query &= dri2_dpy->image->queryImage(dri2_img->dri_image,
3218                                            __DRI_IMAGE_ATTRIB_MODIFIER_LOWER,
3219                                            &mod_lo);
3220       if (query)
3221          modifier = combine_u32_into_u64 (mod_hi, mod_lo);
3222
3223       for (int i = 0; i < num_planes; i++)
3224         modifiers[i] = modifier;
3225    }
3226
3227    mtx_unlock(&dri2_dpy->lock);
3228
3229    return EGL_TRUE;
3230 }
3231
3232 static EGLBoolean
3233 dri2_export_dma_buf_image_mesa(_EGLDisplay *disp, _EGLImage *img,
3234                                int *fds, EGLint *strides, EGLint *offsets)
3235 {
3236    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
3237    struct dri2_egl_image *dri2_img = dri2_egl_image(img);
3238    EGLint nplanes;
3239
3240    if (!dri2_can_export_dma_buf_image(disp, img))
3241       return EGL_FALSE;
3242
3243    /* EGL_MESA_image_dma_buf_export spec says:
3244     *    "If the number of fds is less than the number of planes, then
3245     *    subsequent fd slots should contain -1."
3246     */
3247    if (fds) {
3248       /* Query nplanes so that we know how big the given array is. */
3249       dri2_dpy->image->queryImage(dri2_img->dri_image,
3250                                   __DRI_IMAGE_ATTRIB_NUM_PLANES, &nplanes);
3251       memset(fds, -1, nplanes * sizeof(int));
3252    }
3253
3254    /* rework later to provide multiple fds/strides/offsets */
3255    if (fds)
3256       dri2_dpy->image->queryImage(dri2_img->dri_image,
3257                                   __DRI_IMAGE_ATTRIB_FD, fds);
3258
3259    if (strides)
3260       dri2_dpy->image->queryImage(dri2_img->dri_image,
3261                                   __DRI_IMAGE_ATTRIB_STRIDE, strides);
3262
3263    if (offsets) {
3264       int img_offset;
3265       bool ret = dri2_dpy->image->queryImage(dri2_img->dri_image,
3266                      __DRI_IMAGE_ATTRIB_OFFSET, &img_offset);
3267       if (ret)
3268          offsets[0] = img_offset;
3269       else
3270          offsets[0] = 0;
3271    }
3272
3273    mtx_unlock(&dri2_dpy->lock);
3274
3275    return EGL_TRUE;
3276 }
3277
3278 #endif
3279
3280 _EGLImage *
3281 dri2_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
3282                       EGLClientBuffer buffer, const EGLint *attr_list)
3283 {
3284    switch (target) {
3285    case EGL_GL_TEXTURE_2D_KHR:
3286    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
3287    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
3288    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
3289    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
3290    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
3291    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
3292    case EGL_GL_TEXTURE_3D_KHR:
3293       return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
3294    case EGL_GL_RENDERBUFFER_KHR:
3295       return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
3296 #ifdef HAVE_LIBDRM
3297    case EGL_DRM_BUFFER_MESA:
3298       return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
3299    case EGL_LINUX_DMA_BUF_EXT:
3300       return dri2_create_image_dma_buf(disp, ctx, buffer, attr_list);
3301 #endif
3302 #ifdef HAVE_WAYLAND_PLATFORM
3303    case EGL_WAYLAND_BUFFER_WL:
3304       return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
3305 #endif
3306    default:
3307       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
3308       return EGL_NO_IMAGE_KHR;
3309    }
3310 }
3311
3312 static EGLBoolean
3313 dri2_destroy_image_khr(_EGLDisplay *disp, _EGLImage *image)
3314 {
3315    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
3316    struct dri2_egl_image *dri2_img = dri2_egl_image(image);
3317
3318    dri2_dpy->image->destroyImage(dri2_img->dri_image);
3319    free(dri2_img);
3320
3321    mtx_unlock(&dri2_dpy->lock);
3322
3323    return EGL_TRUE;
3324 }
3325
3326 #ifdef HAVE_WAYLAND_PLATFORM
3327
3328 static void
3329 dri2_wl_reference_buffer(void *user_data, uint32_t name, int fd,
3330                          struct wl_drm_buffer *buffer)
3331 {
3332    _EGLDisplay *disp = user_data;
3333    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3334    __DRIimage *img;
3335    int dri_components = 0;
3336
3337    if (fd == -1)
3338       img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen,
3339                                                   buffer->width,
3340                                                   buffer->height,
3341                                                   buffer->format,
3342                                                   (int*)&name, 1,
3343                                                   buffer->stride,
3344                                                   buffer->offset,
3345                                                   NULL);
3346    else
3347       img = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
3348                                                 buffer->width,
3349                                                 buffer->height,
3350                                                 buffer->format,
3351                                                 &fd, 1,
3352                                                 buffer->stride,
3353                                                 buffer->offset,
3354                                                 NULL);
3355
3356    if (img == NULL)
3357       return;
3358
3359    dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components);
3360
3361    buffer->driver_format = NULL;
3362    for (int i = 0; i < ARRAY_SIZE(wl_drm_components); i++)
3363       if (wl_drm_components[i].dri_components == dri_components)
3364          buffer->driver_format = &wl_drm_components[i];
3365
3366    if (buffer->driver_format == NULL)
3367       dri2_dpy->image->destroyImage(img);
3368    else
3369       buffer->driver_buffer = img;
3370 }
3371
3372 static void
3373 dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer)
3374 {
3375    _EGLDisplay *disp = user_data;
3376    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3377
3378    dri2_dpy->image->destroyImage(buffer->driver_buffer);
3379 }
3380
3381 static EGLBoolean
3382 dri2_bind_wayland_display_wl(_EGLDisplay *disp, struct wl_display *wl_dpy)
3383 {
3384    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
3385    const struct wayland_drm_callbacks wl_drm_callbacks = {
3386       .authenticate = (int(*)(void *, uint32_t)) dri2_dpy->vtbl->authenticate,
3387       .reference_buffer = dri2_wl_reference_buffer,
3388       .release_buffer = dri2_wl_release_buffer,
3389       .is_format_supported = dri2_wl_is_format_supported
3390    };
3391    int flags = 0;
3392    char *device_name;
3393    uint64_t cap;
3394
3395    if (dri2_dpy->wl_server_drm)
3396       goto fail;
3397
3398    device_name = drmGetRenderDeviceNameFromFd(dri2_dpy->fd);
3399    if (!device_name)
3400       device_name = strdup(dri2_dpy->device_name);
3401    if (!device_name)
3402       goto fail;
3403
3404    if (drmGetCap(dri2_dpy->fd, DRM_CAP_PRIME, &cap) == 0 &&
3405        cap == (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT) &&
3406        dri2_dpy->image->base.version >= 7 &&
3407        dri2_dpy->image->createImageFromFds != NULL)
3408       flags |= WAYLAND_DRM_PRIME;
3409
3410    dri2_dpy->wl_server_drm =
3411            wayland_drm_init(wl_dpy, device_name,
3412                             &wl_drm_callbacks, disp, flags);
3413
3414    free(device_name);
3415
3416    if (!dri2_dpy->wl_server_drm)
3417       goto fail;
3418
3419 #ifdef HAVE_DRM_PLATFORM
3420    /* We have to share the wl_drm instance with gbm, so gbm can convert
3421     * wl_buffers to gbm bos. */
3422    if (dri2_dpy->gbm_dri)
3423       dri2_dpy->gbm_dri->wl_drm = dri2_dpy->wl_server_drm;
3424 #endif
3425
3426    mtx_unlock(&dri2_dpy->lock);
3427    return EGL_TRUE;
3428
3429 fail:
3430    mtx_unlock(&dri2_dpy->lock);
3431    return EGL_FALSE;
3432 }
3433
3434 static EGLBoolean
3435 dri2_unbind_wayland_display_wl(_EGLDisplay *disp, struct wl_display *wl_dpy)
3436 {
3437    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3438
3439    if (!dri2_dpy->wl_server_drm)
3440            return EGL_FALSE;
3441
3442    wayland_drm_uninit(dri2_dpy->wl_server_drm);
3443    dri2_dpy->wl_server_drm = NULL;
3444
3445    return EGL_TRUE;
3446 }
3447
3448 static EGLBoolean
3449 dri2_query_wayland_buffer_wl(_EGLDisplay *disp, struct wl_resource *buffer_resource,
3450                              EGLint attribute, EGLint *value)
3451 {
3452    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3453    struct wl_drm_buffer *buffer;
3454    const struct wl_drm_components_descriptor *format;
3455
3456    buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm, buffer_resource);
3457    if (!buffer)
3458       return EGL_FALSE;
3459
3460    format = buffer->driver_format;
3461    switch (attribute) {
3462    case EGL_TEXTURE_FORMAT:
3463       *value = format->components;
3464       return EGL_TRUE;
3465    case EGL_WIDTH:
3466       *value = buffer->width;
3467       return EGL_TRUE;
3468    case EGL_HEIGHT:
3469       *value = buffer->height;
3470       return EGL_TRUE;
3471    }
3472
3473    return EGL_FALSE;
3474 }
3475 #endif
3476
3477 static void
3478 dri2_egl_ref_sync(struct dri2_egl_sync *sync)
3479 {
3480    p_atomic_inc(&sync->refcount);
3481 }
3482
3483 static void
3484 dri2_egl_unref_sync(struct dri2_egl_display *dri2_dpy,
3485                     struct dri2_egl_sync *dri2_sync)
3486 {
3487    if (p_atomic_dec_zero(&dri2_sync->refcount)) {
3488       switch (dri2_sync->base.Type) {
3489       case EGL_SYNC_REUSABLE_KHR:
3490          cnd_destroy(&dri2_sync->cond);
3491          break;
3492       case EGL_SYNC_NATIVE_FENCE_ANDROID:
3493          if (dri2_sync->base.SyncFd != EGL_NO_NATIVE_FENCE_FD_ANDROID)
3494             close(dri2_sync->base.SyncFd);
3495          break;
3496       default:
3497          break;
3498       }
3499
3500       if (dri2_sync->fence)
3501          dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, dri2_sync->fence);
3502
3503       free(dri2_sync);
3504    }
3505 }
3506
3507 static _EGLSync *
3508 dri2_create_sync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list)
3509 {
3510    _EGLContext *ctx = _eglGetCurrentContext();
3511    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
3512    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3513    struct dri2_egl_sync *dri2_sync;
3514    EGLint ret;
3515    pthread_condattr_t attr;
3516
3517    dri2_sync = calloc(1, sizeof(struct dri2_egl_sync));
3518    if (!dri2_sync) {
3519       _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
3520       goto fail;
3521    }
3522
3523    if (!_eglInitSync(&dri2_sync->base, disp, type, attrib_list)) {
3524       goto fail;
3525    }
3526
3527    switch (type) {
3528    case EGL_SYNC_FENCE_KHR:
3529       dri2_sync->fence = dri2_dpy->fence->create_fence(dri2_ctx->dri_context);
3530       if (!dri2_sync->fence) {
3531          /* Why did it fail? DRI doesn't return an error code, so we emit
3532           * a generic EGL error that doesn't communicate user error.
3533           */
3534          _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
3535          goto fail;
3536       }
3537       break;
3538
3539    case EGL_SYNC_CL_EVENT_KHR:
3540       dri2_sync->fence = dri2_dpy->fence->get_fence_from_cl_event(
3541                                  dri2_dpy->dri_screen,
3542                                  dri2_sync->base.CLEvent);
3543       /* this can only happen if the cl_event passed in is invalid. */
3544       if (!dri2_sync->fence) {
3545          _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
3546          goto fail;
3547       }
3548
3549       /* the initial status must be "signaled" if the cl_event is signaled */
3550       if (dri2_dpy->fence->client_wait_sync(dri2_ctx->dri_context,
3551                                             dri2_sync->fence, 0, 0))
3552          dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
3553       break;
3554
3555    case EGL_SYNC_REUSABLE_KHR:
3556       /* intialize attr */
3557       ret = pthread_condattr_init(&attr);
3558
3559       if (ret) {
3560          _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR");
3561          goto fail;
3562       }
3563
3564       /* change clock attribute to CLOCK_MONOTONIC */
3565       ret = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
3566
3567       if (ret) {
3568          _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR");
3569          goto fail;
3570       }
3571
3572       ret = pthread_cond_init(&dri2_sync->cond, &attr);
3573
3574       if (ret) {
3575          _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR");
3576          goto fail;
3577       }
3578
3579       /* initial status of reusable sync must be "unsignaled" */
3580       dri2_sync->base.SyncStatus = EGL_UNSIGNALED_KHR;
3581       break;
3582
3583    case EGL_SYNC_NATIVE_FENCE_ANDROID:
3584       if (dri2_dpy->fence->create_fence_fd) {
3585          dri2_sync->fence = dri2_dpy->fence->create_fence_fd(
3586                                     dri2_ctx->dri_context,
3587                                     dri2_sync->base.SyncFd);
3588       }
3589       if (!dri2_sync->fence) {
3590          _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
3591          goto fail;
3592       }
3593       break;
3594    }
3595
3596    p_atomic_set(&dri2_sync->refcount, 1);
3597    mtx_unlock(&dri2_dpy->lock);
3598
3599    return &dri2_sync->base;
3600
3601 fail:
3602    free(dri2_sync);
3603    mtx_unlock(&dri2_dpy->lock);
3604    return NULL;
3605 }
3606
3607 static EGLBoolean
3608 dri2_destroy_sync(_EGLDisplay *disp, _EGLSync *sync)
3609 {
3610    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
3611    struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3612    EGLint ret = EGL_TRUE;
3613    EGLint err;
3614
3615    /* if type of sync is EGL_SYNC_REUSABLE_KHR and it is not signaled yet,
3616     * then unlock all threads possibly blocked by the reusable sync before
3617     * destroying it.
3618     */
3619    if (dri2_sync->base.Type == EGL_SYNC_REUSABLE_KHR &&
3620        dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR) {
3621       dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
3622       /* unblock all threads currently blocked by sync */
3623       err = cnd_broadcast(&dri2_sync->cond);
3624
3625       if (err) {
3626          _eglError(EGL_BAD_ACCESS, "eglDestroySyncKHR");
3627          ret = EGL_FALSE;
3628       }
3629    }
3630
3631    dri2_egl_unref_sync(dri2_dpy, dri2_sync);
3632
3633    mtx_unlock(&dri2_dpy->lock);
3634
3635    return ret;
3636 }
3637
3638 static EGLint
3639 dri2_dup_native_fence_fd(_EGLDisplay *disp, _EGLSync *sync)
3640 {
3641    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
3642    struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3643
3644    assert(sync->Type == EGL_SYNC_NATIVE_FENCE_ANDROID);
3645
3646    if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
3647       /* try to retrieve the actual native fence fd.. if rendering is
3648        * not flushed this will just return -1, aka NO_NATIVE_FENCE_FD:
3649        */
3650       sync->SyncFd = dri2_dpy->fence->get_fence_fd(dri2_dpy->dri_screen,
3651                                                    dri2_sync->fence);
3652    }
3653
3654    mtx_unlock(&dri2_dpy->lock);
3655
3656    if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
3657       /* if native fence fd still not created, return an error: */
3658       _eglError(EGL_BAD_PARAMETER, "eglDupNativeFenceFDANDROID");
3659       return EGL_NO_NATIVE_FENCE_FD_ANDROID;
3660    }
3661
3662    assert(sync_valid_fd(sync->SyncFd));
3663
3664    return os_dupfd_cloexec(sync->SyncFd);
3665 }
3666
3667 static void
3668 dri2_set_blob_cache_funcs(_EGLDisplay *disp,
3669                           EGLSetBlobFuncANDROID set,
3670                           EGLGetBlobFuncANDROID get)
3671 {
3672    struct dri2_egl_display *dri2_dpy = dri2_egl_display_lock(disp);
3673    dri2_dpy->blob->set_cache_funcs(dri2_dpy->dri_screen, set, get);
3674    mtx_unlock(&dri2_dpy->lock);
3675 }
3676
3677 static EGLint
3678 dri2_client_wait_sync(_EGLDisplay *disp, _EGLSync *sync,
3679                       EGLint flags, EGLTime timeout)
3680 {
3681    _EGLContext *ctx = _eglGetCurrentContext();
3682    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3683    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3684    struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3685    unsigned wait_flags = 0;
3686
3687    EGLint ret = EGL_CONDITION_SATISFIED_KHR;
3688
3689    /* The EGL_KHR_fence_sync spec states:
3690     *
3691     *    "If no context is current for the bound API,
3692     *     the EGL_SYNC_FLUSH_COMMANDS_BIT_KHR bit is ignored.
3693     */
3694    if (dri2_ctx && flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)
3695       wait_flags |= __DRI2_FENCE_FLAG_FLUSH_COMMANDS;
3696
3697    /* the sync object should take a reference while waiting */
3698    dri2_egl_ref_sync(dri2_sync);
3699
3700    switch (sync->Type) {
3701    case EGL_SYNC_FENCE_KHR:
3702    case EGL_SYNC_NATIVE_FENCE_ANDROID:
3703    case EGL_SYNC_CL_EVENT_KHR:
3704       if (dri2_dpy->fence->client_wait_sync(dri2_ctx ? dri2_ctx->dri_context : NULL,
3705                                          dri2_sync->fence, wait_flags,
3706                                          timeout))
3707          dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
3708       else
3709          ret = EGL_TIMEOUT_EXPIRED_KHR;
3710       break;
3711
3712    case EGL_SYNC_REUSABLE_KHR:
3713       if (dri2_ctx && dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR &&
3714           (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)) {
3715          /* flush context if EGL_SYNC_FLUSH_COMMANDS_BIT_KHR is set */
3716          dri2_gl_flush();
3717       }
3718
3719       /* if timeout is EGL_FOREVER_KHR, it should wait without any timeout.*/
3720       if (timeout == EGL_FOREVER_KHR) {
3721          mtx_lock(&dri2_sync->mutex);
3722          cnd_wait(&dri2_sync->cond, &dri2_sync->mutex);
3723          mtx_unlock(&dri2_sync->mutex);
3724       } else {
3725          /* if reusable sync has not been yet signaled */
3726          if (dri2_sync->base.SyncStatus != EGL_SIGNALED_KHR) {
3727             /* timespecs for cnd_timedwait */
3728             struct timespec current;
3729             struct timespec expire;
3730
3731             /* We override the clock to monotonic when creating the condition
3732              * variable. */
3733             clock_gettime(CLOCK_MONOTONIC, &current);
3734
3735             /* calculating when to expire */
3736             expire.tv_nsec = timeout % 1000000000L;
3737             expire.tv_sec = timeout / 1000000000L;
3738
3739             expire.tv_nsec += current.tv_nsec;
3740             expire.tv_sec += current.tv_sec;
3741
3742             /* expire.nsec now is a number between 0 and 1999999998 */
3743             if (expire.tv_nsec > 999999999L) {
3744                expire.tv_sec++;
3745                expire.tv_nsec -= 1000000000L;
3746             }
3747
3748             mtx_lock(&dri2_sync->mutex);
3749             ret = cnd_timedwait(&dri2_sync->cond, &dri2_sync->mutex, &expire);
3750             mtx_unlock(&dri2_sync->mutex);
3751
3752             if (ret == thrd_timedout) {
3753                if (dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR) {
3754                   ret = EGL_TIMEOUT_EXPIRED_KHR;
3755                } else {
3756                   _eglError(EGL_BAD_ACCESS, "eglClientWaitSyncKHR");
3757                   ret = EGL_FALSE;
3758                }
3759             }
3760          }
3761       }
3762       break;
3763    }
3764
3765    dri2_egl_unref_sync(dri2_dpy, dri2_sync);
3766
3767    return ret;
3768 }
3769
3770 static EGLBoolean
3771 dri2_signal_sync(_EGLDisplay *disp, _EGLSync *sync, EGLenum mode)
3772 {
3773    struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3774    EGLint ret;
3775
3776    if (sync->Type != EGL_SYNC_REUSABLE_KHR)
3777       return _eglError(EGL_BAD_MATCH, "eglSignalSyncKHR");
3778
3779    if (mode != EGL_SIGNALED_KHR && mode != EGL_UNSIGNALED_KHR)
3780       return _eglError(EGL_BAD_ATTRIBUTE, "eglSignalSyncKHR");
3781
3782    dri2_sync->base.SyncStatus = mode;
3783
3784    if (mode == EGL_SIGNALED_KHR) {
3785       ret = cnd_broadcast(&dri2_sync->cond);
3786
3787       /* fail to broadcast */
3788       if (ret)
3789          return _eglError(EGL_BAD_ACCESS, "eglSignalSyncKHR");
3790    }
3791
3792    return EGL_TRUE;
3793 }
3794
3795 static EGLint
3796 dri2_server_wait_sync(_EGLDisplay *disp, _EGLSync *sync)
3797 {
3798    _EGLContext *ctx = _eglGetCurrentContext();
3799    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3800    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3801    struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3802
3803    dri2_dpy->fence->server_wait_sync(dri2_ctx->dri_context,
3804                                      dri2_sync->fence, 0);
3805    return EGL_TRUE;
3806 }
3807
3808 static int
3809 dri2_interop_query_device_info(_EGLDisplay *disp, _EGLContext *ctx,
3810                                struct mesa_glinterop_device_info *out)
3811 {
3812    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3813    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3814
3815    if (!dri2_dpy->interop)
3816       return MESA_GLINTEROP_UNSUPPORTED;
3817
3818    return dri2_dpy->interop->query_device_info(dri2_ctx->dri_context, out);
3819 }
3820
3821 static int
3822 dri2_interop_export_object(_EGLDisplay *disp, _EGLContext *ctx,
3823                            struct mesa_glinterop_export_in *in,
3824                            struct mesa_glinterop_export_out *out)
3825 {
3826    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3827    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3828
3829    if (!dri2_dpy->interop)
3830       return MESA_GLINTEROP_UNSUPPORTED;
3831
3832    return dri2_dpy->interop->export_object(dri2_ctx->dri_context, in, out);
3833 }
3834
3835 static int
3836 dri2_interop_flush_objects(_EGLDisplay *disp, _EGLContext *ctx,
3837                            unsigned count, struct mesa_glinterop_export_in *objects,
3838                            GLsync *sync)
3839 {
3840    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3841    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3842
3843    if (!dri2_dpy->interop || dri2_dpy->interop->base.version < 2)
3844       return MESA_GLINTEROP_UNSUPPORTED;
3845
3846    return dri2_dpy->interop->flush_objects(dri2_ctx->dri_context, count, objects, sync);
3847 }
3848
3849 const _EGLDriver _eglDriver = {
3850    .Initialize = dri2_initialize,
3851    .Terminate = dri2_terminate,
3852    .CreateContext = dri2_create_context,
3853    .DestroyContext = dri2_destroy_context,
3854    .MakeCurrent = dri2_make_current,
3855    .CreateWindowSurface = dri2_create_window_surface,
3856    .CreatePixmapSurface = dri2_create_pixmap_surface,
3857    .CreatePbufferSurface = dri2_create_pbuffer_surface,
3858    .DestroySurface = dri2_destroy_surface,
3859    .GetProcAddress = dri2_get_proc_address,
3860    .WaitClient = dri2_wait_client,
3861    .WaitNative = dri2_wait_native,
3862    .BindTexImage = dri2_bind_tex_image,
3863    .ReleaseTexImage = dri2_release_tex_image,
3864    .SwapInterval = dri2_swap_interval,
3865    .SwapBuffers = dri2_swap_buffers,
3866    .SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage,
3867    .SwapBuffersRegionNOK = dri2_swap_buffers_region,
3868    .SetDamageRegion = dri2_set_damage_region,
3869    .PostSubBufferNV = dri2_post_sub_buffer,
3870    .CopyBuffers = dri2_copy_buffers,
3871    .QueryBufferAge = dri2_query_buffer_age,
3872    .CreateImageKHR = dri2_create_image,
3873    .DestroyImageKHR = dri2_destroy_image_khr,
3874    .CreateWaylandBufferFromImageWL = dri2_create_wayland_buffer_from_image,
3875    .QuerySurface = dri2_query_surface,
3876    .QueryDriverName = dri2_query_driver_name,
3877    .QueryDriverConfig = dri2_query_driver_config,
3878 #ifdef HAVE_LIBDRM
3879    .CreateDRMImageMESA = dri2_create_drm_image_mesa,
3880    .ExportDRMImageMESA = dri2_export_drm_image_mesa,
3881    .ExportDMABUFImageQueryMESA = dri2_export_dma_buf_image_query_mesa,
3882    .ExportDMABUFImageMESA = dri2_export_dma_buf_image_mesa,
3883    .QueryDmaBufFormatsEXT = dri2_query_dma_buf_formats,
3884    .QueryDmaBufModifiersEXT = dri2_query_dma_buf_modifiers,
3885 #endif
3886 #ifdef HAVE_WAYLAND_PLATFORM
3887    .BindWaylandDisplayWL = dri2_bind_wayland_display_wl,
3888    .UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl,
3889    .QueryWaylandBufferWL = dri2_query_wayland_buffer_wl,
3890 #endif
3891    .GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium,
3892    .GetMscRateANGLE = dri2_get_msc_rate_angle,
3893    .CreateSyncKHR = dri2_create_sync,
3894    .ClientWaitSyncKHR = dri2_client_wait_sync,
3895    .SignalSyncKHR = dri2_signal_sync,
3896    .WaitSyncKHR = dri2_server_wait_sync,
3897    .DestroySyncKHR = dri2_destroy_sync,
3898    .GLInteropQueryDeviceInfo = dri2_interop_query_device_info,
3899    .GLInteropExportObject = dri2_interop_export_object,
3900    .GLInteropFlushObjects = dri2_interop_flush_objects,
3901    .DupNativeFenceFDANDROID = dri2_dup_native_fence_fd,
3902    .SetBlobCacheFuncsANDROID = dri2_set_blob_cache_funcs,
3903 };