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