Bug 1082248 - Skip redundant deferred texture image initialization when doing full-image updates - r=jgilbert
--- a/dom/canvas/WebGL2ContextTextures.cpp
+++ b/dom/canvas/WebGL2ContextTextures.cpp
@@ -267,18 +267,29 @@ WebGL2Context::TexSubImage3D(GLenum rawT
if (!checked_neededByteLength.isValid())
return ErrorInvalidOperation("texSubImage2D: integer overflow computing the needed buffer size");
uint32_t bytesNeeded = checked_neededByteLength.value();
if (dataLength < bytesNeeded)
return ErrorInvalidOperation("texSubImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, dataLength);
- if (imageInfo.HasUninitializedImageData())
- tex->DoDeferredImageInitialization(texImageTarget, level);
+ if (imageInfo.HasUninitializedImageData()) {
+ bool coversWholeImage = xoffset == 0 &&
+ yoffset == 0 &&
+ zoffset == 0 &&
+ width == imageInfo.Width() &&
+ height == imageInfo.Height() &&
+ depth == imageInfo.Depth();
+ if (coversWholeImage) {
+ tex->SetImageDataStatus(texImageTarget, level, WebGLImageDataStatus::InitializedImageData);
+ } else {
+ tex->DoDeferredImageInitialization(texImageTarget, level);
+ }
+ }
GLenum driverType = LOCAL_GL_NONE;
GLenum driverInternalFormat = LOCAL_GL_NONE;
GLenum driverFormat = LOCAL_GL_NONE;
DriverFormatsFromEffectiveInternalFormat(gl,
existingEffectiveInternalFormat,
&driverInternalFormat,
&driverFormat,
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -589,17 +589,25 @@ WebGLContext::CopyTexSubImage2D(GLenum r
if (yoffset + height > texHeight || yoffset + height < 0)
return ErrorInvalidValue("copyTexSubImage2D: yoffset+height is too large");
if (!mBoundFramebuffer)
ClearBackbufferIfNeeded();
if (imageInfo.HasUninitializedImageData()) {
- tex->DoDeferredImageInitialization(texImageTarget, level);
+ bool coversWholeImage = xoffset == 0 &&
+ yoffset == 0 &&
+ width == texWidth &&
+ height == texHeight;
+ if (coversWholeImage) {
+ tex->SetImageDataStatus(texImageTarget, level, WebGLImageDataStatus::InitializedImageData);
+ } else {
+ tex->DoDeferredImageInitialization(texImageTarget, level);
+ }
}
TexInternalFormat internalformat;
TexType type;
UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(imageInfo.EffectiveInternalFormat(),
&internalformat, &type);
return CopyTexSubImage2D_base(texImageTarget, level, internalformat, xoffset, yoffset, x, y, width, height, true);
}
@@ -3409,18 +3417,27 @@ WebGLContext::CompressedTexSubImage2D(GL
xoffset, yoffset,
width, height,
levelInfo.Width(), levelInfo.Height(),
func, dims))
{
return;
}
- if (levelInfo.HasUninitializedImageData())
- tex->DoDeferredImageInitialization(texImageTarget, level);
+ if (levelInfo.HasUninitializedImageData()) {
+ bool coversWholeImage = xoffset == 0 &&
+ yoffset == 0 &&
+ width == levelInfo.Width() &&
+ height == levelInfo.Height();
+ if (coversWholeImage) {
+ tex->SetImageDataStatus(texImageTarget, level, WebGLImageDataStatus::InitializedImageData);
+ } else {
+ tex->DoDeferredImageInitialization(texImageTarget, level);
+ }
+ }
MakeContextCurrent();
gl->fCompressedTexSubImage2D(texImageTarget.get(), level, xoffset, yoffset, width, height, internalformat, byteLength, view.Data());
}
JS::Value
WebGLContext::GetShaderParameter(WebGLShader *shader, GLenum pname)
{
@@ -3936,19 +3953,27 @@ WebGLContext::TexSubImage2D_base(TexImag
if (!checked_neededByteLength.isValid())
return ErrorInvalidOperation("texSubImage2D: integer overflow computing the needed buffer size");
uint32_t bytesNeeded = checked_neededByteLength.value();
if (byteLength < bytesNeeded)
return ErrorInvalidOperation("texSubImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, byteLength);
- if (imageInfo.HasUninitializedImageData())
- tex->DoDeferredImageInitialization(texImageTarget, level);
-
+ if (imageInfo.HasUninitializedImageData()) {
+ bool coversWholeImage = xoffset == 0 &&
+ yoffset == 0 &&
+ width == imageInfo.Width() &&
+ height == imageInfo.Height();
+ if (coversWholeImage) {
+ tex->SetImageDataStatus(texImageTarget, level, WebGLImageDataStatus::InitializedImageData);
+ } else {
+ tex->DoDeferredImageInitialization(texImageTarget, level);
+ }
+ }
MakeContextCurrent();
size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();
uint32_t dstTexelSize = GetBitsPerTexel(existingEffectiveInternalFormat) / 8;
size_t dstPlainRowSize = dstTexelSize * width;
// There are checks above to ensure that this won't overflow.
size_t dstStride = RoundedToNextMultipleOf(dstPlainRowSize, mPixelStoreUnpackAlignment).value();
--- a/dom/canvas/WebGLTexture.h
+++ b/dom/canvas/WebGLTexture.h
@@ -108,16 +108,17 @@ public:
is_pot_assuming_nonnegative(mHeight); // negative sizes should never happen (caught in texImage2D...)
}
bool HasUninitializedImageData() const {
return mImageDataStatus == WebGLImageDataStatus::UninitializedImageData;
}
size_t MemoryUsage() const;
TexInternalFormat EffectiveInternalFormat() const { return mEffectiveInternalFormat; }
+ GLsizei Depth() const { return mDepth; }
protected:
/*
* This is the "effective internal format" of the texture,
* an official OpenGL spec concept, see
* OpenGL ES 3.0.3 spec, section 3.8.3, page 126 and below.
*/
TexInternalFormat mEffectiveInternalFormat;