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