mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 749678 - 1/5 - Switch GLContext to use mozilla::tls for current context - r=jrmuizel
See comment above class GLContextTLSStorage
This commit is contained in:
parent
802a3dc0cf
commit
1ba7e7e4c1
@ -64,9 +64,8 @@ using namespace mozilla::gfx;
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
#ifdef DEBUG
|
||||
PRUintn GLContext::sCurrentGLContextTLS = -1;
|
||||
#endif
|
||||
tls::key GLContextTLSStorage::sTLSKey;
|
||||
bool GLContextTLSStorage::sTLSKeyAlreadyCreated = false;
|
||||
|
||||
PRUint32 GLContext::sDebugMode = 0;
|
||||
|
||||
|
@ -67,6 +67,7 @@
|
||||
#include "nsRegion.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "thread_helper.h"
|
||||
|
||||
typedef char realGLboolean;
|
||||
|
||||
@ -509,6 +510,71 @@ struct THEBES_API ContextFormat
|
||||
int colorBits() const { return red + green + blue; }
|
||||
};
|
||||
|
||||
/*
|
||||
* This is a helper class to do the little bit of TLS storage that we need
|
||||
* to allow GLContext to keep track of the current GLContext for a given thread.
|
||||
*
|
||||
* This is mostly an optimization to avoid calling MakeCurrent on an
|
||||
* already-current context,which depending on OpenGL libraries/drivers can be
|
||||
* very expensive. An earlier optimization consisted in calling
|
||||
* getCurrentContext to check if the context was already current, but
|
||||
* even that was shown to be very slow at least on Mac and on Linux NVIDIA,
|
||||
* see bug 749678.
|
||||
*
|
||||
* In a general setting, we would have to do a TLS lookup on every MakeCurrent
|
||||
* call. But in GLContext, we currently assume that we only ever make GL calls
|
||||
* on a given GLContext in the same thread that created it (the "owning thread").
|
||||
* That assumption allows us to avoid doing a TLS lookup on every MakeCurrent
|
||||
* call. It's checked by assertions in MOZ_GL_DEBUG mode.
|
||||
*
|
||||
* The way this works is that inside each GLContext, we store a pointer to the
|
||||
* TLS pointer to the current context for this thread. This pointer-to-pointer
|
||||
* (mStorage->mCurrentGLContext) is set during GL context creation: that's where
|
||||
* we rely on the assumption that all GL calls on a given context are made on
|
||||
* the same thread that created that context.
|
||||
*/
|
||||
class GLContextTLSStorage
|
||||
{
|
||||
struct Storage
|
||||
{
|
||||
GLContext *mCurrentGLContext;
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(Storage)
|
||||
Storage() : mCurrentGLContext(nsnull) {}
|
||||
};
|
||||
|
||||
nsRefPtr<Storage> mStorage;
|
||||
static tls::key sTLSKey;
|
||||
static bool sTLSKeyAlreadyCreated;
|
||||
|
||||
public:
|
||||
|
||||
GLContextTLSStorage() {
|
||||
if (!sTLSKeyAlreadyCreated) {
|
||||
tls::create(&sTLSKey);
|
||||
sTLSKeyAlreadyCreated = true;
|
||||
}
|
||||
|
||||
mStorage = tls::get<Storage>(sTLSKey);
|
||||
|
||||
if (!mStorage) {
|
||||
mStorage = new Storage;
|
||||
tls::set<Storage>(sTLSKey, mStorage);
|
||||
}
|
||||
}
|
||||
|
||||
~GLContextTLSStorage() {
|
||||
}
|
||||
|
||||
GLContext *CurrentGLContext() const {
|
||||
return mStorage->mCurrentGLContext;
|
||||
}
|
||||
|
||||
void SetCurrentGLContext(GLContext *c) {
|
||||
mStorage->mCurrentGLContext = c;
|
||||
}
|
||||
};
|
||||
|
||||
class GLContext
|
||||
: public GLLibraryLoader
|
||||
{
|
||||
@ -560,7 +626,7 @@ public:
|
||||
}
|
||||
|
||||
virtual ~GLContext() {
|
||||
NS_ASSERTION(IsDestroyed(), "GLContext implementation must call MarkDestroyed in destructor!");
|
||||
NS_ABORT_IF_FALSE(IsDestroyed(), "GLContext implementation must call MarkDestroyed in destructor!");
|
||||
#ifdef DEBUG
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
@ -570,6 +636,8 @@ public:
|
||||
tip->ReportOutstandingNames();
|
||||
}
|
||||
#endif
|
||||
if (this == CurrentGLContext())
|
||||
SetCurrentGLContext(nsnull);
|
||||
}
|
||||
|
||||
enum ContextFlags {
|
||||
@ -590,17 +658,18 @@ public:
|
||||
|
||||
virtual bool MakeCurrentImpl(bool aForce = false) = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
static void StaticInit() {
|
||||
PR_NewThreadPrivateIndex(&sCurrentGLContextTLS, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool MakeCurrent(bool aForce = false) {
|
||||
#ifdef DEBUG
|
||||
PR_SetThreadPrivate(sCurrentGLContextTLS, this);
|
||||
#endif
|
||||
return MakeCurrentImpl(aForce);
|
||||
if (!aForce &&
|
||||
this == CurrentGLContext())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool success = MakeCurrentImpl(aForce);
|
||||
if (success) {
|
||||
SetCurrentGLContext(this);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool IsContextLost() { return mContextLost; }
|
||||
@ -1087,6 +1156,16 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
GLContext *CurrentGLContext() const {
|
||||
return mTLSStorage.CurrentGLContext();
|
||||
}
|
||||
|
||||
void SetCurrentGLContext(GLContext *c) {
|
||||
mTLSStorage.SetCurrentGLContext(c);
|
||||
}
|
||||
|
||||
|
||||
bool mOffscreenFBOsDirty;
|
||||
|
||||
void GetShaderPrecisionFormatNonES2(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
|
||||
@ -1612,15 +1691,6 @@ protected:
|
||||
|
||||
GLContextSymbols mSymbols;
|
||||
|
||||
#ifdef DEBUG
|
||||
// GLDebugMode will check that we don't send call
|
||||
// to a GLContext that isn't current on the current
|
||||
// thread.
|
||||
// Store the current context when binding to thread local
|
||||
// storage to support DebugMode on an arbitrary thread.
|
||||
static PRUintn sCurrentGLContextTLS;
|
||||
#endif
|
||||
|
||||
void UpdateActualFormat();
|
||||
ContextFormat mActualFormat;
|
||||
|
||||
@ -1629,6 +1699,8 @@ protected:
|
||||
GLuint mOffscreenTexture;
|
||||
bool mFlipped;
|
||||
|
||||
GLContextTLSStorage mTLSStorage;
|
||||
|
||||
// lazy-initialized things
|
||||
GLuint mBlitProgram, mBlitFramebuffer;
|
||||
void UseBlitProgram();
|
||||
@ -1805,16 +1877,12 @@ public:
|
||||
|
||||
void BeforeGLCall(const char* glFunction) {
|
||||
if (DebugMode()) {
|
||||
GLContext *currentGLContext = NULL;
|
||||
|
||||
currentGLContext = (GLContext*)PR_GetThreadPrivate(sCurrentGLContextTLS);
|
||||
|
||||
if (DebugMode() & DebugTrace)
|
||||
printf_stderr("[gl:%p] > %s\n", this, glFunction);
|
||||
if (this != currentGLContext) {
|
||||
if (this != CurrentGLContext()) {
|
||||
printf_stderr("Fatal: %s called on non-current context %p. "
|
||||
"The current context for this thread is %p.\n",
|
||||
glFunction, this, currentGLContext);
|
||||
glFunction, this, CurrentGLContext());
|
||||
NS_ABORT();
|
||||
}
|
||||
}
|
||||
|
@ -301,10 +301,6 @@ gfxPlatform::Init()
|
||||
#error "No gfxPlatform implementation available"
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
mozilla::gl::GLContext::StaticInit();
|
||||
#endif
|
||||
|
||||
nsresult rv;
|
||||
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN) || defined(ANDROID) // temporary, until this is implemented on others
|
||||
|
Loading…
Reference in New Issue
Block a user