Bug 982960 - Use glDrawRangeElements in WebGL.drawElements. r=kamidphish

This commit is contained in:
Jeff Gilbert 2014-03-17 10:52:56 -04:00
Родитель 18eef3b4d4
Коммит c0d67d37f5
7 изменённых файлов: 129 добавлений и 49 удалений

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

@ -4,9 +4,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLBuffer.h"
#include "WebGLContext.h"
#include "GLContext.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "WebGLContext.h"
#include "WebGLElementArrayCache.h"
using namespace mozilla;
@ -55,6 +57,22 @@ WebGLBuffer::ElementArrayCacheBufferSubData(size_t pos, const void* ptr, size_t
mCache->BufferSubData(pos, ptr, update_size_in_bytes);
}
size_t
WebGLBuffer::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
{
size_t sizeOfCache = mCache ? mCache->SizeOfIncludingThis(aMallocSizeOf) : 0;
return aMallocSizeOf(this) + sizeOfCache;
}
bool
WebGLBuffer::Validate(GLenum type, uint32_t max_allowed,
size_t first, size_t count,
uint32_t* out_upperBound)
{
return mCache->Validate(type, max_allowed, first, count, out_upperBound);
}
JSObject*
WebGLBuffer::WrapObject(JSContext *cx, JS::Handle<JSObject*> scope) {
return dom::WebGLBufferBinding::Wrap(cx, scope, this);

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

@ -6,14 +6,12 @@
#ifndef WEBGLBUFFER_H_
#define WEBGLBUFFER_H_
#include "WebGLObjectModel.h"
#include "WebGLElementArrayCache.h"
#include "GLDefs.h"
#include "nsWrapperCache.h"
#include "mozilla/LinkedList.h"
#include "mozilla/MemoryReporting.h"
#include "nsWrapperCache.h"
#include "WebGLObjectModel.h"
#include "WebGLTypes.h"
namespace mozilla {
@ -32,10 +30,7 @@ public:
void Delete();
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
size_t sizeOfCache = mCache ? mCache->SizeOfIncludingThis(aMallocSizeOf) : 0;
return aMallocSizeOf(this) + sizeOfCache;
}
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
bool HasEverBeenBound() { return mHasEverBeenBound; }
void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
@ -51,9 +46,8 @@ public:
void ElementArrayCacheBufferSubData(size_t pos, const void* ptr, size_t update_size_in_bytes);
bool Validate(GLenum type, uint32_t max_allowed, size_t first, size_t count) {
return mCache->Validate(type, max_allowed, first, count);
}
bool Validate(GLenum type, uint32_t max_allowed, size_t first, size_t count,
uint32_t* out_upperBound);
WebGLContext *GetParentObject() const {
return Context();

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

@ -787,7 +787,8 @@ private:
bool DrawArrays_check(GLint first, GLsizei count, GLsizei primcount, const char* info);
bool DrawElements_check(GLsizei count, GLenum type, WebGLintptr byteOffset,
GLsizei primcount, const char* info);
GLsizei primcount, const char* info,
GLuint* out_upperBound = nullptr);
bool DrawInstanced_check(const char* info);
void Draw_cleanup();

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

@ -4,16 +4,18 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLContext.h"
#include "WebGLBuffer.h"
#include "WebGLVertexAttribData.h"
#include "WebGLVertexArray.h"
#include "WebGLTexture.h"
#include "WebGLRenderbuffer.h"
#include "WebGLFramebuffer.h"
#include "WebGLUniformInfo.h"
#include "WebGLShader.h"
#include "WebGLProgram.h"
#include "GLContext.h"
#include "mozilla/CheckedInt.h"
#include "WebGLBuffer.h"
#include "WebGLFramebuffer.h"
#include "WebGLProgram.h"
#include "WebGLRenderbuffer.h"
#include "WebGLShader.h"
#include "WebGLTexture.h"
#include "WebGLUniformInfo.h"
#include "WebGLVertexArray.h"
#include "WebGLVertexAttribData.h"
using namespace mozilla;
using namespace dom;
@ -554,7 +556,9 @@ WebGLContext::DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsiz
}
bool
WebGLContext::DrawElements_check(GLsizei count, GLenum type, WebGLintptr byteOffset, GLsizei primcount, const char* info)
WebGLContext::DrawElements_check(GLsizei count, GLenum type,
WebGLintptr byteOffset, GLsizei primcount,
const char* info, GLuint* out_upperBound)
{
if (count < 0 || byteOffset < 0) {
ErrorInvalidValue("%s: negative count or offset", info);
@ -620,7 +624,9 @@ WebGLContext::DrawElements_check(GLsizei count, GLenum type, WebGLintptr byteOff
return false;
}
if (!mBoundVertexArray->mBoundElementArrayBuffer->ByteLength()) {
WebGLBuffer& elemArrayBuffer = *mBoundVertexArray->mBoundElementArrayBuffer;
if (!elemArrayBuffer.ByteLength()) {
ErrorInvalidOperation("%s: bound element array buffer doesn't have any data", info);
return false;
}
@ -632,7 +638,7 @@ WebGLContext::DrawElements_check(GLsizei count, GLenum type, WebGLintptr byteOff
return false;
}
if (uint32_t(checked_neededByteCount.value()) > mBoundVertexArray->mBoundElementArrayBuffer->ByteLength()) {
if (uint32_t(checked_neededByteCount.value()) > elemArrayBuffer.ByteLength()) {
ErrorInvalidOperation("%s: bound element array buffer is too small for given count and offset", info);
return false;
}
@ -641,7 +647,7 @@ WebGLContext::DrawElements_check(GLsizei count, GLenum type, WebGLintptr byteOff
return false;
if (!mMaxFetchedVertices ||
!mBoundVertexArray->mBoundElementArrayBuffer->Validate(type, mMaxFetchedVertices - 1, first, count))
!elemArrayBuffer.Validate(type, mMaxFetchedVertices - 1, first, count, out_upperBound))
{
ErrorInvalidOperation(
"%s: bound vertex attribute buffers do not have sufficient "
@ -673,7 +679,7 @@ WebGLContext::DrawElements_check(GLsizei count, GLenum type, WebGLintptr byteOff
void
WebGLContext::DrawElements(GLenum mode, GLsizei count, GLenum type,
WebGLintptr byteOffset)
WebGLintptr byteOffset)
{
if (IsContextLost())
return;
@ -681,18 +687,28 @@ WebGLContext::DrawElements(GLenum mode, GLsizei count, GLenum type,
if (!ValidateDrawModeEnum(mode, "drawElements: mode"))
return;
if (!DrawElements_check(count, type, byteOffset, 1, "drawElements"))
GLuint upperBound = UINT_MAX;
if (!DrawElements_check(count, type, byteOffset, 1, "drawElements",
&upperBound))
{
return;
}
SetupContextLossTimer();
gl->fDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(byteOffset));
if (gl->IsSupported(gl::GLFeature::draw_range_elements)) {
gl->fDrawRangeElements(mode, 0, upperBound,
count, type, reinterpret_cast<GLvoid*>(byteOffset));
} else {
gl->fDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(byteOffset));
}
Draw_cleanup();
}
void
WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
WebGLintptr byteOffset, GLsizei primcount)
WebGLintptr byteOffset, GLsizei primcount)
{
if (IsContextLost())
return;

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

@ -16,6 +16,24 @@
namespace mozilla {
static void
SetUpperBound(uint32_t* out_upperBound, uint32_t newBound)
{
if (!out_upperBound)
return;
*out_upperBound = newBound;
}
static void
UpdateUpperBound(uint32_t* out_upperBound, uint32_t newBound)
{
if (!out_upperBound)
return;
*out_upperBound = std::max(*out_upperBound, newBound);
}
/*
* WebGLElementArrayCacheTree contains most of the implementation of WebGLElementArrayCache,
* which performs WebGL element array buffer validation for drawElements.
@ -227,7 +245,9 @@ public:
return ((numElements - 1) | sElementsPerLeafMask) + 1;
}
bool Validate(T maxAllowed, size_t firstLeaf, size_t lastLeaf) {
bool Validate(T maxAllowed, size_t firstLeaf, size_t lastLeaf,
uint32_t* out_upperBound)
{
MOZ_ASSERT(!mInvalidated);
size_t firstTreeIndex = TreeIndexForLeaf(firstLeaf);
@ -240,13 +260,17 @@ public:
// final case where there is only 1 node to validate at the current tree level
if (lastTreeIndex == firstTreeIndex) {
return mTreeData[firstTreeIndex] <= maxAllowed;
const T& curData = mTreeData[firstTreeIndex];
UpdateUpperBound(out_upperBound, curData);
return curData <= maxAllowed;
}
// if the first node at current tree level is a right node, handle it individually
// and replace it with its right neighbor, which is a left node
if (IsRightNode(firstTreeIndex)) {
if (mTreeData[firstTreeIndex] > maxAllowed)
const T& curData = mTreeData[firstTreeIndex];
UpdateUpperBound(out_upperBound, curData);
if (curData > maxAllowed)
return false;
firstTreeIndex = RightNeighborNode(firstTreeIndex);
}
@ -254,7 +278,9 @@ public:
// if the last node at current tree level is a left node, handle it individually
// and replace it with its left neighbor, which is a right node
if (IsLeftNode(lastTreeIndex)) {
if (mTreeData[lastTreeIndex] > maxAllowed)
const T& curData = mTreeData[lastTreeIndex];
UpdateUpperBound(out_upperBound, curData);
if (curData > maxAllowed)
return false;
lastTreeIndex = LeftNeighborNode(lastTreeIndex);
}
@ -490,10 +516,18 @@ void WebGLElementArrayCache::InvalidateTrees(size_t firstByte, size_t lastByte)
}
template<typename T>
bool WebGLElementArrayCache::Validate(uint32_t maxAllowed, size_t firstElement, size_t countElements) {
bool
WebGLElementArrayCache::Validate(uint32_t maxAllowed, size_t firstElement,
size_t countElements, uint32_t* out_upperBound)
{
SetUpperBound(out_upperBound, 0);
// if maxAllowed is >= the max T value, then there is no way that a T index could be invalid
if (maxAllowed >= std::numeric_limits<T>::max())
uint32_t maxTSize = std::numeric_limits<T>::max();
if (maxAllowed >= maxTSize) {
SetUpperBound(out_upperBound, maxTSize);
return true;
}
T maxAllowedT(maxAllowed);
@ -515,8 +549,10 @@ bool WebGLElementArrayCache::Validate(uint32_t maxAllowed, size_t firstElement,
// fast exit path when the global maximum for the whole element array buffer
// falls in the allowed range
if (tree->GlobalMaximum() <= maxAllowedT)
T globalMax = tree->GlobalMaximum();
if (globalMax <= maxAllowedT)
{
SetUpperBound(out_upperBound, globalMax);
return true;
}
@ -527,14 +563,18 @@ bool WebGLElementArrayCache::Validate(uint32_t maxAllowed, size_t firstElement,
size_t firstElementAdjustmentEnd = std::min(lastElement,
tree->LastElementUnderSameLeaf(firstElement));
while (firstElement <= firstElementAdjustmentEnd) {
if (elements[firstElement] > maxAllowedT)
const T& curData = elements[firstElement];
UpdateUpperBound(out_upperBound, curData);
if (curData > maxAllowedT)
return false;
firstElement++;
}
size_t lastElementAdjustmentEnd = std::max(firstElement,
tree->FirstElementUnderSameLeaf(lastElement));
while (lastElement >= lastElementAdjustmentEnd) {
if (elements[lastElement] > maxAllowedT)
const T& curData = elements[lastElement];
UpdateUpperBound(out_upperBound, curData);
if (curData > maxAllowedT)
return false;
lastElement--;
}
@ -546,20 +586,29 @@ bool WebGLElementArrayCache::Validate(uint32_t maxAllowed, size_t firstElement,
// general case
return tree->Validate(maxAllowedT,
tree->LeafForElement(firstElement),
tree->LeafForElement(lastElement));
tree->LeafForElement(lastElement),
out_upperBound);
}
bool WebGLElementArrayCache::Validate(GLenum type, uint32_t maxAllowed, size_t firstElement, size_t countElements) {
bool
WebGLElementArrayCache::Validate(GLenum type, uint32_t maxAllowed,
size_t firstElement, size_t countElements,
uint32_t* out_upperBound)
{
if (type == LOCAL_GL_UNSIGNED_BYTE)
return Validate<uint8_t>(maxAllowed, firstElement, countElements);
return Validate<uint8_t>(maxAllowed, firstElement, countElements, out_upperBound);
if (type == LOCAL_GL_UNSIGNED_SHORT)
return Validate<uint16_t>(maxAllowed, firstElement, countElements);
return Validate<uint16_t>(maxAllowed, firstElement, countElements, out_upperBound);
if (type == LOCAL_GL_UNSIGNED_INT)
return Validate<uint32_t>(maxAllowed, firstElement, countElements);
return Validate<uint32_t>(maxAllowed, firstElement, countElements, out_upperBound);
MOZ_ASSERT(false, "Invalid type.");
return false;
}
size_t WebGLElementArrayCache::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
size_t
WebGLElementArrayCache::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
{
size_t uint8TreeSize = mUint8Tree ? mUint8Tree->SizeOfIncludingThis(aMallocSizeOf) : 0;
size_t uint16TreeSize = mUint16Tree ? mUint16Tree->SizeOfIncludingThis(aMallocSizeOf) : 0;
size_t uint32TreeSize = mUint32Tree ? mUint32Tree->SizeOfIncludingThis(aMallocSizeOf) : 0;

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

@ -33,7 +33,8 @@ public:
bool BufferData(const void* ptr, size_t byteSize);
void BufferSubData(size_t pos, const void* ptr, size_t updateByteSize);
bool Validate(GLenum type, uint32_t maxAllowed, size_t first, size_t count);
bool Validate(GLenum type, uint32_t maxAllowed, size_t first, size_t count,
uint32_t* out_upperBound = nullptr);
template<typename T>
T Element(size_t i) const { return Elements<T>()[i]; }
@ -53,7 +54,8 @@ public:
private:
template<typename T>
bool Validate(uint32_t maxAllowed, size_t first, size_t count);
bool Validate(uint32_t maxAllowed, size_t first, size_t count,
uint32_t* out_upperBound);
size_t ByteSize() const {
return mByteSize;

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

@ -86,7 +86,7 @@ static const FeatureInfo sFeatureInfoArr[] = {
},
{
"draw_range_elements",
200, // OpenGL version
120, // OpenGL version
300, // OpenGL ES version
{
GLContext::EXT_draw_range_elements,