• 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/Thread.h"
15 #include "libANGLE/features.h"
16 
17 #if defined(ANGLE_PLATFORM_APPLE) || (ANGLE_PLATFORM_ANDROID)
18 #    include "common/tls.h"
19 #endif
20 
21 #include <mutex>
22 
23 namespace angle
24 {
25 using GlobalMutex = std::recursive_mutex;
26 
27 //  - TLS_SLOT_OPENGL and TLS_SLOT_OPENGL_API: These two aren't used by bionic
28 //    itself, but allow the graphics code to access TLS directly rather than
29 //    using the pthread API.
30 //
31 // Choose the TLS_SLOT_OPENGL TLS slot with the value that matches value in the header file in
32 // bionic(tls_defines.h)
33 constexpr size_t kAndroidOpenGLTlsSlot = 3;
34 
35 #if defined(ANGLE_PLATFORM_ANDROID)
36 
37 // The following ASM variant provides a much more performant store/retrieve interface
38 // compared to those provided by the pthread library. These have been derived from code
39 // in the bionic module of Android ->
40 // https://cs.android.com/android/platform/superproject/+/master:bionic/libc/platform/bionic/tls.h;l=30
41 
42 #    if defined(__aarch64__)
43 #        define ANGLE_ANDROID_GET_GL_TLS()                  \
44             ({                                              \
45                 void **__val;                               \
46                 __asm__("mrs %0, tpidr_el0" : "=r"(__val)); \
47                 __val;                                      \
48             })
49 #    elif defined(__arm__)
50 #        define ANGLE_ANDROID_GET_GL_TLS()                           \
51             ({                                                       \
52                 void **__val;                                        \
53                 __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__val)); \
54                 __val;                                               \
55             })
56 #    elif defined(__mips__)
57 // On mips32r1, this goes via a kernel illegal instruction trap that's
58 // optimized for v1
59 #        define ANGLE_ANDROID_GET_GL_TLS()       \
60             ({                                   \
61                 register void **__val asm("v1"); \
62                 __asm__(                         \
63                     ".set    push\n"             \
64                     ".set    mips32r2\n"         \
65                     "rdhwr   %0,$29\n"           \
66                     ".set    pop\n"              \
67                     : "=r"(__val));              \
68                 __val;                           \
69             })
70 #    elif defined(__i386__)
71 #        define ANGLE_ANDROID_GET_GL_TLS()                \
72             ({                                            \
73                 void **__val;                             \
74                 __asm__("movl %%gs:0, %0" : "=r"(__val)); \
75                 __val;                                    \
76             })
77 #    elif defined(__x86_64__)
78 #        define ANGLE_ANDROID_GET_GL_TLS()               \
79             ({                                           \
80                 void **__val;                            \
81                 __asm__("mov %%fs:0, %0" : "=r"(__val)); \
82                 __val;                                   \
83             })
84 #    else
85 #        error unsupported architecture
86 #    endif
87 
88 #endif  // ANGLE_PLATFORM_ANDROID
89 }  // namespace angle
90 
91 namespace egl
92 {
93 class Debug;
94 class Thread;
95 
96 #if defined(ANGLE_PLATFORM_APPLE)
97 extern Thread *GetCurrentThreadTLS();
98 extern void SetCurrentThreadTLS(Thread *thread);
99 #else
100 extern thread_local Thread *gCurrentThread;
101 #endif
102 
103 angle::GlobalMutex &GetGlobalMutex();
104 angle::GlobalMutex &GetGlobalSurfaceMutex();
105 gl::Context *GetGlobalLastContext();
106 void SetGlobalLastContext(gl::Context *context);
107 Thread *GetCurrentThread();
108 Debug *GetDebug();
109 
110 // Sync the current context from Thread to global state.
111 class ANGLE_NO_DISCARD ScopedSyncCurrentContextFromThread
112 {
113   public:
114     ScopedSyncCurrentContextFromThread(egl::Thread *thread);
115     ~ScopedSyncCurrentContextFromThread();
116 
117   private:
118     egl::Thread *const mThread;
119 };
120 
121 }  // namespace egl
122 
123 #define ANGLE_GLOBAL_SURFACE_LOCK_VAR_NAME globalSurfaceMutexLock
124 #define ANGLE_SCOPED_GLOBAL_SURFACE_LOCK()                                  \
125     std::lock_guard<angle::GlobalMutex> ANGLE_GLOBAL_SURFACE_LOCK_VAR_NAME( \
126         egl::GetGlobalSurfaceMutex())
127 
128 #define ANGLE_GLOBAL_LOCK_VAR_NAME globalMutexLock
129 #define ANGLE_SCOPED_GLOBAL_LOCK() \
130     std::lock_guard<angle::GlobalMutex> ANGLE_GLOBAL_LOCK_VAR_NAME(egl::GetGlobalMutex())
131 
132 namespace gl
133 {
GetGlobalContext()134 ANGLE_INLINE Context *GetGlobalContext()
135 {
136 #if defined(ANGLE_PLATFORM_ANDROID)
137     // TODO: Replace this branch with a compile time flag (http://anglebug.com/4764)
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)
145     egl::Thread *currentThread = egl::GetCurrentThreadTLS();
146 #else
147     egl::Thread *currentThread = egl::gCurrentThread;
148 #endif
149     ASSERT(currentThread);
150     return currentThread->getContext();
151 }
152 
GetValidGlobalContext()153 ANGLE_INLINE Context *GetValidGlobalContext()
154 {
155 #if defined(ANGLE_PLATFORM_ANDROID)
156     // TODO: Replace this branch with a compile time flag (http://anglebug.com/4764)
157     if (angle::gUseAndroidOpenGLTlsSlot)
158     {
159         Context *context =
160             static_cast<gl::Context *>(ANGLE_ANDROID_GET_GL_TLS()[angle::kAndroidOpenGLTlsSlot]);
161         if (context && !context->isContextLost())
162         {
163             return context;
164         }
165     }
166 #endif
167 
168 #if defined(ANGLE_PLATFORM_APPLE)
169     return GetCurrentValidContextTLS();
170 #else
171     return gCurrentValidContext;
172 #endif
173 }
174 
175 // Generate a context lost error on the context if it is non-null and lost.
176 void GenerateContextLostErrorOnContext(Context *context);
177 void GenerateContextLostErrorOnCurrentGlobalContext();
178 
179 #if defined(ANGLE_FORCE_CONTEXT_CHECK_EVERY_CALL)
180 // TODO(b/177574181): This should be handled in a backend-specific way.
181 // if previous context different from current context, dirty all state
DirtyContextIfNeeded(Context * context)182 static ANGLE_INLINE void DirtyContextIfNeeded(Context *context)
183 {
184     if (context && context != egl::GetGlobalLastContext())
185     {
186         context->dirtyAllState();
187         SetGlobalLastContext(context);
188     }
189 }
190 
191 #endif
192 
GetContextLock(Context * context)193 ANGLE_INLINE std::unique_lock<angle::GlobalMutex> GetContextLock(Context *context)
194 {
195 #if defined(ANGLE_FORCE_CONTEXT_CHECK_EVERY_CALL)
196     auto lock = std::unique_lock<angle::GlobalMutex>(egl::GetGlobalMutex());
197 
198     DirtyContextIfNeeded(context);
199     return lock;
200 #else
201     return context->isShared() ? std::unique_lock<angle::GlobalMutex>(egl::GetGlobalMutex())
202                                : std::unique_lock<angle::GlobalMutex>();
203 #endif
204 }
205 
206 }  // namespace gl
207 
208 #endif  // LIBGLESV2_GLOBALSTATE_H_
209