Bug 1081125 - WebGL2 3D textures - Part 3: implement texStorage3D - r=jgilbert
authorBenoit Jacob <bjacob@mozilla.com>
Mon, 13 Oct 2014 19:42:24 -0400
changeset 210269 160578cdf1919f0bfd570f6d910d3fddfce24612
parent 210268 191b4351c850c480dc62467cf593c8a23f2eb3e9
child 210270 212571e28648a736581a3ee54877bd037fbfb95c
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjgilbert
bugs1081125
milestone35.0a1
Bug 1081125 - WebGL2 3D textures - Part 3: implement texStorage3D - r=jgilbert
dom/canvas/WebGL2ContextTextures.cpp
--- a/dom/canvas/WebGL2ContextTextures.cpp
+++ b/dom/canvas/WebGL2ContextTextures.cpp
@@ -110,24 +110,19 @@ WebGL2Context::ValidateTexStorage(GLenum
         return false;
 
     // GL_INVALID_VALUE is generated if width, height or levels are less than 1.
     if (width < 1)  { ErrorInvalidValue("%s: width is < 1", info);  return false; }
     if (height < 1) { ErrorInvalidValue("%s: height is < 1", info); return false; }
     if (depth < 1)  { ErrorInvalidValue("%s: depth is < 1", info);  return false; }
     if (levels < 1) { ErrorInvalidValue("%s: levels is < 1", info); return false; }
 
-    // The following check via FloorLog2 only requires a depth value if target is TEXTURE_3D.
-    bool is3D = (target != LOCAL_GL_TEXTURE_3D);
-    if (!is3D)
-        depth = 1;
-
     // GL_INVALID_OPERATION is generated if levels is greater than floor(log2(max(width, height, depth)))+1.
-    if (FloorLog2(std::max(std::max(width, height), depth))+1 < levels) {
-        ErrorInvalidOperation("%s: levels > floor(log2(max(width, height%s)))+1", info, is3D ? ", depth" : "");
+    if (FloorLog2(std::max(std::max(width, height), depth)) + 1 < levels) {
+        ErrorInvalidOperation("%s: too many levels for given texture dimensions", info);
         return false;
     }
 
     return true;
 }
 
 // -------------------------------------------------------------------------
 // Texture objects
@@ -135,17 +130,17 @@ WebGL2Context::ValidateTexStorage(GLenum
 void
 WebGL2Context::TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
 {
     if (IsContextLost())
         return;
 
     // GL_INVALID_ENUM is generated if target is not one of the accepted target enumerants.
     if (target != LOCAL_GL_TEXTURE_2D && target != LOCAL_GL_TEXTURE_CUBE_MAP)
-        return ErrorInvalidEnum("texStorage2D: target is not TEXTURE_2D or TEXTURE_CUBE_MAP.");
+        return ErrorInvalidEnum("texStorage2D: target is not TEXTURE_2D or TEXTURE_CUBE_MAP");
 
     if (!ValidateTexStorage(target, levels, internalformat, width, height, 1, "texStorage2D"))
         return;
 
     WebGLTexture* tex = activeBoundTextureForTarget(target);
     tex->SetImmutable();
 
     const size_t facesCount = (target == LOCAL_GL_TEXTURE_2D) ? 1 : 6;
@@ -164,17 +159,43 @@ WebGL2Context::TexStorage2D(GLenum targe
 
     gl->fTexStorage2D(target, levels, internalformat, width, height);
 }
 
 void
 WebGL2Context::TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat,
                             GLsizei width, GLsizei height, GLsizei depth)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (IsContextLost())
+        return;
+
+    // GL_INVALID_ENUM is generated if target is not one of the accepted target enumerants.
+    if (target != LOCAL_GL_TEXTURE_3D)
+        return ErrorInvalidEnum("texStorage3D: target is not TEXTURE_3D");
+
+    if (!ValidateTexStorage(target, levels, internalformat, width, height, depth, "texStorage3D"))
+        return;
+
+    WebGLTexture* tex = activeBoundTextureForTarget(target);
+    tex->SetImmutable();
+
+    GLsizei w = width;
+    GLsizei h = height;
+    GLsizei d = depth;
+    for (size_t l = 0; l < size_t(levels); l++) {
+        tex->SetImageInfo(TexImageTargetForTargetAndFace(target, 0),
+                          l, w, h, d,
+                          internalformat,
+                          WebGLImageDataStatus::UninitializedImageData);
+        w = std::max(1, w >> 1);
+        h = std::max(1, h >> 1);
+        d = std::max(1, d >> 1);
+    }
+
+    gl->fTexStorage3D(target, levels, internalformat, width, height, depth);
 }
 
 void
 WebGL2Context::TexSubImage3D(GLenum target, GLint level,
                              GLint xoffset, GLint yoffset, GLint zoffset,
                              GLsizei width, GLsizei height, GLsizei depth,
                              GLenum format, GLenum type, const Nullable<dom::ArrayBufferView>& pixels,
                              ErrorResult& rv)