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