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