1 //
2 // Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // global_state.cpp : Implements functions for querying the thread-local GL and EGL state.
8 
9 #include "libGLESv2/global_state.h"
10 
11 #include "common/debug.h"
12 #include "common/platform.h"
13 #include "common/tls.h"
14 
15 #include "libANGLE/Thread.h"
16 #include "libANGLE/Display.h"
17 
18 namespace gl
19 {
20 
GetGlobalContext()21 Context *GetGlobalContext()
22 {
23     egl::Thread *thread = egl::GetCurrentThread();
24     return thread->getContext();
25 }
26 
GetValidGlobalContext()27 Context *GetValidGlobalContext()
28 {
29     egl::Thread *thread = egl::GetCurrentThread();
30     return thread->getValidContext();
31 }
32 
33 }  // namespace gl
34 
35 namespace egl
36 {
37 
38 namespace
39 {
40 
41 static TLSIndex threadTLS = TLS_INVALID_INDEX;
42 
AllocateCurrentThread()43 Thread *AllocateCurrentThread()
44 {
45     ASSERT(threadTLS != TLS_INVALID_INDEX);
46     if (threadTLS == TLS_INVALID_INDEX)
47     {
48         return nullptr;
49     }
50 
51     Thread *thread = new Thread();
52     if (!SetTLSValue(threadTLS, thread))
53     {
54         ERR() << "Could not set thread local storage.";
55         return nullptr;
56     }
57 
58     return thread;
59 }
60 
61 }  // anonymous namespace
62 
GetCurrentThread()63 Thread *GetCurrentThread()
64 {
65     // Create a TLS index if one has not been created for this DLL
66     if (threadTLS == TLS_INVALID_INDEX)
67     {
68         threadTLS = CreateTLSIndex();
69     }
70 
71     Thread *current = static_cast<Thread *>(GetTLSValue(threadTLS));
72 
73     // ANGLE issue 488: when the dll is loaded after thread initialization,
74     // thread local storage (current) might not exist yet.
75     return (current ? current : AllocateCurrentThread());
76 }
77 
78 }  // namespace egl
79 
80 #ifdef ANGLE_PLATFORM_WINDOWS
81 namespace egl
82 {
83 
84 namespace
85 {
86 
DeallocateCurrentThread()87 bool DeallocateCurrentThread()
88 {
89     Thread *thread = static_cast<Thread *>(GetTLSValue(threadTLS));
90     SafeDelete(thread);
91     return SetTLSValue(threadTLS, nullptr);
92 }
93 
InitializeProcess()94 bool InitializeProcess()
95 {
96     threadTLS = CreateTLSIndex();
97     if (threadTLS == TLS_INVALID_INDEX)
98     {
99         return false;
100     }
101 
102     return AllocateCurrentThread() != nullptr;
103 }
104 
TerminateProcess()105 bool TerminateProcess()
106 {
107     if (!DeallocateCurrentThread())
108     {
109         return false;
110     }
111 
112     if (threadTLS != TLS_INVALID_INDEX)
113     {
114         TLSIndex tlsCopy = threadTLS;
115         threadTLS        = TLS_INVALID_INDEX;
116 
117         if (!DestroyTLSIndex(tlsCopy))
118         {
119             return false;
120         }
121     }
122 
123     return true;
124 }
125 
126 }  // anonymous namespace
127 
128 }  // namespace egl
129 
DllMain(HINSTANCE,DWORD reason,LPVOID)130 extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID)
131 {
132     switch (reason)
133     {
134         case DLL_PROCESS_ATTACH:
135             return static_cast<BOOL>(egl::InitializeProcess());
136 
137         case DLL_THREAD_ATTACH:
138             return static_cast<BOOL>(egl::AllocateCurrentThread() != nullptr);
139 
140         case DLL_THREAD_DETACH:
141             return static_cast<BOOL>(egl::DeallocateCurrentThread());
142 
143         case DLL_PROCESS_DETACH:
144             egl::Display::CleanupDisplays();
145             return static_cast<BOOL>(egl::TerminateProcess());
146     }
147 
148     return TRUE;
149 }
150 #endif  // ANGLE_PLATFORM_WINDOWS
151