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