From 3ae501809c194c8df3da1b78bde13507cc55cf63 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Mon, 15 Jun 2020 18:26:02 +0000 Subject: [PATCH] Bug 1632249 - NON_PREMULT TextureClient iff NON_PREMULT CanvasClient. r=handyman Differential Revision: https://phabricator.services.mozilla.com/D78800 --- dom/canvas/ClientWebGLContext.cpp | 27 +++++++++---------- dom/canvas/ClientWebGLContext.h | 5 ++-- .../nsICanvasRenderingContextInternal.h | 2 +- gfx/layers/CanvasRenderer.cpp | 5 ++-- gfx/layers/CanvasRenderer.h | 3 ++- gfx/layers/ShareableCanvasRenderer.cpp | 3 ++- gfx/layers/client/CanvasClient.cpp | 6 +++++ 7 files changed, 29 insertions(+), 22 deletions(-) diff --git a/dom/canvas/ClientWebGLContext.cpp b/dom/canvas/ClientWebGLContext.cpp index d8dcc9538746..cfb04ed70e99 100644 --- a/dom/canvas/ClientWebGLContext.cpp +++ b/dom/canvas/ClientWebGLContext.cpp @@ -421,7 +421,6 @@ void ClientWebGLContext::Present(WebGLFramebufferJS* const fb, const layers::TextureType type) { if (!mIsCanvasDirty && !fb) return; mIsCanvasDirty = false; - mFrontBufferSnapshot = nullptr; Run(fb ? fb->mId : 0, type); } @@ -882,7 +881,8 @@ already_AddRefed ClientWebGLContext::GetSurfaceSnapshot( return ret.forget(); } -RefPtr ClientWebGLContext::GetFrontBufferSnapshot() { +RefPtr ClientWebGLContext::GetFrontBufferSnapshot( + const bool requireAlphaPremult) { const FuncScope funcScope(*this, ""); if (IsContextLost()) return nullptr; const auto notLost = @@ -890,20 +890,19 @@ RefPtr ClientWebGLContext::GetFrontBufferSnapshot() { const auto& options = mNotLost->info.options; - if (!mFrontBufferSnapshot) { - mFrontBufferSnapshot = Run(); - if (!mFrontBufferSnapshot) return nullptr; + auto snapshot = Run(); + if (!snapshot) return nullptr; - if (options.alpha && !options.premultipliedAlpha) { - const auto nonPremultSurf = mFrontBufferSnapshot; - const auto& size = nonPremultSurf->GetSize(); - const auto format = nonPremultSurf->GetFormat(); - mFrontBufferSnapshot = - gfx::Factory::CreateDataSourceSurface(size, format, /*zero=*/false); - gfxUtils::PremultiplyDataSurface(nonPremultSurf, mFrontBufferSnapshot); - } + if (requireAlphaPremult && options.alpha && !options.premultipliedAlpha) { + const auto nonPremultSurf = snapshot; + const auto& size = nonPremultSurf->GetSize(); + const auto format = nonPremultSurf->GetFormat(); + snapshot = + gfx::Factory::CreateDataSourceSurface(size, format, /*zero=*/false); + gfxUtils::PremultiplyDataSurface(nonPremultSurf, snapshot); } - return mFrontBufferSnapshot; + + return snapshot; } RefPtr ClientWebGLContext::BackBufferSnapshot() { diff --git a/dom/canvas/ClientWebGLContext.h b/dom/canvas/ClientWebGLContext.h index e7b246f4a3b3..3ef00377569e 100644 --- a/dom/canvas/ClientWebGLContext.h +++ b/dom/canvas/ClientWebGLContext.h @@ -723,8 +723,6 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal, bool mIsCanvasDirty = false; uvec2 mRequestedSize = {}; - RefPtr mFrontBufferSnapshot; - public: explicit ClientWebGLContext(bool webgl2); @@ -997,7 +995,8 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal, void Present(WebGLFramebufferJS*, layers::TextureType); Maybe GetFrontBuffer(WebGLFramebufferJS*, layers::TextureType); - RefPtr GetFrontBufferSnapshot() override; + RefPtr GetFrontBufferSnapshot( + bool requireAlphaPremult = true) override; private: RefPtr BackBufferSnapshot(); diff --git a/dom/canvas/nsICanvasRenderingContextInternal.h b/dom/canvas/nsICanvasRenderingContextInternal.h index f241e610b634..050e39c36571 100644 --- a/dom/canvas/nsICanvasRenderingContextInternal.h +++ b/dom/canvas/nsICanvasRenderingContextInternal.h @@ -137,7 +137,7 @@ class nsICanvasRenderingContextInternal : public nsISupports, virtual already_AddRefed GetSurfaceSnapshot( gfxAlphaType* out_alphaType = nullptr) = 0; - virtual RefPtr GetFrontBufferSnapshot() { + virtual RefPtr GetFrontBufferSnapshot(bool) { return GetSurfaceSnapshot(); } diff --git a/gfx/layers/CanvasRenderer.cpp b/gfx/layers/CanvasRenderer.cpp index 0676d167c7cd..3a2aabd2a5d9 100644 --- a/gfx/layers/CanvasRenderer.cpp +++ b/gfx/layers/CanvasRenderer.cpp @@ -46,7 +46,8 @@ bool CanvasRenderer::IsDataValid(const CanvasRendererData& aData) const { return mData.GetContext() == aData.GetContext(); } -std::shared_ptr CanvasRenderer::BorrowSnapshot() const { +std::shared_ptr CanvasRenderer::BorrowSnapshot( + const bool requireAlphaPremult) const { const auto context = mData.GetContext(); if (!context) return nullptr; const auto& provider = context->GetBufferProvider(); @@ -57,7 +58,7 @@ std::shared_ptr CanvasRenderer::BorrowSnapshot() const { ss = provider->BorrowSnapshot(); } if (!ss) { - ss = context->GetFrontBufferSnapshot(); + ss = context->GetFrontBufferSnapshot(requireAlphaPremult); } if (!ss) return nullptr; diff --git a/gfx/layers/CanvasRenderer.h b/gfx/layers/CanvasRenderer.h index 814751929d95..6285f9bfd58f 100644 --- a/gfx/layers/CanvasRenderer.h +++ b/gfx/layers/CanvasRenderer.h @@ -137,7 +137,8 @@ class CanvasRenderer : public RefCounted { return nullptr; } - std::shared_ptr BorrowSnapshot() const; + std::shared_ptr BorrowSnapshot( + bool requireAlphaPremult = true) const; protected: void FirePreTransactionCallback() const; diff --git a/gfx/layers/ShareableCanvasRenderer.cpp b/gfx/layers/ShareableCanvasRenderer.cpp index 4a4a6e4fe9ca..93ccdfa4b400 100644 --- a/gfx/layers/ShareableCanvasRenderer.cpp +++ b/gfx/layers/ShareableCanvasRenderer.cpp @@ -159,7 +159,8 @@ void ShareableCanvasRenderer::UpdateCompositableClient() { const RefPtr dt = tc->BorrowDrawTarget(); - const auto borrowed = BorrowSnapshot(); + const bool requireAlphaPremult = false; + const auto borrowed = BorrowSnapshot(requireAlphaPremult); if (!borrowed) return nullptr; dt->CopySurface(borrowed->mSurf, {{0, 0}, size}, {0, 0}); diff --git a/gfx/layers/client/CanvasClient.cpp b/gfx/layers/client/CanvasClient.cpp index 412af5561c6c..3068df8dece8 100644 --- a/gfx/layers/client/CanvasClient.cpp +++ b/gfx/layers/client/CanvasClient.cpp @@ -31,6 +31,12 @@ namespace layers { void CanvasClient::UseTexture(TextureClient* const aTexture) { MOZ_ASSERT(aTexture); + const auto isClientNonPremult = + bool(mTextureFlags & TextureFlags::NON_PREMULTIPLIED); + const auto isTextureNonPremult = + bool(aTexture->GetFlags() & TextureFlags::NON_PREMULTIPLIED); + MOZ_ALWAYS_TRUE(isTextureNonPremult == isClientNonPremult); + bool changed = false; if (aTexture != mFrontBuffer) {