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