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