diff --git a/content/canvas/src/WebGLContext.h b/content/canvas/src/WebGLContext.h index e45bc680dfd..f8fec1a3147 100644 --- a/content/canvas/src/WebGLContext.h +++ b/content/canvas/src/WebGLContext.h @@ -872,6 +872,7 @@ private: void VertexAttrib4fv_base(WebGLuint idx, uint32_t arrayLength, const WebGLfloat* ptr); bool ValidateBufferFetching(const char *info); + bool BindArrayAttribToLocation0(WebGLProgram *program); // ----------------------------------------------------------------------------- // PROTECTED diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index ad285a2c239..85093176f8c 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -1966,6 +1966,36 @@ WebGLContext::IsTexture(WebGLTexture *tex) tex->HasEverBeenBound(); } +// Try to bind an attribute that is an array to location 0: +bool WebGLContext::BindArrayAttribToLocation0(WebGLProgram *program) +{ + if (mBoundVertexArray->mAttribBuffers[0].enabled) { + return false; + } + + GLint leastArrayLocation = -1; + + std::map::iterator itr; + for (itr = program->mActiveAttribMap.begin(); + itr != program->mActiveAttribMap.end(); + itr++) { + int32_t index = itr->first; + if (mBoundVertexArray->mAttribBuffers[index].enabled && + index < leastArrayLocation) + { + leastArrayLocation = index; + } + } + + if (leastArrayLocation > 0) { + nsCString& attrName = program->mActiveAttribMap.find(leastArrayLocation)->second; + const char* attrNameCStr = attrName.get(); + gl->fBindAttribLocation(program->GLName(), 0, attrNameCStr); + return true; + } + return false; +} + void WebGLContext::LinkProgram(WebGLProgram *program) { @@ -2003,7 +2033,8 @@ WebGLContext::LinkProgram(WebGLProgram *program) return; } - GLint ok; + bool updateInfoSucceeded = false; + GLint ok = 0; if (gl->WorkAroundDriverBugs() && program->HasBadShaderAttached()) { @@ -2015,12 +2046,25 @@ WebGLContext::LinkProgram(WebGLProgram *program) MakeContextCurrent(); gl->fLinkProgram(progname); gl->fGetProgramiv(progname, LOCAL_GL_LINK_STATUS, &ok); + + if (ok) { + updateInfoSucceeded = program->UpdateInfo(); + program->SetLinkStatus(updateInfoSucceeded); + + if (BindArrayAttribToLocation0(program)) { + GenerateWarning("linkProgram: relinking program to make attrib0 an " + "array."); + gl->fLinkProgram(progname); + gl->fGetProgramiv(progname, LOCAL_GL_LINK_STATUS, &ok); + if (ok) { + updateInfoSucceeded = program->UpdateInfo(); + program->SetLinkStatus(updateInfoSucceeded); + } + } + } } if (ok) { - bool updateInfoSucceeded = program->UpdateInfo(); - program->SetLinkStatus(updateInfoSucceeded); - // Bug 750527 if (gl->WorkAroundDriverBugs() && updateInfoSucceeded && diff --git a/content/canvas/src/WebGLContextValidate.cpp b/content/canvas/src/WebGLContextValidate.cpp index 19ecc012681..127bd22f8a0 100644 --- a/content/canvas/src/WebGLContextValidate.cpp +++ b/content/canvas/src/WebGLContextValidate.cpp @@ -86,6 +86,25 @@ WebGLProgram::UpdateInfo() } } + mActiveAttribMap.clear(); + + GLint numActiveAttrs = 0; + mContext->gl->fGetProgramiv(mGLName, LOCAL_GL_ACTIVE_ATTRIBUTES, &numActiveAttrs); + + // Spec says the maximum attrib name length is 256 chars, so this is + // sufficient to hold any attrib name. + char attrName[257]; + + GLint dummySize; + GLenum dummyType; + for (GLint i = 0; i < numActiveAttrs; i++) { + mContext->gl->fGetActiveAttrib(mGLName, i, 257, nullptr, &dummySize, + &dummyType, attrName); + GLint attrLoc = mContext->gl->fGetAttribLocation(mGLName, attrName); + MOZ_ASSERT(attrLoc >= 0); + mActiveAttribMap.insert(std::make_pair(attrLoc, nsCString(attrName))); + } + return true; } diff --git a/content/canvas/src/WebGLProgram.h b/content/canvas/src/WebGLProgram.h index a5ce6bee1f4..0d6a5c8901f 100644 --- a/content/canvas/src/WebGLProgram.h +++ b/content/canvas/src/WebGLProgram.h @@ -110,6 +110,9 @@ public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WebGLProgram) + // public post-link data + std::map mActiveAttribMap; + protected: WebGLuint mGLName;