diff options
Diffstat (limited to 'gfx/angle/checkout/src/libGLESv2/global_state.h')
-rw-r--r-- | gfx/angle/checkout/src/libGLESv2/global_state.h | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libGLESv2/global_state.h b/gfx/angle/checkout/src/libGLESv2/global_state.h new file mode 100644 index 0000000000..947baf3c06 --- /dev/null +++ b/gfx/angle/checkout/src/libGLESv2/global_state.h @@ -0,0 +1,215 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// global_state.h : Defines functions for querying the thread-local GL and EGL state. + +#ifndef LIBGLESV2_GLOBALSTATE_H_ +#define LIBGLESV2_GLOBALSTATE_H_ + +#include "libANGLE/Context.h" +#include "libANGLE/Debug.h" +#include "libANGLE/Thread.h" +#include "libANGLE/features.h" + +#if defined(ANGLE_PLATFORM_APPLE) || (ANGLE_PLATFORM_ANDROID) +# include "common/tls.h" +#endif + +#include <mutex> + +namespace angle +{ +using GlobalMutex = std::recursive_mutex; + +// - TLS_SLOT_OPENGL and TLS_SLOT_OPENGL_API: These two aren't used by bionic +// itself, but allow the graphics code to access TLS directly rather than +// using the pthread API. +// +// Choose the TLS_SLOT_OPENGL TLS slot with the value that matches value in the header file in +// bionic(tls_defines.h) +constexpr size_t kAndroidOpenGLTlsSlot = 3; + +#if defined(ANGLE_PLATFORM_ANDROID) + +// The following ASM variant provides a much more performant store/retrieve interface +// compared to those provided by the pthread library. These have been derived from code +// in the bionic module of Android -> +// https://cs.android.com/android/platform/superproject/+/master:bionic/libc/platform/bionic/tls.h;l=30 + +# if defined(__aarch64__) +# define ANGLE_ANDROID_GET_GL_TLS() \ + ({ \ + void **__val; \ + __asm__("mrs %0, tpidr_el0" : "=r"(__val)); \ + __val; \ + }) +# elif defined(__arm__) +# define ANGLE_ANDROID_GET_GL_TLS() \ + ({ \ + void **__val; \ + __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__val)); \ + __val; \ + }) +# elif defined(__mips__) +// On mips32r1, this goes via a kernel illegal instruction trap that's +// optimized for v1 +# define ANGLE_ANDROID_GET_GL_TLS() \ + ({ \ + register void **__val asm("v1"); \ + __asm__( \ + ".set push\n" \ + ".set mips32r2\n" \ + "rdhwr %0,$29\n" \ + ".set pop\n" \ + : "=r"(__val)); \ + __val; \ + }) +# elif defined(__i386__) +# define ANGLE_ANDROID_GET_GL_TLS() \ + ({ \ + void **__val; \ + __asm__("movl %%gs:0, %0" : "=r"(__val)); \ + __val; \ + }) +# elif defined(__x86_64__) +# define ANGLE_ANDROID_GET_GL_TLS() \ + ({ \ + void **__val; \ + __asm__("mov %%fs:0, %0" : "=r"(__val)); \ + __val; \ + }) +# else +# error unsupported architecture +# endif + +#endif // ANGLE_PLATFORM_ANDROID +} // namespace angle + +namespace egl +{ +class Debug; +class Thread; + +#if defined(ANGLE_PLATFORM_APPLE) +extern Thread *GetCurrentThreadTLS(); +extern void SetCurrentThreadTLS(Thread *thread); +#else +extern thread_local Thread *gCurrentThread; +#endif + +angle::GlobalMutex &GetGlobalMutex(); +angle::GlobalMutex &GetGlobalSurfaceMutex(); +gl::Context *GetGlobalLastContext(); +void SetGlobalLastContext(gl::Context *context); +Thread *GetCurrentThread(); +Debug *GetDebug(); + +// Sync the current context from Thread to global state. +class [[nodiscard]] ScopedSyncCurrentContextFromThread +{ + public: + ScopedSyncCurrentContextFromThread(egl::Thread *thread); + ~ScopedSyncCurrentContextFromThread(); + + private: + egl::Thread *const mThread; +}; + +} // namespace egl + +#define ANGLE_GLOBAL_SURFACE_LOCK_VAR_NAME globalSurfaceMutexLock +#define ANGLE_SCOPED_GLOBAL_SURFACE_LOCK() \ + std::lock_guard<angle::GlobalMutex> ANGLE_GLOBAL_SURFACE_LOCK_VAR_NAME( \ + egl::GetGlobalSurfaceMutex()) + +#define ANGLE_GLOBAL_LOCK_VAR_NAME globalMutexLock +#define ANGLE_SCOPED_GLOBAL_LOCK() \ + std::lock_guard<angle::GlobalMutex> ANGLE_GLOBAL_LOCK_VAR_NAME(egl::GetGlobalMutex()) + +namespace gl +{ +ANGLE_INLINE Context *GetGlobalContext() +{ +#if defined(ANGLE_USE_ANDROID_TLS_SLOT) + // TODO: Replace this branch with a compile time flag (http://anglebug.com/4764) + if (angle::gUseAndroidOpenGLTlsSlot) + { + return static_cast<gl::Context *>(ANGLE_ANDROID_GET_GL_TLS()[angle::kAndroidOpenGLTlsSlot]); + } +#endif + +#if defined(ANGLE_PLATFORM_APPLE) + egl::Thread *currentThread = egl::GetCurrentThreadTLS(); +#else + egl::Thread *currentThread = egl::gCurrentThread; +#endif + ASSERT(currentThread); + return currentThread->getContext(); +} + +ANGLE_INLINE Context *GetValidGlobalContext() +{ +#if defined(ANGLE_USE_ANDROID_TLS_SLOT) + // TODO: Replace this branch with a compile time flag (http://anglebug.com/4764) + if (angle::gUseAndroidOpenGLTlsSlot) + { + Context *context = + static_cast<gl::Context *>(ANGLE_ANDROID_GET_GL_TLS()[angle::kAndroidOpenGLTlsSlot]); + if (context && !context->isContextLost()) + { + return context; + } + } +#endif + +#if defined(ANGLE_PLATFORM_APPLE) + return GetCurrentValidContextTLS(); +#else + return gCurrentValidContext; +#endif +} + +// Generate a context lost error on the context if it is non-null and lost. +void GenerateContextLostErrorOnContext(Context *context); +void GenerateContextLostErrorOnCurrentGlobalContext(); + +#if defined(ANGLE_FORCE_CONTEXT_CHECK_EVERY_CALL) +// TODO(b/177574181): This should be handled in a backend-specific way. +// if previous context different from current context, dirty all state +static ANGLE_INLINE void DirtyContextIfNeeded(Context *context) +{ + if (context && context != egl::GetGlobalLastContext()) + { + context->dirtyAllState(); + SetGlobalLastContext(context); + } +} + +#endif + +#if !defined(ANGLE_ENABLE_SHARE_CONTEXT_LOCK) +# define SCOPED_SHARE_CONTEXT_LOCK(context) +#else +ANGLE_INLINE std::unique_lock<angle::GlobalMutex> GetContextLock(Context *context) +{ +# if defined(ANGLE_FORCE_CONTEXT_CHECK_EVERY_CALL) + auto lock = std::unique_lock<angle::GlobalMutex>(egl::GetGlobalMutex()); + + DirtyContextIfNeeded(context); + return lock; +# else + return context->isShared() ? std::unique_lock<angle::GlobalMutex>(egl::GetGlobalMutex()) + : std::unique_lock<angle::GlobalMutex>(); +# endif +} + +# define SCOPED_SHARE_CONTEXT_LOCK(context) \ + std::unique_lock<angle::GlobalMutex> shareContextLock = GetContextLock(context) +#endif + +} // namespace gl + +#endif // LIBGLESV2_GLOBALSTATE_H_ |