Bug 1325301 - Validate attribute base types match data base types. - r=daoshengmu draft
authorJeff Gilbert <jgilbert@mozilla.com>
Wed, 21 Dec 2016 20:23:28 -0800
changeset 453727 6c27f325d6ad3273fae6a8590e495bd9799cb3d0
parent 453148 2fa9d9a8690e35ec75147bf0753390860c849883
child 453728 5b5b7b072eec8ad9cd69f667e96c8eac1b0302f9
push id39737
push userbmo:jgilbert@mozilla.com
push dateSun, 25 Dec 2016 03:08:01 +0000
reviewersdaoshengmu
bugs1325301
milestone53.0a1
Bug 1325301 - Validate attribute base types match data base types. - r=daoshengmu MozReview-Commit-ID: IaJt1qIQ3LE
dom/canvas/WebGLContextDraw.cpp
dom/canvas/WebGLProgram.cpp
dom/canvas/WebGLProgram.h
dom/canvas/WebGLVertexArray.h
dom/canvas/WebGLVertexAttribData.cpp
dom/canvas/WebGLVertexAttribData.h
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -389,16 +389,40 @@ public:
                                               funcName);
                 *out_error = true;
                 return;
             }
         }
 
         ////
 
+        for (const auto& progAttrib : mWebGL->mActiveProgramLinkInfo->attribs) {
+            const auto& loc = progAttrib.mLoc;
+
+            const auto& attribData = mWebGL->mBoundVertexArray->mAttribs[loc];
+
+            GLenum attribDataBaseType;
+            if (attribData.mEnabled) {
+                attribDataBaseType = attribData.BaseType();
+            } else {
+                attribDataBaseType = mWebGL->mGenericVertexAttribTypes[loc];
+            }
+
+            if (attribDataBaseType != progAttrib.mBaseType) {
+                mWebGL->ErrorInvalidOperation("%s: Vertex attrib %u data should have type"
+                                              " 0x04x, was 0x04x.",
+                                              funcName, loc, progAttrib.mBaseType,
+                                              attribDataBaseType);
+                *out_error = true;
+                return;
+            }
+        }
+
+        ////
+
         mWebGL->RunContextLossTimer();
     }
 
     ~ScopedDrawHelper() {
         if (mDidFake) {
             mWebGL->UndoFakeVertexAttrib0();
         }
     }
--- a/dom/canvas/WebGLProgram.cpp
+++ b/dom/canvas/WebGLProgram.cpp
@@ -78,17 +78,59 @@ AssembleName(const nsCString& baseName, 
     *out_name = baseName;
     if (isArray) {
         out_name->Append('[');
         out_name->AppendInt(arrayIndex);
         out_name->Append(']');
     }
 }
 
-//////////
+////
+
+static GLenum
+AttribBaseType(GLenum attribType)
+{
+    switch (attribType) {
+    case LOCAL_GL_FLOAT:
+    case LOCAL_GL_FLOAT_VEC2:
+    case LOCAL_GL_FLOAT_VEC3:
+    case LOCAL_GL_FLOAT_VEC4:
+
+    case LOCAL_GL_FLOAT_MAT2:
+    case LOCAL_GL_FLOAT_MAT2x3:
+    case LOCAL_GL_FLOAT_MAT2x4:
+
+    case LOCAL_GL_FLOAT_MAT3x2:
+    case LOCAL_GL_FLOAT_MAT3:
+    case LOCAL_GL_FLOAT_MAT3x4:
+
+    case LOCAL_GL_FLOAT_MAT4x2:
+    case LOCAL_GL_FLOAT_MAT4x3:
+    case LOCAL_GL_FLOAT_MAT4:
+        return LOCAL_GL_FLOAT;
+
+    case LOCAL_GL_INT:
+    case LOCAL_GL_INT_VEC2:
+    case LOCAL_GL_INT_VEC3:
+    case LOCAL_GL_INT_VEC4:
+        return LOCAL_GL_INT;
+
+    case LOCAL_GL_UNSIGNED_INT:
+    case LOCAL_GL_UNSIGNED_INT_VEC2:
+    case LOCAL_GL_UNSIGNED_INT_VEC3:
+    case LOCAL_GL_UNSIGNED_INT_VEC4:
+        return LOCAL_GL_UNSIGNED_INT;
+
+    default:
+        MOZ_ASSERT(false, "unexpected attrib elemType");
+        return 0;
+    }
+}
+
+////
 
 /*static*/ const webgl::UniformInfo::TexListT*
 webgl::UniformInfo::GetTexList(WebGLActiveInfo* activeInfo)
 {
     const auto& webgl = activeInfo->mWebGL;
 
     switch (activeInfo->mElemType) {
     case LOCAL_GL_SAMPLER_2D:
@@ -220,17 +262,18 @@ QueryProgramInfo(WebGLProgram* prog, gl:
 
         ///////
 
         const bool isArray = false;
         const RefPtr<WebGLActiveInfo> activeInfo = new WebGLActiveInfo(webgl, elemCount,
                                                                        elemType, isArray,
                                                                        userName,
                                                                        mappedName);
-        const webgl::AttribInfo attrib = {activeInfo, uint32_t(loc)};
+        const GLenum baseType = AttribBaseType(elemType);
+        const webgl::AttribInfo attrib = {activeInfo, uint32_t(loc), baseType};
         info->attribs.push_back(attrib);
     }
 
     // Uniforms
 
     const bool needsCheckForArrays = gl->WorkAroundDriverBugs();
 
     GLuint numActiveUniforms = 0;
--- a/dom/canvas/WebGLProgram.h
+++ b/dom/canvas/WebGLProgram.h
@@ -33,17 +33,18 @@ class OwningUnsignedLongOrUint32ArrayOrB
 template<typename> class Sequence;
 } // namespace dom
 
 namespace webgl {
 
 struct AttribInfo final
 {
     const RefPtr<WebGLActiveInfo> mActiveInfo;
-    uint32_t mLoc;
+    const uint32_t mLoc;
+    const GLenum mBaseType;
 };
 
 struct UniformInfo final
 {
     typedef decltype(WebGLContext::mBound2DTextures) TexListT;
 
     const RefPtr<WebGLActiveInfo> mActiveInfo;
     const TexListT* const mSamplerTexList;
--- a/dom/canvas/WebGLVertexArray.h
+++ b/dom/canvas/WebGLVertexArray.h
@@ -59,16 +59,17 @@ protected:
     virtual void BindVertexArrayImpl() = 0;
     virtual void DeleteImpl() = 0;
     virtual bool IsVertexArrayImpl() const = 0;
 
     GLuint mGLName;
     nsTArray<WebGLVertexAttribData> mAttribs;
     WebGLRefPtr<WebGLBuffer> mElementArrayBuffer;
 
+    friend class ScopedDrawHelper;
     friend class WebGLContext;
     friend class WebGLVertexArrayFake;
     friend class WebGL2Context;
 };
 
 } // namespace mozilla
 
 #endif // WEBGL_VERTEX_ARRAY_H_
--- a/dom/canvas/WebGLVertexAttribData.cpp
+++ b/dom/canvas/WebGLVertexAttribData.cpp
@@ -38,24 +38,47 @@ CalcBytesPerVertex(GLenum type, uint8_t 
 
     default:
         MOZ_CRASH("Bad `type`.");
     }
 
     return bytesPerType * size;
 }
 
+static GLenum
+AttribPointerBaseType(bool integerFunc, GLenum type)
+{
+    if (!integerFunc)
+        return LOCAL_GL_FLOAT;
+
+    switch (type) {
+    case LOCAL_GL_BYTE:
+    case LOCAL_GL_SHORT:
+    case LOCAL_GL_INT:
+        return LOCAL_GL_INT;
+
+    case LOCAL_GL_UNSIGNED_BYTE:
+    case LOCAL_GL_UNSIGNED_SHORT:
+    case LOCAL_GL_UNSIGNED_INT:
+        return LOCAL_GL_UNSIGNED_INT;
+
+    default:
+        MOZ_CRASH();
+    }
+}
+
 void
 WebGLVertexAttribData::VertexAttribPointer(bool integerFunc, WebGLBuffer* buf,
                                            uint8_t size, GLenum type, bool normalized,
                                            uint32_t stride, uint64_t byteOffset)
 {
     mIntegerFunc = integerFunc;
     mBuf = buf;
     mType = type;
+    mBaseType = AttribPointerBaseType(integerFunc, type);
     mSize = size;
     mBytesPerVertex = CalcBytesPerVertex(mType, mSize);
     mNormalized = normalized;
     mStride = stride;
     mExplicitStride = (mStride ? mStride : mBytesPerVertex);
     mByteOffset = byteOffset;
 }
 
--- a/dom/canvas/WebGLVertexAttribData.h
+++ b/dom/canvas/WebGLVertexAttribData.h
@@ -20,29 +20,31 @@ public:
     bool mEnabled;
 
 private:
     bool mIntegerFunc;
 public:
     WebGLRefPtr<WebGLBuffer> mBuf;
 private:
     GLenum mType;
+    GLenum mBaseType;
     uint8_t mSize; // num of mType vals per vert
     uint8_t mBytesPerVertex;
     bool mNormalized;
     uint32_t mStride; // bytes
     uint32_t mExplicitStride;
     uint64_t mByteOffset;
 
 public:
 
 #define GETTER(X) const decltype(m##X)& X() const { return m##X; }
 
     GETTER(IntegerFunc)
     GETTER(Type)
+    GETTER(BaseType)
     GETTER(Size)
     GETTER(BytesPerVertex)
     GETTER(Normalized)
     GETTER(Stride)
     GETTER(ExplicitStride)
     GETTER(ByteOffset)
 
 #undef GETTER