Bug 1285047 - Initialize all 3D texture data. - r=mtseng draft
authorJeff Gilbert <jgilbert@mozilla.com>
Wed, 06 Jul 2016 15:08:20 -0700
changeset 384683 e808cfd41a2cca674ae487017edef17877806f4a
parent 384060 dbb31bcad5a1f60a35b5600ea1578d9b9fa55237
child 524774 1a673becb2f8ce21687dbba104ecebb32d7faedd
push id22346
push userbmo:jgilbert@mozilla.com
push dateWed, 06 Jul 2016 22:57:11 +0000
reviewersmtseng
bugs1285047
milestone50.0a1
Bug 1285047 - Initialize all 3D texture data. - r=mtseng MozReview-Commit-ID: 8ddc9yvV8tA
dom/canvas/WebGLFramebuffer.cpp
--- a/dom/canvas/WebGLFramebuffer.cpp
+++ b/dom/canvas/WebGLFramebuffer.cpp
@@ -969,122 +969,127 @@ WebGLFramebuffer::ValidateAndInitAttachm
 
         mContext->ErrorInvalidFramebufferOperation("%s: %s.", funcName,
                                                    errorText.BeginReading());
         return false;
     }
 
     // Cool! We've checked out ok. Just need to initialize.
 
+    //////
     // Check if we need to initialize anything
-    {
-        bool hasUninitializedAttachments = false;
+
+    std::vector<WebGLFBAttachPoint*> tex3DToClear;
+
+    const auto fnGatherIf3D = [&](WebGLFBAttachPoint& attach) {
+        if (!attach.Texture())
+            return false;
 
-        if (mColorAttachment0.HasImage() && IsDrawBuffer(0))
-            hasUninitializedAttachments |= mColorAttachment0.HasUninitializedImageData();
+        const auto& info = attach.Texture()->ImageInfoAt(attach.ImageTarget(),
+                                                         attach.MipLevel());
+        if (info.mDepth == 1)
+            return false;
+
+        tex3DToClear.push_back(&attach);
+        return true;
+    };
 
-        size_t i = 1;
-        for (const auto& cur : mMoreColorAttachments) {
-            if (cur.HasImage() && IsDrawBuffer(i))
-                hasUninitializedAttachments |= cur.HasUninitializedImageData();
+    //////
+
+    uint32_t clearBits = 0;
+    std::vector<GLenum> drawBuffersForClear(1 + mMoreColorAttachments.Size(),
+                                            LOCAL_GL_NONE);
+
+    std::vector<WebGLFBAttachPoint*> attachmentsToClear;
+    attachmentsToClear.reserve(1 + mMoreColorAttachments.Size() + 3);
 
-            ++i;
-        }
+    const auto fnGatherColor = [&](WebGLFBAttachPoint& attach, uint32_t colorAttachNum) {
+        if (!IsDrawBuffer(colorAttachNum) || !attach.HasUninitializedImageData())
+            return;
+
+        if (fnGatherIf3D(attach))
+            return;
+
+        attachmentsToClear.push_back(&attach);
+
+        clearBits |= LOCAL_GL_COLOR_BUFFER_BIT;
+        drawBuffersForClear[colorAttachNum] = LOCAL_GL_COLOR_ATTACHMENT0 + colorAttachNum;
+    };
+
+    const auto fnGatherOther = [&](WebGLFBAttachPoint& attach, GLenum attachClearBits) {
+        if (!attach.HasUninitializedImageData())
+            return;
 
-        if (mDepthAttachment.HasImage())
-            hasUninitializedAttachments |= mDepthAttachment.HasUninitializedImageData();
-        if (mStencilAttachment.HasImage())
-            hasUninitializedAttachments |= mStencilAttachment.HasUninitializedImageData();
-        if (mDepthStencilAttachment.HasImage())
-            hasUninitializedAttachments |= mDepthStencilAttachment.HasUninitializedImageData();
+        if (fnGatherIf3D(attach))
+            return;
+
+        attachmentsToClear.push_back(&attach);
+
+        clearBits |= attachClearBits;
+    };
 
-        if (!hasUninitializedAttachments)
-            return true;
+    //////
+
+    fnGatherColor(mColorAttachment0, 0);
+
+    size_t colorAttachNum = 1;
+    for (auto& cur : mMoreColorAttachments) {
+        fnGatherColor(cur, colorAttachNum);
+        ++colorAttachNum;
     }
 
-    // Get buffer-bit-mask and color-attachment-mask-list
-    uint32_t clearBits = 0;
-    std::vector<GLenum> tempDrawBuffers(1 + mMoreColorAttachments.Size(), LOCAL_GL_NONE);
-
-    if (mColorAttachment0.HasUninitializedImageData() && IsDrawBuffer(0)) {
-        clearBits |= LOCAL_GL_COLOR_BUFFER_BIT;
-        tempDrawBuffers[0] = LOCAL_GL_COLOR_ATTACHMENT0;
-    }
+    fnGatherOther(mDepthAttachment, LOCAL_GL_DEPTH_BUFFER_BIT);
+    fnGatherOther(mStencilAttachment, LOCAL_GL_STENCIL_BUFFER_BIT);
+    fnGatherOther(mDepthStencilAttachment,
+                  LOCAL_GL_DEPTH_BUFFER_BIT | LOCAL_GL_STENCIL_BUFFER_BIT);
 
-    size_t i = 1;
-    for (const auto& cur : mMoreColorAttachments) {
-        if (cur.HasUninitializedImageData() && IsDrawBuffer(i)) {
-            clearBits |= LOCAL_GL_COLOR_BUFFER_BIT;
-            tempDrawBuffers[i] = LOCAL_GL_COLOR_ATTACHMENT0 + i;
-        }
-
-        ++i;
-    }
-
-    if (mDepthAttachment.HasUninitializedImageData() ||
-        mDepthStencilAttachment.HasUninitializedImageData())
-    {
-        clearBits |= LOCAL_GL_DEPTH_BUFFER_BIT;
-    }
-
-    if (mStencilAttachment.HasUninitializedImageData() ||
-        mDepthStencilAttachment.HasUninitializedImageData())
-    {
-        clearBits |= LOCAL_GL_STENCIL_BUFFER_BIT;
-    }
+    //////
 
     mContext->MakeContextCurrent();
 
-    const auto fnDrawBuffers = [this](const std::vector<GLenum>& list) {
-        const GLenum* ptr = nullptr;
-        if (list.size()) {
-            ptr = &(list[0]);
+    if (clearBits) {
+        const auto fnDrawBuffers = [this](const std::vector<GLenum>& list) {
+            this->mContext->gl->fDrawBuffers(list.size(), list.data());
+        };
+
+        const auto drawBufferExt = WebGLExtensionID::WEBGL_draw_buffers;
+        const bool hasDrawBuffers = (mContext->IsWebGL2() ||
+                                     mContext->IsExtensionEnabled(drawBufferExt));
+
+        if (hasDrawBuffers) {
+            fnDrawBuffers(drawBuffersForClear);
         }
-        this->mContext->gl->fDrawBuffers(list.size(), ptr);
-    };
+
+        ////////////
+
+        // Clear!
+        {
+            gl::ScopedBindFramebuffer autoBind(mContext->gl, mGLName);
 
-    const auto drawBufferExt = WebGLExtensionID::WEBGL_draw_buffers;
-    const bool hasDrawBuffers = (mContext->IsWebGL2() ||
-                                 mContext->IsExtensionEnabled(drawBufferExt));
+            mContext->ForceClearFramebufferWithDefaultValues(clearBits, false);
+        }
 
-    if (hasDrawBuffers) {
-        fnDrawBuffers(tempDrawBuffers);
+        if (hasDrawBuffers) {
+            fnDrawBuffers(mDrawBuffers);
+        }
+
+        for (auto* cur : attachmentsToClear) {
+            cur->SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
+        }
     }
 
-    // Clear!
-    {
-        // This FB maybe bind to GL_READ_FRAMEBUFFER and glClear only
-        // clear GL_DRAW_FRAMEBUFFER. So bind FB to GL_DRAW_FRAMEBUFFER
-        // here.
-        gl::ScopedBindFramebuffer autoFB(mContext->gl, mGLName);
-        mContext->ForceClearFramebufferWithDefaultValues(clearBits, false);
-    }
-
-    if (hasDrawBuffers) {
-        fnDrawBuffers(mDrawBuffers);
-    }
+    //////
 
-    // Mark all the uninitialized images as initialized.
-    if (mDepthAttachment.HasUninitializedImageData())
-        mDepthAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
-    if (mStencilAttachment.HasUninitializedImageData())
-        mStencilAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
-    if (mDepthStencilAttachment.HasUninitializedImageData())
-        mDepthStencilAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
-
-    if (mColorAttachment0.HasUninitializedImageData() && IsDrawBuffer(0)) {
-        mColorAttachment0.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
-    }
-
-    i = 1;
-    for (auto& cur : mMoreColorAttachments) {
-        if (cur.HasUninitializedImageData() && IsDrawBuffer(i))
-            cur.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
-
-        ++i;
+    for (auto* attach : tex3DToClear) {
+        auto* tex = attach->Texture();
+        if (!tex->InitializeImageData(funcName, attach->ImageTarget(),
+                                      attach->MipLevel()))
+        {
+            return false;
+        }
     }
 
     return true;
 }
 
 static void
 FinalizeDrawAndReadBuffers(gl::GLContext* gl, bool isColorBufferDefined)
 {