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