author | Jon Buckley <jon@jbuckley.ca> |
Mon, 13 May 2013 09:22:30 -0400 | |
changeset 131775 | 6cc9b139557bf49b5e1ca78198c7e79ae29a8729 |
parent 131774 | e4fad18913b34a1bc357ebc83556d3752d75ad2f |
child 131776 | a7b3ef7ded5c3aa9967feda0b4a73497e51d0a77 |
push id | 24671 |
push user | ryanvm@gmail.com |
push date | Mon, 13 May 2013 20:32:09 +0000 |
treeherder | mozilla-central@81dd97739fa1 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bjacob |
bugs | 738867 |
milestone | 23.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/content/canvas/compiledtest/TestWebGLElementArrayCache.cpp +++ b/content/canvas/compiledtest/TestWebGLElementArrayCache.cpp @@ -43,19 +43,25 @@ T RandomInteger(T a, T b) { T result(a + rand() % (b - a + 1)); return result; } 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> void CheckValidateOneType(WebGLElementArrayCache& c, size_t firstByte, size_t countBytes) { size_t first = firstByte / sizeof(T); size_t count = countBytes / sizeof(T); @@ -74,16 +80,17 @@ void CheckValidateOneType(WebGLElementAr VERIFY(!c.Validate(type, 0, first, count)); } } void CheckValidate(WebGLElementArrayCache& c, size_t firstByte, size_t countBytes) { CheckValidateOneType<uint8_t>(c, firstByte, countBytes); CheckValidateOneType<uint16_t>(c, firstByte, countBytes); + CheckValidateOneType<uint32_t>(c, firstByte, countBytes); } template<typename T> void CheckSanity() { const size_t numElems = 64; // should be significantly larger than tree leaf size to // ensure we exercise some nontrivial tree-walking T data[numElems] = {1,0,3,1,2,6,5,4}; // intentionally specify only 8 elements for now @@ -146,16 +153,17 @@ void CheckUintOverflow() } int main(int argc, char *argv[]) { srand(0); // do not want a random seed here. CheckSanity<uint8_t>(); CheckSanity<uint16_t>(); + CheckSanity<uint32_t>(); CheckUintOverflow<uint8_t>(); CheckUintOverflow<uint16_t>(); nsTArray<uint8_t> v, vsub; WebGLElementArrayCache b; for (int maxBufferSize = 1; maxBufferSize <= 4096; maxBufferSize *= 2) {
--- a/content/canvas/src/Makefile.in +++ b/content/canvas/src/Makefile.in @@ -35,16 +35,17 @@ CPPSRCS += \ WebGLContextValidate.cpp \ WebGLElementArrayCache.cpp \ WebGLExtensionBase.cpp \ WebGLExtensionCompressedTextureATC.cpp \ WebGLExtensionCompressedTexturePVRTC.cpp \ WebGLExtensionCompressedTextureS3TC.cpp \ WebGLExtensionDebugRendererInfo.cpp \ WebGLExtensionDepthTexture.cpp \ + WebGLExtensionElementIndexUint.cpp \ WebGLExtensionLoseContext.cpp \ WebGLExtensionStandardDerivatives.cpp \ WebGLExtensionTextureFilterAnisotropic.cpp \ WebGLExtensionTextureFloat.cpp \ WebGLFramebuffer.cpp \ WebGLObjectModel.cpp \ WebGLProgram.cpp \ WebGLRenderbuffer.cpp \
--- a/content/canvas/src/WebGLContext.cpp +++ b/content/canvas/src/WebGLContext.cpp @@ -938,16 +938,18 @@ WebGLContext::MozGetUnderlyingParamStrin bool WebGLContext::IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) const { if (mDisableExtensions) { return false; } 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. return true; case OES_texture_float: return gl->IsExtensionSupported(gl->IsGLES2() ? GLContext::OES_texture_float : GLContext::ARB_texture_float); case EXT_texture_filter_anisotropic: @@ -1008,17 +1010,21 @@ WebGLContext::GetExtension(JSContext *cx if (!IsContextStable()) return nullptr; NS_LossyConvertUTF16toASCII name(aName); 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; } else if (CompareWebGLExtensionName(name, "OES_standard_derivatives")) { ext = OES_standard_derivatives; } else if (CompareWebGLExtensionName(name, "EXT_texture_filter_anisotropic")) @@ -1070,16 +1076,19 @@ WebGLContext::GetExtension(JSContext *cx if (!IsExtensionSupported(cx, ext)) { return nullptr; } // step 3: if the extension hadn't been previously been created, create it now, thus enabling it 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; case EXT_texture_filter_anisotropic: obj = new WebGLExtensionTextureFilterAnisotropic(this); break; case WEBGL_lose_context: obj = new WebGLExtensionLoseContext(this); @@ -1434,16 +1443,18 @@ void WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray<nsString> > &retval) { retval.SetNull(); if (!IsContextStable()) return; 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)) arr.AppendElement(NS_LITERAL_STRING("OES_standard_derivatives")); if (IsExtensionSupported(cx, EXT_texture_filter_anisotropic)) arr.AppendElement(NS_LITERAL_STRING("EXT_texture_filter_anisotropic")); if (IsExtensionSupported(cx, WEBGL_lose_context)) arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_lose_context"));
--- a/content/canvas/src/WebGLContext.h +++ b/content/canvas/src/WebGLContext.h @@ -907,16 +907,17 @@ protected: // script correctly handled the event. We are waiting for the context to // be restored. ContextLostAwaitingRestore }; // extensions enum WebGLExtensionID { EXT_texture_filter_anisotropic, + OES_element_index_uint, OES_standard_derivatives, OES_texture_float, WEBGL_compressed_texture_atc, WEBGL_compressed_texture_pvrtc, WEBGL_compressed_texture_s3tc, WEBGL_debug_renderer_info, WEBGL_depth_texture, WEBGL_lose_context,
--- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -1506,16 +1506,21 @@ WebGLContext::DrawElements(WebGLenum mod if (type == LOCAL_GL_UNSIGNED_SHORT) { checked_byteCount = 2 * CheckedUint32(count); if (byteOffset % 2 != 0) return ErrorInvalidOperation("drawElements: invalid byteOffset for UNSIGNED_SHORT (must be a multiple of 2)"); first = byteOffset / 2; } 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"); } if (!checked_byteCount.isValid()) return ErrorInvalidValue("drawElements: overflow in byteCount"); // If there is no current program, this is silently ignored.
--- a/content/canvas/src/WebGLElementArrayCache.cpp +++ b/content/canvas/src/WebGLElementArrayCache.cpp @@ -101,18 +101,18 @@ namespace mozilla { * specified in the drawElements call. This means that we may potentially have to store caches for * multiple element types, for the same element array buffer. Since we don't know yet how many * element types we'll eventually support (extensions add more), the concern about memory usage is serious. * This is addressed by sSkippedBottomTreeLevels as explained above. Of course, in the typical * case where each element array buffer is only ever used with one type, this is also addressed * 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 * can only keep track of an invalidated interval, from |mFirstInvalidatedLeaf| to |mLastInvalidatedLeaf|. * The problem is that if one does two small, far-apart partial buffer updates, the resulting invalidated * area is very large even though only a small part of the array really needed to be invalidated. * The real solution to this problem would be to use a smarter data structure to keep track of the * invalidated area, probably an interval tree. Meanwhile, we can probably live with the current situation @@ -324,16 +324,22 @@ struct TreeForType<uint8_t> }; template<> 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> void WebGLElementArrayCacheTree<T>::Invalidate(size_t firstByte, size_t lastByte) { lastByte = std::min(lastByte, mNumLeaves * sElementsPerLeaf * sizeof(T) - 1); if (firstByte > lastByte) { return; @@ -436,27 +442,31 @@ void WebGLElementArrayCacheTree<T>::Upda } mInvalidated = false; } WebGLElementArrayCache::~WebGLElementArrayCache() { delete mUint8Tree; delete mUint16Tree; + delete mUint32Tree; free(mUntypedData); } bool WebGLElementArrayCache::BufferData(const void* ptr, size_t byteSize) { mByteSize = byteSize; if (mUint8Tree) if (!mUint8Tree->ResizeToParentSize()) return false; if (mUint16Tree) if (!mUint16Tree->ResizeToParentSize()) return false; + if (mUint32Tree) + if (!mUint32Tree->ResizeToParentSize()) + return false; mUntypedData = realloc(mUntypedData, byteSize); if (!mUntypedData) return false; BufferSubData(0, ptr, byteSize); return true; } void WebGLElementArrayCache::BufferSubData(size_t pos, const void* ptr, size_t updateByteSize) { @@ -469,16 +479,18 @@ void WebGLElementArrayCache::BufferSubDa } void WebGLElementArrayCache::InvalidateTrees(size_t firstByte, size_t lastByte) { if (mUint8Tree) mUint8Tree->Invalidate(firstByte, lastByte); if (mUint16Tree) mUint16Tree->Invalidate(firstByte, lastByte); + if (mUint32Tree) + mUint32Tree->Invalidate(firstByte, lastByte); } template<typename T> bool WebGLElementArrayCache::Validate(uint32_t maxAllowed, size_t firstElement, size_t countElements) { // 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()) return true; @@ -536,21 +548,25 @@ bool WebGLElementArrayCache::Validate(ui tree->LeafForElement(lastElement)); } bool WebGLElementArrayCache::Validate(GLenum type, uint32_t maxAllowed, size_t firstElement, size_t countElements) { if (type == LOCAL_GL_UNSIGNED_BYTE) 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
--- a/content/canvas/src/WebGLElementArrayCache.h +++ b/content/canvas/src/WebGLElementArrayCache.h @@ -37,16 +37,17 @@ public: template<typename T> T Element(size_t i) const { return Elements<T>()[i]; } WebGLElementArrayCache() : mUntypedData(nullptr) , mByteSize(0) , mUint8Tree(nullptr) , mUint16Tree(nullptr) + , mUint32Tree(nullptr) {} ~WebGLElementArrayCache(); size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const; private: @@ -68,14 +69,15 @@ private: friend struct WebGLElementArrayCacheTree; template<typename T> friend struct TreeForType; void* mUntypedData; size_t mByteSize; WebGLElementArrayCacheTree<uint8_t>* mUint8Tree; WebGLElementArrayCacheTree<uint16_t>* mUint16Tree; + WebGLElementArrayCacheTree<uint32_t>* mUint32Tree; }; } // end namespace mozilla #endif // WEBGLELEMENTARRAYCACHE_H
new file mode 100644 --- /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)
--- a/content/canvas/src/WebGLExtensions.h +++ b/content/canvas/src/WebGLExtensions.h @@ -82,16 +82,26 @@ class WebGLExtensionDepthTexture { public: WebGLExtensionDepthTexture(WebGLContext*); virtual ~WebGLExtensionDepthTexture(); DECL_WEBGL_EXTENSION_GOOP }; +class WebGLExtensionElementIndexUint + : public WebGLExtensionBase +{ +public: + WebGLExtensionElementIndexUint(WebGLContext*); + virtual ~WebGLExtensionElementIndexUint(); + + DECL_WEBGL_EXTENSION_GOOP +}; + class WebGLExtensionLoseContext : public WebGLExtensionBase { public: WebGLExtensionLoseContext(WebGLContext*); virtual ~WebGLExtensionLoseContext(); void LoseContext();
--- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -1097,16 +1097,21 @@ DOMInterfaces = { 'headerFile': 'WebGLExtensions.h' }, 'WebGLExtensionDebugRendererInfo': { 'nativeType': 'mozilla::WebGLExtensionDebugRendererInfo', 'headerFile': 'WebGLExtensions.h' }, +'WebGLExtensionElementIndexUint': { + 'nativeType': 'mozilla::WebGLExtensionElementIndexUint', + 'headerFile': 'WebGLExtensions.h' +}, + 'WebGLExtensionLoseContext': { 'nativeType': 'mozilla::WebGLExtensionLoseContext', 'headerFile': 'WebGLExtensions.h' }, 'WebGLExtensionStandardDerivatives': { 'nativeType': 'mozilla::WebGLExtensionStandardDerivatives', 'headerFile': 'WebGLExtensions.h'
--- a/dom/webidl/WebGLRenderingContext.webidl +++ b/dom/webidl/WebGLRenderingContext.webidl @@ -802,16 +802,21 @@ interface WebGLExtensionDebugRendererInf [NoInterfaceObject] interface WebGLExtensionDepthTexture { const GLenum UNSIGNED_INT_24_8_WEBGL = 0x84FA; }; [NoInterfaceObject] +interface WebGLExtensionElementIndexUint +{ +}; + +[NoInterfaceObject] interface WebGLExtensionLoseContext { void loseContext(); void restoreContext(); }; [NoInterfaceObject] interface WebGLExtensionTextureFilterAnisotropic {
--- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -75,16 +75,17 @@ static const char *sExtensionNames[] = { "GL_OES_rgb8_rgba8", "GL_ARB_robustness", "GL_EXT_robustness", "GL_ARB_sync", "GL_OES_EGL_image", "GL_OES_EGL_sync", "GL_OES_EGL_image_external", "GL_EXT_packed_depth_stencil", + "GL_OES_element_index_uint", nullptr }; static int64_t sTextureMemoryUsage = 0; static int64_t GetTextureMemoryUsage() {
--- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -1011,16 +1011,17 @@ public: OES_rgb8_rgba8, ARB_robustness, EXT_robustness, ARB_sync, OES_EGL_image, OES_EGL_sync, OES_EGL_image_external, EXT_packed_depth_stencil, + OES_element_index_uint, Extensions_Max }; bool IsExtensionSupported(GLExtensions aKnownExtension) const { return mAvailableExtensions[aKnownExtension]; } void MarkExtensionUnsupported(GLExtensions aKnownExtension) {