OSDN Git Service

Handle NULL 'value' to eglGetSyncAttribKHR()
[android-x86/external-swiftshader.git] / src / OpenGL / libEGL / libEGL.cpp
index 8e951c6..912fe0c 100644 (file)
-// SwiftShader Software Renderer\r
-//\r
-// Copyright(c) 2005-2012 TransGaming Inc.\r
-//\r
-// All rights reserved. No part of this software may be copied, distributed, transmitted,\r
-// transcribed, stored in a retrieval system, translated into any human or computer\r
-// language by any means, or disclosed to third parties without the explicit written\r
-// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express\r
-// or implied, including but not limited to any patent rights, are granted to you.\r
-//\r
-\r
-// libEGL.cpp: Implements the exported EGL functions.\r
-\r
-#include "main.h"\r
-#include "Display.h"\r
-#include "Surface.h"\r
-#include "Texture.hpp"\r
-#include "Context.hpp"\r
-#include "common/Image.hpp"\r
-#include "common/debug.h"\r
-#include "Common/Version.h"\r
-\r
-#if defined(__ANDROID__)\r
-#include <system/window.h>\r
-#endif\r
-\r
-#include <string.h>\r
-\r
-using namespace egl;\r
-\r
-static bool validateDisplay(egl::Display *display)\r
-{\r
-       if(display == EGL_NO_DISPLAY)\r
-       {\r
-               return error(EGL_BAD_DISPLAY, false);\r
-       }\r
-\r
-       if(!display->isInitialized())\r
-       {\r
-               return error(EGL_NOT_INITIALIZED, false);\r
-       }\r
-\r
-       return true;\r
-}\r
-\r
-static bool validateConfig(egl::Display *display, EGLConfig config)\r
-{\r
-       if(!validateDisplay(display))\r
-       {\r
-               return false;\r
-       }\r
-\r
-       if(!display->isValidConfig(config))\r
-       {\r
-               return error(EGL_BAD_CONFIG, false);\r
-       }\r
-\r
-       return true;\r
-}\r
-\r
-static bool validateContext(egl::Display *display, egl::Context *context)\r
-{\r
-       if(!validateDisplay(display))\r
-       {\r
-               return false;\r
-       }\r
-\r
-       if(!display->isValidContext(context))\r
-       {\r
-               return error(EGL_BAD_CONTEXT, false);\r
-       }\r
-\r
-       return true;\r
-}\r
-\r
-static bool validateSurface(egl::Display *display, egl::Surface *surface)\r
-{\r
-       if(!validateDisplay(display))\r
-       {\r
-               return false;\r
-       }\r
-\r
-       if(!display->isValidSurface(surface))\r
-       {\r
-               return error(EGL_BAD_SURFACE, false);\r
-       }\r
-\r
-       return true;\r
-}\r
-\r
-namespace egl\r
-{\r
-EGLint GetError(void)\r
-{\r
-       TRACE("()");\r
-\r
-       EGLint error = egl::getCurrentError();\r
-\r
-       if(error != EGL_SUCCESS)\r
-       {\r
-               egl::setCurrentError(EGL_SUCCESS);\r
-       }\r
-\r
-       return error;\r
-}\r
-\r
-EGLDisplay GetDisplay(EGLNativeDisplayType display_id)\r
-{\r
-       TRACE("(EGLNativeDisplayType display_id = %p)", display_id);\r
-\r
-       if(display_id == EGL_DEFAULT_DISPLAY)\r
-       {\r
-               return egl::Display::getPlatformDisplay(EGL_UNKNOWN, nullptr);\r
-       }\r
-       else\r
-       {\r
-               return egl::Display::getPlatformDisplay(EGL_UNKNOWN, reinterpret_cast<void*>((uintptr_t)display_id));\r
-       }\r
-}\r
-\r
-EGLBoolean Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLint *major = %p, EGLint *minor = %p)",\r
-                 dpy, major, minor);\r
-\r
-       if(dpy == EGL_NO_DISPLAY)\r
-       {\r
-               return error(EGL_BAD_DISPLAY, EGL_FALSE);\r
-       }\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-\r
-       if(!display->initialize())\r
-       {\r
-               return error(EGL_NOT_INITIALIZED, EGL_FALSE);\r
-       }\r
-\r
-       if(major) *major = 1;\r
-       if(minor) *minor = 4;\r
-\r
-       return success(EGL_TRUE);\r
-}\r
-\r
-EGLBoolean Terminate(EGLDisplay dpy)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p)", dpy);\r
-\r
-       if(dpy == EGL_NO_DISPLAY)\r
-       {\r
-               return error(EGL_BAD_DISPLAY, EGL_FALSE);\r
-       }\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-\r
-       display->terminate();\r
-\r
-       return success(EGL_TRUE);\r
-}\r
-\r
-const char *QueryString(EGLDisplay dpy, EGLint name)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLint name = %d)", dpy, name);\r
-\r
-       if(dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)\r
-       {\r
-               return success("EGL_KHR_platform_gbm "\r
-                              "EGL_KHR_platform_x11 "\r
-                              "EGL_EXT_client_extensions "\r
-                              "EGL_EXT_platform_base");\r
-       }\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-\r
-       if(!validateDisplay(display))\r
-       {\r
-               return NULL;\r
-       }\r
-\r
-       switch(name)\r
-       {\r
-       case EGL_CLIENT_APIS:\r
-               return success("OpenGL_ES");\r
-       case EGL_EXTENSIONS:\r
-               return success("EGL_KHR_gl_texture_2D_image "\r
-                              "EGL_KHR_gl_texture_cubemap_image "\r
-                              "EGL_KHR_gl_renderbuffer_image "\r
-                              "EGL_KHR_fence_sync "\r
-                              "EGL_KHR_image_base "\r
-                              "EGL_ANDROID_framebuffer_target "\r
-                              "EGL_ANDROID_recordable");\r
-       case EGL_VENDOR:\r
-               return success("TransGaming Inc.");\r
-       case EGL_VERSION:\r
-               return success("1.4 SwiftShader " VERSION_STRING);\r
-       }\r
-\r
-       return error(EGL_BAD_PARAMETER, (const char*)NULL);\r
-}\r
-\r
-EGLBoolean GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLConfig *configs = %p, "\r
-                 "EGLint config_size = %d, EGLint *num_config = %p)",\r
-                 dpy, configs, config_size, num_config);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-\r
-       if(!validateDisplay(display))\r
-       {\r
-               return EGL_FALSE;\r
-       }\r
-\r
-       if(!num_config)\r
-       {\r
-               return error(EGL_BAD_PARAMETER, EGL_FALSE);\r
-       }\r
-\r
-       const EGLint attribList[] = {EGL_NONE};\r
-\r
-       if(!display->getConfigs(configs, attribList, config_size, num_config))\r
-       {\r
-               return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);\r
-       }\r
-\r
-       return success(EGL_TRUE);\r
-}\r
-\r
-EGLBoolean ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, const EGLint *attrib_list = %p, "\r
-                 "EGLConfig *configs = %p, EGLint config_size = %d, EGLint *num_config = %p)",\r
-                 dpy, attrib_list, configs, config_size, num_config);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-\r
-       if(!validateDisplay(display))\r
-       {\r
-               return EGL_FALSE;\r
-       }\r
-\r
-       if(!num_config)\r
-       {\r
-               return error(EGL_BAD_PARAMETER, EGL_FALSE);\r
-       }\r
-\r
-       const EGLint attribList[] = {EGL_NONE};\r
-\r
-       if(!attrib_list)\r
-       {\r
-               attrib_list = attribList;\r
-       }\r
-\r
-       if(!display->getConfigs(configs, attrib_list, config_size, num_config))\r
-       {\r
-               return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);\r
-       }\r
-\r
-       return success(EGL_TRUE);\r
-}\r
-\r
-EGLBoolean GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLint attribute = %d, EGLint *value = %p)",\r
-                 dpy, config, attribute, value);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-\r
-       if(!validateConfig(display, config))\r
-       {\r
-               return EGL_FALSE;\r
-       }\r
-\r
-       if(!display->getConfigAttrib(config, attribute, value))\r
-       {\r
-               return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);\r
-       }\r
-\r
-       return success(EGL_TRUE);\r
-}\r
-\r
-EGLSurface CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType window, const EGLint *attrib_list)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativeWindowType win = %p, "\r
-                 "const EGLint *attrib_list = %p)", dpy, config, window, attrib_list);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-\r
-       if(!validateConfig(display, config))\r
-       {\r
-               return EGL_NO_SURFACE;\r
-       }\r
-\r
-       if(!display->isValidWindow(window))\r
-       {\r
-               return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);\r
-       }\r
-\r
-       return display->createWindowSurface(window, config, attrib_list);\r
-}\r
-\r
-EGLSurface CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, const EGLint *attrib_list = %p)",\r
-                 dpy, config, attrib_list);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-\r
-       if(!validateConfig(display, config))\r
-       {\r
-               return EGL_NO_SURFACE;\r
-       }\r
-\r
-       return display->createPBufferSurface(config, attrib_list);\r
-}\r
-\r
-EGLSurface CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativePixmapType pixmap = %p, "\r
-                 "const EGLint *attrib_list = %p)", dpy, config, pixmap, attrib_list);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-\r
-       if(!validateConfig(display, config))\r
-       {\r
-               return EGL_NO_SURFACE;\r
-       }\r
-\r
-       UNIMPLEMENTED();   // FIXME\r
-\r
-       return success(EGL_NO_SURFACE);\r
-}\r
-\r
-EGLBoolean DestroySurface(EGLDisplay dpy, EGLSurface surface)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-       egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);\r
-\r
-       if(!validateSurface(display, eglSurface))\r
-       {\r
-               return EGL_FALSE;\r
-       }\r
-\r
-       if(surface == EGL_NO_SURFACE)\r
-       {\r
-               return error(EGL_BAD_SURFACE, EGL_FALSE);\r
-       }\r
-\r
-       display->destroySurface((egl::Surface*)surface);\r
-\r
-       return success(EGL_TRUE);\r
-}\r
-\r
-EGLBoolean QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint *value = %p)",\r
-                 dpy, surface, attribute, value);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-       egl::Surface *eglSurface = (egl::Surface*)surface;\r
-\r
-       if(!validateSurface(display, eglSurface))\r
-       {\r
-               return EGL_FALSE;\r
-       }\r
-\r
-       if(surface == EGL_NO_SURFACE)\r
-       {\r
-               return error(EGL_BAD_SURFACE, EGL_FALSE);\r
-       }\r
-\r
-       switch(attribute)\r
-       {\r
-       case EGL_VG_ALPHA_FORMAT:\r
-               UNIMPLEMENTED();   // FIXME\r
-               break;\r
-       case EGL_VG_COLORSPACE:\r
-               UNIMPLEMENTED();   // FIXME\r
-               break;\r
-       case EGL_CONFIG_ID:\r
-               *value = eglSurface->getConfigID();\r
-               break;\r
-       case EGL_HEIGHT:\r
-               *value = eglSurface->getHeight();\r
-               break;\r
-       case EGL_HORIZONTAL_RESOLUTION:\r
-               UNIMPLEMENTED();   // FIXME\r
-               break;\r
-       case EGL_LARGEST_PBUFFER:\r
-               if(eglSurface->isPBufferSurface())   // For a window or pixmap surface, the contents of *value are not modified.\r
-               {\r
-                       *value = eglSurface->getLargestPBuffer();\r
-               }\r
-               break;\r
-       case EGL_MIPMAP_TEXTURE:\r
-               UNIMPLEMENTED();   // FIXME\r
-               break;\r
-       case EGL_MIPMAP_LEVEL:\r
-               UNIMPLEMENTED();   // FIXME\r
-               break;\r
-       case EGL_MULTISAMPLE_RESOLVE:\r
-               UNIMPLEMENTED();   // FIXME\r
-               break;\r
-       case EGL_PIXEL_ASPECT_RATIO:\r
-               *value = eglSurface->getPixelAspectRatio();\r
-               break;\r
-       case EGL_RENDER_BUFFER:\r
-               *value = eglSurface->getRenderBuffer();\r
-               break;\r
-       case EGL_SWAP_BEHAVIOR:\r
-               *value = eglSurface->getSwapBehavior();\r
-               break;\r
-       case EGL_TEXTURE_FORMAT:\r
-               *value = eglSurface->getTextureFormat();\r
-               break;\r
-       case EGL_TEXTURE_TARGET:\r
-               *value = eglSurface->getTextureTarget();\r
-               break;\r
-       case EGL_VERTICAL_RESOLUTION:\r
-               UNIMPLEMENTED();   // FIXME\r
-               break;\r
-       case EGL_WIDTH:\r
-               *value = eglSurface->getWidth();\r
-               break;\r
-       default:\r
-               return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);\r
-       }\r
-\r
-       return success(EGL_TRUE);\r
-}\r
-\r
-EGLBoolean BindAPI(EGLenum api)\r
-{\r
-       TRACE("(EGLenum api = 0x%X)", api);\r
-\r
-       switch(api)\r
-       {\r
-       case EGL_OPENGL_API:\r
-       case EGL_OPENVG_API:\r
-               return error(EGL_BAD_PARAMETER, EGL_FALSE);   // Not supported by this implementation\r
-       case EGL_OPENGL_ES_API:\r
-               break;\r
-       default:\r
-               return error(EGL_BAD_PARAMETER, EGL_FALSE);\r
-       }\r
-\r
-       egl::setCurrentAPI(api);\r
-\r
-       return success(EGL_TRUE);\r
-}\r
-\r
-EGLenum QueryAPI(void)\r
-{\r
-       TRACE("()");\r
-\r
-       EGLenum API = egl::getCurrentAPI();\r
-\r
-       return success(API);\r
-}\r
-\r
-EGLBoolean WaitClient(void)\r
-{\r
-       TRACE("()");\r
-\r
-       UNIMPLEMENTED();   // FIXME\r
-\r
-       return success(EGL_FALSE);\r
-}\r
-\r
-EGLBoolean ReleaseThread(void)\r
-{\r
-       TRACE("()");\r
-\r
-       eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);\r
-\r
-       return success(EGL_TRUE);\r
-}\r
-\r
-EGLSurface CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = %p, "\r
-                 "EGLConfig config = %p, const EGLint *attrib_list = %p)",\r
-                 dpy, buftype, buffer, config, attrib_list);\r
-\r
-       UNIMPLEMENTED();\r
-\r
-       return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);\r
-}\r
-\r
-EGLBoolean SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint value = %d)",\r
-                 dpy, surface, attribute, value);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-       egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);\r
-\r
-       if(!validateSurface(display, eglSurface))\r
-       {\r
-               return EGL_FALSE;\r
-       }\r
-\r
-       switch(attribute)\r
-       {\r
-       case EGL_SWAP_BEHAVIOR:\r
-               if(value == EGL_BUFFER_PRESERVED)\r
-               {\r
-                       if(!(eglSurface->getSurfaceType() & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))\r
-                       {\r
-                               return error(EGL_BAD_MATCH, EGL_FALSE);\r
-                       }\r
-               }\r
-               else if(value != EGL_BUFFER_DESTROYED)\r
-               {\r
-                       return error(EGL_BAD_PARAMETER, EGL_FALSE);\r
-               }\r
-               eglSurface->setSwapBehavior(value);\r
-               break;\r
-       default:\r
-               UNIMPLEMENTED();   // FIXME\r
-       }\r
-\r
-       return success(EGL_TRUE);\r
-}\r
-\r
-EGLBoolean BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-       egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);\r
-\r
-       if(!validateSurface(display, eglSurface))\r
-       {\r
-               return EGL_FALSE;\r
-       }\r
-\r
-       if(buffer != EGL_BACK_BUFFER)\r
-       {\r
-               return error(EGL_BAD_PARAMETER, EGL_FALSE);\r
-       }\r
-\r
-       if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface())\r
-       {\r
-               return error(EGL_BAD_SURFACE, EGL_FALSE);\r
-       }\r
-\r
-       if(eglSurface->getBoundTexture())\r
-       {\r
-               return error(EGL_BAD_ACCESS, EGL_FALSE);\r
-       }\r
-\r
-       if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)\r
-       {\r
-               return error(EGL_BAD_MATCH, EGL_FALSE);\r
-       }\r
-\r
-       egl::Context *context = static_cast<egl::Context*>(egl::getCurrentContext());\r
-\r
-       if(context)\r
-       {\r
-               context->bindTexImage(eglSurface);\r
-       }\r
-\r
-       return success(EGL_TRUE);\r
-}\r
-\r
-EGLBoolean ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-       egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);\r
-\r
-       if(!validateSurface(display, eglSurface))\r
-       {\r
-               return EGL_FALSE;\r
-       }\r
-\r
-       if(buffer != EGL_BACK_BUFFER)\r
-       {\r
-               return error(EGL_BAD_PARAMETER, EGL_FALSE);\r
-       }\r
-\r
-       if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface())\r
-       {\r
-               return error(EGL_BAD_SURFACE, EGL_FALSE);\r
-       }\r
-\r
-       if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)\r
-       {\r
-               return error(EGL_BAD_MATCH, EGL_FALSE);\r
-       }\r
-\r
-       egl::Texture *texture = eglSurface->getBoundTexture();\r
-\r
-       if(texture)\r
-       {\r
-               texture->releaseTexImage();\r
-       }\r
-\r
-       return success(EGL_TRUE);\r
-}\r
-\r
-EGLBoolean SwapInterval(EGLDisplay dpy, EGLint interval)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLint interval = %d)", dpy, interval);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-\r
-       if(!validateDisplay(display))\r
-       {\r
-               return EGL_FALSE;\r
-       }\r
-\r
-       egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());\r
-\r
-       if(draw_surface == NULL)\r
-       {\r
-               return error(EGL_BAD_SURFACE, EGL_FALSE);\r
-       }\r
-\r
-       draw_surface->setSwapInterval(interval);\r
-\r
-       return success(EGL_TRUE);\r
-}\r
-\r
-EGLContext CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLContext share_context = %p, "\r
-                 "const EGLint *attrib_list = %p)", dpy, config, share_context, attrib_list);\r
-\r
-       EGLint clientVersion = 1;\r
-       if(attrib_list)\r
-       {\r
-               for(const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)\r
-               {\r
-                       if(attribute[0] == EGL_CONTEXT_CLIENT_VERSION)\r
-                       {\r
-                               clientVersion = attribute[1];\r
-                       }\r
-                       else\r
-                       {\r
-                               return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);\r
-                       }\r
-               }\r
-       }\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-       egl::Context *shareContext = static_cast<egl::Context*>(share_context);\r
-\r
-       if(!validateConfig(display, config))\r
-       {\r
-               return EGL_NO_CONTEXT;\r
-       }\r
-\r
-       if(shareContext && shareContext->getClientVersion() != clientVersion)\r
-       {\r
-               return error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);\r
-       }\r
-\r
-       return display->createContext(config, shareContext, clientVersion);\r
-}\r
-\r
-EGLBoolean DestroyContext(EGLDisplay dpy, EGLContext ctx)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p)", dpy, ctx);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-       egl::Context *context = static_cast<egl::Context*>(ctx);\r
-\r
-       if(!validateContext(display, context))\r
-       {\r
-               return EGL_FALSE;\r
-       }\r
-\r
-       if(ctx == EGL_NO_CONTEXT)\r
-       {\r
-               return error(EGL_BAD_CONTEXT, EGL_FALSE);\r
-       }\r
-\r
-       display->destroyContext(context);\r
-\r
-       return success(EGL_TRUE);\r
-}\r
-\r
-EGLBoolean MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLSurface draw = %p, EGLSurface read = %p, EGLContext ctx = %p)",\r
-                 dpy, draw, read, ctx);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-       egl::Context *context = static_cast<egl::Context*>(ctx);\r
-       egl::Surface *drawSurface = static_cast<egl::Surface*>(draw);\r
-       egl::Surface *readSurface = static_cast<egl::Surface*>(read);\r
-\r
-       if(ctx != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE)\r
-       {\r
-               if(!validateDisplay(display))\r
-               {\r
-                       return EGL_FALSE;\r
-               }\r
-       }\r
-\r
-       if(ctx == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))\r
-       {\r
-               return error(EGL_BAD_MATCH, EGL_FALSE);\r
-       }\r
-\r
-       if(ctx != EGL_NO_CONTEXT && !validateContext(display, context))\r
-       {\r
-               return EGL_FALSE;\r
-       }\r
-\r
-       if((draw != EGL_NO_SURFACE && !validateSurface(display, drawSurface)) ||\r
-          (read != EGL_NO_SURFACE && !validateSurface(display, readSurface)))\r
-       {\r
-               return EGL_FALSE;\r
-       }\r
-\r
-       if((draw != EGL_NO_SURFACE) ^ (read != EGL_NO_SURFACE))\r
-       {\r
-               return error(EGL_BAD_MATCH, EGL_FALSE);\r
-       }\r
-\r
-       if(draw != read)\r
-       {\r
-               UNIMPLEMENTED();   // FIXME\r
-       }\r
-\r
-       egl::setCurrentDisplay(display);\r
-       egl::setCurrentDrawSurface(drawSurface);\r
-       egl::setCurrentReadSurface(readSurface);\r
-       egl::setCurrentContext(context);\r
-\r
-       if(context)\r
-       {\r
-               context->makeCurrent(drawSurface);\r
-       }\r
-\r
-       return success(EGL_TRUE);\r
-}\r
-\r
-EGLContext GetCurrentContext(void)\r
-{\r
-       TRACE("()");\r
-\r
-       EGLContext context = egl::getCurrentContext();\r
-\r
-       return success(context);\r
-}\r
-\r
-EGLSurface GetCurrentSurface(EGLint readdraw)\r
-{\r
-       TRACE("(EGLint readdraw = %d)", readdraw);\r
-\r
-       if(readdraw == EGL_READ)\r
-       {\r
-               EGLSurface read = egl::getCurrentReadSurface();\r
-               return success(read);\r
-       }\r
-       else if(readdraw == EGL_DRAW)\r
-       {\r
-               EGLSurface draw = egl::getCurrentDrawSurface();\r
-               return success(draw);\r
-       }\r
-       else\r
-       {\r
-               return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);\r
-       }\r
-}\r
-\r
-EGLDisplay GetCurrentDisplay(void)\r
-{\r
-       TRACE("()");\r
-\r
-       EGLDisplay dpy = egl::getCurrentDisplay();\r
-\r
-       return success(dpy);\r
-}\r
-\r
-EGLBoolean QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLint attribute = %d, EGLint *value = %p)",\r
-                 dpy, ctx, attribute, value);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-       egl::Context *context = static_cast<egl::Context*>(ctx);\r
-\r
-       if(!validateContext(display, context))\r
-       {\r
-               return EGL_FALSE;\r
-       }\r
-\r
-       UNIMPLEMENTED();   // FIXME\r
-\r
-       return success(0);\r
-}\r
-\r
-EGLBoolean WaitGL(void)\r
-{\r
-       TRACE("()");\r
-\r
-       UNIMPLEMENTED();   // FIXME\r
-\r
-       return success(EGL_FALSE);\r
-}\r
-\r
-EGLBoolean WaitNative(EGLint engine)\r
-{\r
-       TRACE("(EGLint engine = %d)", engine);\r
-\r
-       UNIMPLEMENTED();   // FIXME\r
-\r
-       return success(EGL_FALSE);\r
-}\r
-\r
-EGLBoolean SwapBuffers(EGLDisplay dpy, EGLSurface surface)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-       egl::Surface *eglSurface = (egl::Surface*)surface;\r
-\r
-       if(!validateSurface(display, eglSurface))\r
-       {\r
-               return EGL_FALSE;\r
-       }\r
-\r
-       if(surface == EGL_NO_SURFACE)\r
-       {\r
-               return error(EGL_BAD_SURFACE, EGL_FALSE);\r
-       }\r
-\r
-       eglSurface->swap();\r
-\r
-       return success(EGL_TRUE);\r
-}\r
-\r
-EGLBoolean CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLNativePixmapType target = %p)", dpy, surface, target);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-       egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);\r
-\r
-       if(!validateSurface(display, eglSurface))\r
-       {\r
-               return EGL_FALSE;\r
-       }\r
-\r
-       UNIMPLEMENTED();   // FIXME\r
-\r
-       return success(EGL_FALSE);\r
-}\r
-\r
-EGLImageKHR CreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLenum target = 0x%X, buffer = %p, const EGLint attrib_list = %p)", dpy, ctx, target, buffer, attrib_list);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-       egl::Context *context = static_cast<egl::Context*>(ctx);\r
-\r
-       if(!validateDisplay(display))\r
-       {\r
-               return error(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);\r
-       }\r
-\r
-       if(context != EGL_NO_CONTEXT && !display->isValidContext(context))\r
-       {\r
-               return error(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);\r
-       }\r
-\r
-       EGLenum imagePreserved = EGL_FALSE;\r
-       GLuint textureLevel = 0;\r
-       if(attrib_list)\r
-       {\r
-               for(const EGLint *attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)\r
-               {\r
-                       if(attribute[0] == EGL_IMAGE_PRESERVED_KHR)\r
-                       {\r
-                               imagePreserved = attribute[1];\r
-                       }\r
-                       else if(attribute[0] == EGL_GL_TEXTURE_LEVEL_KHR)\r
-                       {\r
-                               textureLevel = attribute[1];\r
-                       }\r
-                       else\r
-                       {\r
-                               return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR);\r
-                       }\r
-               }\r
-       }\r
-\r
-       #if defined(__ANDROID__)\r
-               if(target == EGL_NATIVE_BUFFER_ANDROID)\r
-               {\r
-                       ANativeWindowBuffer *nativeBuffer = reinterpret_cast<ANativeWindowBuffer*>(buffer);\r
-\r
-                       if(!nativeBuffer || GLPixelFormatFromAndroid(nativeBuffer->format) == GL_NONE)\r
-                       {\r
-                               ALOGW("%s badness unsupported HAL format=%x", __FUNCTION__, nativeBuffer ? nativeBuffer->format : 0);\r
-                               return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR);\r
-                       }\r
-\r
-                       return success(new AndroidNativeImage(nativeBuffer));\r
-               }\r
-       #endif\r
-\r
-       GLuint name = reinterpret_cast<intptr_t>(buffer);\r
-\r
-       if(name == 0)\r
-       {\r
-               return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);\r
-       }\r
-\r
-       EGLenum validationResult = context->validateSharedImage(target, name, textureLevel);\r
-\r
-       if(validationResult != EGL_SUCCESS)\r
-       {\r
-               return error(validationResult, EGL_NO_IMAGE_KHR);\r
-       }\r
-\r
-       egl::Image *image = context->createSharedImage(target, name, textureLevel);\r
-\r
-       if(!image)\r
-       {\r
-               return error(EGL_BAD_MATCH, EGL_NO_IMAGE_KHR);\r
-       }\r
-\r
-       if(image->getDepth() > 1)\r
-       {\r
-               return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);\r
-       }\r
-\r
-       return success((EGLImageKHR)image);\r
-}\r
-\r
-EGLBoolean DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLImageKHR image = %p)", dpy, image);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-\r
-       if(!validateDisplay(display))\r
-       {\r
-               return error(EGL_BAD_DISPLAY, EGL_FALSE);\r
-       }\r
-\r
-       if(!image)\r
-       {\r
-               return error(EGL_BAD_PARAMETER, EGL_FALSE);\r
-       }\r
-\r
-       egl::Image *glImage = static_cast<egl::Image*>(image);\r
-       glImage->destroyShared();\r
-\r
-       return success(EGL_TRUE);\r
-}\r
-\r
-EGLDisplay GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)\r
-{\r
-       TRACE("(EGLenum platform = 0x%X, void *native_display = %p, const EGLint *attrib_list = %p)", platform, native_display, attrib_list);\r
-\r
-       return egl::Display::getPlatformDisplay(platform, native_display);\r
-}\r
-\r
-EGLSurface CreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list)\r
-{\r
-       return CreateWindowSurface(dpy, config, (EGLNativeWindowType)native_window, attrib_list);\r
-}\r
-\r
-EGLSurface CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list)\r
-{\r
-       return CreatePixmapSurface(dpy, config, (EGLNativePixmapType)native_pixmap, attrib_list);\r
-}\r
-\r
-class FenceSync\r
-{\r
-public:\r
-       explicit FenceSync(Context *context) : context(context)\r
-       {\r
-               status = EGL_UNSIGNALED_KHR;\r
-               context->addRef();\r
-       }\r
-\r
-       ~FenceSync()\r
-       {\r
-               context->release();\r
-               context = nullptr;\r
-       }\r
-\r
-       void wait() { context->finish(); signal(); }\r
-       void signal() { status = EGL_SIGNALED_KHR; }\r
-       bool isSignaled() const { return status == EGL_SIGNALED_KHR; }\r
-\r
-private:\r
-       EGLint status;\r
-       Context *context;\r
-};\r
-\r
-EGLSyncKHR CreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLunum type = %x, EGLint *attrib_list=%p)", dpy, type, attrib_list);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-\r
-       if(!validateDisplay(display))\r
-       {\r
-               return error(EGL_BAD_DISPLAY, EGL_NO_SYNC_KHR);\r
-       }\r
-\r
-       if(type != EGL_SYNC_FENCE_KHR)\r
-       {\r
-               return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);\r
-       }\r
-\r
-       if(attrib_list && attrib_list[0] != EGL_NONE)\r
-       {\r
-               return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);\r
-       }\r
-\r
-       egl::Context *context = static_cast<egl::Context*>(egl::getCurrentContext());\r
-\r
-       if(!validateContext(display, context))\r
-       {\r
-               return error(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);\r
-       }\r
-\r
-       return success(new FenceSync(context));\r
-}\r
-\r
-EGLBoolean DestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p)", dpy, sync);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-       FenceSync *eglSync = static_cast<FenceSync*>(sync);\r
-\r
-       if(!validateDisplay(display))\r
-       {\r
-               return error(EGL_BAD_DISPLAY, EGL_FALSE);\r
-       }\r
-\r
-       delete eglSync;\r
-\r
-       return success(EGL_TRUE);\r
-}\r
-\r
-EGLint ClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint flags = %x, EGLTimeKHR value = %llx)", dpy, sync, flags, timeout);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-       FenceSync *eglSync = static_cast<FenceSync*>(sync);\r
-\r
-       if(!validateDisplay(display))\r
-       {\r
-               return error(EGL_BAD_DISPLAY, EGL_FALSE);\r
-       }\r
-\r
-       (void)flags;\r
-       (void)timeout;\r
-\r
-       if(!eglSync->isSignaled())\r
-       {\r
-               eglSync->wait();\r
-       }\r
-\r
-       return success(EGL_CONDITION_SATISFIED_KHR);\r
-}\r
-\r
-EGLBoolean GetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)\r
-{\r
-       TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint attribute = %x, EGLint *value = %p)", dpy, sync, attribute, value);\r
-\r
-       egl::Display *display = static_cast<egl::Display*>(dpy);\r
-\r
-       if(!validateDisplay(display))\r
-       {\r
-               return error(EGL_BAD_DISPLAY, EGL_FALSE);\r
-       }\r
-\r
-       FenceSync *eglSync = static_cast<FenceSync*>(sync);\r
-\r
-       switch(attribute)\r
-       {\r
-       case EGL_SYNC_TYPE_KHR:\r
-               *value = EGL_SYNC_FENCE_KHR;\r
-               return success(EGL_TRUE);\r
-       case EGL_SYNC_STATUS_KHR:\r
-               eglSync->wait();   // TODO: Don't block. Just poll based on sw::Query.\r
-               *value = eglSync->isSignaled() ? EGL_SIGNALED_KHR : EGL_UNSIGNALED_KHR;\r
-               return success(EGL_TRUE);\r
-       case EGL_SYNC_CONDITION_KHR:\r
-               *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;\r
-               return success(EGL_TRUE);\r
-       default:\r
-               return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);\r
-       }\r
-}\r
-\r
-__eglMustCastToProperFunctionPointerType GetProcAddress(const char *procname)\r
-{\r
-       TRACE("(const char *procname = \"%s\")", procname);\r
-\r
-       struct Extension\r
-       {\r
-               const char *name;\r
-               __eglMustCastToProperFunctionPointerType address;\r
-       };\r
-\r
-       static const Extension eglExtensions[] =\r
-       {\r
-               #define EXTENSION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}\r
-\r
-               EXTENSION(eglCreateImageKHR),\r
-               EXTENSION(eglDestroyImageKHR),\r
-               EXTENSION(eglGetPlatformDisplayEXT),\r
-               EXTENSION(eglCreatePlatformWindowSurfaceEXT),\r
-               EXTENSION(eglCreatePlatformPixmapSurfaceEXT),\r
-               EXTENSION(eglCreateSyncKHR),\r
-               EXTENSION(eglDestroySyncKHR),\r
-               EXTENSION(eglClientWaitSyncKHR),\r
-               EXTENSION(eglGetSyncAttribKHR),\r
-\r
-               #undef EXTENSION\r
-       };\r
-\r
-       for(int ext = 0; ext < sizeof(eglExtensions) / sizeof(Extension); ext++)\r
-       {\r
-               if(strcmp(procname, eglExtensions[ext].name) == 0)\r
-               {\r
-                       return success((__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address);\r
-               }\r
-       }\r
-\r
-       if(libGLESv2)\r
-       {\r
-               __eglMustCastToProperFunctionPointerType proc = libGLESv2->es2GetProcAddress(procname);\r
-               if(proc) return success(proc);\r
-       }\r
-\r
-       if(libGLES_CM)\r
-       {\r
-               __eglMustCastToProperFunctionPointerType proc =  libGLES_CM->es1GetProcAddress(procname);\r
-               if(proc) return success(proc);\r
-       }\r
-\r
-       return success((__eglMustCastToProperFunctionPointerType)NULL);\r
-}\r
-}\r
+// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// libEGL.cpp: Implements the exported EGL functions.
+
+#include "main.h"
+#include "Display.h"
+#include "Surface.hpp"
+#include "Texture.hpp"
+#include "Context.hpp"
+#include "common/Image.hpp"
+#include "common/debug.h"
+#include "Common/Version.h"
+
+#if defined(__ANDROID__)
+#include <system/window.h>
+#elif defined(USE_X11)
+#include "Main/libX11.hpp"
+#endif
+
+#include <algorithm>
+#include <vector>
+#include <string.h>
+
+namespace egl
+{
+namespace
+{
+bool validateDisplay(egl::Display *display)
+{
+       if(display == EGL_NO_DISPLAY)
+       {
+               return error(EGL_BAD_DISPLAY, false);
+       }
+
+       if(!display->isInitialized())
+       {
+               return error(EGL_NOT_INITIALIZED, false);
+       }
+
+       return true;
+}
+
+bool validateConfig(egl::Display *display, EGLConfig config)
+{
+       if(!validateDisplay(display))
+       {
+               return false;
+       }
+
+       if(!display->isValidConfig(config))
+       {
+               return error(EGL_BAD_CONFIG, false);
+       }
+
+       return true;
+}
+
+bool validateContext(egl::Display *display, egl::Context *context)
+{
+       if(!validateDisplay(display))
+       {
+               return false;
+       }
+
+       if(!display->isValidContext(context))
+       {
+               return error(EGL_BAD_CONTEXT, false);
+       }
+
+       return true;
+}
+
+bool validateSurface(egl::Display *display, egl::Surface *surface)
+{
+       if(!validateDisplay(display))
+       {
+               return false;
+       }
+
+       if(!display->isValidSurface(surface))
+       {
+               return error(EGL_BAD_SURFACE, false);
+       }
+
+       return true;
+}
+
+// Class to facilitate conversion from EGLint to EGLAttrib lists.
+class EGLAttribs
+{
+public:
+       explicit EGLAttribs(const EGLint *attrib_list)
+       {
+               if(attrib_list)
+               {
+                       while(*attrib_list != EGL_NONE)
+                       {
+                               attrib.push_back(static_cast<EGLAttrib>(*attrib_list));
+                               attrib_list++;
+                       }
+               }
+
+               attrib.push_back(EGL_NONE);
+       }
+
+       const EGLAttrib *operator&() const
+       {
+               return &attrib[0];
+       }
+
+private:
+       std::vector<EGLAttrib> attrib;
+};
+}
+
+EGLint GetError(void)
+{
+       TRACE("()");
+
+       EGLint error = egl::getCurrentError();
+
+       if(error != EGL_SUCCESS)
+       {
+               egl::setCurrentError(EGL_SUCCESS);
+       }
+
+       return error;
+}
+
+EGLDisplay GetDisplay(EGLNativeDisplayType display_id)
+{
+       TRACE("(EGLNativeDisplayType display_id = %p)", display_id);
+
+       if(display_id != EGL_DEFAULT_DISPLAY)
+       {
+               // FIXME: Check if display_id is the default display
+       }
+
+       #if defined(__linux__) && !defined(__ANDROID__)
+               #if defined(USE_X11)
+               if(!libX11)
+               #endif  // Non X11 linux is headless only
+               {
+                       return success(HEADLESS_DISPLAY);
+               }
+       #endif
+
+       return success(PRIMARY_DISPLAY);   // We only support the default display
+}
+
+EGLBoolean Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLint *major = %p, EGLint *minor = %p)",
+                 dpy, major, minor);
+
+       egl::Display *display = egl::Display::get(dpy);
+
+       if(!display)
+       {
+               return error(EGL_BAD_DISPLAY, EGL_FALSE);
+       }
+
+       if(!display->initialize())
+       {
+               return error(EGL_NOT_INITIALIZED, EGL_FALSE);
+       }
+
+       if(major) *major = 1;
+       if(minor) *minor = 4;
+
+       return success(EGL_TRUE);
+}
+
+EGLBoolean Terminate(EGLDisplay dpy)
+{
+       TRACE("(EGLDisplay dpy = %p)", dpy);
+
+       if(dpy == EGL_NO_DISPLAY)
+       {
+               return error(EGL_BAD_DISPLAY, EGL_FALSE);
+       }
+
+       egl::Display *display = egl::Display::get(dpy);
+
+       display->terminate();
+
+       return success(EGL_TRUE);
+}
+
+const char *QueryString(EGLDisplay dpy, EGLint name)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLint name = %d)", dpy, name);
+
+       if(dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)
+       {
+               return success(
+                       "EGL_KHR_client_get_all_proc_addresses "
+#if defined(__linux__) && !defined(__ANDROID__)
+                       "EGL_KHR_platform_gbm "
+#endif
+#if defined(USE_X11)
+                       "EGL_KHR_platform_x11 "
+#endif
+                       "EGL_EXT_client_extensions "
+                       "EGL_EXT_platform_base");
+       }
+
+       egl::Display *display = egl::Display::get(dpy);
+
+       if(!validateDisplay(display))
+       {
+               return nullptr;
+       }
+
+       switch(name)
+       {
+       case EGL_CLIENT_APIS:
+               return success("OpenGL_ES");
+       case EGL_EXTENSIONS:
+               return success("EGL_KHR_create_context "
+                              "EGL_KHR_get_all_proc_addresses "
+                              "EGL_KHR_gl_texture_2D_image "
+                              "EGL_KHR_gl_texture_cubemap_image "
+                              "EGL_KHR_gl_renderbuffer_image "
+                              "EGL_KHR_fence_sync "
+                              "EGL_KHR_image_base "
+                              "EGL_KHR_surfaceless_context "
+                              "EGL_ANGLE_iosurface_client_buffer "
+                              "EGL_ANDROID_framebuffer_target "
+                              "EGL_ANDROID_recordable");
+       case EGL_VENDOR:
+               return success("Google Inc.");
+       case EGL_VERSION:
+               return success("1.4 SwiftShader " VERSION_STRING);
+       }
+
+       return error(EGL_BAD_PARAMETER, (const char*)nullptr);
+}
+
+EGLBoolean GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLConfig *configs = %p, "
+             "EGLint config_size = %d, EGLint *num_config = %p)",
+             dpy, configs, config_size, num_config);
+
+       egl::Display *display = egl::Display::get(dpy);
+
+       if(!validateDisplay(display))
+       {
+               return EGL_FALSE;
+       }
+
+       if(!num_config)
+       {
+               return error(EGL_BAD_PARAMETER, EGL_FALSE);
+       }
+
+       const EGLint attribList[] = {EGL_NONE};
+
+       if(!display->getConfigs(configs, attribList, config_size, num_config))
+       {
+               return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+       }
+
+       return success(EGL_TRUE);
+}
+
+EGLBoolean ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+{
+       TRACE("(EGLDisplay dpy = %p, const EGLint *attrib_list = %p, "
+             "EGLConfig *configs = %p, EGLint config_size = %d, EGLint *num_config = %p)",
+             dpy, attrib_list, configs, config_size, num_config);
+
+       egl::Display *display = egl::Display::get(dpy);
+
+       if(!validateDisplay(display))
+       {
+               return EGL_FALSE;
+       }
+
+       if(!num_config)
+       {
+               return error(EGL_BAD_PARAMETER, EGL_FALSE);
+       }
+
+       const EGLint attribList[] = {EGL_NONE};
+
+       if(!attrib_list)
+       {
+               attrib_list = attribList;
+       }
+
+       if(!display->getConfigs(configs, attrib_list, config_size, num_config))
+       {
+               return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+       }
+
+       return success(EGL_TRUE);
+}
+
+EGLBoolean GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLint attribute = %d, EGLint *value = %p)",
+             dpy, config, attribute, value);
+
+       egl::Display *display = egl::Display::get(dpy);
+
+       if(!validateConfig(display, config))
+       {
+               return EGL_FALSE;
+       }
+
+       if(!display->getConfigAttrib(config, attribute, value))
+       {
+               return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+       }
+
+       return success(EGL_TRUE);
+}
+
+EGLSurface CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, void *native_window = %p, "
+             "const EGLint *attrib_list = %p)", dpy, config, native_window, attrib_list);
+
+       egl::Display *display = egl::Display::get(dpy);
+
+       if(!validateConfig(display, config))
+       {
+               return EGL_NO_SURFACE;
+       }
+
+       if(!display->isValidWindow((EGLNativeWindowType)native_window))
+       {
+               return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+       }
+
+       return display->createWindowSurface((EGLNativeWindowType)native_window, config, attrib_list);
+}
+
+EGLSurface CreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, void *native_window = %p, "
+             "const EGLint *attrib_list = %p)", dpy, config, native_window, attrib_list);
+
+       EGLAttribs attribs(attrib_list);
+       return CreatePlatformWindowSurface(dpy, config, native_window, &attribs);
+}
+
+EGLSurface CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType window, const EGLint *attrib_list)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativeWindowType window = %p, "
+             "const EGLint *attrib_list = %p)", dpy, config, window, attrib_list);
+
+       EGLAttribs attribs(attrib_list);
+       return CreatePlatformWindowSurface(dpy, config, (void*)window, &attribs);
+}
+
+EGLSurface CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, const EGLint *attrib_list = %p)",
+             dpy, config, attrib_list);
+
+       egl::Display *display = egl::Display::get(dpy);
+
+       if(!validateConfig(display, config))
+       {
+               return EGL_NO_SURFACE;
+       }
+
+       return display->createPBufferSurface(config, attrib_list);
+}
+
+EGLSurface CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, void *native_pixmap = %p, "
+             "const EGLint *attrib_list = %p)", dpy, config, native_pixmap, attrib_list);
+
+       egl::Display *display = egl::Display::get(dpy);
+
+       if(!validateConfig(display, config))
+       {
+               return EGL_NO_SURFACE;
+       }
+
+       UNIMPLEMENTED();   // FIXME
+
+       return success(EGL_NO_SURFACE);
+}
+
+EGLSurface CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, void *native_pixmap = %p, "
+             "const EGLint *attrib_list = %p)", dpy, config, native_pixmap, attrib_list);
+
+       EGLAttribs attribs(attrib_list);
+       return CreatePlatformPixmapSurface(dpy, config, native_pixmap, &attribs);
+}
+
+EGLSurface CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativePixmapType pixmap = %p, "
+             "const EGLint *attrib_list = %p)", dpy, config, pixmap, attrib_list);
+
+       EGLAttribs attribs(attrib_list);
+       return CreatePlatformPixmapSurface(dpy, config, (void*)pixmap, &attribs);
+}
+
+EGLBoolean DestroySurface(EGLDisplay dpy, EGLSurface surface)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface);
+
+       egl::Display *display = egl::Display::get(dpy);
+       egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
+
+       if(!validateSurface(display, eglSurface))
+       {
+               return EGL_FALSE;
+       }
+
+       if(surface == EGL_NO_SURFACE)
+       {
+               return error(EGL_BAD_SURFACE, EGL_FALSE);
+       }
+
+       display->destroySurface((egl::Surface*)surface);
+
+       return success(EGL_TRUE);
+}
+
+EGLBoolean QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint *value = %p)",
+             dpy, surface, attribute, value);
+
+       egl::Display *display = egl::Display::get(dpy);
+       egl::Surface *eglSurface = (egl::Surface*)surface;
+
+       if(!validateSurface(display, eglSurface))
+       {
+               return EGL_FALSE;
+       }
+
+       if(surface == EGL_NO_SURFACE)
+       {
+               return error(EGL_BAD_SURFACE, EGL_FALSE);
+       }
+
+       switch(attribute)
+       {
+       case EGL_VG_ALPHA_FORMAT:
+               *value = EGL_VG_ALPHA_FORMAT_NONPRE;   // Default
+               break;
+       case EGL_VG_COLORSPACE:
+               *value = EGL_VG_COLORSPACE_sRGB;   // Default
+               break;
+       case EGL_CONFIG_ID:
+               *value = eglSurface->getConfigID();
+               break;
+       case EGL_HEIGHT:
+               *value = eglSurface->getHeight();
+               break;
+       case EGL_HORIZONTAL_RESOLUTION:
+               *value = EGL_UNKNOWN;
+               break;
+       case EGL_LARGEST_PBUFFER:
+               if(eglSurface->isPBufferSurface())   // For a window or pixmap surface, the contents of *value are not modified.
+               {
+                       *value = eglSurface->getLargestPBuffer();
+               }
+               break;
+       case EGL_MIPMAP_TEXTURE:
+               if(eglSurface->isPBufferSurface())   // For a window or pixmap surface, the contents of *value are not modified.
+               {
+                       *value = EGL_FALSE;   // UNIMPLEMENTED
+               }
+               break;
+       case EGL_MIPMAP_LEVEL:
+               if(eglSurface->isPBufferSurface())   // For a window or pixmap surface, the contents of *value are not modified.
+               {
+                       *value = eglSurface->getMipmapLevel();
+               }
+               break;
+       case EGL_MULTISAMPLE_RESOLVE:
+               *value = eglSurface->getMultisampleResolve();
+               break;
+       case EGL_PIXEL_ASPECT_RATIO:
+               *value = eglSurface->getPixelAspectRatio();
+               break;
+       case EGL_RENDER_BUFFER:
+               *value = eglSurface->getRenderBuffer();
+               break;
+       case EGL_SWAP_BEHAVIOR:
+               *value = eglSurface->getSwapBehavior();
+               break;
+       case EGL_TEXTURE_FORMAT:
+               if(eglSurface->isPBufferSurface())   // For a window or pixmap surface, the contents of *value are not modified.
+               {
+                       *value = eglSurface->getTextureFormat();
+               }
+               break;
+       case EGL_TEXTURE_TARGET:
+               if(eglSurface->isPBufferSurface())   // For a window or pixmap surface, the contents of *value are not modified.
+               {
+                       *value = eglSurface->getTextureTarget();
+               }
+               break;
+       case EGL_VERTICAL_RESOLUTION:
+               *value = EGL_UNKNOWN;
+               break;
+       case EGL_WIDTH:
+               *value = eglSurface->getWidth();
+               break;
+       default:
+               return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+       }
+
+       return success(EGL_TRUE);
+}
+
+EGLBoolean BindAPI(EGLenum api)
+{
+       TRACE("(EGLenum api = 0x%X)", api);
+
+       switch(api)
+       {
+       case EGL_OPENGL_API:
+       case EGL_OPENVG_API:
+               return error(EGL_BAD_PARAMETER, EGL_FALSE);   // Not supported by this implementation
+       case EGL_OPENGL_ES_API:
+               break;
+       default:
+               return error(EGL_BAD_PARAMETER, EGL_FALSE);
+       }
+
+       egl::setCurrentAPI(api);
+
+       return success(EGL_TRUE);
+}
+
+EGLenum QueryAPI(void)
+{
+       TRACE("()");
+
+       EGLenum API = egl::getCurrentAPI();
+
+       return success(API);
+}
+
+EGLBoolean WaitClient(void)
+{
+       TRACE("()");
+
+       // eglWaitClient is ignored if there is no current EGL rendering context for the current rendering API.
+       egl::Context *context = egl::getCurrentContext();
+
+       if(context)
+       {
+               context->finish();
+       }
+
+       return success(EGL_TRUE);
+}
+
+EGLBoolean ReleaseThread(void)
+{
+       TRACE("()");
+
+       detachThread();
+
+       return EGL_TRUE;   // success() is not called here because it would re-allocate thread-local storage.
+}
+
+EGLSurface CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = %p, "
+             "EGLConfig config = %p, const EGLint *attrib_list = %p)",
+             dpy, buftype, buffer, config, attrib_list);
+
+       switch(buftype)
+       {
+       case EGL_IOSURFACE_ANGLE:
+       {
+               egl::Display *display = egl::Display::get(dpy);
+
+               if(!validateConfig(display, config))
+               {
+                       return EGL_NO_SURFACE;
+               }
+
+               return display->createPBufferSurface(config, attrib_list, buffer);
+       }
+       case EGL_OPENVG_IMAGE:
+               UNIMPLEMENTED();
+               return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+       default:
+               return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+       };
+}
+
+EGLBoolean SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint value = %d)",
+             dpy, surface, attribute, value);
+
+       egl::Display *display = egl::Display::get(dpy);
+       egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
+
+       if(!validateSurface(display, eglSurface))
+       {
+               return EGL_FALSE;
+       }
+
+       switch(attribute)
+       {
+       case EGL_MIPMAP_LEVEL:
+               eglSurface->setMipmapLevel(value);
+               break;
+       case EGL_MULTISAMPLE_RESOLVE:
+               switch(value)
+               {
+               case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
+                       break;
+               case EGL_MULTISAMPLE_RESOLVE_BOX:
+                       if(!(eglSurface->getSurfaceType() & EGL_MULTISAMPLE_RESOLVE_BOX_BIT))
+                       {
+                               return error(EGL_BAD_MATCH, EGL_FALSE);
+                       }
+                       break;
+               default:
+                       return error(EGL_BAD_PARAMETER, EGL_FALSE);
+               }
+               eglSurface->setMultisampleResolve(value);
+               break;
+       case EGL_SWAP_BEHAVIOR:
+               switch(value)
+               {
+               case EGL_BUFFER_DESTROYED:
+                       break;
+               case EGL_BUFFER_PRESERVED:
+                       if(!(eglSurface->getSurfaceType() & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))
+                       {
+                               return error(EGL_BAD_MATCH, EGL_FALSE);
+                       }
+                       break;
+               default:
+                       return error(EGL_BAD_PARAMETER, EGL_FALSE);
+               }
+               eglSurface->setSwapBehavior(value);
+               break;
+       default:
+               return error(EGL_BAD_PARAMETER, EGL_FALSE);
+       }
+
+       return success(EGL_TRUE);
+}
+
+EGLBoolean BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer);
+
+       egl::Display *display = egl::Display::get(dpy);
+       egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
+
+       if(!validateSurface(display, eglSurface))
+       {
+               return EGL_FALSE;
+       }
+
+       if(buffer != EGL_BACK_BUFFER)
+       {
+               return error(EGL_BAD_PARAMETER, EGL_FALSE);
+       }
+
+       if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface())
+       {
+               return error(EGL_BAD_SURFACE, EGL_FALSE);
+       }
+
+       if(eglSurface->getBoundTexture())
+       {
+               return error(EGL_BAD_ACCESS, EGL_FALSE);
+       }
+
+       if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
+       {
+               return error(EGL_BAD_MATCH, EGL_FALSE);
+       }
+
+       egl::Context *context = egl::getCurrentContext();
+
+       if(context)
+       {
+               context->bindTexImage(eglSurface);
+       }
+
+       return success(EGL_TRUE);
+}
+
+EGLBoolean ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer);
+
+       egl::Display *display = egl::Display::get(dpy);
+       egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
+
+       if(!validateSurface(display, eglSurface))
+       {
+               return EGL_FALSE;
+       }
+
+       if(buffer != EGL_BACK_BUFFER)
+       {
+               return error(EGL_BAD_PARAMETER, EGL_FALSE);
+       }
+
+       if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface())
+       {
+               return error(EGL_BAD_SURFACE, EGL_FALSE);
+       }
+
+       if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
+       {
+               return error(EGL_BAD_MATCH, EGL_FALSE);
+       }
+
+       egl::Texture *texture = eglSurface->getBoundTexture();
+
+       if(texture)
+       {
+               texture->releaseTexImage();
+       }
+
+       return success(EGL_TRUE);
+}
+
+EGLBoolean SwapInterval(EGLDisplay dpy, EGLint interval)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLint interval = %d)", dpy, interval);
+
+       egl::Display *display = egl::Display::get(dpy);
+       egl::Context *context = egl::getCurrentContext();
+
+       if(!validateContext(display, context))
+       {
+               return EGL_FALSE;
+       }
+
+       egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());
+
+       if(!draw_surface)
+       {
+               return error(EGL_BAD_SURFACE, EGL_FALSE);
+       }
+
+       draw_surface->setSwapInterval(interval);
+
+       return success(EGL_TRUE);
+}
+
+EGLContext CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLContext share_context = %p, "
+             "const EGLint *attrib_list = %p)", dpy, config, share_context, attrib_list);
+
+       EGLint majorVersion = 1;
+       EGLint minorVersion = 0;
+
+       if(attrib_list)
+       {
+               for(const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
+               {
+                       switch(attribute[0])
+                       {
+                       case EGL_CONTEXT_MAJOR_VERSION_KHR:   // This token is an alias for EGL_CONTEXT_CLIENT_VERSION
+                               majorVersion = attribute[1];
+                               break;
+                       case EGL_CONTEXT_MINOR_VERSION_KHR:
+                               minorVersion = attribute[1];
+                               break;
+                       case EGL_CONTEXT_FLAGS_KHR:
+                               switch(attribute[1])
+                               {
+                               case EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR:
+                                       // According to the EGL_KHR_create_context spec:
+                                       // "Khronos is still defining the expected and required features of debug contexts, so
+                                       //  implementations are currently free to implement "debug contexts" with little or no debug
+                                       //  functionality. However, OpenGL and OpenGL ES implementations supporting the GL_KHR_debug
+                                       //  extension should enable it when this bit is set."
+                                       break;
+                               case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR:
+                               case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR:
+                                       // These bits are for OpenGL contexts only, not OpenGL ES contexts
+                                       return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+                               default:
+                                       return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+                               }
+                               break;
+                       case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
+                               switch(attribute[1])
+                               {
+                               case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
+                               case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
+                                       // These bits are for OpenGL contexts only, not OpenGL ES contexts
+                                       return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+                               default:
+                                       return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+                               }
+                               break;
+                       case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
+                               switch(attribute[1])
+                               {
+                               case EGL_NO_RESET_NOTIFICATION_KHR:
+                               case EGL_LOSE_CONTEXT_ON_RESET_KHR:
+                                       // These bits are for OpenGL contexts only, not OpenGL ES contexts
+                                       return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+                               default:
+                                       return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+                               }
+                               break;
+                       default:
+                               return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+                       }
+               }
+       }
+
+       switch(majorVersion)
+       {
+       case 1:
+               if(minorVersion != 0 && minorVersion != 1)
+               {
+                       // 1.X: Only OpenGL ES 1.0 and 1.1 contexts are supported
+                       return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
+               }
+               break;
+       case 2:
+       case 3:
+               if(minorVersion != 0)
+               {
+                       // 2.X and 3.X: Only OpenGL ES 2.0 and 3.0 contexts are currently supported
+                       return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
+               }
+               break;
+       default:
+               return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
+       }
+
+       egl::Display *display = egl::Display::get(dpy);
+       egl::Context *shareContext = static_cast<egl::Context*>(share_context);
+
+       if(!validateConfig(display, config))
+       {
+               return EGL_NO_CONTEXT;
+       }
+
+       // Allow sharing between different context versions >= 2.0, but isolate 1.x
+       // contexts from 2.0+. Strict matching between context versions >= 2.0 is
+       // confusing for apps to navigate because of version promotion.
+       if(shareContext && ((shareContext->getClientVersion() >= 2) ^ (majorVersion >= 2)))
+       {
+               return error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
+       }
+
+       return display->createContext(config, shareContext, majorVersion);
+}
+
+EGLBoolean DestroyContext(EGLDisplay dpy, EGLContext ctx)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p)", dpy, ctx);
+
+       egl::Display *display = egl::Display::get(dpy);
+       egl::Context *context = static_cast<egl::Context*>(ctx);
+
+       if(!validateContext(display, context))
+       {
+               return EGL_FALSE;
+       }
+
+       if(ctx == EGL_NO_CONTEXT)
+       {
+               return error(EGL_BAD_CONTEXT, EGL_FALSE);
+       }
+
+       display->destroyContext(context);
+
+       return success(EGL_TRUE);
+}
+
+EGLBoolean MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLSurface draw = %p, EGLSurface read = %p, EGLContext ctx = %p)",
+             dpy, draw, read, ctx);
+
+       egl::Display *display = egl::Display::get(dpy);
+       egl::Context *context = static_cast<egl::Context*>(ctx);
+       egl::Surface *drawSurface = static_cast<egl::Surface*>(draw);
+       egl::Surface *readSurface = static_cast<egl::Surface*>(read);
+
+       if(ctx != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE)
+       {
+               if(!validateDisplay(display))
+               {
+                       return EGL_FALSE;
+               }
+       }
+
+       if(ctx == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
+       {
+               return error(EGL_BAD_MATCH, EGL_FALSE);
+       }
+
+       if(ctx != EGL_NO_CONTEXT && !validateContext(display, context))
+       {
+               return EGL_FALSE;
+       }
+
+       if((draw != EGL_NO_SURFACE && !validateSurface(display, drawSurface)) ||
+          (read != EGL_NO_SURFACE && !validateSurface(display, readSurface)))
+       {
+               return EGL_FALSE;
+       }
+
+       if((draw != EGL_NO_SURFACE && drawSurface->hasClientBuffer()) ||
+          (read != EGL_NO_SURFACE && readSurface->hasClientBuffer()))
+       {
+               // Make current is not supported on IOSurface pbuffers.
+               return error(EGL_BAD_SURFACE, EGL_FALSE);
+       }
+
+       if((draw != EGL_NO_SURFACE) ^ (read != EGL_NO_SURFACE))
+       {
+               return error(EGL_BAD_MATCH, EGL_FALSE);
+       }
+
+       if(draw != read)
+       {
+               UNIMPLEMENTED();   // FIXME
+       }
+
+       egl::setCurrentDrawSurface(drawSurface);
+       egl::setCurrentReadSurface(readSurface);
+       egl::setCurrentContext(context);
+
+       if(context)
+       {
+               context->makeCurrent(drawSurface);
+       }
+
+       return success(EGL_TRUE);
+}
+
+EGLContext GetCurrentContext(void)
+{
+       TRACE("()");
+
+       EGLContext context = egl::getCurrentContext();
+
+       return success(context);
+}
+
+EGLSurface GetCurrentSurface(EGLint readdraw)
+{
+       TRACE("(EGLint readdraw = %d)", readdraw);
+
+       if(readdraw == EGL_READ)
+       {
+               EGLSurface read = egl::getCurrentReadSurface();
+               return success(read);
+       }
+       else if(readdraw == EGL_DRAW)
+       {
+               EGLSurface draw = egl::getCurrentDrawSurface();
+               return success(draw);
+       }
+       else
+       {
+               return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+       }
+}
+
+EGLDisplay GetCurrentDisplay(void)
+{
+       TRACE("()");
+
+       egl::Context *context = egl::getCurrentContext();
+
+       if(!context)
+       {
+               return success(EGL_NO_DISPLAY);
+       }
+
+       egl::Display *display = context->getDisplay();
+
+       if(!display)
+       {
+               return error(EGL_BAD_ACCESS, EGL_NO_DISPLAY);
+       }
+
+       return success(display->getEGLDisplay());
+}
+
+EGLBoolean QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLint attribute = %d, EGLint *value = %p)",
+             dpy, ctx, attribute, value);
+
+       egl::Display *display = egl::Display::get(dpy);
+       egl::Context *context = static_cast<egl::Context*>(ctx);
+
+       if(!validateContext(display, context))
+       {
+               return EGL_FALSE;
+       }
+
+       switch(attribute)
+       {
+       case EGL_CONFIG_ID:
+               *value = context->getConfigID();
+               break;
+       case EGL_CONTEXT_CLIENT_TYPE:
+               *value = egl::getCurrentAPI();
+               break;
+       case EGL_CONTEXT_CLIENT_VERSION:
+               *value = context->getClientVersion();
+               break;
+       case EGL_RENDER_BUFFER:
+               *value = EGL_BACK_BUFFER;
+               break;
+       default:
+               return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+       }
+
+       return success(EGL_TRUE);
+}
+
+EGLBoolean WaitGL(void)
+{
+       TRACE("()");
+
+       // glWaitGL is ignored if there is no current EGL rendering context for OpenGL ES.
+       egl::Context *context = egl::getCurrentContext();
+
+       if(context)
+       {
+               context->finish();
+       }
+
+       return success(EGL_TRUE);
+}
+
+EGLBoolean WaitNative(EGLint engine)
+{
+       TRACE("(EGLint engine = %d)", engine);
+
+       if(engine != EGL_CORE_NATIVE_ENGINE)
+       {
+               return error(EGL_BAD_PARAMETER, EGL_FALSE);
+       }
+
+       // eglWaitNative is ignored if there is no current EGL rendering context.
+       egl::Context *context = egl::getCurrentContext();
+
+       if(context)
+       {
+               #if defined(USE_X11)
+                       egl::Display *display = context->getDisplay();
+
+                       if(!display)
+                       {
+                               return error(EGL_BAD_DISPLAY, EGL_FALSE);
+                       }
+
+                       libX11->XSync((::Display*)display->getNativeDisplay(), False);
+               #else
+                       UNIMPLEMENTED();
+               #endif
+       }
+
+       return success(EGL_TRUE);
+}
+
+EGLBoolean SwapBuffers(EGLDisplay dpy, EGLSurface surface)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface);
+
+       egl::Display *display = egl::Display::get(dpy);
+       egl::Surface *eglSurface = (egl::Surface*)surface;
+
+       if(!validateSurface(display, eglSurface))
+       {
+               return EGL_FALSE;
+       }
+
+       if(surface == EGL_NO_SURFACE)
+       {
+               return error(EGL_BAD_SURFACE, EGL_FALSE);
+       }
+
+       eglSurface->swap();
+
+       return success(EGL_TRUE);
+}
+
+EGLBoolean CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLNativePixmapType target = %p)", dpy, surface, target);
+
+       egl::Display *display = egl::Display::get(dpy);
+       egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
+
+       if(!validateSurface(display, eglSurface))
+       {
+               return EGL_FALSE;
+       }
+
+       UNIMPLEMENTED();   // FIXME
+
+       return success(EGL_FALSE);
+}
+
+EGLImage CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLenum target = 0x%X, buffer = %p, const EGLAttrib *attrib_list = %p)", dpy, ctx, target, buffer, attrib_list);
+
+       egl::Display *display = egl::Display::get(dpy);
+       egl::Context *context = static_cast<egl::Context*>(ctx);
+
+       if(!validateDisplay(display))
+       {
+               return error(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
+       }
+
+       if(context != EGL_NO_CONTEXT && !display->isValidContext(context))
+       {
+               return error(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
+       }
+
+       EGLenum imagePreserved = EGL_FALSE;
+       (void)imagePreserved; // currently unused
+
+       GLuint textureLevel = 0;
+       if(attrib_list)
+       {
+               for(const EGLAttrib *attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
+               {
+                       if(attribute[0] == EGL_IMAGE_PRESERVED_KHR)
+                       {
+                               imagePreserved = static_cast<EGLenum>(attribute[1]);
+                       }
+                       else if(attribute[0] == EGL_GL_TEXTURE_LEVEL_KHR)
+                       {
+                               textureLevel = static_cast<GLuint>(attribute[1]);
+                       }
+                       else
+                       {
+                               return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR);
+                       }
+               }
+       }
+
+       #if defined(__ANDROID__)
+               if(target == EGL_NATIVE_BUFFER_ANDROID)
+               {
+                       ANativeWindowBuffer *nativeBuffer = reinterpret_cast<ANativeWindowBuffer*>(buffer);
+
+                       if(!nativeBuffer || GLPixelFormatFromAndroid(nativeBuffer->format) == GL_NONE)
+                       {
+                               ERR("%s badness unsupported HAL format=%x", __FUNCTION__, nativeBuffer ? nativeBuffer->format : 0);
+                               return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR);
+                       }
+
+                       Image *image = new AndroidNativeImage(nativeBuffer);
+                       EGLImageKHR eglImage = display->createSharedImage(image);
+
+                       return success(eglImage);
+               }
+       #endif
+
+       GLuint name = static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));
+
+       if(name == 0)
+       {
+               return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+       }
+
+       EGLenum validationResult = context->validateSharedImage(target, name, textureLevel);
+
+       if(validationResult != EGL_SUCCESS)
+       {
+               return error(validationResult, EGL_NO_IMAGE_KHR);
+       }
+
+       Image *image = context->createSharedImage(target, name, textureLevel);
+
+       if(!image)
+       {
+               return error(EGL_BAD_MATCH, EGL_NO_IMAGE_KHR);
+       }
+
+       if(image->getDepth() > 1)
+       {
+               return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+       }
+
+       EGLImage eglImage = display->createSharedImage(image);
+
+       return success(eglImage);
+}
+
+EGLImageKHR CreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLenum target = 0x%X, buffer = %p, const EGLint attrib_list = %p)", dpy, ctx, target, buffer, attrib_list);
+
+       EGLAttribs attribs(attrib_list);
+       return CreateImage(dpy, ctx, target, buffer, &attribs);
+}
+
+EGLBoolean DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLImageKHR image = %p)", dpy, image);
+
+       egl::Display *display = egl::Display::get(dpy);
+
+       if(!validateDisplay(display))
+       {
+               return error(EGL_BAD_DISPLAY, EGL_FALSE);
+       }
+
+       if(!display->destroySharedImage(image))
+       {
+               return error(EGL_BAD_PARAMETER, EGL_FALSE);
+       }
+
+       return success(EGL_TRUE);
+}
+
+EGLDisplay GetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list)
+{
+       TRACE("(EGLenum platform = 0x%X, void *native_display = %p, const EGLAttrib *attrib_list = %p)", platform, native_display, attrib_list);
+
+       #if defined(__linux__) && !defined(__ANDROID__)
+               switch(platform)
+               {
+               #if defined(USE_X11)
+               case EGL_PLATFORM_X11_EXT: break;
+               #endif
+               case EGL_PLATFORM_GBM_KHR: break;
+               default:
+                       return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+               }
+
+               if(platform == EGL_PLATFORM_GBM_KHR)
+               {
+                       if(native_display != (void*)EGL_DEFAULT_DISPLAY)
+                       {
+                               return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);   // Unimplemented
+                       }
+
+                       if(attrib_list && attrib_list[0] != EGL_NONE)
+                       {
+                               return error(EGL_BAD_ATTRIBUTE, EGL_NO_DISPLAY);   // Unimplemented
+                       }
+
+                       return success(HEADLESS_DISPLAY);
+               }
+               #if defined(USE_X11)
+               else if(platform == EGL_PLATFORM_X11_EXT)
+               {
+                       if(!libX11)
+                       {
+                               return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+                       }
+
+                       if(native_display != (void*)EGL_DEFAULT_DISPLAY)
+                       {
+                               return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);   // Unimplemented
+                       }
+
+                       if(attrib_list && attrib_list[0] != EGL_NONE)
+                       {
+                               return error(EGL_BAD_ATTRIBUTE, EGL_NO_DISPLAY);   // Unimplemented
+                       }
+               }
+               #endif
+
+               return success(PRIMARY_DISPLAY);   // We only support the default display
+       #else
+               return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+       #endif
+}
+
+EGLDisplay GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)
+{
+       TRACE("(EGLenum platform = 0x%X, void *native_display = %p, const EGLint *attrib_list = %p)", platform, native_display, attrib_list);
+
+       EGLAttribs attribs(attrib_list);
+       return GetPlatformDisplay(platform, native_display, &attribs);
+}
+
+EGLSync CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLunum type = %x, EGLAttrib *attrib_list=%p)", dpy, type, attrib_list);
+
+       egl::Display *display = egl::Display::get(dpy);
+
+       if(!validateDisplay(display))
+       {
+               return error(EGL_BAD_DISPLAY, EGL_NO_SYNC_KHR);
+       }
+
+       if(type != EGL_SYNC_FENCE_KHR)
+       {
+               return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
+       }
+
+       if(attrib_list && attrib_list[0] != EGL_NONE)
+       {
+               return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
+       }
+
+       egl::Context *context = egl::getCurrentContext();
+
+       if(!validateContext(display, context))
+       {
+               return error(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
+       }
+
+       EGLSyncKHR sync = display->createSync(context);
+
+       return success(sync);
+}
+
+EGLSyncKHR CreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLunum type = %x, EGLint *attrib_list=%p)", dpy, type, attrib_list);
+
+       EGLAttribs attribs(attrib_list);
+       return CreateSync(dpy, type, &attribs);
+}
+
+EGLBoolean DestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p)", dpy, sync);
+
+       egl::Display *display = egl::Display::get(dpy);
+       FenceSync *eglSync = static_cast<FenceSync*>(sync);
+
+       if(!validateDisplay(display))
+       {
+               return error(EGL_BAD_DISPLAY, EGL_FALSE);
+       }
+
+       if(!display->isValidSync(eglSync))
+       {
+               return error(EGL_BAD_PARAMETER, EGL_FALSE);
+       }
+
+       display->destroySync(eglSync);
+
+       return success(EGL_TRUE);
+}
+
+EGLint ClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint flags = %x, EGLTimeKHR value = %llx)", dpy, sync, flags, timeout);
+
+       egl::Display *display = egl::Display::get(dpy);
+       FenceSync *eglSync = static_cast<FenceSync*>(sync);
+
+       if(!validateDisplay(display))
+       {
+               return error(EGL_BAD_DISPLAY, EGL_FALSE);
+       }
+
+       if(!display->isValidSync(eglSync))
+       {
+               return error(EGL_BAD_PARAMETER, EGL_FALSE);
+       }
+
+       (void)flags;
+       (void)timeout;
+
+       if(!eglSync->isSignaled())
+       {
+               eglSync->wait();
+       }
+
+       return success(EGL_CONDITION_SATISFIED_KHR);
+}
+
+EGLBoolean GetSyncAttrib(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLAttrib *value)
+{
+       TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint attribute = %x, EGLAttrib *value = %p)", dpy, sync, attribute, value);
+
+       egl::Display *display = egl::Display::get(dpy);
+       FenceSync *eglSync = static_cast<FenceSync*>(sync);
+
+       if(!validateDisplay(display))
+       {
+               return error(EGL_BAD_DISPLAY, EGL_FALSE);
+       }
+
+       if(!display->isValidSync(eglSync))
+       {
+               return error(EGL_BAD_PARAMETER, EGL_FALSE);
+       }
+
+       if(!value)
+       {
+               return error(EGL_BAD_PARAMETER, EGL_FALSE);
+       }
+
+       switch(attribute)
+       {
+       case EGL_SYNC_TYPE_KHR:
+               *value = EGL_SYNC_FENCE_KHR;
+               return success(EGL_TRUE);
+       case EGL_SYNC_STATUS_KHR:
+               eglSync->wait();   // TODO: Don't block. Just poll based on sw::Query.
+               *value = eglSync->isSignaled() ? EGL_SIGNALED_KHR : EGL_UNSIGNALED_KHR;
+               return success(EGL_TRUE);
+       case EGL_SYNC_CONDITION_KHR:
+               *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
+               return success(EGL_TRUE);
+       default:
+               return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+       }
+}
+
+EGLBoolean GetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
+{
+       EGLAttrib attrib_value;
+       EGLBoolean result = GetSyncAttrib(dpy, sync, attribute, &attrib_value);
+       *value = static_cast<EGLint>(attrib_value);
+       return result;
+}
+
+__eglMustCastToProperFunctionPointerType GetProcAddress(const char *procname)
+{
+       TRACE("(const char *procname = \"%s\")", procname);
+
+       struct Function
+       {
+               const char *name;
+               __eglMustCastToProperFunctionPointerType address;
+       };
+
+       struct CompareFunctor
+       {
+               bool operator()(const Function &a, const Function &b) const
+               {
+                       return strcmp(a.name, b.name) < 0;
+               }
+       };
+
+       // This array must be kept sorted with respect to strcmp(), so that binary search works correctly.
+       // The Unix command "LC_COLLATE=C sort" will generate the correct order.
+       static const Function eglFunctions[] =
+       {
+               #define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
+
+               FUNCTION(eglBindAPI),
+               FUNCTION(eglBindTexImage),
+               FUNCTION(eglChooseConfig),
+               FUNCTION(eglClientWaitSync),
+               FUNCTION(eglClientWaitSyncKHR),
+               FUNCTION(eglCopyBuffers),
+               FUNCTION(eglCreateContext),
+               FUNCTION(eglCreateImage),
+               FUNCTION(eglCreateImageKHR),
+               FUNCTION(eglCreatePbufferFromClientBuffer),
+               FUNCTION(eglCreatePbufferSurface),
+               FUNCTION(eglCreatePixmapSurface),
+               FUNCTION(eglCreatePlatformPixmapSurface),
+               FUNCTION(eglCreatePlatformPixmapSurfaceEXT),
+               FUNCTION(eglCreatePlatformWindowSurface),
+               FUNCTION(eglCreatePlatformWindowSurfaceEXT),
+               FUNCTION(eglCreateSync),
+               FUNCTION(eglCreateSyncKHR),
+               FUNCTION(eglCreateWindowSurface),
+               FUNCTION(eglDestroyContext),
+               FUNCTION(eglDestroyImage),
+               FUNCTION(eglDestroyImageKHR),
+               FUNCTION(eglDestroySurface),
+               FUNCTION(eglDestroySync),
+               FUNCTION(eglDestroySyncKHR),
+               FUNCTION(eglGetConfigAttrib),
+               FUNCTION(eglGetConfigs),
+               FUNCTION(eglGetCurrentContext),
+               FUNCTION(eglGetCurrentDisplay),
+               FUNCTION(eglGetCurrentSurface),
+               FUNCTION(eglGetDisplay),
+               FUNCTION(eglGetError),
+               FUNCTION(eglGetPlatformDisplay),
+               FUNCTION(eglGetPlatformDisplayEXT),
+               FUNCTION(eglGetProcAddress),
+               FUNCTION(eglGetSyncAttrib),
+               FUNCTION(eglGetSyncAttribKHR),
+               FUNCTION(eglInitialize),
+               FUNCTION(eglMakeCurrent),
+               FUNCTION(eglQueryAPI),
+               FUNCTION(eglQueryContext),
+               FUNCTION(eglQueryString),
+               FUNCTION(eglQuerySurface),
+               FUNCTION(eglReleaseTexImage),
+               FUNCTION(eglReleaseThread),
+               FUNCTION(eglSurfaceAttrib),
+               FUNCTION(eglSwapBuffers),
+               FUNCTION(eglSwapInterval),
+               FUNCTION(eglTerminate),
+               FUNCTION(eglWaitClient),
+               FUNCTION(eglWaitGL),
+               FUNCTION(eglWaitNative),
+               FUNCTION(eglWaitSync),
+               FUNCTION(eglWaitSyncKHR),
+
+               #undef FUNCTION
+       };
+
+       static const size_t numFunctions = sizeof eglFunctions / sizeof(Function);
+       static const Function *const eglFunctionsEnd = eglFunctions + numFunctions;
+
+       Function needle;
+       needle.name = procname;
+
+       if(procname && strncmp("egl", procname, 3) == 0)
+       {
+               const Function *result = std::lower_bound(eglFunctions, eglFunctionsEnd, needle, CompareFunctor());
+               if (result != eglFunctionsEnd && strcmp(procname, result->name) == 0)
+               {
+                       return success((__eglMustCastToProperFunctionPointerType)result->address);
+               }
+       }
+
+       if(libGLESv2)
+       {
+               __eglMustCastToProperFunctionPointerType proc = libGLESv2->es2GetProcAddress(procname);
+               if(proc) return success(proc);
+       }
+
+       if(libGLES_CM)
+       {
+               __eglMustCastToProperFunctionPointerType proc =  libGLES_CM->es1GetProcAddress(procname);
+               if(proc) return success(proc);
+       }
+
+       return success((__eglMustCastToProperFunctionPointerType)NULL);
+}
+}