--- 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)