egl_stubs.cpp (27194B)
1 // 2 // Copyright 2020 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 // egl_stubs.cpp: Stubs for EGL entry points. 7 // 8 9 #include "libGLESv2/egl_stubs_autogen.h" 10 11 #include "common/angle_version_info.h" 12 #include "libANGLE/Context.h" 13 #include "libANGLE/Display.h" 14 #include "libANGLE/EGLSync.h" 15 #include "libANGLE/Surface.h" 16 #include "libANGLE/Thread.h" 17 #include "libANGLE/capture/capture_egl.h" 18 #include "libANGLE/capture/frame_capture_utils_autogen.h" 19 #include "libANGLE/capture/gl_enum_utils_autogen.h" 20 #include "libANGLE/queryutils.h" 21 #include "libANGLE/validationEGL.h" 22 #include "libGLESv2/global_state.h" 23 #include "libGLESv2/proc_table_egl.h" 24 25 namespace egl 26 { 27 namespace 28 { 29 30 bool CompareProc(const ProcEntry &a, const char *b) 31 { 32 return strcmp(a.first, b) < 0; 33 } 34 35 void ClipConfigs(const std::vector<const Config *> &filteredConfigs, 36 EGLConfig *outputConfigs, 37 EGLint configSize, 38 EGLint *numConfigs) 39 { 40 EGLint resultSize = static_cast<EGLint>(filteredConfigs.size()); 41 if (outputConfigs) 42 { 43 resultSize = std::max(std::min(resultSize, configSize), 0); 44 for (EGLint i = 0; i < resultSize; i++) 45 { 46 outputConfigs[i] = const_cast<Config *>(filteredConfigs[i]); 47 } 48 } 49 *numConfigs = resultSize; 50 } 51 } // anonymous namespace 52 53 EGLBoolean BindAPI(Thread *thread, EGLenum api) 54 { 55 thread->setAPI(api); 56 57 thread->setSuccess(); 58 return EGL_TRUE; 59 } 60 61 EGLBoolean BindTexImage(Thread *thread, Display *display, Surface *eglSurface, EGLint buffer) 62 { 63 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglBindTexImage", 64 GetDisplayIfValid(display), EGL_FALSE); 65 66 gl::Context *context = thread->getContext(); 67 if (context && !context->isContextLost()) 68 { 69 gl::TextureType type = 70 egl_gl::EGLTextureTargetToTextureType(eglSurface->getTextureTarget()); 71 gl::Texture *textureObject = context->getTextureByType(type); 72 ANGLE_EGL_TRY_RETURN(thread, eglSurface->bindTexImage(context, textureObject, buffer), 73 "eglBindTexImage", GetSurfaceIfValid(display, eglSurface), EGL_FALSE); 74 75 ANGLE_CAPTURE_EGL(EGLBindTexImage, thread, eglSurface, buffer); 76 } 77 78 thread->setSuccess(); 79 return EGL_TRUE; 80 } 81 82 EGLBoolean ChooseConfig(Thread *thread, 83 Display *display, 84 const AttributeMap &attribMap, 85 EGLConfig *configs, 86 EGLint config_size, 87 EGLint *num_config) 88 { 89 ClipConfigs(display->chooseConfig(attribMap), configs, config_size, num_config); 90 91 thread->setSuccess(); 92 return EGL_TRUE; 93 } 94 95 EGLint ClientWaitSync(Thread *thread, 96 Display *display, 97 Sync *syncObject, 98 EGLint flags, 99 EGLTime timeout) 100 { 101 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglClientWaitSync", 102 GetDisplayIfValid(display), EGL_FALSE); 103 gl::Context *currentContext = thread->getContext(); 104 EGLint syncStatus = EGL_FALSE; 105 ANGLE_EGL_TRY_RETURN( 106 thread, syncObject->clientWait(display, currentContext, flags, timeout, &syncStatus), 107 "eglClientWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE); 108 109 thread->setSuccess(); 110 return syncStatus; 111 } 112 113 EGLBoolean CopyBuffers(Thread *thread, 114 Display *display, 115 Surface *eglSurface, 116 EGLNativePixmapType target) 117 { 118 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCopyBuffers", 119 GetDisplayIfValid(display), EGL_FALSE); 120 UNIMPLEMENTED(); // FIXME 121 122 thread->setSuccess(); 123 return 0; 124 } 125 126 EGLContext CreateContext(Thread *thread, 127 Display *display, 128 Config *configuration, 129 gl::Context *sharedGLContext, 130 const AttributeMap &attributes) 131 { 132 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateContext", 133 GetDisplayIfValid(display), EGL_NO_CONTEXT); 134 gl::Context *context = nullptr; 135 ANGLE_EGL_TRY_RETURN(thread, 136 display->createContext(configuration, sharedGLContext, thread->getAPI(), 137 attributes, &context), 138 "eglCreateContext", GetDisplayIfValid(display), EGL_NO_CONTEXT); 139 140 thread->setSuccess(); 141 return static_cast<EGLContext>(context); 142 } 143 144 EGLImage CreateImage(Thread *thread, 145 Display *display, 146 gl::Context *context, 147 EGLenum target, 148 EGLClientBuffer buffer, 149 const AttributeMap &attributes) 150 { 151 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateImage", 152 GetDisplayIfValid(display), EGL_FALSE); 153 154 Image *image = nullptr; 155 Error error = display->createImage(context, target, buffer, attributes, &image); 156 if (error.isError()) 157 { 158 thread->setError(error, "eglCreateImage", GetDisplayIfValid(display)); 159 return EGL_NO_IMAGE; 160 } 161 162 ANGLE_CAPTURE_EGL(EGLCreateImage, thread, context, target, buffer, attributes, image); 163 164 thread->setSuccess(); 165 return static_cast<EGLImage>(image); 166 } 167 168 EGLSurface CreatePbufferFromClientBuffer(Thread *thread, 169 Display *display, 170 EGLenum buftype, 171 EGLClientBuffer buffer, 172 Config *configuration, 173 const AttributeMap &attributes) 174 { 175 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePbufferFromClientBuffer", 176 GetDisplayIfValid(display), EGL_NO_SURFACE); 177 Surface *surface = nullptr; 178 ANGLE_EGL_TRY_RETURN(thread, 179 display->createPbufferFromClientBuffer(configuration, buftype, buffer, 180 attributes, &surface), 181 "eglCreatePbufferFromClientBuffer", GetDisplayIfValid(display), 182 EGL_NO_SURFACE); 183 184 return static_cast<EGLSurface>(surface); 185 } 186 187 EGLSurface CreatePbufferSurface(Thread *thread, 188 Display *display, 189 Config *configuration, 190 const AttributeMap &attributes) 191 { 192 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePbufferSurface", 193 GetDisplayIfValid(display), EGL_NO_SURFACE); 194 Surface *surface = nullptr; 195 ANGLE_EGL_TRY_RETURN(thread, display->createPbufferSurface(configuration, attributes, &surface), 196 "eglCreatePbufferSurface", GetDisplayIfValid(display), EGL_NO_SURFACE); 197 198 ANGLE_CAPTURE_EGL(EGLCreatePbufferSurface, thread, attributes, surface); 199 200 return static_cast<EGLSurface>(surface); 201 } 202 203 EGLSurface CreatePixmapSurface(Thread *thread, 204 Display *display, 205 Config *configuration, 206 EGLNativePixmapType pixmap, 207 const AttributeMap &attributes) 208 { 209 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePixmapSurface", 210 GetDisplayIfValid(display), EGL_NO_SURFACE); 211 Surface *surface = nullptr; 212 ANGLE_EGL_TRY_RETURN(thread, 213 display->createPixmapSurface(configuration, pixmap, attributes, &surface), 214 "eglCreatePixmapSurface", GetDisplayIfValid(display), EGL_NO_SURFACE); 215 216 thread->setSuccess(); 217 return static_cast<EGLSurface>(surface); 218 } 219 220 EGLSurface CreatePlatformPixmapSurface(Thread *thread, 221 Display *display, 222 Config *configuration, 223 void *pixmap, 224 const AttributeMap &attributes) 225 { 226 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePlatformPixmapSurface", 227 GetDisplayIfValid(display), EGL_NO_SURFACE); 228 Surface *surface = nullptr; 229 EGLNativePixmapType nativePixmap = reinterpret_cast<EGLNativePixmapType>(pixmap); 230 ANGLE_EGL_TRY_RETURN( 231 thread, display->createPixmapSurface(configuration, nativePixmap, attributes, &surface), 232 "eglCreatePlatformPixmapSurface", GetDisplayIfValid(display), EGL_NO_SURFACE); 233 234 thread->setSuccess(); 235 return static_cast<EGLSurface>(surface); 236 } 237 238 EGLSurface CreatePlatformWindowSurface(Thread *thread, 239 Display *display, 240 Config *configuration, 241 void *win, 242 const AttributeMap &attributes) 243 { 244 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePlatformWindowSurface", 245 GetDisplayIfValid(display), EGL_NO_SURFACE); 246 Surface *surface = nullptr; 247 EGLNativeWindowType nativeWindow = reinterpret_cast<EGLNativeWindowType>(win); 248 ANGLE_EGL_TRY_RETURN( 249 thread, display->createWindowSurface(configuration, nativeWindow, attributes, &surface), 250 "eglPlatformCreateWindowSurface", GetDisplayIfValid(display), EGL_NO_SURFACE); 251 252 return static_cast<EGLSurface>(surface); 253 } 254 255 EGLSync CreateSync(Thread *thread, Display *display, EGLenum type, const AttributeMap &attributes) 256 { 257 gl::Context *currentContext = thread->getContext(); 258 259 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateSync", 260 GetDisplayIfValid(display), EGL_FALSE); 261 Sync *syncObject = nullptr; 262 ANGLE_EGL_TRY_RETURN(thread, display->createSync(currentContext, type, attributes, &syncObject), 263 "eglCreateSync", GetDisplayIfValid(display), EGL_NO_SYNC); 264 265 thread->setSuccess(); 266 return static_cast<EGLSync>(syncObject); 267 } 268 269 EGLSurface CreateWindowSurface(Thread *thread, 270 Display *display, 271 Config *configuration, 272 EGLNativeWindowType win, 273 const AttributeMap &attributes) 274 { 275 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateWindowSurface", 276 GetDisplayIfValid(display), EGL_NO_SURFACE); 277 278 Surface *surface = nullptr; 279 ANGLE_EGL_TRY_RETURN(thread, 280 display->createWindowSurface(configuration, win, attributes, &surface), 281 "eglCreateWindowSurface", GetDisplayIfValid(display), EGL_NO_SURFACE); 282 283 return static_cast<EGLSurface>(surface); 284 } 285 286 EGLBoolean DestroyContext(Thread *thread, Display *display, gl::Context *context) 287 { 288 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroyContext", 289 GetDisplayIfValid(display), EGL_FALSE); 290 291 ScopedSyncCurrentContextFromThread scopedSyncCurrent(thread); 292 293 ANGLE_EGL_TRY_RETURN(thread, display->destroyContext(thread, context), "eglDestroyContext", 294 GetContextIfValid(display, context), EGL_FALSE); 295 thread->setSuccess(); 296 return EGL_TRUE; 297 } 298 299 EGLBoolean DestroyImage(Thread *thread, Display *display, Image *img) 300 { 301 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroyImage", 302 GetDisplayIfValid(display), EGL_FALSE); 303 display->destroyImage(img); 304 305 ANGLE_CAPTURE_EGL(EGLDestroyImage, thread, display, img); 306 307 thread->setSuccess(); 308 return EGL_TRUE; 309 } 310 311 EGLBoolean DestroySurface(Thread *thread, Display *display, Surface *eglSurface) 312 { 313 ANGLE_CAPTURE_EGL(EGLDestroySurface, thread, display, eglSurface); 314 315 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroySurface", 316 GetDisplayIfValid(display), EGL_FALSE); 317 318 ANGLE_EGL_TRY_RETURN(thread, display->destroySurface(eglSurface), "eglDestroySurface", 319 GetSurfaceIfValid(display, eglSurface), EGL_FALSE); 320 321 thread->setSuccess(); 322 return EGL_TRUE; 323 } 324 325 EGLBoolean DestroySync(Thread *thread, Display *display, Sync *syncObject) 326 { 327 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroySync", 328 GetDisplayIfValid(display), EGL_FALSE); 329 display->destroySync(syncObject); 330 331 thread->setSuccess(); 332 return EGL_TRUE; 333 } 334 335 EGLBoolean GetConfigAttrib(Thread *thread, 336 Display *display, 337 Config *configuration, 338 EGLint attribute, 339 EGLint *value) 340 { 341 QueryConfigAttrib(configuration, attribute, value); 342 343 thread->setSuccess(); 344 return EGL_TRUE; 345 } 346 347 EGLBoolean GetConfigs(Thread *thread, 348 Display *display, 349 EGLConfig *configs, 350 EGLint config_size, 351 EGLint *num_config) 352 { 353 ClipConfigs(display->getConfigs(AttributeMap()), configs, config_size, num_config); 354 355 thread->setSuccess(); 356 return EGL_TRUE; 357 } 358 359 EGLContext GetCurrentContext(Thread *thread) 360 { 361 gl::Context *context = thread->getContext(); 362 363 thread->setSuccess(); 364 return static_cast<EGLContext>(context); 365 } 366 367 EGLDisplay GetCurrentDisplay(Thread *thread) 368 { 369 thread->setSuccess(); 370 if (thread->getContext() != nullptr) 371 { 372 return thread->getContext()->getDisplay(); 373 } 374 return EGL_NO_DISPLAY; 375 } 376 377 EGLSurface GetCurrentSurface(Thread *thread, EGLint readdraw) 378 { 379 if (readdraw == EGL_READ) 380 { 381 thread->setSuccess(); 382 return thread->getCurrentReadSurface(); 383 } 384 else if (readdraw == EGL_DRAW) 385 { 386 thread->setSuccess(); 387 return thread->getCurrentDrawSurface(); 388 } 389 else 390 { 391 thread->setError(EglBadParameter(), "eglGetCurrentSurface", nullptr); 392 return EGL_NO_SURFACE; 393 } 394 } 395 396 EGLDisplay GetDisplay(Thread *thread, EGLNativeDisplayType display_id) 397 { 398 return Display::GetDisplayFromNativeDisplay(EGL_PLATFORM_ANGLE_ANGLE, display_id, 399 AttributeMap()); 400 } 401 402 EGLint GetError(Thread *thread) 403 { 404 EGLint error = thread->getError(); 405 thread->setSuccess(); 406 return error; 407 } 408 409 EGLDisplay GetPlatformDisplay(Thread *thread, 410 EGLenum platform, 411 void *native_display, 412 const AttributeMap &attribMap) 413 { 414 switch (platform) 415 { 416 case EGL_PLATFORM_ANGLE_ANGLE: 417 case EGL_PLATFORM_GBM_KHR: 418 case EGL_PLATFORM_WAYLAND_EXT: 419 { 420 return Display::GetDisplayFromNativeDisplay( 421 platform, gl::bitCast<EGLNativeDisplayType>(native_display), attribMap); 422 } 423 case EGL_PLATFORM_DEVICE_EXT: 424 { 425 Device *eglDevice = static_cast<Device *>(native_display); 426 return Display::GetDisplayFromDevice(eglDevice, attribMap); 427 } 428 default: 429 { 430 UNREACHABLE(); 431 return EGL_NO_DISPLAY; 432 } 433 } 434 } 435 436 __eglMustCastToProperFunctionPointerType GetProcAddress(Thread *thread, const char *procname) 437 { 438 const ProcEntry *entry = 439 std::lower_bound(&g_procTable[0], &g_procTable[g_numProcs], procname, CompareProc); 440 441 thread->setSuccess(); 442 443 if (entry == &g_procTable[g_numProcs] || strcmp(entry->first, procname) != 0) 444 { 445 return nullptr; 446 } 447 448 return entry->second; 449 } 450 451 EGLBoolean GetSyncAttrib(Thread *thread, 452 Display *display, 453 Sync *syncObject, 454 EGLint attribute, 455 EGLAttrib *value) 456 { 457 EGLint valueExt; 458 ANGLE_EGL_TRY_RETURN(thread, GetSyncAttrib(display, syncObject, attribute, &valueExt), 459 "eglGetSyncAttrib", GetSyncIfValid(display, syncObject), EGL_FALSE); 460 *value = valueExt; 461 462 thread->setSuccess(); 463 return EGL_TRUE; 464 } 465 466 EGLBoolean Initialize(Thread *thread, Display *display, EGLint *major, EGLint *minor) 467 { 468 ANGLE_EGL_TRY_RETURN(thread, display->initialize(), "eglInitialize", GetDisplayIfValid(display), 469 EGL_FALSE); 470 471 if (major) 472 { 473 *major = kEglMajorVersion; 474 } 475 if (minor) 476 { 477 *minor = kEglMinorVersion; 478 } 479 480 thread->setSuccess(); 481 return EGL_TRUE; 482 } 483 484 EGLBoolean MakeCurrent(Thread *thread, 485 Display *display, 486 Surface *drawSurface, 487 Surface *readSurface, 488 gl::Context *context) 489 { 490 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglMakeCurrent", 491 GetDisplayIfValid(display), EGL_FALSE); 492 ScopedSyncCurrentContextFromThread scopedSyncCurrent(thread); 493 494 Surface *previousDraw = thread->getCurrentDrawSurface(); 495 Surface *previousRead = thread->getCurrentReadSurface(); 496 gl::Context *previousContext = thread->getContext(); 497 498 // Only call makeCurrent if the context or surfaces have changed. 499 if (previousDraw != drawSurface || previousRead != readSurface || previousContext != context) 500 { 501 ANGLE_EGL_TRY_RETURN( 502 thread, 503 display->makeCurrent(thread, previousContext, drawSurface, readSurface, context), 504 "eglMakeCurrent", GetContextIfValid(display, context), EGL_FALSE); 505 506 ANGLE_CAPTURE_EGL(EGLMakeCurrent, thread, drawSurface, readSurface, context); 507 } 508 509 thread->setSuccess(); 510 return EGL_TRUE; 511 } 512 513 EGLenum QueryAPI(Thread *thread) 514 { 515 EGLenum API = thread->getAPI(); 516 517 thread->setSuccess(); 518 return API; 519 } 520 521 EGLBoolean QueryContext(Thread *thread, 522 Display *display, 523 gl::Context *context, 524 EGLint attribute, 525 EGLint *value) 526 { 527 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryContext", 528 GetDisplayIfValid(display), EGL_FALSE); 529 QueryContextAttrib(context, attribute, value); 530 531 thread->setSuccess(); 532 return EGL_TRUE; 533 } 534 535 const char *QueryString(Thread *thread, Display *display, EGLint name) 536 { 537 if (display) 538 { 539 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryString", 540 GetDisplayIfValid(display), nullptr); 541 } 542 543 const char *result = nullptr; 544 switch (name) 545 { 546 case EGL_CLIENT_APIS: 547 result = display->getClientAPIString().c_str(); 548 break; 549 case EGL_EXTENSIONS: 550 if (display == EGL_NO_DISPLAY) 551 { 552 result = Display::GetClientExtensionString().c_str(); 553 } 554 else 555 { 556 result = display->getExtensionString().c_str(); 557 } 558 break; 559 case EGL_VENDOR: 560 result = display->getVendorString().c_str(); 561 break; 562 case EGL_VERSION: 563 { 564 static const char *sVersionString = 565 MakeStaticString(std::string("1.5 (ANGLE ") + angle::GetANGLEVersionString() + ")"); 566 result = sVersionString; 567 break; 568 } 569 default: 570 UNREACHABLE(); 571 break; 572 } 573 574 thread->setSuccess(); 575 return result; 576 } 577 578 EGLBoolean QuerySurface(Thread *thread, 579 Display *display, 580 Surface *eglSurface, 581 EGLint attribute, 582 EGLint *value) 583 { 584 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQuerySurface", 585 GetDisplayIfValid(display), EGL_FALSE); 586 ANGLE_EGL_TRY_RETURN( 587 thread, QuerySurfaceAttrib(display, thread->getContext(), eglSurface, attribute, value), 588 "eglQuerySurface", GetSurfaceIfValid(display, eglSurface), EGL_FALSE); 589 590 thread->setSuccess(); 591 return EGL_TRUE; 592 } 593 594 EGLBoolean ReleaseTexImage(Thread *thread, Display *display, Surface *eglSurface, EGLint buffer) 595 { 596 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglReleaseTexImage", 597 GetDisplayIfValid(display), EGL_FALSE); 598 gl::Context *context = thread->getContext(); 599 if (context && !context->isContextLost()) 600 { 601 gl::Texture *texture = eglSurface->getBoundTexture(); 602 603 if (texture) 604 { 605 ANGLE_EGL_TRY_RETURN(thread, eglSurface->releaseTexImage(thread->getContext(), buffer), 606 "eglReleaseTexImage", GetSurfaceIfValid(display, eglSurface), 607 EGL_FALSE); 608 ANGLE_CAPTURE_EGL(EGLReleaseTexImage, thread, eglSurface, buffer); 609 } 610 } 611 thread->setSuccess(); 612 return EGL_TRUE; 613 } 614 615 EGLBoolean ReleaseThread(Thread *thread) 616 { 617 ScopedSyncCurrentContextFromThread scopedSyncCurrent(thread); 618 619 Surface *previousDraw = thread->getCurrentDrawSurface(); 620 Surface *previousRead = thread->getCurrentReadSurface(); 621 gl::Context *previousContext = thread->getContext(); 622 Display *previousDisplay = thread->getDisplay(); 623 624 if (previousDisplay != EGL_NO_DISPLAY) 625 { 626 ANGLE_EGL_TRY_RETURN(thread, previousDisplay->prepareForCall(), "eglReleaseThread", 627 GetDisplayIfValid(previousDisplay), EGL_FALSE); 628 // Only call makeCurrent if the context or surfaces have changed. 629 if (previousDraw != EGL_NO_SURFACE || previousRead != EGL_NO_SURFACE || 630 previousContext != EGL_NO_CONTEXT) 631 { 632 ANGLE_EGL_TRY_RETURN( 633 thread, 634 previousDisplay->makeCurrent(thread, previousContext, nullptr, nullptr, nullptr), 635 "eglReleaseThread", nullptr, EGL_FALSE); 636 } 637 ANGLE_EGL_TRY_RETURN(thread, previousDisplay->releaseThread(), "eglReleaseThread", 638 GetDisplayIfValid(previousDisplay), EGL_FALSE); 639 } 640 641 thread->setSuccess(); 642 return EGL_TRUE; 643 } 644 645 EGLBoolean SurfaceAttrib(Thread *thread, 646 Display *display, 647 Surface *eglSurface, 648 EGLint attribute, 649 EGLint value) 650 { 651 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglSurfaceAttrib", 652 GetDisplayIfValid(display), EGL_FALSE); 653 654 ANGLE_EGL_TRY_RETURN(thread, SetSurfaceAttrib(eglSurface, attribute, value), "eglSurfaceAttrib", 655 GetDisplayIfValid(display), EGL_FALSE); 656 657 thread->setSuccess(); 658 return EGL_TRUE; 659 } 660 661 EGLBoolean SwapBuffers(Thread *thread, Display *display, Surface *eglSurface) 662 { 663 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglSwapBuffers", 664 GetDisplayIfValid(display), EGL_FALSE); 665 666 ANGLE_EGL_TRY_RETURN(thread, eglSurface->swap(thread->getContext()), "eglSwapBuffers", 667 GetSurfaceIfValid(display, eglSurface), EGL_FALSE); 668 669 thread->setSuccess(); 670 return EGL_TRUE; 671 } 672 673 EGLBoolean SwapInterval(Thread *thread, Display *display, EGLint interval) 674 { 675 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglSwapInterval", 676 GetDisplayIfValid(display), EGL_FALSE); 677 678 Surface *drawSurface = static_cast<Surface *>(thread->getCurrentDrawSurface()); 679 const Config *surfaceConfig = drawSurface->getConfig(); 680 EGLint clampedInterval = std::min(std::max(interval, surfaceConfig->minSwapInterval), 681 surfaceConfig->maxSwapInterval); 682 683 drawSurface->setSwapInterval(clampedInterval); 684 685 thread->setSuccess(); 686 return EGL_TRUE; 687 } 688 689 EGLBoolean Terminate(Thread *thread, Display *display) 690 { 691 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglTerminate", 692 GetDisplayIfValid(display), EGL_FALSE); 693 694 ScopedSyncCurrentContextFromThread scopedSyncCurrent(thread); 695 696 ANGLE_EGL_TRY_RETURN(thread, display->terminate(thread, Display::TerminateReason::Api), 697 "eglTerminate", GetDisplayIfValid(display), EGL_FALSE); 698 699 thread->setSuccess(); 700 return EGL_TRUE; 701 } 702 703 EGLBoolean WaitClient(Thread *thread) 704 { 705 Display *display = thread->getDisplay(); 706 if (display == nullptr) 707 { 708 // EGL spec says this about eglWaitClient - 709 // If there is no current context for the current rendering API, 710 // the function has no effect but still returns EGL_TRUE. 711 return EGL_TRUE; 712 } 713 714 gl::Context *context = thread->getContext(); 715 716 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitClient", 717 GetDisplayIfValid(display), EGL_FALSE); 718 ANGLE_EGL_TRY_RETURN(thread, display->waitClient(context), "eglWaitClient", 719 GetContextIfValid(display, context), EGL_FALSE); 720 721 thread->setSuccess(); 722 return EGL_TRUE; 723 } 724 725 EGLBoolean WaitGL(Thread *thread) 726 { 727 Display *display = thread->getDisplay(); 728 if (display == nullptr) 729 { 730 // EGL spec says this about eglWaitGL - 731 // eglWaitGL is ignored if there is no current EGL rendering context for OpenGL ES. 732 return EGL_TRUE; 733 } 734 735 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitGL", GetDisplayIfValid(display), 736 EGL_FALSE); 737 738 // eglWaitGL like calling eglWaitClient with the OpenGL ES API bound. Since we only implement 739 // OpenGL ES we can do the call directly. 740 ANGLE_EGL_TRY_RETURN(thread, display->waitClient(thread->getContext()), "eglWaitGL", 741 GetDisplayIfValid(display), EGL_FALSE); 742 743 thread->setSuccess(); 744 return EGL_TRUE; 745 } 746 747 EGLBoolean WaitNative(Thread *thread, EGLint engine) 748 { 749 Display *display = thread->getDisplay(); 750 if (display == nullptr) 751 { 752 // EGL spec says this about eglWaitNative - 753 // eglWaitNative is ignored if there is no current EGL rendering context. 754 return EGL_TRUE; 755 } 756 757 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitNative", 758 GetDisplayIfValid(display), EGL_FALSE); 759 ANGLE_EGL_TRY_RETURN(thread, display->waitNative(thread->getContext(), engine), "eglWaitNative", 760 GetThreadIfValid(thread), EGL_FALSE); 761 762 thread->setSuccess(); 763 return EGL_TRUE; 764 } 765 766 EGLBoolean WaitSync(Thread *thread, Display *display, Sync *syncObject, EGLint flags) 767 { 768 ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitSync", 769 GetDisplayIfValid(display), EGL_FALSE); 770 gl::Context *currentContext = thread->getContext(); 771 ANGLE_EGL_TRY_RETURN(thread, syncObject->serverWait(display, currentContext, flags), 772 "eglWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE); 773 774 thread->setSuccess(); 775 return EGL_TRUE; 776 } 777 } // namespace egl