global_state.h (7228B)
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 [[nodiscard]] 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 { 134 ANGLE_INLINE Context *GetGlobalContext() 135 { 136 #if defined(ANGLE_USE_ANDROID_TLS_SLOT) 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 153 ANGLE_INLINE Context *GetValidGlobalContext() 154 { 155 #if defined(ANGLE_USE_ANDROID_TLS_SLOT) 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 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 193 #if !defined(ANGLE_ENABLE_SHARE_CONTEXT_LOCK) 194 # define SCOPED_SHARE_CONTEXT_LOCK(context) 195 #else 196 ANGLE_INLINE std::unique_lock<angle::GlobalMutex> GetContextLock(Context *context) 197 { 198 # if defined(ANGLE_FORCE_CONTEXT_CHECK_EVERY_CALL) 199 auto lock = std::unique_lock<angle::GlobalMutex>(egl::GetGlobalMutex()); 200 201 DirtyContextIfNeeded(context); 202 return lock; 203 # else 204 return context->isShared() ? std::unique_lock<angle::GlobalMutex>(egl::GetGlobalMutex()) 205 : std::unique_lock<angle::GlobalMutex>(); 206 # endif 207 } 208 209 # define SCOPED_SHARE_CONTEXT_LOCK(context) \ 210 std::unique_lock<angle::GlobalMutex> shareContextLock = GetContextLock(context) 211 #endif 212 213 } // namespace gl 214 215 #endif // LIBGLESV2_GLOBALSTATE_H_