1 /************************************************************************** 2 * 3 * Copyright 2008 VMware, Inc. 4 * Copyright 2009-2010 Chia-I Wu <olvaffe (at) gmail.com> 5 * Copyright 2010-2011 LunarG, Inc. 6 * All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the 10 * "Software"), to deal in the Software without restriction, including 11 * without limitation the rights to use, copy, modify, merge, publish, 12 * distribute, sub license, and/or sell copies of the Software, and to 13 * permit persons to whom the Software is furnished to do so, subject to 14 * the following conditions: 15 * 16 * The above copyright notice and this permission notice (including the 17 * next paragraph) shall be included in all copies or substantial portions 18 * of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 * DEALINGS IN THE SOFTWARE. 27 * 28 **************************************************************************/ 29 30 31 /** 32 * Public EGL API entrypoints 33 * 34 * Generally, we use the EGLDisplay parameter as a key to lookup the 35 * appropriate device driver handle, then jump though the driver's 36 * dispatch table to handle the function. 37 * 38 * That allows us the option of supporting multiple, simultaneous, 39 * heterogeneous hardware devices in the future. 40 * 41 * The EGLDisplay, EGLConfig, EGLContext and EGLSurface types are 42 * opaque handles. Internal objects are linked to a display to 43 * create the handles. 44 * 45 * For each public API entry point, the opaque handles are looked up 46 * before being dispatched to the drivers. When it fails to look up 47 * a handle, one of 48 * 49 * EGL_BAD_DISPLAY 50 * EGL_BAD_CONFIG 51 * EGL_BAD_CONTEXT 52 * EGL_BAD_SURFACE 53 * EGL_BAD_SCREEN_MESA 54 * EGL_BAD_MODE_MESA 55 * 56 * is generated and the driver function is not called. An 57 * uninitialized EGLDisplay has no driver associated with it. When 58 * such display is detected, 59 * 60 * EGL_NOT_INITIALIZED 61 * 62 * is generated. 63 * 64 * Some of the entry points use current display, context, or surface 65 * implicitly. For such entry points, the implicit objects are also 66 * checked before calling the driver function. Other than the 67 * errors listed above, 68 * 69 * EGL_BAD_CURRENT_SURFACE 70 * 71 * may also be generated. 72 * 73 * Notes on naming conventions: 74 * 75 * eglFooBar - public EGL function 76 * EGL_FOO_BAR - public EGL token 77 * EGLDatatype - public EGL datatype 78 * 79 * _eglFooBar - private EGL function 80 * _EGLDatatype - private EGL datatype, typedef'd struct 81 * _egl_struct - private EGL struct, non-typedef'd 82 * 83 */ 84 85 86 #include <stdio.h> 87 #include <stdlib.h> 88 #include <string.h> 89 #include "c99_compat.h" 90 #include "c11/threads.h" 91 #include "GL/mesa_glinterop.h" 92 #include "eglcompiler.h" 93 94 #include "eglglobals.h" 95 #include "eglcontext.h" 96 #include "egldisplay.h" 97 #include "egltypedefs.h" 98 #include "eglcurrent.h" 99 #include "egldriver.h" 100 #include "eglsurface.h" 101 #include "eglconfig.h" 102 #include "eglimage.h" 103 #include "eglsync.h" 104 105 106 /** 107 * Macros to help return an API entrypoint. 108 * 109 * These macros will unlock the display and record the error code. 110 */ 111 #define RETURN_EGL_ERROR(disp, err, ret) \ 112 do { \ 113 if (disp) \ 114 _eglUnlockDisplay(disp); \ 115 /* EGL error codes are non-zero */ \ 116 if (err) \ 117 _eglError(err, __func__); \ 118 return ret; \ 119 } while (0) 120 121 #define RETURN_EGL_SUCCESS(disp, ret) \ 122 RETURN_EGL_ERROR(disp, EGL_SUCCESS, ret) 123 124 /* record EGL_SUCCESS only when ret evaluates to true */ 125 #define RETURN_EGL_EVAL(disp, ret) \ 126 RETURN_EGL_ERROR(disp, (ret) ? EGL_SUCCESS : 0, ret) 127 128 129 /* 130 * A bunch of macros and checks to simplify error checking. 131 */ 132 133 #define _EGL_CHECK_DISPLAY(disp, ret, drv) \ 134 do { \ 135 drv = _eglCheckDisplay(disp, __func__); \ 136 if (!drv) \ 137 RETURN_EGL_ERROR(disp, 0, ret); \ 138 } while (0) 139 140 #define _EGL_CHECK_OBJECT(disp, type, obj, ret, drv) \ 141 do { \ 142 drv = _eglCheck ## type(disp, obj, __func__); \ 143 if (!drv) \ 144 RETURN_EGL_ERROR(disp, 0, ret); \ 145 } while (0) 146 147 #define _EGL_CHECK_SURFACE(disp, surf, ret, drv) \ 148 _EGL_CHECK_OBJECT(disp, Surface, surf, ret, drv) 149 150 #define _EGL_CHECK_CONTEXT(disp, context, ret, drv) \ 151 _EGL_CHECK_OBJECT(disp, Context, context, ret, drv) 152 153 #define _EGL_CHECK_CONFIG(disp, conf, ret, drv) \ 154 _EGL_CHECK_OBJECT(disp, Config, conf, ret, drv) 155 156 #define _EGL_CHECK_SYNC(disp, s, ret, drv) \ 157 _EGL_CHECK_OBJECT(disp, Sync, s, ret, drv) 158 159 160 static inline _EGLDriver * 161 _eglCheckDisplay(_EGLDisplay *disp, const char *msg) 162 { 163 if (!disp) { 164 _eglError(EGL_BAD_DISPLAY, msg); 165 return NULL; 166 } 167 if (!disp->Initialized) { 168 _eglError(EGL_NOT_INITIALIZED, msg); 169 return NULL; 170 } 171 return disp->Driver; 172 } 173 174 175 static inline _EGLDriver * 176 _eglCheckSurface(_EGLDisplay *disp, _EGLSurface *surf, const char *msg) 177 { 178 _EGLDriver *drv = _eglCheckDisplay(disp, msg); 179 if (!drv) 180 return NULL; 181 if (!surf) { 182 _eglError(EGL_BAD_SURFACE, msg); 183 return NULL; 184 } 185 return drv; 186 } 187 188 189 static inline _EGLDriver * 190 _eglCheckContext(_EGLDisplay *disp, _EGLContext *context, const char *msg) 191 { 192 _EGLDriver *drv = _eglCheckDisplay(disp, msg); 193 if (!drv) 194 return NULL; 195 if (!context) { 196 _eglError(EGL_BAD_CONTEXT, msg); 197 return NULL; 198 } 199 return drv; 200 } 201 202 203 static inline _EGLDriver * 204 _eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg) 205 { 206 _EGLDriver *drv = _eglCheckDisplay(disp, msg); 207 if (!drv) 208 return NULL; 209 if (!conf) { 210 _eglError(EGL_BAD_CONFIG, msg); 211 return NULL; 212 } 213 return drv; 214 } 215 216 217 static inline _EGLDriver * 218 _eglCheckSync(_EGLDisplay *disp, _EGLSync *s, const char *msg) 219 { 220 _EGLDriver *drv = _eglCheckDisplay(disp, msg); 221 if (!drv) 222 return NULL; 223 if (!s) { 224 _eglError(EGL_BAD_PARAMETER, msg); 225 return NULL; 226 } 227 return drv; 228 } 229 230 231 /** 232 * Lookup and lock a display. 233 */ 234 static inline _EGLDisplay * 235 _eglLockDisplay(EGLDisplay display) 236 { 237 _EGLDisplay *dpy = _eglLookupDisplay(display); 238 if (dpy) 239 mtx_lock(&dpy->Mutex); 240 return dpy; 241 } 242 243 244 /** 245 * Unlock a display. 246 */ 247 static inline void 248 _eglUnlockDisplay(_EGLDisplay *dpy) 249 { 250 mtx_unlock(&dpy->Mutex); 251 } 252 253 static EGLBoolean 254 _eglSetFuncName(const char *funcName, _EGLDisplay *disp, EGLenum objectType, _EGLResource *object) 255 { 256 _EGLThreadInfo *thr = _eglGetCurrentThread(); 257 if (!_eglIsCurrentThreadDummy()) { 258 thr->CurrentFuncName = funcName; 259 thr->CurrentObjectLabel = NULL; 260 261 if (objectType == EGL_OBJECT_THREAD_KHR) 262 thr->CurrentObjectLabel = thr->Label; 263 else if (objectType == EGL_OBJECT_DISPLAY_KHR && disp) 264 thr->CurrentObjectLabel = disp->Label; 265 else if (object) 266 thr->CurrentObjectLabel = object->Label; 267 268 return EGL_TRUE; 269 } 270 271 _eglDebugReportFull(EGL_BAD_ALLOC, funcName, funcName, 272 EGL_DEBUG_MSG_CRITICAL_KHR, NULL, NULL); 273 return EGL_FALSE; 274 } 275 276 #define _EGL_FUNC_START(disp, objectType, object, ret) \ 277 do { \ 278 if (!_eglSetFuncName(__func__, disp, objectType, (_EGLResource *) object)) { \ 279 if (disp) \ 280 _eglUnlockDisplay(disp); \ 281 return ret; \ 282 } \ 283 } while(0) 284 285 /** 286 * Convert an attribute list from EGLint[] to EGLAttrib[]. 287 * 288 * Return an EGL error code. The output parameter out_attrib_list is modified 289 * only on success. 290 */ 291 static EGLint 292 _eglConvertIntsToAttribs(const EGLint *int_list, EGLAttrib **out_attrib_list) 293 { 294 size_t len = 0; 295 EGLAttrib *attrib_list; 296 297 if (int_list) { 298 while (int_list[2*len] != EGL_NONE) 299 ++len; 300 } 301 302 if (len == 0) { 303 *out_attrib_list = NULL; 304 return EGL_SUCCESS; 305 } 306 307 if (2*len + 1 > SIZE_MAX / sizeof(EGLAttrib)) 308 return EGL_BAD_ALLOC; 309 310 attrib_list = malloc((2*len + 1) * sizeof(EGLAttrib)); 311 if (!attrib_list) 312 return EGL_BAD_ALLOC; 313 314 for (size_t i = 0; i < len; ++i) { 315 attrib_list[2*i + 0] = int_list[2*i + 0]; 316 attrib_list[2*i + 1] = int_list[2*i + 1]; 317 } 318 319 attrib_list[2*len] = EGL_NONE; 320 321 *out_attrib_list = attrib_list; 322 return EGL_SUCCESS; 323 } 324 325 326 static EGLint * 327 _eglConvertAttribsToInt(const EGLAttrib *attr_list) 328 { 329 EGLint *int_attribs = NULL; 330 331 /* Convert attributes from EGLAttrib[] to EGLint[] */ 332 if (attr_list) { 333 int i, size = 0; 334 335 while (attr_list[size] != EGL_NONE) 336 size += 2; 337 338 size += 1; /* add space for EGL_NONE */ 339 340 int_attribs = calloc(size, sizeof(int_attribs[0])); 341 if (!int_attribs) 342 return NULL; 343 344 for (i = 0; i < size; i++) 345 int_attribs[i] = attr_list[i]; 346 } 347 return int_attribs; 348 } 349 350 351 /** 352 * This is typically the first EGL function that an application calls. 353 * It associates a private _EGLDisplay object to the native display. 354 */ 355 EGLDisplay EGLAPIENTRY 356 eglGetDisplay(EGLNativeDisplayType nativeDisplay) 357 { 358 _EGLPlatformType plat; 359 _EGLDisplay *dpy; 360 void *native_display_ptr; 361 362 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY); 363 364 STATIC_ASSERT(sizeof(void*) == sizeof(nativeDisplay)); 365 native_display_ptr = (void*) nativeDisplay; 366 367 plat = _eglGetNativePlatform(native_display_ptr); 368 dpy = _eglFindDisplay(plat, native_display_ptr); 369 return _eglGetDisplayHandle(dpy); 370 } 371 372 static EGLDisplay 373 _eglGetPlatformDisplayCommon(EGLenum platform, void *native_display, 374 const EGLint *attrib_list) 375 { 376 _EGLDisplay *dpy; 377 378 switch (platform) { 379 #ifdef HAVE_X11_PLATFORM 380 case EGL_PLATFORM_X11_EXT: 381 dpy = _eglGetX11Display((Display*) native_display, attrib_list); 382 break; 383 #endif 384 #ifdef HAVE_DRM_PLATFORM 385 case EGL_PLATFORM_GBM_MESA: 386 dpy = _eglGetGbmDisplay((struct gbm_device*) native_display, 387 attrib_list); 388 break; 389 #endif 390 #ifdef HAVE_WAYLAND_PLATFORM 391 case EGL_PLATFORM_WAYLAND_EXT: 392 dpy = _eglGetWaylandDisplay((struct wl_display*) native_display, 393 attrib_list); 394 break; 395 #endif 396 #ifdef HAVE_SURFACELESS_PLATFORM 397 case EGL_PLATFORM_SURFACELESS_MESA: 398 dpy = _eglGetSurfacelessDisplay(native_display, attrib_list); 399 break; 400 #endif 401 default: 402 RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, NULL); 403 } 404 405 return _eglGetDisplayHandle(dpy); 406 } 407 408 static EGLDisplay EGLAPIENTRY 409 eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, 410 const EGLint *attrib_list) 411 { 412 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY); 413 return _eglGetPlatformDisplayCommon(platform, native_display, attrib_list); 414 } 415 416 EGLDisplay EGLAPIENTRY 417 eglGetPlatformDisplay(EGLenum platform, void *native_display, 418 const EGLAttrib *attrib_list) 419 { 420 EGLDisplay display; 421 EGLint *int_attribs; 422 423 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY); 424 425 int_attribs = _eglConvertAttribsToInt(attrib_list); 426 if (attrib_list && !int_attribs) 427 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL); 428 429 display = _eglGetPlatformDisplayCommon(platform, native_display, int_attribs); 430 free(int_attribs); 431 return display; 432 } 433 434 /** 435 * Copy the extension into the string and update the string pointer. 436 */ 437 static EGLint 438 _eglAppendExtension(char **str, const char *ext) 439 { 440 char *s = *str; 441 size_t len = strlen(ext); 442 443 if (s) { 444 memcpy(s, ext, len); 445 s[len++] = ' '; 446 s[len] = '\0'; 447 448 *str += len; 449 } 450 else { 451 len++; 452 } 453 454 return (EGLint) len; 455 } 456 457 /** 458 * Examine the individual extension enable/disable flags and recompute 459 * the driver's Extensions string. 460 */ 461 static void 462 _eglCreateExtensionsString(_EGLDisplay *dpy) 463 { 464 #define _EGL_CHECK_EXTENSION(ext) \ 465 do { \ 466 if (dpy->Extensions.ext) { \ 467 _eglAppendExtension(&exts, "EGL_" #ext); \ 468 assert(exts <= dpy->ExtensionsString + _EGL_MAX_EXTENSIONS_LEN); \ 469 } \ 470 } while (0) 471 472 char *exts = dpy->ExtensionsString; 473 474 /* Please keep these sorted alphabetically. */ 475 _EGL_CHECK_EXTENSION(ANDROID_framebuffer_target); 476 _EGL_CHECK_EXTENSION(ANDROID_image_native_buffer); 477 _EGL_CHECK_EXTENSION(ANDROID_native_fence_sync); 478 _EGL_CHECK_EXTENSION(ANDROID_recordable); 479 480 _EGL_CHECK_EXTENSION(CHROMIUM_sync_control); 481 482 _EGL_CHECK_EXTENSION(EXT_buffer_age); 483 _EGL_CHECK_EXTENSION(EXT_create_context_robustness); 484 _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import); 485 _EGL_CHECK_EXTENSION(EXT_swap_buffers_with_damage); 486 487 _EGL_CHECK_EXTENSION(KHR_cl_event2); 488 _EGL_CHECK_EXTENSION(KHR_config_attribs); 489 _EGL_CHECK_EXTENSION(KHR_create_context); 490 _EGL_CHECK_EXTENSION(KHR_fence_sync); 491 _EGL_CHECK_EXTENSION(KHR_get_all_proc_addresses); 492 _EGL_CHECK_EXTENSION(KHR_gl_colorspace); 493 _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image); 494 _EGL_CHECK_EXTENSION(KHR_gl_texture_2D_image); 495 _EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image); 496 _EGL_CHECK_EXTENSION(KHR_gl_texture_cubemap_image); 497 if (dpy->Extensions.KHR_image_base && dpy->Extensions.KHR_image_pixmap) 498 _eglAppendExtension(&exts, "EGL_KHR_image"); 499 _EGL_CHECK_EXTENSION(KHR_image_base); 500 _EGL_CHECK_EXTENSION(KHR_image_pixmap); 501 _EGL_CHECK_EXTENSION(KHR_no_config_context); 502 _EGL_CHECK_EXTENSION(KHR_reusable_sync); 503 _EGL_CHECK_EXTENSION(KHR_surfaceless_context); 504 if (dpy->Extensions.EXT_swap_buffers_with_damage) 505 _eglAppendExtension(&exts, "EGL_KHR_swap_buffers_with_damage"); 506 _EGL_CHECK_EXTENSION(KHR_wait_sync); 507 508 if (dpy->Extensions.KHR_no_config_context) 509 _eglAppendExtension(&exts, "EGL_MESA_configless_context"); 510 _EGL_CHECK_EXTENSION(MESA_drm_image); 511 _EGL_CHECK_EXTENSION(MESA_image_dma_buf_export); 512 513 _EGL_CHECK_EXTENSION(NOK_swap_region); 514 _EGL_CHECK_EXTENSION(NOK_texture_from_pixmap); 515 516 _EGL_CHECK_EXTENSION(NV_post_sub_buffer); 517 518 _EGL_CHECK_EXTENSION(WL_bind_wayland_display); 519 _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image); 520 521 #undef _EGL_CHECK_EXTENSION 522 } 523 524 static void 525 _eglCreateAPIsString(_EGLDisplay *dpy) 526 { 527 if (dpy->ClientAPIs & EGL_OPENGL_BIT) 528 strcat(dpy->ClientAPIsString, "OpenGL "); 529 530 if (dpy->ClientAPIs & EGL_OPENGL_ES_BIT || 531 dpy->ClientAPIs & EGL_OPENGL_ES2_BIT || 532 dpy->ClientAPIs & EGL_OPENGL_ES3_BIT_KHR) { 533 strcat(dpy->ClientAPIsString, "OpenGL_ES "); 534 } 535 536 if (dpy->ClientAPIs & EGL_OPENVG_BIT) 537 strcat(dpy->ClientAPIsString, "OpenVG "); 538 539 assert(strlen(dpy->ClientAPIsString) < sizeof(dpy->ClientAPIsString)); 540 } 541 542 static void 543 _eglComputeVersion(_EGLDisplay *disp) 544 { 545 disp->Version = 14; 546 547 if (disp->Extensions.KHR_fence_sync && 548 disp->Extensions.KHR_cl_event2 && 549 disp->Extensions.KHR_wait_sync && 550 disp->Extensions.KHR_image_base && 551 disp->Extensions.KHR_gl_texture_2D_image && 552 disp->Extensions.KHR_gl_texture_3D_image && 553 disp->Extensions.KHR_gl_texture_cubemap_image && 554 disp->Extensions.KHR_gl_renderbuffer_image && 555 disp->Extensions.KHR_create_context && 556 disp->Extensions.EXT_create_context_robustness && 557 disp->Extensions.KHR_get_all_proc_addresses && 558 disp->Extensions.KHR_gl_colorspace && 559 disp->Extensions.KHR_surfaceless_context) 560 disp->Version = 15; 561 } 562 563 /** 564 * This is typically the second EGL function that an application calls. 565 * Here we load/initialize the actual hardware driver. 566 */ 567 EGLBoolean EGLAPIENTRY 568 eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 569 { 570 _EGLDisplay *disp = _eglLockDisplay(dpy); 571 572 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 573 574 if (!disp) 575 RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE); 576 577 if (!disp->Initialized) { 578 if (!_eglMatchDriver(disp, EGL_FALSE)) 579 RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE); 580 581 /* limit to APIs supported by core */ 582 disp->ClientAPIs &= _EGL_API_ALL_BITS; 583 584 /* EGL_KHR_get_all_proc_addresses is a corner-case extension. The spec 585 * classifies it as an EGL display extension, though conceptually it's an 586 * EGL client extension. 587 * 588 * From the EGL_KHR_get_all_proc_addresses spec: 589 * 590 * The EGL implementation must expose the name 591 * EGL_KHR_client_get_all_proc_addresses if and only if it exposes 592 * EGL_KHR_get_all_proc_addresses and supports 593 * EGL_EXT_client_extensions. 594 * 595 * Mesa unconditionally exposes both client extensions mentioned above, 596 * so the spec requires that each EGLDisplay unconditionally expose 597 * EGL_KHR_get_all_proc_addresses also. 598 */ 599 disp->Extensions.KHR_get_all_proc_addresses = EGL_TRUE; 600 601 /* Extensions is used to provide EGL 1.3 functionality for 1.2 aware 602 * programs. It is driver agnostic and handled in the main EGL code. 603 */ 604 disp->Extensions.KHR_config_attribs = EGL_TRUE; 605 606 _eglComputeVersion(disp); 607 _eglCreateExtensionsString(disp); 608 _eglCreateAPIsString(disp); 609 snprintf(disp->VersionString, sizeof(disp->VersionString), 610 "%d.%d (%s)", disp->Version / 10, disp->Version % 10, 611 disp->Driver->Name); 612 } 613 614 /* Update applications version of major and minor if not NULL */ 615 if ((major != NULL) && (minor != NULL)) { 616 *major = disp->Version / 10; 617 *minor = disp->Version % 10; 618 } 619 620 RETURN_EGL_SUCCESS(disp, EGL_TRUE); 621 } 622 623 624 EGLBoolean EGLAPIENTRY 625 eglTerminate(EGLDisplay dpy) 626 { 627 _EGLDisplay *disp = _eglLockDisplay(dpy); 628 629 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 630 631 if (!disp) 632 RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE); 633 634 if (disp->Initialized) { 635 _EGLDriver *drv = disp->Driver; 636 637 drv->API.Terminate(drv, disp); 638 /* do not reset disp->Driver */ 639 disp->ClientAPIsString[0] = 0; 640 disp->Initialized = EGL_FALSE; 641 } 642 643 RETURN_EGL_SUCCESS(disp, EGL_TRUE); 644 } 645 646 647 const char * EGLAPIENTRY 648 eglQueryString(EGLDisplay dpy, EGLint name) 649 { 650 _EGLDisplay *disp; 651 _EGLDriver *drv; 652 653 if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) { 654 RETURN_EGL_SUCCESS(NULL, _eglGlobal.ClientExtensionString); 655 } 656 657 disp = _eglLockDisplay(dpy); 658 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, NULL); 659 _EGL_CHECK_DISPLAY(disp, NULL, drv); 660 661 switch (name) { 662 case EGL_VENDOR: 663 RETURN_EGL_SUCCESS(disp, _EGL_VENDOR_STRING); 664 case EGL_VERSION: 665 RETURN_EGL_SUCCESS(disp, disp->VersionString); 666 case EGL_EXTENSIONS: 667 RETURN_EGL_SUCCESS(disp, disp->ExtensionsString); 668 case EGL_CLIENT_APIS: 669 RETURN_EGL_SUCCESS(disp, disp->ClientAPIsString); 670 default: 671 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL); 672 } 673 } 674 675 676 EGLBoolean EGLAPIENTRY 677 eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, 678 EGLint config_size, EGLint *num_config) 679 { 680 _EGLDisplay *disp = _eglLockDisplay(dpy); 681 _EGLDriver *drv; 682 EGLBoolean ret; 683 684 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 685 686 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 687 ret = drv->API.GetConfigs(drv, disp, configs, config_size, num_config); 688 689 RETURN_EGL_EVAL(disp, ret); 690 } 691 692 693 EGLBoolean EGLAPIENTRY 694 eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, 695 EGLint config_size, EGLint *num_config) 696 { 697 _EGLDisplay *disp = _eglLockDisplay(dpy); 698 _EGLDriver *drv; 699 EGLBoolean ret; 700 701 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 702 703 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 704 ret = drv->API.ChooseConfig(drv, disp, attrib_list, configs, 705 config_size, num_config); 706 707 RETURN_EGL_EVAL(disp, ret); 708 } 709 710 711 EGLBoolean EGLAPIENTRY 712 eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 713 EGLint attribute, EGLint *value) 714 { 715 _EGLDisplay *disp = _eglLockDisplay(dpy); 716 _EGLConfig *conf = _eglLookupConfig(config, disp); 717 _EGLDriver *drv; 718 EGLBoolean ret; 719 720 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 721 722 _EGL_CHECK_CONFIG(disp, conf, EGL_FALSE, drv); 723 ret = drv->API.GetConfigAttrib(drv, disp, conf, attribute, value); 724 725 RETURN_EGL_EVAL(disp, ret); 726 } 727 728 729 EGLContext EGLAPIENTRY 730 eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, 731 const EGLint *attrib_list) 732 { 733 _EGLDisplay *disp = _eglLockDisplay(dpy); 734 _EGLConfig *conf = _eglLookupConfig(config, disp); 735 _EGLContext *share = _eglLookupContext(share_list, disp); 736 _EGLDriver *drv; 737 _EGLContext *context; 738 EGLContext ret; 739 740 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_CONTEXT); 741 742 _EGL_CHECK_DISPLAY(disp, EGL_NO_CONTEXT, drv); 743 744 if (config != EGL_NO_CONFIG_KHR) 745 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_CONTEXT, drv); 746 else if (!disp->Extensions.KHR_no_config_context) 747 RETURN_EGL_ERROR(disp, EGL_BAD_CONFIG, EGL_NO_CONTEXT); 748 749 if (!share && share_list != EGL_NO_CONTEXT) 750 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT); 751 752 context = drv->API.CreateContext(drv, disp, conf, share, attrib_list); 753 ret = (context) ? _eglLinkContext(context) : EGL_NO_CONTEXT; 754 755 RETURN_EGL_EVAL(disp, ret); 756 } 757 758 759 EGLBoolean EGLAPIENTRY 760 eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 761 { 762 _EGLDisplay *disp = _eglLockDisplay(dpy); 763 _EGLContext *context = _eglLookupContext(ctx, disp); 764 _EGLDriver *drv; 765 EGLBoolean ret; 766 767 _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE); 768 769 _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv); 770 _eglUnlinkContext(context); 771 ret = drv->API.DestroyContext(drv, disp, context); 772 773 RETURN_EGL_EVAL(disp, ret); 774 } 775 776 777 EGLBoolean EGLAPIENTRY 778 eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, 779 EGLContext ctx) 780 { 781 _EGLDisplay *disp = _eglLockDisplay(dpy); 782 _EGLContext *context = _eglLookupContext(ctx, disp); 783 _EGLSurface *draw_surf = _eglLookupSurface(draw, disp); 784 _EGLSurface *read_surf = _eglLookupSurface(read, disp); 785 _EGLDriver *drv; 786 EGLBoolean ret; 787 788 _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE); 789 790 if (!disp) 791 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE); 792 drv = disp->Driver; 793 794 /* display is allowed to be uninitialized under certain condition */ 795 if (!disp->Initialized) { 796 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE || 797 ctx != EGL_NO_CONTEXT) 798 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE); 799 } 800 if (!drv) 801 RETURN_EGL_SUCCESS(disp, EGL_TRUE); 802 803 if (!context && ctx != EGL_NO_CONTEXT) 804 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE); 805 if (!draw_surf || !read_surf) { 806 /* From the EGL 1.4 (20130211) spec: 807 * 808 * To release the current context without assigning a new one, set ctx 809 * to EGL_NO_CONTEXT and set draw and read to EGL_NO_SURFACE. 810 */ 811 if (!disp->Extensions.KHR_surfaceless_context && ctx != EGL_NO_CONTEXT) 812 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 813 814 if ((!draw_surf && draw != EGL_NO_SURFACE) || 815 (!read_surf && read != EGL_NO_SURFACE)) 816 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 817 if (draw_surf || read_surf) 818 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE); 819 } 820 821 ret = drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context); 822 823 RETURN_EGL_EVAL(disp, ret); 824 } 825 826 827 EGLBoolean EGLAPIENTRY 828 eglQueryContext(EGLDisplay dpy, EGLContext ctx, 829 EGLint attribute, EGLint *value) 830 { 831 _EGLDisplay *disp = _eglLockDisplay(dpy); 832 _EGLContext *context = _eglLookupContext(ctx, disp); 833 _EGLDriver *drv; 834 EGLBoolean ret; 835 836 _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE); 837 838 _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv); 839 ret = drv->API.QueryContext(drv, disp, context, attribute, value); 840 841 RETURN_EGL_EVAL(disp, ret); 842 } 843 844 845 static EGLSurface 846 _eglCreateWindowSurfaceCommon(_EGLDisplay *disp, EGLConfig config, 847 void *native_window, const EGLint *attrib_list) 848 { 849 _EGLConfig *conf = _eglLookupConfig(config, disp); 850 _EGLDriver *drv; 851 _EGLSurface *surf; 852 EGLSurface ret; 853 854 855 if (native_window == NULL) 856 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 857 858 #ifdef HAVE_SURFACELESS_PLATFORM 859 if (disp && disp->Platform == _EGL_PLATFORM_SURFACELESS) { 860 /* From the EGL_MESA_platform_surfaceless spec (v1): 861 * 862 * eglCreatePlatformWindowSurface fails when called with a <display> 863 * that belongs to the surfaceless platform. It returns 864 * EGL_NO_SURFACE and generates EGL_BAD_NATIVE_WINDOW. The 865 * justification for this unconditional failure is that the 866 * surfaceless platform has no native windows, and therefore the 867 * <native_window> parameter is always invalid. 868 * 869 * This check must occur before checking the EGLConfig, which emits 870 * EGL_BAD_CONFIG. 871 */ 872 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 873 } 874 #endif 875 876 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); 877 878 if ((conf->SurfaceType & EGL_WINDOW_BIT) == 0) 879 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE); 880 881 surf = drv->API.CreateWindowSurface(drv, disp, conf, native_window, 882 attrib_list); 883 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; 884 885 RETURN_EGL_EVAL(disp, ret); 886 } 887 888 889 EGLSurface EGLAPIENTRY 890 eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, 891 EGLNativeWindowType window, const EGLint *attrib_list) 892 { 893 _EGLDisplay *disp = _eglLockDisplay(dpy); 894 895 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 896 STATIC_ASSERT(sizeof(void*) == sizeof(window)); 897 return _eglCreateWindowSurfaceCommon(disp, config, (void*) window, 898 attrib_list); 899 } 900 901 static void * 902 _fixupNativeWindow(_EGLDisplay *disp, void *native_window) 903 { 904 #ifdef HAVE_X11_PLATFORM 905 if (disp->Platform == _EGL_PLATFORM_X11 && native_window != NULL) { 906 /* The `native_window` parameter for the X11 platform differs between 907 * eglCreateWindowSurface() and eglCreatePlatformPixmapSurfaceEXT(). In 908 * eglCreateWindowSurface(), the type of `native_window` is an Xlib 909 * `Window`. In eglCreatePlatformWindowSurfaceEXT(), the type is 910 * `Window*`. Convert `Window*` to `Window` because that's what 911 * dri2_x11_create_window_surface() expects. 912 */ 913 return (void *)(* (Window*) native_window); 914 } 915 #endif 916 return native_window; 917 } 918 919 static EGLSurface EGLAPIENTRY 920 eglCreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, 921 void *native_window, 922 const EGLint *attrib_list) 923 { 924 _EGLDisplay *disp = _eglLockDisplay(dpy); 925 926 native_window = _fixupNativeWindow(disp, native_window); 927 928 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 929 return _eglCreateWindowSurfaceCommon(disp, config, native_window, 930 attrib_list); 931 } 932 933 934 EGLSurface EGLAPIENTRY 935 eglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, 936 void *native_window, 937 const EGLAttrib *attrib_list) 938 { 939 _EGLDisplay *disp = _eglLockDisplay(dpy); 940 EGLSurface surface; 941 EGLint *int_attribs; 942 943 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 944 945 int_attribs = _eglConvertAttribsToInt(attrib_list); 946 if (attrib_list && !int_attribs) 947 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE); 948 949 native_window = _fixupNativeWindow(disp, native_window); 950 surface = _eglCreateWindowSurfaceCommon(disp, config, native_window, 951 int_attribs); 952 free(int_attribs); 953 return surface; 954 } 955 956 static void * 957 _fixupNativePixmap(_EGLDisplay *disp, void *native_pixmap) 958 { 959 #ifdef HAVE_X11_PLATFORM 960 /* The `native_pixmap` parameter for the X11 platform differs between 961 * eglCreatePixmapSurface() and eglCreatePlatformPixmapSurfaceEXT(). In 962 * eglCreatePixmapSurface(), the type of `native_pixmap` is an Xlib 963 * `Pixmap`. In eglCreatePlatformPixmapSurfaceEXT(), the type is 964 * `Pixmap*`. Convert `Pixmap*` to `Pixmap` because that's what 965 * dri2_x11_create_pixmap_surface() expects. 966 */ 967 if (disp->Platform == _EGL_PLATFORM_X11 && native_pixmap != NULL) 968 return (void *)(* (Pixmap*) native_pixmap); 969 #endif 970 return native_pixmap; 971 } 972 973 static EGLSurface 974 _eglCreatePixmapSurfaceCommon(_EGLDisplay *disp, EGLConfig config, 975 void *native_pixmap, const EGLint *attrib_list) 976 { 977 _EGLConfig *conf = _eglLookupConfig(config, disp); 978 _EGLDriver *drv; 979 _EGLSurface *surf; 980 EGLSurface ret; 981 982 #if HAVE_SURFACELESS_PLATFORM 983 if (disp && disp->Platform == _EGL_PLATFORM_SURFACELESS) { 984 /* From the EGL_MESA_platform_surfaceless spec (v1): 985 * 986 * [Like eglCreatePlatformWindowSurface,] eglCreatePlatformPixmapSurface 987 * also fails when called with a <display> that belongs to the 988 * surfaceless platform. It returns EGL_NO_SURFACE and generates 989 * EGL_BAD_NATIVE_PIXMAP. 990 * 991 * This check must occur before checking the EGLConfig, which emits 992 * EGL_BAD_CONFIG. 993 */ 994 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE); 995 } 996 #endif 997 998 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); 999 1000 if ((conf->SurfaceType & EGL_PIXMAP_BIT) == 0) 1001 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE); 1002 1003 surf = drv->API.CreatePixmapSurface(drv, disp, conf, native_pixmap, 1004 attrib_list); 1005 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; 1006 1007 RETURN_EGL_EVAL(disp, ret); 1008 } 1009 1010 1011 EGLSurface EGLAPIENTRY 1012 eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, 1013 EGLNativePixmapType pixmap, const EGLint *attrib_list) 1014 { 1015 _EGLDisplay *disp = _eglLockDisplay(dpy); 1016 1017 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 1018 STATIC_ASSERT(sizeof(void*) == sizeof(pixmap)); 1019 return _eglCreatePixmapSurfaceCommon(disp, config, (void*) pixmap, 1020 attrib_list); 1021 } 1022 1023 static EGLSurface EGLAPIENTRY 1024 eglCreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, 1025 void *native_pixmap, 1026 const EGLint *attrib_list) 1027 { 1028 _EGLDisplay *disp = _eglLockDisplay(dpy); 1029 1030 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 1031 native_pixmap = _fixupNativePixmap(disp, native_pixmap); 1032 return _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap, 1033 attrib_list); 1034 } 1035 1036 1037 EGLSurface EGLAPIENTRY 1038 eglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, 1039 void *native_pixmap, 1040 const EGLAttrib *attrib_list) 1041 { 1042 _EGLDisplay *disp = _eglLockDisplay(dpy); 1043 EGLSurface surface; 1044 EGLint *int_attribs; 1045 1046 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 1047 1048 int_attribs = _eglConvertAttribsToInt(attrib_list); 1049 if (attrib_list && !int_attribs) 1050 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE); 1051 1052 native_pixmap = _fixupNativePixmap(disp, native_pixmap); 1053 surface = _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap, 1054 int_attribs); 1055 free(int_attribs); 1056 return surface; 1057 } 1058 1059 1060 EGLSurface EGLAPIENTRY 1061 eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, 1062 const EGLint *attrib_list) 1063 { 1064 _EGLDisplay *disp = _eglLockDisplay(dpy); 1065 _EGLConfig *conf = _eglLookupConfig(config, disp); 1066 _EGLDriver *drv; 1067 _EGLSurface *surf; 1068 EGLSurface ret; 1069 1070 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 1071 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); 1072 1073 if ((conf->SurfaceType & EGL_PBUFFER_BIT) == 0) 1074 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE); 1075 1076 surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list); 1077 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; 1078 1079 RETURN_EGL_EVAL(disp, ret); 1080 } 1081 1082 1083 EGLBoolean EGLAPIENTRY 1084 eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 1085 { 1086 _EGLDisplay *disp = _eglLockDisplay(dpy); 1087 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1088 _EGLDriver *drv; 1089 EGLBoolean ret; 1090 1091 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1092 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1093 _eglUnlinkSurface(surf); 1094 ret = drv->API.DestroySurface(drv, disp, surf); 1095 1096 RETURN_EGL_EVAL(disp, ret); 1097 } 1098 1099 EGLBoolean EGLAPIENTRY 1100 eglQuerySurface(EGLDisplay dpy, EGLSurface surface, 1101 EGLint attribute, EGLint *value) 1102 { 1103 _EGLDisplay *disp = _eglLockDisplay(dpy); 1104 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1105 _EGLDriver *drv; 1106 EGLBoolean ret; 1107 1108 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1109 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1110 ret = drv->API.QuerySurface(drv, disp, surf, attribute, value); 1111 1112 RETURN_EGL_EVAL(disp, ret); 1113 } 1114 1115 EGLBoolean EGLAPIENTRY 1116 eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, 1117 EGLint attribute, EGLint value) 1118 { 1119 _EGLDisplay *disp = _eglLockDisplay(dpy); 1120 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1121 _EGLDriver *drv; 1122 EGLBoolean ret; 1123 1124 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1125 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1126 ret = drv->API.SurfaceAttrib(drv, disp, surf, attribute, value); 1127 1128 RETURN_EGL_EVAL(disp, ret); 1129 } 1130 1131 1132 EGLBoolean EGLAPIENTRY 1133 eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1134 { 1135 _EGLDisplay *disp = _eglLockDisplay(dpy); 1136 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1137 _EGLDriver *drv; 1138 EGLBoolean ret; 1139 1140 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1141 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1142 ret = drv->API.BindTexImage(drv, disp, surf, buffer); 1143 1144 RETURN_EGL_EVAL(disp, ret); 1145 } 1146 1147 1148 EGLBoolean EGLAPIENTRY 1149 eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1150 { 1151 _EGLDisplay *disp = _eglLockDisplay(dpy); 1152 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1153 _EGLDriver *drv; 1154 EGLBoolean ret; 1155 1156 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1157 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1158 ret = drv->API.ReleaseTexImage(drv, disp, surf, buffer); 1159 1160 RETURN_EGL_EVAL(disp, ret); 1161 } 1162 1163 1164 EGLBoolean EGLAPIENTRY 1165 eglSwapInterval(EGLDisplay dpy, EGLint interval) 1166 { 1167 _EGLDisplay *disp = _eglLockDisplay(dpy); 1168 _EGLContext *ctx = _eglGetCurrentContext(); 1169 _EGLSurface *surf = ctx ? ctx->DrawSurface : NULL; 1170 _EGLDriver *drv; 1171 EGLBoolean ret; 1172 1173 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1174 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 1175 1176 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1177 ctx->Resource.Display != disp) 1178 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE); 1179 1180 if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE) 1181 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 1182 1183 ret = drv->API.SwapInterval(drv, disp, surf, interval); 1184 1185 RETURN_EGL_EVAL(disp, ret); 1186 } 1187 1188 1189 EGLBoolean EGLAPIENTRY 1190 eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) 1191 { 1192 _EGLContext *ctx = _eglGetCurrentContext(); 1193 _EGLDisplay *disp = _eglLockDisplay(dpy); 1194 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1195 _EGLDriver *drv; 1196 EGLBoolean ret; 1197 1198 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1199 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1200 1201 /* surface must be bound to current context in EGL 1.4 */ 1202 #ifndef _EGL_BUILT_IN_DRIVER_HAIKU 1203 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1204 surf != ctx->DrawSurface) 1205 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 1206 #endif 1207 1208 ret = drv->API.SwapBuffers(drv, disp, surf); 1209 1210 RETURN_EGL_EVAL(disp, ret); 1211 } 1212 1213 1214 static EGLBoolean 1215 _eglSwapBuffersWithDamageCommon(_EGLDisplay *disp, _EGLSurface *surf, 1216 EGLint *rects, EGLint n_rects) 1217 { 1218 _EGLContext *ctx = _eglGetCurrentContext(); 1219 _EGLDriver *drv; 1220 EGLBoolean ret; 1221 1222 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1223 1224 /* surface must be bound to current context in EGL 1.4 */ 1225 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1226 surf != ctx->DrawSurface) 1227 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 1228 1229 if ((n_rects > 0 && rects == NULL) || n_rects < 0) 1230 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1231 1232 ret = drv->API.SwapBuffersWithDamageEXT(drv, disp, surf, rects, n_rects); 1233 1234 RETURN_EGL_EVAL(disp, ret); 1235 } 1236 1237 static EGLBoolean EGLAPIENTRY 1238 eglSwapBuffersWithDamageEXT(EGLDisplay dpy, EGLSurface surface, 1239 EGLint *rects, EGLint n_rects) 1240 { 1241 _EGLDisplay *disp = _eglLockDisplay(dpy); 1242 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1243 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1244 return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects); 1245 } 1246 1247 static EGLBoolean EGLAPIENTRY 1248 eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface surface, 1249 EGLint *rects, EGLint n_rects) 1250 { 1251 _EGLDisplay *disp = _eglLockDisplay(dpy); 1252 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1253 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1254 return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects); 1255 } 1256 1257 EGLBoolean EGLAPIENTRY 1258 eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) 1259 { 1260 _EGLDisplay *disp = _eglLockDisplay(dpy); 1261 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1262 _EGLDriver *drv; 1263 EGLBoolean ret; 1264 void *native_pixmap_ptr; 1265 1266 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1267 STATIC_ASSERT(sizeof(void*) == sizeof(target)); 1268 native_pixmap_ptr = (void*) target; 1269 1270 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1271 if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay)) 1272 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_FALSE); 1273 ret = drv->API.CopyBuffers(drv, disp, surf, native_pixmap_ptr); 1274 1275 RETURN_EGL_EVAL(disp, ret); 1276 } 1277 1278 1279 static EGLBoolean 1280 _eglWaitClientCommon(void) 1281 { 1282 _EGLContext *ctx = _eglGetCurrentContext(); 1283 _EGLDisplay *disp; 1284 _EGLDriver *drv; 1285 EGLBoolean ret; 1286 1287 if (!ctx) 1288 RETURN_EGL_SUCCESS(NULL, EGL_TRUE); 1289 1290 disp = ctx->Resource.Display; 1291 mtx_lock(&disp->Mutex); 1292 1293 /* let bad current context imply bad current surface */ 1294 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1295 _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE) 1296 RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE); 1297 1298 /* a valid current context implies an initialized current display */ 1299 assert(disp->Initialized); 1300 drv = disp->Driver; 1301 ret = drv->API.WaitClient(drv, disp, ctx); 1302 1303 RETURN_EGL_EVAL(disp, ret); 1304 } 1305 1306 EGLBoolean EGLAPIENTRY 1307 eglWaitClient(void) 1308 { 1309 _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE); 1310 return _eglWaitClientCommon(); 1311 } 1312 1313 EGLBoolean EGLAPIENTRY 1314 eglWaitGL(void) 1315 { 1316 /* Since we only support OpenGL and GLES, eglWaitGL is equivalent to eglWaitClient. */ 1317 _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE); 1318 return _eglWaitClientCommon(); 1319 } 1320 1321 1322 EGLBoolean EGLAPIENTRY 1323 eglWaitNative(EGLint engine) 1324 { 1325 _EGLContext *ctx = _eglGetCurrentContext(); 1326 _EGLDisplay *disp; 1327 _EGLDriver *drv; 1328 EGLBoolean ret; 1329 1330 if (!ctx) 1331 RETURN_EGL_SUCCESS(NULL, EGL_TRUE); 1332 1333 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE); 1334 1335 disp = ctx->Resource.Display; 1336 mtx_lock(&disp->Mutex); 1337 1338 /* let bad current context imply bad current surface */ 1339 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1340 _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE) 1341 RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE); 1342 1343 /* a valid current context implies an initialized current display */ 1344 assert(disp->Initialized); 1345 drv = disp->Driver; 1346 ret = drv->API.WaitNative(drv, disp, engine); 1347 1348 RETURN_EGL_EVAL(disp, ret); 1349 } 1350 1351 1352 EGLDisplay EGLAPIENTRY 1353 eglGetCurrentDisplay(void) 1354 { 1355 _EGLContext *ctx = _eglGetCurrentContext(); 1356 EGLDisplay ret; 1357 1358 ret = (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY; 1359 1360 RETURN_EGL_SUCCESS(NULL, ret); 1361 } 1362 1363 1364 EGLContext EGLAPIENTRY 1365 eglGetCurrentContext(void) 1366 { 1367 _EGLContext *ctx = _eglGetCurrentContext(); 1368 EGLContext ret; 1369 1370 ret = _eglGetContextHandle(ctx); 1371 1372 RETURN_EGL_SUCCESS(NULL, ret); 1373 } 1374 1375 1376 EGLSurface EGLAPIENTRY 1377 eglGetCurrentSurface(EGLint readdraw) 1378 { 1379 _EGLContext *ctx = _eglGetCurrentContext(); 1380 EGLint err = EGL_SUCCESS; 1381 _EGLSurface *surf; 1382 EGLSurface ret; 1383 1384 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_NO_SURFACE); 1385 1386 if (!ctx) 1387 RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE); 1388 1389 switch (readdraw) { 1390 case EGL_DRAW: 1391 surf = ctx->DrawSurface; 1392 break; 1393 case EGL_READ: 1394 surf = ctx->ReadSurface; 1395 break; 1396 default: 1397 surf = NULL; 1398 err = EGL_BAD_PARAMETER; 1399 break; 1400 } 1401 1402 ret = _eglGetSurfaceHandle(surf); 1403 1404 RETURN_EGL_ERROR(NULL, err, ret); 1405 } 1406 1407 1408 EGLint EGLAPIENTRY 1409 eglGetError(void) 1410 { 1411 _EGLThreadInfo *t = _eglGetCurrentThread(); 1412 EGLint e = t->LastError; 1413 if (!_eglIsCurrentThreadDummy()) 1414 t->LastError = EGL_SUCCESS; 1415 return e; 1416 } 1417 1418 1419 /** 1420 ** EGL 1.2 1421 **/ 1422 1423 /** 1424 * Specify the client API to use for subsequent calls including: 1425 * eglCreateContext() 1426 * eglGetCurrentContext() 1427 * eglGetCurrentDisplay() 1428 * eglGetCurrentSurface() 1429 * eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT) 1430 * eglWaitClient() 1431 * eglWaitNative() 1432 * See section 3.7 "Rendering Context" in the EGL specification for details. 1433 */ 1434 EGLBoolean EGLAPIENTRY 1435 eglBindAPI(EGLenum api) 1436 { 1437 _EGLThreadInfo *t; 1438 1439 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE); 1440 1441 t = _eglGetCurrentThread(); 1442 if (_eglIsCurrentThreadDummy()) 1443 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE); 1444 1445 if (!_eglIsApiValid(api)) 1446 RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE); 1447 1448 t->CurrentAPI = api; 1449 1450 RETURN_EGL_SUCCESS(NULL, EGL_TRUE); 1451 } 1452 1453 1454 /** 1455 * Return the last value set with eglBindAPI(). 1456 */ 1457 EGLenum EGLAPIENTRY 1458 eglQueryAPI(void) 1459 { 1460 _EGLThreadInfo *t = _eglGetCurrentThread(); 1461 EGLenum ret; 1462 1463 /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */ 1464 ret = t->CurrentAPI; 1465 1466 RETURN_EGL_SUCCESS(NULL, ret); 1467 } 1468 1469 1470 EGLSurface EGLAPIENTRY 1471 eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, 1472 EGLClientBuffer buffer, EGLConfig config, 1473 const EGLint *attrib_list) 1474 { 1475 _EGLDisplay *disp = _eglLockDisplay(dpy); 1476 _EGLConfig *conf = _eglLookupConfig(config, disp); 1477 _EGLDriver *drv; 1478 _EGLSurface *surf; 1479 EGLSurface ret; 1480 1481 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 1482 1483 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); 1484 1485 surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer, 1486 conf, attrib_list); 1487 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; 1488 1489 RETURN_EGL_EVAL(disp, ret); 1490 } 1491 1492 1493 EGLBoolean EGLAPIENTRY 1494 eglReleaseThread(void) 1495 { 1496 /* unbind current contexts */ 1497 if (!_eglIsCurrentThreadDummy()) { 1498 _EGLThreadInfo *t = _eglGetCurrentThread(); 1499 _EGLContext *ctx = t->CurrentContext; 1500 1501 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE); 1502 1503 if (ctx) { 1504 _EGLDisplay *disp = ctx->Resource.Display; 1505 _EGLDriver *drv; 1506 1507 mtx_lock(&disp->Mutex); 1508 drv = disp->Driver; 1509 (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL); 1510 mtx_unlock(&disp->Mutex); 1511 } 1512 } 1513 1514 _eglDestroyCurrentThread(); 1515 1516 RETURN_EGL_SUCCESS(NULL, EGL_TRUE); 1517 } 1518 1519 1520 static EGLImage 1521 _eglCreateImageCommon(_EGLDisplay *disp, EGLContext ctx, EGLenum target, 1522 EGLClientBuffer buffer, const EGLint *attr_list) 1523 { 1524 _EGLContext *context = _eglLookupContext(ctx, disp); 1525 _EGLDriver *drv; 1526 _EGLImage *img; 1527 EGLImage ret; 1528 1529 _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv); 1530 if (!disp->Extensions.KHR_image_base) 1531 RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR); 1532 if (!context && ctx != EGL_NO_CONTEXT) 1533 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); 1534 /* "If <target> is EGL_LINUX_DMA_BUF_EXT, <dpy> must be a valid display, 1535 * <ctx> must be EGL_NO_CONTEXT..." 1536 */ 1537 if (ctx != EGL_NO_CONTEXT && target == EGL_LINUX_DMA_BUF_EXT) 1538 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); 1539 1540 img = drv->API.CreateImageKHR(drv, 1541 disp, context, target, buffer, attr_list); 1542 ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR; 1543 1544 RETURN_EGL_EVAL(disp, ret); 1545 } 1546 1547 static EGLImage EGLAPIENTRY 1548 eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1549 EGLClientBuffer buffer, const EGLint *attr_list) 1550 { 1551 _EGLDisplay *disp = _eglLockDisplay(dpy); 1552 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR); 1553 return _eglCreateImageCommon(disp, ctx, target, buffer, attr_list); 1554 } 1555 1556 1557 EGLImage EGLAPIENTRY 1558 eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1559 EGLClientBuffer buffer, const EGLAttrib *attr_list) 1560 { 1561 _EGLDisplay *disp = _eglLockDisplay(dpy); 1562 EGLImage image; 1563 EGLint *int_attribs; 1564 1565 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR); 1566 1567 int_attribs = _eglConvertAttribsToInt(attr_list); 1568 if (attr_list && !int_attribs) 1569 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_IMAGE); 1570 1571 image = _eglCreateImageCommon(disp, ctx, target, buffer, int_attribs); 1572 free(int_attribs); 1573 return image; 1574 } 1575 1576 1577 EGLBoolean EGLAPIENTRY 1578 eglDestroyImage(EGLDisplay dpy, EGLImage image) 1579 { 1580 _EGLDisplay *disp = _eglLockDisplay(dpy); 1581 _EGLImage *img = _eglLookupImage(image, disp); 1582 _EGLDriver *drv; 1583 EGLBoolean ret; 1584 1585 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); 1586 1587 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 1588 if (!disp->Extensions.KHR_image_base) 1589 RETURN_EGL_EVAL(disp, EGL_FALSE); 1590 if (!img) 1591 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1592 1593 _eglUnlinkImage(img); 1594 ret = drv->API.DestroyImageKHR(drv, disp, img); 1595 1596 RETURN_EGL_EVAL(disp, ret); 1597 } 1598 1599 1600 static EGLSync 1601 _eglCreateSync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list, 1602 EGLBoolean orig_is_EGLAttrib, 1603 EGLenum invalid_type_error) 1604 { 1605 _EGLContext *ctx = _eglGetCurrentContext(); 1606 _EGLDriver *drv; 1607 _EGLSync *sync; 1608 EGLSync ret; 1609 1610 _EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv); 1611 1612 if (!disp->Extensions.KHR_cl_event2 && orig_is_EGLAttrib) { 1613 /* There exist two EGLAttrib variants of eglCreateSync*: 1614 * eglCreateSync64KHR which requires EGL_KHR_cl_event2, and eglCreateSync 1615 * which requires EGL 1.5. Here we use the presence of EGL_KHR_cl_event2 1616 * support as a proxy for EGL 1.5 support, even though that's not 1617 * entirely correct (though _eglComputeVersion does the same). 1618 * 1619 * The EGL spec provides no guidance on how to handle unsupported 1620 * functions. EGL_BAD_MATCH seems reasonable. 1621 */ 1622 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR); 1623 } 1624 1625 /* If type is EGL_SYNC_FENCE and no context is current for the bound API 1626 * (i.e., eglGetCurrentContext returns EGL_NO_CONTEXT ), an EGL_BAD_MATCH 1627 * error is generated. 1628 */ 1629 if (!ctx && 1630 (type == EGL_SYNC_FENCE_KHR || type == EGL_SYNC_NATIVE_FENCE_ANDROID)) 1631 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR); 1632 1633 /* return an error if the client API doesn't support GL_OES_EGL_sync */ 1634 if (ctx && (ctx->Resource.Display != disp || 1635 ctx->ClientAPI != EGL_OPENGL_ES_API)) 1636 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR); 1637 1638 switch (type) { 1639 case EGL_SYNC_FENCE_KHR: 1640 if (!disp->Extensions.KHR_fence_sync) 1641 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); 1642 break; 1643 case EGL_SYNC_REUSABLE_KHR: 1644 if (!disp->Extensions.KHR_reusable_sync) 1645 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); 1646 break; 1647 case EGL_SYNC_CL_EVENT_KHR: 1648 if (!disp->Extensions.KHR_cl_event2) 1649 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); 1650 break; 1651 case EGL_SYNC_NATIVE_FENCE_ANDROID: 1652 if (!disp->Extensions.ANDROID_native_fence_sync) 1653 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); 1654 break; 1655 default: 1656 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); 1657 } 1658 1659 sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list); 1660 ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR; 1661 1662 RETURN_EGL_EVAL(disp, ret); 1663 } 1664 1665 1666 static EGLSync EGLAPIENTRY 1667 eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *int_list) 1668 { 1669 _EGLDisplay *disp = _eglLockDisplay(dpy); 1670 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 1671 1672 EGLSync sync; 1673 EGLAttrib *attrib_list; 1674 EGLint err; 1675 1676 if (sizeof(int_list[0]) == sizeof(attrib_list[0])) { 1677 attrib_list = (EGLAttrib *) int_list; 1678 } else { 1679 err = _eglConvertIntsToAttribs(int_list, &attrib_list); 1680 if (err != EGL_SUCCESS) 1681 RETURN_EGL_ERROR(disp, err, EGL_NO_SYNC); 1682 } 1683 1684 sync = _eglCreateSync(disp, type, attrib_list, EGL_FALSE, 1685 EGL_BAD_ATTRIBUTE); 1686 1687 if (sizeof(int_list[0]) != sizeof(attrib_list[0])) 1688 free(attrib_list); 1689 1690 /* Don't double-unlock the display. _eglCreateSync already unlocked it. */ 1691 return sync; 1692 } 1693 1694 1695 static EGLSync EGLAPIENTRY 1696 eglCreateSync64KHR(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list) 1697 { 1698 _EGLDisplay *disp = _eglLockDisplay(dpy); 1699 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 1700 return _eglCreateSync(disp, type, attrib_list, EGL_TRUE, 1701 EGL_BAD_ATTRIBUTE); 1702 } 1703 1704 1705 EGLSync EGLAPIENTRY 1706 eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list) 1707 { 1708 _EGLDisplay *disp = _eglLockDisplay(dpy); 1709 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 1710 return _eglCreateSync(disp, type, attrib_list, EGL_TRUE, 1711 EGL_BAD_PARAMETER); 1712 } 1713 1714 1715 EGLBoolean EGLAPIENTRY 1716 eglDestroySync(EGLDisplay dpy, EGLSync sync) 1717 { 1718 _EGLDisplay *disp = _eglLockDisplay(dpy); 1719 _EGLSync *s = _eglLookupSync(sync, disp); 1720 _EGLDriver *drv; 1721 EGLBoolean ret; 1722 1723 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1724 1725 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 1726 assert(disp->Extensions.KHR_reusable_sync || 1727 disp->Extensions.KHR_fence_sync || 1728 disp->Extensions.ANDROID_native_fence_sync); 1729 1730 _eglUnlinkSync(s); 1731 ret = drv->API.DestroySyncKHR(drv, disp, s); 1732 1733 RETURN_EGL_EVAL(disp, ret); 1734 } 1735 1736 1737 EGLint EGLAPIENTRY 1738 eglClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout) 1739 { 1740 _EGLDisplay *disp = _eglLockDisplay(dpy); 1741 _EGLSync *s = _eglLookupSync(sync, disp); 1742 _EGLDriver *drv; 1743 EGLint ret; 1744 1745 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1746 1747 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 1748 assert(disp->Extensions.KHR_reusable_sync || 1749 disp->Extensions.KHR_fence_sync || 1750 disp->Extensions.ANDROID_native_fence_sync); 1751 1752 if (s->SyncStatus == EGL_SIGNALED_KHR) 1753 RETURN_EGL_EVAL(disp, EGL_CONDITION_SATISFIED_KHR); 1754 1755 /* if sync type is EGL_SYNC_REUSABLE_KHR, dpy should be 1756 * unlocked here to allow other threads also to be able to 1757 * go into waiting state. 1758 */ 1759 1760 if (s->Type == EGL_SYNC_REUSABLE_KHR) 1761 _eglUnlockDisplay(dpy); 1762 1763 ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout); 1764 1765 /* 1766 * 'disp' is already unlocked for reusable sync type, 1767 * so passing 'NULL' to bypass unlocking display. 1768 */ 1769 if (s->Type == EGL_SYNC_REUSABLE_KHR) 1770 RETURN_EGL_EVAL(NULL, ret); 1771 else 1772 RETURN_EGL_EVAL(disp, ret); 1773 } 1774 1775 1776 static EGLint 1777 _eglWaitSyncCommon(_EGLDisplay *disp, _EGLSync *s, EGLint flags) 1778 { 1779 _EGLContext *ctx = _eglGetCurrentContext(); 1780 _EGLDriver *drv; 1781 EGLint ret; 1782 1783 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 1784 assert(disp->Extensions.KHR_wait_sync); 1785 1786 /* return an error if the client API doesn't support GL_OES_EGL_sync */ 1787 if (ctx == EGL_NO_CONTEXT || ctx->ClientAPI != EGL_OPENGL_ES_API) 1788 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE); 1789 1790 /* the API doesn't allow any flags yet */ 1791 if (flags != 0) 1792 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1793 1794 ret = drv->API.WaitSyncKHR(drv, disp, s); 1795 1796 RETURN_EGL_EVAL(disp, ret); 1797 } 1798 1799 static EGLint EGLAPIENTRY 1800 eglWaitSyncKHR(EGLDisplay dpy, EGLSync sync, EGLint flags) 1801 { 1802 _EGLDisplay *disp = _eglLockDisplay(dpy); 1803 _EGLSync *s = _eglLookupSync(sync, disp); 1804 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1805 return _eglWaitSyncCommon(disp, s, flags); 1806 } 1807 1808 1809 EGLBoolean EGLAPIENTRY 1810 eglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) 1811 { 1812 /* The KHR version returns EGLint, while the core version returns 1813 * EGLBoolean. In both cases, the return values can only be EGL_FALSE and 1814 * EGL_TRUE. 1815 */ 1816 _EGLDisplay *disp = _eglLockDisplay(dpy); 1817 _EGLSync *s = _eglLookupSync(sync, disp); 1818 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1819 return _eglWaitSyncCommon(disp, s, flags); 1820 } 1821 1822 1823 static EGLBoolean EGLAPIENTRY 1824 eglSignalSyncKHR(EGLDisplay dpy, EGLSync sync, EGLenum mode) 1825 { 1826 _EGLDisplay *disp = _eglLockDisplay(dpy); 1827 _EGLSync *s = _eglLookupSync(sync, disp); 1828 _EGLDriver *drv; 1829 EGLBoolean ret; 1830 1831 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1832 1833 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 1834 assert(disp->Extensions.KHR_reusable_sync); 1835 ret = drv->API.SignalSyncKHR(drv, disp, s, mode); 1836 1837 RETURN_EGL_EVAL(disp, ret); 1838 } 1839 1840 1841 static EGLBoolean 1842 _eglGetSyncAttribCommon(_EGLDisplay *disp, _EGLSync *s, EGLint attribute, EGLAttrib *value) 1843 { 1844 _EGLDriver *drv; 1845 EGLBoolean ret; 1846 1847 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 1848 assert(disp->Extensions.KHR_reusable_sync || 1849 disp->Extensions.KHR_fence_sync || 1850 disp->Extensions.ANDROID_native_fence_sync); 1851 ret = drv->API.GetSyncAttrib(drv, disp, s, attribute, value); 1852 1853 RETURN_EGL_EVAL(disp, ret); 1854 } 1855 1856 EGLBoolean EGLAPIENTRY 1857 eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value) 1858 { 1859 _EGLDisplay *disp = _eglLockDisplay(dpy); 1860 _EGLSync *s = _eglLookupSync(sync, disp); 1861 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1862 return _eglGetSyncAttribCommon(disp, s, attribute, value); 1863 } 1864 1865 1866 static EGLBoolean EGLAPIENTRY 1867 eglGetSyncAttribKHR(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint *value) 1868 { 1869 _EGLDisplay *disp = _eglLockDisplay(dpy); 1870 _EGLSync *s = _eglLookupSync(sync, disp); 1871 EGLAttrib attrib; 1872 EGLBoolean result; 1873 1874 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1875 1876 if (!value) 1877 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1878 1879 attrib = *value; 1880 result = _eglGetSyncAttribCommon(disp, s, attribute, &attrib); 1881 1882 /* The EGL_KHR_fence_sync spec says this about eglGetSyncAttribKHR: 1883 * 1884 * If any error occurs, <*value> is not modified. 1885 */ 1886 if (result == EGL_FALSE) 1887 return result; 1888 1889 *value = attrib; 1890 return result; 1891 } 1892 1893 static EGLint EGLAPIENTRY 1894 eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync) 1895 { 1896 _EGLDisplay *disp = _eglLockDisplay(dpy); 1897 _EGLSync *s = _eglLookupSync(sync, disp); 1898 _EGLDriver *drv; 1899 EGLBoolean ret; 1900 1901 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1902 1903 /* the spec doesn't seem to specify what happens if the fence 1904 * type is not EGL_SYNC_NATIVE_FENCE_ANDROID, but this seems 1905 * sensible: 1906 */ 1907 if (!(s && (s->Type == EGL_SYNC_NATIVE_FENCE_ANDROID))) 1908 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_NATIVE_FENCE_FD_ANDROID); 1909 1910 _EGL_CHECK_SYNC(disp, s, EGL_NO_NATIVE_FENCE_FD_ANDROID, drv); 1911 assert(disp->Extensions.ANDROID_native_fence_sync); 1912 ret = drv->API.DupNativeFenceFDANDROID(drv, disp, s); 1913 1914 RETURN_EGL_EVAL(disp, ret); 1915 } 1916 1917 static EGLBoolean EGLAPIENTRY 1918 eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface, 1919 EGLint numRects, const EGLint *rects) 1920 { 1921 _EGLContext *ctx = _eglGetCurrentContext(); 1922 _EGLDisplay *disp = _eglLockDisplay(dpy); 1923 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1924 _EGLDriver *drv; 1925 EGLBoolean ret; 1926 1927 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1928 1929 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1930 1931 if (!disp->Extensions.NOK_swap_region) 1932 RETURN_EGL_EVAL(disp, EGL_FALSE); 1933 1934 /* surface must be bound to current context in EGL 1.4 */ 1935 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1936 surf != ctx->DrawSurface) 1937 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 1938 1939 ret = drv->API.SwapBuffersRegionNOK(drv, disp, surf, numRects, rects); 1940 1941 RETURN_EGL_EVAL(disp, ret); 1942 } 1943 1944 1945 static EGLImage EGLAPIENTRY 1946 eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list) 1947 { 1948 _EGLDisplay *disp = _eglLockDisplay(dpy); 1949 _EGLDriver *drv; 1950 _EGLImage *img; 1951 EGLImage ret; 1952 1953 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 1954 1955 _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv); 1956 if (!disp->Extensions.MESA_drm_image) 1957 RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR); 1958 1959 img = drv->API.CreateDRMImageMESA(drv, disp, attr_list); 1960 ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR; 1961 1962 RETURN_EGL_EVAL(disp, ret); 1963 } 1964 1965 static EGLBoolean EGLAPIENTRY 1966 eglExportDRMImageMESA(EGLDisplay dpy, EGLImage image, 1967 EGLint *name, EGLint *handle, EGLint *stride) 1968 { 1969 _EGLDisplay *disp = _eglLockDisplay(dpy); 1970 _EGLImage *img = _eglLookupImage(image, disp); 1971 _EGLDriver *drv; 1972 EGLBoolean ret; 1973 1974 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); 1975 1976 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 1977 assert(disp->Extensions.MESA_drm_image); 1978 1979 if (!img) 1980 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1981 1982 ret = drv->API.ExportDRMImageMESA(drv, disp, img, name, handle, stride); 1983 1984 RETURN_EGL_EVAL(disp, ret); 1985 } 1986 1987 1988 struct wl_display; 1989 1990 static EGLBoolean EGLAPIENTRY 1991 eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) 1992 { 1993 _EGLDisplay *disp = _eglLockDisplay(dpy); 1994 _EGLDriver *drv; 1995 EGLBoolean ret; 1996 1997 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 1998 1999 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2000 assert(disp->Extensions.WL_bind_wayland_display); 2001 2002 if (!display) 2003 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2004 2005 ret = drv->API.BindWaylandDisplayWL(drv, disp, display); 2006 2007 RETURN_EGL_EVAL(disp, ret); 2008 } 2009 2010 static EGLBoolean EGLAPIENTRY 2011 eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) 2012 { 2013 _EGLDisplay *disp = _eglLockDisplay(dpy); 2014 _EGLDriver *drv; 2015 EGLBoolean ret; 2016 2017 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 2018 2019 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2020 assert(disp->Extensions.WL_bind_wayland_display); 2021 2022 if (!display) 2023 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2024 2025 ret = drv->API.UnbindWaylandDisplayWL(drv, disp, display); 2026 2027 RETURN_EGL_EVAL(disp, ret); 2028 } 2029 2030 static EGLBoolean EGLAPIENTRY 2031 eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer, 2032 EGLint attribute, EGLint *value) 2033 { 2034 _EGLDisplay *disp = _eglLockDisplay(dpy); 2035 _EGLDriver *drv; 2036 EGLBoolean ret; 2037 2038 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 2039 2040 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2041 assert(disp->Extensions.WL_bind_wayland_display); 2042 2043 if (!buffer) 2044 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2045 2046 ret = drv->API.QueryWaylandBufferWL(drv, disp, buffer, attribute, value); 2047 2048 RETURN_EGL_EVAL(disp, ret); 2049 } 2050 2051 2052 static struct wl_buffer * EGLAPIENTRY 2053 eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImage image) 2054 { 2055 _EGLDisplay *disp = _eglLockDisplay(dpy); 2056 _EGLImage *img; 2057 _EGLDriver *drv; 2058 struct wl_buffer *ret; 2059 2060 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 2061 2062 _EGL_CHECK_DISPLAY(disp, NULL, drv); 2063 assert(disp->Extensions.WL_create_wayland_buffer_from_image); 2064 2065 img = _eglLookupImage(image, disp); 2066 2067 if (!img) 2068 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL); 2069 2070 ret = drv->API.CreateWaylandBufferFromImageWL(drv, disp, img); 2071 2072 RETURN_EGL_EVAL(disp, ret); 2073 } 2074 2075 static EGLBoolean EGLAPIENTRY 2076 eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, 2077 EGLint x, EGLint y, EGLint width, EGLint height) 2078 { 2079 _EGLDisplay *disp = _eglLockDisplay(dpy); 2080 _EGLSurface *surf = _eglLookupSurface(surface, disp); 2081 _EGLDriver *drv; 2082 EGLBoolean ret; 2083 2084 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 2085 2086 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 2087 2088 if (!disp->Extensions.NV_post_sub_buffer) 2089 RETURN_EGL_EVAL(disp, EGL_FALSE); 2090 2091 ret = drv->API.PostSubBufferNV(drv, disp, surf, x, y, width, height); 2092 2093 RETURN_EGL_EVAL(disp, ret); 2094 } 2095 2096 static EGLBoolean EGLAPIENTRY 2097 eglGetSyncValuesCHROMIUM(EGLDisplay display, EGLSurface surface, 2098 EGLuint64KHR *ust, EGLuint64KHR *msc, 2099 EGLuint64KHR *sbc) 2100 { 2101 _EGLDisplay *disp = _eglLockDisplay(display); 2102 _EGLSurface *surf = _eglLookupSurface(surface, disp); 2103 _EGLDriver *drv; 2104 EGLBoolean ret; 2105 2106 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 2107 2108 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 2109 if (!disp->Extensions.CHROMIUM_sync_control) 2110 RETURN_EGL_EVAL(disp, EGL_FALSE); 2111 2112 if (!ust || !msc || !sbc) 2113 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2114 2115 ret = drv->API.GetSyncValuesCHROMIUM(disp, surf, ust, msc, sbc); 2116 2117 RETURN_EGL_EVAL(disp, ret); 2118 } 2119 2120 static EGLBoolean EGLAPIENTRY 2121 eglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImage image, 2122 EGLint *fourcc, EGLint *nplanes, 2123 EGLuint64KHR *modifiers) 2124 { 2125 _EGLDisplay *disp = _eglLockDisplay(dpy); 2126 _EGLImage *img = _eglLookupImage(image, disp); 2127 _EGLDriver *drv; 2128 EGLBoolean ret; 2129 2130 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); 2131 2132 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2133 assert(disp->Extensions.MESA_image_dma_buf_export); 2134 2135 if (!img) 2136 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2137 2138 ret = drv->API.ExportDMABUFImageQueryMESA(drv, disp, img, fourcc, nplanes, 2139 modifiers); 2140 2141 RETURN_EGL_EVAL(disp, ret); 2142 } 2143 2144 static EGLBoolean EGLAPIENTRY 2145 eglExportDMABUFImageMESA(EGLDisplay dpy, EGLImage image, 2146 int *fds, EGLint *strides, EGLint *offsets) 2147 { 2148 _EGLDisplay *disp = _eglLockDisplay(dpy); 2149 _EGLImage *img = _eglLookupImage(image, disp); 2150 _EGLDriver *drv; 2151 EGLBoolean ret; 2152 2153 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); 2154 2155 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2156 assert(disp->Extensions.MESA_image_dma_buf_export); 2157 2158 if (!img) 2159 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2160 2161 ret = drv->API.ExportDMABUFImageMESA(drv, disp, img, fds, strides, offsets); 2162 2163 RETURN_EGL_EVAL(disp, ret); 2164 } 2165 2166 static EGLint EGLAPIENTRY 2167 eglLabelObjectKHR(EGLDisplay dpy, EGLenum objectType, EGLObjectKHR object, 2168 EGLLabelKHR label) 2169 { 2170 _EGLDisplay *disp = NULL; 2171 _EGLResourceType type; 2172 2173 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC); 2174 2175 if (objectType == EGL_OBJECT_THREAD_KHR) { 2176 _EGLThreadInfo *t = _eglGetCurrentThread(); 2177 2178 if (!_eglIsCurrentThreadDummy()) { 2179 t->Label = label; 2180 return EGL_SUCCESS; 2181 } 2182 2183 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_BAD_ALLOC); 2184 } 2185 2186 disp = _eglLockDisplay(dpy); 2187 if (disp == NULL) 2188 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_BAD_DISPLAY); 2189 2190 if (objectType == EGL_OBJECT_DISPLAY_KHR) { 2191 if (dpy != (EGLDisplay) object) 2192 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER); 2193 2194 disp->Label = label; 2195 RETURN_EGL_EVAL(disp, EGL_SUCCESS); 2196 } 2197 2198 switch (objectType) { 2199 case EGL_OBJECT_CONTEXT_KHR: 2200 type = _EGL_RESOURCE_CONTEXT; 2201 break; 2202 case EGL_OBJECT_SURFACE_KHR: 2203 type = _EGL_RESOURCE_SURFACE; 2204 break; 2205 case EGL_OBJECT_IMAGE_KHR: 2206 type = _EGL_RESOURCE_IMAGE; 2207 break; 2208 case EGL_OBJECT_SYNC_KHR: 2209 type = _EGL_RESOURCE_SYNC; 2210 break; 2211 case EGL_OBJECT_STREAM_KHR: 2212 default: 2213 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER); 2214 } 2215 2216 if (_eglCheckResource(object, type, disp)) { 2217 _EGLResource *res = (_EGLResource *) object; 2218 2219 res->Label = label; 2220 RETURN_EGL_EVAL(disp, EGL_SUCCESS); 2221 } 2222 2223 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER); 2224 } 2225 2226 static EGLBoolean 2227 _validDebugMessageLevel(EGLAttrib level) 2228 { 2229 return (level >= EGL_DEBUG_MSG_CRITICAL_KHR && 2230 level <= EGL_DEBUG_MSG_INFO_KHR); 2231 } 2232 2233 static EGLint EGLAPIENTRY 2234 eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback, 2235 const EGLAttrib *attrib_list) 2236 { 2237 unsigned int newEnabled; 2238 2239 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC); 2240 2241 mtx_lock(_eglGlobal.Mutex); 2242 2243 newEnabled = _eglGlobal.debugTypesEnabled; 2244 if (attrib_list != NULL) { 2245 int i; 2246 2247 for (i = 0; attrib_list[i] != EGL_NONE; i += 2) { 2248 if (_validDebugMessageLevel(attrib_list[i])) { 2249 if (attrib_list[i + 1]) 2250 newEnabled |= DebugBitFromType(attrib_list[i]); 2251 else 2252 newEnabled &= ~DebugBitFromType(attrib_list[i]); 2253 continue; 2254 } 2255 2256 // On error, set the last error code, call the current 2257 // debug callback, and return the error code. 2258 mtx_unlock(_eglGlobal.Mutex); 2259 _eglReportError(EGL_BAD_ATTRIBUTE, NULL, 2260 "Invalid attribute 0x%04lx", (unsigned long) attrib_list[i]); 2261 return EGL_BAD_ATTRIBUTE; 2262 } 2263 } 2264 2265 if (callback != NULL) { 2266 _eglGlobal.debugCallback = callback; 2267 _eglGlobal.debugTypesEnabled = newEnabled; 2268 } else { 2269 _eglGlobal.debugCallback = NULL; 2270 _eglGlobal.debugTypesEnabled = _EGL_DEBUG_BIT_CRITICAL | _EGL_DEBUG_BIT_ERROR; 2271 } 2272 2273 mtx_unlock(_eglGlobal.Mutex); 2274 return EGL_SUCCESS; 2275 } 2276 2277 static EGLBoolean EGLAPIENTRY 2278 eglQueryDebugKHR(EGLint attribute, EGLAttrib *value) 2279 { 2280 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC); 2281 2282 mtx_lock(_eglGlobal.Mutex); 2283 2284 do { 2285 if (_validDebugMessageLevel(attribute)) { 2286 if (_eglGlobal.debugTypesEnabled & DebugBitFromType(attribute)) 2287 *value = EGL_TRUE; 2288 else 2289 *value = EGL_FALSE; 2290 break; 2291 } 2292 2293 if (attribute == EGL_DEBUG_CALLBACK_KHR) { 2294 *value = (EGLAttrib) _eglGlobal.debugCallback; 2295 break; 2296 } 2297 2298 mtx_unlock(_eglGlobal.Mutex); 2299 _eglReportError(EGL_BAD_ATTRIBUTE, NULL, 2300 "Invalid attribute 0x%04lx", (unsigned long) attribute); 2301 return EGL_FALSE; 2302 } while (0); 2303 2304 mtx_unlock(_eglGlobal.Mutex); 2305 return EGL_TRUE; 2306 } 2307 2308 __eglMustCastToProperFunctionPointerType EGLAPIENTRY 2309 eglGetProcAddress(const char *procname) 2310 { 2311 static const struct { 2312 const char *name; 2313 _EGLProc function; 2314 } egl_functions[] = { 2315 /* core functions queryable in the presence of 2316 * EGL_KHR_get_all_proc_addresses or EGL 1.5 2317 */ 2318 /* alphabetical order */ 2319 { "eglBindAPI", (_EGLProc) eglBindAPI }, 2320 { "eglBindTexImage", (_EGLProc) eglBindTexImage }, 2321 { "eglChooseConfig", (_EGLProc) eglChooseConfig }, 2322 { "eglCopyBuffers", (_EGLProc) eglCopyBuffers }, 2323 { "eglCreateContext", (_EGLProc) eglCreateContext }, 2324 { "eglCreatePbufferFromClientBuffer", (_EGLProc) eglCreatePbufferFromClientBuffer }, 2325 { "eglCreatePbufferSurface", (_EGLProc) eglCreatePbufferSurface }, 2326 { "eglCreatePixmapSurface", (_EGLProc) eglCreatePixmapSurface }, 2327 { "eglCreateWindowSurface", (_EGLProc) eglCreateWindowSurface }, 2328 { "eglDestroyContext", (_EGLProc) eglDestroyContext }, 2329 { "eglDestroySurface", (_EGLProc) eglDestroySurface }, 2330 { "eglGetConfigAttrib", (_EGLProc) eglGetConfigAttrib }, 2331 { "eglGetConfigs", (_EGLProc) eglGetConfigs }, 2332 { "eglGetCurrentContext", (_EGLProc) eglGetCurrentContext }, 2333 { "eglGetCurrentDisplay", (_EGLProc) eglGetCurrentDisplay }, 2334 { "eglGetCurrentSurface", (_EGLProc) eglGetCurrentSurface }, 2335 { "eglGetDisplay", (_EGLProc) eglGetDisplay }, 2336 { "eglGetError", (_EGLProc) eglGetError }, 2337 { "eglGetProcAddress", (_EGLProc) eglGetProcAddress }, 2338 { "eglInitialize", (_EGLProc) eglInitialize }, 2339 { "eglMakeCurrent", (_EGLProc) eglMakeCurrent }, 2340 { "eglQueryAPI", (_EGLProc) eglQueryAPI }, 2341 { "eglQueryContext", (_EGLProc) eglQueryContext }, 2342 { "eglQueryString", (_EGLProc) eglQueryString }, 2343 { "eglQuerySurface", (_EGLProc) eglQuerySurface }, 2344 { "eglReleaseTexImage", (_EGLProc) eglReleaseTexImage }, 2345 { "eglReleaseThread", (_EGLProc) eglReleaseThread }, 2346 { "eglSurfaceAttrib", (_EGLProc) eglSurfaceAttrib }, 2347 { "eglSwapBuffers", (_EGLProc) eglSwapBuffers }, 2348 { "eglSwapInterval", (_EGLProc) eglSwapInterval }, 2349 { "eglTerminate", (_EGLProc) eglTerminate }, 2350 { "eglWaitClient", (_EGLProc) eglWaitClient }, 2351 { "eglWaitGL", (_EGLProc) eglWaitGL }, 2352 { "eglWaitNative", (_EGLProc) eglWaitNative }, 2353 { "eglCreateSync", (_EGLProc) eglCreateSync }, 2354 { "eglDestroySync", (_EGLProc) eglDestroySync }, 2355 { "eglClientWaitSync", (_EGLProc) eglClientWaitSync }, 2356 { "eglGetSyncAttrib", (_EGLProc) eglGetSyncAttrib }, 2357 { "eglWaitSync", (_EGLProc) eglWaitSync }, 2358 { "eglCreateImage", (_EGLProc) eglCreateImage }, 2359 { "eglDestroyImage", (_EGLProc) eglDestroyImage }, 2360 { "eglGetPlatformDisplay", (_EGLProc) eglGetPlatformDisplay }, 2361 { "eglCreatePlatformWindowSurface", (_EGLProc) eglCreatePlatformWindowSurface }, 2362 { "eglCreatePlatformPixmapSurface", (_EGLProc) eglCreatePlatformPixmapSurface }, 2363 { "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR }, 2364 { "eglDestroyImageKHR", (_EGLProc) eglDestroyImage }, 2365 { "eglCreateSyncKHR", (_EGLProc) eglCreateSyncKHR }, 2366 { "eglCreateSync64KHR", (_EGLProc) eglCreateSync64KHR }, 2367 { "eglDestroySyncKHR", (_EGLProc) eglDestroySync }, 2368 { "eglClientWaitSyncKHR", (_EGLProc) eglClientWaitSync }, 2369 { "eglWaitSyncKHR", (_EGLProc) eglWaitSyncKHR }, 2370 { "eglSignalSyncKHR", (_EGLProc) eglSignalSyncKHR }, 2371 { "eglGetSyncAttribKHR", (_EGLProc) eglGetSyncAttribKHR }, 2372 { "eglSwapBuffersRegionNOK", (_EGLProc) eglSwapBuffersRegionNOK }, 2373 { "eglCreateDRMImageMESA", (_EGLProc) eglCreateDRMImageMESA }, 2374 { "eglExportDRMImageMESA", (_EGLProc) eglExportDRMImageMESA }, 2375 { "eglBindWaylandDisplayWL", (_EGLProc) eglBindWaylandDisplayWL }, 2376 { "eglUnbindWaylandDisplayWL", (_EGLProc) eglUnbindWaylandDisplayWL }, 2377 { "eglQueryWaylandBufferWL", (_EGLProc) eglQueryWaylandBufferWL }, 2378 { "eglCreateWaylandBufferFromImageWL", (_EGLProc) eglCreateWaylandBufferFromImageWL }, 2379 { "eglPostSubBufferNV", (_EGLProc) eglPostSubBufferNV }, 2380 { "eglSwapBuffersWithDamageEXT", (_EGLProc) eglSwapBuffersWithDamageEXT }, 2381 { "eglSwapBuffersWithDamageKHR", (_EGLProc) eglSwapBuffersWithDamageKHR }, 2382 { "eglGetPlatformDisplayEXT", (_EGLProc) eglGetPlatformDisplayEXT }, 2383 { "eglCreatePlatformWindowSurfaceEXT", (_EGLProc) eglCreatePlatformWindowSurfaceEXT }, 2384 { "eglCreatePlatformPixmapSurfaceEXT", (_EGLProc) eglCreatePlatformPixmapSurfaceEXT }, 2385 { "eglGetSyncValuesCHROMIUM", (_EGLProc) eglGetSyncValuesCHROMIUM }, 2386 { "eglExportDMABUFImageQueryMESA", (_EGLProc) eglExportDMABUFImageQueryMESA }, 2387 { "eglExportDMABUFImageMESA", (_EGLProc) eglExportDMABUFImageMESA }, 2388 { "eglLabelObjectKHR", (_EGLProc) eglLabelObjectKHR }, 2389 { "eglDebugMessageControlKHR", (_EGLProc) eglDebugMessageControlKHR }, 2390 { "eglQueryDebugKHR", (_EGLProc) eglQueryDebugKHR }, 2391 { "eglDupNativeFenceFDANDROID", (_EGLProc) eglDupNativeFenceFDANDROID }, 2392 { NULL, NULL } 2393 }; 2394 EGLint i; 2395 _EGLProc ret; 2396 2397 if (!procname) 2398 RETURN_EGL_SUCCESS(NULL, NULL); 2399 2400 _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL); 2401 2402 ret = NULL; 2403 if (strncmp(procname, "egl", 3) == 0) { 2404 for (i = 0; egl_functions[i].name; i++) { 2405 if (strcmp(egl_functions[i].name, procname) == 0) { 2406 ret = egl_functions[i].function; 2407 break; 2408 } 2409 } 2410 } 2411 if (!ret) 2412 ret = _eglGetDriverProc(procname); 2413 2414 RETURN_EGL_SUCCESS(NULL, ret); 2415 } 2416 2417 static int 2418 _eglLockDisplayInterop(EGLDisplay dpy, EGLContext context, 2419 _EGLDisplay **disp, _EGLDriver **drv, 2420 _EGLContext **ctx) 2421 { 2422 2423 *disp = _eglLockDisplay(dpy); 2424 if (!*disp || !(*disp)->Initialized || !(*disp)->Driver) { 2425 if (*disp) 2426 _eglUnlockDisplay(*disp); 2427 return MESA_GLINTEROP_INVALID_DISPLAY; 2428 } 2429 2430 *drv = (*disp)->Driver; 2431 2432 *ctx = _eglLookupContext(context, *disp); 2433 if (!*ctx || 2434 ((*ctx)->ClientAPI != EGL_OPENGL_API && 2435 (*ctx)->ClientAPI != EGL_OPENGL_ES_API)) { 2436 _eglUnlockDisplay(*disp); 2437 return MESA_GLINTEROP_INVALID_CONTEXT; 2438 } 2439 2440 return MESA_GLINTEROP_SUCCESS; 2441 } 2442 2443 PUBLIC int 2444 MesaGLInteropEGLQueryDeviceInfo(EGLDisplay dpy, EGLContext context, 2445 struct mesa_glinterop_device_info *out) 2446 { 2447 _EGLDisplay *disp; 2448 _EGLDriver *drv; 2449 _EGLContext *ctx; 2450 int ret; 2451 2452 ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx); 2453 if (ret != MESA_GLINTEROP_SUCCESS) 2454 return ret; 2455 2456 if (drv->API.GLInteropQueryDeviceInfo) 2457 ret = drv->API.GLInteropQueryDeviceInfo(disp, ctx, out); 2458 else 2459 ret = MESA_GLINTEROP_UNSUPPORTED; 2460 2461 _eglUnlockDisplay(disp); 2462 return ret; 2463 } 2464 2465 PUBLIC int 2466 MesaGLInteropEGLExportObject(EGLDisplay dpy, EGLContext context, 2467 struct mesa_glinterop_export_in *in, 2468 struct mesa_glinterop_export_out *out) 2469 { 2470 _EGLDisplay *disp; 2471 _EGLDriver *drv; 2472 _EGLContext *ctx; 2473 int ret; 2474 2475 ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx); 2476 if (ret != MESA_GLINTEROP_SUCCESS) 2477 return ret; 2478 2479 if (drv->API.GLInteropExportObject) 2480 ret = drv->API.GLInteropExportObject(disp, ctx, in, out); 2481 else 2482 ret = MESA_GLINTEROP_UNSUPPORTED; 2483 2484 _eglUnlockDisplay(disp); 2485 return ret; 2486 } 2487