Make all EGL functions dynamically loaded

This commit is contained in:
Camilla Berglund 2015-08-24 16:39:01 +02:00
parent afe4aadade
commit 7e13a4909e
4 changed files with 187 additions and 42 deletions

View File

@ -402,6 +402,11 @@ if (_GLFW_EGL)
list(APPEND glfw_PKG_DEPS "glesv2") list(APPEND glfw_PKG_DEPS "glesv2")
endif() endif()
if (CMAKE_DL_LIBS)
list(APPEND glfw_LIBRARIES "${CMAKE_DL_LIBS}")
list(APPEND glfw_PKG_LIBS "-l${CMAKE_DL_LIBS}")
endif()
endif() endif()
#-------------------------------------------------------------------- #--------------------------------------------------------------------

View File

@ -102,6 +102,7 @@ GLFW bundles a number of dependencies in the `deps/` directory.
- [GLX] Made all GLX functions dynamically loaded - [GLX] Made all GLX functions dynamically loaded
- [GLX] Removed `_GLFW_HAS_GLXGETPROCADDRESS*` and `_GLFW_HAS_DLOPEN` - [GLX] Removed `_GLFW_HAS_GLXGETPROCADDRESS*` and `_GLFW_HAS_DLOPEN`
compile-time options compile-time options
- [EGL] Made all EGL functions dynamically loaded
## Contact ## Contact

View File

@ -78,7 +78,7 @@ static const char* getErrorString(EGLint error)
static int getConfigAttrib(EGLConfig config, int attrib) static int getConfigAttrib(EGLConfig config, int attrib)
{ {
int value; int value;
eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value); _glfw_eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value);
return value; return value;
} }
@ -93,7 +93,7 @@ static GLboolean chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* closest; const _GLFWfbconfig* closest;
int i, nativeCount, usableCount; int i, nativeCount, usableCount;
eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount); _glfw_eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);
if (!nativeCount) if (!nativeCount)
{ {
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned"); _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned");
@ -101,7 +101,8 @@ static GLboolean chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
} }
nativeConfigs = calloc(nativeCount, sizeof(EGLConfig)); nativeConfigs = calloc(nativeCount, sizeof(EGLConfig));
eglGetConfigs(_glfw.egl.display, nativeConfigs, nativeCount, &nativeCount); _glfw_eglGetConfigs(_glfw.egl.display, nativeConfigs,
nativeCount, &nativeCount);
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig)); usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
usableCount = 0; usableCount = 0;
@ -178,23 +179,86 @@ static GLboolean chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
// //
int _glfwInitContextAPI(void) int _glfwInitContextAPI(void)
{ {
int i;
const char* sonames[] =
{
#if defined(_GLFW_WIN32)
"libEGL.dll",
"EGL.dll",
#elif defined(_GLFW_COCOA)
"libEGL.dylib",
#else
"libEGL.so.1",
#endif
NULL
};
if (!_glfwCreateContextTLS()) if (!_glfwCreateContextTLS())
return GL_FALSE; return GL_FALSE;
_glfw.egl.display = eglGetDisplay((EGLNativeDisplayType)_GLFW_EGL_NATIVE_DISPLAY); for (i = 0; sonames[i]; i++)
{
_glfw.egl.handle = _glfw_dlopen(sonames[i]);
if (_glfw.egl.handle)
break;
}
if (!_glfw.egl.handle)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to load EGL");
return GL_FALSE;
}
_glfw.egl.GetConfigAttrib =
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
_glfw.egl.GetConfigs =
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigs");
_glfw.egl.GetDisplay =
_glfw_dlsym(_glfw.egl.handle, "eglGetDisplay");
_glfw.egl.GetError =
_glfw_dlsym(_glfw.egl.handle, "eglGetError");
_glfw.egl.Initialize =
_glfw_dlsym(_glfw.egl.handle, "eglInitialize");
_glfw.egl.Terminate =
_glfw_dlsym(_glfw.egl.handle, "eglTerminate");
_glfw.egl.BindAPI =
_glfw_dlsym(_glfw.egl.handle, "eglBindAPI");
_glfw.egl.CreateContext =
_glfw_dlsym(_glfw.egl.handle, "eglCreateContext");
_glfw.egl.DestroySurface =
_glfw_dlsym(_glfw.egl.handle, "eglDestroySurface");
_glfw.egl.DestroyContext =
_glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");
_glfw.egl.CreateWindowSurface =
_glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");
_glfw.egl.MakeCurrent =
_glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");
_glfw.egl.SwapBuffers =
_glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers");
_glfw.egl.SwapInterval =
_glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");
_glfw.egl.QueryString =
_glfw_dlsym(_glfw.egl.handle, "eglQueryString");
_glfw.egl.GetProcAddress =
_glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress");
_glfw.egl.display =
_glfw_eglGetDisplay((EGLNativeDisplayType)_GLFW_EGL_NATIVE_DISPLAY);
if (_glfw.egl.display == EGL_NO_DISPLAY) if (_glfw.egl.display == EGL_NO_DISPLAY)
{ {
_glfwInputError(GLFW_API_UNAVAILABLE, _glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to get EGL display: %s", "EGL: Failed to get EGL display: %s",
getErrorString(eglGetError())); getErrorString(_glfw_eglGetError()));
return GL_FALSE; return GL_FALSE;
} }
if (!eglInitialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor)) if (!_glfw_eglInitialize(_glfw.egl.display,
&_glfw.egl.major,
&_glfw.egl.minor))
{ {
_glfwInputError(GLFW_API_UNAVAILABLE, _glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to initialize EGL: %s", "EGL: Failed to initialize EGL: %s",
getErrorString(eglGetError())); getErrorString(_glfw_eglGetError()));
return GL_FALSE; return GL_FALSE;
} }
@ -208,7 +272,14 @@ int _glfwInitContextAPI(void)
// //
void _glfwTerminateContextAPI(void) void _glfwTerminateContextAPI(void)
{ {
eglTerminate(_glfw.egl.display); if (_glfw_eglTerminate)
_glfw_eglTerminate(_glfw.egl.display);
if (_glfw.egl.handle)
{
_glfw_dlclose(_glfw.egl.handle);
_glfw.egl.handle = NULL;
}
_glfwDestroyContextTLS(); _glfwDestroyContextTLS();
} }
@ -248,7 +319,7 @@ int _glfwCreateContext(_GLFWwindow* window,
EGLint redBits, greenBits, blueBits, alphaBits, visualID = 0; EGLint redBits, greenBits, blueBits, alphaBits, visualID = 0;
XVisualInfo info; XVisualInfo info;
eglGetConfigAttrib(_glfw.egl.display, config, _glfw_eglGetConfigAttrib(_glfw.egl.display, config,
EGL_NATIVE_VISUAL_ID, &visualID); EGL_NATIVE_VISUAL_ID, &visualID);
info.screen = _glfw.x11.screen; info.screen = _glfw.x11.screen;
@ -265,13 +336,13 @@ int _glfwCreateContext(_GLFWwindow* window,
// Some EGL drivers do not implement the EGL_NATIVE_VISUAL_ID // Some EGL drivers do not implement the EGL_NATIVE_VISUAL_ID
// attribute, so attempt to find the closest match // attribute, so attempt to find the closest match
eglGetConfigAttrib(_glfw.egl.display, config, _glfw_eglGetConfigAttrib(_glfw.egl.display, config,
EGL_RED_SIZE, &redBits); EGL_RED_SIZE, &redBits);
eglGetConfigAttrib(_glfw.egl.display, config, _glfw_eglGetConfigAttrib(_glfw.egl.display, config,
EGL_GREEN_SIZE, &greenBits); EGL_GREEN_SIZE, &greenBits);
eglGetConfigAttrib(_glfw.egl.display, config, _glfw_eglGetConfigAttrib(_glfw.egl.display, config,
EGL_BLUE_SIZE, &blueBits); EGL_BLUE_SIZE, &blueBits);
eglGetConfigAttrib(_glfw.egl.display, config, _glfw_eglGetConfigAttrib(_glfw.egl.display, config,
EGL_ALPHA_SIZE, &alphaBits); EGL_ALPHA_SIZE, &alphaBits);
info.depth = redBits + greenBits + blueBits + alphaBits; info.depth = redBits + greenBits + blueBits + alphaBits;
@ -291,21 +362,21 @@ int _glfwCreateContext(_GLFWwindow* window,
if (ctxconfig->api == GLFW_OPENGL_ES_API) if (ctxconfig->api == GLFW_OPENGL_ES_API)
{ {
if (!eglBindAPI(EGL_OPENGL_ES_API)) if (!_glfw_eglBindAPI(EGL_OPENGL_ES_API))
{ {
_glfwInputError(GLFW_API_UNAVAILABLE, _glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to bind OpenGL ES: %s", "EGL: Failed to bind OpenGL ES: %s",
getErrorString(eglGetError())); getErrorString(_glfw_eglGetError()));
return GL_FALSE; return GL_FALSE;
} }
} }
else else
{ {
if (!eglBindAPI(EGL_OPENGL_API)) if (!_glfw_eglBindAPI(EGL_OPENGL_API))
{ {
_glfwInputError(GLFW_API_UNAVAILABLE, _glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to bind OpenGL: %s", "EGL: Failed to bind OpenGL: %s",
getErrorString(eglGetError())); getErrorString(_glfw_eglGetError()));
return GL_FALSE; return GL_FALSE;
} }
} }
@ -371,14 +442,14 @@ int _glfwCreateContext(_GLFWwindow* window,
// Context release behaviors (GL_KHR_context_flush_control) are not yet // Context release behaviors (GL_KHR_context_flush_control) are not yet
// supported on EGL but are not a hard constraint, so ignore and continue // supported on EGL but are not a hard constraint, so ignore and continue
window->egl.context = eglCreateContext(_glfw.egl.display, window->egl.context = _glfw_eglCreateContext(_glfw.egl.display,
config, share, attribs); config, share, attribs);
if (window->egl.context == EGL_NO_CONTEXT) if (window->egl.context == EGL_NO_CONTEXT)
{ {
_glfwInputError(GLFW_VERSION_UNAVAILABLE, _glfwInputError(GLFW_VERSION_UNAVAILABLE,
"EGL: Failed to create context: %s", "EGL: Failed to create context: %s",
getErrorString(eglGetError())); getErrorString(_glfw_eglGetError()));
return GL_FALSE; return GL_FALSE;
} }
@ -403,13 +474,13 @@ void _glfwDestroyContext(_GLFWwindow* window)
if (window->egl.surface) if (window->egl.surface)
{ {
eglDestroySurface(_glfw.egl.display, window->egl.surface); _glfw_eglDestroySurface(_glfw.egl.display, window->egl.surface);
window->egl.surface = EGL_NO_SURFACE; window->egl.surface = EGL_NO_SURFACE;
} }
if (window->egl.context) if (window->egl.context)
{ {
eglDestroyContext(_glfw.egl.display, window->egl.context); _glfw_eglDestroyContext(_glfw.egl.display, window->egl.context);
window->egl.context = EGL_NO_CONTEXT; window->egl.context = EGL_NO_CONTEXT;
} }
} }
@ -438,7 +509,8 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
{ {
if (window->egl.surface == EGL_NO_SURFACE) if (window->egl.surface == EGL_NO_SURFACE)
{ {
window->egl.surface = eglCreateWindowSurface(_glfw.egl.display, window->egl.surface =
_glfw_eglCreateWindowSurface(_glfw.egl.display,
window->egl.config, window->egl.config,
(EGLNativeWindowType)_GLFW_EGL_NATIVE_WINDOW, (EGLNativeWindowType)_GLFW_EGL_NATIVE_WINDOW,
NULL); NULL);
@ -446,19 +518,21 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: Failed to create window surface: %s", "EGL: Failed to create window surface: %s",
getErrorString(eglGetError())); getErrorString(_glfw_eglGetError()));
} }
} }
eglMakeCurrent(_glfw.egl.display, _glfw_eglMakeCurrent(_glfw.egl.display,
window->egl.surface, window->egl.surface,
window->egl.surface, window->egl.surface,
window->egl.context); window->egl.context);
} }
else else
{ {
eglMakeCurrent(_glfw.egl.display, _glfw_eglMakeCurrent(_glfw.egl.display,
EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); EGL_NO_SURFACE,
EGL_NO_SURFACE,
EGL_NO_CONTEXT);
} }
_glfwSetContextTLS(window); _glfwSetContextTLS(window);
@ -466,17 +540,18 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
void _glfwPlatformSwapBuffers(_GLFWwindow* window) void _glfwPlatformSwapBuffers(_GLFWwindow* window)
{ {
eglSwapBuffers(_glfw.egl.display, window->egl.surface); _glfw_eglSwapBuffers(_glfw.egl.display, window->egl.surface);
} }
void _glfwPlatformSwapInterval(int interval) void _glfwPlatformSwapInterval(int interval)
{ {
eglSwapInterval(_glfw.egl.display, interval); _glfw_eglSwapInterval(_glfw.egl.display, interval);
} }
int _glfwPlatformExtensionSupported(const char* extension) int _glfwPlatformExtensionSupported(const char* extension)
{ {
const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS); const char* extensions = _glfw_eglQueryString(_glfw.egl.display,
EGL_EXTENSIONS);
if (extensions) if (extensions)
{ {
if (_glfwStringInExtensionString(extension, extensions)) if (_glfwStringInExtensionString(extension, extensions))
@ -488,7 +563,7 @@ int _glfwPlatformExtensionSupported(const char* extension)
GLFWglproc _glfwPlatformGetProcAddress(const char* procname) GLFWglproc _glfwPlatformGetProcAddress(const char* procname)
{ {
return eglGetProcAddress(procname); return _glfw_eglGetProcAddress(procname);
} }

View File

@ -28,6 +28,17 @@
#ifndef _glfw3_egl_context_h_ #ifndef _glfw3_egl_context_h_
#define _glfw3_egl_context_h_ #define _glfw3_egl_context_h_
#if defined(_GLFW_WIN32)
#define _glfw_dlopen(name) LoadLibraryA(name)
#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
#define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
#else
#include <dlfcn.h>
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle)
#define _glfw_dlsym(handle, name) dlsym(handle, name)
#endif
#include <EGL/egl.h> #include <EGL/egl.h>
// This path may need to be changed if you build GLFW using your own setup // This path may need to be changed if you build GLFW using your own setup
@ -35,6 +46,40 @@
// extensions and not all operating systems come with an up-to-date version // extensions and not all operating systems come with an up-to-date version
#include "../deps/EGL/eglext.h" #include "../deps/EGL/eglext.h"
// EGL function pointer typedefs
typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETCONFIGATTRIBPROC)(EGLDisplay,EGLConfig,EGLint,EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETCONFIGSPROC)(EGLDisplay,EGLConfig*,EGLint,EGLint*);
typedef EGLDisplay (EGLAPIENTRY * PFNEGLGETDISPLAYPROC)(EGLNativeDisplayType);
typedef EGLint (EGLAPIENTRY * PFNEGLGETERRORPROC)(void);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLINITIALIZEPROC)(EGLDisplay,EGLint*,EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLTERMINATEPROC)(EGLDisplay);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLBINDAPIPROC)(EGLenum);
typedef EGLContext (EGLAPIENTRY * PFNEGLCREATECONTEXTPROC)(EGLDisplay,EGLConfig,EGLContext,const EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYSURFACEPROC)(EGLDisplay,EGLSurface);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYCONTEXTPROC)(EGLDisplay,EGLContext);
typedef EGLSurface (EGLAPIENTRY * PFNEGLCREATEWINDOWSURFACEPROC)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLMAKECURRENTPROC)(EGLDisplay,EGLSurface,EGLSurface,EGLContext);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSWAPBUFFERSPROC)(EGLDisplay,EGLSurface);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSWAPINTERVALPROC)(EGLDisplay,EGLint);
typedef const char* (EGLAPIENTRY * PFNEGLQUERYSTRINGPROC)(EGLDisplay,EGLint);
typedef GLFWglproc (EGLAPIENTRY * PFNEGLGETPROCADDRESSPROC)(const char*);
#define _glfw_eglGetConfigAttrib _glfw.egl.GetConfigAttrib
#define _glfw_eglGetConfigs _glfw.egl.GetConfigs
#define _glfw_eglGetDisplay _glfw.egl.GetDisplay
#define _glfw_eglGetError _glfw.egl.GetError
#define _glfw_eglInitialize _glfw.egl.Initialize
#define _glfw_eglTerminate _glfw.egl.Terminate
#define _glfw_eglBindAPI _glfw.egl.BindAPI
#define _glfw_eglCreateContext _glfw.egl.CreateContext
#define _glfw_eglDestroySurface _glfw.egl.DestroySurface
#define _glfw_eglDestroyContext _glfw.egl.DestroyContext
#define _glfw_eglCreateWindowSurface _glfw.egl.CreateWindowSurface
#define _glfw_eglMakeCurrent _glfw.egl.MakeCurrent
#define _glfw_eglSwapBuffers _glfw.egl.SwapBuffers
#define _glfw_eglSwapInterval _glfw.egl.SwapInterval
#define _glfw_eglQueryString _glfw.egl.QueryString
#define _glfw_eglGetProcAddress _glfw.egl.GetProcAddress
#define _GLFW_PLATFORM_FBCONFIG EGLConfig egl #define _GLFW_PLATFORM_FBCONFIG EGLConfig egl
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextEGL egl #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextEGL egl
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryEGL egl #define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryEGL egl
@ -64,6 +109,25 @@ typedef struct _GLFWlibraryEGL
GLboolean KHR_create_context; GLboolean KHR_create_context;
void* handle;
PFNEGLGETCONFIGATTRIBPROC GetConfigAttrib;
PFNEGLGETCONFIGSPROC GetConfigs;
PFNEGLGETDISPLAYPROC GetDisplay;
PFNEGLGETERRORPROC GetError;
PFNEGLINITIALIZEPROC Initialize;
PFNEGLTERMINATEPROC Terminate;
PFNEGLBINDAPIPROC BindAPI;
PFNEGLCREATECONTEXTPROC CreateContext;
PFNEGLDESTROYSURFACEPROC DestroySurface;
PFNEGLDESTROYCONTEXTPROC DestroyContext;
PFNEGLCREATEWINDOWSURFACEPROC CreateWindowSurface;
PFNEGLMAKECURRENTPROC MakeCurrent;
PFNEGLSWAPBUFFERSPROC SwapBuffers;
PFNEGLSWAPINTERVALPROC SwapInterval;
PFNEGLQUERYSTRINGPROC QueryString;
PFNEGLGETPROCADDRESSPROC GetProcAddress;
} _GLFWlibraryEGL; } _GLFWlibraryEGL;