Revert "egl/dri2: Don't dlclose() the driver on dri2_load_driver_common failure"
[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 }
1010 if (dri2_dpy->image->base.version >= 15 &&
1011 dri2_dpy->image->createImageFromDmaBufs2 &&
1012 dri2_dpy->image->queryDmaBufFormats &&
1013 dri2_dpy->image->queryDmaBufModifiers) {
1014 disp->Extensions.EXT_image_dma_buf_import_modifiers = EGL_TRUE;
1015 }
1016 #endif
1017 }
1018
1019 if (dri2_dpy->flush_control)
1020 disp->Extensions.KHR_context_flush_control = EGL_TRUE;
1021
1022 if (dri2_dpy->buffer_damage && dri2_dpy->buffer_damage->set_damage_region)
1023 disp->Extensions.KHR_partial_update = EGL_TRUE;
1024 }
1025
1026 void
1027 dri2_setup_swap_interval(_EGLDisplay *disp, int max_swap_interval)
1028 {
1029 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1030 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
1031
1032 /* Allow driconf to override applications.*/
1033 if (dri2_dpy->config)
1034 dri2_dpy->config->configQueryi(dri2_dpy->dri_screen,
1035 "vblank_mode", &vblank_mode);
1036 switch (vblank_mode) {
1037 case DRI_CONF_VBLANK_NEVER:
1038 dri2_dpy->min_swap_interval = 0;
1039 dri2_dpy->max_swap_interval = 0;
1040 dri2_dpy->default_swap_interval = 0;
1041 break;
1042 case DRI_CONF_VBLANK_ALWAYS_SYNC:
1043 dri2_dpy->min_swap_interval = 1;
1044 dri2_dpy->max_swap_interval = max_swap_interval;
1045 dri2_dpy->default_swap_interval = 1;
1046 break;
1047 case DRI_CONF_VBLANK_DEF_INTERVAL_0:
1048 dri2_dpy->min_swap_interval = 0;
1049 dri2_dpy->max_swap_interval = max_swap_interval;
1050 dri2_dpy->default_swap_interval = 0;
1051 break;
1052 default:
1053 case DRI_CONF_VBLANK_DEF_INTERVAL_1:
1054 dri2_dpy->min_swap_interval = 0;
1055 dri2_dpy->max_swap_interval = max_swap_interval;
1056 dri2_dpy->default_swap_interval = 1;
1057 break;
1058 }
1059 }
1060
1061 /* All platforms but DRM call this function to create the screen and populate
1062 * the driver_configs. DRM inherits that information from its display - GBM.
1063 */
1064 EGLBoolean
1065 dri2_create_screen(_EGLDisplay *disp)
1066 {
1067 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1068
1069 if (dri2_dpy->image_driver) {
1070 dri2_dpy->dri_screen =
1071 dri2_dpy->image_driver->createNewScreen2(0, dri2_dpy->fd,
1072 dri2_dpy->loader_extensions,
1073 dri2_dpy->driver_extensions,
1074 &dri2_dpy->driver_configs,
1075 disp);
1076 } else if (dri2_dpy->dri2) {
1077 if (dri2_dpy->dri2->base.version >= 4) {
1078 dri2_dpy->dri_screen =
1079 dri2_dpy->dri2->createNewScreen2(0, dri2_dpy->fd,
1080 dri2_dpy->loader_extensions,
1081 dri2_dpy->driver_extensions,
1082 &dri2_dpy->driver_configs, disp);
1083 } else {
1084 dri2_dpy->dri_screen =
1085 dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd,
1086 dri2_dpy->loader_extensions,
1087 &dri2_dpy->driver_configs, disp);
1088 }
1089 } else {
1090 assert(dri2_dpy->swrast);
1091 if (dri2_dpy->swrast->base.version >= 4) {
1092 dri2_dpy->dri_screen =
1093 dri2_dpy->swrast->createNewScreen2(0, dri2_dpy->loader_extensions,
1094 dri2_dpy->driver_extensions,
1095 &dri2_dpy->driver_configs, disp);
1096 } else {
1097 dri2_dpy->dri_screen =
1098 dri2_dpy->swrast->createNewScreen(0, dri2_dpy->loader_extensions,
1099 &dri2_dpy->driver_configs, disp);
1100 }
1101 }
1102
1103 if (dri2_dpy->dri_screen == NULL) {
1104 _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
1105 return EGL_FALSE;
1106 }
1107
1108 dri2_dpy->own_dri_screen = true;
1109 return EGL_TRUE;
1110 }
1111
1112 EGLBoolean
1113 dri2_setup_extensions(_EGLDisplay *disp)
1114 {
1115 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1116 const struct dri2_extension_match *mandatory_core_extensions;
1117 const __DRIextension **extensions;
1118
1119 extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
1120
1121 if (dri2_dpy->image_driver || dri2_dpy->dri2)
1122 mandatory_core_extensions = dri2_core_extensions;
1123 else
1124 mandatory_core_extensions = swrast_core_extensions;
1125
1126 if (!dri2_bind_extensions(dri2_dpy, mandatory_core_extensions, extensions, false))
1127 return EGL_FALSE;
1128
1129 #ifdef HAVE_DRI3_MODIFIERS
1130 dri2_dpy->multibuffers_available =
1131 (dri2_dpy->dri3_major_version > 1 || (dri2_dpy->dri3_major_version == 1 &&
1132 dri2_dpy->dri3_minor_version >= 2)) &&
1133 (dri2_dpy->present_major_version > 1 || (dri2_dpy->present_major_version == 1 &&
1134 dri2_dpy->present_minor_version >= 2)) &&
1135 (dri2_dpy->image && dri2_dpy->image->base.version >= 15);
1136 #endif
1137
1138 dri2_bind_extensions(dri2_dpy, optional_core_extensions, extensions, true);
1139 return EGL_TRUE;
1140 }
1141
1142 /**
1143 * Called via eglInitialize(), GLX_drv->API.Initialize().
1144 *
1145 * This must be guaranteed to be called exactly once, even if eglInitialize is
1146 * called many times (without a eglTerminate in between).
1147 */
1148 static EGLBoolean
1149 dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp)
1150 {
1151 EGLBoolean ret = EGL_FALSE;
1152 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1153
1154 /* In the case where the application calls eglMakeCurrent(context1),
1155 * eglTerminate, then eglInitialize again (without a call to eglReleaseThread
1156 * or eglMakeCurrent(NULL) before that), dri2_dpy structure is still
1157 * initialized, as we need it to be able to free context1 correctly.
1158 *
1159 * It would probably be safest to forcibly release the display with
1160 * dri2_display_release, to make sure the display is reinitialized correctly.
1161 * However, the EGL spec states that we need to keep a reference to the
1162 * current context (so we cannot call dri2_make_current(NULL)), and therefore
1163 * we would leak context1 as we would be missing the old display connection
1164 * to free it up correctly.
1165 */
1166 if (dri2_dpy) {
1167 dri2_dpy->ref_count++;
1168 return EGL_TRUE;
1169 }
1170
1171 loader_set_logger(_eglLog);
1172
1173 switch (disp->Platform) {
1174 case _EGL_PLATFORM_SURFACELESS:
1175 ret = dri2_initialize_surfaceless(drv, disp);
1176 break;
1177 case _EGL_PLATFORM_DEVICE:
1178 ret = dri2_initialize_device(drv, disp);
1179 break;
1180 case _EGL_PLATFORM_X11:
1181 ret = dri2_initialize_x11(drv, disp);
1182 break;
1183 case _EGL_PLATFORM_DRM:
1184 ret = dri2_initialize_drm(drv, disp);
1185 break;
1186 case _EGL_PLATFORM_WAYLAND:
1187 ret = dri2_initialize_wayland(drv, disp);
1188 break;
1189 case _EGL_PLATFORM_ANDROID:
1190 ret = dri2_initialize_android(drv, disp);
1191 break;
1192 default:
1193 unreachable("Callers ensure we cannot get here.");
1194 return EGL_FALSE;
1195 }
1196
1197 if (!ret)
1198 return EGL_FALSE;
1199
1200 dri2_dpy = dri2_egl_display(disp);
1201 dri2_dpy->ref_count++;
1202
1203 return EGL_TRUE;
1204 }
1205
1206 /**
1207 * Decrement display reference count, and free up display if necessary.
1208 */
1209 static void
1210 dri2_display_release(_EGLDisplay *disp)
1211 {
1212 struct dri2_egl_display *dri2_dpy;
1213
1214 if (!disp)
1215 return;
1216
1217 dri2_dpy = dri2_egl_display(disp);
1218
1219 assert(dri2_dpy->ref_count > 0);
1220 dri2_dpy->ref_count--;
1221
1222 if (dri2_dpy->ref_count > 0)
1223 return;
1224
1225 _eglCleanupDisplay(disp);
1226 dri2_display_destroy(disp);
1227 }
1228
1229 void
1230 dri2_display_destroy(_EGLDisplay *disp)
1231 {
1232 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1233
1234 if (dri2_dpy->own_dri_screen) {
1235 if (dri2_dpy->vtbl && dri2_dpy->vtbl->close_screen_notify)
1236 dri2_dpy->vtbl->close_screen_notify(disp);
1237 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
1238 }
1239 if (dri2_dpy->fd >= 0)
1240 close(dri2_dpy->fd);
1241 if (dri2_dpy->driver)
1242 dlclose(dri2_dpy->driver);
1243 free(dri2_dpy->driver_name);
1244
1245 #ifdef HAVE_WAYLAND_PLATFORM
1246 free(dri2_dpy->device_name);
1247 #endif
1248
1249 switch (disp->Platform) {
1250 case _EGL_PLATFORM_X11:
1251 dri2_teardown_x11(dri2_dpy);
1252 break;
1253 case _EGL_PLATFORM_DRM:
1254 dri2_teardown_drm(dri2_dpy);
1255 break;
1256 case _EGL_PLATFORM_WAYLAND:
1257 dri2_teardown_wayland(dri2_dpy);
1258 break;
1259 default:
1260 /* TODO: add teardown for other platforms */
1261 break;
1262 }
1263
1264 /* The drm platform does not create the screen/driver_configs but reuses
1265 * the ones from the gbm device. As such the gbm itself is responsible
1266 * for the cleanup.
1267 */
1268 if (disp->Platform != _EGL_PLATFORM_DRM && dri2_dpy->driver_configs) {
1269 for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++)
1270 free((__DRIconfig *) dri2_dpy->driver_configs[i]);
1271 free(dri2_dpy->driver_configs);
1272 }
1273 free(dri2_dpy);
1274 disp->DriverData = NULL;
1275 }
1276
1277 __DRIbuffer *
1278 dri2_egl_surface_alloc_local_buffer(struct dri2_egl_surface *dri2_surf,
1279 unsigned int att, unsigned int format)
1280 {
1281 struct dri2_egl_display *dri2_dpy =
1282 dri2_egl_display(dri2_surf->base.Resource.Display);
1283
1284 if (att >= ARRAY_SIZE(dri2_surf->local_buffers))
1285 return NULL;
1286
1287 if (!dri2_surf->local_buffers[att]) {
1288 dri2_surf->local_buffers[att] =
1289 dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, att, format,
1290 dri2_surf->base.Width, dri2_surf->base.Height);
1291 }
1292
1293 return dri2_surf->local_buffers[att];
1294 }
1295
1296 void
1297 dri2_egl_surface_free_local_buffers(struct dri2_egl_surface *dri2_surf)
1298 {
1299 struct dri2_egl_display *dri2_dpy =
1300 dri2_egl_display(dri2_surf->base.Resource.Display);
1301
1302 for (int i = 0; i < ARRAY_SIZE(dri2_surf->local_buffers); i++) {
1303 if (dri2_surf->local_buffers[i]) {
1304 dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
1305 dri2_surf->local_buffers[i]);
1306 dri2_surf->local_buffers[i] = NULL;
1307 }
1308 }
1309 }
1310
1311 /**
1312 * Called via eglTerminate(), drv->API.Terminate().
1313 *
1314 * This must be guaranteed to be called exactly once, even if eglTerminate is
1315 * called many times (without a eglInitialize in between).
1316 */
1317 static EGLBoolean
1318 dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
1319 {
1320 /* Release all non-current Context/Surfaces. */
1321 _eglReleaseDisplayResources(drv, disp);
1322
1323 dri2_display_release(disp);
1324
1325 return EGL_TRUE;
1326 }
1327
1328 /**
1329 * Set the error code after a call to
1330 * dri2_egl_display::dri2::createContextAttribs.
1331 */
1332 static void
1333 dri2_create_context_attribs_error(int dri_error)
1334 {
1335 EGLint egl_error;
1336
1337 switch (dri_error) {
1338 case __DRI_CTX_ERROR_SUCCESS:
1339 return;
1340
1341 case __DRI_CTX_ERROR_NO_MEMORY:
1342 egl_error = EGL_BAD_ALLOC;
1343 break;
1344
1345 /* From the EGL_KHR_create_context spec, section "Errors":
1346 *
1347 * * If <config> does not support a client API context compatible
1348 * with the requested API major and minor version, [...] context flags,
1349 * and context reset notification behavior (for client API types where
1350 * these attributes are supported), then an EGL_BAD_MATCH error is
1351 * generated.
1352 *
1353 * * If an OpenGL ES context is requested and the values for
1354 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
1355 * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
1356 * is not defined, than an EGL_BAD_MATCH error is generated.
1357 *
1358 * * If an OpenGL context is requested, the requested version is
1359 * greater than 3.2, and the value for attribute
1360 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has any
1361 * bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and
1362 * EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than
1363 * one of these bits set; or if the implementation does not support
1364 * the requested profile, then an EGL_BAD_MATCH error is generated.
1365 */
1366 case __DRI_CTX_ERROR_BAD_API:
1367 case __DRI_CTX_ERROR_BAD_VERSION:
1368 case __DRI_CTX_ERROR_BAD_FLAG:
1369 egl_error = EGL_BAD_MATCH;
1370 break;
1371
1372 /* From the EGL_KHR_create_context spec, section "Errors":
1373 *
1374 * * If an attribute name or attribute value in <attrib_list> is not
1375 * recognized (including unrecognized bits in bitmask attributes),
1376 * then an EGL_BAD_ATTRIBUTE error is generated."
1377 */
1378 case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE:
1379 case __DRI_CTX_ERROR_UNKNOWN_FLAG:
1380 egl_error = EGL_BAD_ATTRIBUTE;
1381 break;
1382
1383 default:
1384 assert(!"unknown dri_error code");
1385 egl_error = EGL_BAD_MATCH;
1386 break;
1387 }
1388
1389 _eglError(egl_error, "dri2_create_context");
1390 }
1391
1392 static bool
1393 dri2_fill_context_attribs(struct dri2_egl_context *dri2_ctx,
1394 struct dri2_egl_display *dri2_dpy,
1395 uint32_t *ctx_attribs,
1396 unsigned *num_attribs)
1397 {
1398 int pos = 0;
1399
1400 assert(*num_attribs >= NUM_ATTRIBS);
1401
1402 ctx_attribs[pos++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
1403 ctx_attribs[pos++] = dri2_ctx->base.ClientMajorVersion;
1404 ctx_attribs[pos++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
1405 ctx_attribs[pos++] = dri2_ctx->base.ClientMinorVersion;
1406
1407 if (dri2_ctx->base.Flags != 0 || dri2_ctx->base.NoError) {
1408 /* If the implementation doesn't support the __DRI2_ROBUSTNESS
1409 * extension, don't even try to send it the robust-access flag.
1410 * It may explode. Instead, generate the required EGL error here.
1411 */
1412 if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0
1413 && !dri2_dpy->robustness) {
1414 _eglError(EGL_BAD_MATCH, "eglCreateContext");
1415 return false;
1416 }
1417
1418 ctx_attribs[pos++] = __DRI_CTX_ATTRIB_FLAGS;
1419 ctx_attribs[pos++] = dri2_ctx->base.Flags |
1420 (dri2_ctx->base.NoError ? __DRI_CTX_FLAG_NO_ERROR : 0);
1421 }
1422
1423 if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) {
1424 /* If the implementation doesn't support the __DRI2_ROBUSTNESS
1425 * extension, don't even try to send it a reset strategy. It may
1426 * explode. Instead, generate the required EGL error here.
1427 */
1428 if (!dri2_dpy->robustness) {
1429 _eglError(EGL_BAD_CONFIG, "eglCreateContext");
1430 return false;
1431 }
1432
1433 ctx_attribs[pos++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
1434 ctx_attribs[pos++] = __DRI_CTX_RESET_LOSE_CONTEXT;
1435 }
1436
1437 if (dri2_ctx->base.ContextPriority != EGL_CONTEXT_PRIORITY_MEDIUM_IMG) {
1438 unsigned val;
1439
1440 switch (dri2_ctx->base.ContextPriority) {
1441 case EGL_CONTEXT_PRIORITY_HIGH_IMG:
1442 val = __DRI_CTX_PRIORITY_HIGH;
1443 break;
1444 case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
1445 val = __DRI_CTX_PRIORITY_MEDIUM;
1446 break;
1447 case EGL_CONTEXT_PRIORITY_LOW_IMG:
1448 val = __DRI_CTX_PRIORITY_LOW;
1449 break;
1450 default:
1451 _eglError(EGL_BAD_CONFIG, "eglCreateContext");
1452 return false;
1453 }
1454
1455 ctx_attribs[pos++] = __DRI_CTX_ATTRIB_PRIORITY;
1456 ctx_attribs[pos++] = val;
1457 }
1458
1459 if (dri2_ctx->base.ReleaseBehavior == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR) {
1460 ctx_attribs[pos++] = __DRI_CTX_ATTRIB_RELEASE_BEHAVIOR;
1461 ctx_attribs[pos++] = __DRI_CTX_RELEASE_BEHAVIOR_NONE;
1462 }
1463
1464 *num_attribs = pos;
1465
1466 return true;
1467 }
1468
1469 /**
1470 * Called via eglCreateContext(), drv->API.CreateContext().
1471 */
1472 static _EGLContext *
1473 dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
1474 _EGLContext *share_list, const EGLint *attrib_list)
1475 {
1476 struct dri2_egl_context *dri2_ctx;
1477 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1478 struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list);
1479 __DRIcontext *shared =
1480 dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL;
1481 struct dri2_egl_config *dri2_config = dri2_egl_config(conf);
1482 const __DRIconfig *dri_config;
1483 int api;
1484 unsigned error;
1485 unsigned num_attribs = NUM_ATTRIBS;
1486 uint32_t ctx_attribs[NUM_ATTRIBS];
1487
1488 (void) drv;
1489
1490 dri2_ctx = malloc(sizeof *dri2_ctx);
1491 if (!dri2_ctx) {
1492 _eglError(EGL_BAD_ALLOC, "eglCreateContext");
1493 return NULL;
1494 }
1495
1496 if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list))
1497 goto cleanup;
1498
1499 /* The EGL_EXT_create_context_robustness spec says:
1500 *
1501 * "Add to the eglCreateContext context creation errors: [...]
1502 *
1503 * * If the reset notification behavior of <share_context> and the
1504 * newly created context are different then an EGL_BAD_MATCH error is
1505 * generated."
1506 */
1507 if (share_list && share_list->ResetNotificationStrategy !=
1508 dri2_ctx->base.ResetNotificationStrategy) {
1509 _eglError(EGL_BAD_MATCH, "eglCreateContext");
1510 goto cleanup;
1511 }
1512
1513 /* The EGL_KHR_create_context_no_error spec says:
1514 *
1515 * "BAD_MATCH is generated if the value of EGL_CONTEXT_OPENGL_NO_ERROR_KHR
1516 * used to create <share_context> does not match the value of
1517 * EGL_CONTEXT_OPENGL_NO_ERROR_KHR for the context being created."
1518 */
1519 if (share_list && share_list->NoError != dri2_ctx->base.NoError) {
1520 _eglError(EGL_BAD_MATCH, "eglCreateContext");
1521 goto cleanup;
1522 }
1523
1524 switch (dri2_ctx->base.ClientAPI) {
1525 case EGL_OPENGL_ES_API:
1526 switch (dri2_ctx->base.ClientMajorVersion) {
1527 case 1:
1528 api = __DRI_API_GLES;
1529 break;
1530 case 2:
1531 api = __DRI_API_GLES2;
1532 break;
1533 case 3:
1534 api = __DRI_API_GLES3;
1535 break;
1536 default:
1537 _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
1538 free(dri2_ctx);
1539 return NULL;
1540 }
1541 break;
1542 case EGL_OPENGL_API:
1543 if ((dri2_ctx->base.ClientMajorVersion >= 4
1544 || (dri2_ctx->base.ClientMajorVersion == 3
1545 && dri2_ctx->base.ClientMinorVersion >= 2))
1546 && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
1547 api = __DRI_API_OPENGL_CORE;
1548 else if (dri2_ctx->base.ClientMajorVersion == 3 &&
1549 dri2_ctx->base.ClientMinorVersion == 1)
1550 api = __DRI_API_OPENGL_CORE;
1551 else
1552 api = __DRI_API_OPENGL;
1553 break;
1554 default:
1555 _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
1556 free(dri2_ctx);
1557 return NULL;
1558 }
1559
1560 if (conf != NULL) {
1561 /* The config chosen here isn't necessarily
1562 * used for surfaces later.
1563 * A pixmap surface will use the single config.
1564 * This opportunity depends on disabling the
1565 * doubleBufferMode check in
1566 * src/mesa/main/context.c:check_compatible()
1567 */
1568 if (dri2_config->dri_config[1][0])
1569 dri_config = dri2_config->dri_config[1][0];
1570 else
1571 dri_config = dri2_config->dri_config[0][0];
1572 }
1573 else
1574 dri_config = NULL;
1575
1576 if (!dri2_fill_context_attribs(dri2_ctx, dri2_dpy, ctx_attribs,
1577 &num_attribs))
1578 goto cleanup;
1579
1580 if (dri2_dpy->image_driver) {
1581 dri2_ctx->dri_context =
1582 dri2_dpy->image_driver->createContextAttribs(dri2_dpy->dri_screen,
1583 api,
1584 dri_config,
1585 shared,
1586 num_attribs / 2,
1587 ctx_attribs,
1588 & error,
1589 dri2_ctx);
1590 dri2_create_context_attribs_error(error);
1591 } else if (dri2_dpy->dri2) {
1592 if (dri2_dpy->dri2->base.version >= 3) {
1593 dri2_ctx->dri_context =
1594 dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen,
1595 api,
1596 dri_config,
1597 shared,
1598 num_attribs / 2,
1599 ctx_attribs,
1600 & error,
1601 dri2_ctx);
1602 dri2_create_context_attribs_error(error);
1603 } else {
1604 dri2_ctx->dri_context =
1605 dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
1606 api,
1607 dri_config,
1608 shared,
1609 dri2_ctx);
1610 }
1611 } else {
1612 assert(dri2_dpy->swrast);
1613 if (dri2_dpy->swrast->base.version >= 3) {
1614 dri2_ctx->dri_context =
1615 dri2_dpy->swrast->createContextAttribs(dri2_dpy->dri_screen,
1616 api,
1617 dri_config,
1618 shared,
1619 num_attribs / 2,
1620 ctx_attribs,
1621 & error,
1622 dri2_ctx);
1623 dri2_create_context_attribs_error(error);
1624 } else {
1625 dri2_ctx->dri_context =
1626 dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen,
1627 api,
1628 dri_config,
1629 shared,
1630 dri2_ctx);
1631 }
1632 }
1633
1634 if (!dri2_ctx->dri_context)
1635 goto cleanup;
1636
1637 return &dri2_ctx->base;
1638
1639 cleanup:
1640 free(dri2_ctx);
1641 return NULL;
1642 }
1643
1644 /**
1645 * Called via eglDestroyContext(), drv->API.DestroyContext().
1646 */
1647 static EGLBoolean
1648 dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
1649 {
1650 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1651 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1652
1653 if (_eglPutContext(ctx)) {
1654 dri2_dpy->core->destroyContext(dri2_ctx->dri_context);
1655 free(dri2_ctx);
1656 }
1657
1658 return EGL_TRUE;
1659 }
1660
1661 EGLBoolean
1662 dri2_init_surface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type,
1663 _EGLConfig *conf, const EGLint *attrib_list,
1664 EGLBoolean enable_out_fence, void *native_surface)
1665 {
1666 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1667 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1668
1669 dri2_surf->out_fence_fd = -1;
1670 dri2_surf->enable_out_fence = false;
1671 if (dri2_dpy->fence && dri2_dpy->fence->base.version >= 2 &&
1672 dri2_dpy->fence->get_capabilities &&
1673 (dri2_dpy->fence->get_capabilities(dri2_dpy->dri_screen) &
1674 __DRI_FENCE_CAP_NATIVE_FD)) {
1675 dri2_surf->enable_out_fence = enable_out_fence;
1676 }
1677
1678 return _eglInitSurface(surf, disp, type, conf, attrib_list, native_surface);
1679 }
1680
1681 static void
1682 dri2_surface_set_out_fence_fd( _EGLSurface *surf, int fence_fd)
1683 {
1684 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1685
1686 if (dri2_surf->out_fence_fd >= 0)
1687 close(dri2_surf->out_fence_fd);
1688
1689 dri2_surf->out_fence_fd = fence_fd;
1690 }
1691
1692 void
1693 dri2_fini_surface(_EGLSurface *surf)
1694 {
1695 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1696
1697 dri2_surface_set_out_fence_fd(surf, -1);
1698 dri2_surf->enable_out_fence = false;
1699 }
1700
1701 static EGLBoolean
1702 dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
1703 {
1704 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1705
1706 if (!_eglPutSurface(surf))
1707 return EGL_TRUE;
1708
1709 return dri2_dpy->vtbl->destroy_surface(drv, disp, surf);
1710 }
1711
1712 static void
1713 dri2_surf_update_fence_fd(_EGLContext *ctx,
1714 _EGLDisplay *disp, _EGLSurface *surf)
1715 {
1716 __DRIcontext *dri_ctx = dri2_egl_context(ctx)->dri_context;
1717 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1718 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1719 int fence_fd = -1;
1720 void *fence;
1721
1722 if (!dri2_surf->enable_out_fence)
1723 return;
1724
1725 fence = dri2_dpy->fence->create_fence_fd(dri_ctx, -1);
1726 if (fence) {
1727 fence_fd = dri2_dpy->fence->get_fence_fd(dri2_dpy->dri_screen,
1728 fence);
1729 dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, fence);
1730 }
1731 dri2_surface_set_out_fence_fd(surf, fence_fd);
1732 }
1733
1734 EGLBoolean
1735 dri2_create_drawable(struct dri2_egl_display *dri2_dpy,
1736 const __DRIconfig *config,
1737 struct dri2_egl_surface *dri2_surf,
1738 void *loaderPrivate)
1739 {
1740 __DRIcreateNewDrawableFunc createNewDrawable;
1741
1742 if (dri2_dpy->image_driver)
1743 createNewDrawable = dri2_dpy->image_driver->createNewDrawable;
1744 else if (dri2_dpy->dri2)
1745 createNewDrawable = dri2_dpy->dri2->createNewDrawable;
1746 else if (dri2_dpy->swrast)
1747 createNewDrawable = dri2_dpy->swrast->createNewDrawable;
1748 else
1749 return _eglError(EGL_BAD_ALLOC, "no createNewDrawable");
1750
1751 dri2_surf->dri_drawable = createNewDrawable(dri2_dpy->dri_screen,
1752 config, loaderPrivate);
1753 if (dri2_surf->dri_drawable == NULL)
1754 return _eglError(EGL_BAD_ALLOC, "createNewDrawable");
1755
1756 return EGL_TRUE;
1757 }
1758
1759 /**
1760 * Called via eglMakeCurrent(), drv->API.MakeCurrent().
1761 */
1762 static EGLBoolean
1763 dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
1764 _EGLSurface *rsurf, _EGLContext *ctx)
1765 {
1766 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1767 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1768 _EGLDisplay *old_disp = NULL;
1769 struct dri2_egl_display *old_dri2_dpy = NULL;
1770 _EGLContext *old_ctx;
1771 _EGLSurface *old_dsurf, *old_rsurf;
1772 _EGLSurface *tmp_dsurf, *tmp_rsurf;
1773 __DRIdrawable *ddraw, *rdraw;
1774 __DRIcontext *cctx;
1775 EGLBoolean unbind;
1776
1777 if (!dri2_dpy)
1778 return _eglError(EGL_NOT_INITIALIZED, "eglMakeCurrent");
1779
1780 /* make new bindings */
1781 if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf)) {
1782 /* _eglBindContext already sets the EGL error (in _eglCheckMakeCurrent) */
1783 return EGL_FALSE;
1784 }
1785
1786 if (old_ctx) {
1787 old_disp = old_ctx->Resource.Display;
1788 old_dri2_dpy = dri2_egl_display(old_disp);
1789 }
1790
1791 /* flush before context switch */
1792 if (old_ctx)
1793 dri2_gl_flush();
1794
1795 ddraw = (dsurf) ? dri2_dpy->vtbl->get_dri_drawable(dsurf) : NULL;
1796 rdraw = (rsurf) ? dri2_dpy->vtbl->get_dri_drawable(rsurf) : NULL;
1797 cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL;
1798
1799 if (old_ctx) {
1800 __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context;
1801
1802 if (old_dsurf)
1803 dri2_surf_update_fence_fd(old_ctx, disp, old_dsurf);
1804
1805 /* Disable shared buffer mode */
1806 if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) &&
1807 old_dri2_dpy->vtbl->set_shared_buffer_mode) {
1808 old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, false);
1809 }
1810
1811 dri2_dpy->core->unbindContext(old_cctx);
1812 }
1813
1814 unbind = (cctx == NULL && ddraw == NULL && rdraw == NULL);
1815
1816 if (!unbind && !dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
1817 /* undo the previous _eglBindContext */
1818 _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &tmp_dsurf, &tmp_rsurf);
1819 assert(&dri2_ctx->base == ctx &&
1820 tmp_dsurf == dsurf &&
1821 tmp_rsurf == rsurf);
1822
1823 if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) &&
1824 old_dri2_dpy->vtbl->set_shared_buffer_mode) {
1825 old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, true);
1826 }
1827
1828 _eglPutSurface(dsurf);
1829 _eglPutSurface(rsurf);
1830 _eglPutContext(ctx);
1831
1832 _eglPutSurface(old_dsurf);
1833 _eglPutSurface(old_rsurf);
1834 _eglPutContext(old_ctx);
1835
1836 /* dri2_dpy->core->bindContext failed. We cannot tell for sure why, but
1837 * setting the error to EGL_BAD_MATCH is surely better than leaving it
1838 * as EGL_SUCCESS.
1839 */
1840 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
1841 }
1842
1843 dri2_destroy_surface(drv, disp, old_dsurf);
1844 dri2_destroy_surface(drv, disp, old_rsurf);
1845
1846 if (!unbind)
1847 dri2_dpy->ref_count++;
1848
1849 if (old_ctx) {
1850 dri2_destroy_context(drv, disp, old_ctx);
1851 dri2_display_release(old_disp);
1852 }
1853
1854 if (dsurf && _eglSurfaceHasMutableRenderBuffer(dsurf) &&
1855 dri2_dpy->vtbl->set_shared_buffer_mode) {
1856 /* Always update the shared buffer mode. This is obviously needed when
1857 * the active EGL_RENDER_BUFFER is EGL_SINGLE_BUFFER. When
1858 * EGL_RENDER_BUFFER is EGL_BACK_BUFFER, the update protects us in the
1859 * case where external non-EGL API may have changed window's shared
1860 * buffer mode since we last saw it.
1861 */
1862 bool mode = (dsurf->ActiveRenderBuffer == EGL_SINGLE_BUFFER);
1863 dri2_dpy->vtbl->set_shared_buffer_mode(disp, dsurf, mode);
1864 }
1865
1866 return EGL_TRUE;
1867 }
1868
1869 __DRIdrawable *
1870 dri2_surface_get_dri_drawable(_EGLSurface *surf)
1871 {
1872 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1873
1874 return dri2_surf->dri_drawable;
1875 }
1876
1877 /*
1878 * Called from eglGetProcAddress() via drv->API.GetProcAddress().
1879 */
1880 static _EGLProc
1881 dri2_get_proc_address(_EGLDriver *drv, const char *procname)
1882 {
1883 return _glapi_get_proc_address(procname);
1884 }
1885
1886 static _EGLSurface*
1887 dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
1888 _EGLConfig *conf, void *native_window,
1889 const EGLint *attrib_list)
1890 {
1891 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1892 return dri2_dpy->vtbl->create_window_surface(drv, disp, conf, native_window,
1893 attrib_list);
1894 }
1895
1896 static _EGLSurface*
1897 dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
1898 _EGLConfig *conf, void *native_pixmap,
1899 const EGLint *attrib_list)
1900 {
1901 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1902 return dri2_dpy->vtbl->create_pixmap_surface(drv, disp, conf, native_pixmap,
1903 attrib_list);
1904 }
1905
1906 static _EGLSurface*
1907 dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
1908 _EGLConfig *conf, const EGLint *attrib_list)
1909 {
1910 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1911 return dri2_dpy->vtbl->create_pbuffer_surface(drv, disp, conf, attrib_list);
1912 }
1913
1914 static EGLBoolean
1915 dri2_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
1916 EGLint interval)
1917 {
1918 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1919 if (!dri2_dpy->vtbl->swap_interval)
1920 return EGL_TRUE;
1921 return dri2_dpy->vtbl->swap_interval(drv, disp, surf, interval);
1922 }
1923
1924 /**
1925 * Asks the client API to flush any rendering to the drawable so that we can
1926 * do our swapbuffers.
1927 */
1928 void
1929 dri2_flush_drawable_for_swapbuffers(_EGLDisplay *disp, _EGLSurface *draw)
1930 {
1931 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1932 __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(draw);
1933
1934 if (dri2_dpy->flush) {
1935 if (dri2_dpy->flush->base.version >= 4) {
1936 /* We know there's a current context because:
1937 *
1938 * "If surface is not bound to the calling thread’s current
1939 * context, an EGL_BAD_SURFACE error is generated."
1940 */
1941 _EGLContext *ctx = _eglGetCurrentContext();
1942 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1943
1944 /* From the EGL 1.4 spec (page 52):
1945 *
1946 * "The contents of ancillary buffers are always undefined
1947 * after calling eglSwapBuffers."
1948 */
1949 dri2_dpy->flush->flush_with_flags(dri2_ctx->dri_context,
1950 dri_drawable,
1951 __DRI2_FLUSH_DRAWABLE |
1952 __DRI2_FLUSH_INVALIDATE_ANCILLARY,
1953 __DRI2_THROTTLE_SWAPBUFFER);
1954 } else {
1955 dri2_dpy->flush->flush(dri_drawable);
1956 }
1957 }
1958 }
1959
1960 static EGLBoolean
1961 dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
1962 {
1963 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1964 __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
1965 _EGLContext *ctx = _eglGetCurrentContext();
1966 EGLBoolean ret;
1967
1968 if (ctx && surf)
1969 dri2_surf_update_fence_fd(ctx, disp, surf);
1970 ret = dri2_dpy->vtbl->swap_buffers(drv, disp, surf);
1971
1972 /* SwapBuffers marks the end of the frame; reset the damage region for
1973 * use again next time.
1974 */
1975 if (ret && dri2_dpy->buffer_damage &&
1976 dri2_dpy->buffer_damage->set_damage_region)
1977 dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL);
1978
1979 return ret;
1980 }
1981
1982 static EGLBoolean
1983 dri2_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *disp,
1984 _EGLSurface *surf,
1985 const EGLint *rects, EGLint n_rects)
1986 {
1987 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1988 __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
1989 _EGLContext *ctx = _eglGetCurrentContext();
1990 EGLBoolean ret;
1991
1992 if (ctx && surf)
1993 dri2_surf_update_fence_fd(ctx, disp, surf);
1994 ret = dri2_dpy->vtbl->swap_buffers_with_damage(drv, disp, surf,
1995 rects, n_rects);
1996
1997 /* SwapBuffers marks the end of the frame; reset the damage region for
1998 * use again next time.
1999 */
2000 if (ret && dri2_dpy->buffer_damage &&
2001 dri2_dpy->buffer_damage->set_damage_region)
2002 dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL);
2003
2004 return ret;
2005 }
2006
2007 static EGLBoolean
2008 dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
2009 EGLint numRects, const EGLint *rects)
2010 {
2011 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2012 __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2013 EGLBoolean ret;
2014
2015 ret = dri2_dpy->vtbl->swap_buffers_region(drv, disp, surf, numRects, rects);
2016
2017 /* SwapBuffers marks the end of the frame; reset the damage region for
2018 * use again next time.
2019 */
2020 if (ret && dri2_dpy->buffer_damage &&
2021 dri2_dpy->buffer_damage->set_damage_region)
2022 dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL);
2023
2024 return ret;
2025 }
2026
2027 static EGLBoolean
2028 dri2_set_damage_region(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
2029 EGLint *rects, EGLint n_rects)
2030 {
2031 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2032 __DRIdrawable *drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2033
2034 if (!dri2_dpy->buffer_damage || !dri2_dpy->buffer_damage->set_damage_region)
2035 return EGL_FALSE;
2036
2037 dri2_dpy->buffer_damage->set_damage_region(drawable, n_rects, rects);
2038 return EGL_TRUE;
2039 }
2040
2041 static EGLBoolean
2042 dri2_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
2043 EGLint x, EGLint y, EGLint width, EGLint height)
2044 {
2045 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2046 return dri2_dpy->vtbl->post_sub_buffer(drv, disp, surf, x, y, width, height);
2047 }
2048
2049 static EGLBoolean
2050 dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
2051 void *native_pixmap_target)
2052 {
2053 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2054 return dri2_dpy->vtbl->copy_buffers(drv, disp, surf, native_pixmap_target);
2055 }
2056
2057 static EGLint
2058 dri2_query_buffer_age(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
2059 {
2060 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2061 return dri2_dpy->vtbl->query_buffer_age(drv, disp, surf);
2062 }
2063
2064 static EGLBoolean
2065 dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
2066 {
2067 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2068 _EGLSurface *surf = ctx->DrawSurface;
2069 __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2070
2071 (void) drv;
2072
2073 /* FIXME: If EGL allows frontbuffer rendering for window surfaces,
2074 * we need to copy fake to real here.*/
2075
2076 if (dri2_dpy->flush != NULL)
2077 dri2_dpy->flush->flush(dri_drawable);
2078
2079 return EGL_TRUE;
2080 }
2081
2082 static EGLBoolean
2083 dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine)
2084 {
2085 (void) drv;
2086 (void) disp;
2087
2088 if (engine != EGL_CORE_NATIVE_ENGINE)
2089 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
2090 /* glXWaitX(); */
2091
2092 return EGL_TRUE;
2093 }
2094
2095 static EGLBoolean
2096 dri2_bind_tex_image(_EGLDriver *drv,
2097 _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
2098 {
2099 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2100 struct dri2_egl_context *dri2_ctx;
2101 _EGLContext *ctx;
2102 GLint format, target;
2103 __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2104
2105 ctx = _eglGetCurrentContext();
2106 dri2_ctx = dri2_egl_context(ctx);
2107
2108 if (!_eglBindTexImage(drv, disp, surf, buffer))
2109 return EGL_FALSE;
2110
2111 switch (surf->TextureFormat) {
2112 case EGL_TEXTURE_RGB:
2113 format = __DRI_TEXTURE_FORMAT_RGB;
2114 break;
2115 case EGL_TEXTURE_RGBA:
2116 format = __DRI_TEXTURE_FORMAT_RGBA;
2117 break;
2118 default:
2119 assert(!"Unexpected texture format in dri2_bind_tex_image()");
2120 format = __DRI_TEXTURE_FORMAT_RGBA;
2121 }
2122
2123 switch (surf->TextureTarget) {
2124 case EGL_TEXTURE_2D:
2125 target = GL_TEXTURE_2D;
2126 break;
2127 default:
2128 target = GL_TEXTURE_2D;
2129 assert(!"Unexpected texture target in dri2_bind_tex_image()");
2130 }
2131
2132 dri2_dpy->tex_buffer->setTexBuffer2(dri2_ctx->dri_context,
2133 target, format,
2134 dri_drawable);
2135
2136 return EGL_TRUE;
2137 }
2138
2139 static EGLBoolean
2140 dri2_release_tex_image(_EGLDriver *drv,
2141 _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
2142 {
2143 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2144 struct dri2_egl_context *dri2_ctx;
2145 _EGLContext *ctx;
2146 GLint target;
2147 __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2148
2149 ctx = _eglGetCurrentContext();
2150 dri2_ctx = dri2_egl_context(ctx);
2151
2152 if (!_eglReleaseTexImage(drv, disp, surf, buffer))
2153 return EGL_FALSE;
2154
2155 switch (surf->TextureTarget) {
2156 case EGL_TEXTURE_2D:
2157 target = GL_TEXTURE_2D;
2158 break;
2159 default:
2160 assert(!"missing texture target");
2161 }
2162
2163 if (dri2_dpy->tex_buffer->base.version >= 3 &&
2164 dri2_dpy->tex_buffer->releaseTexBuffer != NULL) {
2165 dri2_dpy->tex_buffer->releaseTexBuffer(dri2_ctx->dri_context,
2166 target, dri_drawable);
2167 }
2168
2169 return EGL_TRUE;
2170 }
2171
2172 static _EGLImage*
2173 dri2_create_image(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx,
2174 EGLenum target, EGLClientBuffer buffer,
2175 const EGLint *attr_list)
2176 {
2177 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2178 return dri2_dpy->vtbl->create_image(drv, disp, ctx, target, buffer,
2179 attr_list);
2180 }
2181
2182 static _EGLImage *
2183 dri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image)
2184 {
2185 struct dri2_egl_image *dri2_img;
2186
2187 if (dri_image == NULL) {
2188 _eglError(EGL_BAD_ALLOC, "dri2_create_image");
2189 return NULL;
2190 }
2191
2192 dri2_img = malloc(sizeof *dri2_img);
2193 if (!dri2_img) {
2194 _eglError(EGL_BAD_ALLOC, "dri2_create_image");
2195 return NULL;
2196 }
2197
2198 _eglInitImage(&dri2_img->base, disp);
2199
2200 dri2_img->dri_image = dri_image;
2201
2202 return &dri2_img->base;
2203 }
2204
2205 /**
2206 * Translate a DRI Image extension error code into an EGL error code.
2207 */
2208 static EGLint
2209 egl_error_from_dri_image_error(int dri_error)
2210 {
2211 switch (dri_error) {
2212 case __DRI_IMAGE_ERROR_SUCCESS:
2213 return EGL_SUCCESS;
2214 case __DRI_IMAGE_ERROR_BAD_ALLOC:
2215 return EGL_BAD_ALLOC;
2216 case __DRI_IMAGE_ERROR_BAD_MATCH:
2217 return EGL_BAD_MATCH;
2218 case __DRI_IMAGE_ERROR_BAD_PARAMETER:
2219 return EGL_BAD_PARAMETER;
2220 case __DRI_IMAGE_ERROR_BAD_ACCESS:
2221 return EGL_BAD_ACCESS;
2222 default:
2223 assert(!"unknown dri_error code");
2224 return EGL_BAD_ALLOC;
2225 }
2226 }
2227
2228 static _EGLImage *
2229 dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
2230 EGLClientBuffer buffer,
2231 const EGLint *attr_list)
2232 {
2233 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2234 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
2235 GLuint renderbuffer = (GLuint) (uintptr_t) buffer;
2236 __DRIimage *dri_image;
2237
2238 if (renderbuffer == 0) {
2239 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2240 return EGL_NO_IMAGE_KHR;
2241 }
2242
2243 if (!disp->Extensions.KHR_gl_renderbuffer_image) {
2244 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2245 return EGL_NO_IMAGE_KHR;
2246 }
2247
2248 if (dri2_dpy->image->base.version >= 17 &&
2249 dri2_dpy->image->createImageFromRenderbuffer2) {
2250 unsigned error = ~0;
2251
2252 dri_image = dri2_dpy->image->createImageFromRenderbuffer2(
2253 dri2_ctx->dri_context, renderbuffer, NULL, &error);
2254
2255 assert(!!dri_image == (error == __DRI_IMAGE_ERROR_SUCCESS));
2256
2257 if (!dri_image) {
2258 _eglError(egl_error_from_dri_image_error(error), "dri2_create_image_khr");
2259 return EGL_NO_IMAGE_KHR;
2260 }
2261 } else {
2262 dri_image = dri2_dpy->image->createImageFromRenderbuffer(
2263 dri2_ctx->dri_context, renderbuffer, NULL);
2264 if (!dri_image) {
2265 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
2266 return EGL_NO_IMAGE_KHR;
2267 }
2268 }
2269
2270 return dri2_create_image_from_dri(disp, dri_image);
2271 }
2272
2273 #ifdef HAVE_WAYLAND_PLATFORM
2274
2275 /* This structure describes how a wl_buffer maps to one or more
2276 * __DRIimages. A wl_drm_buffer stores the wl_drm format code and the
2277 * offsets and strides of the planes in the buffer. This table maps a
2278 * wl_drm format code to a description of the planes in the buffer
2279 * that lets us create a __DRIimage for each of the planes. */
2280
2281 static const struct wl_drm_components_descriptor {
2282 uint32_t dri_components;
2283 EGLint components;
2284 int nplanes;
2285 } wl_drm_components[] = {
2286 { __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 },
2287 { __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 },
2288 { __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 },
2289 { __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 },
2290 { __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 },
2291 };
2292
2293 static _EGLImage *
2294 dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
2295 EGLClientBuffer _buffer,
2296 const EGLint *attr_list)
2297 {
2298 struct wl_drm_buffer *buffer;
2299 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2300 const struct wl_drm_components_descriptor *f;
2301 __DRIimage *dri_image;
2302 _EGLImageAttribs attrs;
2303 int32_t plane;
2304
2305 buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm,
2306 (struct wl_resource *) _buffer);
2307 if (!buffer)
2308 return NULL;
2309
2310 if (!_eglParseImageAttribList(&attrs, disp, attr_list))
2311 return NULL;
2312
2313 plane = attrs.PlaneWL;
2314 f = buffer->driver_format;
2315 if (plane < 0 || plane >= f->nplanes) {
2316 _eglError(EGL_BAD_PARAMETER,
2317 "dri2_create_image_wayland_wl_buffer (plane out of bounds)");
2318 return NULL;
2319 }
2320
2321 dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL);
2322 if (dri_image == NULL && plane == 0)
2323 dri_image = dri2_dpy->image->dupImage(buffer->driver_buffer, NULL);
2324 if (dri_image == NULL) {
2325 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
2326 return NULL;
2327 }
2328
2329 return dri2_create_image_from_dri(disp, dri_image);
2330 }
2331 #endif
2332
2333 static EGLBoolean
2334 dri2_get_sync_values_chromium(_EGLDisplay *disp, _EGLSurface *surf,
2335 EGLuint64KHR *ust, EGLuint64KHR *msc,
2336 EGLuint64KHR *sbc)
2337 {
2338 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2339 return dri2_dpy->vtbl->get_sync_values(disp, surf, ust, msc, sbc);
2340 }
2341
2342 /**
2343 * Set the error code after a call to
2344 * dri2_egl_image::dri_image::createImageFromTexture.
2345 */
2346 static void
2347 dri2_create_image_khr_texture_error(int dri_error)
2348 {
2349 EGLint egl_error = egl_error_from_dri_image_error(dri_error);
2350
2351 if (egl_error != EGL_SUCCESS)
2352 _eglError(egl_error, "dri2_create_image_khr_texture");
2353 }
2354
2355 static _EGLImage *
2356 dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
2357 EGLenum target,
2358 EGLClientBuffer buffer,
2359 const EGLint *attr_list)
2360 {
2361 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2362 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
2363 struct dri2_egl_image *dri2_img;
2364 GLuint texture = (GLuint) (uintptr_t) buffer;
2365 _EGLImageAttribs attrs;
2366 GLuint depth;
2367 GLenum gl_target;
2368 unsigned error;
2369
2370 if (texture == 0) {
2371 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2372 return EGL_NO_IMAGE_KHR;
2373 }
2374
2375 if (!_eglParseImageAttribList(&attrs, disp, attr_list))
2376 return EGL_NO_IMAGE_KHR;
2377
2378 switch (target) {
2379 case EGL_GL_TEXTURE_2D_KHR:
2380 if (!disp->Extensions.KHR_gl_texture_2D_image) {
2381 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2382 return EGL_NO_IMAGE_KHR;
2383 }
2384 depth = 0;
2385 gl_target = GL_TEXTURE_2D;
2386 break;
2387 case EGL_GL_TEXTURE_3D_KHR:
2388 if (!disp->Extensions.KHR_gl_texture_3D_image) {
2389 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2390 return EGL_NO_IMAGE_KHR;
2391 }
2392
2393 depth = attrs.GLTextureZOffset;
2394 gl_target = GL_TEXTURE_3D;
2395 break;
2396 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
2397 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
2398 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
2399 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
2400 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
2401 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
2402 if (!disp->Extensions.KHR_gl_texture_cubemap_image) {
2403 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2404 return EGL_NO_IMAGE_KHR;
2405 }
2406
2407 depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
2408 gl_target = GL_TEXTURE_CUBE_MAP;
2409 break;
2410 default:
2411 unreachable("Unexpected target in dri2_create_image_khr_texture()");
2412 return EGL_NO_IMAGE_KHR;
2413 }
2414
2415 dri2_img = malloc(sizeof *dri2_img);
2416 if (!dri2_img) {
2417 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
2418 return EGL_NO_IMAGE_KHR;
2419 }
2420
2421 _eglInitImage(&dri2_img->base, disp);
2422
2423 dri2_img->dri_image =
2424 dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context,
2425 gl_target,
2426 texture,
2427 depth,
2428 attrs.GLTextureLevel,
2429 &error,
2430 dri2_img);
2431 dri2_create_image_khr_texture_error(error);
2432
2433 if (!dri2_img->dri_image) {
2434 free(dri2_img);
2435 return EGL_NO_IMAGE_KHR;
2436 }
2437 return &dri2_img->base;
2438 }
2439
2440 static EGLBoolean
2441 dri2_query_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
2442 EGLint attribute, EGLint *value)
2443 {
2444 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2445 if (!dri2_dpy->vtbl->query_surface)
2446 return _eglQuerySurface(drv, disp, surf, attribute, value);
2447 return dri2_dpy->vtbl->query_surface(drv, disp, surf, attribute, value);
2448 }
2449
2450 static struct wl_buffer*
2451 dri2_create_wayland_buffer_from_image(_EGLDriver *drv, _EGLDisplay *disp,
2452 _EGLImage *img)
2453 {
2454 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2455 return dri2_dpy->vtbl->create_wayland_buffer_from_image(drv, disp, img);
2456 }
2457
2458 #ifdef HAVE_LIBDRM
2459 static _EGLImage *
2460 dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
2461 EGLClientBuffer buffer, const EGLint *attr_list)
2462 {
2463 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2464 EGLint format, name, pitch;
2465 _EGLImageAttribs attrs;
2466 __DRIimage *dri_image;
2467
2468 name = (EGLint) (uintptr_t) buffer;
2469
2470 if (!_eglParseImageAttribList(&attrs, disp, attr_list))
2471 return NULL;
2472
2473 if (attrs.Width <= 0 || attrs.Height <= 0 ||
2474 attrs.DRMBufferStrideMESA <= 0) {
2475 _eglError(EGL_BAD_PARAMETER,
2476 "bad width, height or stride");
2477 return NULL;
2478 }
2479
2480 switch (attrs.DRMBufferFormatMESA) {
2481 case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
2482 format = __DRI_IMAGE_FORMAT_ARGB8888;
2483 pitch = attrs.DRMBufferStrideMESA;
2484 break;
2485 default:
2486 _eglError(EGL_BAD_PARAMETER,
2487 "dri2_create_image_khr: unsupported pixmap depth");
2488 return NULL;
2489 }
2490
2491 dri_image =
2492 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
2493 attrs.Width,
2494 attrs.Height,
2495 format,
2496 name,
2497 pitch,
2498 NULL);
2499
2500 return dri2_create_image_from_dri(disp, dri_image);
2501 }
2502
2503 static EGLBoolean
2504 dri2_check_dma_buf_attribs(const _EGLImageAttribs *attrs)
2505 {
2506 /**
2507 * The spec says:
2508 *
2509 * "Required attributes and their values are as follows:
2510 *
2511 * * EGL_WIDTH & EGL_HEIGHT: The logical dimensions of the buffer in pixels
2512 *
2513 * * EGL_LINUX_DRM_FOURCC_EXT: The pixel format of the buffer, as specified
2514 * by drm_fourcc.h and used as the pixel_format parameter of the
2515 * drm_mode_fb_cmd2 ioctl."
2516 *
2517 * and
2518 *
2519 * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is
2520 * incomplete, EGL_BAD_PARAMETER is generated."
2521 */
2522 if (attrs->Width <= 0 || attrs->Height <= 0 ||
2523 !attrs->DMABufFourCC.IsPresent)
2524 return _eglError(EGL_BAD_PARAMETER, "attribute(s) missing");
2525
2526 /**
2527 * Also:
2528 *
2529 * "If <target> is EGL_LINUX_DMA_BUF_EXT and one or more of the values
2530 * specified for a plane's pitch or offset isn't supported by EGL,
2531 * EGL_BAD_ACCESS is generated."
2532 */
2533 for (unsigned i = 0; i < ARRAY_SIZE(attrs->DMABufPlanePitches); ++i) {
2534 if (attrs->DMABufPlanePitches[i].IsPresent &&
2535 attrs->DMABufPlanePitches[i].Value <= 0)
2536 return _eglError(EGL_BAD_ACCESS, "invalid pitch");
2537 }
2538
2539 /**
2540 * If <target> is EGL_LINUX_DMA_BUF_EXT, both or neither of the following
2541 * attribute values may be given.
2542 *
2543 * This is referring to EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT and
2544 * EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, and the same for other planes.
2545 */
2546 for (unsigned i = 0; i < DMA_BUF_MAX_PLANES; ++i) {
2547 if (attrs->DMABufPlaneModifiersLo[i].IsPresent !=
2548 attrs->DMABufPlaneModifiersHi[i].IsPresent)
2549 return _eglError(EGL_BAD_PARAMETER, "modifier attribute lo or hi missing");
2550 }
2551
2552 /* Although the EGL_EXT_image_dma_buf_import_modifiers spec doesn't
2553 * mandate it, we only accept the same modifier across all planes. */
2554 for (unsigned i = 1; i < DMA_BUF_MAX_PLANES; ++i) {
2555 if (attrs->DMABufPlaneFds[i].IsPresent) {
2556 if ((attrs->DMABufPlaneModifiersLo[0].IsPresent !=
2557 attrs->DMABufPlaneModifiersLo[i].IsPresent) ||
2558 (attrs->DMABufPlaneModifiersLo[0].Value !=
2559 attrs->DMABufPlaneModifiersLo[i].Value) ||
2560 (attrs->DMABufPlaneModifiersHi[0].Value !=
2561 attrs->DMABufPlaneModifiersHi[i].Value))
2562 return _eglError(EGL_BAD_PARAMETER, "modifier attributes not equal");
2563 }
2564 }
2565
2566 return EGL_TRUE;
2567 }
2568
2569 /* Returns the total number of planes for the format or zero if it isn't a
2570 * valid fourcc format.
2571 */
2572 static unsigned
2573 dri2_num_fourcc_format_planes(EGLint format)
2574 {
2575 switch (format) {
2576 case DRM_FORMAT_R8:
2577 case DRM_FORMAT_RG88:
2578 case DRM_FORMAT_GR88:
2579 case DRM_FORMAT_R16:
2580 case DRM_FORMAT_GR1616:
2581 case DRM_FORMAT_RGB332:
2582 case DRM_FORMAT_BGR233:
2583 case DRM_FORMAT_XRGB4444:
2584 case DRM_FORMAT_XBGR4444:
2585 case DRM_FORMAT_RGBX4444:
2586 case DRM_FORMAT_BGRX4444:
2587 case DRM_FORMAT_ARGB4444:
2588 case DRM_FORMAT_ABGR4444:
2589 case DRM_FORMAT_RGBA4444:
2590 case DRM_FORMAT_BGRA4444:
2591 case DRM_FORMAT_XRGB1555:
2592 case DRM_FORMAT_XBGR1555:
2593 case DRM_FORMAT_RGBX5551:
2594 case DRM_FORMAT_BGRX5551:
2595 case DRM_FORMAT_ARGB1555:
2596 case DRM_FORMAT_ABGR1555:
2597 case DRM_FORMAT_RGBA5551:
2598 case DRM_FORMAT_BGRA5551:
2599 case DRM_FORMAT_RGB565:
2600 case DRM_FORMAT_BGR565:
2601 case DRM_FORMAT_RGB888:
2602 case DRM_FORMAT_BGR888:
2603 case DRM_FORMAT_XRGB8888:
2604 case DRM_FORMAT_XBGR8888:
2605 case DRM_FORMAT_RGBX8888:
2606 case DRM_FORMAT_BGRX8888:
2607 case DRM_FORMAT_ARGB8888:
2608 case DRM_FORMAT_ABGR8888:
2609 case DRM_FORMAT_RGBA8888:
2610 case DRM_FORMAT_BGRA8888:
2611 case DRM_FORMAT_XRGB2101010:
2612 case DRM_FORMAT_XBGR2101010:
2613 case DRM_FORMAT_RGBX1010102:
2614 case DRM_FORMAT_BGRX1010102:
2615 case DRM_FORMAT_ARGB2101010:
2616 case DRM_FORMAT_ABGR2101010:
2617 case DRM_FORMAT_RGBA1010102:
2618 case DRM_FORMAT_BGRA1010102:
2619 case DRM_FORMAT_XBGR16161616F:
2620 case DRM_FORMAT_ABGR16161616F:
2621 case DRM_FORMAT_YUYV:
2622 case DRM_FORMAT_YVYU:
2623 case DRM_FORMAT_UYVY:
2624 case DRM_FORMAT_VYUY:
2625 case DRM_FORMAT_AYUV:
2626 case DRM_FORMAT_XYUV8888:
2627 return 1;
2628
2629 case DRM_FORMAT_NV12:
2630 case DRM_FORMAT_NV21:
2631 case DRM_FORMAT_NV16:
2632 case DRM_FORMAT_NV61:
2633 case DRM_FORMAT_P010:
2634 case DRM_FORMAT_P012:
2635 case DRM_FORMAT_P016:
2636 return 2;
2637
2638 case DRM_FORMAT_YUV410:
2639 case DRM_FORMAT_YVU410:
2640 case DRM_FORMAT_YUV411:
2641 case DRM_FORMAT_YVU411:
2642 case DRM_FORMAT_YUV420:
2643 case DRM_FORMAT_YVU420:
2644 case DRM_FORMAT_YUV422:
2645 case DRM_FORMAT_YVU422:
2646 case DRM_FORMAT_YUV444:
2647 case DRM_FORMAT_YVU444:
2648 return 3;
2649
2650 default:
2651 return 0;
2652 }
2653 }
2654
2655 /* Returns the total number of file descriptors. Zero indicates an error. */
2656 static unsigned
2657 dri2_check_dma_buf_format(const _EGLImageAttribs *attrs)
2658 {
2659 unsigned plane_n = dri2_num_fourcc_format_planes(attrs->DMABufFourCC.Value);
2660 if (plane_n == 0) {
2661 _eglError(EGL_BAD_MATCH, "unknown drm fourcc format");
2662 return 0;
2663 }
2664
2665 for (unsigned i = plane_n; i < DMA_BUF_MAX_PLANES; i++) {
2666 /**
2667 * The modifiers extension spec says:
2668 *
2669 * "Modifiers may modify any attribute of a buffer import, including
2670 * but not limited to adding extra planes to a format which
2671 * otherwise does not have those planes. As an example, a modifier
2672 * may add a plane for an external compression buffer to a
2673 * single-plane format. The exact meaning and effect of any
2674 * modifier is canonically defined by drm_fourcc.h, not as part of
2675 * this extension."
2676 */
2677 if (attrs->DMABufPlaneModifiersLo[i].IsPresent &&
2678 attrs->DMABufPlaneModifiersHi[i].IsPresent) {
2679 plane_n = i + 1;
2680 }
2681 }
2682
2683 /**
2684 * The spec says:
2685 *
2686 * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is
2687 * incomplete, EGL_BAD_PARAMETER is generated."
2688 */
2689 for (unsigned i = 0; i < plane_n; ++i) {
2690 if (!attrs->DMABufPlaneFds[i].IsPresent ||
2691 !attrs->DMABufPlaneOffsets[i].IsPresent ||
2692 !attrs->DMABufPlanePitches[i].IsPresent) {
2693 _eglError(EGL_BAD_PARAMETER, "plane attribute(s) missing");
2694 return 0;
2695 }
2696 }
2697
2698 /**
2699 * The spec also says:
2700 *
2701 * "If <target> is EGL_LINUX_DMA_BUF_EXT, and the EGL_LINUX_DRM_FOURCC_EXT
2702 * attribute indicates a single-plane format, EGL_BAD_ATTRIBUTE is
2703 * generated if any of the EGL_DMA_BUF_PLANE1_* or EGL_DMA_BUF_PLANE2_*
2704 * or EGL_DMA_BUF_PLANE3_* attributes are specified."
2705 */
2706 for (unsigned i = plane_n; i < DMA_BUF_MAX_PLANES; ++i) {
2707 if (attrs->DMABufPlaneFds[i].IsPresent ||
2708 attrs->DMABufPlaneOffsets[i].IsPresent ||
2709 attrs->DMABufPlanePitches[i].IsPresent) {
2710 _eglError(EGL_BAD_ATTRIBUTE, "too many plane attributes");
2711 return 0;
2712 }
2713 }
2714
2715 return plane_n;
2716 }
2717
2718 static EGLBoolean
2719 dri2_query_dma_buf_formats(_EGLDriver *drv, _EGLDisplay *disp,
2720 EGLint max, EGLint *formats, EGLint *count)
2721 {
2722 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2723 if (max < 0 || (max > 0 && formats == NULL))
2724 return _eglError(EGL_BAD_PARAMETER, "invalid value for max count of formats");
2725
2726 if (dri2_dpy->image->base.version < 15 ||
2727 dri2_dpy->image->queryDmaBufFormats == NULL)
2728 return EGL_FALSE;
2729
2730 if (!dri2_dpy->image->queryDmaBufFormats(dri2_dpy->dri_screen, max,
2731 formats, count))
2732 return EGL_FALSE;
2733
2734 if (max > 0) {
2735 /* Assert that all of the formats returned are actually fourcc formats.
2736 * Some day, if we want the internal interface function to be able to
2737 * return the fake fourcc formats defined in dri_interface.h, we'll have
2738 * to do something more clever here to pair the list down to just real
2739 * fourcc formats so that we don't leak the fake internal ones.
2740 */
2741 for (int i = 0; i < *count; i++) {
2742 assert(dri2_num_fourcc_format_planes(formats[i]) > 0);
2743 }
2744 }
2745
2746 return EGL_TRUE;
2747 }
2748
2749 static EGLBoolean
2750 dri2_query_dma_buf_modifiers(_EGLDriver *drv, _EGLDisplay *disp, EGLint format,
2751 EGLint max, EGLuint64KHR *modifiers,
2752 EGLBoolean *external_only, EGLint *count)
2753 {
2754 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2755
2756 if (dri2_num_fourcc_format_planes(format) == 0)
2757 return _eglError(EGL_BAD_PARAMETER, "invalid fourcc format");
2758
2759 if (max < 0)
2760 return _eglError(EGL_BAD_PARAMETER, "invalid value for max count of formats");
2761
2762 if (max > 0 && modifiers == NULL)
2763 return _eglError(EGL_BAD_PARAMETER, "invalid modifiers array");
2764
2765 if (dri2_dpy->image->base.version < 15 ||
2766 dri2_dpy->image->queryDmaBufModifiers == NULL)
2767 return EGL_FALSE;
2768
2769 if (dri2_dpy->image->queryDmaBufModifiers(dri2_dpy->dri_screen, format,
2770 max, modifiers,
2771 (unsigned int *) external_only,
2772 count) == false)
2773 return _eglError(EGL_BAD_PARAMETER, "invalid format");
2774
2775 return EGL_TRUE;
2776 }
2777
2778 /**
2779 * The spec says:
2780 *
2781 * "If eglCreateImageKHR is successful for a EGL_LINUX_DMA_BUF_EXT target, the
2782 * EGL will take a reference to the dma_buf(s) which it will release at any
2783 * time while the EGLDisplay is initialized. It is the responsibility of the
2784 * application to close the dma_buf file descriptors."
2785 *
2786 * Therefore we must never close or otherwise modify the file descriptors.
2787 */
2788 _EGLImage *
2789 dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
2790 EGLClientBuffer buffer, const EGLint *attr_list)
2791 {
2792 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2793 _EGLImage *res;
2794 _EGLImageAttribs attrs;
2795 __DRIimage *dri_image;
2796 unsigned num_fds;
2797 int fds[DMA_BUF_MAX_PLANES];
2798 int pitches[DMA_BUF_MAX_PLANES];
2799 int offsets[DMA_BUF_MAX_PLANES];
2800 uint64_t modifier;
2801 bool has_modifier = false;
2802 unsigned error;
2803
2804 /**
2805 * The spec says:
2806 *
2807 * ""* If <target> is EGL_LINUX_DMA_BUF_EXT and <buffer> is not NULL, the
2808 * error EGL_BAD_PARAMETER is generated."
2809 */
2810 if (buffer != NULL) {
2811 _eglError(EGL_BAD_PARAMETER, "buffer not NULL");
2812 return NULL;
2813 }
2814
2815 if (!_eglParseImageAttribList(&attrs, disp, attr_list))
2816 return NULL;
2817
2818 if (!dri2_check_dma_buf_attribs(&attrs))
2819 return NULL;
2820
2821 num_fds = dri2_check_dma_buf_format(&attrs);
2822 if (!num_fds)
2823 return NULL;
2824
2825 for (unsigned i = 0; i < num_fds; ++i) {
2826 fds[i] = attrs.DMABufPlaneFds[i].Value;
2827 pitches[i] = attrs.DMABufPlanePitches[i].Value;
2828 offsets[i] = attrs.DMABufPlaneOffsets[i].Value;
2829 }
2830
2831 /* dri2_check_dma_buf_attribs ensures that the modifier, if available,
2832 * will be present in attrs.DMABufPlaneModifiersLo[0] and
2833 * attrs.DMABufPlaneModifiersHi[0] */
2834 if (attrs.DMABufPlaneModifiersLo[0].IsPresent) {
2835 modifier = combine_u32_into_u64(attrs.DMABufPlaneModifiersHi[0].Value,
2836 attrs.DMABufPlaneModifiersLo[0].Value);
2837 has_modifier = true;
2838 }
2839
2840 if (has_modifier) {
2841 if (dri2_dpy->image->base.version < 15 ||
2842 dri2_dpy->image->createImageFromDmaBufs2 == NULL) {
2843 _eglError(EGL_BAD_MATCH, "unsupported dma_buf format modifier");
2844 return EGL_NO_IMAGE_KHR;
2845 }
2846 dri_image =
2847 dri2_dpy->image->createImageFromDmaBufs2(dri2_dpy->dri_screen,
2848 attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
2849 modifier, fds, num_fds, pitches, offsets,
2850 attrs.DMABufYuvColorSpaceHint.Value,
2851 attrs.DMABufSampleRangeHint.Value,
2852 attrs.DMABufChromaHorizontalSiting.Value,
2853 attrs.DMABufChromaVerticalSiting.Value,
2854 &error,
2855 NULL);
2856 }
2857 else {
2858 dri_image =
2859 dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen,
2860 attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
2861 fds, num_fds, pitches, offsets,
2862 attrs.DMABufYuvColorSpaceHint.Value,
2863 attrs.DMABufSampleRangeHint.Value,
2864 attrs.DMABufChromaHorizontalSiting.Value,
2865 attrs.DMABufChromaVerticalSiting.Value,
2866 &error,
2867 NULL);
2868 }
2869 dri2_create_image_khr_texture_error(error);
2870
2871 if (!dri_image)
2872 return EGL_NO_IMAGE_KHR;
2873
2874 res = dri2_create_image_from_dri(disp, dri_image);
2875
2876 return res;
2877 }
2878 static _EGLImage *
2879 dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp,
2880 const EGLint *attr_list)
2881 {
2882 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2883 struct dri2_egl_image *dri2_img;
2884 _EGLImageAttribs attrs;
2885 unsigned int dri_use, valid_mask;
2886 int format;
2887
2888 (void) drv;
2889
2890 if (!attr_list) {
2891 _eglError(EGL_BAD_PARAMETER, __func__);
2892 return EGL_NO_IMAGE_KHR;
2893 }
2894
2895 if (!_eglParseImageAttribList(&attrs, disp, attr_list))
2896 return EGL_NO_IMAGE_KHR;
2897
2898 if (attrs.Width <= 0 || attrs.Height <= 0) {
2899 _eglError(EGL_BAD_PARAMETER, __func__);
2900 return EGL_NO_IMAGE_KHR;
2901 }
2902
2903 switch (attrs.DRMBufferFormatMESA) {
2904 case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
2905 format = __DRI_IMAGE_FORMAT_ARGB8888;
2906 break;
2907 default:
2908 _eglError(EGL_BAD_PARAMETER, __func__);
2909 return EGL_NO_IMAGE_KHR;
2910 }
2911
2912 valid_mask =
2913 EGL_DRM_BUFFER_USE_SCANOUT_MESA |
2914 EGL_DRM_BUFFER_USE_SHARE_MESA |
2915 EGL_DRM_BUFFER_USE_CURSOR_MESA;
2916 if (attrs.DRMBufferUseMESA & ~valid_mask) {
2917 _eglError(EGL_BAD_PARAMETER, __func__);
2918 return EGL_NO_IMAGE_KHR;
2919 }
2920
2921 dri_use = 0;
2922 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA)
2923 dri_use |= __DRI_IMAGE_USE_SHARE;
2924 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
2925 dri_use |= __DRI_IMAGE_USE_SCANOUT;
2926 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA)
2927 dri_use |= __DRI_IMAGE_USE_CURSOR;
2928
2929 dri2_img = malloc(sizeof *dri2_img);
2930 if (!dri2_img) {
2931 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
2932 return EGL_NO_IMAGE_KHR;
2933 }
2934
2935 _eglInitImage(&dri2_img->base, disp);
2936
2937 dri2_img->dri_image =
2938 dri2_dpy->image->createImage(dri2_dpy->dri_screen,
2939 attrs.Width, attrs.Height,
2940 format, dri_use, dri2_img);
2941 if (dri2_img->dri_image == NULL) {
2942 free(dri2_img);
2943 _eglError(EGL_BAD_ALLOC, "dri2_create_drm_image_mesa");
2944 return EGL_NO_IMAGE_KHR;
2945 }
2946
2947 return &dri2_img->base;
2948 }
2949
2950 static EGLBoolean
2951 dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
2952 EGLint *name, EGLint *handle, EGLint *stride)
2953 {
2954 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2955 struct dri2_egl_image *dri2_img = dri2_egl_image(img);
2956
2957 (void) drv;
2958
2959 if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image,
2960 __DRI_IMAGE_ATTRIB_NAME, name))
2961 return _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa");
2962
2963 if (handle)
2964 dri2_dpy->image->queryImage(dri2_img->dri_image,
2965 __DRI_IMAGE_ATTRIB_HANDLE, handle);
2966
2967 if (stride)
2968 dri2_dpy->image->queryImage(dri2_img->dri_image,
2969 __DRI_IMAGE_ATTRIB_STRIDE, stride);
2970
2971 return EGL_TRUE;
2972 }
2973
2974 /**
2975 * Checks if we can support EGL_MESA_image_dma_buf_export on this image.
2976
2977 * The spec provides a boolean return for the driver to reject exporting for
2978 * basically any reason, but doesn't specify any particular error cases. For
2979 * now, we just fail if we don't have a DRM fourcc for the format.
2980 */
2981 static bool
2982 dri2_can_export_dma_buf_image(_EGLDisplay *disp, _EGLImage *img)
2983 {
2984 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2985 struct dri2_egl_image *dri2_img = dri2_egl_image(img);
2986 EGLint fourcc;
2987
2988 if (!dri2_dpy->image->queryImage(dri2_img->dri_image,
2989 __DRI_IMAGE_ATTRIB_FOURCC, &fourcc)) {
2990 return false;
2991 }
2992
2993 return true;
2994 }
2995
2996 static EGLBoolean
2997 dri2_export_dma_buf_image_query_mesa(_EGLDriver *drv, _EGLDisplay *disp,
2998 _EGLImage *img,
2999 EGLint *fourcc, EGLint *nplanes,
3000 EGLuint64KHR *modifiers)
3001 {
3002 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3003 struct dri2_egl_image *dri2_img = dri2_egl_image(img);
3004 int num_planes;
3005
3006 (void) drv;
3007
3008 if (!dri2_can_export_dma_buf_image(disp, img))
3009 return EGL_FALSE;
3010
3011 dri2_dpy->image->queryImage(dri2_img->dri_image,
3012 __DRI_IMAGE_ATTRIB_NUM_PLANES, &num_planes);
3013 if (nplanes)
3014 *nplanes = num_planes;
3015
3016 if (fourcc)
3017 dri2_dpy->image->queryImage(dri2_img->dri_image,
3018 __DRI_IMAGE_ATTRIB_FOURCC, fourcc);
3019
3020 if (modifiers) {
3021 int mod_hi, mod_lo;
3022 uint64_t modifier = DRM_FORMAT_MOD_INVALID;
3023 bool query;
3024
3025 query = dri2_dpy->image->queryImage(dri2_img->dri_image,
3026 __DRI_IMAGE_ATTRIB_MODIFIER_UPPER,
3027 &mod_hi);
3028 query &= dri2_dpy->image->queryImage(dri2_img->dri_image,
3029 __DRI_IMAGE_ATTRIB_MODIFIER_LOWER,
3030 &mod_lo);
3031 if (query)
3032 modifier = combine_u32_into_u64 (mod_hi, mod_lo);
3033
3034 for (int i = 0; i < num_planes; i++)
3035 modifiers[i] = modifier;
3036 }
3037
3038 return EGL_TRUE;
3039 }
3040
3041 static EGLBoolean
3042 dri2_export_dma_buf_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
3043 int *fds, EGLint *strides, EGLint *offsets)
3044 {
3045 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3046 struct dri2_egl_image *dri2_img = dri2_egl_image(img);
3047 EGLint nplanes;
3048
3049 (void) drv;
3050
3051 if (!dri2_can_export_dma_buf_image(disp, img))
3052 return EGL_FALSE;
3053
3054 /* EGL_MESA_image_dma_buf_export spec says:
3055 * "If the number of fds is less than the number of planes, then
3056 * subsequent fd slots should contain -1."
3057 */
3058 if (fds) {
3059 /* Query nplanes so that we know how big the given array is. */
3060 dri2_dpy->image->queryImage(dri2_img->dri_image,
3061 __DRI_IMAGE_ATTRIB_NUM_PLANES, &nplanes);
3062 memset(fds, -1, nplanes * sizeof(int));
3063 }
3064
3065 /* rework later to provide multiple fds/strides/offsets */
3066 if (fds)
3067 dri2_dpy->image->queryImage(dri2_img->dri_image,
3068 __DRI_IMAGE_ATTRIB_FD, fds);
3069
3070 if (strides)
3071 dri2_dpy->image->queryImage(dri2_img->dri_image,
3072 __DRI_IMAGE_ATTRIB_STRIDE, strides);
3073
3074 if (offsets) {
3075 int img_offset;
3076 bool ret = dri2_dpy->image->queryImage(dri2_img->dri_image,
3077 __DRI_IMAGE_ATTRIB_OFFSET, &img_offset);
3078 if (ret)
3079 offsets[0] = img_offset;
3080 else
3081 offsets[0] = 0;
3082 }
3083
3084 return EGL_TRUE;
3085 }
3086
3087 #endif
3088
3089 _EGLImage *
3090 dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
3091 _EGLContext *ctx, EGLenum target,
3092 EGLClientBuffer buffer, const EGLint *attr_list)
3093 {
3094 (void) drv;
3095
3096 switch (target) {
3097 case EGL_GL_TEXTURE_2D_KHR:
3098 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
3099 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
3100 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
3101 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
3102 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
3103 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
3104 case EGL_GL_TEXTURE_3D_KHR:
3105 return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
3106 case EGL_GL_RENDERBUFFER_KHR:
3107 return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
3108 #ifdef HAVE_LIBDRM
3109 case EGL_DRM_BUFFER_MESA:
3110 return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
3111 case EGL_LINUX_DMA_BUF_EXT:
3112 return dri2_create_image_dma_buf(disp, ctx, buffer, attr_list);
3113 #endif
3114 #ifdef HAVE_WAYLAND_PLATFORM
3115 case EGL_WAYLAND_BUFFER_WL:
3116 return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
3117 #endif
3118 default:
3119 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
3120 return EGL_NO_IMAGE_KHR;
3121 }
3122 }
3123
3124 static EGLBoolean
3125 dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image)
3126 {
3127 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3128 struct dri2_egl_image *dri2_img = dri2_egl_image(image);
3129
3130 (void) drv;
3131
3132 dri2_dpy->image->destroyImage(dri2_img->dri_image);
3133 free(dri2_img);
3134
3135 return EGL_TRUE;
3136 }
3137
3138 #ifdef HAVE_WAYLAND_PLATFORM
3139
3140 static void
3141 dri2_wl_reference_buffer(void *user_data, uint32_t name, int fd,
3142 struct wl_drm_buffer *buffer)
3143 {
3144 _EGLDisplay *disp = user_data;
3145 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3146 __DRIimage *img;
3147 int dri_components = 0;
3148
3149 if (fd == -1)
3150 img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen,
3151 buffer->width,
3152 buffer->height,
3153 buffer->format,
3154 (int*)&name, 1,
3155 buffer->stride,
3156 buffer->offset,
3157 NULL);
3158 else
3159 img = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
3160 buffer->width,
3161 buffer->height,
3162 buffer->format,
3163 &fd, 1,
3164 buffer->stride,
3165 buffer->offset,
3166 NULL);
3167
3168 if (img == NULL)
3169 return;
3170
3171 dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components);
3172
3173 buffer->driver_format = NULL;
3174 for (int i = 0; i < ARRAY_SIZE(wl_drm_components); i++)
3175 if (wl_drm_components[i].dri_components == dri_components)
3176 buffer->driver_format = &wl_drm_components[i];
3177
3178 if (buffer->driver_format == NULL)
3179 dri2_dpy->image->destroyImage(img);
3180 else
3181 buffer->driver_buffer = img;
3182 }
3183
3184 static void
3185 dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer)
3186 {
3187 _EGLDisplay *disp = user_data;
3188 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3189
3190 dri2_dpy->image->destroyImage(buffer->driver_buffer);
3191 }
3192
3193 static EGLBoolean
3194 dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
3195 struct wl_display *wl_dpy)
3196 {
3197 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3198 const struct wayland_drm_callbacks wl_drm_callbacks = {
3199 .authenticate = (int(*)(void *, uint32_t)) dri2_dpy->vtbl->authenticate,
3200 .reference_buffer = dri2_wl_reference_buffer,
3201 .release_buffer = dri2_wl_release_buffer,
3202 .is_format_supported = dri2_wl_is_format_supported
3203 };
3204 int flags = 0;
3205 uint64_t cap;
3206
3207 (void) drv;
3208
3209 if (dri2_dpy->wl_server_drm)
3210 return EGL_FALSE;
3211
3212 if (drmGetCap(dri2_dpy->fd, DRM_CAP_PRIME, &cap) == 0 &&
3213 cap == (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT) &&
3214 dri2_dpy->image->base.version >= 7 &&
3215 dri2_dpy->image->createImageFromFds != NULL)
3216 flags |= WAYLAND_DRM_PRIME;
3217
3218 dri2_dpy->wl_server_drm =
3219 wayland_drm_init(wl_dpy, dri2_dpy->device_name,
3220 &wl_drm_callbacks, disp, flags);
3221
3222 if (!dri2_dpy->wl_server_drm)
3223 return EGL_FALSE;
3224
3225 #ifdef HAVE_DRM_PLATFORM
3226 /* We have to share the wl_drm instance with gbm, so gbm can convert
3227 * wl_buffers to gbm bos. */
3228 if (dri2_dpy->gbm_dri)
3229 dri2_dpy->gbm_dri->wl_drm = dri2_dpy->wl_server_drm;
3230 #endif
3231
3232 return EGL_TRUE;
3233 }
3234
3235 static EGLBoolean
3236 dri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
3237 struct wl_display *wl_dpy)
3238 {
3239 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3240
3241 (void) drv;
3242
3243 if (!dri2_dpy->wl_server_drm)
3244 return EGL_FALSE;
3245
3246 wayland_drm_uninit(dri2_dpy->wl_server_drm);
3247 dri2_dpy->wl_server_drm = NULL;
3248
3249 return EGL_TRUE;
3250 }
3251
3252 static EGLBoolean
3253 dri2_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *disp,
3254 struct wl_resource *buffer_resource,
3255 EGLint attribute, EGLint *value)
3256 {
3257 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3258 struct wl_drm_buffer *buffer;
3259 const struct wl_drm_components_descriptor *format;
3260
3261 buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm, buffer_resource);
3262 if (!buffer)
3263 return EGL_FALSE;
3264
3265 format = buffer->driver_format;
3266 switch (attribute) {
3267 case EGL_TEXTURE_FORMAT:
3268 *value = format->components;
3269 return EGL_TRUE;
3270 case EGL_WIDTH:
3271 *value = buffer->width;
3272 return EGL_TRUE;
3273 case EGL_HEIGHT:
3274 *value = buffer->height;
3275 return EGL_TRUE;
3276 }
3277
3278 return EGL_FALSE;
3279 }
3280 #endif
3281
3282 static void
3283 dri2_egl_ref_sync(struct dri2_egl_sync *sync)
3284 {
3285 p_atomic_inc(&sync->refcount);
3286 }
3287
3288 static void
3289 dri2_egl_unref_sync(struct dri2_egl_display *dri2_dpy,
3290 struct dri2_egl_sync *dri2_sync)
3291 {
3292 if (p_atomic_dec_zero(&dri2_sync->refcount)) {
3293 switch (dri2_sync->base.Type) {
3294 case EGL_SYNC_REUSABLE_KHR:
3295 cnd_destroy(&dri2_sync->cond);
3296 break;
3297 case EGL_SYNC_NATIVE_FENCE_ANDROID:
3298 if (dri2_sync->base.SyncFd != EGL_NO_NATIVE_FENCE_FD_ANDROID)
3299 close(dri2_sync->base.SyncFd);
3300 break;
3301 default:
3302 break;
3303 }
3304
3305 if (dri2_sync->fence)
3306 dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, dri2_sync->fence);
3307
3308 free(dri2_sync);
3309 }
3310 }
3311
3312 static _EGLSync *
3313 dri2_create_sync(_EGLDriver *drv, _EGLDisplay *disp,
3314 EGLenum type, const EGLAttrib *attrib_list)
3315 {
3316 _EGLContext *ctx = _eglGetCurrentContext();
3317 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3318 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3319 struct dri2_egl_sync *dri2_sync;
3320 EGLint ret;
3321 pthread_condattr_t attr;
3322
3323 dri2_sync = calloc(1, sizeof(struct dri2_egl_sync));
3324 if (!dri2_sync) {
3325 _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
3326 return NULL;
3327 }
3328
3329 if (!_eglInitSync(&dri2_sync->base, disp, type, attrib_list)) {
3330 free(dri2_sync);
3331 return NULL;
3332 }
3333
3334 switch (type) {
3335 case EGL_SYNC_FENCE_KHR:
3336 dri2_sync->fence = dri2_dpy->fence->create_fence(dri2_ctx->dri_context);
3337 if (!dri2_sync->fence) {
3338 /* Why did it fail? DRI doesn't return an error code, so we emit
3339 * a generic EGL error that doesn't communicate user error.
3340 */
3341 _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
3342 free(dri2_sync);
3343 return NULL;
3344 }
3345 break;
3346
3347 case EGL_SYNC_CL_EVENT_KHR:
3348 dri2_sync->fence = dri2_dpy->fence->get_fence_from_cl_event(
3349 dri2_dpy->dri_screen,
3350 dri2_sync->base.CLEvent);
3351 /* this can only happen if the cl_event passed in is invalid. */
3352 if (!dri2_sync->fence) {
3353 _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
3354 free(dri2_sync);
3355 return NULL;
3356 }
3357
3358 /* the initial status must be "signaled" if the cl_event is signaled */
3359 if (dri2_dpy->fence->client_wait_sync(dri2_ctx->dri_context,
3360 dri2_sync->fence, 0, 0))
3361 dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
3362 break;
3363
3364 case EGL_SYNC_REUSABLE_KHR:
3365 /* intialize attr */
3366 ret = pthread_condattr_init(&attr);
3367
3368 if (ret) {
3369 _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR");
3370 free(dri2_sync);
3371 return NULL;
3372 }
3373
3374 /* change clock attribute to CLOCK_MONOTONIC */
3375 ret = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
3376
3377 if (ret) {
3378 _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR");
3379 free(dri2_sync);
3380 return NULL;
3381 }
3382
3383 ret = pthread_cond_init(&dri2_sync->cond, &attr);
3384
3385 if (ret) {
3386 _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR");
3387 free(dri2_sync);
3388 return NULL;
3389 }
3390
3391 /* initial status of reusable sync must be "unsignaled" */
3392 dri2_sync->base.SyncStatus = EGL_UNSIGNALED_KHR;
3393 break;
3394
3395 case EGL_SYNC_NATIVE_FENCE_ANDROID:
3396 if (dri2_dpy->fence->create_fence_fd) {
3397 dri2_sync->fence = dri2_dpy->fence->create_fence_fd(
3398 dri2_ctx->dri_context,
3399 dri2_sync->base.SyncFd);
3400 }
3401 if (!dri2_sync->fence) {
3402 _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
3403 free(dri2_sync);
3404 return NULL;
3405 }
3406 break;
3407 }
3408
3409 p_atomic_set(&dri2_sync->refcount, 1);
3410 return &dri2_sync->base;
3411 }
3412
3413 static EGLBoolean
3414 dri2_destroy_sync(_EGLDriver *drv, _EGLDisplay *disp, _EGLSync *sync)
3415 {
3416 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3417 struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3418 EGLint ret = EGL_TRUE;
3419 EGLint err;
3420
3421 /* if type of sync is EGL_SYNC_REUSABLE_KHR and it is not signaled yet,
3422 * then unlock all threads possibly blocked by the reusable sync before
3423 * destroying it.
3424 */
3425 if (dri2_sync->base.Type == EGL_SYNC_REUSABLE_KHR &&
3426 dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR) {
3427 dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
3428 /* unblock all threads currently blocked by sync */
3429 err = cnd_broadcast(&dri2_sync->cond);
3430
3431 if (err) {
3432 _eglError(EGL_BAD_ACCESS, "eglDestroySyncKHR");
3433 ret = EGL_FALSE;
3434 }
3435 }
3436
3437 dri2_egl_unref_sync(dri2_dpy, dri2_sync);
3438
3439 return ret;
3440 }
3441
3442 static EGLint
3443 dri2_dup_native_fence_fd(_EGLDriver *drv, _EGLDisplay *disp, _EGLSync *sync)
3444 {
3445 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3446 struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3447
3448 assert(sync->Type == EGL_SYNC_NATIVE_FENCE_ANDROID);
3449
3450 if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
3451 /* try to retrieve the actual native fence fd.. if rendering is
3452 * not flushed this will just return -1, aka NO_NATIVE_FENCE_FD:
3453 */
3454 sync->SyncFd = dri2_dpy->fence->get_fence_fd(dri2_dpy->dri_screen,
3455 dri2_sync->fence);
3456 }
3457
3458 if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
3459 /* if native fence fd still not created, return an error: */
3460 _eglError(EGL_BAD_PARAMETER, "eglDupNativeFenceFDANDROID");
3461 return EGL_NO_NATIVE_FENCE_FD_ANDROID;
3462 }
3463
3464 return dup(sync->SyncFd);
3465 }
3466
3467 static void
3468 dri2_set_blob_cache_funcs(_EGLDriver *drv, _EGLDisplay *disp,
3469 EGLSetBlobFuncANDROID set,
3470 EGLGetBlobFuncANDROID get)
3471 {
3472 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3473 dri2_dpy->blob->set_cache_funcs(dri2_dpy->dri_screen,
3474 disp->BlobCacheSet,
3475 disp->BlobCacheGet);
3476 }
3477
3478 static EGLint
3479 dri2_client_wait_sync(_EGLDriver *drv, _EGLDisplay *disp, _EGLSync *sync,
3480 EGLint flags, EGLTime timeout)
3481 {
3482 _EGLContext *ctx = _eglGetCurrentContext();
3483 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3484 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3485 struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3486 unsigned wait_flags = 0;
3487
3488 EGLint ret = EGL_CONDITION_SATISFIED_KHR;
3489
3490 /* The EGL_KHR_fence_sync spec states:
3491 *
3492 * "If no context is current for the bound API,
3493 * the EGL_SYNC_FLUSH_COMMANDS_BIT_KHR bit is ignored.
3494 */
3495 if (dri2_ctx && flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)
3496 wait_flags |= __DRI2_FENCE_FLAG_FLUSH_COMMANDS;
3497
3498 /* the sync object should take a reference while waiting */
3499 dri2_egl_ref_sync(dri2_sync);
3500
3501 switch (sync->Type) {
3502 case EGL_SYNC_FENCE_KHR:
3503 case EGL_SYNC_NATIVE_FENCE_ANDROID:
3504 case EGL_SYNC_CL_EVENT_KHR:
3505 if (dri2_dpy->fence->client_wait_sync(dri2_ctx ? dri2_ctx->dri_context : NULL,
3506 dri2_sync->fence, wait_flags,
3507 timeout))
3508 dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
3509 else
3510 ret = EGL_TIMEOUT_EXPIRED_KHR;
3511 break;
3512
3513 case EGL_SYNC_REUSABLE_KHR:
3514 if (dri2_ctx && dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR &&
3515 (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)) {
3516 /* flush context if EGL_SYNC_FLUSH_COMMANDS_BIT_KHR is set */
3517 dri2_gl_flush();
3518 }
3519
3520 /* if timeout is EGL_FOREVER_KHR, it should wait without any timeout.*/
3521 if (timeout == EGL_FOREVER_KHR) {
3522 mtx_lock(&dri2_sync->mutex);
3523 cnd_wait(&dri2_sync->cond, &dri2_sync->mutex);
3524 mtx_unlock(&dri2_sync->mutex);
3525 } else {
3526 /* if reusable sync has not been yet signaled */
3527 if (dri2_sync->base.SyncStatus != EGL_SIGNALED_KHR) {
3528 /* timespecs for cnd_timedwait */
3529 struct timespec current;
3530 struct timespec expire;
3531
3532 /* We override the clock to monotonic when creating the condition
3533 * variable. */
3534 clock_gettime(CLOCK_MONOTONIC, &current);
3535
3536 /* calculating when to expire */
3537 expire.tv_nsec = timeout % 1000000000L;
3538 expire.tv_sec = timeout / 1000000000L;
3539
3540 expire.tv_nsec += current.tv_nsec;
3541 expire.tv_sec += current.tv_sec;
3542
3543 /* expire.nsec now is a number between 0 and 1999999998 */
3544 if (expire.tv_nsec > 999999999L) {
3545 expire.tv_sec++;
3546 expire.tv_nsec -= 1000000000L;
3547 }
3548
3549 mtx_lock(&dri2_sync->mutex);
3550 ret = cnd_timedwait(&dri2_sync->cond, &dri2_sync->mutex, &expire);
3551 mtx_unlock(&dri2_sync->mutex);
3552
3553 if (ret == thrd_busy) {
3554 if (dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR) {
3555 ret = EGL_TIMEOUT_EXPIRED_KHR;
3556 } else {
3557 _eglError(EGL_BAD_ACCESS, "eglClientWaitSyncKHR");
3558 ret = EGL_FALSE;
3559 }
3560 }
3561 }
3562 }
3563 break;
3564 }
3565 dri2_egl_unref_sync(dri2_dpy, dri2_sync);
3566
3567 return ret;
3568 }
3569
3570 static EGLBoolean
3571 dri2_signal_sync(_EGLDriver *drv, _EGLDisplay *disp, _EGLSync *sync,
3572 EGLenum mode)
3573 {
3574 struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3575 EGLint ret;
3576
3577 if (sync->Type != EGL_SYNC_REUSABLE_KHR)
3578 return _eglError(EGL_BAD_MATCH, "eglSignalSyncKHR");
3579
3580 if (mode != EGL_SIGNALED_KHR && mode != EGL_UNSIGNALED_KHR)
3581 return _eglError(EGL_BAD_ATTRIBUTE, "eglSignalSyncKHR");
3582
3583 dri2_sync->base.SyncStatus = mode;
3584
3585 if (mode == EGL_SIGNALED_KHR) {
3586 ret = cnd_broadcast(&dri2_sync->cond);
3587
3588 /* fail to broadcast */
3589 if (ret)
3590 return _eglError(EGL_BAD_ACCESS, "eglSignalSyncKHR");
3591 }
3592
3593 return EGL_TRUE;
3594 }
3595
3596 static EGLint
3597 dri2_server_wait_sync(_EGLDriver *drv, _EGLDisplay *disp, _EGLSync *sync)
3598 {
3599 _EGLContext *ctx = _eglGetCurrentContext();
3600 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3601 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3602 struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3603
3604 dri2_dpy->fence->server_wait_sync(dri2_ctx->dri_context,
3605 dri2_sync->fence, 0);
3606 return EGL_TRUE;
3607 }
3608
3609 static int
3610 dri2_interop_query_device_info(_EGLDisplay *disp, _EGLContext *ctx,
3611 struct mesa_glinterop_device_info *out)
3612 {
3613 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3614 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3615
3616 if (!dri2_dpy->interop)
3617 return MESA_GLINTEROP_UNSUPPORTED;
3618
3619 return dri2_dpy->interop->query_device_info(dri2_ctx->dri_context, out);
3620 }
3621
3622 static int
3623 dri2_interop_export_object(_EGLDisplay *disp, _EGLContext *ctx,
3624 struct mesa_glinterop_export_in *in,
3625 struct mesa_glinterop_export_out *out)
3626 {
3627 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3628 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3629
3630 if (!dri2_dpy->interop)
3631 return MESA_GLINTEROP_UNSUPPORTED;
3632
3633 return dri2_dpy->interop->export_object(dri2_ctx->dri_context, in, out);
3634 }
3635
3636 /**
3637 * This is the main entrypoint into the driver, called by libEGL.
3638 * Gets an _EGLDriver object and init its dispatch table.
3639 */
3640 void
3641 _eglInitDriver(_EGLDriver *dri2_drv)
3642 {
3643 dri2_drv->API.Initialize = dri2_initialize;
3644 dri2_drv->API.Terminate = dri2_terminate;
3645 dri2_drv->API.CreateContext = dri2_create_context;
3646 dri2_drv->API.DestroyContext = dri2_destroy_context;
3647 dri2_drv->API.MakeCurrent = dri2_make_current;
3648 dri2_drv->API.CreateWindowSurface = dri2_create_window_surface;
3649 dri2_drv->API.CreatePixmapSurface = dri2_create_pixmap_surface;
3650 dri2_drv->API.CreatePbufferSurface = dri2_create_pbuffer_surface;
3651 dri2_drv->API.DestroySurface = dri2_destroy_surface;
3652 dri2_drv->API.GetProcAddress = dri2_get_proc_address;
3653 dri2_drv->API.WaitClient = dri2_wait_client;
3654 dri2_drv->API.WaitNative = dri2_wait_native;
3655 dri2_drv->API.BindTexImage = dri2_bind_tex_image;
3656 dri2_drv->API.ReleaseTexImage = dri2_release_tex_image;
3657 dri2_drv->API.SwapInterval = dri2_swap_interval;
3658 dri2_drv->API.SwapBuffers = dri2_swap_buffers;
3659 dri2_drv->API.SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage;
3660 dri2_drv->API.SwapBuffersRegionNOK = dri2_swap_buffers_region;
3661 dri2_drv->API.SetDamageRegion = dri2_set_damage_region;
3662 dri2_drv->API.PostSubBufferNV = dri2_post_sub_buffer;
3663 dri2_drv->API.CopyBuffers = dri2_copy_buffers,
3664 dri2_drv->API.QueryBufferAge = dri2_query_buffer_age;
3665 dri2_drv->API.CreateImageKHR = dri2_create_image;
3666 dri2_drv->API.DestroyImageKHR = dri2_destroy_image_khr;
3667 dri2_drv->API.CreateWaylandBufferFromImageWL = dri2_create_wayland_buffer_from_image;
3668 dri2_drv->API.QuerySurface = dri2_query_surface;
3669 dri2_drv->API.QueryDriverName = dri2_query_driver_name;
3670 dri2_drv->API.QueryDriverConfig = dri2_query_driver_config;
3671 #ifdef HAVE_LIBDRM
3672 dri2_drv->API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
3673 dri2_drv->API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
3674 dri2_drv->API.ExportDMABUFImageQueryMESA = dri2_export_dma_buf_image_query_mesa;
3675 dri2_drv->API.ExportDMABUFImageMESA = dri2_export_dma_buf_image_mesa;
3676 dri2_drv->API.QueryDmaBufFormatsEXT = dri2_query_dma_buf_formats;
3677 dri2_drv->API.QueryDmaBufModifiersEXT = dri2_query_dma_buf_modifiers;
3678 #endif
3679 #ifdef HAVE_WAYLAND_PLATFORM
3680 dri2_drv->API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl;
3681 dri2_drv->API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl;
3682 dri2_drv->API.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl;
3683 #endif
3684 dri2_drv->API.GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium;
3685 dri2_drv->API.CreateSyncKHR = dri2_create_sync;
3686 dri2_drv->API.ClientWaitSyncKHR = dri2_client_wait_sync;
3687 dri2_drv->API.SignalSyncKHR = dri2_signal_sync;
3688 dri2_drv->API.WaitSyncKHR = dri2_server_wait_sync;
3689 dri2_drv->API.DestroySyncKHR = dri2_destroy_sync;
3690 dri2_drv->API.GLInteropQueryDeviceInfo = dri2_interop_query_device_info;
3691 dri2_drv->API.GLInteropExportObject = dri2_interop_export_object;
3692 dri2_drv->API.DupNativeFenceFDANDROID = dri2_dup_native_fence_fd;
3693 dri2_drv->API.SetBlobCacheFuncsANDROID = dri2_set_blob_cache_funcs;
3694 }