| // |
| // Copyright 2014 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. |
| // |
| |
| // entry_points_egl.cpp : Implements the EGL entry points. |
| |
| #include "libGLESv2/entry_points_egl.h" |
| |
| #include "common/debug.h" |
| #include "common/utilities.h" |
| #include "common/version.h" |
| #include "libANGLE/Context.h" |
| #include "libANGLE/Display.h" |
| #include "libANGLE/EGLSync.h" |
| #include "libANGLE/Surface.h" |
| #include "libANGLE/Texture.h" |
| #include "libANGLE/Thread.h" |
| #include "libANGLE/entry_points_utils.h" |
| #include "libANGLE/queryutils.h" |
| #include "libANGLE/validationEGL.h" |
| #include "libGLESv2/global_state.h" |
| #include "libGLESv2/proc_table_egl.h" |
| |
| using 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 *output_configs, |
| EGLint config_size, |
| EGLint *num_config) |
| { |
| EGLint result_size = static_cast<EGLint>(filteredConfigs.size()); |
| if (output_configs) |
| { |
| result_size = std::max(std::min(result_size, config_size), 0); |
| for (EGLint i = 0; i < result_size; i++) |
| { |
| output_configs[i] = const_cast<Config *>(filteredConfigs[i]); |
| } |
| } |
| *num_config = result_size; |
| } |
| } // anonymous namespace |
| |
| extern "C" { |
| // EGL 1.0 |
| EGLint EGLAPIENTRY EGL_GetError(void) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| EVENT(__FUNCTION__, ""); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| EGLint error = thread->getError(); |
| thread->setSuccess(); |
| return error; |
| } |
| |
| EGLDisplay EGLAPIENTRY EGL_GetDisplay(EGLNativeDisplayType display_id) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLNativeDisplayType display_id = 0x%016" PRIxPTR, (uintptr_t)display_id); |
| |
| return egl::Display::GetDisplayFromNativeDisplay(display_id, AttributeMap()); |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLint *major = 0x%016" PRIxPTR |
| ", EGLint *minor = 0x%016" PRIxPTR, |
| (uintptr_t)dpy, (uintptr_t)major, (uintptr_t)minor); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| ANGLE_EGL_TRY_RETURN(thread, ValidateInitialize(display), "eglInitialize", |
| GetDisplayIfValid(display), EGL_FALSE); |
| |
| ANGLE_EGL_TRY_RETURN(thread, display->initialize(), "eglInitialize", GetDisplayIfValid(display), |
| EGL_FALSE); |
| |
| if (major) |
| *major = 1; |
| if (minor) |
| *minor = 4; |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_Terminate(EGLDisplay dpy) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR, (uintptr_t)dpy); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| ANGLE_EGL_TRY_RETURN(thread, ValidateTerminate(display), "eglTerminate", |
| GetDisplayIfValid(display), EGL_FALSE); |
| |
| ANGLE_EGL_TRY_RETURN(thread, display->makeCurrent(thread, nullptr, nullptr, nullptr), |
| "eglTerminate", GetDisplayIfValid(display), EGL_FALSE); |
| SetContextCurrent(thread, nullptr); |
| ANGLE_EGL_TRY_RETURN(thread, display->terminate(thread), "eglTerminate", |
| GetDisplayIfValid(display), EGL_FALSE); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| const char *EGLAPIENTRY EGL_QueryString(EGLDisplay dpy, EGLint name) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLint name = %d", (uintptr_t)dpy, name); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| if (!(display == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, ValidateDisplay(display), "eglQueryString", |
| GetDisplayIfValid(display), nullptr); |
| } |
| |
| const char *result; |
| switch (name) |
| { |
| case EGL_CLIENT_APIS: |
| result = "OpenGL_ES"; |
| break; |
| case EGL_EXTENSIONS: |
| if (display == EGL_NO_DISPLAY) |
| { |
| result = egl::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.4 (ANGLE " ANGLE_VERSION_STRING ")"; |
| break; |
| default: |
| thread->setError(EglBadParameter(), GetDebug(), "eglQueryString", |
| GetDisplayIfValid(display)); |
| return nullptr; |
| } |
| |
| thread->setSuccess(); |
| return result; |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_GetConfigs(EGLDisplay dpy, |
| EGLConfig *configs, |
| EGLint config_size, |
| EGLint *num_config) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLConfig *configs = 0x%016" PRIxPTR |
| ", " |
| "EGLint config_size = %d, EGLint *num_config = 0x%016" PRIxPTR, |
| (uintptr_t)dpy, (uintptr_t)configs, config_size, (uintptr_t)num_config); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateGetConfigs(display, config_size, num_config), |
| "eglGetConfigs", GetDisplayIfValid(display), EGL_FALSE); |
| |
| ClipConfigs(display->getConfigs(AttributeMap()), configs, config_size, num_config); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_ChooseConfig(EGLDisplay dpy, |
| const EGLint *attrib_list, |
| EGLConfig *configs, |
| EGLint config_size, |
| EGLint *num_config) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", const EGLint *attrib_list = 0x%016" PRIxPTR |
| ", " |
| "EGLConfig *configs = 0x%016" PRIxPTR |
| ", EGLint config_size = %d, EGLint *num_config = 0x%016" PRIxPTR, |
| (uintptr_t)dpy, (uintptr_t)attrib_list, (uintptr_t)configs, config_size, |
| (uintptr_t)num_config); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| AttributeMap attribMap = AttributeMap::CreateFromIntArray(attrib_list); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateChooseConfig(display, attribMap, config_size, num_config), |
| "eglChooseConfig", GetDisplayIfValid(display), EGL_FALSE); |
| |
| ClipConfigs(display->chooseConfig(attribMap), configs, config_size, num_config); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_GetConfigAttrib(EGLDisplay dpy, |
| EGLConfig config, |
| EGLint attribute, |
| EGLint *value) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLConfig config = 0x%016" PRIxPTR |
| ", EGLint attribute = %d, EGLint " |
| "*value = 0x%016" PRIxPTR, |
| (uintptr_t)dpy, (uintptr_t)config, attribute, (uintptr_t)value); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| Config *configuration = static_cast<Config *>(config); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateGetConfigAttrib(display, configuration, attribute), |
| "eglGetConfigAttrib", GetDisplayIfValid(display), EGL_FALSE); |
| |
| QueryConfigAttrib(configuration, attribute, value); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLSurface EGLAPIENTRY EGL_CreateWindowSurface(EGLDisplay dpy, |
| EGLConfig config, |
| EGLNativeWindowType win, |
| const EGLint *attrib_list) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLConfig config = 0x%016" PRIxPTR |
| ", EGLNativeWindowType win = 0x%016" PRIxPTR |
| ", " |
| "const EGLint *attrib_list = 0x%016" PRIxPTR, |
| (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)win, (uintptr_t)attrib_list); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| Config *configuration = static_cast<Config *>(config); |
| AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list); |
| |
| ANGLE_EGL_TRY_RETURN(thread, |
| ValidateCreateWindowSurface(display, configuration, win, attributes), |
| "eglCreateWindowSurface", GetDisplayIfValid(display), EGL_NO_SURFACE); |
| |
| egl::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); |
| } |
| |
| EGLSurface EGLAPIENTRY EGL_CreatePbufferSurface(EGLDisplay dpy, |
| EGLConfig config, |
| const EGLint *attrib_list) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLConfig config = 0x%016" PRIxPTR |
| ", const EGLint *attrib_list = " |
| "0x%016" PRIxPTR, |
| (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)attrib_list); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| Config *configuration = static_cast<Config *>(config); |
| AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateCreatePbufferSurface(display, configuration, attributes), |
| "eglCreatePbufferSurface", GetDisplayIfValid(display), EGL_NO_SURFACE); |
| |
| egl::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 EGLAPIENTRY EGL_CreatePixmapSurface(EGLDisplay dpy, |
| EGLConfig config, |
| EGLNativePixmapType pixmap, |
| const EGLint *attrib_list) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLConfig config = 0x%016" PRIxPTR |
| ", EGLNativePixmapType pixmap = " |
| "0x%016" PRIxPTR |
| ", " |
| "const EGLint *attrib_list = 0x%016" PRIxPTR, |
| (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)pixmap, (uintptr_t)attrib_list); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| Config *configuration = static_cast<Config *>(config); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateConfig(display, configuration), "eglCreatePixmapSurface", |
| GetDisplayIfValid(display), EGL_NO_SURFACE); |
| |
| UNIMPLEMENTED(); // FIXME |
| |
| thread->setSuccess(); |
| return EGL_NO_SURFACE; |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_DestroySurface(EGLDisplay dpy, EGLSurface surface) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR, |
| (uintptr_t)dpy, (uintptr_t)surface); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| Surface *eglSurface = static_cast<Surface *>(surface); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateDestroySurface(display, eglSurface, surface), |
| "eglDestroySurface", GetSurfaceIfValid(display, eglSurface), EGL_FALSE); |
| |
| ANGLE_EGL_TRY_RETURN(thread, display->destroySurface(eglSurface), "eglDestroySurface", |
| GetSurfaceIfValid(display, eglSurface), EGL_FALSE); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_QuerySurface(EGLDisplay dpy, |
| EGLSurface surface, |
| EGLint attribute, |
| EGLint *value) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR |
| ", EGLint attribute = %d, EGLint " |
| "*value = 0x%016" PRIxPTR, |
| (uintptr_t)dpy, (uintptr_t)surface, attribute, (uintptr_t)value); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| const egl::Display *display = static_cast<const egl::Display *>(dpy); |
| const Surface *eglSurface = static_cast<const Surface *>(surface); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateQuerySurface(display, eglSurface, attribute, value), |
| "eglQuerySurface", GetSurfaceIfValid(display, eglSurface), EGL_FALSE); |
| |
| QuerySurfaceAttrib(eglSurface, attribute, value); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLContext EGLAPIENTRY EGL_CreateContext(EGLDisplay dpy, |
| EGLConfig config, |
| EGLContext share_context, |
| const EGLint *attrib_list) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLConfig config = 0x%016" PRIxPTR |
| ", EGLContext share_context = %d, " |
| "const EGLint *attrib_list = 0x%016" PRIxPTR, |
| (uintptr_t)dpy, (uintptr_t)config, CID(dpy, share_context), (uintptr_t)attrib_list); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| Config *configuration = static_cast<Config *>(config); |
| gl::Context *sharedGLContext = static_cast<gl::Context *>(share_context); |
| AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list); |
| |
| ANGLE_EGL_TRY_RETURN(thread, |
| ValidateCreateContext(display, configuration, sharedGLContext, attributes), |
| "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); |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_DestroyContext(EGLDisplay dpy, EGLContext ctx) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLContext ctx = %d", (uintptr_t)dpy, |
| CID(dpy, ctx)); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| gl::Context *context = static_cast<gl::Context *>(ctx); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateDestroyContext(display, context, ctx), "eglDestroyContext", |
| GetContextIfValid(display, context), EGL_FALSE); |
| |
| bool contextWasCurrent = context == thread->getContext(); |
| |
| ANGLE_EGL_TRY_RETURN(thread, display->destroyContext(thread, context), "eglDestroyContext", |
| GetContextIfValid(display, context), EGL_FALSE); |
| |
| if (contextWasCurrent) |
| { |
| SetContextCurrent(thread, nullptr); |
| } |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_MakeCurrent(EGLDisplay dpy, |
| EGLSurface draw, |
| EGLSurface read, |
| EGLContext ctx) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface draw = 0x%016" PRIxPTR |
| ", EGLSurface read = 0x%016" PRIxPTR |
| ", " |
| "EGLContext ctx = %d", |
| (uintptr_t)dpy, (uintptr_t)draw, (uintptr_t)read, CID(dpy, ctx)); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| Surface *drawSurface = static_cast<Surface *>(draw); |
| Surface *readSurface = static_cast<Surface *>(read); |
| gl::Context *context = static_cast<gl::Context *>(ctx); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateMakeCurrent(display, drawSurface, readSurface, context), |
| "eglMakeCurrent", GetContextIfValid(display, context), EGL_FALSE); |
| |
| 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, drawSurface, readSurface, context), |
| "eglMakeCurrent", GetContextIfValid(display, context), EGL_FALSE); |
| |
| SetContextCurrent(thread, context); |
| } |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLSurface EGLAPIENTRY EGL_GetCurrentSurface(EGLint readdraw) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLint readdraw = %d", readdraw); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| if (readdraw == EGL_READ) |
| { |
| thread->setSuccess(); |
| return thread->getCurrentReadSurface(); |
| } |
| else if (readdraw == EGL_DRAW) |
| { |
| thread->setSuccess(); |
| return thread->getCurrentDrawSurface(); |
| } |
| else |
| { |
| thread->setError(EglBadParameter(), GetDebug(), "eglGetCurrentSurface", nullptr); |
| return EGL_NO_SURFACE; |
| } |
| } |
| |
| EGLDisplay EGLAPIENTRY EGL_GetCurrentDisplay(void) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| EVENT(__FUNCTION__, ""); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| thread->setSuccess(); |
| if (thread->getContext() != nullptr) |
| { |
| return thread->getContext()->getDisplay(); |
| } |
| return EGL_NO_DISPLAY; |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_QueryContext(EGLDisplay dpy, |
| EGLContext ctx, |
| EGLint attribute, |
| EGLint *value) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR |
| ", EGLContext ctx = %d" |
| ", EGLint attribute = %d, EGLint *value " |
| "= 0x%016" PRIxPTR, |
| (uintptr_t)dpy, CID(dpy, ctx), attribute, (uintptr_t)value); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| gl::Context *context = static_cast<gl::Context *>(ctx); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateQueryContext(display, context, attribute, value), |
| "eglQueryContext", GetContextIfValid(display, context), EGL_FALSE); |
| |
| QueryContextAttrib(context, attribute, value); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_WaitGL(void) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| EVENT(__FUNCTION__, ""); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = thread->getDisplay(); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateDisplay(display), "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 EGLAPIENTRY EGL_WaitNative(EGLint engine) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLint engine = %d", engine); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = thread->getDisplay(); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateWaitNative(display, engine), "eglWaitNative", |
| GetThreadIfValid(thread), EGL_FALSE); |
| |
| ANGLE_EGL_TRY_RETURN(thread, display->waitNative(thread->getContext(), engine), "eglWaitNative", |
| GetThreadIfValid(thread), EGL_FALSE); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_SwapBuffers(EGLDisplay dpy, EGLSurface surface) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR, |
| (uintptr_t)dpy, (uintptr_t)surface); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| Surface *eglSurface = (Surface *)surface; |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateSwapBuffers(thread, display, eglSurface), "eglSwapBuffers", |
| GetSurfaceIfValid(display, eglSurface), EGL_FALSE); |
| |
| ANGLE_EGL_TRY_RETURN(thread, eglSurface->swap(thread->getContext()), "eglSwapBuffers", |
| GetSurfaceIfValid(display, eglSurface), EGL_FALSE); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_CopyBuffers(EGLDisplay dpy, |
| EGLSurface surface, |
| EGLNativePixmapType target) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR |
| ", EGLNativePixmapType target = " |
| "0x%016" PRIxPTR, |
| (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)target); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| Surface *eglSurface = static_cast<Surface *>(surface); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateCopyBuffers(display, eglSurface), "eglCopyBuffers", |
| GetSurfaceIfValid(display, eglSurface), EGL_FALSE); |
| |
| UNIMPLEMENTED(); // FIXME |
| |
| thread->setSuccess(); |
| return 0; |
| } |
| |
| // EGL 1.1 |
| EGLBoolean EGLAPIENTRY EGL_BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR |
| ", EGLint buffer = %d", |
| (uintptr_t)dpy, (uintptr_t)surface, buffer); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| Surface *eglSurface = static_cast<Surface *>(surface); |
| gl::Context *context = thread->getContext(); |
| gl::Texture *textureObject = nullptr; |
| |
| ANGLE_EGL_TRY_RETURN( |
| thread, ValidateBindTexImage(display, eglSurface, surface, buffer, context, &textureObject), |
| "eglBindTexImage", GetSurfaceIfValid(display, eglSurface), EGL_FALSE); |
| |
| if (context) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, eglSurface->bindTexImage(context, textureObject, buffer), |
| "eglBindTexImage", GetSurfaceIfValid(display, eglSurface), EGL_FALSE); |
| } |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_SurfaceAttrib(EGLDisplay dpy, |
| EGLSurface surface, |
| EGLint attribute, |
| EGLint value) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR |
| ", EGLint attribute = %d, EGLint " |
| "value = %d", |
| (uintptr_t)dpy, (uintptr_t)surface, attribute, value); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| Surface *eglSurface = static_cast<Surface *>(surface); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateSurfaceAttrib(display, eglSurface, attribute, value), |
| "eglSurfaceAttrib", GetSurfaceIfValid(display, eglSurface), EGL_FALSE); |
| |
| SetSurfaceAttrib(eglSurface, attribute, value); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR |
| ", EGLint buffer = %d", |
| (uintptr_t)dpy, (uintptr_t)surface, buffer); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| Surface *eglSurface = static_cast<Surface *>(surface); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateReleaseTexImage(display, eglSurface, surface, buffer), |
| "eglReleaseTexImage", GetSurfaceIfValid(display, eglSurface), 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 EGLAPIENTRY EGL_SwapInterval(EGLDisplay dpy, EGLint interval) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLint interval = %d", (uintptr_t)dpy, |
| interval); |
| Thread *thread = egl::GetCurrentThread(); |
| gl::Context *context = thread->getContext(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| Surface *draw_surface = static_cast<Surface *>(thread->getCurrentDrawSurface()); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateSwapInterval(display, draw_surface, context), |
| "eglSwapInterval", GetDisplayIfValid(display), EGL_FALSE); |
| |
| const egl::Config *surfaceConfig = draw_surface->getConfig(); |
| EGLint clampedInterval = std::min(std::max(interval, surfaceConfig->minSwapInterval), |
| surfaceConfig->maxSwapInterval); |
| |
| draw_surface->setSwapInterval(clampedInterval); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| // EGL 1.2 |
| EGLBoolean EGLAPIENTRY EGL_BindAPI(EGLenum api) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLenum api = 0x%X", api); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateBindAPI(api), "eglBindAPI", GetThreadIfValid(thread), |
| EGL_FALSE); |
| |
| thread->setAPI(api); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLenum EGLAPIENTRY EGL_QueryAPI(void) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| EVENT(__FUNCTION__, ""); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| EGLenum API = thread->getAPI(); |
| |
| thread->setSuccess(); |
| return API; |
| } |
| |
| EGLSurface EGLAPIENTRY EGL_CreatePbufferFromClientBuffer(EGLDisplay dpy, |
| EGLenum buftype, |
| EGLClientBuffer buffer, |
| EGLConfig config, |
| const EGLint *attrib_list) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR |
| ", EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%016" PRIxPTR |
| ", " |
| "EGLConfig config = 0x%016" PRIxPTR ", const EGLint *attrib_list = 0x%016" PRIxPTR, |
| (uintptr_t)dpy, buftype, (uintptr_t)buffer, (uintptr_t)config, |
| (uintptr_t)attrib_list); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| Config *configuration = static_cast<Config *>(config); |
| AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list); |
| |
| ANGLE_EGL_TRY_RETURN( |
| thread, |
| ValidateCreatePbufferFromClientBuffer(display, buftype, buffer, configuration, attributes), |
| "eglCreatePbufferFromClientBuffer", GetDisplayIfValid(display), EGL_NO_SURFACE); |
| |
| egl::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); |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_ReleaseThread(void) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| EVENT(__FUNCTION__, ""); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| Surface *previousDraw = thread->getCurrentDrawSurface(); |
| Surface *previousRead = thread->getCurrentReadSurface(); |
| gl::Context *previousContext = thread->getContext(); |
| egl::Display *previousDisplay = thread->getDisplay(); |
| |
| // Only call makeCurrent if the context or surfaces have changed. |
| if (previousDraw != EGL_NO_SURFACE || previousRead != EGL_NO_SURFACE || |
| previousContext != EGL_NO_CONTEXT) |
| { |
| if (previousDisplay != EGL_NO_DISPLAY) |
| { |
| ANGLE_EGL_TRY_RETURN(thread, |
| previousDisplay->makeCurrent(thread, nullptr, nullptr, nullptr), |
| "eglReleaseThread", nullptr, EGL_FALSE); |
| } |
| |
| SetContextCurrent(thread, nullptr); |
| } |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_WaitClient(void) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| EVENT(__FUNCTION__, ""); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = thread->getDisplay(); |
| gl::Context *context = thread->getContext(); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateDisplay(display), "eglWaitClient", |
| GetContextIfValid(display, context), EGL_FALSE); |
| |
| ANGLE_EGL_TRY_RETURN(thread, display->waitClient(context), "eglWaitClient", |
| GetContextIfValid(display, context), EGL_FALSE); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| // EGL 1.4 |
| EGLContext EGLAPIENTRY EGL_GetCurrentContext(void) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| EVENT(__FUNCTION__, ""); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| gl::Context *context = thread->getContext(); |
| |
| thread->setSuccess(); |
| return static_cast<EGLContext>(context); |
| } |
| |
| // EGL 1.5 |
| EGLSync EGLAPIENTRY EGL_CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR |
| ", EGLenum type = 0x%X, const EGLint* attrib_list = 0x%016" PRIxPTR, |
| (uintptr_t)dpy, type, (uintptr_t)attrib_list); |
| |
| Thread *thread = egl::GetCurrentThread(); |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| AttributeMap attributes = AttributeMap::CreateFromAttribArray(attrib_list); |
| |
| gl::Context *currentContext = thread->getContext(); |
| egl::Display *currentDisplay = currentContext ? currentContext->getDisplay() : nullptr; |
| |
| ANGLE_EGL_TRY_RETURN( |
| thread, ValidateCreateSyncKHR(display, type, attributes, currentDisplay, currentContext), |
| "eglCreateSync", GetDisplayIfValid(display), EGL_NO_SYNC); |
| |
| egl::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); |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_DestroySync(EGLDisplay dpy, EGLSync sync) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSync sync = 0x%016" PRIxPTR, (uintptr_t)dpy, |
| (uintptr_t)sync); |
| |
| Thread *thread = egl::GetCurrentThread(); |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| egl::Sync *syncObject = static_cast<Sync *>(sync); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateDestroySync(display, syncObject), "eglDestroySync", |
| GetDisplayIfValid(display), EGL_FALSE); |
| |
| display->destroySync(syncObject); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLint EGLAPIENTRY EGL_ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSync sync = 0x%016" PRIxPTR |
| ", EGLint flags = 0x%X, EGLTime timeout = " |
| "%llu", |
| (uintptr_t)dpy, (uintptr_t)sync, flags, static_cast<unsigned long long>(timeout)); |
| |
| Thread *thread = egl::GetCurrentThread(); |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| egl::Sync *syncObject = static_cast<Sync *>(sync); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateClientWaitSync(display, syncObject, flags, timeout), |
| "eglClientWaitSync", GetSyncIfValid(display, syncObject), 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 EGLAPIENTRY EGL_GetSyncAttrib(EGLDisplay dpy, |
| EGLSync sync, |
| EGLint attribute, |
| EGLAttrib *value) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSync sync = 0x%016" PRIxPTR |
| ", EGLint attribute = 0x%X, EGLAttrib " |
| "*value = 0x%016" PRIxPTR, |
| (uintptr_t)dpy, (uintptr_t)sync, attribute, (uintptr_t)value); |
| |
| Thread *thread = egl::GetCurrentThread(); |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| egl::Sync *syncObject = static_cast<Sync *>(sync); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateGetSyncAttrib(display, syncObject, attribute, value), |
| "eglGetSyncAttrib", GetSyncIfValid(display, syncObject), EGL_FALSE); |
| |
| 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; |
| } |
| |
| EGLImage EGLAPIENTRY EGL_CreateImage(EGLDisplay dpy, |
| EGLContext ctx, |
| EGLenum target, |
| EGLClientBuffer buffer, |
| const EGLAttrib *attrib_list) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR |
| ", EGLContext ctx = %d" |
| ", EGLenum target = 0x%X, " |
| "EGLClientBuffer buffer = 0x%016" PRIxPTR |
| ", const EGLAttrib *attrib_list = 0x%016" PRIxPTR, |
| (uintptr_t)dpy, CID(dpy, ctx), target, (uintptr_t)buffer, (uintptr_t)attrib_list); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| gl::Context *context = static_cast<gl::Context *>(ctx); |
| AttributeMap attributes = AttributeMap::CreateFromIntArray((const EGLint *)attrib_list); |
| |
| Error error = ValidateCreateImage(display, context, target, buffer, attributes); |
| if (error.isError()) |
| { |
| thread->setError(error, GetDebug(), "eglCreateImage", GetDisplayIfValid(display)); |
| return EGL_NO_IMAGE; |
| } |
| |
| Image *image = nullptr; |
| error = display->createImage(context, target, buffer, attributes, &image); |
| if (error.isError()) |
| { |
| thread->setError(error, GetDebug(), "eglCreateImage", GetDisplayIfValid(display)); |
| return EGL_NO_IMAGE; |
| } |
| |
| thread->setSuccess(); |
| return static_cast<EGLImage>(image); |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_DestroyImage(EGLDisplay dpy, EGLImage image) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLImage image = 0x%016" PRIxPTR, |
| (uintptr_t)dpy, (uintptr_t)image); |
| Thread *thread = egl::GetCurrentThread(); |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| Image *img = static_cast<Image *>(image); |
| |
| Error error = ValidateDestroyImage(display, img); |
| if (error.isError()) |
| { |
| thread->setError(error, GetDebug(), "eglDestroyImage", GetImageIfValid(display, img)); |
| return EGL_FALSE; |
| } |
| |
| display->destroyImage(img); |
| |
| thread->setSuccess(); |
| return EGL_TRUE; |
| } |
| |
| EGLDisplay EGLAPIENTRY EGL_GetPlatformDisplay(EGLenum platform, |
| void *native_display, |
| const EGLAttrib *attrib_list) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLenum platform = %d, void* native_display = 0x%016" PRIxPTR |
| ", const EGLint* attrib_list = " |
| "0x%016" PRIxPTR, |
| platform, (uintptr_t)native_display, (uintptr_t)attrib_list); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateGetPlatformDisplay(platform, native_display, attrib_list), |
| "eglGetPlatformDisplay", GetThreadIfValid(thread), EGL_NO_DISPLAY); |
| |
| const auto &attribMap = AttributeMap::CreateFromAttribArray(attrib_list); |
| if (platform == EGL_PLATFORM_ANGLE_ANGLE) |
| { |
| return egl::Display::GetDisplayFromNativeDisplay( |
| gl::bitCast<EGLNativeDisplayType>(native_display), attribMap); |
| } |
| else if (platform == EGL_PLATFORM_DEVICE_EXT) |
| { |
| Device *eglDevice = static_cast<Device *>(native_display); |
| return egl::Display::GetDisplayFromDevice(eglDevice, attribMap); |
| } |
| else |
| { |
| UNREACHABLE(); |
| return EGL_NO_DISPLAY; |
| } |
| } |
| |
| EGLSurface EGLAPIENTRY EGL_CreatePlatformWindowSurface(EGLDisplay dpy, |
| EGLConfig config, |
| void *native_window, |
| const EGLAttrib *attrib_list) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLConfig config = 0x%016" PRIxPTR |
| ", void* native_window = 0x%016" PRIxPTR |
| ", " |
| "const EGLint* attrib_list = 0x%016" PRIxPTR, |
| (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)native_window, (uintptr_t)attrib_list); |
| Thread *thread = egl::GetCurrentThread(); |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| |
| UNIMPLEMENTED(); |
| thread->setError(EglBadDisplay() << "eglCreatePlatformWindowSurface unimplemented.", GetDebug(), |
| "eglCreatePlatformWindowSurface", GetDisplayIfValid(display)); |
| return EGL_NO_SURFACE; |
| } |
| |
| EGLSurface EGLAPIENTRY EGL_CreatePlatformPixmapSurface(EGLDisplay dpy, |
| EGLConfig config, |
| void *native_pixmap, |
| const EGLAttrib *attrib_list) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLConfig config = 0x%016" PRIxPTR |
| ", void* native_pixmap = 0x%016" PRIxPTR |
| ", " |
| "const EGLint* attrib_list = 0x%016" PRIxPTR, |
| (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)native_pixmap, (uintptr_t)attrib_list); |
| Thread *thread = egl::GetCurrentThread(); |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| |
| UNIMPLEMENTED(); |
| thread->setError(EglBadDisplay() << "eglCreatePlatformPixmapSurface unimplemented.", GetDebug(), |
| "eglCreatePlatformPixmapSurface", GetDisplayIfValid(display)); |
| return EGL_NO_SURFACE; |
| } |
| |
| EGLBoolean EGLAPIENTRY EGL_WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("EGLDisplay dpy =0x%016" PRIxPTR "p, EGLSync sync = 0x%016" PRIxPTR |
| ", EGLint flags = 0x%X", |
| (uintptr_t)dpy, (uintptr_t)sync, flags); |
| |
| Thread *thread = egl::GetCurrentThread(); |
| egl::Display *display = static_cast<egl::Display *>(dpy); |
| gl::Context *context = thread->getContext(); |
| egl::Sync *syncObject = static_cast<Sync *>(sync); |
| |
| ANGLE_EGL_TRY_RETURN(thread, ValidateWaitSync(display, context, syncObject, flags), |
| "eglWaitSync", GetSyncIfValid(display, syncObject), 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; |
| } |
| |
| __eglMustCastToProperFunctionPointerType EGLAPIENTRY EGL_GetProcAddress(const char *procname) |
| { |
| ANGLE_SCOPED_GLOBAL_LOCK(); |
| FUNC_EVENT("const char *procname = \"%s\"", procname); |
| Thread *thread = egl::GetCurrentThread(); |
| |
| 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; |
| } |
| } // extern "C" |