Bug 615013 - Implement section 6.8 on mutually incompatible blend factors - r=vlad
authorBenoit Jacob <bjacob@mozilla.com>
Mon, 06 Dec 2010 06:34:35 -0500
changeset 58667 ed4a6c4db3580d72c262d4ead6b7a480abdd9ae3
parent 58666 7125f195f026dd64c23caee7a5db671c9e62c9eb
child 58668 ea40cb0cd2180df55ad67f66b0053b1f98c36335
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersvlad
bugs615013
milestone2.0b8pre
Bug 615013 - Implement section 6.8 on mutually incompatible blend factors - r=vlad
content/canvas/src/WebGLContext.h
content/canvas/src/WebGLContextGL.cpp
content/canvas/src/WebGLContextValidate.cpp
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -417,19 +417,20 @@ protected:
     PRInt32 mGLMaxVaryingVectors;
     PRInt32 mGLMaxFragmentUniformVectors;
     PRInt32 mGLMaxVertexUniformVectors;
 
     PRBool SafeToCreateCanvas3DContext(nsHTMLCanvasElement *canvasElement);
     PRBool InitAndValidateGL();
     PRBool ValidateBuffers(PRUint32 count);
     PRBool ValidateCapabilityEnum(WebGLenum cap, const char *info);
-    PRBool ValidateBlendEquationEnum(WebGLuint cap, const char *info);
-    PRBool ValidateBlendFuncDstEnum(WebGLuint mode, const char *info);
-    PRBool ValidateBlendFuncSrcEnum(WebGLuint mode, const char *info);
+    PRBool ValidateBlendEquationEnum(WebGLenum cap, const char *info);
+    PRBool ValidateBlendFuncDstEnum(WebGLenum mode, const char *info);
+    PRBool ValidateBlendFuncSrcEnum(WebGLenum mode, const char *info);
+    PRBool ValidateBlendFuncEnumsCompatibility(WebGLenum sfactor, WebGLenum dfactor, const char *info);
     PRBool ValidateTextureTargetEnum(WebGLenum target, const char *info);
     PRBool ValidateComparisonEnum(WebGLenum target, const char *info);
     PRBool ValidateStencilOpEnum(WebGLenum action, const char *info);
     PRBool ValidateFaceEnum(WebGLenum face, const char *info);
     PRBool ValidateBufferUsageEnum(WebGLenum target, const char *info);
     PRBool ValidateTexFormatAndType(WebGLenum format, WebGLenum type,
                                       PRUint32 *texelSize, const char *info);
     PRBool ValidateDrawModeEnum(WebGLenum mode, const char *info);
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -319,31 +319,39 @@ NS_IMETHODIMP WebGLContext::BlendEquatio
 }
 
 NS_IMETHODIMP WebGLContext::BlendFunc(WebGLenum sfactor, WebGLenum dfactor)
 {
     if (!ValidateBlendFuncSrcEnum(sfactor, "blendFunc: sfactor") ||
         !ValidateBlendFuncDstEnum(dfactor, "blendFunc: dfactor"))
         return NS_OK;
 
+    if (!ValidateBlendFuncEnumsCompatibility(sfactor, dfactor, "blendFuncSeparate: srcRGB and dstRGB"))
+        return NS_OK;
+
     MakeContextCurrent();
     gl->fBlendFunc(sfactor, dfactor);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::BlendFuncSeparate(WebGLenum srcRGB, WebGLenum dstRGB,
                                 WebGLenum srcAlpha, WebGLenum dstAlpha)
 {
     if (!ValidateBlendFuncSrcEnum(srcRGB, "blendFuncSeparate: srcRGB") ||
         !ValidateBlendFuncSrcEnum(srcAlpha, "blendFuncSeparate: srcAlpha") ||
         !ValidateBlendFuncDstEnum(dstRGB, "blendFuncSeparate: dstRGB") ||
         !ValidateBlendFuncDstEnum(dstAlpha, "blendFuncSeparate: dstAlpha"))
         return NS_OK;
 
+    // note that we only check compatibity for the RGB enums, no need to for the Alpha enums, see
+    // "Section 6.8 forgetting to mention alpha factors?" thread on the public_webgl mailing list
+    if (!ValidateBlendFuncEnumsCompatibility(srcRGB, dstRGB, "blendFuncSeparate: srcRGB and dstRGB"))
+        return NS_OK;
+
     MakeContextCurrent();
     gl->fBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::BufferData(PRInt32 dummy)
 {
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -199,16 +199,35 @@ PRBool WebGLContext::ValidateBlendFuncDs
 PRBool WebGLContext::ValidateBlendFuncSrcEnum(WebGLenum factor, const char *info)
 {
     if (factor == LOCAL_GL_SRC_ALPHA_SATURATE)
         return PR_TRUE;
     else
         return ValidateBlendFuncDstEnum(factor, info);
 }
 
+PRBool WebGLContext::ValidateBlendFuncEnumsCompatibility(WebGLenum sfactor, WebGLenum dfactor, const char *info)
+{
+    PRBool sfactorIsConstantColor = sfactor == LOCAL_GL_CONSTANT_COLOR ||
+                                    sfactor == LOCAL_GL_ONE_MINUS_CONSTANT_COLOR;
+    PRBool sfactorIsConstantAlpha = sfactor == LOCAL_GL_CONSTANT_ALPHA ||
+                                    sfactor == LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA;
+    PRBool dfactorIsConstantColor = dfactor == LOCAL_GL_CONSTANT_COLOR ||
+                                    dfactor == LOCAL_GL_ONE_MINUS_CONSTANT_COLOR;
+    PRBool dfactorIsConstantAlpha = dfactor == LOCAL_GL_CONSTANT_ALPHA ||
+                                    dfactor == LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA;
+    if ( (sfactorIsConstantColor && dfactorIsConstantAlpha) ||
+         (dfactorIsConstantColor && sfactorIsConstantAlpha) ) {
+        ErrorInvalidOperation("%s are mutually incompatible, see section 6.8 in the WebGL 1.0 spec", info);
+        return PR_FALSE;
+    } else {
+        return PR_TRUE;
+    }
+}
+
 PRBool WebGLContext::ValidateTextureTargetEnum(WebGLenum target, const char *info)
 {
     switch (target) {
         case LOCAL_GL_TEXTURE_2D:
         case LOCAL_GL_TEXTURE_CUBE_MAP:
             return PR_TRUE;
         default:
             ErrorInvalidEnumInfo(info, target);