Bug 1004309 - Add func to assert shadowed state is correct. - r=kamidphish

* * *
Bug 980178 - Dither default is true. - r=kamidphish
This commit is contained in:
Jeff Gilbert 2014-05-21 19:03:09 -07:00
parent b7b4c09739
commit d0ed462277
6 changed files with 225 additions and 107 deletions

View File

@ -588,14 +588,12 @@ WebGLContext::SetDimensions(int32_t width, int32_t height)
// we'll end up displaying random memory // we'll end up displaying random memory
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0); gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
gl->fClearColor(0.0f, 0.0f, 0.0f, 0.0f); AssertCachedBindings();
gl->fClearDepth(1.0f); AssertCachedState();
gl->fClearStencil(0);
mBackbufferNeedsClear = true;
// Clear immediately, because we need to present the cleared initial // Clear immediately, because we need to present the cleared initial
// buffer. // buffer.
mBackbufferNeedsClear = true;
ClearBackbufferIfNeeded(); ClearBackbufferIfNeeded();
mShouldPresent = true; mShouldPresent = true;
@ -607,6 +605,9 @@ WebGLContext::SetDimensions(int32_t width, int32_t height)
MOZ_ASSERT(gl->Caps().antialias == caps.antialias || !gl->Caps().antialias); MOZ_ASSERT(gl->Caps().antialias == caps.antialias || !gl->Caps().antialias);
MOZ_ASSERT(gl->Caps().preserve == caps.preserve); MOZ_ASSERT(gl->Caps().preserve == caps.preserve);
AssertCachedBindings();
AssertCachedState();
reporter.SetSuccessful(); reporter.SetSuccessful();
return NS_OK; return NS_OK;
} }
@ -973,19 +974,6 @@ WebGLContext::ClearScreen()
ForceClearFramebufferWithDefaultValues(clearMask, colorAttachmentsMask); ForceClearFramebufferWithDefaultValues(clearMask, colorAttachmentsMask);
} }
#ifdef DEBUG
// For NaNs, etc.
static bool IsShadowCorrect(float shadow, float actual) {
if (IsNaN(shadow)) {
// GL is allowed to do anything it wants for NaNs, so if we're shadowing
// a NaN, then whatever `actual` is might be correct.
return true;
}
return shadow == actual;
}
#endif
void void
WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield mask, const bool colorAttachmentsMask[kMaxColorAttachments]) WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield mask, const bool colorAttachmentsMask[kMaxColorAttachments])
{ {
@ -1000,67 +988,8 @@ WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield mask, const bool
// Fun GL fact: No need to worry about the viewport here, glViewport is just // Fun GL fact: No need to worry about the viewport here, glViewport is just
// setting up a coordinates transformation, it doesn't affect glClear at all. // setting up a coordinates transformation, it doesn't affect glClear at all.
AssertCachedState(); // Can't check cached bindings, as we could
#ifdef DEBUG // have a different FB bound temporarily.
// Scope to hide our variables.
{
// Sanity-check that all our state is set properly. Otherwise, when we
// reset out state to what we *think* it is, we'll get it wrong.
// Dither shouldn't matter when we're clearing to {0,0,0,0}.
MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_SCISSOR_TEST) == mScissorTestEnabled);
if (initializeColorBuffer) {
realGLboolean colorWriteMask[4] = {2, 2, 2, 2};
GLfloat colorClearValue[4] = {-1.0f, -1.0f, -1.0f, -1.0f};
gl->fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, colorWriteMask);
gl->fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, colorClearValue);
MOZ_ASSERT(colorWriteMask[0] == mColorWriteMask[0] &&
colorWriteMask[1] == mColorWriteMask[1] &&
colorWriteMask[2] == mColorWriteMask[2] &&
colorWriteMask[3] == mColorWriteMask[3]);
MOZ_ASSERT(IsShadowCorrect(mColorClearValue[0], colorClearValue[0]) &&
IsShadowCorrect(mColorClearValue[1], colorClearValue[1]) &&
IsShadowCorrect(mColorClearValue[2], colorClearValue[2]) &&
IsShadowCorrect(mColorClearValue[3], colorClearValue[3]));
}
if (initializeDepthBuffer) {
realGLboolean depthWriteMask = 2;
GLfloat depthClearValue = -1.0f;
gl->fGetBooleanv(LOCAL_GL_DEPTH_WRITEMASK, &depthWriteMask);
gl->fGetFloatv(LOCAL_GL_DEPTH_CLEAR_VALUE, &depthClearValue);
MOZ_ASSERT(depthWriteMask == mDepthWriteMask);
MOZ_ASSERT(IsShadowCorrect(mDepthClearValue, depthClearValue));
}
if (initializeStencilBuffer) {
GLuint stencilWriteMaskFront = 0xdeadbad1;
GLuint stencilWriteMaskBack = 0xdeadbad1;
GLuint stencilClearValue = 0xdeadbad1;
gl->GetUIntegerv(LOCAL_GL_STENCIL_WRITEMASK, &stencilWriteMaskFront);
gl->GetUIntegerv(LOCAL_GL_STENCIL_BACK_WRITEMASK, &stencilWriteMaskBack);
gl->GetUIntegerv(LOCAL_GL_STENCIL_CLEAR_VALUE, &stencilClearValue);
GLuint stencilBits = 0;
gl->GetUIntegerv(LOCAL_GL_STENCIL_BITS, &stencilBits);
GLuint stencilMask = (GLuint(1) << stencilBits) - 1;
MOZ_ASSERT( ( stencilWriteMaskFront & stencilMask) ==
(mStencilWriteMaskFront & stencilMask) );
MOZ_ASSERT( ( stencilWriteMaskBack & stencilMask) ==
(mStencilWriteMaskBack & stencilMask) );
MOZ_ASSERT( ( stencilClearValue & stencilMask) ==
(mStencilClearValue & stencilMask) );
}
}
#endif
// Prepare GL state for clearing. // Prepare GL state for clearing.
gl->fDisable(LOCAL_GL_SCISSOR_TEST); gl->fDisable(LOCAL_GL_SCISSOR_TEST);

View File

@ -10,6 +10,7 @@
#include "GLDefs.h" #include "GLDefs.h"
#include "WebGLActiveInfo.h" #include "WebGLActiveInfo.h"
#include "WebGLObjectModel.h" #include "WebGLObjectModel.h"
#include "WebGLRenderbuffer.h"
#include <stdarg.h> #include <stdarg.h>
#include "nsTArray.h" #include "nsTArray.h"
@ -88,6 +89,8 @@ class SourceSurface;
WebGLTexelFormat GetWebGLTexelFormat(GLenum format, GLenum type); WebGLTexelFormat GetWebGLTexelFormat(GLenum format, GLenum type);
void AssertUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint shadow);
struct WebGLContextOptions { struct WebGLContextOptions {
// these are defaults // these are defaults
WebGLContextOptions(); WebGLContextOptions();
@ -114,6 +117,19 @@ struct WebGLContextOptions {
bool preserveDrawingBuffer; bool preserveDrawingBuffer;
}; };
#ifdef DEBUG
static bool
IsTextureBinding(GLenum binding)
{
switch (binding) {
case LOCAL_GL_TEXTURE_BINDING_2D:
case LOCAL_GL_TEXTURE_BINDING_CUBE_MAP:
return true;
}
return false;
}
#endif
class WebGLContext : class WebGLContext :
public nsIDOMWebGLRenderingContext, public nsIDOMWebGLRenderingContext,
public nsICanvasRenderingContextInternal, public nsICanvasRenderingContextInternal,
@ -204,7 +220,8 @@ public:
void DummyFramebufferOperation(const char *info); void DummyFramebufferOperation(const char *info);
WebGLTexture *activeBoundTextureForTarget(GLenum target) const { WebGLTexture* activeBoundTextureForTarget(GLenum target) const {
MOZ_ASSERT(!IsTextureBinding(target));
return target == LOCAL_GL_TEXTURE_2D ? mBound2DTextures[mActiveTexture] return target == LOCAL_GL_TEXTURE_2D ? mBound2DTextures[mActiveTexture]
: mBoundCubeMapTextures[mActiveTexture]; : mBoundCubeMapTextures[mActiveTexture];
} }
@ -249,6 +266,9 @@ public:
void SetupContextLossTimer(); void SetupContextLossTimer();
void TerminateContextLossTimer(); void TerminateContextLossTimer();
void AssertCachedBindings();
void AssertCachedState();
// WebIDL WebGLRenderingContext API // WebIDL WebGLRenderingContext API
dom::HTMLCanvasElement* GetCanvas() const { return mCanvasElement; } dom::HTMLCanvasElement* GetCanvas() const { return mCanvasElement; }
GLsizei DrawingBufferWidth() const { return IsContextLost() ? 0 : mWidth; } GLsizei DrawingBufferWidth() const { return IsContextLost() ? 0 : mWidth; }

View File

@ -3,25 +3,26 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLContext.h"
#include <stdarg.h> #include <stdarg.h>
#include "WebGLContext.h"
#include "GLContext.h" #include "GLContext.h"
#include "prprf.h"
#include "jsapi.h" #include "jsapi.h"
#include "nsIScriptSecurityManager.h"
#include "nsServiceManagerUtils.h"
#include "nsIVariant.h"
#include "nsCxPusher.h"
#include "nsIDOMEvent.h"
#include "nsIDOMDataContainerEvent.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "nsCxPusher.h"
using namespace mozilla; #include "nsIDOMDataContainerEvent.h"
#include "nsIDOMEvent.h"
#include "nsIScriptSecurityManager.h"
#include "nsIVariant.h"
#include "nsServiceManagerUtils.h"
#include "prprf.h"
#include "WebGLBuffer.h"
#include "WebGLExtensions.h"
#include "WebGLFramebuffer.h"
#include "WebGLProgram.h"
#include "WebGLTexture.h"
#include "WebGLVertexArray.h"
namespace mozilla { namespace mozilla {
@ -193,8 +194,6 @@ DriverTypeFromType(GLContext* gl, GLenum webGLType)
return webGLType; return webGLType;
} }
} // namespace mozilla
void void
WebGLContext::GenerateWarning(const char *fmt, ...) WebGLContext::GenerateWarning(const char *fmt, ...)
{ {
@ -398,3 +397,151 @@ WebGLContext::GetAndFlushUnderlyingGLErrors()
return error; return error;
} }
#ifdef DEBUG
// For NaNs, etc.
static bool
IsCacheCorrect(float cached, float actual)
{
if (IsNaN(cached)) {
// GL is allowed to do anything it wants for NaNs, so if we're shadowing
// a NaN, then whatever `actual` is might be correct.
return true;
}
return cached == actual;
}
void
AssertUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint shadow)
{
GLuint val = 0;
gl->GetUIntegerv(pname, &val);
if (val != shadow) {
printf_stderr("Failed 0x%04x shadow: Cached 0x%x/%u, should be 0x%x/%u.\n",
pname, shadow, shadow, val, val);
MOZ_ASSERT(false, "Bad cached value.");
}
}
#else
void
AssertUintParamCorrect(gl::GLContext*, GLenum, GLuint)
{
}
#endif
void
WebGLContext::AssertCachedBindings()
{
#ifdef DEBUG
MakeContextCurrent();
GetAndFlushUnderlyingGLErrors();
if (IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
GLuint bound = mBoundVertexArray ? mBoundVertexArray->GLName() : 0;
AssertUintParamCorrect(gl, LOCAL_GL_VERTEX_ARRAY_BINDING, bound);
}
// Bound object state
GLuint bound = mBoundFramebuffer ? mBoundFramebuffer->GLName() : 0;
AssertUintParamCorrect(gl, LOCAL_GL_FRAMEBUFFER_BINDING, bound);
bound = mCurrentProgram ? mCurrentProgram->GLName() : 0;
AssertUintParamCorrect(gl, LOCAL_GL_CURRENT_PROGRAM, bound);
// Textures
GLenum activeTexture = mActiveTexture + LOCAL_GL_TEXTURE0;
AssertUintParamCorrect(gl, LOCAL_GL_ACTIVE_TEXTURE, activeTexture);
WebGLTexture* curTex = activeBoundTextureForTarget(LOCAL_GL_TEXTURE_2D);
bound = curTex ? curTex->GLName() : 0;
AssertUintParamCorrect(gl, LOCAL_GL_TEXTURE_BINDING_2D, bound);
curTex = activeBoundTextureForTarget(LOCAL_GL_TEXTURE_CUBE_MAP);
bound = curTex ? curTex->GLName() : 0;
AssertUintParamCorrect(gl, LOCAL_GL_TEXTURE_BINDING_CUBE_MAP, bound);
// Buffers
bound = mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0;
AssertUintParamCorrect(gl, LOCAL_GL_ARRAY_BUFFER_BINDING, bound);
MOZ_ASSERT(mBoundVertexArray);
WebGLBuffer* curBuff = mBoundVertexArray->mBoundElementArrayBuffer;
bound = curBuff ? curBuff->GLName() : 0;
AssertUintParamCorrect(gl, LOCAL_GL_ELEMENT_ARRAY_BUFFER_BINDING, bound);
MOZ_ASSERT(!GetAndFlushUnderlyingGLErrors());
#endif
}
void
WebGLContext::AssertCachedState()
{
#ifdef DEBUG
MakeContextCurrent();
GetAndFlushUnderlyingGLErrors();
// extensions
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
AssertUintParamCorrect(gl, LOCAL_GL_MAX_COLOR_ATTACHMENTS, mGLMaxColorAttachments);
AssertUintParamCorrect(gl, LOCAL_GL_MAX_DRAW_BUFFERS, mGLMaxDrawBuffers);
}
// Draw state
MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_SCISSOR_TEST) == mScissorTestEnabled);
MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_DITHER) == mDitherEnabled);
MOZ_ASSERT_IF(IsWebGL2(),
gl->fIsEnabled(LOCAL_GL_RASTERIZER_DISCARD) == mRasterizerDiscardEnabled);
realGLboolean colorWriteMask[4] = {0, 0, 0, 0};
gl->fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, colorWriteMask);
MOZ_ASSERT(colorWriteMask[0] == mColorWriteMask[0] &&
colorWriteMask[1] == mColorWriteMask[1] &&
colorWriteMask[2] == mColorWriteMask[2] &&
colorWriteMask[3] == mColorWriteMask[3]);
GLfloat colorClearValue[4] = {0.0f, 0.0f, 0.0f, 0.0f};
gl->fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, colorClearValue);
MOZ_ASSERT(IsCacheCorrect(mColorClearValue[0], colorClearValue[0]) &&
IsCacheCorrect(mColorClearValue[1], colorClearValue[1]) &&
IsCacheCorrect(mColorClearValue[2], colorClearValue[2]) &&
IsCacheCorrect(mColorClearValue[3], colorClearValue[3]));
realGLboolean depthWriteMask = 0;
gl->fGetBooleanv(LOCAL_GL_DEPTH_WRITEMASK, &depthWriteMask);
MOZ_ASSERT(depthWriteMask == mDepthWriteMask);
GLfloat depthClearValue = 0.0f;
gl->fGetFloatv(LOCAL_GL_DEPTH_CLEAR_VALUE, &depthClearValue);
MOZ_ASSERT(IsCacheCorrect(mDepthClearValue, depthClearValue));
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_CLEAR_VALUE, mStencilClearValue);
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_REF, mStencilRefFront);
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_REF, mStencilRefBack);
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_VALUE_MASK, mStencilValueMaskFront);
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_VALUE_MASK, mStencilValueMaskBack);
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_WRITEMASK, mStencilWriteMaskFront);
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_WRITEMASK, mStencilWriteMaskBack);
// Viewport
GLint int4[4] = {0, 0, 0, 0};
gl->fGetIntegerv(LOCAL_GL_VIEWPORT, int4);
MOZ_ASSERT(int4[0] == mViewportX &&
int4[1] == mViewportY &&
int4[2] == mViewportWidth &&
int4[3] == mViewportHeight);
AssertUintParamCorrect(gl, LOCAL_GL_PACK_ALIGNMENT, mPixelStorePackAlignment);
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_ALIGNMENT, mPixelStoreUnpackAlignment);
MOZ_ASSERT(!GetAndFlushUnderlyingGLErrors());
#endif
}
} // namespace mozilla

View File

@ -1642,10 +1642,32 @@ WebGLContext::InitAndValidateGL()
mStencilClearValue = 0; mStencilClearValue = 0;
mStencilRefFront = 0; mStencilRefFront = 0;
mStencilRefBack = 0; mStencilRefBack = 0;
mStencilValueMaskFront = 0xffffffff;
mStencilValueMaskBack = 0xffffffff; /*
mStencilWriteMaskFront = 0xffffffff; // Technically, we should be setting mStencil[...] values to
mStencilWriteMaskBack = 0xffffffff; // `allOnes`, but either ANGLE breaks or the SGX540s on Try break.
GLuint stencilBits = 0;
gl->GetUIntegerv(LOCAL_GL_STENCIL_BITS, &stencilBits);
GLuint allOnes = ~(UINT32_MAX << stencilBits);
mStencilValueMaskFront = allOnes;
mStencilValueMaskBack = allOnes;
mStencilWriteMaskFront = allOnes;
mStencilWriteMaskBack = allOnes;
*/
gl->GetUIntegerv(LOCAL_GL_STENCIL_VALUE_MASK, &mStencilValueMaskFront);
gl->GetUIntegerv(LOCAL_GL_STENCIL_BACK_VALUE_MASK, &mStencilValueMaskBack);
gl->GetUIntegerv(LOCAL_GL_STENCIL_WRITEMASK, &mStencilWriteMaskFront);
gl->GetUIntegerv(LOCAL_GL_STENCIL_BACK_WRITEMASK, &mStencilWriteMaskBack);
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_VALUE_MASK, mStencilValueMaskFront);
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_VALUE_MASK, mStencilValueMaskBack);
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_WRITEMASK, mStencilWriteMaskFront);
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_WRITEMASK, mStencilWriteMaskBack);
mDitherEnabled = true;
mRasterizerDiscardEnabled = false;
mScissorTestEnabled = false;
// Bindings, etc. // Bindings, etc.
mActiveTexture = 0; mActiveTexture = 0;

View File

@ -8,12 +8,14 @@
#include "WebGLObjectModel.h" #include "WebGLObjectModel.h"
#include "nsWrapperCache.h"
#include "mozilla/LinkedList.h"
#include "mozilla/CheckedInt.h"
#include <map> #include <map>
#include "mozilla/CheckedInt.h"
#include "mozilla/LinkedList.h"
#include "nsWrapperCache.h"
#include "WebGLShader.h"
#include "WebGLUniformInfo.h"
namespace mozilla { namespace mozilla {
class WebGLShader; class WebGLShader;

View File

@ -1183,11 +1183,9 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
0, nullptr, 0, nullptr,
true); true);
} }
}
if (mInitialized)
reporter.SetSuccessful(); reporter.SetSuccessful();
else { } else {
// if initialization fails, ensure all symbols are zero, to avoid hard-to-understand bugs // if initialization fails, ensure all symbols are zero, to avoid hard-to-understand bugs
mSymbols.Zero(); mSymbols.Zero();
NS_WARNING("InitWithPrefix failed!"); NS_WARNING("InitWithPrefix failed!");