From 9c6c3991f08f52d960155d90dc2fe54cf32fc90c Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Tue, 3 Apr 2012 16:42:06 -0700 Subject: [PATCH] Bug 738126 - Enforce spec for webgl.generateMipmap, and zero is not PoT - r=bjacob --- content/canvas/src/WebGLContext.h | 24 ++++++++++++++++++----- content/canvas/src/WebGLContextGL.cpp | 19 +++++++++++------- content/canvas/src/WebGLContextUtils.cpp | 25 +++++++++++++++++++++++- 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/content/canvas/src/WebGLContext.h b/content/canvas/src/WebGLContext.h index d2b2d0d21f8b..1fa253668859 100644 --- a/content/canvas/src/WebGLContext.h +++ b/content/canvas/src/WebGLContext.h @@ -127,9 +127,10 @@ struct WebGLTexelPremultiplicationOp { int GetWebGLTexelFormat(GLenum format, GLenum type); +// Zero is not an integer power of two. inline bool is_pot_assuming_nonnegative(WebGLsizei x) { - return (x & (x-1)) == 0; + return x && (x & (x-1)) == 0; } /* Each WebGL object class WebGLFoo wants to: @@ -585,6 +586,7 @@ public: nsresult ErrorOutOfMemory(const char *fmt = 0, ...); const char *ErrorName(GLenum error); + bool IsTextureFormatCompressed(GLenum format); nsresult DummyFramebufferOperation(const char *info); @@ -1247,14 +1249,26 @@ public: class ImageInfo : public WebGLRectangleObject { public: - ImageInfo() : mFormat(0), mType(0), mIsDefined(false) {} + ImageInfo() + : mFormat(0) + , mType(0) + , mIsDefined(false) + {} + ImageInfo(WebGLsizei width, WebGLsizei height, WebGLenum format, WebGLenum type) - : WebGLRectangleObject(width, height), mFormat(format), mType(type), mIsDefined(true) {} + : WebGLRectangleObject(width, height) + , mFormat(format) + , mType(type) + , mIsDefined(true) + {} bool operator==(const ImageInfo& a) const { - return mWidth == a.mWidth && mHeight == a.mHeight && - mFormat == a.mFormat && mType == a.mType; + return mIsDefined == a.mIsDefined && + mWidth == a.mWidth && + mHeight == a.mHeight && + mFormat == a.mFormat && + mType == a.mType; } bool operator!=(const ImageInfo& a) const { return !(*this == a); diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 13365d8684d1..8532c7d83c30 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -1911,15 +1911,20 @@ WebGLContext::GenerateMipmap(WebGLenum target) WebGLTexture *tex = activeBoundTextureForTarget(target); if (!tex) - return ErrorInvalidOperation("generateMipmap: no texture is bound to this target"); + return ErrorInvalidOperation("generateMipmap: No texture is bound to this target."); - if (!tex->IsFirstImagePowerOfTwo()) { - return ErrorInvalidOperation("generateMipmap: the width or height of this texture is not a power of two"); - } + if (!tex->HasImageInfoAt(0, 0)) + return ErrorInvalidOperation("generateMipmap: Level zero of texture is not defined."); - if (!tex->AreAllLevel0ImageInfosEqual()) { - return ErrorInvalidOperation("generateMipmap: the six faces of this cube map have different dimensions, format, or type."); - } + if (!tex->IsFirstImagePowerOfTwo()) + return ErrorInvalidOperation("generateMipmap: Level zero of texture does not have power-of-two width and height."); + + GLenum format = tex->ImageInfoAt(0, 0).Format(); + if (IsTextureFormatCompressed(format)) + return ErrorInvalidOperation("generateMipmap: Texture data at level zero is compressed."); + + if (!tex->AreAllLevel0ImageInfosEqual()) + return ErrorInvalidOperation("generateMipmap: The six faces of this cube map have different dimensions, format, or type."); tex->SetGeneratedMipmap(); diff --git a/content/canvas/src/WebGLContextUtils.cpp b/content/canvas/src/WebGLContextUtils.cpp index 898fb9a05fea..f448fe138eb7 100644 --- a/content/canvas/src/WebGLContextUtils.cpp +++ b/content/canvas/src/WebGLContextUtils.cpp @@ -239,4 +239,27 @@ WebGLContext::ErrorName(GLenum error) NS_ABORT(); return "[unknown WebGL error!]"; } -}; +} + +bool +WebGLContext::IsTextureFormatCompressed(GLenum format) +{ + switch(format) { + case LOCAL_GL_RGB: + case LOCAL_GL_RGBA: + case LOCAL_GL_ALPHA: + case LOCAL_GL_LUMINANCE: + case LOCAL_GL_LUMINANCE_ALPHA: + return false; + + case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + return true; + } + + NS_NOTREACHED("Invalid WebGL texture format?"); + NS_ABORT(); + return false; +}