Bug 569431 - Optimization in DrawElements - r=vlad, a=joe

This commit is contained in:
Benoit Jacob
2011-01-25 22:19:46 -05:00
parent 98a6d0e96e
commit 3a4de143dd
3 changed files with 103 additions and 35 deletions

View File

@@ -83,14 +83,13 @@ WebGLProgram::UpdateInfo(gl::GLContext *gl)
}
/*
* Verify that we can read count consecutive elements from each bound VBO.
* Verify that state is consistent for drawing, and compute max number of elements (maxAllowedCount)
* that will be legal to be read from bound VBOs.
*/
PRBool
WebGLContext::ValidateBuffers(PRUint32 count)
WebGLContext::ValidateBuffers(PRInt32 *maxAllowedCount, const char *info)
{
NS_ENSURE_TRUE(count > 0, PR_TRUE);
#ifdef DEBUG
GLuint currentProgram = 0;
MakeContextCurrent();
@@ -101,6 +100,8 @@ WebGLContext::ValidateBuffers(PRUint32 count)
return PR_FALSE;
#endif
*maxAllowedCount = -1;
PRUint32 attribs = mAttribBuffers.Length();
for (PRUint32 i = 0; i < attribs; ++i) {
const WebGLVertexAttribData& vd = mAttribBuffers[i];
@@ -111,7 +112,7 @@ WebGLContext::ValidateBuffers(PRUint32 count)
continue;
if (vd.buf == nsnull) {
LogMessageIfVerbose("No VBO bound to enabled attrib index %d!", i);
ErrorInvalidOperation("%s: no VBO bound to enabled vertex attrib index %d!", info, i);
return PR_FALSE;
}
@@ -120,20 +121,32 @@ WebGLContext::ValidateBuffers(PRUint32 count)
if (!mCurrentProgram->IsAttribInUse(i))
continue;
// compute the number of bytes we actually need
CheckedUint32 checked_needed = CheckedUint32(vd.byteOffset) + // the base offset
CheckedUint32(vd.actualStride()) * (count-1) + // to stride to the start of the last element group
CheckedUint32(vd.componentSize()) * vd.size; // and the number of bytes needed for these components
// the base offset
CheckedUint32 checked_byteLength
= CheckedUint32(vd.buf->ByteLength()) - vd.byteOffset;
CheckedUint32 checked_sizeOfLastElement
= CheckedUint32(vd.componentSize()) * vd.size;
if (!checked_needed.valid()) {
LogMessageIfVerbose("Integer overflow computing the size of bound vertex attrib buffer at index %d", i);
return PR_FALSE;
if (!checked_byteLength.valid() ||
!checked_sizeOfLastElement.valid())
{
ErrorInvalidOperation("%s: integer overflow occured while checking vertex attrib %d", info, i);
return PR_FALSE;
}
if (vd.buf->ByteLength() < checked_needed.value()) {
LogMessageIfVerbose("VBO too small for bound attrib index %d: need at least %d bytes, but have only %d",
i, checked_needed.value(), vd.buf->ByteLength());
if (checked_byteLength.value() < checked_sizeOfLastElement.value()) {
*maxAllowedCount = 0;
} else {
CheckedUint32 checked_maxAllowedCount
= ((checked_byteLength - checked_sizeOfLastElement) / vd.actualStride()) + 1;
if (!checked_maxAllowedCount.valid()) {
ErrorInvalidOperation("%s: integer overflow occured while checking vertex attrib %d", info, i);
return PR_FALSE;
}
if (*maxAllowedCount == -1 || *maxAllowedCount > checked_maxAllowedCount.value())
*maxAllowedCount = checked_maxAllowedCount.value();
}
}