From 78efc180792d232ac2740cd7e2ed404731c61ebf Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Sun, 30 Mar 2014 14:37:20 +0200 Subject: [PATCH] Split out TLS code into separate modules. This allows the TLS code to be re-used by partial ports like EGL. --- src/CMakeLists.txt | 12 ++++---- src/cocoa_platform.h | 2 ++ src/egl_context.c | 28 ++++-------------- src/glx_context.c | 19 ++++-------- src/glx_platform.h | 5 ---- src/internal.h | 2 ++ src/nsgl_context.m | 17 ++--------- src/nsgl_platform.h | 4 --- src/posix_tls.c | 66 ++++++++++++++++++++++++++++++++++++++++++ src/posix_tls.h | 55 +++++++++++++++++++++++++++++++++++ src/wgl_context.c | 25 ++++------------ src/wgl_platform.h | 4 --- src/win32_platform.h | 2 ++ src/win32_tls.c | 69 ++++++++++++++++++++++++++++++++++++++++++++ src/win32_tls.h | 54 ++++++++++++++++++++++++++++++++++ src/x11_platform.h | 2 ++ 16 files changed, 278 insertions(+), 88 deletions(-) create mode 100644 src/posix_tls.c create mode 100644 src/posix_tls.h create mode 100644 src/win32_tls.c create mode 100644 src/win32_tls.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cd699efd..de00a8c1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,20 +12,20 @@ set(common_SOURCES clipboard.c context.c gamma.c init.c input.c joystick.c monitor.c time.c window.c) if (_GLFW_COCOA) - set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h) + set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h posix_tls.h) set(glfw_SOURCES ${common_SOURCES} cocoa_clipboard.m cocoa_gamma.c cocoa_init.m cocoa_joystick.m cocoa_monitor.m cocoa_time.c - cocoa_window.m) + cocoa_window.m posix_tls.c) elseif (_GLFW_WIN32) - set(glfw_HEADERS ${common_HEADERS} win32_platform.h) + set(glfw_HEADERS ${common_HEADERS} win32_platform.h win32_tls.h) set(glfw_SOURCES ${common_SOURCES} win32_clipboard.c win32_gamma.c win32_init.c win32_joystick.c win32_monitor.c win32_time.c - win32_window.c) + win32_tls.c win32_window.c) elseif (_GLFW_X11) - set(glfw_HEADERS ${common_HEADERS} x11_platform.h) + set(glfw_HEADERS ${common_HEADERS} x11_platform.h posix_tls.h) set(glfw_SOURCES ${common_SOURCES} x11_clipboard.c x11_gamma.c x11_init.c x11_joystick.c x11_monitor.c x11_time.c x11_window.c - x11_unicode.c) + x11_unicode.c posix_tls.c) endif() if (_GLFW_EGL) diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index b9acb66e..ef44abbd 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -37,6 +37,8 @@ typedef void* id; #endif +#include "posix_tls.h" + #if defined(_GLFW_NSGL) #include "nsgl_platform.h" #else diff --git a/src/egl_context.c b/src/egl_context.c index 7caff10f..e9fd0242 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -32,22 +32,6 @@ #include -// Thread local storage attribute macro -// -#if defined(_MSC_VER) - #define _GLFW_TLS __declspec(thread) -#elif defined(__GNUC__) - #define _GLFW_TLS __thread -#else - #define _GLFW_TLS -#endif - - -// The per-thread current context/window pointer -// -static _GLFW_TLS _GLFWwindow* _glfwCurrentWindow = NULL; - - // Return a description of the specified EGL error // static const char* getErrorString(EGLint error) @@ -207,6 +191,9 @@ static GLboolean chooseFBConfigs(const _GLFWctxconfig* ctxconfig, // int _glfwInitContextAPI(void) { + if (!_glfwInitTLS()) + return GL_FALSE; + _glfw.egl.display = eglGetDisplay((EGLNativeDisplayType)_GLFW_EGL_NATIVE_DISPLAY); if (_glfw.egl.display == EGL_NO_DISPLAY) { @@ -237,6 +224,8 @@ int _glfwInitContextAPI(void) void _glfwTerminateContextAPI(void) { eglTerminate(_glfw.egl.display); + + _glfwTerminateTLS(); } #define setEGLattrib(attribName, attribValue) \ @@ -482,12 +471,7 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window) EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } - _glfwCurrentWindow = window; -} - -_GLFWwindow* _glfwPlatformGetCurrentContext(void) -{ - return _glfwCurrentWindow; + _glfwSetCurrentContext(window); } void _glfwPlatformSwapBuffers(_GLFWwindow* window) diff --git a/src/glx_context.c b/src/glx_context.c index 0cf10fd0..076b7b3c 100644 --- a/src/glx_context.c +++ b/src/glx_context.c @@ -165,6 +165,9 @@ static GLXContext createLegacyContext(_GLFWwindow* window, // int _glfwInitContextAPI(void) { + if (!_glfwInitTLS()) + return GL_FALSE; + #ifdef _GLFW_DLOPEN_LIBGL _glfw.glx.libGL = dlopen("libGL.so.1", RTLD_LAZY | RTLD_GLOBAL); if (!_glfw.glx.libGL) @@ -174,13 +177,6 @@ int _glfwInitContextAPI(void) } #endif - if (pthread_key_create(&_glfw.glx.current, NULL) != 0) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "GLX: Failed to create context TLS"); - return GL_FALSE; - } - if (!glXQueryExtension(_glfw.x11.display, &_glfw.glx.errorBase, &_glfw.glx.eventBase)) @@ -272,7 +268,7 @@ void _glfwTerminateContextAPI(void) } #endif - pthread_key_delete(_glfw.glx.current); + _glfwTerminateTLS(); } #define setGLXattrib(attribName, attribValue) \ @@ -478,12 +474,7 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window) else glXMakeCurrent(_glfw.x11.display, None, NULL); - pthread_setspecific(_glfw.glx.current, window); -} - -_GLFWwindow* _glfwPlatformGetCurrentContext(void) -{ - return (_GLFWwindow*) pthread_getspecific(_glfw.glx.current); + _glfwSetCurrentContext(window); } void _glfwPlatformSwapBuffers(_GLFWwindow* window) diff --git a/src/glx_platform.h b/src/glx_platform.h index da96b433..440f599c 100644 --- a/src/glx_platform.h +++ b/src/glx_platform.h @@ -41,8 +41,6 @@ #include #endif -#include - // We support four different ways for getting addresses for GL/GLX // extension functions: glXGetProcAddress, glXGetProcAddressARB, // glXGetProcAddressEXT, and dlsym @@ -93,9 +91,6 @@ typedef struct _GLFWlibraryGLX int eventBase; int errorBase; - // TLS key for per-thread current context/window - pthread_key_t current; - // GLX extensions PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI; PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT; diff --git a/src/internal.h b/src/internal.h index 7a44d12f..5b24b427 100644 --- a/src/internal.h +++ b/src/internal.h @@ -348,6 +348,8 @@ struct _GLFWlibrary _GLFW_PLATFORM_LIBRARY_WINDOW_STATE; // This is defined in the context API's platform.h _GLFW_PLATFORM_LIBRARY_OPENGL_STATE; + // This is defined in the platform's tls.h + _GLFW_PLATFORM_TLS_STATE; }; diff --git a/src/nsgl_context.m b/src/nsgl_context.m index 47d01956..32ef85c8 100644 --- a/src/nsgl_context.m +++ b/src/nsgl_context.m @@ -26,8 +26,6 @@ #include "internal.h" -#include - ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// @@ -37,12 +35,8 @@ // int _glfwInitContextAPI(void) { - if (pthread_key_create(&_glfw.nsgl.current, NULL) != 0) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "NSGL: Failed to create context TLS"); + if (!_glfwInitTLS()) return GL_FALSE; - } _glfw.nsgl.framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); @@ -60,7 +54,7 @@ int _glfwInitContextAPI(void) // void _glfwTerminateContextAPI(void) { - pthread_key_delete(_glfw.nsgl.current); + _glfwTerminateTLS(); } // Create the OpenGL context @@ -235,12 +229,7 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window) else [NSOpenGLContext clearCurrentContext]; - pthread_setspecific(_glfw.nsgl.current, window); -} - -_GLFWwindow* _glfwPlatformGetCurrentContext(void) -{ - return (_GLFWwindow*) pthread_getspecific(_glfw.nsgl.current); + _glfwSetCurrentContext(window); } void _glfwPlatformSwapBuffers(_GLFWwindow* window) diff --git a/src/nsgl_platform.h b/src/nsgl_platform.h index fd9b5e05..86c0dd1f 100644 --- a/src/nsgl_platform.h +++ b/src/nsgl_platform.h @@ -27,7 +27,6 @@ #ifndef _nsgl_platform_h_ #define _nsgl_platform_h_ - #define _GLFW_PLATFORM_FBCONFIG #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl #define _GLFW_PLATFORM_LIBRARY_OPENGL_STATE _GLFWlibraryNSGL nsgl @@ -55,9 +54,6 @@ typedef struct _GLFWlibraryNSGL // dlopen handle for dynamically loading OpenGL extension entry points void* framework; - // TLS key for per-thread current context/window - pthread_key_t current; - } _GLFWlibraryNSGL; diff --git a/src/posix_tls.c b/src/posix_tls.c new file mode 100644 index 00000000..70fe19bb --- /dev/null +++ b/src/posix_tls.c @@ -0,0 +1,66 @@ +//======================================================================== +// GLFW 3.1 POSIX - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2002-2006 Marcus Geelnard +// Copyright (c) 2006-2010 Camilla Berglund +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#include "internal.h" + + +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +int _glfwInitTLS(void) +{ + if (pthread_key_create(&_glfw.posix_tls.context, NULL) != 0) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "POSIX: Failed to create context TLS"); + return GL_FALSE; + } + + return GL_TRUE; +} + +void _glfwTerminateTLS(void) +{ + pthread_key_delete(_glfw.posix_tls.context); +} + +void _glfwSetCurrentContext(_GLFWwindow* context) +{ + pthread_setspecific(_glfw.posix_tls.context, context); +} + + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +_GLFWwindow* _glfwPlatformGetCurrentContext(void) +{ + return pthread_getspecific(_glfw.posix_tls.context); +} + diff --git a/src/posix_tls.h b/src/posix_tls.h new file mode 100644 index 00000000..bd644da4 --- /dev/null +++ b/src/posix_tls.h @@ -0,0 +1,55 @@ +//======================================================================== +// GLFW 3.1 POSIX - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2002-2006 Marcus Geelnard +// Copyright (c) 2006-2010 Camilla Berglund +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#ifndef _posix_tls_h_ +#define _posix_tls_h_ + +#include + +#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsPOSIX posix_tls + + +//======================================================================== +// GLFW platform specific types +//======================================================================== + +typedef struct _GLFWtlsPOSIX +{ + pthread_key_t context; + +} _GLFWtlsPOSIX; + + +//======================================================================== +// Prototypes for platform specific internal functions +//======================================================================== + +int _glfwInitTLS(void); +void _glfwTerminateTLS(void); +void _glfwSetCurrentContext(_GLFWwindow* context); + +#endif // _posix_tls_h_ diff --git a/src/wgl_context.c b/src/wgl_context.c index 2cb85ec2..038846c5 100644 --- a/src/wgl_context.c +++ b/src/wgl_context.c @@ -306,6 +306,9 @@ static GLboolean choosePixelFormat(_GLFWwindow* window, // int _glfwInitContextAPI(void) { + if (!_glfwInitTLS()) + return GL_FALSE; + _glfw.wgl.opengl32.instance = LoadLibraryW(L"opengl32.dll"); if (!_glfw.wgl.opengl32.instance) { @@ -313,16 +316,6 @@ int _glfwInitContextAPI(void) return GL_FALSE; } - _glfw.wgl.current = TlsAlloc(); - if (_glfw.wgl.current == TLS_OUT_OF_INDEXES) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "WGL: Failed to allocate TLS index"); - return GL_FALSE; - } - - _glfw.wgl.hasTLS = GL_TRUE; - return GL_TRUE; } @@ -330,11 +323,10 @@ int _glfwInitContextAPI(void) // void _glfwTerminateContextAPI(void) { - if (_glfw.wgl.hasTLS) - TlsFree(_glfw.wgl.current); - if (_glfw.wgl.opengl32.instance) FreeLibrary(_glfw.wgl.opengl32.instance); + + _glfwTerminateTLS(); } #define setWGLattrib(attribName, attribValue) \ @@ -588,12 +580,7 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window) else wglMakeCurrent(NULL, NULL); - TlsSetValue(_glfw.wgl.current, window); -} - -_GLFWwindow* _glfwPlatformGetCurrentContext(void) -{ - return TlsGetValue(_glfw.wgl.current); + _glfwSetCurrentContext(window); } void _glfwPlatformSwapBuffers(_GLFWwindow* window) diff --git a/src/wgl_platform.h b/src/wgl_platform.h index dd1cc5b7..7fea8695 100644 --- a/src/wgl_platform.h +++ b/src/wgl_platform.h @@ -33,7 +33,6 @@ // extensions and not all operating systems come with an up-to-date version #include "../deps/GL/wglext.h" - #define _GLFW_PLATFORM_FBCONFIG int wgl #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextWGL wgl #define _GLFW_PLATFORM_LIBRARY_OPENGL_STATE _GLFWlibraryWGL wgl @@ -74,9 +73,6 @@ typedef struct _GLFWcontextWGL //------------------------------------------------------------------------ typedef struct _GLFWlibraryWGL { - GLboolean hasTLS; - DWORD current; - // opengl32.dll struct { HINSTANCE instance; diff --git a/src/win32_platform.h b/src/win32_platform.h index 5ecdd09f..aecdf272 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -151,6 +151,8 @@ typedef HRESULT (WINAPI * DWMISCOMPOSITIONENABLED_T)(BOOL*); #define _GLFW_RECREATION_IMPOSSIBLE 2 +#include "win32_tls.h" + #if defined(_GLFW_WGL) #include "wgl_platform.h" #elif defined(_GLFW_EGL) diff --git a/src/win32_tls.c b/src/win32_tls.c new file mode 100644 index 00000000..088e25df --- /dev/null +++ b/src/win32_tls.c @@ -0,0 +1,69 @@ +//======================================================================== +// GLFW 3.1 Win32 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2002-2006 Marcus Geelnard +// Copyright (c) 2006-2010 Camilla Berglund +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#include "internal.h" + + +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +int _glfwInitTLS(void) +{ + _glfw.win32_tls.context = TlsAlloc(); + if (_glfw.win32_tls.context == TLS_OUT_OF_INDEXES) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Win32: Failed to allocate TLS index"); + return GL_FALSE; + } + + _glfw.win32_tls.allocated = GL_TRUE; + return GL_TRUE; +} + +void _glfwTerminateTLS(void) +{ + if (_glfw.win32_tls.allocated) + TlsFree(_glfw.win32_tls.context); +} + +void _glfwSetCurrentContext(_GLFWwindow* context) +{ + TlsSetValue(_glfw.win32_tls.context, context); +} + + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +_GLFWwindow* _glfwPlatformGetCurrentContext(void) +{ + return TlsGetValue(_glfw.win32_tls.context); +} + diff --git a/src/win32_tls.h b/src/win32_tls.h new file mode 100644 index 00000000..ef2d4194 --- /dev/null +++ b/src/win32_tls.h @@ -0,0 +1,54 @@ +//======================================================================== +// GLFW 3.1 Win32 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2002-2006 Marcus Geelnard +// Copyright (c) 2006-2010 Camilla Berglund +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#ifndef _win32_tls_h_ +#define _win32_tls_h_ + +#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsWin32 win32_tls + + +//======================================================================== +// GLFW platform specific types +//======================================================================== + +typedef struct _GLFWtlsWin32 +{ + GLboolean allocated; + DWORD context; + +} _GLFWtlsWin32; + + +//======================================================================== +// Prototypes for platform specific internal functions +//======================================================================== + +int _glfwInitTLS(void); +void _glfwTerminateTLS(void); +void _glfwSetCurrentContext(_GLFWwindow* context); + +#endif // _win32_tls_h_ diff --git a/src/x11_platform.h b/src/x11_platform.h index 0eb27fb5..fca8d3e1 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -48,6 +48,8 @@ // The Xkb extension provides improved keyboard support #include +#include "posix_tls.h" + #if defined(_GLFW_GLX) #define _GLFW_X11_CONTEXT_VISUAL window->glx.visual #include "glx_platform.h"