Bug 1926862 - Add transparency support to RenderCompositorANGLE. r=gfx-reviewers,nical

Bring back some of the code from
https://hg.mozilla.org/mozilla-central/rev/5942e11048ea to achieve this.

Partial present seems to work fine, so we can just keep it working.

Differential Revision: https://phabricator.services.mozilla.com/D226886
This commit is contained in:
Emilio Cobos Álvarez 2024-11-08 16:09:40 +00:00
parent 2059f55557
commit ecb1eeb9ed
11 changed files with 76 additions and 39 deletions

View File

@ -226,6 +226,7 @@ bool RenderCompositorANGLE::CreateSwapChain(nsACString& aError) {
return false;
}
const bool alpha = ShouldUseAlpha();
if (!mSwapChain && dxgiFactory2) {
RefPtr<IDXGISwapChain1> swapChain1;
bool useTripleBuffering = false;
@ -237,7 +238,6 @@ bool RenderCompositorANGLE::CreateSwapChain(nsACString& aError) {
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
bool useFlipSequential = gfx::gfxVars::UseWebRenderFlipSequentialWin();
if (useFlipSequential && !mWidget->AsWindows()->GetCompositorHwnd()) {
useFlipSequential = false;
@ -258,6 +258,8 @@ bool RenderCompositorANGLE::CreateSwapChain(nsACString& aError) {
desc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
desc.Scaling = DXGI_SCALING_STRETCH;
}
desc.AlphaMode =
alpha ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE;
desc.Flags = 0;
hr = dxgiFactory2->CreateSwapChainForHwnd(
@ -268,6 +270,7 @@ bool RenderCompositorANGLE::CreateSwapChain(nsACString& aError) {
mSwapChain = swapChain1;
mSwapChain1 = swapChain1;
mUseTripleBuffering = useTripleBuffering;
mSwapChainUsingAlpha = alpha;
} else if (useFlipSequential) {
gfxCriticalNoteOnce << "FLIP_SEQUENTIAL is not supported. Fallback";
}
@ -307,7 +310,7 @@ bool RenderCompositorANGLE::CreateSwapChain(nsACString& aError) {
hr = mSwapChain->QueryInterface(
(IDXGISwapChain1**)getter_AddRefs(swapChain1));
if (SUCCEEDED(hr)) {
mSwapChain1 = swapChain1;
mSwapChain1 = std::move(swapChain1);
}
}
@ -341,7 +344,7 @@ void RenderCompositorANGLE::CreateSwapChainForDCompIfPossible(
// When compositor is enabled, CompositionSurface is used for rendering.
// It does not support triple buffering.
bool useTripleBuffering =
const bool useTripleBuffering =
gfx::gfxVars::UseWebRenderTripleBufferingWin() && !UseCompositor();
RefPtr<IDXGISwapChain1> swapChain1 =
CreateSwapChainForDComp(useTripleBuffering);
@ -396,7 +399,10 @@ RefPtr<IDXGISwapChain1> RenderCompositorANGLE::CreateSwapChainForDComp(
// DXGI_SCALING_NONE caused swap chain creation failure.
desc.Scaling = DXGI_SCALING_STRETCH;
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
const bool alpha = ShouldUseAlpha();
// See if we need to use transparency.
desc.AlphaMode =
alpha ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE;
desc.Flags = 0;
hr = dxgiFactory2->CreateSwapChainForComposition(mDevice, &desc, nullptr,
@ -404,17 +410,30 @@ RefPtr<IDXGISwapChain1> RenderCompositorANGLE::CreateSwapChainForDComp(
if (SUCCEEDED(hr) && swapChain1) {
DXGI_RGBA color = {1.0f, 1.0f, 1.0f, 1.0f};
swapChain1->SetBackgroundColor(&color);
mSwapChainUsingAlpha = alpha;
return swapChain1;
}
return nullptr;
}
bool RenderCompositorANGLE::ShouldUseAlpha() const {
return mWidget->AsWindows()->TransparencyModeIs(
widget::TransparencyMode::Transparent);
}
bool RenderCompositorANGLE::BeginFrame() {
mWidget->AsWindows()->UpdateCompositorWndSizeIfNecessary();
if (!UseCompositor() && !ResizeBufferIfNeeded()) {
return false;
if (!UseCompositor()) {
if (!mSwapChainUsingAlpha && ShouldUseAlpha()) {
if (!RecreateNonNativeCompositorSwapChain()) {
return false;
}
}
if (!ResizeBufferIfNeeded()) {
return false;
}
}
if (!MakeCurrent()) {
@ -788,15 +807,9 @@ gfx::DeviceResetReason RenderCompositorANGLE::IsContextLost(bool aForce) {
return layers::DXGIErrorToDeviceResetReason(reason);
}
bool RenderCompositorANGLE::UseCompositor() {
if (!mUseNativeCompositor) {
return false;
}
if (!mDCLayerTree || !gfx::gfxVars::UseWebRenderCompositor()) {
return false;
}
return true;
bool RenderCompositorANGLE::UseCompositor() const {
return mUseNativeCompositor && mDCLayerTree &&
gfx::gfxVars::UseWebRenderCompositor();
}
bool RenderCompositorANGLE::SupportAsyncScreenshot() {
@ -887,21 +900,28 @@ void RenderCompositorANGLE::EnableNativeCompositor(bool aEnable) {
mUseNativeCompositor = false;
mDCLayerTree->DisableNativeCompositor();
if (!RecreateNonNativeCompositorSwapChain()) {
gfxCriticalNote << "Failed to re-create SwapChain";
RenderThread::Get()->HandleWebRenderError(WebRenderError::NEW_SURFACE);
return;
}
mDisablingNativeCompositor = true;
}
bool RenderCompositorANGLE::RecreateNonNativeCompositorSwapChain() {
DestroyEGLSurface();
mBufferSize.reset();
RefPtr<IDXGISwapChain1> swapChain1 =
CreateSwapChainForDComp(mUseTripleBuffering);
if (swapChain1) {
mSwapChain = swapChain1;
mDCLayerTree->SetDefaultSwapChain(swapChain1);
ResizeBufferIfNeeded();
} else {
gfxCriticalNote << "Failed to re-create SwapChain";
RenderThread::Get()->HandleWebRenderError(WebRenderError::NEW_SURFACE);
return;
if (!swapChain1) {
return false;
}
mDisablingNativeCompositor = true;
mSwapChain = swapChain1;
mSwapChain1 = swapChain1;
mDCLayerTree->SetDefaultSwapChain(swapChain1);
return ResizeBufferIfNeeded();
}
void RenderCompositorANGLE::InitializeUsePartialPresent() {

View File

@ -30,7 +30,7 @@ namespace wr {
class DCLayerTree;
class RenderCompositorANGLE : public RenderCompositor {
class RenderCompositorANGLE final : public RenderCompositor {
public:
static UniquePtr<RenderCompositor> Create(
const RefPtr<widget::CompositorWidget>& aWidget, nsACString& aError);
@ -110,7 +110,8 @@ class RenderCompositorANGLE : public RenderCompositor {
bool* aNeedsYFlip) override;
protected:
bool UseCompositor();
bool UseCompositor() const;
bool RecreateNonNativeCompositorSwapChain();
void InitializeUsePartialPresent();
void InsertGraphicsCommandsFinishedWaitQuery(
RenderedFrameId aRenderedFrameId);
@ -125,6 +126,7 @@ class RenderCompositorANGLE : public RenderCompositor {
RefPtr<ID3D11Query> GetD3D11Query();
void ReleaseNativeCompositorResources();
HWND GetCompositorHwnd();
bool ShouldUseAlpha() const;
RefPtr<gl::GLContext> mGL;
@ -152,6 +154,8 @@ class RenderCompositorANGLE : public RenderCompositor {
// Used to know a timing of disabling native compositor.
bool mDisablingNativeCompositor = false;
bool mFirstPresent = true;
// Wether we're currently using alpha.
bool mSwapChainUsingAlpha = false;
};
} // namespace wr

View File

@ -66,6 +66,10 @@ void CompositorWidgetChild::NotifyVisibilityUpdated(bool aIsFullyOccluded) {
Unused << SendNotifyVisibilityUpdated(aIsFullyOccluded);
};
void CompositorWidgetChild::UpdateTransparency(TransparencyMode aMode) {
Unused << SendUpdateTransparency(aMode);
}
void CompositorWidgetChild::ClearTransparentWindow() {
Unused << SendClearTransparentWindow();
}

View File

@ -35,7 +35,7 @@ class CompositorWidgetChild final : public PCompositorWidgetChild,
bool OnWindowResize(const LayoutDeviceIntSize& aSize) override;
void NotifyVisibilityUpdated(bool aIsFullyOccluded) override;
void UpdateTransparency(TransparencyMode) override {}
void UpdateTransparency(TransparencyMode) override;
void ClearTransparentWindow() override;
mozilla::ipc::IPCResult RecvObserveVsync() override;

View File

@ -138,6 +138,12 @@ bool CompositorWidgetParent::GetWindowIsFullyOccluded() const {
return mIsFullyOccluded;
}
mozilla::ipc::IPCResult CompositorWidgetParent::RecvUpdateTransparency(
const TransparencyMode& aMode) {
SetTransparencyMode(aMode);
return IPC_OK();
}
mozilla::ipc::IPCResult CompositorWidgetParent::RecvClearTransparentWindow() {
gfx::CriticalSectionAutoEnter lock(&mPresentLock);

View File

@ -53,6 +53,8 @@ class CompositorWidgetParent final : public PCompositorWidgetParent,
mozilla::ipc::IPCResult RecvLeavePresentLock() override;
mozilla::ipc::IPCResult RecvNotifyVisibilityUpdated(
const bool& aIsFullyOccluded) override;
mozilla::ipc::IPCResult RecvUpdateTransparency(
const TransparencyMode& aTransparencyMode) override;
mozilla::ipc::IPCResult RecvClearTransparentWindow() override;
void ActorDestroy(ActorDestroyReason aWhy) override;
@ -73,9 +75,6 @@ class CompositorWidgetParent final : public PCompositorWidgetParent,
gfx::CriticalSection mPresentLock;
// Transparency handling.
mozilla::Atomic<uint32_t, MemoryOrdering::Relaxed> mTransparencyMode;
// Visibility handling.
mozilla::Atomic<nsSizeMode, MemoryOrdering::Relaxed> mSizeMode;
mozilla::Atomic<bool, MemoryOrdering::Relaxed> mIsFullyOccluded;

View File

@ -51,7 +51,6 @@ InProcessWinCompositorWidget::InProcessWinCompositorWidget(
mWindow(aWindow),
mWnd(reinterpret_cast<HWND>(aInitData.hWnd())),
mTransparentSurfaceLock("mTransparentSurfaceLock"),
mTransparencyMode(uint32_t(aInitData.transparencyMode())),
mMemoryDC(nullptr),
mCompositeDC(nullptr),
mLockedBackBufferData(nullptr) {
@ -265,7 +264,7 @@ void InProcessWinCompositorWidget::UpdateTransparency(TransparencyMode aMode) {
return;
}
mTransparencyMode = uint32_t(aMode);
SetTransparencyMode(aMode);
mTransparentSurface = nullptr;
mMemoryDC = nullptr;

View File

@ -83,11 +83,6 @@ class InProcessWinCompositorWidget final
// Transparency handling.
mozilla::Mutex mTransparentSurfaceLock MOZ_UNANNOTATED;
mozilla::Atomic<uint32_t, MemoryOrdering::Relaxed> mTransparencyMode;
bool TransparencyModeIs(TransparencyMode aMode) const {
return TransparencyMode(uint32_t(mTransparencyMode)) == aMode;
}
// Visibility handling.
mozilla::Atomic<bool, MemoryOrdering::Relaxed> mIsFullyOccluded;

View File

@ -34,6 +34,7 @@ parent:
sync EnterPresentLock();
sync LeavePresentLock();
async NotifyVisibilityUpdated(bool aIsFullyOccluded);
async UpdateTransparency(TransparencyMode aMode);
sync ClearTransparentWindow();
async __delete__();

View File

@ -32,6 +32,7 @@ WinCompositorWidget::WinCompositorWidget(
mSetParentCompleted(false),
mWidgetKey(aInitData.widgetKey()),
mWnd(reinterpret_cast<HWND>(aInitData.hWnd())),
mTransparencyMode(uint32_t(aInitData.transparencyMode())),
mCompositorWnds(nullptr, nullptr) {
MOZ_ASSERT(mWnd && ::IsWindow(mWnd));
}

View File

@ -80,13 +80,21 @@ class WinCompositorWidget : public CompositorWidget {
const HWND aParentWnd) = 0;
virtual void SetRootLayerTreeID(const layers::LayersId& aRootLayerTreeId) = 0;
bool TransparencyModeIs(TransparencyMode aMode) const {
return TransparencyMode(uint32_t(mTransparencyMode)) == aMode;
}
protected:
bool mSetParentCompleted;
void SetTransparencyMode(TransparencyMode aMode) {
mTransparencyMode = uint32_t(aMode);
}
bool mSetParentCompleted = false;
private:
uintptr_t mWidgetKey;
HWND mWnd;
mozilla::Atomic<uint32_t, MemoryOrdering::Relaxed> mTransparencyMode;
WinCompositorWnds mCompositorWnds;
LayoutDeviceIntSize mLastCompositorWndSize;