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