egl_dri2.c revision 848b8605
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 <stdlib.h>
31#include <string.h>
32#include <stdio.h>
33#include <limits.h>
34#include <dlfcn.h>
35#include <fcntl.h>
36#include <errno.h>
37#include <unistd.h>
38#ifdef HAVE_LIBDRM
39#include <xf86drm.h>
40#include <drm_fourcc.h>
41#endif
42#include <GL/gl.h>
43#include <GL/internal/dri_interface.h>
44#include <sys/types.h>
45#include <sys/stat.h>
46
47#ifdef HAVE_WAYLAND_PLATFORM
48#include "wayland-drm.h"
49#include "wayland-drm-client-protocol.h"
50#endif
51
52#include "egl_dri2.h"
53
54const __DRIuseInvalidateExtension use_invalidate = {
55   .base = { __DRI_USE_INVALIDATE, 1 }
56};
57
58EGLint dri2_to_egl_attribute_map[] = {
59   0,
60   EGL_BUFFER_SIZE,		/* __DRI_ATTRIB_BUFFER_SIZE */
61   EGL_LEVEL,			/* __DRI_ATTRIB_LEVEL */
62   EGL_RED_SIZE,		/* __DRI_ATTRIB_RED_SIZE */
63   EGL_GREEN_SIZE,		/* __DRI_ATTRIB_GREEN_SIZE */
64   EGL_BLUE_SIZE,		/* __DRI_ATTRIB_BLUE_SIZE */
65   EGL_LUMINANCE_SIZE,		/* __DRI_ATTRIB_LUMINANCE_SIZE */
66   EGL_ALPHA_SIZE,		/* __DRI_ATTRIB_ALPHA_SIZE */
67   0,				/* __DRI_ATTRIB_ALPHA_MASK_SIZE */
68   EGL_DEPTH_SIZE,		/* __DRI_ATTRIB_DEPTH_SIZE */
69   EGL_STENCIL_SIZE,		/* __DRI_ATTRIB_STENCIL_SIZE */
70   0,				/* __DRI_ATTRIB_ACCUM_RED_SIZE */
71   0,				/* __DRI_ATTRIB_ACCUM_GREEN_SIZE */
72   0,				/* __DRI_ATTRIB_ACCUM_BLUE_SIZE */
73   0,				/* __DRI_ATTRIB_ACCUM_ALPHA_SIZE */
74   EGL_SAMPLE_BUFFERS,		/* __DRI_ATTRIB_SAMPLE_BUFFERS */
75   EGL_SAMPLES,			/* __DRI_ATTRIB_SAMPLES */
76   0,				/* __DRI_ATTRIB_RENDER_TYPE, */
77   0,				/* __DRI_ATTRIB_CONFIG_CAVEAT */
78   0,				/* __DRI_ATTRIB_CONFORMANT */
79   0,				/* __DRI_ATTRIB_DOUBLE_BUFFER */
80   0,				/* __DRI_ATTRIB_STEREO */
81   0,				/* __DRI_ATTRIB_AUX_BUFFERS */
82   0,				/* __DRI_ATTRIB_TRANSPARENT_TYPE */
83   0,				/* __DRI_ATTRIB_TRANSPARENT_INDEX_VALUE */
84   0,				/* __DRI_ATTRIB_TRANSPARENT_RED_VALUE */
85   0,				/* __DRI_ATTRIB_TRANSPARENT_GREEN_VALUE */
86   0,				/* __DRI_ATTRIB_TRANSPARENT_BLUE_VALUE */
87   0,				/* __DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE */
88   0,				/* __DRI_ATTRIB_FLOAT_MODE (deprecated) */
89   0,				/* __DRI_ATTRIB_RED_MASK */
90   0,				/* __DRI_ATTRIB_GREEN_MASK */
91   0,				/* __DRI_ATTRIB_BLUE_MASK */
92   0,				/* __DRI_ATTRIB_ALPHA_MASK */
93   EGL_MAX_PBUFFER_WIDTH,	/* __DRI_ATTRIB_MAX_PBUFFER_WIDTH */
94   EGL_MAX_PBUFFER_HEIGHT,	/* __DRI_ATTRIB_MAX_PBUFFER_HEIGHT */
95   EGL_MAX_PBUFFER_PIXELS,	/* __DRI_ATTRIB_MAX_PBUFFER_PIXELS */
96   0,				/* __DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH */
97   0,				/* __DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT */
98   0,				/* __DRI_ATTRIB_VISUAL_SELECT_GROUP */
99   0,				/* __DRI_ATTRIB_SWAP_METHOD */
100   EGL_MAX_SWAP_INTERVAL,	/* __DRI_ATTRIB_MAX_SWAP_INTERVAL */
101   EGL_MIN_SWAP_INTERVAL,	/* __DRI_ATTRIB_MIN_SWAP_INTERVAL */
102   0,				/* __DRI_ATTRIB_BIND_TO_TEXTURE_RGB */
103   0,				/* __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA */
104   0,				/* __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE */
105   0,				/* __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS */
106   EGL_Y_INVERTED_NOK,		/* __DRI_ATTRIB_YINVERTED */
107   0,				/* __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE */
108};
109
110static EGLBoolean
111dri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria)
112{
113   if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0)
114      return EGL_FALSE;
115
116   if (!_eglMatchConfig(conf, criteria))
117      return EGL_FALSE;
118
119   return EGL_TRUE;
120}
121
122struct dri2_egl_config *
123dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
124		EGLint surface_type, const EGLint *attr_list,
125		const unsigned int *rgba_masks)
126{
127   struct dri2_egl_config *conf;
128   struct dri2_egl_display *dri2_dpy;
129   _EGLConfig base;
130   unsigned int attrib, value, double_buffer;
131   EGLint key, bind_to_texture_rgb, bind_to_texture_rgba;
132   unsigned int dri_masks[4] = { 0, 0, 0, 0 };
133   _EGLConfig *matching_config;
134   EGLint num_configs = 0;
135   EGLint config_id;
136   int i;
137
138   dri2_dpy = disp->DriverData;
139   _eglInitConfig(&base, disp, id);
140
141   i = 0;
142   double_buffer = 0;
143   bind_to_texture_rgb = 0;
144   bind_to_texture_rgba = 0;
145
146   while (dri2_dpy->core->indexConfigAttrib(dri_config, i++, &attrib, &value)) {
147      switch (attrib) {
148      case __DRI_ATTRIB_RENDER_TYPE:
149	 if (value & __DRI_ATTRIB_RGBA_BIT)
150	    value = EGL_RGB_BUFFER;
151	 else if (value & __DRI_ATTRIB_LUMINANCE_BIT)
152	    value = EGL_LUMINANCE_BUFFER;
153	 else
154	    return NULL;
155	 _eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value);
156	 break;
157
158      case __DRI_ATTRIB_CONFIG_CAVEAT:
159         if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
160            value = EGL_NON_CONFORMANT_CONFIG;
161         else if (value & __DRI_ATTRIB_SLOW_BIT)
162            value = EGL_SLOW_CONFIG;
163	 else
164	    value = EGL_NONE;
165	 _eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value);
166         break;
167
168      case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB:
169	 bind_to_texture_rgb = value;
170	 break;
171
172      case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA:
173	 bind_to_texture_rgba = value;
174	 break;
175
176      case __DRI_ATTRIB_DOUBLE_BUFFER:
177	 double_buffer = value;
178	 break;
179
180      case __DRI_ATTRIB_RED_MASK:
181         dri_masks[0] = value;
182         break;
183
184      case __DRI_ATTRIB_GREEN_MASK:
185         dri_masks[1] = value;
186         break;
187
188      case __DRI_ATTRIB_BLUE_MASK:
189         dri_masks[2] = value;
190         break;
191
192      case __DRI_ATTRIB_ALPHA_MASK:
193         dri_masks[3] = value;
194         break;
195
196      default:
197	 key = dri2_to_egl_attribute_map[attrib];
198	 if (key != 0)
199	    _eglSetConfigKey(&base, key, value);
200	 break;
201      }
202   }
203
204   if (attr_list)
205      for (i = 0; attr_list[i] != EGL_NONE; i += 2)
206         _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]);
207
208   if (rgba_masks && memcmp(rgba_masks, dri_masks, sizeof(dri_masks)))
209      return NULL;
210
211   base.NativeRenderable = EGL_TRUE;
212
213   base.SurfaceType = surface_type;
214   if (surface_type & (EGL_PBUFFER_BIT |
215       (disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) {
216      base.BindToTextureRGB = bind_to_texture_rgb;
217      if (base.AlphaSize > 0)
218         base.BindToTextureRGBA = bind_to_texture_rgba;
219   }
220
221   base.RenderableType = disp->ClientAPIs;
222   base.Conformant = disp->ClientAPIs;
223
224   base.MinSwapInterval = dri2_dpy->min_swap_interval;
225   base.MaxSwapInterval = dri2_dpy->max_swap_interval;
226
227   if (!_eglValidateConfig(&base, EGL_FALSE)) {
228      _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id);
229      return NULL;
230   }
231
232   config_id = base.ConfigID;
233   base.ConfigID    = EGL_DONT_CARE;
234   base.SurfaceType = EGL_DONT_CARE;
235   num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1,
236                                 (_EGLArrayForEach) dri2_match_config, &base);
237
238   if (num_configs == 1) {
239      conf = (struct dri2_egl_config *) matching_config;
240
241      if (double_buffer && !conf->dri_double_config)
242         conf->dri_double_config = dri_config;
243      else if (!double_buffer && !conf->dri_single_config)
244         conf->dri_single_config = dri_config;
245      else
246         /* a similar config type is already added (unlikely) => discard */
247         return NULL;
248   }
249   else if (num_configs == 0) {
250      conf = malloc(sizeof *conf);
251      if (conf == NULL)
252         return NULL;
253
254      memcpy(&conf->base, &base, sizeof base);
255      if (double_buffer) {
256         conf->dri_double_config = dri_config;
257         conf->dri_single_config = NULL;
258      } else {
259         conf->dri_single_config = dri_config;
260         conf->dri_double_config = NULL;
261      }
262      conf->base.SurfaceType = 0;
263      conf->base.ConfigID = config_id;
264
265      _eglLinkConfig(&conf->base);
266   }
267   else {
268      assert(0);
269      return NULL;
270   }
271
272   if (double_buffer) {
273      surface_type &= ~EGL_PIXMAP_BIT;
274   }
275
276   conf->base.SurfaceType |= surface_type;
277
278   return conf;
279}
280
281__DRIimage *
282dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
283{
284   _EGLDisplay *disp = data;
285   struct dri2_egl_image *dri2_img;
286   _EGLImage *img;
287
288   (void) screen;
289
290   img = _eglLookupImage(image, disp);
291   if (img == NULL) {
292      _eglError(EGL_BAD_PARAMETER, "dri2_lookup_egl_image");
293      return NULL;
294   }
295
296   dri2_img = dri2_egl_image(image);
297
298   return dri2_img->dri_image;
299}
300
301const __DRIimageLookupExtension image_lookup_extension = {
302   .base = { __DRI_IMAGE_LOOKUP, 1 },
303
304   .lookupEGLImage       = dri2_lookup_egl_image
305};
306
307struct dri2_extension_match {
308   const char *name;
309   int version;
310   int offset;
311};
312
313static struct dri2_extension_match dri2_driver_extensions[] = {
314   { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
315   { __DRI_DRI2, 2, offsetof(struct dri2_egl_display, dri2) },
316   { NULL, 0, 0 }
317};
318
319static struct dri2_extension_match dri2_core_extensions[] = {
320   { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) },
321   { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
322   { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) },
323   { NULL, 0, 0 }
324};
325
326static struct dri2_extension_match swrast_driver_extensions[] = {
327   { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
328   { __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) },
329   { NULL, 0, 0 }
330};
331
332static struct dri2_extension_match swrast_core_extensions[] = {
333   { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
334   { NULL, 0, 0 }
335};
336
337static EGLBoolean
338dri2_bind_extensions(struct dri2_egl_display *dri2_dpy,
339		     struct dri2_extension_match *matches,
340		     const __DRIextension **extensions)
341{
342   int i, j, ret = EGL_TRUE;
343   void *field;
344
345   for (i = 0; extensions[i]; i++) {
346      _eglLog(_EGL_DEBUG, "DRI2: found extension `%s'", extensions[i]->name);
347      for (j = 0; matches[j].name; j++) {
348	 if (strcmp(extensions[i]->name, matches[j].name) == 0 &&
349	     extensions[i]->version >= matches[j].version) {
350	    field = ((char *) dri2_dpy + matches[j].offset);
351	    *(const __DRIextension **) field = extensions[i];
352	    _eglLog(_EGL_INFO, "DRI2: found extension %s version %d",
353		    extensions[i]->name, extensions[i]->version);
354	 }
355      }
356   }
357
358   for (j = 0; matches[j].name; j++) {
359      field = ((char *) dri2_dpy + matches[j].offset);
360      if (*(const __DRIextension **) field == NULL) {
361	 _eglLog(_EGL_WARNING, "DRI2: did not find extension %s version %d",
362		 matches[j].name, matches[j].version);
363	 ret = EGL_FALSE;
364      }
365   }
366
367   return ret;
368}
369
370static const __DRIextension **
371dri2_open_driver(_EGLDisplay *disp)
372{
373   struct dri2_egl_display *dri2_dpy = disp->DriverData;
374   const __DRIextension **extensions = NULL;
375   char path[PATH_MAX], *search_paths, *p, *next, *end;
376   char *get_extensions_name;
377   const __DRIextension **(*get_extensions)(void);
378
379   search_paths = NULL;
380   if (geteuid() == getuid()) {
381      /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
382      search_paths = getenv("LIBGL_DRIVERS_PATH");
383   }
384   if (search_paths == NULL)
385      search_paths = DEFAULT_DRIVER_DIR;
386
387   dri2_dpy->driver = NULL;
388   end = search_paths + strlen(search_paths);
389   for (p = search_paths; p < end && dri2_dpy->driver == NULL; p = next + 1) {
390      int len;
391      next = strchr(p, ':');
392      if (next == NULL)
393         next = end;
394
395      len = next - p;
396#if GLX_USE_TLS
397      snprintf(path, sizeof path,
398	       "%.*s/tls/%s_dri.so", len, p, dri2_dpy->driver_name);
399      dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
400#endif
401      if (dri2_dpy->driver == NULL) {
402	 snprintf(path, sizeof path,
403		  "%.*s/%s_dri.so", len, p, dri2_dpy->driver_name);
404	 dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
405	 if (dri2_dpy->driver == NULL)
406	    _eglLog(_EGL_DEBUG, "failed to open %s: %s\n", path, dlerror());
407      }
408      /* not need continue to loop all paths once the driver is found */
409      if (dri2_dpy->driver != NULL)
410         break;
411   }
412
413   if (dri2_dpy->driver == NULL) {
414      _eglLog(_EGL_WARNING,
415	      "DRI2: failed to open %s (search paths %s)",
416	      dri2_dpy->driver_name, search_paths);
417      return NULL;
418   }
419
420   _eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path);
421
422   if (asprintf(&get_extensions_name, "%s_%s",
423                __DRI_DRIVER_GET_EXTENSIONS, dri2_dpy->driver_name) != -1) {
424      get_extensions = dlsym(dri2_dpy->driver, get_extensions_name);
425      if (get_extensions) {
426         extensions = get_extensions();
427      } else {
428         _eglLog(_EGL_DEBUG, "driver does not expose %s(): %s\n",
429                 get_extensions_name, dlerror());
430      }
431      free(get_extensions_name);
432   }
433
434   if (!extensions)
435      extensions = dlsym(dri2_dpy->driver, __DRI_DRIVER_EXTENSIONS);
436   if (extensions == NULL) {
437      _eglLog(_EGL_WARNING,
438	      "DRI2: driver exports no extensions (%s)", dlerror());
439      dlclose(dri2_dpy->driver);
440   }
441
442   return extensions;
443}
444
445EGLBoolean
446dri2_load_driver(_EGLDisplay *disp)
447{
448   struct dri2_egl_display *dri2_dpy = disp->DriverData;
449   const __DRIextension **extensions;
450
451   extensions = dri2_open_driver(disp);
452   if (!extensions)
453      return EGL_FALSE;
454
455   if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) {
456      dlclose(dri2_dpy->driver);
457      return EGL_FALSE;
458   }
459   dri2_dpy->driver_extensions = extensions;
460
461   return EGL_TRUE;
462}
463
464EGLBoolean
465dri2_load_driver_swrast(_EGLDisplay *disp)
466{
467   struct dri2_egl_display *dri2_dpy = disp->DriverData;
468   const __DRIextension **extensions;
469
470   extensions = dri2_open_driver(disp);
471   if (!extensions)
472      return EGL_FALSE;
473
474   if (!dri2_bind_extensions(dri2_dpy, swrast_driver_extensions, extensions)) {
475      dlclose(dri2_dpy->driver);
476      return EGL_FALSE;
477   }
478   dri2_dpy->driver_extensions = extensions;
479
480   return EGL_TRUE;
481}
482
483void
484dri2_setup_screen(_EGLDisplay *disp)
485{
486   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
487   unsigned int api_mask;
488
489   if (dri2_dpy->dri2) {
490      api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
491   } else {
492      assert(dri2_dpy->swrast);
493      api_mask = 1 << __DRI_API_OPENGL |
494                 1 << __DRI_API_GLES |
495                 1 << __DRI_API_GLES2 |
496                 1 << __DRI_API_GLES3;
497   }
498
499   disp->ClientAPIs = 0;
500   if (api_mask & (1 <<__DRI_API_OPENGL))
501      disp->ClientAPIs |= EGL_OPENGL_BIT;
502   if (api_mask & (1 <<__DRI_API_GLES))
503      disp->ClientAPIs |= EGL_OPENGL_ES_BIT;
504   if (api_mask & (1 << __DRI_API_GLES2))
505      disp->ClientAPIs |= EGL_OPENGL_ES2_BIT;
506   if (api_mask & (1 << __DRI_API_GLES3))
507      disp->ClientAPIs |= EGL_OPENGL_ES3_BIT_KHR;
508
509   assert(dri2_dpy->dri2 || dri2_dpy->swrast);
510   disp->Extensions.KHR_surfaceless_context = EGL_TRUE;
511   disp->Extensions.MESA_configless_context = EGL_TRUE;
512
513   if (dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) {
514      disp->Extensions.KHR_create_context = EGL_TRUE;
515
516      if (dri2_dpy->robustness)
517         disp->Extensions.EXT_create_context_robustness = EGL_TRUE;
518   }
519
520   if (dri2_dpy->image) {
521      if (dri2_dpy->image->base.version >= 10 &&
522          dri2_dpy->image->getCapabilities != NULL) {
523         int capabilities;
524
525         capabilities = dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen);
526         disp->Extensions.MESA_drm_image = (capabilities & __DRI_IMAGE_CAP_GLOBAL_NAMES) != 0;
527      } else
528         disp->Extensions.MESA_drm_image = EGL_TRUE;
529
530      disp->Extensions.KHR_image_base = EGL_TRUE;
531      disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
532      if (dri2_dpy->image->base.version >= 5 &&
533          dri2_dpy->image->createImageFromTexture) {
534         disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
535         disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE;
536      }
537#ifdef HAVE_DRM_PLATFORM
538      if (dri2_dpy->image->base.version >= 8 &&
539          dri2_dpy->image->createImageFromDmaBufs) {
540         disp->Extensions.EXT_image_dma_buf_import = EGL_TRUE;
541      }
542#endif
543   }
544}
545
546EGLBoolean
547dri2_create_screen(_EGLDisplay *disp)
548{
549   const __DRIextension **extensions;
550   struct dri2_egl_display *dri2_dpy;
551
552   dri2_dpy = disp->DriverData;
553
554   if (dri2_dpy->dri2) {
555      if (dri2_dpy->dri2->base.version >= 4) {
556         dri2_dpy->dri_screen =
557            dri2_dpy->dri2->createNewScreen2(0, dri2_dpy->fd,
558                                             dri2_dpy->extensions,
559                                             dri2_dpy->driver_extensions,
560                                             &dri2_dpy->driver_configs, disp);
561      } else {
562         dri2_dpy->dri_screen =
563            dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd,
564                                            dri2_dpy->extensions,
565                                            &dri2_dpy->driver_configs, disp);
566      }
567   } else {
568      assert(dri2_dpy->swrast);
569      if (dri2_dpy->swrast->base.version >= 4) {
570         dri2_dpy->dri_screen =
571            dri2_dpy->swrast->createNewScreen2(0, dri2_dpy->extensions,
572                                               dri2_dpy->driver_extensions,
573                                               &dri2_dpy->driver_configs, disp);
574      } else {
575         dri2_dpy->dri_screen =
576            dri2_dpy->swrast->createNewScreen(0, dri2_dpy->extensions,
577                                              &dri2_dpy->driver_configs, disp);
578      }
579   }
580
581   if (dri2_dpy->dri_screen == NULL) {
582      _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
583      return EGL_FALSE;
584   }
585
586   dri2_dpy->own_dri_screen = 1;
587
588   extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
589
590   if (dri2_dpy->dri2) {
591      unsigned i;
592
593      if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
594         goto cleanup_dri_screen;
595
596      for (i = 0; extensions[i]; i++) {
597	 if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0) {
598            dri2_dpy->robustness = (__DRIrobustnessExtension *) extensions[i];
599	 }
600	 if (strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0) {
601	    dri2_dpy->config = (__DRI2configQueryExtension *) extensions[i];
602	 }
603      }
604   } else {
605      assert(dri2_dpy->swrast);
606      if (!dri2_bind_extensions(dri2_dpy, swrast_core_extensions, extensions))
607         goto cleanup_dri_screen;
608   }
609
610   dri2_setup_screen(disp);
611
612   return EGL_TRUE;
613
614 cleanup_dri_screen:
615   dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
616
617   return EGL_FALSE;
618}
619
620/**
621 * Called via eglInitialize(), GLX_drv->API.Initialize().
622 */
623static EGLBoolean
624dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp)
625{
626   /* not until swrast_dri is supported */
627   if (disp->Options.UseFallback)
628      return EGL_FALSE;
629
630   switch (disp->Platform) {
631#ifdef HAVE_X11_PLATFORM
632   case _EGL_PLATFORM_X11:
633      if (disp->Options.TestOnly)
634         return EGL_TRUE;
635      return dri2_initialize_x11(drv, disp);
636#endif
637
638#ifdef HAVE_DRM_PLATFORM
639   case _EGL_PLATFORM_DRM:
640      if (disp->Options.TestOnly)
641         return EGL_TRUE;
642      return dri2_initialize_drm(drv, disp);
643#endif
644#ifdef HAVE_WAYLAND_PLATFORM
645   case _EGL_PLATFORM_WAYLAND:
646      if (disp->Options.TestOnly)
647         return EGL_TRUE;
648      return dri2_initialize_wayland(drv, disp);
649#endif
650#ifdef HAVE_ANDROID_PLATFORM
651   case _EGL_PLATFORM_ANDROID:
652      if (disp->Options.TestOnly)
653         return EGL_TRUE;
654      return dri2_initialize_android(drv, disp);
655#endif
656
657   default:
658      return EGL_FALSE;
659   }
660}
661
662/**
663 * Called via eglTerminate(), drv->API.Terminate().
664 */
665static EGLBoolean
666dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
667{
668   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
669
670   _eglReleaseDisplayResources(drv, disp);
671   _eglCleanupDisplay(disp);
672
673   if (dri2_dpy->own_dri_screen)
674      dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
675   if (dri2_dpy->fd)
676      close(dri2_dpy->fd);
677   if (dri2_dpy->driver)
678      dlclose(dri2_dpy->driver);
679   free(dri2_dpy->device_name);
680   free(dri2_dpy->driver_name);
681
682   switch (disp->Platform) {
683#ifdef HAVE_X11_PLATFORM
684   case _EGL_PLATFORM_X11:
685      if (dri2_dpy->own_device) {
686         xcb_disconnect(dri2_dpy->conn);
687      }
688      break;
689#endif
690#ifdef HAVE_DRM_PLATFORM
691   case _EGL_PLATFORM_DRM:
692      if (dri2_dpy->own_device) {
693         gbm_device_destroy(&dri2_dpy->gbm_dri->base.base);
694      }
695      break;
696#endif
697#ifdef HAVE_WAYLAND_PLATFORM
698   case _EGL_PLATFORM_WAYLAND:
699      wl_drm_destroy(dri2_dpy->wl_drm);
700      if (dri2_dpy->own_device) {
701         wl_display_disconnect(dri2_dpy->wl_dpy);
702      }
703      break;
704#endif
705   default:
706      break;
707   }
708
709   free(dri2_dpy);
710   disp->DriverData = NULL;
711
712   return EGL_TRUE;
713}
714
715/**
716 * Set the error code after a call to
717 * dri2_egl_display::dri2::createContextAttribs.
718 */
719static void
720dri2_create_context_attribs_error(int dri_error)
721{
722   EGLint egl_error;
723
724   switch (dri_error) {
725   case __DRI_CTX_ERROR_SUCCESS:
726      return;
727
728   case __DRI_CTX_ERROR_NO_MEMORY:
729      egl_error = EGL_BAD_ALLOC;
730      break;
731
732  /* From the EGL_KHR_create_context spec, section "Errors":
733   *
734   *   * If <config> does not support a client API context compatible
735   *     with the requested API major and minor version, [...] context flags,
736   *     and context reset notification behavior (for client API types where
737   *     these attributes are supported), then an EGL_BAD_MATCH error is
738   *     generated.
739   *
740   *   * If an OpenGL ES context is requested and the values for
741   *     attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
742   *     EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
743   *     is not defined, than an EGL_BAD_MATCH error is generated.
744   *
745   *   * If an OpenGL context is requested, the requested version is
746   *     greater than 3.2, and the value for attribute
747   *     EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has any
748   *     bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and
749   *     EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than
750   *     one of these bits set; or if the implementation does not support
751   *     the requested profile, then an EGL_BAD_MATCH error is generated.
752   */
753   case __DRI_CTX_ERROR_BAD_API:
754   case __DRI_CTX_ERROR_BAD_VERSION:
755   case __DRI_CTX_ERROR_BAD_FLAG:
756      egl_error = EGL_BAD_MATCH;
757      break;
758
759  /* From the EGL_KHR_create_context spec, section "Errors":
760   *
761   *   * If an attribute name or attribute value in <attrib_list> is not
762   *     recognized (including unrecognized bits in bitmask attributes),
763   *     then an EGL_BAD_ATTRIBUTE error is generated."
764   */
765   case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE:
766   case __DRI_CTX_ERROR_UNKNOWN_FLAG:
767      egl_error = EGL_BAD_ATTRIBUTE;
768      break;
769
770   default:
771      assert(0);
772      egl_error = EGL_BAD_MATCH;
773      break;
774   }
775
776   _eglError(egl_error, "dri2_create_context");
777}
778
779/**
780 * Called via eglCreateContext(), drv->API.CreateContext().
781 */
782static _EGLContext *
783dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
784		    _EGLContext *share_list, const EGLint *attrib_list)
785{
786   struct dri2_egl_context *dri2_ctx;
787   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
788   struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list);
789   __DRIcontext *shared =
790      dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL;
791   struct dri2_egl_config *dri2_config = dri2_egl_config(conf);
792   const __DRIconfig *dri_config;
793   int api;
794
795   (void) drv;
796
797   dri2_ctx = malloc(sizeof *dri2_ctx);
798   if (!dri2_ctx) {
799      _eglError(EGL_BAD_ALLOC, "eglCreateContext");
800      return NULL;
801   }
802
803   if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list))
804      goto cleanup;
805
806   switch (dri2_ctx->base.ClientAPI) {
807   case EGL_OPENGL_ES_API:
808      switch (dri2_ctx->base.ClientMajorVersion) {
809      case 1:
810         api = __DRI_API_GLES;
811         break;
812      case 2:
813         api = __DRI_API_GLES2;
814         break;
815      case 3:
816         api = __DRI_API_GLES3;
817         break;
818      default:
819         _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
820         free(dri2_ctx);
821         return NULL;
822      }
823      break;
824   case EGL_OPENGL_API:
825      if ((dri2_ctx->base.ClientMajorVersion >= 4
826           || (dri2_ctx->base.ClientMajorVersion == 3
827               && dri2_ctx->base.ClientMinorVersion >= 2))
828          && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
829         api = __DRI_API_OPENGL_CORE;
830      else
831         api = __DRI_API_OPENGL;
832      break;
833   default:
834      _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
835      free(dri2_ctx);
836      return NULL;
837   }
838
839   if (conf != NULL) {
840      /* The config chosen here isn't necessarily
841       * used for surfaces later.
842       * A pixmap surface will use the single config.
843       * This opportunity depends on disabling the
844       * doubleBufferMode check in
845       * src/mesa/main/context.c:check_compatible()
846       */
847      if (dri2_config->dri_double_config)
848         dri_config = dri2_config->dri_double_config;
849      else
850         dri_config = dri2_config->dri_single_config;
851
852      /* EGL_WINDOW_BIT is set only when there is a dri_double_config.  This
853       * makes sure the back buffer will always be used.
854       */
855      if (conf->SurfaceType & EGL_WINDOW_BIT)
856         dri2_ctx->base.WindowRenderBuffer = EGL_BACK_BUFFER;
857   }
858   else
859      dri_config = NULL;
860
861   if (dri2_dpy->dri2) {
862      if (dri2_dpy->dri2->base.version >= 3) {
863         unsigned error;
864         unsigned num_attribs = 0;
865         uint32_t ctx_attribs[8];
866
867         ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
868         ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMajorVersion;
869         ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
870         ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMinorVersion;
871
872         if (dri2_ctx->base.Flags != 0) {
873            /* If the implementation doesn't support the __DRI2_ROBUSTNESS
874             * extension, don't even try to send it the robust-access flag.
875             * It may explode.  Instead, generate the required EGL error here.
876             */
877            if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0
878                && !dri2_dpy->robustness) {
879               _eglError(EGL_BAD_MATCH, "eglCreateContext");
880               goto cleanup;
881            }
882
883            ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
884            ctx_attribs[num_attribs++] = dri2_ctx->base.Flags;
885         }
886
887         if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) {
888            /* If the implementation doesn't support the __DRI2_ROBUSTNESS
889             * extension, don't even try to send it a reset strategy.  It may
890             * explode.  Instead, generate the required EGL error here.
891             */
892            if (!dri2_dpy->robustness) {
893               _eglError(EGL_BAD_CONFIG, "eglCreateContext");
894               goto cleanup;
895            }
896
897            ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
898            ctx_attribs[num_attribs++] = __DRI_CTX_RESET_LOSE_CONTEXT;
899         }
900
901         assert(num_attribs <= ARRAY_SIZE(ctx_attribs));
902
903	 dri2_ctx->dri_context =
904	    dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen,
905                                                 api,
906                                                 dri_config,
907                                                 shared,
908                                                 num_attribs / 2,
909                                                 ctx_attribs,
910                                                 & error,
911                                                 dri2_ctx);
912	 dri2_create_context_attribs_error(error);
913      } else {
914	 dri2_ctx->dri_context =
915	    dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
916						   api,
917						   dri_config,
918                                                   shared,
919						   dri2_ctx);
920      }
921   } else {
922      assert(dri2_dpy->swrast);
923      dri2_ctx->dri_context =
924         dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen,
925                                                  api,
926                                                  dri_config,
927                                                  shared,
928                                                  dri2_ctx);
929   }
930
931   if (!dri2_ctx->dri_context)
932      goto cleanup;
933
934   return &dri2_ctx->base;
935
936 cleanup:
937   free(dri2_ctx);
938   return NULL;
939}
940
941/**
942 * Called via eglDestroyContext(), drv->API.DestroyContext().
943 */
944static EGLBoolean
945dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
946{
947   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
948   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
949
950   if (_eglPutContext(ctx)) {
951      dri2_dpy->core->destroyContext(dri2_ctx->dri_context);
952      free(dri2_ctx);
953   }
954
955   return EGL_TRUE;
956}
957
958/**
959 * Called via eglMakeCurrent(), drv->API.MakeCurrent().
960 */
961static EGLBoolean
962dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
963		  _EGLSurface *rsurf, _EGLContext *ctx)
964{
965   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
966   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
967   struct dri2_egl_surface *dri2_dsurf = dri2_egl_surface(dsurf);
968   struct dri2_egl_surface *dri2_rsurf = dri2_egl_surface(rsurf);
969   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
970   _EGLContext *old_ctx;
971   _EGLSurface *old_dsurf, *old_rsurf;
972   __DRIdrawable *ddraw, *rdraw;
973   __DRIcontext *cctx;
974
975   /* make new bindings */
976   if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
977      return EGL_FALSE;
978
979   /* flush before context switch */
980   if (old_ctx && dri2_drv->glFlush)
981      dri2_drv->glFlush();
982
983   ddraw = (dri2_dsurf) ? dri2_dsurf->dri_drawable : NULL;
984   rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL;
985   cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL;
986
987   if (old_ctx) {
988      __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context;
989      dri2_dpy->core->unbindContext(old_cctx);
990   }
991
992   if ((cctx == NULL && ddraw == NULL && rdraw == NULL) ||
993       dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
994      if (old_dsurf)
995         drv->API.DestroySurface(drv, disp, old_dsurf);
996      if (old_rsurf)
997         drv->API.DestroySurface(drv, disp, old_rsurf);
998      if (old_ctx)
999         drv->API.DestroyContext(drv, disp, old_ctx);
1000
1001      return EGL_TRUE;
1002   } else {
1003      /* undo the previous _eglBindContext */
1004      _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf);
1005      assert(&dri2_ctx->base == ctx &&
1006             &dri2_dsurf->base == dsurf &&
1007             &dri2_rsurf->base == rsurf);
1008
1009      _eglPutSurface(dsurf);
1010      _eglPutSurface(rsurf);
1011      _eglPutContext(ctx);
1012
1013      _eglPutSurface(old_dsurf);
1014      _eglPutSurface(old_rsurf);
1015      _eglPutContext(old_ctx);
1016
1017      return EGL_FALSE;
1018   }
1019}
1020
1021/*
1022 * Called from eglGetProcAddress() via drv->API.GetProcAddress().
1023 */
1024static _EGLProc
1025dri2_get_proc_address(_EGLDriver *drv, const char *procname)
1026{
1027   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
1028
1029   return dri2_drv->get_proc_address(procname);
1030}
1031
1032static _EGLSurface*
1033dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy,
1034                           _EGLConfig *conf, void *native_window,
1035                           const EGLint *attrib_list)
1036{
1037   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1038   return dri2_dpy->vtbl->create_window_surface(drv, dpy, conf, native_window,
1039                                                attrib_list);
1040}
1041
1042static _EGLSurface*
1043dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy,
1044                           _EGLConfig *conf, void *native_pixmap,
1045                           const EGLint *attrib_list)
1046{
1047   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1048   return dri2_dpy->vtbl->create_pixmap_surface(drv, dpy, conf, native_pixmap,
1049                                                attrib_list);
1050}
1051
1052static _EGLSurface*
1053dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy,
1054                           _EGLConfig *conf, const EGLint *attrib_list)
1055{
1056   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1057   return dri2_dpy->vtbl->create_pbuffer_surface(drv, dpy, conf, attrib_list);
1058}
1059
1060static EGLBoolean
1061dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
1062{
1063   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1064   return dri2_dpy->vtbl->destroy_surface(drv, dpy, surf);
1065}
1066
1067static EGLBoolean
1068dri2_swap_interval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
1069                   EGLint interval)
1070{
1071   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1072   return dri2_dpy->vtbl->swap_interval(drv, dpy, surf, interval);
1073}
1074
1075static EGLBoolean
1076dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
1077{
1078   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1079   return dri2_dpy->vtbl->swap_buffers(drv, dpy, surf);
1080}
1081
1082static EGLBoolean
1083dri2_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *dpy,
1084                              _EGLSurface *surf,
1085                              const EGLint *rects, EGLint n_rects)
1086{
1087   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1088   return dri2_dpy->vtbl->swap_buffers_with_damage(drv, dpy, surf,
1089                                                   rects, n_rects);
1090}
1091
1092static EGLBoolean
1093dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
1094                         EGLint numRects, const EGLint *rects)
1095{
1096   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1097   return dri2_dpy->vtbl->swap_buffers_region(drv, dpy, surf, numRects, rects);
1098}
1099
1100static EGLBoolean
1101dri2_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
1102                     EGLint x, EGLint y, EGLint width, EGLint height)
1103{
1104   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1105   return dri2_dpy->vtbl->post_sub_buffer(drv, dpy, surf, x, y, width, height);
1106}
1107
1108static EGLBoolean
1109dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
1110                  void *native_pixmap_target)
1111{
1112   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1113   return dri2_dpy->vtbl->copy_buffers(drv, dpy, surf, native_pixmap_target);
1114}
1115
1116static EGLint
1117dri2_query_buffer_age(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
1118{
1119   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1120   return dri2_dpy->vtbl->query_buffer_age(drv, dpy, surf);
1121}
1122
1123static EGLBoolean
1124dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
1125{
1126   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1127   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(ctx->DrawSurface);
1128
1129   (void) drv;
1130
1131   /* FIXME: If EGL allows frontbuffer rendering for window surfaces,
1132    * we need to copy fake to real here.*/
1133
1134   if (dri2_dpy->flush != NULL)
1135      dri2_dpy->flush->flush(dri2_surf->dri_drawable);
1136
1137   return EGL_TRUE;
1138}
1139
1140static EGLBoolean
1141dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine)
1142{
1143   (void) drv;
1144   (void) disp;
1145
1146   if (engine != EGL_CORE_NATIVE_ENGINE)
1147      return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
1148   /* glXWaitX(); */
1149
1150   return EGL_TRUE;
1151}
1152
1153static EGLBoolean
1154dri2_bind_tex_image(_EGLDriver *drv,
1155		    _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
1156{
1157   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1158   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1159   struct dri2_egl_context *dri2_ctx;
1160   _EGLContext *ctx;
1161   GLint format, target;
1162
1163   ctx = _eglGetCurrentContext();
1164   dri2_ctx = dri2_egl_context(ctx);
1165
1166   if (!_eglBindTexImage(drv, disp, surf, buffer))
1167      return EGL_FALSE;
1168
1169   switch (dri2_surf->base.TextureFormat) {
1170   case EGL_TEXTURE_RGB:
1171      format = __DRI_TEXTURE_FORMAT_RGB;
1172      break;
1173   case EGL_TEXTURE_RGBA:
1174      format = __DRI_TEXTURE_FORMAT_RGBA;
1175      break;
1176   default:
1177      assert(0);
1178   }
1179
1180   switch (dri2_surf->base.TextureTarget) {
1181   case EGL_TEXTURE_2D:
1182      target = GL_TEXTURE_2D;
1183      break;
1184   default:
1185      assert(0);
1186   }
1187
1188   (*dri2_dpy->tex_buffer->setTexBuffer2)(dri2_ctx->dri_context,
1189					  target, format,
1190					  dri2_surf->dri_drawable);
1191
1192   return EGL_TRUE;
1193}
1194
1195static EGLBoolean
1196dri2_release_tex_image(_EGLDriver *drv,
1197		       _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
1198{
1199   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1200   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1201   struct dri2_egl_context *dri2_ctx;
1202   _EGLContext *ctx;
1203   GLint  target;
1204
1205   ctx = _eglGetCurrentContext();
1206   dri2_ctx = dri2_egl_context(ctx);
1207
1208   if (!_eglReleaseTexImage(drv, disp, surf, buffer))
1209      return EGL_FALSE;
1210
1211   switch (dri2_surf->base.TextureTarget) {
1212   case EGL_TEXTURE_2D:
1213      target = GL_TEXTURE_2D;
1214      break;
1215   default:
1216      assert(0);
1217   }
1218
1219   if (dri2_dpy->tex_buffer->base.version >= 3 &&
1220       dri2_dpy->tex_buffer->releaseTexBuffer != NULL) {
1221      (*dri2_dpy->tex_buffer->releaseTexBuffer)(dri2_ctx->dri_context,
1222                                                target,
1223                                                dri2_surf->dri_drawable);
1224   }
1225
1226   return EGL_TRUE;
1227}
1228
1229static _EGLImage*
1230dri2_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
1231                  EGLenum target, EGLClientBuffer buffer,
1232                  const EGLint *attr_list)
1233{
1234   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1235   return dri2_dpy->vtbl->create_image(drv, dpy, ctx, target, buffer,
1236                                       attr_list);
1237}
1238
1239static _EGLImage *
1240dri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image)
1241{
1242   struct dri2_egl_image *dri2_img;
1243
1244   if (dri_image == NULL) {
1245      _eglError(EGL_BAD_ALLOC, "dri2_create_image");
1246      return NULL;
1247   }
1248
1249   dri2_img = malloc(sizeof *dri2_img);
1250   if (!dri2_img) {
1251      _eglError(EGL_BAD_ALLOC, "dri2_create_image");
1252      return NULL;
1253   }
1254
1255   if (!_eglInitImage(&dri2_img->base, disp)) {
1256      free(dri2_img);
1257      return NULL;
1258   }
1259
1260   dri2_img->dri_image = dri_image;
1261
1262   return &dri2_img->base;
1263}
1264
1265static _EGLImage *
1266dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
1267				   EGLClientBuffer buffer,
1268				   const EGLint *attr_list)
1269{
1270   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1271   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1272   GLuint renderbuffer = (GLuint) (uintptr_t) buffer;
1273   __DRIimage *dri_image;
1274
1275   if (renderbuffer == 0) {
1276      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
1277      return EGL_NO_IMAGE_KHR;
1278   }
1279
1280   dri_image =
1281      dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context,
1282                                                   renderbuffer, NULL);
1283
1284   return dri2_create_image_from_dri(disp, dri_image);
1285}
1286
1287#ifdef HAVE_DRM_PLATFORM
1288static _EGLImage *
1289dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
1290				  EGLClientBuffer buffer, const EGLint *attr_list)
1291{
1292   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1293   EGLint format, name, pitch, err;
1294   _EGLImageAttribs attrs;
1295   __DRIimage *dri_image;
1296
1297   name = (EGLint) (uintptr_t) buffer;
1298
1299   err = _eglParseImageAttribList(&attrs, disp, attr_list);
1300   if (err != EGL_SUCCESS)
1301      return NULL;
1302
1303   if (attrs.Width <= 0 || attrs.Height <= 0 ||
1304       attrs.DRMBufferStrideMESA <= 0) {
1305      _eglError(EGL_BAD_PARAMETER,
1306		"bad width, height or stride");
1307      return NULL;
1308   }
1309
1310   switch (attrs.DRMBufferFormatMESA) {
1311   case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
1312      format = __DRI_IMAGE_FORMAT_ARGB8888;
1313      pitch = attrs.DRMBufferStrideMESA;
1314      break;
1315   default:
1316      _eglError(EGL_BAD_PARAMETER,
1317		"dri2_create_image_khr: unsupported pixmap depth");
1318      return NULL;
1319   }
1320
1321   dri_image =
1322      dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
1323					   attrs.Width,
1324					   attrs.Height,
1325					   format,
1326					   name,
1327					   pitch,
1328					   NULL);
1329
1330   return dri2_create_image_from_dri(disp, dri_image);
1331}
1332#endif
1333
1334#ifdef HAVE_WAYLAND_PLATFORM
1335
1336/* This structure describes how a wl_buffer maps to one or more
1337 * __DRIimages.  A wl_drm_buffer stores the wl_drm format code and the
1338 * offsets and strides of the planes in the buffer.  This table maps a
1339 * wl_drm format code to a description of the planes in the buffer
1340 * that lets us create a __DRIimage for each of the planes. */
1341
1342static const struct wl_drm_components_descriptor {
1343   uint32_t dri_components;
1344   EGLint components;
1345   int nplanes;
1346} wl_drm_components[] = {
1347   { __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 },
1348   { __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 },
1349   { __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 },
1350   { __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 },
1351   { __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 },
1352};
1353
1354static _EGLImage *
1355dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
1356				    EGLClientBuffer _buffer,
1357				    const EGLint *attr_list)
1358{
1359   struct wl_drm_buffer *buffer;
1360   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1361   const struct wl_drm_components_descriptor *f;
1362   __DRIimage *dri_image;
1363   _EGLImageAttribs attrs;
1364   EGLint err;
1365   int32_t plane;
1366
1367   buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm,
1368                                   (struct wl_resource *) _buffer);
1369   if (!buffer)
1370       return NULL;
1371
1372   err = _eglParseImageAttribList(&attrs, disp, attr_list);
1373   plane = attrs.PlaneWL;
1374   if (err != EGL_SUCCESS) {
1375      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
1376      return NULL;
1377   }
1378
1379   f = buffer->driver_format;
1380   if (plane < 0 || plane >= f->nplanes) {
1381      _eglError(EGL_BAD_PARAMETER,
1382                "dri2_create_image_wayland_wl_buffer (plane out of bounds)");
1383      return NULL;
1384   }
1385
1386   dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL);
1387
1388   if (dri_image == NULL) {
1389      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
1390      return NULL;
1391   }
1392
1393   return dri2_create_image_from_dri(disp, dri_image);
1394}
1395#endif
1396
1397static EGLBoolean
1398dri2_get_sync_values_chromium(_EGLDisplay *dpy, _EGLSurface *surf,
1399                              EGLuint64KHR *ust, EGLuint64KHR *msc,
1400                              EGLuint64KHR *sbc)
1401{
1402   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1403   return dri2_dpy->vtbl->get_sync_values(dpy, surf, ust, msc, sbc);
1404}
1405
1406/**
1407 * Set the error code after a call to
1408 * dri2_egl_image::dri_image::createImageFromTexture.
1409 */
1410static void
1411dri2_create_image_khr_texture_error(int dri_error)
1412{
1413   EGLint egl_error;
1414
1415   switch (dri_error) {
1416   case __DRI_IMAGE_ERROR_SUCCESS:
1417      return;
1418
1419   case __DRI_IMAGE_ERROR_BAD_ALLOC:
1420      egl_error = EGL_BAD_ALLOC;
1421      break;
1422
1423   case __DRI_IMAGE_ERROR_BAD_MATCH:
1424      egl_error = EGL_BAD_MATCH;
1425      break;
1426
1427   case __DRI_IMAGE_ERROR_BAD_PARAMETER:
1428      egl_error = EGL_BAD_PARAMETER;
1429      break;
1430
1431   default:
1432      assert(0);
1433      egl_error = EGL_BAD_MATCH;
1434      break;
1435   }
1436
1437   _eglError(egl_error, "dri2_create_image_khr_texture");
1438}
1439
1440static _EGLImage *
1441dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
1442				   EGLenum target,
1443				   EGLClientBuffer buffer,
1444				   const EGLint *attr_list)
1445{
1446   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1447   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1448   struct dri2_egl_image *dri2_img;
1449   GLuint texture = (GLuint) (uintptr_t) buffer;
1450   _EGLImageAttribs attrs;
1451   GLuint depth;
1452   GLenum gl_target;
1453   unsigned error;
1454
1455   if (texture == 0) {
1456      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
1457      return EGL_NO_IMAGE_KHR;
1458   }
1459
1460   if (_eglParseImageAttribList(&attrs, disp, attr_list) != EGL_SUCCESS)
1461      return EGL_NO_IMAGE_KHR;
1462
1463   switch (target) {
1464   case EGL_GL_TEXTURE_2D_KHR:
1465      depth = 0;
1466      gl_target = GL_TEXTURE_2D;
1467      break;
1468   case EGL_GL_TEXTURE_3D_KHR:
1469      depth = attrs.GLTextureZOffset;
1470      gl_target = GL_TEXTURE_3D;
1471      break;
1472   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
1473   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
1474   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
1475   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
1476   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
1477   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
1478      depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
1479      gl_target = GL_TEXTURE_CUBE_MAP;
1480      break;
1481   default:
1482      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
1483      return EGL_NO_IMAGE_KHR;
1484   }
1485
1486   dri2_img = malloc(sizeof *dri2_img);
1487   if (!dri2_img) {
1488      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
1489      return EGL_NO_IMAGE_KHR;
1490   }
1491
1492   if (!_eglInitImage(&dri2_img->base, disp)) {
1493      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
1494      free(dri2_img);
1495      return EGL_NO_IMAGE_KHR;
1496   }
1497
1498   dri2_img->dri_image =
1499      dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context,
1500                                              gl_target,
1501                                              texture,
1502                                              depth,
1503                                              attrs.GLTextureLevel,
1504                                              &error,
1505                                              dri2_img);
1506   dri2_create_image_khr_texture_error(error);
1507
1508   if (!dri2_img->dri_image) {
1509      free(dri2_img);
1510      return EGL_NO_IMAGE_KHR;
1511   }
1512   return &dri2_img->base;
1513}
1514
1515static struct wl_buffer*
1516dri2_create_wayland_buffer_from_image(_EGLDriver *drv, _EGLDisplay *dpy,
1517                                      _EGLImage *img)
1518{
1519   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1520   return dri2_dpy->vtbl->create_wayland_buffer_from_image(drv, dpy, img);
1521}
1522
1523#ifdef HAVE_DRM_PLATFORM
1524static EGLBoolean
1525dri2_check_dma_buf_attribs(const _EGLImageAttribs *attrs)
1526{
1527   unsigned i;
1528
1529   /**
1530     * The spec says:
1531     *
1532     * "Required attributes and their values are as follows:
1533     *
1534     *  * EGL_WIDTH & EGL_HEIGHT: The logical dimensions of the buffer in pixels
1535     *
1536     *  * EGL_LINUX_DRM_FOURCC_EXT: The pixel format of the buffer, as specified
1537     *    by drm_fourcc.h and used as the pixel_format parameter of the
1538     *    drm_mode_fb_cmd2 ioctl."
1539     *
1540     * and
1541     *
1542     * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is
1543     *    incomplete, EGL_BAD_PARAMETER is generated."
1544     */
1545   if (attrs->Width <= 0 || attrs->Height <= 0 ||
1546       !attrs->DMABufFourCC.IsPresent) {
1547      _eglError(EGL_BAD_PARAMETER, "attribute(s) missing");
1548      return EGL_FALSE;
1549   }
1550
1551   /**
1552    * Also:
1553    *
1554    * "If <target> is EGL_LINUX_DMA_BUF_EXT and one or more of the values
1555    *  specified for a plane's pitch or offset isn't supported by EGL,
1556    *  EGL_BAD_ACCESS is generated."
1557    */
1558   for (i = 0; i < ARRAY_SIZE(attrs->DMABufPlanePitches); ++i) {
1559      if (attrs->DMABufPlanePitches[i].IsPresent &&
1560          attrs->DMABufPlanePitches[i].Value <= 0) {
1561         _eglError(EGL_BAD_ACCESS, "invalid pitch");
1562         return EGL_FALSE;
1563      }
1564   }
1565
1566   return EGL_TRUE;
1567}
1568
1569/* Returns the total number of file descriptors. Zero indicates an error. */
1570static unsigned
1571dri2_check_dma_buf_format(const _EGLImageAttribs *attrs)
1572{
1573   unsigned i, plane_n;
1574
1575   switch (attrs->DMABufFourCC.Value) {
1576   case DRM_FORMAT_RGB332:
1577   case DRM_FORMAT_BGR233:
1578   case DRM_FORMAT_XRGB4444:
1579   case DRM_FORMAT_XBGR4444:
1580   case DRM_FORMAT_RGBX4444:
1581   case DRM_FORMAT_BGRX4444:
1582   case DRM_FORMAT_ARGB4444:
1583   case DRM_FORMAT_ABGR4444:
1584   case DRM_FORMAT_RGBA4444:
1585   case DRM_FORMAT_BGRA4444:
1586   case DRM_FORMAT_XRGB1555:
1587   case DRM_FORMAT_XBGR1555:
1588   case DRM_FORMAT_RGBX5551:
1589   case DRM_FORMAT_BGRX5551:
1590   case DRM_FORMAT_ARGB1555:
1591   case DRM_FORMAT_ABGR1555:
1592   case DRM_FORMAT_RGBA5551:
1593   case DRM_FORMAT_BGRA5551:
1594   case DRM_FORMAT_RGB565:
1595   case DRM_FORMAT_BGR565:
1596   case DRM_FORMAT_RGB888:
1597   case DRM_FORMAT_BGR888:
1598   case DRM_FORMAT_XRGB8888:
1599   case DRM_FORMAT_XBGR8888:
1600   case DRM_FORMAT_RGBX8888:
1601   case DRM_FORMAT_BGRX8888:
1602   case DRM_FORMAT_ARGB8888:
1603   case DRM_FORMAT_ABGR8888:
1604   case DRM_FORMAT_RGBA8888:
1605   case DRM_FORMAT_BGRA8888:
1606   case DRM_FORMAT_XRGB2101010:
1607   case DRM_FORMAT_XBGR2101010:
1608   case DRM_FORMAT_RGBX1010102:
1609   case DRM_FORMAT_BGRX1010102:
1610   case DRM_FORMAT_ARGB2101010:
1611   case DRM_FORMAT_ABGR2101010:
1612   case DRM_FORMAT_RGBA1010102:
1613   case DRM_FORMAT_BGRA1010102:
1614   case DRM_FORMAT_YUYV:
1615   case DRM_FORMAT_YVYU:
1616   case DRM_FORMAT_UYVY:
1617   case DRM_FORMAT_VYUY:
1618      plane_n = 1;
1619      break;
1620   case DRM_FORMAT_NV12:
1621   case DRM_FORMAT_NV21:
1622   case DRM_FORMAT_NV16:
1623   case DRM_FORMAT_NV61:
1624      plane_n = 2;
1625      break;
1626   case DRM_FORMAT_YUV410:
1627   case DRM_FORMAT_YVU410:
1628   case DRM_FORMAT_YUV411:
1629   case DRM_FORMAT_YVU411:
1630   case DRM_FORMAT_YUV420:
1631   case DRM_FORMAT_YVU420:
1632   case DRM_FORMAT_YUV422:
1633   case DRM_FORMAT_YVU422:
1634   case DRM_FORMAT_YUV444:
1635   case DRM_FORMAT_YVU444:
1636      plane_n = 3;
1637      break;
1638   default:
1639      _eglError(EGL_BAD_ATTRIBUTE, "invalid format");
1640      return 0;
1641   }
1642
1643   /**
1644     * The spec says:
1645     *
1646     * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is
1647     *    incomplete, EGL_BAD_PARAMETER is generated."
1648     */
1649   for (i = 0; i < plane_n; ++i) {
1650      if (!attrs->DMABufPlaneFds[i].IsPresent ||
1651          !attrs->DMABufPlaneOffsets[i].IsPresent ||
1652          !attrs->DMABufPlanePitches[i].IsPresent) {
1653         _eglError(EGL_BAD_PARAMETER, "plane attribute(s) missing");
1654         return 0;
1655      }
1656   }
1657
1658   /**
1659    * The spec also says:
1660    *
1661    * "If <target> is EGL_LINUX_DMA_BUF_EXT, and the EGL_LINUX_DRM_FOURCC_EXT
1662    *  attribute indicates a single-plane format, EGL_BAD_ATTRIBUTE is
1663    *  generated if any of the EGL_DMA_BUF_PLANE1_* or EGL_DMA_BUF_PLANE2_*
1664    *  attributes are specified."
1665    */
1666   for (i = plane_n; i < 3; ++i) {
1667      if (attrs->DMABufPlaneFds[i].IsPresent ||
1668          attrs->DMABufPlaneOffsets[i].IsPresent ||
1669          attrs->DMABufPlanePitches[i].IsPresent) {
1670         _eglError(EGL_BAD_ATTRIBUTE, "too many plane attributes");
1671         return 0;
1672      }
1673   }
1674
1675   return plane_n;
1676}
1677
1678/**
1679 * The spec says:
1680 *
1681 * "If eglCreateImageKHR is successful for a EGL_LINUX_DMA_BUF_EXT target, the
1682 *  EGL will take a reference to the dma_buf(s) which it will release at any
1683 *  time while the EGLDisplay is initialized. It is the responsibility of the
1684 *  application to close the dma_buf file descriptors."
1685 *
1686 * Therefore we must never close or otherwise modify the file descriptors.
1687 */
1688static _EGLImage *
1689dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
1690			  EGLClientBuffer buffer, const EGLint *attr_list)
1691{
1692   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1693   _EGLImage *res;
1694   EGLint err;
1695   _EGLImageAttribs attrs;
1696   __DRIimage *dri_image;
1697   unsigned num_fds;
1698   unsigned i;
1699   int fds[3];
1700   int pitches[3];
1701   int offsets[3];
1702   unsigned error;
1703
1704   /**
1705    * The spec says:
1706    *
1707    * ""* If <target> is EGL_LINUX_DMA_BUF_EXT and <buffer> is not NULL, the
1708    *     error EGL_BAD_PARAMETER is generated."
1709    */
1710   if (buffer != NULL) {
1711      _eglError(EGL_BAD_PARAMETER, "buffer not NULL");
1712      return NULL;
1713   }
1714
1715   err = _eglParseImageAttribList(&attrs, disp, attr_list);
1716   if (err != EGL_SUCCESS) {
1717      _eglError(err, "bad attribute");
1718      return NULL;
1719   }
1720
1721   if (!dri2_check_dma_buf_attribs(&attrs))
1722      return NULL;
1723
1724   num_fds = dri2_check_dma_buf_format(&attrs);
1725   if (!num_fds)
1726      return NULL;
1727
1728   for (i = 0; i < num_fds; ++i) {
1729      fds[i] = attrs.DMABufPlaneFds[i].Value;
1730      pitches[i] = attrs.DMABufPlanePitches[i].Value;
1731      offsets[i] = attrs.DMABufPlaneOffsets[i].Value;
1732   }
1733
1734   dri_image =
1735      dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen,
1736         attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
1737         fds, num_fds, pitches, offsets,
1738         attrs.DMABufYuvColorSpaceHint.Value,
1739         attrs.DMABufSampleRangeHint.Value,
1740         attrs.DMABufChromaHorizontalSiting.Value,
1741         attrs.DMABufChromaVerticalSiting.Value,
1742         &error,
1743         NULL);
1744   dri2_create_image_khr_texture_error(error);
1745
1746   if (!dri_image)
1747      return EGL_NO_IMAGE_KHR;
1748
1749   res = dri2_create_image_from_dri(disp, dri_image);
1750
1751   return res;
1752}
1753#endif
1754
1755_EGLImage *
1756dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
1757		      _EGLContext *ctx, EGLenum target,
1758		      EGLClientBuffer buffer, const EGLint *attr_list)
1759{
1760   (void) drv;
1761
1762   switch (target) {
1763   case EGL_GL_TEXTURE_2D_KHR:
1764   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
1765   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
1766   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
1767   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
1768   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
1769   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
1770      return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
1771   case EGL_GL_RENDERBUFFER_KHR:
1772      return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
1773#ifdef HAVE_DRM_PLATFORM
1774   case EGL_DRM_BUFFER_MESA:
1775      return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
1776#endif
1777#ifdef HAVE_WAYLAND_PLATFORM
1778   case EGL_WAYLAND_BUFFER_WL:
1779      return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
1780#endif
1781#ifdef HAVE_DRM_PLATFORM
1782   case EGL_LINUX_DMA_BUF_EXT:
1783      return dri2_create_image_dma_buf(disp, ctx, buffer, attr_list);
1784#endif
1785   default:
1786      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
1787      return EGL_NO_IMAGE_KHR;
1788   }
1789}
1790
1791static EGLBoolean
1792dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image)
1793{
1794   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1795   struct dri2_egl_image *dri2_img = dri2_egl_image(image);
1796
1797   (void) drv;
1798
1799   dri2_dpy->image->destroyImage(dri2_img->dri_image);
1800   free(dri2_img);
1801
1802   return EGL_TRUE;
1803}
1804
1805#ifdef HAVE_DRM_PLATFORM
1806static _EGLImage *
1807dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp,
1808			   const EGLint *attr_list)
1809{
1810   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1811   struct dri2_egl_image *dri2_img;
1812   _EGLImageAttribs attrs;
1813   unsigned int dri_use, valid_mask;
1814   int format;
1815   EGLint err = EGL_SUCCESS;
1816
1817   (void) drv;
1818
1819   dri2_img = malloc(sizeof *dri2_img);
1820   if (!dri2_img) {
1821      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
1822      return EGL_NO_IMAGE_KHR;
1823   }
1824
1825   if (!attr_list) {
1826      err = EGL_BAD_PARAMETER;
1827      goto cleanup_img;
1828   }
1829
1830   if (!_eglInitImage(&dri2_img->base, disp)) {
1831      err = EGL_BAD_PARAMETER;
1832      goto cleanup_img;
1833   }
1834
1835   err = _eglParseImageAttribList(&attrs, disp, attr_list);
1836   if (err != EGL_SUCCESS)
1837      goto cleanup_img;
1838
1839   if (attrs.Width <= 0 || attrs.Height <= 0) {
1840      _eglLog(_EGL_WARNING, "bad width or height (%dx%d)",
1841            attrs.Width, attrs.Height);
1842      goto cleanup_img;
1843   }
1844
1845   switch (attrs.DRMBufferFormatMESA) {
1846   case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
1847      format = __DRI_IMAGE_FORMAT_ARGB8888;
1848      break;
1849   default:
1850      _eglLog(_EGL_WARNING, "bad image format value 0x%04x",
1851            attrs.DRMBufferFormatMESA);
1852      goto cleanup_img;
1853   }
1854
1855   valid_mask =
1856      EGL_DRM_BUFFER_USE_SCANOUT_MESA |
1857      EGL_DRM_BUFFER_USE_SHARE_MESA |
1858      EGL_DRM_BUFFER_USE_CURSOR_MESA;
1859   if (attrs.DRMBufferUseMESA & ~valid_mask) {
1860      _eglLog(_EGL_WARNING, "bad image use bit 0x%04x",
1861            attrs.DRMBufferUseMESA & ~valid_mask);
1862      goto cleanup_img;
1863   }
1864
1865   dri_use = 0;
1866   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA)
1867      dri_use |= __DRI_IMAGE_USE_SHARE;
1868   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
1869      dri_use |= __DRI_IMAGE_USE_SCANOUT;
1870   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA)
1871      dri_use |= __DRI_IMAGE_USE_CURSOR;
1872
1873   dri2_img->dri_image =
1874      dri2_dpy->image->createImage(dri2_dpy->dri_screen,
1875				   attrs.Width, attrs.Height,
1876                                   format, dri_use, dri2_img);
1877   if (dri2_img->dri_image == NULL) {
1878      err = EGL_BAD_ALLOC;
1879      goto cleanup_img;
1880   }
1881
1882   return &dri2_img->base;
1883
1884 cleanup_img:
1885   free(dri2_img);
1886   _eglError(err, "dri2_create_drm_image_mesa");
1887
1888   return EGL_NO_IMAGE_KHR;
1889}
1890
1891static EGLBoolean
1892dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
1893			  EGLint *name, EGLint *handle, EGLint *stride)
1894{
1895   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1896   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
1897
1898   (void) drv;
1899
1900   if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image,
1901					    __DRI_IMAGE_ATTRIB_NAME, name)) {
1902      _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa");
1903      return EGL_FALSE;
1904   }
1905
1906   if (handle)
1907      dri2_dpy->image->queryImage(dri2_img->dri_image,
1908				  __DRI_IMAGE_ATTRIB_HANDLE, handle);
1909
1910   if (stride)
1911      dri2_dpy->image->queryImage(dri2_img->dri_image,
1912				  __DRI_IMAGE_ATTRIB_STRIDE, stride);
1913
1914   return EGL_TRUE;
1915}
1916#endif
1917
1918#ifdef HAVE_WAYLAND_PLATFORM
1919
1920static void
1921dri2_wl_reference_buffer(void *user_data, uint32_t name, int fd,
1922                         struct wl_drm_buffer *buffer)
1923{
1924   _EGLDisplay *disp = user_data;
1925   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1926   __DRIimage *img;
1927   int i, dri_components = 0;
1928
1929   if (fd == -1)
1930      img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen,
1931                                                  buffer->width,
1932                                                  buffer->height,
1933                                                  buffer->format,
1934                                                  (int*)&name, 1,
1935                                                  buffer->stride,
1936                                                  buffer->offset,
1937                                                  NULL);
1938   else
1939      img = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
1940                                                buffer->width,
1941                                                buffer->height,
1942                                                buffer->format,
1943                                                &fd, 1,
1944                                                buffer->stride,
1945                                                buffer->offset,
1946                                                NULL);
1947
1948   if (img == NULL)
1949      return;
1950
1951   dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components);
1952
1953   buffer->driver_format = NULL;
1954   for (i = 0; i < ARRAY_SIZE(wl_drm_components); i++)
1955      if (wl_drm_components[i].dri_components == dri_components)
1956         buffer->driver_format = &wl_drm_components[i];
1957
1958   if (buffer->driver_format == NULL)
1959      dri2_dpy->image->destroyImage(img);
1960   else
1961      buffer->driver_buffer = img;
1962}
1963
1964static void
1965dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer)
1966{
1967   _EGLDisplay *disp = user_data;
1968   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1969
1970   dri2_dpy->image->destroyImage(buffer->driver_buffer);
1971}
1972
1973static struct wayland_drm_callbacks wl_drm_callbacks = {
1974	.authenticate = NULL,
1975	.reference_buffer = dri2_wl_reference_buffer,
1976	.release_buffer = dri2_wl_release_buffer
1977};
1978
1979static EGLBoolean
1980dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
1981			     struct wl_display *wl_dpy)
1982{
1983   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1984   int flags = 0;
1985   uint64_t cap;
1986
1987   (void) drv;
1988
1989   if (dri2_dpy->wl_server_drm)
1990	   return EGL_FALSE;
1991
1992   wl_drm_callbacks.authenticate =
1993      (int(*)(void *, uint32_t)) dri2_dpy->vtbl->authenticate;
1994
1995#ifdef HAVE_LIBDRM
1996   if (drmGetCap(dri2_dpy->fd, DRM_CAP_PRIME, &cap) == 0 &&
1997       cap == (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT) &&
1998       dri2_dpy->image->base.version >= 7 &&
1999       dri2_dpy->image->createImageFromFds != NULL)
2000      flags |= WAYLAND_DRM_PRIME;
2001#endif
2002
2003   dri2_dpy->wl_server_drm =
2004	   wayland_drm_init(wl_dpy, dri2_dpy->device_name,
2005                            &wl_drm_callbacks, disp, flags);
2006
2007   if (!dri2_dpy->wl_server_drm)
2008	   return EGL_FALSE;
2009
2010#ifdef HAVE_DRM_PLATFORM
2011   /* We have to share the wl_drm instance with gbm, so gbm can convert
2012    * wl_buffers to gbm bos. */
2013   if (dri2_dpy->gbm_dri)
2014      dri2_dpy->gbm_dri->wl_drm = dri2_dpy->wl_server_drm;
2015#endif
2016
2017   return EGL_TRUE;
2018}
2019
2020static EGLBoolean
2021dri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
2022			       struct wl_display *wl_dpy)
2023{
2024   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2025
2026   (void) drv;
2027
2028   if (!dri2_dpy->wl_server_drm)
2029	   return EGL_FALSE;
2030
2031   wayland_drm_uninit(dri2_dpy->wl_server_drm);
2032   dri2_dpy->wl_server_drm = NULL;
2033
2034   return EGL_TRUE;
2035}
2036
2037static EGLBoolean
2038dri2_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *disp,
2039                             struct wl_resource *buffer_resource,
2040                             EGLint attribute, EGLint *value)
2041{
2042   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2043   struct wl_drm_buffer *buffer;
2044   const struct wl_drm_components_descriptor *format;
2045
2046   buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm, buffer_resource);
2047   if (!buffer)
2048      return EGL_FALSE;
2049
2050   format = buffer->driver_format;
2051   switch (attribute) {
2052   case EGL_TEXTURE_FORMAT:
2053      *value = format->components;
2054      return EGL_TRUE;
2055   case EGL_WIDTH:
2056      *value = buffer->width;
2057      return EGL_TRUE;
2058   case EGL_HEIGHT:
2059      *value = buffer->height;
2060      return EGL_TRUE;
2061   }
2062
2063   return EGL_FALSE;
2064}
2065#endif
2066
2067static void
2068dri2_unload(_EGLDriver *drv)
2069{
2070   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
2071
2072   if (dri2_drv->handle)
2073      dlclose(dri2_drv->handle);
2074   free(dri2_drv);
2075}
2076
2077static EGLBoolean
2078dri2_load(_EGLDriver *drv)
2079{
2080   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
2081#ifdef HAVE_SHARED_GLAPI
2082#ifdef HAVE_ANDROID_PLATFORM
2083   const char *libname = "libglapi.so";
2084#else
2085   const char *libname = "libglapi.so.0";
2086#endif
2087#else
2088   /*
2089    * Both libGL.so and libglapi.so are glapi providers.  There is no way to
2090    * tell which one to load.
2091    */
2092   const char *libname = NULL;
2093#endif
2094   void *handle;
2095
2096   /* RTLD_GLOBAL to make sure glapi symbols are visible to DRI drivers */
2097   handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL);
2098   if (handle) {
2099      dri2_drv->get_proc_address = (_EGLProc (*)(const char *))
2100         dlsym(handle, "_glapi_get_proc_address");
2101      if (!dri2_drv->get_proc_address || !libname) {
2102         /* no need to keep a reference */
2103         dlclose(handle);
2104         handle = NULL;
2105      }
2106   }
2107
2108   /* if glapi is not available, loading DRI drivers will fail */
2109   if (!dri2_drv->get_proc_address) {
2110      _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address");
2111      return EGL_FALSE;
2112   }
2113
2114   dri2_drv->glFlush = (void (*)(void))
2115      dri2_drv->get_proc_address("glFlush");
2116
2117   dri2_drv->handle = handle;
2118
2119   return EGL_TRUE;
2120}
2121
2122/**
2123 * This is the main entrypoint into the driver, called by libEGL.
2124 * Create a new _EGLDriver object and init its dispatch table.
2125 */
2126_EGLDriver *
2127_eglBuiltInDriverDRI2(const char *args)
2128{
2129   struct dri2_egl_driver *dri2_drv;
2130
2131   (void) args;
2132
2133   dri2_drv = calloc(1, sizeof *dri2_drv);
2134   if (!dri2_drv)
2135      return NULL;
2136
2137   if (!dri2_load(&dri2_drv->base)) {
2138      free(dri2_drv);
2139      return NULL;
2140   }
2141
2142   _eglInitDriverFallbacks(&dri2_drv->base);
2143   dri2_drv->base.API.Initialize = dri2_initialize;
2144   dri2_drv->base.API.Terminate = dri2_terminate;
2145   dri2_drv->base.API.CreateContext = dri2_create_context;
2146   dri2_drv->base.API.DestroyContext = dri2_destroy_context;
2147   dri2_drv->base.API.MakeCurrent = dri2_make_current;
2148   dri2_drv->base.API.CreateWindowSurface = dri2_create_window_surface;
2149   dri2_drv->base.API.CreatePixmapSurface = dri2_create_pixmap_surface;
2150   dri2_drv->base.API.CreatePbufferSurface = dri2_create_pbuffer_surface;
2151   dri2_drv->base.API.DestroySurface = dri2_destroy_surface;
2152   dri2_drv->base.API.GetProcAddress = dri2_get_proc_address;
2153   dri2_drv->base.API.WaitClient = dri2_wait_client;
2154   dri2_drv->base.API.WaitNative = dri2_wait_native;
2155   dri2_drv->base.API.BindTexImage = dri2_bind_tex_image;
2156   dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image;
2157   dri2_drv->base.API.SwapInterval = dri2_swap_interval;
2158   dri2_drv->base.API.SwapBuffers = dri2_swap_buffers;
2159   dri2_drv->base.API.SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage;
2160   dri2_drv->base.API.SwapBuffersRegionNOK = dri2_swap_buffers_region;
2161   dri2_drv->base.API.PostSubBufferNV = dri2_post_sub_buffer;
2162   dri2_drv->base.API.CopyBuffers = dri2_copy_buffers,
2163   dri2_drv->base.API.QueryBufferAge = dri2_query_buffer_age;
2164   dri2_drv->base.API.CreateImageKHR = dri2_create_image;
2165   dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr;
2166   dri2_drv->base.API.CreateWaylandBufferFromImageWL = dri2_create_wayland_buffer_from_image;
2167#ifdef HAVE_DRM_PLATFORM
2168   dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
2169   dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
2170#endif
2171#ifdef HAVE_WAYLAND_PLATFORM
2172   dri2_drv->base.API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl;
2173   dri2_drv->base.API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl;
2174   dri2_drv->base.API.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl;
2175#endif
2176   dri2_drv->base.API.GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium;
2177
2178   dri2_drv->base.Name = "DRI2";
2179   dri2_drv->base.Unload = dri2_unload;
2180
2181   return &dri2_drv->base;
2182}
2183