diff --git a/content/canvas/compiledtest/TestWebGLElementArrayCache.cpp b/content/canvas/compiledtest/TestWebGLElementArrayCache.cpp index 5fa4a701dc63..b5f05ea58b03 100644 --- a/content/canvas/compiledtest/TestWebGLElementArrayCache.cpp +++ b/content/canvas/compiledtest/TestWebGLElementArrayCache.cpp @@ -48,9 +48,15 @@ T RandomInteger(T a, T b) template 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 @@ -79,6 +85,7 @@ void CheckValidate(WebGLElementArrayCache& c, size_t firstByte, size_t countByte { CheckValidateOneType(c, firstByte, countBytes); CheckValidateOneType(c, firstByte, countBytes); + CheckValidateOneType(c, firstByte, countBytes); } template @@ -151,6 +158,7 @@ int main(int argc, char *argv[]) CheckSanity(); CheckSanity(); + CheckSanity(); CheckUintOverflow(); CheckUintOverflow(); diff --git a/content/canvas/src/Makefile.in b/content/canvas/src/Makefile.in index 76095e93f10e..47cff6df562e 100644 --- a/content/canvas/src/Makefile.in +++ b/content/canvas/src/Makefile.in @@ -40,6 +40,7 @@ CPPSRCS += \ WebGLExtensionCompressedTextureS3TC.cpp \ WebGLExtensionDebugRendererInfo.cpp \ WebGLExtensionDepthTexture.cpp \ + WebGLExtensionElementIndexUint.cpp \ WebGLExtensionLoseContext.cpp \ WebGLExtensionStandardDerivatives.cpp \ WebGLExtensionTextureFilterAnisotropic.cpp \ diff --git a/content/canvas/src/WebGLContext.cpp b/content/canvas/src/WebGLContext.cpp index 907853921f2c..611906fed097 100644 --- a/content/canvas/src/WebGLContext.cpp +++ b/content/canvas/src/WebGLContext.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 nsTArray& 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)) diff --git a/content/canvas/src/WebGLContext.h b/content/canvas/src/WebGLContext.h index 5c9d09c01089..5ffc98c2a598 100644 --- a/content/canvas/src/WebGLContext.h +++ b/content/canvas/src/WebGLContext.h @@ -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, diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 508ee6abed30..4940f12a26c4 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -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"); } diff --git a/content/canvas/src/WebGLElementArrayCache.cpp b/content/canvas/src/WebGLElementArrayCache.cpp index 791640e8cdf4..5780935500b8 100644 --- a/content/canvas/src/WebGLElementArrayCache.cpp +++ b/content/canvas/src/WebGLElementArrayCache.cpp @@ -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 static WebGLElementArrayCacheTree*& Run(WebGLElementArrayCache *b) { return b->mUint16Tree; } }; +template<> +struct TreeForType +{ + static WebGLElementArrayCacheTree*& Run(WebGLElementArrayCache *b) { return b->mUint32Tree; } +}; + // When the buffer gets updated from firstByte to lastByte, // calling this method will notify the tree accordingly template @@ -441,6 +447,7 @@ void WebGLElementArrayCacheTree::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 @@ -541,16 +553,20 @@ bool WebGLElementArrayCache::Validate(GLenum type, uint32_t maxAllowed, size_t f return Validate(maxAllowed, firstElement, countElements); if (type == LOCAL_GL_UNSIGNED_SHORT) return Validate(maxAllowed, firstElement, countElements); + if (type == LOCAL_GL_UNSIGNED_INT) + return Validate(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 diff --git a/content/canvas/src/WebGLElementArrayCache.h b/content/canvas/src/WebGLElementArrayCache.h index 3646f60cf2e5..68d1f582ea64 100644 --- a/content/canvas/src/WebGLElementArrayCache.h +++ b/content/canvas/src/WebGLElementArrayCache.h @@ -42,6 +42,7 @@ public: , mByteSize(0) , mUint8Tree(nullptr) , mUint16Tree(nullptr) + , mUint32Tree(nullptr) {} ~WebGLElementArrayCache(); @@ -73,6 +74,7 @@ private: size_t mByteSize; WebGLElementArrayCacheTree* mUint8Tree; WebGLElementArrayCacheTree* mUint16Tree; + WebGLElementArrayCacheTree* mUint32Tree; }; diff --git a/content/canvas/src/WebGLExtensionElementIndexUint.cpp b/content/canvas/src/WebGLExtensionElementIndexUint.cpp new file mode 100644 index 000000000000..49ab44527e3a --- /dev/null +++ b/content/canvas/src/WebGLExtensionElementIndexUint.cpp @@ -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) diff --git a/content/canvas/src/WebGLExtensions.h b/content/canvas/src/WebGLExtensions.h index 504295d414ee..fe7352181af1 100644 --- a/content/canvas/src/WebGLExtensions.h +++ b/content/canvas/src/WebGLExtensions.h @@ -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 { diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index a12d4e8cb3f8..e7166932708c 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -1102,6 +1102,11 @@ DOMInterfaces = { 'headerFile': 'WebGLExtensions.h' }, +'WebGLExtensionElementIndexUint': { + 'nativeType': 'mozilla::WebGLExtensionElementIndexUint', + 'headerFile': 'WebGLExtensions.h' +}, + 'WebGLExtensionLoseContext': { 'nativeType': 'mozilla::WebGLExtensionLoseContext', 'headerFile': 'WebGLExtensions.h' diff --git a/dom/webidl/WebGLRenderingContext.webidl b/dom/webidl/WebGLRenderingContext.webidl index b458599e5d03..dffb49429b62 100644 --- a/dom/webidl/WebGLRenderingContext.webidl +++ b/dom/webidl/WebGLRenderingContext.webidl @@ -806,6 +806,11 @@ interface WebGLExtensionDepthTexture const GLenum UNSIGNED_INT_24_8_WEBGL = 0x84FA; }; +[NoInterfaceObject] +interface WebGLExtensionElementIndexUint +{ +}; + [NoInterfaceObject] interface WebGLExtensionLoseContext { void loseContext(); diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index a74541149444..2c1aa0ce4ac6 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -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 }; diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h index 303e4fdf2fde..8b11a6c10881 100644 --- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -1016,6 +1016,7 @@ public: OES_EGL_sync, OES_EGL_image_external, EXT_packed_depth_stencil, + OES_element_index_uint, Extensions_Max };