Bug 738867 - Implement WebGL OES_element_index_uint extension. r=bjacob
This commit is contained in:
@@ -48,9 +48,15 @@ T RandomInteger(T a, T b)
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
GLenum GLType()
|
GLenum GLType()
|
||||||
{
|
{
|
||||||
return sizeof(T) == 1
|
switch (sizeof(T))
|
||||||
? LOCAL_GL_UNSIGNED_BYTE
|
{
|
||||||
: LOCAL_GL_UNSIGNED_SHORT;
|
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>
|
template<typename T>
|
||||||
@@ -79,6 +85,7 @@ void CheckValidate(WebGLElementArrayCache& c, size_t firstByte, size_t countByte
|
|||||||
{
|
{
|
||||||
CheckValidateOneType<uint8_t>(c, firstByte, countBytes);
|
CheckValidateOneType<uint8_t>(c, firstByte, countBytes);
|
||||||
CheckValidateOneType<uint16_t>(c, firstByte, countBytes);
|
CheckValidateOneType<uint16_t>(c, firstByte, countBytes);
|
||||||
|
CheckValidateOneType<uint32_t>(c, firstByte, countBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -151,6 +158,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
CheckSanity<uint8_t>();
|
CheckSanity<uint8_t>();
|
||||||
CheckSanity<uint16_t>();
|
CheckSanity<uint16_t>();
|
||||||
|
CheckSanity<uint32_t>();
|
||||||
|
|
||||||
CheckUintOverflow<uint8_t>();
|
CheckUintOverflow<uint8_t>();
|
||||||
CheckUintOverflow<uint16_t>();
|
CheckUintOverflow<uint16_t>();
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ CPPSRCS += \
|
|||||||
WebGLExtensionCompressedTextureS3TC.cpp \
|
WebGLExtensionCompressedTextureS3TC.cpp \
|
||||||
WebGLExtensionDebugRendererInfo.cpp \
|
WebGLExtensionDebugRendererInfo.cpp \
|
||||||
WebGLExtensionDepthTexture.cpp \
|
WebGLExtensionDepthTexture.cpp \
|
||||||
|
WebGLExtensionElementIndexUint.cpp \
|
||||||
WebGLExtensionLoseContext.cpp \
|
WebGLExtensionLoseContext.cpp \
|
||||||
WebGLExtensionStandardDerivatives.cpp \
|
WebGLExtensionStandardDerivatives.cpp \
|
||||||
WebGLExtensionTextureFilterAnisotropic.cpp \
|
WebGLExtensionTextureFilterAnisotropic.cpp \
|
||||||
|
|||||||
@@ -943,6 +943,8 @@ bool WebGLContext::IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) con
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (ext) {
|
switch (ext) {
|
||||||
|
case OES_element_index_uint:
|
||||||
|
return !gl->IsGLES2() || gl->IsExtensionSupported(GLContext::OES_element_index_uint);
|
||||||
case OES_standard_derivatives:
|
case OES_standard_derivatives:
|
||||||
case WEBGL_lose_context:
|
case WEBGL_lose_context:
|
||||||
// We always support these extensions.
|
// We always support these extensions.
|
||||||
@@ -1013,7 +1015,11 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, ErrorResult& r
|
|||||||
WebGLExtensionID ext = WebGLExtensionID_unknown_extension;
|
WebGLExtensionID ext = WebGLExtensionID_unknown_extension;
|
||||||
|
|
||||||
// step 1: figure what extension is wanted
|
// 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;
|
ext = OES_texture_float;
|
||||||
}
|
}
|
||||||
@@ -1075,6 +1081,9 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, ErrorResult& r
|
|||||||
if (!IsExtensionEnabled(ext)) {
|
if (!IsExtensionEnabled(ext)) {
|
||||||
WebGLExtensionBase *obj = nullptr;
|
WebGLExtensionBase *obj = nullptr;
|
||||||
switch (ext) {
|
switch (ext) {
|
||||||
|
case OES_element_index_uint:
|
||||||
|
obj = new WebGLExtensionElementIndexUint(this);
|
||||||
|
break;
|
||||||
case OES_standard_derivatives:
|
case OES_standard_derivatives:
|
||||||
obj = new WebGLExtensionStandardDerivatives(this);
|
obj = new WebGLExtensionStandardDerivatives(this);
|
||||||
break;
|
break;
|
||||||
@@ -1439,6 +1448,8 @@ WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray<nsString>
|
|||||||
|
|
||||||
nsTArray<nsString>& arr = retval.SetValue();
|
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))
|
if (IsExtensionSupported(cx, OES_texture_float))
|
||||||
arr.AppendElement(NS_LITERAL_STRING("OES_texture_float"));
|
arr.AppendElement(NS_LITERAL_STRING("OES_texture_float"));
|
||||||
if (IsExtensionSupported(cx, OES_standard_derivatives))
|
if (IsExtensionSupported(cx, OES_standard_derivatives))
|
||||||
|
|||||||
@@ -912,6 +912,7 @@ protected:
|
|||||||
// extensions
|
// extensions
|
||||||
enum WebGLExtensionID {
|
enum WebGLExtensionID {
|
||||||
EXT_texture_filter_anisotropic,
|
EXT_texture_filter_anisotropic,
|
||||||
|
OES_element_index_uint,
|
||||||
OES_standard_derivatives,
|
OES_standard_derivatives,
|
||||||
OES_texture_float,
|
OES_texture_float,
|
||||||
WEBGL_compressed_texture_atc,
|
WEBGL_compressed_texture_atc,
|
||||||
|
|||||||
@@ -1511,6 +1511,11 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type,
|
|||||||
} else if (type == LOCAL_GL_UNSIGNED_BYTE) {
|
} else if (type == LOCAL_GL_UNSIGNED_BYTE) {
|
||||||
checked_byteCount = count;
|
checked_byteCount = count;
|
||||||
first = byteOffset;
|
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 {
|
} else {
|
||||||
return ErrorInvalidEnum("drawElements: type must be UNSIGNED_SHORT or UNSIGNED_BYTE");
|
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.
|
* 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
|
* 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,
|
* 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 both trees even if one of the two types is never
|
* 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.
|
* 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:
|
* 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
|
* 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; }
|
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,
|
// When the buffer gets updated from firstByte to lastByte,
|
||||||
// calling this method will notify the tree accordingly
|
// calling this method will notify the tree accordingly
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -441,6 +447,7 @@ void WebGLElementArrayCacheTree<T>::Update()
|
|||||||
WebGLElementArrayCache::~WebGLElementArrayCache() {
|
WebGLElementArrayCache::~WebGLElementArrayCache() {
|
||||||
delete mUint8Tree;
|
delete mUint8Tree;
|
||||||
delete mUint16Tree;
|
delete mUint16Tree;
|
||||||
|
delete mUint32Tree;
|
||||||
free(mUntypedData);
|
free(mUntypedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,6 +459,9 @@ bool WebGLElementArrayCache::BufferData(const void* ptr, size_t byteSize) {
|
|||||||
if (mUint16Tree)
|
if (mUint16Tree)
|
||||||
if (!mUint16Tree->ResizeToParentSize())
|
if (!mUint16Tree->ResizeToParentSize())
|
||||||
return false;
|
return false;
|
||||||
|
if (mUint32Tree)
|
||||||
|
if (!mUint32Tree->ResizeToParentSize())
|
||||||
|
return false;
|
||||||
mUntypedData = realloc(mUntypedData, byteSize);
|
mUntypedData = realloc(mUntypedData, byteSize);
|
||||||
if (!mUntypedData)
|
if (!mUntypedData)
|
||||||
return false;
|
return false;
|
||||||
@@ -474,6 +484,8 @@ void WebGLElementArrayCache::InvalidateTrees(size_t firstByte, size_t lastByte)
|
|||||||
mUint8Tree->Invalidate(firstByte, lastByte);
|
mUint8Tree->Invalidate(firstByte, lastByte);
|
||||||
if (mUint16Tree)
|
if (mUint16Tree)
|
||||||
mUint16Tree->Invalidate(firstByte, lastByte);
|
mUint16Tree->Invalidate(firstByte, lastByte);
|
||||||
|
if (mUint32Tree)
|
||||||
|
mUint32Tree->Invalidate(firstByte, lastByte);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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);
|
return Validate<uint8_t>(maxAllowed, firstElement, countElements);
|
||||||
if (type == LOCAL_GL_UNSIGNED_SHORT)
|
if (type == LOCAL_GL_UNSIGNED_SHORT)
|
||||||
return Validate<uint16_t>(maxAllowed, firstElement, countElements);
|
return Validate<uint16_t>(maxAllowed, firstElement, countElements);
|
||||||
|
if (type == LOCAL_GL_UNSIGNED_INT)
|
||||||
|
return Validate<uint32_t>(maxAllowed, firstElement, countElements);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t WebGLElementArrayCache::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
|
size_t WebGLElementArrayCache::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
|
||||||
size_t uint8TreeSize = mUint8Tree ? mUint8Tree->SizeOfIncludingThis(aMallocSizeOf) : 0;
|
size_t uint8TreeSize = mUint8Tree ? mUint8Tree->SizeOfIncludingThis(aMallocSizeOf) : 0;
|
||||||
size_t uint16TreeSize = mUint16Tree ? mUint16Tree->SizeOfIncludingThis(aMallocSizeOf) : 0;
|
size_t uint16TreeSize = mUint16Tree ? mUint16Tree->SizeOfIncludingThis(aMallocSizeOf) : 0;
|
||||||
|
size_t uint32TreeSize = mUint32Tree ? mUint32Tree->SizeOfIncludingThis(aMallocSizeOf) : 0;
|
||||||
return aMallocSizeOf(this) +
|
return aMallocSizeOf(this) +
|
||||||
mByteSize +
|
mByteSize +
|
||||||
uint8TreeSize +
|
uint8TreeSize +
|
||||||
uint16TreeSize;
|
uint16TreeSize +
|
||||||
|
uint32TreeSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace mozilla
|
} // end namespace mozilla
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ public:
|
|||||||
, mByteSize(0)
|
, mByteSize(0)
|
||||||
, mUint8Tree(nullptr)
|
, mUint8Tree(nullptr)
|
||||||
, mUint16Tree(nullptr)
|
, mUint16Tree(nullptr)
|
||||||
|
, mUint32Tree(nullptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~WebGLElementArrayCache();
|
~WebGLElementArrayCache();
|
||||||
@@ -73,6 +74,7 @@ private:
|
|||||||
size_t mByteSize;
|
size_t mByteSize;
|
||||||
WebGLElementArrayCacheTree<uint8_t>* mUint8Tree;
|
WebGLElementArrayCacheTree<uint8_t>* mUint8Tree;
|
||||||
WebGLElementArrayCacheTree<uint16_t>* mUint16Tree;
|
WebGLElementArrayCacheTree<uint16_t>* mUint16Tree;
|
||||||
|
WebGLElementArrayCacheTree<uint32_t>* mUint32Tree;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
21
content/canvas/src/WebGLExtensionElementIndexUint.cpp
Normal file
21
content/canvas/src/WebGLExtensionElementIndexUint.cpp
Normal file
@@ -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
|
DECL_WEBGL_EXTENSION_GOOP
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WebGLExtensionElementIndexUint
|
||||||
|
: public WebGLExtensionBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WebGLExtensionElementIndexUint(WebGLContext*);
|
||||||
|
virtual ~WebGLExtensionElementIndexUint();
|
||||||
|
|
||||||
|
DECL_WEBGL_EXTENSION_GOOP
|
||||||
|
};
|
||||||
|
|
||||||
class WebGLExtensionLoseContext
|
class WebGLExtensionLoseContext
|
||||||
: public WebGLExtensionBase
|
: public WebGLExtensionBase
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1102,6 +1102,11 @@ DOMInterfaces = {
|
|||||||
'headerFile': 'WebGLExtensions.h'
|
'headerFile': 'WebGLExtensions.h'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'WebGLExtensionElementIndexUint': {
|
||||||
|
'nativeType': 'mozilla::WebGLExtensionElementIndexUint',
|
||||||
|
'headerFile': 'WebGLExtensions.h'
|
||||||
|
},
|
||||||
|
|
||||||
'WebGLExtensionLoseContext': {
|
'WebGLExtensionLoseContext': {
|
||||||
'nativeType': 'mozilla::WebGLExtensionLoseContext',
|
'nativeType': 'mozilla::WebGLExtensionLoseContext',
|
||||||
'headerFile': 'WebGLExtensions.h'
|
'headerFile': 'WebGLExtensions.h'
|
||||||
|
|||||||
@@ -806,6 +806,11 @@ interface WebGLExtensionDepthTexture
|
|||||||
const GLenum UNSIGNED_INT_24_8_WEBGL = 0x84FA;
|
const GLenum UNSIGNED_INT_24_8_WEBGL = 0x84FA;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[NoInterfaceObject]
|
||||||
|
interface WebGLExtensionElementIndexUint
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
[NoInterfaceObject]
|
[NoInterfaceObject]
|
||||||
interface WebGLExtensionLoseContext {
|
interface WebGLExtensionLoseContext {
|
||||||
void loseContext();
|
void loseContext();
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ static const char *sExtensionNames[] = {
|
|||||||
"GL_OES_EGL_sync",
|
"GL_OES_EGL_sync",
|
||||||
"GL_OES_EGL_image_external",
|
"GL_OES_EGL_image_external",
|
||||||
"GL_EXT_packed_depth_stencil",
|
"GL_EXT_packed_depth_stencil",
|
||||||
|
"GL_OES_element_index_uint",
|
||||||
nullptr
|
nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1016,6 +1016,7 @@ public:
|
|||||||
OES_EGL_sync,
|
OES_EGL_sync,
|
||||||
OES_EGL_image_external,
|
OES_EGL_image_external,
|
||||||
EXT_packed_depth_stencil,
|
EXT_packed_depth_stencil,
|
||||||
|
OES_element_index_uint,
|
||||||
Extensions_Max
|
Extensions_Max
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user