Bug 738867 - Implement WebGL OES_element_index_uint extension. r=bjacob

This commit is contained in:
Jon Buckley 2013-05-13 09:22:30 -04:00
Родитель a25810ce35
Коммит 68bdfcf2af
13 изменённых файлов: 94 добавлений и 7 удалений

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

@ -48,9 +48,15 @@ T RandomInteger(T a, T b)
template<typename T>
GLenum GLType()
{
return sizeof(T) == 1
? LOCAL_GL_UNSIGNED_BYTE
: LOCAL_GL_UNSIGNED_SHORT;
switch (sizeof(T))
{
case 4: return LOCAL_GL_UNSIGNED_INT;
case 2: return LOCAL_GL_UNSIGNED_SHORT;
case 1: return LOCAL_GL_UNSIGNED_BYTE;
default:
VERIFY(false);
return 0;
}
}
template<typename T>
@ -79,6 +85,7 @@ void CheckValidate(WebGLElementArrayCache& c, size_t firstByte, size_t countByte
{
CheckValidateOneType<uint8_t>(c, firstByte, countBytes);
CheckValidateOneType<uint16_t>(c, firstByte, countBytes);
CheckValidateOneType<uint32_t>(c, firstByte, countBytes);
}
template<typename T>
@ -151,6 +158,7 @@ int main(int argc, char *argv[])
CheckSanity<uint8_t>();
CheckSanity<uint16_t>();
CheckSanity<uint32_t>();
CheckUintOverflow<uint8_t>();
CheckUintOverflow<uint16_t>();

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

@ -40,6 +40,7 @@ CPPSRCS += \
WebGLExtensionCompressedTextureS3TC.cpp \
WebGLExtensionDebugRendererInfo.cpp \
WebGLExtensionDepthTexture.cpp \
WebGLExtensionElementIndexUint.cpp \
WebGLExtensionLoseContext.cpp \
WebGLExtensionStandardDerivatives.cpp \
WebGLExtensionTextureFilterAnisotropic.cpp \

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

@ -943,6 +943,8 @@ bool WebGLContext::IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) con
}
switch (ext) {
case OES_element_index_uint:
return !gl->IsGLES2() || gl->IsExtensionSupported(GLContext::OES_element_index_uint);
case OES_standard_derivatives:
case WEBGL_lose_context:
// We always support these extensions.
@ -1013,7 +1015,11 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, ErrorResult& r
WebGLExtensionID ext = WebGLExtensionID_unknown_extension;
// step 1: figure what extension is wanted
if (CompareWebGLExtensionName(name, "OES_texture_float"))
if (CompareWebGLExtensionName(name, "OES_element_index_uint"))
{
ext = OES_element_index_uint;
}
else if (CompareWebGLExtensionName(name, "OES_texture_float"))
{
ext = OES_texture_float;
}
@ -1075,6 +1081,9 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, ErrorResult& r
if (!IsExtensionEnabled(ext)) {
WebGLExtensionBase *obj = nullptr;
switch (ext) {
case OES_element_index_uint:
obj = new WebGLExtensionElementIndexUint(this);
break;
case OES_standard_derivatives:
obj = new WebGLExtensionStandardDerivatives(this);
break;
@ -1439,6 +1448,8 @@ WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray<nsString>
nsTArray<nsString>& arr = retval.SetValue();
if (IsExtensionSupported(cx, OES_element_index_uint))
arr.AppendElement(NS_LITERAL_STRING("OES_element_index_uint"));
if (IsExtensionSupported(cx, OES_texture_float))
arr.AppendElement(NS_LITERAL_STRING("OES_texture_float"));
if (IsExtensionSupported(cx, OES_standard_derivatives))

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

@ -912,6 +912,7 @@ protected:
// extensions
enum WebGLExtensionID {
EXT_texture_filter_anisotropic,
OES_element_index_uint,
OES_standard_derivatives,
OES_texture_float,
WEBGL_compressed_texture_atc,

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

@ -1511,6 +1511,11 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type,
} else if (type == LOCAL_GL_UNSIGNED_BYTE) {
checked_byteCount = count;
first = byteOffset;
} else if (type == LOCAL_GL_UNSIGNED_INT && IsExtensionEnabled(OES_element_index_uint)) {
checked_byteCount = 4 * CheckedUint32(count);
if (byteOffset % 4 != 0)
return ErrorInvalidOperation("drawElements: invalid byteOffset for UNSIGNED_INT (must be a multiple of 4)");
first = byteOffset / 4;
} else {
return ErrorInvalidEnum("drawElements: type must be UNSIGNED_SHORT or UNSIGNED_BYTE");
}

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

@ -106,8 +106,8 @@ namespace mozilla {
* by having WebGLElementArrayCache lazily create trees for each type only upon first use.
*
* Another consequence of this constraint is that when invalidating the trees, we have to invalidate
* all existing trees. So if trees for types uint8_t and uint16_t have ever been constructed for this buffer,
* every subsequent invalidation will have to invalidate both trees even if one of the two types is never
* all existing trees. So if trees for types uint8_t, uint16_t and uint32_t have ever been constructed for this buffer,
* every subsequent invalidation will have to invalidate all trees even if one of the types is never
* used again. This implies that it is important to minimize the cost of invalidation i.e.
* do lazy updates upon use as opposed to immediately updating invalidated trees. This poses a problem:
* it is nontrivial to keep track of the part of the tree that's invalidated. The current solution
@ -329,6 +329,12 @@ struct TreeForType<uint16_t>
static WebGLElementArrayCacheTree<uint16_t>*& Run(WebGLElementArrayCache *b) { return b->mUint16Tree; }
};
template<>
struct TreeForType<uint32_t>
{
static WebGLElementArrayCacheTree<uint32_t>*& Run(WebGLElementArrayCache *b) { return b->mUint32Tree; }
};
// When the buffer gets updated from firstByte to lastByte,
// calling this method will notify the tree accordingly
template<typename T>
@ -441,6 +447,7 @@ void WebGLElementArrayCacheTree<T>::Update()
WebGLElementArrayCache::~WebGLElementArrayCache() {
delete mUint8Tree;
delete mUint16Tree;
delete mUint32Tree;
free(mUntypedData);
}
@ -452,6 +459,9 @@ bool WebGLElementArrayCache::BufferData(const void* ptr, size_t byteSize) {
if (mUint16Tree)
if (!mUint16Tree->ResizeToParentSize())
return false;
if (mUint32Tree)
if (!mUint32Tree->ResizeToParentSize())
return false;
mUntypedData = realloc(mUntypedData, byteSize);
if (!mUntypedData)
return false;
@ -474,6 +484,8 @@ void WebGLElementArrayCache::InvalidateTrees(size_t firstByte, size_t lastByte)
mUint8Tree->Invalidate(firstByte, lastByte);
if (mUint16Tree)
mUint16Tree->Invalidate(firstByte, lastByte);
if (mUint32Tree)
mUint32Tree->Invalidate(firstByte, lastByte);
}
template<typename T>
@ -541,16 +553,20 @@ bool WebGLElementArrayCache::Validate(GLenum type, uint32_t maxAllowed, size_t f
return Validate<uint8_t>(maxAllowed, firstElement, countElements);
if (type == LOCAL_GL_UNSIGNED_SHORT)
return Validate<uint16_t>(maxAllowed, firstElement, countElements);
if (type == LOCAL_GL_UNSIGNED_INT)
return Validate<uint32_t>(maxAllowed, firstElement, countElements);
return false;
}
size_t WebGLElementArrayCache::SizeOfIncludingThis(nsMallocSizeOfFun 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;
return aMallocSizeOf(this) +
mByteSize +
uint8TreeSize +
uint16TreeSize;
uint16TreeSize +
uint32TreeSize;
}
} // end namespace mozilla

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

@ -42,6 +42,7 @@ public:
, mByteSize(0)
, mUint8Tree(nullptr)
, mUint16Tree(nullptr)
, mUint32Tree(nullptr)
{}
~WebGLElementArrayCache();
@ -73,6 +74,7 @@ private:
size_t mByteSize;
WebGLElementArrayCacheTree<uint8_t>* mUint8Tree;
WebGLElementArrayCacheTree<uint16_t>* mUint16Tree;
WebGLElementArrayCacheTree<uint32_t>* mUint32Tree;
};

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

@ -0,0 +1,21 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLContext.h"
#include "WebGLExtensions.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
using namespace mozilla;
WebGLExtensionElementIndexUint::WebGLExtensionElementIndexUint(WebGLContext* context)
: WebGLExtensionBase(context)
{
}
WebGLExtensionElementIndexUint::~WebGLExtensionElementIndexUint()
{
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionElementIndexUint)

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

@ -87,6 +87,16 @@ public:
DECL_WEBGL_EXTENSION_GOOP
};
class WebGLExtensionElementIndexUint
: public WebGLExtensionBase
{
public:
WebGLExtensionElementIndexUint(WebGLContext*);
virtual ~WebGLExtensionElementIndexUint();
DECL_WEBGL_EXTENSION_GOOP
};
class WebGLExtensionLoseContext
: public WebGLExtensionBase
{

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

@ -1102,6 +1102,11 @@ DOMInterfaces = {
'headerFile': 'WebGLExtensions.h'
},
'WebGLExtensionElementIndexUint': {
'nativeType': 'mozilla::WebGLExtensionElementIndexUint',
'headerFile': 'WebGLExtensions.h'
},
'WebGLExtensionLoseContext': {
'nativeType': 'mozilla::WebGLExtensionLoseContext',
'headerFile': 'WebGLExtensions.h'

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

@ -806,6 +806,11 @@ interface WebGLExtensionDepthTexture
const GLenum UNSIGNED_INT_24_8_WEBGL = 0x84FA;
};
[NoInterfaceObject]
interface WebGLExtensionElementIndexUint
{
};
[NoInterfaceObject]
interface WebGLExtensionLoseContext {
void loseContext();

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

@ -80,6 +80,7 @@ static const char *sExtensionNames[] = {
"GL_OES_EGL_sync",
"GL_OES_EGL_image_external",
"GL_EXT_packed_depth_stencil",
"GL_OES_element_index_uint",
nullptr
};

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

@ -1016,6 +1016,7 @@ public:
OES_EGL_sync,
OES_EGL_image_external,
EXT_packed_depth_stencil,
OES_element_index_uint,
Extensions_Max
};