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