michael@0: // michael@0: // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: // michael@0: michael@0: // libEGL.cpp: Implements the exported EGL functions. michael@0: michael@0: #include michael@0: michael@0: #include "common/debug.h" michael@0: #include "common/version.h" michael@0: #include "libGLESv2/Context.h" michael@0: #include "libGLESv2/Texture.h" michael@0: #include "libGLESv2/main.h" michael@0: #include "libGLESv2/renderer/SwapChain.h" michael@0: michael@0: #include "libEGL/main.h" michael@0: #include "libEGL/Display.h" michael@0: #include "libEGL/Surface.h" michael@0: michael@0: bool validateDisplay(egl::Display *display) michael@0: { michael@0: if (display == EGL_NO_DISPLAY) michael@0: { michael@0: return egl::error(EGL_BAD_DISPLAY, false); michael@0: } michael@0: michael@0: if (!display->isInitialized()) michael@0: { michael@0: return egl::error(EGL_NOT_INITIALIZED, false); michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool validateConfig(egl::Display *display, EGLConfig config) michael@0: { michael@0: if (!validateDisplay(display)) michael@0: { michael@0: return false; michael@0: } michael@0: michael@0: if (!display->isValidConfig(config)) michael@0: { michael@0: return egl::error(EGL_BAD_CONFIG, false); michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool validateContext(egl::Display *display, gl::Context *context) michael@0: { michael@0: if (!validateDisplay(display)) michael@0: { michael@0: return false; michael@0: } michael@0: michael@0: if (!display->isValidContext(context)) michael@0: { michael@0: return egl::error(EGL_BAD_CONTEXT, false); michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool validateSurface(egl::Display *display, egl::Surface *surface) michael@0: { michael@0: if (!validateDisplay(display)) michael@0: { michael@0: return false; michael@0: } michael@0: michael@0: if (!display->isValidSurface(surface)) michael@0: { michael@0: return egl::error(EGL_BAD_SURFACE, false); michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: extern "C" michael@0: { michael@0: EGLint __stdcall eglGetError(void) michael@0: { michael@0: EVENT("()"); michael@0: michael@0: EGLint error = egl::getCurrentError(); michael@0: michael@0: if (error != EGL_SUCCESS) michael@0: { michael@0: egl::setCurrentError(EGL_SUCCESS); michael@0: } michael@0: michael@0: return error; michael@0: } michael@0: michael@0: EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id) michael@0: { michael@0: EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id); michael@0: michael@0: try michael@0: { michael@0: return egl::Display::getDisplay(display_id); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_NO_DISPLAY); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)", michael@0: dpy, major, minor); michael@0: michael@0: try michael@0: { michael@0: if (dpy == EGL_NO_DISPLAY) michael@0: { michael@0: return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); michael@0: } michael@0: michael@0: egl::Display *display = static_cast(dpy); michael@0: michael@0: if (!display->initialize()) michael@0: { michael@0: return egl::error(EGL_NOT_INITIALIZED, EGL_FALSE); michael@0: } michael@0: michael@0: if (major) *major = 1; michael@0: if (minor) *minor = 4; michael@0: michael@0: return egl::success(EGL_TRUE); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglTerminate(EGLDisplay dpy) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p)", dpy); michael@0: michael@0: try michael@0: { michael@0: if (dpy == EGL_NO_DISPLAY) michael@0: { michael@0: return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); michael@0: } michael@0: michael@0: egl::Display *display = static_cast(dpy); michael@0: michael@0: display->terminate(); michael@0: michael@0: return egl::success(EGL_TRUE); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: michael@0: if (!validateDisplay(display)) michael@0: { michael@0: return NULL; michael@0: } michael@0: michael@0: switch (name) michael@0: { michael@0: case EGL_CLIENT_APIS: michael@0: return egl::success("OpenGL_ES"); michael@0: case EGL_EXTENSIONS: michael@0: return egl::success(display->getExtensionString()); michael@0: case EGL_VENDOR: michael@0: return egl::success(display->getVendorString()); michael@0: case EGL_VERSION: michael@0: return egl::success("1.4 (ANGLE " VERSION_STRING ")"); michael@0: } michael@0: michael@0: return egl::error(EGL_BAD_PARAMETER, (const char*)NULL); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, (const char*)NULL); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig *configs = 0x%0.8p, " michael@0: "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)", michael@0: dpy, configs, config_size, num_config); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: michael@0: if (!validateDisplay(display)) michael@0: { michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: if (!num_config) michael@0: { michael@0: return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); michael@0: } michael@0: michael@0: const EGLint attribList[] = {EGL_NONE}; michael@0: michael@0: if (!display->getConfigs(configs, attribList, config_size, num_config)) michael@0: { michael@0: return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); michael@0: } michael@0: michael@0: return egl::success(EGL_TRUE); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p, " michael@0: "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)", michael@0: dpy, attrib_list, configs, config_size, num_config); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: michael@0: if (!validateDisplay(display)) michael@0: { michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: if (!num_config) michael@0: { michael@0: return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); michael@0: } michael@0: michael@0: const EGLint attribList[] = {EGL_NONE}; michael@0: michael@0: if (!attrib_list) michael@0: { michael@0: attrib_list = attribList; michael@0: } michael@0: michael@0: display->getConfigs(configs, attrib_list, config_size, num_config); michael@0: michael@0: return egl::success(EGL_TRUE); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", michael@0: dpy, config, attribute, value); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: michael@0: if (!validateConfig(display, config)) michael@0: { michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: if (!display->getConfigAttrib(config, attribute, value)) michael@0: { michael@0: return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); michael@0: } michael@0: michael@0: return egl::success(EGL_TRUE); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, " michael@0: "const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: michael@0: if (!validateConfig(display, config)) michael@0: { michael@0: return EGL_NO_SURFACE; michael@0: } michael@0: michael@0: HWND window = (HWND)win; michael@0: michael@0: if (!IsWindow(window)) michael@0: { michael@0: return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); michael@0: } michael@0: michael@0: return display->createWindowSurface(window, config, attrib_list); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); michael@0: } michael@0: } michael@0: michael@0: EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)", michael@0: dpy, config, attrib_list); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: michael@0: if (!validateConfig(display, config)) michael@0: { michael@0: return EGL_NO_SURFACE; michael@0: } michael@0: michael@0: return display->createOffscreenSurface(config, NULL, attrib_list); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); michael@0: } michael@0: } michael@0: michael@0: EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = 0x%0.8p, " michael@0: "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: michael@0: if (!validateConfig(display, config)) michael@0: { michael@0: return EGL_NO_SURFACE; michael@0: } michael@0: michael@0: UNIMPLEMENTED(); // FIXME michael@0: michael@0: return egl::success(EGL_NO_SURFACE); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: egl::Surface *eglSurface = static_cast(surface); michael@0: michael@0: if (!validateSurface(display, eglSurface)) michael@0: { michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: if (surface == EGL_NO_SURFACE) michael@0: { michael@0: return egl::error(EGL_BAD_SURFACE, EGL_FALSE); michael@0: } michael@0: michael@0: display->destroySurface((egl::Surface*)surface); michael@0: michael@0: return egl::success(EGL_TRUE); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", michael@0: dpy, surface, attribute, value); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: egl::Surface *eglSurface = (egl::Surface*)surface; michael@0: michael@0: if (!validateSurface(display, eglSurface)) michael@0: { michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: if (surface == EGL_NO_SURFACE) michael@0: { michael@0: return egl::error(EGL_BAD_SURFACE, EGL_FALSE); michael@0: } michael@0: michael@0: switch (attribute) michael@0: { michael@0: case EGL_VG_ALPHA_FORMAT: michael@0: UNIMPLEMENTED(); // FIXME michael@0: break; michael@0: case EGL_VG_COLORSPACE: michael@0: UNIMPLEMENTED(); // FIXME michael@0: break; michael@0: case EGL_CONFIG_ID: michael@0: UNIMPLEMENTED(); // FIXME michael@0: break; michael@0: case EGL_HEIGHT: michael@0: *value = eglSurface->getHeight(); michael@0: break; michael@0: case EGL_HORIZONTAL_RESOLUTION: michael@0: UNIMPLEMENTED(); // FIXME michael@0: break; michael@0: case EGL_LARGEST_PBUFFER: michael@0: UNIMPLEMENTED(); // FIXME michael@0: break; michael@0: case EGL_MIPMAP_TEXTURE: michael@0: UNIMPLEMENTED(); // FIXME michael@0: break; michael@0: case EGL_MIPMAP_LEVEL: michael@0: UNIMPLEMENTED(); // FIXME michael@0: break; michael@0: case EGL_MULTISAMPLE_RESOLVE: michael@0: UNIMPLEMENTED(); // FIXME michael@0: break; michael@0: case EGL_PIXEL_ASPECT_RATIO: michael@0: UNIMPLEMENTED(); // FIXME michael@0: break; michael@0: case EGL_RENDER_BUFFER: michael@0: UNIMPLEMENTED(); // FIXME michael@0: break; michael@0: case EGL_SWAP_BEHAVIOR: michael@0: UNIMPLEMENTED(); // FIXME michael@0: break; michael@0: case EGL_TEXTURE_FORMAT: michael@0: UNIMPLEMENTED(); // FIXME michael@0: break; michael@0: case EGL_TEXTURE_TARGET: michael@0: UNIMPLEMENTED(); // FIXME michael@0: break; michael@0: case EGL_VERTICAL_RESOLUTION: michael@0: UNIMPLEMENTED(); // FIXME michael@0: break; michael@0: case EGL_WIDTH: michael@0: *value = eglSurface->getWidth(); michael@0: break; michael@0: case EGL_POST_SUB_BUFFER_SUPPORTED_NV: michael@0: *value = eglSurface->isPostSubBufferSupported(); michael@0: break; michael@0: default: michael@0: return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); michael@0: } michael@0: michael@0: return egl::success(EGL_TRUE); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value) michael@0: { michael@0: TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)", michael@0: dpy, surface, attribute, value); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: egl::Surface *eglSurface = (egl::Surface*)surface; michael@0: michael@0: if (!validateSurface(display, eglSurface)) michael@0: { michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: if (surface == EGL_NO_SURFACE) michael@0: { michael@0: return egl::error(EGL_BAD_SURFACE, EGL_FALSE); michael@0: } michael@0: michael@0: switch (attribute) michael@0: { michael@0: case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: michael@0: { michael@0: rx::SwapChain *swapchain = eglSurface->getSwapChain(); michael@0: *value = (void*) (swapchain ? swapchain->getShareHandle() : NULL); michael@0: } michael@0: break; michael@0: default: michael@0: return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); michael@0: } michael@0: michael@0: return egl::success(EGL_TRUE); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglBindAPI(EGLenum api) michael@0: { michael@0: EVENT("(EGLenum api = 0x%X)", api); michael@0: michael@0: try michael@0: { michael@0: switch (api) michael@0: { michael@0: case EGL_OPENGL_API: michael@0: case EGL_OPENVG_API: michael@0: return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation michael@0: case EGL_OPENGL_ES_API: michael@0: break; michael@0: default: michael@0: return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); michael@0: } michael@0: michael@0: egl::setCurrentAPI(api); michael@0: michael@0: return egl::success(EGL_TRUE); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLenum __stdcall eglQueryAPI(void) michael@0: { michael@0: EVENT("()"); michael@0: michael@0: try michael@0: { michael@0: EGLenum API = egl::getCurrentAPI(); michael@0: michael@0: return egl::success(API); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglWaitClient(void) michael@0: { michael@0: EVENT("()"); michael@0: michael@0: try michael@0: { michael@0: UNIMPLEMENTED(); // FIXME michael@0: michael@0: return egl::success(0); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglReleaseThread(void) michael@0: { michael@0: EVENT("()"); michael@0: michael@0: try michael@0: { michael@0: eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE); michael@0: michael@0: return egl::success(EGL_TRUE); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, " michael@0: "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)", michael@0: dpy, buftype, buffer, config, attrib_list); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: michael@0: if (!validateConfig(display, config)) michael@0: { michael@0: return EGL_NO_SURFACE; michael@0: } michael@0: michael@0: if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer) michael@0: { michael@0: return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); michael@0: } michael@0: michael@0: return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)", michael@0: dpy, surface, attribute, value); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: egl::Surface *eglSurface = static_cast(surface); michael@0: michael@0: if (!validateSurface(display, eglSurface)) michael@0: { michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: UNIMPLEMENTED(); // FIXME michael@0: michael@0: return egl::success(EGL_TRUE); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: egl::Surface *eglSurface = static_cast(surface); michael@0: michael@0: if (!validateSurface(display, eglSurface)) michael@0: { michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: if (buffer != EGL_BACK_BUFFER) michael@0: { michael@0: return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); michael@0: } michael@0: michael@0: if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) michael@0: { michael@0: return egl::error(EGL_BAD_SURFACE, EGL_FALSE); michael@0: } michael@0: michael@0: if (eglSurface->getBoundTexture()) michael@0: { michael@0: return egl::error(EGL_BAD_ACCESS, EGL_FALSE); michael@0: } michael@0: michael@0: if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) michael@0: { michael@0: return egl::error(EGL_BAD_MATCH, EGL_FALSE); michael@0: } michael@0: michael@0: if (!glBindTexImage(eglSurface)) michael@0: { michael@0: return egl::error(EGL_BAD_MATCH, EGL_FALSE); michael@0: } michael@0: michael@0: return egl::success(EGL_TRUE); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: egl::Surface *eglSurface = static_cast(surface); michael@0: michael@0: if (!validateSurface(display, eglSurface)) michael@0: { michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: if (buffer != EGL_BACK_BUFFER) michael@0: { michael@0: return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); michael@0: } michael@0: michael@0: if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) michael@0: { michael@0: return egl::error(EGL_BAD_SURFACE, EGL_FALSE); michael@0: } michael@0: michael@0: if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) michael@0: { michael@0: return egl::error(EGL_BAD_MATCH, EGL_FALSE); michael@0: } michael@0: michael@0: gl::Texture2D *texture = eglSurface->getBoundTexture(); michael@0: michael@0: if (texture) michael@0: { michael@0: texture->releaseTexImage(); michael@0: } michael@0: michael@0: return egl::success(EGL_TRUE); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: michael@0: if (!validateDisplay(display)) michael@0: { michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: egl::Surface *draw_surface = static_cast(egl::getCurrentDrawSurface()); michael@0: michael@0: if (draw_surface == NULL) michael@0: { michael@0: return egl::error(EGL_BAD_SURFACE, EGL_FALSE); michael@0: } michael@0: michael@0: draw_surface->setSwapInterval(interval); michael@0: michael@0: return egl::success(EGL_TRUE); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, " michael@0: "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list); michael@0: michael@0: try michael@0: { michael@0: // Get the requested client version (default is 1) and check it is two. michael@0: EGLint client_version = 1; michael@0: bool reset_notification = false; michael@0: bool robust_access = false; michael@0: michael@0: if (attrib_list) michael@0: { michael@0: for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2) michael@0: { michael@0: switch (attribute[0]) michael@0: { michael@0: case EGL_CONTEXT_CLIENT_VERSION: michael@0: client_version = attribute[1]; michael@0: break; michael@0: case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT: michael@0: if (attribute[1] == EGL_TRUE) michael@0: { michael@0: return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); // Unimplemented michael@0: // robust_access = true; michael@0: } michael@0: else if (attribute[1] != EGL_FALSE) michael@0: return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); michael@0: break; michael@0: case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT: michael@0: if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT) michael@0: reset_notification = true; michael@0: else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT) michael@0: return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); michael@0: break; michael@0: default: michael@0: return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); michael@0: } michael@0: } michael@0: } michael@0: michael@0: if (client_version != 2) michael@0: { michael@0: return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); michael@0: } michael@0: michael@0: if (share_context && static_cast(share_context)->isResetNotificationEnabled() != reset_notification) michael@0: { michael@0: return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); michael@0: } michael@0: michael@0: egl::Display *display = static_cast(dpy); michael@0: michael@0: if (!validateConfig(display, config)) michael@0: { michael@0: return EGL_NO_CONTEXT; michael@0: } michael@0: michael@0: EGLContext context = display->createContext(config, static_cast(share_context), reset_notification, robust_access); michael@0: michael@0: if (context) michael@0: return egl::success(context); michael@0: else michael@0: return egl::error(EGL_CONTEXT_LOST, EGL_NO_CONTEXT); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: gl::Context *context = static_cast(ctx); michael@0: michael@0: if (!validateContext(display, context)) michael@0: { michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: if (ctx == EGL_NO_CONTEXT) michael@0: { michael@0: return egl::error(EGL_BAD_CONTEXT, EGL_FALSE); michael@0: } michael@0: michael@0: display->destroyContext(context); michael@0: michael@0: return egl::success(EGL_TRUE); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)", michael@0: dpy, draw, read, ctx); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: gl::Context *context = static_cast(ctx); michael@0: michael@0: if (ctx != EGL_NO_CONTEXT && !validateContext(display, context)) michael@0: { michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: if (dpy != EGL_NO_DISPLAY) michael@0: { michael@0: rx::Renderer *renderer = display->getRenderer(); michael@0: if (renderer->testDeviceLost(true)) michael@0: { michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: if (renderer->isDeviceLost()) michael@0: { michael@0: return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast(draw))) || michael@0: (read != EGL_NO_SURFACE && !validateSurface(display, static_cast(read)))) michael@0: { michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: if (draw != read) michael@0: { michael@0: UNIMPLEMENTED(); // FIXME michael@0: } michael@0: michael@0: egl::setCurrentDisplay(dpy); michael@0: egl::setCurrentDrawSurface(draw); michael@0: egl::setCurrentReadSurface(read); michael@0: michael@0: glMakeCurrent(context, display, static_cast(draw)); michael@0: michael@0: return egl::success(EGL_TRUE); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLContext __stdcall eglGetCurrentContext(void) michael@0: { michael@0: EVENT("()"); michael@0: michael@0: try michael@0: { michael@0: EGLContext context = glGetCurrentContext(); michael@0: michael@0: return egl::success(context); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT); michael@0: } michael@0: } michael@0: michael@0: EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw) michael@0: { michael@0: EVENT("(EGLint readdraw = %d)", readdraw); michael@0: michael@0: try michael@0: { michael@0: if (readdraw == EGL_READ) michael@0: { michael@0: EGLSurface read = egl::getCurrentReadSurface(); michael@0: return egl::success(read); michael@0: } michael@0: else if (readdraw == EGL_DRAW) michael@0: { michael@0: EGLSurface draw = egl::getCurrentDrawSurface(); michael@0: return egl::success(draw); michael@0: } michael@0: else michael@0: { michael@0: return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); michael@0: } michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); michael@0: } michael@0: } michael@0: michael@0: EGLDisplay __stdcall eglGetCurrentDisplay(void) michael@0: { michael@0: EVENT("()"); michael@0: michael@0: try michael@0: { michael@0: EGLDisplay dpy = egl::getCurrentDisplay(); michael@0: michael@0: return egl::success(dpy); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_NO_DISPLAY); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", michael@0: dpy, ctx, attribute, value); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: gl::Context *context = static_cast(ctx); michael@0: michael@0: if (!validateContext(display, context)) michael@0: { michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: UNIMPLEMENTED(); // FIXME michael@0: michael@0: return egl::success(0); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglWaitGL(void) michael@0: { michael@0: EVENT("()"); michael@0: michael@0: try michael@0: { michael@0: UNIMPLEMENTED(); // FIXME michael@0: michael@0: return egl::success(0); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglWaitNative(EGLint engine) michael@0: { michael@0: EVENT("(EGLint engine = %d)", engine); michael@0: michael@0: try michael@0: { michael@0: UNIMPLEMENTED(); // FIXME michael@0: michael@0: return egl::success(0); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: egl::Surface *eglSurface = (egl::Surface*)surface; michael@0: michael@0: if (!validateSurface(display, eglSurface)) michael@0: { michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: if (display->getRenderer()->isDeviceLost()) michael@0: { michael@0: return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); michael@0: } michael@0: michael@0: if (surface == EGL_NO_SURFACE) michael@0: { michael@0: return egl::error(EGL_BAD_SURFACE, EGL_FALSE); michael@0: } michael@0: michael@0: if (eglSurface->swap()) michael@0: { michael@0: return egl::success(EGL_TRUE); michael@0: } michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target); michael@0: michael@0: try michael@0: { michael@0: egl::Display *display = static_cast(dpy); michael@0: egl::Surface *eglSurface = static_cast(surface); michael@0: michael@0: if (!validateSurface(display, eglSurface)) michael@0: { michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: if (display->getRenderer()->isDeviceLost()) michael@0: { michael@0: return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); michael@0: } michael@0: michael@0: UNIMPLEMENTED(); // FIXME michael@0: michael@0: return egl::success(0); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: } michael@0: michael@0: EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height) michael@0: { michael@0: EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, EGLint width = %d, EGLint height = %d)", dpy, surface, x, y, width, height); michael@0: michael@0: try michael@0: { michael@0: if (x < 0 || y < 0 || width < 0 || height < 0) michael@0: { michael@0: return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); michael@0: } michael@0: michael@0: egl::Display *display = static_cast(dpy); michael@0: egl::Surface *eglSurface = static_cast(surface); michael@0: michael@0: if (!validateSurface(display, eglSurface)) michael@0: { michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: if (display->getRenderer()->isDeviceLost()) michael@0: { michael@0: return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); michael@0: } michael@0: michael@0: if (surface == EGL_NO_SURFACE) michael@0: { michael@0: return egl::error(EGL_BAD_SURFACE, EGL_FALSE); michael@0: } michael@0: michael@0: if (eglSurface->postSubBuffer(x, y, width, height)) michael@0: { michael@0: return egl::success(EGL_TRUE); michael@0: } michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, EGL_FALSE); michael@0: } michael@0: michael@0: return EGL_FALSE; michael@0: } michael@0: michael@0: __eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname) michael@0: { michael@0: EVENT("(const char *procname = \"%s\")", procname); michael@0: michael@0: try michael@0: { michael@0: struct Extension michael@0: { michael@0: const char *name; michael@0: __eglMustCastToProperFunctionPointerType address; michael@0: }; michael@0: michael@0: static const Extension eglExtensions[] = michael@0: { michael@0: {"eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE}, michael@0: {"eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)eglPostSubBufferNV}, michael@0: {"", NULL}, michael@0: }; michael@0: michael@0: for (unsigned int ext = 0; ext < ArraySize(eglExtensions); ext++) michael@0: { michael@0: if (strcmp(procname, eglExtensions[ext].name) == 0) michael@0: { michael@0: return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address; michael@0: } michael@0: } michael@0: michael@0: return glGetProcAddress(procname); michael@0: } michael@0: catch(std::bad_alloc&) michael@0: { michael@0: return egl::error(EGL_BAD_ALLOC, (__eglMustCastToProperFunctionPointerType)NULL); michael@0: } michael@0: } michael@0: }