зеркало из https://github.com/mozilla/gecko-dev.git
Bug 982960 - Use glDrawRangeElements in WebGL.drawElements. r=kamidphish
This commit is contained in:
Родитель
18eef3b4d4
Коммит
c0d67d37f5
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче