From 51b90535254f44ba02ab66642fe74b36479a2bf0 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 9 Feb 2009 05:32:12 +0000 Subject: [PATCH] Added test program for SDL_CreateWindowFrom() Make sure OpenGL library is loaded before working with OpenGL windows, even those created with SDL_CreateWindowFrom() --- include/SDL_video.h | 13 +- src/video/SDL_sysvideo.h | 1 + src/video/SDL_video.c | 101 ++++++++++++-- src/video/cocoa/SDL_cocoaopengl.h | 3 +- src/video/cocoa/SDL_cocoaopengl.m | 74 +--------- src/video/cocoa/SDL_cocoavideo.m | 1 + src/video/cocoa/SDL_cocoawindow.m | 13 -- src/video/win32/SDL_win32opengl.c | 93 +++---------- src/video/win32/SDL_win32opengl.h | 3 +- src/video/win32/SDL_win32video.c | 1 + src/video/win32/SDL_win32window.c | 5 - src/video/x11/SDL_x11opengl.c | 129 ++++++------------ src/video/x11/SDL_x11opengl.h | 4 +- src/video/x11/SDL_x11video.c | 1 + src/video/x11/SDL_x11window.c | 18 --- test/testnative.c | 219 ++++++++++++++++++++++++++++++ test/testnativecocoa.m | 51 +++++++ test/testnativew32.c | 28 ++++ test/testnativex11.c | 42 ++++++ 19 files changed, 513 insertions(+), 287 deletions(-) create mode 100644 test/testnative.c create mode 100644 test/testnativecocoa.m create mode 100644 test/testnativew32.c create mode 100644 test/testnativex11.c diff --git a/include/SDL_video.h b/include/SDL_video.h index 02aec6864..fc46ee5e8 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -111,7 +111,8 @@ typedef enum 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 @@ extern DECLSPEC void SDLCALL SDL_DisableScreenSaver(void); * 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); @@ -1373,6 +1375,15 @@ extern DECLSPEC int SDLCALL SDL_GL_LoadLibrary(const char *path); */ 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) * diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 5b08e492d..29c3e9586 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -260,6 +260,7 @@ struct SDL_VideoDevice */ 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); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index c49379b51..87c7d20e8 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -762,9 +762,12 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) 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 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) 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 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) 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_CreateWindowFrom(const void *data) 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 @@ SDL_CreateWindowFrom(const void *data) 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 @@ SDL_DestroyWindow(SDL_WindowID windowID) 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_TextureID 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 @@ SDL_CreateTextureFromSurface(Uint32 format, SDL_Surface * surface) 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_GL_LoadLibrary(const char *path) 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 @@ SDL_GL_GetProcAddress(const char *proc) 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) { diff --git a/src/video/cocoa/SDL_cocoaopengl.h b/src/video/cocoa/SDL_cocoaopengl.h index 37e7d0916..177d4de2a 100644 --- a/src/video/cocoa/SDL_cocoaopengl.h +++ b/src/video/cocoa/SDL_cocoaopengl.h @@ -34,8 +34,7 @@ struct SDL_GLDriverData /* 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); diff --git a/src/video/cocoa/SDL_cocoaopengl.m b/src/video/cocoa/SDL_cocoaopengl.m index 9c564a495..5d1de80bd 100644 --- a/src/video/cocoa/SDL_cocoaopengl.m +++ b/src/video/cocoa/SDL_cocoaopengl.m @@ -48,15 +48,7 @@ - (CGLContextObj)CGLContextObj; 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 @@ - (CGLContextObj)CGLContextObj; } 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 @@ - (CGLContextObj)CGLContextObj; return SDL_LoadFunction(_this->gl_config.dll_handle, proc); } -static 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_UnloadLibrary(_THIS) { - Cocoa_GL_Shutdown(_this); + SDL_UnloadObject(_this->gl_config.dll_handle); + _this->gl_config.dll_handle = NULL; } SDL_GLContext diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m index eb6355fe1..331e6abad 100644 --- a/src/video/cocoa/SDL_cocoavideo.m +++ b/src/video/cocoa/SDL_cocoavideo.m @@ -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; diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index 564c3840f..f13f9c5de 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -422,14 +422,6 @@ - (BOOL)canBecomeMainWindow [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 @@ - (BOOL)canBecomeMainWindow 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) { diff --git a/src/video/win32/SDL_win32opengl.c b/src/video/win32/SDL_win32opengl.c index 4583263e5..451bd03be 100644 --- a/src/video/win32/SDL_win32opengl.c +++ b/src/video/win32/SDL_win32opengl.c @@ -37,15 +37,6 @@ WIN_GL_LoadLibrary(_THIS, const char *path) 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 @@ WIN_GL_LoadLibrary(_THIS, const char *path) 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 @@ WIN_GL_LoadLibrary(_THIS, const char *path) 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 @@ WIN_GL_GetProcAddress(_THIS, const char *proc) 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 @@ WIN_GL_ChoosePixelFormatARB(_THIS, int *iAttribs, float *fAttribs) 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 @@ WIN_GL_SetupWindow(_THIS, SDL_Window * window) 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 @@ WIN_GL_SetupWindow(_THIS, SDL_Window * window) return 0; } -void -WIN_GL_CleanupWindow(_THIS, SDL_Window * window) -{ - WIN_GL_Shutdown(_this); -} - SDL_GLContext WIN_GL_CreateContext(_THIS, SDL_Window * window) { diff --git a/src/video/win32/SDL_win32opengl.h b/src/video/win32/SDL_win32opengl.h index 6588e2094..3b6dc7018 100644 --- a/src/video/win32/SDL_win32opengl.h +++ b/src/video/win32/SDL_win32opengl.h @@ -28,7 +28,6 @@ struct SDL_GLDriverData { - int initialized; int WGL_ARB_pixel_format; void *(WINAPI * wglGetProcAddress) (const char *proc); @@ -53,8 +52,8 @@ struct SDL_GLDriverData /* 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); diff --git a/src/video/win32/SDL_win32video.c b/src/video/win32/SDL_win32video.c index d8f0d5fd5..22e574262 100644 --- a/src/video/win32/SDL_win32video.c +++ b/src/video/win32/SDL_win32video.c @@ -161,6 +161,7 @@ WIN_CreateDevice(int devindex) #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; diff --git a/src/video/win32/SDL_win32window.c b/src/video/win32/SDL_win32window.c index a2b076fd4..3d606352c 100644 --- a/src/video/win32/SDL_win32window.c +++ b/src/video/win32/SDL_win32window.c @@ -521,11 +521,6 @@ WIN_DestroyWindow(_THIS, SDL_Window * window) 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) { diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c index 783f20534..63b3ced38 100644 --- a/src/video/x11/SDL_x11opengl.c +++ b/src/video/x11/SDL_x11opengl.c @@ -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; + } + 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; } - X11_GL_InitializeMemory(_this); - /* Load new function pointers */ + /* Load function pointers */ + handle = _this->gl_config.dll_handle; _this->gl_data->glXGetProcAddress = (void *(*)(const GLubyte *)) GL_LoadFunction(handle, "glXGetProcAddressARB"); @@ -123,7 +125,9 @@ X11_GL_LoadLibrary(_THIS, const char *path) return -1; } - ++_this->gl_config.driver_loaded; + /* Initialize extensions */ + X11_GL_InitExtensions(_this); + return 0; } @@ -139,16 +143,21 @@ X11_GL_GetProcAddress(_THIS, const char *proc) 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_GL_InitExtensions(_THIS) 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) { diff --git a/src/video/x11/SDL_x11opengl.h b/src/video/x11/SDL_x11opengl.h index 200dd5168..d42daaa34 100644 --- a/src/video/x11/SDL_x11opengl.h +++ b/src/video/x11/SDL_x11opengl.h @@ -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 @@ struct SDL_GLDriverData /* 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, diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index f7a0e35a8..d26c5bc09 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -190,6 +190,7 @@ X11_CreateDevice(int devindex) #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; diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 97550f81f..c59f674cf 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -188,9 +188,6 @@ X11_CreateWindow(_THIS, SDL_Window * window) 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 @@ X11_CreateWindow(_THIS, SDL_Window * window) (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 @@ X11_CreateWindow(_THIS, SDL_Window * window) 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 @@ X11_DestroyWindow(_THIS, SDL_Window * window) } } } -#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); diff --git a/test/testnative.c b/test/testnative.c new file mode 100644 index 000000000..96c469d7c --- /dev/null +++ b/test/testnative.c @@ -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: */ diff --git a/test/testnativecocoa.m b/test/testnativecocoa.m new file mode 100644 index 000000000..030607d66 --- /dev/null +++ b/test/testnativecocoa.m @@ -0,0 +1,51 @@ + +#include "testnative.h" + +#ifdef TEST_NATIVE_COCOA + +#include + +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 diff --git a/test/testnativew32.c b/test/testnativew32.c new file mode 100644 index 000000000..9bcaa6b84 --- /dev/null +++ b/test/testnativew32.c @@ -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 diff --git a/test/testnativex11.c b/test/testnativex11.c new file mode 100644 index 000000000..0f84aa974 --- /dev/null +++ b/test/testnativex11.c @@ -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