OSDN Git Service

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