From 912b7f8ef19ffde56b4a5fd64a69afcc93032725 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Thu, 22 Jul 2021 22:58:57 +0000 Subject: [PATCH] Bug 1721537 - Split out WindowRenderer base class from LayerManager. r=miko Depends on D120439 Differential Revision: https://phabricator.services.mozilla.com/D120440 --- dom/animation/KeyframeEffect.cpp | 4 +- dom/base/nsContentUtils.cpp | 10 +- dom/base/nsContentUtils.h | 24 +- dom/base/nsDOMWindowUtils.cpp | 124 +++++------ dom/canvas/CanvasRenderingContext2D.cpp | 13 +- dom/html/HTMLCanvasElement.cpp | 6 +- dom/ipc/BrowserChild.cpp | 26 ++- dom/media/MediaDecoder.cpp | 6 +- .../mediacapabilities/MediaCapabilities.cpp | 7 +- gfx/layers/AnimationInfo.cpp | 6 +- gfx/layers/LayerManager.cpp | 61 ----- gfx/layers/LayerManager.h | 157 +------------ gfx/layers/Layers.cpp | 97 -------- gfx/layers/apz/util/APZCCallbackHelper.cpp | 8 +- gfx/layers/wr/WebRenderBridgeParent.h | 3 +- gfx/layers/wr/WebRenderLayerManager.h | 1 + layout/base/DisplayPortUtils.cpp | 6 +- layout/base/PresShell.cpp | 60 +++-- layout/base/PresShell.h | 4 +- layout/base/nsRefreshDriver.cpp | 6 +- layout/generic/nsGfxScrollFrame.cpp | 7 +- layout/ipc/RemoteLayerTreeOwner.cpp | 12 +- layout/painting/WindowRenderer.cpp | 170 ++++++++++++++ layout/painting/WindowRenderer.h | 210 ++++++++++++++++++ layout/painting/moz.build | 2 + layout/painting/nsDisplayList.cpp | 27 +-- layout/painting/nsDisplayListInvalidation.h | 1 + toolkit/components/browser/nsWebBrowser.cpp | 4 +- view/nsViewManager.cpp | 10 +- widget/PuppetWidget.cpp | 4 +- widget/PuppetWidget.h | 2 +- widget/android/nsWindow.cpp | 4 +- widget/android/nsWindow.h | 4 +- widget/cocoa/nsChildView.mm | 8 +- widget/cocoa/nsCocoaWindow.h | 2 +- widget/cocoa/nsCocoaWindow.mm | 4 +- widget/gtk/nsWindow.cpp | 29 +-- widget/gtk/nsWindow.h | 2 +- widget/headless/HeadlessWidget.cpp | 4 +- widget/headless/HeadlessWidget.h | 2 +- widget/nsBaseWidget.cpp | 6 +- widget/nsBaseWidget.h | 2 +- widget/nsIWidget.h | 4 +- widget/windows/nsWindow.cpp | 16 +- widget/windows/nsWindow.h | 2 +- widget/windows/nsWindowGfx.cpp | 29 +-- 46 files changed, 650 insertions(+), 546 deletions(-) create mode 100644 layout/painting/WindowRenderer.cpp create mode 100644 layout/painting/WindowRenderer.h diff --git a/dom/animation/KeyframeEffect.cpp b/dom/animation/KeyframeEffect.cpp index b24bb81d05f2..3cc4432f7886 100644 --- a/dom/animation/KeyframeEffect.cpp +++ b/dom/animation/KeyframeEffect.cpp @@ -736,8 +736,8 @@ void KeyframeEffect::ResetPartialPrerendered() { return; } - if (layers::LayerManager* layerManager = widget->GetLayerManager()) { - layerManager->RemovePartialPrerenderedAnimation( + if (WindowRenderer* windowRenderer = widget->GetWindowRenderer()) { + windowRenderer->RemovePartialPrerenderedAnimation( mAnimation->IdOnCompositor(), mAnimation); } } diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index babc1ebf6e67..d615d4782a96 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -6674,23 +6674,21 @@ nsIWidget* nsContentUtils::WidgetForContent(const nsIContent* aContent) { return nullptr; } -already_AddRefed nsContentUtils::LayerManagerForContent( +WindowRenderer* nsContentUtils::WindowRendererForContent( const nsIContent* aContent) { nsIWidget* widget = nsContentUtils::WidgetForContent(aContent); if (widget) { - RefPtr manager = widget->GetLayerManager(); - return manager.forget(); + return widget->GetWindowRenderer(); } return nullptr; } -already_AddRefed nsContentUtils::LayerManagerForDocument( +WindowRenderer* nsContentUtils::WindowRendererForDocument( const Document* aDoc) { nsIWidget* widget = nsContentUtils::WidgetForDocument(aDoc); if (widget) { - RefPtr manager = widget->GetLayerManager(); - return manager.forget(); + return widget->GetWindowRenderer(); } return nullptr; diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index dfd2b41c7bdd..f3386bdd4947 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -207,9 +207,7 @@ class DataSourceSurface; enum class SurfaceFormat : int8_t; } // namespace gfx -namespace layers { -class LayerManager; -} // namespace layers +class WindowRenderer; } // namespace mozilla @@ -2349,29 +2347,29 @@ class nsContentUtils { static nsIWidget* WidgetForContent(const nsIContent* aContent); /** - * Returns a layer manager to use for the given document. Basically we + * Returns a window renderer to use for the given document. Basically we * look up the document hierarchy for the first document which has * a presentation with an associated widget, and use that widget's - * layer manager. + * window renderer. * - * You should probably use LayerManagerForContent() instead of this, unless + * You should probably use WindowRendererForContent() instead of this, unless * you have a good reason to do otherwise. * - * @param aDoc the document for which to return a layer manager. + * @param aDoc the document for which to return a window renderer. * @param aAllowRetaining an outparam that states whether the returned * layer manager should be used for retained layers */ - static already_AddRefed - LayerManagerForDocument(const Document* aDoc); + static mozilla::WindowRenderer* WindowRendererForDocument( + const Document* aDoc); /** - * Returns a layer manager to use for the given content. Unlike - * LayerManagerForDocument(), this returns the correct layer manager for + * Returns a window renderer to use for the given content. Unlike + * WindowRendererForDocument(), this returns the correct window renderer for * content in popups. * - * You should probably use this instead of LayerManagerForDocument(). + * You should probably use this instead of WindowRendererForDocument(). */ - static already_AddRefed LayerManagerForContent( + static mozilla::WindowRenderer* WindowRendererForContent( const nsIContent* aContent); /** diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 2ca7e2f8ca42..c16e2f70a918 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -294,10 +294,10 @@ LayerTransactionChild* nsDOMWindowUtils::GetLayerTransaction() { nsIWidget* widget = GetWidget(); if (!widget) return nullptr; - LayerManager* manager = widget->GetLayerManager(); - if (!manager) return nullptr; + WindowRenderer* renderer = widget->GetWindowRenderer(); + if (!renderer) return nullptr; - ShadowLayerForwarder* forwarder = manager->AsShadowForwarder(); + ShadowLayerForwarder* forwarder = renderer->AsShadowForwarder(); return forwarder && forwarder->HasShadowManager() ? forwarder->GetShadowManager() : nullptr; @@ -305,9 +305,9 @@ LayerTransactionChild* nsDOMWindowUtils::GetLayerTransaction() { WebRenderBridgeChild* nsDOMWindowUtils::GetWebRenderBridge() { if (nsIWidget* widget = GetWidget()) { - if (LayerManager* lm = widget->GetLayerManager()) { - if (WebRenderLayerManager* wrlm = lm->AsWebRenderLayerManager()) { - return wrlm->WrBridge(); + if (WindowRenderer* renderer = widget->GetWindowRenderer()) { + if (WebRenderLayerManager* wr = renderer->AsWebRender()) { + return wr->WrBridge(); } } } @@ -316,8 +316,8 @@ WebRenderBridgeChild* nsDOMWindowUtils::GetWebRenderBridge() { CompositorBridgeChild* nsDOMWindowUtils::GetCompositorBridge() { if (nsIWidget* widget = GetWidget()) { - if (LayerManager* lm = widget->GetLayerManager()) { - if (CompositorBridgeChild* cbc = lm->GetCompositorBridgeChild()) { + if (WindowRenderer* renderer = widget->GetWindowRenderer()) { + if (CompositorBridgeChild* cbc = renderer->GetCompositorBridgeChild()) { return cbc; } } @@ -328,8 +328,8 @@ CompositorBridgeChild* nsDOMWindowUtils::GetCompositorBridge() { NS_IMETHODIMP nsDOMWindowUtils::SyncFlushCompositor() { if (nsIWidget* widget = GetWidget()) { - if (LayerManager* lm = widget->GetLayerManager()) { - if (KnowsCompositor* kc = lm->AsKnowsCompositor()) { + if (WindowRenderer* renderer = widget->GetWindowRenderer()) { + if (KnowsCompositor* kc = renderer->AsKnowsCompositor()) { kc->SyncWithCompositor(); } } @@ -412,7 +412,7 @@ nsDOMWindowUtils::UpdateLayerTree() { presShell->Paint( view, view->GetBounds(), PaintFlags::PaintLayers | PaintFlags::PaintSyncDecodeImages); - presShell->GetLayerManager()->WaitOnTransactionProcessed(); + presShell->GetWindowRenderer()->WaitOnTransactionProcessed(); } } return NS_OK; @@ -533,14 +533,10 @@ nsDOMWindowUtils::SetDisplayPortForElement(float aXPx, float aYPx, rootFrame == nsLayoutUtils::GetDisplayRootFrame(rootFrame)) { nsCOMPtr widget = GetWidget(); if (widget) { - LayerManager* manager = widget->GetLayerManager(); - manager->BeginTransaction(); using PaintFrameFlags = nsLayoutUtils::PaintFrameFlags; - nsLayoutUtils::PaintFrame(nullptr, rootFrame, nsRegion(), - NS_RGB(255, 255, 255), - nsDisplayListBuilderMode::Painting, - PaintFrameFlags::WidgetLayers | - PaintFrameFlags::ExistingTransaction); + nsLayoutUtils::PaintFrame( + nullptr, rootFrame, nsRegion(), NS_RGB(255, 255, 255), + nsDisplayListBuilderMode::Painting, PaintFrameFlags::WidgetLayers); } } } @@ -2545,10 +2541,10 @@ nsDOMWindowUtils::GetLayerManagerType(nsAString& aType) { nsCOMPtr widget = GetWidget(); if (!widget) return NS_ERROR_FAILURE; - LayerManager* mgr = widget->GetLayerManager(); - if (!mgr) return NS_ERROR_FAILURE; + WindowRenderer* renderer = widget->GetWindowRenderer(); + if (!renderer) return NS_ERROR_FAILURE; - mgr->GetBackendName(aType); + renderer->GetBackendName(aType); return NS_OK; } @@ -2558,10 +2554,10 @@ nsDOMWindowUtils::GetLayerManagerRemote(bool* retval) { nsCOMPtr widget = GetWidget(); if (!widget) return NS_ERROR_FAILURE; - LayerManager* mgr = widget->GetLayerManager(); - if (!mgr) return NS_ERROR_FAILURE; + WindowRenderer* renderer = widget->GetWindowRenderer(); + if (!renderer) return NS_ERROR_FAILURE; - *retval = !!mgr->AsKnowsCompositor(); + *retval = !!renderer->AsKnowsCompositor(); return NS_OK; } @@ -2572,13 +2568,13 @@ nsDOMWindowUtils::GetUsingAdvancedLayers(bool* retval) { return NS_ERROR_FAILURE; } - LayerManager* mgr = widget->GetLayerManager(); - if (!mgr) { + WindowRenderer* renderer = widget->GetWindowRenderer(); + if (!renderer) { return NS_ERROR_FAILURE; } *retval = false; - if (KnowsCompositor* fwd = mgr->AsKnowsCompositor()) { + if (KnowsCompositor* fwd = renderer->AsKnowsCompositor()) { *retval = fwd->GetTextureFactoryIdentifier().mUsingAdvancedLayers; } return NS_OK; @@ -2688,8 +2684,8 @@ nsDOMWindowUtils::StartFrameTimeRecording(uint32_t* startIndex) { nsCOMPtr widget = GetWidget(); if (!widget) return NS_ERROR_FAILURE; - LayerManager* mgr = widget->GetLayerManager(); - if (!mgr) return NS_ERROR_FAILURE; + WindowRenderer* renderer = widget->GetWindowRenderer(); + if (!renderer) return NS_ERROR_FAILURE; const uint32_t kRecordingMinSize = 60 * 10; // 10 seconds @60 fps. const uint32_t kRecordingMaxSize = 60 * 60 * 60; // One hour @@ -2697,7 +2693,7 @@ nsDOMWindowUtils::StartFrameTimeRecording(uint32_t* startIndex) { Preferences::GetUint("toolkit.framesRecording.bufferSize", uint32_t(0)); bufferSize = std::min(bufferSize, kRecordingMaxSize); bufferSize = std::max(bufferSize, kRecordingMinSize); - *startIndex = mgr->StartFrameTimeRecording(bufferSize); + *startIndex = renderer->StartFrameTimeRecording(bufferSize); return NS_OK; } @@ -2708,10 +2704,10 @@ nsDOMWindowUtils::StopFrameTimeRecording(uint32_t startIndex, nsCOMPtr widget = GetWidget(); if (!widget) return NS_ERROR_FAILURE; - LayerManager* mgr = widget->GetLayerManager(); - if (!mgr) return NS_ERROR_FAILURE; + WindowRenderer* renderer = widget->GetWindowRenderer(); + if (!renderer) return NS_ERROR_FAILURE; - mgr->StopFrameTimeRecording(startIndex, frameIntervals); + renderer->StopFrameTimeRecording(startIndex, frameIntervals); return NS_OK; } @@ -2814,19 +2810,19 @@ nsDOMWindowUtils::SetAsyncScrollOffset(Element* aElement, float aX, float aY) { if (!widget) { return NS_ERROR_FAILURE; } - LayerManager* manager = widget->GetLayerManager(); - if (!manager) { + WindowRenderer* renderer = widget->GetWindowRenderer(); + if (!renderer) { return NS_ERROR_FAILURE; } - if (WebRenderLayerManager* wrlm = manager->AsWebRenderLayerManager()) { - WebRenderBridgeChild* wrbc = wrlm->WrBridge(); + if (WebRenderLayerManager* wr = renderer->AsWebRender()) { + WebRenderBridgeChild* wrbc = wr->WrBridge(); if (!wrbc) { return NS_ERROR_UNEXPECTED; } wrbc->SendSetAsyncScrollOffset(viewId, aX, aY); return NS_OK; } - ShadowLayerForwarder* forwarder = manager->AsShadowForwarder(); + ShadowLayerForwarder* forwarder = renderer->AsShadowForwarder(); if (!forwarder || !forwarder->HasShadowManager()) { return NS_ERROR_UNEXPECTED; } @@ -2847,19 +2843,19 @@ nsDOMWindowUtils::SetAsyncZoom(Element* aRootElement, float aValue) { if (!widget) { return NS_ERROR_FAILURE; } - LayerManager* manager = widget->GetLayerManager(); - if (!manager) { + WindowRenderer* renderer = widget->GetWindowRenderer(); + if (!renderer) { return NS_ERROR_FAILURE; } - if (WebRenderLayerManager* wrlm = manager->AsWebRenderLayerManager()) { - WebRenderBridgeChild* wrbc = wrlm->WrBridge(); + if (WebRenderLayerManager* wr = renderer->AsWebRender()) { + WebRenderBridgeChild* wrbc = wr->WrBridge(); if (!wrbc) { return NS_ERROR_UNEXPECTED; } wrbc->SendSetAsyncZoom(viewId, aValue); return NS_OK; } - ShadowLayerForwarder* forwarder = manager->AsShadowForwarder(); + ShadowLayerForwarder* forwarder = renderer->AsShadowForwarder(); if (!forwarder || !forwarder->HasShadowManager()) { return NS_ERROR_UNEXPECTED; } @@ -2879,13 +2875,13 @@ nsDOMWindowUtils::FlushApzRepaints(bool* aOutResult) { *aOutResult = false; return NS_OK; } - LayerManager* manager = widget->GetLayerManager(); - if (!manager) { + WindowRenderer* renderer = widget->GetWindowRenderer(); + if (!renderer) { *aOutResult = false; return NS_OK; } - if (WebRenderLayerManager* wrlm = manager->AsWebRenderLayerManager()) { - WebRenderBridgeChild* wrbc = wrlm->WrBridge(); + if (WebRenderLayerManager* wr = renderer->AsWebRender()) { + WebRenderBridgeChild* wrbc = wr->WrBridge(); if (!wrbc) { return NS_ERROR_UNEXPECTED; } @@ -2893,7 +2889,7 @@ nsDOMWindowUtils::FlushApzRepaints(bool* aOutResult) { *aOutResult = true; return NS_OK; } - ShadowLayerForwarder* forwarder = manager->AsShadowForwarder(); + ShadowLayerForwarder* forwarder = renderer->AsShadowForwarder(); if (!forwarder || !forwarder->HasShadowManager()) { *aOutResult = false; return NS_OK; @@ -3227,7 +3223,9 @@ nsDOMWindowUtils::LeafLayersPartitionWindow(bool* aResult) { #ifdef DEBUG nsIWidget* widget = GetWidget(); if (!widget) return NS_ERROR_FAILURE; - LayerManager* manager = widget->GetLayerManager(); + WindowRenderer* renderer = widget->GetWindowRenderer(); + if (!renderer) return NS_ERROR_FAILURE; + LayerManager* manager = renderer->AsLayerManager(); if (!manager) return NS_ERROR_FAILURE; nsPresContext* presContext = GetPresContext(); if (!presContext) return NS_ERROR_FAILURE; @@ -4206,16 +4204,16 @@ NS_IMETHODIMP nsDOMWindowUtils::GetContentAPZTestData( JSContext* aContext, JS::MutableHandleValue aOutContentTestData) { if (nsIWidget* widget = GetWidget()) { - RefPtr lm = widget->GetLayerManager(); - if (!lm) { + WindowRenderer* renderer = widget->GetWindowRenderer(); + if (!renderer) { return NS_OK; } - if (ClientLayerManager* clm = lm->AsClientLayerManager()) { + if (ClientLayerManager* clm = renderer->AsClientLayerManager()) { if (!clm->GetAPZTestData().ToJS(aOutContentTestData, aContext)) { return NS_ERROR_FAILURE; } - } else if (WebRenderLayerManager* wrlm = lm->AsWebRenderLayerManager()) { - if (!wrlm->GetAPZTestData().ToJS(aOutContentTestData, aContext)) { + } else if (WebRenderLayerManager* wr = renderer->AsWebRender()) { + if (!wr->GetAPZTestData().ToJS(aOutContentTestData, aContext)) { return NS_ERROR_FAILURE; } } @@ -4228,18 +4226,18 @@ NS_IMETHODIMP nsDOMWindowUtils::GetCompositorAPZTestData( JSContext* aContext, JS::MutableHandleValue aOutCompositorTestData) { if (nsIWidget* widget = GetWidget()) { - RefPtr lm = widget->GetLayerManager(); - if (!lm) { + WindowRenderer* renderer = widget->GetWindowRenderer(); + if (!renderer) { return NS_OK; } APZTestData compositorSideData; - if (ClientLayerManager* clm = lm->AsClientLayerManager()) { + if (ClientLayerManager* clm = renderer->AsClientLayerManager()) { clm->GetCompositorSideAPZTestData(&compositorSideData); - } else if (WebRenderLayerManager* wrlm = lm->AsWebRenderLayerManager()) { - if (!wrlm->WrBridge()) { + } else if (WebRenderLayerManager* wr = renderer->AsWebRender()) { + if (!wr->WrBridge()) { return NS_ERROR_UNEXPECTED; } - if (!wrlm->WrBridge()->SendGetAPZTestData(&compositorSideData)) { + if (!wr->WrBridge()->SendGetAPZTestData(&compositorSideData)) { return NS_ERROR_FAILURE; } } @@ -4290,13 +4288,13 @@ nsDOMWindowUtils::GetFrameUniformityTestData( return NS_ERROR_NOT_AVAILABLE; } - RefPtr manager = widget->GetLayerManager(); - if (!manager) { + WindowRenderer* renderer = widget->GetWindowRenderer(); + if (!renderer) { return NS_ERROR_NOT_AVAILABLE; } FrameUniformityData outData; - manager->GetFrameUniformity(&outData); + renderer->GetFrameUniformity(&outData); outData.ToJS(aOutFrameUniformity, aContext); return NS_OK; } diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index 16eff45fdee8..c76aca495e80 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -1412,13 +1412,13 @@ void CanvasRenderingContext2D::RegisterAllocation() { } } -static already_AddRefed LayerManagerFromCanvasElement( +static WindowRenderer* WindowRendererFromCanvasElement( nsINode* aCanvasElement) { if (!aCanvasElement) { return nullptr; } - return nsContentUtils::LayerManagerForDocument(aCanvasElement->OwnerDoc()); + return nsContentUtils::WindowRendererForDocument(aCanvasElement->OwnerDoc()); } bool CanvasRenderingContext2D::TrySharedTarget( @@ -1441,15 +1441,14 @@ bool CanvasRenderingContext2D::TrySharedTarget( return false; } - RefPtr layerManager = - LayerManagerFromCanvasElement(mCanvasElement); + WindowRenderer* renderer = WindowRendererFromCanvasElement(mCanvasElement); - if (!layerManager) { + if (!renderer) { return false; } - aOutProvider = layerManager->CreatePersistentBufferProvider( - GetSize(), GetSurfaceFormat()); + aOutProvider = + renderer->CreatePersistentBufferProvider(GetSize(), GetSurfaceFormat()); if (!aOutProvider) { return false; diff --git a/dom/html/HTMLCanvasElement.cpp b/dom/html/HTMLCanvasElement.cpp index ee3eff4a1203..01aae05535ea 100644 --- a/dom/html/HTMLCanvasElement.cpp +++ b/dom/html/HTMLCanvasElement.cpp @@ -1293,9 +1293,9 @@ already_AddRefed HTMLCanvasElement::GetSurfaceSnapshot( layers::LayersBackend HTMLCanvasElement::GetCompositorBackendType() const { nsIWidget* docWidget = nsContentUtils::WidgetForDocument(OwnerDoc()); if (docWidget) { - layers::LayerManager* layerManager = docWidget->GetLayerManager(); - if (layerManager) { - return layerManager->GetCompositorBackendType(); + WindowRenderer* renderer = docWidget->GetWindowRenderer(); + if (renderer) { + return renderer->GetCompositorBackendType(); } } diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp index 9f1bccda2efe..565ada348518 100644 --- a/dom/ipc/BrowserChild.cpp +++ b/dom/ipc/BrowserChild.cpp @@ -2643,7 +2643,8 @@ mozilla::ipc::IPCResult BrowserChild::RecvRenderLayers( if (mCompositorOptions) { MOZ_ASSERT(mPuppetWidget); - RefPtr lm = mPuppetWidget->GetLayerManager(); + RefPtr lm = + mPuppetWidget->GetWindowRenderer()->AsLayerManager(); MOZ_ASSERT(lm); // We send the current layer observer epoch to the compositor so that @@ -2812,7 +2813,7 @@ void BrowserChild::InitRenderingState( // layers. CreateRemoteLayerManager will destroy us if we manage to get a // remote layer manager though, so that's fine. MOZ_ASSERT(!mPuppetWidget->HasLayerManager() || - mPuppetWidget->GetLayerManager()->GetBackendType() == + mPuppetWidget->GetWindowRenderer()->GetBackendType() == layers::LayersBackend::LAYERS_BASIC); bool success = false; if (mLayersConnected == Some(true)) { @@ -2825,7 +2826,8 @@ void BrowserChild::InitRenderingState( ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier); gfx::VRManagerChild::IdentifyTextureHost(mTextureFactoryIdentifier); InitAPZState(); - RefPtr lm = mPuppetWidget->GetLayerManager(); + RefPtr lm = + mPuppetWidget->GetWindowRenderer()->AsLayerManager(); MOZ_ASSERT(lm); lm->SetLayersObserverEpoch(mLayersObserverEpoch); } else { @@ -3121,7 +3123,8 @@ void BrowserChild::DidComposite(mozilla::layers::TransactionId aTransactionId, const TimeStamp& aCompositeStart, const TimeStamp& aCompositeEnd) { MOZ_ASSERT(mPuppetWidget); - RefPtr lm = mPuppetWidget->GetLayerManager(); + RefPtr lm = + mPuppetWidget->GetWindowRenderer()->AsLayerManager(); MOZ_ASSERT(lm); lm->DidComposite(aTransactionId, aCompositeStart, aCompositeEnd); @@ -3153,7 +3156,8 @@ void BrowserChild::DidRequestComposite(const TimeStamp& aCompositeReqStart, void BrowserChild::ClearCachedResources() { MOZ_ASSERT(mPuppetWidget); - RefPtr lm = mPuppetWidget->GetLayerManager(); + RefPtr lm = + mPuppetWidget->GetWindowRenderer()->AsLayerManager(); MOZ_ASSERT(lm); lm->ClearCachedResources(); @@ -3168,7 +3172,8 @@ void BrowserChild::ClearCachedResources() { void BrowserChild::InvalidateLayers() { MOZ_ASSERT(mPuppetWidget); - RefPtr lm = mPuppetWidget->GetLayerManager(); + RefPtr lm = + mPuppetWidget->GetWindowRenderer()->AsLayerManager(); MOZ_ASSERT(lm); FrameLayerBuilder::InvalidateAllLayers(lm); @@ -3225,7 +3230,8 @@ void BrowserChild::ReinitRendering() { gfx::VRManagerChild::IdentifyTextureHost(mTextureFactoryIdentifier); InitAPZState(); - RefPtr lm = mPuppetWidget->GetLayerManager(); + RefPtr lm = + mPuppetWidget->GetWindowRenderer()->AsLayerManager(); MOZ_ASSERT(lm); lm->SetLayersObserverEpoch(mLayersObserverEpoch); @@ -3236,7 +3242,8 @@ void BrowserChild::ReinitRendering() { void BrowserChild::ReinitRenderingForDeviceReset() { InvalidateLayers(); - RefPtr lm = mPuppetWidget->GetLayerManager(); + RefPtr lm = + mPuppetWidget->GetWindowRenderer()->AsLayerManager(); if (WebRenderLayerManager* wlm = lm->AsWebRenderLayerManager()) { wlm->DoDestroy(/* aIsSync */ true); } else if (ClientLayerManager* clm = lm->AsClientLayerManager()) { @@ -3276,7 +3283,8 @@ BrowserChild::OnHideTooltip() { void BrowserChild::NotifyJankedAnimations( const nsTArray& aJankedAnimations) { MOZ_ASSERT(mPuppetWidget); - RefPtr lm = mPuppetWidget->GetLayerManager(); + RefPtr lm = + mPuppetWidget->GetWindowRenderer()->AsLayerManager(); MOZ_ASSERT(lm); lm->UpdatePartialPrerenderedAnimations(aJankedAnimations); } diff --git a/dom/media/MediaDecoder.cpp b/dom/media/MediaDecoder.cpp index 7696375479e2..9c93a76be1f7 100644 --- a/dom/media/MediaDecoder.cpp +++ b/dom/media/MediaDecoder.cpp @@ -973,10 +973,10 @@ void MediaDecoder::DurationChanged() { already_AddRefed MediaDecoder::GetCompositor() { MediaDecoderOwner* owner = GetOwner(); Document* ownerDoc = owner ? owner->GetDocument() : nullptr; - RefPtr layerManager = - ownerDoc ? nsContentUtils::LayerManagerForDocument(ownerDoc) : nullptr; + WindowRenderer* renderer = + ownerDoc ? nsContentUtils::WindowRendererForDocument(ownerDoc) : nullptr; RefPtr knows = - layerManager ? layerManager->AsKnowsCompositor() : nullptr; + renderer ? renderer->AsKnowsCompositor() : nullptr; return knows ? knows->GetForMedia().forget() : nullptr; } diff --git a/dom/media/mediacapabilities/MediaCapabilities.cpp b/dom/media/mediacapabilities/MediaCapabilities.cpp index 6fcfc9c9b9a5..4c25b32f0ee1 100644 --- a/dom/media/mediacapabilities/MediaCapabilities.cpp +++ b/dom/media/mediacapabilities/MediaCapabilities.cpp @@ -572,12 +572,11 @@ already_AddRefed MediaCapabilities::GetCompositor() { if (NS_WARN_IF(!doc)) { return nullptr; } - RefPtr layerManager = - nsContentUtils::LayerManagerForDocument(doc); - if (NS_WARN_IF(!layerManager)) { + WindowRenderer* renderer = nsContentUtils::WindowRendererForDocument(doc); + if (NS_WARN_IF(!renderer)) { return nullptr; } - RefPtr knows = layerManager->AsKnowsCompositor(); + RefPtr knows = renderer->AsKnowsCompositor(); if (NS_WARN_IF(!knows)) { return nullptr; } diff --git a/gfx/layers/AnimationInfo.cpp b/gfx/layers/AnimationInfo.cpp index 278271fa69c6..375e88493e9b 100644 --- a/gfx/layers/AnimationInfo.cpp +++ b/gfx/layers/AnimationInfo.cpp @@ -204,11 +204,9 @@ void AnimationInfo::EnumerateGenerationOnFrame( } } - RefPtr layerManager = - nsContentUtils::LayerManagerForContent(aContent); + WindowRenderer* renderer = nsContentUtils::WindowRendererForContent(aContent); - if (layerManager && - layerManager->GetBackendType() == layers::LayersBackend::LAYERS_WR) { + if (renderer && renderer->AsWebRender()) { // In case of continuation, nsDisplayItem uses its last continuation, so we // have to use the last continuation frame here. if (nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aFrame)) { diff --git a/gfx/layers/LayerManager.cpp b/gfx/layers/LayerManager.cpp index dec5d6a1dab1..251ea8167dd9 100644 --- a/gfx/layers/LayerManager.cpp +++ b/gfx/layers/LayerManager.cpp @@ -122,28 +122,6 @@ already_AddRefed LayerManager::CreateDrawTarget( aFormat); } -already_AddRefed -LayerManager::CreatePersistentBufferProvider( - const mozilla::gfx::IntSize& aSize, mozilla::gfx::SurfaceFormat aFormat) { - RefPtr bufferProvider; - // If we are using remote canvas we don't want to use acceleration in - // non-remote layer managers, so we always use the fallback software one. - if (!gfxPlatform::UseRemoteCanvas() || - !gfxPlatform::IsBackendAccelerated( - gfxPlatform::GetPlatform()->GetPreferredCanvasBackend())) { - bufferProvider = PersistentBufferProviderBasic::Create( - aSize, aFormat, - gfxPlatform::GetPlatform()->GetPreferredCanvasBackend()); - } - - if (!bufferProvider) { - bufferProvider = PersistentBufferProviderBasic::Create( - aSize, aFormat, gfxPlatform::GetPlatform()->GetFallbackCanvasBackend()); - } - - return bufferProvider.forget(); -} - already_AddRefed LayerManager::CreateImageContainer( ImageContainer::Mode flag) { RefPtr container = new ImageContainer(flag); @@ -180,44 +158,5 @@ void LayerManager::PayloadPresented(const TimeStamp& aTimeStamp) { RecordCompositionPayloadsPresented(aTimeStamp, mPayload); } -void LayerManager::AddPartialPrerenderedAnimation( - uint64_t aCompositorAnimationId, dom::Animation* aAnimation) { - mPartialPrerenderedAnimations.InsertOrUpdate(aCompositorAnimationId, - RefPtr{aAnimation}); - aAnimation->SetPartialPrerendered(aCompositorAnimationId); -} - -void LayerManager::RemovePartialPrerenderedAnimation( - uint64_t aCompositorAnimationId, dom::Animation* aAnimation) { - MOZ_ASSERT(aAnimation); -#ifdef DEBUG - RefPtr animation; - if (mPartialPrerenderedAnimations.Remove(aCompositorAnimationId, - getter_AddRefs(animation)) && - // It may be possible that either animation's effect has already been - // nulled out via Animation::SetEffect() so ignore such cases. - aAnimation->GetEffect() && aAnimation->GetEffect()->AsKeyframeEffect() && - animation->GetEffect() && animation->GetEffect()->AsKeyframeEffect()) { - MOZ_ASSERT(EffectSet::GetEffectSetForEffect( - aAnimation->GetEffect()->AsKeyframeEffect()) == - EffectSet::GetEffectSetForEffect( - animation->GetEffect()->AsKeyframeEffect())); - } -#else - mPartialPrerenderedAnimations.Remove(aCompositorAnimationId); -#endif - aAnimation->ResetPartialPrerendered(); -} - -void LayerManager::UpdatePartialPrerenderedAnimations( - const nsTArray& aJankedAnimations) { - for (uint64_t id : aJankedAnimations) { - RefPtr animation; - if (mPartialPrerenderedAnimations.Remove(id, getter_AddRefs(animation))) { - animation->UpdatePartialPrerendered(); - } - } -} - } // namespace layers } // namespace mozilla diff --git a/gfx/layers/LayerManager.h b/gfx/layers/LayerManager.h index 2aead3664360..880b044e051a 100644 --- a/gfx/layers/LayerManager.h +++ b/gfx/layers/LayerManager.h @@ -14,6 +14,7 @@ #include // for forward #include "FrameMetrics.h" // for ScrollUpdatesMap #include "ImageContainer.h" // for ImageContainer, ImageContainer::Mode, ImageContainer::SYNCHRONOUS +#include "WindowRenderer.h" #include "mozilla/AlreadyAddRefed.h" // for already_AddRefed #include "mozilla/Maybe.h" // for Maybe #include "mozilla/RefPtr.h" // for RefPtr @@ -94,62 +95,6 @@ class DidCompositeObserver { virtual void DidComposite() = 0; }; -class FrameRecorder { - public: - /** - * Record (and return) frame-intervals and paint-times for frames which were - * presented between calling StartFrameTimeRecording and - * StopFrameTimeRecording. - * - * - Uses a cyclic buffer and serves concurrent consumers, so if Stop is - * called too late - * (elements were overwritten since Start), result is considered invalid - * and hence empty.) - * - Buffer is capable of holding 10 seconds @ 60fps (or more if frames were - * less frequent). - * Can be changed (up to 1 hour) via pref: - * toolkit.framesRecording.bufferSize. - * - Note: the first frame-interval may be longer than expected because last - * frame - * might have been presented some time before calling - * StartFrameTimeRecording. - */ - - /** - * Returns a handle which represents current recording start position. - */ - virtual uint32_t StartFrameTimeRecording(int32_t aBufferSize); - - /** - * Clears, then populates aFrameIntervals with the recorded frame timing - * data. The array will be empty if data was overwritten since - * aStartIndex was obtained. - */ - virtual void StopFrameTimeRecording(uint32_t aStartIndex, - nsTArray& aFrameIntervals); - - void RecordFrame(); - - private: - struct FramesTimingRecording { - // Stores state and data for frame intervals and paint times recording. - // see LayerManager::StartFrameTimeRecording() at Layers.cpp for more - // details. - FramesTimingRecording() - : mNextIndex(0), - mLatestStartIndex(0), - mCurrentRunStartIndex(0), - mIsPaused(true) {} - nsTArray mIntervals; - TimeStamp mLastFrameTime; - uint32_t mNextIndex; - uint32_t mLatestStartIndex; - uint32_t mCurrentRunStartIndex; - bool mIsPaused; - }; - FramesTimingRecording mRecording; -}; - /* * Motivation: For truly smooth animation and video playback, we need to * be able to compose frames and render them on a dedicated thread (i.e. @@ -198,7 +143,7 @@ class FrameRecorder { * Layers are refcounted. The layer manager holds a reference to the * root layer, and each container layer holds a reference to its children. */ -class LayerManager : public FrameRecorder { +class LayerManager : public WindowRenderer { NS_INLINE_DECL_REFCOUNTING(LayerManager) protected: @@ -218,14 +163,10 @@ class LayerManager : public FrameRecorder { virtual void Destroy(); bool IsDestroyed() { return mDestroyed; } - virtual ShadowLayerForwarder* AsShadowForwarder() { return nullptr; } - - virtual KnowsCompositor* AsKnowsCompositor() { return nullptr; } + virtual LayerManager* AsLayerManager() override { return this; } virtual LayerManagerComposite* AsLayerManagerComposite() { return nullptr; } - virtual ClientLayerManager* AsClientLayerManager() { return nullptr; } - virtual BasicLayerManager* AsBasicLayerManager() { return nullptr; } virtual HostLayerManager* AsHostLayerManager() { return nullptr; } @@ -238,13 +179,6 @@ class LayerManager : public FrameRecorder { virtual bool IsWidgetLayerManager() { return true; } virtual bool IsInactiveLayerManager() { return false; } - /** - * Start a new transaction. Nested transactions are not allowed so - * there must be no transaction currently in progress. - * This transaction will update the state of the window from which - * this LayerManager was obtained. - */ - virtual bool BeginTransaction(const nsCString& aURL = nsCString()) = 0; /** * Start a new transaction. Nested transactions are not allowed so * there must be no transaction currently in progress. @@ -255,31 +189,11 @@ class LayerManager : public FrameRecorder { virtual bool BeginTransactionWithTarget( gfxContext* aTarget, const nsCString& aURL = nsCString()) = 0; - enum EndTransactionFlags { - END_DEFAULT = 0, - END_NO_IMMEDIATE_REDRAW = 1 << 0, // Do not perform the drawing phase - END_NO_COMPOSITE = - 1 << 1, // Do not composite after drawing painted layer contents. - END_NO_REMOTE_COMPOSITE = 1 << 2 // Do not schedule a composition with a - // remote Compositor, if one exists. - }; - FrameLayerBuilder* GetLayerBuilder() { return reinterpret_cast( GetUserData(&gLayerManagerLayerBuilder)); } - /** - * Attempts to end an "empty transaction". There must have been no - * changes to the layer tree since the BeginTransaction(). - * It's possible for this to fail; PaintedLayers may need to be updated - * due to VRAM data being lost, for example. In such cases this method - * returns false, and the caller must proceed with a normal layer tree - * update and EndTransaction. - */ - virtual bool EndEmptyTransaction( - EndTransactionFlags aFlags = END_DEFAULT) = 0; - /** * Function called to draw the contents of each PaintedLayer. * aRegionToDraw contains the region that needs to be drawn. @@ -466,20 +380,6 @@ class LayerManager : public FrameRecorder { static already_AddRefed CreateImageContainer( ImageContainer::Mode flag = ImageContainer::SYNCHRONOUS); - /** - * Type of layer manager his is. This is to be used sparsely in order to - * avoid a lot of Layers backend specific code. It should be used only when - * Layers backend specific functionality is necessary. - */ - virtual LayersBackend GetBackendType() = 0; - - /** - * Type of layers backend that will be used to composite this layer tree. - * When compositing is done remotely, then this returns the layers type - * of the compositor. - */ - virtual LayersBackend GetCompositorBackendType() { return GetBackendType(); } - /** * Creates a DrawTarget which is optimized for inter-operating with this * layer manager. @@ -503,14 +403,6 @@ class LayerManager : public FrameRecorder { virtual already_AddRefed CreateDrawTarget( const mozilla::gfx::IntSize& aSize, mozilla::gfx::SurfaceFormat aFormat); - /** - * Creates a PersistentBufferProvider for use with canvas which is optimized - * for inter-operating with this layermanager. - */ - virtual already_AddRefed - CreatePersistentBufferProvider(const mozilla::gfx::IntSize& aSize, - mozilla::gfx::SurfaceFormat aFormat); - virtual bool CanUseCanvasLayerForSize(const gfx::IntSize& aSize) { return true; } @@ -521,11 +413,6 @@ class LayerManager : public FrameRecorder { */ virtual int32_t GetMaxTextureSize() const = 0; - /** - * Return the name of the layer manager's backend. - */ - virtual void GetBackendName(nsAString& aName) = 0; - /** * This setter can be used anytime. The user data for all keys is * initially null. Ownership pases to the layer manager. @@ -583,28 +470,8 @@ class LayerManager : public FrameRecorder { */ virtual void SetFocusTarget(const FocusTarget& aFocusTarget) {} - /** - * Make sure that the previous transaction has been entirely - * completed. - * - * Note: This may sychronously wait on a remote compositor - * to complete rendering. - */ - virtual void FlushRendering() {} - - /** - * Make sure that the previous transaction has been - * received. This will synchronsly wait on a remote compositor. */ - virtual void WaitOnTransactionProcessed() {} - virtual void SendInvalidRegion(const nsIntRegion& aRegion) {} - /** - * Checks if we need to invalidate the OS widget to trigger - * painting when updating this layer manager. - */ - virtual bool NeedsWidgetInvalidation() { return true; } - virtual const char* Name() const { return "???"; } /** @@ -650,7 +517,6 @@ class LayerManager : public FrameRecorder { virtual bool IsCompositingCheap() { return true; } bool IsInTransaction() const { return mInTransaction; } - virtual void GetFrameUniformity(FrameUniformityData* aOutData) {} virtual void SetRegionToClear(const nsIntRegion& aRegion) { mRegionToClear = aRegion; @@ -696,8 +562,6 @@ class LayerManager : public FrameRecorder { virtual TransactionId GetLastTransactionId() { return TransactionId{0}; } - virtual CompositorBridgeChild* GetCompositorBridgeChild() { return nullptr; } - void RegisterPayload(const CompositionPayload& aPayload) { mPayload.AppendElement(aPayload); MOZ_ASSERT(mPayload.Length() < 10000); @@ -712,13 +576,6 @@ class LayerManager : public FrameRecorder { void SetContainsSVG(bool aContainsSVG) { mContainsSVG = aContainsSVG; } - void AddPartialPrerenderedAnimation(uint64_t aCompositorAnimationId, - dom::Animation* aAnimation); - void RemovePartialPrerenderedAnimation(uint64_t aCompositorAnimationId, - dom::Animation* aAnimation); - void UpdatePartialPrerenderedAnimations( - const nsTArray& aJankedAnimations); - protected: RefPtr mRoot; gfx::UserData mUserData; @@ -756,12 +613,6 @@ class LayerManager : public FrameRecorder { // IMPORTANT: Clients should take care to clear this or risk it slowly // growing out of control. nsTArray mPayload; - // Transform animations which are not fully pre-rendered because it's on a - // large frame. We need to update the pre-rendered area once after we tried - // to composite area which is outside of the pre-rendered area on the - // compositor. - nsRefPtrHashtable - mPartialPrerenderedAnimations; public: /* @@ -771,7 +622,7 @@ class LayerManager : public FrameRecorder { */ virtual bool AddPendingScrollUpdateForNextTransaction( ScrollableLayerGuid::ViewID aScrollId, - const ScrollPositionUpdate& aUpdateInfo); + const ScrollPositionUpdate& aUpdateInfo) override; Maybe> GetPendingScrollInfoUpdate( ScrollableLayerGuid::ViewID aScrollId); std::unordered_set diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index 466858365204..deb9198ed9ea 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -1217,103 +1217,6 @@ void RefLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs) { mRemoteDocumentSize); } -/** - * StartFrameTimeRecording, together with StopFrameTimeRecording - * enable recording of frame intervals. - * - * To allow concurrent consumers, a cyclic array is used which serves all - * consumers, practically stateless with regard to consumers. - * - * To save resources, the buffer is allocated on first call to - * StartFrameTimeRecording and recording is paused if no consumer which called - * StartFrameTimeRecording is able to get valid results (because the cyclic - * buffer was overwritten since that call). - * - * To determine availability of the data upon StopFrameTimeRecording: - * - mRecording.mNextIndex increases on each RecordFrame, and never resets. - * - Cyclic buffer position is realized as mNextIndex % bufferSize. - * - StartFrameTimeRecording returns mNextIndex. When StopFrameTimeRecording is - * called, the required start index is passed as an arg, and we're able to - * calculate the required length. If this length is bigger than bufferSize, it - * means data was overwritten. otherwise, we can return the entire sequence. - * - To determine if we need to pause, mLatestStartIndex is updated to - * mNextIndex on each call to StartFrameTimeRecording. If this index gets - * overwritten, it means that all earlier start indices obtained via - * StartFrameTimeRecording were also overwritten, hence, no point in - * recording, so pause. - * - mCurrentRunStartIndex indicates the oldest index of the recording after - * which the recording was not paused. If StopFrameTimeRecording is invoked - * with a start index older than this, it means that some frames were not - * recorded, so data is invalid. - */ -uint32_t FrameRecorder::StartFrameTimeRecording(int32_t aBufferSize) { - if (mRecording.mIsPaused) { - mRecording.mIsPaused = false; - - if (!mRecording.mIntervals.Length()) { // Initialize recording buffers - mRecording.mIntervals.SetLength(aBufferSize); - } - - // After being paused, recent values got invalid. Update them to now. - mRecording.mLastFrameTime = TimeStamp::Now(); - - // Any recording which started before this is invalid, since we were paused. - mRecording.mCurrentRunStartIndex = mRecording.mNextIndex; - } - - // If we'll overwrite this index, there are no more consumers with aStartIndex - // for which we're able to provide the full recording, so no point in keep - // recording. - mRecording.mLatestStartIndex = mRecording.mNextIndex; - return mRecording.mNextIndex; -} - -void FrameRecorder::RecordFrame() { - if (!mRecording.mIsPaused) { - TimeStamp now = TimeStamp::Now(); - uint32_t i = mRecording.mNextIndex % mRecording.mIntervals.Length(); - mRecording.mIntervals[i] = - static_cast((now - mRecording.mLastFrameTime).ToMilliseconds()); - mRecording.mNextIndex++; - mRecording.mLastFrameTime = now; - - if (mRecording.mNextIndex > - (mRecording.mLatestStartIndex + mRecording.mIntervals.Length())) { - // We've just overwritten the most recent recording start -> pause. - mRecording.mIsPaused = true; - } - } -} - -void FrameRecorder::StopFrameTimeRecording(uint32_t aStartIndex, - nsTArray& aFrameIntervals) { - uint32_t bufferSize = mRecording.mIntervals.Length(); - uint32_t length = mRecording.mNextIndex - aStartIndex; - if (mRecording.mIsPaused || length > bufferSize || - aStartIndex < mRecording.mCurrentRunStartIndex) { - // aStartIndex is too old. Also if aStartIndex was issued before - // mRecordingNextIndex overflowed (uint32_t) - // and stopped after the overflow (would happen once every 828 days of - // constant 60fps). - length = 0; - } - - if (!length) { - aFrameIntervals.Clear(); - return; // empty recording, return empty arrays. - } - // Set length in advance to avoid possibly repeated reallocations - aFrameIntervals.SetLength(length); - - uint32_t cyclicPos = aStartIndex % bufferSize; - for (uint32_t i = 0; i < length; i++, cyclicPos++) { - if (cyclicPos == bufferSize) { - cyclicPos = 0; - } - aFrameIntervals[i] = mRecording.mIntervals[cyclicPos]; - } -} - static void PrintInfo(std::stringstream& aStream, HostLayer* aLayerComposite); #ifdef MOZ_DUMP_PAINTING diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp index 7f4b02ccabd1..b9f24a553b9b 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.cpp +++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp @@ -688,19 +688,19 @@ static void SendLayersDependentApzcTargetConfirmation( return; } - LayerManager* lm = ps->GetLayerManager(); - if (!lm) { + WindowRenderer* renderer = ps->GetWindowRenderer(); + if (!renderer) { return; } - if (WebRenderLayerManager* wrlm = lm->AsWebRenderLayerManager()) { + if (WebRenderLayerManager* wrlm = renderer->AsWebRender()) { if (WebRenderBridgeChild* wrbc = wrlm->WrBridge()) { wrbc->SendSetConfirmedTargetAPZC(aInputBlockId, aTargets); } return; } - ShadowLayerForwarder* lf = lm->AsShadowForwarder(); + ShadowLayerForwarder* lf = renderer->AsShadowForwarder(); if (!lf) { return; } diff --git a/gfx/layers/wr/WebRenderBridgeParent.h b/gfx/layers/wr/WebRenderBridgeParent.h index 9bb12ee86e96..5c2510f0e13e 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.h +++ b/gfx/layers/wr/WebRenderBridgeParent.h @@ -24,6 +24,7 @@ #include "mozilla/webrender/WebRenderTypes.h" #include "mozilla/webrender/WebRenderAPI.h" #include "nsTArrayForwardDeclare.h" +#include "WindowRenderer.h" namespace mozilla { @@ -64,7 +65,7 @@ struct CompositorAnimationIdsForEpoch { class WebRenderBridgeParent final : public PWebRenderBridgeParent, public CompositorVsyncSchedulerOwner, public CompositableParentManager, - public layers::FrameRecorder { + public FrameRecorder { public: WebRenderBridgeParent(CompositorBridgeParentBase* aCompositorBridge, const wr::PipelineId& aPipelineId, diff --git a/gfx/layers/wr/WebRenderLayerManager.h b/gfx/layers/wr/WebRenderLayerManager.h index 005b5688c414..a1073399c602 100644 --- a/gfx/layers/wr/WebRenderLayerManager.h +++ b/gfx/layers/wr/WebRenderLayerManager.h @@ -72,6 +72,7 @@ class WebRenderLayerManager final : public LayerManager { public: KnowsCompositor* AsKnowsCompositor() override; + WebRenderLayerManager* AsWebRender() override { return this; } WebRenderLayerManager* AsWebRenderLayerManager() override { return this; } CompositorBridgeChild* GetCompositorBridgeChild() override; diff --git a/layout/base/DisplayPortUtils.cpp b/layout/base/DisplayPortUtils.cpp index 9270c6d4b9e2..6903f5b1cc86 100644 --- a/layout/base/DisplayPortUtils.cpp +++ b/layout/base/DisplayPortUtils.cpp @@ -212,13 +212,13 @@ static nscoord GetMaxDisplayPortSize(nsIContent* aContent, if (!widget) { return safeMaximum; } - LayerManager* lm = widget->GetLayerManager(); - if (!lm) { + WindowRenderer* renderer = widget->GetWindowRenderer(); + if (!renderer || !renderer->AsLayerManager()) { return safeMaximum; } nsPresContext* presContext = frame->PresContext(); - int32_t maxSizeInDevPixels = lm->GetMaxTextureSize(); + int32_t maxSizeInDevPixels = renderer->AsLayerManager()->GetMaxTextureSize(); if (maxSizeInDevPixels < 0 || maxSizeInDevPixels == INT_MAX) { return safeMaximum; } diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp index 241066d2cffe..dd4c9466a095 100644 --- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp @@ -4565,11 +4565,11 @@ nsresult PresShell::RenderDocument(const nsRect& aRect, nsView* view = rootFrame->GetView(); if (view && view->GetWidget() && nsLayoutUtils::GetDisplayRootFrame(rootFrame) == rootFrame) { - LayerManager* layerManager = view->GetWidget()->GetLayerManager(); + WindowRenderer* renderer = view->GetWidget()->GetWindowRenderer(); // ClientLayerManagers or WebRenderLayerManagers in content processes // don't support taking snapshots. - if (layerManager && - (!layerManager->AsKnowsCompositor() || XRE_IsParentProcess())) { + if (renderer && + (!renderer->AsKnowsCompositor() || XRE_IsParentProcess())) { flags |= PaintFrameFlags::WidgetLayers; } } @@ -5351,13 +5351,13 @@ struct PaintParams { nscolor mBackgroundColor; }; -LayerManager* PresShell::GetLayerManager() { +WindowRenderer* PresShell::GetWindowRenderer() { NS_ASSERTION(mViewManager, "Should have view manager"); nsView* rootView = mViewManager->GetRootView(); if (rootView) { if (nsIWidget* widget = rootView->GetWidget()) { - return widget->GetLayerManager(); + return widget->GetWindowRenderer(); } } return nullptr; @@ -5429,9 +5429,9 @@ void PresShell::SetRenderingState(const RenderingState& aState) { if (mRenderingStateFlags != aState.mRenderingStateFlags) { // Rendering state changed in a way that forces us to flush any // retained layers we might already have. - LayerManager* manager = GetLayerManager(); - if (manager) { - FrameLayerBuilder::InvalidateAllLayers(manager); + WindowRenderer* renderer = GetWindowRenderer(); + if (renderer && renderer->AsLayerManager()) { + FrameLayerBuilder::InvalidateAllLayers(renderer->AsLayerManager()); } } @@ -6271,9 +6271,10 @@ void PresShell::Paint(nsView* aViewToPaint, const nsRegion& aDirtyRegion, nsIFrame* frame = aViewToPaint->GetFrame(); - LayerManager* layerManager = aViewToPaint->GetWidget()->GetLayerManager(); - NS_ASSERTION(layerManager, "Must be in paint event"); - bool shouldInvalidate = layerManager->NeedsWidgetInvalidation(); + WindowRenderer* renderer = aViewToPaint->GetWidget()->GetWindowRenderer(); + NS_ASSERTION(renderer, "Must be in paint event"); + LayerManager* layerManager = renderer->AsLayerManager(); + bool shouldInvalidate = renderer->NeedsWidgetInvalidation(); nsAutoNotifyDidPaint notifyDidPaint(this, aFlags); @@ -6285,17 +6286,21 @@ void PresShell::Paint(nsView* aViewToPaint, const nsRegion& aDirtyRegion, MOZ_LOG(gLog, LogLevel::Debug, ("PresShell::Paint, first paint, this=%p", this)); - layerManager->SetIsFirstPaint(); + if (layerManager) { + layerManager->SetIsFirstPaint(); + } mIsFirstPaint = false; } - if (!layerManager->BeginTransaction(url)) { + if (!renderer->BeginTransaction(url)) { return; } // Send an updated focus target with this transaction. Be sure to do this // before we paint in the case this is an empty transaction. - layerManager->SetFocusTarget(mAPZFocusTarget); + if (layerManager) { + layerManager->SetFocusTarget(mAPZFocusTarget); + } if (frame) { // Try to do an empty transaction, if the frame tree does not @@ -6306,7 +6311,7 @@ void PresShell::Paint(nsView* aViewToPaint, const nsRegion& aDirtyRegion, // that will cause us to forget to update the real layer manager! if (!(aFlags & PaintFlags::PaintLayers)) { - if (layerManager->EndEmptyTransaction()) { + if (renderer->EndEmptyTransaction()) { return; } NS_WARNING("Must complete empty transaction when compositing!"); @@ -6321,22 +6326,23 @@ void PresShell::Paint(nsView* aViewToPaint, const nsRegion& aDirtyRegion, : 0; bool computeInvalidRect = computeInvalidFunc || - (layerManager->GetBackendType() == LayersBackend::LAYERS_BASIC); + (renderer->GetBackendType() == LayersBackend::LAYERS_BASIC); UniquePtr props; // For WR, the layermanager has no root layer. We want to avoid // calling ComputeDifferences in that case because it assumes non-null // and crashes. - if (computeInvalidRect && layerManager->GetRoot()) { + if (computeInvalidRect && layerManager && layerManager->GetRoot()) { props = LayerProperties::CloneFrom(layerManager->GetRoot()); } - MaybeSetupTransactionIdAllocator(layerManager, presContext); + if (layerManager) { + MaybeSetupTransactionIdAllocator(layerManager, presContext); + } - if (layerManager->EndEmptyTransaction( - (aFlags & PaintFlags::PaintComposite) - ? LayerManager::END_DEFAULT - : LayerManager::END_NO_COMPOSITE)) { + if (renderer->EndEmptyTransaction((aFlags & PaintFlags::PaintComposite) + ? LayerManager::END_DEFAULT + : LayerManager::END_NO_COMPOSITE)) { nsIntRegion invalid; bool areaOverflowed = false; if (props) { @@ -6344,7 +6350,7 @@ void PresShell::Paint(nsView* aViewToPaint, const nsRegion& aDirtyRegion, computeInvalidFunc)) { areaOverflowed = true; } - } else { + } else if (layerManager) { LayerProperties::ClearInvalidations(layerManager->GetRoot()); } if (props && !areaOverflowed) { @@ -6391,7 +6397,7 @@ void PresShell::Paint(nsView* aViewToPaint, const nsRegion& aDirtyRegion, flags |= PaintFrameFlags::Compressed; mNextPaintCompressed = false; } - if (layerManager->GetBackendType() == layers::LayersBackend::LAYERS_WR) { + if (renderer->GetBackendType() == layers::LayersBackend::LAYERS_WR) { flags |= PaintFrameFlags::ForWebRender; } @@ -6402,6 +6408,12 @@ void PresShell::Paint(nsView* aViewToPaint, const nsRegion& aDirtyRegion, return; } + if (!layerManager) { + // TODO: Once we support WindowRenderers that aren't a LayerManager, + // then we need to handle this single color case for them. + return; + } + if (layerManager->GetBackendType() == layers::LayersBackend::LAYERS_WR) { nsPresContext* pc = GetPresContext(); LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits( diff --git a/layout/base/PresShell.h b/layout/base/PresShell.h index f51bdf04c9a0..0efbd50e07a1 100644 --- a/layout/base/PresShell.h +++ b/layout/base/PresShell.h @@ -912,10 +912,10 @@ class PresShell final : public nsStubDocumentObserver, already_AddRefed GetFocusedContentInOurWindow() const; /** - * Get the layer manager for the widget of the root view, if it has + * Get the window renderer for the widget of the root view, if it has * one. */ - LayerManager* GetLayerManager(); + WindowRenderer* GetWindowRenderer(); /** * Return true iff there is a widget rendering this presShell and that diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index b14813fd5ba6..84a19df600d4 100644 --- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -2435,9 +2435,9 @@ void nsRefreshDriver::Tick(VsyncId aId, TimeStamp aNowTime, // Forward our composition payloads to the layer manager. if (!mCompositionPayloads.IsEmpty()) { nsIWidget* widget = mPresContext->GetRootWidget(); - layers::LayerManager* lm = widget ? widget->GetLayerManager() : nullptr; - if (lm) { - lm->RegisterPayloads(mCompositionPayloads); + WindowRenderer* renderer = widget ? widget->GetWindowRenderer() : nullptr; + if (renderer && renderer->AsLayerManager()) { + renderer->AsLayerManager()->RegisterPayloads(mCompositionPayloads); } mCompositionPayloads.Clear(); } diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index a79f841a1c8b..2d46c2c063e5 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -3089,8 +3089,9 @@ void ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, PAINT_SKIP_LOG("Skipping due to APZ scroll\n"); } else if (mScrollableByAPZ) { nsIWidget* widget = presContext->GetNearestWidget(); - LayerManager* manager = widget ? widget->GetLayerManager() : nullptr; - if (manager) { + WindowRenderer* renderer = + widget ? widget->GetWindowRenderer() : nullptr; + if (renderer) { mozilla::layers::ScrollableLayerGuid::ViewID id; bool success = nsLayoutUtils::FindIDFor(content, &id); MOZ_ASSERT(success); // we have a displayport, we better have an ID @@ -3100,7 +3101,7 @@ void ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, // might still get squashed into a full transaction if something // happens to trigger one. MOZ_ASSERT(!mScrollUpdates.IsEmpty()); - success = manager->AddPendingScrollUpdateForNextTransaction( + success = renderer->AddPendingScrollUpdateForNextTransaction( id, mScrollUpdates.LastElement()); if (success) { schedulePaint = false; diff --git a/layout/ipc/RemoteLayerTreeOwner.cpp b/layout/ipc/RemoteLayerTreeOwner.cpp index a55cf461a6c2..992199053e27 100644 --- a/layout/ipc/RemoteLayerTreeOwner.cpp +++ b/layout/ipc/RemoteLayerTreeOwner.cpp @@ -32,12 +32,18 @@ namespace layout { static already_AddRefed GetLayerManager( BrowserParent* aBrowserParent) { + RefPtr lm; if (Element* element = aBrowserParent->GetOwnerElement()) { - if (RefPtr lm = - nsContentUtils::LayerManagerForContent(element)) { + if (WindowRenderer* renderer = + nsContentUtils::WindowRendererForContent(element)) { + lm = renderer->AsLayerManager(); + return lm.forget(); + } + if (WindowRenderer* renderer = + nsContentUtils::WindowRendererForDocument(element->OwnerDoc())) { + lm = renderer->AsLayerManager(); return lm.forget(); } - return nsContentUtils::LayerManagerForDocument(element->OwnerDoc()); } return nullptr; } diff --git a/layout/painting/WindowRenderer.cpp b/layout/painting/WindowRenderer.cpp new file mode 100644 index 000000000000..421983254f8b --- /dev/null +++ b/layout/painting/WindowRenderer.cpp @@ -0,0 +1,170 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "WindowRenderer.h" + +#include "mozilla/dom/Animation.h" // for Animation +#include "mozilla/layers/PersistentBufferProvider.h" // for PersistentBufferProviderBasic, PersistentBufferProvider (ptr only) + +namespace mozilla { + +/** + * StartFrameTimeRecording, together with StopFrameTimeRecording + * enable recording of frame intervals. + * + * To allow concurrent consumers, a cyclic array is used which serves all + * consumers, practically stateless with regard to consumers. + * + * To save resources, the buffer is allocated on first call to + * StartFrameTimeRecording and recording is paused if no consumer which called + * StartFrameTimeRecording is able to get valid results (because the cyclic + * buffer was overwritten since that call). + * + * To determine availability of the data upon StopFrameTimeRecording: + * - mRecording.mNextIndex increases on each RecordFrame, and never resets. + * - Cyclic buffer position is realized as mNextIndex % bufferSize. + * - StartFrameTimeRecording returns mNextIndex. When StopFrameTimeRecording is + * called, the required start index is passed as an arg, and we're able to + * calculate the required length. If this length is bigger than bufferSize, it + * means data was overwritten. otherwise, we can return the entire sequence. + * - To determine if we need to pause, mLatestStartIndex is updated to + * mNextIndex on each call to StartFrameTimeRecording. If this index gets + * overwritten, it means that all earlier start indices obtained via + * StartFrameTimeRecording were also overwritten, hence, no point in + * recording, so pause. + * - mCurrentRunStartIndex indicates the oldest index of the recording after + * which the recording was not paused. If StopFrameTimeRecording is invoked + * with a start index older than this, it means that some frames were not + * recorded, so data is invalid. + */ +uint32_t FrameRecorder::StartFrameTimeRecording(int32_t aBufferSize) { + if (mRecording.mIsPaused) { + mRecording.mIsPaused = false; + + if (!mRecording.mIntervals.Length()) { // Initialize recording buffers + mRecording.mIntervals.SetLength(aBufferSize); + } + + // After being paused, recent values got invalid. Update them to now. + mRecording.mLastFrameTime = TimeStamp::Now(); + + // Any recording which started before this is invalid, since we were paused. + mRecording.mCurrentRunStartIndex = mRecording.mNextIndex; + } + + // If we'll overwrite this index, there are no more consumers with aStartIndex + // for which we're able to provide the full recording, so no point in keep + // recording. + mRecording.mLatestStartIndex = mRecording.mNextIndex; + return mRecording.mNextIndex; +} + +void FrameRecorder::RecordFrame() { + if (!mRecording.mIsPaused) { + TimeStamp now = TimeStamp::Now(); + uint32_t i = mRecording.mNextIndex % mRecording.mIntervals.Length(); + mRecording.mIntervals[i] = + static_cast((now - mRecording.mLastFrameTime).ToMilliseconds()); + mRecording.mNextIndex++; + mRecording.mLastFrameTime = now; + + if (mRecording.mNextIndex > + (mRecording.mLatestStartIndex + mRecording.mIntervals.Length())) { + // We've just overwritten the most recent recording start -> pause. + mRecording.mIsPaused = true; + } + } +} + +void FrameRecorder::StopFrameTimeRecording(uint32_t aStartIndex, + nsTArray& aFrameIntervals) { + uint32_t bufferSize = mRecording.mIntervals.Length(); + uint32_t length = mRecording.mNextIndex - aStartIndex; + if (mRecording.mIsPaused || length > bufferSize || + aStartIndex < mRecording.mCurrentRunStartIndex) { + // aStartIndex is too old. Also if aStartIndex was issued before + // mRecordingNextIndex overflowed (uint32_t) + // and stopped after the overflow (would happen once every 828 days of + // constant 60fps). + length = 0; + } + + if (!length) { + aFrameIntervals.Clear(); + return; // empty recording, return empty arrays. + } + // Set length in advance to avoid possibly repeated reallocations + aFrameIntervals.SetLength(length); + + uint32_t cyclicPos = aStartIndex % bufferSize; + for (uint32_t i = 0; i < length; i++, cyclicPos++) { + if (cyclicPos == bufferSize) { + cyclicPos = 0; + } + aFrameIntervals[i] = mRecording.mIntervals[cyclicPos]; + } +} + +already_AddRefed +WindowRenderer::CreatePersistentBufferProvider( + const mozilla::gfx::IntSize& aSize, mozilla::gfx::SurfaceFormat aFormat) { + RefPtr bufferProvider; + // If we are using remote canvas we don't want to use acceleration in + // non-remote layer managers, so we always use the fallback software one. + if (!gfxPlatform::UseRemoteCanvas() || + !gfxPlatform::IsBackendAccelerated( + gfxPlatform::GetPlatform()->GetPreferredCanvasBackend())) { + bufferProvider = PersistentBufferProviderBasic::Create( + aSize, aFormat, + gfxPlatform::GetPlatform()->GetPreferredCanvasBackend()); + } + + if (!bufferProvider) { + bufferProvider = PersistentBufferProviderBasic::Create( + aSize, aFormat, gfxPlatform::GetPlatform()->GetFallbackCanvasBackend()); + } + + return bufferProvider.forget(); +} + +void WindowRenderer::AddPartialPrerenderedAnimation( + uint64_t aCompositorAnimationId, dom::Animation* aAnimation) { + mPartialPrerenderedAnimations.InsertOrUpdate(aCompositorAnimationId, + RefPtr{aAnimation}); + aAnimation->SetPartialPrerendered(aCompositorAnimationId); +} +void WindowRenderer::RemovePartialPrerenderedAnimation( + uint64_t aCompositorAnimationId, dom::Animation* aAnimation) { + MOZ_ASSERT(aAnimation); +#ifdef DEBUG + RefPtr animation; + if (mPartialPrerenderedAnimations.Remove(aCompositorAnimationId, + getter_AddRefs(animation)) && + // It may be possible that either animation's effect has already been + // nulled out via Animation::SetEffect() so ignore such cases. + aAnimation->GetEffect() && aAnimation->GetEffect()->AsKeyframeEffect() && + animation->GetEffect() && animation->GetEffect()->AsKeyframeEffect()) { + MOZ_ASSERT(EffectSet::GetEffectSetForEffect( + aAnimation->GetEffect()->AsKeyframeEffect()) == + EffectSet::GetEffectSetForEffect( + animation->GetEffect()->AsKeyframeEffect())); + } +#else + mPartialPrerenderedAnimations.Remove(aCompositorAnimationId); +#endif + aAnimation->ResetPartialPrerendered(); +} +void WindowRenderer::UpdatePartialPrerenderedAnimations( + const nsTArray& aJankedAnimations) { + for (uint64_t id : aJankedAnimations) { + RefPtr animation; + if (mPartialPrerenderedAnimations.Remove(id, getter_AddRefs(animation))) { + animation->UpdatePartialPrerendered(); + } + } +} + +} // namespace mozilla diff --git a/layout/painting/WindowRenderer.h b/layout/painting/WindowRenderer.h new file mode 100644 index 000000000000..6ffd1eb9dba6 --- /dev/null +++ b/layout/painting/WindowRenderer.h @@ -0,0 +1,210 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef MOZILLA_PAINTING_WINDOWRENDERER_H +#define MOZILLA_PAINTING_WINDOWRENDERER_H + +#include "mozilla/layers/LayersTypes.h" +#include "mozilla/dom/Animation.h" // for Animation +#include "mozilla/layers/ScrollableLayerGuid.h" // for ScrollableLayerGuid, ScrollableLayerGuid::ViewID +#include "nsRefPtrHashtable.h" // for nsRefPtrHashtable + +namespace mozilla { + +namespace layers { +class LayerManager; +class WebRenderLayerManager; +class KnowsCompositor; +class ShadowLayerForwarder; +class CompositorBridgeChild; +class ClientLayerManager; +class FrameUniformityData; +class PersistentBufferProvider; +} // namespace layers + +class FrameRecorder { + public: + /** + * Record (and return) frame-intervals and paint-times for frames which were + * presented between calling StartFrameTimeRecording and + * StopFrameTimeRecording. + * + * - Uses a cyclic buffer and serves concurrent consumers, so if Stop is + * called too late + * (elements were overwritten since Start), result is considered invalid + * and hence empty.) + * - Buffer is capable of holding 10 seconds @ 60fps (or more if frames were + * less frequent). + * Can be changed (up to 1 hour) via pref: + * toolkit.framesRecording.bufferSize. + * - Note: the first frame-interval may be longer than expected because last + * frame + * might have been presented some time before calling + * StartFrameTimeRecording. + */ + + /** + * Returns a handle which represents current recording start position. + */ + virtual uint32_t StartFrameTimeRecording(int32_t aBufferSize); + + /** + * Clears, then populates aFrameIntervals with the recorded frame timing + * data. The array will be empty if data was overwritten since + * aStartIndex was obtained. + */ + virtual void StopFrameTimeRecording(uint32_t aStartIndex, + nsTArray& aFrameIntervals); + + void RecordFrame(); + + private: + struct FramesTimingRecording { + // Stores state and data for frame intervals and paint times recording. + // see LayerManager::StartFrameTimeRecording() at Layers.cpp for more + // details. + FramesTimingRecording() + : mNextIndex(0), + mLatestStartIndex(0), + mCurrentRunStartIndex(0), + mIsPaused(true) {} + nsTArray mIntervals; + TimeStamp mLastFrameTime; + uint32_t mNextIndex; + uint32_t mLatestStartIndex; + uint32_t mCurrentRunStartIndex; + bool mIsPaused; + }; + FramesTimingRecording mRecording; +}; + +class WindowRenderer : public FrameRecorder { + public: + // Cast to implementation types. + virtual layers::LayerManager* AsLayerManager() { return nullptr; } + virtual layers::WebRenderLayerManager* AsWebRender() { return nullptr; } + + // Required functionality + + /** + * Start a new transaction. Nested transactions are not allowed so + * there must be no transaction currently in progress. + * This transaction will update the state of the window from which + * this LayerManager was obtained. + */ + virtual bool BeginTransaction(const nsCString& aURL = nsCString()) = 0; + + enum EndTransactionFlags { + END_DEFAULT = 0, + END_NO_IMMEDIATE_REDRAW = 1 << 0, // Do not perform the drawing phase + END_NO_COMPOSITE = + 1 << 1, // Do not composite after drawing painted layer contents. + END_NO_REMOTE_COMPOSITE = 1 << 2 // Do not schedule a composition with a + // remote Compositor, if one exists. + }; + + /** + * Attempts to end an "empty transaction". There must have been no + * changes to the layer tree since the BeginTransaction(). + * It's possible for this to fail; PaintedLayers may need to be updated + * due to VRAM data being lost, for example. In such cases this method + * returns false, and the caller must proceed with a normal layer tree + * update and EndTransaction. + */ + virtual bool EndEmptyTransaction( + EndTransactionFlags aFlags = END_DEFAULT) = 0; + + /** + * Type of layer manager this is. This is to be used sparsely in order to + * avoid a lot of Layers backend specific code. It should be used only when + * Layers backend specific functionality is necessary. + */ + virtual layers::LayersBackend GetBackendType() = 0; + + /** + * Type of layers backend that will be used to composite this layer tree. + * When compositing is done remotely, then this returns the layers type + * of the compositor. + */ + virtual layers::LayersBackend GetCompositorBackendType() { + return GetBackendType(); + } + + /** + * Checks if we need to invalidate the OS widget to trigger + * painting when updating this renderer. + */ + virtual bool NeedsWidgetInvalidation() { return true; } + + /** + * Make sure that the previous transaction has been entirely + * completed. + * + * Note: This may sychronously wait on a remote compositor + * to complete rendering. + */ + virtual void FlushRendering() {} + + /** + * Make sure that the previous transaction has been + * received. This will synchronsly wait on a remote compositor. + */ + virtual void WaitOnTransactionProcessed() {} + + /** + * Return the name of the layer manager's backend. + */ + virtual void GetBackendName(nsAString& aName) = 0; + + virtual void GetFrameUniformity(layers::FrameUniformityData* aOutData) {} + + virtual bool AddPendingScrollUpdateForNextTransaction( + layers::ScrollableLayerGuid::ViewID aScrollId, + const ScrollPositionUpdate& aUpdateInfo) { + return false; + } + + /** + * Creates a PersistentBufferProvider for use with canvas which is optimized + * for inter-operating with this layermanager. + */ + virtual already_AddRefed + CreatePersistentBufferProvider(const mozilla::gfx::IntSize& aSize, + mozilla::gfx::SurfaceFormat aFormat); + + // Helper wrappers around cast to impl and then cast again. + + virtual layers::KnowsCompositor* AsKnowsCompositor() { return nullptr; } + + virtual layers::ShadowLayerForwarder* AsShadowForwarder() { return nullptr; } + + virtual layers::CompositorBridgeChild* GetCompositorBridgeChild() { + return nullptr; + } + + virtual layers::ClientLayerManager* AsClientLayerManager() { return nullptr; } + + // Provided functionality + + void AddPartialPrerenderedAnimation(uint64_t aCompositorAnimationId, + dom::Animation* aAnimation); + void RemovePartialPrerenderedAnimation(uint64_t aCompositorAnimationId, + dom::Animation* aAnimation); + void UpdatePartialPrerenderedAnimations( + const nsTArray& aJankedAnimations); + + protected: + // Transform animations which are not fully pre-rendered because it's on a + // large frame. We need to update the pre-rendered area once after we tried + // to composite area which is outside of the pre-rendered area on the + // compositor. + nsRefPtrHashtable + mPartialPrerenderedAnimations; +}; + +} // namespace mozilla + +#endif /* MOZILLA_PAINTING_WINDOWRENDERER_H */ diff --git a/layout/painting/moz.build b/layout/painting/moz.build index f27a971afa30..8385a6b684a8 100644 --- a/layout/painting/moz.build +++ b/layout/painting/moz.build @@ -27,6 +27,7 @@ EXPORTS += [ "RetainedDisplayListBuilder.h", "RetainedDisplayListHelpers.h", "TransformClipNode.h", + "WindowRenderer.h", ] EXPORTS.mozilla += [ @@ -51,6 +52,7 @@ UNIFIED_SOURCES += [ "nsImageRenderer.cpp", "PaintTracker.cpp", "RetainedDisplayListBuilder.cpp", + "WindowRenderer.cpp", ] include("/ipc/chromium/chromium-config.mozbuild") diff --git a/layout/painting/nsDisplayList.cpp b/layout/painting/nsDisplayList.cpp index 26f502592497..6596b089ef9e 100644 --- a/layout/painting/nsDisplayList.cpp +++ b/layout/painting/nsDisplayList.cpp @@ -2294,7 +2294,10 @@ LayerManager* nsDisplayListBuilder::GetWidgetLayerManager(nsView** aView) { } nsIWidget* window = RootReferenceFrame()->GetNearestWidget(); if (window) { - return window->GetLayerManager(); + WindowRenderer* renderer = window->GetWindowRenderer(); + if (renderer) { + return renderer->AsLayerManager(); + } } return nullptr; } @@ -6455,8 +6458,8 @@ bool nsDisplayOwnLayer::CreateWebRenderCommands( return true; } -bool nsDisplayOwnLayer::UpdateScrollData( - WebRenderScrollData* aData, WebRenderLayerScrollData* aLayerData) { +bool nsDisplayOwnLayer::UpdateScrollData(WebRenderScrollData* aData, + WebRenderLayerScrollData* aLayerData) { bool isRelevantToApz = (IsScrollThumbLayer() || IsScrollbarContainer() || IsZoomingLayer() || (IsFixedPositionLayer() && HasDynamicToolbar()) || @@ -6757,8 +6760,7 @@ bool nsDisplayFixedPosition::CreateWebRenderCommands( } bool nsDisplayFixedPosition::UpdateScrollData( - WebRenderScrollData* aData, - WebRenderLayerScrollData* aLayerData) { + WebRenderScrollData* aData, WebRenderLayerScrollData* aLayerData) { if (aLayerData) { if (!mIsFixedBackground) { aLayerData->SetFixedPositionSides( @@ -7139,8 +7141,7 @@ void nsDisplayStickyPosition::CalculateLayerScrollRanges( } bool nsDisplayStickyPosition::UpdateScrollData( - WebRenderScrollData* aData, - WebRenderLayerScrollData* aLayerData) { + WebRenderScrollData* aData, WebRenderLayerScrollData* aLayerData) { bool hasDynamicToolbar = HasDynamicToolbar(); if (aLayerData && hasDynamicToolbar) { StickyScrollContainer* stickyScrollContainer = GetStickyScrollContainer(); @@ -7226,8 +7227,7 @@ UniquePtr nsDisplayScrollInfoLayer::ComputeScrollMetadata( } bool nsDisplayScrollInfoLayer::UpdateScrollData( - WebRenderScrollData* aData, - WebRenderLayerScrollData* aLayerData) { + WebRenderScrollData* aData, WebRenderLayerScrollData* aLayerData) { if (aLayerData) { UniquePtr metadata = ComputeScrollMetadata( aData->GetBuilder(), aData->GetManager(), ContainerLayerParameters()); @@ -7331,8 +7331,7 @@ bool nsDisplayZoom::ComputeVisibility(nsDisplayListBuilder* aBuilder, nsDisplayAsyncZoom::nsDisplayAsyncZoom( nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayList* aList, - const ActiveScrolledRoot* aActiveScrolledRoot, - FrameMetrics::ViewID aViewID) + const ActiveScrolledRoot* aActiveScrolledRoot, FrameMetrics::ViewID aViewID) : nsDisplayOwnLayer(aBuilder, aFrame, aList, aActiveScrolledRoot), mViewID(aViewID) { MOZ_COUNT_CTOR(nsDisplayAsyncZoom); @@ -7377,8 +7376,7 @@ already_AddRefed nsDisplayAsyncZoom::BuildLayer( } bool nsDisplayAsyncZoom::UpdateScrollData( - WebRenderScrollData* aData, - WebRenderLayerScrollData* aLayerData) { + WebRenderScrollData* aData, WebRenderLayerScrollData* aLayerData) { bool ret = nsDisplayOwnLayer::UpdateScrollData(aData, aLayerData); MOZ_ASSERT(ret); if (aLayerData) { @@ -8143,8 +8141,7 @@ bool nsDisplayTransform::CreateWebRenderCommands( } bool nsDisplayTransform::UpdateScrollData( - WebRenderScrollData* aData, - WebRenderLayerScrollData* aLayerData) { + WebRenderScrollData* aData, WebRenderLayerScrollData* aLayerData) { if (!mFrame->ChildrenHavePerspective()) { // This case is handled in CreateWebRenderCommands by stashing the transform // on the stacking context. diff --git a/layout/painting/nsDisplayListInvalidation.h b/layout/painting/nsDisplayListInvalidation.h index 2cf1c861c927..7b1642ddaabd 100644 --- a/layout/painting/nsDisplayListInvalidation.h +++ b/layout/painting/nsDisplayListInvalidation.h @@ -9,6 +9,7 @@ #include "mozilla/Attributes.h" #include "FrameLayerBuilder.h" +#include "ImgDrawResult.h" #include "nsRect.h" #include "nsColor.h" #include "gfxRect.h" diff --git a/toolkit/components/browser/nsWebBrowser.cpp b/toolkit/components/browser/nsWebBrowser.cpp index 42213c4a461f..c382ff5199df 100644 --- a/toolkit/components/browser/nsWebBrowser.cpp +++ b/toolkit/components/browser/nsWebBrowser.cpp @@ -1177,7 +1177,9 @@ void nsWebBrowser::WindowDeactivated() { bool nsWebBrowser::PaintWindow(nsIWidget* aWidget, LayoutDeviceIntRegion aRegion) { - LayerManager* layerManager = aWidget->GetLayerManager(); + WindowRenderer* renderer = aWidget->GetWindowRenderer(); + NS_ASSERTION(renderer, "Must be in paint event"); + LayerManager* layerManager = renderer->AsLayerManager(); NS_ASSERTION(layerManager, "Must be in paint event"); layerManager->BeginTransaction(); diff --git a/view/nsViewManager.cpp b/view/nsViewManager.cpp index e20db88e57ad..cda53c873490 100644 --- a/view/nsViewManager.cpp +++ b/view/nsViewManager.cpp @@ -329,9 +329,9 @@ void nsViewManager::Refresh(nsView* aView, printf_stderr("--COMPOSITE-- %p\n", presShell.get()); } #endif - LayerManager* manager = widget->GetLayerManager(); - if (!manager->NeedsWidgetInvalidation()) { - manager->FlushRendering(); + WindowRenderer* renderer = widget->GetWindowRenderer(); + if (!renderer->NeedsWidgetInvalidation()) { + renderer->FlushRendering(); } else { presShell->Paint(aView, damageRegion, PaintFlags::PaintComposite); } @@ -619,9 +619,9 @@ void nsViewManager::InvalidateViews(nsView* aView) { void nsViewManager::WillPaintWindow(nsIWidget* aWidget) { if (aWidget) { nsView* view = nsView::GetViewFor(aWidget); - LayerManager* manager = aWidget->GetLayerManager(); + WindowRenderer* renderer = aWidget->GetWindowRenderer(); if (view && - (view->ForcedRepaint() || !manager->NeedsWidgetInvalidation())) { + (view->ForcedRepaint() || !renderer->NeedsWidgetInvalidation())) { ProcessPendingUpdates(); // Re-get the view pointer here since the ProcessPendingUpdates might have // destroyed it during CallWillPaintOnObservers. diff --git a/widget/PuppetWidget.cpp b/widget/PuppetWidget.cpp index 5823fab8834a..b769736fbb81 100644 --- a/widget/PuppetWidget.cpp +++ b/widget/PuppetWidget.cpp @@ -117,7 +117,7 @@ void PuppetWidget::InfallibleCreate(nsIWidget* aParent, PuppetWidget* parent = static_cast(aParent); if (parent) { parent->SetChild(this); - mLayerManager = parent->GetLayerManager(); + mLayerManager = parent->GetWindowRenderer()->AsLayerManager(); } else { Resize(mBounds.X(), mBounds.Y(), mBounds.Width(), mBounds.Height(), false); } @@ -585,7 +585,7 @@ bool PuppetWidget::GetEditCommands(NativeKeyBindingsType aType, return true; } -LayerManager* PuppetWidget::GetLayerManager() { +WindowRenderer* PuppetWidget::GetWindowRenderer() { if (!mLayerManager) { if (XRE_IsParentProcess()) { // On the parent process there is no CompositorBridgeChild which confuses diff --git a/widget/PuppetWidget.h b/widget/PuppetWidget.h index f6f2c6c6eb84..c765e495815e 100644 --- a/widget/PuppetWidget.h +++ b/widget/PuppetWidget.h @@ -171,7 +171,7 @@ class PuppetWidget : public nsBaseWidget, return eTransparencyTransparent; } - virtual LayerManager* GetLayerManager() override; + virtual WindowRenderer* GetWindowRenderer() override; // This is used for creating remote layer managers and for re-creating // them after a compositor reset. The lambda aInitializeFunc is used to diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index b9924fb5f984..51be701f6e60 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -2176,7 +2176,7 @@ nsresult nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen*) { return NS_OK; } -mozilla::layers::LayerManager* nsWindow::GetLayerManager() { +mozilla::WindowRenderer* nsWindow::GetWindowRenderer() { if (mLayerManager) { return mLayerManager; } @@ -2571,7 +2571,7 @@ bool nsWindow::WidgetPaintsBackground() { bool nsWindow::NeedsPaint() { auto lvs(mLayerViewSupport.Access()); - if (!lvs || lvs->CompositorPaused() || !GetLayerManager(nullptr)) { + if (!lvs || lvs->CompositorPaused() || !GetWindowRenderer()) { return false; } diff --git a/widget/android/nsWindow.h b/widget/android/nsWindow.h index fadce4940be7..6db10ac85b7c 100644 --- a/widget/android/nsWindow.h +++ b/widget/android/nsWindow.h @@ -55,7 +55,7 @@ class nsWindow final : public nsBaseWidget { virtual ~nsWindow(); public: - using nsBaseWidget::GetLayerManager; + using nsBaseWidget::GetWindowRenderer; nsWindow(); @@ -178,7 +178,7 @@ class nsWindow final : public nsBaseWidget { const InputContextAction& aAction) override; virtual InputContext GetInputContext() override; - LayerManager* GetLayerManager() override; + WindowRenderer* GetWindowRenderer() override; virtual bool NeedsPaint() override; diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index b7c6b0f3f500..7209027e9f93 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -1203,7 +1203,7 @@ void nsChildView::Invalidate(const LayoutDeviceIntRect& aRect) { if (!mView || !mVisible) return; - NS_ASSERTION(GetLayerManager()->GetBackendType() != LayersBackend::LAYERS_CLIENT, + NS_ASSERTION(GetWindowRenderer()->GetBackendType() != LayersBackend::LAYERS_CLIENT, "Shouldn't need to invalidate with accelerated OMTC layers!"); EnsureContentLayerForMainThreadPainting(); @@ -1348,12 +1348,12 @@ bool nsChildView::PaintWindowInDrawTarget(gfx::DrawTarget* aDT, targetContext->Clip(); nsAutoRetainCocoaObject kungFuDeathGrip(mView); - if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC) { + if (GetWindowRenderer()->GetBackendType() == LayersBackend::LAYERS_BASIC) { nsBaseWidget::AutoLayerManagerSetup setupLayerManager(this, targetContext, BufferMode::BUFFER_NONE); return PaintWindow(aRegion); } - if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT) { + if (GetWindowRenderer()->GetBackendType() == LayersBackend::LAYERS_CLIENT) { // We only need this so that we actually get DidPaintWindow fired return PaintWindow(aRegion); } @@ -1399,7 +1399,7 @@ void nsChildView::PaintWindowInContentLayer() { void nsChildView::HandleMainThreadCATransaction() { WillPaintWindow(); - if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC) { + if (GetWindowRenderer()->GetBackendType() == LayersBackend::LAYERS_BASIC) { // We're in BasicLayers mode, i.e. main thread software compositing. // Composite the window into our layer's surface. PaintWindowInContentLayer(); diff --git a/widget/cocoa/nsCocoaWindow.h b/widget/cocoa/nsCocoaWindow.h index a232d9c0fab0..9d9ecef4cf9a 100644 --- a/widget/cocoa/nsCocoaWindow.h +++ b/widget/cocoa/nsCocoaWindow.h @@ -296,7 +296,7 @@ class nsCocoaWindow final : public nsBaseWidget, public nsPIWidgetCocoa { virtual void Invalidate(const LayoutDeviceIntRect& aRect) override; virtual nsresult ConfigureChildren(const nsTArray& aConfigurations) override; - virtual LayerManager* GetLayerManager() override; + virtual WindowRenderer* GetWindowRenderer() override; virtual nsresult DispatchEvent(mozilla::WidgetGUIEvent* aEvent, nsEventStatus& aStatus) override; virtual void CaptureRollupEvents(nsIRollupListener* aListener, bool aDoCapture) override; [[nodiscard]] virtual nsresult GetAttention(int32_t aCycleCount) override; diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm index 7133ec34637f..da26bd42ae7b 100644 --- a/widget/cocoa/nsCocoaWindow.mm +++ b/widget/cocoa/nsCocoaWindow.mm @@ -1035,9 +1035,9 @@ nsresult nsCocoaWindow::ConfigureChildren(const nsTArray& aConfig return NS_OK; } -LayerManager* nsCocoaWindow::GetLayerManager() { +WindowRenderer* nsCocoaWindow::GetWindowRenderer() { if (mPopupContentView) { - return mPopupContentView->GetLayerManager(); + return mPopupContentView->GetWindowRenderer(); } return nullptr; } diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp index d20edf4db53d..3753b6b73b1d 100644 --- a/widget/gtk/nsWindow.cpp +++ b/widget/gtk/nsWindow.cpp @@ -3382,11 +3382,15 @@ gboolean nsWindow::OnExposeEvent(cairo_t* cr) { LayoutDeviceIntRegion region = exposeRegion; region.ScaleRoundOut(scale, scale); - if (GetLayerManager()->AsKnowsCompositor() && mCompositorSession) { + WindowRenderer* renderer = GetWindowRenderer(); + LayerManager* layerManager = renderer->AsLayerManager(); + KnowsCompositor* knowsCompositor = renderer->AsKnowsCompositor(); + + if (knowsCompositor && layerManager && mCompositorSession) { // We need to paint to the screen even if nothing changed, since if we // don't have a compositing window manager, our pixels could be stale. - GetLayerManager()->SetNeedsComposite(true); - GetLayerManager()->SendInvalidRegion(region.ToUnknownRegion()); + layerManager->SetNeedsComposite(true); + layerManager->SendInvalidRegion(region.ToUnknownRegion()); } RefPtr strongThis(this); @@ -3406,10 +3410,9 @@ gboolean nsWindow::OnExposeEvent(cairo_t* cr) { if (!listener) return FALSE; } - if (GetLayerManager()->AsKnowsCompositor() && - GetLayerManager()->NeedsComposite()) { - GetLayerManager()->ScheduleComposite(); - GetLayerManager()->SetNeedsComposite(false); + if (knowsCompositor && layerManager && layerManager->NeedsComposite()) { + layerManager->ScheduleComposite(); + layerManager->SetNeedsComposite(false); } // Our bounds may have changed after calling WillPaintWindow. Clip @@ -3460,8 +3463,8 @@ gboolean nsWindow::OnExposeEvent(cairo_t* cr) { } // If this widget uses OMTC... - if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT || - GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_WR) { + if (renderer->GetBackendType() == LayersBackend::LAYERS_CLIENT || + renderer->GetBackendType() == LayersBackend::LAYERS_WR) { listener->PaintWindow(this, region); // Re-get the listener since the will paint notification might have @@ -3526,7 +3529,7 @@ gboolean nsWindow::OnExposeEvent(cairo_t* cr) { bool painted = false; { - if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC) { + if (renderer->GetBackendType() == LayersBackend::LAYERS_BASIC) { if (GetTransparencyMode() == eTransparencyTransparent && layerBuffering == BufferMode::BUFFER_NONE && mHasAlphaVisual) { // If our draw target is unbuffered and we use an alpha channel, @@ -3668,7 +3671,7 @@ gboolean nsWindow::OnConfigureEvent(GtkWidget* aWidget, // frame, and its contents might be incorrect. See bug 1280653 comment 7 // and comment 10. Specifically we must ensure we recomposite the frame // as soon as possible to avoid the corrupted frame being displayed. - GetLayerManager()->FlushRendering(); + GetWindowRenderer()->FlushRendering(); return FALSE; } @@ -8276,7 +8279,7 @@ nsresult nsWindow::BeginResizeDrag(WidgetGUIEvent* aEvent, int32_t aHorizontal, return NS_OK; } -nsIWidget::LayerManager* nsWindow::GetLayerManager() { +nsIWidget::WindowRenderer* nsWindow::GetWindowRenderer() { if (mIsDestroyed) { // Prevent external code from triggering the re-creation of the // LayerManager/Compositor during shutdown. Just return what we currently @@ -8284,7 +8287,7 @@ nsIWidget::LayerManager* nsWindow::GetLayerManager() { return mLayerManager; } - return nsBaseWidget::GetLayerManager(); + return nsBaseWidget::GetWindowRenderer(); } void nsWindow::SetCompositorWidgetDelegate(CompositorWidgetDelegate* delegate) { diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h index 9df0b03c15aa..190f6ab9001b 100644 --- a/widget/gtk/nsWindow.h +++ b/widget/gtk/nsWindow.h @@ -598,7 +598,7 @@ class nsWindow final : public nsBaseWidget { void DispatchMissedButtonReleases(GdkEventCrossing* aGdkEvent); // nsBaseWidget - virtual LayerManager* GetLayerManager() override; + virtual WindowRenderer* GetWindowRenderer() override; void SetCompositorWidgetDelegate(CompositorWidgetDelegate* delegate) override; diff --git a/widget/headless/HeadlessWidget.cpp b/widget/headless/HeadlessWidget.cpp index 0f4f00bda4fe..4b419261bd62 100644 --- a/widget/headless/HeadlessWidget.cpp +++ b/widget/headless/HeadlessWidget.cpp @@ -250,8 +250,8 @@ LayoutDeviceIntPoint HeadlessWidget::WidgetToScreenOffset() { return mTopLevel->GetBounds().TopLeft(); } -LayerManager* HeadlessWidget::GetLayerManager() { - return nsBaseWidget::GetLayerManager(); +WindowRenderer* HeadlessWidget::GetWindowRenderer() { + return nsBaseWidget::GetWindowRenderer(); } void HeadlessWidget::SetCompositorWidgetDelegate( diff --git a/widget/headless/HeadlessWidget.h b/widget/headless/HeadlessWidget.h index a81338925c7b..60ba5d03bbd4 100644 --- a/widget/headless/HeadlessWidget.h +++ b/widget/headless/HeadlessWidget.h @@ -100,7 +100,7 @@ class HeadlessWidget : public nsBaseWidget { } virtual InputContext GetInputContext() override { return mInputContext; } - virtual LayerManager* GetLayerManager() override; + virtual WindowRenderer* GetWindowRenderer() override; void SetCompositorWidgetDelegate(CompositorWidgetDelegate* delegate) override; diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index 1d975b49bca9..0c4022e23305 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -884,7 +884,9 @@ nsBaseWidget::AutoLayerManagerSetup::AutoLayerManagerSetup( nsBaseWidget* aWidget, gfxContext* aTarget, BufferMode aDoubleBuffering, ScreenRotation aRotation) : mWidget(aWidget) { - LayerManager* lm = mWidget->GetLayerManager(); + LayerManager* lm = mWidget->GetWindowRenderer() + ? mWidget->GetWindowRenderer()->AsLayerManager() + : nullptr; NS_ASSERTION( !lm || lm->GetBackendType() == LayersBackend::LAYERS_BASIC, "AutoLayerManagerSetup instantiated for non-basic layer backend!"); @@ -1505,7 +1507,7 @@ bool nsBaseWidget::ShouldUseOffMainThreadCompositing() { return gfxPlatform::UsesOffMainThreadCompositing(); } -LayerManager* nsBaseWidget::GetLayerManager() { +WindowRenderer* nsBaseWidget::GetWindowRenderer() { if (!mLayerManager) { if (!mShutdownObserver) { // We are shutting down, do not try to re-create a LayerManager diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index 554efb5adf90..ea45344db93a 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -218,7 +218,7 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference { nsIScreen* aScreen = nullptr) override; void InfallibleMakeFullScreen(bool aFullScreen, nsIScreen* aScreen = nullptr); - LayerManager* GetLayerManager() override; + WindowRenderer* GetWindowRenderer() override; // A remote compositor session tied to this window has been lost and IPC // messages will no longer work. The widget must clean up any lingering diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h index 10881af9eac9..6d4861ba74f0 100644 --- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -74,6 +74,7 @@ namespace dom { class BrowserChild; enum class CallerType : uint32_t; } // namespace dom +class WindowRenderer; namespace layers { class AsyncDragMetrics; class Compositor; @@ -377,6 +378,7 @@ class nsIWidget : public nsISupports { typedef mozilla::layers::AsyncDragMetrics AsyncDragMetrics; typedef mozilla::layers::FrameMetrics FrameMetrics; typedef mozilla::layers::LayerManager LayerManager; + typedef mozilla::WindowRenderer WindowRenderer; typedef mozilla::layers::LayerManagerComposite LayerManagerComposite; typedef mozilla::layers::LayersBackend LayersBackend; typedef mozilla::layers::PLayerTransactionChild PLayerTransactionChild; @@ -1294,7 +1296,7 @@ class nsIWidget : public nsISupports { * Return the widget's LayerManager. The layer tree for that * LayerManager is what gets rendered to the widget. */ - virtual LayerManager* GetLayerManager() = 0; + virtual WindowRenderer* GetWindowRenderer() = 0; /** * Called before each layer manager transaction to allow any preparation diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index 7c1b7a9d2c79..b0357f73d7e3 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -4074,13 +4074,13 @@ bool nsWindow::HasPendingInputEvent() { /************************************************************** * - * SECTION: nsIWidget::GetLayerManager + * SECTION: nsIWidget::GetWindowRenderer * - * Get the layer manager associated with this widget. + * Get the window renderer associated with this widget. * **************************************************************/ -LayerManager* nsWindow::GetLayerManager() { +WindowRenderer* nsWindow::GetWindowRenderer() { if (mLayerManager) { return mLayerManager; } @@ -4205,7 +4205,8 @@ nsresult nsWindow::OnDefaultButtonLoaded( void nsWindow::UpdateThemeGeometries( const nsTArray& aThemeGeometries) { - RefPtr layerManager = GetLayerManager(); + RefPtr layerManager = + GetWindowRenderer() ? GetWindowRenderer()->AsLayerManager() : nullptr; if (!layerManager) { return; } @@ -7329,7 +7330,8 @@ nsresult nsWindow::ConfigureChildren( w->Move(configuration.mBounds.X(), configuration.mBounds.Y()); if (gfxWindowsPlatform::GetPlatform()->IsDirect2DBackend() || - GetLayerManager()->GetBackendType() != LayersBackend::LAYERS_BASIC) { + GetWindowRenderer()->GetBackendType() != + LayersBackend::LAYERS_BASIC) { // XXX - Workaround for Bug 587508. This will invalidate the part of the // plugin window that might be touched by moving content somehow. The // underlying problem should be found and fixed! @@ -7775,8 +7777,8 @@ void nsWindow::SetWindowTranslucencyInner(nsTransparencyMode aMode) { // Clear window by transparent black when compositor window is used in GPU // process and non-client area rendering by DWM is enabled. // It is for showing non-client area rendering. See nsWindow::UpdateGlass(). - if (HasGlass() && GetLayerManager()->AsKnowsCompositor() && - GetLayerManager()->AsKnowsCompositor()->GetUseCompositorWnd()) { + if (HasGlass() && GetWindowRenderer()->AsKnowsCompositor() && + GetWindowRenderer()->AsKnowsCompositor()->GetUseCompositorWnd()) { HDC hdc; RECT rect; hdc = ::GetWindowDC(mWnd); diff --git a/widget/windows/nsWindow.h b/widget/windows/nsWindow.h index cef7aa5c4095..3943a7ddb6b9 100644 --- a/widget/windows/nsWindow.h +++ b/widget/windows/nsWindow.h @@ -210,7 +210,7 @@ class nsWindow final : public nsWindowBase { bool aDoCapture) override; [[nodiscard]] virtual nsresult GetAttention(int32_t aCycleCount) override; virtual bool HasPendingInputEvent() override; - virtual LayerManager* GetLayerManager() override; + virtual WindowRenderer* GetWindowRenderer() override; void SetCompositorWidgetDelegate(CompositorWidgetDelegate* delegate) override; [[nodiscard]] virtual nsresult OnDefaultButtonLoaded( const LayoutDeviceIntRect& aButtonRect) override; diff --git a/widget/windows/nsWindowGfx.cpp b/widget/windows/nsWindowGfx.cpp index ad3aeaddac27..ee94c89f7837 100644 --- a/widget/windows/nsWindowGfx.cpp +++ b/widget/windows/nsWindowGfx.cpp @@ -169,11 +169,14 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t aNestingLevel) { return true; } + WindowRenderer* renderer = GetWindowRenderer(); + KnowsCompositor* knowsCompositor = renderer->AsKnowsCompositor(); + LayerManager* layerManager = renderer->AsLayerManager(); + // Clear window by transparent black when compositor window is used in GPU // process and non-client area rendering by DWM is enabled. // It is for showing non-client area rendering. See nsWindow::UpdateGlass(). - if (HasGlass() && GetLayerManager()->AsKnowsCompositor() && - GetLayerManager()->AsKnowsCompositor()->GetUseCompositorWnd()) { + if (HasGlass() && knowsCompositor && knowsCompositor->GetUseCompositorWnd()) { HDC hdc; RECT rect; hdc = ::GetWindowDC(mWnd); @@ -184,17 +187,16 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t aNestingLevel) { ReleaseDC(mWnd, hdc); } - if (GetLayerManager()->AsKnowsCompositor() && + if (knowsCompositor && layerManager && !mBounds.IsEqualEdges(mLastPaintBounds)) { // Do an early async composite so that we at least have something on the // screen in the right place, even if the content is out of date. - GetLayerManager()->ScheduleComposite(); + layerManager->ScheduleComposite(); } mLastPaintBounds = mBounds; #ifdef MOZ_XUL - if (!aDC && - (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC) && + if (!aDC && (renderer->GetBackendType() == LayersBackend::LAYERS_BASIC) && (eTransparencyTransparent == mTransparencyMode)) { // For layered translucent windows all drawing should go to memory DC and no // WM_PAINT messages are normally generated. To support asynchronous @@ -233,11 +235,11 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t aNestingLevel) { #endif LayoutDeviceIntRegion region = GetRegionToPaint(forceRepaint, ps, hDC); - if (GetLayerManager()->AsKnowsCompositor()) { + if (knowsCompositor && layerManager) { // We need to paint to the screen even if nothing changed, since if we // don't have a compositing window manager, our pixels could be stale. - GetLayerManager()->SetNeedsComposite(true); - GetLayerManager()->SendInvalidRegion(region.ToUnknownRegion()); + layerManager->SetNeedsComposite(true); + layerManager->SendInvalidRegion(region.ToUnknownRegion()); } RefPtr strongThis(this); @@ -252,10 +254,9 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t aNestingLevel) { return false; } - if (GetLayerManager()->AsKnowsCompositor() && - GetLayerManager()->NeedsComposite()) { - GetLayerManager()->ScheduleComposite(); - GetLayerManager()->SetNeedsComposite(false); + if (knowsCompositor && layerManager && layerManager->NeedsComposite()) { + layerManager->ScheduleComposite(); + layerManager->SetNeedsComposite(false); } bool result = true; @@ -268,7 +269,7 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t aNestingLevel) { (int32_t)mWnd); #endif // WIDGET_DEBUG_OUTPUT - switch (GetLayerManager()->GetBackendType()) { + switch (renderer->GetBackendType()) { case LayersBackend::LAYERS_BASIC: { RefPtr targetSurface;