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