зеркало из https://github.com/mozilla/pjs.git
Bug 676071 - use ANGLE long identifier mapping - r=jgilbert
This also fixes the leak reported in bug 723261, and makes us avoid generating the shader translator output when we don't use it (on Android).
This commit is contained in:
Родитель
0a59450680
Коммит
dd24afa5ec
|
@ -63,6 +63,7 @@
|
|||
#include "Layers.h"
|
||||
|
||||
#include "CheckedInt.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#include "ForceDiscreteGPUHelperCGL.h"
|
||||
|
@ -1627,16 +1628,25 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
struct WebGLMappedIdentifier {
|
||||
nsCString original, mapped; // ASCII strings
|
||||
WebGLMappedIdentifier(const nsACString& o, const nsACString& m) : original(o), mapped(m) {}
|
||||
};
|
||||
|
||||
class WebGLShader MOZ_FINAL
|
||||
: public nsIWebGLShader
|
||||
, public WebGLRefCountedObject<WebGLShader>
|
||||
, public WebGLContextBoundObject
|
||||
{
|
||||
friend class WebGLContext;
|
||||
friend class WebGLProgram;
|
||||
|
||||
public:
|
||||
WebGLShader(WebGLContext *context, WebGLenum stype)
|
||||
: WebGLContextBoundObject(context)
|
||||
, mType(stype)
|
||||
, mNeedsTranslation(true)
|
||||
, mAttribMaxNameLength(0)
|
||||
{
|
||||
mContext->MakeContextCurrent();
|
||||
mGLName = mContext->gl->fCreateShader(mType);
|
||||
|
@ -1693,11 +1703,45 @@ protected:
|
|||
WebGLuint mGLName;
|
||||
WebGLenum mType;
|
||||
nsString mSource;
|
||||
nsCString mTranslationLog;
|
||||
nsCString mTranslationLog; // The translation log should contain only ASCII characters
|
||||
bool mNeedsTranslation;
|
||||
WebGLMonotonicHandle mMonotonicHandle;
|
||||
nsTArray<WebGLMappedIdentifier> mAttributes;
|
||||
nsTArray<WebGLMappedIdentifier> mUniforms;
|
||||
int mAttribMaxNameLength;
|
||||
};
|
||||
|
||||
/** Takes an ASCII string like "foo[i]", turns it into "foo" and returns "[i]" in bracketPart
|
||||
*
|
||||
* \param string input/output: the string to split, becomes the string without the bracket part
|
||||
* \param bracketPart output: gets the bracket part.
|
||||
*
|
||||
* Notice that if there are multiple brackets like "foo[i].bar[j]", only the last bracket is split.
|
||||
*/
|
||||
static bool SplitLastSquareBracket(nsACString& string, nsCString& bracketPart)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(bracketPart.Length() == 0, "SplitLastSquareBracket must be called with empty bracketPart string");
|
||||
char *string_start = string.BeginWriting();
|
||||
char *s = string_start + string.Length() - 1;
|
||||
|
||||
if (*s != ']')
|
||||
return false;
|
||||
|
||||
while (*s != '[' && s != string_start)
|
||||
s--;
|
||||
|
||||
if (*s != '[')
|
||||
return false;
|
||||
|
||||
bracketPart.Assign(s);
|
||||
*s = 0;
|
||||
string.EndWriting();
|
||||
string.SetLength(s - string_start);
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef nsDataHashtable<nsCStringHashKey, nsCString> CStringHash;
|
||||
|
||||
class WebGLProgram MOZ_FINAL
|
||||
: public nsIWebGLProgram
|
||||
, public WebGLRefCountedObject<WebGLProgram>
|
||||
|
@ -1708,10 +1752,7 @@ public:
|
|||
: WebGLContextBoundObject(context)
|
||||
, mLinkStatus(false)
|
||||
, mGeneration(0)
|
||||
, mUniformMaxNameLength(0)
|
||||
, mAttribMaxNameLength(0)
|
||||
, mUniformCount(0)
|
||||
, mAttribCount(0)
|
||||
{
|
||||
mContext->MakeContextCurrent();
|
||||
mGLName = mContext->gl->fCreateProgram();
|
||||
|
@ -1790,15 +1831,107 @@ public:
|
|||
}
|
||||
|
||||
/* Called only after LinkProgram */
|
||||
bool UpdateInfo(gl::GLContext *gl);
|
||||
bool UpdateInfo();
|
||||
|
||||
/* Getters for cached program info */
|
||||
WebGLint UniformMaxNameLength() const { return mUniformMaxNameLength; }
|
||||
WebGLint AttribMaxNameLength() const { return mAttribMaxNameLength; }
|
||||
WebGLint UniformCount() const { return mUniformCount; }
|
||||
WebGLint AttribCount() const { return mAttribCount; }
|
||||
bool IsAttribInUse(unsigned i) const { return mAttribsInUse[i]; }
|
||||
|
||||
/* Maps identifier |name| to the mapped identifier |*mappedName|
|
||||
* Both are ASCII strings.
|
||||
*/
|
||||
void MapIdentifier(const nsACString& name, nsCString *mappedName) {
|
||||
if (!mIdentifierMap) {
|
||||
// if the identifier map doesn't exist yet, build it now
|
||||
mIdentifierMap = new CStringHash;
|
||||
mIdentifierMap->Init();
|
||||
for (size_t i = 0; i < mAttachedShaders.Length(); i++) {
|
||||
for (size_t j = 0; j < mAttachedShaders[i]->mAttributes.Length(); j++) {
|
||||
const WebGLMappedIdentifier& attrib = mAttachedShaders[i]->mAttributes[j];
|
||||
mIdentifierMap->Put(attrib.original, attrib.mapped);
|
||||
}
|
||||
for (size_t j = 0; j < mAttachedShaders[i]->mUniforms.Length(); j++) {
|
||||
const WebGLMappedIdentifier& uniform = mAttachedShaders[i]->mUniforms[j];
|
||||
mIdentifierMap->Put(uniform.original, uniform.mapped);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCString mutableName(name);
|
||||
nsCString bracketPart;
|
||||
bool hadBracketPart = SplitLastSquareBracket(mutableName, bracketPart);
|
||||
if (hadBracketPart)
|
||||
mutableName.AppendLiteral("[0]");
|
||||
|
||||
if (mIdentifierMap->Get(mutableName, mappedName)) {
|
||||
if (hadBracketPart) {
|
||||
nsCString mappedBracketPart;
|
||||
bool mappedHadBracketPart = SplitLastSquareBracket(*mappedName, mappedBracketPart);
|
||||
if (mappedHadBracketPart)
|
||||
mappedName->Append(bracketPart);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// not found? We might be in the situation we have a uniform array name and the GL's glGetActiveUniform
|
||||
// returned its name without [0], as is allowed by desktop GL but not in ES. Let's then try with [0].
|
||||
mutableName.AppendLiteral("[0]");
|
||||
if (mIdentifierMap->Get(mutableName, mappedName))
|
||||
return;
|
||||
|
||||
// not found? return name unchanged. This case happens e.g. on bad user input, or when
|
||||
// we're not using identifier mapping, or if we didn't store an identifier in the map because
|
||||
// e.g. its mapping is trivial (as happens for short identifiers)
|
||||
mappedName->Assign(name);
|
||||
}
|
||||
|
||||
/* Un-maps mapped identifier |name| to the original identifier |*reverseMappedName|
|
||||
* Both are ASCII strings.
|
||||
*/
|
||||
void ReverseMapIdentifier(const nsACString& name, nsCString *reverseMappedName) {
|
||||
if (!mIdentifierReverseMap) {
|
||||
// if the identifier reverse map doesn't exist yet, build it now
|
||||
mIdentifierReverseMap = new CStringHash;
|
||||
mIdentifierReverseMap->Init();
|
||||
for (size_t i = 0; i < mAttachedShaders.Length(); i++) {
|
||||
for (size_t j = 0; j < mAttachedShaders[i]->mAttributes.Length(); j++) {
|
||||
const WebGLMappedIdentifier& attrib = mAttachedShaders[i]->mAttributes[j];
|
||||
mIdentifierReverseMap->Put(attrib.mapped, attrib.original);
|
||||
}
|
||||
for (size_t j = 0; j < mAttachedShaders[i]->mUniforms.Length(); j++) {
|
||||
const WebGLMappedIdentifier& uniform = mAttachedShaders[i]->mUniforms[j];
|
||||
mIdentifierReverseMap->Put(uniform.mapped, uniform.original);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCString mutableName(name);
|
||||
nsCString bracketPart;
|
||||
bool hadBracketPart = SplitLastSquareBracket(mutableName, bracketPart);
|
||||
if (hadBracketPart)
|
||||
mutableName.AppendLiteral("[0]");
|
||||
|
||||
if (mIdentifierReverseMap->Get(mutableName, reverseMappedName)) {
|
||||
if (hadBracketPart) {
|
||||
nsCString reverseMappedBracketPart;
|
||||
bool reverseMappedHadBracketPart = SplitLastSquareBracket(*reverseMappedName, reverseMappedBracketPart);
|
||||
if (reverseMappedHadBracketPart)
|
||||
reverseMappedName->Append(bracketPart);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// not found? We might be in the situation we have a uniform array name and the GL's glGetActiveUniform
|
||||
// returned its name without [0], as is allowed by desktop GL but not in ES. Let's then try with [0].
|
||||
mutableName.AppendLiteral("[0]");
|
||||
if (mIdentifierReverseMap->Get(mutableName, reverseMappedName))
|
||||
return;
|
||||
|
||||
// not found? return name unchanged. This case happens e.g. on bad user input, or when
|
||||
// we're not using identifier mapping, or if we didn't store an identifier in the map because
|
||||
// e.g. its mapping is trivial (as happens for short identifiers)
|
||||
reverseMappedName->Assign(name);
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWEBGLPROGRAM
|
||||
|
||||
|
@ -1811,13 +1944,10 @@ protected:
|
|||
CheckedUint32 mGeneration;
|
||||
|
||||
// post-link data
|
||||
|
||||
GLint mUniformMaxNameLength;
|
||||
GLint mAttribMaxNameLength;
|
||||
GLint mUniformCount;
|
||||
GLint mAttribCount;
|
||||
std::vector<bool> mAttribsInUse;
|
||||
WebGLMonotonicHandle mMonotonicHandle;
|
||||
nsAutoPtr<CStringHash> mIdentifierMap, mIdentifierReverseMap;
|
||||
int mAttribMaxNameLength;
|
||||
};
|
||||
|
||||
class WebGLRenderbuffer MOZ_FINAL
|
||||
|
@ -2366,12 +2496,11 @@ class WebGLActiveInfo MOZ_FINAL
|
|||
: public nsIWebGLActiveInfo
|
||||
{
|
||||
public:
|
||||
WebGLActiveInfo(WebGLint size, WebGLenum type, const char *nameptr, PRUint32 namelength) :
|
||||
WebGLActiveInfo(WebGLint size, WebGLenum type, const nsACString& name) :
|
||||
mSize(size),
|
||||
mType(type)
|
||||
{
|
||||
mName.AssignASCII(nameptr, namelength);
|
||||
}
|
||||
mType(type),
|
||||
mName(NS_ConvertASCIItoUTF16(name))
|
||||
{}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWEBGLACTIVEINFO
|
||||
|
|
|
@ -121,7 +121,6 @@ NS_IMETHODIMP WebGLContext::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) { \
|
|||
MakeContextCurrent(); gl->f##glname(a1,a2,a3,a4,a5,a6); return NS_OK; \
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// WebGL API
|
||||
//
|
||||
|
@ -181,7 +180,8 @@ WebGLContext::BindAttribLocation(nsIWebGLProgram *pobj, WebGLuint location, cons
|
|||
return NS_OK;
|
||||
|
||||
WebGLuint progname;
|
||||
if (!GetGLName<WebGLProgram>("bindAttribLocation: program", pobj, &progname))
|
||||
WebGLProgram *prog;
|
||||
if (!GetConcreteObjectAndGLName("bindAttribLocation: program", pobj, &prog, &progname))
|
||||
return NS_OK;
|
||||
|
||||
if (!ValidateGLSLVariableName(name, "bindAttribLocation"))
|
||||
|
@ -190,10 +190,12 @@ WebGLContext::BindAttribLocation(nsIWebGLProgram *pobj, WebGLuint location, cons
|
|||
if (!ValidateAttribIndex(location, "bindAttribLocation"))
|
||||
return NS_OK;
|
||||
|
||||
NS_LossyConvertUTF16toASCII cname(name);
|
||||
nsCString mappedName;
|
||||
prog->MapIdentifier(cname, &mappedName);
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
gl->fBindAttribLocation(progname, location, NS_LossyConvertUTF16toASCII(name).get());
|
||||
|
||||
gl->fBindAttribLocation(progname, location, mappedName.get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1852,7 +1854,8 @@ WebGLContext::GetActiveAttrib(nsIWebGLProgram *pobj, PRUint32 index, nsIWebGLAct
|
|||
*retval = nsnull;
|
||||
|
||||
WebGLuint progname;
|
||||
if (!GetGLName<WebGLProgram>("getActiveAttrib: program", pobj, &progname))
|
||||
WebGLProgram *prog;
|
||||
if (!GetConcreteObjectAndGLName("getActiveAttrib: program", pobj, &prog, &progname))
|
||||
return NS_OK;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
@ -1872,7 +1875,10 @@ WebGLContext::GetActiveAttrib(nsIWebGLProgram *pobj, PRUint32 index, nsIWebGLAct
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
WebGLActiveInfo *retActiveInfo = new WebGLActiveInfo(attrsize, attrtype, name.get(), len);
|
||||
nsCString reverseMappedName;
|
||||
prog->ReverseMapIdentifier(nsDependentCString(name), &reverseMappedName);
|
||||
|
||||
WebGLActiveInfo *retActiveInfo = new WebGLActiveInfo(attrsize, attrtype, reverseMappedName);
|
||||
NS_ADDREF(*retval = retActiveInfo);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1916,7 +1922,8 @@ WebGLContext::GetActiveUniform(nsIWebGLProgram *pobj, PRUint32 index, nsIWebGLAc
|
|||
*retval = nsnull;
|
||||
|
||||
WebGLuint progname;
|
||||
if (!GetGLName<WebGLProgram>("getActiveUniform: program", pobj, &progname))
|
||||
WebGLProgram *prog;
|
||||
if (!GetConcreteObjectAndGLName("getActiveUniform: program", pobj, &prog, &progname))
|
||||
return NS_OK;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
@ -1926,17 +1933,20 @@ WebGLContext::GetActiveUniform(nsIWebGLProgram *pobj, PRUint32 index, nsIWebGLAc
|
|||
if (len == 0)
|
||||
*retval = nsnull;
|
||||
|
||||
nsAutoArrayPtr<char> name(new char[len + 3]); // +3 because we might have to append "[0]", see below
|
||||
nsAutoArrayPtr<char> name(new char[len]);
|
||||
|
||||
GLint attrsize = 0;
|
||||
GLuint attrtype = 0;
|
||||
GLint usize = 0;
|
||||
GLuint utype = 0;
|
||||
|
||||
gl->fGetActiveUniform(progname, index, len, &len, &attrsize, &attrtype, name);
|
||||
if (len == 0 || attrsize == 0 || attrtype == 0) {
|
||||
gl->fGetActiveUniform(progname, index, len, &len, &usize, &utype, name);
|
||||
if (len == 0 || usize == 0 || utype == 0) {
|
||||
*retval = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCString reverseMappedName;
|
||||
prog->ReverseMapIdentifier(nsDependentCString(name), &reverseMappedName);
|
||||
|
||||
// OpenGL ES 2.0 specifies that if foo is a uniform array, GetActiveUniform returns its name as "foo[0]".
|
||||
// See section 2.10 page 35 in the OpenGL ES 2.0.24 specification:
|
||||
//
|
||||
|
@ -1950,16 +1960,11 @@ WebGLContext::GetActiveUniform(nsIWebGLProgram *pobj, PRUint32 index, nsIWebGLAc
|
|||
// In principle we don't need to do that on OpenGL ES, but this is such a tricky difference between the ES and non-ES
|
||||
// specs that it seems probable that some ES implementers will overlook it. Since the work-around is quite cheap,
|
||||
// we do it unconditionally.
|
||||
if (attrsize > 1 && name[len-1] != ']') {
|
||||
name[len++] = '[';
|
||||
name[len++] = '0';
|
||||
name[len++] = ']';
|
||||
}
|
||||
|
||||
WebGLActiveInfo *retActiveInfo = new WebGLActiveInfo(attrsize, attrtype, name.get(), len);
|
||||
if (usize > 1 && reverseMappedName.CharAt(reverseMappedName.Length()-1) != ']')
|
||||
reverseMappedName.AppendLiteral("[0]");
|
||||
|
||||
WebGLActiveInfo *retActiveInfo = new WebGLActiveInfo(usize, utype, reverseMappedName);
|
||||
NS_ADDREF(*retval = retActiveInfo);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2009,23 +2014,25 @@ WebGLContext::GetAttribLocation(nsIWebGLProgram *pobj,
|
|||
const nsAString& name,
|
||||
PRInt32 *retval)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
{
|
||||
*retval = -1;
|
||||
return NS_OK;
|
||||
}
|
||||
*retval = -1;
|
||||
|
||||
*retval = 0;
|
||||
if (!IsContextStable())
|
||||
return NS_OK;
|
||||
|
||||
WebGLuint progname;
|
||||
if (!GetGLName<WebGLProgram>("getAttribLocation: program", pobj, &progname))
|
||||
WebGLProgram *prog;
|
||||
if (!GetConcreteObjectAndGLName("getAttribLocation: program", pobj, &prog, &progname))
|
||||
return NS_OK;
|
||||
|
||||
if (!ValidateGLSLVariableName(name, "getAttribLocation"))
|
||||
return NS_OK;
|
||||
|
||||
NS_LossyConvertUTF16toASCII cname(name);
|
||||
nsCString mappedName;
|
||||
prog->MapIdentifier(cname, &mappedName);
|
||||
|
||||
MakeContextCurrent();
|
||||
*retval = gl->fGetAttribLocation(progname, NS_LossyConvertUTF16toASCII(name).get());
|
||||
*retval = gl->fGetAttribLocation(progname, mappedName.get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2980,11 +2987,14 @@ WebGLContext::GetUniformLocation(nsIWebGLProgram *pobj, const nsAString& name, n
|
|||
return NS_OK;
|
||||
|
||||
if (!ValidateGLSLVariableName(name, "getUniformLocation"))
|
||||
return NS_OK;
|
||||
return NS_OK;
|
||||
|
||||
NS_LossyConvertUTF16toASCII cname(name);
|
||||
nsCString mappedName;
|
||||
prog->MapIdentifier(cname, &mappedName);
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
GLint intlocation = gl->fGetUniformLocation(progname, NS_LossyConvertUTF16toASCII(name).get());
|
||||
GLint intlocation = gl->fGetUniformLocation(progname, mappedName.get());
|
||||
|
||||
WebGLUniformLocation *loc = nsnull;
|
||||
if (intlocation >= 0)
|
||||
|
@ -3251,18 +3261,16 @@ WebGLContext::LinkProgram(nsIWebGLProgram *pobj)
|
|||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
gl->fLinkProgram(progname);
|
||||
|
||||
GLint ok;
|
||||
gl->fGetProgramiv(progname, LOCAL_GL_LINK_STATUS, &ok);
|
||||
if (ok) {
|
||||
program->SetLinkStatus(true);
|
||||
program->UpdateInfo(gl);
|
||||
bool updateInfoSucceeded = program->UpdateInfo();
|
||||
program->SetLinkStatus(updateInfoSucceeded);
|
||||
} else {
|
||||
program->SetLinkStatus(false);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -4387,6 +4395,20 @@ WebGLContext::CompileShader(nsIWebGLShader *sobj)
|
|||
|
||||
MakeContextCurrent();
|
||||
|
||||
ShShaderOutput targetShaderSourceLanguage = gl->IsGLES2() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT;
|
||||
bool useShaderSourceTranslation = true;
|
||||
|
||||
#ifdef ANDROID
|
||||
// see bug 709947. On Android, we can't use the ESSL backend because of strange crashes (might be
|
||||
// an allocator mismatch). So we use the GLSL backend, and discard the output, instead just passing
|
||||
// the original WebGL shader source to the GL (since that's ESSL already). The problem is that means
|
||||
// we can't use shader translations on Android, in particular we can't use long identifier shortening,
|
||||
// which means we can't reach 100% conformance. We need to fix that by debugging the ESSL backend
|
||||
// memory crashes.
|
||||
targetShaderSourceLanguage = SH_GLSL_OUTPUT;
|
||||
useShaderSourceTranslation = false;
|
||||
#endif
|
||||
|
||||
#if defined(USE_ANGLE)
|
||||
if (shader->NeedsTranslation() && mShaderValidation) {
|
||||
ShHandle compiler = 0;
|
||||
|
@ -4404,20 +4426,6 @@ WebGLContext::CompileShader(nsIWebGLShader *sobj)
|
|||
if (mEnabledExtensions[WebGL_OES_standard_derivatives])
|
||||
resources.OES_standard_derivatives = 1;
|
||||
|
||||
// notice that on Android, we always use SH_GLSL_OUTPUT, we never use the ESSL backend.
|
||||
// see bug 709947, the reason is that 1) we dont really need a ESSL backend since the
|
||||
// source is already ESSL, and 2) we ran into massive Android crashes when we used the ESSL backend.
|
||||
// But if we wanted to use shader transformations on ES platforms, we would have to use the
|
||||
// ESSL backend
|
||||
compiler = ShConstructCompiler((ShShaderType) shader->ShaderType(),
|
||||
SH_WEBGL_SPEC,
|
||||
#ifdef ANDROID
|
||||
SH_GLSL_OUTPUT,
|
||||
#else
|
||||
gl->IsGLES2() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT,
|
||||
#endif
|
||||
&resources);
|
||||
|
||||
// We're storing an actual instance of StripComments because, if we don't, the
|
||||
// cleanSource nsAString instance will be destroyed before the reference is
|
||||
// actually used.
|
||||
|
@ -4431,20 +4439,29 @@ WebGLContext::CompileShader(nsIWebGLShader *sobj)
|
|||
// shaderSource() already checks that the source stripped of comments is in the
|
||||
// 7-bit ASCII range, so we can skip the NS_IsAscii() check.
|
||||
const nsCString& sourceCString = NS_LossyConvertUTF16toASCII(flatSource);
|
||||
|
||||
|
||||
const PRUint32 maxSourceLength = (PRUint32(1)<<18) - 1;
|
||||
if (sourceCString.Length() > maxSourceLength)
|
||||
return ErrorInvalidValue("compileShader: source has more than %d characters", maxSourceLength);
|
||||
|
||||
const char *s = sourceCString.get();
|
||||
|
||||
int compileOptions = SH_OBJECT_CODE;
|
||||
|
||||
|
||||
compiler = ShConstructCompiler((ShShaderType) shader->ShaderType(),
|
||||
SH_WEBGL_SPEC,
|
||||
targetShaderSourceLanguage,
|
||||
&resources);
|
||||
|
||||
int compileOptions = 0;
|
||||
if (useShaderSourceTranslation) {
|
||||
compileOptions |= SH_OBJECT_CODE
|
||||
| SH_MAP_LONG_VARIABLE_NAMES
|
||||
| SH_ATTRIBUTES_UNIFORMS;
|
||||
#ifdef XP_MACOSX
|
||||
// work around bug 665578
|
||||
if (!nsCocoaFeatures::OnLionOrLater() && gl->Vendor() == gl::GLContext::VendorATI)
|
||||
compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS;
|
||||
// work around bug 665578
|
||||
if (!nsCocoaFeatures::OnLionOrLater() && gl->Vendor() == gl::GLContext::VendorATI)
|
||||
compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!ShCompile(compiler, &s, 1, compileOptions)) {
|
||||
int len = 0;
|
||||
|
@ -4462,11 +4479,50 @@ WebGLContext::CompileShader(nsIWebGLShader *sobj)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* If the GL context is really GLES2, we want to use the original provided code,
|
||||
* since it's actually GLES2. We still need to validate it however, which is
|
||||
* why we ran it through the above, but we don't want the desktop GLSL.
|
||||
*/
|
||||
if (!gl->IsGLES2()) {
|
||||
int num_attributes = 0;
|
||||
ShGetInfo(compiler, SH_ACTIVE_ATTRIBUTES, &num_attributes);
|
||||
int num_uniforms = 0;
|
||||
ShGetInfo(compiler, SH_ACTIVE_UNIFORMS, &num_uniforms);
|
||||
int attrib_max_length = 0;
|
||||
ShGetInfo(compiler, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &attrib_max_length);
|
||||
int uniform_max_length = 0;
|
||||
ShGetInfo(compiler, SH_ACTIVE_UNIFORM_MAX_LENGTH, &uniform_max_length);
|
||||
int mapped_max_length = 0;
|
||||
ShGetInfo(compiler, SH_MAPPED_NAME_MAX_LENGTH, &mapped_max_length);
|
||||
|
||||
shader->mAttribMaxNameLength = attrib_max_length;
|
||||
|
||||
shader->mAttributes.Clear();
|
||||
shader->mUniforms.Clear();
|
||||
nsAutoArrayPtr<char> attribute_name(new char[attrib_max_length+1]);
|
||||
nsAutoArrayPtr<char> uniform_name(new char[uniform_max_length+1]);
|
||||
nsAutoArrayPtr<char> mapped_name(new char[mapped_max_length+1]);
|
||||
|
||||
if (useShaderSourceTranslation) {
|
||||
for (int i = 0; i < num_attributes; i++) {
|
||||
int length, size;
|
||||
ShDataType type;
|
||||
ShGetActiveAttrib(compiler, i,
|
||||
&length, &size, &type,
|
||||
attribute_name,
|
||||
mapped_name);
|
||||
shader->mAttributes.AppendElement(WebGLMappedIdentifier(
|
||||
nsDependentCString(attribute_name),
|
||||
nsDependentCString(mapped_name)));
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_uniforms; i++) {
|
||||
int length, size;
|
||||
ShDataType type;
|
||||
ShGetActiveUniform(compiler, i,
|
||||
&length, &size, &type,
|
||||
uniform_name,
|
||||
mapped_name);
|
||||
shader->mUniforms.AppendElement(WebGLMappedIdentifier(
|
||||
nsDependentCString(uniform_name),
|
||||
nsDependentCString(mapped_name)));
|
||||
}
|
||||
|
||||
int len = 0;
|
||||
ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &len);
|
||||
|
||||
|
@ -4478,7 +4534,10 @@ WebGLContext::CompileShader(nsIWebGLShader *sobj)
|
|||
const char *ts = translatedSrc2.get();
|
||||
|
||||
gl->fShaderSource(shadername, 1, &ts, NULL);
|
||||
} else {
|
||||
} else { // not useShaderSourceTranslation
|
||||
// we just pass the raw untranslated shader source. We then can't use ANGLE idenfier mapping.
|
||||
// that's really bad, as that means we can't be 100% conformant. We should work towards always
|
||||
// using ANGLE identifier mapping.
|
||||
gl->fShaderSource(shadername, 1, &s, NULL);
|
||||
}
|
||||
|
||||
|
|
|
@ -49,38 +49,46 @@
|
|||
#include "angle/ShaderLang.h"
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
/*
|
||||
* Pull all the data out of the program that will be used by validate later on
|
||||
* Pull data out of the program, post-linking
|
||||
*/
|
||||
bool
|
||||
WebGLProgram::UpdateInfo(gl::GLContext *gl)
|
||||
WebGLProgram::UpdateInfo()
|
||||
{
|
||||
gl->fGetProgramiv(mGLName, LOCAL_GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &mAttribMaxNameLength);
|
||||
gl->fGetProgramiv(mGLName, LOCAL_GL_ACTIVE_UNIFORM_MAX_LENGTH, &mUniformMaxNameLength);
|
||||
gl->fGetProgramiv(mGLName, LOCAL_GL_ACTIVE_UNIFORMS, &mUniformCount);
|
||||
gl->fGetProgramiv(mGLName, LOCAL_GL_ACTIVE_ATTRIBUTES, &mAttribCount);
|
||||
mIdentifierMap = nsnull;
|
||||
mIdentifierReverseMap = nsnull;
|
||||
|
||||
GLint numVertexAttribs;
|
||||
if (mContext->MinCapabilityMode()) {
|
||||
numVertexAttribs = MINVALUE_GL_MAX_VERTEX_ATTRIBS;
|
||||
} else {
|
||||
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &numVertexAttribs);
|
||||
}
|
||||
mAttribsInUse.clear();
|
||||
mAttribsInUse.resize(numVertexAttribs);
|
||||
mAttribMaxNameLength = 0;
|
||||
|
||||
for (size_t i = 0; i < mAttachedShaders.Length(); i++)
|
||||
mAttribMaxNameLength = NS_MAX(mAttribMaxNameLength, mAttachedShaders[i]->mAttribMaxNameLength);
|
||||
|
||||
GLint attribCount;
|
||||
mContext->gl->fGetProgramiv(mGLName, LOCAL_GL_ACTIVE_ATTRIBUTES, &attribCount);
|
||||
|
||||
mAttribsInUse.resize(mContext->mGLMaxVertexAttribs);
|
||||
std::fill(mAttribsInUse.begin(), mAttribsInUse.end(), false);
|
||||
|
||||
nsAutoArrayPtr<char> nameBuf(new char[mAttribMaxNameLength]);
|
||||
|
||||
for (int i = 0; i < mAttribCount; ++i) {
|
||||
for (int i = 0; i < attribCount; ++i) {
|
||||
GLint attrnamelen;
|
||||
GLint attrsize;
|
||||
GLenum attrtype;
|
||||
gl->fGetActiveAttrib(mGLName, i, mAttribMaxNameLength, &attrnamelen, &attrsize, &attrtype, nameBuf);
|
||||
mContext->gl->fGetActiveAttrib(mGLName, i, mAttribMaxNameLength, &attrnamelen, &attrsize, &attrtype, nameBuf);
|
||||
if (attrnamelen > 0) {
|
||||
GLint loc = gl->fGetAttribLocation(mGLName, nameBuf);
|
||||
mAttribsInUse[loc] = true;
|
||||
GLint loc = mContext->gl->fGetAttribLocation(mGLName, nameBuf);
|
||||
NS_ABORT_IF_FALSE(loc >= 0, "major oops in managing the attributes of a WebGL program");
|
||||
if (loc < mContext->mGLMaxVertexAttribs) {
|
||||
mAttribsInUse[loc] = true;
|
||||
} else {
|
||||
mContext->ErrorInvalidOperation("program exceeds MAX_VERTEX_ATTRIBS");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,7 +342,7 @@ bool WebGLContext::ValidateDrawModeEnum(WebGLenum mode, const char *info)
|
|||
|
||||
bool WebGLContext::ValidateGLSLVariableName(const nsAString& name, const char *info)
|
||||
{
|
||||
const PRUint32 maxSize = 255;
|
||||
const PRUint32 maxSize = 256;
|
||||
if (name.Length() > maxSize) {
|
||||
ErrorInvalidValue("%s: identifier is %d characters long, exceeds the maximum allowed length of %d characters",
|
||||
info, name.Length(), maxSize);
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
conformance/context/premultiplyalpha-test.html
|
||||
conformance/glsl/misc/glsl-long-variable-names.html
|
||||
conformance/glsl/misc/shader-with-256-character-identifier.frag.html
|
||||
conformance/glsl/misc/shader-with-long-line.html
|
||||
conformance/misc/uninitialized-test.html
|
||||
conformance/programs/gl-get-active-attribute.html
|
||||
conformance/textures/texture-mips.html
|
||||
conformance/uniforms/gl-uniform-bool.html
|
||||
conformance/more/conformance/quickCheckAPI-S_V.html
|
||||
conformance/more/functions/uniformfArrayLen1.html
|
||||
conformance/glsl/misc/attrib-location-length-limits.html
|
||||
conformance/glsl/misc/uniform-location-length-limits.html
|
||||
conformance/renderbuffers/framebuffer-object-attachment.html
|
|
@ -1,11 +1,6 @@
|
|||
conformance/context/premultiplyalpha-test.html
|
||||
conformance/glsl/misc/glsl-function-nodes.html
|
||||
conformance/glsl/misc/glsl-long-variable-names.html
|
||||
conformance/glsl/misc/shader-with-256-character-identifier.frag.html
|
||||
conformance/glsl/misc/shader-with-long-line.html
|
||||
conformance/more/conformance/quickCheckAPI-S_V.html
|
||||
conformance/glsl/misc/attrib-location-length-limits.html
|
||||
conformance/glsl/misc/uniform-location-length-limits.html
|
||||
conformance/programs/program-test.html
|
||||
conformance/textures/texture-mips.html
|
||||
conformance/textures/texture-npot.html
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
conformance/context/premultiplyalpha-test.html
|
||||
conformance/glsl/functions/glsl-function-atan.html
|
||||
conformance/glsl/functions/glsl-function-atan-xy.html
|
||||
conformance/glsl/misc/glsl-long-variable-names.html
|
||||
conformance/glsl/misc/shader-with-256-character-identifier.frag.html
|
||||
conformance/glsl/misc/shader-with-long-line.html
|
||||
conformance/more/conformance/quickCheckAPI-S_V.html
|
||||
conformance/more/functions/uniformfArrayLen1.html
|
||||
conformance/glsl/misc/attrib-location-length-limits.html
|
||||
conformance/glsl/misc/struct-nesting-under-maximum.html
|
||||
conformance/glsl/misc/uniform-location-length-limits.html
|
|
@ -105,3 +105,5 @@ ShGetInfoLog
|
|||
ShCompile
|
||||
ShGetInfo
|
||||
ShConstructCompiler
|
||||
ShGetActiveAttrib
|
||||
ShGetActiveUniform
|
||||
|
|
Загрузка…
Ссылка в новой задаче