| // |
| // Copyright 2020 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // egl_stubs.cpp: Stubs for EGL entry points. |
| // |
| |
| #include "libGLESv2/egl_stubs_autogen.h" |
| |
| #include "common/angle_version.h" |
| #include "libANGLE/Context.h" |
| #include "libANGLE/Display.h" |
| #include "libANGLE/EGLSync.h" |
| #include "libANGLE/Surface.h" |
| #include "libANGLE/Thread.h" |
| #include "libANGLE/queryutils.h" |
| #include "libANGLE/validationEGL.h" |
| #include "libGLESv2/global_state.h" |
| #include "libGLESv2/proc_table_egl.h" |
| |
| namespace egl |
| { |
| namespace |
| { |
| |
| bool CompareProc(const ProcEntry &a, const char *b) |
| { |
| return strcmp(a.first, b) < 0; |
| } |
| |
| void ClipConfigs(const std::vector<const Config *> &filteredConfigs, |
| EGLConfig *outputConfigs, |
| EGLint configSize, |
| EGLint *numConfigs) |
| { |
| EGLint resultSize = static_cast<EGLint>(filteredConfigs.size()); |
| if (outputConfigs) |
| { |
| resultSize = std::max(std::min(resultSize, configSize), 0); |
| for (EGLint i = 0; i < resultSize; i++) |
| { |
| outputConfigs[i] = const_cast<Config *>(filteredConfigs[i]); |
| } |
| } |
| *numConfigs = resultSize; |
| } |
| } // anonymous namespace |
| |
| EGLBoolean BindAPI(Thread *thread, EGLenum api) |
| { |
| thread->setAPI(api); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean BindTexImage(Thread *thread, Display *display, Surface *eglSurface, EGLint buffer) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglBindTexImage", |
| GetDisplayIfValid(display), EGL_FALSE); |
| |
| gl::Context *context = thread->getContext(); |
| if (context) |
| { |
| gl::TextureType type = |
| egl_gl::EGLTextureTargetToTextureType(eglSurface->getTextureTarget()); |
| gl::Texture *textureObject = context->getTextureByType(type); |
| ANGLE_EGL_TRY_RETURN(thread, eglSurface->bindTexImage(context, textureObject, buffer), |
| "eglBindTexImage", GetSurfaceIfValid(display, eglSurface), EGL_FALSE); |
| } |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean ChooseConfig(Thread *thread, |
| Display *display, |
| const AttributeMap &attribMap, |
| EGLConfig *configs, |
| EGLint config_size, |
| EGLint *num_config) |
| { |
| ClipConfigs(display->chooseConfig(attribMap), configs, config_size, num_config); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLint ClientWaitSync(Thread *thread, |
| Display *display, |
| Sync *syncObject, |
| EGLint flags, |
| EGLTime timeout) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglClientWaitSync", |
| GetDisplayIfValid(display), EGL_FALSE); |
| gl::Context *currentContext = thread->getContext(); |
| EGLint syncStatus = EGL_FALSE; |
| ANGLE_EGL_TRY_RETURN( |
| thread, syncObject->clientWait(display, currentContext, flags, timeout, &syncStatus), |
| "eglClientWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE); |
| |
| thread->setSuccess(); |
| return syncStatus; |
| } |
| |
| EGLBoolean CopyBuffers(Thread *thread, |
| Display *display, |
| Surface *eglSurface, |
| EGLNativePixmapType target) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCopyBuffers", |
| GetDisplayIfValid(display), EGL_FALSE); |
| UNIMPLEMENTED(); // FIXME |
| |
| thread->setSuccess(); |
| return 0; |
| } |
| |
| EGLContext CreateContext(Thread *thread, |
| Display *display, |
| Config *configuration, |
| gl::Context *sharedGLContext, |
| const AttributeMap &attributes) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateContext", |
| GetDisplayIfValid(display), EGL_NO_CONTEXT); |
| gl::Context *context = nullptr; |
| ANGLE_EGL_TRY_RETURN(thread, |
| display->createContext(configuration, sharedGLContext, thread->getAPI(), |
| attributes, &context), |
| "eglCreateContext", GetDisplayIfValid(display), EGL_NO_CONTEXT); |
| |
| thread->setSuccess(); |
| return static_cast<EGLContext>(context); |
| } |
| |
| EGLImage CreateImage(Thread *thread, |
| Display *display, |
| gl::Context *context, |
| EGLenum target, |
| EGLClientBuffer buffer, |
| const AttributeMap &attributes) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateImage", |
| GetDisplayIfValid(display), EGL_FALSE); |
| |
| Image *image = nullptr; |
| Error error = display->createImage(context, target, buffer, attributes, &image); |
| if (error.isError()) |
| { |
| thread->setError(error, "eglCreateImage", GetDisplayIfValid(display)); |
| return EGL_NO_IMAGE; |
| } |
| |
| thread->setSuccess(); |
| return static_cast<EGLImage>(image); |
| } |
| |
| EGLSurface CreatePbufferFromClientBuffer(Thread *thread, |
| Display *display, |
| EGLenum buftype, |
| EGLClientBuffer buffer, |
| Config *configuration, |
| const AttributeMap &attributes) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePbufferFromClientBuffer", |
| GetDisplayIfValid(display), EGL_NO_SURFACE); |
| Surface *surface = nullptr; |
| ANGLE_EGL_TRY_RETURN(thread, |
| display->createPbufferFromClientBuffer(configuration, buftype, buffer, |
| attributes, &surface), |
| "eglCreatePbufferFromClientBuffer", GetDisplayIfValid(display), |
| EGL_NO_SURFACE); |
| |
| return static_cast<EGLSurface>(surface); |
| } |
| |
| EGLSurface CreatePbufferSurface(Thread *thread, |
| Display *display, |
| Config *configuration, |
| const AttributeMap &attributes) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePbufferSurface", |
| GetDisplayIfValid(display), EGL_NO_SURFACE); |
| Surface *surface = nullptr; |
| ANGLE_EGL_TRY_RETURN(thread, display->createPbufferSurface(configuration, attributes, &surface), |
| "eglCreatePbufferSurface", GetDisplayIfValid(display), EGL_NO_SURFACE); |
| |
| return static_cast<EGLSurface>(surface); |
| } |
| |
| EGLSurface CreatePixmapSurface(Thread *thread, |
| Display *display, |
| Config *configuration, |
| EGLNativePixmapType pixmap, |
| const AttributeMap &attributes) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePixmapSurface", |
| GetDisplayIfValid(display), EGL_NO_SURFACE); |
| Surface *surface = nullptr; |
| ANGLE_EGL_TRY_RETURN(thread, |
| display->createPixmapSurface(configuration, pixmap, attributes, &surface), |
| "eglCreatePixmapSurface", GetDisplayIfValid(display), EGL_NO_SURFACE); |
| |
| thread->setSuccess(); |
| return static_cast<EGLSurface>(surface); |
| } |
| |
| EGLSurface CreatePlatformPixmapSurface(Thread *thread, |
| Display *display, |
| Config *configuration, |
| void *pixmap, |
| const AttributeMap &attributes) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePlatformPixmapSurface", |
| GetDisplayIfValid(display), EGL_NO_SURFACE); |
| Surface *surface = nullptr; |
| EGLNativePixmapType nativePixmap = reinterpret_cast<EGLNativePixmapType>(pixmap); |
| ANGLE_EGL_TRY_RETURN( |
| thread, display->createPixmapSurface(configuration, nativePixmap, attributes, &surface), |
| "eglCreatePlatformPixmapSurface", GetDisplayIfValid(display), EGL_NO_SURFACE); |
| |
| thread->setSuccess(); |
| return static_cast<EGLSurface>(surface); |
| } |
| |
| EGLSurface CreatePlatformWindowSurface(Thread *thread, |
| Display *display, |
| Config *configuration, |
| void *win, |
| const AttributeMap &attributes) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePlatformWindowSurface", |
| GetDisplayIfValid(display), EGL_NO_SURFACE); |
| Surface *surface = nullptr; |
| EGLNativeWindowType nativeWindow = reinterpret_cast<EGLNativeWindowType>(win); |
| ANGLE_EGL_TRY_RETURN( |
| thread, display->createWindowSurface(configuration, nativeWindow, attributes, &surface), |
| "eglPlatformCreateWindowSurface", GetDisplayIfValid(display), EGL_NO_SURFACE); |
| |
| return static_cast<EGLSurface>(surface); |
| } |
| |
| EGLSync CreateSync(Thread *thread, Display *display, EGLenum type, const AttributeMap &attributes) |
| { |
| gl::Context *currentContext = thread->getContext(); |
| |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateSync", |
| GetDisplayIfValid(display), EGL_FALSE); |
| Sync *syncObject = nullptr; |
| ANGLE_EGL_TRY_RETURN(thread, display->createSync(currentContext, type, attributes, &syncObject), |
| "eglCreateSync", GetDisplayIfValid(display), EGL_NO_SYNC); |
| |
| thread->setSuccess(); |
| return static_cast<EGLSync>(syncObject); |
| } |
| |
| EGLSurface CreateWindowSurface(Thread *thread, |
| Display *display, |
| Config *configuration, |
| EGLNativeWindowType win, |
| const AttributeMap &attributes) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateWindowSurface", |
| GetDisplayIfValid(display), EGL_NO_SURFACE); |
| |
| Surface *surface = nullptr; |
| ANGLE_EGL_TRY_RETURN(thread, |
| display->createWindowSurface(configuration, win, attributes, &surface), |
| "eglCreateWindowSurface", GetDisplayIfValid(display), EGL_NO_SURFACE); |
| |
| return static_cast<EGLSurface>(surface); |
| } |
| |
| EGLBoolean DestroyContext(Thread *thread, Display *display, gl::Context *context) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroyContext", |
| GetDisplayIfValid(display), EGL_FALSE); |
| |
| ScopedSyncCurrentContextFromThread scopedSyncCurrent(thread); |
| |
| ANGLE_EGL_TRY_RETURN(thread, display->destroyContext(thread, context), "eglDestroyContext", |
| GetContextIfValid(display, context), EGL_FALSE); |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean DestroyImage(Thread *thread, Display *display, Image *img) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroyImage", |
| GetDisplayIfValid(display), EGL_FALSE); |
| display->destroyImage(img); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean DestroySurface(Thread *thread, Display *display, Surface *eglSurface) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroySurface", |
| GetDisplayIfValid(display), EGL_FALSE); |
| ANGLE_EGL_TRY_RETURN(thread, display->destroySurface(eglSurface), "eglDestroySurface", |
| GetSurfaceIfValid(display, eglSurface), EGL_FALSE); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean DestroySync(Thread *thread, Display *display, Sync *syncObject) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroySync", |
| GetDisplayIfValid(display), EGL_FALSE); |
| display->destroySync(syncObject); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean GetConfigAttrib(Thread *thread, |
| Display *display, |
| Config *configuration, |
| EGLint attribute, |
| EGLint *value) |
| { |
| QueryConfigAttrib(configuration, attribute, value); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean GetConfigs(Thread *thread, |
| Display *display, |
| EGLConfig *configs, |
| EGLint config_size, |
| EGLint *num_config) |
| { |
| ClipConfigs(display->getConfigs(AttributeMap()), configs, config_size, num_config); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLContext GetCurrentContext(Thread *thread) |
| { |
| gl::Context *context = thread->getContext(); |
| |
| thread->setSuccess(); |
| return static_cast<EGLContext>(context); |
| } |
| |
| EGLDisplay GetCurrentDisplay(Thread *thread) |
| { |
| thread->setSuccess(); |
| if (thread->getContext() != nullptr) |
| { |
| return thread->getContext()->getDisplay(); |
| } |
| return EGL_NO_DISPLAY; |
| } |
| |
| EGLSurface GetCurrentSurface(Thread *thread, EGLint readdraw) |
| { |
| if (readdraw == EGL_READ) |
| { |
| thread->setSuccess(); |
| return thread->getCurrentReadSurface(); |
| } |
| else if (readdraw == EGL_DRAW) |
| { |
| thread->setSuccess(); |
| return thread->getCurrentDrawSurface(); |
| } |
| else |
| { |
| thread->setError(EglBadParameter(), "eglGetCurrentSurface", nullptr); |
| return EGL_NO_SURFACE; |
| } |
| } |
| |
| EGLDisplay GetDisplay(Thread *thread, EGLNativeDisplayType display_id) |
| { |
| return Display::GetDisplayFromNativeDisplay(display_id, AttributeMap()); |
| } |
| |
| EGLint GetError(Thread *thread) |
| { |
| EGLint error = thread->getError(); |
| thread->setSuccess(); |
| return error; |
| } |
| |
| EGLDisplay GetPlatformDisplay(Thread *thread, |
| EGLenum platform, |
| void *native_display, |
| const AttributeMap &attribMap) |
| { |
| if (platform == EGL_PLATFORM_ANGLE_ANGLE) |
| { |
| return Display::GetDisplayFromNativeDisplay( |
| gl::bitCast<EGLNativeDisplayType>(native_display), attribMap); |
| } |
| else if (platform == EGL_PLATFORM_DEVICE_EXT) |
| { |
| Device *eglDevice = static_cast<Device *>(native_display); |
| return Display::GetDisplayFromDevice(eglDevice, attribMap); |
| } |
| else |
| { |
| UNREACHABLE(); |
| return EGL_NO_DISPLAY; |
| } |
| } |
| |
| __eglMustCastToProperFunctionPointerType GetProcAddress(Thread *thread, const char *procname) |
| { |
| const ProcEntry *entry = |
| std::lower_bound(&g_procTable[0], &g_procTable[g_numProcs], procname, CompareProc); |
| |
| thread->setSuccess(); |
| |
| if (entry == &g_procTable[g_numProcs] || strcmp(entry->first, procname) != 0) |
| { |
| return nullptr; |
| } |
| |
| return entry->second; |
| } |
| |
| EGLBoolean GetSyncAttrib(Thread *thread, |
| Display *display, |
| Sync *syncObject, |
| EGLint attribute, |
| EGLAttrib *value) |
| { |
| EGLint valueExt; |
| ANGLE_EGL_TRY_RETURN(thread, GetSyncAttrib(display, syncObject, attribute, &valueExt), |
| "eglGetSyncAttrib", GetSyncIfValid(display, syncObject), EGL_FALSE); |
| *value = valueExt; |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean Initialize(Thread *thread, Display *display, EGLint *major, EGLint *minor) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->initialize(), "eglInitialize", GetDisplayIfValid(display), |
| EGL_FALSE); |
| |
| if (major) |
| *major = 1; |
| if (minor) |
| *minor = 5; |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean MakeCurrent(Thread *thread, |
| Display *display, |
| Surface *drawSurface, |
| Surface *readSurface, |
| gl::Context *context) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglMakeCurrent", |
| GetDisplayIfValid(display), EGL_FALSE); |
| ScopedSyncCurrentContextFromThread scopedSyncCurrent(thread); |
| |
| Surface *previousDraw = thread->getCurrentDrawSurface(); |
| Surface *previousRead = thread->getCurrentReadSurface(); |
| gl::Context *previousContext = thread->getContext(); |
| |
| // Only call makeCurrent if the context or surfaces have changed. |
| if (previousDraw != drawSurface || previousRead != readSurface || previousContext != context) |
| { |
| ANGLE_EGL_TRY_RETURN( |
| thread, |
| display->makeCurrent(thread, previousContext, drawSurface, readSurface, context), |
| "eglMakeCurrent", GetContextIfValid(display, context), EGL_FALSE); |
| } |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLenum QueryAPI(Thread *thread) |
| { |
| EGLenum API = thread->getAPI(); |
| |
| thread->setSuccess(); |
| return API; |
| } |
| |
| EGLBoolean QueryContext(Thread *thread, |
| Display *display, |
| gl::Context *context, |
| EGLint attribute, |
| EGLint *value) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryContext", |
| GetDisplayIfValid(display), EGL_FALSE); |
| QueryContextAttrib(context, attribute, value); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| const char *QueryString(Thread *thread, Display *display, EGLint name) |
| { |
| if (display) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryString", |
| GetDisplayIfValid(display), nullptr); |
| } |
| |
| const char *result = nullptr; |
| switch (name) |
| { |
| case EGL_CLIENT_APIS: |
| result = "OpenGL_ES"; |
| break; |
| case EGL_EXTENSIONS: |
| if (display == EGL_NO_DISPLAY) |
| { |
| result = Display::GetClientExtensionString().c_str(); |
| } |
| else |
| { |
| result = display->getExtensionString().c_str(); |
| } |
| break; |
| case EGL_VENDOR: |
| result = display->getVendorString().c_str(); |
| break; |
| case EGL_VERSION: |
| result = "1.5 (ANGLE " ANGLE_VERSION_STRING ")"; |
| break; |
| default: |
| UNREACHABLE(); |
| break; |
| } |
| |
| thread->setSuccess(); |
| return result; |
| } |
| |
| EGLBoolean QuerySurface(Thread *thread, |
| Display *display, |
| Surface *eglSurface, |
| EGLint attribute, |
| EGLint *value) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQuerySurface", |
| GetDisplayIfValid(display), EGL_FALSE); |
| ANGLE_EGL_TRY_RETURN( |
| thread, QuerySurfaceAttrib(display, thread->getContext(), eglSurface, attribute, value), |
| "eglQuerySurface", GetSurfaceIfValid(display, eglSurface), EGL_FALSE); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean ReleaseTexImage(Thread *thread, Display *display, Surface *eglSurface, EGLint buffer) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglReleaseTexImage", |
| GetDisplayIfValid(display), EGL_FALSE); |
| gl::Texture *texture = eglSurface->getBoundTexture(); |
| |
| if (texture) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, eglSurface->releaseTexImage(thread->getContext(), buffer), |
| "eglReleaseTexImage", GetSurfaceIfValid(display, eglSurface), |
| EGL_FALSE); |
| } |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean ReleaseThread(Thread *thread) |
| { |
| ScopedSyncCurrentContextFromThread scopedSyncCurrent(thread); |
| |
| Surface *previousDraw = thread->getCurrentDrawSurface(); |
| Surface *previousRead = thread->getCurrentReadSurface(); |
| gl::Context *previousContext = thread->getContext(); |
| Display *previousDisplay = thread->getDisplay(); |
| |
| if (previousDisplay != EGL_NO_DISPLAY) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, previousDisplay->prepareForCall(), "eglReleaseThread", |
| GetDisplayIfValid(previousDisplay), EGL_FALSE); |
| // Only call makeCurrent if the context or surfaces have changed. |
| if (previousDraw != EGL_NO_SURFACE || previousRead != EGL_NO_SURFACE || |
| previousContext != EGL_NO_CONTEXT) |
| { |
| ANGLE_EGL_TRY_RETURN( |
| thread, |
| previousDisplay->makeCurrent(thread, previousContext, nullptr, nullptr, nullptr), |
| "eglReleaseThread", nullptr, EGL_FALSE); |
| } |
| ANGLE_EGL_TRY_RETURN(thread, previousDisplay->releaseThread(), "eglReleaseThread", |
| GetDisplayIfValid(previousDisplay), EGL_FALSE); |
| } |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean SurfaceAttrib(Thread *thread, |
| Display *display, |
| Surface *eglSurface, |
| EGLint attribute, |
| EGLint value) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglSurfaceAttrib", |
| GetDisplayIfValid(display), EGL_FALSE); |
| SetSurfaceAttrib(eglSurface, attribute, value); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean SwapBuffers(Thread *thread, Display *display, Surface *eglSurface) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglSwapBuffers", |
| GetDisplayIfValid(display), EGL_FALSE); |
| |
| ANGLE_EGL_TRY_RETURN(thread, eglSurface->swap(thread->getContext()), "eglSwapBuffers", |
| GetSurfaceIfValid(display, eglSurface), EGL_FALSE); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean SwapInterval(Thread *thread, Display *display, EGLint interval) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglSwapInterval", |
| GetDisplayIfValid(display), EGL_FALSE); |
| |
| Surface *drawSurface = static_cast<Surface *>(thread->getCurrentDrawSurface()); |
| const Config *surfaceConfig = drawSurface->getConfig(); |
| EGLint clampedInterval = std::min(std::max(interval, surfaceConfig->minSwapInterval), |
| surfaceConfig->maxSwapInterval); |
| |
| drawSurface->setSwapInterval(clampedInterval); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean Terminate(Thread *thread, Display *display) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglTerminate", |
| GetDisplayIfValid(display), EGL_FALSE); |
| |
| ScopedSyncCurrentContextFromThread scopedSyncCurrent(thread); |
| |
| ANGLE_EGL_TRY_RETURN( |
| thread, display->makeCurrent(thread, thread->getContext(), nullptr, nullptr, nullptr), |
| "eglTerminate", GetDisplayIfValid(display), EGL_FALSE); |
| ANGLE_EGL_TRY_RETURN(thread, display->terminate(thread), "eglTerminate", |
| GetDisplayIfValid(display), EGL_FALSE); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean WaitClient(Thread *thread) |
| { |
| Display *display = thread->getDisplay(); |
| if (display == nullptr) |
| { |
| // EGL spec says this about eglWaitClient - |
| // If there is no current context for the current rendering API, |
| // the function has no effect but still returns EGL_TRUE. |
| return EGL_TRUE; |
| } |
| |
| gl::Context *context = thread->getContext(); |
| |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitClient", |
| GetDisplayIfValid(display), EGL_FALSE); |
| ANGLE_EGL_TRY_RETURN(thread, display->waitClient(context), "eglWaitClient", |
| GetContextIfValid(display, context), EGL_FALSE); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean WaitGL(Thread *thread) |
| { |
| Display *display = thread->getDisplay(); |
| if (display == nullptr) |
| { |
| // EGL spec says this about eglWaitGL - |
| // eglWaitGL is ignored if there is no current EGL rendering context for OpenGL ES. |
| return EGL_TRUE; |
| } |
| |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitGL", GetDisplayIfValid(display), |
| EGL_FALSE); |
| |
| // eglWaitGL like calling eglWaitClient with the OpenGL ES API bound. Since we only implement |
| // OpenGL ES we can do the call directly. |
| ANGLE_EGL_TRY_RETURN(thread, display->waitClient(thread->getContext()), "eglWaitGL", |
| GetDisplayIfValid(display), EGL_FALSE); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean WaitNative(Thread *thread, EGLint engine) |
| { |
| Display *display = thread->getDisplay(); |
| if (display == nullptr) |
| { |
| // EGL spec says this about eglWaitNative - |
| // eglWaitNative is ignored if there is no current EGL rendering context. |
| return EGL_TRUE; |
| } |
| |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitNative", |
| GetDisplayIfValid(display), EGL_FALSE); |
| ANGLE_EGL_TRY_RETURN(thread, display->waitNative(thread->getContext(), engine), "eglWaitNative", |
| GetThreadIfValid(thread), EGL_FALSE); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean WaitSync(Thread *thread, Display *display, Sync *syncObject, EGLint flags) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitSync", |
| GetDisplayIfValid(display), EGL_FALSE); |
| gl::Context *currentContext = thread->getContext(); |
| ANGLE_EGL_TRY_RETURN(thread, syncObject->serverWait(display, currentContext, flags), |
| "eglWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| } // namespace egl |