Bug 1305832 - Only glClear for ANGLE's ANGLE_depth_texture textures. - r=ethlin
authorJeff Gilbert <jdashg@gmail.com>
Thu, 08 Dec 2016 12:58:23 -1000
changeset 370952 ea8f02c6edba660b7a6d55d1ec3c71d6cc9a158d
parent 370951 128cffb39a39a4d024a3ce780649b11b62c74125
child 370953 80265d017a0777e31b7f4e751f09feea823c66ce
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersethlin
bugs1305832
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1305832 - Only glClear for ANGLE's ANGLE_depth_texture textures. - r=ethlin MozReview-Commit-ID: H6yE1ib2TRI
dom/canvas/WebGLContext.cpp
dom/canvas/WebGLTextureUpload.cpp
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -2216,77 +2216,55 @@ Intersect(uint32_t srcSize, int32_t dstS
     // [=====|==]    // dst box
     // ^-----^
     *out_intStartInDst = std::max<int32_t>(0, 0 - dstStartInSrc);
 
     int32_t intEndInSrc = std::min<int32_t>(srcSize, dstStartInSrc + dstSize);
     *out_intSize = std::max<int32_t>(0, intEndInSrc - *out_intStartInSrc);
 }
 
-static bool
-ZeroTexImageWithClear(WebGLContext* webgl, GLContext* gl, TexImageTarget target,
-                      GLuint tex, uint32_t level, const webgl::FormatUsageInfo* usage,
-                      uint32_t width, uint32_t height)
+static void
+ZeroANGLEDepthTexture(WebGLContext* webgl, GLuint tex,
+                      const webgl::FormatUsageInfo* usage, uint32_t width,
+                      uint32_t height)
 {
-    MOZ_ASSERT(gl->IsCurrent());
-
-    ScopedFramebuffer scopedFB(gl);
-    ScopedBindFramebuffer scopedBindFB(gl, scopedFB.FB());
-
-    const auto format = usage->format;
-
+    const auto& format = usage->format;
     GLenum attachPoint = 0;
     GLbitfield clearBits = 0;
 
-    if (format->IsColorFormat()) {
-        attachPoint = LOCAL_GL_COLOR_ATTACHMENT0;
-        clearBits = LOCAL_GL_COLOR_BUFFER_BIT;
-    }
-
     if (format->d) {
         attachPoint = LOCAL_GL_DEPTH_ATTACHMENT;
         clearBits |= LOCAL_GL_DEPTH_BUFFER_BIT;
     }
 
     if (format->s) {
         attachPoint = (format->d ? LOCAL_GL_DEPTH_STENCIL_ATTACHMENT
                                  : LOCAL_GL_STENCIL_ATTACHMENT);
         clearBits |= LOCAL_GL_STENCIL_BUFFER_BIT;
     }
 
     MOZ_RELEASE_ASSERT(attachPoint && clearBits, "GFX: No bits cleared.");
 
-    {
-        gl::GLContext::LocalErrorScope errorScope(*gl);
-        MOZ_ASSERT(target != LOCAL_GL_TEXTURE_2D_ARRAY &&
-                   target != LOCAL_GL_TEXTURE_3D);
-        gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, attachPoint, target.get(), tex,
-                                  level);
-        if (errorScope.GetError()) {
-            MOZ_ASSERT(false);
-            return false;
-        }
-    }
-
-    auto status = gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
-    if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE)
-        return false;
-
-    {
-        gl::GLContext::LocalErrorScope errorScope(*gl);
-
-        const bool fakeNoAlpha = false;
-        webgl->ForceClearFramebufferWithDefaultValues(clearBits, fakeNoAlpha);
-        if (errorScope.GetError()) {
-            MOZ_ASSERT(false);
-            return false;
-        }
-    }
-
-    return true;
+    ////
+    const auto& gl = webgl->gl;
+    MOZ_ASSERT(gl->IsCurrent());
+
+    ScopedFramebuffer scopedFB(gl);
+    ScopedBindFramebuffer scopedBindFB(gl, scopedFB.FB());
+
+    gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, attachPoint, LOCAL_GL_TEXTURE_2D,
+                              tex, 0);
+
+    const auto& status = gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
+    MOZ_RELEASE_ASSERT(status == LOCAL_GL_FRAMEBUFFER_COMPLETE);
+
+    ////
+
+    const bool fakeNoAlpha = false;
+    webgl->ForceClearFramebufferWithDefaultValues(clearBits, fakeNoAlpha);
 }
 
 bool
 ZeroTextureData(WebGLContext* webgl, const char* funcName, GLuint tex,
                 TexImageTarget target, uint32_t level,
                 const webgl::FormatUsageInfo* usage, uint32_t width, uint32_t height,
                 uint32_t depth)
 {
@@ -2355,22 +2333,26 @@ ZeroTextureData(WebGLContext* webgl, con
                                                    width, height, depth, sizedFormat,
                                                    byteCount, zeros.get());
         return !error;
     }
 
     const auto driverUnpackInfo = usage->idealUnpack;
     MOZ_RELEASE_ASSERT(driverUnpackInfo, "GFX: ideal unpack info not set.");
 
-    if (!webgl->IsWebGL2() && usage->format->d) {
+    if (webgl->IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture) &&
+        gl->IsANGLE() &&
+        usage->format->d)
+    {
         // ANGLE_depth_texture does not allow uploads, so we have to clear.
-        const bool success = ZeroTexImageWithClear(webgl, gl, target, tex, level, usage,
-                                                   width, height);
-        MOZ_ASSERT(success);
-        return success;
+        // (Restriction because of D3D9)
+        MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D);
+        MOZ_ASSERT(level == 0);
+        ZeroANGLEDepthTexture(webgl, tex, usage, width, height);
+        return true;
     }
 
     const webgl::PackingInfo packing = driverUnpackInfo->ToPacking();
 
     const auto bytesPerPixel = webgl::BytesPerPixel(packing);
 
     CheckedUint32 checkedByteCount = bytesPerPixel;
     checkedByteCount *= width;
--- a/dom/canvas/WebGLTextureUpload.cpp
+++ b/dom/canvas/WebGLTextureUpload.cpp
@@ -1952,26 +1952,39 @@ DoCopyTexOrSubImage(WebGLContext* webgl,
     Intersect(srcTotalHeight, yWithinSrc, dstHeight, &readY, &writeY, &rwHeight);
 
     ////
 
     GLenum error = 0;
     do {
         const auto& idealUnpack = dstUsage->idealUnpack;
         if (!isSubImage) {
-            const auto& pi = idealUnpack->ToPacking();
-            const auto& bpp = BytesPerPixel(pi);
-            const UniqueBuffer zeros(calloc(1, dstWidth * dstHeight * bpp));
-            if (!zeros.get()) {
-                webgl->ErrorOutOfMemory("%s: Ran out of memory allocating zeros.",
-                                        funcName);
-                return false;
+            UniqueBuffer buffer;
+
+            if (rwWidth != dstWidth || rwHeight != dstHeight) {
+                const auto& pi = idealUnpack->ToPacking();
+                CheckedUint32 byteCount = BytesPerPixel(pi);
+                byteCount *= dstWidth;
+                byteCount *= dstHeight;
+
+                if (byteCount.isValid()) {
+                    buffer = calloc(1, byteCount.value());
+                }
+
+                if (!buffer.get()) {
+                    webgl->ErrorOutOfMemory("%s: Ran out of memory allocating zeros.",
+                                            funcName);
+                    return false;
+                }
             }
+
+            const ScopedUnpackReset unpackReset(webgl);
+            gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1);
             error = DoTexImage(gl, target, level, idealUnpack, dstWidth, dstHeight, 1,
-                               zeros.get());
+                               buffer.get());
             if (error)
                 break;
         }
 
         if (!rwWidth || !rwHeight) {
             // There aren't any pixels to copy, so we're 'done'.
             return true;
         }