1 //
2 // Copyright 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.h : Defines functions for querying the thread-local GL and EGL state.
8
9 #ifndef LIBGLESV2_GLOBALSTATE_H_
10 #define LIBGLESV2_GLOBALSTATE_H_
11
12 #include "libANGLE/Context.h"
13 #include "libANGLE/Debug.h"
14 #include "libANGLE/Display.h"
15 #include "libANGLE/GlobalMutex.h"
16 #include "libANGLE/Thread.h"
17 #include "libANGLE/features.h"
18 #include "libANGLE/validationEGL.h"
19
20 #if defined(ANGLE_PLATFORM_APPLE) || (ANGLE_PLATFORM_ANDROID)
21 # include "common/tls.h"
22 #endif
23
24 #include <mutex>
25
26 namespace egl
27 {
28 class Debug;
29 class Thread;
30
31 #if defined(ANGLE_PLATFORM_APPLE) || defined(ANGLE_USE_STATIC_THREAD_LOCAL_VARIABLES)
32 extern Thread *GetCurrentThreadTLS();
33 extern void SetCurrentThreadTLS(Thread *thread);
34 #else
35 extern thread_local Thread *gCurrentThread;
36 #endif
37
38 gl::Context *GetGlobalLastContext();
39 void SetGlobalLastContext(gl::Context *context);
40 Thread *GetCurrentThread();
41 Debug *GetDebug();
42
43 void SetEGLValidationEnabled(bool enabled);
44 bool IsEGLValidationEnabled();
45
46 // Sync the current context from Thread to global state.
47 class [[nodiscard]] ScopedSyncCurrentContextFromThread
48 {
49 public:
50 ScopedSyncCurrentContextFromThread(egl::Thread *thread);
51 ~ScopedSyncCurrentContextFromThread();
52
53 private:
54 egl::Thread *const mThread;
55 };
56
57 // Tries to lock "ContextMutex" of the Context current to the "thread".
TryLockCurrentContext(Thread * thread)58 ANGLE_INLINE ScopedContextMutexLock TryLockCurrentContext(Thread *thread)
59 {
60 ASSERT(kIsContextMutexEnabled);
61 gl::Context *context = thread->getContext();
62 return context != nullptr ? ScopedContextMutexLock(context->getContextMutex())
63 : ScopedContextMutexLock();
64 }
65
66 // Tries to lock "ContextMutex" of the Context with "contextID" if it is valid.
TryLockContext(Display * display,gl::ContextID contextID)67 ANGLE_INLINE ScopedContextMutexLock TryLockContext(Display *display, gl::ContextID contextID)
68 {
69 ASSERT(kIsContextMutexEnabled);
70 gl::Context *context = GetContextIfValid(display, contextID);
71 return context != nullptr ? ScopedContextMutexLock(context->getContextMutex())
72 : ScopedContextMutexLock();
73 }
74
75 // Locks "ContextMutex" of the "context" and then tries to merge it with the "ContextMutex" of the
76 // Image with "imageID" if it is valid.
LockAndTryMergeContextMutexes(gl::Context * context,ImageID imageID)77 ANGLE_INLINE ScopedContextMutexLock LockAndTryMergeContextMutexes(gl::Context *context,
78 ImageID imageID)
79 {
80 ASSERT(kIsContextMutexEnabled);
81 ASSERT(context->getDisplay() != nullptr);
82 ScopedContextMutexLock lock(context->getContextMutex());
83 const Image *image = context->getDisplay()->getImage(imageID);
84 if (image != nullptr)
85 {
86 ContextMutex *imageMutex = image->getContextMutex();
87 if (imageMutex != nullptr)
88 {
89 ContextMutex::Merge(&context->getContextMutex(), imageMutex);
90 }
91 }
92 return lock;
93 }
94
95 #if !defined(ANGLE_ENABLE_CONTEXT_MUTEX)
96 # define ANGLE_EGL_SCOPED_CONTEXT_LOCK(EP, THREAD, ...)
97 #else
98 # define ANGLE_EGL_SCOPED_CONTEXT_LOCK(EP, THREAD, ...) \
99 egl::ScopedContextMutexLock shareContextLock = GetContextLock_##EP(THREAD, ##__VA_ARGS__)
100 #endif
101
102 } // namespace egl
103
104 #define ANGLE_SCOPED_GLOBAL_LOCK() egl::ScopedGlobalMutexLock globalMutexLock
105
106 namespace gl
107 {
GetGlobalContext()108 ANGLE_INLINE Context *GetGlobalContext()
109 {
110 #if defined(ANGLE_PLATFORM_APPLE) || defined(ANGLE_USE_STATIC_THREAD_LOCAL_VARIABLES)
111 egl::Thread *currentThread = egl::GetCurrentThreadTLS();
112 #else
113 egl::Thread *currentThread = egl::gCurrentThread;
114 #endif
115 ASSERT(currentThread);
116 return currentThread->getContext();
117 }
118
GetValidGlobalContext()119 ANGLE_INLINE Context *GetValidGlobalContext()
120 {
121 #if defined(ANGLE_USE_ANDROID_TLS_SLOT)
122 // TODO: Replace this branch with a compile time flag (http://anglebug.com/4764)
123 if (angle::gUseAndroidOpenGLTlsSlot)
124 {
125 return static_cast<gl::Context *>(ANGLE_ANDROID_GET_GL_TLS()[angle::kAndroidOpenGLTlsSlot]);
126 }
127 #endif
128
129 #if defined(ANGLE_PLATFORM_APPLE) || defined(ANGLE_USE_STATIC_THREAD_LOCAL_VARIABLES)
130 return GetCurrentValidContextTLS();
131 #else
132 return gCurrentValidContext;
133 #endif
134 }
135
136 // Generate a context lost error on the context if it is non-null and lost.
137 void GenerateContextLostErrorOnContext(Context *context);
138 void GenerateContextLostErrorOnCurrentGlobalContext();
139
140 #if defined(ANGLE_FORCE_CONTEXT_CHECK_EVERY_CALL)
141 // TODO(b/177574181): This should be handled in a backend-specific way.
142 // if previous context different from current context, dirty all state
DirtyContextIfNeeded(Context * context)143 static ANGLE_INLINE void DirtyContextIfNeeded(Context *context)
144 {
145 if (context && context != egl::GetGlobalLastContext())
146 {
147 context->dirtyAllState();
148 SetGlobalLastContext(context);
149 }
150 }
151
152 #endif
153
154 #if !defined(ANGLE_ENABLE_SHARE_CONTEXT_LOCK)
155 # define SCOPED_SHARE_CONTEXT_LOCK(context)
156 # define SCOPED_EGL_IMAGE_SHARE_CONTEXT_LOCK(context, imageID) ANGLE_SCOPED_GLOBAL_LOCK()
157 #else
158 # if defined(ANGLE_FORCE_CONTEXT_CHECK_EVERY_CALL)
159 # define SCOPED_SHARE_CONTEXT_LOCK(context) \
160 egl::ScopedGlobalMutexLock shareContextLock; \
161 DirtyContextIfNeeded(context)
162 # define SCOPED_EGL_IMAGE_SHARE_CONTEXT_LOCK(context, imageID) \
163 SCOPED_SHARE_CONTEXT_LOCK(context)
164 # elif !defined(ANGLE_ENABLE_CONTEXT_MUTEX)
165 # define SCOPED_SHARE_CONTEXT_LOCK(context) \
166 egl::ScopedOptionalGlobalMutexLock shareContextLock(context->isShared())
167 # define SCOPED_EGL_IMAGE_SHARE_CONTEXT_LOCK(context, imageID) ANGLE_SCOPED_GLOBAL_LOCK()
168 # else
169 # define SCOPED_SHARE_CONTEXT_LOCK(context) \
170 egl::ScopedContextMutexLock shareContextLock(context->getContextMutex())
171 # define SCOPED_EGL_IMAGE_SHARE_CONTEXT_LOCK(context, imageID) \
172 ANGLE_SCOPED_GLOBAL_LOCK(); \
173 egl::ScopedContextMutexLock shareContextLock = \
174 egl::LockAndTryMergeContextMutexes(context, imageID)
175 # endif
176 #endif
177
178 } // namespace gl
179
180 #endif // LIBGLESV2_GLOBALSTATE_H_
181