Bug 1136494 - Update LinkInfo. - r=mtseng

MozReview-Commit-ID: Fr4j8bHO5AG
This commit is contained in:
Jeff Gilbert 2016-07-14 12:04:31 -07:00
Родитель 95dd193042
Коммит 55d9d2af29
8 изменённых файлов: 299 добавлений и 197 удалений

Просмотреть файл

@ -76,6 +76,8 @@ ElemSizeFromType(GLenum elemType)
} }
} }
////////////////////
WebGLActiveInfo::WebGLActiveInfo(WebGLContext* webgl, GLint elemCount, GLenum elemType, WebGLActiveInfo::WebGLActiveInfo(WebGLContext* webgl, GLint elemCount, GLenum elemType,
bool isArray, const nsACString& baseUserName, bool isArray, const nsACString& baseUserName,
const nsACString& baseMappedName) const nsACString& baseMappedName)
@ -88,6 +90,32 @@ WebGLActiveInfo::WebGLActiveInfo(WebGLContext* webgl, GLint elemCount, GLenum el
, mBaseMappedName(baseMappedName) , 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* JSObject*

Просмотреть файл

@ -43,6 +43,8 @@ public:
const uint8_t mElemSize; const uint8_t mElemSize;
const nsCString mBaseMappedName; // Without any final "[0]". const nsCString mBaseMappedName; // Without any final "[0]".
bool IsSampler() const;
WebGLActiveInfo(WebGLContext* webgl, GLint elemCount, GLenum elemType, bool isArray, WebGLActiveInfo(WebGLContext* webgl, GLint elemCount, GLenum elemType, bool isArray,
const nsACString& baseUserName, const nsACString& baseMappedName); const nsACString& baseUserName, const nsACString& baseMappedName);
@ -91,6 +93,7 @@ private:
////////// //////////
uint8_t ElemSizeFromType(GLenum elemType); uint8_t ElemSizeFromType(GLenum elemType);
bool IsElemTypeSampler(GLenum elemType);
} // namespace mozilla } // namespace mozilla

Просмотреть файл

@ -122,6 +122,7 @@ namespace webgl {
struct LinkedProgramInfo; struct LinkedProgramInfo;
class ShaderValidator; class ShaderValidator;
class TexUnpackBlob; class TexUnpackBlob;
struct UniformInfo;
} // namespace webgl } // namespace webgl
WebGLTexelFormat GetWebGLTexelFormat(TexInternalFormat format); WebGLTexelFormat GetWebGLTexelFormat(TexInternalFormat format);
@ -1607,6 +1608,9 @@ public:
virtual UniquePtr<webgl::FormatUsageAuthority> virtual UniquePtr<webgl::FormatUsageAuthority>
CreateFormatUsage(gl::GLContext* gl) const = 0; CreateFormatUsage(gl::GLContext* gl) const = 0;
const decltype(mBound2DTextures)* TexListForElemType(GLenum elemType) const;
// Friend list // Friend list
friend class ScopedCopyTexImageSource; friend class ScopedCopyTexImageSource;
friend class ScopedResolveTexturesForDraw; friend class ScopedResolveTexturesForDraw;
@ -1615,6 +1619,7 @@ public:
friend class webgl::TexUnpackBytes; friend class webgl::TexUnpackBytes;
friend class webgl::TexUnpackImage; friend class webgl::TexUnpackImage;
friend class webgl::TexUnpackSurface; friend class webgl::TexUnpackSurface;
friend struct webgl::UniformInfo;
friend class WebGLTexture; friend class WebGLTexture;
friend class WebGLFBAttachPoint; friend class WebGLFBAttachPoint;
friend class WebGLFramebuffer; friend class WebGLFramebuffer;

Просмотреть файл

@ -971,10 +971,10 @@ WebGLContext::GetUniform(JSContext* js, WebGLProgram* prog,
if (!ValidateObject("getUniform: `location`", loc)) if (!ValidateObject("getUniform: `location`", loc))
return JS::NullValue(); return JS::NullValue();
if (!loc->ValidateForProgram(prog, this, "getUniform")) if (!loc->ValidateForProgram(prog, "getUniform"))
return JS::NullValue(); return JS::NullValue();
return loc->GetUniform(js, this); return loc->GetUniform(js);
} }
already_AddRefed<WebGLUniformLocation> already_AddRefed<WebGLUniformLocation>

Просмотреть файл

@ -69,36 +69,60 @@ ParseName(const nsCString& name, nsCString* const out_baseName,
return true; 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)
{
RefPtr<WebGLActiveInfo> info = new WebGLActiveInfo(webgl, elemCount, elemType,
isArray, baseUserName,
baseMappedName);
activeInfoList->push_back(info);
infoLocMap->insert(std::make_pair(info->mBaseUserName, info.get())); /*static*/ const webgl::UniformInfo::TexListT*
return info.get(); webgl::UniformInfo::GetTexList(WebGLActiveInfo* activeInfo)
{
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;
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 webgl::UniformInfo::UniformInfo(WebGLActiveInfo* activeInfo)
AddActiveBlockInfo(const nsACString& baseUserName, : mActiveInfo(activeInfo)
const nsACString& baseMappedName, , mSamplerTexList(GetTexList(activeInfo))
std::vector<RefPtr<webgl::UniformBlockInfo>>* activeInfoList)
{ {
RefPtr<webgl::UniformBlockInfo> info = new webgl::UniformBlockInfo(baseUserName, baseMappedName); if (mSamplerTexList) {
mSamplerValues.assign(mActiveInfo->mElemCount, 0);
activeInfoList->push_back(info); }
} }
//////////
//#define DUMP_SHADERVAR_MAPPINGS //#define DUMP_SHADERVAR_MAPPINGS
static already_AddRefed<const webgl::LinkedProgramInfo> static already_AddRefed<const webgl::LinkedProgramInfo>
QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl) QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
{ {
WebGLContext* const webgl = prog->mContext;
RefPtr<webgl::LinkedProgramInfo> info(new webgl::LinkedProgramInfo(prog)); RefPtr<webgl::LinkedProgramInfo> info(new webgl::LinkedProgramInfo(prog));
GLuint maxAttribLenWithNull = 0; GLuint maxAttribLenWithNull = 0;
@ -154,33 +178,37 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
mappedName.SetLength(lengthWithoutNull); mappedName.SetLength(lengthWithoutNull);
// Collect ActiveInfos:
// Attribs can't be arrays, so we can skip some of the mess we have in the Uniform // Attribs can't be arrays, so we can skip some of the mess we have in the Uniform
// path. // path.
nsDependentCString userName; nsDependentCString userName;
if (!prog->FindAttribUserNameByMappedName(mappedName, &userName)) if (!prog->FindAttribUserNameByMappedName(mappedName, &userName))
userName.Rebind(mappedName, 0); 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 #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()); userName.BeginReading());
printf_stderr(" lengthWithoutNull: %d\n", lengthWithoutNull); printf_stderr(" lengthWithoutNull: %d\n", lengthWithoutNull);
#endif #endif
const bool isArray = false; ///////
const auto attrib = AddActiveInfo(prog->mContext, elemCount, elemType, isArray,
userName, mappedName, &info->activeAttribs,
&info->attribMap);
// Collect active locations: const bool isArray = false;
GLint loc = gl->fGetAttribLocation(prog->mGLName, mappedName.BeginReading()); const RefPtr<WebGLActiveInfo> activeInfo = new WebGLActiveInfo(webgl, elemCount,
if (loc == -1) { elemType, isArray,
if (mappedName != "gl_InstanceID") userName,
MOZ_CRASH("GFX: Active attrib has no location."); mappedName);
} else { const webgl::AttribInfo attrib = {activeInfo, uint32_t(loc)};
info->activeAttribLocs.insert({attrib, (GLuint)loc}); info->attribs.push_back(attrib);
}
} }
// Uniforms // Uniforms
@ -203,6 +231,8 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
mappedName.SetLength(lengthWithoutNull); mappedName.SetLength(lengthWithoutNull);
///////
nsAutoCString baseMappedName; nsAutoCString baseMappedName;
bool isArray; bool isArray;
size_t arrayIndex; size_t arrayIndex;
@ -212,8 +242,11 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
// Note that for good drivers, `isArray` should already be correct. // Note that for good drivers, `isArray` should already be correct.
// However, if FindUniform succeeds, it will be validator-guaranteed correct. // However, if FindUniform succeeds, it will be validator-guaranteed correct.
///////
nsAutoCString baseUserName; nsAutoCString baseUserName;
if (!prog->FindUniformByMappedName(baseMappedName, &baseUserName, &isArray)) { if (!prog->FindUniformByMappedName(baseMappedName, &baseUserName, &isArray)) {
// Validator likely missing.
baseUserName = baseMappedName; baseUserName = baseMappedName;
if (needsCheckForArrays && !isArray) { if (needsCheckForArrays && !isArray) {
@ -229,6 +262,8 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
} }
} }
///////
#ifdef DUMP_SHADERVAR_MAPPINGS #ifdef DUMP_SHADERVAR_MAPPINGS
printf_stderr("[uniform %i] %s/%i/%s/%s\n", i, mappedName.BeginReading(), printf_stderr("[uniform %i] %s/%i/%s/%s\n", i, mappedName.BeginReading(),
(int)isArray, baseMappedName.BeginReading(), (int)isArray, baseMappedName.BeginReading(),
@ -237,11 +272,23 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
printf_stderr(" isArray: %d\n", (int)isArray); printf_stderr(" isArray: %d\n", (int)isArray);
#endif #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 // Uniform Blocks
// (no sampler types allowed!)
if (gl->IsSupported(gl::GLFeature::uniform_buffer_object)) { if (gl->IsSupported(gl::GLFeature::uniform_buffer_object)) {
GLuint numActiveUniformBlocks = 0; GLuint numActiveUniformBlocks = 0;
@ -281,14 +328,15 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
} }
#ifdef DUMP_SHADERVAR_MAPPINGS #ifdef DUMP_SHADERVAR_MAPPINGS
printf_stderr("[uniform block %i] %s/%i/%s/%s\n", i, mappedName.BeginReading(), printf_stderr("[uniform block %i] %s/%i/%s/%s\n", i,
(int)isArray, baseMappedName.BeginReading(), mappedName.BeginReading(), (int)isArray,
baseUserName.BeginReading()); baseMappedName.BeginReading(), baseUserName.BeginReading());
printf_stderr(" lengthWithoutNull: %d\n", lengthWithoutNull); printf_stderr(" lengthWithoutNull: %d\n", lengthWithoutNull);
printf_stderr(" isArray: %d\n", (int)isArray); printf_stderr(" isArray: %d\n", (int)isArray);
#endif #endif
AddActiveBlockInfo(baseUserName, baseMappedName, &info->uniformBlocks); const auto* block = new webgl::UniformBlockInfo(baseUserName, baseMappedName);
info->uniformBlocks.push_back(block);
} }
} }
@ -304,19 +352,23 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
mappedName.SetLength(maxTransformFeedbackVaryingLenWithNull - 1); mappedName.SetLength(maxTransformFeedbackVaryingLenWithNull - 1);
GLint lengthWithoutNull; GLint lengthWithoutNull;
GLsizei size; GLsizei elemCount;
GLenum type; GLenum elemType;
gl->fGetTransformFeedbackVarying(prog->mGLName, i, maxTransformFeedbackVaryingLenWithNull, gl->fGetTransformFeedbackVarying(prog->mGLName, i,
&lengthWithoutNull, &size, &type, maxTransformFeedbackVaryingLenWithNull,
&lengthWithoutNull, &elemCount, &elemType,
mappedName.BeginWriting()); mappedName.BeginWriting());
mappedName.SetLength(lengthWithoutNull); mappedName.SetLength(lengthWithoutNull);
////
nsAutoCString baseMappedName; nsAutoCString baseMappedName;
bool isArray; bool isArray;
size_t arrayIndex; size_t arrayIndex;
if (!ParseName(mappedName, &baseMappedName, &isArray, &arrayIndex)) if (!ParseName(mappedName, &baseMappedName, &isArray, &arrayIndex))
MOZ_CRASH("GFX: Failed to parse `mappedName` received from driver."); MOZ_CRASH("GFX: Failed to parse `mappedName` received from driver.");
nsAutoCString baseUserName; nsAutoCString baseUserName;
if (!prog->FindVaryingByMappedName(mappedName, &baseUserName, &isArray)) { if (!prog->FindVaryingByMappedName(mappedName, &baseUserName, &isArray)) {
baseUserName = baseMappedName; baseUserName = baseMappedName;
@ -332,9 +384,15 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
} }
} }
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);
} }
} }
@ -347,6 +405,16 @@ webgl::LinkedProgramInfo::LinkedProgramInfo(WebGLProgram* prog)
: prog(prog) : prog(prog)
{ } { }
webgl::LinkedProgramInfo::~LinkedProgramInfo()
{
for (auto& cur : uniforms) {
delete cur;
}
for (auto& cur : uniformBlocks) {
delete cur;
}
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// WebGLProgram // WebGLProgram
@ -487,15 +555,15 @@ WebGLProgram::GetActiveAttrib(GLuint index) const
return ret.forget(); 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).", mContext->ErrorInvalidValue("`index` (%i) must be less than %s (%i).",
index, "ACTIVE_ATTRIBS", activeList.size()); index, "ACTIVE_ATTRIBS", attribs.size());
return nullptr; return nullptr;
} }
RefPtr<WebGLActiveInfo> ret = activeList[index]; RefPtr<WebGLActiveInfo> ret = attribs[index].mActiveInfo;
return ret.forget(); return ret.forget();
} }
@ -508,15 +576,15 @@ WebGLProgram::GetActiveUniform(GLuint index) const
return ret.forget(); 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).", mContext->ErrorInvalidValue("`index` (%i) must be less than %s (%i).",
index, "ACTIVE_UNIFORMS", activeList.size()); index, "ACTIVE_UNIFORMS", uniforms.size());
return nullptr; return nullptr;
} }
RefPtr<WebGLActiveInfo> ret = activeList[index]; RefPtr<WebGLActiveInfo> ret = uniforms[index]->mActiveInfo;
return ret.forget(); return ret.forget();
} }
@ -545,16 +613,11 @@ WebGLProgram::GetAttribLocation(const nsAString& userName_wide) const
const NS_LossyConvertUTF16toASCII userName(userName_wide); const NS_LossyConvertUTF16toASCII userName(userName_wide);
const WebGLActiveInfo* info; const webgl::AttribInfo* info;
if (!LinkInfo()->FindAttrib(userName, &info)) if (!LinkInfo()->FindAttrib(userName, &info))
return -1; return -1;
const nsCString& mappedName = info->mBaseMappedName; return GLint(info->mLoc);
gl::GLContext* gl = mContext->GL();
gl->MakeCurrent();
return gl->fGetAttribLocation(mGLName, mappedName.BeginReading());
} }
GLint GLint
@ -658,13 +721,12 @@ WebGLProgram::GetUniformBlockIndex(const nsAString& userName_wide) const
if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex)) if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex))
return LOCAL_GL_INVALID_INDEX; return LOCAL_GL_INVALID_INDEX;
RefPtr<const webgl::UniformBlockInfo> info; const webgl::UniformBlockInfo* info;
if (!LinkInfo()->FindUniformBlock(baseUserName, &info)) { if (!LinkInfo()->FindUniformBlock(baseUserName, &info)) {
return LOCAL_GL_INVALID_INDEX; return LOCAL_GL_INVALID_INDEX;
} }
const nsCString& baseMappedName = info->mBaseMappedName; nsAutoCString mappedName(info->mBaseMappedName);
nsAutoCString mappedName(baseMappedName);
if (isArray) { if (isArray) {
mappedName.AppendLiteral("["); mappedName.AppendLiteral("[");
mappedName.AppendInt(uint32_t(arrayIndex)); mappedName.AppendInt(uint32_t(arrayIndex));
@ -799,13 +861,11 @@ WebGLProgram::GetUniformLocation(const nsAString& userName_wide) const
if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex)) if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex))
return nullptr; return nullptr;
const WebGLActiveInfo* activeInfo; webgl::UniformInfo* info;
if (!LinkInfo()->FindUniform(baseUserName, &activeInfo)) if (!LinkInfo()->FindUniform(baseUserName, &info))
return nullptr; return nullptr;
const nsCString& baseMappedName = activeInfo->mBaseMappedName; nsAutoCString mappedName(info->mActiveInfo->mBaseMappedName);
nsAutoCString mappedName(baseMappedName);
if (isArray) { if (isArray) {
mappedName.AppendLiteral("["); mappedName.AppendLiteral("[");
mappedName.AppendInt(uint32_t(arrayIndex)); mappedName.AppendInt(uint32_t(arrayIndex));
@ -820,8 +880,7 @@ WebGLProgram::GetUniformLocation(const nsAString& userName_wide) const
return nullptr; return nullptr;
RefPtr<WebGLUniformLocation> locObj = new WebGLUniformLocation(mContext, LinkInfo(), RefPtr<WebGLUniformLocation> locObj = new WebGLUniformLocation(mContext, LinkInfo(),
loc, arrayIndex, info, loc, arrayIndex);
activeInfo);
return locObj.forget(); return locObj.forget();
} }
@ -846,15 +905,13 @@ WebGLProgram::GetUniformIndices(const dom::Sequence<nsString>& uniformNames,
continue; continue;
} }
const WebGLActiveInfo* activeInfo; webgl::UniformInfo* info;
if (!LinkInfo()->FindUniform(baseUserName, &activeInfo)) { if (!LinkInfo()->FindUniform(baseUserName, &info)) {
arr.AppendElement(LOCAL_GL_INVALID_INDEX); arr.AppendElement(LOCAL_GL_INVALID_INDEX);
continue; continue;
} }
const nsCString& baseMappedName = activeInfo->mBaseMappedName; nsAutoCString mappedName(info->mActiveInfo->mBaseMappedName);
nsAutoCString mappedName(baseMappedName);
if (isArray) { if (isArray) {
mappedName.AppendLiteral("["); mappedName.AppendLiteral("[");
mappedName.AppendInt(uint32_t(arrayIndex)); mappedName.AppendInt(uint32_t(arrayIndex));
@ -879,8 +936,7 @@ WebGLProgram::UniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockB
} }
const webgl::LinkedProgramInfo* linkInfo = LinkInfo(); const webgl::LinkedProgramInfo* linkInfo = LinkInfo();
GLuint uniformBlockCount = (GLuint)linkInfo->uniformBlocks.size(); if (uniformBlockIndex >= linkInfo->uniformBlocks.size()) {
if (uniformBlockIndex >= uniformBlockCount) {
mContext->ErrorInvalidValue("getActiveUniformBlockName: index %u invalid.", uniformBlockIndex); mContext->ErrorInvalidValue("getActiveUniformBlockName: index %u invalid.", uniformBlockIndex);
return; return;
} }
@ -1234,6 +1290,50 @@ WebGLProgram::FindUniformBlockByMappedName(const nsACString& mappedName,
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
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* JSObject*
WebGLProgram::WrapObject(JSContext* js, JS::Handle<JSObject*> givenProto) WebGLProgram::WrapObject(JSContext* js, JS::Handle<JSObject*> givenProto)
{ {

Просмотреть файл

@ -35,11 +35,30 @@ template<typename> class Sequence;
namespace webgl { namespace webgl {
struct UniformBlockInfo final struct AttribInfo final
: public RefCounted<UniformBlockInfo>
{ {
MOZ_DECLARE_REFCOUNTED_TYPENAME(UniformBlockInfo); const RefPtr<WebGLActiveInfo> mActiveInfo;
uint32_t mLoc;
};
struct UniformInfo final
{
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 mBaseUserName;
const nsCString mBaseMappedName; const nsCString mBaseMappedName;
@ -57,61 +76,27 @@ struct LinkedProgramInfo final
MOZ_DECLARE_REFCOUNTED_TYPENAME(LinkedProgramInfo) MOZ_DECLARE_REFCOUNTED_TYPENAME(LinkedProgramInfo)
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(LinkedProgramInfo) MOZ_DECLARE_WEAKREFERENCE_TYPENAME(LinkedProgramInfo)
//////
WebGLProgram* const prog; 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; 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. // Needed for draw call validation.
std::map<const WebGLActiveInfo*, GLuint> activeAttribLocs; std::vector<UniformInfo*> uniformSamplers;
////// //////
explicit LinkedProgramInfo(WebGLProgram* prog); explicit LinkedProgramInfo(WebGLProgram* prog);
~LinkedProgramInfo();
bool FindAttrib(const nsCString& baseUserName, bool FindAttrib(const nsCString& baseUserName, const AttribInfo** const out) const;
const WebGLActiveInfo** const out_activeInfo) const bool FindUniform(const nsCString& baseUserName, UniformInfo** const out) const;
{
auto itr = attribMap.find(baseUserName);
if (itr == attribMap.end())
return false;
*out_activeInfo = itr->second;
return true;
}
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 FindUniformBlock(const nsCString& baseUserName, bool FindUniformBlock(const nsCString& baseUserName,
RefPtr<const UniformBlockInfo>* const out_info) const const UniformBlockInfo** const out) 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;
}
}; };
} // namespace webgl } // namespace webgl

Просмотреть файл

@ -16,34 +16,32 @@ namespace mozilla {
WebGLUniformLocation::WebGLUniformLocation(WebGLContext* webgl, WebGLUniformLocation::WebGLUniformLocation(WebGLContext* webgl,
const webgl::LinkedProgramInfo* linkInfo, const webgl::LinkedProgramInfo* linkInfo,
GLuint loc, webgl::UniformInfo* info, GLuint loc,
size_t arrayIndex, size_t arrayIndex)
const WebGLActiveInfo* activeInfo)
: WebGLContextBoundObject(webgl) : WebGLContextBoundObject(webgl)
, mLinkInfo(linkInfo) , mLinkInfo(linkInfo)
, mInfo(info)
, mLoc(loc) , mLoc(loc)
, mArrayIndex(arrayIndex) , mArrayIndex(arrayIndex)
, mActiveInfo(activeInfo)
{ } { }
WebGLUniformLocation::~WebGLUniformLocation() WebGLUniformLocation::~WebGLUniformLocation()
{ } { }
bool bool
WebGLUniformLocation::ValidateForProgram(WebGLProgram* prog, WebGLContext* webgl, WebGLUniformLocation::ValidateForProgram(WebGLProgram* prog, const char* funcName) const
const char* funcName) const
{ {
// Check the weak-pointer. // Check the weak-pointer.
if (!mLinkInfo) { if (!mLinkInfo) {
webgl->ErrorInvalidOperation("%s: This uniform location is obsolete because its" mContext->ErrorInvalidOperation("%s: This uniform location is obsolete because"
" program has been successfully relinked.", " its program has been successfully relinked.",
funcName); funcName);
return false; return false;
} }
if (mLinkInfo->prog != prog) { if (mLinkInfo->prog != prog) {
webgl->ErrorInvalidOperation("%s: This uniform location corresponds to a" mContext->ErrorInvalidOperation("%s: This uniform location corresponds to a"
" different program.", funcName); " different program.", funcName);
return false; return false;
} }
@ -121,19 +119,22 @@ IsUniformSetterTypeValid(GLenum setterType, GLenum uniformType)
bool bool
WebGLUniformLocation::ValidateSizeAndType(uint8_t setterElemSize, GLenum setterType, WebGLUniformLocation::ValidateSizeAndType(uint8_t setterElemSize, GLenum setterType,
WebGLContext* webgl, const char* funcName) const const char* funcName) const
{ {
MOZ_ASSERT(mLinkInfo); MOZ_ASSERT(mLinkInfo);
if (setterElemSize != mActiveInfo->mElemSize) { const auto& uniformElemSize = mInfo->mActiveInfo->mElemSize;
webgl->ErrorInvalidOperation("%s: Bad uniform size: %i", funcName, if (setterElemSize != uniformElemSize) {
mActiveInfo->mElemSize); mContext->ErrorInvalidOperation("%s: Function used differs from uniform size: %i",
funcName, uniformElemSize);
return false; return false;
} }
if (!IsUniformSetterTypeValid(setterType, mActiveInfo->mElemType)) { const auto& uniformElemType = mInfo->mActiveInfo->mElemType;
webgl->ErrorInvalidOperation("%s: Bad uniform type: %i", funcName, if (!IsUniformSetterTypeValid(setterType, uniformElemType)) {
mActiveInfo->mElemSize); mContext->ErrorInvalidOperation("%s: Function used is incompatible with uniform"
" type: %i",
funcName, uniformElemType);
return false; return false;
} }
@ -142,16 +143,16 @@ WebGLUniformLocation::ValidateSizeAndType(uint8_t setterElemSize, GLenum setterT
bool bool
WebGLUniformLocation::ValidateArrayLength(uint8_t setterElemSize, size_t setterArraySize, WebGLUniformLocation::ValidateArrayLength(uint8_t setterElemSize, size_t setterArraySize,
WebGLContext* webgl, const char* funcName) const const char* funcName) const
{ {
MOZ_ASSERT(mLinkInfo); MOZ_ASSERT(mLinkInfo);
if (setterArraySize == 0 || if (setterArraySize == 0 ||
setterArraySize % setterElemSize) setterArraySize % setterElemSize)
{ {
webgl->ErrorInvalidValue("%s: expected an array of length a multiple of" mContext->ErrorInvalidValue("%s: Expected an array of length a multiple of %d,"
" %d, got an array of length %d.", " got an array of length %d.",
funcName, setterElemSize, setterArraySize); funcName, setterElemSize, setterArraySize);
return false; return false;
} }
@ -162,55 +163,34 @@ WebGLUniformLocation::ValidateArrayLength(uint8_t setterElemSize, size_t setterA
* highest array element index used, as reported by `GetActiveUniform`, will be * highest array element index used, as reported by `GetActiveUniform`, will be
* ignored by GL. * ignored by GL.
*/ */
if (!mActiveInfo->mIsArray && if (!mInfo->mActiveInfo->mIsArray &&
setterArraySize != setterElemSize) setterArraySize != setterElemSize)
{ {
webgl->ErrorInvalidOperation("%s: expected an array of length exactly %d" mContext->ErrorInvalidOperation("%s: Expected an array of length exactly %d"
" (since this uniform is not an array" " (since this uniform is not an array uniform),"
" uniform), got an array of length %d.", " got an array of length %d.",
funcName, setterElemSize, setterArraySize); funcName, setterElemSize, setterArraySize);
return false; return false;
} }
return true; return true;
} }
bool
WebGLUniformLocation::ValidateSamplerSetter(GLint value, WebGLContext* webgl,
const char* funcName) 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 JS::Value
WebGLUniformLocation::GetUniform(JSContext* js, WebGLContext* webgl) const WebGLUniformLocation::GetUniform(JSContext* js) const
{ {
MOZ_ASSERT(mLinkInfo); MOZ_ASSERT(mLinkInfo);
uint8_t elemSize = mActiveInfo->mElemSize; const uint8_t elemSize = mInfo->mActiveInfo->mElemSize;
static const uint8_t kMaxElemSize = 16; static const uint8_t kMaxElemSize = 16;
MOZ_ASSERT(elemSize <= kMaxElemSize); MOZ_ASSERT(elemSize <= kMaxElemSize);
GLuint prog = mLinkInfo->prog->mGLName; GLuint prog = mLinkInfo->prog->mGLName;
gl::GLContext* gl = webgl->GL(); gl::GLContext* gl = mContext->GL();
gl->MakeCurrent(); gl->MakeCurrent();
switch (mActiveInfo->mElemType) { switch (mInfo->mActiveInfo->mElemType) {
case LOCAL_GL_INT: case LOCAL_GL_INT:
case LOCAL_GL_INT_VEC2: case LOCAL_GL_INT_VEC2:
case LOCAL_GL_INT_VEC3: case LOCAL_GL_INT_VEC3:
@ -237,9 +217,9 @@ WebGLUniformLocation::GetUniform(JSContext* js, WebGLContext* webgl) const
if (elemSize == 1) if (elemSize == 1)
return JS::Int32Value(buffer[0]); 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) { if (!obj) {
webgl->ErrorOutOfMemory("getUniform: out of memory"); mContext->ErrorOutOfMemory("getUniform: Out of memory.");
return JS::NullValue(); return JS::NullValue();
} }
return JS::ObjectOrNullValue(obj); return JS::ObjectOrNullValue(obj);
@ -263,7 +243,7 @@ WebGLUniformLocation::GetUniform(JSContext* js, WebGLContext* webgl) const
JS::RootedValue val(js); JS::RootedValue val(js);
// Be careful: we don't want to convert all of |uv|! // Be careful: we don't want to convert all of |uv|!
if (!dom::ToJSValue(js, boolBuffer, elemSize, &val)) { if (!dom::ToJSValue(js, boolBuffer, elemSize, &val)) {
webgl->ErrorOutOfMemory("getUniform: out of memory"); mContext->ErrorOutOfMemory("getUniform: Out of memory.");
return JS::NullValue(); return JS::NullValue();
} }
return val; return val;
@ -289,9 +269,9 @@ WebGLUniformLocation::GetUniform(JSContext* js, WebGLContext* webgl) const
if (elemSize == 1) if (elemSize == 1)
return JS::DoubleValue(buffer[0]); 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) { if (!obj) {
webgl->ErrorOutOfMemory("getUniform: out of memory"); mContext->ErrorOutOfMemory("getUniform: Out of memory.");
return JS::NullValue(); return JS::NullValue();
} }
return JS::ObjectOrNullValue(obj); return JS::ObjectOrNullValue(obj);
@ -308,9 +288,9 @@ WebGLUniformLocation::GetUniform(JSContext* js, WebGLContext* webgl) const
if (elemSize == 1) if (elemSize == 1)
return JS::DoubleValue(buffer[0]); // This is Double because only Int32 is special cased. 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) { if (!obj) {
webgl->ErrorOutOfMemory("getUniform: out of memory"); mContext->ErrorOutOfMemory("getUniform: Out of memory.");
return JS::NullValue(); return JS::NullValue();
} }
return JS::ObjectOrNullValue(obj); return JS::ObjectOrNullValue(obj);

Просмотреть файл

@ -39,24 +39,25 @@ public:
return mContext; return mContext;
} }
//////
const WeakPtr<const webgl::LinkedProgramInfo> mLinkInfo; const WeakPtr<const webgl::LinkedProgramInfo> mLinkInfo;
webgl::UniformInfo* const mInfo;
const GLuint mLoc; const GLuint mLoc;
const size_t mArrayIndex; const size_t mArrayIndex;
const WebGLActiveInfo* const mActiveInfo;
//////
WebGLUniformLocation(WebGLContext* webgl, const webgl::LinkedProgramInfo* linkInfo, 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, bool ValidateForProgram(WebGLProgram* prog, const char* funcName) const;
const char* funcName) const;
bool ValidateSamplerSetter(GLint value, WebGLContext* webgl,
const char* funcName) const;
bool ValidateSizeAndType(uint8_t setterElemSize, GLenum setterType, 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, 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. // Needed for certain helper functions like ValidateObject.
// `WebGLUniformLocation`s can't be 'Deleted' in the WebGL sense. // `WebGLUniformLocation`s can't be 'Deleted' in the WebGL sense.