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