changeset 3057:089a77aebb7d

Added test program for SDL_CreateWindowFrom() Make sure OpenGL library is loaded before working with OpenGL windows, even those created with SDL_CreateWindowFrom()
author Sam Lantinga <slouken@libsdl.org>
date Mon, 09 Feb 2009 05:32:12 +0000
parents a434fe6360df
children 17c5930f498e
files include/SDL_video.h src/video/SDL_sysvideo.h src/video/SDL_video.c src/video/cocoa/SDL_cocoaopengl.h src/video/cocoa/SDL_cocoaopengl.m src/video/cocoa/SDL_cocoavideo.m src/video/cocoa/SDL_cocoawindow.m src/video/win32/SDL_win32opengl.c src/video/win32/SDL_win32opengl.h src/video/win32/SDL_win32video.c src/video/win32/SDL_win32window.c src/video/x11/SDL_x11opengl.c src/video/x11/SDL_x11opengl.h src/video/x11/SDL_x11video.c src/video/x11/SDL_x11window.c test/testnative.c test/testnativecocoa.m test/testnativew32.c test/testnativex11.c
diffstat 19 files changed, 513 insertions(+), 287 deletions(-) [+]
line wrap: on
line diff
--- a/include/SDL_video.h	Sun Feb 08 15:35:06 2009 +0000
+++ b/include/SDL_video.h	Mon Feb 09 05:32:12 2009 +0000
@@ -111,7 +111,8 @@
     SDL_WINDOW_MAXIMIZED = 0x00000040,          /**< maximized */
     SDL_WINDOW_INPUT_GRABBED = 0x00000100,      /**< window has grabbed input focus */
     SDL_WINDOW_INPUT_FOCUS = 0x00000200,        /**< window has input focus */
-    SDL_WINDOW_MOUSE_FOCUS = 0x00000400         /**< window has mouse focus */
+    SDL_WINDOW_MOUSE_FOCUS = 0x00000400,        /**< window has mouse focus */
+    SDL_WINDOW_FOREIGN = 0x00000800             /**< window not created by SDL */
 } SDL_WindowFlags;
 
 /**
@@ -1363,6 +1364,7 @@
  *       your program from the dynamic library using SDL_GL_GetProcAddress().
  *
  * \sa SDL_GL_GetProcAddress()
+ * \sa SDL_GL_UnloadLibrary()
  */
 extern DECLSPEC int SDLCALL SDL_GL_LoadLibrary(const char *path);
 
@@ -1374,6 +1376,15 @@
 extern DECLSPEC void *SDLCALL SDL_GL_GetProcAddress(const char *proc);
 
 /**
+ * \fn void SDL_GL_UnloadLibrary(void)
+ *
+ * \brief Unload the OpenGL library previously loaded by SDL_GL_LoadLibrary()
+ *
+ * \sa SDL_GL_LoadLibrary()
+ */
+extern DECLSPEC void SDLCALL SDL_GL_UnloadLibrary(void);
+
+/**
  * \fn SDL_bool SDL_GL_ExtensionSupported(const char *extension)
  *
  * \brief Return true if an OpenGL extension is supported for the current context.
--- a/src/video/SDL_sysvideo.h	Sun Feb 08 15:35:06 2009 +0000
+++ b/src/video/SDL_sysvideo.h	Mon Feb 09 05:32:12 2009 +0000
@@ -260,6 +260,7 @@
      */
     int (*GL_LoadLibrary) (_THIS, const char *path);
     void *(*GL_GetProcAddress) (_THIS, const char *proc);
+    void (*GL_UnloadLibrary) (_THIS);
       SDL_GLContext(*GL_CreateContext) (_THIS, SDL_Window * window);
     int (*GL_MakeCurrent) (_THIS, SDL_Window * window, SDL_GLContext context);
     int (*GL_SetSwapInterval) (_THIS, int interval);
--- a/src/video/SDL_video.c	Sun Feb 08 15:35:06 2009 +0000
+++ b/src/video/SDL_video.c	Mon Feb 09 05:32:12 2009 +0000
@@ -762,9 +762,12 @@
         SDL_UninitializedVideo();
         return 0;
     }
-    if ((flags & SDL_WINDOW_OPENGL) && !_this->GL_CreateContext) {
-        SDL_SetError("No OpenGL support in video driver");
-        return 0;
+    if (flags & SDL_WINDOW_OPENGL) {
+        if (!_this->GL_CreateContext) {
+            SDL_SetError("No OpenGL support in video driver");
+            return 0;
+        }
+        SDL_GL_LoadLibrary(NULL);
     }
     SDL_zero(window);
     window.id = _this->next_object_id++;
@@ -776,6 +779,9 @@
     window.display = _this->current_display;
 
     if (_this->CreateWindow && _this->CreateWindow(_this, &window) < 0) {
+        if (flags & SDL_WINDOW_OPENGL) {
+            SDL_GL_UnloadLibrary();
+        }
         return 0;
     }
     display = &SDL_CurrentDisplay;
@@ -786,6 +792,9 @@
         if (_this->DestroyWindow) {
             _this->DestroyWindow(_this, &window);
         }
+        if (flags & SDL_WINDOW_OPENGL) {
+            SDL_GL_UnloadLibrary();
+        }
         return 0;
     }
     windows[num_windows] = window;
@@ -824,6 +833,7 @@
     SDL_zero(window);
     window.id = _this->next_object_id++;
     window.display = _this->current_display;
+    window.flags = SDL_WINDOW_FOREIGN;
 
     if (!_this->CreateWindowFrom ||
         _this->CreateWindowFrom(_this, &window, data) < 0) {
@@ -852,24 +862,48 @@
 int
 SDL_RecreateWindow(SDL_Window * window, Uint32 flags)
 {
+    const Uint32 allowed_flags = (SDL_WINDOW_FULLSCREEN |
+                                  SDL_WINDOW_OPENGL |
+                                  SDL_WINDOW_BORDERLESS |
+                                  SDL_WINDOW_RESIZABLE |
+                                  SDL_WINDOW_INPUT_GRABBED);
     char *title = window->title;
 
     if ((flags & SDL_WINDOW_OPENGL) && !_this->GL_CreateContext) {
         SDL_SetError("No OpenGL support in video driver");
         return -1;
     }
-    if (_this->DestroyWindow) {
+    if ((window->flags & SDL_WINDOW_OPENGL) != (flags & SDL_WINDOW_OPENGL)) {
+        if (flags & SDL_WINDOW_OPENGL) {
+            SDL_GL_LoadLibrary(NULL);
+        } else {
+            SDL_GL_UnloadLibrary();
+        }
+    }
+
+    if (window->flags & SDL_WINDOW_FOREIGN) {
+        /* Can't destroy and re-create foreign windows, hrm */
+        flags |= SDL_WINDOW_FOREIGN;
+    } else {
+        flags &= ~SDL_WINDOW_FOREIGN;
+    }
+
+    if (_this->DestroyWindow && !(flags & SDL_WINDOW_FOREIGN)) {
         _this->DestroyWindow(_this, window);
     }
+
     window->title = NULL;
-    window->flags =
-        (flags &
-         ~(SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED | SDL_WINDOW_SHOWN |
-           SDL_WINDOW_INPUT_GRABBED));
+    window->flags = (flags & allowed_flags);
 
-    if (_this->CreateWindow && _this->CreateWindow(_this, window) < 0) {
-        return -1;
+    if (_this->CreateWindow && !(flags & SDL_WINDOW_FOREIGN)) {
+        if (_this->CreateWindow(_this, window) < 0) {
+            if (flags & SDL_WINDOW_OPENGL) {
+                SDL_GL_UnloadLibrary();
+            }
+            return -1;
+        }
     }
+
     if (title) {
         SDL_SetWindowTitle(window->id, title);
         SDL_free(title);
@@ -1352,6 +1386,9 @@
             if (_this->DestroyWindow) {
                 _this->DestroyWindow(_this, window);
             }
+            if (window->flags & SDL_WINDOW_OPENGL) {
+                SDL_GL_UnloadLibrary();
+            }
             if (j != display->num_windows - 1) {
                 SDL_memcpy(&display->windows[i],
                            &display->windows[i + 1],
@@ -1543,6 +1580,7 @@
 SDL_CreateTextureFromSurface(Uint32 format, SDL_Surface * surface)
 {
     SDL_TextureID textureID;
+    Uint32 requested_format = format;
     SDL_PixelFormat *fmt;
     int bpp;
     Uint32 Rmask, Gmask, Bmask, Amask;
@@ -1586,6 +1624,14 @@
     textureID =
         SDL_CreateTexture(format, SDL_TEXTUREACCESS_STATIC, surface->w,
                           surface->h);
+    if (!textureID && !requested_format) {
+        SDL_DisplayMode desktop_mode;
+        SDL_GetDesktopDisplayMode(&desktop_mode);
+        format = desktop_mode.format;
+        textureID =
+            SDL_CreateTexture(format, SDL_TEXTUREACCESS_STATIC, surface->w,
+                              surface->h);
+    }
     if (!textureID) {
         return 0;
     }
@@ -2460,11 +2506,21 @@
         SDL_UninitializedVideo();
         return -1;
     }
-    if (_this->GL_LoadLibrary) {
-        retval = _this->GL_LoadLibrary(_this, path);
+    if (_this->gl_config.driver_loaded) {
+        if (path && SDL_strcmp(path, _this->gl_config.driver_path) != 0) {
+            SDL_SetError("OpenGL library already loaded");
+            return -1;
+        }
+        retval = 0;
     } else {
-        SDL_SetError("No dynamic GL support in video driver");
-        retval = -1;
+        if (!_this->GL_LoadLibrary) {
+            SDL_SetError("No dynamic GL support in video driver");
+            return -1;
+        }
+        retval = _this->GL_LoadLibrary(_this, path);
+    }
+    if (retval == 0) {
+        ++_this->gl_config.driver_loaded;
     }
     return (retval);
 }
@@ -2491,6 +2547,23 @@
     return func;
 }
 
+void
+SDL_GL_UnloadLibrary(void)
+{
+    if (!_this) {
+        SDL_UninitializedVideo();
+        return;
+    }
+    if (_this->gl_config.driver_loaded > 0) {
+        if (--_this->gl_config.driver_loaded > 0) {
+            return;
+        }
+        if (_this->GL_UnloadLibrary) {
+            _this->GL_UnloadLibrary(_this);
+        }
+    }
+}
+
 SDL_bool
 SDL_GL_ExtensionSupported(const char *extension)
 {
--- a/src/video/cocoa/SDL_cocoaopengl.h	Sun Feb 08 15:35:06 2009 +0000
+++ b/src/video/cocoa/SDL_cocoaopengl.h	Mon Feb 09 05:32:12 2009 +0000
@@ -34,8 +34,7 @@
 /* OpenGL functions */
 extern int Cocoa_GL_LoadLibrary(_THIS, const char *path);
 extern void *Cocoa_GL_GetProcAddress(_THIS, const char *proc);
-extern int Cocoa_GL_SetupWindow(_THIS, SDL_Window * window);
-extern void Cocoa_GL_CleanupWindow(_THIS, SDL_Window * window);
+extern void Cocoa_GL_UnloadLibrary(_THIS);
 extern SDL_GLContext Cocoa_GL_CreateContext(_THIS, SDL_Window * window);
 extern int Cocoa_GL_MakeCurrent(_THIS, SDL_Window * window,
                                 SDL_GLContext context);
--- a/src/video/cocoa/SDL_cocoaopengl.m	Sun Feb 08 15:35:06 2009 +0000
+++ b/src/video/cocoa/SDL_cocoaopengl.m	Mon Feb 09 05:32:12 2009 +0000
@@ -48,15 +48,7 @@
 int
 Cocoa_GL_LoadLibrary(_THIS, const char *path)
 {
-    if (_this->gl_config.driver_loaded) {
-        if (path) {
-            SDL_SetError("OpenGL library already loaded");
-            return -1;
-        } else {
-            ++_this->gl_config.driver_loaded;
-            return 0;
-        }
-    }
+    /* Load the OpenGL library */
     if (path == NULL) {
         path = SDL_getenv("SDL_OPENGL_LIBRARY");
     }
@@ -69,7 +61,6 @@
     }
     SDL_strlcpy(_this->gl_config.driver_path, path,
                 SDL_arraysize(_this->gl_config.driver_path));
-    _this->gl_config.driver_loaded = 1;
     return 0;
 }
 
@@ -79,68 +70,11 @@
     return SDL_LoadFunction(_this->gl_config.dll_handle, proc);
 }
 
-static void
+void
 Cocoa_GL_UnloadLibrary(_THIS)
 {
-    if (_this->gl_config.driver_loaded > 0) {
-        if (--_this->gl_config.driver_loaded > 0) {
-            return;
-        }
-        SDL_UnloadObject(_this->gl_config.dll_handle);
-        _this->gl_config.dll_handle = NULL;
-    }
-}
-
-static int
-Cocoa_GL_Initialize(_THIS)
-{
-    if (_this->gl_data) {
-        ++_this->gl_data->initialized;
-        return 0;
-    }
-
-    _this->gl_data =
-        (struct SDL_GLDriverData *) SDL_calloc(1,
-                                               sizeof(struct
-                                                      SDL_GLDriverData));
-    if (!_this->gl_data) {
-        SDL_OutOfMemory();
-        return -1;
-    }
-    _this->gl_data->initialized = 1;
-
-    if (Cocoa_GL_LoadLibrary(_this, NULL) < 0) {
-        return -1;
-    }
-    return 0;
-}
-
-static void
-Cocoa_GL_Shutdown(_THIS)
-{
-    if (!_this->gl_data || (--_this->gl_data->initialized > 0)) {
-        return;
-    }
-
-    Cocoa_GL_UnloadLibrary(_this);
-
-    SDL_free(_this->gl_data);
-    _this->gl_data = NULL;
-}
-
-int
-Cocoa_GL_SetupWindow(_THIS, SDL_Window * window)
-{
-    if (Cocoa_GL_Initialize(_this) < 0) {
-        return -1;
-    }
-    return 0;
-}
-
-void
-Cocoa_GL_CleanupWindow(_THIS, SDL_Window * window)
-{
-    Cocoa_GL_Shutdown(_this);
+    SDL_UnloadObject(_this->gl_config.dll_handle);
+    _this->gl_config.dll_handle = NULL;
 }
 
 SDL_GLContext
--- a/src/video/cocoa/SDL_cocoavideo.m	Sun Feb 08 15:35:06 2009 +0000
+++ b/src/video/cocoa/SDL_cocoavideo.m	Mon Feb 09 05:32:12 2009 +0000
@@ -93,6 +93,7 @@
 #ifdef SDL_VIDEO_OPENGL_CGL
     device->GL_LoadLibrary = Cocoa_GL_LoadLibrary;
     device->GL_GetProcAddress = Cocoa_GL_GetProcAddress;
+    device->GL_UnloadLibrary = Cocoa_GL_UnloadLibrary;
     device->GL_CreateContext = Cocoa_GL_CreateContext;
     device->GL_MakeCurrent = Cocoa_GL_MakeCurrent;
     device->GL_SetSwapInterval = Cocoa_GL_SetSwapInterval;
--- a/src/video/cocoa/SDL_cocoawindow.m	Sun Feb 08 15:35:06 2009 +0000
+++ b/src/video/cocoa/SDL_cocoawindow.m	Mon Feb 09 05:32:12 2009 +0000
@@ -422,14 +422,6 @@
         [nswindow release];
         return -1;
     }
-#ifdef SDL_VIDEO_OPENGL_CGL
-    if (window->flags & SDL_WINDOW_OPENGL) {
-        if (Cocoa_GL_SetupWindow(_this, window) < 0) {
-            Cocoa_DestroyWindow(_this, window);
-            return -1;
-        }
-    }
-#endif
     return 0;
 }
 
@@ -586,11 +578,6 @@
     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
 
     if (data) {
-#ifdef SDL_VIDEO_OPENGL_CGL
-        if (window->flags & SDL_WINDOW_OPENGL) {
-            Cocoa_GL_CleanupWindow(_this, window);
-        }
-#endif
         [data->listener close];
         [data->listener release];
         if (data->created) {
--- a/src/video/win32/SDL_win32opengl.c	Sun Feb 08 15:35:06 2009 +0000
+++ b/src/video/win32/SDL_win32opengl.c	Mon Feb 09 05:32:12 2009 +0000
@@ -37,15 +37,6 @@
     LPTSTR wpath;
     HANDLE handle;
 
-    if (_this->gl_config.driver_loaded) {
-        if (path) {
-            SDL_SetError("OpenGL library already loaded");
-            return -1;
-        } else {
-            ++_this->gl_config.driver_loaded;
-            return 0;
-        }
-    }
     if (path == NULL) {
         path = SDL_getenv("SDL_OPENGL_LIBRARY");
     }
@@ -53,17 +44,30 @@
         path = DEFAULT_OPENGL;
     }
     wpath = WIN_UTF8ToString(path);
-    handle = LoadLibrary(wpath);
+    _this->gl_config.dll_handle = LoadLibrary(wpath);
     SDL_free(wpath);
-    if (!handle) {
+    if (!_this->gl_config.dll_handle) {
         char message[1024];
         SDL_snprintf(message, SDL_arraysize(message), "LoadLibrary(\"%s\")",
                      path);
         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));
+    if (!_this->gl_data) {
+        SDL_OutOfMemory();
+        return -1;
+    }
 
     /* Load function pointers */
+    handle = _this->gl_config.dll_handle;
     _this->gl_data->wglGetProcAddress = (void *(WINAPI *) (const char *))
         GetProcAddress(handle, "wglGetProcAddress");
     _this->gl_data->wglCreateContext = (HGLRC(WINAPI *) (HDC))
@@ -86,10 +90,6 @@
         return -1;
     }
 
-    _this->gl_config.dll_handle = handle;
-    SDL_strlcpy(_this->gl_config.driver_path, path,
-                SDL_arraysize(_this->gl_config.driver_path));
-    _this->gl_config.driver_loaded = 1;
     return 0;
 }
 
@@ -107,16 +107,15 @@
     return func;
 }
 
-static void
+void
 WIN_GL_UnloadLibrary(_THIS)
 {
-    if (_this->gl_config.driver_loaded > 0) {
-        if (--_this->gl_config.driver_loaded > 0) {
-            return;
-        }
-        FreeLibrary((HMODULE) _this->gl_config.dll_handle);
-        _this->gl_config.dll_handle = NULL;
-    }
+    FreeLibrary((HMODULE) _this->gl_config.dll_handle);
+    _this->gl_config.dll_handle = NULL;
+
+    /* Free OpenGL memory */
+    SDL_free(_this->gl_data);
+    _this->gl_data = NULL;
 }
 
 static void
@@ -378,44 +377,6 @@
     return pixel_format;
 }
 
-static int
-WIN_GL_Initialize(_THIS)
-{
-    if (_this->gl_data) {
-        ++_this->gl_data->initialized;
-        return 0;
-    }
-
-    _this->gl_data =
-        (struct SDL_GLDriverData *) SDL_calloc(1,
-                                               sizeof(struct
-                                                      SDL_GLDriverData));
-    if (!_this->gl_data) {
-        SDL_OutOfMemory();
-        return -1;
-    }
-    _this->gl_data->initialized = 1;
-
-    if (WIN_GL_LoadLibrary(_this, NULL) < 0) {
-        return -1;
-    }
-
-    return 0;
-}
-
-static void
-WIN_GL_Shutdown(_THIS)
-{
-    if (!_this->gl_data || (--_this->gl_data->initialized > 0)) {
-        return;
-    }
-
-    WIN_GL_UnloadLibrary(_this);
-
-    SDL_free(_this->gl_data);
-    _this->gl_data = NULL;
-}
-
 int
 WIN_GL_SetupWindow(_THIS, SDL_Window * window)
 {
@@ -426,10 +387,6 @@
     int *iAttr;
     float fAttribs[1] = { 0 };
 
-    if (WIN_GL_Initialize(_this) < 0) {
-        return -1;
-    }
-
     WIN_GL_SetupPixelFormat(_this, &pfd);
 
     /* setup WGL_ARB_pixel_format attribs */
@@ -522,12 +479,6 @@
     return 0;
 }
 
-void
-WIN_GL_CleanupWindow(_THIS, SDL_Window * window)
-{
-    WIN_GL_Shutdown(_this);
-}
-
 SDL_GLContext
 WIN_GL_CreateContext(_THIS, SDL_Window * window)
 {
--- a/src/video/win32/SDL_win32opengl.h	Sun Feb 08 15:35:06 2009 +0000
+++ b/src/video/win32/SDL_win32opengl.h	Mon Feb 09 05:32:12 2009 +0000
@@ -28,7 +28,6 @@
 
 struct SDL_GLDriverData
 {
-    int initialized;
     int WGL_ARB_pixel_format;
 
     void *(WINAPI * wglGetProcAddress) (const char *proc);
@@ -53,8 +52,8 @@
 /* OpenGL functions */
 extern int WIN_GL_LoadLibrary(_THIS, const char *path);
 extern void *WIN_GL_GetProcAddress(_THIS, const char *proc);
+extern void WIN_GL_UnloadLibrary(_THIS);
 extern int WIN_GL_SetupWindow(_THIS, SDL_Window * window);
-extern void WIN_GL_CleanupWindow(_THIS, SDL_Window * window);
 extern SDL_GLContext WIN_GL_CreateContext(_THIS, SDL_Window * window);
 extern int WIN_GL_MakeCurrent(_THIS, SDL_Window * window,
                               SDL_GLContext context);
--- a/src/video/win32/SDL_win32video.c	Sun Feb 08 15:35:06 2009 +0000
+++ b/src/video/win32/SDL_win32video.c	Mon Feb 09 05:32:12 2009 +0000
@@ -161,6 +161,7 @@
 #ifdef SDL_VIDEO_OPENGL_WGL
     device->GL_LoadLibrary = WIN_GL_LoadLibrary;
     device->GL_GetProcAddress = WIN_GL_GetProcAddress;
+    device->GL_UnloadLibrary = WIN_GL_UnloadLibrary;
     device->GL_CreateContext = WIN_GL_CreateContext;
     device->GL_MakeCurrent = WIN_GL_MakeCurrent;
     device->GL_SetSwapInterval = WIN_GL_SetSwapInterval;
--- a/src/video/win32/SDL_win32window.c	Sun Feb 08 15:35:06 2009 +0000
+++ b/src/video/win32/SDL_win32window.c	Mon Feb 09 05:32:12 2009 +0000
@@ -521,11 +521,6 @@
     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
 
     if (data) {
-#ifdef SDL_VIDEO_OPENGL_WGL
-        if (window->flags & SDL_WINDOW_OPENGL) {
-            WIN_GL_CleanupWindow(_this, window);
-        }
-#endif
         ReleaseDC(data->hwnd, data->hdc);
         if (data->created) {
             if (videodata->wintabDLL) {
--- a/src/video/x11/SDL_x11opengl.c	Sun Feb 08 15:35:06 2009 +0000
+++ b/src/video/x11/SDL_x11opengl.c	Mon Feb 09 05:32:12 2009 +0000
@@ -65,37 +65,39 @@
 #define GL_UnloadObject	SDL_UnloadObject
 #endif
 
-static int X11_GL_InitializeMemory(_THIS);
+static void X11_GL_InitExtensions(_THIS);
 
 int
 X11_GL_LoadLibrary(_THIS, const char *path)
 {
     void *handle;
 
-    if (_this->gl_config.driver_loaded) {
-        /* do not return without reinitializing the function hooks */
-        if (path) {
-            SDL_SetError("OpenGL library already loaded");
-        }
-        handle = _this->gl_config.dll_handle;
-    } else {
-        if (path == NULL) {
-            path = SDL_getenv("SDL_OPENGL_LIBRARY");
-        }
-        if (path == NULL) {
-            path = DEFAULT_OPENGL;
-        }
-        handle = GL_LoadObject(path);
-        if (!handle) {
-            return -1;
-        }
-        _this->gl_config.dll_handle = handle;
-        SDL_strlcpy(_this->gl_config.driver_path, path,
-                    SDL_arraysize(_this->gl_config.driver_path));
+    /* Load the OpenGL library */
+    if (path == NULL) {
+        path = SDL_getenv("SDL_OPENGL_LIBRARY");
+    }
+    if (path == NULL) {
+        path = DEFAULT_OPENGL;
+    }
+    _this->gl_config.dll_handle = SDL_LoadObject(path);
+    if (!_this->gl_config.dll_handle) {
+        return -1;
     }
-    X11_GL_InitializeMemory(_this);
+    SDL_strlcpy(_this->gl_config.driver_path, path,
+                SDL_arraysize(_this->gl_config.driver_path));
 
-    /* Load new function pointers */
+    /* Allocate OpenGL memory */
+    _this->gl_data =
+        (struct SDL_GLDriverData *) SDL_calloc(1,
+                                               sizeof(struct
+                                                      SDL_GLDriverData));
+    if (!_this->gl_data) {
+        SDL_OutOfMemory();
+        return -1;
+    }
+
+    /* Load function pointers */
+    handle = _this->gl_config.dll_handle;
     _this->gl_data->glXGetProcAddress =
         (void *(*)(const GLubyte *)) GL_LoadFunction(handle,
                                                      "glXGetProcAddressARB");
@@ -123,7 +125,9 @@
         return -1;
     }
 
-    ++_this->gl_config.driver_loaded;
+    /* Initialize extensions */
+    X11_GL_InitExtensions(_this);
+
     return 0;
 }
 
@@ -139,16 +143,21 @@
     return GL_LoadFunction(handle, proc);
 }
 
-static void
+void
 X11_GL_UnloadLibrary(_THIS)
 {
-    if (_this->gl_config.driver_loaded > 0) {
-        if (--_this->gl_config.driver_loaded > 0) {
-            return;
-        }
-        GL_UnloadObject(_this->gl_config.dll_handle);
-        _this->gl_config.dll_handle = NULL;
-    }
+    /* Don't actually unload the library, since it may have registered
+     * X11 shutdown hooks, per the notes at:
+     * http://dri.sourceforge.net/doc/DRIuserguide.html
+     */
+#if 0
+    GL_UnloadObject(_this->gl_config.dll_handle);
+    _this->gl_config.dll_handle = NULL;
+#endif
+
+    /* Free OpenGL memory */
+    SDL_free(_this->gl_data);
+    _this->gl_data = NULL;
 }
 
 static SDL_bool
@@ -254,62 +263,6 @@
     X11_PumpEvents(_this);
 }
 
-static int
-X11_GL_InitializeMemory(_THIS)
-{
-    if (_this->gl_data) {
-        return 0;
-    }
-
-    _this->gl_data =
-        (struct SDL_GLDriverData *) SDL_calloc(1,
-                                               sizeof(struct
-                                                      SDL_GLDriverData));
-    if (!_this->gl_data) {
-        SDL_OutOfMemory();
-        return -1;
-    }
-    _this->gl_data->initialized = 0;
-
-    return 0;
-}
-
-int
-X11_GL_Initialize(_THIS)
-{
-
-    if (X11_GL_InitializeMemory(_this) < 0) {
-        return -1;
-    }
-    ++_this->gl_data->initialized;
-
-    if (X11_GL_LoadLibrary(_this, NULL) < 0) {
-        return -1;
-    }
-
-    /* Initialize extensions */
-    X11_GL_InitExtensions(_this);
-
-    return 0;
-}
-
-void
-X11_GL_Shutdown(_THIS)
-{
-    if (!_this->gl_data || (--_this->gl_data->initialized > 0)) {
-        return;
-    }
-
-    /* Don't actually unload the library, since it may have registered
-     * X11 shutdown hooks, per the notes at:
-     * http://dri.sourceforge.net/doc/DRIuserguide.html
-     * //X11_GL_UnloadLibrary(_this);
-     */
-
-    SDL_free(_this->gl_data);
-    _this->gl_data = NULL;
-}
-
 XVisualInfo *
 X11_GL_GetVisual(_THIS, Display * display, int screen)
 {
--- a/src/video/x11/SDL_x11opengl.h	Sun Feb 08 15:35:06 2009 +0000
+++ b/src/video/x11/SDL_x11opengl.h	Mon Feb 09 05:32:12 2009 +0000
@@ -30,7 +30,6 @@
 
 struct SDL_GLDriverData
 {
-    int initialized;
     SDL_bool HAS_GLX_EXT_visual_rating;
 
     void *(*glXGetProcAddress) (const GLubyte * procName);
@@ -58,8 +57,7 @@
 /* OpenGL functions */
 extern int X11_GL_LoadLibrary(_THIS, const char *path);
 extern void *X11_GL_GetProcAddress(_THIS, const char *proc);
-extern int X11_GL_Initialize(_THIS);
-extern void X11_GL_Shutdown(_THIS);
+extern void X11_GL_UnloadLibrary(_THIS);
 extern XVisualInfo *X11_GL_GetVisual(_THIS, Display * display, int screen);
 extern SDL_GLContext X11_GL_CreateContext(_THIS, SDL_Window * window);
 extern int X11_GL_MakeCurrent(_THIS, SDL_Window * window,
--- a/src/video/x11/SDL_x11video.c	Sun Feb 08 15:35:06 2009 +0000
+++ b/src/video/x11/SDL_x11video.c	Mon Feb 09 05:32:12 2009 +0000
@@ -190,6 +190,7 @@
 #ifdef SDL_VIDEO_OPENGL_GLX
     device->GL_LoadLibrary = X11_GL_LoadLibrary;
     device->GL_GetProcAddress = X11_GL_GetProcAddress;
+    device->GL_UnloadLibrary = X11_GL_UnloadLibrary;
     device->GL_CreateContext = X11_GL_CreateContext;
     device->GL_MakeCurrent = X11_GL_MakeCurrent;
     device->GL_SetSwapInterval = X11_GL_SetSwapInterval;
--- a/src/video/x11/SDL_x11window.c	Sun Feb 08 15:35:06 2009 +0000
+++ b/src/video/x11/SDL_x11window.c	Mon Feb 09 05:32:12 2009 +0000
@@ -188,9 +188,6 @@
     if (window->flags & SDL_WINDOW_OPENGL) {
         XVisualInfo *vinfo;
 
-        if (X11_GL_Initialize(_this) < 0) {
-            return -1;
-        }
         vinfo = X11_GL_GetVisual(_this, data->display, displaydata->screen);
         if (!vinfo) {
             return -1;
@@ -461,11 +458,6 @@
                       (CWOverrideRedirect | CWBackPixel | CWBorderPixel |
                        CWColormap), &xattr);
     if (!w) {
-#ifdef SDL_VIDEO_OPENGL_GLX
-        if (window->flags & SDL_WINDOW_OPENGL) {
-            X11_GL_Shutdown(_this);
-        }
-#endif
         SDL_SetError("Couldn't create window");
         return -1;
     }
@@ -622,11 +614,6 @@
     XSetWMProtocols(data->display, w, &data->WM_DELETE_WINDOW, 1);
 
     if (SetupWindowData(_this, window, w, SDL_TRUE) < 0) {
-#ifdef SDL_VIDEO_OPENGL_GLX
-        if (window->flags & SDL_WINDOW_OPENGL) {
-            X11_GL_Shutdown(_this);
-        }
-#endif
         XDestroyWindow(data->display, w);
         return -1;
     }
@@ -942,11 +929,6 @@
                 }
             }
         }
-#ifdef SDL_VIDEO_OPENGL_GLX
-        if (window->flags & SDL_WINDOW_OPENGL) {
-            X11_GL_Shutdown(_this);
-        }
-#endif
 #ifdef X_HAVE_UTF8_STRING
         if (data->ic) {
             XDestroyIC(data->ic);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testnative.c	Mon Feb 09 05:32:12 2009 +0000
@@ -0,0 +1,219 @@
+/* Simple program:  Create a native window and attach an SDL renderer */
+
+#include "testnative.h"
+
+#define WINDOW_W    640
+#define WINDOW_H    480
+#define NUM_SPRITES 100
+#define MAX_SPEED 	1
+
+static NativeWindowFactory *factories[] = {
+#ifdef TEST_NATIVE_WIN32
+    &Win32WindowFactory,
+#endif
+#ifdef TEST_NATIVE_X11
+    &X11WindowFactory,
+#endif
+#ifdef TEST_NATIVE_COCOA
+    &CocoaWindowFactory,
+#endif
+    NULL
+};
+static NativeWindowFactory *factory = NULL;
+static void *native_window;
+static SDL_Rect *positions, *velocities;
+
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void
+quit(int rc)
+{
+    SDL_VideoQuit();
+    if (native_window) {
+        factory->DestroyWindow(native_window);
+    }
+    exit(rc);
+}
+
+SDL_TextureID
+LoadSprite(SDL_WindowID window, char *file)
+{
+    SDL_Surface *temp;
+    SDL_TextureID sprite;
+
+    /* Load the sprite image */
+    temp = SDL_LoadBMP(file);
+    if (temp == NULL) {
+        fprintf(stderr, "Couldn't load %s: %s", file, SDL_GetError());
+        return 0;
+    }
+
+    /* Set transparent pixel as the pixel at (0,0) */
+    if (temp->format->palette) {
+        SDL_SetColorKey(temp, SDL_SRCCOLORKEY, *(Uint8 *) temp->pixels);
+    }
+
+    /* Create textures from the image */
+    SDL_SelectRenderer(window);
+    sprite = SDL_CreateTextureFromSurface(0, temp);
+    if (!sprite) {
+        fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError());
+        SDL_FreeSurface(temp);
+        return 0;
+    }
+    SDL_FreeSurface(temp);
+
+    /* We're ready to roll. :) */
+    return sprite;
+}
+
+void
+MoveSprites(SDL_WindowID window, SDL_TextureID sprite)
+{
+    int i, n;
+    int window_w, window_h;
+    int sprite_w, sprite_h;
+    SDL_Rect *position, *velocity;
+
+    SDL_SelectRenderer(window);
+
+    /* Query the sizes */
+    SDL_GetWindowSize(window, &window_w, &window_h);
+    SDL_QueryTexture(sprite, NULL, NULL, &sprite_w, &sprite_h);
+
+    /* Move the sprite, bounce at the wall, and draw */
+    n = 0;
+    SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
+    SDL_RenderFill(NULL);
+    for (i = 0; i < NUM_SPRITES; ++i) {
+        position = &positions[i];
+        velocity = &velocities[i];
+        position->x += velocity->x;
+        if ((position->x < 0) || (position->x >= (window_w - sprite_w))) {
+            velocity->x = -velocity->x;
+            position->x += velocity->x;
+        }
+        position->y += velocity->y;
+        if ((position->y < 0) || (position->y >= (window_h - sprite_h))) {
+            velocity->y = -velocity->y;
+            position->y += velocity->y;
+        }
+
+        /* Blit the sprite onto the screen */
+        SDL_RenderCopy(sprite, NULL, position);
+    }
+
+    /* Update the screen! */
+    SDL_RenderPresent();
+}
+
+int
+main(int argc, char *argv[])
+{
+    int i, done;
+    const char *driver;
+    SDL_WindowID window;
+    SDL_TextureID sprite;
+    int window_w, window_h;
+    int sprite_w, sprite_h;
+    SDL_Event event;
+
+    if (SDL_VideoInit(NULL, 0) < 0) {
+        fprintf(stderr, "Couldn't initialize SDL video: %s\n",
+                SDL_GetError());
+        exit(1);
+    }
+    driver = SDL_GetCurrentVideoDriver();
+
+    /* Find a native window driver and create a native window */
+    for (i = 0; factories[i]; ++i) {
+        if (SDL_strcmp(driver, factories[i]->tag) == 0) {
+            factory = factories[i];
+            break;
+        }
+    }
+    if (!factory) {
+        fprintf(stderr, "Couldn't find native window code for %s driver\n",
+                driver);
+        quit(2);
+    }
+    printf("Creating native window for %s driver\n", driver);
+    native_window = factory->CreateWindow(WINDOW_W, WINDOW_H);
+    if (!native_window) {
+        fprintf(stderr, "Couldn't create native window\n");
+        quit(3);
+    }
+    window = SDL_CreateWindowFrom(native_window);
+    if (!window) {
+        fprintf(stderr, "Couldn't create SDL window: %s\n", SDL_GetError());
+        quit(4);
+    }
+    SDL_SetWindowTitle(window, "SDL Native Window Test");
+
+    /* Create the renderer */
+    if (SDL_CreateRenderer(window, -1, 0) < 0) {
+        fprintf(stderr, "Couldn't create renderer: %s\n", SDL_GetError());
+        quit(5);
+    }
+
+    /* Clear the window, load the sprite and go! */
+    SDL_SelectRenderer(window);
+    SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
+    SDL_RenderFill(NULL);
+
+    sprite = LoadSprite(window, "icon.bmp");
+    if (!sprite) {
+        quit(6);
+    }
+
+    /* Allocate memory for the sprite info */
+    SDL_GetWindowSize(window, &window_w, &window_h);
+    SDL_QueryTexture(sprite, NULL, NULL, &sprite_w, &sprite_h);
+    positions = (SDL_Rect *) SDL_malloc(NUM_SPRITES * sizeof(SDL_Rect));
+    velocities = (SDL_Rect *) SDL_malloc(NUM_SPRITES * sizeof(SDL_Rect));
+    if (!positions || !velocities) {
+        fprintf(stderr, "Out of memory!\n");
+        quit(2);
+    }
+    srand(time(NULL));
+    for (i = 0; i < NUM_SPRITES; ++i) {
+        positions[i].x = rand() % (window_w - sprite_w);
+        positions[i].y = rand() % (window_h - sprite_h);
+        positions[i].w = sprite_w;
+        positions[i].h = sprite_h;
+        velocities[i].x = 0;
+        velocities[i].y = 0;
+        while (!velocities[i].x && !velocities[i].y) {
+            velocities[i].x = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED;
+            velocities[i].y = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED;
+        }
+    }
+
+    /* Main render loop */
+    done = 0;
+    while (!done) {
+        /* Check for events */
+        while (SDL_PollEvent(&event)) {
+            switch (event.type) {
+            case SDL_WINDOWEVENT:
+                switch (event.window.event) {
+                case SDL_WINDOWEVENT_EXPOSED:
+                    SDL_SelectRenderer(event.window.windowID);
+                    SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
+                    SDL_RenderFill(NULL);
+                    break;
+                }
+                break;
+            case SDL_QUIT:
+                done = 1;
+                break;
+            default:
+                break;
+            }
+        }
+        MoveSprites(window, sprite);
+    }
+
+    quit(0);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testnativecocoa.m	Mon Feb 09 05:32:12 2009 +0000
@@ -0,0 +1,51 @@
+
+#include "testnative.h"
+
+#ifdef TEST_NATIVE_COCOA
+
+#include <Cocoa/Cocoa.h>
+
+static void *CreateWindowCocoa(int w, int h);
+static void DestroyWindowCocoa(void *window);
+
+NativeWindowFactory CocoaWindowFactory = {
+    "cocoa",
+    CreateWindowCocoa,
+    DestroyWindowCocoa
+};
+
+static void *CreateWindowCocoa(int w, int h)
+{
+    NSAutoreleasePool *pool;
+    NSWindow *nswindow;
+    NSRect rect;
+    unsigned int style;
+
+    pool = [[NSAutoreleasePool alloc] init];
+
+    rect.origin.x = 0;
+    rect.origin.y = 0;
+    rect.size.width = w;
+    rect.size.height = h;
+    rect.origin.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - rect.origin.y - rect.size.height;
+
+    style = (NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask);
+
+    nswindow = [[NSWindow alloc] initWithContentRect:rect styleMask:style backing:NSBackingStoreBuffered defer:FALSE];
+    [nswindow makeKeyAndOrderFront:nil];
+
+    [pool release];
+
+    return nswindow;
+}
+
+static void DestroyWindowCocoa(void *window)
+{
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    NSWindow *nswindow = (NSWindow *)window;
+
+    [nswindow close];
+    [pool release];
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testnativew32.c	Mon Feb 09 05:32:12 2009 +0000
@@ -0,0 +1,28 @@
+
+#include "testnative.h"
+
+#ifdef TEST_NATIVE_WIN32
+
+static void *CreateWindowWin32(int w, int h);
+static void DestroyWindowWin32(void *window);
+
+NativeWindowFactory Win32WindowFactory = {
+    "win32",
+    CreateWindowWin32,
+    DestroyWindowWin32
+};
+
+static Display *dpy;
+
+static void *
+CreateWindowWin32(int w, int h)
+{
+    return NULL;
+}
+
+static void
+DestroyWindowWin32(void *window)
+{
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testnativex11.c	Mon Feb 09 05:32:12 2009 +0000
@@ -0,0 +1,42 @@
+
+#include "testnative.h"
+
+#ifdef TEST_NATIVE_X11
+
+static void *CreateWindowX11(int w, int h);
+static void DestroyWindowX11(void *window);
+
+NativeWindowFactory X11WindowFactory = {
+    "x11",
+    CreateWindowX11,
+    DestroyWindowX11
+};
+
+static Display *dpy;
+
+static void *
+CreateWindowX11(int w, int h)
+{
+    Window window = 0;
+
+    dpy = XOpenDisplay(NULL);
+    if (dpy) {
+        window =
+            XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, w, h, 0, 0,
+                                0);
+        XMapRaised(dpy, window);
+        XSync(dpy, False);
+    }
+    return (void *) window;
+}
+
+static void
+DestroyWindowX11(void *window)
+{
+    if (dpy) {
+        XDestroyWindow(dpy, (Window) window);
+        XCloseDisplay(dpy);
+    }
+}
+
+#endif