Bug 1285047 - Initialize all 3D texture data. - r=mtseng
MozReview-Commit-ID: 8ddc9yvV8tA
--- 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)
{