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