• 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 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