• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // Sync the current context from Thread to global state.
44 class [[nodiscard]] ScopedSyncCurrentContextFromThread
45 {
46   public:
47     ScopedSyncCurrentContextFromThread(egl::Thread *thread);
48     ~ScopedSyncCurrentContextFromThread();
49 
50   private:
51     egl::Thread *const mThread;
52 };
53 
54 // Tries to lock "ContextMutex" of the Context current to the "thread".
TryLockCurrentContext(Thread * thread)55 ANGLE_INLINE ScopedContextMutexLock TryLockCurrentContext(Thread *thread)
56 {
57     ASSERT(kIsSharedContextMutexEnabled);
58     gl::Context *context = thread->getContext();
59     return context != nullptr ? ScopedContextMutexLock(context->getContextMutex(), context)
60                               : ScopedContextMutexLock();
61 }
62 
63 // Tries to lock "ContextMutex" or "SharedContextMutex" of the Context with "contextID" if it is
64 // valid, in order to safely use the Context from the "thread".
65 // Note: this function may change mutex type to SharedContextMutex.
TryLockContextForThread(Thread * thread,Display * display,gl::ContextID contextID)66 ANGLE_INLINE ScopedContextMutexLock TryLockContextForThread(Thread *thread,
67                                                             Display *display,
68                                                             gl::ContextID contextID)
69 {
70     ASSERT(kIsSharedContextMutexEnabled);
71     gl::Context *context = GetContextIfValid(display, contextID);
72     return context != nullptr ? (context == thread->getContext()
73                                      ? ScopedContextMutexLock(context->getContextMutex(), context)
74                                      : context->lockAndActivateSharedContextMutex())
75                               : ScopedContextMutexLock();
76 }
77 
78 // Tries to lock "SharedContextMutex" of the Context with "contextID" if it is valid.
79 // Note: this function will change mutex type to SharedContextMutex.
TryLockAndActivateSharedContextMutex(Display * display,gl::ContextID contextID)80 ANGLE_INLINE ScopedContextMutexLock TryLockAndActivateSharedContextMutex(Display *display,
81                                                                          gl::ContextID contextID)
82 {
83     ASSERT(kIsSharedContextMutexEnabled);
84     gl::Context *context = GetContextIfValid(display, contextID);
85     return context != nullptr ? context->lockAndActivateSharedContextMutex()
86                               : ScopedContextMutexLock();
87 }
88 
89 // Locks "SharedContextMutex" of the "context" and then tries to merge it with the
90 // "SharedContextMutex" of the Image with "imageID" if it is valid.
91 // Note: this function may change mutex type to SharedContextMutex.
LockAndTryMergeSharedContextMutexes(gl::Context * context,ImageID imageID)92 ANGLE_INLINE ScopedContextMutexLock LockAndTryMergeSharedContextMutexes(gl::Context *context,
93                                                                         ImageID imageID)
94 {
95     ASSERT(kIsSharedContextMutexEnabled);
96     ASSERT(context->getDisplay() != nullptr);
97     const Image *image = context->getDisplay()->getImage(imageID);
98     if (image != nullptr)
99     {
100         ContextMutex *imageMutex = image->getSharedContextMutex();
101         if (imageMutex != nullptr)
102         {
103             ScopedContextMutexLock lock = context->lockAndActivateSharedContextMutex();
104             context->mergeSharedContextMutexes(imageMutex);
105             return lock;
106         }
107     }
108     // Do not activate "SharedContextMutex" if Image is not valid or does not have the mutex.
109     return ScopedContextMutexLock(context->getContextMutex(), context);
110 }
111 
112 #if !defined(ANGLE_ENABLE_SHARED_CONTEXT_MUTEX)
113 #    define ANGLE_EGL_SCOPED_CONTEXT_LOCK(EP, THREAD, ...)
114 #else
115 #    define ANGLE_EGL_SCOPED_CONTEXT_LOCK(EP, THREAD, ...) \
116         egl::ScopedContextMutexLock shareContextLock = GetContextLock_##EP(THREAD, ##__VA_ARGS__)
117 #endif
118 
119 }  // namespace egl
120 
121 #define ANGLE_SCOPED_GLOBAL_LOCK() egl::ScopedGlobalMutexLock globalMutexLock
122 
123 namespace gl
124 {
GetGlobalContext()125 ANGLE_INLINE Context *GetGlobalContext()
126 {
127 #if defined(ANGLE_PLATFORM_APPLE) || defined(ANGLE_USE_STATIC_THREAD_LOCAL_VARIABLES)
128     egl::Thread *currentThread = egl::GetCurrentThreadTLS();
129 #else
130     egl::Thread *currentThread = egl::gCurrentThread;
131 #endif
132     ASSERT(currentThread);
133     return currentThread->getContext();
134 }
135 
GetValidGlobalContext()136 ANGLE_INLINE Context *GetValidGlobalContext()
137 {
138 #if defined(ANGLE_USE_ANDROID_TLS_SLOT)
139     // TODO: Replace this branch with a compile time flag (http://anglebug.com/4764)
140     if (angle::gUseAndroidOpenGLTlsSlot)
141     {
142         return static_cast<gl::Context *>(ANGLE_ANDROID_GET_GL_TLS()[angle::kAndroidOpenGLTlsSlot]);
143     }
144 #endif
145 
146 #if defined(ANGLE_PLATFORM_APPLE) || defined(ANGLE_USE_STATIC_THREAD_LOCAL_VARIABLES)
147     return GetCurrentValidContextTLS();
148 #else
149     return gCurrentValidContext;
150 #endif
151 }
152 
153 // Generate a context lost error on the context if it is non-null and lost.
154 void GenerateContextLostErrorOnContext(Context *context);
155 void GenerateContextLostErrorOnCurrentGlobalContext();
156 
157 #if defined(ANGLE_FORCE_CONTEXT_CHECK_EVERY_CALL)
158 // TODO(b/177574181): This should be handled in a backend-specific way.
159 // if previous context different from current context, dirty all state
DirtyContextIfNeeded(Context * context)160 static ANGLE_INLINE void DirtyContextIfNeeded(Context *context)
161 {
162     if (context && context != egl::GetGlobalLastContext())
163     {
164         context->dirtyAllState();
165         SetGlobalLastContext(context);
166     }
167 }
168 
169 #endif
170 
171 #if !defined(ANGLE_ENABLE_SHARE_CONTEXT_LOCK)
172 #    define SCOPED_SHARE_CONTEXT_LOCK(context)
173 #    define SCOPED_EGL_IMAGE_SHARE_CONTEXT_LOCK(context, imageID) ANGLE_SCOPED_GLOBAL_LOCK()
174 #else
175 #    if defined(ANGLE_FORCE_CONTEXT_CHECK_EVERY_CALL)
176 #        define SCOPED_SHARE_CONTEXT_LOCK(context)       \
177             egl::ScopedGlobalMutexLock shareContextLock; \
178             DirtyContextIfNeeded(context)
179 #        define SCOPED_EGL_IMAGE_SHARE_CONTEXT_LOCK(context, imageID) \
180             SCOPED_SHARE_CONTEXT_LOCK(context)
181 #    elif !defined(ANGLE_ENABLE_SHARED_CONTEXT_MUTEX)
182 #        define SCOPED_SHARE_CONTEXT_LOCK(context) \
183             egl::ScopedOptionalGlobalMutexLock shareContextLock(context->isShared())
184 #        define SCOPED_EGL_IMAGE_SHARE_CONTEXT_LOCK(context, imageID) ANGLE_SCOPED_GLOBAL_LOCK()
185 #    else
186 #        define SCOPED_SHARE_CONTEXT_LOCK(context) \
187             egl::ScopedContextMutexLock shareContextLock(context->getContextMutex(), context)
188 #        define SCOPED_EGL_IMAGE_SHARE_CONTEXT_LOCK(context, imageID) \
189             ANGLE_SCOPED_GLOBAL_LOCK();                               \
190             egl::ScopedContextMutexLock shareContextLock =            \
191                 egl::LockAndTryMergeSharedContextMutexes(context, imageID)
192 #    endif
193 #endif
194 
195 }  // namespace gl
196 
197 #endif  // LIBGLESV2_GLOBALSTATE_H_
198