xref: /aosp_15_r20/external/angle/src/libGLESv2/global_state.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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) || defined(ANGLE_USE_ANDROID_TLS_SLOT)
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::ScopedGlobalEGLMutexLock globalMutexLock
105 #if ANGLE_CAPTURE_ENABLED
106 #    define ANGLE_SCOPED_GLOBAL_EGL_AND_EGL_SYNC_LOCK() \
107         egl::ScopedGlobalEGLMutexLock globalMutexLock
108 #else
109 #    define ANGLE_SCOPED_GLOBAL_EGL_AND_EGL_SYNC_LOCK() \
110         egl::ScopedGlobalEGLMutexLock globalMutexLock;  \
111         egl::ScopedGlobalEGLSyncObjectMutexLock globalEGLSyncObjectMutexLock
112 #endif
113 
114 #if ANGLE_CAPTURE_ENABLED
115 #    define ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK() egl::ScopedGlobalEGLMutexLock globalMutexLock
116 #else
117 #    define ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK() \
118         egl::ScopedGlobalEGLSyncObjectMutexLock globalEGLSyncObjectMutexLock
119 #endif
120 
121 namespace gl
122 {
GetGlobalContext()123 ANGLE_INLINE Context *GetGlobalContext()
124 {
125 #if defined(ANGLE_PLATFORM_APPLE) || defined(ANGLE_USE_STATIC_THREAD_LOCAL_VARIABLES)
126     egl::Thread *currentThread = egl::GetCurrentThreadTLS();
127 #else
128     egl::Thread *currentThread = egl::gCurrentThread;
129 #endif
130     ASSERT(currentThread);
131     return currentThread->getContext();
132 }
133 
GetValidGlobalContext()134 ANGLE_INLINE Context *GetValidGlobalContext()
135 {
136 #if defined(ANGLE_USE_ANDROID_TLS_SLOT)
137     // TODO: Replace this branch with a compile time flag (http://anglebug.com/42263361)
138     if (angle::gUseAndroidOpenGLTlsSlot)
139     {
140         return static_cast<gl::Context *>(ANGLE_ANDROID_GET_GL_TLS()[angle::kAndroidOpenGLTlsSlot]);
141     }
142 #endif
143 
144 #if defined(ANGLE_PLATFORM_APPLE) || defined(ANGLE_USE_STATIC_THREAD_LOCAL_VARIABLES)
145     return GetCurrentValidContextTLS();
146 #else
147     return gCurrentValidContext;
148 #endif
149 }
150 
151 // Generate a context lost error on the context if it is non-null and lost.
152 void GenerateContextLostErrorOnContext(Context *context);
153 void GenerateContextLostErrorOnCurrentGlobalContext();
154 
155 #if defined(ANGLE_FORCE_CONTEXT_CHECK_EVERY_CALL)
156 // TODO(b/177574181): This should be handled in a backend-specific way.
157 // if previous context different from current context, dirty all state
DirtyContextIfNeeded(Context * context)158 static ANGLE_INLINE void DirtyContextIfNeeded(Context *context)
159 {
160     if (context && context != egl::GetGlobalLastContext())
161     {
162         context->dirtyAllState();
163         SetGlobalLastContext(context);
164     }
165 }
166 
167 #endif
168 
169 #if !defined(ANGLE_ENABLE_SHARE_CONTEXT_LOCK)
170 #    define SCOPED_SHARE_CONTEXT_LOCK(context)
171 #    define SCOPED_EGL_IMAGE_SHARE_CONTEXT_LOCK(context, imageID) ANGLE_SCOPED_GLOBAL_LOCK()
172 #else
173 #    if defined(ANGLE_FORCE_CONTEXT_CHECK_EVERY_CALL)
174 #        define SCOPED_SHARE_CONTEXT_LOCK(context)          \
175             egl::ScopedGlobalEGLMutexLock shareContextLock; \
176             DirtyContextIfNeeded(context)
177 #        define SCOPED_EGL_IMAGE_SHARE_CONTEXT_LOCK(context, imageID) \
178             SCOPED_SHARE_CONTEXT_LOCK(context)
179 #    elif !defined(ANGLE_ENABLE_CONTEXT_MUTEX)
180 #        define SCOPED_SHARE_CONTEXT_LOCK(context) \
181             egl::ScopedOptionalGlobalMutexLock shareContextLock(context->isShared())
182 #        define SCOPED_EGL_IMAGE_SHARE_CONTEXT_LOCK(context, imageID) ANGLE_SCOPED_GLOBAL_LOCK()
183 #    else
184 #        define SCOPED_SHARE_CONTEXT_LOCK(context) \
185             egl::ScopedContextMutexLock shareContextLock(context->getContextMutex())
186 #        define SCOPED_EGL_IMAGE_SHARE_CONTEXT_LOCK(context, imageID) \
187             ANGLE_SCOPED_GLOBAL_LOCK();                               \
188             egl::ScopedContextMutexLock shareContextLock =            \
189                 egl::LockAndTryMergeContextMutexes(context, imageID)
190 #    endif
191 #endif
192 
193 }  // namespace gl
194 
195 #endif  // LIBGLESV2_GLOBALSTATE_H_
196