Fix conformance/textures/misc/tex-storage-2d. draft
authorJeff Gilbert <jdashg@gmail.com>
Thu, 17 Dec 2015 16:16:53 -0800
changeset 316094 29ed303d6ede7ce878e821a3c0c3959a9ee63e55
parent 316093 8d98a0c78d8991c670f19f991cb1da276a883027
child 316095 c536f648af8eababfaedd548bc4d85e95f5b1408
push id8514
push userjgilbert@mozilla.com
push dateFri, 18 Dec 2015 00:24:33 +0000
milestone45.0a1
Fix conformance/textures/misc/tex-storage-2d.
dom/canvas/WebGLTextureUpload.cpp
--- a/dom/canvas/WebGLTextureUpload.cpp
+++ b/dom/canvas/WebGLTextureUpload.cpp
@@ -314,24 +314,21 @@ ValidateTexImage(WebGLContext* webgl, We
                  WebGLTexture::ImageInfo** const out_imageInfo)
 {
     // Check level
     if (level < 0) {
         webgl->ErrorInvalidValue("%s: `level` must be >= 0.", funcName);
         return false;
     }
 
-    if (level > WebGLTexture::kMaxLevelCount) {
+    if (level >= WebGLTexture::kMaxLevelCount) {
         webgl->ErrorInvalidValue("%s: `level` is too large.", funcName);
         return false;
     }
 
-    // Right-shift is only defined for bits-1, so 31 for GLsizei.
-    MOZ_ASSERT(level <= 31);
-
     WebGLTexture::ImageInfo& imageInfo = texture->ImageInfoAt(target, level);
 
     *out_imageInfo = &imageInfo;
     return true;
 }
 
 
 // For *TexImage*
@@ -447,21 +444,16 @@ WebGLTexture::ValidateTexImageSpecificat
 // For *TexSubImage*
 bool
 WebGLTexture::ValidateTexImageSelection(const char* funcName, TexImageTarget target,
                                         GLint level, GLint xOffset, GLint yOffset,
                                         GLint zOffset, GLsizei width, GLsizei height,
                                         GLsizei depth,
                                         WebGLTexture::ImageInfo** const out_imageInfo)
 {
-    if (mImmutable) {
-        mContext->ErrorInvalidOperation("%s: Specified texture is immutable.", funcName);
-        return false;
-    }
-
     // The conformance test wants bad arg checks before imageInfo checks.
     if (xOffset < 0 || yOffset < 0 || zOffset < 0 ||
         width < 0 || height < 0 || depth < 0)
     {
         mContext->ErrorInvalidValue("%s: Offsets and dimensions must be >=0.", funcName);
         return false;
     }
 
@@ -911,20 +903,18 @@ WebGLTexture::TexStorage(const char* fun
                          GLenum sizedFormat, GLsizei width, GLsizei height, GLsizei depth)
 {
     // Check levels
     if (levels < 1) {
         mContext->ErrorInvalidValue("%s: `levels` must be >= 1.", funcName);
         return;
     }
 
-    if (levels > 31) {
-        // Right-shift is only defined for bits-1, so 31 for GLsizei.
-        // Besides,
-        mContext->ErrorInvalidValue("%s: `level` is too large.", funcName);
+    if (!width || !height || !depth) {
+        mContext->ErrorInvalidValue("%s: Dimensions must be non-zero.", funcName);
         return;
     }
 
     const TexImageTarget testTarget = IsCubeMap() ? LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X
                                                   : target.get();
     const GLint testLevel = 0;
     const GLint border = 0;
 
@@ -953,16 +943,33 @@ WebGLTexture::TexStorage(const char* fun
                                                     testLevel, dstFormat, width, height,
                                                     depth))
         {
             return;
         }
     }
 
     ////////////////////////////////////
+
+    const auto lastLevel = levels - 1;
+    MOZ_ASSERT(lastLevel <= 31, "Right-shift is only defined for bits-1.");
+
+    const uint32_t lastLevelWidth = uint32_t(width) >> lastLevel;
+    const uint32_t lastLevelHeight = uint32_t(height) >> lastLevel;
+    const uint32_t lastLevelDepth = uint32_t(depth) >> lastLevel;
+
+    if (!lastLevelWidth && !lastLevelHeight && !lastLevelDepth) {
+        mContext->ErrorInvalidOperation("%s: Too many levels requested for the given"
+                                        " dimensions. (levels: %u, width: %u, height: %u,"
+                                        " depth: %u)",
+                                        funcName, levels, width, height, depth);
+        return;
+    }
+
+    ////////////////////////////////////
     // Do the thing!
 
     mContext->gl->MakeCurrent();
 
     GLenum error = DoTexStorage(mContext->gl, target.get(), levels, sizedFormat, width,
                                 height, depth);
 
     if (error == LOCAL_GL_OUT_OF_MEMORY) {
@@ -981,16 +988,18 @@ WebGLTexture::TexStorage(const char* fun
     // Update our specification data.
 
     const bool isDataInitialized = false;
     const WebGLTexture::ImageInfo newInfo(dstUsage, width, height, depth,
                                           isDataInitialized);
     SetImageInfosAtLevel(0, newInfo);
 
     PopulateMipChain(0, levels-1);
+
+    mImmutable = true;
 }
 
 ////////////////////////////////////////
 // Tex(Sub)Image
 
 static bool
 ValidateUnpackEnums(const webgl::PackingInfo& pi, WebGLContext* webgl,
                     const char* funcName)