--- a/dom/canvas/WebGLProgram.cpp
+++ b/dom/canvas/WebGLProgram.cpp
@@ -25,28 +25,29 @@ namespace mozilla {
* `out_baseName`: "foo"
* `out_isArray`: true
* `out_index`: 3
*
* If `name`: "foo"
* Then returns true, with
* `out_baseName`: "foo"
* `out_isArray`: false
- * `out_index`: <not written>
+ * `out_index`: 0
*/
static bool
ParseName(const nsCString& name, nsCString* const out_baseName,
bool* const out_isArray, size_t* const out_arrayIndex)
{
int32_t indexEnd = name.RFind("]");
if (indexEnd == -1 ||
(uint32_t)indexEnd != name.Length() - 1)
{
*out_baseName = name;
*out_isArray = false;
+ *out_arrayIndex = 0;
return true;
}
int32_t indexOpenBracket = name.RFind("[");
if (indexOpenBracket == -1)
return false;
uint32_t indexStart = indexOpenBracket + 1;
@@ -65,16 +66,28 @@ ParseName(const nsCString& name, nsCStri
return false;
*out_baseName = StringHead(name, indexOpenBracket);
*out_isArray = true;
*out_arrayIndex = indexNum;
return true;
}
+static void
+AssembleName(const nsCString& baseName, bool isArray, size_t arrayIndex,
+ nsCString* const out_name)
+{
+ *out_name = baseName;
+ if (isArray) {
+ out_name->Append('[');
+ out_name->AppendInt(arrayIndex);
+ out_name->Append(']');
+ }
+}
+
//////////
/*static*/ const webgl::UniformInfo::TexListT*
webgl::UniformInfo::GetTexList(WebGLActiveInfo* activeInfo)
{
const auto& webgl = activeInfo->mWebGL;
switch (activeInfo->mElemType) {
@@ -646,24 +659,21 @@ WebGLProgram::GetFragDataLocation(const
if (!IsLinked()) {
mContext->ErrorInvalidOperation("getFragDataLocation: `program` must be linked.");
return -1;
}
const NS_LossyConvertUTF16toASCII userName(userName_wide);
nsCString mappedName;
-
- if (!LinkInfo()->FindFragData(userName, &mappedName)) {
- mappedName = userName;
- }
+ if (!LinkInfo()->MapFragDataName(userName, &mappedName))
+ return -1;
gl::GLContext* gl = mContext->GL();
gl->MakeCurrent();
-
return gl->fGetFragDataLocation(mGLName, mappedName.BeginReading());
}
void
WebGLProgram::GetProgramInfoLog(nsAString* const out) const
{
CopyASCIItoUTF16(mLinkLog, *out);
}
@@ -730,33 +740,19 @@ WebGLProgram::GetUniformBlockIndex(const
if (!IsLinked()) {
mContext->ErrorInvalidOperation("getUniformBlockIndex: `program` must be linked.");
return LOCAL_GL_INVALID_INDEX;
}
const NS_LossyConvertUTF16toASCII userName(userName_wide);
- nsDependentCString baseUserName;
- bool isArray;
- size_t arrayIndex;
- if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex))
- return LOCAL_GL_INVALID_INDEX;
-
- const webgl::UniformBlockInfo* info;
- if (!LinkInfo()->FindUniformBlock(baseUserName, &info)) {
+ nsCString mappedName;
+ if (!LinkInfo()->MapUniformBlockName(userName, &mappedName))
return LOCAL_GL_INVALID_INDEX;
- }
-
- nsAutoCString mappedName(info->mBaseMappedName);
- if (isArray) {
- mappedName.AppendLiteral("[");
- mappedName.AppendInt(uint32_t(arrayIndex));
- mappedName.AppendLiteral("]");
- }
gl::GLContext* gl = mContext->GL();
gl->MakeCurrent();
return gl->fGetUniformBlockIndex(mGLName, mappedName.BeginReading());
}
void
@@ -862,39 +858,26 @@ WebGLProgram::GetUniformLocation(const n
if (!IsLinked()) {
mContext->ErrorInvalidOperation("getUniformLocation: `program` must be linked.");
return nullptr;
}
const NS_LossyConvertUTF16toASCII userName(userName_wide);
- nsDependentCString baseUserName;
- bool isArray = false;
// GLES 2.0.25, Section 2.10, p35
// If the the uniform location is an array, then the location of the first
// element of that array can be retrieved by either using the name of the
// uniform array, or the name of the uniform array appended with "[0]".
- // The ParseName() can't recognize this rule. So always initialize
- // arrayIndex with 0.
- size_t arrayIndex = 0;
- if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex))
- return nullptr;
-
+ nsCString mappedName;
+ size_t arrayIndex;
webgl::UniformInfo* info;
- if (!LinkInfo()->FindUniform(baseUserName, &info))
+ if (!LinkInfo()->FindUniform(userName, &mappedName, &arrayIndex, &info))
return nullptr;
- nsAutoCString mappedName(info->mActiveInfo->mBaseMappedName);
- if (isArray) {
- mappedName.AppendLiteral("[");
- mappedName.AppendInt(uint32_t(arrayIndex));
- mappedName.AppendLiteral("]");
- }
-
gl::GLContext* gl = mContext->GL();
gl->MakeCurrent();
GLint loc = gl->fGetUniformLocation(mGLName, mappedName.BeginReading());
if (loc == -1)
return nullptr;
RefPtr<WebGLUniformLocation> locObj = new WebGLUniformLocation(mContext, LinkInfo(),
@@ -916,46 +899,32 @@ WebGLProgram::GetUniformIndices(const do
nsTArray<GLuint>& arr = retval.SetValue();
gl::GLContext* gl = mContext->GL();
gl->MakeCurrent();
for (size_t i = 0; i < count; i++) {
const NS_LossyConvertUTF16toASCII userName(uniformNames[i]);
- nsDependentCString baseUserName;
- bool isArray;
+ nsCString mappedName;
size_t arrayIndex;
- if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex)) {
- arr.AppendElement(LOCAL_GL_INVALID_INDEX);
- continue;
- }
-
webgl::UniformInfo* info;
- if (!LinkInfo()->FindUniform(baseUserName, &info)) {
+ if (!LinkInfo()->FindUniform(userName, &mappedName, &arrayIndex, &info)) {
arr.AppendElement(LOCAL_GL_INVALID_INDEX);
continue;
}
- nsAutoCString mappedName(info->mActiveInfo->mBaseMappedName);
- if (isArray) {
- mappedName.AppendLiteral("[");
- mappedName.AppendInt(uint32_t(arrayIndex));
- mappedName.AppendLiteral("]");
- }
+ const GLchar* const mappedNameBegin = mappedName.get();
- const GLchar* mappedNameBytes = mappedName.BeginReading();
-
- GLuint index = 0;
- gl->fGetUniformIndices(mGLName, 1, &mappedNameBytes, &index);
+ GLuint index = LOCAL_GL_INVALID_INDEX;
+ gl->fGetUniformIndices(mGLName, 1, &mappedNameBegin, &index);
arr.AppendElement(index);
}
}
-
void
WebGLProgram::UniformBlockBinding(GLuint uniformBlockIndex,
GLuint uniformBlockBinding) const
{
const char funcName[] = "getActiveUniformBlockName";
if (!IsLinked()) {
mContext->ErrorInvalidOperation("%s: `program` must be linked.", funcName);
return;
@@ -1506,55 +1475,120 @@ WebGLProgram::EnumerateFragOutputs(std::
MOZ_ASSERT(mFragShader);
mFragShader->EnumerateFragOutputs(out_FragOutputs);
}
////////////////////////////////////////////////////////////////////////////////
bool
-webgl::LinkedProgramInfo::FindAttrib(const nsCString& baseUserName,
+IsBaseName(const nsCString& name)
+{
+ if (!name.Length())
+ return true;
+
+ return name[name.Length() - 1] != ']'; // Doesn't end in ']'.
+}
+
+bool
+webgl::LinkedProgramInfo::FindAttrib(const nsCString& userName,
const webgl::AttribInfo** const out) const
{
+ // VS inputs cannot be arrays or structures.
+ // `userName` is thus always `baseUserName`.
for (const auto& attrib : attribs) {
- if (attrib.mActiveInfo->mBaseUserName == baseUserName) {
+ if (attrib.mActiveInfo->mBaseUserName == userName) {
*out = &attrib;
return true;
}
}
return false;
}
bool
-webgl::LinkedProgramInfo::FindUniform(const nsCString& baseUserName,
- webgl::UniformInfo** const out) const
+webgl::LinkedProgramInfo::FindUniform(const nsCString& userName,
+ nsCString* const out_mappedName,
+ size_t* const out_arrayIndex,
+ webgl::UniformInfo** const out_info) const
{
+ nsCString baseUserName;
+ bool isArray;
+ size_t arrayIndex;
+ if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex))
+ return false;
+
+ webgl::UniformInfo* info = nullptr;
for (const auto& uniform : uniforms) {
if (uniform->mActiveInfo->mBaseUserName == baseUserName) {
- *out = uniform;
- return true;
+ info = uniform;
+ break;
}
}
+ if (!info)
+ return false;
- return false;
+ const auto& baseMappedName = info->mActiveInfo->mBaseMappedName;
+ AssembleName(baseMappedName, isArray, arrayIndex, out_mappedName);
+
+ *out_arrayIndex = arrayIndex;
+ *out_info = info;
+ return true;
}
bool
-webgl::LinkedProgramInfo::FindUniformBlock(const nsCString& baseUserName,
- const webgl::UniformBlockInfo** const out) const
+webgl::LinkedProgramInfo::MapUniformBlockName(const nsCString& userName,
+ nsCString* const out_mappedName) const
{
+ nsCString baseUserName;
+ bool isArray;
+ size_t arrayIndex;
+ if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex))
+ return false;
+
+ const webgl::UniformBlockInfo* info = nullptr;
for (const auto& block : uniformBlocks) {
if (block->mBaseUserName == baseUserName) {
- *out = block;
- return true;
+ info = block;
+ break;
}
}
+ if (!info)
+ return false;
- return false;
+ const auto& baseMappedName = info->mBaseMappedName;
+ AssembleName(baseMappedName, isArray, arrayIndex, out_mappedName);
+ return true;
+}
+
+bool
+webgl::LinkedProgramInfo::MapFragDataName(const nsCString& userName,
+ nsCString* const out_mappedName) const
+{
+ // FS outputs can be arrays, but not structures.
+
+ if (!fragDataMap.size()) {
+ // No mappings map from validation, so just forward it.
+ *out_mappedName = userName;
+ return true;
+ }
+
+ nsCString baseUserName;
+ bool isArray;
+ size_t arrayIndex;
+ if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex))
+ return false;
+
+ const auto itr = fragDataMap.find(baseUserName);
+ if (itr == fragDataMap.end())
+ return false;
+
+ const auto& baseMappedName = itr->second;
+ AssembleName(baseMappedName, isArray, arrayIndex, out_mappedName);
+ return true;
}
////////////////////////////////////////////////////////////////////////////////
JSObject*
WebGLProgram::WrapObject(JSContext* js, JS::Handle<JSObject*> givenProto)
{
return dom::WebGLProgramBinding::Wrap(js, this, givenProto);
--- a/dom/canvas/WebGLProgram.h
+++ b/dom/canvas/WebGLProgram.h
@@ -100,33 +100,23 @@ struct LinkedProgramInfo final
//////
// The maps for the frag data names to the translated names.
std::map<nsCString, const nsCString> fragDataMap;
explicit LinkedProgramInfo(WebGLProgram* prog);
~LinkedProgramInfo();
- bool FindAttrib(const nsCString& baseUserName, const AttribInfo** const out) const;
- bool FindUniform(const nsCString& baseUserName, UniformInfo** const out) const;
- bool FindUniformBlock(const nsCString& baseUserName,
- const UniformBlockInfo** const out) const;
-
- bool
- FindFragData(const nsCString& baseUserName,
- nsCString* const out_baseMappedName) const
- {
- const auto itr = fragDataMap.find(baseUserName);
- if (itr == fragDataMap.end()) {
- return false;
- }
-
- *out_baseMappedName = itr->second;
- return true;
- }
+ bool FindAttrib(const nsCString& userName, const AttribInfo** const out_info) const;
+ bool FindUniform(const nsCString& userName, nsCString* const out_mappedName,
+ size_t* const out_arrayIndex, UniformInfo** const out_info) const;
+ bool MapUniformBlockName(const nsCString& userName,
+ nsCString* const out_mappedName) const;
+ bool MapFragDataName(const nsCString& userName,
+ nsCString* const out_mappedName) const;
};
} // namespace webgl
class WebGLProgram final
: public nsWrapperCache
, public WebGLRefCountedObject<WebGLProgram>
, public LinkedListElement<WebGLProgram>