b=571078; fix webgl attribute validation; r=bjacob
This commit is contained in:
@@ -41,6 +41,38 @@
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
/*
|
||||
* Pull all the data out of the program that will be used by validate later on
|
||||
*/
|
||||
PRBool
|
||||
WebGLProgram::UpdateInfo(gl::GLContext *gl)
|
||||
{
|
||||
gl->fGetProgramiv(mName, LOCAL_GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &mAttribMaxNameLength);
|
||||
gl->fGetProgramiv(mName, LOCAL_GL_ACTIVE_UNIFORM_MAX_LENGTH, &mUniformMaxNameLength);
|
||||
gl->fGetProgramiv(mName, LOCAL_GL_ACTIVE_UNIFORMS, &mUniformCount);
|
||||
gl->fGetProgramiv(mName, LOCAL_GL_ACTIVE_ATTRIBUTES, &mAttribCount);
|
||||
|
||||
GLint numVertexAttribs;
|
||||
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &numVertexAttribs);
|
||||
mAttribsInUse.clear();
|
||||
mAttribsInUse.resize(numVertexAttribs);
|
||||
|
||||
nsAutoArrayPtr<char> nameBuf(new char[mAttribMaxNameLength]);
|
||||
|
||||
for (int i = 0; i < mAttribCount; ++i) {
|
||||
GLint attrnamelen;
|
||||
GLint attrsize;
|
||||
GLenum attrtype;
|
||||
gl->fGetActiveAttrib(mName, i, mAttribMaxNameLength, &attrnamelen, &attrsize, &attrtype, nameBuf);
|
||||
if (attrnamelen > 0) {
|
||||
GLint loc = gl->fGetAttribLocation(mName, nameBuf);
|
||||
mAttribsInUse[loc] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that we can read count consecutive elements from each bound VBO.
|
||||
*/
|
||||
@@ -48,61 +80,46 @@ using namespace mozilla;
|
||||
PRBool
|
||||
WebGLContext::ValidateBuffers(PRUint32 count)
|
||||
{
|
||||
GLint currentProgram = -1;
|
||||
GLint numAttributes = -1;
|
||||
|
||||
NS_ENSURE_TRUE(count > 0, PR_TRUE);
|
||||
|
||||
#ifdef DEBUG
|
||||
GLuint currentProgram = 0;
|
||||
MakeContextCurrent();
|
||||
|
||||
// XXX cache this per program
|
||||
gl->fGetIntegerv(LOCAL_GL_CURRENT_PROGRAM, ¤tProgram);
|
||||
if (currentProgram == -1) {
|
||||
// what?
|
||||
LogMessage("glGetIntegerv GL_CURRENT_PROGRAM failed: 0x%08x", (uint) gl->fGetError());
|
||||
gl->fGetIntegerv(LOCAL_GL_CURRENT_PROGRAM, (GLint*) ¤tProgram);
|
||||
NS_ASSERTION(currentProgram == mCurrentProgram->GLName(),
|
||||
"WebGL: current program doesn't agree with GL state");
|
||||
if (currentProgram != mCurrentProgram->GLName())
|
||||
return PR_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (WebGLuint(currentProgram) != mCurrentProgram->GLName()) {
|
||||
LogMessage("WebGL internal error: current program (%u) doesn't agree with GL current program (%d)", mCurrentProgram->GLName(), currentProgram);
|
||||
return PR_FALSE;
|
||||
}
|
||||
PRUint32 attribs = mAttribBuffers.Length();
|
||||
for (PRUint32 i = 0; i < attribs; ++i) {
|
||||
const WebGLVertexAttribData& vd = mAttribBuffers[i];
|
||||
|
||||
gl->fGetProgramiv(currentProgram, LOCAL_GL_ACTIVE_ATTRIBUTES, &numAttributes);
|
||||
if (numAttributes == -1) {
|
||||
// what?
|
||||
LogMessage("glGetProgramiv GL_ACTIVE_ATTRIBUTES failed: 0x%08x", (uint) gl->fGetError());
|
||||
return PR_FALSE;
|
||||
}
|
||||
// If the attrib array isn't enabled, there's nothing to check;
|
||||
// it's a static value.
|
||||
if (!vd.enabled)
|
||||
continue;
|
||||
|
||||
// is this valid?
|
||||
if (numAttributes > (GLint) mAttribBuffers.Length()) {
|
||||
// what?
|
||||
LogMessage("GL_ACTIVE_ATTRIBUTES > GL_MAX_VERTEX_ATTRIBS");
|
||||
return PR_FALSE;
|
||||
}
|
||||
PRUint32 maxAttribs = numAttributes;
|
||||
if (vd.buf == nsnull) {
|
||||
LogMessage("No VBO bound to enabled attrib index %d!", i);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0; i < maxAttribs; ++i) {
|
||||
WebGLVertexAttribData& vd = mAttribBuffers[i];
|
||||
// If the attrib is not in use, then we don't have to validate
|
||||
// it, just need to make sure that the binding is non-null.
|
||||
if (!mCurrentProgram->IsAttribInUse(i))
|
||||
continue;
|
||||
|
||||
// is this a problem?
|
||||
if (!vd.enabled)
|
||||
continue;
|
||||
// compute the number of bytes we actually need
|
||||
WebGLuint needed = vd.byteOffset + // the base offset
|
||||
vd.actualStride() * (count-1) + // to stride to the start of the last element group
|
||||
vd.componentSize() * vd.size; // and the number of bytes needed for these components
|
||||
|
||||
if (vd.buf == nsnull) {
|
||||
LogMessage("No VBO bound to index %d (or it's been deleted)!", i);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
WebGLuint needed = vd.byteOffset + // the base offset
|
||||
vd.actualStride() * (count-1) + // to stride to the start of the last element group
|
||||
vd.componentSize() * vd.size; // and the number of bytes needed for these components
|
||||
|
||||
if (vd.buf->ByteLength() < needed) {
|
||||
LogMessage("VBO too small for bound attrib index %d: need at least %d bytes, but have only %d", i, needed, vd.buf->ByteLength());
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (vd.buf->ByteLength() < needed) {
|
||||
LogMessage("VBO too small for bound attrib index %d: need at least %d bytes, but have only %d", i, needed, vd.buf->ByteLength());
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
@@ -125,3 +142,57 @@ PRBool WebGLContext::ValidateCapabilityEnum(WebGLenum cap)
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
WebGLContext::ValidateGL()
|
||||
{
|
||||
// make sure that the opengl stuff that we need is supported
|
||||
GLint val = 0;
|
||||
|
||||
// XXX this exposes some strange latent bug; what's going on?
|
||||
//MakeContextCurrent();
|
||||
|
||||
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &val);
|
||||
if (val == 0) {
|
||||
LogMessage("GL_MAX_VERTEX_ATTRIBS is 0!");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
mAttribBuffers.SetLength(val);
|
||||
|
||||
//fprintf(stderr, "GL_MAX_VERTEX_ATTRIBS: %d\n", val);
|
||||
|
||||
// Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware,
|
||||
// even though the hardware supports much more. The
|
||||
// GL_MAX_{COMBINED_}TEXTURE_IMAGE_UNITS value is the accurate
|
||||
// value. For GLES2, GL_MAX_TEXTURE_UNITS is still correct.
|
||||
gl->fGetIntegerv(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &val);
|
||||
if (val == 0) {
|
||||
LogMessage("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS is 0!");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
mBound2DTextures.SetLength(val);
|
||||
mBoundCubeMapTextures.SetLength(val);
|
||||
|
||||
//fprintf(stderr, "GL_MAX_TEXTURE_UNITS: %d\n", val);
|
||||
|
||||
gl->fGetIntegerv(LOCAL_GL_MAX_COLOR_ATTACHMENTS, &val);
|
||||
mFramebufferColorAttachments.SetLength(val);
|
||||
|
||||
#if defined(DEBUG_vladimir) && defined(USE_GLES2)
|
||||
gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT, &val);
|
||||
fprintf(stderr, "GL_IMPLEMENTATION_COLOR_READ_FORMAT: 0x%04x\n", val);
|
||||
|
||||
gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE, &val);
|
||||
fprintf(stderr, "GL_IMPLEMENTATION_COLOR_READ_TYPE: 0x%04x\n", val);
|
||||
#endif
|
||||
|
||||
#ifndef USE_GLES2
|
||||
// gl_PointSize is always available in ES2 GLSL, but has to be
|
||||
// specifically enabled on desktop GLSL.
|
||||
gl->fEnable(LOCAL_GL_VERTEX_PROGRAM_POINT_SIZE);
|
||||
#endif
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user