From 38db0ec252f6a2cbbd634b6a4b93af8d0a731b9e Mon Sep 17 00:00:00 2001 From: sotaro Date: Tue, 19 Dec 2023 00:38:32 +0000 Subject: [PATCH] Bug 1867700 - Add workaround for SwapChain Present() of RenderCompositorANGLE on Windows r=gfx-reviewers,lsalzman Implement a workaround of framebuffer's SwapChain Present() that exists in chromium. Differential Revision: https://phabricator.services.mozilla.com/D195201 --- .../RenderCompositorANGLE.cpp | 33 +++++++++++++++++-- .../RenderCompositorANGLE.h | 1 + 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/gfx/webrender_bindings/RenderCompositorANGLE.cpp b/gfx/webrender_bindings/RenderCompositorANGLE.cpp index cda306284e0c..e01ac6a187d6 100644 --- a/gfx/webrender_bindings/RenderCompositorANGLE.cpp +++ b/gfx/webrender_bindings/RenderCompositorANGLE.cpp @@ -197,6 +197,7 @@ HWND RenderCompositorANGLE::GetCompositorHwnd() { bool RenderCompositorANGLE::CreateSwapChain(nsACString& aError) { MOZ_ASSERT(!UseCompositor()); + mFirstPresent = true; HWND hwnd = mWidget->AsWindows()->GetHwnd(); RefPtr dxgiDevice; @@ -449,6 +450,14 @@ RenderedFrameId RenderCompositorANGLE::EndFrame( } } + const UINT interval = + mFirstPresent || + StaticPrefs:: + gfx_webrender_dcomp_video_swap_chain_present_interval_0() + ? 0 + : 1; + const UINT flags = 0; + const LayoutDeviceIntSize& bufferSize = mBufferSize.ref(); if (mUsePartialPresent && mSwapChain1) { // Clear full render flag. @@ -483,7 +492,7 @@ RenderedFrameId RenderCompositorANGLE::EndFrame( params.pDirtyRects = rects.data(); HRESULT hr; - hr = mSwapChain1->Present1(0, 0, ¶ms); + hr = mSwapChain1->Present1(interval, flags, ¶ms); if (FAILED(hr) && hr != DXGI_STATUS_OCCLUDED) { gfxCriticalNote << "Present1 failed: " << gfx::hexa(hr); mFullRender = true; @@ -491,11 +500,31 @@ RenderedFrameId RenderCompositorANGLE::EndFrame( } } } else { - mSwapChain->Present(0, 0); + mSwapChain->Present(interval, flags); } auto end = TimeStamp::Now(); mozilla::Telemetry::Accumulate(mozilla::Telemetry::COMPOSITE_SWAP_TIME, (end - start).ToMilliseconds() * 10.); + + if (mFirstPresent && mDCLayerTree) { + // Wait for the GPU to finish executing its commands before + // committing the DirectComposition tree, or else the swapchain + // may flicker black when it's first presented. + RefPtr dxgiDevice2; + mDevice->QueryInterface((IDXGIDevice2**)getter_AddRefs(dxgiDevice2)); + MOZ_ASSERT(dxgiDevice2); + + HANDLE event = ::CreateEvent(nullptr, false, false, nullptr); + HRESULT hr = dxgiDevice2->EnqueueSetEvent(event); + if (SUCCEEDED(hr)) { + DebugOnly result = ::WaitForSingleObject(event, INFINITE); + MOZ_ASSERT(result == WAIT_OBJECT_0); + } else { + gfxCriticalNoteOnce << "EnqueueSetEvent failed: " << gfx::hexa(hr); + } + ::CloseHandle(event); + } + mFirstPresent = false; } if (mDisablingNativeCompositor) { diff --git a/gfx/webrender_bindings/RenderCompositorANGLE.h b/gfx/webrender_bindings/RenderCompositorANGLE.h index ccf37d1d6ba1..29f5652b3e07 100644 --- a/gfx/webrender_bindings/RenderCompositorANGLE.h +++ b/gfx/webrender_bindings/RenderCompositorANGLE.h @@ -151,6 +151,7 @@ class RenderCompositorANGLE : public RenderCompositor { bool mFullRender = false; // Used to know a timing of disabling native compositor. bool mDisablingNativeCompositor = false; + bool mFirstPresent = true; }; } // namespace wr