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