Bug 1015561 - WebGL change getParameter(STENCIL_[BACK]_REF) to return correct masked values and update debug cached value test. r=jgilbert
authorWalter Litwinczyk <wlitwinczyk@mozilla.com>
Fri, 26 Sep 2014 15:06:38 -0700
changeset 226478 e4d22e719c37f783a4c7b0a33440131a6852e8c6
parent 226477 551b01d447d19fcfaef8fa0edf74b565c4194905
child 226479 250146966b12a553836fa37968d109fe34186a06
push id7326
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:58:42 +0000
treeherdermozilla-aurora@d3a3b2a0f2f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs1015561
milestone35.0a1
Bug 1015561 - WebGL change getParameter(STENCIL_[BACK]_REF) to return correct masked values and update debug cached value test. r=jgilbert
dom/canvas/WebGLContext.h
dom/canvas/WebGLContextState.cpp
dom/canvas/WebGLContextUtils.cpp
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -831,16 +831,17 @@ private:
     WebGLRefPtr<WebGLBuffer>* GetBufferSlotByTargetIndexed(GLenum target, GLuint index, const char* infos);
     bool ValidateBufferUsageEnum(GLenum target, const char* infos);
 
 // -----------------------------------------------------------------------------
 // State and State Requests (WebGLContextState.cpp)
 public:
     void Disable(GLenum cap);
     void Enable(GLenum cap);
+    bool GetStencilBits(GLint* out_stencilBits);
     JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv);
     void GetParameter(JSContext* cx, GLenum pname,
                       JS::MutableHandle<JS::Value> retval, ErrorResult& rv) {
         retval.set(GetParameter(cx, pname, rv));
     }
     void GetParameterIndexed(JSContext* cx, GLenum pname, GLuint index,
                              JS::MutableHandle<JS::Value> retval);
     bool IsEnabled(GLenum cap);
--- a/dom/canvas/WebGLContextState.cpp
+++ b/dom/canvas/WebGLContextState.cpp
@@ -65,16 +65,39 @@ StringValue(JSContext* cx, const char* c
     if (!str) {
         rv.Throw(NS_ERROR_OUT_OF_MEMORY);
         return JS::NullValue();
     }
 
     return JS::StringValue(str);
 }
 
+bool
+WebGLContext::GetStencilBits(GLint* out_stencilBits)
+{
+    *out_stencilBits = 0;
+    if (mBoundFramebuffer) {
+        if (mBoundFramebuffer->HasDepthStencilConflict()) {
+            // Error, we don't know which stencil buffer's bits to use
+            ErrorInvalidFramebufferOperation("getParameter: framebuffer has two stencil buffers bound");
+            return false;
+        }
+
+        if (mBoundFramebuffer->StencilAttachment().IsDefined() ||
+            mBoundFramebuffer->DepthStencilAttachment().IsDefined())
+        {
+            *out_stencilBits = 8;
+        }
+    } else if (mOptions.stencil) {
+        *out_stencilBits = 8;
+    }
+
+    return true;
+}
+
 JS::Value
 WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
 {
     if (IsContextLost())
         return JS::NullValue();
 
     MakeContextCurrent();
 
@@ -236,34 +259,50 @@ WebGLContext::GetParameter(JSContext* cx
             if (gl->IsSupported(gl::GLFeature::ES2_compatibility)) {
                 gl->fGetIntegerv(pname, &i);
             } else {
                 i = LOCAL_GL_RGBA;
             }
             return JS::NumberValue(uint32_t(i));
         }
         // int
+        case LOCAL_GL_STENCIL_REF:
+        case LOCAL_GL_STENCIL_BACK_REF: {
+            GLint stencilBits = 0;
+            if (!GetStencilBits(&stencilBits))
+                return JS::NullValue();
+
+            // Assuming stencils have 8 bits
+            const GLint stencilMask = (1 << stencilBits) - 1;
+
+            GLint refValue = 0;
+            gl->fGetIntegerv(pname, &refValue);
+
+            return JS::Int32Value(refValue & stencilMask);
+        }
+        case LOCAL_GL_STENCIL_BITS: {
+            GLint stencilBits = 0;
+            GetStencilBits(&stencilBits);
+            return JS::Int32Value(stencilBits);
+        }
         case LOCAL_GL_STENCIL_CLEAR_VALUE:
-        case LOCAL_GL_STENCIL_REF:
-        case LOCAL_GL_STENCIL_BACK_REF:
         case LOCAL_GL_UNPACK_ALIGNMENT:
         case LOCAL_GL_PACK_ALIGNMENT:
         case LOCAL_GL_SUBPIXEL_BITS:
         case LOCAL_GL_SAMPLE_BUFFERS:
         case LOCAL_GL_SAMPLES:
         case LOCAL_GL_MAX_VERTEX_ATTRIBS:
         case LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
         case LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
         case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS:
         case LOCAL_GL_RED_BITS:
         case LOCAL_GL_GREEN_BITS:
         case LOCAL_GL_BLUE_BITS:
         case LOCAL_GL_ALPHA_BITS:
-        case LOCAL_GL_DEPTH_BITS:
-        case LOCAL_GL_STENCIL_BITS: {
+        case LOCAL_GL_DEPTH_BITS: {
             GLint i = 0;
             gl->fGetIntegerv(pname, &i);
             return JS::Int32Value(i);
         }
         case LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT: {
             if (IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives)) {
                 GLint i = 0;
                 gl->fGetIntegerv(pname, &i);
--- a/dom/canvas/WebGLContextUtils.cpp
+++ b/dom/canvas/WebGLContextUtils.cpp
@@ -700,16 +700,32 @@ AssertUintParamCorrect(gl::GLContext* gl
     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.");
     }
 }
+
+void
+AssertMaskedUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint mask, GLuint shadow)
+{
+    GLuint val = 0;
+    gl->GetUIntegerv(pname, &val);
+
+    const GLuint valMasked = val & mask;
+    const GLuint shadowMasked = shadow & mask;
+
+    if (valMasked != shadowMasked) {
+      printf_stderr("Failed 0x%04x shadow: Cached 0x%x/%u, should be 0x%x/%u.\n",
+                    pname, shadowMasked, shadowMasked, valMasked, valMasked);
+      MOZ_ASSERT(false, "Bad cached value.");
+    }
+}
 #else
 void
 AssertUintParamCorrect(gl::GLContext*, GLenum, GLuint)
 {
 }
 #endif
 
 void
@@ -797,18 +813,22 @@ WebGLContext::AssertCachedState()
     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);
+    GLint stencilBits = 0;
+    gl->fGetIntegerv(LOCAL_GL_STENCIL_BITS, &stencilBits);
+    const GLuint stencilRefMask = (1 << stencilBits) - 1;
+
+    AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_REF,      stencilRefMask, mStencilRefFront);
+    AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_REF, stencilRefMask, 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