From 360c3d853a5e79c6ee28cb5e8199a43a6e7bd04e Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 21 Oct 2013 00:15:24 -0700 Subject: [PATCH] Better cleanup if OpenGL initialization fails --- src/video/SDL_egl.c | 52 ++++++++++++++------------- src/video/SDL_video.c | 6 +++- src/video/windows/SDL_windowsopengl.c | 31 ++++++---------- 3 files changed, 44 insertions(+), 45 deletions(-) diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c index 39d94daac8cfd..ccfb92e180dba 100644 --- a/src/video/SDL_egl.c +++ b/src/video/SDL_egl.c @@ -91,17 +91,23 @@ SDL_EGL_GetProcAddress(_THIS, const char *proc) void SDL_EGL_UnloadLibrary(_THIS) { - if ((_this->egl_data) && (_this->gl_config.driver_loaded)) { - _this->egl_data->eglTerminate(_this->egl_data->egl_display); - - dlclose(_this->gl_config.dll_handle); - dlclose(_this->egl_data->egl_dll_handle); + if (_this->egl_data) { + if (_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); + _this->gl_config.dll_handle = NULL; + } + if (_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); _this->egl_data = NULL; - - _this->gl_config.dll_handle = NULL; - _this->gl_config.driver_loaded = 0; } } @@ -115,16 +121,18 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa if (_this->egl_data) { return SDL_SetError("OpenGL ES context already created"); } - - /* Unload the old driver and reset the pointers */ - SDL_EGL_UnloadLibrary(_this); - - #ifdef RTLD_GLOBAL + + _this->egl_data = (struct SDL_EGL_VideoData *) SDL_calloc(1, sizeof(SDL_EGL_VideoData)); + if (!_this->egl_data) { + return SDL_OutOfMemory(); + } + +#ifdef RTLD_GLOBAL dlopen_flags = RTLD_LAZY | RTLD_GLOBAL; - #else +#else dlopen_flags = RTLD_LAZY; - #endif - +#endif + /* A funny thing, loading EGL.so first does not work on the Raspberry, so we load libGL* first */ path = getenv("SDL_VIDEO_GL_DRIVER"); egl_dll_handle = dlopen(path, dlopen_flags); @@ -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) { 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); } - + _this->gl_config.dll_handle = dll_handle; + if (dll_handle == NULL) { 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_FUNC(eglGetDisplay); LOAD_FUNC(eglInitialize); @@ -185,7 +190,6 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa LOAD_FUNC(eglWaitGL); _this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display); - if (!_this->egl_data->egl_display) { return SDL_SetError("Could not get EGL display"); } @@ -424,4 +428,4 @@ SDL_EGL_DestroySurface(_THIS, EGLSurface egl_surface) #endif /* SDL_VIDEO_OPENGL_EGL */ /* vi: set ts=4 sw=4 expandtab: */ - \ No newline at end of file + diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 201ba535d7ffa..613bf4cf6b3f4 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -2333,12 +2333,16 @@ SDL_GL_LoadLibrary(const char *path) retval = 0; } else { if (!_this->GL_LoadLibrary) { - return SDL_SetError("No dynamic GL support in video driver"); + return SDL_SetError("No dynamic GL support in video driver"); } retval = _this->GL_LoadLibrary(_this, path); } if (retval == 0) { ++_this->gl_config.driver_loaded; + } else { + if (_this->GL_UnloadLibrary) { + _this->GL_UnloadLibrary(_this); + } } return (retval); } diff --git a/src/video/windows/SDL_windowsopengl.c b/src/video/windows/SDL_windowsopengl.c index 3cc6737a1d91f..20d9913d873c1 100644 --- a/src/video/windows/SDL_windowsopengl.c +++ b/src/video/windows/SDL_windowsopengl.c @@ -23,6 +23,7 @@ #if SDL_VIDEO_DRIVER_WINDOWS #include "SDL_assert.h" +#include "SDL_loadso.h" #include "SDL_windowsvideo.h" /* WGL implementation of SDL OpenGL support */ @@ -81,8 +82,7 @@ typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, int WIN_GL_LoadLibrary(_THIS, const char *path) { - LPTSTR wpath; - HANDLE handle; + void *handle; if (path == NULL) { path = SDL_getenv("SDL_OPENGL_LIBRARY"); @@ -90,23 +90,15 @@ WIN_GL_LoadLibrary(_THIS, const char *path) if (path == NULL) { path = DEFAULT_OPENGL; } - wpath = WIN_UTF8ToString(path); - _this->gl_config.dll_handle = LoadLibrary(wpath); - SDL_free(wpath); + _this->gl_config.dll_handle = SDL_LoadObject(path); if (!_this->gl_config.dll_handle) { - char message[1024]; - SDL_snprintf(message, SDL_arraysize(message), "LoadLibrary(\"%s\")", - path); - return WIN_SetError(message); + return -1; } SDL_strlcpy(_this->gl_config.driver_path, path, SDL_arraysize(_this->gl_config.driver_path)); /* Allocate OpenGL memory */ - _this->gl_data = - (struct SDL_GLDriverData *) SDL_calloc(1, - sizeof(struct - SDL_GLDriverData)); + _this->gl_data = (struct SDL_GLDriverData *) SDL_calloc(1, sizeof(struct SDL_GLDriverData)); if (!_this->gl_data) { return SDL_OutOfMemory(); } @@ -114,21 +106,20 @@ WIN_GL_LoadLibrary(_THIS, const char *path) /* Load function pointers */ handle = _this->gl_config.dll_handle; _this->gl_data->wglGetProcAddress = (void *(WINAPI *) (const char *)) - GetProcAddress(handle, "wglGetProcAddress"); + SDL_LoadFunction(handle, "wglGetProcAddress"); _this->gl_data->wglCreateContext = (HGLRC(WINAPI *) (HDC)) - GetProcAddress(handle, "wglCreateContext"); + SDL_LoadFunction(handle, "wglCreateContext"); _this->gl_data->wglDeleteContext = (BOOL(WINAPI *) (HGLRC)) - GetProcAddress(handle, "wglDeleteContext"); + SDL_LoadFunction(handle, "wglDeleteContext"); _this->gl_data->wglMakeCurrent = (BOOL(WINAPI *) (HDC, HGLRC)) - GetProcAddress(handle, "wglMakeCurrent"); + SDL_LoadFunction(handle, "wglMakeCurrent"); _this->gl_data->wglShareLists = (BOOL(WINAPI *) (HGLRC, HGLRC)) - GetProcAddress(handle, "wglShareLists"); + SDL_LoadFunction(handle, "wglShareLists"); if (!_this->gl_data->wglGetProcAddress || !_this->gl_data->wglCreateContext || !_this->gl_data->wglDeleteContext || !_this->gl_data->wglMakeCurrent) { - SDL_UnloadObject(handle); return SDL_SetError("Could not retrieve OpenGL functions"); } @@ -152,7 +143,7 @@ WIN_GL_GetProcAddress(_THIS, const char *proc) void WIN_GL_UnloadLibrary(_THIS) { - FreeLibrary((HMODULE) _this->gl_config.dll_handle); + SDL_UnloadObject(_this->gl_config.dll_handle); _this->gl_config.dll_handle = NULL; /* Free OpenGL memory */