Better cleanup if OpenGL initialization fails

This commit is contained in:
Sam Lantinga 2013-10-21 00:15:24 -07:00
parent 5697089d98
commit 360c3d853a
3 changed files with 44 additions and 45 deletions

View File

@ -91,17 +91,23 @@ SDL_EGL_GetProcAddress(_THIS, const char *proc)
void void
SDL_EGL_UnloadLibrary(_THIS) SDL_EGL_UnloadLibrary(_THIS)
{ {
if ((_this->egl_data) && (_this->gl_config.driver_loaded)) { if (_this->egl_data) {
if (_this->egl_data->egl_display) {
_this->egl_data->eglTerminate(_this->egl_data->egl_display); _this->egl_data->eglTerminate(_this->egl_data->egl_display);
_this->egl_data->egl_display = NULL;
}
if (_this->gl_config.dll_handle) {
dlclose(_this->gl_config.dll_handle); dlclose(_this->gl_config.dll_handle);
_this->gl_config.dll_handle = NULL;
}
if (_this->egl_data->egl_dll_handle) {
dlclose(_this->egl_data->egl_dll_handle); dlclose(_this->egl_data->egl_dll_handle);
_this->egl_data->egl_dll_handle = NULL;
}
SDL_free(_this->egl_data); SDL_free(_this->egl_data);
_this->egl_data = NULL; _this->egl_data = NULL;
_this->gl_config.dll_handle = NULL;
_this->gl_config.driver_loaded = 0;
} }
} }
@ -116,14 +122,16 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa
return SDL_SetError("OpenGL ES context already created"); return SDL_SetError("OpenGL ES context already created");
} }
/* Unload the old driver and reset the pointers */ _this->egl_data = (struct SDL_EGL_VideoData *) SDL_calloc(1, sizeof(SDL_EGL_VideoData));
SDL_EGL_UnloadLibrary(_this); if (!_this->egl_data) {
return SDL_OutOfMemory();
}
#ifdef RTLD_GLOBAL #ifdef RTLD_GLOBAL
dlopen_flags = RTLD_LAZY | RTLD_GLOBAL; dlopen_flags = RTLD_LAZY | RTLD_GLOBAL;
#else #else
dlopen_flags = RTLD_LAZY; dlopen_flags = RTLD_LAZY;
#endif #endif
/* A funny thing, loading EGL.so first does not work on the Raspberry, so we load libGL* first */ /* A funny thing, loading EGL.so first does not work on the Raspberry, so we load libGL* first */
path = getenv("SDL_VIDEO_GL_DRIVER"); path = getenv("SDL_VIDEO_GL_DRIVER");
@ -141,6 +149,7 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa
} }
} }
} }
_this->egl_data->egl_dll_handle = egl_dll_handle;
if (egl_dll_handle == NULL) { if (egl_dll_handle == NULL) {
return SDL_SetError("Could not initialize OpenGL ES library: %s", dlerror()); return SDL_SetError("Could not initialize OpenGL ES library: %s", dlerror());
@ -157,16 +166,12 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa
} }
dll_handle = dlopen(path, dlopen_flags); dll_handle = dlopen(path, dlopen_flags);
} }
_this->gl_config.dll_handle = dll_handle;
if (dll_handle == NULL) { if (dll_handle == NULL) {
return SDL_SetError("Could not load EGL library: %s", dlerror()); return SDL_SetError("Could not load EGL library: %s", dlerror());
} }
_this->egl_data = (struct SDL_EGL_VideoData *) SDL_calloc(1, sizeof(SDL_EGL_VideoData));
if (!_this->egl_data) {
return SDL_OutOfMemory();
}
/* Load new function pointers */ /* Load new function pointers */
LOAD_FUNC(eglGetDisplay); LOAD_FUNC(eglGetDisplay);
LOAD_FUNC(eglInitialize); LOAD_FUNC(eglInitialize);
@ -185,7 +190,6 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa
LOAD_FUNC(eglWaitGL); LOAD_FUNC(eglWaitGL);
_this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display); _this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display);
if (!_this->egl_data->egl_display) { if (!_this->egl_data->egl_display) {
return SDL_SetError("Could not get EGL display"); return SDL_SetError("Could not get EGL display");
} }

View File

@ -2339,6 +2339,10 @@ SDL_GL_LoadLibrary(const char *path)
} }
if (retval == 0) { if (retval == 0) {
++_this->gl_config.driver_loaded; ++_this->gl_config.driver_loaded;
} else {
if (_this->GL_UnloadLibrary) {
_this->GL_UnloadLibrary(_this);
}
} }
return (retval); return (retval);
} }

View File

@ -23,6 +23,7 @@
#if SDL_VIDEO_DRIVER_WINDOWS #if SDL_VIDEO_DRIVER_WINDOWS
#include "SDL_assert.h" #include "SDL_assert.h"
#include "SDL_loadso.h"
#include "SDL_windowsvideo.h" #include "SDL_windowsvideo.h"
/* WGL implementation of SDL OpenGL support */ /* WGL implementation of SDL OpenGL support */
@ -81,8 +82,7 @@ typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC,
int int
WIN_GL_LoadLibrary(_THIS, const char *path) WIN_GL_LoadLibrary(_THIS, const char *path)
{ {
LPTSTR wpath; void *handle;
HANDLE handle;
if (path == NULL) { if (path == NULL) {
path = SDL_getenv("SDL_OPENGL_LIBRARY"); path = SDL_getenv("SDL_OPENGL_LIBRARY");
@ -90,23 +90,15 @@ WIN_GL_LoadLibrary(_THIS, const char *path)
if (path == NULL) { if (path == NULL) {
path = DEFAULT_OPENGL; path = DEFAULT_OPENGL;
} }
wpath = WIN_UTF8ToString(path); _this->gl_config.dll_handle = SDL_LoadObject(path);
_this->gl_config.dll_handle = LoadLibrary(wpath);
SDL_free(wpath);
if (!_this->gl_config.dll_handle) { if (!_this->gl_config.dll_handle) {
char message[1024]; return -1;
SDL_snprintf(message, SDL_arraysize(message), "LoadLibrary(\"%s\")",
path);
return WIN_SetError(message);
} }
SDL_strlcpy(_this->gl_config.driver_path, path, SDL_strlcpy(_this->gl_config.driver_path, path,
SDL_arraysize(_this->gl_config.driver_path)); SDL_arraysize(_this->gl_config.driver_path));
/* Allocate OpenGL memory */ /* Allocate OpenGL memory */
_this->gl_data = _this->gl_data = (struct SDL_GLDriverData *) SDL_calloc(1, sizeof(struct SDL_GLDriverData));
(struct SDL_GLDriverData *) SDL_calloc(1,
sizeof(struct
SDL_GLDriverData));
if (!_this->gl_data) { if (!_this->gl_data) {
return SDL_OutOfMemory(); return SDL_OutOfMemory();
} }
@ -114,21 +106,20 @@ WIN_GL_LoadLibrary(_THIS, const char *path)
/* Load function pointers */ /* Load function pointers */
handle = _this->gl_config.dll_handle; handle = _this->gl_config.dll_handle;
_this->gl_data->wglGetProcAddress = (void *(WINAPI *) (const char *)) _this->gl_data->wglGetProcAddress = (void *(WINAPI *) (const char *))
GetProcAddress(handle, "wglGetProcAddress"); SDL_LoadFunction(handle, "wglGetProcAddress");
_this->gl_data->wglCreateContext = (HGLRC(WINAPI *) (HDC)) _this->gl_data->wglCreateContext = (HGLRC(WINAPI *) (HDC))
GetProcAddress(handle, "wglCreateContext"); SDL_LoadFunction(handle, "wglCreateContext");
_this->gl_data->wglDeleteContext = (BOOL(WINAPI *) (HGLRC)) _this->gl_data->wglDeleteContext = (BOOL(WINAPI *) (HGLRC))
GetProcAddress(handle, "wglDeleteContext"); SDL_LoadFunction(handle, "wglDeleteContext");
_this->gl_data->wglMakeCurrent = (BOOL(WINAPI *) (HDC, HGLRC)) _this->gl_data->wglMakeCurrent = (BOOL(WINAPI *) (HDC, HGLRC))
GetProcAddress(handle, "wglMakeCurrent"); SDL_LoadFunction(handle, "wglMakeCurrent");
_this->gl_data->wglShareLists = (BOOL(WINAPI *) (HGLRC, HGLRC)) _this->gl_data->wglShareLists = (BOOL(WINAPI *) (HGLRC, HGLRC))
GetProcAddress(handle, "wglShareLists"); SDL_LoadFunction(handle, "wglShareLists");
if (!_this->gl_data->wglGetProcAddress || if (!_this->gl_data->wglGetProcAddress ||
!_this->gl_data->wglCreateContext || !_this->gl_data->wglCreateContext ||
!_this->gl_data->wglDeleteContext || !_this->gl_data->wglDeleteContext ||
!_this->gl_data->wglMakeCurrent) { !_this->gl_data->wglMakeCurrent) {
SDL_UnloadObject(handle);
return SDL_SetError("Could not retrieve OpenGL functions"); return SDL_SetError("Could not retrieve OpenGL functions");
} }
@ -152,7 +143,7 @@ WIN_GL_GetProcAddress(_THIS, const char *proc)
void void
WIN_GL_UnloadLibrary(_THIS) WIN_GL_UnloadLibrary(_THIS)
{ {
FreeLibrary((HMODULE) _this->gl_config.dll_handle); SDL_UnloadObject(_this->gl_config.dll_handle);
_this->gl_config.dll_handle = NULL; _this->gl_config.dll_handle = NULL;
/* Free OpenGL memory */ /* Free OpenGL memory */