diff options
Diffstat (limited to 'gfx/angle/src/libGLESv2/global_state.cpp')
-rwxr-xr-x | gfx/angle/src/libGLESv2/global_state.cpp | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/gfx/angle/src/libGLESv2/global_state.cpp b/gfx/angle/src/libGLESv2/global_state.cpp new file mode 100755 index 000000000..bc776b1f7 --- /dev/null +++ b/gfx/angle/src/libGLESv2/global_state.cpp @@ -0,0 +1,148 @@ +// +// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// global_state.cpp : Implements functions for querying the thread-local GL and EGL state. + +#include "libGLESv2/global_state.h" + +#include "common/debug.h" +#include "common/platform.h" +#include "common/tls.h" + +#include "libANGLE/Thread.h" + +namespace gl +{ + +Context *GetGlobalContext() +{ + egl::Thread *thread = egl::GetCurrentThread(); + return thread->getContext(); +} + +Context *GetValidGlobalContext() +{ + egl::Thread *thread = egl::GetCurrentThread(); + return thread->getValidContext(); +} + +} // namespace gl + +namespace egl +{ + +namespace +{ + +static TLSIndex threadTLS = TLS_INVALID_INDEX; + +Thread *AllocateCurrentThread() +{ + ASSERT(threadTLS != TLS_INVALID_INDEX); + if (threadTLS == TLS_INVALID_INDEX) + { + return nullptr; + } + + Thread *thread = new Thread(); + if (!SetTLSValue(threadTLS, thread)) + { + ERR("Could not set thread local storage."); + return nullptr; + } + + return thread; +} + +} // anonymous namespace + +Thread *GetCurrentThread() +{ + // Create a TLS index if one has not been created for this DLL + if (threadTLS == TLS_INVALID_INDEX) + { + threadTLS = CreateTLSIndex(); + } + + Thread *current = static_cast<Thread *>(GetTLSValue(threadTLS)); + + // ANGLE issue 488: when the dll is loaded after thread initialization, + // thread local storage (current) might not exist yet. + return (current ? current : AllocateCurrentThread()); +} + +} // namespace egl + +#ifdef ANGLE_PLATFORM_WINDOWS +namespace egl +{ + +namespace +{ + +bool DeallocateCurrentThread() +{ + Thread *thread = static_cast<Thread *>(GetTLSValue(threadTLS)); + SafeDelete(thread); + return SetTLSValue(threadTLS, nullptr); +} + +bool InitializeProcess() +{ + threadTLS = CreateTLSIndex(); + if (threadTLS == TLS_INVALID_INDEX) + { + return false; + } + + return AllocateCurrentThread() != nullptr; +} + +bool TerminateProcess() +{ + if (!DeallocateCurrentThread()) + { + return false; + } + + if (threadTLS != TLS_INVALID_INDEX) + { + TLSIndex tlsCopy = threadTLS; + threadTLS = TLS_INVALID_INDEX; + + if (!DestroyTLSIndex(tlsCopy)) + { + return false; + } + } + + return true; +} + +} // anonymous namespace + +} // namespace egl + +extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID) +{ + switch (reason) + { + case DLL_PROCESS_ATTACH: + return static_cast<BOOL>(egl::InitializeProcess()); + + case DLL_THREAD_ATTACH: + return static_cast<BOOL>(egl::AllocateCurrentThread() != nullptr); + + case DLL_THREAD_DETACH: + return static_cast<BOOL>(egl::DeallocateCurrentThread()); + + case DLL_PROCESS_DETACH: + return static_cast<BOOL>(egl::TerminateProcess()); + } + + return TRUE; +} +#endif // ANGLE_PLATFORM_WINDOWS |