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