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