• 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 gl::Context *GetGlobalLastContext();
105 void SetGlobalLastContext(gl::Context *context);
106 Thread *GetCurrentThread();
107 Debug *GetDebug();
108 
109 // Sync the current context from Thread to global state.
110 class ScopedSyncCurrentContextFromThread
111 {
112   public:
113     ScopedSyncCurrentContextFromThread(egl::Thread *thread);
114     ~ScopedSyncCurrentContextFromThread();
115 
116   private:
117     egl::Thread *const mThread;
118 };
119 
120 }  // namespace egl
121 
122 #define ANGLE_SCOPED_GLOBAL_LOCK() \
123     std::lock_guard<angle::GlobalMutex> globalMutexLock(egl::GetGlobalMutex())
124 
125 namespace gl
126 {
GetGlobalContext()127 ANGLE_INLINE Context *GetGlobalContext()
128 {
129 #if defined(ANGLE_PLATFORM_ANDROID)
130     // TODO: Replace this branch with a compile time flag (http://anglebug.com/4764)
131     if (angle::gUseAndroidOpenGLTlsSlot)
132     {
133         return static_cast<gl::Context *>(ANGLE_ANDROID_GET_GL_TLS()[angle::kAndroidOpenGLTlsSlot]);
134     }
135 #endif
136 
137 #if defined(ANGLE_PLATFORM_APPLE)
138     egl::Thread *currentThread = egl::GetCurrentThreadTLS();
139 #else
140     egl::Thread *currentThread = egl::gCurrentThread;
141 #endif
142     ASSERT(currentThread);
143     return currentThread->getContext();
144 }
145 
GetValidGlobalContext()146 ANGLE_INLINE Context *GetValidGlobalContext()
147 {
148 #if defined(ANGLE_PLATFORM_ANDROID)
149     // TODO: Replace this branch with a compile time flag (http://anglebug.com/4764)
150     if (angle::gUseAndroidOpenGLTlsSlot)
151     {
152         Context *context =
153             static_cast<gl::Context *>(ANGLE_ANDROID_GET_GL_TLS()[angle::kAndroidOpenGLTlsSlot]);
154         if (context && !context->isContextLost())
155         {
156             return context;
157         }
158     }
159 #endif
160 
161 #if defined(ANGLE_PLATFORM_APPLE)
162     return GetCurrentValidContextTLS();
163 #else
164     return gCurrentValidContext;
165 #endif
166 }
167 
168 // Generate a context lost error on the context if it is non-null and lost.
169 void GenerateContextLostErrorOnContext(Context *context);
170 void GenerateContextLostErrorOnCurrentGlobalContext();
171 
172 #if defined(ANGLE_FORCE_CONTEXT_CHECK_EVERY_CALL)
173 // TODO(b/177574181): This should be handled in a backend-specific way.
174 // if previous context different from current context, dirty all state
DirtyContextIfNeeded(Context * context)175 static ANGLE_INLINE void DirtyContextIfNeeded(Context *context)
176 {
177     if (context && context != egl::GetGlobalLastContext())
178     {
179         context->dirtyAllState();
180         SetGlobalLastContext(context);
181     }
182 }
183 
184 #endif
185 
GetContextLock(Context * context)186 ANGLE_INLINE std::unique_lock<angle::GlobalMutex> GetContextLock(Context *context)
187 {
188 #if defined(ANGLE_FORCE_CONTEXT_CHECK_EVERY_CALL)
189     auto lock = std::unique_lock<angle::GlobalMutex>(egl::GetGlobalMutex());
190 
191     DirtyContextIfNeeded(context);
192     return lock;
193 #else
194     return context->isShared() ? std::unique_lock<angle::GlobalMutex>(egl::GetGlobalMutex())
195                                : std::unique_lock<angle::GlobalMutex>();
196 #endif
197 }
198 
199 }  // namespace gl
200 
201 #endif  // LIBGLESV2_GLOBALSTATE_H_
202