--- a/dom/canvas/WebGLActiveInfo.cpp
+++ b/dom/canvas/WebGLActiveInfo.cpp
@@ -71,28 +71,56 @@ ElemSizeFromType(GLenum elemType)
case LOCAL_GL_FLOAT_MAT4:
return 16;
default:
MOZ_CRASH("GFX: Bad `elemType`.");
}
}
+////////////////////
+
WebGLActiveInfo::WebGLActiveInfo(WebGLContext* webgl, GLint elemCount, GLenum elemType,
bool isArray, const nsACString& baseUserName,
const nsACString& baseMappedName)
: mWebGL(webgl)
, mElemCount(elemCount)
, mElemType(elemType)
, mBaseUserName(baseUserName)
, mIsArray(isArray)
, mElemSize(ElemSizeFromType(elemType))
, mBaseMappedName(baseMappedName)
{ }
+bool
+WebGLActiveInfo::IsSampler() const
+{
+ switch (mElemType) {
+ case LOCAL_GL_SAMPLER_2D:
+ case LOCAL_GL_SAMPLER_3D:
+ case LOCAL_GL_SAMPLER_CUBE:
+ case LOCAL_GL_SAMPLER_2D_SHADOW:
+ case LOCAL_GL_SAMPLER_2D_ARRAY:
+ case LOCAL_GL_SAMPLER_2D_ARRAY_SHADOW:
+ case LOCAL_GL_SAMPLER_CUBE_SHADOW:
+ case LOCAL_GL_INT_SAMPLER_2D:
+ case LOCAL_GL_INT_SAMPLER_3D:
+ case LOCAL_GL_INT_SAMPLER_CUBE:
+ case LOCAL_GL_INT_SAMPLER_2D_ARRAY:
+ case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D:
+ case LOCAL_GL_UNSIGNED_INT_SAMPLER_3D:
+ case LOCAL_GL_UNSIGNED_INT_SAMPLER_CUBE:
+ case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
JSObject*
WebGLActiveInfo::WrapObject(JSContext* js, JS::Handle<JSObject*> givenProto)
{
return dom::WebGLActiveInfoBinding::Wrap(js, this, givenProto);
}
--- a/dom/canvas/WebGLActiveInfo.h
+++ b/dom/canvas/WebGLActiveInfo.h
@@ -38,16 +38,18 @@ public:
const GLenum mElemType; // `type`
const nsCString mBaseUserName; // `name`, but ASCII, and without any final "[0]".
// Not actually part of ActiveInfo:
const bool mIsArray;
const uint8_t mElemSize;
const nsCString mBaseMappedName; // Without any final "[0]".
+ bool IsSampler() const;
+
WebGLActiveInfo(WebGLContext* webgl, GLint elemCount, GLenum elemType, bool isArray,
const nsACString& baseUserName, const nsACString& baseMappedName);
/* GLES 2.0.25, p33:
* This command will return as much information about active
* attributes as possible. If no information is available, length will
* be set to zero and name will be an empty string. This situation
* could arise if GetActiveAttrib is issued after a failed link.
@@ -86,12 +88,13 @@ private:
// Private destructor, to discourage deletion outside of Release():
~WebGLActiveInfo() { }
};
//////////
uint8_t ElemSizeFromType(GLenum elemType);
+bool IsElemTypeSampler(GLenum elemType);
} // namespace mozilla
#endif // WEBGL_ACTIVE_INFO_H_
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -117,16 +117,17 @@ template<typename> struct Nullable;
namespace gfx {
class SourceSurface;
} // namespace gfx
namespace webgl {
struct LinkedProgramInfo;
class ShaderValidator;
class TexUnpackBlob;
+struct UniformInfo;
} // namespace webgl
WebGLTexelFormat GetWebGLTexelFormat(TexInternalFormat format);
void AssertUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint shadow);
struct WebGLContextOptions
{
@@ -1598,24 +1599,28 @@ public:
void GenerateWarning(const char* fmt, va_list ap);
public:
UniquePtr<webgl::FormatUsageAuthority> mFormatUsage;
virtual UniquePtr<webgl::FormatUsageAuthority>
CreateFormatUsage(gl::GLContext* gl) const = 0;
+
+ const decltype(mBound2DTextures)* TexListForElemType(GLenum elemType) const;
+
// Friend list
friend class ScopedCopyTexImageSource;
friend class ScopedResolveTexturesForDraw;
friend class ScopedUnpackReset;
friend class webgl::TexUnpackBlob;
friend class webgl::TexUnpackBytes;
friend class webgl::TexUnpackImage;
friend class webgl::TexUnpackSurface;
+ friend struct webgl::UniformInfo;
friend class WebGLTexture;
friend class WebGLFBAttachPoint;
friend class WebGLFramebuffer;
friend class WebGLRenderbuffer;
friend class WebGLProgram;
friend class WebGLQuery;
friend class WebGLBuffer;
friend class WebGLSampler;
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -965,20 +965,20 @@ WebGLContext::GetUniform(JSContext* js,
return JS::NullValue();
if (!ValidateObject("getUniform: `program`", prog))
return JS::NullValue();
if (!ValidateObject("getUniform: `location`", loc))
return JS::NullValue();
- if (!loc->ValidateForProgram(prog, this, "getUniform"))
+ if (!loc->ValidateForProgram(prog, "getUniform"))
return JS::NullValue();
- return loc->GetUniform(js, this);
+ return loc->GetUniform(js);
}
already_AddRefed<WebGLUniformLocation>
WebGLContext::GetUniformLocation(WebGLProgram* prog, const nsAString& name)
{
if (IsContextLost())
return nullptr;
--- a/dom/canvas/WebGLProgram.cpp
+++ b/dom/canvas/WebGLProgram.cpp
@@ -64,46 +64,70 @@ ParseName(const nsCString& name, nsCStri
return false;
*out_baseName = StringHead(name, indexOpenBracket);
*out_isArray = true;
*out_arrayIndex = indexNum;
return true;
}
-static WebGLActiveInfo*
-AddActiveInfo(WebGLContext* webgl, GLint elemCount, GLenum elemType, bool isArray,
- const nsACString& baseUserName, const nsACString& baseMappedName,
- std::vector<RefPtr<WebGLActiveInfo>>* activeInfoList,
- std::map<nsCString, const WebGLActiveInfo*>* infoLocMap)
+//////////
+
+/*static*/ const webgl::UniformInfo::TexListT*
+webgl::UniformInfo::GetTexList(WebGLActiveInfo* activeInfo)
{
- RefPtr<WebGLActiveInfo> info = new WebGLActiveInfo(webgl, elemCount, elemType,
- isArray, baseUserName,
- baseMappedName);
- activeInfoList->push_back(info);
+ const auto& webgl = activeInfo->mWebGL;
+
+ switch (activeInfo->mElemType) {
+ case LOCAL_GL_SAMPLER_2D:
+ case LOCAL_GL_SAMPLER_2D_SHADOW:
+ case LOCAL_GL_INT_SAMPLER_2D:
+ case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D:
+ return &webgl->mBound2DTextures;
+
+ case LOCAL_GL_SAMPLER_CUBE:
+ case LOCAL_GL_SAMPLER_CUBE_SHADOW:
+ case LOCAL_GL_INT_SAMPLER_CUBE:
+ case LOCAL_GL_UNSIGNED_INT_SAMPLER_CUBE:
+ return &webgl->mBoundCubeMapTextures;
- infoLocMap->insert(std::make_pair(info->mBaseUserName, info.get()));
- return info.get();
+ case LOCAL_GL_SAMPLER_3D:
+ case LOCAL_GL_INT_SAMPLER_3D:
+ case LOCAL_GL_UNSIGNED_INT_SAMPLER_3D:
+ return &webgl->mBound3DTextures;
+
+ case LOCAL_GL_SAMPLER_2D_ARRAY:
+ case LOCAL_GL_SAMPLER_2D_ARRAY_SHADOW:
+ case LOCAL_GL_INT_SAMPLER_2D_ARRAY:
+ case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ return &webgl->mBound2DArrayTextures;
+
+ default:
+ return nullptr;
+ }
}
-static void
-AddActiveBlockInfo(const nsACString& baseUserName,
- const nsACString& baseMappedName,
- std::vector<RefPtr<webgl::UniformBlockInfo>>* activeInfoList)
+webgl::UniformInfo::UniformInfo(WebGLActiveInfo* activeInfo)
+ : mActiveInfo(activeInfo)
+ , mSamplerTexList(GetTexList(activeInfo))
{
- RefPtr<webgl::UniformBlockInfo> info = new webgl::UniformBlockInfo(baseUserName, baseMappedName);
-
- activeInfoList->push_back(info);
+ if (mSamplerTexList) {
+ mSamplerValues.assign(mActiveInfo->mElemCount, 0);
+ }
}
-//#define DUMP_SHADERVAR_MAPPINGS
+//////////
+
+#define DUMP_SHADERVAR_MAPPINGS
static already_AddRefed<const webgl::LinkedProgramInfo>
QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
{
+ WebGLContext* const webgl = prog->mContext;
+
RefPtr<webgl::LinkedProgramInfo> info(new webgl::LinkedProgramInfo(prog));
GLuint maxAttribLenWithNull = 0;
gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_ATTRIBUTE_MAX_LENGTH,
(GLint*)&maxAttribLenWithNull);
if (maxAttribLenWithNull < 1)
maxAttribLenWithNull = 1;
@@ -149,43 +173,47 @@ QueryProgramInfo(WebGLProgram* prog, gl:
GLsizei lengthWithoutNull = 0;
GLint elemCount = 0; // `size`
GLenum elemType = 0; // `type`
gl->fGetActiveAttrib(prog->mGLName, i, mappedName.Length()+1, &lengthWithoutNull,
&elemCount, &elemType, mappedName.BeginWriting());
mappedName.SetLength(lengthWithoutNull);
- // Collect ActiveInfos:
-
// 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());
+ if (loc == -1) {
+ MOZ_ASSERT(mappedName == "gl_InstanceID",
+ "Active attrib should have a location.");
+ continue;
+ }
+
#ifdef DUMP_SHADERVAR_MAPPINGS
- printf_stderr("[attrib %i] %s/%s\n", i, mappedName.BeginReading(),
+ printf_stderr("[attrib %i: %i] %s/%s\n", i, loc, mappedName.BeginReading(),
userName.BeginReading());
printf_stderr(" lengthWithoutNull: %d\n", lengthWithoutNull);
#endif
- const bool isArray = false;
- const auto attrib = AddActiveInfo(prog->mContext, elemCount, elemType, isArray,
- userName, mappedName, &info->activeAttribs,
- &info->attribMap);
+ ///////
- // Collect active locations:
- GLint loc = gl->fGetAttribLocation(prog->mGLName, mappedName.BeginReading());
- if (loc == -1) {
- if (mappedName != "gl_InstanceID")
- MOZ_CRASH("GFX: Active attrib has no location.");
- } else {
- info->activeAttribLocs.insert({attrib, (GLuint)loc});
- }
+ const bool isArray = false;
+ const RefPtr<WebGLActiveInfo> activeInfo = new WebGLActiveInfo(webgl, elemCount,
+ elemType, isArray,
+ userName,
+ mappedName);
+ const webgl::AttribInfo attrib = {activeInfo, uint32_t(loc)};
+ info->attribs.push_back(attrib);
}
// Uniforms
const bool needsCheckForArrays = gl->WorkAroundDriverBugs();
GLuint numActiveUniforms = 0;
gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_UNIFORMS,
@@ -198,55 +226,74 @@ 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);
+ ///////
+
nsAutoCString baseMappedName;
bool isArray;
size_t arrayIndex;
if (!ParseName(mappedName, &baseMappedName, &isArray, &arrayIndex))
MOZ_CRASH("GFX: Failed to parse `mappedName` received from driver.");
// Note that for good drivers, `isArray` should already be correct.
// However, if FindUniform succeeds, it will be validator-guaranteed correct.
+ ///////
+
nsAutoCString baseUserName;
if (!prog->FindUniformByMappedName(baseMappedName, &baseUserName, &isArray)) {
+ // Validator likely missing.
baseUserName = baseMappedName;
if (needsCheckForArrays && !isArray) {
// By GLES 3, GetUniformLocation("foo[0]") should return -1 if `foo` is
// not an array. Our current linux Try slaves return the location of `foo`
// anyways, though.
std::string mappedNameStr = baseMappedName.BeginReading();
mappedNameStr += "[0]";
GLint loc = gl->fGetUniformLocation(prog->mGLName, mappedNameStr.c_str());
if (loc != -1)
isArray = true;
}
}
+ ///////
+
#ifdef DUMP_SHADERVAR_MAPPINGS
printf_stderr("[uniform %i] %s/%i/%s/%s\n", i, mappedName.BeginReading(),
(int)isArray, baseMappedName.BeginReading(),
baseUserName.BeginReading());
printf_stderr(" lengthWithoutNull: %d\n", lengthWithoutNull);
printf_stderr(" isArray: %d\n", (int)isArray);
#endif
- AddActiveInfo(prog->mContext, elemCount, elemType, isArray, baseUserName,
- baseMappedName, &info->activeUniforms, &info->uniformMap);
+ ///////
+
+ const RefPtr<WebGLActiveInfo> activeInfo = new WebGLActiveInfo(webgl, elemCount,
+ elemType, isArray,
+ baseUserName,
+ baseMappedName);
+
+ 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!)
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;
@@ -276,82 +323,103 @@ QueryProgramInfo(WebGLProgram* prog, gl:
GLuint loc = gl->fGetUniformBlockIndex(prog->mGLName,
mappedNameStr.c_str());
if (loc != LOCAL_GL_INVALID_INDEX)
isArray = true;
}
}
#ifdef DUMP_SHADERVAR_MAPPINGS
- printf_stderr("[uniform block %i] %s/%i/%s/%s\n", i, mappedName.BeginReading(),
- (int)isArray, baseMappedName.BeginReading(),
- baseUserName.BeginReading());
+ printf_stderr("[uniform block %i] %s/%i/%s/%s\n", i,
+ mappedName.BeginReading(), (int)isArray,
+ baseMappedName.BeginReading(), baseUserName.BeginReading());
printf_stderr(" lengthWithoutNull: %d\n", lengthWithoutNull);
printf_stderr(" isArray: %d\n", (int)isArray);
#endif
- AddActiveBlockInfo(baseUserName, baseMappedName, &info->uniformBlocks);
+ const auto* block = new webgl::UniformBlockInfo(baseUserName, baseMappedName);
+ info->uniformBlocks.push_back(block);
}
}
// Transform feedback varyings
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;
mappedName.SetLength(maxTransformFeedbackVaryingLenWithNull - 1);
GLint lengthWithoutNull;
- GLsizei size;
- GLenum type;
- gl->fGetTransformFeedbackVarying(prog->mGLName, i, maxTransformFeedbackVaryingLenWithNull,
- &lengthWithoutNull, &size, &type,
+ GLsizei elemCount;
+ GLenum elemType;
+ gl->fGetTransformFeedbackVarying(prog->mGLName, i,
+ maxTransformFeedbackVaryingLenWithNull,
+ &lengthWithoutNull, &elemCount, &elemType,
mappedName.BeginWriting());
mappedName.SetLength(lengthWithoutNull);
+ ////
+
nsAutoCString baseMappedName;
bool isArray;
size_t arrayIndex;
if (!ParseName(mappedName, &baseMappedName, &isArray, &arrayIndex))
MOZ_CRASH("GFX: Failed to parse `mappedName` received from driver.");
+
nsAutoCString baseUserName;
if (!prog->FindVaryingByMappedName(mappedName, &baseUserName, &isArray)) {
baseUserName = baseMappedName;
if (needsCheckForArrays && !isArray) {
std::string mappedNameStr = baseMappedName.BeginReading();
mappedNameStr += "[0]";
GLuint loc = gl->fGetUniformBlockIndex(prog->mGLName,
mappedNameStr.c_str());
if (loc != LOCAL_GL_INVALID_INDEX)
isArray = true;
}
}
- AddActiveInfo(prog->mContext, size, type, isArray, baseUserName, mappedName,
- &info->transformFeedbackVaryings,
- &info->transformFeedbackVaryingsMap);
+ ////
+
+ const RefPtr<WebGLActiveInfo> activeInfo = new WebGLActiveInfo(webgl,
+ elemCount,
+ elemType,
+ isArray,
+ baseUserName,
+ mappedName);
+ info->transformFeedbackVaryings.push_back(activeInfo);
}
}
return info.forget();
}
////////////////////////////////////////////////////////////////////////////////
webgl::LinkedProgramInfo::LinkedProgramInfo(WebGLProgram* prog)
: prog(prog)
{ }
+webgl::LinkedProgramInfo::~LinkedProgramInfo()
+{
+ for (auto& cur : uniforms) {
+ delete cur;
+ }
+ for (auto& cur : uniformBlocks) {
+ delete cur;
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// WebGLProgram
static GLuint
CreateProgram(gl::GLContext* gl)
{
gl->MakeCurrent();
return gl->fCreateProgram();
@@ -482,46 +550,46 @@ WebGLProgram::DetachShader(WebGLShader*
already_AddRefed<WebGLActiveInfo>
WebGLProgram::GetActiveAttrib(GLuint index) const
{
if (!mMostRecentLinkInfo) {
RefPtr<WebGLActiveInfo> ret = WebGLActiveInfo::CreateInvalid(mContext);
return ret.forget();
}
- const auto& activeList = mMostRecentLinkInfo->activeAttribs;
+ const auto& attribs = mMostRecentLinkInfo->attribs;
- if (index >= activeList.size()) {
+ if (index >= attribs.size()) {
mContext->ErrorInvalidValue("`index` (%i) must be less than %s (%i).",
- index, "ACTIVE_ATTRIBS", activeList.size());
+ index, "ACTIVE_ATTRIBS", attribs.size());
return nullptr;
}
- RefPtr<WebGLActiveInfo> ret = activeList[index];
+ RefPtr<WebGLActiveInfo> ret = attribs[index].mActiveInfo;
return ret.forget();
}
already_AddRefed<WebGLActiveInfo>
WebGLProgram::GetActiveUniform(GLuint index) const
{
if (!mMostRecentLinkInfo) {
// According to the spec, this can return null.
RefPtr<WebGLActiveInfo> ret = WebGLActiveInfo::CreateInvalid(mContext);
return ret.forget();
}
- const auto& activeList = mMostRecentLinkInfo->activeUniforms;
+ const auto& uniforms = mMostRecentLinkInfo->uniforms;
- if (index >= activeList.size()) {
+ if (index >= uniforms.size()) {
mContext->ErrorInvalidValue("`index` (%i) must be less than %s (%i).",
- index, "ACTIVE_UNIFORMS", activeList.size());
+ index, "ACTIVE_UNIFORMS", uniforms.size());
return nullptr;
}
- RefPtr<WebGLActiveInfo> ret = activeList[index];
+ RefPtr<WebGLActiveInfo> ret = uniforms[index]->mActiveInfo;
return ret.forget();
}
void
WebGLProgram::GetAttachedShaders(nsTArray<RefPtr<WebGLShader>>* const out) const
{
out->TruncateLength(0);
@@ -540,26 +608,21 @@ WebGLProgram::GetAttribLocation(const ns
if (!IsLinked()) {
mContext->ErrorInvalidOperation("getAttribLocation: `program` must be linked.");
return -1;
}
const NS_LossyConvertUTF16toASCII userName(userName_wide);
- const WebGLActiveInfo* info;
+ const webgl::AttribInfo* info;
if (!LinkInfo()->FindAttrib(userName, &info))
return -1;
- const nsCString& mappedName = info->mBaseMappedName;
-
- gl::GLContext* gl = mContext->GL();
- gl->MakeCurrent();
-
- return gl->fGetAttribLocation(mGLName, mappedName.BeginReading());
+ return GLint(info->mLoc);
}
GLint
WebGLProgram::GetFragDataLocation(const nsAString& userName_wide) const
{
if (!ValidateGLSLVariableName(userName_wide, mContext, "getFragDataLocation"))
return -1;
@@ -653,23 +716,22 @@ WebGLProgram::GetUniformBlockIndex(const
const NS_LossyConvertUTF16toASCII userName(userName_wide);
nsDependentCString baseUserName;
bool isArray;
size_t arrayIndex;
if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex))
return LOCAL_GL_INVALID_INDEX;
- RefPtr<const webgl::UniformBlockInfo> info;
+ const webgl::UniformBlockInfo* info;
if (!LinkInfo()->FindUniformBlock(baseUserName, &info)) {
return LOCAL_GL_INVALID_INDEX;
}
- const nsCString& baseMappedName = info->mBaseMappedName;
- nsAutoCString mappedName(baseMappedName);
+ nsAutoCString mappedName(info->mBaseMappedName);
if (isArray) {
mappedName.AppendLiteral("[");
mappedName.AppendInt(uint32_t(arrayIndex));
mappedName.AppendLiteral("]");
}
gl::GLContext* gl = mContext->GL();
gl->MakeCurrent();
@@ -794,39 +856,36 @@ WebGLProgram::GetUniformLocation(const n
// 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;
- const WebGLActiveInfo* activeInfo;
- if (!LinkInfo()->FindUniform(baseUserName, &activeInfo))
+ webgl::UniformInfo* info;
+ if (!LinkInfo()->FindUniform(baseUserName, &info))
return nullptr;
- const nsCString& baseMappedName = activeInfo->mBaseMappedName;
-
- nsAutoCString mappedName(baseMappedName);
+ 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(),
- loc, arrayIndex,
- activeInfo);
+ info, loc, arrayIndex);
return locObj.forget();
}
void
WebGLProgram::GetUniformIndices(const dom::Sequence<nsString>& uniformNames,
dom::Nullable< nsTArray<GLuint> >& retval) const
{
size_t count = uniformNames.Length();
@@ -841,25 +900,23 @@ WebGLProgram::GetUniformIndices(const do
nsDependentCString baseUserName;
bool isArray;
size_t arrayIndex;
if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex)) {
arr.AppendElement(LOCAL_GL_INVALID_INDEX);
continue;
}
- const WebGLActiveInfo* activeInfo;
- if (!LinkInfo()->FindUniform(baseUserName, &activeInfo)) {
+ webgl::UniformInfo* info;
+ if (!LinkInfo()->FindUniform(baseUserName, &info)) {
arr.AppendElement(LOCAL_GL_INVALID_INDEX);
continue;
}
- const nsCString& baseMappedName = activeInfo->mBaseMappedName;
-
- nsAutoCString mappedName(baseMappedName);
+ nsAutoCString mappedName(info->mActiveInfo->mBaseMappedName);
if (isArray) {
mappedName.AppendLiteral("[");
mappedName.AppendInt(uint32_t(arrayIndex));
mappedName.AppendLiteral("]");
}
const GLchar* mappedNameBytes = mappedName.BeginReading();
@@ -874,18 +931,17 @@ void
WebGLProgram::UniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) const
{
if (!IsLinked()) {
mContext->ErrorInvalidOperation("getActiveUniformBlockName: `program` must be linked.");
return;
}
const webgl::LinkedProgramInfo* linkInfo = LinkInfo();
- GLuint uniformBlockCount = (GLuint)linkInfo->uniformBlocks.size();
- if (uniformBlockIndex >= uniformBlockCount) {
+ if (uniformBlockIndex >= linkInfo->uniformBlocks.size()) {
mContext->ErrorInvalidValue("getActiveUniformBlockName: index %u invalid.", uniformBlockIndex);
return;
}
if (uniformBlockBinding > mContext->mGLMaxUniformBufferBindings) {
mContext->ErrorInvalidEnum("getActiveUniformBlockName: binding %u invalid.", uniformBlockBinding);
return;
}
@@ -1229,16 +1285,60 @@ WebGLProgram::FindUniformBlockByMappedNa
if (mFragShader->FindUniformBlockByMappedName(mappedName, out_userName, out_isArray))
return true;
return false;
}
////////////////////////////////////////////////////////////////////////////////
+bool
+webgl::LinkedProgramInfo::FindAttrib(const nsCString& baseUserName,
+ const webgl::AttribInfo** const out) const
+{
+ for (const auto& attrib : attribs) {
+ if (attrib.mActiveInfo->mBaseUserName == baseUserName) {
+ *out = &attrib;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool
+webgl::LinkedProgramInfo::FindUniform(const nsCString& baseUserName,
+ webgl::UniformInfo** const out) const
+{
+ for (const auto& uniform : uniforms) {
+ if (uniform->mActiveInfo->mBaseUserName == baseUserName) {
+ *out = uniform;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool
+webgl::LinkedProgramInfo::FindUniformBlock(const nsCString& baseUserName,
+ const webgl::UniformBlockInfo** const out) const
+{
+ for (const auto& block : uniformBlocks) {
+ if (block->mBaseUserName == baseUserName) {
+ *out = block;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
JSObject*
WebGLProgram::WrapObject(JSContext* js, JS::Handle<JSObject*> givenProto)
{
return dom::WebGLProgramBinding::Wrap(js, this, givenProto);
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLProgram, mVertShader, mFragShader)
--- a/dom/canvas/WebGLProgram.h
+++ b/dom/canvas/WebGLProgram.h
@@ -30,21 +30,40 @@ class WebGLUniformLocation;
namespace dom {
template<typename> struct Nullable;
class OwningUnsignedLongOrUint32ArrayOrBoolean;
template<typename> class Sequence;
} // namespace dom
namespace webgl {
-struct UniformBlockInfo final
- : public RefCounted<UniformBlockInfo>
+struct AttribInfo final
+{
+ const RefPtr<WebGLActiveInfo> mActiveInfo;
+ uint32_t mLoc;
+};
+
+struct UniformInfo final
{
- MOZ_DECLARE_REFCOUNTED_TYPENAME(UniformBlockInfo);
+ typedef decltype(WebGLContext::mBound2DTextures) TexListT;
+
+ const RefPtr<WebGLActiveInfo> mActiveInfo;
+ const TexListT* const mSamplerTexList;
+ std::vector<uint32_t> mSamplerValues;
+protected:
+ static const TexListT*
+ GetTexList(WebGLActiveInfo* activeInfo);
+
+public:
+ explicit UniformInfo(WebGLActiveInfo* activeInfo);
+};
+
+struct UniformBlockInfo final
+{
const nsCString mBaseUserName;
const nsCString mBaseMappedName;
UniformBlockInfo(const nsACString& baseUserName,
const nsACString& baseMappedName)
: mBaseUserName(baseUserName)
, mBaseMappedName(baseMappedName)
{}
@@ -52,71 +71,37 @@ struct UniformBlockInfo final
struct LinkedProgramInfo final
: public RefCounted<LinkedProgramInfo>
, public SupportsWeakPtr<LinkedProgramInfo>
{
MOZ_DECLARE_REFCOUNTED_TYPENAME(LinkedProgramInfo)
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(LinkedProgramInfo)
+ //////
+
WebGLProgram* const prog;
- std::vector<RefPtr<WebGLActiveInfo>> activeAttribs;
- std::vector<RefPtr<WebGLActiveInfo>> activeUniforms;
+
+ std::vector<AttribInfo> attribs;
+ std::vector<UniformInfo*> uniforms; // Owns its contents.
+ std::vector<const UniformBlockInfo*> uniformBlocks; // Owns its contents.
std::vector<RefPtr<WebGLActiveInfo>> transformFeedbackVaryings;
- // Needed for Get{Attrib,Uniform}Location. The keys for these are non-mapped
- // user-facing `GLActiveInfo::name`s, without any final "[0]".
- std::map<nsCString, const WebGLActiveInfo*> attribMap;
- std::map<nsCString, const WebGLActiveInfo*> uniformMap;
- std::map<nsCString, const WebGLActiveInfo*> transformFeedbackVaryingsMap;
-
- std::vector<RefPtr<UniformBlockInfo>> uniformBlocks;
-
// Needed for draw call validation.
- std::map<const WebGLActiveInfo*, GLuint> activeAttribLocs;
+ std::vector<UniformInfo*> uniformSamplers;
//////
explicit LinkedProgramInfo(WebGLProgram* prog);
-
- bool FindAttrib(const nsCString& baseUserName,
- const WebGLActiveInfo** const out_activeInfo) const
- {
- auto itr = attribMap.find(baseUserName);
- if (itr == attribMap.end())
- return false;
-
- *out_activeInfo = itr->second;
- return true;
- }
+ ~LinkedProgramInfo();
- bool FindUniform(const nsCString& baseUserName,
- const WebGLActiveInfo** const out_activeInfo) const
- {
- auto itr = uniformMap.find(baseUserName);
- if (itr == uniformMap.end())
- return false;
-
- *out_activeInfo = itr->second;
- return true;
- }
-
+ bool FindAttrib(const nsCString& baseUserName, const AttribInfo** const out) const;
+ bool FindUniform(const nsCString& baseUserName, UniformInfo** const out) const;
bool FindUniformBlock(const nsCString& baseUserName,
- RefPtr<const UniformBlockInfo>* const out_info) const
- {
- const size_t count = uniformBlocks.size();
- for (size_t i = 0; i < count; i++) {
- if (baseUserName == uniformBlocks[i]->mBaseUserName) {
- *out_info = uniformBlocks[i].get();
- return true;
- }
- }
-
- return false;
- }
+ const UniformBlockInfo** const out) const;
};
} // namespace webgl
class WebGLProgram final
: public nsWrapperCache
, public WebGLRefCountedObject<WebGLProgram>
, public LinkedListElement<WebGLProgram>
--- a/dom/canvas/WebGLUniformLocation.cpp
+++ b/dom/canvas/WebGLUniformLocation.cpp
@@ -11,44 +11,42 @@
#include "WebGLActiveInfo.h"
#include "WebGLContext.h"
#include "WebGLProgram.h"
namespace mozilla {
WebGLUniformLocation::WebGLUniformLocation(WebGLContext* webgl,
const webgl::LinkedProgramInfo* linkInfo,
- GLuint loc,
- size_t arrayIndex,
- const WebGLActiveInfo* activeInfo)
+ webgl::UniformInfo* info, GLuint loc,
+ size_t arrayIndex)
: WebGLContextBoundObject(webgl)
, mLinkInfo(linkInfo)
+ , mInfo(info)
, mLoc(loc)
, mArrayIndex(arrayIndex)
- , mActiveInfo(activeInfo)
{ }
WebGLUniformLocation::~WebGLUniformLocation()
{ }
bool
-WebGLUniformLocation::ValidateForProgram(WebGLProgram* prog, WebGLContext* webgl,
- const char* funcName) const
+WebGLUniformLocation::ValidateForProgram(WebGLProgram* prog, const char* funcName) const
{
// Check the weak-pointer.
if (!mLinkInfo) {
- webgl->ErrorInvalidOperation("%s: This uniform location is obsolete because its"
- " program has been successfully relinked.",
- funcName);
+ mContext->ErrorInvalidOperation("%s: This uniform location is obsolete because"
+ " its program has been successfully relinked.",
+ funcName);
return false;
}
if (mLinkInfo->prog != prog) {
- webgl->ErrorInvalidOperation("%s: This uniform location corresponds to a"
- " different program.", funcName);
+ mContext->ErrorInvalidOperation("%s: This uniform location corresponds to a"
+ " different program.", funcName);
return false;
}
return true;
}
static bool
IsUniformSetterTypeValid(GLenum setterType, GLenum uniformType)
@@ -116,106 +114,88 @@ IsUniformSetterTypeValid(GLenum setterTy
default:
MOZ_CRASH("GFX: Bad `uniformType`.");
}
}
bool
WebGLUniformLocation::ValidateSizeAndType(uint8_t setterElemSize, GLenum setterType,
- WebGLContext* webgl, const char* funcName) const
+ const char* funcName) const
{
MOZ_ASSERT(mLinkInfo);
- if (setterElemSize != mActiveInfo->mElemSize) {
- webgl->ErrorInvalidOperation("%s: Bad uniform size: %i", funcName,
- mActiveInfo->mElemSize);
+ const auto& uniformElemSize = mInfo->mActiveInfo->mElemSize;
+ if (setterElemSize != uniformElemSize) {
+ mContext->ErrorInvalidOperation("%s: Function used differs from uniform size: %i",
+ funcName, uniformElemSize);
return false;
}
- if (!IsUniformSetterTypeValid(setterType, mActiveInfo->mElemType)) {
- webgl->ErrorInvalidOperation("%s: Bad uniform type: %i", funcName,
- mActiveInfo->mElemSize);
+ const auto& uniformElemType = mInfo->mActiveInfo->mElemType;
+ if (!IsUniformSetterTypeValid(setterType, uniformElemType)) {
+ mContext->ErrorInvalidOperation("%s: Function used is incompatible with uniform"
+ " type: %i",
+ funcName, uniformElemType);
return false;
}
return true;
}
bool
WebGLUniformLocation::ValidateArrayLength(uint8_t setterElemSize, size_t setterArraySize,
- WebGLContext* webgl, const char* funcName) const
+ const char* funcName) const
{
MOZ_ASSERT(mLinkInfo);
if (setterArraySize == 0 ||
setterArraySize % setterElemSize)
{
- webgl->ErrorInvalidValue("%s: expected an array of length a multiple of"
- " %d, got an array of length %d.",
- funcName, setterElemSize, setterArraySize);
+ mContext->ErrorInvalidValue("%s: Expected an array of length a multiple of %d,"
+ " got an array of length %d.",
+ funcName, setterElemSize, setterArraySize);
return false;
}
/* GLES 2.0.25, Section 2.10, p38
* When loading `N` elements starting at an arbitrary position `k` in a uniform
* declared as an array, elements `k` through `k + N - 1` in the array will be
* replaced with the new values. Values for any array element that exceeds the
* highest array element index used, as reported by `GetActiveUniform`, will be
* ignored by GL.
*/
- if (!mActiveInfo->mIsArray &&
+ if (!mInfo->mActiveInfo->mIsArray &&
setterArraySize != setterElemSize)
{
- webgl->ErrorInvalidOperation("%s: expected an array of length exactly %d"
- " (since this uniform is not an array"
- " uniform), got an array of length %d.",
- funcName, setterElemSize, setterArraySize);
+ mContext->ErrorInvalidOperation("%s: Expected an array of length exactly %d"
+ " (since this uniform is not an array uniform),"
+ " got an array of length %d.",
+ funcName, setterElemSize, setterArraySize);
return false;
}
return true;
}
-bool
-WebGLUniformLocation::ValidateSamplerSetter(GLint value, WebGLContext* webgl,
- const char* funcName) const
+JS::Value
+WebGLUniformLocation::GetUniform(JSContext* js) const
{
MOZ_ASSERT(mLinkInfo);
- if (mActiveInfo->mElemType != LOCAL_GL_SAMPLER_2D &&
- mActiveInfo->mElemType != LOCAL_GL_SAMPLER_CUBE)
- {
- return true;
- }
-
- if (value >= 0 && value < (GLint)webgl->GLMaxTextureUnits())
- return true;
-
- webgl->ErrorInvalidValue("%s: This uniform location is a sampler, but %d is not a"
- " valid texture unit.",
- funcName, value);
- return false;
-}
-
-JS::Value
-WebGLUniformLocation::GetUniform(JSContext* js, WebGLContext* webgl) const
-{
- MOZ_ASSERT(mLinkInfo);
-
- uint8_t elemSize = mActiveInfo->mElemSize;
+ const uint8_t elemSize = mInfo->mActiveInfo->mElemSize;
static const uint8_t kMaxElemSize = 16;
MOZ_ASSERT(elemSize <= kMaxElemSize);
GLuint prog = mLinkInfo->prog->mGLName;
- gl::GLContext* gl = webgl->GL();
+ gl::GLContext* gl = mContext->GL();
gl->MakeCurrent();
- switch (mActiveInfo->mElemType) {
+ switch (mInfo->mActiveInfo->mElemType) {
case LOCAL_GL_INT:
case LOCAL_GL_INT_VEC2:
case LOCAL_GL_INT_VEC3:
case LOCAL_GL_INT_VEC4:
case LOCAL_GL_SAMPLER_2D:
case LOCAL_GL_SAMPLER_3D:
case LOCAL_GL_SAMPLER_CUBE:
case LOCAL_GL_SAMPLER_2D_SHADOW:
@@ -232,19 +212,19 @@ WebGLUniformLocation::GetUniform(JSConte
case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
{
GLint buffer[kMaxElemSize] = {0};
gl->fGetUniformiv(prog, mLoc, buffer);
if (elemSize == 1)
return JS::Int32Value(buffer[0]);
- JSObject* obj = dom::Int32Array::Create(js, webgl, elemSize, buffer);
+ JSObject* obj = dom::Int32Array::Create(js, mContext, elemSize, buffer);
if (!obj) {
- webgl->ErrorOutOfMemory("getUniform: out of memory");
+ mContext->ErrorOutOfMemory("getUniform: Out of memory.");
return JS::NullValue();
}
return JS::ObjectOrNullValue(obj);
}
case LOCAL_GL_BOOL:
case LOCAL_GL_BOOL_VEC2:
case LOCAL_GL_BOOL_VEC3:
@@ -258,17 +238,17 @@ WebGLUniformLocation::GetUniform(JSConte
bool boolBuffer[kMaxElemSize];
for (uint8_t i = 0; i < kMaxElemSize; i++)
boolBuffer[i] = buffer[i];
JS::RootedValue val(js);
// Be careful: we don't want to convert all of |uv|!
if (!dom::ToJSValue(js, boolBuffer, elemSize, &val)) {
- webgl->ErrorOutOfMemory("getUniform: out of memory");
+ mContext->ErrorOutOfMemory("getUniform: Out of memory.");
return JS::NullValue();
}
return val;
}
case LOCAL_GL_FLOAT:
case LOCAL_GL_FLOAT_VEC2:
case LOCAL_GL_FLOAT_VEC3:
@@ -284,38 +264,38 @@ WebGLUniformLocation::GetUniform(JSConte
case LOCAL_GL_FLOAT_MAT4x3:
{
GLfloat buffer[16] = {0.0f};
gl->fGetUniformfv(prog, mLoc, buffer);
if (elemSize == 1)
return JS::DoubleValue(buffer[0]);
- JSObject* obj = dom::Float32Array::Create(js, webgl, elemSize, buffer);
+ JSObject* obj = dom::Float32Array::Create(js, mContext, elemSize, buffer);
if (!obj) {
- webgl->ErrorOutOfMemory("getUniform: out of memory");
+ mContext->ErrorOutOfMemory("getUniform: Out of memory.");
return JS::NullValue();
}
return JS::ObjectOrNullValue(obj);
}
case LOCAL_GL_UNSIGNED_INT:
case LOCAL_GL_UNSIGNED_INT_VEC2:
case LOCAL_GL_UNSIGNED_INT_VEC3:
case LOCAL_GL_UNSIGNED_INT_VEC4:
{
GLuint buffer[kMaxElemSize] = {0};
gl->fGetUniformuiv(prog, mLoc, buffer);
if (elemSize == 1)
return JS::DoubleValue(buffer[0]); // This is Double because only Int32 is special cased.
- JSObject* obj = dom::Uint32Array::Create(js, webgl, elemSize, buffer);
+ JSObject* obj = dom::Uint32Array::Create(js, mContext, elemSize, buffer);
if (!obj) {
- webgl->ErrorOutOfMemory("getUniform: out of memory");
+ mContext->ErrorOutOfMemory("getUniform: Out of memory.");
return JS::NullValue();
}
return JS::ObjectOrNullValue(obj);
}
default:
MOZ_CRASH("GFX: Invalid elemType.");
}
--- a/dom/canvas/WebGLUniformLocation.h
+++ b/dom/canvas/WebGLUniformLocation.h
@@ -34,34 +34,35 @@ public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLUniformLocation)
virtual JSObject* WrapObject(JSContext* js, JS::Handle<JSObject*> givenProto) override;
WebGLContext* GetParentObject() const {
return mContext;
}
+ //////
+
const WeakPtr<const webgl::LinkedProgramInfo> mLinkInfo;
+ webgl::UniformInfo* const mInfo;
const GLuint mLoc;
const size_t mArrayIndex;
- const WebGLActiveInfo* const mActiveInfo;
+
+ //////
WebGLUniformLocation(WebGLContext* webgl, const webgl::LinkedProgramInfo* linkInfo,
- GLuint loc, size_t arrayIndex, const WebGLActiveInfo* activeInfo);
+ webgl::UniformInfo* info, GLuint loc, size_t arrayIndex);
- bool ValidateForProgram(WebGLProgram* prog, WebGLContext* webgl,
- const char* funcName) const;
- bool ValidateSamplerSetter(GLint value, WebGLContext* webgl,
- const char* funcName) const;
+ bool ValidateForProgram(WebGLProgram* prog, const char* funcName) const;
bool ValidateSizeAndType(uint8_t setterElemSize, GLenum setterType,
- WebGLContext* webgl, const char* funcName) const;
+ const char* funcName) const;
bool ValidateArrayLength(uint8_t setterElemSize, size_t setterArraySize,
- WebGLContext* webgl, const char* funcName) const;
+ const char* funcName) const;
- JS::Value GetUniform(JSContext* js, WebGLContext* webgl) const;
+ JS::Value GetUniform(JSContext* js) const;
// Needed for certain helper functions like ValidateObject.
// `WebGLUniformLocation`s can't be 'Deleted' in the WebGL sense.
bool IsDeleted() const { return false; }
protected:
~WebGLUniformLocation();
};