blob: c5f3dfe4e12695ca1e94f5e325c8af1477540f3e [file] [log] [blame]
//
// 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