Bug 1325699 - Handle -1 attrib locations. - r=daoshengmu draft
authorJeff Gilbert <jgilbert@mozilla.com>
Sat, 24 Dec 2016 22:06:56 -0800
changeset 453825 7a245c9b2260bd93515140c96f98b03596655691
parent 453824 a8a07602d470c80dc8aaa1b120131477ece9623c
child 540529 1ac634f07e710930bd40b8e86610257e33fb9afc
push id39739
push userbmo:jgilbert@mozilla.com
push dateSun, 25 Dec 2016 06:53:30 +0000
reviewersdaoshengmu
bugs1325699
milestone53.0a1
Bug 1325699 - Handle -1 attrib locations. - r=daoshengmu MozReview-Commit-ID: E0kov9LsB6W
dom/canvas/WebGLContextDraw.cpp
dom/canvas/WebGLProgram.cpp
dom/canvas/WebGLProgram.h
dom/canvas/WebGLShader.cpp
dom/canvas/WebGLShader.h
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -391,16 +391,18 @@ public:
                 return;
             }
         }
 
         ////
 
         for (const auto& progAttrib : mWebGL->mActiveProgramLinkInfo->attribs) {
             const auto& loc = progAttrib.mLoc;
+            if (loc == -1)
+                continue;
 
             const auto& attribData = mWebGL->mBoundVertexArray->mAttribs[loc];
 
             GLenum attribDataBaseType;
             if (attribData.mEnabled) {
                 attribDataBaseType = attribData.BaseType();
             } else {
                 attribDataBaseType = mWebGL->mGenericVertexAttribTypes[loc];
@@ -926,18 +928,20 @@ WebGLContext::ValidateBufferFetching(con
         }
 
         ++i;
     }
 
     mBufferFetch_IsAttrib0Active = false;
 
     for (const auto& attrib : mActiveProgramLinkInfo->attribs) {
-        const auto& attribLoc = attrib.mLoc;
+        if (attrib.mLoc == -1)
+            continue;
 
+        const uint32_t attribLoc(attrib.mLoc);
         if (attribLoc >= attribCount)
             continue;
 
         if (attribLoc == 0) {
             mBufferFetch_IsAttrib0Active = true;
         }
 
         const auto& vd = mBoundVertexArray->mAttribs[attribLoc];
--- a/dom/canvas/WebGLProgram.cpp
+++ b/dom/canvas/WebGLProgram.cpp
@@ -204,24 +204,17 @@ QueryProgramInfo(WebGLProgram* prog, gl:
     GLuint maxTransformFeedbackVaryingLenWithNull = 0;
     if (gl->IsSupported(gl::GLFeature::transform_feedback2)) {
         gl->fGetProgramiv(prog->mGLName, LOCAL_GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH,
                           (GLint*)&maxTransformFeedbackVaryingLenWithNull);
         if (maxTransformFeedbackVaryingLenWithNull < 1)
             maxTransformFeedbackVaryingLenWithNull = 1;
     }
 
-
-#ifdef DUMP_SHADERVAR_MAPPINGS
-    printf_stderr("maxAttribLenWithNull: %d\n", maxAttribLenWithNull);
-    printf_stderr("maxUniformLenWithNull: %d\n", maxUniformLenWithNull);
-    printf_stderr("maxUniformBlockLenWithNull: %d\n", maxUniformBlockLenWithNull);
-#endif
-
-    // Attribs
+    // Attribs (can't be arrays)
 
     GLuint numActiveAttribs = 0;
     gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_ATTRIBUTES,
                       (GLint*)&numActiveAttribs);
 
     for (GLuint i = 0; i < numActiveAttribs; i++) {
         nsAutoCString mappedName;
         mappedName.SetLength(maxAttribLenWithNull - 1);
@@ -233,53 +226,45 @@ QueryProgramInfo(WebGLProgram* prog, gl:
                              &elemCount, &elemType, mappedName.BeginWriting());
         GLenum error = gl->fGetError();
         if (error != LOCAL_GL_NO_ERROR) {
             gfxCriticalNote << "Failed to do glGetActiveAttrib: " << error;
         }
 
         mappedName.SetLength(lengthWithoutNull);
 
-        if (mappedName.Find("gl_") == 0) {
-#ifdef DUMP_SHADERVAR_MAPPINGS
-          printf_stderr("[attrib %u/%u] <skipping %s>\n", i, numActiveAttribs,
-                        mappedName.BeginReading());
-#endif
-            continue;
+        ////
+
+        nsCString userName;
+        if (!prog->FindAttribUserNameByMappedName(mappedName, &userName)) {
+            userName = mappedName;
         }
 
-        // Attribs can't be arrays, so we can skip some of the mess we have in the Uniform
-        // path.
-        nsDependentCString userName;
-        if (!prog->FindAttribUserNameByMappedName(mappedName, &userName))
-            userName.Rebind(mappedName, 0);
-
         ///////
 
         const GLint loc = gl->fGetAttribLocation(prog->mGLName,
                                                  mappedName.BeginReading());
-
 #ifdef DUMP_SHADERVAR_MAPPINGS
-        printf_stderr("[attrib %u/%u] @%u %s->%s\n", i, numActiveAttribs, loc,
+        printf_stderr("[attrib %u/%u] @%i %s->%s\n", i, numActiveAttribs, loc,
                       userName.BeginReading(), mappedName.BeginReading());
 #endif
 
         ///////
 
         const bool isArray = false;
         const RefPtr<WebGLActiveInfo> activeInfo = new WebGLActiveInfo(webgl, elemCount,
                                                                        elemType, isArray,
                                                                        userName,
                                                                        mappedName);
         const GLenum baseType = AttribBaseType(elemType);
-        const webgl::AttribInfo attrib = {activeInfo, uint32_t(loc), baseType};
+        const webgl::AttribInfo attrib = {activeInfo, loc, baseType};
         info->attribs.push_back(attrib);
     }
 
-    // Uniforms
+    // Uniforms (can be basically anything)
 
     const bool needsCheckForArrays = gl->WorkAroundDriverBugs();
 
     GLuint numActiveUniforms = 0;
     gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_UNIFORMS,
                       (GLint*)&numActiveUniforms);
 
     for (GLuint i = 0; i < numActiveUniforms; i++) {
@@ -288,17 +273,16 @@ QueryProgramInfo(WebGLProgram* prog, gl:
 
         GLsizei lengthWithoutNull = 0;
         GLint elemCount = 0; // `size`
         GLenum elemType = 0; // `type`
         gl->fGetActiveUniform(prog->mGLName, i, mappedName.Length()+1, &lengthWithoutNull,
                               &elemCount, &elemType, mappedName.BeginWriting());
 
         mappedName.SetLength(lengthWithoutNull);
-        MOZ_ASSERT(mappedName.Find("gl_") != 0);
 
         ///////
 
         nsAutoCString baseMappedName;
         bool isArray;
         size_t arrayIndex;
         if (!ParseName(mappedName, &baseMappedName, &isArray, &arrayIndex))
             MOZ_CRASH("GFX: Failed to parse `mappedName` received from driver.");
@@ -343,35 +327,32 @@ QueryProgramInfo(WebGLProgram* prog, gl:
         auto* uniform = new webgl::UniformInfo(activeInfo);
         info->uniforms.push_back(uniform);
 
         if (uniform->mSamplerTexList) {
             info->uniformSamplers.push_back(uniform);
         }
     }
 
-    // Uniform Blocks
-    // (no sampler types allowed!)
+    // Uniform Blocks (can be arrays, but can't contain sampler types)
 
     if (gl->IsSupported(gl::GLFeature::uniform_buffer_object)) {
         GLuint numActiveUniformBlocks = 0;
         gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_UNIFORM_BLOCKS,
                           (GLint*)&numActiveUniformBlocks);
 
         for (GLuint i = 0; i < numActiveUniformBlocks; i++) {
             nsAutoCString mappedName;
             mappedName.SetLength(maxUniformBlockLenWithNull - 1);
 
             GLint lengthWithoutNull;
             gl->fGetActiveUniformBlockiv(prog->mGLName, i, LOCAL_GL_UNIFORM_BLOCK_NAME_LENGTH, &lengthWithoutNull);
             gl->fGetActiveUniformBlockName(prog->mGLName, i, maxUniformBlockLenWithNull, &lengthWithoutNull, mappedName.BeginWriting());
             mappedName.SetLength(lengthWithoutNull);
 
-            MOZ_ASSERT(mappedName.Find("gl_") != 0);
-
             ////
 
             nsCString userName;
             if (!prog->UnmapUniformBlockName(mappedName, &userName))
                 continue;
 
 #ifdef DUMP_SHADERVAR_MAPPINGS
             printf_stderr("[uniform block %u/%u] %s->%s\n", i, numActiveUniformBlocks,
@@ -387,17 +368,17 @@ QueryProgramInfo(WebGLProgram* prog, gl:
 
 
             auto* block = new webgl::UniformBlockInfo(webgl, userName, mappedName,
                                                       dataSize);
             info->uniformBlocks.push_back(block);
         }
     }
 
-    // Transform feedback varyings
+    // Transform feedback varyings (can be arrays)
 
     if (gl->IsSupported(gl::GLFeature::transform_feedback2)) {
         GLuint numTransformFeedbackVaryings = 0;
         gl->fGetProgramiv(prog->mGLName, LOCAL_GL_TRANSFORM_FEEDBACK_VARYINGS,
                           (GLint*)&numTransformFeedbackVaryings);
 
         for (GLuint i = 0; i < numTransformFeedbackVaryings; i++) {
             nsAutoCString mappedName;
@@ -407,18 +388,16 @@ QueryProgramInfo(WebGLProgram* prog, gl:
             GLsizei elemCount;
             GLenum elemType;
             gl->fGetTransformFeedbackVarying(prog->mGLName, i,
                                              maxTransformFeedbackVaryingLenWithNull,
                                              &lengthWithoutNull, &elemCount, &elemType,
                                              mappedName.BeginWriting());
             mappedName.SetLength(lengthWithoutNull);
 
-            // Allowed to start with "gl_".
-
             ////
 
             nsAutoCString baseMappedName;
             bool isArray;
             size_t arrayIndex;
             if (!ParseName(mappedName, &baseMappedName, &isArray, &arrayIndex))
                 MOZ_CRASH("GFX: Failed to parse `mappedName` received from driver.");
 
@@ -1201,16 +1180,19 @@ WebGLProgram::ValidateAfterTentativeLink
                                                attribName.BeginReading());
                 return false;
             }
         }
     }
 
     std::map<uint32_t, const webgl::AttribInfo*> attribsByLoc;
     for (const auto& attrib : linkInfo->attribs) {
+        if (attrib.mLoc == -1)
+            continue;
+
         const auto& elemType = attrib.mActiveInfo->mElemType;
         const auto numUsedLocs = NumUsedLocationsByElemType(elemType);
         for (uint32_t i = 0; i < numUsedLocs; i++) {
             const uint32_t usedLoc = attrib.mLoc + i;
 
             const auto res = attribsByLoc.insert({usedLoc, &attrib});
             const bool& didInsert = res.second;
             if (!didInsert) {
@@ -1385,17 +1367,17 @@ WebGLProgram::LinkAndUpdate()
         return;
 
     mMostRecentLinkInfo = QueryProgramInfo(this, gl);
     MOZ_RELEASE_ASSERT(mMostRecentLinkInfo, "GFX: most recent link info not set.");
 }
 
 bool
 WebGLProgram::FindAttribUserNameByMappedName(const nsACString& mappedName,
-                                             nsDependentCString* const out_userName) const
+                                             nsCString* const out_userName) const
 {
     if (mVertShader->FindAttribUserNameByMappedName(mappedName, out_userName))
         return true;
 
     return false;
 }
 
 bool
--- a/dom/canvas/WebGLProgram.h
+++ b/dom/canvas/WebGLProgram.h
@@ -33,17 +33,17 @@ class OwningUnsignedLongOrUint32ArrayOrB
 template<typename> class Sequence;
 } // namespace dom
 
 namespace webgl {
 
 struct AttribInfo final
 {
     const RefPtr<WebGLActiveInfo> mActiveInfo;
-    const uint32_t mLoc;
+    const GLint mLoc; // -1 for active built-ins
     const GLenum mBaseType;
 };
 
 struct UniformInfo final
 {
     typedef decltype(WebGLContext::mBound2DTextures) TexListT;
 
     const RefPtr<WebGLActiveInfo> mActiveInfo;
@@ -154,17 +154,17 @@ public:
 
     void LinkProgram();
     bool UseProgram() const;
     void ValidateProgram() const;
 
     ////////////////
 
     bool FindAttribUserNameByMappedName(const nsACString& mappedName,
-                                        nsDependentCString* const out_userName) const;
+                                        nsCString* const out_userName) const;
     bool FindVaryingByMappedName(const nsACString& mappedName,
                                  nsCString* const out_userName,
                                  bool* const out_isArray) const;
     bool FindUniformByMappedName(const nsACString& mappedName,
                                  nsCString* const out_userName,
                                  bool* const out_isArray) const;
     bool UnmapUniformBlockName(const nsCString& mappedName,
                                nsCString* const out_userName) const;
--- a/dom/canvas/WebGLShader.cpp
+++ b/dom/canvas/WebGLShader.cpp
@@ -326,27 +326,27 @@ WebGLShader::BindAttribLocation(GLuint p
     if (mValidator)
         mValidator->FindAttribMappedNameByUserName(userNameStr, &mappedNameStr);
 
     mContext->gl->fBindAttribLocation(prog, index, mappedNameStr->c_str());
 }
 
 bool
 WebGLShader::FindAttribUserNameByMappedName(const nsACString& mappedName,
-                                            nsDependentCString* const out_userName) const
+                                            nsCString* const out_userName) const
 {
     if (!mValidator)
         return false;
 
     const std::string mappedNameStr(mappedName.BeginReading());
     const std::string* userNameStr;
     if (!mValidator->FindAttribUserNameByMappedName(mappedNameStr, &userNameStr))
         return false;
 
-    out_userName->Rebind(userNameStr->c_str());
+    *out_userName = userNameStr->c_str();
     return true;
 }
 
 bool
 WebGLShader::FindVaryingByMappedName(const nsACString& mappedName,
                                      nsCString* const out_userName,
                                      bool* const out_isArray) const
 {
--- a/dom/canvas/WebGLShader.h
+++ b/dom/canvas/WebGLShader.h
@@ -47,17 +47,17 @@ public:
     void GetShaderTranslatedSource(nsAString* out) const;
     void ShaderSource(const nsAString& source);
 
     // Util funcs
     bool CanLinkTo(const WebGLShader* prev, nsCString* const out_log) const;
     size_t CalcNumSamplerUniforms() const;
     size_t NumAttributes() const;
     bool FindAttribUserNameByMappedName(const nsACString& mappedName,
-                                        nsDependentCString* const out_userName) const;
+                                        nsCString* const out_userName) const;
     bool FindVaryingByMappedName(const nsACString& mappedName,
                                  nsCString* const out_userName,
                                  bool* const out_isArray) const;
     bool FindUniformByMappedName(const nsACString& mappedName,
                                  nsCString* const out_userName,
                                  bool* const out_isArray) const;
     bool UnmapUniformBlockName(const nsACString& baseMappedName,
                                nsCString* const out_baseUserName) const;