Bug 1082248 - Skip redundant deferred texture image initialization when doing full-image updates - r=jgilbert
authorBenoit Jacob <bjacob@mozilla.com>
Tue, 14 Oct 2014 08:54:52 -0400
changeset 210345 1e5f45339d3f3dea4f43c078b4c93fe752e5d204
parent 210344 bc87d0ccf6a9cf51056fd889576f83335887915c
child 210346 8f524c6e6fc3f372c6cb7ecd77c9d9268c6f11a9
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjgilbert
bugs1082248
milestone36.0a1
Bug 1082248 - Skip redundant deferred texture image initialization when doing full-image updates - r=jgilbert
dom/canvas/WebGL2ContextTextures.cpp
dom/canvas/WebGLContextGL.cpp
dom/canvas/WebGLTexture.h
--- 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;