Bug 1278403 - Choose GLContext::DebugFlags based on ContextCreateFlags. - r=jrmuizel
MozReview-Commit-ID: KSjIhu8I20C
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -294,20 +294,19 @@ WebGLContext::DestroyResourcesAndContext
continue;
mExtensions[extension]->MarkLost();
mExtensions[extension] = nullptr;
}
// We just got rid of everything, so the context had better
// have been going away.
-#ifdef DEBUG
- if (gl->DebugMode())
+ if (GLContext::ShouldSpew()) {
printf_stderr("--- WebGL context destroyed: %p\n", gl.get());
-#endif
+ }
gl = nullptr;
}
void
WebGLContext::Invalidate()
{
if (!mCanvasElement)
@@ -956,20 +955,19 @@ WebGLContext::SetDimensions(int32_t sign
if (!ResizeBackbuffer(width, height)) {
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID,
NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_RESIZE"));
const nsLiteralCString text("Initializing WebGL backbuffer failed.");
ThrowEvent_WebGLContextCreationError(text);
return NS_ERROR_FAILURE;
}
-#ifdef DEBUG
- if (gl->DebugMode())
+ if (GLContext::ShouldSpew()) {
printf_stderr("--- WebGL context created: %p\n", gl.get());
-#endif
+ }
mResetLayer = true;
mOptionsFrozen = true;
// Update our internal stuff:
if (gl->WorkAroundDriverBugs()) {
if (!mOptions.alpha && gl->Caps().alpha)
mNeedsFakeNoAlpha = true;
--- a/gfx/gl/GLBlitHelper.cpp
+++ b/gfx/gl/GLBlitHelper.cpp
@@ -324,17 +324,17 @@ GLBlitHelper::InitTexQuadProgram(BlitTyp
mGL->fCompileShader(fragShader);
program = mGL->fCreateProgram();
mGL->fAttachShader(program, mTexBlit_VertShader);
mGL->fAttachShader(program, fragShader);
mGL->fBindAttribLocation(program, 0, "aPosition");
mGL->fLinkProgram(program);
- if (mGL->DebugMode()) {
+ if (GLContext::ShouldSpew()) {
GLint status = 0;
mGL->fGetShaderiv(mTexBlit_VertShader, LOCAL_GL_COMPILE_STATUS, &status);
if (status != LOCAL_GL_TRUE) {
NS_ERROR("Vert shader compilation failed.");
GLint length = 0;
mGL->fGetShaderiv(mTexBlit_VertShader, LOCAL_GL_INFO_LOG_LENGTH, &length);
if (!length) {
@@ -367,17 +367,17 @@ GLBlitHelper::InitTexQuadProgram(BlitTyp
printf_stderr("Shader info log (%d bytes): %s\n", length, buffer.get());
break;
}
}
GLint status = 0;
mGL->fGetProgramiv(program, LOCAL_GL_LINK_STATUS, &status);
if (status != LOCAL_GL_TRUE) {
- if (mGL->DebugMode()) {
+ if (GLContext::ShouldSpew()) {
NS_ERROR("Linking blit program failed.");
GLint length = 0;
mGL->fGetProgramiv(program, LOCAL_GL_INFO_LOG_LENGTH, &length);
if (!length) {
printf_stderr("No program info log available.\n");
break;
}
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -50,18 +50,16 @@ namespace gl {
using namespace mozilla::gfx;
using namespace mozilla::layers;
#ifdef MOZ_GL_DEBUG
unsigned GLContext::sCurrentGLContextTLS = -1;
#endif
-uint32_t GLContext::sDebugMode = 0;
-
// If adding defines, don't forget to undefine symbols. See #undef block below.
#define CORE_SYMBOL(x) { (PRFuncPtr*) &mSymbols.f##x, { #x, nullptr } }
#define CORE_EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, { #x, #x #y, #x #z, nullptr } }
#define EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, { #x #y, #x #z, nullptr } }
#define EXT_SYMBOL3(x,y,z,w) { (PRFuncPtr*) &mSymbols.f##x, { #x #y, #x #z, #x #w, nullptr } }
#define END_SYMBOLS { nullptr, { nullptr } }
// should match the order of GLExtensions, and be null-terminated.
@@ -395,26 +393,68 @@ ParseGLVersion(GLContext* gl, uint32_t*
MOZ_ASSERT(false, "Invalid minor version.");
return false;
}
*out_version = (uint32_t)majorVersion * 100 + (uint32_t)minorVersion * 10;
return true;
}
+static uint8_t
+ChooseDebugFlags(CreateContextFlags createFlags)
+{
+ uint8_t debugFlags = 0;
+
+#ifdef MOZ_GL_DEBUG
+ if (gfxEnv::GlDebug()) {
+ debugFlags |= GLContext::DebugFlagEnabled;
+ }
+
+ // Enables extra verbose output, informing of the start and finish of every GL call.
+ // Useful e.g. to record information to investigate graphics system crashes/lockups
+ if (gfxEnv::GlDebugVerbose()) {
+ debugFlags |= GLContext::DebugFlagTrace;
+ }
+
+ // Aborts on GL error. Can be useful to debug quicker code that is known not to
+ // generate any GL error in principle.
+ bool abortOnError = false;
+
+ if (createFlags & CreateContextFlags::NO_VALIDATION) {
+ abortOnError = true;
+
+ const auto fnStringsMatch = [](const char* a, const char* b) {
+ return strcmp(a, b) == 0;
+ };
+
+ const char* envAbortOnError = PR_GetEnv("MOZ_GL_DEBUG_ABORT_ON_ERROR");
+ if (envAbortOnError && fnStringsMatch(envAbortOnError, "0")) {
+ abortOnError = false;
+ }
+ }
+
+ if (abortOnError) {
+ debugFlags |= GLContext::DebugFlagAbortOnError;
+ }
+#endif
+
+ return debugFlags;
+}
+
GLContext::GLContext(CreateContextFlags flags, const SurfaceCaps& caps,
GLContext* sharedContext, bool isOffscreen)
: mIsOffscreen(isOffscreen),
mContextLost(false),
mVersion(0),
mProfile(ContextProfile::Unknown),
mShadingLanguageVersion(0),
mVendor(GLVendor::Other),
mRenderer(GLRenderer::Other),
mTopError(LOCAL_GL_NO_ERROR),
+ mDebugFlags(ChooseDebugFlags(flags)),
mSharedContext(sharedContext),
mCaps(caps),
mScreen(nullptr),
mLockedSurface(nullptr),
mMaxTextureSize(0),
mMaxCubeMapTextureSize(0),
mMaxTextureImageSize(0),
mMaxRenderbufferSize(0),
@@ -525,30 +565,16 @@ GLContext::LoadFeatureSymbols(const char
return true;
};
bool
GLContext::InitWithPrefixImpl(const char* prefix, bool trygl)
{
mWorkAroundDriverBugs = gfxPrefs::WorkAroundDriverBugs();
-#ifdef MOZ_GL_DEBUG
- if (gfxEnv::GlDebug())
- sDebugMode |= DebugEnabled;
-
- // enables extra verbose output, informing of the start and finish of every GL call.
- // useful e.g. to record information to investigate graphics system crashes/lockups
- if (gfxEnv::GlDebugVerbose())
- sDebugMode |= DebugTrace;
-
- // aborts on GL error. Can be useful to debug quicker code that is known not to generate any GL error in principle.
- if (gfxEnv::GlDebugAbortOnError())
- sDebugMode |= DebugAbortOnError;
-#endif
-
const SymLoadStruct coreSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fActiveTexture, { "ActiveTexture", "ActiveTextureARB", nullptr } },
{ (PRFuncPtr*) &mSymbols.fAttachShader, { "AttachShader", "AttachShaderARB", nullptr } },
{ (PRFuncPtr*) &mSymbols.fBindAttribLocation, { "BindAttribLocation", "BindAttribLocationARB", nullptr } },
{ (PRFuncPtr*) &mSymbols.fBindBuffer, { "BindBuffer", "BindBufferARB", nullptr } },
{ (PRFuncPtr*) &mSymbols.fBindTexture, { "BindTexture", "BindTextureARB", nullptr } },
{ (PRFuncPtr*) &mSymbols.fBlendColor, { "BlendColor", nullptr } },
{ (PRFuncPtr*) &mSymbols.fBlendEquation, { "BlendEquation", nullptr } },
@@ -1045,17 +1071,17 @@ GLContext::InitWithPrefixImpl(const char
mCaps.color = true;
mCaps.alpha = false;
}
mTexGarbageBin = new TextureGarbageBin(this);
MOZ_ASSERT(IsCurrent());
- if (DebugMode() && IsExtensionSupported(KHR_debug)) {
+ if (ShouldSpew() && IsExtensionSupported(KHR_debug)) {
fEnable(LOCAL_GL_DEBUG_OUTPUT);
fDisable(LOCAL_GL_DEBUG_OUTPUT_SYNCHRONOUS);
fDebugMessageCallback(&StaticDebugCallback, (void*)this);
fDebugMessageControl(LOCAL_GL_DONT_CARE,
LOCAL_GL_DONT_CARE,
LOCAL_GL_DONT_CARE,
0, nullptr,
true);
@@ -1586,17 +1612,17 @@ GLContext::LoadMoreSymbols(const char* p
}
// Load developer symbols, don't fail if we can't find them.
const SymLoadStruct devSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fGetTexImage, { "GetTexImage", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGetTexLevelParameteriv, { "GetTexLevelParameteriv", nullptr } },
END_SYMBOLS
};
- const bool warnOnFailures = DebugMode();
+ const bool warnOnFailures = ShouldSpew();
LoadSymbols(devSymbols, trygl, prefix, warnOnFailures);
}
#undef CORE_SYMBOL
#undef CORE_EXT_SYMBOL2
#undef EXT_SYMBOL2
#undef EXT_SYMBOL3
#undef END_SYMBOLS
@@ -2038,27 +2064,27 @@ GLContext::AssembleOffscreenFBs(const GL
// We should be all resized. Check for framebuffer completeness.
GLenum status;
bool isComplete = true;
if (!IsFramebufferComplete(drawFB, &status)) {
NS_WARNING("DrawFBO: Incomplete");
#ifdef MOZ_GL_DEBUG
- if (DebugMode()) {
+ if (ShouldSpew()) {
printf_stderr("Framebuffer status: %X\n", status);
}
#endif
isComplete = false;
}
if (!IsFramebufferComplete(readFB, &status)) {
NS_WARNING("ReadFBO: Incomplete");
#ifdef MOZ_GL_DEBUG
- if (DebugMode()) {
+ if (ShouldSpew()) {
printf_stderr("Framebuffer status: %X\n", status);
}
#endif
isComplete = false;
}
if (drawFB_out) {
*drawFB_out = drawFB;
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -716,53 +716,54 @@ private:
# else
# define MOZ_FUNCTION_NAME __func__ // defined in C99, supported in various C++ compilers. Just raw function name.
# endif
#endif
void BeforeGLCall(const char* funcName) {
MOZ_ASSERT(IsCurrent());
- if (DebugMode()) {
+ if (mDebugFlags) {
FlushErrors();
- if (DebugMode() & DebugTrace)
+ if (mDebugFlags & DebugFlagTrace) {
printf_stderr("[gl:%p] > %s\n", this, funcName);
+ }
GLContext* tlsContext = (GLContext*)PR_GetThreadPrivate(sCurrentGLContextTLS);
if (this != tlsContext) {
printf_stderr("Fatal: %s called on non-current context %p. The"
" current context for this thread is %p.\n",
funcName, this, tlsContext);
MOZ_CRASH("GFX: GLContext is not current.");
}
}
}
void AfterGLCall(const char* funcName) {
- if (DebugMode()) {
+ if (mDebugFlags) {
// calling fFinish() immediately after every GL call makes sure that if this GL command crashes,
// the stack trace will actually point to it. Otherwise, OpenGL being an asynchronous API, stack traces
// tend to be meaningless
mSymbols.fFinish();
GLenum err = FlushErrors();
- if (DebugMode() & DebugTrace) {
+ if (mDebugFlags & DebugFlagTrace) {
printf_stderr("[gl:%p] < %s [%s (0x%04x)]\n", this, funcName,
GLErrorToString(err), err);
}
if (err != LOCAL_GL_NO_ERROR &&
!mLocalErrorScopeStack.size())
{
printf_stderr("[gl:%p] %s: Generated unexpected %s error."
" (0x%04x)\n", this, funcName,
GLErrorToString(err), err);
- if (DebugMode() & DebugAbortOnError)
+ if (mDebugFlags & DebugFlagAbortOnError)
MOZ_CRASH("MOZ_GL_DEBUG_ABORT_ON_ERROR");
}
}
}
GLContext *TrackingContext()
{
GLContext *tip = this;
@@ -3347,45 +3348,37 @@ public:
const char *extension);
GLint GetMaxTextureImageSize() { return mMaxTextureImageSize; }
public:
std::map<GLuint, SharedSurface*> mFBOMapping;
enum {
- DebugEnabled = 1 << 0,
- DebugTrace = 1 << 1,
- DebugAbortOnError = 1 << 2
+ DebugFlagEnabled = 1 << 0,
+ DebugFlagTrace = 1 << 1,
+ DebugFlagAbortOnError = 1 << 2
};
- static uint32_t sDebugMode;
-
- static uint32_t DebugMode() {
-#ifdef MOZ_GL_DEBUG
- return sDebugMode;
-#else
- return 0;
-#endif
- }
+ const uint8_t mDebugFlags;
protected:
RefPtr<GLContext> mSharedContext;
// The thread id which this context was created.
PlatformThreadId mOwningThreadId;
GLContextSymbols mSymbols;
#ifdef MOZ_GL_DEBUG
- // GLDebugMode will check that we don't send call
+ // Non-zero debug flags 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.
+ // storage to support debug flags on an arbitrary thread.
static unsigned sCurrentGLContextTLS;
#endif
UniquePtr<GLBlitHelper> mBlitHelper;
UniquePtr<GLReadTexImageHelper> mReadTexImageHelper;
public:
GLBlitHelper* BlitHelper();
--- a/gfx/gl/GLContextProviderGLX.cpp
+++ b/gfx/gl/GLContextProviderGLX.cpp
@@ -791,21 +791,19 @@ GLContextGLX::CreateGLContext(CreateCont
ContextProfile profile)
{
GLXLibrary& glx = sGLXLibrary;
int db = 0;
int err = glx.xGetFBConfigAttrib(display, cfg,
LOCAL_GLX_DOUBLEBUFFER, &db);
if (LOCAL_GLX_BAD_ATTRIBUTE != err) {
-#ifdef DEBUG
- if (DebugMode()) {
+ if (ShouldSpew()) {
printf("[GLX] FBConfig is %sdouble-buffered\n", db ? "" : "not ");
}
-#endif
}
GLXContext context;
RefPtr<GLContextGLX> glContext;
bool error;
ScopedXErrorHandler xErrorHandler;
--- a/gfx/gl/GLLibraryEGL.cpp
+++ b/gfx/gl/GLLibraryEGL.cpp
@@ -671,37 +671,43 @@ void
GLLibraryEGL::DumpEGLConfigs()
{
int nc = 0;
fGetConfigs(mEGLDisplay, nullptr, 0, &nc);
EGLConfig *ec = new EGLConfig[nc];
fGetConfigs(mEGLDisplay, ec, nc, &nc);
for (int i = 0; i < nc; ++i) {
- printf_stderr ("========= EGL Config %d ========\n", i);
+ printf_stderr("========= EGL Config %d ========\n", i);
DumpEGLConfig(ec[i]);
}
delete [] ec;
}
#ifdef DEBUG
+static bool
+ShouldTrace()
+{
+ static bool ret = gfxEnv::GlDebugVerbose();
+ return ret;
+}
+
/*static*/ void
GLLibraryEGL::BeforeGLCall(const char* glFunction)
{
- if (GLContext::DebugMode()) {
- if (GLContext::DebugMode() & GLContext::DebugTrace)
- printf_stderr("[egl] > %s\n", glFunction);
+ if (ShouldTrace()) {
+ printf_stderr("[egl] > %s\n", glFunction);
}
}
/*static*/ void
GLLibraryEGL::AfterGLCall(const char* glFunction)
{
- if (GLContext::DebugMode() & GLContext::DebugTrace) {
+ if (ShouldTrace()) {
printf_stderr("[egl] < %s\n", glFunction);
}
}
#endif
} /* namespace gl */
} /* namespace mozilla */
--- a/gfx/gl/GLReadTexImageHelper.cpp
+++ b/gfx/gl/GLReadTexImageHelper.cpp
@@ -327,17 +327,17 @@ ReadPixelsIntoDataSurface(GLContext* gl,
DataSourceSurface* readSurf = dest;
int readAlignment = GuessAlignment(dest->GetSize().width,
destPixelSize,
dest->Stride());
if (!readAlignment) {
needsTempSurf = true;
}
if (needsTempSurf) {
- if (gl->DebugMode()) {
+ if (GLContext::ShouldSpew()) {
NS_WARNING("Needing intermediary surface for ReadPixels. This will be slow!");
}
SurfaceFormat readFormatGFX;
switch (readFormat) {
case LOCAL_GL_RGBA: {
readFormatGFX = hasAlpha ? SurfaceFormat::R8G8B8A8
: SurfaceFormat::R8G8B8X8;