b=571078; fix webgl attribute validation; r=bjacob

This commit is contained in:
Vladimir Vukicevic
2010-06-10 10:45:00 -07:00
parent aee583b4ff
commit 0227fdd23a
3 changed files with 158 additions and 115 deletions

View File

@@ -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, &currentProgram);
if (currentProgram == -1) {
// what?
LogMessage("glGetIntegerv GL_CURRENT_PROGRAM failed: 0x%08x", (uint) gl->fGetError());
gl->fGetIntegerv(LOCAL_GL_CURRENT_PROGRAM, (GLint*) &currentProgram);
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;
}