Commit 360c3d853a5e79c6ee28cb5e8199a43a6e7bd04e

Sam Lantinga 2013-10-21T00:15:24

Better cleanup if OpenGL initialization fails

diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c
index 39d94da..ccfb92e 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 201ba53..613bf4c 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 3cc6737..20d9913 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 */