diff --git a/dom/animation/KeyframeEffect.cpp b/dom/animation/KeyframeEffect.cpp index 7c42ec96d23eb4cf72cb1f3a2b730b4331f14807..3a3c5336880401217e2fcf9430ea3a4519c6a63b 100644 --- a/dom/animation/KeyframeEffect.cpp +++ b/dom/animation/KeyframeEffect.cpp @@ -6,7 +6,6 @@ #include "mozilla/dom/KeyframeEffect.h" -#include "FrameLayerBuilder.h" #include "mozilla/dom/Animation.h" #include "mozilla/dom/KeyframeAnimationOptionsBinding.h" // For UnrestrictedDoubleOrKeyframeAnimationOptions; diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index c4e5a23965846871a2d5ec2b9e4963c7fbfa4c78..b73b1041deb5eb86ab253f2de957e51fbe828054 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -101,7 +101,6 @@ #include "nsViewportInfo.h" #include "nsIFormControl.h" //#include "nsWidgetsCID.h" -#include "FrameLayerBuilder.h" #include "nsDisplayList.h" #include "nsROCSSPrimitiveValue.h" #include "nsIBaseWindow.h" @@ -184,37 +183,6 @@ class OldWindowSize : public LinkedListElement<OldWindowSize> { nsSize mSize; }; -/** - * Return the layer that all display items of aFrame were assigned to in the - * last paint, or nullptr if there was no single layer assigned to all of the - * frame's display items (i.e. zero, or more than one). - * This function is for testing purposes and not performance sensitive. - */ -template <class T> -T* mozilla::FrameLayerBuilder::GetDebugSingleOldLayerForFrame( - nsIFrame* aFrame) { - SmallPointerArray<DisplayItemData>* array = aFrame->DisplayItemData(); - - if (!array) { - return nullptr; - } - - Layer* layer = nullptr; - for (DisplayItemData* data : *array) { - DisplayItemData::AssertDisplayItemData(data); - if (data->mLayer->GetType() != T::Type()) { - continue; - } - if (layer && layer != data->mLayer) { - // More than one layer assigned, bail. - return nullptr; - } - layer = data->mLayer; - } - - return static_cast<T*>(layer); -} - namespace { class NativeInputRunnable final : public PrioritizableRunnable { @@ -3351,45 +3319,13 @@ nsDOMWindowUtils::IsPartOfOpaqueLayer(Element* aElement, bool* aResult) { return NS_ERROR_FAILURE; } - ColorLayer* colorLayer = - FrameLayerBuilder::GetDebugSingleOldLayerForFrame<ColorLayer>(frame); - if (colorLayer) { - auto color = colorLayer->GetColor(); - *aResult = color.a == 1.0f; - return NS_OK; - } - - PaintedLayer* paintedLayer = - FrameLayerBuilder::GetDebugSingleOldLayerForFrame<PaintedLayer>(frame); - if (paintedLayer) { - *aResult = paintedLayer->IsOpaque(); - return NS_OK; - } - return NS_ERROR_FAILURE; } NS_IMETHODIMP nsDOMWindowUtils::NumberOfAssignedPaintedLayers( const nsTArray<RefPtr<Element>>& aElements, uint32_t* aResult) { - nsTHashSet<PaintedLayer*> layers; - for (Element* element : aElements) { - nsIFrame* frame = element->GetPrimaryFrame(); - if (!frame) { - return NS_ERROR_FAILURE; - } - - PaintedLayer* layer = - FrameLayerBuilder::GetDebugSingleOldLayerForFrame<PaintedLayer>(frame); - if (!layer) { - return NS_ERROR_FAILURE; - } - - layers.Insert(layer); - } - - *aResult = layers.Count(); - return NS_OK; + return NS_ERROR_FAILURE; } NS_IMETHODIMP @@ -4003,14 +3939,7 @@ static OMTAValue GetOMTAValue(nsIFrame* aFrame, DisplayItemType aDisplayItemKey, WebRenderBridgeChild* aWebRenderBridgeChild) { OMTAValue value = mozilla::null_t(); - Layer* layer = FrameLayerBuilder::GetDedicatedLayer(aFrame, aDisplayItemKey); - if (layer) { - ShadowLayerForwarder* forwarder = layer->Manager()->AsShadowForwarder(); - if (forwarder && forwarder->HasShadowManager()) { - forwarder->GetShadowManager()->SendGetAnimationValue( - layer->GetCompositorAnimationsId(), &value); - } - } else if (aWebRenderBridgeChild) { + if (aWebRenderBridgeChild) { RefPtr<WebRenderAnimationData> animationData = GetWebRenderUserData<WebRenderAnimationData>(aFrame, (uint32_t)aDisplayItemKey); @@ -4110,35 +4039,7 @@ nsDOMWindowUtils::GetOMTCTransform(Element* aElement, itemType = DisplayItemType::TYPE_OPACITY; } - Layer* layer = FrameLayerBuilder::GetDedicatedLayer(frame, itemType); - if (!layer) { - return NS_OK; - } - - ShadowLayerForwarder* forwarder = layer->Manager()->AsShadowForwarder(); - if (!forwarder || !forwarder->HasShadowManager()) { - return NS_OK; - } - - Maybe<Matrix4x4> transform; - forwarder->GetShadowManager()->SendGetTransform( - layer->AsShadowableLayer()->GetShadow(), &transform); - if (transform.isNothing()) { - return NS_OK; - } - - Matrix4x4 matrix = transform.value(); - RefPtr<nsROCSSPrimitiveValue> cssValue = - nsComputedDOMStyle::MatrixToCSSValue(matrix); - if (!cssValue) { - return NS_OK; - } - - nsAutoString text; - ErrorResult rv; - cssValue->GetCssText(text, rv); - aResult.Assign(text); - return rv.StealNSResult(); + return NS_OK; } NS_IMETHODIMP diff --git a/dom/events/PointerEventHandler.cpp b/dom/events/PointerEventHandler.cpp index 6b2cd29f6829807d8902b9cdbe8808ab843317fd..caf4d435611d08250e37c2608f0a388839c08705 100644 --- a/dom/events/PointerEventHandler.cpp +++ b/dom/events/PointerEventHandler.cpp @@ -8,6 +8,7 @@ #include "nsIFrame.h" #include "PointerEvent.h" #include "PointerLockManager.h" +#include "nsRFPService.h" #include "mozilla/PresShell.h" #include "mozilla/StaticPrefs_dom.h" #include "mozilla/dom/BrowserChild.h" diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp index 19cbcae565f9caa6a2df29f572c4f81c9d9d6f51..7c7489dd62ec6250d94470c52c3934c7c92e47f5 100644 --- a/dom/ipc/BrowserChild.cpp +++ b/dom/ipc/BrowserChild.cpp @@ -19,7 +19,6 @@ #include "ContentChild.h" #include "DocumentInlines.h" #include "EventStateManager.h" -#include "FrameLayerBuilder.h" #include "Layers.h" #include "MMPrinter.h" #include "PermissionMessageUtils.h" @@ -2724,8 +2723,6 @@ mozilla::ipc::IPCResult BrowserChild::RecvRenderLayers( } if (nsIFrame* root = presShell->GetRootFrame()) { - FrameLayerBuilder::InvalidateAllLayersForFrame( - nsLayoutUtils::GetDisplayRootFrame(root)); root->SchedulePaint(); } @@ -3181,14 +3178,7 @@ void BrowserChild::ClearCachedResources() { } } -void BrowserChild::InvalidateLayers() { - MOZ_ASSERT(mPuppetWidget); - RefPtr<LayerManager> lm = - mPuppetWidget->GetWindowRenderer()->AsLayerManager(); - if (lm) { - FrameLayerBuilder::InvalidateAllLayers(lm); - } -} +void BrowserChild::InvalidateLayers() { MOZ_ASSERT(mPuppetWidget); } void BrowserChild::SchedulePaint() { nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation()); diff --git a/gfx/layers/AnimationInfo.cpp b/gfx/layers/AnimationInfo.cpp index 7bd2f7acab40d288d61f73c5d2eacac6178637f7..eb788b4c6fccc8cbaa1e7643c15396e31826f4d9 100644 --- a/gfx/layers/AnimationInfo.cpp +++ b/gfx/layers/AnimationInfo.cpp @@ -155,12 +155,6 @@ Maybe<uint64_t> AnimationInfo::GetGenerationFromFrame( MOZ_ASSERT(aFrame->IsPrimaryFrame() || nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aFrame)); - layers::Layer* layer = - FrameLayerBuilder::GetDedicatedLayer(aFrame, aDisplayItemKey); - if (layer) { - return layer->GetAnimationInfo().GetAnimationGeneration(); - } - // In case of continuation, KeyframeEffectReadOnly uses its first frame, // whereas nsDisplayItem uses its last continuation, so we have to use the // last continuation frame here. @@ -231,8 +225,6 @@ void AnimationInfo::EnumerateGenerationOnFrame( } return; } - - FrameLayerBuilder::EnumerateGenerationForDedicatedLayers(aFrame, aCallback); } static StyleTransformOperation ResolveTranslate( diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp index 4732ce077a4d466c80fc51a1532278bd562c62da..30be1619e993c7e1e2ed67871015716300d46b52 100644 --- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -34,7 +34,6 @@ #include "nsTArray.h" // for AutoTArray #include "nsXULAppAPI.h" // for XRE_GetProcessType, etc #include "TiledLayerBuffer.h" -#include "FrameLayerBuilder.h" // for FrameLayerbuilder #ifdef MOZ_WIDGET_ANDROID # include "AndroidBridge.h" # include "LayerMetricsWrapper.h" @@ -371,10 +370,6 @@ bool ClientLayerManager::EndTransactionInternal( NS_ASSERTION(!aCallback || !mTransactionIncomplete, "If callback is not null, transaction must be complete"); - if (gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) { - FrameLayerBuilder::InvalidateAllLayers(this); - } - if (startTime) { PaintTiming& pt = mForwarder->GetPaintTiming(); pt.rasterMs() = (TimeStamp::Now() - startTime.value()).ToMilliseconds(); diff --git a/gfx/layers/ipc/CompositorBridgeChild.cpp b/gfx/layers/ipc/CompositorBridgeChild.cpp index ade296e929050f85333f0d94420ed0c4b4cb52ba..b1a14ffa7b8b05fb12b0aeaf6ff2c2b8b73c0920 100644 --- a/gfx/layers/ipc/CompositorBridgeChild.cpp +++ b/gfx/layers/ipc/CompositorBridgeChild.cpp @@ -36,7 +36,6 @@ #include "nsDebug.h" // for NS_WARNING #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc #include "nsTArray.h" // for nsTArray, nsTArray_Impl -#include "FrameLayerBuilder.h" #include "mozilla/dom/BrowserChild.h" #include "mozilla/dom/BrowserParent.h" #include "mozilla/dom/ContentChild.h" @@ -339,7 +338,6 @@ mozilla::ipc::IPCResult CompositorBridgeChild::RecvInvalidateLayers( const LayersId& aLayersId) { if (mLayerManager) { MOZ_ASSERT(!aLayersId.IsValid()); - FrameLayerBuilder::InvalidateAllLayers(mLayerManager); } else if (aLayersId.IsValid()) { if (dom::BrowserChild* child = dom::BrowserChild::GetFrom(aLayersId)) { child->InvalidateLayers(); diff --git a/gfx/layers/wr/ClipManager.cpp b/gfx/layers/wr/ClipManager.cpp index 48071e6c2a54573512015064bd43bd704d1f0ce9..1240c8384509ecf4c6ee1a0a889d259873404d8a 100644 --- a/gfx/layers/wr/ClipManager.cpp +++ b/gfx/layers/wr/ClipManager.cpp @@ -275,7 +275,7 @@ Maybe<wr::WrSpatialId> ClipManager::DefineScrollLayers( Maybe<ScrollMetadata> metadata = aASR->mScrollableFrame->ComputeScrollMetadata( - mManager, aItem->ReferenceFrame(), Nothing(), nullptr); + mManager, aItem->ReferenceFrame(), nullptr); if (!metadata) { MOZ_ASSERT_UNREACHABLE("Expected scroll metadata to be available!"); return ancestorSpace; diff --git a/gfx/layers/wr/StackingContextHelper.cpp b/gfx/layers/wr/StackingContextHelper.cpp index a56f3c1c73a1cbee171f40356b1a8c7f9cb2d693..721ba892e22ade640765c7aea012eeb76cda276c 100644 --- a/gfx/layers/wr/StackingContextHelper.cpp +++ b/gfx/layers/wr/StackingContextHelper.cpp @@ -7,12 +7,17 @@ #include "mozilla/layers/StackingContextHelper.h" #include "mozilla/PresShell.h" +#include "mozilla/gfx/Point.h" +#include "mozilla/gfx/Matrix.h" #include "UnitTransforms.h" #include "nsDisplayList.h" #include "mozilla/dom/BrowserChild.h" +#include "nsLayoutUtils.h" +#include "ActiveLayerTracker.h" namespace mozilla { namespace layers { +using namespace gfx; StackingContextHelper::StackingContextHelper() : mBuilder(nullptr), @@ -23,6 +28,103 @@ StackingContextHelper::StackingContextHelper() // mOrigin remains at 0,0 } +static nsSize ComputeDesiredDisplaySizeForAnimation(nsIFrame* aContainerFrame) { + // Use the size of the nearest widget as the maximum size. This + // is important since it might be a popup that is bigger than the + // pres context's size. + nsPresContext* presContext = aContainerFrame->PresContext(); + nsIWidget* widget = aContainerFrame->GetNearestWidget(); + if (widget) { + return LayoutDevicePixel::ToAppUnits(widget->GetClientSize(), + presContext->AppUnitsPerDevPixel()); + } + + return presContext->GetVisibleArea().Size(); +} + +/* static */ +Size ChooseScale(nsIFrame* aContainerFrame, nsDisplayItem* aContainerItem, + const nsRect& aVisibleRect, float aXScale, float aYScale, + const Matrix& aTransform2d, bool aCanDraw2D) { + Size scale; + // XXX Should we do something for 3D transforms? + if (aCanDraw2D && !aContainerFrame->Combines3DTransformWithAncestors() && + !aContainerFrame->HasPerspective()) { + // If the container's transform is animated off main thread, fix a suitable + // scale size for animation + if (aContainerItem && + aContainerItem->GetType() == DisplayItemType::TYPE_TRANSFORM && + // FIXME: What we need is only transform, rotate, and scale, not + // translate, so it's be better to use a property set, instead of + // display item type here. + EffectCompositor::HasAnimationsForCompositor( + aContainerFrame, DisplayItemType::TYPE_TRANSFORM)) { + nsSize displaySize = + ComputeDesiredDisplaySizeForAnimation(aContainerFrame); + // compute scale using the animation on the container, taking ancestors in + // to account + nsSize scaledVisibleSize = nsSize(aVisibleRect.Width() * aXScale, + aVisibleRect.Height() * aYScale); + scale = nsLayoutUtils::ComputeSuitableScaleForAnimation( + aContainerFrame, scaledVisibleSize, displaySize); + // multiply by the scale inherited from ancestors--we use a uniform + // scale factor to prevent blurring when the layer is rotated. + float incomingScale = std::max(aXScale, aYScale); + scale.width *= incomingScale; + scale.height *= incomingScale; + } else { + // Scale factors are normalized to a power of 2 to reduce the number of + // resolution changes + scale = aTransform2d.ScaleFactors(); + // For frames with a changing scale transform round scale factors up to + // nearest power-of-2 boundary so that we don't keep having to redraw + // the content as it scales up and down. Rounding up to nearest + // power-of-2 boundary ensures we never scale up, only down --- avoiding + // jaggies. It also ensures we never scale down by more than a factor of + // 2, avoiding bad downscaling quality. + Matrix frameTransform; + if (ActiveLayerTracker::IsScaleSubjectToAnimation(aContainerFrame)) { + scale.width = gfxUtils::ClampToScaleFactor(scale.width); + scale.height = gfxUtils::ClampToScaleFactor(scale.height); + + // Limit animated scale factors to not grow excessively beyond the + // display size. + nsSize maxScale(4, 4); + if (!aVisibleRect.IsEmpty()) { + nsSize displaySize = + ComputeDesiredDisplaySizeForAnimation(aContainerFrame); + maxScale = Max(maxScale, displaySize / aVisibleRect.Size()); + } + if (scale.width > maxScale.width) { + scale.width = gfxUtils::ClampToScaleFactor(maxScale.width, true); + } + if (scale.height > maxScale.height) { + scale.height = gfxUtils::ClampToScaleFactor(maxScale.height, true); + } + } else { + // XXX Do we need to move nearly-integer values to integers here? + } + } + // If the scale factors are too small, just use 1.0. The content is being + // scaled out of sight anyway. + if (fabs(scale.width) < 1e-8 || fabs(scale.height) < 1e-8) { + scale = Size(1.0, 1.0); + } + } else { + scale = Size(1.0, 1.0); + } + + // Prevent the scale from getting too large, to avoid excessive memory + // allocation. Usually memory allocation is limited by the visible region, + // which should be restricted to the display port. But at very large scales + // the visible region itself can become excessive due to rounding errors. + // Clamping the scale here prevents that. + scale = + Size(std::min(scale.width, 32768.0f), std::min(scale.height, 32768.0f)); + + return scale; +} + StackingContextHelper::StackingContextHelper( const StackingContextHelper& aParentSC, const ActiveScrolledRoot* aAsr, nsIFrame* aContainerFrame, nsDisplayItem* aContainerItem, @@ -49,10 +151,10 @@ StackingContextHelper::StackingContextHelper( int32_t apd = aContainerFrame->PresContext()->AppUnitsPerDevPixel(); nsRect r = LayoutDevicePixel::ToAppUnits(aBounds, apd); - mScale = FrameLayerBuilder::ChooseScale( - aContainerFrame, aContainerItem, r, aParentSC.mScale.width, - aParentSC.mScale.height, mInheritedTransform, - /* aCanDraw2D = */ true); + mScale = ChooseScale(aContainerFrame, aContainerItem, r, + aParentSC.mScale.width, aParentSC.mScale.height, + mInheritedTransform, + /* aCanDraw2D = */ true); } else { mScale = gfx::Size(1.0f, 1.0f); mInheritedTransform = gfx::Matrix::Scaling(1.f, 1.f); diff --git a/gfx/layers/wr/WebRenderCommandBuilder.cpp b/gfx/layers/wr/WebRenderCommandBuilder.cpp index b4a40dd06e1cfd534e557dcab7f2cef9a16d707d..21aa4abf59a4b35c3eadba9b8f272ce85c2b99b5 100644 --- a/gfx/layers/wr/WebRenderCommandBuilder.cpp +++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp @@ -1608,8 +1608,8 @@ void WebRenderCommandBuilder::BuildWebRenderCommands( [&aScrollData](ScrollableLayerGuid::ViewID aScrollId) -> bool { return aScrollData.HasMetadataFor(aScrollId).isSome(); }; - Maybe<ScrollMetadata> rootMetadata = nsLayoutUtils::GetRootMetadata( - aDisplayListBuilder, mManager, ContainerLayerParameters(), callback); + Maybe<ScrollMetadata> rootMetadata = + nsLayoutUtils::GetRootMetadata(aDisplayListBuilder, mManager, callback); if (rootMetadata) { // Put the fallback root metadata on the rootmost layer that is // a matching async zoom container, or the root layer that we just diff --git a/gfx/layers/wr/WebRenderScrollData.cpp b/gfx/layers/wr/WebRenderScrollData.cpp index dac7a7a51ae15c8a2e9e01644192db28c49bfb42..c7c2e77b87ccba83c73a12bffda0e39d5c73ebbd 100644 --- a/gfx/layers/wr/WebRenderScrollData.cpp +++ b/gfx/layers/wr/WebRenderScrollData.cpp @@ -64,7 +64,7 @@ void WebRenderLayerScrollData::Initialize( } else { Maybe<ScrollMetadata> metadata = asr->mScrollableFrame->ComputeScrollMetadata( - aOwner.GetManager(), aItem->ReferenceFrame(), Nothing(), nullptr); + aOwner.GetManager(), aItem->ReferenceFrame(), nullptr); aOwner.GetBuilder()->AddScrollFrameToNotify(asr->mScrollableFrame); if (metadata) { MOZ_ASSERT(metadata->GetMetrics().GetScrollId() == scrollId); diff --git a/gfx/thebes/gfxFontMissingGlyphs.cpp b/gfx/thebes/gfxFontMissingGlyphs.cpp index 285c64b8375f69e37a8b139b569a5fccf0d269a8..6e777b175c63b8c9dfc3f7eb4c8e638b9bb1d56f 100644 --- a/gfx/thebes/gfxFontMissingGlyphs.cpp +++ b/gfx/thebes/gfxFontMissingGlyphs.cpp @@ -14,6 +14,7 @@ #include "nsDeviceContext.h" #include "nsLayoutUtils.h" #include "TextDrawTarget.h" +#include "LayerUserData.h" using namespace mozilla; using namespace mozilla::gfx; diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp index d94c6e295b876f5e18003d2b36248f7a696233d3..a00298cf74fc1ef7312a639ad2f778332b9bfc44 100644 --- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp @@ -69,7 +69,6 @@ #include "nsNameSpaceManager.h" // for Pref-related rule management (bugs 22963,20760,31816) #include "nsFlexContainerFrame.h" #include "nsIFrame.h" -#include "FrameLayerBuilder.h" #include "nsViewManager.h" #include "nsView.h" #include "nsCRTGlue.h" @@ -5449,15 +5448,6 @@ void PresShell::SetRestoreResolution(float aResolution, } 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. - WindowRenderer* renderer = GetWindowRenderer(); - if (renderer && renderer->AsLayerManager()) { - FrameLayerBuilder::InvalidateAllLayers(renderer->AsLayerManager()); - } - } - if (GetResolution() != aState.mResolution.valueOr(1.f)) { if (nsIFrame* frame = GetRootFrame()) { frame->SchedulePaint(); diff --git a/layout/base/nsLayoutDebugger.cpp b/layout/base/nsLayoutDebugger.cpp index 8aea6a662b81453874976c388d57eebd283337bd..4847f3d63d22391d175bba6728fec4fcc6eaee5a 100644 --- a/layout/base/nsLayoutDebugger.cpp +++ b/layout/base/nsLayoutDebugger.cpp @@ -9,7 +9,6 @@ #include "nsAttrValue.h" #include "nsIFrame.h" #include "nsDisplayList.h" -#include "FrameLayerBuilder.h" #include "nsPrintfCString.h" #include <stdio.h> @@ -134,15 +133,6 @@ static void PrintDisplayItemTo(nsDisplayListBuilder* aBuilder, aStream << "</a>"; } #endif - DisplayItemData* data = mozilla::FrameLayerBuilder::GetOldDataFor(aItem); - if (data && data->GetLayer()) { - if (aDumpHtml) { - aStream << nsPrintfCString(" <a href=\"#%p\">layer=%p</a>", - data->GetLayer(), data->GetLayer()); - } else { - aStream << nsPrintfCString(" layer=0x%p", data->GetLayer()); - } - } #ifdef MOZ_DUMP_PAINTING if (aItem->GetType() == DisplayItemType::TYPE_MASK) { nsCString str; diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index af04dea04064ee1662066d657f213aa7442662b4..6f2d2b41a16b63f2aa3595ef20a293fd3062add1 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -12,7 +12,6 @@ #include "ActiveLayerTracker.h" #include "ClientLayerManager.h" #include "DisplayItemClip.h" -#include "FrameLayerBuilder.h" #include "gfx2DGlue.h" #include "gfxContext.h" #include "gfxDrawable.h" @@ -1412,49 +1411,6 @@ SideBits nsLayoutUtils::GetSideBitsAndAdjustAnchorForFixedPositionContent( return sides; } -/* static */ -void nsLayoutUtils::SetFixedPositionLayerData( - Layer* aLayer, const nsIFrame* aViewportFrame, const nsRect& aAnchorRect, - const nsIFrame* aFixedPosFrame, nsPresContext* aPresContext, - const ContainerLayerParameters& aContainerParameters) { - // Find out the rect of the viewport frame relative to the reference frame. - // This, in conjunction with the container scale, will correspond to the - // coordinate-space of the built layer. - float factor = aPresContext->AppUnitsPerDevPixel(); - Rect anchorRect(NSAppUnitsToFloatPixels(aAnchorRect.x, factor) * - aContainerParameters.mXScale, - NSAppUnitsToFloatPixels(aAnchorRect.y, factor) * - aContainerParameters.mYScale, - NSAppUnitsToFloatPixels(aAnchorRect.width, factor) * - aContainerParameters.mXScale, - NSAppUnitsToFloatPixels(aAnchorRect.height, factor) * - aContainerParameters.mYScale); - // Need to transform anchorRect from the container layer's coordinate system - // into aLayer's coordinate system. - Matrix transform2d; - if (aLayer->GetTransform().Is2D(&transform2d)) { - transform2d.Invert(); - anchorRect = transform2d.TransformBounds(anchorRect); - } else { - NS_ERROR( - "3D transform found between fixedpos content and its viewport (should " - "never happen)"); - anchorRect = Rect(0, 0, 0, 0); - } - - // Work out the anchor point for this fixed position layer. We assume that - // any positioning set (left/top/right/bottom) indicates that the - // corresponding side of its container should be the anchor point, - // defaulting to top-left. - LayerPoint anchor(anchorRect.x, anchorRect.y); - - SideBits sides = GetSideBitsAndAdjustAnchorForFixedPositionContent( - aViewportFrame, aFixedPosFrame, &anchor, &anchorRect); - - ViewID id = ScrollIdForRootScrollFrame(aPresContext); - aLayer->SetFixedPositionData(id, anchor, sides); -} - ScrollableLayerGuid::ViewID nsLayoutUtils::ScrollIdForRootScrollFrame( nsPresContext* aPresContext) { ViewID id = ScrollableLayerGuid::NULL_SCROLL_ID; @@ -3120,12 +3076,6 @@ static void DumpAfterPaintDisplayList(UniquePtr<std::stringstream>& aStream, nsIFrame::PrintDisplayList(aBuilder, *aList, *aStream, gfxEnv::DumpPaintToFile()); - *aStream << "Painting --- layer tree:\n"; - if (aManager) { - FrameLayerBuilder::DumpRetainedLayerTree(aManager, *aStream, - gfxEnv::DumpPaintToFile()); - } - fprint_stderr(gfxUtils::sDumpPaintFile, *aStream); #ifdef MOZ_DUMP_PAINTING @@ -3573,12 +3523,6 @@ nsresult nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, gfxUtils::sDumpPaintFile = savedDumpFile; #endif - if (StaticPrefs::layers_dump_client_layers() && layerManager) { - std::stringstream ss; - FrameLayerBuilder::DumpRetainedLayerTree(layerManager, ss, false); - print_stderr(ss); - } - // Update the widget's opaque region information. This sets // glass boundaries on Windows. Also set up the window dragging region. if ((aFlags & PaintFrameFlags::WidgetLayers) && @@ -8686,8 +8630,7 @@ ScrollMetadata nsLayoutUtils::ComputeScrollMetadata( nsIContent* aContent, const nsIFrame* aReferenceFrame, LayerManager* aLayerManager, ViewID aScrollParentId, const nsSize& aScrollPortSize, const Maybe<nsRect>& aClipRect, - bool aIsRootContent, - const Maybe<ContainerLayerParameters>& aContainerParameters) { + bool aIsRootContent) { const nsPresContext* presContext = aForFrame->PresContext(); int32_t auPerDevPixel = presContext->AppUnitsPerDevPixel(); @@ -8917,11 +8860,8 @@ ScrollMetadata nsLayoutUtils::ComputeScrollMetadata( // don't have a aContainerParameters. In that case we're also not rasterizing // in Gecko anyway, so the only resolution we care about here is the presShell // resolution which we need to propagate to WebRender. - metrics.SetCumulativeResolution( - aContainerParameters - ? aContainerParameters->Scale() - : LayoutDeviceToLayerScale2D(LayoutDeviceToLayerScale( - presShell->GetCumulativeResolution()))); + metrics.SetCumulativeResolution(LayoutDeviceToLayerScale2D( + LayoutDeviceToLayerScale(presShell->GetCumulativeResolution()))); LayoutDeviceToScreenScale2D resolutionToScreen( presShell->GetCumulativeResolution() * @@ -9062,7 +9002,6 @@ ScrollMetadata nsLayoutUtils::ComputeScrollMetadata( /*static*/ Maybe<ScrollMetadata> nsLayoutUtils::GetRootMetadata( nsDisplayListBuilder* aBuilder, LayerManager* aLayerManager, - const ContainerLayerParameters& aContainerParameters, const std::function<bool(ViewID& aScrollId)>& aCallback) { nsIFrame* frame = aBuilder->RootReferenceFrame(); nsPresContext* presContext = frame->PresContext(); @@ -9112,7 +9051,7 @@ Maybe<ScrollMetadata> nsLayoutUtils::GetRootMetadata( return Some(nsLayoutUtils::ComputeScrollMetadata( frame, rootScrollFrame, content, aBuilder->FindReferenceFrameFor(frame), aLayerManager, ScrollableLayerGuid::NULL_SCROLL_ID, scrollPortSize, - Nothing(), isRootContent, Some(aContainerParameters))); + Nothing(), isRootContent)); } return Nothing(); diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 41b0e23ab50333f64ef94e0bce0acf7b1a1265ed..e204901ee322d8b672fca113a2aa6fc0a79e64a2 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -75,7 +75,6 @@ enum class PseudoStyleType : uint8_t; class EventListenerManager; enum class LayoutFrameType : uint8_t; struct IntrinsicSize; -struct ContainerLayerParameters; class ReflowOutput; class WritingMode; class DisplayItemClip; @@ -146,7 +145,6 @@ class nsLayoutUtils { typedef mozilla::dom::DOMRectList DOMRectList; typedef mozilla::layers::Layer Layer; typedef mozilla::layers::StackingContextHelper StackingContextHelper; - typedef mozilla::ContainerLayerParameters ContainerLayerParameters; typedef mozilla::IntrinsicSize IntrinsicSize; typedef mozilla::RelativeTo RelativeTo; typedef mozilla::ScrollOrigin ScrollOrigin; @@ -552,22 +550,6 @@ class nsLayoutUtils { const nsIFrame* aAncestorFrame, const nsIFrame* aFrame, const nsIFrame* aCommonAncestor = nullptr); - /** - * Sets the fixed-pos metadata properties on aLayer. - * aAnchorRect is the basic anchor rectangle. If aFixedPosFrame is not a - * viewport frame, then we pick a corner of aAnchorRect to as the anchor point - * for the fixed-pos layer (i.e. the point to remain stable during zooming), - * based on which of the fixed-pos frame's CSS absolute positioning offset - * properties (top, left, right, bottom) are auto. aAnchorRect is in the - * coordinate space of aLayer's container layer (i.e. relative to the - * reference frame of the display item which is building aLayer's container - * layer). - */ - static void SetFixedPositionLayerData( - Layer* aLayer, const nsIFrame* aViewportFrame, const nsRect& aAnchorRect, - const nsIFrame* aFixedPosFrame, nsPresContext* aPresContext, - const ContainerLayerParameters& aContainerParameters); - static mozilla::SideBits GetSideBitsAndAdjustAnchorForFixedPositionContent( const nsIFrame* aViewportFrame, const nsIFrame* aFixedPosFrame, mozilla::LayerPoint* aAnchor, const Rect* aAnchorRect); @@ -2780,8 +2762,7 @@ class nsLayoutUtils { nsIContent* aContent, const nsIFrame* aReferenceFrame, mozilla::layers::LayerManager* aLayerManager, ViewID aScrollParentId, const nsSize& aScrollPortSize, const mozilla::Maybe<nsRect>& aClipRect, - bool aIsRoot, - const mozilla::Maybe<ContainerLayerParameters>& aContainerParameters); + bool aIsRoot); /** * Returns the metadata to put onto the root layer of a layer tree, if one is @@ -2791,7 +2772,6 @@ class nsLayoutUtils { static mozilla::Maybe<ScrollMetadata> GetRootMetadata( nsDisplayListBuilder* aBuilder, mozilla::layers::LayerManager* aLayerManager, - const ContainerLayerParameters& aContainerParameters, const std::function<bool(ViewID& aScrollId)>& aCallback); /** diff --git a/layout/base/nsPresArena.cpp b/layout/base/nsPresArena.cpp index 20e813d62669ff12ca9c16d03120a7759423a5e1..d164599e3da471339ebe837e7886c878e30c6890 100644 --- a/layout/base/nsPresArena.cpp +++ b/layout/base/nsPresArena.cpp @@ -13,7 +13,6 @@ #include "nsDebug.h" #include "nsDisplayList.h" #include "nsPrintfCString.h" -#include "FrameLayerBuilder.h" #include "mozilla/ArrayUtils.h" #include "mozilla/ComputedStyle.h" #include "mozilla/ComputedStyleInlines.h" diff --git a/layout/base/nsPresArenaObjectList.h b/layout/base/nsPresArenaObjectList.h index 84088772cfe693bee0fe579a901da4b50d2dcd99..54c319d36b4f62f3f93be9496e6a1ffc6e45223c 100644 --- a/layout/base/nsPresArenaObjectList.h +++ b/layout/base/nsPresArenaObjectList.h @@ -17,7 +17,6 @@ #undef FRAME_ID #undef ABSTRACT_FRAME_ID PRES_ARENA_OBJECT(nsLineBox) -PRES_ARENA_OBJECT(DisplayItemData) PRES_ARENA_OBJECT(nsFrameList) PRES_ARENA_OBJECT(CustomCounterStyle) PRES_ARENA_OBJECT(DependentBuiltinCounterStyle) diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index a205a6fcbcff3c6c75cd67bb3b1b49115f71a2c9..47f51bac28c9e055c7053e1068f266653b2575fe 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -59,7 +59,6 @@ #include "DisplayItemClip.h" #include "HitTestInfo.h" #include "ActiveLayerTracker.h" -#include "FrameLayerBuilder.h" #include "AnimationCommon.h" #include "LayerAnimationInfo.h" #include "mozilla/TimelineConsumers.h" @@ -357,7 +356,6 @@ void nsLayoutStatics::Shutdown() { nsGlobalWindowInner::ShutDown(); nsGlobalWindowOuter::ShutDown(); nsListControlFrame::Shutdown(); - FrameLayerBuilder::Shutdown(); CubebUtils::ShutdownLibrary(); WebAudioUtils::Shutdown(); diff --git a/layout/generic/nsCanvasFrame.cpp b/layout/generic/nsCanvasFrame.cpp index e1d3b82366208af526f774c1df41e18709f88447..3ecdd88502bec81ba70eed2e45e65ab1ae211c1b 100644 --- a/layout/generic/nsCanvasFrame.cpp +++ b/layout/generic/nsCanvasFrame.cpp @@ -341,43 +341,11 @@ void nsDisplayCanvasBackgroundColor::Paint(nsDisplayListBuilder* aBuilder, } } -already_AddRefed<Layer> nsDisplayCanvasBackgroundColor::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - if (NS_GET_A(mColor) == 0) { - return nullptr; - } - - RefPtr<ColorLayer> layer = static_cast<ColorLayer*>( - aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this)); - if (!layer) { - layer = aManager->CreateColorLayer(); - if (!layer) { - return nullptr; - } - } - layer->SetColor(ToDeviceColor(mColor)); - - nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame); - nsPoint offset = ToReferenceFrame(); - nsRect bgClipRect = frame->CanvasArea() + offset; - - int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel(); - - layer->SetBounds(bgClipRect.ToNearestPixels(appUnitsPerDevPixel)); - layer->SetBaseTransform(gfx::Matrix4x4::Translation( - aContainerParameters.mOffset.x, aContainerParameters.mOffset.y, 0)); - - return layer.forget(); -} - bool nsDisplayCanvasBackgroundColor::CreateWebRenderCommands( mozilla::wr::DisplayListBuilder& aBuilder, mozilla::wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc, RenderRootStateManager* aManager, nsDisplayListBuilder* aDisplayListBuilder) { - ContainerLayerParameters parameter; - nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame); nsPoint offset = ToReferenceFrame(); nsRect bgClipRect = frame->CanvasArea() + offset; diff --git a/layout/generic/nsCanvasFrame.h b/layout/generic/nsCanvasFrame.h index fd4f8fc6a87a82075d72c33bf27a65db8f6107ce..d3f1629c441a7f2c9c62bad49ff01e9efa95bd9c 100644 --- a/layout/generic/nsCanvasFrame.h +++ b/layout/generic/nsCanvasFrame.h @@ -159,23 +159,12 @@ class nsDisplayCanvasBackgroundColor final : public nsDisplaySolidColorBase { // We need to override so we don't consider border-radius. aOutFrames->AppendElement(mFrame); } - virtual already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; virtual bool CreateWebRenderCommands( mozilla::wr::DisplayListBuilder& aBuilder, mozilla::wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc, mozilla::layers::RenderRootStateManager* aManager, nsDisplayListBuilder* aDisplayListBuilder) override; - virtual LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override { - if (ForceActiveLayers()) { - return mozilla::LayerState::LAYER_ACTIVE; - } - return mozilla::LayerState::LAYER_NONE; - } virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override; void SetExtraBackgroundColor(nscolor aColor) { mColor = aColor; } diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index de4ae78b4c7fc14206349b08b6cf984eb31d29ce..0056d2c36407253311b883a2ad34e87ce2dbf3b5 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -58,7 +58,6 @@ #include <stdint.h> #include "mozilla/MathAlgorithms.h" #include "mozilla/Telemetry.h" -#include "FrameLayerBuilder.h" #include "nsSubDocumentFrame.h" #include "mozilla/Attributes.h" #include "ScrollbarActivity.h" @@ -2867,6 +2866,38 @@ bool ScrollFrameHelper::GetDisplayPortAtLastApproximateFrameVisibilityUpdate( return mHadDisplayPortAtLastFrameUpdate; } +gfxSize GetPaintedLayerScaleForFrame(nsIFrame* aFrame) { + MOZ_ASSERT(aFrame, "need a frame"); + + nsPresContext* presCtx = aFrame->PresContext()->GetRootPresContext(); + + if (!presCtx) { + presCtx = aFrame->PresContext(); + MOZ_ASSERT(presCtx); + } + + nsIFrame* root = presCtx->PresShell()->GetRootFrame(); + + MOZ_ASSERT(root); + + float resolution = presCtx->PresShell()->GetResolution(); + + Matrix4x4Flagged transform = Matrix4x4::Scaling(resolution, resolution, 1.0); + if (aFrame != root) { + // aTransform is applied first, then the scale is applied to the result + transform = nsLayoutUtils::GetTransformToAncestor(RelativeTo{aFrame}, + RelativeTo{root}) * + transform; + } + + Matrix transform2d; + if (transform.CanDraw2D(&transform2d)) { + return ThebesMatrix(transform2d).ScaleFactors(); + } + + return gfxSize(1.0, 1.0); +} + void ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, ScrollOrigin aOrigin) { // None is never a valid scroll origin to be passed in. @@ -2916,8 +2947,7 @@ void ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); // 'scale' is our estimate of the scale factor that will be applied // when rendering the scrolled content to its own PaintedLayer. - gfxSize scale = - FrameLayerBuilder::GetPaintedLayerScaleForFrame(mScrolledFrame); + gfxSize scale = GetPaintedLayerScaleForFrame(mScrolledFrame); nsPoint curPos = GetScrollPosition(); nsPoint alignWithPos = mScrollPosForLayerPixelAlignment == nsPoint(-1, -1) @@ -4473,7 +4503,6 @@ void ScrollFrameHelper::NotifyApzTransaction() { Maybe<ScrollMetadata> ScrollFrameHelper::ComputeScrollMetadata( LayerManager* aLayerManager, const nsIFrame* aContainerReferenceFrame, - const Maybe<ContainerLayerParameters>& aParameters, const DisplayItemClip* aClip) const { if (!mWillBuildScrollableLayer) { return Nothing(); @@ -4492,36 +4521,7 @@ Maybe<ScrollMetadata> ScrollFrameHelper::ComputeScrollMetadata( return Some(nsLayoutUtils::ComputeScrollMetadata( mScrolledFrame, mOuter, mOuter->GetContent(), aContainerReferenceFrame, aLayerManager, mScrollParentID, mScrollPort.Size(), parentLayerClip, - isRootContent, aParameters)); -} - -void ScrollFrameHelper::ClipLayerToDisplayPort( - Layer* aLayer, const DisplayItemClip* aClip, - const ContainerLayerParameters& aParameters) const { - // If APZ is not enabled, we still need the displayport to be clipped - // in the compositor. - if (!nsLayoutUtils::UsesAsyncScrolling(mOuter)) { - Maybe<nsRect> parentLayerClip; - if (aClip) { - parentLayerClip = Some(aClip->GetClipRect()); - } - - if (parentLayerClip) { - ParentLayerIntRect displayportClip = - ViewAs<ParentLayerPixel>(parentLayerClip->ScaleToNearestPixels( - aParameters.mXScale, aParameters.mYScale, - mScrolledFrame->PresContext()->AppUnitsPerDevPixel())); - - ParentLayerIntRect layerClip; - if (const ParentLayerIntRect* origClip = - aLayer->GetClipRect().ptrOr(nullptr)) { - layerClip = displayportClip.Intersect(*origClip); - } else { - layerClip = displayportClip; - } - aLayer->SetClipRect(Some(layerClip)); - } - } + isRootContent)); } bool ScrollFrameHelper::IsRectNearlyVisible(const nsRect& aRect) const { @@ -7103,8 +7103,7 @@ nsRect ScrollFrameHelper::GetScrolledRect() const { // We snap to layer pixels, so we need to respect the layer's scale. nscoord appUnitsPerDevPixel = mScrolledFrame->PresContext()->AppUnitsPerDevPixel(); - gfxSize scale = - FrameLayerBuilder::GetPaintedLayerScaleForFrame(mScrolledFrame); + gfxSize scale = GetPaintedLayerScaleForFrame(mScrolledFrame); if (scale.IsEmpty()) { scale = gfxSize(1.0f, 1.0f); } diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index a911342ec2a843025a5ce971af11f88d0e4b8fb9..b4634f2aebc6ae929af419aa689f45ab878dd647 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -489,12 +489,7 @@ class ScrollFrameHelper : public nsIReflowCallback { bool WantAsyncScroll() const; Maybe<mozilla::layers::ScrollMetadata> ComputeScrollMetadata( LayerManager* aLayerManager, const nsIFrame* aContainerReferenceFrame, - const Maybe<ContainerLayerParameters>& aParameters, const mozilla::DisplayItemClip* aClip) const; - void ClipLayerToDisplayPort( - Layer* aLayer, const mozilla::DisplayItemClip* aClip, - const ContainerLayerParameters& aParameters) const; - // nsIScrollbarMediator void ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection, nsIScrollbarMediator::ScrollSnapMode aSnap = @@ -1097,15 +1092,9 @@ class nsHTMLScrollFrame : public nsContainerFrame, bool WantAsyncScroll() const final { return mHelper.WantAsyncScroll(); } mozilla::Maybe<mozilla::layers::ScrollMetadata> ComputeScrollMetadata( LayerManager* aLayerManager, const nsIFrame* aContainerReferenceFrame, - const Maybe<ContainerLayerParameters>& aParameters, const mozilla::DisplayItemClip* aClip) const final { - return mHelper.ComputeScrollMetadata( - aLayerManager, aContainerReferenceFrame, aParameters, aClip); - } - void ClipLayerToDisplayPort( - Layer* aLayer, const mozilla::DisplayItemClip* aClip, - const ContainerLayerParameters& aParameters) const final { - mHelper.ClipLayerToDisplayPort(aLayer, aClip, aParameters); + return mHelper.ComputeScrollMetadata(aLayerManager, + aContainerReferenceFrame, aClip); } void MarkScrollbarsDirtyForReflow() const final { mHelper.MarkScrollbarsDirtyForReflow(); @@ -1583,15 +1572,9 @@ class nsXULScrollFrame final : public nsBoxFrame, bool WantAsyncScroll() const final { return mHelper.WantAsyncScroll(); } mozilla::Maybe<mozilla::layers::ScrollMetadata> ComputeScrollMetadata( LayerManager* aLayerManager, const nsIFrame* aContainerReferenceFrame, - const Maybe<ContainerLayerParameters>& aParameters, const mozilla::DisplayItemClip* aClip) const final { - return mHelper.ComputeScrollMetadata( - aLayerManager, aContainerReferenceFrame, aParameters, aClip); - } - void ClipLayerToDisplayPort( - Layer* aLayer, const mozilla::DisplayItemClip* aClip, - const ContainerLayerParameters& aParameters) const final { - mHelper.ClipLayerToDisplayPort(aLayer, aClip, aParameters); + return mHelper.ComputeScrollMetadata(aLayerManager, + aContainerReferenceFrame, aClip); } void MarkScrollbarsDirtyForReflow() const final { mHelper.MarkScrollbarsDirtyForReflow(); diff --git a/layout/generic/nsHTMLCanvasFrame.cpp b/layout/generic/nsHTMLCanvasFrame.cpp index c290355fed1f720ec8faa9d071524bbc09a7b2ca..2bde3c66c0fe1f141e695b27e39641c4e5cabe8f 100644 --- a/layout/generic/nsHTMLCanvasFrame.cpp +++ b/layout/generic/nsHTMLCanvasFrame.cpp @@ -101,13 +101,6 @@ class nsDisplayCanvas final : public nsPaintedDisplayItem { return f->GetInnerArea() + ToReferenceFrame(); } - virtual already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override { - return static_cast<nsHTMLCanvasFrame*>(mFrame)->BuildLayer( - aBuilder, aManager, this, aContainerParameters); - } - virtual bool CreateWebRenderCommands( mozilla::wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc, @@ -278,21 +271,6 @@ class nsDisplayCanvas final : public nsPaintedDisplayItem { return true; } - virtual LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override { - if (HTMLCanvasElement::FromNode(mFrame->GetContent()) - ->ShouldForceInactiveLayer(aManager)) - return LayerState::LAYER_INACTIVE; - - // If compositing is cheap, just do that - if (aManager->IsCompositingCheap() || - ActiveLayerTracker::IsContentActive(mFrame)) - return mozilla::LayerState::LAYER_ACTIVE; - - return LayerState::LAYER_INACTIVE; - } - // FirstContentfulPaint is supposed to ignore "white" canvases. We use // MaybeModified (if GetContext() was called on the canvas) as a standin for // "white" @@ -559,57 +537,6 @@ nsRect nsHTMLCanvasFrame::GetInnerArea() const { return r; } -already_AddRefed<Layer> nsHTMLCanvasFrame::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - nsDisplayItem* aItem, - const ContainerLayerParameters& aContainerParameters) { - nsRect area = GetContentRectRelativeToSelf() + aItem->ToReferenceFrame(); - HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(GetContent()); - nsIntSize canvasSizeInPx = GetCanvasSize(); - - nsPresContext* presContext = PresContext(); - element->HandlePrintCallback(presContext); - - if (canvasSizeInPx.width <= 0 || canvasSizeInPx.height <= 0 || area.IsEmpty()) - return nullptr; - - Layer* oldLayer = - aManager->GetLayerBuilder() - ? aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem) - : nullptr; - RefPtr<Layer> layer = element->GetCanvasLayer(aBuilder, oldLayer, aManager); - if (!layer) return nullptr; - - IntrinsicSize intrinsicSize = IntrinsicSizeFromCanvasSize(canvasSizeInPx); - AspectRatio intrinsicRatio = IntrinsicRatioFromCanvasSize(canvasSizeInPx); - - nsRect dest = nsLayoutUtils::ComputeObjectDestRect( - area, intrinsicSize, intrinsicRatio, StylePosition()); - - gfxRect destGFXRect = presContext->AppUnitsToGfxUnits(dest); - - // Transform the canvas into the right place - gfxPoint p = destGFXRect.TopLeft() + aContainerParameters.mOffset; - Matrix transform = Matrix::Translation(p.x, p.y); - transform.PreScale(destGFXRect.Width() / canvasSizeInPx.width, - destGFXRect.Height() / canvasSizeInPx.height); - layer->SetBaseTransform(gfx::Matrix4x4::From2D(transform)); - if (layer->GetType() == layers::Layer::TYPE_CANVAS) { - RefPtr<CanvasLayer> canvasLayer = static_cast<CanvasLayer*>(layer.get()); - canvasLayer->SetSamplingFilter( - nsLayoutUtils::GetSamplingFilterForFrame(this)); - nsIntRect bounds; - bounds.SetRect(0, 0, canvasSizeInPx.width, canvasSizeInPx.height); - canvasLayer->SetBounds(bounds); - } else if (layer->GetType() == layers::Layer::TYPE_IMAGE) { - RefPtr<ImageLayer> imageLayer = static_cast<ImageLayer*>(layer.get()); - imageLayer->SetSamplingFilter( - nsLayoutUtils::GetSamplingFilterForFrame(this)); - } - - return layer.forget(); -} - bool nsHTMLCanvasFrame::UpdateWebRenderCanvasData( nsDisplayListBuilder* aBuilder, WebRenderCanvasData* aCanvasData) { HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(GetContent()); diff --git a/layout/generic/nsHTMLCanvasFrame.h b/layout/generic/nsHTMLCanvasFrame.h index 3dcd5dc2d70106656043f67fec65f78dd6412743..a5a3e4213d8ebf19ffb5ea449a8923424f9cd96d 100644 --- a/layout/generic/nsHTMLCanvasFrame.h +++ b/layout/generic/nsHTMLCanvasFrame.h @@ -12,7 +12,6 @@ #include "mozilla/Attributes.h" #include "nsContainerFrame.h" #include "nsStringFwd.h" -#include "FrameLayerBuilder.h" namespace mozilla { class PresShell; @@ -35,7 +34,6 @@ class nsHTMLCanvasFrame final : public nsContainerFrame { typedef mozilla::layers::Layer Layer; typedef mozilla::layers::LayerManager LayerManager; typedef mozilla::layers::WebRenderCanvasData WebRenderCanvasData; - typedef mozilla::ContainerLayerParameters ContainerLayerParameters; NS_DECL_QUERYFRAME NS_DECL_FRAMEARENA_HELPERS(nsHTMLCanvasFrame) @@ -52,11 +50,6 @@ class nsHTMLCanvasFrame final : public nsContainerFrame { void DestroyFrom(nsIFrame*, PostDestroyData&) override; - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - nsDisplayItem* aItem, - const ContainerLayerParameters& aContainerParameters); - bool UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder, WebRenderCanvasData* aCanvasData); diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp index 986a3bf860cd3791194d849ce5a43bba769e77f9..75bc59df75598f8bdad3515e1ce443ca0cf0cb85 100644 --- a/layout/generic/nsIFrame.cpp +++ b/layout/generic/nsIFrame.cpp @@ -80,7 +80,6 @@ #include "nsNameSpaceManager.h" #include "nsIPercentBSizeObserver.h" #include "nsStyleStructInlines.h" -#include "FrameLayerBuilder.h" #include "ImageLayers.h" #include "nsBidiPresUtils.h" @@ -1047,8 +1046,6 @@ void nsIFrame::RemoveDisplayItemDataForDeletion() { delete userDataTable; } - FrameLayerBuilder::RemoveFrameFromLayerManager(this); - for (nsDisplayItem* i : DisplayItems()) { if (i->GetDependentFrame() == this && !i->HasDeletedFrame()) { i->Frame()->MarkNeedsDisplayItemRebuild(); @@ -7278,11 +7275,20 @@ void nsIFrame::ClearInvalidationStateBits() { NS_FRAME_ALL_DESCENDANTS_NEED_PAINT); } +bool HasRetainedDataFor(const nsIFrame* aFrame, uint32_t aDisplayItemKey) { + if (RefPtr<WebRenderUserData> data = + GetWebRenderUserData<WebRenderFallbackData>(aFrame, + aDisplayItemKey)) { + return true; + } + + return false; +} + void nsIFrame::InvalidateFrame(uint32_t aDisplayItemKey, bool aRebuildDisplayItems /* = true */) { bool hasDisplayItem = - !aDisplayItemKey || - FrameLayerBuilder::HasRetainedDataFor(this, aDisplayItemKey); + !aDisplayItemKey || HasRetainedDataFor(this, aDisplayItemKey); InvalidateFrameInternal(this, hasDisplayItem, aRebuildDisplayItems); } @@ -7293,8 +7299,7 @@ void nsIFrame::InvalidateFrameWithRect(const nsRect& aRect, return; } bool hasDisplayItem = - !aDisplayItemKey || - FrameLayerBuilder::HasRetainedDataFor(this, aDisplayItemKey); + !aDisplayItemKey || HasRetainedDataFor(this, aDisplayItemKey); bool alreadyInvalid = false; if (!HasAnyStateBits(NS_FRAME_NEEDS_PAINT)) { InvalidateFrameInternal(this, hasDisplayItem, aRebuildDisplayItems); @@ -7325,94 +7330,7 @@ void nsIFrame::InvalidateFrameWithRect(const nsRect& aRect, /*static*/ uint8_t nsIFrame::sLayerIsPrerenderedDataKey; -static bool DoesLayerHaveOutOfDateFrameMetrics(Layer* aLayer) { - for (uint32_t i = 0; i < aLayer->GetScrollMetadataCount(); i++) { - const FrameMetrics& metrics = aLayer->GetFrameMetrics(i); - if (!metrics.IsScrollable()) { - continue; - } - nsIScrollableFrame* scrollableFrame = - nsLayoutUtils::FindScrollableFrameFor(metrics.GetScrollId()); - if (!scrollableFrame) { - // This shouldn't happen, so let's do the safe thing and trigger a full - // paint if it does. - return true; - } - nsPoint scrollPosition = scrollableFrame->GetScrollPosition(); - if (metrics.GetLayoutScrollOffset() != - CSSPoint::FromAppUnits(scrollPosition)) { - return true; - } - } - return false; -} - -static bool DoesLayerOrAncestorsHaveOutOfDateFrameMetrics(Layer* aLayer) { - for (Layer* layer = aLayer; layer; layer = layer->GetParent()) { - if (DoesLayerHaveOutOfDateFrameMetrics(layer)) { - return true; - } - } - return false; -} - -bool nsIFrame::TryUpdateTransformOnly(Layer** aLayerResult) { - // If we move a transformed layer when we have a merged display - // list, then it can end up intersecting other items for which - // we don't have a defined ordering. - // We could allow this if the display list is in the canonical - // ordering (correctly sorted for all intersections), but we - // don't have a way to check that yet. - if (nsLayoutUtils::AreRetainedDisplayListsEnabled()) { - return false; - } - - Layer* layer = FrameLayerBuilder::GetDedicatedLayer( - this, DisplayItemType::TYPE_TRANSFORM); - if (!layer || !layer->HasUserData(LayerIsPrerenderedDataKey())) { - // If this layer isn't prerendered or we clip composites to our OS - // window, then we can't correctly optimize to an empty - // transaction in general. - return false; - } - - if (DoesLayerOrAncestorsHaveOutOfDateFrameMetrics(layer)) { - // At least one scroll frame that can affect the position of this layer - // has changed its scroll offset since the last paint. Schedule a full - // paint to make sure that this layer's transform and all the frame - // metrics that affect it are in sync. - return false; - } - - gfx::Matrix4x4Flagged transform3d; - if (!nsLayoutUtils::GetLayerTransformForFrame(this, &transform3d)) { - // We're not able to compute a layer transform that we know would - // be used at the next layers transaction, so we can't only update - // the transform and will need to schedule an invalidating paint. - return false; - } - gfx::Matrix transform; - gfx::Matrix previousTransform; - // FIXME/bug 796690 and 796705: in general, changes to 3D - // transforms, or transform changes to properties other than - // translation, may lead us to choose a different rendering - // resolution for our layer. So if the transform is 3D or has a - // non-translation change, bail and schedule an invalidating paint. - // (We can often do better than this, for example for scale-down - // changes.) - static const gfx::Float kError = 0.0001f; - if (!transform3d.Is2D(&transform) || - !layer->GetBaseTransform().Is2D(&previousTransform) || - !gfx::FuzzyEqual(transform._11, previousTransform._11, kError) || - !gfx::FuzzyEqual(transform._22, previousTransform._22, kError) || - !gfx::FuzzyEqual(transform._21, previousTransform._21, kError) || - !gfx::FuzzyEqual(transform._12, previousTransform._12, kError)) { - return false; - } - layer->SetBaseTransformForNextTransaction(transform3d.GetMatrix()); - *aLayerResult = layer; - return true; -} +bool nsIFrame::TryUpdateTransformOnly(Layer** aLayerResult) { return false; } bool nsIFrame::IsInvalid(nsRect& aRect) { if (!HasAnyStateBits(NS_FRAME_NEEDS_PAINT)) { @@ -7447,8 +7365,6 @@ Layer* nsIFrame::InvalidateLayer(DisplayItemType aDisplayItemKey, uint32_t aFlags /* = 0 */) { NS_ASSERTION(aDisplayItemKey > DisplayItemType::TYPE_ZERO, "Need a key"); - Layer* layer = FrameLayerBuilder::GetDedicatedLayer(this, aDisplayItemKey); - nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(this); InvalidateRenderingObservers(displayRoot, this, false); @@ -7459,48 +7375,27 @@ Layer* nsIFrame::InvalidateLayer(DisplayItemType aDisplayItemKey, return nullptr; } - // If the layer is being updated asynchronously, and it's being forwarded - // to a compositor, then we don't need to invalidate. - if ((aFlags & UPDATE_IS_ASYNC) && layer && layer->SupportsAsyncUpdate()) { - return layer; - } - - if (!layer) { - if (aFrameDamageRect && aFrameDamageRect->IsEmpty()) { - return nullptr; - } - - // In the bug 930056, dialer app startup but not shown on the - // screen because sometimes we don't have any retainned data - // for remote type displayitem and thus Repaint event is not - // triggered. So, always invalidate in this case. - DisplayItemType displayItemKey = aDisplayItemKey; - if (aDisplayItemKey == DisplayItemType::TYPE_REMOTE) { - displayItemKey = DisplayItemType::TYPE_ZERO; - } - - if (aFrameDamageRect) { - InvalidateFrameWithRect(*aFrameDamageRect, - static_cast<uint32_t>(displayItemKey)); - } else { - InvalidateFrame(static_cast<uint32_t>(displayItemKey)); - } - + if (aFrameDamageRect && aFrameDamageRect->IsEmpty()) { return nullptr; } - if (aDamageRect && aDamageRect->IsEmpty()) { - return layer; + // In the bug 930056, dialer app startup but not shown on the + // screen because sometimes we don't have any retainned data + // for remote type displayitem and thus Repaint event is not + // triggered. So, always invalidate in this case. + DisplayItemType displayItemKey = aDisplayItemKey; + if (aDisplayItemKey == DisplayItemType::TYPE_REMOTE) { + displayItemKey = DisplayItemType::TYPE_ZERO; } - if (aDamageRect) { - layer->AddInvalidRect(*aDamageRect); + if (aFrameDamageRect) { + InvalidateFrameWithRect(*aFrameDamageRect, + static_cast<uint32_t>(displayItemKey)); } else { - layer->SetInvalidRectToVisibleRegion(); + InvalidateFrame(static_cast<uint32_t>(displayItemKey)); } - SchedulePaintInternal(displayRoot, this, PAINT_COMPOSITE_ONLY); - return layer; + return nullptr; } static nsRect ComputeEffectsRect(nsIFrame* aFrame, const nsRect& aOverflowRect, diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index a3fb2e4c5dd774a050d05678b4ebe5968a338946..c2d3f2963b856cc965604684178a00ee8434558f 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -140,7 +140,6 @@ class nsDisplayListSet; class EventStates; class ServoRestyleState; -class DisplayItemData; class EffectSet; class LazyLogModule; class PresShell; @@ -639,8 +638,6 @@ class nsIFrame : public nsQueryFrame { typedef mozilla::gfx::Matrix4x4Flagged Matrix4x4Flagged; typedef mozilla::Sides Sides; typedef mozilla::LogicalSides LogicalSides; - typedef mozilla::SmallPointerArray<mozilla::DisplayItemData> - DisplayItemDataArray; typedef mozilla::SmallPointerArray<nsDisplayItem> DisplayItemArray; typedef nsQueryFrame::ClassID ClassID; @@ -1391,9 +1388,6 @@ class nsIFrame : public nsQueryFrame { NS_DECLARE_FRAME_PROPERTY_RELEASABLE(OffsetPathCache, mozilla::gfx::Path) - NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayItemDataProperty, - DisplayItemDataArray) - mozilla::FrameBidiData GetBidiData() const { bool exists; mozilla::FrameBidiData bidiData = GetProperty(BidiDataProperty(), &exists); @@ -4867,10 +4861,6 @@ class nsIFrame : public nsQueryFrame { availbleISizeOverride, aSizeOverrides, aFlags); } - DisplayItemDataArray* DisplayItemData() const { - return GetProperty(nsIFrame::DisplayItemDataProperty()); - } - DisplayItemArray& DisplayItems() { return mDisplayItems; } const DisplayItemArray& DisplayItems() const { return mDisplayItems; } diff --git a/layout/generic/nsIScrollableFrame.h b/layout/generic/nsIScrollableFrame.h index 9209f719e9305735b993a2de226c8c3c007dfb09..c64d26dab9438d8a9aff64de149c8bb97ee67cf9 100644 --- a/layout/generic/nsIScrollableFrame.h +++ b/layout/generic/nsIScrollableFrame.h @@ -34,7 +34,6 @@ class nsPresContext; class nsIContent; namespace mozilla { -struct ContainerLayerParameters; class DisplayItemClip; class nsDisplayListBuilder; @@ -56,7 +55,6 @@ class ScrollAnchorContainer; class nsIScrollableFrame : public nsIScrollbarMediator { public: typedef mozilla::CSSIntPoint CSSIntPoint; - typedef mozilla::ContainerLayerParameters ContainerLayerParameters; typedef mozilla::layers::ScrollSnapInfo ScrollSnapInfo; typedef mozilla::layout::ScrollAnchorContainer ScrollAnchorContainer; typedef mozilla::ScrollMode ScrollMode; @@ -484,14 +482,7 @@ class nsIScrollableFrame : public nsIScrollbarMediator { virtual mozilla::Maybe<mozilla::layers::ScrollMetadata> ComputeScrollMetadata( mozilla::layers::LayerManager* aLayerManager, const nsIFrame* aContainerReferenceFrame, - const mozilla::Maybe<ContainerLayerParameters>& aParameters, const mozilla::DisplayItemClip* aClip) const = 0; - /** - * Ensure's aLayer is clipped to the display port. - */ - virtual void ClipLayerToDisplayPort( - mozilla::layers::Layer* aLayer, const mozilla::DisplayItemClip* aClip, - const ContainerLayerParameters& aParameters) const = 0; /** * Mark the scrollbar frames for reflow. diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 81bbf74ddd5fcaa3b5668dc5426e4701adf4c4e8..8ad5325c4e84fc67d747258838d96e8b8bfac111 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -63,7 +63,6 @@ #include "nsLayoutUtils.h" #include "nsDisplayList.h" #include "nsIContent.h" -#include "FrameLayerBuilder.h" #include "mozilla/dom/Selection.h" #include "nsIURIMutator.h" @@ -2055,62 +2054,6 @@ nsRect nsDisplayImage::GetDestRect() const { return imageFrame->PredictedDestRect(frameContentBox); } -LayerState nsDisplayImage::GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - if (!nsDisplayItem::ForceActiveLayers()) { - bool animated = false; - if (!StaticPrefs::layout_animated_image_layers_enabled() || - mImage->GetType() != imgIContainer::TYPE_RASTER || - NS_FAILED(mImage->GetAnimated(&animated)) || !animated) { - if (!aManager->IsCompositingCheap() || - !nsLayoutUtils::GPUImageScalingEnabled()) { - return LayerState::LAYER_NONE; - } - } - - if (!animated) { - int32_t imageWidth; - int32_t imageHeight; - mImage->GetWidth(&imageWidth); - mImage->GetHeight(&imageHeight); - - NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!"); - - const int32_t factor = mFrame->PresContext()->AppUnitsPerDevPixel(); - const LayoutDeviceRect destRect = - LayoutDeviceRect::FromAppUnits(GetDestRect(), factor); - const LayerRect destLayerRect = destRect * aParameters.Scale(); - - // Calculate the scaling factor for the frame. - const gfxSize scale = gfxSize(destLayerRect.width / imageWidth, - destLayerRect.height / imageHeight); - - // If we are not scaling at all, no point in separating this into a layer. - if (scale.width == 1.0f && scale.height == 1.0f) { - return LayerState::LAYER_NONE; - } - - // If the target size is pretty small, no point in using a layer. - if (destLayerRect.width * destLayerRect.height < 64 * 64) { - return LayerState::LAYER_NONE; - } - } - } - - if (!CanOptimizeToImageLayer(aManager, aBuilder)) { - return LayerState::LAYER_NONE; - } - - // Image layer doesn't support draw focus ring for image map. - nsImageFrame* f = static_cast<nsImageFrame*>(mFrame); - if (f->HasImageMap()) { - return LayerState::LAYER_NONE; - } - - return LayerState::LAYER_ACTIVE; -} - nsRegion nsDisplayImage::GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) const { *aSnap = false; @@ -2121,30 +2064,6 @@ nsRegion nsDisplayImage::GetOpaqueRegion(nsDisplayListBuilder* aBuilder, return nsRegion(); } -already_AddRefed<Layer> nsDisplayImage::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - uint32_t flags = imgIContainer::FLAG_ASYNC_NOTIFY; - if (aBuilder->ShouldSyncDecodeImages()) { - flags |= imgIContainer::FLAG_SYNC_DECODE; - } - - RefPtr<ImageContainer> container = mImage->GetImageContainer(aManager, flags); - if (!container || !container->HasCurrentImage()) { - return nullptr; - } - - RefPtr<ImageLayer> layer = static_cast<ImageLayer*>( - aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this)); - if (!layer) { - layer = aManager->CreateImageLayer(); - if (!layer) return nullptr; - } - layer->SetContainer(container); - ConfigureLayer(layer, aParameters); - return layer.forget(); -} - bool nsDisplayImage::CreateWebRenderCommands( mozilla::wr::DisplayListBuilder& aBuilder, mozilla::wr::IpcResourceUpdateQueue& aResources, diff --git a/layout/generic/nsImageFrame.h b/layout/generic/nsImageFrame.h index dadc40fc45c86f0975dac3073511b46052021cae..be7dfe8ae6324dd131b00f148b9d5b16306aeed2 100644 --- a/layout/generic/nsImageFrame.h +++ b/layout/generic/nsImageFrame.h @@ -475,9 +475,6 @@ class nsDisplayImage final : public nsDisplayImageContainer { void UpdateDrawResult(mozilla::image::ImgDrawResult aResult) final { nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, aResult); } - - LayerState GetLayerState(nsDisplayListBuilder*, LayerManager*, - const ContainerLayerParameters&) final; nsRect GetBounds(bool* aSnap) const { *aSnap = true; @@ -491,8 +488,6 @@ class nsDisplayImage final : public nsDisplayImageContainer { nsRegion GetOpaqueRegion(nsDisplayListBuilder*, bool* aSnap) const final; - already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder*, LayerManager*, - const ContainerLayerParameters&) final; bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder&, mozilla::wr::IpcResourceUpdateQueue&, const StackingContextHelper&, diff --git a/layout/generic/nsSubDocumentFrame.cpp b/layout/generic/nsSubDocumentFrame.cpp index ae6abaeb622e4ee6512c0e16569f731ade68aca5..8de95ad1606f82cbd48cb6ad51fa07fe9856ed5e 100644 --- a/layout/generic/nsSubDocumentFrame.cpp +++ b/layout/generic/nsSubDocumentFrame.cpp @@ -39,7 +39,6 @@ #include "nsIScrollableFrame.h" #include "nsIObjectLoadingContent.h" #include "nsLayoutUtils.h" -#include "FrameLayerBuilder.h" #include "nsContentUtils.h" #include "nsServiceManagerUtils.h" #include "nsQueryObject.h" @@ -989,8 +988,6 @@ nsIDocShell* nsSubDocumentFrame::GetDocShell() const { } static void DestroyDisplayItemDataForFrames(nsIFrame* aFrame) { - FrameLayerBuilder::DestroyDisplayItemDataFor(aFrame); - for (const auto& childList : aFrame->ChildLists()) { for (nsIFrame* child : childList.mList) { DestroyDisplayItemDataForFrames(child); @@ -1237,11 +1234,6 @@ static nsPoint GetContentRectLayerOffset(nsIFrame* aContainerFrame, // used for small software rendering tasks, like drawWindow. That's // currently implemented by a BasicLayerManager without a backing // widget, and hence in non-retained mode. -inline static bool IsTempLayerManager(LayerManager* aManager) { - return (LayersBackend::LAYERS_BASIC == aManager->GetBackendType() && - !static_cast<BasicLayerManager*>(aManager)->IsRetained()); -} - nsDisplayRemote::nsDisplayRemote(nsDisplayListBuilder* aBuilder, nsSubDocumentFrame* aFrame) : nsPaintedDisplayItem(aBuilder, aFrame), @@ -1259,15 +1251,6 @@ nsDisplayRemote::nsDisplayRemote(nsDisplayListBuilder* aBuilder, mPaintData = aFrame->GetRemotePaintData(); } -mozilla::LayerState nsDisplayRemote::GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - if (IsTempLayerManager(aManager)) { - return mozilla::LayerState::LAYER_NONE; - } - return mozilla::LayerState::LAYER_ACTIVE_FORCE; -} - LayerIntSize GetFrameSize(const nsIFrame* aFrame) { LayoutDeviceSize size = LayoutDeviceRect::FromAppUnits( aFrame->GetContentRectRelativeToSelf().Size(), @@ -1278,85 +1261,6 @@ LayerIntSize GetFrameSize(const nsIFrame* aFrame) { size.height * cumulativeResolution); } -already_AddRefed<mozilla::layers::Layer> nsDisplayRemote::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - MOZ_ASSERT(mFrame, "Makes no sense to have a shadow tree without a frame"); - - if (IsTempLayerManager(aManager)) { - // This can happen if aManager is a "temporary" manager, or if the - // widget's layer manager changed out from under us. We need to - // FIXME handle the former case somehow, probably with an API to - // draw a manager's subtree. The latter is bad bad bad, but the the - // MOZ_ASSERT() above will flag it. Returning nullptr here will just - // cause the shadow subtree not to be rendered. - NS_WARNING("Remote iframe not rendered"); - return nullptr; - } - - if (!mPaintData.mLayersId.IsValid()) { - return nullptr; - } - - if (RefPtr<RemoteBrowser> remoteBrowser = - GetFrameLoader()->GetRemoteBrowser()) { - // Adjust mItemVisibleRect, which is relative to the reference frame, to be - // relative to this frame - nsRect visibleRect; - if (aContainerParameters.mItemVisibleRect) { - visibleRect = *aContainerParameters.mItemVisibleRect; - } else { - visibleRect = GetBuildingRect(); - } - visibleRect -= ToReferenceFrame(); - nsRect contentRect = Frame()->GetContentRectRelativeToSelf(); - visibleRect.IntersectRect(visibleRect, contentRect); - visibleRect -= contentRect.TopLeft(); - - // Generate an effects update notifying the browser it is visible - aBuilder->AddEffectUpdate(remoteBrowser, - EffectsInfo::VisibleWithinRect( - visibleRect, aContainerParameters.mXScale, - aContainerParameters.mYScale)); - // FrameLayerBuilder will take care of notifying the browser when it is no - // longer visible - } - - RefPtr<Layer> layer = - aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this); - - if (!layer) { - layer = aManager->CreateRefLayer(); - } - if (!layer || !layer->AsRefLayer()) { - // Probably a temporary layer manager that doesn't know how to - // use ref layers. - return nullptr; - } - RefLayer* refLayer = layer->AsRefLayer(); - - nsPoint layerOffset = GetContentRectLayerOffset(Frame(), aBuilder); - nscoord auPerDevPixel = Frame()->PresContext()->AppUnitsPerDevPixel(); - LayoutDeviceIntPoint offset = - mozilla::LayoutDeviceIntPoint::FromAppUnitsToNearest(layerOffset, - auPerDevPixel); - - // We can only have an offset if we're a child of an inactive - // container, but our display item is LAYER_ACTIVE_FORCE which - // forces all layers above to be active. - MOZ_ASSERT(aContainerParameters.mOffset == nsIntPoint()); - Matrix4x4 m = Matrix4x4::Translation(offset.x, offset.y, 0.0); - // Remote content can't be repainted by us, so we multiply down - // the resolution that our container expects onto our container. - m.PostScale(aContainerParameters.mXScale, aContainerParameters.mYScale, 1.0); - refLayer->SetBaseTransform(m); - refLayer->SetEventRegionsOverride(mEventRegionsOverride); - refLayer->SetReferentId(mPaintData.mLayersId); - refLayer->SetRemoteDocumentSize(GetFrameSize(mFrame)); - - return layer.forget(); -} - namespace mozilla { void nsDisplayRemote::Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) { diff --git a/layout/generic/nsSubDocumentFrame.h b/layout/generic/nsSubDocumentFrame.h index dc37e3c9a2210da86ddea0dfe56f03894968b029..835a48f41364dd761a046a370f8465e3a2c4f448 100644 --- a/layout/generic/nsSubDocumentFrame.h +++ b/layout/generic/nsSubDocumentFrame.h @@ -198,7 +198,6 @@ namespace mozilla { * nsFrameLoader) into its parent frame's layer tree. */ class nsDisplayRemote final : public nsPaintedDisplayItem { - typedef mozilla::ContainerLayerParameters ContainerLayerParameters; typedef mozilla::dom::TabId TabId; typedef mozilla::gfx::Matrix4x4 Matrix4x4; typedef mozilla::layers::EventRegionsOverride EventRegionsOverride; @@ -213,14 +212,6 @@ class nsDisplayRemote final : public nsPaintedDisplayItem { public: nsDisplayRemote(nsDisplayListBuilder* aBuilder, nsSubDocumentFrame* aFrame); - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override; - - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; - void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override; bool CreateWebRenderCommands( diff --git a/layout/generic/nsVideoFrame.cpp b/layout/generic/nsVideoFrame.cpp index e018d152369f30b390710717b64ee46a7d4a9ad8..f8748dcfcc16902125431558984474a0d75b9c7c 100644 --- a/layout/generic/nsVideoFrame.cpp +++ b/layout/generic/nsVideoFrame.cpp @@ -169,76 +169,6 @@ void nsVideoFrame::DestroyFrom(nsIFrame* aDestructRoot, nsContainerFrame::DestroyFrom(aDestructRoot, aPostDestroyData); } -already_AddRefed<Layer> nsVideoFrame::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - nsDisplayItem* aItem, - const ContainerLayerParameters& aContainerParameters) { - nsRect area = GetContentRectRelativeToSelf() + aItem->ToReferenceFrame(); - HTMLVideoElement* element = static_cast<HTMLVideoElement*>(GetContent()); - - Maybe<CSSIntSize> videoSizeInPx = element->GetVideoSize(); - if (videoSizeInPx.isNothing() || area.IsEmpty()) { - return nullptr; - } - - RefPtr<ImageContainer> container = element->GetImageContainer(); - if (!container) return nullptr; - - // Retrieve the size of the decoded video frame, before being scaled - // by pixel aspect ratio. - mozilla::gfx::IntSize frameSize = container->GetCurrentSize(); - if (frameSize.width == 0 || frameSize.height == 0) { - // No image, or zero-sized image. No point creating a layer. - return nullptr; - } - - const auto aspectRatio = AspectRatio::FromSize(*videoSizeInPx); - const IntrinsicSize intrinsicSize(CSSPixel::ToAppUnits(*videoSizeInPx)); - nsRect dest = nsLayoutUtils::ComputeObjectDestRect( - area, intrinsicSize, aspectRatio, StylePosition()); - - gfxRect destGFXRect = PresContext()->AppUnitsToGfxUnits(dest); - destGFXRect.Round(); - if (destGFXRect.IsEmpty()) { - return nullptr; - } - - VideoInfo::Rotation rotationDeg = element->RotationDegrees(); - IntSize scaleHint(static_cast<int32_t>(destGFXRect.Width()), - static_cast<int32_t>(destGFXRect.Height())); - // scaleHint is set regardless of rotation, so swap w/h if needed. - SwapScaleWidthHeightForRotation(scaleHint, rotationDeg); - container->SetScaleHint(scaleHint); - - RefPtr<ImageLayer> layer = static_cast<ImageLayer*>( - aManager->GetLayerBuilder() - ? aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem) - : nullptr); - if (!layer) { - layer = aManager->CreateImageLayer(); - if (!layer) return nullptr; - } - - layer->SetContainer(container); - layer->SetSamplingFilter(nsLayoutUtils::GetSamplingFilterForFrame(this)); - // Set a transform on the layer to draw the video in the right place - gfxPoint p = destGFXRect.TopLeft() + aContainerParameters.mOffset; - - Matrix preTransform = ComputeRotationMatrix( - destGFXRect.Width(), destGFXRect.Height(), rotationDeg); - - Matrix transform = preTransform * Matrix::Translation(p.x, p.y); - - layer->SetBaseTransform(gfx::Matrix4x4::From2D(transform)); - layer->SetScaleToSize(scaleHint, ScaleMode::STRETCH); - - uint32_t flags = element->HasAlpha() ? 0 : Layer::CONTENT_OPAQUE; - layer->SetContentFlags(flags); - - RefPtr<Layer> result = std::move(layer); - return result.forget(); -} - class DispatchResizeEvent : public Runnable { public: explicit DispatchResizeEvent(nsIContent* aContent, const nsString& aName) @@ -667,31 +597,6 @@ class nsDisplayVideo : public nsPaintedDisplayItem { return f->GetContentRectRelativeToSelf() + ToReferenceFrame(); } - virtual already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override { - return static_cast<nsVideoFrame*>(mFrame)->BuildLayer( - aBuilder, aManager, this, aContainerParameters); - } - - virtual LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override { - if (aManager->IsCompositingCheap()) { - // Since ImageLayers don't require additional memory of the - // video frames we have to have anyway, we can't save much by - // making layers inactive. Also, for many accelerated layer - // managers calling imageContainer->GetCurrentAsSurface can be - // very expensive. So just always be active when compositing is - // cheap (i.e. hardware accelerated). - return LayerState::LAYER_ACTIVE; - } - HTMLMediaElement* elem = - static_cast<HTMLMediaElement*>(mFrame->GetContent()); - return elem->IsPotentiallyPlaying() ? LayerState::LAYER_ACTIVE_FORCE - : LayerState::LAYER_INACTIVE; - } - // Only report FirstContentfulPaint when the video is set bool IsContentful() const override { nsVideoFrame* f = static_cast<nsVideoFrame*>(Frame()); diff --git a/layout/generic/nsVideoFrame.h b/layout/generic/nsVideoFrame.h index 5bf833cd12127f1ed9b8f38d73cc9a7d1bab29bf..08093f9cb3bd0a99a5a5868e8e84f69c3f65af1c 100644 --- a/layout/generic/nsVideoFrame.h +++ b/layout/generic/nsVideoFrame.h @@ -14,7 +14,6 @@ #include "nsIAnonymousContentCreator.h" #include "nsStringFwd.h" #include "nsTArrayForwardDeclare.h" -#include "FrameLayerBuilder.h" namespace mozilla { namespace layers { @@ -36,7 +35,6 @@ class nsVideoFrame final : public nsContainerFrame, typedef mozilla::layers::Layer Layer; typedef mozilla::layers::LayerManager LayerManager; - typedef mozilla::ContainerLayerParameters ContainerLayerParameters; explicit nsVideoFrame(ComputedStyle*, nsPresContext*); @@ -99,11 +97,6 @@ class nsVideoFrame final : public nsContainerFrame, nsresult GetFrameName(nsAString& aResult) const override; #endif - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - nsDisplayItem* aItem, - const ContainerLayerParameters& aContainerParameters); - protected: // Returns true if we're rendering for a video element. We still create // nsVideoFrame to render controls for an audio element. diff --git a/layout/ipc/RemoteLayerTreeOwner.cpp b/layout/ipc/RemoteLayerTreeOwner.cpp index d45f95652724c980641ace7b633bf352cb6cdb8f..feb442cb1cbb21689fa47824776e9d480d39b270 100644 --- a/layout/ipc/RemoteLayerTreeOwner.cpp +++ b/layout/ipc/RemoteLayerTreeOwner.cpp @@ -112,7 +112,6 @@ bool RemoteLayerTreeOwner::AttachWindowRenderer() { renderer != mWindowRenderer) { mLayersConnected = renderer->GetCompositorBridgeChild()->SendAdoptChild(mLayersId); - FrameLayerBuilder::InvalidateAllLayers(renderer->AsLayerManager()); } mWindowRenderer = std::move(renderer); diff --git a/layout/painting/FrameLayerBuilder.cpp b/layout/painting/FrameLayerBuilder.cpp deleted file mode 100644 index 88c8a2bd35dcdcbc4b81ee6bb24ab8767bd31ef2..0000000000000000000000000000000000000000 --- a/layout/painting/FrameLayerBuilder.cpp +++ /dev/null @@ -1,7516 +0,0 @@ -/* -*- 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 "FrameLayerBuilder.h" - -#include <algorithm> -#include <deque> -#include <functional> -#include <utility> - -#include "ActiveLayerTracker.h" -#include "BasicLayers.h" -#include "ImageContainer.h" -#include "ImageLayers.h" -#include "LayerTreeInvalidation.h" -#include "LayerUserData.h" -#include "Layers.h" -#include "MaskLayerImageCache.h" -#include "MatrixStack.h" -#include "TransformClipNode.h" -#include "UnitTransforms.h" -#include "Units.h" -#include "gfx2DGlue.h" -#include "gfxContext.h" -#include "gfxEnv.h" -#include "gfxUtils.h" -#include "mozilla/DebugOnly.h" -#include "mozilla/DisplayPortUtils.h" -#include "mozilla/EffectCompositor.h" -#include "mozilla/LayerAnimationInfo.h" -#include "mozilla/LayerTimelineMarker.h" -#include "mozilla/LookAndFeel.h" -#include "mozilla/Maybe.h" -#include "mozilla/PerfStats.h" -#include "mozilla/PresShell.h" -#include "mozilla/ProfilerLabels.h" -#include "mozilla/ReverseIterator.h" -#include "mozilla/StaticPrefs_gfx.h" -#include "mozilla/StaticPrefs_layers.h" -#include "mozilla/StaticPrefs_layout.h" -#include "mozilla/SVGIntegrationUtils.h" -#include "mozilla/Unused.h" -#include "mozilla/dom/EffectsInfo.h" -#include "mozilla/dom/ProfileTimelineMarkerBinding.h" -#include "mozilla/dom/RemoteBrowser.h" -#include "mozilla/gfx/2D.h" -#include "mozilla/gfx/Matrix.h" -#include "mozilla/gfx/Tools.h" -#include "mozilla/layers/ShadowLayers.h" -#include "mozilla/layers/TextureClient.h" -#include "mozilla/layers/TextureWrapperImage.h" -#include "mozilla/layers/WebRenderUserData.h" -#include "nsDisplayList.h" -#include "nsDocShell.h" -#include "nsIScrollableFrame.h" -#include "nsImageFrame.h" -#include "nsLayoutUtils.h" -#include "nsPresContext.h" -#include "nsPrintfCString.h" -#include "nsSubDocumentFrame.h" -#include "nsTransitionManager.h" -#include "nsTHashMap.h" - -using namespace mozilla::layers; -using namespace mozilla::gfx; -using mozilla::UniquePtr; -using mozilla::WrapUnique; - -// PaintedLayerData::mAssignedDisplayItems is a std::vector, which is -// non-memmovable -MOZ_DECLARE_RELOCATE_USING_MOVE_CONSTRUCTOR(mozilla::PaintedLayerData); - -namespace mozilla { - -class PaintedDisplayItemLayerUserData; - -static nsTHashSet<DisplayItemData*>* sAliveDisplayItemDatas; - -// DO NOT MODIFY THE ARRAY RETURNED BY THIS FUNCTION. -// It might be the static empty array. -SmallPointerArray<DisplayItemData>& GetDisplayItemDataArray( - const nsIFrame* aFrame) { - static SmallPointerArray<DisplayItemData> sEmpty; - MOZ_ASSERT(sEmpty.IsEmpty()); - auto* array = aFrame->DisplayItemData(); - return array ? *array : sEmpty; -} - -/** - * The address of gPaintedDisplayItemLayerUserData is used as the user - * data key for PaintedLayers created by FrameLayerBuilder. - * It identifies PaintedLayers used to draw non-layer content, which are - * therefore eligible for recycling. We want display items to be able to - * create their own dedicated PaintedLayers in BuildLayer, if necessary, - * and we wouldn't want to accidentally recycle those. - * The user data is a PaintedDisplayItemLayerUserData. - */ -uint8_t gPaintedDisplayItemLayerUserData; -/** - * The address of gColorLayerUserData is used as the user - * data key for ColorLayers created by FrameLayerBuilder. - * The user data is null. - */ -uint8_t gColorLayerUserData; -/** - * The address of gImageLayerUserData is used as the user - * data key for ImageLayers created by FrameLayerBuilder. - * The user data is null. - */ -uint8_t gImageLayerUserData; -/** - * The address of gLayerManagerUserData is used as the user - * data key for retained LayerManagers managed by FrameLayerBuilder. - * The user data is a LayerManagerData. - */ -uint8_t gLayerManagerUserData; -/** - * The address of gMaskLayerUserData is used as the user - * data key for mask layers managed by FrameLayerBuilder. - * The user data is a MaskLayerUserData. - */ -uint8_t gMaskLayerUserData; -/** - * The address of gCSSMaskLayerUserData is used as the user - * data key for mask layers of css masking managed by FrameLayerBuilder. - * The user data is a CSSMaskLayerUserData. - */ -uint8_t gCSSMaskLayerUserData; - -// a global cache of image containers used for mask layers -static MaskLayerImageCache* gMaskLayerImageCache = nullptr; - -static inline MaskLayerImageCache* GetMaskLayerImageCache() { - if (!gMaskLayerImageCache) { - gMaskLayerImageCache = new MaskLayerImageCache(); - } - - return gMaskLayerImageCache; -} - -struct InactiveLayerData { - RefPtr<layers::BasicLayerManager> mLayerManager; - RefPtr<layers::Layer> mLayer; - UniquePtr<layers::LayerProperties> mProps; - - ~InactiveLayerData(); -}; - -struct AssignedDisplayItem { - AssignedDisplayItem(nsPaintedDisplayItem* aItem, LayerState aLayerState, - DisplayItemData* aData, const nsRect& aContentRect, - DisplayItemEntryType aType, const bool aHasOpacity, - const RefPtr<TransformClipNode>& aTransform, - const bool aIsMerged); - AssignedDisplayItem(AssignedDisplayItem&& aRhs) = default; - - bool HasOpacity() const { return mHasOpacity; } - - bool HasTransform() const { return mTransform; } - - nsPaintedDisplayItem* mItem; - DisplayItemData* mDisplayItemData; - - /** - * If the display item is being rendered as an inactive - * layer, then this stores the layer manager being - * used for the inactive transaction. - */ - UniquePtr<InactiveLayerData> mInactiveLayerData; - RefPtr<TransformClipNode> mTransform; - - nsRect mContentRect; - LayerState mLayerState; - DisplayItemEntryType mType; - - bool mReused; - bool mMerged; - bool mHasOpacity; - bool mHasPaintRect; -}; - -struct DisplayItemEntry { - DisplayItemEntry(nsDisplayItem* aItem, DisplayItemEntryType aType) - : mItem(aItem), mType(aType) {} - - nsDisplayItem* mItem; - DisplayItemEntryType mType; -}; - -/** - * Returns true if the given |aType| is an effect start marker. - */ -static bool IsEffectStartMarker(DisplayItemEntryType aType) { - return aType == DisplayItemEntryType::PushOpacity || - aType == DisplayItemEntryType::PushOpacityWithBg || - aType == DisplayItemEntryType::PushTransform; -} - -/** - * Returns true if the given |aType| is an effect end marker. - */ -static bool IsEffectEndMarker(DisplayItemEntryType aType) { - return aType == DisplayItemEntryType::PopOpacity || - aType == DisplayItemEntryType::PopTransform; -} - -enum class MarkerType { StartMarker, EndMarker }; - -/** - * Returns true if the given nsDisplayOpacity |aItem| has had opacity applied - * to its children and can be flattened away. - */ -static bool IsOpacityAppliedToChildren(nsDisplayItem* aItem) { - MOZ_ASSERT(aItem->GetType() == DisplayItemType::TYPE_OPACITY); - return static_cast<nsDisplayOpacity*>(aItem)->OpacityAppliedToChildren(); -} - -/** - * Returns true if the given display item type supports flattening with markers. - */ -static bool SupportsFlatteningWithMarkers(const DisplayItemType& aType) { - return aType == DisplayItemType::TYPE_OPACITY || - aType == DisplayItemType::TYPE_TRANSFORM; -} - -/** - * Adds the effect marker to |aMarkers| based on the type of |aItem| and whether - * |markerType| is a start or end marker. - */ -template <MarkerType markerType> -static bool AddMarkerIfNeeded(nsDisplayItem* aItem, - std::deque<DisplayItemEntry>& aMarkers) { - const DisplayItemType type = aItem->GetType(); - if (!SupportsFlatteningWithMarkers(type)) { - return false; - } - - DisplayItemEntryType marker; - -// Just a fancy way to avoid writing two separate functions to select between -// PUSH and POP markers. This is done during compile time based on |markerType|. -#define GET_MARKER(start_marker, end_marker) \ - std::conditional< \ - markerType == MarkerType::StartMarker, \ - std::integral_constant<DisplayItemEntryType, start_marker>, \ - std::integral_constant<DisplayItemEntryType, end_marker>>::type::value; - - switch (type) { - case DisplayItemType::TYPE_OPACITY: - if (IsOpacityAppliedToChildren(aItem)) { - // TODO(miko): I am not a fan of this. The more correct solution would - // be to return an enum from nsDisplayItem::ShouldFlattenAway(), so that - // we could distinguish between different flattening methods and avoid - // entering this function when markers are not needed. - return false; - } - - marker = GET_MARKER(DisplayItemEntryType::PushOpacity, - DisplayItemEntryType::PopOpacity); - break; - case DisplayItemType::TYPE_TRANSFORM: - marker = GET_MARKER(DisplayItemEntryType::PushTransform, - DisplayItemEntryType::PopTransform); - break; - default: - MOZ_ASSERT_UNREACHABLE("Invalid display item type!"); - break; - } - - aMarkers.emplace_back(aItem, marker); - return true; -} - -DisplayItemData::DisplayItemData(LayerManagerData* aParent, uint32_t aKey, - Layer* aLayer, nsIFrame* aFrame) - - : mRefCnt(0), - mParent(aParent), - mLayer(aLayer), - mDisplayItemKey(aKey), - mItem(nullptr), - mUsed(true), - mIsInvalid(false), - mReusedItem(false) { - MOZ_COUNT_CTOR(DisplayItemData); - - if (!sAliveDisplayItemDatas) { - sAliveDisplayItemDatas = new nsTHashSet<DisplayItemData*>(); - } - MOZ_RELEASE_ASSERT(!sAliveDisplayItemDatas->Contains(this)); - sAliveDisplayItemDatas->Insert(this); - - MOZ_RELEASE_ASSERT(mLayer); - if (aFrame) { - AddFrame(aFrame); - } -} - -void DisplayItemData::Destroy() { - // Get the pres context. - RefPtr<nsPresContext> presContext = mFrameList[0]->PresContext(); - - // Call our destructor. - this->~DisplayItemData(); - - // Don't let the memory be freed, since it will be recycled - // instead. Don't call the global operator delete. - presContext->PresShell()->FreeByObjectID(eArenaObjectID_DisplayItemData, - this); -} - -void DisplayItemData::AddFrame(nsIFrame* aFrame) { - MOZ_RELEASE_ASSERT(mLayer); - MOZ_RELEASE_ASSERT(!mFrameList.Contains(aFrame)); - mFrameList.AppendElement(aFrame); - - SmallPointerArray<DisplayItemData>* array = aFrame->DisplayItemData(); - - if (!array) { - array = new SmallPointerArray<DisplayItemData>(); - aFrame->SetProperty(nsIFrame::DisplayItemDataProperty(), array); - } - - array->AppendElement(this); -} - -void DisplayItemData::RemoveFrame(nsIFrame* aFrame) { - MOZ_RELEASE_ASSERT(mLayer); - bool result = mFrameList.RemoveElement(aFrame); - MOZ_RELEASE_ASSERT(result, "Can't remove a frame that wasn't added!"); - - SmallPointerArray<DisplayItemData>* array = aFrame->DisplayItemData(); - if (array) { - array->RemoveElement(this); - } -} - -void DisplayItemData::EndUpdate() { - MOZ_RELEASE_ASSERT(mLayer); - mIsInvalid = false; - mUsed = false; - mReusedItem = false; - mOldTransform = nullptr; -} - -void DisplayItemData::EndUpdate(UniquePtr<nsDisplayItemGeometry>&& aGeometry) { - MOZ_RELEASE_ASSERT(mLayer); - MOZ_ASSERT(mItem); - MOZ_ASSERT(mGeometry || aGeometry); - - if (aGeometry) { - mGeometry = std::move(aGeometry); - } - mClip = mItem->GetClip(); - mChangedFrameInvalidations.SetEmpty(); - - EndUpdate(); -} - -void DisplayItemData::BeginUpdate(Layer* aLayer, LayerState aState, - bool aFirstUpdate, - nsPaintedDisplayItem* aItem /* = nullptr */) { - bool isReused = false; - bool isMerged = false; - - if (aItem) { - isReused = !aFirstUpdate ? aItem->IsReused() : false; - - const nsDisplayWrapList* wraplist = aItem->AsDisplayWrapList(); - isMerged = wraplist && wraplist->HasMergedFrames(); - } - - BeginUpdate(aLayer, aState, aItem, isReused, isMerged); -} - -void DisplayItemData::BeginUpdate(Layer* aLayer, LayerState aState, - nsPaintedDisplayItem* aItem, bool aIsReused, - bool aIsMerged) { - MOZ_RELEASE_ASSERT(mLayer); - MOZ_RELEASE_ASSERT(aLayer); - mLayer = aLayer; - mOptLayer = nullptr; - mInactiveManager = nullptr; - mLayerState = aState; - mUsed = true; - - mItem = aItem; - mReusedItem = aIsReused; - - if (!aItem) { - return; - } - - if (!aIsMerged && mFrameList.Length() == 1) { - MOZ_ASSERT(mFrameList[0] == aItem->Frame()); - return; - } - - // We avoid adding or removing element unnecessarily - // since we have to modify userdata each time - CopyableAutoTArray<nsIFrame*, 4> copy(mFrameList); - if (!copy.RemoveElement(aItem->Frame())) { - AddFrame(aItem->Frame()); - mChangedFrameInvalidations.Or(mChangedFrameInvalidations, - aItem->Frame()->InkOverflowRect()); - } - - if (aIsMerged) { - MOZ_ASSERT(aItem->AsDisplayWrapList()); - - for (nsIFrame* frame : aItem->AsDisplayWrapList()->GetMergedFrames()) { - if (!copy.RemoveElement(frame)) { - AddFrame(frame); - mChangedFrameInvalidations.Or(mChangedFrameInvalidations, - frame->InkOverflowRect()); - } - } - } - - for (nsIFrame* frame : copy) { - RemoveFrame(frame); - mChangedFrameInvalidations.Or(mChangedFrameInvalidations, - frame->InkOverflowRect()); - } -} - -static const nsIFrame* sDestroyedFrame = nullptr; -DisplayItemData::~DisplayItemData() { - MOZ_COUNT_DTOR(DisplayItemData); - - for (nsIFrame* frame : mFrameList) { - if (frame == sDestroyedFrame) { - continue; - } - - SmallPointerArray<DisplayItemData>* array = frame->DisplayItemData(); - if (array) { - array->RemoveElement(this); - } - } - - MOZ_RELEASE_ASSERT(sAliveDisplayItemDatas); - const bool removed = sAliveDisplayItemDatas->EnsureRemoved(this); - MOZ_RELEASE_ASSERT(removed); - - if (sAliveDisplayItemDatas->Count() == 0) { - delete sAliveDisplayItemDatas; - sAliveDisplayItemDatas = nullptr; - } -} - -void DisplayItemData::NotifyRemoved() { - if (mDisplayItemKey > static_cast<uint8_t>(DisplayItemType::TYPE_MAX)) { - // This is sort of a hack. The display item key has higher bits set, which - // means that it is not the only display item for the frame. - // This branch skips separator transforms. - return; - } - - const DisplayItemType type = GetDisplayItemTypeFromKey(mDisplayItemKey); - - if (type == DisplayItemType::TYPE_REMOTE) { - // TYPE_REMOTE doesn't support merging, so access it directly - MOZ_ASSERT(mFrameList.Length() == 1); - if (mFrameList.Length() != 1) { - return; - } - - // This is a remote browser that is going away, notify it that it is now - // hidden - nsIFrame* frame = mFrameList[0]; - nsSubDocumentFrame* subdoc = static_cast<nsSubDocumentFrame*>(frame); - nsFrameLoader* frameLoader = subdoc->FrameLoader(); - if (frameLoader && frameLoader->GetRemoteBrowser()) { - frameLoader->GetRemoteBrowser()->UpdateEffects( - mozilla::dom::EffectsInfo::FullyHidden()); - } - } - - if (type != DisplayItemType::TYPE_TRANSFORM && - type != DisplayItemType::TYPE_OPACITY && - type != DisplayItemType::TYPE_BACKGROUND_COLOR) { - return; - } - - for (nsIFrame* frame : mFrameList) { - EffectCompositor::ClearIsRunningOnCompositor(frame, type); - } -} - -const nsRegion& DisplayItemData::GetChangedFrameInvalidations() { - return mChangedFrameInvalidations; -} - -DisplayItemData* DisplayItemData::AssertDisplayItemData( - DisplayItemData* aData) { - MOZ_RELEASE_ASSERT(aData); - MOZ_RELEASE_ASSERT(sAliveDisplayItemDatas && - sAliveDisplayItemDatas->Contains(aData)); - MOZ_RELEASE_ASSERT(aData->mLayer); - return aData; -} - -void* DisplayItemData::operator new(size_t sz, nsPresContext* aPresContext) { - // Check the recycle list first. - return aPresContext->PresShell()->AllocateByObjectID( - eArenaObjectID_DisplayItemData, sz); -} - -/** - * This is the userdata we associate with a layer manager. - */ -class LayerManagerData : public LayerUserData { - public: - explicit LayerManagerData(LayerManager* aManager) - : mLayerManager(aManager), -#ifdef DEBUG_DISPLAY_ITEM_DATA - mParent(nullptr), -#endif - mInvalidateAllLayers(false) { - MOZ_COUNT_CTOR(LayerManagerData); - } - ~LayerManagerData() override { MOZ_COUNT_DTOR(LayerManagerData); } - -#ifdef DEBUG_DISPLAY_ITEM_DATA - void Dump(const char* aPrefix = "") { - printf_stderr("%sLayerManagerData %p\n", aPrefix, this); - - for (auto& data : mDisplayItems) { - nsAutoCString prefix; - prefix += aPrefix; - prefix += " "; - - const char* layerState; - switch (data->mLayerState) { - case LayerState::LAYER_NONE: - layerState = "LAYER_NONE"; - break; - case LayerState::LAYER_INACTIVE: - layerState = "LAYER_INACTIVE"; - break; - case LayerState::LAYER_ACTIVE: - layerState = "LAYER_ACTIVE"; - break; - case LayerState::LAYER_ACTIVE_FORCE: - layerState = "LAYER_ACTIVE_FORCE"; - break; - case LayerState::LAYER_ACTIVE_EMPTY: - layerState = "LAYER_ACTIVE_EMPTY"; - break; - case LayerState::LAYER_SVG_EFFECTS: - layerState = "LAYER_SVG_EFFECTS"; - break; - } - uint32_t mask = (1 << TYPE_BITS) - 1; - - nsAutoCString str; - str += prefix; - str += nsPrintfCString("Frame %p ", data->mFrameList[0]); - str += nsDisplayItem::DisplayItemTypeName( - static_cast<nsDisplayItem::Type>(data->mDisplayItemKey & mask)); - if ((data->mDisplayItemKey >> TYPE_BITS)) { - str += nsPrintfCString("(%i)", data->mDisplayItemKey >> TYPE_BITS); - } - str += nsPrintfCString(", %s, Layer %p", layerState, data->mLayer.get()); - if (data->mOptLayer) { - str += nsPrintfCString(", OptLayer %p", data->mOptLayer.get()); - } - if (data->mInactiveManager) { - str += nsPrintfCString(", InactiveLayerManager %p", - data->mInactiveManager.get()); - } - str += "\n"; - - printf_stderr("%s", str.get()); - - if (data->mInactiveManager) { - prefix += " "; - printf_stderr("%sDumping inactive layer info:\n", prefix.get()); - LayerManagerData* lmd = static_cast<LayerManagerData*>( - data->mInactiveManager->GetUserData(&gLayerManagerUserData)); - lmd->Dump(prefix.get()); - } - } - } -#endif - - /** - * Tracks which frames have layers associated with them. - */ - LayerManager* mLayerManager; -#ifdef DEBUG_DISPLAY_ITEM_DATA - LayerManagerData* mParent; -#endif - std::vector<RefPtr<DisplayItemData>> mDisplayItems; - bool mInvalidateAllLayers; -}; - -/* static */ -void FrameLayerBuilder::DestroyDisplayItemDataFor(nsIFrame* aFrame) { - RemoveFrameFromLayerManager(aFrame); - - // Destroying a WebRenderUserDataTable can cause destruction of other objects - // which can remove frame properties in their destructor. If we delete a frame - // property it runs the destructor of the stored object in the middle of - // updating the frame property table, so if the destruction of that object - // causes another update to the frame property table it would leave the frame - // property table in an inconsistent state. So we remove it from the table and - // then destroy it. (bug 1530657) - WebRenderUserDataTable* userDataTable = - aFrame->TakeProperty(WebRenderUserDataProperty::Key()); - if (userDataTable) { - for (const auto& data : userDataTable->Values()) { - data->RemoveFromTable(); - } - delete userDataTable; - } -} - -/** - * We keep a stack of these to represent the PaintedLayers that are - * currently available to have display items added to. - * We use a stack here because as much as possible we want to - * assign display items to existing PaintedLayers, and to the lowest - * PaintedLayer in z-order. This reduces the number of layers and - * makes it more likely a display item will be rendered to an opaque - * layer, giving us the best chance of getting subpixel AA. - */ -class PaintedLayerData { - public: - PaintedLayerData() - : mAnimatedGeometryRoot(nullptr), - mASR(nullptr), - mClipChain(nullptr), - mReferenceFrame(nullptr), - mLayer(nullptr), - mSolidColor(NS_RGBA(0, 0, 0, 0)), - mIsSolidColorInVisibleRegion(false), - mNeedComponentAlpha(false), - mForceTransparentSurface(false), - mHideAllLayersBelow(false), - mOpaqueForAnimatedGeometryRootParent(false), - mBackfaceHidden(false), - mDTCRequiresTargetConfirmation(false), - mImage(nullptr), - mItemClip(nullptr), - mNewChildLayersIndex(-1) -#ifdef DEBUG - , - mTransformLevel(0) -#endif - { - } - - PaintedLayerData(PaintedLayerData&& aRhs) = default; - - ~PaintedLayerData() { MOZ_ASSERT(mTransformLevel == 0); } - -#ifdef MOZ_DUMP_PAINTING - /** - * Keep track of important decisions for debugging. - */ - nsCString mLog; - -# define FLB_LOG_PAINTED_LAYER_DECISION(pld, ...) \ - if (StaticPrefs::layers_dump_decision()) { \ - pld->mLog.AppendPrintf("\t\t\t\t"); \ - pld->mLog.AppendPrintf(__VA_ARGS__); \ - } -#else -# define FLB_LOG_PAINTED_LAYER_DECISION(...) -#endif - - /** - * Disables component alpha for |aItem| if the component alpha bounds are not - * contained in |mOpaqueRegion|. Alternatively if possible, sets - * |mNeedComponentAlpha| to true for this PaintedLayerData. - */ - bool SetupComponentAlpha(ContainerState* aState, nsPaintedDisplayItem* aItem, - const nsIntRect& aVisibleRect, - const TransformClipNode* aTransform); - - /** - * Record that an item has been added to the PaintedLayer, so we - * need to update our regions. - * @param aVisibleRect the area of the item that's visible - */ - void Accumulate(ContainerState* aState, nsDisplayItem* aItem, - const nsIntRect& aVisibleRect, const nsRect& aContentRect, - const DisplayItemClip& aClip, LayerState aLayerState, - nsDisplayList* aList, DisplayItemEntryType aType, - nsTArray<size_t>& aOpacityIndices, - const RefPtr<TransformClipNode>& aTransform); - - UniquePtr<InactiveLayerData> CreateInactiveLayerData( - ContainerState* aState, nsPaintedDisplayItem* aItem, - DisplayItemData* aData); - - /** - * Updates the status of |mTransform| and |aOpacityIndices|, based on |aType|. - */ - void UpdateEffectStatus(DisplayItemEntryType aType, - nsTArray<size_t>& aOpacityIndices); - - AnimatedGeometryRoot* GetAnimatedGeometryRoot() { - return mAnimatedGeometryRoot; - } - - /** - * A region including the horizontal pan, vertical pan, and no action regions. - */ - nsRegion CombinedTouchActionRegion(); - - /** - * Add the given hit test info to the hit regions for this PaintedLayer. - */ - void AccumulateHitTestItem(ContainerState* aState, nsDisplayItem* aItem, - const DisplayItemClip& aClip, - TransformClipNode* aTransform); - - void HitRegionsUpdated(); - - /** - * If this represents only a nsDisplayImage, and the image type supports being - * optimized to an ImageLayer, returns true. - */ - bool CanOptimizeToImageLayer(nsDisplayListBuilder* aBuilder); - - /** - * If this represents only a nsDisplayImage, and the image type supports being - * optimized to an ImageLayer, returns an ImageContainer for the underlying - * image if one is available. - */ - already_AddRefed<ImageContainer> GetContainerForImageLayer( - nsDisplayListBuilder* aBuilder); - - bool VisibleAboveRegionIntersects(const nsIntRegion& aRegion) const { - return !mVisibleAboveRegion.Intersect(aRegion).IsEmpty(); - } - bool VisibleRegionIntersects(const nsIntRegion& aRegion) const { - return !mVisibleRegion.Intersect(aRegion).IsEmpty(); - } - - /** - * The owning ContainerState that created this PaintedLayerData. - */ - ContainerState* mState; - - /** - * The region of visible content in the layer, relative to the - * container layer (which is at the snapped top-left of the display - * list reference frame). - */ - nsIntRegion mVisibleRegion; - /** - * The region of visible content in the layer that is opaque. - * Same coordinate system as mVisibleRegion. - */ - nsIntRegion mOpaqueRegion; - /** - * The definitely-hit region for this PaintedLayer. - */ - nsRegion mHitRegion; - /** - * The maybe-hit region for this PaintedLayer. - */ - nsRegion mMaybeHitRegion; - /** - * The dispatch-to-content hit region for this PaintedLayer. - */ - nsRegion mDispatchToContentHitRegion; - /** - * The region for this PaintedLayer that is sensitive to events - * but disallows panning and zooming. This is an approximation - * and any deviation from the true region will be part of the - * mDispatchToContentHitRegion. - */ - nsRegion mNoActionRegion; - /** - * The region for this PaintedLayer that is sensitive to events and - * allows horizontal panning but not zooming. This is an approximation - * and any deviation from the true region will be part of the - * mDispatchToContentHitRegion. - */ - nsRegion mHorizontalPanRegion; - /** - * The region for this PaintedLayer that is sensitive to events and - * allows vertical panning but not zooming. This is an approximation - * and any deviation from the true region will be part of the - * mDispatchToContentHitRegion. - */ - nsRegion mVerticalPanRegion; - - bool mCollapsedTouchActions = false; - /** - * Scaled versions of the bounds of mHitRegion and mMaybeHitRegion. - * We store these because FindPaintedLayerFor() needs to consume them - * in this form, and it's a hot code path so we don't want to scale - * them inside that function. - */ - nsIntRect mScaledHitRegionBounds; - nsIntRect mScaledMaybeHitRegionBounds; - /** - * The "active scrolled root" for all content in the layer. Must - * be non-null; all content in a PaintedLayer must have the same - * active scrolled root. - */ - AnimatedGeometryRoot* mAnimatedGeometryRoot; - const ActiveScrolledRoot* mASR; - /** - * The chain of clips that should apply to this layer. - */ - const DisplayItemClipChain* mClipChain; - /** - * The offset between mAnimatedGeometryRoot and the reference frame. - */ - nsPoint mAnimatedGeometryRootOffset; - /** - * If non-null, the frame from which we'll extract "fixed positioning" - * metadata for this layer. This can be a position:fixed frame or a viewport - * frame; the latter case is used for background-attachment:fixed content. - */ - const nsIFrame* mReferenceFrame; - PaintedLayer* mLayer; - /** - * If mIsSolidColorInVisibleRegion is true, this is the color of the visible - * region. - */ - nscolor mSolidColor; - /** - * True if every pixel in mVisibleRegion will have color mSolidColor. - */ - bool mIsSolidColorInVisibleRegion; - /** - * True if there is any text visible in the layer that's over - * transparent pixels in the layer. - */ - bool mNeedComponentAlpha; - /** - * Set if the layer should be treated as transparent, even if its entire - * area is covered by opaque display items. For example, this needs to - * be set if something is going to "punch holes" in the layer by clearing - * part of its surface. - */ - bool mForceTransparentSurface; - /** - * Set if all layers below this PaintedLayer should be hidden. - */ - bool mHideAllLayersBelow; - /** - * Set if the opaque region for this layer can be applied to the parent - * animated geometry root of this layer's animated geometry root. - * We set this when a PaintedLayer's animated geometry root is a scrollframe - * and the PaintedLayer completely fills the displayport of the scrollframe. - */ - bool mOpaqueForAnimatedGeometryRootParent; - /** - * Set if the backface of this region is hidden to the user. - * Content that backface is hidden should not be draw on the layer - * with visible backface. - */ - bool mBackfaceHidden; - /** - * Set to true if events targeting the dispatch-to-content region - * require target confirmation. - * See CompositorHitTestFlags::eRequiresTargetConfirmation and - * EventRegions::mDTCRequiresTargetConfirmation. - */ - bool mDTCRequiresTargetConfirmation; - /** - * Stores the pointer to the nsDisplayImage if we want to - * convert this to an ImageLayer. - */ - nsDisplayImageContainer* mImage; - /** - * Stores the clip that we need to apply to the image or, if there is no - * image, a clip for SOME item in the layer. There is no guarantee which - * item's clip will be stored here and mItemClip should not be used to clip - * the whole layer - only some part of the clip should be used, as determined - * by PaintedDisplayItemLayerUserData::GetCommonClipCount() - which may even - * be no part at all. - */ - const DisplayItemClip* mItemClip; - /** - * Index of this layer in mNewChildLayers. - */ - int32_t mNewChildLayersIndex; - /** - * The region of visible content above the layer and below the - * next PaintedLayerData currently in the stack, if any. - * This is a conservative approximation: it contains the true region. - */ - nsIntRegion mVisibleAboveRegion; - /** - * All the display items that have been assigned to this painted layer. - * These items get added by Accumulate(). - */ - std::vector<AssignedDisplayItem> mAssignedDisplayItems; - -#ifdef DEBUG - /** - * Tracks the level of transform to ensure balanced PUSH/POP markers. - */ - int mTransformLevel; -#endif -}; - -struct NewLayerEntry { - NewLayerEntry() - : mAnimatedGeometryRoot(nullptr), - mASR(nullptr), - mClipChain(nullptr), - mScrollMetadataASR(nullptr), - mLayerContentsVisibleRect(0, 0, -1, -1), - mLayerState(LayerState::LAYER_INACTIVE), - mHideAllLayersBelow(false), - mOpaqueForAnimatedGeometryRootParent(false), - mUntransformedVisibleRegion(false), - mIsFixedToRootScrollFrame(false) {} - // mLayer is null if the previous entry is for a PaintedLayer that hasn't - // been optimized to some other form (yet). - RefPtr<Layer> mLayer; - AnimatedGeometryRoot* mAnimatedGeometryRoot; - const ActiveScrolledRoot* mASR; - const DisplayItemClipChain* mClipChain; - const ActiveScrolledRoot* mScrollMetadataASR; - // If non-null, this ScrollMetadata is set to the be the first ScrollMetadata - // on the layer. - UniquePtr<ScrollMetadata> mBaseScrollMetadata; - // The following are only used for retained layers (for occlusion - // culling of those layers). These regions are all relative to the - // container reference frame. - nsIntRegion mVisibleRegion; - nsIntRegion mOpaqueRegion; - // This rect is in the layer's own coordinate space. The computed visible - // region for the layer cannot extend beyond this rect. - nsIntRect mLayerContentsVisibleRect; - LayerState mLayerState; - bool mHideAllLayersBelow; - // When mOpaqueForAnimatedGeometryRootParent is true, the opaque region of - // this layer is opaque in the same position even subject to the animation of - // geometry of mAnimatedGeometryRoot. For example when mAnimatedGeometryRoot - // is a scrolled frame and the scrolled content is opaque everywhere in the - // displayport, we can set this flag. - // When this flag is set, we can treat this opaque region as covering - // content whose animated geometry root is the animated geometry root for - // mAnimatedGeometryRoot->GetParent(). - bool mOpaqueForAnimatedGeometryRootParent; - - // mVisibleRegion is relative to the associated frame before - // transform. - bool mUntransformedVisibleRegion; - bool mIsFixedToRootScrollFrame; -}; - -class PaintedLayerDataTree; - -/** - * This is tree node type for PaintedLayerDataTree. - * Each node corresponds to a different animated geometry root, and contains - * a stack of PaintedLayerDatas, in bottom-to-top order. - * There is at most one node per animated geometry root. The ancestor and - * descendant relations in PaintedLayerDataTree tree mirror those in the frame - * tree. - * Each node can have clip that describes the potential extents that items in - * this node can cover. If mHasClip is false, it means that the node's contents - * can move anywhere. - * Testing against the clip instead of the node's actual contents has the - * advantage that the node's contents can move or animate without affecting - * content in other nodes. So we don't need to re-layerize during animations - * (sync or async), and during async animations everything is guaranteed to - * look correct. - * The contents of a node's PaintedLayerData stack all share the node's - * animated geometry root. The child nodes are on top of the PaintedLayerData - * stack, in z-order, and the clip rects of the child nodes are allowed to - * intersect with the visible region or visible above region of their parent - * node's PaintedLayerDatas. - */ -class PaintedLayerDataNode { - public: - PaintedLayerDataNode(PaintedLayerDataTree& aTree, - PaintedLayerDataNode* aParent, - AnimatedGeometryRoot* aAnimatedGeometryRoot); - ~PaintedLayerDataNode(); - - AnimatedGeometryRoot* GetAnimatedGeometryRoot() const { - return mAnimatedGeometryRoot; - } - - /** - * Whether this node's contents can potentially intersect aRect. - * aRect is in our tree's ContainerState's coordinate space. - */ - bool Intersects(const nsIntRect& aRect) const { - return !mHasClip || mClipRect.Intersects(aRect); - } - - /** - * Create a PaintedLayerDataNode for aAnimatedGeometryRoot, add it to our - * children, and return it. - */ - PaintedLayerDataNode* AddChildNodeFor( - AnimatedGeometryRoot* aAnimatedGeometryRoot); - - /** - * Find a PaintedLayerData in our mPaintedLayerDataStack that aItem can be - * added to. Creates a new PaintedLayerData by calling - * aNewPaintedLayerCallback if necessary. - */ - template <typename NewPaintedLayerCallbackType> - PaintedLayerData* FindPaintedLayerFor( - const nsIntRect& aVisibleRect, bool aBackfaceHidden, - const ActiveScrolledRoot* aASR, const DisplayItemClipChain* aClipChain, - NewPaintedLayerCallbackType aNewPaintedLayerCallback); - - /** - * Find an opaque background color for aRegion. Pulls a color from the parent - * geometry root if appropriate, but only if that color is present underneath - * the whole clip of this node, so that this node's contents can animate or - * move (possibly async) without having to change the background color. - * @param aUnderIndex Searching will start in mPaintedLayerDataStack right - * below aUnderIndex. - */ - enum { ABOVE_TOP = -1 }; - nscolor FindOpaqueBackgroundColor(const nsIntRegion& aRegion, - int32_t aUnderIndex = ABOVE_TOP) const; - /** - * Same as FindOpaqueBackgroundColor, but only returns a color if absolutely - * nothing is in between, so that it can be used for a layer that can move - * anywhere inside our clip. - */ - nscolor FindOpaqueBackgroundColorCoveringEverything() const; - - /** - * Adds aRect to this node's top PaintedLayerData's mVisibleAboveRegion, - * or mVisibleAboveBackgroundRegion if mPaintedLayerDataStack is empty. - */ - void AddToVisibleAboveRegion(const nsIntRect& aRect); - /** - * Call this if all of our existing content can potentially be covered, so - * nothing can merge with it and all new content needs to create new items - * on top. This will finish all of our children and pop our whole - * mPaintedLayerDataStack. - */ - void SetAllDrawingAbove(); - - /** - * Finish this node: Finish all children, finish our PaintedLayer contents, - * and (if requested) adjust our parent's visible above region to include - * our clip. - */ - void Finish(bool aParentNeedsAccurateVisibleAboveRegion); - - /** - * Finish any children that intersect aRect. - */ - void FinishChildrenIntersecting(const nsIntRect& aRect); - - /** - * Finish all children. - */ - void FinishAllChildren() { FinishAllChildren(true); } - - protected: - /** - * Finish all items in mPaintedLayerDataStack and clear the stack. - */ - void PopAllPaintedLayerData(); - /** - * Finish all of our child nodes, but don't touch mPaintedLayerDataStack. - */ - void FinishAllChildren(bool aThisNodeNeedsAccurateVisibleAboveRegion); - /** - * Pass off opaque background color searching to our parent node, if we have - * one. - */ - nscolor FindOpaqueBackgroundColorInParentNode() const; - - PaintedLayerDataTree& mTree; - PaintedLayerDataNode* mParent; - AnimatedGeometryRoot* mAnimatedGeometryRoot; - - /** - * Our contents: a PaintedLayerData stack and our child nodes. - */ - AutoTArray<PaintedLayerData, 3> mPaintedLayerDataStack; - - /** - * UniquePtr is used here in the sense of "unique ownership", i.e. there is - * only one owner. Not in the sense of "this is the only pointer to the - * node": There are two other, non-owning, pointers to our child nodes: The - * node's respective children point to their parent node with their mParent - * pointer, and the tree keeps a map of animated geometry root to node in its - * mNodes member. These outside pointers are the reason that mChildren isn't - * just an nsTArray<PaintedLayerDataNode> (since the pointers would become - * invalid whenever the array expands its capacity). - */ - nsTArray<UniquePtr<PaintedLayerDataNode>> mChildren; - - /** - * The region that's covered between our "background" and the bottom of - * mPaintedLayerDataStack. This is used to indicate whether we can pull - * a background color from our parent node. If mVisibleAboveBackgroundRegion - * should be considered infinite, mAllDrawingAboveBackground will be true and - * the value of mVisibleAboveBackgroundRegion will be meaningless. - */ - nsIntRegion mVisibleAboveBackgroundRegion; - - /** - * Our clip, if we have any. If not, that means we can move anywhere, and - * mHasClip will be false and mClipRect will be meaningless. - */ - nsIntRect mClipRect; - bool mHasClip; - - /** - * Whether mVisibleAboveBackgroundRegion should be considered infinite. - */ - bool mAllDrawingAboveBackground; -}; - -class ContainerState; - -/** - * A tree of PaintedLayerDataNodes. At any point in time, the tree only - * contains nodes for animated geometry roots that new items can potentially - * merge into. Any time content is added on top that overlaps existing things - * in such a way that we no longer want to merge new items with some existing - * content, that existing content gets "finished". - * The public-facing methods of this class are FindPaintedLayerFor, - * AddingOwnLayer, and Finish. The other public methods are for - * PaintedLayerDataNode. - * The tree calls out to its containing ContainerState for some things. - * All coordinates / rects in the tree or the tree nodes are in the - * ContainerState's coordinate space, i.e. relative to the reference frame and - * in layer pixels. - * The clip rects of sibling nodes never overlap. This is ensured by finishing - * existing nodes before adding new ones, if this property were to be violated. - * The root tree node doesn't get finished until the ContainerState is - * finished. - * The tree's root node is always the root reference frame of the builder. We - * don't stop at the container state's mContainerAnimatedGeometryRoot because - * some of our contents can have animated geometry roots that are not - * descendants of the container's animated geometry root. Every animated - * geometry root we encounter for our contents needs to have a defined place in - * the tree. - */ -class PaintedLayerDataTree { - public: - PaintedLayerDataTree(ContainerState& aContainerState, - nscolor& aBackgroundColor) - : mContainerState(aContainerState), - mContainerUniformBackgroundColor(aBackgroundColor), - mForInactiveLayer(false) {} - - ~PaintedLayerDataTree() { - MOZ_ASSERT(!mRoot); - MOZ_ASSERT(mNodes.Count() == 0); - } - - void InitializeForInactiveLayer(AnimatedGeometryRoot* aAnimatedGeometryRoot); - - /** - * Notify our contents that some non-PaintedLayer content has been added. - * *aRect needs to be a rectangle that doesn't move with respect to - * aAnimatedGeometryRoot and that contains the added item. - * If aRect is null, the extents will be considered infinite. - * If aOutUniformBackgroundColor is non-null, it will be set to an opaque - * color that can be pulled into the background of the added content, or - * transparent if that is not possible. - */ - void AddingOwnLayer(AnimatedGeometryRoot* aAnimatedGeometryRoot, - const nsIntRect* aRect, - nscolor* aOutUniformBackgroundColor); - - /** - * Find a PaintedLayerData for aItem. This can either be an existing - * PaintedLayerData from inside a node in our tree, or a new one that gets - * created by a call out to aNewPaintedLayerCallback. - */ - template <typename NewPaintedLayerCallbackType> - PaintedLayerData* FindPaintedLayerFor( - AnimatedGeometryRoot* aAnimatedGeometryRoot, - const ActiveScrolledRoot* aASR, const DisplayItemClipChain* aClipChain, - const nsIntRect& aVisibleRect, const bool aBackfaceHidden, - NewPaintedLayerCallbackType aNewPaintedLayerCallback); - - /** - * Finish everything. - */ - void Finish(); - - /** - * Get the parent animated geometry root of aAnimatedGeometryRoot. - * That's either aAnimatedGeometryRoot's animated geometry root, or, if - * that's aAnimatedGeometryRoot itself, then it's the animated geometry - * root for aAnimatedGeometryRoot's cross-doc parent frame. - */ - AnimatedGeometryRoot* GetParentAnimatedGeometryRoot( - AnimatedGeometryRoot* aAnimatedGeometryRoot); - - /** - * Whether aAnimatedGeometryRoot has an intrinsic clip that doesn't move with - * respect to aAnimatedGeometryRoot's parent animated geometry root. - * If aAnimatedGeometryRoot is a scroll frame, this will be the scroll frame's - * scroll port, otherwise there is no clip. - * This method doesn't have much to do with PaintedLayerDataTree, but this is - * where we have easy access to a display list builder, which we use to get - * the clip rect result into the right coordinate space. - */ - bool IsClippedWithRespectToParentAnimatedGeometryRoot( - AnimatedGeometryRoot* aAnimatedGeometryRoot, nsIntRect* aOutClip); - - /** - * Called by PaintedLayerDataNode when it is finished, so that we can drop - * our pointers to it. - */ - void NodeWasFinished(AnimatedGeometryRoot* aAnimatedGeometryRoot); - - nsDisplayListBuilder* Builder() const; - ContainerState& ContState() const { return mContainerState; } - nscolor UniformBackgroundColor() const { - return mContainerUniformBackgroundColor; - } - - protected: - /** - * Finish all nodes that potentially intersect *aRect, where *aRect is a rect - * that doesn't move with respect to aAnimatedGeometryRoot. - * If aRect is null, *aRect will be considered infinite. - */ - void FinishPotentiallyIntersectingNodes( - AnimatedGeometryRoot* aAnimatedGeometryRoot, const nsIntRect* aRect); - - /** - * Make sure that there is a node for aAnimatedGeometryRoot and all of its - * ancestor geometry roots. Return the node for aAnimatedGeometryRoot. - */ - PaintedLayerDataNode* EnsureNodeFor( - AnimatedGeometryRoot* aAnimatedGeometryRoot); - - /** - * Find an existing node in the tree for an ancestor of aAnimatedGeometryRoot. - * *aOutAncestorChild will be set to the last ancestor that was encountered - * in the search up from aAnimatedGeometryRoot; it will be a child animated - * geometry root of the result, if neither are null. - */ - PaintedLayerDataNode* FindNodeForAncestorAnimatedGeometryRoot( - AnimatedGeometryRoot* aAnimatedGeometryRoot, - AnimatedGeometryRoot** aOutAncestorChild); - - ContainerState& mContainerState; - Maybe<PaintedLayerDataNode> mRoot; - - /** - * The uniform opaque color from behind this container layer, or - * NS_RGBA(0,0,0,0) if the background behind this container layer is not - * uniform and opaque. This color can be pulled into PaintedLayers that are - * directly above the background. - */ - nscolor mContainerUniformBackgroundColor; - - /** - * A hash map for quick access the node belonging to a particular animated - * geometry root. - */ - nsTHashMap<nsPtrHashKey<AnimatedGeometryRoot>, PaintedLayerDataNode*> mNodes; - - bool mForInactiveLayer; -}; - -/** - * This is a helper object used to build up the layer children for - * a ContainerLayer. - */ -class ContainerState { - public: - ContainerState(nsDisplayListBuilder* aBuilder, LayerManager* aManager, - FrameLayerBuilder* aLayerBuilder, nsIFrame* aContainerFrame, - nsDisplayItem* aContainerItem, const nsRect& aContainerBounds, - ContainerLayer* aContainerLayer, - const ContainerLayerParameters& aParameters, - nscolor aBackgroundColor, - const ActiveScrolledRoot* aContainerASR, - const ActiveScrolledRoot* aContainerScrollMetadataASR, - const ActiveScrolledRoot* aContainerCompositorASR) - : mBuilder(aBuilder), - mManager(aManager), - mLayerBuilder(aLayerBuilder), - mContainerFrame(aContainerFrame), - mContainerLayer(aContainerLayer), - mContainerBounds(aContainerBounds), - mContainerASR(aContainerASR), - mContainerScrollMetadataASR(aContainerScrollMetadataASR), - mContainerCompositorASR(aContainerCompositorASR), - mParameters(aParameters), - mPaintedLayerDataTree(*this, aBackgroundColor), - mLastDisplayPortAGR(nullptr), - mContainerItem(aContainerItem) { - nsPresContext* presContext = aContainerFrame->PresContext(); - mAppUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); - mContainerReferenceFrame = const_cast<nsIFrame*>( - aContainerItem ? aContainerItem->ReferenceFrameForChildren() - : mBuilder->FindReferenceFrameFor(mContainerFrame)); - bool isAtRoot = !aContainerItem || - (aContainerItem->Frame() == mBuilder->RootReferenceFrame()); - MOZ_ASSERT(!isAtRoot || - mContainerReferenceFrame == mBuilder->RootReferenceFrame()); - mContainerAnimatedGeometryRoot = - isAtRoot ? aBuilder->GetRootAnimatedGeometryRoot() - : aContainerItem->GetAnimatedGeometryRoot(); - MOZ_ASSERT( - !mBuilder->IsPaintingToWindow() || - nsLayoutUtils::IsAncestorFrameCrossDocInProcess( - mBuilder->RootReferenceFrame(), *mContainerAnimatedGeometryRoot)); - // When AllowResidualTranslation is false, display items will be drawn - // scaled with a translation by integer pixels, so we know how the snapping - // will work. - mSnappingEnabled = aManager->IsSnappingEffectiveTransforms() && - !mParameters.AllowResidualTranslation(); - CollectOldLayers(); - } - - /** - * This is the method that actually walks a display list and builds - * the child layers. - */ - void ProcessDisplayItems(nsDisplayList* aList); - /** - * This finalizes all the open PaintedLayers by popping every element off - * mPaintedLayerDataStack, then sets the children of the container layer - * to be all the layers in mNewChildLayers in that order and removes any - * layers as children of the container that aren't in mNewChildLayers. - * @param aTextContentFlags if any child layer has CONTENT_COMPONENT_ALPHA, - * set *aTextContentFlags to CONTENT_COMPONENT_ALPHA - */ - void Finish(uint32_t* aTextContentFlags, - const nsIntRect& aContainerPixelBounds, - nsDisplayList* aChildItems); - - nscoord GetAppUnitsPerDevPixel() { return mAppUnitsPerDevPixel; } - - nsIntRect ScaleToNearestPixels(const nsRect& aRect) const { - return aRect.ScaleToNearestPixels(mParameters.mXScale, mParameters.mYScale, - mAppUnitsPerDevPixel); - } - nsIntRect ScaleToOutsidePixels(const nsRect& aRect, - bool aSnap = false) const { - if (aRect.IsEmpty()) { - return nsIntRect(); - } - if (aSnap && mSnappingEnabled) { - return ScaleToNearestPixels(aRect); - } - return aRect.ScaleToOutsidePixels(mParameters.mXScale, mParameters.mYScale, - mAppUnitsPerDevPixel); - } - nsIntRect ScaleToInsidePixels(const nsRect& aRect, bool aSnap = false) const { - if (aSnap && mSnappingEnabled) { - return ScaleToNearestPixels(aRect); - } - return aRect.ScaleToInsidePixels(mParameters.mXScale, mParameters.mYScale, - mAppUnitsPerDevPixel); - } - nsIntRegion ScaleRegionToNearestPixels(const nsRegion& aRegion) const { - return aRegion.ScaleToNearestPixels( - mParameters.mXScale, mParameters.mYScale, mAppUnitsPerDevPixel); - } - nsIntRegion ScaleRegionToInsidePixels(const nsRegion& aRegion, - bool aSnap = false) const { - if (aSnap && mSnappingEnabled) { - return ScaleRegionToNearestPixels(aRegion); - } - return aRegion.ScaleToInsidePixels(mParameters.mXScale, mParameters.mYScale, - mAppUnitsPerDevPixel); - } - - nsIntRegion ScaleRegionToOutsidePixels(const nsRegion& aRegion, - bool aSnap = false) const { - if (aRegion.IsEmpty()) { - return nsIntRegion(); - } - if (aSnap && mSnappingEnabled) { - return ScaleRegionToNearestPixels(aRegion); - } - return aRegion.ScaleToOutsidePixels( - mParameters.mXScale, mParameters.mYScale, mAppUnitsPerDevPixel); - } - - nsIFrame* GetContainerFrame() const { return mContainerFrame; } - nsDisplayListBuilder* Builder() const { return mBuilder; } - FrameLayerBuilder* LayerBuilder() const { return mLayerBuilder; } - - /** - * Check if we are currently inside an inactive layer. - */ - bool IsInInactiveLayer() const { - return mLayerBuilder->GetContainingPaintedLayerData(); - } - - /** - * Sets aOuterVisibleRegion as aLayer's visible region. - * @param aOuterVisibleRegion - * is in the coordinate space of the container reference frame. - * @param aLayerContentsVisibleRect, if non-null, is in the layer's own - * coordinate system. - * @param aOuterUntransformed is true if the given aOuterVisibleRegion - * is already untransformed with the matrix of the layer. - */ - void SetOuterVisibleRegionForLayer( - Layer* aLayer, const nsIntRegion& aOuterVisibleRegion, - const nsIntRect* aLayerContentsVisibleRect = nullptr, - bool aOuterUntransformed = false) const; - - /** - * Try to determine whether the PaintedLayer aData has a single opaque color - * covering aRect. If successful, return that color, otherwise return - * NS_RGBA(0,0,0,0). - * If aRect turns out not to intersect any content in the layer, - * *aOutIntersectsLayer will be set to false. - */ - nscolor FindOpaqueBackgroundColorInLayer(const PaintedLayerData* aData, - const nsIntRect& aRect, - bool* aOutIntersectsLayer) const; - - /** - * Indicate that we are done adding items to the PaintedLayer represented by - * aData. Make sure that a real PaintedLayer exists for it, and set the final - * visible region and opaque-content. - */ - template <typename FindOpaqueBackgroundColorCallbackType> - void FinishPaintedLayerData( - PaintedLayerData& aData, - FindOpaqueBackgroundColorCallbackType aFindOpaqueBackgroundColor); - - protected: - friend class PaintedLayerData; - friend class FLBDisplayListIterator; - - LayerManager::PaintedLayerCreationHint GetLayerCreationHint( - AnimatedGeometryRoot* aAnimatedGeometryRoot); - - /** - * Creates a new PaintedLayer and sets up the transform on the PaintedLayer - * to account for scrolling. - */ - already_AddRefed<PaintedLayer> CreatePaintedLayer(PaintedLayerData* aData); - - /** - * Find a PaintedLayer for recycling, recycle it and prepare it for use, or - * return null if no suitable layer was found. - */ - already_AddRefed<PaintedLayer> AttemptToRecyclePaintedLayer( - AnimatedGeometryRoot* aAnimatedGeometryRoot, nsDisplayItem* aItem, - const nsPoint& aTopLeft, const nsIFrame* aReferenceFrame); - /** - * Recycle aLayer and do any necessary invalidation. - */ - PaintedDisplayItemLayerUserData* RecyclePaintedLayer( - PaintedLayer* aLayer, AnimatedGeometryRoot* aAnimatedGeometryRoot, - bool& didResetScrollPositionForLayerPixelAlignment); - - /** - * Perform the last step of CreatePaintedLayer / AttemptToRecyclePaintedLayer: - * Initialize aData, set up the layer's transform for scrolling, and - * invalidate the layer for layer pixel alignment changes if necessary. - */ - void PreparePaintedLayerForUse( - PaintedLayer* aLayer, PaintedDisplayItemLayerUserData* aData, - AnimatedGeometryRoot* aAnimatedGeometryRoot, - const nsIFrame* aReferenceFrame, const nsPoint& aTopLeft, - bool aDidResetScrollPositionForLayerPixelAlignment); - - /** - * Attempt to prepare an ImageLayer based upon the provided PaintedLayerData. - * Returns nullptr on failure. - */ - already_AddRefed<Layer> PrepareImageLayer(PaintedLayerData* aData); - - /** - * Attempt to prepare a ColorLayer based upon the provided PaintedLayerData. - * Returns nullptr on failure. - */ - already_AddRefed<Layer> PrepareColorLayer(PaintedLayerData* aData); - - /** - * Grab the next recyclable ColorLayer, or create one if there are no - * more recyclable ColorLayers. - */ - already_AddRefed<ColorLayer> CreateOrRecycleColorLayer( - PaintedLayer* aPainted); - /** - * Grab the next recyclable ImageLayer, or create one if there are no - * more recyclable ImageLayers. - */ - already_AddRefed<ImageLayer> CreateOrRecycleImageLayer( - PaintedLayer* aPainted); - /** - * Grab a recyclable ImageLayer for use as a mask layer for aLayer (that is a - * mask layer which has been used for aLayer before), or create one if such - * a layer doesn't exist. - * - * Since mask layers can exist either on the layer directly, or as a side- - * attachment to FrameMetrics (for ancestor scrollframe clips), we key the - * recycle operation on both the originating layer and the mask layer's - * index in the layer, if any. - */ - struct MaskLayerKey; - template <typename UserData> - already_AddRefed<ImageLayer> CreateOrRecycleMaskImageLayerFor( - const MaskLayerKey& aKey, UserData* (*aGetUserData)(Layer* aLayer), - void (*aSetDefaultUserData)(Layer* aLayer)); - /** - * Grabs all PaintedLayers and ColorLayers from the ContainerLayer and makes - * them available for recycling. - */ - void CollectOldLayers(); - /** - * If aItem used to belong to a PaintedLayer, invalidates the area of - * aItem in that layer. If aNewLayer is a PaintedLayer, invalidates the area - * of aItem in that layer. - */ - void InvalidateForLayerChange(nsDisplayItem* aItem, PaintedLayer* aNewLayer, - DisplayItemData* aData); - /** - * Returns true if aItem's opaque area (in aOpaque) covers the entire - * scrollable area of its presshell. - */ - bool ItemCoversScrollableArea(nsDisplayItem* aItem, const nsRegion& aOpaque); - - /** - * Set ScrollMetadata and scroll-induced clipping on aEntry's layer. - */ - void SetupScrollingMetadata(NewLayerEntry* aEntry); - - /** - * Applies occlusion culling. - * For each layer in mNewChildLayers, remove from its visible region the - * opaque regions of the layers at higher z-index, but only if they have - * the same animated geometry root and fixed-pos frame ancestor. - * The opaque region for the child layers that share the same animated - * geometry root as the container frame is returned in - * *aOpaqueRegionForContainer. - * - * Also sets scroll metadata on the layers. - */ - void PostprocessRetainedLayers(nsIntRegion* aOpaqueRegionForContainer); - - /** - * Computes the snapped opaque area of aItem. Sets aList's opaque flag - * if it covers the entire list bounds. Sets *aHideAllLayersBelow to true - * this item covers the entire viewport so that all layers below are - * permanently invisible. - */ - nsIntRegion ComputeOpaqueRect(nsDisplayItem* aItem, - AnimatedGeometryRoot* aAnimatedGeometryRoot, - const ActiveScrolledRoot* aASR, - const DisplayItemClip& aClip, - nsDisplayList* aList, bool* aHideAllLayersBelow, - bool* aOpaqueForAnimatedGeometryRootParent); - - /** - * Fills a PaintedLayerData object that is initialized for a layer that the - * current item will be assigned to. Also creates mNewChildLayers entries. - * @param aData The PaintedLayerData that will be filled. - * @param aVisibleRect The visible rect of the item. - * @param aAnimatedGeometryRoot The item's animated geometry root. - * @param aASR The active scrolled root that moves this - * PaintedLayer. - * @param aClipChain The clip chain that the compositor needs to - * apply to this layer. - * @param aScrollMetadataASR The leaf ASR for which scroll metadata needs - * to be set on the layer, because either the layer itself or its scrolled - * clip need to move with that ASR. - * @param aTopLeft The offset between aAnimatedGeometryRoot and - * the reference frame. - * @param aReferenceFrame The reference frame for the item. - * @param aBackfaceHidden The backface visibility for the item frame. - */ - void NewPaintedLayerData( - PaintedLayerData* aData, AnimatedGeometryRoot* aAnimatedGeometryRoot, - const ActiveScrolledRoot* aASR, const DisplayItemClipChain* aClipChain, - const ActiveScrolledRoot* aScrollMetadataASR, const nsPoint& aTopLeft, - const nsIFrame* aReferenceFrame, const bool aBackfaceHidden); - - /* Build a mask layer to represent the clipping region. Will return null if - * there is no clipping specified or a mask layer cannot be built. - * Builds an ImageLayer for the appropriate backend; the mask is relative to - * aLayer's visible region. - * aLayer is the layer to be clipped. - * relative to the container reference frame - * aRoundedRectClipCount is used when building mask layers for PaintedLayers, - */ - void SetupMaskLayer(Layer* aLayer, const DisplayItemClip& aClip); - - /** - * If |aClip| has rounded corners, create a mask layer for them, and - * add it to |aLayer|'s ancestor mask layers, returning an index into - * the array of ancestor mask layers. Returns an empty Maybe if - * |aClip| does not have rounded corners, or if no mask layer could - * be created. - */ - Maybe<size_t> SetupMaskLayerForScrolledClip(Layer* aLayer, - const DisplayItemClip& aClip); - - /** - * Create/find a mask layer with suitable size for aMaskItem to paint - * css-positioned-masking onto. - */ - void SetupMaskLayerForCSSMask(Layer* aLayer, - nsDisplayMasksAndClipPaths* aMaskItem); - - already_AddRefed<Layer> CreateMaskLayer( - Layer* aLayer, const DisplayItemClip& aClip, - const Maybe<size_t>& aForAncestorMaskLayer); - - /** - * Get the display port for an AGR. - * The result would be cached for later reusing. - */ - nsRect GetDisplayPortForAnimatedGeometryRoot( - AnimatedGeometryRoot* aAnimatedGeometryRoot); - - nsDisplayListBuilder* mBuilder; - LayerManager* mManager; - FrameLayerBuilder* mLayerBuilder; - nsIFrame* mContainerFrame; - nsIFrame* mContainerReferenceFrame; - AnimatedGeometryRoot* mContainerAnimatedGeometryRoot; - ContainerLayer* mContainerLayer; - nsRect mContainerBounds; - - // Due to the way we store scroll annotations in the layer tree, we need to - // keep track of three (possibly different) ASRs here. - // mContainerASR is the ASR of the container display item that this - // ContainerState was created for. - // mContainerScrollMetadataASR is the ASR of the leafmost scroll metadata - // that's in effect on mContainerLayer. - // mContainerCompositorASR is the ASR that mContainerLayer moves with on - // the compositor / APZ side, taking into account both the scroll meta data - // and the fixed position annotation on itself and its ancestors. - const ActiveScrolledRoot* mContainerASR; - const ActiveScrolledRoot* mContainerScrollMetadataASR; - const ActiveScrolledRoot* mContainerCompositorASR; -#ifdef DEBUG - nsRect mAccumulatedChildBounds; -#endif - ContainerLayerParameters mParameters; - /** - * The region of PaintedLayers that should be invalidated every time - * we recycle one. - */ - nsIntRegion mInvalidPaintedContent; - PaintedLayerDataTree mPaintedLayerDataTree; - /** - * We collect the list of children in here. During ProcessDisplayItems, - * the layers in this array either have mContainerLayer as their parent, - * or no parent. - * PaintedLayers have two entries in this array: the second one is used only - * if the PaintedLayer is optimized away to a ColorLayer or ImageLayer. It's - * essential that this array is only appended to, since PaintedLayerData - * records the index of its PaintedLayer in this array. - */ - typedef AutoTArray<NewLayerEntry, 1> AutoLayersArray; - AutoLayersArray mNewChildLayers; - nsTHashSet<RefPtr<PaintedLayer>> mPaintedLayersAvailableForRecycling; - nscoord mAppUnitsPerDevPixel; - bool mSnappingEnabled; - - struct MaskLayerKey { - MaskLayerKey() : mLayer(nullptr) {} - MaskLayerKey(Layer* aLayer, const Maybe<size_t>& aAncestorIndex) - : mLayer(aLayer), mAncestorIndex(aAncestorIndex) {} - - PLDHashNumber Hash() const { - // Hash the layer and add the layer index to the hash. - return (NS_PTR_TO_UINT32(mLayer) >> 2) + - (mAncestorIndex ? (*mAncestorIndex + 1) : 0); - } - bool operator==(const MaskLayerKey& aOther) const { - return mLayer == aOther.mLayer && mAncestorIndex == aOther.mAncestorIndex; - } - - Layer* mLayer; - Maybe<size_t> mAncestorIndex; - }; - - nsTHashMap<nsGenericHashKey<MaskLayerKey>, RefPtr<ImageLayer>> - mRecycledMaskImageLayers; - // Keep display port of AGR to avoid wasting time on doing the same - // thing repeatly. - AnimatedGeometryRoot* mLastDisplayPortAGR; - nsRect mLastDisplayPortRect; - - nsDisplayItem* mContainerItem; - - // Cache ScrollMetadata so it doesn't need recomputed if the ASR and clip are - // unchanged. If mASR == nullptr then mMetadata is not valid. - struct CachedScrollMetadata { - const ActiveScrolledRoot* mASR; - const DisplayItemClip* mClip; - Maybe<ScrollMetadata> mMetadata; - - CachedScrollMetadata() : mASR(nullptr), mClip(nullptr) {} - }; - CachedScrollMetadata mCachedScrollMetadata; -}; - -class FLBDisplayListIterator : public FlattenedDisplayListIterator { - public: - FLBDisplayListIterator(nsDisplayListBuilder* aBuilder, nsDisplayList* aList, - ContainerState* aState) - : FlattenedDisplayListIterator(aBuilder, aList, false), mState(aState) { - MOZ_ASSERT(mState); - ResolveFlattening(); - } - - DisplayItemEntry GetNextEntry() { - if (!mMarkers.empty()) { - DisplayItemEntry entry = mMarkers.front(); - mMarkers.pop_front(); - return entry; - } - - return DisplayItemEntry{GetNextItem(), DisplayItemEntryType::Item}; - } - - bool HasNext() const override { - return FlattenedDisplayListIterator::HasNext() || !mMarkers.empty(); - } - - private: - bool ShouldFlattenNextItem() override { - if (!FlattenedDisplayListIterator::ShouldFlattenNextItem()) { - return false; - } - - nsDisplayItem* next = PeekNext(); - const DisplayItemType type = next->GetType(); - if (type == DisplayItemType::TYPE_SVG_WRAPPER) { - // We mark SetContainsSVG for the CONTENT_FRAME_TIME_WITH_SVG metric - if (RefPtr<LayerManager> lm = mState->mBuilder->GetWidgetLayerManager()) { - lm->SetContainsSVG(true); - } - } - - if (!SupportsFlatteningWithMarkers(type)) { - return true; - } - - if (type == DisplayItemType::TYPE_OPACITY && - IsOpacityAppliedToChildren(next)) { - // This is the previous opacity flattening path, where the opacity has - // been applied to children. - return true; - } - - if (mState->IsInInactiveLayer() || !ItemWantsInactiveLayer(next)) { - // Do not flatten nested inactive display items, or display items that - // want an active layer. - return false; - } - - // If we reach here, we will emit an effect start marker for - // nsDisplayTransform or nsDisplayOpacity. - MOZ_ASSERT(type == DisplayItemType::TYPE_TRANSFORM || - !IsOpacityAppliedToChildren(next)); - return true; - } - - void EnterChildList(nsDisplayItem* aContainerItem) override { - mFlattenedLists.AppendElement(aContainerItem); - AddMarkerIfNeeded<MarkerType::StartMarker>(aContainerItem, mMarkers); - } - - void ExitChildList() override { - MOZ_ASSERT(!mFlattenedLists.IsEmpty()); - nsDisplayItem* aContainerItem = mFlattenedLists.PopLastElement(); - AddMarkerIfNeeded<MarkerType::EndMarker>(aContainerItem, mMarkers); - } - - bool ItemWantsInactiveLayer(nsDisplayItem* aItem) { - const LayerState layerState = aItem->GetLayerState( - mState->mBuilder, mState->mManager, mState->mParameters); - - return layerState == LayerState::LAYER_INACTIVE; - } - - std::deque<DisplayItemEntry> mMarkers; - AutoTArray<nsDisplayItem*, 16> mFlattenedLists; - ContainerState* mState; -}; - -class PaintedDisplayItemLayerUserData : public LayerUserData { - public: - PaintedDisplayItemLayerUserData() - : mForcedBackgroundColor(NS_RGBA(0, 0, 0, 0)), - mXScale(1.f), - mYScale(1.f), - mAppUnitsPerDevPixel(0), - mTranslation(0, 0), - mAnimatedGeometryRootPosition(0, 0), - mLastItemCount(0), - mContainerLayerFrame(nullptr), - mDisabledAlpha(false) {} - - NS_INLINE_DECL_REFCOUNTING(PaintedDisplayItemLayerUserData); - - /** - * A color that should be painted over the bounds of the layer's visible - * region before any other content is painted. - */ - nscolor mForcedBackgroundColor; - - /** - * The resolution scale used. - */ - float mXScale, mYScale; - - /** - * The appunits per dev pixel for the items in this layer. - */ - nscoord mAppUnitsPerDevPixel; - - /** - * The offset from the PaintedLayer's 0,0 to the - * reference frame. This isn't necessarily the same as the transform - * set on the PaintedLayer since we might also be applying an extra - * offset specified by the parent ContainerLayer/ - */ - nsIntPoint mTranslation; - - /** - * We try to make 0,0 of the PaintedLayer be the top-left of the - * border-box of the "active scrolled root" frame (i.e. the nearest ancestor - * frame for the display items that is being actively scrolled). But - * we force the PaintedLayer transform to be an integer translation, and we - * may have a resolution scale, so we have to snap the PaintedLayer transform, - * so 0,0 may not be exactly the top-left of the active scrolled root. Here we - * store the coordinates in PaintedLayer space of the top-left of the - * active scrolled root. - */ - gfxPoint mAnimatedGeometryRootPosition; - - nsIntRegion mRegionToInvalidate; - - // The offset between the active scrolled root of this layer - // and the root of the container for the previous and current - // paints respectively. - nsPoint mLastAnimatedGeometryRootOrigin; - nsPoint mAnimatedGeometryRootOrigin; - - RefPtr<ColorLayer> mColorLayer; - RefPtr<ImageLayer> mImageLayer; - - // The region for which display item visibility for this layer has already - // been calculated. Used to reduce the number of calls to - // RecomputeVisibilityForItems if it is known in advance that a larger - // region will be painted during a transaction than in a single call to - // DrawPaintedLayer, for example when progressive paint is enabled. - nsIntRegion mVisibilityComputedRegion; - - // The area for which we called RecomputeVisibilityForItems on the - // previous paint. - nsRect mPreviousRecomputeVisibilityRect; - - // The number of items assigned to this layer on the previous paint. - size_t mLastItemCount; - - // The translation set on this PaintedLayer during the previous paint. This - // is needed when invalidating based on a display item's geometry information - // from the previous paint. - Maybe<nsIntPoint> mLastPaintOffset; - - // Temporary state only valid during the FrameLayerBuilder's lifetime. - // FLB's mPaintedLayerItems is responsible for cleaning these up when - // we finish painting to avoid dangling pointers. - std::vector<AssignedDisplayItem> mItems; - nsIFrame* mContainerLayerFrame; - - /** - * This is set when the painted layer has no component alpha. - */ - bool mDisabledAlpha; - - protected: - ~PaintedDisplayItemLayerUserData() override = default; -}; - -FrameLayerBuilder::FrameLayerBuilder() - : mRetainingManager(nullptr), - mDisplayListBuilder(nullptr), - mContainingPaintedLayer(nullptr), - mInactiveLayerClip(nullptr), - mInvalidateAllLayers(false), - mInLayerTreeCompressionMode(false), - mIsInactiveLayerManager(false) { - MOZ_COUNT_CTOR(FrameLayerBuilder); -} - -FrameLayerBuilder::~FrameLayerBuilder() { - GetMaskLayerImageCache()->Sweep(); - for (PaintedDisplayItemLayerUserData* userData : mPaintedLayerItems) { - userData->mLastPaintOffset = Some(userData->mTranslation); - userData->mItems.clear(); - userData->mContainerLayerFrame = nullptr; - } - MOZ_COUNT_DTOR(FrameLayerBuilder); -} - -void FrameLayerBuilder::AddPaintedLayerItemsEntry( - PaintedDisplayItemLayerUserData* aData) { - mPaintedLayerItems.AppendElement(aData); -} - -/* - * User data for layers which will be used as masks. - */ -struct MaskLayerUserData : public LayerUserData { - MaskLayerUserData() - : mScaleX(-1.0f), mScaleY(-1.0f), mAppUnitsPerDevPixel(-1) {} - MaskLayerUserData(const DisplayItemClip& aClip, int32_t aAppUnitsPerDevPixel, - const ContainerLayerParameters& aParams) - : mScaleX(aParams.mXScale), - mScaleY(aParams.mYScale), - mOffset(aParams.mOffset), - mAppUnitsPerDevPixel(aAppUnitsPerDevPixel) { - aClip.AppendRoundedRects(&mRoundedClipRects); - } - - void operator=(MaskLayerUserData&& aOther) { - mScaleX = aOther.mScaleX; - mScaleY = aOther.mScaleY; - mOffset = aOther.mOffset; - mAppUnitsPerDevPixel = aOther.mAppUnitsPerDevPixel; - mRoundedClipRects = std::move(aOther.mRoundedClipRects); - } - - bool operator==(const MaskLayerUserData& aOther) const { - return mRoundedClipRects == aOther.mRoundedClipRects && - mScaleX == aOther.mScaleX && mScaleY == aOther.mScaleY && - mOffset == aOther.mOffset && - mAppUnitsPerDevPixel == aOther.mAppUnitsPerDevPixel; - } - - // Keeps a MaskLayerImageKey alive by managing its mLayerCount member-var - MaskLayerImageCache::MaskLayerImageKeyRef mImageKey; - // properties of the mask layer; the mask layer may be re-used if these - // remain unchanged. - nsTArray<DisplayItemClip::RoundedRect> mRoundedClipRects; - // scale from the masked layer which is applied to the mask - float mScaleX, mScaleY; - // The ContainerLayerParameters offset which is applied to the mask's - // transform. - nsIntPoint mOffset; - int32_t mAppUnitsPerDevPixel; -}; - -/* - * User data for layers which will be used as masks for css positioned mask. - */ -struct CSSMaskLayerUserData : public LayerUserData { - CSSMaskLayerUserData() : mMaskStyle(nsStyleImageLayers::LayerType::Mask) {} - - CSSMaskLayerUserData(nsIFrame* aFrame, const nsIntRect& aMaskBounds, - const nsPoint& aMaskLayerOffset) - : mMaskBounds(aMaskBounds), - mMaskStyle(aFrame->StyleSVGReset()->mMask), - mMaskLayerOffset(aMaskLayerOffset) {} - - void operator=(CSSMaskLayerUserData&& aOther) { - mMaskBounds = aOther.mMaskBounds; - mMaskStyle = std::move(aOther.mMaskStyle); - mMaskLayerOffset = aOther.mMaskLayerOffset; - } - - bool operator==(const CSSMaskLayerUserData& aOther) const { - if (!mMaskBounds.IsEqualInterior(aOther.mMaskBounds)) { - return false; - } - - // Make sure we draw the same portion of the mask onto mask layer. - if (mMaskLayerOffset != aOther.mMaskLayerOffset) { - return false; - } - - return mMaskStyle == aOther.mMaskStyle; - } - - private: - nsIntRect mMaskBounds; - nsStyleImageLayers mMaskStyle; - nsPoint mMaskLayerOffset; // The offset from the origin of mask bounds to - // the origin of mask layer. -}; - -/* - * A helper object to create a draw target for painting mask and create a - * image container to hold the drawing result. The caller can then bind this - * image container with a image mask layer via ImageLayer::SetContainer. - */ -class MaskImageData { - public: - MaskImageData(const gfx::IntSize& aSize, LayerManager* aLayerManager) - : mTextureClientLocked(false), - mSize(aSize), - mLayerManager(aLayerManager) { - MOZ_ASSERT(!mSize.IsEmpty()); - MOZ_ASSERT(mLayerManager); - } - - ~MaskImageData() { - if (mTextureClientLocked) { - MOZ_ASSERT(mTextureClient); - // Clear DrawTarget before Unlock. - mDrawTarget = nullptr; - mTextureClient->Unlock(); - } - } - - gfx::DrawTarget* CreateDrawTarget() { - if (mDrawTarget) { - return mDrawTarget; - } - - if (mLayerManager->GetBackendType() == LayersBackend::LAYERS_BASIC) { - mDrawTarget = mLayerManager->CreateOptimalMaskDrawTarget(mSize); - return mDrawTarget; - } - - MOZ_ASSERT(mLayerManager->GetBackendType() == - LayersBackend::LAYERS_CLIENT || - mLayerManager->GetBackendType() == LayersBackend::LAYERS_WR); - - KnowsCompositor* knowsCompositor = mLayerManager->AsKnowsCompositor(); - if (!knowsCompositor) { - return nullptr; - } - mTextureClient = TextureClient::CreateForDrawing( - knowsCompositor, SurfaceFormat::A8, mSize, BackendSelector::Content, - TextureFlags::DISALLOW_BIGIMAGE, - TextureAllocationFlags::ALLOC_CLEAR_BUFFER); - if (!mTextureClient) { - return nullptr; - } - - mTextureClientLocked = mTextureClient->Lock(OpenMode::OPEN_READ_WRITE); - if (!mTextureClientLocked) { - return nullptr; - } - - mDrawTarget = mTextureClient->BorrowDrawTarget(); - return mDrawTarget; - } - - already_AddRefed<ImageContainer> CreateImageAndImageContainer() { - RefPtr<ImageContainer> container = LayerManager::CreateImageContainer(); - RefPtr<Image> image = CreateImage(); - - if (!image) { - return nullptr; - } - container->SetCurrentImageInTransaction(image); - - return container.forget(); - } - - private: - already_AddRefed<Image> CreateImage() { - if (mLayerManager->GetBackendType() == LayersBackend::LAYERS_BASIC && - mDrawTarget) { - RefPtr<SourceSurface> surface = mDrawTarget->Snapshot(); - RefPtr<SourceSurfaceImage> image = new SourceSurfaceImage(mSize, surface); - // Disallow BIGIMAGE (splitting into multiple textures) for mask - // layer images - image->SetTextureFlags(TextureFlags::DISALLOW_BIGIMAGE); - return image.forget(); - } - - if ((mLayerManager->GetBackendType() == LayersBackend::LAYERS_CLIENT || - mLayerManager->GetBackendType() == LayersBackend::LAYERS_WR) && - mTextureClient && mDrawTarget) { - RefPtr<TextureWrapperImage> image = new TextureWrapperImage( - mTextureClient, gfx::IntRect(gfx::IntPoint(0, 0), mSize)); - return image.forget(); - } - - return nullptr; - } - - bool mTextureClientLocked; - gfx::IntSize mSize; - LayerManager* mLayerManager; - RefPtr<gfx::DrawTarget> mDrawTarget; - RefPtr<TextureClient> mTextureClient; -}; - -/* static */ -void FrameLayerBuilder::Shutdown() { - if (gMaskLayerImageCache) { - delete gMaskLayerImageCache; - gMaskLayerImageCache = nullptr; - } -} - -void FrameLayerBuilder::Init(nsDisplayListBuilder* aBuilder, - LayerManager* aManager, - PaintedLayerData* aLayerData, - bool aIsInactiveLayerManager, - const DisplayItemClip* aInactiveLayerClip) { - mDisplayListBuilder = aBuilder; - mRootPresContext = - aBuilder->RootReferenceFrame()->PresContext()->GetRootPresContext(); - mContainingPaintedLayer = aLayerData; - mIsInactiveLayerManager = aIsInactiveLayerManager; - mInactiveLayerClip = aInactiveLayerClip; - aManager->SetUserData(&gLayerManagerLayerBuilder, this); -} - -void FrameLayerBuilder::FlashPaint(gfxContext* aContext) { - float r = float(rand()) / float(RAND_MAX); - float g = float(rand()) / float(RAND_MAX); - float b = float(rand()) / float(RAND_MAX); - aContext->SetColor(sRGBColor(r, g, b, 0.4f)); - aContext->Paint(); -} - -DisplayItemData* FrameLayerBuilder::GetDisplayItemData(nsIFrame* aFrame, - uint32_t aKey) { - for (auto* did : GetDisplayItemDataArray(aFrame)) { - DisplayItemData* data = DisplayItemData::AssertDisplayItemData(did); - if (data->mDisplayItemKey == aKey && data->FirstFrame() == aFrame && - data->mLayer->Manager() == mRetainingManager) { - return data; - } - } - - return nullptr; -} - -#ifdef MOZ_DUMP_PAINTING -static nsACString& AppendToString(nsACString& s, const nsIntRect& r, - const char* pfx = "", const char* sfx = "") { - s += pfx; - s += nsPrintfCString("(x=%d, y=%d, w=%d, h=%d)", r.x, r.y, r.width, r.height); - return s += sfx; -} - -static nsACString& AppendToString(nsACString& s, const nsIntRegion& r, - const char* pfx = "", const char* sfx = "") { - s += pfx; - - s += "< "; - for (auto iter = r.RectIter(); !iter.Done(); iter.Next()) { - AppendToString(s, iter.Get()) += "; "; - } - s += ">"; - - return s += sfx; -} -#endif // MOZ_DUMP_PAINTING - -/** - * Invalidate aRegion in aLayer. aLayer is in the coordinate system - * *after* aTranslation has been applied, so we need to - * apply the inverse of that transform before calling InvalidateRegion. - */ -static void InvalidatePostTransformRegion(PaintedLayer* aLayer, - const nsIntRegion& aRegion, - const nsIntPoint& aTranslation) { - // Convert the region from the coordinates of the container layer - // (relative to the snapped top-left of the display list reference frame) - // to the PaintedLayer's own coordinates - nsIntRegion rgn = aRegion; - - rgn.MoveBy(-aTranslation); - aLayer->InvalidateRegion(rgn); -#ifdef MOZ_DUMP_PAINTING - if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { - nsAutoCString str; - AppendToString(str, rgn); - printf_stderr("Invalidating layer %p: %s\n", aLayer, str.get()); - } -#endif -} - -static PaintedDisplayItemLayerUserData* GetPaintedDisplayItemLayerUserData( - Layer* aLayer) { - return static_cast<PaintedDisplayItemLayerUserData*>( - aLayer->GetUserData(&gPaintedDisplayItemLayerUserData)); -} - -static nsIntPoint GetTranslationForPaintedLayer(PaintedLayer* aLayer) { - PaintedDisplayItemLayerUserData* layerData = - GetPaintedDisplayItemLayerUserData(aLayer); - NS_ASSERTION(layerData, "Must be a tracked painted layer!"); - - return layerData->mTranslation; -} - -/** - * Get the translation transform that was in aLayer when we last painted. It's - * either the transform saved by ~FrameLayerBuilder(), or else the transform - * that's currently in the layer (which must be an integer translation). - */ -static nsIntPoint GetLastPaintOffset(PaintedLayer* aLayer) { - auto* layerData = GetPaintedDisplayItemLayerUserData(aLayer); - MOZ_ASSERT(layerData); - return layerData->mLastPaintOffset.valueOr(layerData->mTranslation); -} - -static void InvalidatePreTransformRect(PaintedLayer* aLayer, - const nsRect& aRect, - const DisplayItemClip& aClip, - const nsIntPoint& aTranslation, - TransformClipNode* aTransform) { - auto* data = GetPaintedDisplayItemLayerUserData(aLayer); - - nsRect rect = aClip.ApplyNonRoundedIntersection(aRect); - - if (aTransform) { - rect = aTransform->TransformRect(rect, data->mAppUnitsPerDevPixel); - } - - nsIntRect pixelRect = rect.ScaleToOutsidePixels(data->mXScale, data->mYScale, - data->mAppUnitsPerDevPixel); - - InvalidatePostTransformRegion(aLayer, pixelRect, aTranslation); -} - -/** - * Some frames can have multiple, nested, retaining layer managers - * associated with them (normal manager, inactive managers, SVG effects). - * In these cases we store the 'outermost' LayerManager data property - * on the frame since we can walk down the chain from there. - * - * If one of these frames has just been destroyed, we will free the inner - * layer manager when removing the entry from mFramesWithLayers. Destroying - * the layer manager destroys the LayerManagerData and calls into - * the DisplayItemData destructor. If the inner layer manager had any - * items with the same frame, then we attempt to retrieve properties - * from the deleted frame. - * - * Cache the destroyed frame pointer here so we can avoid crashing in this case. - */ - -/* static */ -void FrameLayerBuilder::RemoveFrameFromLayerManager(nsIFrame* aFrame) { - MOZ_RELEASE_ASSERT(!sDestroyedFrame); - sDestroyedFrame = aFrame; - - SmallPointerArray<DisplayItemData>* array = - aFrame->TakeProperty(nsIFrame::DisplayItemDataProperty()); - - // Hold a reference to all the items so that they don't get - // deleted from under us. - nsTArray<RefPtr<DisplayItemData>> arrayCopy; - - if (array) { - for (DisplayItemData* data : *array) { - arrayCopy.AppendElement(data); - } - } - -#ifdef DEBUG_DISPLAY_ITEM_DATA - if (array && array->Length()) { - LayerManagerData* rootData = array->ElementAt(0)->mParent; - while (rootData->mParent) { - rootData = rootData->mParent; - } - printf_stderr("Removing frame %p - dumping display data\n", aFrame); - rootData->Dump(); - } -#endif - - for (DisplayItemData* data : arrayCopy) { - PaintedLayer* t = data->mLayer ? data->mLayer->AsPaintedLayer() : nullptr; - if (t) { - auto* paintedData = GetPaintedDisplayItemLayerUserData(t); - if (paintedData && data->mGeometry) { - const int32_t appUnitsPerDevPixel = paintedData->mAppUnitsPerDevPixel; - nsRegion rgn = data->mGeometry->ComputeInvalidationRegion(); - nsIntRegion pixelRgn = rgn.ToOutsidePixels(appUnitsPerDevPixel); - - if (data->mTransform) { - pixelRgn = data->mTransform->TransformRegion(pixelRgn); - } - - pixelRgn = - pixelRgn.ScaleRoundOut(paintedData->mXScale, paintedData->mYScale); - - pixelRgn.MoveBy(-GetTranslationForPaintedLayer(t)); - - paintedData->mRegionToInvalidate.Or(paintedData->mRegionToInvalidate, - pixelRgn); - paintedData->mRegionToInvalidate.SimplifyOutward(8); - } - } - - auto it = std::find(data->mParent->mDisplayItems.begin(), - data->mParent->mDisplayItems.end(), data); - MOZ_ASSERT(it != data->mParent->mDisplayItems.end()); - std::iter_swap(it, data->mParent->mDisplayItems.end() - 1); - data->mParent->mDisplayItems.pop_back(); - } - - if (aFrame->IsSubDocumentFrame()) { - const nsSubDocumentFrame* subdoc = - static_cast<const nsSubDocumentFrame*>(aFrame); - nsFrameLoader* frameLoader = subdoc->FrameLoader(); - if (frameLoader && frameLoader->GetRemoteBrowser()) { - // This is a remote browser that is going away, notify it that it is now - // hidden - frameLoader->GetRemoteBrowser()->UpdateEffects( - mozilla::dom::EffectsInfo::FullyHidden()); - } - } - - arrayCopy.Clear(); - delete array; - sDestroyedFrame = nullptr; -} - -void FrameLayerBuilder::DidBeginRetainedLayerTransaction( - LayerManager* aManager) { - mRetainingManager = aManager; - LayerManagerData* data = static_cast<LayerManagerData*>( - aManager->GetUserData(&gLayerManagerUserData)); - if (data) { - mInvalidateAllLayers = data->mInvalidateAllLayers; - } else { - data = new LayerManagerData(aManager); - aManager->SetUserData(&gLayerManagerUserData, data); - } -} - -void FrameLayerBuilder::DidEndTransaction() { - GetMaskLayerImageCache()->Sweep(); -} - -void FrameLayerBuilder::WillEndTransaction() { - if (!mRetainingManager) { - return; - } - - // We need to save the data we'll need to support retaining. - LayerManagerData* data = static_cast<LayerManagerData*>( - mRetainingManager->GetUserData(&gLayerManagerUserData)); - NS_ASSERTION(data, "Must have data!"); - - // Update all the frames that used to have layers. - auto iter = data->mDisplayItems.begin(); - while (iter != data->mDisplayItems.end()) { - DisplayItemData* did = iter->get(); - if (!did->mUsed) { - // This item was visible, but isn't anymore. - PaintedLayer* t = did->mLayer->AsPaintedLayer(); - if (t && did->mGeometry) { -#ifdef MOZ_DUMP_PAINTING - if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { - printf_stderr( - "Invalidating unused display item (%i) belonging to " - "frame %p from layer %p\n", - did->mDisplayItemKey, did->mFrameList[0], t); - } -#endif - InvalidatePreTransformRect( - t, did->mGeometry->ComputeInvalidationRegion(), did->mClip, - GetLastPaintOffset(t), did->mTransform); - } - - did->NotifyRemoved(); - - // Remove this item. Swapping it with the last element first is - // quicker than erasing from the middle. - if (iter != data->mDisplayItems.end() - 1) { - std::iter_swap(iter, data->mDisplayItems.end() - 1); - data->mDisplayItems.pop_back(); - } else { - data->mDisplayItems.pop_back(); - break; - } - - // Don't increment iter because we still need to process the item which - // was moved. - - } else { - ComputeGeometryChangeForItem(did); - iter++; - } - } - - data->mInvalidateAllLayers = false; -} - -/* static */ -DisplayItemData* FrameLayerBuilder::GetDisplayItemDataForManager( - nsPaintedDisplayItem* aItem, LayerManager* aManager) { - for (auto* did : GetDisplayItemDataArray(aItem->Frame())) { - DisplayItemData* data = DisplayItemData::AssertDisplayItemData(did); - if (data->mDisplayItemKey == aItem->GetPerFrameKey() && - data->mLayer->Manager() == aManager) { - return data; - } - } - - return nullptr; -} - -bool FrameLayerBuilder::HasRetainedDataFor(const nsIFrame* aFrame, - uint32_t aDisplayItemKey) { - for (auto* did : GetDisplayItemDataArray(aFrame)) { - DisplayItemData* data = DisplayItemData::AssertDisplayItemData(did); - if (data->mDisplayItemKey == aDisplayItemKey) { - return true; - } - } - - if (RefPtr<WebRenderUserData> data = - GetWebRenderUserData<WebRenderFallbackData>(aFrame, - aDisplayItemKey)) { - return true; - } - - return false; -} - -DisplayItemData* FrameLayerBuilder::GetOldLayerForFrame( - nsIFrame* aFrame, uint32_t aDisplayItemKey, - DisplayItemData* aOldData, /* = nullptr */ - LayerManager* aOldLayerManager /* = nullptr */) { - // If we need to build a new layer tree, then just refuse to recycle - // anything. - if (!mRetainingManager || mInvalidateAllLayers) { - return nullptr; - } - - MOZ_ASSERT(!aOldData || aOldLayerManager, - "You must provide aOldLayerManager to check aOldData's validity."); - MOZ_ASSERT_IF(aOldData, aOldLayerManager == aOldData->mLayer->Manager()); - - DisplayItemData* data = aOldData; - if (!data || aOldLayerManager != mRetainingManager) { - data = GetDisplayItemData(aFrame, aDisplayItemKey); - } - - MOZ_ASSERT(data == GetDisplayItemData(aFrame, aDisplayItemKey)); - - return data; -} - -Layer* FrameLayerBuilder::GetOldLayerFor(nsDisplayItem* aItem, - nsDisplayItemGeometry** aOldGeometry, - DisplayItemClip** aOldClip) { - uint32_t key = aItem->GetPerFrameKey(); - nsIFrame* frame = aItem->Frame(); - - DisplayItemData* oldData = GetOldLayerForFrame(frame, key); - if (oldData) { - if (aOldGeometry) { - *aOldGeometry = oldData->mGeometry.get(); - } - if (aOldClip) { - *aOldClip = &oldData->mClip; - } - return oldData->mLayer; - } - - return nullptr; -} - -/* static */ -DisplayItemData* FrameLayerBuilder::GetOldDataFor(nsDisplayItem* aItem) { - for (auto* did : GetDisplayItemDataArray(aItem->Frame())) { - DisplayItemData* data = DisplayItemData::AssertDisplayItemData(did); - if (data->mDisplayItemKey == aItem->GetPerFrameKey()) { - return data; - } - } - - return nullptr; -} - -// Reset state that should not persist when a layer is recycled. -static void ResetLayerStateForRecycling(Layer* aLayer) { - // Currently, this clears the mask layer and ancestor mask layers. - // Other cleanup may be added here. - aLayer->SetMaskLayer(nullptr); - aLayer->SetAncestorMaskLayers({}); -} - -already_AddRefed<ColorLayer> ContainerState::CreateOrRecycleColorLayer( - PaintedLayer* aPainted) { - auto* data = GetPaintedDisplayItemLayerUserData(aPainted); - RefPtr<ColorLayer> layer = data->mColorLayer; - if (layer) { - ResetLayerStateForRecycling(layer); - layer->ClearExtraDumpInfo(); - } else { - // Create a new layer - layer = mManager->CreateColorLayer(); - if (!layer) { - return nullptr; - } - // Mark this layer as being used for painting display items - data->mColorLayer = layer; - layer->SetUserData(&gColorLayerUserData, nullptr); - - // Remove other layer types we might have stored for this PaintedLayer - data->mImageLayer = nullptr; - } - return layer.forget(); -} - -already_AddRefed<ImageLayer> ContainerState::CreateOrRecycleImageLayer( - PaintedLayer* aPainted) { - auto* data = GetPaintedDisplayItemLayerUserData(aPainted); - RefPtr<ImageLayer> layer = data->mImageLayer; - if (layer) { - ResetLayerStateForRecycling(layer); - layer->ClearExtraDumpInfo(); - } else { - // Create a new layer - layer = mManager->CreateImageLayer(); - if (!layer) { - return nullptr; - } - // Mark this layer as being used for painting display items - data->mImageLayer = layer; - layer->SetUserData(&gImageLayerUserData, nullptr); - - // Remove other layer types we might have stored for this PaintedLayer - data->mColorLayer = nullptr; - } - return layer.forget(); -} - -template <typename UserData> -already_AddRefed<ImageLayer> ContainerState::CreateOrRecycleMaskImageLayerFor( - const MaskLayerKey& aKey, UserData* (*aGetUserData)(Layer* aLayer), - void (*aSetDefaultUserData)(Layer* aLayer)) { - RefPtr<ImageLayer> result = mRecycledMaskImageLayers.Get(aKey); - - if (result && aGetUserData(result.get())) { - mRecycledMaskImageLayers.Remove(aKey); - aKey.mLayer->ClearExtraDumpInfo(); - // XXX if we use clip on mask layers, null it out here - } else { - // Create a new layer - result = mManager->CreateImageLayer(); - if (!result) { - return nullptr; - } - aSetDefaultUserData(result); - } - - return result.forget(); -} - -static const double SUBPIXEL_OFFSET_EPSILON = 0.02; - -/** - * This normally computes NSToIntRoundUp(aValue). However, if that would - * give a residual near 0.5 while aOldResidual is near -0.5, or - * it would give a residual near -0.5 while aOldResidual is near 0.5, then - * instead we return the integer in the other direction so that the residual - * is close to aOldResidual. - */ -static int32_t RoundToMatchResidual(double aValue, double aOldResidual) { - int32_t v = NSToIntRoundUp(aValue); - double residual = aValue - v; - if (aOldResidual < 0) { - if (residual > 0 && - fabs(residual - 1.0 - aOldResidual) < SUBPIXEL_OFFSET_EPSILON) { - // Round up instead - return int32_t(ceil(aValue)); - } - } else if (aOldResidual > 0) { - if (residual < 0 && - fabs(residual + 1.0 - aOldResidual) < SUBPIXEL_OFFSET_EPSILON) { - // Round down instead - return int32_t(floor(aValue)); - } - } - return v; -} - -static void ResetScrollPositionForLayerPixelAlignment( - AnimatedGeometryRoot* aAnimatedGeometryRoot) { - nsIScrollableFrame* sf = - nsLayoutUtils::GetScrollableFrameFor(*aAnimatedGeometryRoot); - if (sf) { - sf->ResetScrollPositionForLayerPixelAlignment(); - } -} - -static void InvalidateEntirePaintedLayer( - PaintedLayer* aLayer, AnimatedGeometryRoot* aAnimatedGeometryRoot, - const char* aReason) { -#ifdef MOZ_DUMP_PAINTING - if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { - printf_stderr("Invalidating entire layer %p: %s\n", aLayer, aReason); - } -#endif - aLayer->InvalidateWholeLayer(); - aLayer->SetInvalidRectToVisibleRegion(); - ResetScrollPositionForLayerPixelAlignment(aAnimatedGeometryRoot); -} - -LayerManager::PaintedLayerCreationHint ContainerState::GetLayerCreationHint( - AnimatedGeometryRoot* aAnimatedGeometryRoot) { - // Check whether the layer will be scrollable. This is used as a hint to - // influence whether tiled layers are used or not. - - // Check creation hint inherited from our parent. - if (mParameters.mLayerCreationHint == LayerManager::SCROLLABLE) { - return LayerManager::SCROLLABLE; - } - - // Check whether there's any active scroll frame on the animated geometry - // root chain. - for (AnimatedGeometryRoot* agr = aAnimatedGeometryRoot; - agr && agr != mContainerAnimatedGeometryRoot; agr = agr->mParentAGR) { - nsIFrame* fParent = nsLayoutUtils::GetCrossDocParentFrameInProcess(*agr); - if (!fParent) { - break; - } - nsIScrollableFrame* scrollable = do_QueryFrame(fParent); - if (scrollable) { - return LayerManager::SCROLLABLE; - } - } - return LayerManager::NONE; -} - -already_AddRefed<PaintedLayer> ContainerState::AttemptToRecyclePaintedLayer( - AnimatedGeometryRoot* aAnimatedGeometryRoot, nsDisplayItem* aItem, - const nsPoint& aTopLeft, const nsIFrame* aReferenceFrame) { - Layer* oldLayer = mLayerBuilder->GetOldLayerFor(aItem); - if (!oldLayer || !oldLayer->AsPaintedLayer()) { - return nullptr; - } - - if (!mPaintedLayersAvailableForRecycling.EnsureRemoved( - oldLayer->AsPaintedLayer())) { - // Not found. - return nullptr; - } - - // Try to recycle the layer. - RefPtr<PaintedLayer> layer = oldLayer->AsPaintedLayer(); - - // Check if the layer hint has changed and whether or not the layer should - // be recreated because of it. - if (!layer->IsOptimizedFor(GetLayerCreationHint(aAnimatedGeometryRoot))) { - return nullptr; - } - - bool didResetScrollPositionForLayerPixelAlignment = false; - PaintedDisplayItemLayerUserData* data = - RecyclePaintedLayer(layer, aAnimatedGeometryRoot, - didResetScrollPositionForLayerPixelAlignment); - PreparePaintedLayerForUse(layer, data, aAnimatedGeometryRoot, aReferenceFrame, - aTopLeft, - didResetScrollPositionForLayerPixelAlignment); - - return layer.forget(); -} - -static void ReleaseLayerUserData(void* aData) { - PaintedDisplayItemLayerUserData* userData = - static_cast<PaintedDisplayItemLayerUserData*>(aData); - userData->Release(); -} - -already_AddRefed<PaintedLayer> ContainerState::CreatePaintedLayer( - PaintedLayerData* aData) { - LayerManager::PaintedLayerCreationHint creationHint = - GetLayerCreationHint(aData->mAnimatedGeometryRoot); - - // Create a new painted layer - RefPtr<PaintedLayer> layer = - mManager->CreatePaintedLayerWithHint(creationHint); - if (!layer) { - return nullptr; - } - - // Mark this layer as being used for painting display items - RefPtr<PaintedDisplayItemLayerUserData> userData = - new PaintedDisplayItemLayerUserData(); - userData->mDisabledAlpha = - mParameters.mDisableSubpixelAntialiasingInDescendants; - userData.get()->AddRef(); - layer->SetUserData(&gPaintedDisplayItemLayerUserData, userData, - ReleaseLayerUserData); - ResetScrollPositionForLayerPixelAlignment(aData->mAnimatedGeometryRoot); - - PreparePaintedLayerForUse(layer, userData, aData->mAnimatedGeometryRoot, - aData->mReferenceFrame, - aData->mAnimatedGeometryRootOffset, true); - - return layer.forget(); -} - -PaintedDisplayItemLayerUserData* ContainerState::RecyclePaintedLayer( - PaintedLayer* aLayer, AnimatedGeometryRoot* aAnimatedGeometryRoot, - bool& didResetScrollPositionForLayerPixelAlignment) { - // Clear clip rect and mask layer so we don't accidentally stay clipped. - // We will reapply any necessary clipping. - ResetLayerStateForRecycling(aLayer); - aLayer->ClearExtraDumpInfo(); - - auto* data = GetPaintedDisplayItemLayerUserData(aLayer); - NS_ASSERTION(data, "Recycled PaintedLayers must have user data"); - - // This gets called on recycled PaintedLayers that are going to be in the - // final layer tree, so it's a convenient time to invalidate the - // content that changed where we don't know what PaintedLayer it belonged - // to, or if we need to invalidate the entire layer, we can do that. - // This needs to be done before we update the PaintedLayer to its new - // transform. See nsGfxScrollFrame::InvalidateInternal, where - // we ensure that mInvalidPaintedContent is updated according to the - // scroll position as of the most recent paint. - if (!FuzzyEqual(data->mXScale, mParameters.mXScale, 0.00001f) || - !FuzzyEqual(data->mYScale, mParameters.mYScale, 0.00001f) || - data->mAppUnitsPerDevPixel != mAppUnitsPerDevPixel) { -#ifdef MOZ_DUMP_PAINTING - if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { - printf_stderr("Recycled layer %p changed scale\n", aLayer); - } -#endif - InvalidateEntirePaintedLayer(aLayer, aAnimatedGeometryRoot, - "recycled layer changed state"); - didResetScrollPositionForLayerPixelAlignment = true; - } - if (!data->mRegionToInvalidate.IsEmpty()) { -#ifdef MOZ_DUMP_PAINTING - if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { - printf_stderr("Invalidating deleted frame content from layer %p\n", - aLayer); - } -#endif - aLayer->InvalidateRegion(data->mRegionToInvalidate); -#ifdef MOZ_DUMP_PAINTING - if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { - nsAutoCString str; - AppendToString(str, data->mRegionToInvalidate); - printf_stderr("Invalidating layer %p: %s\n", aLayer, str.get()); - } -#endif - data->mRegionToInvalidate.SetEmpty(); - } - return data; -} - -void ContainerState::PreparePaintedLayerForUse( - PaintedLayer* aLayer, PaintedDisplayItemLayerUserData* aData, - AnimatedGeometryRoot* aAnimatedGeometryRoot, - const nsIFrame* aReferenceFrame, const nsPoint& aTopLeft, - bool didResetScrollPositionForLayerPixelAlignment) { - aData->mXScale = mParameters.mXScale; - aData->mYScale = mParameters.mYScale; - aData->mLastAnimatedGeometryRootOrigin = aData->mAnimatedGeometryRootOrigin; - aData->mAnimatedGeometryRootOrigin = aTopLeft; - aData->mAppUnitsPerDevPixel = mAppUnitsPerDevPixel; - aLayer->SetAllowResidualTranslation(mParameters.AllowResidualTranslation()); - - // Set up transform so that 0,0 in the PaintedLayer corresponds to the - // (pixel-snapped) top-left of the aAnimatedGeometryRoot. - nsPoint offset = - (*aAnimatedGeometryRoot)->GetOffsetToCrossDoc(aReferenceFrame); - nscoord appUnitsPerDevPixel = - (*aAnimatedGeometryRoot)->PresContext()->AppUnitsPerDevPixel(); - gfxPoint scaledOffset( - NSAppUnitsToDoublePixels(offset.x, appUnitsPerDevPixel) * - mParameters.mXScale, - NSAppUnitsToDoublePixels(offset.y, appUnitsPerDevPixel) * - mParameters.mYScale); - // We call RoundToMatchResidual here so that the residual after rounding - // is close to aData->mAnimatedGeometryRootPosition if possible. - nsIntPoint pixOffset( - RoundToMatchResidual(scaledOffset.x, - aData->mAnimatedGeometryRootPosition.x), - RoundToMatchResidual(scaledOffset.y, - aData->mAnimatedGeometryRootPosition.y)); - aData->mTranslation = pixOffset; - pixOffset += mParameters.mOffset; - Matrix matrix = Matrix::Translation(pixOffset.x, pixOffset.y); - aLayer->SetBaseTransform(Matrix4x4::From2D(matrix)); - - aData->mVisibilityComputedRegion.SetEmpty(); - - // Calculate exact position of the top-left of the active scrolled root. - // This might not be 0,0 due to the snapping in ScaleToNearestPixels. - gfxPoint animatedGeometryRootTopLeft = - scaledOffset - ThebesPoint(matrix.GetTranslation()) + mParameters.mOffset; - const bool disableAlpha = - mParameters.mDisableSubpixelAntialiasingInDescendants; - if (aData->mDisabledAlpha != disableAlpha) { - aData->mAnimatedGeometryRootPosition = animatedGeometryRootTopLeft; - InvalidateEntirePaintedLayer(aLayer, aAnimatedGeometryRoot, - "change of subpixel-AA"); - aData->mDisabledAlpha = disableAlpha; - return; - } - - // FIXME: Temporary workaround for bug 681192 and bug 724786. -#ifndef MOZ_WIDGET_ANDROID - // If it has changed, then we need to invalidate the entire layer since the - // pixels in the layer buffer have the content at a (subpixel) offset - // from what we need. - if (!animatedGeometryRootTopLeft.WithinEpsilonOf( - aData->mAnimatedGeometryRootPosition, SUBPIXEL_OFFSET_EPSILON)) { - aData->mAnimatedGeometryRootPosition = animatedGeometryRootTopLeft; - InvalidateEntirePaintedLayer(aLayer, aAnimatedGeometryRoot, - "subpixel offset"); - } else if (didResetScrollPositionForLayerPixelAlignment) { - aData->mAnimatedGeometryRootPosition = animatedGeometryRootTopLeft; - } -#else - Unused << didResetScrollPositionForLayerPixelAlignment; -#endif -} - -#if defined(DEBUG) || defined(MOZ_DUMP_PAINTING) -/** - * Returns the appunits per dev pixel for the item's frame - */ -static int32_t AppUnitsPerDevPixel(nsDisplayItem* aItem) { - // The underlying frame for zoom items is the root frame of the subdocument. - // But zoom display items report their bounds etc using the parent document's - // APD because zoom items act as a conversion layer between the two different - // APDs. - if (aItem->GetType() == DisplayItemType::TYPE_ZOOM) { - return static_cast<nsDisplayZoom*>(aItem)->GetParentAppUnitsPerDevPixel(); - } - return aItem->Frame()->PresContext()->AppUnitsPerDevPixel(); -} -#endif - -/** - * Set the visible region for aLayer. - * aOuterVisibleRegion is the visible region relative to the parent layer. - * aLayerContentsVisibleRect, if non-null, is a rectangle in the layer's - * own coordinate system to which the layer's visible region is restricted. - * Consumes *aOuterVisibleRegion. - */ -static void SetOuterVisibleRegion( - Layer* aLayer, nsIntRegion* aOuterVisibleRegion, - const nsIntRect* aLayerContentsVisibleRect = nullptr, - bool aOuterUntransformed = false) { - Matrix4x4 transform = aLayer->GetTransform(); - Matrix transform2D; - if (aOuterUntransformed) { - if (aLayerContentsVisibleRect) { - aOuterVisibleRegion->And(*aOuterVisibleRegion, - *aLayerContentsVisibleRect); - } - } else if (transform.Is2D(&transform2D) && - !transform2D.HasNonIntegerTranslation()) { - aOuterVisibleRegion->MoveBy(-int(transform2D._31), -int(transform2D._32)); - if (aLayerContentsVisibleRect) { - aOuterVisibleRegion->And(*aOuterVisibleRegion, - *aLayerContentsVisibleRect); - } - } else { - nsIntRect outerRect = aOuterVisibleRegion->GetBounds(); - // if 'transform' is not invertible, then nothing will be displayed - // for the layer, so it doesn't really matter what we do here - Rect outerVisible(outerRect.x, outerRect.y, outerRect.width, - outerRect.height); - transform.Invert(); - - Rect layerContentsVisible = Rect::MaxIntRect(); - - if (aLayerContentsVisibleRect) { - NS_ASSERTION(aLayerContentsVisibleRect->width >= 0 && - aLayerContentsVisibleRect->height >= 0, - "Bad layer contents rectangle"); - // restrict to aLayerContentsVisibleRect before call GfxRectToIntRect, - // in case layerVisible is extremely large (as it can be when - // projecting through the inverse of a 3D transform) - layerContentsVisible = Rect( - aLayerContentsVisibleRect->x, aLayerContentsVisibleRect->y, - aLayerContentsVisibleRect->width, aLayerContentsVisibleRect->height); - } - - Rect layerVisible = - transform.ProjectRectBounds(outerVisible, layerContentsVisible); - - layerVisible.RoundOut(); - - IntRect intRect; - if (!layerVisible.ToIntRect(&intRect)) { - intRect = IntRect::MaxIntRect(); - } - - *aOuterVisibleRegion = intRect; - } - - aLayer->SetVisibleRegion( - LayerIntRegion::FromUnknownRegion(*aOuterVisibleRegion)); -} - -void ContainerState::SetOuterVisibleRegionForLayer( - Layer* aLayer, const nsIntRegion& aOuterVisibleRegion, - const nsIntRect* aLayerContentsVisibleRect, - bool aOuterUntransformed) const { - nsIntRegion visRegion = aOuterVisibleRegion; - if (!aOuterUntransformed) { - visRegion.MoveBy(mParameters.mOffset); - } - SetOuterVisibleRegion(aLayer, &visRegion, aLayerContentsVisibleRect, - aOuterUntransformed); -} - -nscolor ContainerState::FindOpaqueBackgroundColorInLayer( - const PaintedLayerData* aData, const nsIntRect& aRect, - bool* aOutIntersectsLayer) const { - *aOutIntersectsLayer = true; - - // Scan the candidate's display items. - nsIntRect deviceRect = aRect; - nsRect appUnitRect = ToAppUnits(deviceRect, mAppUnitsPerDevPixel); - appUnitRect.ScaleInverseRoundOut(mParameters.mXScale, mParameters.mYScale); - - for (auto& assignedItem : Reversed(aData->mAssignedDisplayItems)) { - if (assignedItem.HasOpacity() || assignedItem.HasTransform()) { - // We cannot easily calculate the opaque background color for items inside - // a flattened effect. - continue; - } - - if (IsEffectEndMarker(assignedItem.mType)) { - // An optimization: the underlying display item for effect markers is the - // same for both start and end markers. Skip the effect end markers. - continue; - } - - nsDisplayItem* item = assignedItem.mItem; - bool snap; - nsRect bounds = item->GetBounds(mBuilder, &snap); - if (snap && mSnappingEnabled) { - nsIntRect snappedBounds = ScaleToNearestPixels(bounds); - if (!snappedBounds.Intersects(deviceRect)) continue; - - if (!snappedBounds.Contains(deviceRect)) return NS_RGBA(0, 0, 0, 0); - - } else { - // The layer's visible rect is already (close enough to) pixel - // aligned, so no need to round out and in here. - if (!bounds.Intersects(appUnitRect)) continue; - - if (!bounds.Contains(appUnitRect)) return NS_RGBA(0, 0, 0, 0); - } - - if (item->IsInvisibleInRect(appUnitRect)) { - continue; - } - - if (item->GetClip().IsRectAffectedByClip(deviceRect, mParameters.mXScale, - mParameters.mYScale, - mAppUnitsPerDevPixel)) { - return NS_RGBA(0, 0, 0, 0); - } - - MOZ_ASSERT(!assignedItem.HasOpacity() && !assignedItem.HasTransform()); - Maybe<nscolor> color = item->IsUniform(mBuilder); - - if (color && NS_GET_A(*color) == 255) { - return *color; - } - - return NS_RGBA(0, 0, 0, 0); - } - - *aOutIntersectsLayer = false; - return NS_RGBA(0, 0, 0, 0); -} - -nscolor PaintedLayerDataNode::FindOpaqueBackgroundColor( - const nsIntRegion& aTargetVisibleRegion, int32_t aUnderIndex) const { - if (aUnderIndex == ABOVE_TOP) { - aUnderIndex = mPaintedLayerDataStack.Length(); - } - for (int32_t i = aUnderIndex - 1; i >= 0; --i) { - const PaintedLayerData* candidate = &mPaintedLayerDataStack[i]; - if (candidate->VisibleAboveRegionIntersects(aTargetVisibleRegion)) { - // Some non-PaintedLayer content between target and candidate; this is - // hopeless - return NS_RGBA(0, 0, 0, 0); - } - - if (!candidate->VisibleRegionIntersects(aTargetVisibleRegion)) { - // The layer doesn't intersect our target, ignore it and move on - continue; - } - - bool intersectsLayer = true; - nsIntRect rect = aTargetVisibleRegion.GetBounds(); - nscolor color = mTree.ContState().FindOpaqueBackgroundColorInLayer( - candidate, rect, &intersectsLayer); - if (!intersectsLayer) { - continue; - } - return color; - } - if (mAllDrawingAboveBackground || - !mVisibleAboveBackgroundRegion.Intersect(aTargetVisibleRegion) - .IsEmpty()) { - // Some non-PaintedLayer content is between this node's background and - // target. - return NS_RGBA(0, 0, 0, 0); - } - return FindOpaqueBackgroundColorInParentNode(); -} - -nscolor PaintedLayerDataNode::FindOpaqueBackgroundColorCoveringEverything() - const { - if (!mPaintedLayerDataStack.IsEmpty() || mAllDrawingAboveBackground || - !mVisibleAboveBackgroundRegion.IsEmpty()) { - return NS_RGBA(0, 0, 0, 0); - } - return FindOpaqueBackgroundColorInParentNode(); -} - -nscolor PaintedLayerDataNode::FindOpaqueBackgroundColorInParentNode() const { - if (mParent) { - if (mHasClip) { - // Check whether our parent node has uniform content behind our whole - // clip. - // There's one tricky case here: If our parent node is also a scrollable, - // and is currently scrolled in such a way that this inner one is - // clipped by it, then it's not really clear how we should determine - // whether we have a uniform background in the parent: There might be - // non-uniform content in the parts that our scroll port covers in the - // parent and that are currently outside the parent's clip. - // For now, we'll fail to pull a background color in that case. - return mParent->FindOpaqueBackgroundColor(mClipRect); - } - return mParent->FindOpaqueBackgroundColorCoveringEverything(); - } - // We are the root. - return mTree.UniformBackgroundColor(); -} - -bool PaintedLayerData::CanOptimizeToImageLayer(nsDisplayListBuilder* aBuilder) { - if (!mImage) { - return false; - } - - return mImage->CanOptimizeToImageLayer(mLayer->Manager(), aBuilder); -} - -already_AddRefed<ImageContainer> PaintedLayerData::GetContainerForImageLayer( - nsDisplayListBuilder* aBuilder) { - if (!mImage) { - return nullptr; - } - - return mImage->GetContainer(mLayer->Manager(), aBuilder); -} - -PaintedLayerDataNode::PaintedLayerDataNode( - PaintedLayerDataTree& aTree, PaintedLayerDataNode* aParent, - AnimatedGeometryRoot* aAnimatedGeometryRoot) - : mTree(aTree), - mParent(aParent), - mAnimatedGeometryRoot(aAnimatedGeometryRoot), - mAllDrawingAboveBackground(false) { - MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDocInProcess( - mTree.Builder()->RootReferenceFrame(), *mAnimatedGeometryRoot)); - mHasClip = mTree.IsClippedWithRespectToParentAnimatedGeometryRoot( - mAnimatedGeometryRoot, &mClipRect); -} - -PaintedLayerDataNode::~PaintedLayerDataNode() { - MOZ_ASSERT(mPaintedLayerDataStack.IsEmpty()); - MOZ_ASSERT(mChildren.IsEmpty()); -} - -PaintedLayerDataNode* PaintedLayerDataNode::AddChildNodeFor( - AnimatedGeometryRoot* aAnimatedGeometryRoot) { - MOZ_ASSERT(aAnimatedGeometryRoot->mParentAGR == mAnimatedGeometryRoot); - UniquePtr<PaintedLayerDataNode> child = - MakeUnique<PaintedLayerDataNode>(mTree, this, aAnimatedGeometryRoot); - mChildren.AppendElement(std::move(child)); - return mChildren.LastElement().get(); -} - -template <typename NewPaintedLayerCallbackType> -PaintedLayerData* PaintedLayerDataNode::FindPaintedLayerFor( - const nsIntRect& aVisibleRect, const bool aBackfaceHidden, - const ActiveScrolledRoot* aASR, const DisplayItemClipChain* aClipChain, - NewPaintedLayerCallbackType aNewPaintedLayerCallback) { - if (!mPaintedLayerDataStack.IsEmpty()) { - PaintedLayerData* lowestUsableLayer = nullptr; - for (auto& data : Reversed(mPaintedLayerDataStack)) { - if (data.mVisibleAboveRegion.Intersects(aVisibleRect)) { - break; - } - if (data.mBackfaceHidden == aBackfaceHidden && data.mASR == aASR && - data.mClipChain == aClipChain) { - lowestUsableLayer = &data; - } - // Also check whether the event-regions intersect the visible rect, - // unless we're in an inactive layer, in which case the event-regions - // will be hoisted out into their own layer. - // For performance reasons, we check the intersection with the bounds - // of the event-regions. - if (!mTree.ContState().IsInInactiveLayer() && - (data.mScaledHitRegionBounds.Intersects(aVisibleRect) || - data.mScaledMaybeHitRegionBounds.Intersects(aVisibleRect))) { - break; - } - // If the visible region intersects with the current layer then we - // can't possibly use any of the layers below it, so stop the search - // now. - // - // If we're trying to minimize painted layer size and we don't - // intersect the current visible region, then make sure we don't - // use this painted layer. - if (data.mVisibleRegion.Intersects(aVisibleRect)) { - break; - } - - if (StaticPrefs::layout_smaller_painted_layers()) { - lowestUsableLayer = nullptr; - } - } - if (lowestUsableLayer) { - return lowestUsableLayer; - } - } - PaintedLayerData* data = mPaintedLayerDataStack.AppendElement(); - aNewPaintedLayerCallback(data); - - return data; -} - -void PaintedLayerDataNode::FinishChildrenIntersecting(const nsIntRect& aRect) { - for (int32_t i = mChildren.Length() - 1; i >= 0; i--) { - if (mChildren[i]->Intersects(aRect)) { - mChildren[i]->Finish(true); - mChildren.RemoveElementAt(i); - } - } -} - -void PaintedLayerDataNode::FinishAllChildren( - bool aThisNodeNeedsAccurateVisibleAboveRegion) { - for (int32_t i = mChildren.Length() - 1; i >= 0; i--) { - mChildren[i]->Finish(aThisNodeNeedsAccurateVisibleAboveRegion); - } - mChildren.Clear(); -} - -void PaintedLayerDataNode::Finish(bool aParentNeedsAccurateVisibleAboveRegion) { - // Skip "visible above region" maintenance, because this node is going away. - FinishAllChildren(false); - - PopAllPaintedLayerData(); - - if (mParent && aParentNeedsAccurateVisibleAboveRegion) { - if (mHasClip) { - mParent->AddToVisibleAboveRegion(mClipRect); - } else { - mParent->SetAllDrawingAbove(); - } - } - mTree.NodeWasFinished(mAnimatedGeometryRoot); -} - -void PaintedLayerDataNode::AddToVisibleAboveRegion(const nsIntRect& aRect) { - nsIntRegion& visibleAboveRegion = - mPaintedLayerDataStack.IsEmpty() - ? mVisibleAboveBackgroundRegion - : mPaintedLayerDataStack.LastElement().mVisibleAboveRegion; - visibleAboveRegion.Or(visibleAboveRegion, aRect); - visibleAboveRegion.SimplifyOutward(8); -} - -void PaintedLayerDataNode::SetAllDrawingAbove() { - PopAllPaintedLayerData(); - mAllDrawingAboveBackground = true; - mVisibleAboveBackgroundRegion.SetEmpty(); -} - -void PaintedLayerDataNode::PopAllPaintedLayerData() { - for (int32_t index = mPaintedLayerDataStack.Length() - 1; index >= 0; - index--) { - PaintedLayerData& data = mPaintedLayerDataStack[index]; - mTree.ContState().FinishPaintedLayerData(data, [this, &data, index]() { - return this->FindOpaqueBackgroundColor(data.mVisibleRegion, index); - }); - } - mPaintedLayerDataStack.Clear(); -} - -void PaintedLayerDataTree::InitializeForInactiveLayer( - AnimatedGeometryRoot* aAnimatedGeometryRoot) { - mForInactiveLayer = true; - mRoot.emplace(*this, nullptr, aAnimatedGeometryRoot); -} - -nsDisplayListBuilder* PaintedLayerDataTree::Builder() const { - return mContainerState.Builder(); -} - -void PaintedLayerDataTree::Finish() { - if (mRoot) { - mRoot->Finish(false); - } - MOZ_ASSERT(mNodes.Count() == 0); - mRoot.reset(); -} - -void PaintedLayerDataTree::NodeWasFinished( - AnimatedGeometryRoot* aAnimatedGeometryRoot) { - mNodes.Remove(aAnimatedGeometryRoot); -} - -void PaintedLayerDataTree::AddingOwnLayer( - AnimatedGeometryRoot* aAnimatedGeometryRoot, const nsIntRect* aRect, - nscolor* aOutUniformBackgroundColor) { - PaintedLayerDataNode* node = nullptr; - if (mForInactiveLayer) { - node = mRoot.ptr(); - } else { - FinishPotentiallyIntersectingNodes(aAnimatedGeometryRoot, aRect); - node = EnsureNodeFor(aAnimatedGeometryRoot); - } - if (aRect) { - if (aOutUniformBackgroundColor) { - *aOutUniformBackgroundColor = node->FindOpaqueBackgroundColor(*aRect); - } - node->AddToVisibleAboveRegion(*aRect); - } else { - if (aOutUniformBackgroundColor) { - *aOutUniformBackgroundColor = - node->FindOpaqueBackgroundColorCoveringEverything(); - } - node->SetAllDrawingAbove(); - } -} - -template <typename NewPaintedLayerCallbackType> -PaintedLayerData* PaintedLayerDataTree::FindPaintedLayerFor( - AnimatedGeometryRoot* aAnimatedGeometryRoot, const ActiveScrolledRoot* aASR, - const DisplayItemClipChain* aClipChain, const nsIntRect& aVisibleRect, - const bool aBackfaceHidden, - NewPaintedLayerCallbackType aNewPaintedLayerCallback) { - const nsIntRect* bounds = &aVisibleRect; - PaintedLayerDataNode* node = nullptr; - if (mForInactiveLayer) { - node = mRoot.ptr(); - } else { - FinishPotentiallyIntersectingNodes(aAnimatedGeometryRoot, bounds); - node = EnsureNodeFor(aAnimatedGeometryRoot); - } - - PaintedLayerData* data = - node->FindPaintedLayerFor(aVisibleRect, aBackfaceHidden, aASR, aClipChain, - aNewPaintedLayerCallback); - return data; -} - -void PaintedLayerDataTree::FinishPotentiallyIntersectingNodes( - AnimatedGeometryRoot* aAnimatedGeometryRoot, const nsIntRect* aRect) { - AnimatedGeometryRoot* ancestorThatIsChildOfCommonAncestor = nullptr; - PaintedLayerDataNode* ancestorNode = FindNodeForAncestorAnimatedGeometryRoot( - aAnimatedGeometryRoot, &ancestorThatIsChildOfCommonAncestor); - if (!ancestorNode) { - // None of our ancestors are in the tree. This should only happen if this - // is the very first item we're looking at. - MOZ_ASSERT(!mRoot); - return; - } - - if (ancestorNode->GetAnimatedGeometryRoot() == aAnimatedGeometryRoot) { - // aAnimatedGeometryRoot already has a node in the tree. - // This is the common case. - MOZ_ASSERT(!ancestorThatIsChildOfCommonAncestor); - if (aRect) { - ancestorNode->FinishChildrenIntersecting(*aRect); - } else { - ancestorNode->FinishAllChildren(); - } - return; - } - - // We have found an existing ancestor, but it's a proper ancestor of our - // animated geometry root. - // ancestorThatIsChildOfCommonAncestor is the last animated geometry root - // encountered on the way up from aAnimatedGeometryRoot to ancestorNode. - MOZ_ASSERT(ancestorThatIsChildOfCommonAncestor); - MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDocInProcess( - *ancestorThatIsChildOfCommonAncestor, *aAnimatedGeometryRoot)); - MOZ_ASSERT(ancestorThatIsChildOfCommonAncestor->mParentAGR == - ancestorNode->GetAnimatedGeometryRoot()); - - // ancestorThatIsChildOfCommonAncestor is not in the tree yet! - MOZ_ASSERT(!mNodes.Get(ancestorThatIsChildOfCommonAncestor)); - - // We're about to add a node for ancestorThatIsChildOfCommonAncestor, so we - // finish all intersecting siblings. - nsIntRect clip; - if (IsClippedWithRespectToParentAnimatedGeometryRoot( - ancestorThatIsChildOfCommonAncestor, &clip)) { - ancestorNode->FinishChildrenIntersecting(clip); - } else { - ancestorNode->FinishAllChildren(); - } -} - -PaintedLayerDataNode* PaintedLayerDataTree::EnsureNodeFor( - AnimatedGeometryRoot* aAnimatedGeometryRoot) { - MOZ_ASSERT(aAnimatedGeometryRoot); - PaintedLayerDataNode* node = mNodes.Get(aAnimatedGeometryRoot); - if (node) { - return node; - } - - AnimatedGeometryRoot* parentAnimatedGeometryRoot = - aAnimatedGeometryRoot->mParentAGR; - if (!parentAnimatedGeometryRoot) { - MOZ_ASSERT(!mRoot); - MOZ_ASSERT(*aAnimatedGeometryRoot == Builder()->RootReferenceFrame()); - mRoot.emplace(*this, nullptr, aAnimatedGeometryRoot); - node = mRoot.ptr(); - } else { - PaintedLayerDataNode* parentNode = - EnsureNodeFor(parentAnimatedGeometryRoot); - MOZ_ASSERT(parentNode); - node = parentNode->AddChildNodeFor(aAnimatedGeometryRoot); - } - MOZ_ASSERT(node); - mNodes.InsertOrUpdate(aAnimatedGeometryRoot, node); - return node; -} - -bool PaintedLayerDataTree::IsClippedWithRespectToParentAnimatedGeometryRoot( - AnimatedGeometryRoot* aAnimatedGeometryRoot, nsIntRect* aOutClip) { - if (mForInactiveLayer) { - return false; - } - nsIScrollableFrame* scrollableFrame = - nsLayoutUtils::GetScrollableFrameFor(*aAnimatedGeometryRoot); - if (!scrollableFrame) { - return false; - } - nsIFrame* scrollFrame = do_QueryFrame(scrollableFrame); - nsRect scrollPort = scrollableFrame->GetScrollPortRect() + - Builder()->ToReferenceFrame(scrollFrame); - *aOutClip = mContainerState.ScaleToNearestPixels(scrollPort); - return true; -} - -PaintedLayerDataNode* -PaintedLayerDataTree::FindNodeForAncestorAnimatedGeometryRoot( - AnimatedGeometryRoot* aAnimatedGeometryRoot, - AnimatedGeometryRoot** aOutAncestorChild) { - if (!aAnimatedGeometryRoot) { - return nullptr; - } - PaintedLayerDataNode* node = mNodes.Get(aAnimatedGeometryRoot); - if (node) { - return node; - } - *aOutAncestorChild = aAnimatedGeometryRoot; - return FindNodeForAncestorAnimatedGeometryRoot( - aAnimatedGeometryRoot->mParentAGR, aOutAncestorChild); -} - -static bool CanOptimizeAwayPaintedLayer(PaintedLayerData* aData, - FrameLayerBuilder* aLayerBuilder) { - if (!aLayerBuilder->IsBuildingRetainedLayers()) { - return false; - } - - // If there's no painted layer with valid content in it that we can reuse, - // always create a color or image layer (and potentially throw away an - // existing completely invalid painted layer). - if (aData->mLayer->GetValidRegion().IsEmpty()) { - return true; - } - - // There is an existing painted layer we can reuse. Throwing it away can make - // compositing cheaper (see bug 946952), but it might cause us to re-allocate - // the painted layer frequently due to an animation. So we only discard it if - // we're in tree compression mode, which is triggered at a low frequency. - return aLayerBuilder->CheckInLayerTreeCompressionMode(); -} - -#ifdef DEBUG -static int32_t FindIndexOfLayerIn(nsTArray<NewLayerEntry>& aArray, - Layer* aLayer) { - for (uint32_t i = 0; i < aArray.Length(); ++i) { - if (aArray[i].mLayer == aLayer) { - return i; - } - } - return -1; -} -#endif - -already_AddRefed<Layer> ContainerState::PrepareImageLayer( - PaintedLayerData* aData) { - RefPtr<ImageContainer> imageContainer = - aData->GetContainerForImageLayer(mBuilder); - if (!imageContainer) { - return nullptr; - } - - RefPtr<ImageLayer> imageLayer = CreateOrRecycleImageLayer(aData->mLayer); - imageLayer->SetContainer(imageContainer); - aData->mImage->ConfigureLayer(imageLayer, mParameters); - imageLayer->SetPostScale(mParameters.mXScale, mParameters.mYScale); - - if (aData->mItemClip->HasClip()) { - ParentLayerIntRect clip = ViewAs<ParentLayerPixel>( - ScaleToNearestPixels(aData->mItemClip->GetClipRect())); - clip.MoveBy(ViewAs<ParentLayerPixel>(mParameters.mOffset)); - imageLayer->SetClipRect(Some(clip)); - } else { - imageLayer->SetClipRect(Nothing()); - } - - FLB_LOG_PAINTED_LAYER_DECISION(aData, " Selected image layer=%p\n", - imageLayer.get()); - - return imageLayer.forget(); -} - -already_AddRefed<Layer> ContainerState::PrepareColorLayer( - PaintedLayerData* aData) { - RefPtr<ColorLayer> colorLayer = CreateOrRecycleColorLayer(aData->mLayer); - colorLayer->SetColor(ToDeviceColor(aData->mSolidColor)); - - // Copy transform - colorLayer->SetBaseTransform(aData->mLayer->GetBaseTransform()); - colorLayer->SetPostScale(aData->mLayer->GetPostXScale(), - aData->mLayer->GetPostYScale()); - - nsIntRect visibleRect = aData->mVisibleRegion.GetBounds(); - visibleRect.MoveBy(-GetTranslationForPaintedLayer(aData->mLayer)); - colorLayer->SetBounds(visibleRect); - colorLayer->SetClipRect(Nothing()); - - FLB_LOG_PAINTED_LAYER_DECISION(aData, " Selected color layer=%p\n", - colorLayer.get()); - - return colorLayer.forget(); -} - -static void SetBackfaceHiddenForLayer(bool aBackfaceHidden, Layer* aLayer) { - if (aBackfaceHidden) { - aLayer->SetContentFlags(aLayer->GetContentFlags() | - Layer::CONTENT_BACKFACE_HIDDEN); - } else { - aLayer->SetContentFlags(aLayer->GetContentFlags() & - ~Layer::CONTENT_BACKFACE_HIDDEN); - } -} - -template <typename FindOpaqueBackgroundColorCallbackType> -void ContainerState::FinishPaintedLayerData( - PaintedLayerData& aData, - FindOpaqueBackgroundColorCallbackType aFindOpaqueBackgroundColor) { - PaintedLayerData* data = &aData; - - if (!data->mLayer) { - // No layer was recycled, so we create a new one. - RefPtr<PaintedLayer> paintedLayer = CreatePaintedLayer(data); - data->mLayer = paintedLayer; - - NS_ASSERTION(FindIndexOfLayerIn(mNewChildLayers, paintedLayer) < 0, - "Layer already in list???"); - mNewChildLayers[data->mNewChildLayersIndex].mLayer = - std::move(paintedLayer); - } - - auto* userData = GetPaintedDisplayItemLayerUserData(data->mLayer); - NS_ASSERTION(userData, "where did our user data go?"); - userData->mLastItemCount = data->mAssignedDisplayItems.size(); - - NewLayerEntry* newLayerEntry = &mNewChildLayers[data->mNewChildLayersIndex]; - - RefPtr<Layer> layer; - bool canOptimizeToImageLayer = data->CanOptimizeToImageLayer(mBuilder); - - FLB_LOG_PAINTED_LAYER_DECISION(data, "Selecting layer for pld=%p\n", data); - FLB_LOG_PAINTED_LAYER_DECISION( - data, " Solid=%i, hasImage=%c, canOptimizeAwayPaintedLayer=%i\n", - data->mIsSolidColorInVisibleRegion, canOptimizeToImageLayer ? 'y' : 'n', - CanOptimizeAwayPaintedLayer(data, mLayerBuilder)); - - if ((data->mIsSolidColorInVisibleRegion || canOptimizeToImageLayer) && - CanOptimizeAwayPaintedLayer(data, mLayerBuilder)) { - NS_ASSERTION( - !(data->mIsSolidColorInVisibleRegion && canOptimizeToImageLayer), - "Can't be a solid color as well as an image!"); - - layer = canOptimizeToImageLayer ? PrepareImageLayer(data) - : PrepareColorLayer(data); - - if (layer) { - NS_ASSERTION(FindIndexOfLayerIn(mNewChildLayers, layer) < 0, - "Layer already in list???"); - NS_ASSERTION(newLayerEntry->mLayer == data->mLayer, - "Painted layer at wrong index"); - // Store optimized layer in reserved slot - NewLayerEntry* paintedLayerEntry = newLayerEntry; - newLayerEntry = &mNewChildLayers[data->mNewChildLayersIndex + 1]; - NS_ASSERTION(!newLayerEntry->mLayer, "Slot already occupied?"); - newLayerEntry->mLayer = layer; - newLayerEntry->mAnimatedGeometryRoot = data->mAnimatedGeometryRoot; - newLayerEntry->mASR = paintedLayerEntry->mASR; - newLayerEntry->mClipChain = paintedLayerEntry->mClipChain; - newLayerEntry->mScrollMetadataASR = paintedLayerEntry->mScrollMetadataASR; - - // Hide the PaintedLayer. We leave it in the layer tree so that we - // can find and recycle it later. - ParentLayerIntRect emptyRect; - data->mLayer->SetClipRect(Some(emptyRect)); - data->mLayer->SetVisibleRegion(LayerIntRegion()); - data->mLayer->InvalidateWholeLayer(); - data->mLayer->SetEventRegions(EventRegions()); - } - } - - if (!layer) { - // We couldn't optimize to an image layer or a color layer above. - layer = data->mLayer; - layer->SetClipRect(Nothing()); - FLB_LOG_PAINTED_LAYER_DECISION(data, " Selected painted layer=%p\n", - layer.get()); - } - - for (auto& item : data->mAssignedDisplayItems) { - MOZ_ASSERT(item.mItem->GetType() != - DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO); - - if (IsEffectEndMarker(item.mType)) { - // Do not invalidate for end markers. - continue; - } - - InvalidateForLayerChange(item.mItem, data->mLayer, item.mDisplayItemData); - mLayerBuilder->AddPaintedDisplayItem(data, item, layer); - item.mDisplayItemData = nullptr; - } - - if (mLayerBuilder->IsBuildingRetainedLayers()) { - newLayerEntry->mVisibleRegion = data->mVisibleRegion; - newLayerEntry->mOpaqueRegion = data->mOpaqueRegion; - newLayerEntry->mHideAllLayersBelow = data->mHideAllLayersBelow; - newLayerEntry->mOpaqueForAnimatedGeometryRootParent = - data->mOpaqueForAnimatedGeometryRootParent; - } else { - SetOuterVisibleRegionForLayer(layer, data->mVisibleRegion); - } - -#ifdef MOZ_DUMP_PAINTING - if (!data->mLog.IsEmpty()) { - PaintedLayerData* containingPld = - mLayerBuilder->GetContainingPaintedLayerData(); - if (containingPld && containingPld->mLayer) { - containingPld->mLayer->AddExtraDumpInfo(nsCString(data->mLog)); - } else { - layer->AddExtraDumpInfo(nsCString(data->mLog)); - } - } -#endif - - mLayerBuilder->AddPaintedLayerItemsEntry(userData); - - nsIntRegion transparentRegion; - transparentRegion.Sub(data->mVisibleRegion, data->mOpaqueRegion); - bool isOpaque = transparentRegion.IsEmpty(); - // For translucent PaintedLayers, try to find an opaque background - // color that covers the entire area beneath it so we can pull that - // color into this layer to make it opaque. - if (layer == data->mLayer) { - nscolor backgroundColor = NS_RGBA(0, 0, 0, 0); - if (!isOpaque) { - backgroundColor = aFindOpaqueBackgroundColor(); - if (NS_GET_A(backgroundColor) == 255) { - isOpaque = true; - } - } - - // Store the background color - if (userData->mForcedBackgroundColor != backgroundColor) { - // Invalidate the entire target PaintedLayer since we're changing - // the background color -#ifdef MOZ_DUMP_PAINTING - if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { - printf_stderr( - "Forced background color has changed from #%08X to #%08X " - "on layer %p\n", - userData->mForcedBackgroundColor, backgroundColor, data->mLayer); - nsAutoCString str; - AppendToString(str, data->mLayer->GetValidRegion()); - printf_stderr("Invalidating layer %p: %s\n", data->mLayer, str.get()); - } -#endif - data->mLayer->InvalidateWholeLayer(); - } - userData->mForcedBackgroundColor = backgroundColor; - } else { - // mask layer for image and color layers - SetupMaskLayer(layer, *data->mItemClip); - } - - uint32_t flags = 0; - nsIWidget* widget = mContainerReferenceFrame->PresContext()->GetRootWidget(); - // See bug 941095. Not quite ready to disable this. - bool hidpi = false && widget && widget->GetDefaultScale().scale >= 2; - if (hidpi) { - flags |= Layer::CONTENT_DISABLE_SUBPIXEL_AA; - } - if (isOpaque && !data->mForceTransparentSurface) { - flags |= Layer::CONTENT_OPAQUE; - } else if (data->mNeedComponentAlpha && !hidpi) { - flags |= Layer::CONTENT_COMPONENT_ALPHA; - } - layer->SetContentFlags(flags); - - userData->mItems = std::move(data->mAssignedDisplayItems); - userData->mContainerLayerFrame = GetContainerFrame(); - - PaintedLayerData* containingPaintedLayerData = - mLayerBuilder->GetContainingPaintedLayerData(); - // If we're building layers for an inactive layer, the event regions are - // clipped to the inactive layer's clip prior to being combined into the - // event regions of the containing PLD. - // For the dispatch-to-content and maybe-hit regions, rounded corners on - // the clip are ignored, since these are approximate regions. For the - // remaining regions, rounded corners in the clip cause the region to - // be combined into the corresponding "imprecise" region of the - // containing's PLD (e.g. the maybe-hit region instead of the hit region). - const DisplayItemClip* inactiveLayerClip = - mLayerBuilder->GetInactiveLayerClip(); - if (containingPaintedLayerData) { - if (!data->mDispatchToContentHitRegion.GetBounds().IsEmpty()) { - nsRect rect = nsLayoutUtils::TransformFrameRectToAncestor( - mContainerReferenceFrame, - data->mDispatchToContentHitRegion.GetBounds(), - containingPaintedLayerData->mReferenceFrame); - if (inactiveLayerClip) { - rect = inactiveLayerClip->ApplyNonRoundedIntersection(rect); - } - containingPaintedLayerData->mDispatchToContentHitRegion.Or( - containingPaintedLayerData->mDispatchToContentHitRegion, rect); - containingPaintedLayerData->mDispatchToContentHitRegion.SimplifyOutward( - 8); - if (data->mDTCRequiresTargetConfirmation) { - containingPaintedLayerData->mDTCRequiresTargetConfirmation = true; - } - } - if (!data->mMaybeHitRegion.GetBounds().IsEmpty()) { - nsRect rect = nsLayoutUtils::TransformFrameRectToAncestor( - mContainerReferenceFrame, data->mMaybeHitRegion.GetBounds(), - containingPaintedLayerData->mReferenceFrame); - if (inactiveLayerClip) { - rect = inactiveLayerClip->ApplyNonRoundedIntersection(rect); - } - containingPaintedLayerData->mMaybeHitRegion.Or( - containingPaintedLayerData->mMaybeHitRegion, rect); - containingPaintedLayerData->mMaybeHitRegion.SimplifyOutward(8); - } - Maybe<Matrix4x4Flagged> matrixCache; - nsLayoutUtils::TransformToAncestorAndCombineRegions( - data->mHitRegion, mContainerReferenceFrame, - containingPaintedLayerData->mReferenceFrame, - &containingPaintedLayerData->mHitRegion, - &containingPaintedLayerData->mMaybeHitRegion, &matrixCache, - inactiveLayerClip); - // See the comment in nsDisplayList::AddFrame, where the touch action - // regions are handled. The same thing applies here. - bool alreadyHadRegions = - !containingPaintedLayerData->mNoActionRegion.IsEmpty() || - !containingPaintedLayerData->mHorizontalPanRegion.IsEmpty() || - !containingPaintedLayerData->mVerticalPanRegion.IsEmpty(); - nsLayoutUtils::TransformToAncestorAndCombineRegions( - data->mNoActionRegion, mContainerReferenceFrame, - containingPaintedLayerData->mReferenceFrame, - &containingPaintedLayerData->mNoActionRegion, - &containingPaintedLayerData->mDispatchToContentHitRegion, &matrixCache, - inactiveLayerClip); - nsLayoutUtils::TransformToAncestorAndCombineRegions( - data->mHorizontalPanRegion, mContainerReferenceFrame, - containingPaintedLayerData->mReferenceFrame, - &containingPaintedLayerData->mHorizontalPanRegion, - &containingPaintedLayerData->mDispatchToContentHitRegion, &matrixCache, - inactiveLayerClip); - nsLayoutUtils::TransformToAncestorAndCombineRegions( - data->mVerticalPanRegion, mContainerReferenceFrame, - containingPaintedLayerData->mReferenceFrame, - &containingPaintedLayerData->mVerticalPanRegion, - &containingPaintedLayerData->mDispatchToContentHitRegion, &matrixCache, - inactiveLayerClip); - if (alreadyHadRegions) { - containingPaintedLayerData->mDispatchToContentHitRegion.OrWith( - containingPaintedLayerData->CombinedTouchActionRegion()); - } - containingPaintedLayerData->HitRegionsUpdated(); - } else { - EventRegions regions( - ScaleRegionToOutsidePixels(data->mHitRegion), - ScaleRegionToOutsidePixels(data->mMaybeHitRegion), - ScaleRegionToOutsidePixels(data->mDispatchToContentHitRegion), - ScaleRegionToOutsidePixels(data->mNoActionRegion), - ScaleRegionToOutsidePixels(data->mHorizontalPanRegion), - ScaleRegionToOutsidePixels(data->mVerticalPanRegion), - data->mDTCRequiresTargetConfirmation); - - Matrix mat = layer->GetTransform().As2D(); - mat.Invert(); - regions.ApplyTranslationAndScale(mat._31, mat._32, mat._11, mat._22); - - layer->SetEventRegions(regions); - } - - SetBackfaceHiddenForLayer(data->mBackfaceHidden, data->mLayer); - if (layer != data->mLayer) { - SetBackfaceHiddenForLayer(data->mBackfaceHidden, layer); - } -} - -static bool IsItemAreaInWindowOpaqueRegion( - nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem, - const nsRect& aComponentAlphaBounds) { - if (!aItem->Frame()->PresContext()->IsChrome()) { - // Assume that Web content is always in the window opaque region. - return true; - } - if (aItem->ReferenceFrame() != aBuilder->RootReferenceFrame()) { - // aItem is probably in some transformed subtree. - // We're not going to bother figuring out where this landed, we're just - // going to assume it might have landed over a transparent part of - // the window. - return false; - } - return aBuilder->GetWindowOpaqueRegion().Contains(aComponentAlphaBounds); -} - -void PaintedLayerData::UpdateEffectStatus(DisplayItemEntryType aType, - nsTArray<size_t>& aOpacityIndices) { - switch (aType) { - case DisplayItemEntryType::PushOpacity: - // The index of the new assigned display item in |mAssignedDisplayItems| - // array will be the current length of the array. - aOpacityIndices.AppendElement(mAssignedDisplayItems.size()); - break; - case DisplayItemEntryType::PopOpacity: - MOZ_ASSERT(!aOpacityIndices.IsEmpty()); - aOpacityIndices.RemoveLastElement(); - break; -#ifdef DEBUG - case DisplayItemEntryType::PopTransform: - MOZ_ASSERT(mTransformLevel >= 0); - mTransformLevel--; - break; - case DisplayItemEntryType::PushTransform: - mTransformLevel++; - break; -#endif - default: - break; - } -} - -bool PaintedLayerData::SetupComponentAlpha( - ContainerState* aState, nsPaintedDisplayItem* aItem, - const nsIntRect& aVisibleRect, const TransformClipNode* aTransform) { - nsRect componentAlphaBounds = - aItem->GetComponentAlphaBounds(aState->mBuilder); - - if (componentAlphaBounds.IsEmpty()) { - // The item does not require component alpha, nothing do do here. - return false; - } - - if (aTransform) { - componentAlphaBounds = aTransform->TransformRect( - componentAlphaBounds, aState->mAppUnitsPerDevPixel); - } - - const nsIntRect pixelBounds = - aState->ScaleToOutsidePixels(componentAlphaBounds, false); - - const nsIntRect visibleRect = pixelBounds.Intersect(aVisibleRect); - - if (!mOpaqueRegion.Contains(visibleRect)) { - nsRect buildingRect = aItem->GetBuildingRect(); - - if (aTransform) { - buildingRect = - aTransform->TransformRect(buildingRect, aState->mAppUnitsPerDevPixel); - } - - const nsRect tightBounds = componentAlphaBounds.Intersect(buildingRect); - - if (IsItemAreaInWindowOpaqueRegion(aState->mBuilder, aItem, tightBounds)) { - mNeedComponentAlpha = true; - } else { - // There is no opaque background below the item, disable component alpha. - aItem->DisableComponentAlpha(); - return false; - } - } - - return true; -} - -UniquePtr<InactiveLayerData> PaintedLayerData::CreateInactiveLayerData( - ContainerState* aState, nsPaintedDisplayItem* aItem, - DisplayItemData* aData) { - RefPtr<BasicLayerManager> tempManager; - if (aData) { - tempManager = aData->InactiveManager(); - } - if (!tempManager) { - tempManager = new BasicLayerManager(BasicLayerManager::BLM_INACTIVE); - } - UniquePtr<InactiveLayerData> data = MakeUnique<InactiveLayerData>(); - data->mLayerManager = tempManager; - - FrameLayerBuilder* layerBuilder = new FrameLayerBuilder(); - // Ownership of layerBuilder is passed to tempManager. - layerBuilder->Init(aState->Builder(), tempManager, this, true, - &aItem->GetClip()); - - tempManager->BeginTransaction(); - if (aState->LayerBuilder()->GetRetainingLayerManager()) { - layerBuilder->DidBeginRetainedLayerTransaction(tempManager); - } - - data->mProps = LayerProperties::CloneFrom(tempManager->GetRoot()); - data->mLayer = aItem->BuildLayer(aState->Builder(), tempManager, - ContainerLayerParameters()); - return data; -} - -void PaintedLayerData::Accumulate(ContainerState* aState, nsDisplayItem* aItem, - const nsIntRect& aVisibleRect, - const nsRect& aContentRect, - const DisplayItemClip& aClip, - LayerState aLayerState, nsDisplayList* aList, - DisplayItemEntryType aType, - nsTArray<size_t>& aOpacityIndices, - const RefPtr<TransformClipNode>& aTransform) { - if (aItem->HasHitTestInfo()) { - AccumulateHitTestItem(aState, aItem, aClip, aTransform); - } - - if (aItem->GetType() == DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO) { - // These items only carry hit test information. - return; - } - - nsPaintedDisplayItem* item = aItem->AsPaintedDisplayItem(); - // If aItem is nullptr, the cast to nsPaintedDisplayItem failed. - MOZ_ASSERT(item, "Can only accumulate display items that are painted!"); - - FLB_LOG_PAINTED_LAYER_DECISION( - this, "Accumulating dp=%s(%p), f=%p against pld=%p\n", item->Name(), item, - item->Frame(), this); - - const bool hasOpacity = aOpacityIndices.Length() > 0; - UpdateEffectStatus(aType, aOpacityIndices); - - const DisplayItemClip* oldClip = mItemClip; - mItemClip = &aClip; - - const bool isMerged = - item->AsDisplayWrapList() && item->AsDisplayWrapList()->HasMergedFrames(); - - if (IsEffectEndMarker(aType)) { - mAssignedDisplayItems.emplace_back(item, aLayerState, nullptr, aContentRect, - aType, hasOpacity, aTransform, isMerged); - return; - } - - bool clipMatches = - (oldClip == mItemClip) || (oldClip && *oldClip == *mItemClip); - - DisplayItemData* oldData = aState->mLayerBuilder->GetOldLayerForFrame( - item->Frame(), item->GetPerFrameKey()); - - mAssignedDisplayItems.emplace_back(item, aLayerState, oldData, aContentRect, - aType, hasOpacity, aTransform, isMerged); - - if (aLayerState != LayerState::LAYER_NONE) { - FLB_LOG_PAINTED_LAYER_DECISION(this, "Creating nested FLB for item %p\n", - item); - mAssignedDisplayItems.back().mInactiveLayerData = - CreateInactiveLayerData(aState, item, oldData); - } - - if (aState->mBuilder->NeedToForceTransparentSurfaceForItem(item)) { - mForceTransparentSurface = true; - } - - if (aState->mParameters.mDisableSubpixelAntialiasingInDescendants) { - // Disable component alpha. - // Note that the transform (if any) on the PaintedLayer is always an integer - // translation so we don't have to factor that in here. - item->DisableComponentAlpha(); - } else { - const bool needsComponentAlpha = - SetupComponentAlpha(aState, item, aVisibleRect, aTransform); - - if (needsComponentAlpha) { - // This display item needs background copy when pushing opacity group. - for (size_t i : aOpacityIndices) { - AssignedDisplayItem& item = mAssignedDisplayItems[i]; - MOZ_ASSERT(item.mType == DisplayItemEntryType::PushOpacity || - item.mType == DisplayItemEntryType::PushOpacityWithBg); - item.mType = DisplayItemEntryType::PushOpacityWithBg; - } - } - } - - if (aTransform && aType == DisplayItemEntryType::Item) { - // Bounds transformed with axis-aligned transforms could be included in the - // opaque region calculations. For simplicity, this is currently not done. - return; - } - - if (!mIsSolidColorInVisibleRegion && mOpaqueRegion.Contains(aVisibleRect) && - mVisibleRegion.Contains(aVisibleRect) && !mImage) { - // A very common case! Most pages have a PaintedLayer with the page - // background (opaque) visible and most or all of the page content over the - // top of that background. - // The rest of this method won't do anything. mVisibleRegion and - // mOpaqueRegion don't need updating. mVisibleRegion contains aVisibleRect - // already, mOpaqueRegion contains aVisibleRect and therefore whatever the - // opaque region of the item is. mVisibleRegion must contain mOpaqueRegion - // and therefore aVisibleRect. - return; - } - - nsIntRegion opaquePixels; - - // Active opacity means no opaque pixels. - if (!hasOpacity) { - opaquePixels = aState->ComputeOpaqueRect( - item, mAnimatedGeometryRoot, mASR, aClip, aList, &mHideAllLayersBelow, - &mOpaqueForAnimatedGeometryRootParent); - opaquePixels.AndWith(aVisibleRect); - } - - /* Mark as available for conversion to image layer if this is a nsDisplayImage - * and it's the only thing visible in this layer. - */ - if (nsIntRegion(aVisibleRect).Contains(mVisibleRegion) && - opaquePixels.Contains(mVisibleRegion) && - item->SupportsOptimizingToImage()) { - mImage = static_cast<nsDisplayImageContainer*>(item); - FLB_LOG_PAINTED_LAYER_DECISION( - this, " Tracking image: nsDisplayImageContainer covers the layer\n"); - } else if (mImage) { - FLB_LOG_PAINTED_LAYER_DECISION(this, " No longer tracking image\n"); - mImage = nullptr; - } - - bool isFirstVisibleItem = mVisibleRegion.IsEmpty(); - - Maybe<nscolor> uniformColor; - if (!hasOpacity) { - uniformColor = item->IsUniform(aState->mBuilder); - } - - // Some display items have to exist (so they can set forceTransparentSurface - // below) but don't draw anything. They'll return true for isUniform but - // a color with opacity 0. - if (!uniformColor || NS_GET_A(*uniformColor) > 0) { - // Make sure that the visible area is covered by uniform pixels. In - // particular this excludes cases where the edges of the item are not - // pixel-aligned (thus the item will not be truly uniform). - if (uniformColor) { - bool snap; - nsRect bounds = item->GetBounds(aState->mBuilder, &snap); - if (!aState->ScaleToInsidePixels(bounds, snap).Contains(aVisibleRect)) { - uniformColor = Nothing(); - FLB_LOG_PAINTED_LAYER_DECISION( - this, " Display item does not cover the visible rect\n"); - } - } - if (uniformColor) { - if (isFirstVisibleItem) { - // This color is all we have - mSolidColor = *uniformColor; - mIsSolidColorInVisibleRegion = true; - } else if (mIsSolidColorInVisibleRegion && - mVisibleRegion.IsEqual(nsIntRegion(aVisibleRect)) && - clipMatches) { - // we can just blend the colors together - mSolidColor = NS_ComposeColors(mSolidColor, *uniformColor); - } else { - FLB_LOG_PAINTED_LAYER_DECISION( - this, " Layer not a solid color: Can't blend colors togethers\n"); - mIsSolidColorInVisibleRegion = false; - } - } else { - FLB_LOG_PAINTED_LAYER_DECISION(this, - " Layer is not a solid color: Display " - "item is not uniform over the visible " - "bound\n"); - mIsSolidColorInVisibleRegion = false; - } - - mVisibleRegion.Or(mVisibleRegion, aVisibleRect); - mVisibleRegion.SimplifyOutward(4); - } - - if (!opaquePixels.IsEmpty()) { - for (auto iter = opaquePixels.RectIter(); !iter.Done(); iter.Next()) { - // We don't use SimplifyInward here since it's not defined exactly - // what it will discard. For our purposes the most important case - // is a large opaque background at the bottom of z-order (e.g., - // a canvas background), so we need to make sure that the first rect - // we see doesn't get discarded. - nsIntRegion tmp; - tmp.Or(mOpaqueRegion, iter.Get()); - // Opaque display items in chrome documents whose window is partially - // transparent are always added to the opaque region. This helps ensure - // that we get as much subpixel-AA as possible in the chrome. - if (tmp.GetNumRects() <= 4 || item->Frame()->PresContext()->IsChrome()) { - mOpaqueRegion = std::move(tmp); - } - } - } -} - -nsRegion PaintedLayerData::CombinedTouchActionRegion() { - nsRegion result; - result.Or(mHorizontalPanRegion, mVerticalPanRegion); - result.OrWith(mNoActionRegion); - return result; -} - -void PaintedLayerData::AccumulateHitTestItem(ContainerState* aState, - nsDisplayItem* aItem, - const DisplayItemClip& aClip, - TransformClipNode* aTransform) { - const auto& hitTestInfo = aItem->GetHitTestInfo(); - nsRect area = hitTestInfo.Area(); - const CompositorHitTestInfo& flags = hitTestInfo.Info(); - - FLB_LOG_PAINTED_LAYER_DECISION( - this, - "Accumulating hit test info %p against pld=%p, " - "area: [%d, %d, %d, %d], flags: 0x%x]\n", - aItem, this, area.x, area.y, area.width, area.height, flags.serialize()); - - area = aClip.ApplyNonRoundedIntersection(area); - - if (aTransform) { - area = aTransform->TransformRect(area, aState->mAppUnitsPerDevPixel); - } - - if (area.IsEmpty()) { - FLB_LOG_PAINTED_LAYER_DECISION( - this, "Discarded empty hit test info %p for pld=%p\n", aItem, this); - return; - } - - bool hasRoundedCorners = aClip.GetRoundedRectCount() > 0; - - // use the NS_FRAME_SIMPLE_EVENT_REGIONS to avoid calling the slightly - // expensive HasNonZeroCorner function if we know from a previous run that - // the frame has zero corners. - nsIFrame* frame = aItem->Frame(); - bool simpleRegions = frame->HasAnyStateBits(NS_FRAME_SIMPLE_EVENT_REGIONS); - if (!simpleRegions) { - if (nsLayoutUtils::HasNonZeroCorner(frame->StyleBorder()->mBorderRadius)) { - hasRoundedCorners = true; - } else { - frame->AddStateBits(NS_FRAME_SIMPLE_EVENT_REGIONS); - } - } - - if (hasRoundedCorners || frame->HasAnyStateBits(NS_FRAME_SVG_LAYOUT)) { - mMaybeHitRegion.OrWith(area); - } else { - mHitRegion.OrWith(area); - } - - const auto dtcFlags = flags & CompositorHitTestDispatchToContent; - if (!dtcFlags.isEmpty()) { - mDispatchToContentHitRegion.OrWith(area); - - if (flags.contains(CompositorHitTestFlags::eRequiresTargetConfirmation)) { - mDTCRequiresTargetConfirmation = true; - } - } - - const auto touchFlags = flags & CompositorHitTestTouchActionMask; - if (!touchFlags.isEmpty()) { - // If there are multiple touch-action areas, there are multiple elements - // with touch-action properties. We don't know what the relationship is - // between those elements in terms of DOM ancestry, and so we don't know how - // to combine the regions properly. Instead, we just add all the areas to - // the dispatch-to-content region, so that the APZ knows to check with the - // main thread. See bug 1286957. - if (mCollapsedTouchActions) { - mDispatchToContentHitRegion.OrWith(area); - } else if (touchFlags == CompositorHitTestTouchActionMask) { - // everything was disabled, so touch-action:none - mNoActionRegion.OrWith(area); - } else { - // The event regions code does not store enough information to actually - // represent all the different states. Prior to the introduction of - // CompositorHitTestInfo here in bug 1389149, the following two cases - // were effectively getting collapsed: - // (1) touch-action: auto - // (2) touch-action: manipulation - // In both of these cases, none of {mNoActionRegion, mHorizontalPanRegion, - // mVerticalPanRegion} were modified, and so the fact that case (2) should - // have prevented double-tap-zooming was getting lost. - // With CompositorHitTestInfo we can now represent that case correctly, - // but only if we use CompositorHitTestInfo all the way to the compositor - // (i.e. in the WebRender-enabled case). In the non-WebRender case where - // we still use the event regions, we must collapse these two cases back - // together. Or add another region to the event regions to fix this - // properly. - if (touchFlags != - CompositorHitTestFlags::eTouchActionDoubleTapZoomDisabled) { - if (!flags.contains(CompositorHitTestFlags::eTouchActionPanXDisabled)) { - // pan-x is allowed - mHorizontalPanRegion.OrWith(area); - } - if (!flags.contains(CompositorHitTestFlags::eTouchActionPanYDisabled)) { - // pan-y is allowed - mVerticalPanRegion.OrWith(area); - } - } else { - // the touch-action: manipulation case described above. To preserve the - // existing behaviour, don't touch either mHorizontalPanRegion or - // mVerticalPanRegion - } - } - } - - if (!mCollapsedTouchActions) { - // If there are multiple touch-action areas, there are multiple elements - // with touch-action properties. We don't know what the relationship is - // between those elements in terms of DOM ancestry, and so we don't know how - // to combine the regions properly. Instead, we just add all the areas to - // the dispatch-to-content region, so that the APZ knows to check with the - // main thread. See bug 1286957. - const int alreadyHadRegions = mNoActionRegion.GetNumRects() + - mHorizontalPanRegion.GetNumRects() + - mVerticalPanRegion.GetNumRects(); - - if (alreadyHadRegions > 1) { - mDispatchToContentHitRegion.OrWith(CombinedTouchActionRegion()); - mNoActionRegion.SetEmpty(); - mHorizontalPanRegion.SetEmpty(); - mVerticalPanRegion.SetEmpty(); - mCollapsedTouchActions = true; - } - } - - // Avoid quadratic performance as a result of the region growing to include - // and arbitrarily large number of rects, which can happen on some pages. - mMaybeHitRegion.SimplifyOutward(8); - mDispatchToContentHitRegion.SimplifyOutward(8); - - HitRegionsUpdated(); -} - -void PaintedLayerData::HitRegionsUpdated() { - // Calculate scaled versions of the bounds of mHitRegion and mMaybeHitRegion - // for quick access in FindPaintedLayerFor(). - mScaledHitRegionBounds = mState->ScaleToOutsidePixels(mHitRegion.GetBounds()); - mScaledMaybeHitRegionBounds = - mState->ScaleToOutsidePixels(mMaybeHitRegion.GetBounds()); -} - -void ContainerState::NewPaintedLayerData( - PaintedLayerData* aData, AnimatedGeometryRoot* aAnimatedGeometryRoot, - const ActiveScrolledRoot* aASR, const DisplayItemClipChain* aClipChain, - const ActiveScrolledRoot* aScrollMetadataASR, const nsPoint& aTopLeft, - const nsIFrame* aReferenceFrame, const bool aBackfaceHidden) { - aData->mState = this; - aData->mAnimatedGeometryRoot = aAnimatedGeometryRoot; - aData->mASR = aASR; - aData->mClipChain = aClipChain; - aData->mAnimatedGeometryRootOffset = aTopLeft; - aData->mReferenceFrame = aReferenceFrame; - aData->mBackfaceHidden = aBackfaceHidden; - - aData->mNewChildLayersIndex = mNewChildLayers.Length(); - NewLayerEntry* newLayerEntry = mNewChildLayers.AppendElement(); - newLayerEntry->mAnimatedGeometryRoot = aAnimatedGeometryRoot; - newLayerEntry->mASR = aASR; - newLayerEntry->mScrollMetadataASR = aScrollMetadataASR; - newLayerEntry->mClipChain = aClipChain; - // newLayerEntry->mOpaqueRegion is filled in later from - // paintedLayerData->mOpaqueRegion, if necessary. - - // Allocate another entry for this layer's optimization to - // ColorLayer/ImageLayer - mNewChildLayers.AppendElement(); -} - -#ifdef MOZ_DUMP_PAINTING -static void DumpPaintedImage(nsDisplayItem* aItem, SourceSurface* aSurface) { - nsCString string(aItem->Name()); - string.Append('-'); - string.AppendInt((uint64_t)aItem); - fprintf_stderr(gfxUtils::sDumpPaintFile, "<script>array[\"%s\"]=\"", - string.BeginReading()); - gfxUtils::DumpAsDataURI(aSurface, gfxUtils::sDumpPaintFile); - fprintf_stderr(gfxUtils::sDumpPaintFile, "\";</script>\n"); -} -#endif - -static void PaintInactiveLayer(nsDisplayListBuilder* aBuilder, - LayerManager* aManager, nsDisplayItem* aItem, - gfxContext* aContext, gfxContext* aCtx) { - // This item has an inactive layer. Render it to a PaintedLayer - // using a temporary BasicLayerManager. - BasicLayerManager* basic = static_cast<BasicLayerManager*>(aManager); - RefPtr<gfxContext> context = aContext; -#ifdef MOZ_DUMP_PAINTING - int32_t appUnitsPerDevPixel = AppUnitsPerDevPixel(aItem); - nsIntRect itemVisibleRect = - aItem->GetPaintRect().ToOutsidePixels(appUnitsPerDevPixel); - - RefPtr<DrawTarget> tempDT; - if (gfxEnv::DumpPaint()) { - tempDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget( - itemVisibleRect.Size(), SurfaceFormat::B8G8R8A8); - if (tempDT) { - context = gfxContext::CreateOrNull(tempDT); - if (!context) { - // Leave this as crash, it's in the debugging code, we want to know - gfxDevCrash(LogReason::InvalidContext) - << "PaintInactive context problem " << gfx::hexa(tempDT); - return; - } - context->SetMatrix( - Matrix::Translation(-itemVisibleRect.x, -itemVisibleRect.y)); - } - } -#endif - basic->BeginTransaction(); - basic->SetTarget(context); - - if (aItem->GetType() == DisplayItemType::TYPE_MASK) { - static_cast<nsDisplayMasksAndClipPaths*>(aItem)->PaintAsLayer(aBuilder, - aCtx, basic); - if (basic->InTransaction()) { - basic->AbortTransaction(); - } - } else if (aItem->GetType() == DisplayItemType::TYPE_FILTER) { - static_cast<nsDisplayFilters*>(aItem)->PaintAsLayer(aBuilder, aCtx, basic); - if (basic->InTransaction()) { - basic->AbortTransaction(); - } - } else { - basic->EndTransaction(FrameLayerBuilder::DrawPaintedLayer, aBuilder); - } - FrameLayerBuilder* builder = static_cast<FrameLayerBuilder*>( - basic->GetUserData(&gLayerManagerLayerBuilder)); - if (builder) { - builder->DidEndTransaction(); - } - - basic->SetTarget(nullptr); - -#ifdef MOZ_DUMP_PAINTING - if (gfxEnv::DumpPaint() && tempDT) { - RefPtr<SourceSurface> surface = tempDT->Snapshot(); - DumpPaintedImage(aItem, surface); - - DrawTarget* drawTarget = aContext->GetDrawTarget(); - Rect rect(itemVisibleRect.x, itemVisibleRect.y, itemVisibleRect.width, - itemVisibleRect.height); - drawTarget->DrawSurface(surface, rect, Rect(Point(0, 0), rect.Size())); - - aItem->SetPainted(); - } -#endif -} - -nsRect ContainerState::GetDisplayPortForAnimatedGeometryRoot( - AnimatedGeometryRoot* aAnimatedGeometryRoot) { - if (mLastDisplayPortAGR == aAnimatedGeometryRoot) { - return mLastDisplayPortRect; - } - - mLastDisplayPortAGR = aAnimatedGeometryRoot; - - nsIScrollableFrame* sf = - nsLayoutUtils::GetScrollableFrameFor(*aAnimatedGeometryRoot); - if (sf == nullptr || - nsLayoutUtils::UsesAsyncScrolling(*aAnimatedGeometryRoot)) { - mLastDisplayPortRect = nsRect(); - return mLastDisplayPortRect; - } - - bool usingDisplayport = DisplayPortUtils::GetDisplayPort( - (*aAnimatedGeometryRoot)->GetContent(), &mLastDisplayPortRect, - DisplayPortOptions().With(DisplayportRelativeTo::ScrollFrame)); - if (!usingDisplayport) { - // No async scrolling, so all that matters is that the layer contents - // cover the scrollport. - mLastDisplayPortRect = sf->GetScrollPortRect(); - } - nsIFrame* scrollFrame = do_QueryFrame(sf); - mLastDisplayPortRect += - scrollFrame->GetOffsetToCrossDoc(mContainerReferenceFrame); - return mLastDisplayPortRect; -} - -nsIntRegion ContainerState::ComputeOpaqueRect( - nsDisplayItem* aItem, AnimatedGeometryRoot* aAnimatedGeometryRoot, - const ActiveScrolledRoot* aASR, const DisplayItemClip& aClip, - nsDisplayList* aList, bool* aHideAllLayersBelow, - bool* aOpaqueForAnimatedGeometryRootParent) { - bool snapOpaque; - nsRegion opaque = aItem->GetOpaqueRegion(mBuilder, &snapOpaque); - MOZ_ASSERT(!opaque.IsComplex()); - if (opaque.IsEmpty()) { - return nsIntRegion(); - } - - nsIntRegion opaquePixels; - nsRegion opaqueClipped; - for (auto iter = opaque.RectIter(); !iter.Done(); iter.Next()) { - opaqueClipped.Or(opaqueClipped, - aClip.ApproximateIntersectInward(iter.Get())); - } - if (aAnimatedGeometryRoot == mContainerAnimatedGeometryRoot && - aASR == mContainerASR && opaqueClipped.Contains(mContainerBounds)) { - *aHideAllLayersBelow = true; - aList->SetIsOpaque(); - } - // Add opaque areas to the "exclude glass" region. Only do this when our - // container layer is going to be the rootmost layer, otherwise transforms - // etc will mess us up (and opaque contributions from other containers are - // not needed). - if (!nsLayoutUtils::GetCrossDocParentFrameInProcess(mContainerFrame)) { - mBuilder->AddWindowOpaqueRegion(aItem->Frame(), opaqueClipped.GetBounds()); - } - opaquePixels = ScaleRegionToInsidePixels(opaqueClipped, snapOpaque); - - if (IsInInactiveLayer()) { - return opaquePixels; - } - - const nsRect& displayport = - GetDisplayPortForAnimatedGeometryRoot(aAnimatedGeometryRoot); - if (!displayport.IsEmpty() && - opaquePixels.Contains(ScaleRegionToNearestPixels(displayport))) { - *aOpaqueForAnimatedGeometryRootParent = true; - } - return opaquePixels; -} - -Maybe<size_t> ContainerState::SetupMaskLayerForScrolledClip( - Layer* aLayer, const DisplayItemClip& aClip) { - if (aClip.GetRoundedRectCount() > 0) { - Maybe<size_t> maskLayerIndex = Some(aLayer->GetAncestorMaskLayerCount()); - if (RefPtr<Layer> maskLayer = - CreateMaskLayer(aLayer, aClip, maskLayerIndex)) { - aLayer->AddAncestorMaskLayer(maskLayer); - return maskLayerIndex; - } - // Fall through to |return Nothing()|. - } - return Nothing(); -} - -static const ActiveScrolledRoot* GetASRForPerspective( - const ActiveScrolledRoot* aASR, nsIFrame* aPerspectiveFrame) { - for (const ActiveScrolledRoot* asr = aASR; asr; asr = asr->mParent) { - nsIFrame* scrolledFrame = asr->mScrollableFrame->GetScrolledFrame(); - // In OOP documents, the root scrollable frame of the in-process root - // document is always active, so using IsAncestorFrameCrossDocInProcess - // should be fine here. - if (nsLayoutUtils::IsAncestorFrameCrossDocInProcess(scrolledFrame, - aPerspectiveFrame)) { - return asr; - } - } - return nullptr; -} - -static CSSMaskLayerUserData* GetCSSMaskLayerUserData(Layer* aMaskLayer) { - if (!aMaskLayer) { - return nullptr; - } - - return static_cast<CSSMaskLayerUserData*>( - aMaskLayer->GetUserData(&gCSSMaskLayerUserData)); -} - -static void SetCSSMaskLayerUserData(Layer* aMaskLayer) { - MOZ_ASSERT(aMaskLayer); - - aMaskLayer->SetUserData(&gCSSMaskLayerUserData, new CSSMaskLayerUserData()); -} - -void ContainerState::SetupMaskLayerForCSSMask( - Layer* aLayer, nsDisplayMasksAndClipPaths* aMaskItem) { - RefPtr<ImageLayer> maskLayer = CreateOrRecycleMaskImageLayerFor( - MaskLayerKey(aLayer, Nothing()), GetCSSMaskLayerUserData, - SetCSSMaskLayerUserData); - CSSMaskLayerUserData* oldUserData = GetCSSMaskLayerUserData(maskLayer.get()); - MOZ_ASSERT(oldUserData); - - bool snap; - nsRect bounds = aMaskItem->GetBounds(mBuilder, &snap); - nsIntRect itemRect = ScaleToOutsidePixels(bounds, snap); - - // Setup mask layer offset. - // We do not repaint mask for mask position change, so update base transform - // each time is required. - Matrix4x4 matrix; - matrix.PreTranslate(itemRect.x, itemRect.y, 0); - matrix.PreTranslate(mParameters.mOffset.x, mParameters.mOffset.y, 0); - maskLayer->SetBaseTransform(matrix); - - nsPoint maskLayerOffset = aMaskItem->ToReferenceFrame() - bounds.TopLeft(); - - CSSMaskLayerUserData newUserData(aMaskItem->Frame(), itemRect, - maskLayerOffset); - nsRect dirtyRect; - if (!aMaskItem->IsInvalid(dirtyRect) && *oldUserData == newUserData) { - aLayer->SetMaskLayer(maskLayer); - return; - } - - int32_t maxSize = mManager->GetMaxTextureSize(); - IntSize surfaceSize(std::min(itemRect.width, maxSize), - std::min(itemRect.height, maxSize)); - - if (surfaceSize.IsEmpty()) { - // Return early if we know that the size of this mask surface is empty. - return; - } - - MaskImageData imageData(surfaceSize, mManager); - RefPtr<DrawTarget> dt = imageData.CreateDrawTarget(); - if (!dt || !dt->IsValid()) { - NS_WARNING("Could not create DrawTarget for mask layer."); - return; - } - - RefPtr<gfxContext> maskCtx = gfxContext::CreateOrNull(dt); - maskCtx->SetMatrix(Matrix::Translation(-itemRect.TopLeft())); - maskCtx->Multiply( - gfxMatrix::Scaling(mParameters.mXScale, mParameters.mYScale)); - - bool isPaintFinished = aMaskItem->PaintMask(mBuilder, maskCtx); - - RefPtr<ImageContainer> imgContainer = - imageData.CreateImageAndImageContainer(); - if (!imgContainer) { - return; - } - maskLayer->SetContainer(imgContainer); - - if (isPaintFinished) { - *oldUserData = std::move(newUserData); - } - aLayer->SetMaskLayer(maskLayer); -} - -static bool IsScrollThumbLayer(nsDisplayItem* aItem) { - return aItem->GetType() == DisplayItemType::TYPE_OWN_LAYER && - static_cast<nsDisplayOwnLayer*>(aItem)->IsScrollThumbLayer(); -} - -template <typename ClearFn, typename SelectFn> -static void ProcessDisplayItemMarker(DisplayItemEntryType aMarker, - ClearFn ClearLayerSelectionIfNeeded, - SelectFn SelectLayerIfNeeded) { - switch (aMarker) { - case DisplayItemEntryType::PushTransform: - case DisplayItemEntryType::PushOpacity: - SelectLayerIfNeeded(); - break; - case DisplayItemEntryType::PopTransform: - case DisplayItemEntryType::PopOpacity: - ClearLayerSelectionIfNeeded(); - break; - default: - break; - } -} -/* - * Iterate through the non-clip items in aList and its descendants. - * For each item we compute the effective clip rect. Each item is assigned - * to a layer. We invalidate the areas in PaintedLayers where an item - * has moved from one PaintedLayer to another. Also, - * aState->mInvalidPaintedContent is invalidated in every PaintedLayer. - * We set the clip rect for items that generated their own layer, and - * create a mask layer to do any rounded rect clipping. - * (PaintedLayers don't need a clip rect on the layer, we clip the items - * individually when we draw them.) - * We set the visible rect for all layers, although the actual setting - * of visible rects for some PaintedLayers is deferred until the calling - * of ContainerState::Finish. - */ -void ContainerState::ProcessDisplayItems(nsDisplayList* aList) { - AUTO_PROFILER_LABEL("ContainerState::ProcessDisplayItems", - GRAPHICS_LayerBuilding); - PerfStats::AutoMetricRecording<PerfStats::Metric::LayerBuilding> - autoRecording; - - nsPoint topLeft(0, 0); - - int32_t maxLayers = StaticPrefs::layers_max_active(); - int layerCount = 0; - - if (!mManager->IsWidgetLayerManager()) { - mPaintedLayerDataTree.InitializeForInactiveLayer( - mContainerAnimatedGeometryRoot); - } - - AnimatedGeometryRoot* lastAnimatedGeometryRoot = nullptr; - nsPoint lastTopLeft; - - // Tracks the PaintedLayerData that the item will be accumulated in, if it is - // non-null. - PaintedLayerData* selectedLayer = nullptr; - AutoTArray<size_t, 2> opacityIndices; - - // AGR and ASR for the container item that was flattened. - AnimatedGeometryRoot* containerAGR = nullptr; - const ActiveScrolledRoot* containerASR = nullptr; - nsIFrame* containerReferenceFrame = nullptr; - RefPtr<TransformClipNode> transformNode = nullptr; - - const auto InTransform = [&]() { return transformNode; }; - - const auto InOpacity = [&]() { - return selectedLayer && opacityIndices.Length() > 0; - }; - - FLBDisplayListIterator iter(mBuilder, aList, this); - while (iter.HasNext()) { - DisplayItemEntry e = iter.GetNextEntry(); - DisplayItemEntryType marker = e.mType; - nsDisplayItem* item = e.mItem; - MOZ_ASSERT(item); - DisplayItemType itemType = item->GetType(); - const bool isHitTestItem = - itemType == DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO; - - NS_ASSERTION(mAppUnitsPerDevPixel == AppUnitsPerDevPixel(item), - "items in a container layer should all have the same app " - "units per dev pixel"); - - if (mBuilder->NeedToForceTransparentSurfaceForItem(item)) { - aList->SetNeedsTransparentSurface(); - } - - LayerState layerState = LayerState::LAYER_NONE; - if (marker == DisplayItemEntryType::Item) { - layerState = item->GetLayerState(mBuilder, mManager, mParameters); - - if (layerState == LayerState::LAYER_INACTIVE && - nsDisplayItem::ForceActiveLayers()) { - layerState = LayerState::LAYER_ACTIVE; - } - } - - AnimatedGeometryRoot* itemAGR = item->GetAnimatedGeometryRoot(); - const ActiveScrolledRoot* itemASR = item->GetActiveScrolledRoot(); - const DisplayItemClipChain* itemClipChain = item->GetClipChain(); - const DisplayItemClipChain* layerClipChain = nullptr; - const DisplayItemClip* itemClipPtr = &item->GetClip(); - - const bool inEffect = InTransform() || InOpacity(); - if (mManager->IsWidgetLayerManager() && !inEffect) { - if (itemClipChain && itemClipChain->mASR == itemASR && - itemType != DisplayItemType::TYPE_STICKY_POSITION) { - layerClipChain = itemClipChain->mParent; - } else { - layerClipChain = itemClipChain; - } - } else { - // Inside a flattened effect or inactive layer, use container AGR and ASR. - itemAGR = inEffect ? containerAGR : mContainerAnimatedGeometryRoot; - itemASR = inEffect ? containerASR : mContainerASR; - - if (!IsEffectEndMarker(marker)) { - // No need to fuse clip chain for effect end markers, since it was - // already done for effect start markers. - item->FuseClipChainUpTo(mBuilder, itemASR); - itemClipChain = item->GetClipChain(); - } - - itemClipPtr = itemClipChain ? &itemClipChain->mClip : nullptr; - } - - const DisplayItemClip& itemClip = - itemClipPtr ? *itemClipPtr : DisplayItemClip::NoClip(); - - if (inEffect && marker == DisplayItemEntryType::Item) { - // Fast-path for items inside flattened inactive layers. This works - // because the layer state of the item cannot be active, otherwise the - // parent item would not have been flattened. - MOZ_ASSERT(selectedLayer); - selectedLayer->Accumulate(this, item, nsIntRect(), nsRect(), itemClip, - layerState, aList, marker, opacityIndices, - transformNode); - continue; - } - - // Items outside of flattened effects and non-item markers inside flattened - // effects are processed here. - MOZ_ASSERT(!inEffect || (marker != DisplayItemEntryType::Item)); - - if (itemAGR == lastAnimatedGeometryRoot) { - topLeft = lastTopLeft; - } else { - lastTopLeft = topLeft = - (*itemAGR)->GetOffsetToCrossDoc(mContainerReferenceFrame); - lastAnimatedGeometryRoot = itemAGR; - } - - const ActiveScrolledRoot* scrollMetadataASR = - layerClipChain - ? ActiveScrolledRoot::PickDescendant(itemASR, layerClipChain->mASR) - : itemASR; - - const bool prerenderedTransform = - itemType == DisplayItemType::TYPE_TRANSFORM && - static_cast<nsDisplayTransform*>(item)->MayBeAnimated(mBuilder); - - bool snap = false; - nsRect itemContent = isHitTestItem ? item->GetHitTestInfo().Area() - : item->GetBounds(mBuilder, &snap); - - nsIntRect itemDrawRect = ScaleToOutsidePixels(itemContent, snap); - ParentLayerIntRect clipRect; - if (itemClip.HasClip()) { - const nsRect& itemClipRect = itemClip.GetClipRect(); - itemContent.IntersectRect(itemContent, itemClipRect); - clipRect = ViewAs<ParentLayerPixel>(ScaleToNearestPixels(itemClipRect)); - - if (!prerenderedTransform && !IsScrollThumbLayer(item)) { - itemDrawRect.IntersectRect(itemDrawRect, clipRect.ToUnknownRect()); - } - - clipRect.MoveBy(ViewAs<ParentLayerPixel>(mParameters.mOffset)); - } - - if (marker == DisplayItemEntryType::PopTransform) { - MOZ_ASSERT(transformNode); - transformNode = transformNode->Parent(); - } - - nsRect itemVisibleRectAu = itemContent; - if (transformNode) { - // If we are within transform, transform itemContent and itemDrawRect. - MOZ_ASSERT(transformNode); - - itemContent = - transformNode->TransformRect(itemContent, mAppUnitsPerDevPixel); - - itemDrawRect = transformNode->TransformRect(itemDrawRect); - } - -#ifdef DEBUG - nsRect bounds = itemContent; - - if (inEffect || isHitTestItem) { - bounds.SetEmpty(); - } - - if (!bounds.IsEmpty() && itemASR != mContainerASR) { - if (Maybe<nsRect> clip = - item->GetClipWithRespectToASR(mBuilder, mContainerASR)) { - bounds = clip.ref(); - } - } - - ((nsRect&)mAccumulatedChildBounds) - .UnionRect(mAccumulatedChildBounds, bounds); -#endif - - nsIntRect itemVisibleRect = itemDrawRect; - - // We intersect the building rect with the clipped item bounds to get a - // tighter visible rect. - if (!prerenderedTransform) { - nsRect itemBuildingRect = item->GetBuildingRect(); - - if (transformNode) { - itemBuildingRect = transformNode->TransformRect(itemBuildingRect, - mAppUnitsPerDevPixel); - } - - itemVisibleRect = itemVisibleRect.Intersect( - ScaleToOutsidePixels(itemBuildingRect, false)); - } - - const bool forceInactive = maxLayers != -1 && layerCount >= maxLayers; - - // Assign the item to a layer - bool treatInactiveItemAsActive = - (layerState == LayerState::LAYER_INACTIVE && - mLayerBuilder->GetContainingPaintedLayerData()); - if (layerState == LayerState::LAYER_ACTIVE_FORCE || - treatInactiveItemAsActive || - (!forceInactive && (layerState == LayerState::LAYER_ACTIVE_EMPTY || - layerState == LayerState::LAYER_ACTIVE))) { - layerCount++; - - // Currently we do not support flattening effects within nested inactive - // layer trees. - MOZ_ASSERT(selectedLayer == nullptr); - MOZ_ASSERT(marker == DisplayItemEntryType::Item); - - // LayerState::LAYER_ACTIVE_EMPTY means the layer is created just for its - // metadata. We should never see an empty layer with any visible content! - NS_ASSERTION( - layerState != LayerState::LAYER_ACTIVE_EMPTY || - itemVisibleRect.IsEmpty(), - "State is LayerState::LAYER_ACTIVE_EMPTY but visible rect is not."); - - // As long as the new layer isn't going to be a PaintedLayer, - // InvalidateForLayerChange doesn't need the new layer pointer. - // We also need to check the old data now, because BuildLayer - // can overwrite it. - DisplayItemData* oldData = mLayerBuilder->GetOldLayerForFrame( - item->Frame(), item->GetPerFrameKey()); - InvalidateForLayerChange(item, nullptr, oldData); - - // 3D-transformed layers don't necessarily draw in the order in which - // they're added to their parent container layer. - bool mayDrawOutOfOrder = itemType == DisplayItemType::TYPE_TRANSFORM && - (item->Combines3DTransformWithAncestors() || - item->Frame()->Extend3DContext()); - - // Let mPaintedLayerDataTree know about this item, so that - // FindPaintedLayerFor and FindOpaqueBackgroundColor are aware of this - // item, even though it's not in any PaintedLayerDataStack. - // Ideally we'd only need the "else" case here and have - // mPaintedLayerDataTree figure out the right clip from the animated - // geometry root that we give it, but it can't easily figure about - // overflow:hidden clips on ancestors just by looking at the frame. - // So we'll do a little hand holding and pass the clip instead of the - // visible rect for the two important cases. - nscolor uniformColor = NS_RGBA(0, 0, 0, 0); - nscolor* uniformColorPtr = - (mayDrawOutOfOrder || IsInInactiveLayer()) ? nullptr : &uniformColor; - nsIntRect clipRectUntyped; - nsIntRect* clipPtr = nullptr; - if (itemClip.HasClip()) { - clipRectUntyped = clipRect.ToUnknownRect(); - clipPtr = &clipRectUntyped; - } - - bool isStickyNotClippedToDisplayPort = - itemType == DisplayItemType::TYPE_STICKY_POSITION && - !static_cast<nsDisplayStickyPosition*>(item) - ->IsClippedToDisplayPort(); - bool hasScrolledClip = - layerClipChain && layerClipChain->mClip.HasClip() && - (!ActiveScrolledRoot::IsAncestor(layerClipChain->mASR, itemASR) || - isStickyNotClippedToDisplayPort); - - if (hasScrolledClip) { - // If the clip is scrolled, reserve just the area of the clip for - // layerization, so that elements outside the clip can still merge - // into the same layer. - const ActiveScrolledRoot* clipASR = layerClipChain->mASR; - AnimatedGeometryRoot* clipAGR = - mBuilder->AnimatedGeometryRootForASR(clipASR); - nsIntRect scrolledClipRect = - ScaleToNearestPixels(layerClipChain->mClip.GetClipRect()) + - mParameters.mOffset; - mPaintedLayerDataTree.AddingOwnLayer(clipAGR, &scrolledClipRect, - uniformColorPtr); - } else if (item->ShouldFixToViewport(mBuilder) && itemClip.HasClip() && - item->AnimatedGeometryRootForScrollMetadata() != itemAGR && - !nsLayoutUtils::UsesAsyncScrolling(item->Frame())) { - // This is basically the same as the case above, but for the non-APZ - // case. At the moment, when APZ is off, there is only the root ASR - // (because scroll frames without display ports don't create ASRs) and - // the whole clip chain is always just one fused clip. - // Bug 1336516 aims to change that and to remove this workaround. - AnimatedGeometryRoot* clipAGR = - item->AnimatedGeometryRootForScrollMetadata(); - nsIntRect scrolledClipRect = - ScaleToNearestPixels(itemClip.GetClipRect()) + mParameters.mOffset; - mPaintedLayerDataTree.AddingOwnLayer(clipAGR, &scrolledClipRect, - uniformColorPtr); - } else if (IsScrollThumbLayer(item) && mManager->IsWidgetLayerManager()) { - // For scrollbar thumbs, the clip we care about is the clip added by the - // slider frame. - mPaintedLayerDataTree.AddingOwnLayer(itemAGR->mParentAGR, clipPtr, - uniformColorPtr); - } else if (prerenderedTransform && mManager->IsWidgetLayerManager()) { - if (itemAGR->mParentAGR) { - mPaintedLayerDataTree.AddingOwnLayer(itemAGR->mParentAGR, clipPtr, - uniformColorPtr); - } else { - mPaintedLayerDataTree.AddingOwnLayer(itemAGR, nullptr, - uniformColorPtr); - } - } else { - // Using itemVisibleRect here isn't perfect. itemVisibleRect can be - // larger or smaller than the potential bounds of item's contents in - // itemAGR: It's too large if there's a clipped display - // port somewhere among item's contents (see bug 1147673), and it can - // be too small if the contents can move, because it only looks at the - // contents' current bounds and doesn't anticipate any animations. - // Time will tell whether this is good enough, or whether we need to do - // something more sophisticated here. - mPaintedLayerDataTree.AddingOwnLayer(itemAGR, &itemVisibleRect, - uniformColorPtr); - } - - ContainerLayerParameters params = mParameters; - params.mBackgroundColor = uniformColor; - params.mLayerCreationHint = GetLayerCreationHint(itemAGR); - if (!transformNode) { - params.mItemVisibleRect = &itemVisibleRectAu; - } else { - // We only use mItemVisibleRect for getting the visible rect for - // remote browsers (which should never have inactive transforms), so we - // avoid doing transforms on itemVisibleRectAu above and can't report - // an accurate bounds here. - params.mItemVisibleRect = nullptr; - } - params.mScrollMetadataASR = - ActiveScrolledRoot::IsAncestor(scrollMetadataASR, - mContainerScrollMetadataASR) - ? mContainerScrollMetadataASR - : scrollMetadataASR; - params.mCompositorASR = - params.mScrollMetadataASR != mContainerScrollMetadataASR - ? params.mScrollMetadataASR - : mContainerCompositorASR; - if (itemType == DisplayItemType::TYPE_FIXED_POSITION) { - params.mCompositorASR = itemASR; - } - - // Perspective items have a single child item, an nsDisplayTransform. - // If the perspective item is scrolled, but the perspective-inducing - // frame is outside the scroll frame (indicated by item->Frame() - // being outside that scroll frame), we have to take special care to - // make APZ scrolling work properly. APZ needs us to put the scroll - // frame's FrameMetrics on our child transform ContainerLayer instead. - // We make a similar adjustment for OwnLayer items built for frames - // with perspective transforms (e.g. when they have rounded corners). - // It's worth investigating whether this ASR adjustment can be done at - // display item creation time. - bool deferASRForPerspective = - itemType == DisplayItemType::TYPE_PERSPECTIVE || - (itemType == DisplayItemType::TYPE_OWN_LAYER && - item->Frame()->IsTransformed() && item->Frame()->HasPerspective()); - if (deferASRForPerspective) { - scrollMetadataASR = GetASRForPerspective( - scrollMetadataASR, - item->Frame()->GetClosestFlattenedTreeAncestorPrimaryFrame()); - params.mScrollMetadataASR = scrollMetadataASR; - itemASR = scrollMetadataASR; - } - - // Just use its layer. - // Set layerContentsVisibleRect.width/height to -1 to indicate we - // currently don't know. If BuildContainerLayerFor gets called by - // item->BuildLayer, this will be set to a proper rect. - nsIntRect layerContentsVisibleRect(0, 0, -1, -1); - params.mLayerContentsVisibleRect = &layerContentsVisibleRect; - - // If this display item wants to build inactive layers but we are treating - // it as active because we are already inside an inactive layer tree, - // we need to make sure that the display item's clip is reflected in - // FrameLayerBuilder::mInactiveLayerClip (which is normally set in - // AddPaintedDisplayItem() when entering an inactive layer tree). - // We intersect the display item's clip into any existing inactive layer - // clip. - const DisplayItemClip* originalInactiveClip = nullptr; - DisplayItemClip combinedInactiveClip; - if (treatInactiveItemAsActive) { - originalInactiveClip = mLayerBuilder->GetInactiveLayerClip(); - if (originalInactiveClip) { - combinedInactiveClip = *originalInactiveClip; - } - DisplayItemClip nestedClip = item->GetClip(); - if (nestedClip.HasClip()) { - nsRect nestedClipRect = nestedClip.NonRoundedIntersection(); - - // Transform the nested clip to be relative to the same reference - // frame as the existing mInactiveLayerClip, so that we can intersect - // them below. - nestedClipRect = nsLayoutUtils::TransformFrameRectToAncestor( - item->ReferenceFrame(), nestedClipRect, - mLayerBuilder->GetContainingPaintedLayerData()->mReferenceFrame); - - nestedClip.SetTo(nestedClipRect); - combinedInactiveClip.IntersectWith(nestedClip); - mLayerBuilder->SetInactiveLayerClip(&combinedInactiveClip); - } - } - - RefPtr<Layer> ownLayer = - item->AsPaintedDisplayItem()->BuildLayer(mBuilder, mManager, params); - - // If above we combined a nested clip into mInactiveLayerClip, restore - // the original inactive layer clip here. - if (treatInactiveItemAsActive) { - mLayerBuilder->SetInactiveLayerClip(originalInactiveClip); - } - - if (!ownLayer) { - continue; - } - - NS_ASSERTION(!ownLayer->AsPaintedLayer(), - "Should never have created a dedicated Painted layer!"); - - SetBackfaceHiddenForLayer(item->BackfaceIsHidden(), ownLayer); - - nsRect invalid; - if (item->IsInvalid(invalid)) { - ownLayer->SetInvalidRectToVisibleRegion(); - } - - // If it's not a ContainerLayer, we need to apply the scale transform - // ourselves. - if (!ownLayer->AsContainerLayer()) { - ownLayer->SetPostScale(mParameters.mXScale, mParameters.mYScale); - } - - // Update that layer's clip and visible rects. - NS_ASSERTION(ownLayer->Manager() == mManager, "Wrong manager"); - NS_ASSERTION(!ownLayer->HasUserData(&gLayerManagerUserData), - "We shouldn't have a FrameLayerBuilder-managed layer here!"); - NS_ASSERTION(itemClip.HasClip() || itemClip.GetRoundedRectCount() == 0, - "If we have rounded rects, we must have a clip rect"); - - // It has its own layer. Update that layer's clip and visible rects. - ownLayer->SetClipRect(Nothing()); - ownLayer->SetScrolledClip(Nothing()); - ownLayer->SetAncestorMaskLayers({}); - if (itemClip.HasClip()) { - ownLayer->SetClipRect(Some(clipRect)); - - // rounded rectangle clipping using mask layers - // (must be done after visible rect is set on layer) - if (itemClip.GetRoundedRectCount() > 0) { - SetupMaskLayer(ownLayer, itemClip); - } - } - - if (hasScrolledClip) { - const DisplayItemClip& scrolledClip = layerClipChain->mClip; - LayerClip scrolledLayerClip; - scrolledLayerClip.SetClipRect(ViewAs<ParentLayerPixel>( - ScaleToNearestPixels(scrolledClip.GetClipRect()) + - mParameters.mOffset)); - if (scrolledClip.GetRoundedRectCount() > 0) { - scrolledLayerClip.SetMaskLayerIndex( - SetupMaskLayerForScrolledClip(ownLayer.get(), scrolledClip)); - } - ownLayer->SetScrolledClip(Some(scrolledLayerClip)); - } - - if (item->GetType() == DisplayItemType::TYPE_MASK) { - MOZ_ASSERT(itemClip.GetRoundedRectCount() == 0); - - nsDisplayMasksAndClipPaths* maskItem = - static_cast<nsDisplayMasksAndClipPaths*>(item); - SetupMaskLayerForCSSMask(ownLayer, maskItem); - - if (iter.PeekNext() && iter.PeekNext()->GetType() == - DisplayItemType::TYPE_SCROLL_INFO_LAYER) { - // Since we do build a layer for mask, there is no need for this - // scroll info layer anymore. - iter.GetNextItem(); - } - } - - // Convert the visible rect to a region and give the item - // a chance to try restrict it further. - nsIntRegion itemVisibleRegion = itemVisibleRect; - nsRegion tightBounds = item->GetTightBounds(mBuilder, &snap); - if (!tightBounds.IsEmpty()) { - itemVisibleRegion.AndWith( - ScaleRegionToOutsidePixels(tightBounds, snap)); - } - - ContainerLayer* oldContainer = ownLayer->GetParent(); - if (oldContainer && oldContainer != mContainerLayer) { - oldContainer->RemoveChild(ownLayer); - } - NS_ASSERTION(FindIndexOfLayerIn(mNewChildLayers, ownLayer) < 0, - "Layer already in list???"); - - // NewLayerEntry::mClipChain is used by SetupScrollingMetadata() to - // populate any scroll clips in the scroll metadata. Perspective layers - // have their ASR adjusted such that a scroll metadata that would normally - // go on the perspective layer goes on its transform layer child instead. - // However, the transform item's clip chain does not contain the - // corresponding scroll clip, so we use the perspective item's clip - // chain instead. - const DisplayItemClipChain* clipChainForScrollClips = layerClipChain; - if (itemType == DisplayItemType::TYPE_TRANSFORM && mContainerItem && - mContainerItem->GetType() == DisplayItemType::TYPE_PERSPECTIVE) { - clipChainForScrollClips = mContainerItem->GetClipChain(); - } - - NewLayerEntry* newLayerEntry = mNewChildLayers.AppendElement(); - newLayerEntry->mLayer = ownLayer; - newLayerEntry->mAnimatedGeometryRoot = itemAGR; - newLayerEntry->mASR = itemASR; - newLayerEntry->mScrollMetadataASR = scrollMetadataASR; - newLayerEntry->mClipChain = clipChainForScrollClips; - newLayerEntry->mLayerState = layerState; - if (itemType == DisplayItemType::TYPE_FIXED_POSITION) { - newLayerEntry->mIsFixedToRootScrollFrame = - item->Frame()->StyleDisplay()->mPosition == - StylePositionProperty::Fixed && - nsLayoutUtils::IsReallyFixedPos(item->Frame()); - } - - float contentXScale = 1.0f; - float contentYScale = 1.0f; - if (ContainerLayer* ownContainer = ownLayer->AsContainerLayer()) { - contentXScale = 1 / ownContainer->GetPreXScale(); - contentYScale = 1 / ownContainer->GetPreYScale(); - } - // nsDisplayTransform::BuildLayer must set layerContentsVisibleRect. - // We rely on this to ensure 3D transforms compute a reasonable - // layer visible region. - NS_ASSERTION(itemType != DisplayItemType::TYPE_TRANSFORM || - layerContentsVisibleRect.width >= 0, - "Transform items must set layerContentsVisibleRect!"); - if (mLayerBuilder->IsBuildingRetainedLayers()) { - newLayerEntry->mLayerContentsVisibleRect = layerContentsVisibleRect; - if (itemType == DisplayItemType::TYPE_PERSPECTIVE || - (itemType == DisplayItemType::TYPE_TRANSFORM && - (item->Combines3DTransformWithAncestors() || - item->Frame()->Extend3DContext() || - item->Frame()->HasPerspective()))) { - // Give untransformed visible region as outer visible region - // to avoid failure caused by singular transforms. - newLayerEntry->mUntransformedVisibleRegion = true; - newLayerEntry->mVisibleRegion = - item->GetBuildingRectForChildren().ScaleToOutsidePixels( - contentXScale, contentYScale, mAppUnitsPerDevPixel); - } else { - newLayerEntry->mVisibleRegion = itemVisibleRegion; - } - newLayerEntry->mOpaqueRegion = ComputeOpaqueRect( - item, itemAGR, itemASR, itemClip, aList, - &newLayerEntry->mHideAllLayersBelow, - &newLayerEntry->mOpaqueForAnimatedGeometryRootParent); - } else { - bool useChildrenVisible = itemType == DisplayItemType::TYPE_TRANSFORM && - (item->Frame()->IsPreserve3DLeaf() || - item->Frame()->HasPerspective()); - const nsIntRegion& visible = - useChildrenVisible - ? item->GetBuildingRectForChildren().ScaleToOutsidePixels( - contentXScale, contentYScale, mAppUnitsPerDevPixel) - : itemVisibleRegion; - - SetOuterVisibleRegionForLayer(ownLayer, visible, - layerContentsVisibleRect.width >= 0 - ? &layerContentsVisibleRect - : nullptr, - useChildrenVisible); - } - if (itemType == DisplayItemType::TYPE_SCROLL_INFO_LAYER) { - nsDisplayScrollInfoLayer* scrollItem = - static_cast<nsDisplayScrollInfoLayer*>(item); - newLayerEntry->mOpaqueForAnimatedGeometryRootParent = false; - newLayerEntry->mBaseScrollMetadata = scrollItem->ComputeScrollMetadata( - mBuilder, ownLayer->Manager(), mParameters); - } - - /** - * No need to allocate geometry for items that aren't - * part of a PaintedLayer. - */ - if (ownLayer->Manager() == mLayerBuilder->GetRetainingLayerManager()) { - oldData = mLayerBuilder->GetOldLayerForFrame(item->Frame(), - item->GetPerFrameKey()); - - mLayerBuilder->StoreDataForFrame(item->AsPaintedDisplayItem(), ownLayer, - layerState, oldData); - } - } else { - const bool backfaceHidden = item->In3DContextAndBackfaceIsHidden(); - - // When container item hit test info is processed, we need to use the same - // reference frame as the container children. - const nsIFrame* referenceFrame = item == mContainerItem - ? mContainerReferenceFrame - : item->ReferenceFrame(); - - PaintedLayerData* paintedLayerData = selectedLayer; - - if (!paintedLayerData) { - paintedLayerData = mPaintedLayerDataTree.FindPaintedLayerFor( - itemAGR, itemASR, layerClipChain, itemVisibleRect, backfaceHidden, - [&](PaintedLayerData* aData) { - NewPaintedLayerData(aData, itemAGR, itemASR, layerClipChain, - scrollMetadataASR, topLeft, referenceFrame, - backfaceHidden); - }); - } - MOZ_ASSERT(paintedLayerData); - - paintedLayerData->Accumulate(this, item, itemVisibleRect, itemContent, - itemClip, layerState, aList, marker, - opacityIndices, transformNode); - - if (!paintedLayerData->mLayer) { - // Try to recycle the old layer of this display item. - RefPtr<PaintedLayer> layer = AttemptToRecyclePaintedLayer( - itemAGR, item, topLeft, - inEffect ? containerReferenceFrame : referenceFrame); - if (layer) { - paintedLayerData->mLayer = layer; - - auto* userData = GetPaintedDisplayItemLayerUserData(layer); - paintedLayerData->mAssignedDisplayItems.reserve( - userData->mLastItemCount); - - NS_ASSERTION(FindIndexOfLayerIn(mNewChildLayers, layer) < 0, - "Layer already in list???"); - mNewChildLayers[paintedLayerData->mNewChildLayersIndex].mLayer = - std::move(layer); - } - } - - const auto ClearLayerSelectionIfNeeded = [&]() { - if (!InOpacity() && !InTransform()) { - selectedLayer = nullptr; - containerAGR = nullptr; - containerASR = nullptr; - containerReferenceFrame = nullptr; - } - }; - - const auto SelectLayerIfNeeded = [&]() { - if (!selectedLayer) { - selectedLayer = paintedLayerData; - containerAGR = itemAGR; - containerASR = itemASR; - containerReferenceFrame = const_cast<nsIFrame*>(referenceFrame); - } - }; - - if (marker == DisplayItemEntryType::PushTransform) { - nsDisplayTransform* transform = static_cast<nsDisplayTransform*>(item); - - const Matrix4x4Flagged& matrix = transform->GetTransformForRendering(); - - Maybe<gfx::IntRect> clip; - if (itemClip.HasClip()) { - const nsRect nonRoundedClip = itemClip.NonRoundedIntersection(); - clip.emplace(nonRoundedClip.ToNearestPixels(mAppUnitsPerDevPixel)); - } - - transformNode = new TransformClipNode(transformNode, matrix, clip); - } - - ProcessDisplayItemMarker(marker, ClearLayerSelectionIfNeeded, - SelectLayerIfNeeded); - } - - nsDisplayList* childItems = item->GetSameCoordinateSystemChildren(); - if (childItems && childItems->NeedsTransparentSurface()) { - aList->SetNeedsTransparentSurface(); - } - } - - MOZ_ASSERT(selectedLayer == nullptr); -} - -void ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem, - PaintedLayer* aNewLayer, - DisplayItemData* aData) { - NS_ASSERTION(aItem->GetPerFrameKey(), - "Display items that render using Thebes must have a key"); - Layer* oldLayer = aData ? aData->mLayer.get() : nullptr; - if (aNewLayer != oldLayer && oldLayer) { - // The item has changed layers. - // Invalidate the old bounds in the old layer and new bounds in the new - // layer. - PaintedLayer* t = oldLayer->AsPaintedLayer(); - if (t && aData->mGeometry) { - // Note that whenever the layer's scale changes, we invalidate the whole - // thing, so it doesn't matter whether we are using the old scale at last - // paint or a new scale here -#ifdef MOZ_DUMP_PAINTING - if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { - printf_stderr("Display item type %s(%p) changed layers %p to %p!\n", - aItem->Name(), aItem->Frame(), t, aNewLayer); - } -#endif - InvalidatePreTransformRect( - t, aData->mGeometry->ComputeInvalidationRegion(), aData->mClip, - GetLastPaintOffset(t), aData->mTransform); - } - // Clear the old geometry so that invalidation thinks the item has been - // added this paint. - aData->mGeometry = nullptr; - } -} - -static nsRect GetInvalidationRect(nsDisplayItemGeometry* aGeometry, - const DisplayItemClip& aClip, - TransformClipNode* aTransform, - const int32_t aA2D) { - const nsRect& rect = aGeometry->ComputeInvalidationRegion(); - const nsRect clipped = aClip.ApplyNonRoundedIntersection(rect); - - if (aTransform) { - return aTransform->TransformRect(clipped, aA2D); - } - - return clipped; -} - -void FrameLayerBuilder::ComputeGeometryChangeForItem(DisplayItemData* aData) { - nsDisplayItem* item = aData->mItem; - PaintedLayer* paintedLayer = aData->mLayer->AsPaintedLayer(); - // If aData->mOptLayer is presence, means this item has been optimized to the - // separate layer. Thus, skip geometry change calculation. - if (aData->mOptLayer || !item || !paintedLayer) { - aData->EndUpdate(); - return; - } - - // If we're a reused display item, then we can't be invalid, so no need to - // do an in-depth comparison. If we haven't previously stored geometry - // for this item (if it was an active layer), then we can't skip this - // yet. - UniquePtr<nsDisplayItemGeometry> geometry; - if (aData->mReusedItem && aData->mGeometry) { - aData->EndUpdate(); - return; - } - - auto* layerData = GetPaintedDisplayItemLayerUserData(aData->mLayer); - nsPoint shift = layerData->mAnimatedGeometryRootOrigin - - layerData->mLastAnimatedGeometryRootOrigin; - - const DisplayItemClip& clip = item->GetClip(); - const int32_t appUnitsPerDevPixel = layerData->mAppUnitsPerDevPixel; - - // If the frame is marked as invalidated, and didn't specify a rect to - // invalidate then we want to invalidate both the old and new bounds, - // otherwise we only want to invalidate the changed areas. If we do get an - // invalid rect, then we want to add this on top of the change areas. - nsRect invalid; - nsIntRegion invalidPixels; - - if (!aData->mGeometry) { - // This item is being added for the first time, invalidate its entire area. - geometry = WrapUnique(item->AllocateGeometry(mDisplayListBuilder)); - - const nsRect bounds = GetInvalidationRect( - geometry.get(), clip, aData->mTransform, appUnitsPerDevPixel); - - invalidPixels = bounds.ScaleToOutsidePixels( - layerData->mXScale, layerData->mYScale, appUnitsPerDevPixel); -#ifdef MOZ_DUMP_PAINTING - if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { - printf_stderr("Display item type %s(%p) added to layer %p!\n", - item->Name(), item->Frame(), aData->mLayer.get()); - } -#endif - } else if (aData->mIsInvalid || - (item->IsInvalid(invalid) && invalid.IsEmpty())) { - // Layout marked item/frame as needing repainting (without an explicit - // rect), invalidate the entire old and new areas. - geometry = WrapUnique(item->AllocateGeometry(mDisplayListBuilder)); - - nsRect oldArea = - GetInvalidationRect(aData->mGeometry.get(), aData->mClip, - aData->mOldTransform, appUnitsPerDevPixel); - oldArea.MoveBy(shift); - - nsRect newArea = GetInvalidationRect( - geometry.get(), clip, aData->mTransform, appUnitsPerDevPixel); - - nsRegion combined; - combined.Or(oldArea, newArea); - invalidPixels = combined.ScaleToOutsidePixels( - layerData->mXScale, layerData->mYScale, appUnitsPerDevPixel); -#ifdef MOZ_DUMP_PAINTING - if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { - printf_stderr( - "Display item type %s(%p) (in layer %p) belongs to an " - "invalidated frame!\n", - item->Name(), item->Frame(), aData->mLayer.get()); - } -#endif - } else { - // Let the display item check for geometry changes and decide what needs to - // be repainted. - const nsRegion& changedFrameInvalidations = - aData->GetChangedFrameInvalidations(); - - if (aData->mTransform) { - // If this display item is inside a flattened transform the offset is - // already included in the root transform, so there is no need to shift. - shift = nsPoint(); - } - - aData->mGeometry->MoveBy(shift); - - nsRegion combined; - item->ComputeInvalidationRegion(mDisplayListBuilder, aData->mGeometry.get(), - &combined); - - // Only allocate a new geometry object if something actually changed, - // otherwise the existing one should be fine. We always reallocate for - // inactive layers, since these types don't implement - // ComputeInvalidateRegion (and rely on the ComputeDifferences call in - // AddPaintedDisplayItem instead). - if (!combined.IsEmpty() || - aData->mLayerState == LayerState::LAYER_INACTIVE || - item->NeedsGeometryUpdates()) { - geometry = WrapUnique(item->AllocateGeometry(mDisplayListBuilder)); - } - - aData->mClip.AddOffsetAndComputeDifference( - shift, aData->mGeometry->ComputeInvalidationRegion(), clip, - geometry ? geometry->ComputeInvalidationRegion() - : aData->mGeometry->ComputeInvalidationRegion(), - &combined); - - // Add in any rect that the frame specified - combined.Or(combined, invalid); - combined.Or(combined, changedFrameInvalidations); - - // Restrict invalidation to the clipped region - nsRegion clipRegion; - if (clip.ComputeRegionInClips(&aData->mClip, shift, &clipRegion)) { - combined.And(combined, clipRegion); - } - - invalidPixels = combined.ToOutsidePixels(appUnitsPerDevPixel); - - if (aData->mTransform) { - invalidPixels = aData->mTransform->TransformRegion(invalidPixels); - } - - invalidPixels.ScaleRoundOut(layerData->mXScale, layerData->mYScale); - -#ifdef MOZ_DUMP_PAINTING - if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { - if (!combined.IsEmpty()) { - printf_stderr( - "Display item type %s(%p) (in layer %p) changed geometry!\n", - item->Name(), item->Frame(), aData->mLayer.get()); - } - } -#endif - } - - if (!invalidPixels.IsEmpty()) { - InvalidatePostTransformRegion(paintedLayer, invalidPixels, - layerData->mTranslation); - } - - aData->EndUpdate(std::move(geometry)); -} - -void FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, - AssignedDisplayItem& aItem, - Layer* aLayer) { - PaintedLayer* layer = aLayerData->mLayer; - auto* paintedData = GetPaintedDisplayItemLayerUserData(layer); - - if (layer->Manager() == mRetainingManager) { - DisplayItemData* data = aItem.mDisplayItemData; - if (data && !data->mUsed) { - data->BeginUpdate(layer, aItem.mLayerState, aItem.mItem, aItem.mReused, - aItem.mMerged); - } else { - data = StoreDataForFrame(aItem.mItem, layer, aItem.mLayerState, nullptr); - } - data->mInactiveManager = aItem.mInactiveLayerData - ? aItem.mInactiveLayerData->mLayerManager - : nullptr; - // We optimized this PaintedLayer into a ColorLayer/ImageLayer. Store the - // optimized layer here. - if (aLayer != layer) { - data->mOptLayer = aLayer; - } - - data->mOldTransform = data->mTransform; - data->mTransform = aItem.mTransform; - } - - if (aItem.mInactiveLayerData) { - RefPtr<BasicLayerManager> tempManager = - aItem.mInactiveLayerData->mLayerManager; - FrameLayerBuilder* layerBuilder = tempManager->GetLayerBuilder(); - Layer* tmpLayer = aItem.mInactiveLayerData->mLayer; - - // We have no easy way of detecting if this transaction will ever actually - // get finished. For now, I've just silenced the warning with nested - // transactions in BasicLayers.cpp - if (!tmpLayer) { - tempManager->EndTransaction(nullptr, nullptr); - tempManager->SetUserData(&gLayerManagerLayerBuilder, nullptr); - aItem.mItem = nullptr; - return; - } - - bool snap; - nsRect visibleRect = aItem.mItem->GetBuildingRect().Intersect( - aItem.mItem->GetBounds(mDisplayListBuilder, &snap)); - nsIntRegion rgn = - visibleRect.ToOutsidePixels(paintedData->mAppUnitsPerDevPixel); - - // Convert the visible rect to a region and give the item - // a chance to try restrict it further. - nsRegion tightBounds = - aItem.mItem->GetTightBounds(mDisplayListBuilder, &snap); - if (!tightBounds.IsEmpty()) { - rgn.AndWith( - tightBounds.ToOutsidePixels(paintedData->mAppUnitsPerDevPixel)); - } - SetOuterVisibleRegion(tmpLayer, &rgn); - - DisplayItemData* data = nullptr; - // If BuildLayer didn't call BuildContainerLayerFor, then our new layer - // won't have been stored in layerBuilder. Manually add it now. - if (mRetainingManager) { -#ifdef DEBUG_DISPLAY_ITEM_DATA - LayerManagerData* parentLmd = static_cast<LayerManagerData*>( - layer->Manager()->GetUserData(&gLayerManagerUserData)); - LayerManagerData* lmd = static_cast<LayerManagerData*>( - tempManager->GetUserData(&gLayerManagerUserData)); - lmd->mParent = parentLmd; -#endif - data = - layerBuilder->GetDisplayItemDataForManager(aItem.mItem, tempManager); - data = layerBuilder->StoreDataForFrame(aItem.mItem, tmpLayer, - LayerState::LAYER_ACTIVE, data); - data->mOldTransform = data->mTransform; - data->mTransform = aItem.mTransform; - } - - tempManager->SetRoot(tmpLayer); - layerBuilder->WillEndTransaction(); - tempManager->AbortTransaction(); - - if (gfxUtils::DumpDisplayList() || gfxEnv::DumpPaint()) { - fprintf_stderr( - gfxUtils::sDumpPaintFile, - "Basic layer tree for painting contents of display item %s(%p):\n", - aItem.mItem->Name(), aItem.mItem->Frame()); - std::stringstream stream; - tempManager->Dump(stream, "", gfxEnv::DumpPaintToFile()); - fprint_stderr(gfxUtils::sDumpPaintFile, - stream); // not a typo, fprint_stderr declared in nsDebug.h - } - - nsIntPoint offset = - GetLastPaintOffset(layer) - GetTranslationForPaintedLayer(layer); - aItem.mInactiveLayerData->mProps->MoveBy(-offset); - // Effective transforms are needed by ComputeDifferences(). - tmpLayer->ComputeEffectiveTransforms(Matrix4x4()); - nsIntRegion invalid; - if (!aItem.mInactiveLayerData->mProps->ComputeDifferences(tmpLayer, invalid, - nullptr)) { - nsRect visible = aItem.mItem->Frame()->InkOverflowRect(); - invalid = visible.ToOutsidePixels(paintedData->mAppUnitsPerDevPixel); - } - if (aItem.mLayerState == LayerState::LAYER_SVG_EFFECTS) { - invalid = SVGIntegrationUtils::AdjustInvalidAreaForSVGEffects( - aItem.mItem->Frame(), aItem.mItem->ToReferenceFrame(), invalid); - } - if (!invalid.IsEmpty()) { -#ifdef MOZ_DUMP_PAINTING - if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { - printf_stderr( - "Inactive LayerManager(%p) for display item %s(%p) has " - "an invalid region - invalidating layer %p\n", - tempManager.get(), aItem.mItem->Name(), aItem.mItem->Frame(), - layer); - } -#endif - - if (data && data->mTransform) { - invalid = data->mTransform->TransformRegion(invalid); - } - - invalid.ScaleRoundOut(paintedData->mXScale, paintedData->mYScale); - - InvalidatePostTransformRegion(layer, invalid, - GetTranslationForPaintedLayer(layer)); - } - } -} - -DisplayItemData* FrameLayerBuilder::StoreDataForFrame( - nsPaintedDisplayItem* aItem, Layer* aLayer, LayerState aState, - DisplayItemData* aData) { - MOZ_ASSERT(aItem); - - if (aData) { - if (!aData->mUsed) { - aData->BeginUpdate(aLayer, aState, false, aItem); - } - return aData; - } - - LayerManagerData* lmd = static_cast<LayerManagerData*>( - mRetainingManager->GetUserData(&gLayerManagerUserData)); - - RefPtr<DisplayItemData> data = new (aItem->Frame()->PresContext()) - DisplayItemData(lmd, aItem->GetPerFrameKey(), aLayer); - - data->BeginUpdate(aLayer, aState, true, aItem); - - lmd->mDisplayItems.push_back(data); - return data; -} - -void FrameLayerBuilder::StoreDataForFrame(nsIFrame* aFrame, - uint32_t aDisplayItemKey, - Layer* aLayer, LayerState aState) { - DisplayItemData* oldData = GetDisplayItemData(aFrame, aDisplayItemKey); - if (oldData && oldData->mFrameList.Length() == 1) { - oldData->BeginUpdate(aLayer, aState, false); - return; - } - - LayerManagerData* lmd = static_cast<LayerManagerData*>( - mRetainingManager->GetUserData(&gLayerManagerUserData)); - - RefPtr<DisplayItemData> data = new (aFrame->PresContext()) - DisplayItemData(lmd, aDisplayItemKey, aLayer, aFrame); - - data->BeginUpdate(aLayer, aState, true); - - lmd->mDisplayItems.push_back(data); -} - -AssignedDisplayItem::AssignedDisplayItem( - nsPaintedDisplayItem* aItem, LayerState aLayerState, DisplayItemData* aData, - const nsRect& aContentRect, DisplayItemEntryType aType, - const bool aHasOpacity, const RefPtr<TransformClipNode>& aTransform, - const bool aIsMerged) - : mItem(aItem), - mDisplayItemData(aData), - mTransform(aTransform), - mContentRect(aContentRect), - mLayerState(aLayerState), - mType(aType), - mReused(aItem->IsReused()), - mMerged(aIsMerged), - mHasOpacity(aHasOpacity), - mHasPaintRect(aItem->HasPaintRect()) {} - -InactiveLayerData::~InactiveLayerData() { - if (mLayerManager) { - mLayerManager->SetUserData(&gLayerManagerLayerBuilder, nullptr); - } -} - -bool FrameLayerBuilder::CheckInLayerTreeCompressionMode() { - if (mInLayerTreeCompressionMode) { - return true; - } - - // If we wanted to be in layer tree compression mode, but weren't, then - // scheduled a delayed repaint where we will be. - mRootPresContext->PresShell()->GetRootFrame()->SchedulePaint( - nsIFrame::PAINT_DELAYED_COMPRESS, false); - - return false; -} - -void ContainerState::CollectOldLayers() { - for (Layer* layer = mContainerLayer->GetFirstChild(); layer; - layer = layer->GetNextSibling()) { - NS_ASSERTION(!layer->HasUserData(&gMaskLayerUserData), - "Mask layers should not be part of the layer tree."); - if (layer->HasUserData(&gPaintedDisplayItemLayerUserData)) { - NS_ASSERTION(layer->AsPaintedLayer(), "Wrong layer type"); - mPaintedLayersAvailableForRecycling.Insert( - static_cast<PaintedLayer*>(layer)); - } - - if (Layer* maskLayer = layer->GetMaskLayer()) { - NS_ASSERTION(maskLayer->GetType() == Layer::TYPE_IMAGE, - "Could not recycle mask layer, unsupported layer type."); - mRecycledMaskImageLayers.InsertOrUpdate( - MaskLayerKey(layer, Nothing()), - RefPtr{static_cast<ImageLayer*>(maskLayer)}); - } - for (size_t i = 0; i < layer->GetAncestorMaskLayerCount(); i++) { - Layer* maskLayer = layer->GetAncestorMaskLayerAt(i); - - NS_ASSERTION(maskLayer->GetType() == Layer::TYPE_IMAGE, - "Could not recycle mask layer, unsupported layer type."); - mRecycledMaskImageLayers.InsertOrUpdate( - MaskLayerKey(layer, Some(i)), - RefPtr{static_cast<ImageLayer*>(maskLayer)}); - } - } -} - -struct OpaqueRegionEntry { - AnimatedGeometryRoot* mAnimatedGeometryRoot; - const ActiveScrolledRoot* mASR; - nsIntRegion mOpaqueRegion; -}; - -static OpaqueRegionEntry* FindOpaqueRegionEntry( - nsTArray<OpaqueRegionEntry>& aEntries, - AnimatedGeometryRoot* aAnimatedGeometryRoot, - const ActiveScrolledRoot* aASR) { - for (uint32_t i = 0; i < aEntries.Length(); ++i) { - OpaqueRegionEntry* d = &aEntries[i]; - if (d->mAnimatedGeometryRoot == aAnimatedGeometryRoot && d->mASR == aASR) { - return d; - } - } - return nullptr; -} - -static const ActiveScrolledRoot* FindDirectChildASR( - const ActiveScrolledRoot* aParent, const ActiveScrolledRoot* aDescendant) { - MOZ_ASSERT(aDescendant, "can't start at the root when looking for a child"); - MOZ_ASSERT(ActiveScrolledRoot::IsAncestor(aParent, aDescendant)); - const ActiveScrolledRoot* directChild = aDescendant; - while (directChild->mParent != aParent) { - directChild = directChild->mParent; - MOZ_RELEASE_ASSERT(directChild, "this must not be null"); - } - return directChild; -} - -static void FixUpFixedPositionLayer( - Layer* aLayer, const ActiveScrolledRoot* aTargetASR, - const ActiveScrolledRoot* aLeafScrollMetadataASR, - const ActiveScrolledRoot* aContainerScrollMetadataASR, - const ActiveScrolledRoot* aContainerCompositorASR, - bool aIsFixedToRootScrollFrame) { - if (!aLayer->GetIsFixedPosition()) { - return; - } - - // Analyze ASRs to figure out if we need to fix up fixedness annotations on - // the layer. Fixed annotations are required in multiple cases: - // - Sometimes we set scroll metadata on a layer for a scroll frame that we - // don't want the layer to be moved by. (We have to do this if there is a - // scrolled clip that is moved by that scroll frame.) So we set the fixed - // annotation so that the compositor knows that it should ignore that - // scroll metadata when determining the layer's position. - // - Sometimes there is a scroll meta data on aLayer's parent layer for a - // scroll frame that we don't want aLayer to be moved by. The most common - // way for this to happen is with containerful root scrolling, where the - // scroll metadata for the root scroll frame is on a container layer that - // wraps the whole document's contents. - // - Sometimes it's just needed for hit testing, i.e. figuring out what - // scroll frame should be scrolled by events over the layer. - // A fixed layer needs to be annotated with the scroll ID of the scroll frame - // that it is *fixed with respect to*, i.e. the outermost scroll frame which - // does not move the layer. nsDisplayFixedPosition only ever annotates layers - // with the scroll ID of the presshell's root scroll frame, which is - // sometimes the wrong thing to do, so we correct it here. Specifically, - // it's the wrong thing to do if the fixed frame's containing block is a - // transformed frame - in that case, the fixed frame needs to scroll along - // with the transformed frame instead of being fixed with respect to the rsf. - // (It would be nice to compute the annotation only in one place and get it - // right, instead of fixing it up after the fact like this, but this will - // need to do for now.) - // compositorASR is the ASR that the layer would move with on the compositor - // if there were no fixed annotation on it. - const ActiveScrolledRoot* compositorASR = - aLeafScrollMetadataASR == aContainerScrollMetadataASR - ? aContainerCompositorASR - : aLeafScrollMetadataASR; - - // The goal of the annotation is to have the layer move with aTargetASR. - if (compositorASR && aTargetASR != compositorASR) { - // Mark this layer as fixed with respect to the child scroll frame of - // aTargetASR. - aLayer->SetFixedPositionData( - FindDirectChildASR(aTargetASR, compositorASR)->GetViewId(), - aLayer->GetFixedPositionAnchor(), aLayer->GetFixedPositionSides()); - } else { - // Remove the fixed annotation from the layer, unless this layers is fixed - // to the document's root scroll frame - in that case, the annotation is - // needed for hit testing, because fixed layers in iframes should scroll - // the iframe, even though their position is not affected by scrolling in - // the iframe. (The APZ hit testing code has a special case for this.) - // nsDisplayFixedPosition has annotated this layer with the document's - // root scroll frame's scroll id. - aLayer->SetIsFixedPosition(aIsFixedToRootScrollFrame); - } -} - -void ContainerState::SetupScrollingMetadata(NewLayerEntry* aEntry) { - if (!mBuilder->IsPaintingToWindow()) { - // async scrolling not possible, and async scrolling info not computed - // for this paint. - return; - } - - const ActiveScrolledRoot* startASR = aEntry->mScrollMetadataASR; - const ActiveScrolledRoot* stopASR = mContainerScrollMetadataASR; - if (!ActiveScrolledRoot::IsAncestor(stopASR, startASR)) { - if (ActiveScrolledRoot::IsAncestor(startASR, stopASR)) { - // startASR and stopASR are in the same branch of the ASR tree, but - // startASR is closer to the root. Just start at stopASR so that the loop - // below doesn't actually do anything. - startASR = stopASR; - } else { - // startASR and stopASR are in different branches of the - // ASR tree. Find a common ancestor and make that the stopASR. - // This can happen when there's a scrollable frame inside a fixed layer - // which has a scrolled clip. As far as scroll metadata is concerned, - // the scroll frame's scroll metadata will be a child of the scroll ID - // that scrolls the clip on the fixed layer. But as far as ASRs are - // concerned, those two ASRs are siblings, parented to the ASR of the - // fixed layer. - do { - stopASR = stopASR->mParent; - } while (!ActiveScrolledRoot::IsAncestor(stopASR, startASR)); - } - } - - FixUpFixedPositionLayer(aEntry->mLayer, aEntry->mASR, startASR, - mContainerScrollMetadataASR, mContainerCompositorASR, - aEntry->mIsFixedToRootScrollFrame); - - AutoTArray<ScrollMetadata, 2> metricsArray; - if (aEntry->mBaseScrollMetadata) { - metricsArray.AppendElement(*aEntry->mBaseScrollMetadata); - - // The base FrameMetrics was not computed by the nsIScrollableframe, so it - // should not have a mask layer. - MOZ_ASSERT(!aEntry->mBaseScrollMetadata->HasMaskLayer()); - } - - // Any extra mask layers we need to attach to ScrollMetadatas. - // The list may already contain an entry added for the layer's scrolled clip - // so add to it rather than overwriting it (we clear the list when recycling - // a layer). - nsTArray<RefPtr<Layer>> maskLayers( - aEntry->mLayer->GetAllAncestorMaskLayers().Clone()); - - // Iterate over the ASR chain and create the corresponding scroll metadatas. - // This loop is slightly tricky because the scrollframe-to-clip relationship - // is reversed between DisplayItemClipChain and ScrollMetadata: - // - DisplayItemClipChain associates the clip with the scroll frame that - // this clip is *moved by*, i.e. the clip is moving inside the scroll - // frame. - // - ScrollMetaData associates the scroll frame with the clip that's - // *just outside* the scroll frame, i.e. not moved by the scroll frame - // itself. - // This discrepancy means that the leaf clip item of the clip chain is never - // applied to any scroll meta data. Instead, it was applied earlier as the - // layer's clip (or fused with the painted layer contents), or it was applied - // as a ScrolledClip on the layer. - const DisplayItemClipChain* clipChain = aEntry->mClipChain; - - for (const ActiveScrolledRoot* asr = startASR; asr != stopASR; - asr = asr->mParent) { - if (!asr) { - MOZ_ASSERT_UNREACHABLE("Should have encountered stopASR on the way up."); - break; - } - if (clipChain && clipChain->mASR == asr) { - clipChain = clipChain->mParent; - } - - nsIScrollableFrame* scrollFrame = asr->mScrollableFrame; - const DisplayItemClip* clip = (clipChain && clipChain->mASR == asr->mParent) - ? &clipChain->mClip - : nullptr; - - scrollFrame->ClipLayerToDisplayPort(aEntry->mLayer, clip, mParameters); - - Maybe<ScrollMetadata> metadata; - if (mCachedScrollMetadata.mASR == asr && - mCachedScrollMetadata.mClip == clip) { - metadata = mCachedScrollMetadata.mMetadata; - } else { - metadata = scrollFrame->ComputeScrollMetadata(aEntry->mLayer->Manager(), - mContainerReferenceFrame, - Some(mParameters), clip); - mBuilder->AddScrollFrameToNotify(scrollFrame); - mCachedScrollMetadata.mASR = asr; - mCachedScrollMetadata.mClip = clip; - mCachedScrollMetadata.mMetadata = metadata; - } - - if (!metadata) { - continue; - } - - if (clip && clip->HasClip() && clip->GetRoundedRectCount() > 0) { - // The clip in between this scrollframe and its ancestor scrollframe - // requires a mask layer. Since this mask layer should not move with - // the APZC associated with this FrameMetrics, we attach the mask - // layer as an additional, separate clip. - Maybe<size_t> nextIndex = Some(maskLayers.Length()); - RefPtr<Layer> maskLayer = - CreateMaskLayer(aEntry->mLayer, *clip, nextIndex); - if (maskLayer) { - MOZ_ASSERT(metadata->HasScrollClip()); - metadata->ScrollClip().SetMaskLayerIndex(nextIndex); - maskLayers.AppendElement(maskLayer); - } - } - - metricsArray.AppendElement(*metadata); - } - - // Watch out for FrameMetrics copies in profiles - aEntry->mLayer->SetScrollMetadata(metricsArray); - aEntry->mLayer->SetAncestorMaskLayers(maskLayers); -} - -static inline Maybe<ParentLayerIntRect> GetStationaryClipInContainer( - Layer* aLayer) { - if (size_t metricsCount = aLayer->GetScrollMetadataCount()) { - return aLayer->GetScrollMetadata(metricsCount - 1).GetClipRect(); - } - return aLayer->GetClipRect(); -} - -void ContainerState::PostprocessRetainedLayers( - nsIntRegion* aOpaqueRegionForContainer) { - AutoTArray<OpaqueRegionEntry, 4> opaqueRegions; - bool hideAll = false; - int32_t opaqueRegionForContainer = -1; - - for (int32_t i = mNewChildLayers.Length() - 1; i >= 0; --i) { - NewLayerEntry* e = &mNewChildLayers.ElementAt(i); - if (!e->mLayer) { - continue; - } - - OpaqueRegionEntry* data = - FindOpaqueRegionEntry(opaqueRegions, e->mAnimatedGeometryRoot, e->mASR); - - SetupScrollingMetadata(e); - - if (hideAll) { - e->mVisibleRegion.SetEmpty(); - } else if (!e->mLayer->IsScrollbarContainer()) { - Maybe<ParentLayerIntRect> clipRect = - GetStationaryClipInContainer(e->mLayer); - if (clipRect && opaqueRegionForContainer >= 0 && - opaqueRegions[opaqueRegionForContainer].mOpaqueRegion.Contains( - clipRect->ToUnknownRect())) { - e->mVisibleRegion.SetEmpty(); - } else if (data) { - e->mVisibleRegion.Sub(e->mVisibleRegion, data->mOpaqueRegion); - } - } - - SetOuterVisibleRegionForLayer(e->mLayer, e->mVisibleRegion, - e->mLayerContentsVisibleRect.width >= 0 - ? &e->mLayerContentsVisibleRect - : nullptr, - e->mUntransformedVisibleRegion); - - if (!e->mOpaqueRegion.IsEmpty()) { - AnimatedGeometryRoot* animatedGeometryRootToCover = - e->mAnimatedGeometryRoot; - const ActiveScrolledRoot* asrToCover = e->mASR; - if (e->mOpaqueForAnimatedGeometryRootParent && - e->mAnimatedGeometryRoot->mParentAGR == - mContainerAnimatedGeometryRoot) { - animatedGeometryRootToCover = mContainerAnimatedGeometryRoot; - asrToCover = mContainerASR; - data = FindOpaqueRegionEntry(opaqueRegions, animatedGeometryRootToCover, - asrToCover); - } - - if (!data) { - if (animatedGeometryRootToCover == mContainerAnimatedGeometryRoot && - asrToCover == mContainerASR) { - NS_ASSERTION(opaqueRegionForContainer == -1, "Already found it?"); - opaqueRegionForContainer = opaqueRegions.Length(); - } - data = opaqueRegions.AppendElement(); - data->mAnimatedGeometryRoot = animatedGeometryRootToCover; - data->mASR = asrToCover; - } - - nsIntRegion clippedOpaque = e->mOpaqueRegion; - Maybe<ParentLayerIntRect> clipRect = e->mLayer->GetCombinedClipRect(); - if (clipRect) { - clippedOpaque.AndWith(clipRect->ToUnknownRect()); - } - if (e->mLayer->GetScrolledClip()) { - // The clip can move asynchronously, so we can't rely on opaque parts - // staying visible. - clippedOpaque.SetEmpty(); - } else if (e->mHideAllLayersBelow) { - hideAll = true; - } - data->mOpaqueRegion.Or(data->mOpaqueRegion, clippedOpaque); - } - - if (e->mLayer->GetType() == Layer::TYPE_READBACK) { - // ReadbackLayers need to accurately read what's behind them. So, - // we don't want to do any occlusion culling of layers behind them. - // Theoretically we could just punch out the ReadbackLayer's rectangle - // from all mOpaqueRegions, but that's probably not worth doing. - opaqueRegions.Clear(); - opaqueRegionForContainer = -1; - } - } - - if (opaqueRegionForContainer >= 0) { - aOpaqueRegionForContainer->Or( - *aOpaqueRegionForContainer, - opaqueRegions[opaqueRegionForContainer].mOpaqueRegion); - } -} - -void ContainerState::Finish(uint32_t* aTextContentFlags, - const nsIntRect& aContainerPixelBounds, - nsDisplayList* aChildItems) { - mPaintedLayerDataTree.Finish(); - - NS_ASSERTION(mContainerBounds.IsEqualInterior(mAccumulatedChildBounds), - "Bounds computation mismatch"); - - if (mLayerBuilder->IsBuildingRetainedLayers()) { - nsIntRegion containerOpaqueRegion; - PostprocessRetainedLayers(&containerOpaqueRegion); - if (containerOpaqueRegion.Contains(aContainerPixelBounds)) { - aChildItems->SetIsOpaque(); - } - } - - uint32_t textContentFlags = 0; - - // Make sure that current/existing layers are added to the parent and are - // in the correct order. - Layer* layer = nullptr; - Layer* prevChild = nullptr; - for (uint32_t i = 0; i < mNewChildLayers.Length(); ++i, prevChild = layer) { - if (!mNewChildLayers[i].mLayer) { - continue; - } - - layer = mNewChildLayers[i].mLayer; - - if (!layer->GetVisibleRegion().IsEmpty()) { - textContentFlags |= layer->GetContentFlags() & - (Layer::CONTENT_COMPONENT_ALPHA | - Layer::CONTENT_COMPONENT_ALPHA_DESCENDANT | - Layer::CONTENT_DISABLE_FLATTENING); - } - - if (!layer->GetParent()) { - // This is not currently a child of the container, so just add it - // now. - mContainerLayer->InsertAfter(layer, prevChild); - } else { - NS_ASSERTION(layer->GetParent() == mContainerLayer, - "Layer shouldn't be the child of some other container"); - if (layer->GetPrevSibling() != prevChild) { - mContainerLayer->RepositionChild(layer, prevChild); - } - } - } - - // Remove old layers that have become unused. - if (!layer) { - layer = mContainerLayer->GetFirstChild(); - } else { - layer = layer->GetNextSibling(); - } - while (layer) { - Layer* layerToRemove = layer; - layer = layer->GetNextSibling(); - mContainerLayer->RemoveChild(layerToRemove); - } - - *aTextContentFlags = textContentFlags; -} - -static void RestrictScaleToMaxLayerSize(Size& aScale, - const nsRect& aVisibleRect, - nsIFrame* aContainerFrame, - Layer* aContainerLayer) { - if (!aContainerLayer->Manager()->IsWidgetLayerManager()) { - return; - } - - nsIntRect pixelSize = aVisibleRect.ScaleToOutsidePixels( - aScale.width, aScale.height, - aContainerFrame->PresContext()->AppUnitsPerDevPixel()); - - int32_t maxLayerSize = aContainerLayer->GetMaxLayerSize(); - - if (pixelSize.width > maxLayerSize) { - float scale = (float)pixelSize.width / maxLayerSize; - scale = gfxUtils::ClampToScaleFactor(scale); - aScale.width /= scale; - } - if (pixelSize.height > maxLayerSize) { - float scale = (float)pixelSize.height / maxLayerSize; - scale = gfxUtils::ClampToScaleFactor(scale); - aScale.height /= scale; - } -} - -static nsSize ComputeDesiredDisplaySizeForAnimation(nsIFrame* aContainerFrame) { - // Use the size of the nearest widget as the maximum size. This - // is important since it might be a popup that is bigger than the - // pres context's size. - nsPresContext* presContext = aContainerFrame->PresContext(); - nsIWidget* widget = aContainerFrame->GetNearestWidget(); - if (widget) { - return LayoutDevicePixel::ToAppUnits(widget->GetClientSize(), - presContext->AppUnitsPerDevPixel()); - } - - return presContext->GetVisibleArea().Size(); -} - -/* static */ -Size FrameLayerBuilder::ChooseScale(nsIFrame* aContainerFrame, - nsDisplayItem* aContainerItem, - const nsRect& aVisibleRect, float aXScale, - float aYScale, const Matrix& aTransform2d, - bool aCanDraw2D) { - Size scale; - // XXX Should we do something for 3D transforms? - if (aCanDraw2D && !aContainerFrame->Combines3DTransformWithAncestors() && - !aContainerFrame->HasPerspective()) { - // If the container's transform is animated off main thread, fix a suitable - // scale size for animation - if (aContainerItem && - aContainerItem->GetType() == DisplayItemType::TYPE_TRANSFORM && - // FIXME: What we need is only transform, rotate, and scale, not - // translate, so it's be better to use a property set, instead of - // display item type here. - EffectCompositor::HasAnimationsForCompositor( - aContainerFrame, DisplayItemType::TYPE_TRANSFORM)) { - nsSize displaySize = - ComputeDesiredDisplaySizeForAnimation(aContainerFrame); - // compute scale using the animation on the container, taking ancestors in - // to account - nsSize scaledVisibleSize = nsSize(aVisibleRect.Width() * aXScale, - aVisibleRect.Height() * aYScale); - scale = nsLayoutUtils::ComputeSuitableScaleForAnimation( - aContainerFrame, scaledVisibleSize, displaySize); - // multiply by the scale inherited from ancestors--we use a uniform - // scale factor to prevent blurring when the layer is rotated. - float incomingScale = std::max(aXScale, aYScale); - scale.width *= incomingScale; - scale.height *= incomingScale; - } else { - // Scale factors are normalized to a power of 2 to reduce the number of - // resolution changes - scale = aTransform2d.ScaleFactors(); - // For frames with a changing scale transform round scale factors up to - // nearest power-of-2 boundary so that we don't keep having to redraw - // the content as it scales up and down. Rounding up to nearest - // power-of-2 boundary ensures we never scale up, only down --- avoiding - // jaggies. It also ensures we never scale down by more than a factor of - // 2, avoiding bad downscaling quality. - Matrix frameTransform; - if (ActiveLayerTracker::IsScaleSubjectToAnimation(aContainerFrame)) { - scale.width = gfxUtils::ClampToScaleFactor(scale.width); - scale.height = gfxUtils::ClampToScaleFactor(scale.height); - - // Limit animated scale factors to not grow excessively beyond the - // display size. - nsSize maxScale(4, 4); - if (!aVisibleRect.IsEmpty()) { - nsSize displaySize = - ComputeDesiredDisplaySizeForAnimation(aContainerFrame); - maxScale = Max(maxScale, displaySize / aVisibleRect.Size()); - } - if (scale.width > maxScale.width) { - scale.width = gfxUtils::ClampToScaleFactor(maxScale.width, true); - } - if (scale.height > maxScale.height) { - scale.height = gfxUtils::ClampToScaleFactor(maxScale.height, true); - } - } else { - // XXX Do we need to move nearly-integer values to integers here? - } - } - // If the scale factors are too small, just use 1.0. The content is being - // scaled out of sight anyway. - if (fabs(scale.width) < 1e-8 || fabs(scale.height) < 1e-8) { - scale = Size(1.0, 1.0); - } - } else { - scale = Size(1.0, 1.0); - } - - // Prevent the scale from getting too large, to avoid excessive memory - // allocation. Usually memory allocation is limited by the visible region, - // which should be restricted to the display port. But at very large scales - // the visible region itself can become excessive due to rounding errors. - // Clamping the scale here prevents that. - scale = - Size(std::min(scale.width, 32768.0f), std::min(scale.height, 32768.0f)); - - return scale; -} - -static bool ChooseScaleAndSetTransform( - FrameLayerBuilder* aLayerBuilder, nsDisplayListBuilder* aDisplayListBuilder, - nsIFrame* aContainerFrame, nsDisplayItem* aContainerItem, - const nsRect& aVisibleRect, const Matrix4x4* aTransform, - const ContainerLayerParameters& aIncomingScale, ContainerLayer* aLayer, - ContainerLayerParameters& aOutgoingScale) { - nsIntPoint offset; - - Matrix4x4 transform = - Matrix4x4::Scaling(aIncomingScale.mXScale, aIncomingScale.mYScale, 1.0); - if (aTransform) { - // aTransform is applied first, then the scale is applied to the result - transform = (*aTransform) * transform; - // Set any matrix entries close to integers to be those exact integers. - // This protects against floating-point inaccuracies causing problems - // in the checks below. - // We use the fixed epsilon version here because we don't want the nudging - // to depend on the scroll position. - transform.NudgeToIntegersFixedEpsilon(); - } - Matrix transform2d; - if (aContainerFrame && aLayerBuilder->GetContainingPaintedLayerData() && - (!aTransform || - (aTransform->Is2D(&transform2d) && !transform2d.HasNonTranslation()))) { - // When we have an inactive ContainerLayer, translate the container by the - // offset to the reference frame (and offset all child layers by the - // reverse) so that the coordinate space of the child layers isn't affected - // by scrolling. This gets confusing for complicated transform (since we'd - // have to compute the scale factors for the matrix), so we don't bother. - // Any frames that are building an nsDisplayTransform for a css transform - // would have 0,0 as their offset to the reference frame, so this doesn't - // matter. - nsPoint appUnitOffset = - aDisplayListBuilder->ToReferenceFrame(aContainerFrame); - nscoord appUnitsPerDevPixel = - aContainerFrame->PresContext()->AppUnitsPerDevPixel(); - offset = nsIntPoint(NS_lround(NSAppUnitsToDoublePixels( - appUnitOffset.x, appUnitsPerDevPixel) * - aIncomingScale.mXScale), - NS_lround(NSAppUnitsToDoublePixels( - appUnitOffset.y, appUnitsPerDevPixel) * - aIncomingScale.mYScale)); - } - transform.PostTranslate(offset.x + aIncomingScale.mOffset.x, - offset.y + aIncomingScale.mOffset.y, 0); - - if (transform.IsSingular()) { - return false; - } - - bool canDraw2D = transform.CanDraw2D(&transform2d); - Size scale = FrameLayerBuilder::ChooseScale( - aContainerFrame, aContainerItem, aVisibleRect, aIncomingScale.mXScale, - aIncomingScale.mYScale, transform2d, canDraw2D); - - // If this is a transform container layer, then pre-rendering might - // mean we try render a layer bigger than the max texture size. If we have - // tiling, that's not a problem, since we'll automatically choose a tiled - // layer for layers of that size. If not, we need to apply clamping to - // prevent this. - if (aTransform && !StaticPrefs::layers_enable_tiles_AtStartup()) { - RestrictScaleToMaxLayerSize(scale, aVisibleRect, aContainerFrame, aLayer); - } - - // Store the inverse of our resolution-scale on the layer - aLayer->SetBaseTransform(transform); - aLayer->SetPreScale(1.0f / scale.width, 1.0f / scale.height); - aLayer->SetInheritedScale(aIncomingScale.mXScale, aIncomingScale.mYScale); - - aOutgoingScale = ContainerLayerParameters(scale.width, scale.height, -offset, - aIncomingScale); - if (aTransform) { - aOutgoingScale.mInTransformedSubtree = true; - if (ActiveLayerTracker::IsTransformAnimated(aDisplayListBuilder, - aContainerFrame)) { - aOutgoingScale.mInActiveTransformedSubtree = true; - } - } - if ((aLayerBuilder->IsBuildingRetainedLayers() && - (!canDraw2D || transform2d.HasNonIntegerTranslation())) || - aContainerFrame->Extend3DContext() || - aContainerFrame->Combines3DTransformWithAncestors() || - // For async transform animation, the value would be changed at - // any time, integer translation is not always true. - aContainerFrame->HasAnimationOfTransform()) { - aOutgoingScale.mDisableSubpixelAntialiasingInDescendants = true; - } - return true; -} - -already_AddRefed<ContainerLayer> FrameLayerBuilder::BuildContainerLayerFor( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - nsIFrame* aContainerFrame, nsDisplayItem* aContainerItem, - nsDisplayList* aChildren, const ContainerLayerParameters& aParameters, - const Matrix4x4* aTransform, uint32_t aFlags) { - uint32_t containerDisplayItemKey = - aContainerItem ? aContainerItem->GetPerFrameKey() : 0; - NS_ASSERTION(aContainerFrame, - "Container display items here should have a frame"); - NS_ASSERTION(!aContainerItem || aContainerItem->Frame() == aContainerFrame, - "Container display item must match given frame"); - - if (!aParameters.mXScale || !aParameters.mYScale) { - return nullptr; - } - - RefPtr<ContainerLayer> containerLayer; - if (aManager == mRetainingManager) { - // Using GetOldLayerFor will search merged frames, as well as the underlying - // frame. The underlying frame can change when a page scrolls, so this - // avoids layer recreation in the situation that a new underlying frame is - // picked for a layer. - Layer* oldLayer = nullptr; - if (aContainerItem) { - oldLayer = GetOldLayerFor(aContainerItem); - } else { - DisplayItemData* data = - GetOldLayerForFrame(aContainerFrame, containerDisplayItemKey); - if (data) { - oldLayer = data->mLayer; - } - } - - if (oldLayer) { - NS_ASSERTION(oldLayer->Manager() == aManager, "Wrong manager"); - if (oldLayer->HasUserData(&gPaintedDisplayItemLayerUserData)) { - // The old layer for this item is actually our PaintedLayer - // because we rendered its layer into that PaintedLayer. So we - // don't actually have a retained container layer. - } else { - NS_ASSERTION(oldLayer->GetType() == Layer::TYPE_CONTAINER, - "Wrong layer type"); - containerLayer = static_cast<ContainerLayer*>(oldLayer); - ResetLayerStateForRecycling(containerLayer); - } - } - } - if (!containerLayer) { - // No suitable existing layer was found. - containerLayer = aManager->CreateContainerLayer(); - if (!containerLayer) return nullptr; - } - - if (aContainerItem && - aContainerItem->GetType() == DisplayItemType::TYPE_SCROLL_INFO_LAYER) { - // Empty layers only have metadata and should never have display items. We - // early exit because later, invalidation will walk up the frame tree to - // determine which painted layer gets invalidated. Since an empty layer - // should never have anything to paint, it should never be invalidated. - NS_ASSERTION(aChildren->IsEmpty(), "Should have no children"); - return containerLayer.forget(); - } - - const ActiveScrolledRoot* containerASR = - aContainerItem ? aContainerItem->GetActiveScrolledRoot() : nullptr; - const ActiveScrolledRoot* containerScrollMetadataASR = - aParameters.mScrollMetadataASR; - const ActiveScrolledRoot* containerCompositorASR = aParameters.mCompositorASR; - - ContainerLayerParameters scaleParameters; - nsRect bounds = - aChildren->GetClippedBoundsWithRespectToASR(aBuilder, containerASR); - nsRect childrenVisible = - aContainerItem ? aContainerItem->GetBuildingRectForChildren() - : aContainerFrame->InkOverflowRectRelativeToSelf(); - if (!ChooseScaleAndSetTransform( - this, aBuilder, aContainerFrame, aContainerItem, - bounds.Intersect(childrenVisible), aTransform, aParameters, - containerLayer, scaleParameters)) { - return nullptr; - } - - if (mRetainingManager) { - if (aContainerItem) { - nsPaintedDisplayItem* item = aContainerItem->AsPaintedDisplayItem(); - MOZ_ASSERT(item, "Only painted display items should build layers"); - - DisplayItemData* data = - GetDisplayItemDataForManager(item, mRetainingManager); - StoreDataForFrame(item, containerLayer, LayerState::LAYER_ACTIVE, data); - } else { - StoreDataForFrame(aContainerFrame, containerDisplayItemKey, - containerLayer, LayerState::LAYER_ACTIVE); - } - } - - nsIntRect pixBounds; - nscoord appUnitsPerDevPixel; - - nscolor backgroundColor = NS_RGBA(0, 0, 0, 0); - if (aFlags & CONTAINER_ALLOW_PULL_BACKGROUND_COLOR) { - backgroundColor = aParameters.mBackgroundColor; - } - - uint32_t flags; - ContainerState state(aBuilder, aManager, aManager->GetLayerBuilder(), - aContainerFrame, aContainerItem, bounds, containerLayer, - scaleParameters, backgroundColor, containerASR, - containerScrollMetadataASR, containerCompositorASR); - - state.ProcessDisplayItems(aChildren); - - // Set CONTENT_COMPONENT_ALPHA if any of our children have it. - // This is suboptimal ... a child could have text that's over transparent - // pixels in its own layer, but over opaque parts of previous siblings. - pixBounds = state.ScaleToOutsidePixels(bounds, false); - appUnitsPerDevPixel = state.GetAppUnitsPerDevPixel(); - state.Finish(&flags, pixBounds, aChildren); - - // CONTENT_COMPONENT_ALPHA is propogated up to the nearest CONTENT_OPAQUE - // ancestor so that BasicLayerManager knows when to copy the background into - // pushed groups. Accelerated layers managers can't necessarily do this (only - // when the visible region is a simple rect), so we propogate - // CONTENT_COMPONENT_ALPHA_DESCENDANT all the way to the root. - if (flags & Layer::CONTENT_COMPONENT_ALPHA) { - flags |= Layer::CONTENT_COMPONENT_ALPHA_DESCENDANT; - } - - // Make sure that rounding the visible region out didn't add any area - // we won't paint - if (aChildren->IsOpaque() && !aChildren->NeedsTransparentSurface()) { - bounds.ScaleRoundIn(scaleParameters.mXScale, scaleParameters.mYScale); - if (bounds.Contains(ToAppUnits(pixBounds, appUnitsPerDevPixel))) { - // Clear CONTENT_COMPONENT_ALPHA and add CONTENT_OPAQUE instead. - flags &= ~Layer::CONTENT_COMPONENT_ALPHA; - flags |= Layer::CONTENT_OPAQUE; - } - } - if (nsLayoutUtils::ShouldSnapToGrid(aContainerFrame)) { - flags |= Layer::CONTENT_SNAP_TO_GRID; - } - containerLayer->SetContentFlags(flags); - // If aContainerItem is non-null some BuildContainerLayer further up the - // call stack is responsible for setting containerLayer's visible region. - if (!aContainerItem) { - containerLayer->SetVisibleRegion( - LayerIntRegion::FromUnknownRegion(pixBounds)); - } - if (aParameters.mLayerContentsVisibleRect) { - *aParameters.mLayerContentsVisibleRect = - pixBounds + scaleParameters.mOffset; - } - - nsPresContext::ClearNotifySubDocInvalidationData(containerLayer); - - return containerLayer.forget(); -} - -Layer* FrameLayerBuilder::GetLeafLayerFor(nsDisplayListBuilder* aBuilder, - nsDisplayItem* aItem) { - Layer* layer = GetOldLayerFor(aItem); - if (!layer) { - return nullptr; - } - if (layer->HasUserData(&gPaintedDisplayItemLayerUserData)) { - // This layer was created to render Thebes-rendered content for this - // display item. The display item should not use it for its own - // layer rendering. - return nullptr; - } - ResetLayerStateForRecycling(layer); - return layer; -} - -/* static */ -void FrameLayerBuilder::InvalidateAllLayers(LayerManager* aManager) { - LayerManagerData* data = static_cast<LayerManagerData*>( - aManager->GetUserData(&gLayerManagerUserData)); - if (data) { - data->mInvalidateAllLayers = true; - } -} - -/* static */ -void FrameLayerBuilder::InvalidateAllLayersForFrame(nsIFrame* aFrame) { - for (auto* did : GetDisplayItemDataArray(aFrame)) { - DisplayItemData* data = DisplayItemData::AssertDisplayItemData(did); - data->mParent->mInvalidateAllLayers = true; - } -} - -/* static */ -Layer* FrameLayerBuilder::GetDedicatedLayer(nsIFrame* aFrame, - DisplayItemType aDisplayItemKey) { - // TODO: This isn't completely correct, since a frame could exist as a layer - // in the normal widget manager, and as a different layer (or no layer) - // in the secondary manager - for (auto* did : GetDisplayItemDataArray(aFrame)) { - DisplayItemData* data = DisplayItemData::AssertDisplayItemData(did); - if (!data->mParent->mLayerManager->IsWidgetLayerManager()) { - continue; - } - - if (GetDisplayItemTypeFromKey(data->mDisplayItemKey) == aDisplayItemKey) { - if (data->mOptLayer) { - return data->mOptLayer; - } - - Layer* layer = data->mLayer; - if (!layer->HasUserData(&gColorLayerUserData) && - !layer->HasUserData(&gImageLayerUserData) && - !layer->HasUserData(&gPaintedDisplayItemLayerUserData)) { - return layer; - } - } - } - - return nullptr; -} - -/* static */ -void FrameLayerBuilder::EnumerateGenerationForDedicatedLayers( - const nsIFrame* aFrame, AnimationGenerationCallback aCallback) { - std::bitset<static_cast<uint32_t>(DisplayItemType::TYPE_MAX)> notFoundTypes; - for (auto displayItemType : LayerAnimationInfo::sDisplayItemTypes) { - notFoundTypes.set(static_cast<uint32_t>(displayItemType)); - } - - for (auto displayItemType : LayerAnimationInfo::sDisplayItemTypes) { - // For transform animations, the animation is on the primary frame but - // |aFrame| is the style frame. - const nsIFrame* frameToQuery = - displayItemType == DisplayItemType::TYPE_TRANSFORM - ? nsLayoutUtils::GetPrimaryFrameFromStyleFrame(aFrame) - : aFrame; - - for (auto* did : GetDisplayItemDataArray(frameToQuery)) { - DisplayItemData* data = DisplayItemData::AssertDisplayItemData(did); - if (!data->mParent->mLayerManager->IsWidgetLayerManager()) { - continue; - } - - if (GetDisplayItemTypeFromKey(data->mDisplayItemKey) != displayItemType) { - continue; - } - - notFoundTypes.reset(static_cast<uint32_t>(displayItemType)); - - Maybe<uint64_t> generation; - if (data->mOptLayer) { - generation = data->mOptLayer->GetAnimationGeneration(); - } else if (!data->mLayer->HasUserData(&gColorLayerUserData) && - !data->mLayer->HasUserData(&gImageLayerUserData) && - !data->mLayer->HasUserData( - &gPaintedDisplayItemLayerUserData)) { - generation = data->mLayer->GetAnimationGeneration(); - } - - if (!aCallback(generation, displayItemType)) { - return; - } - - break; - } - } - - // Bail out if we have already enumerated all possible layers for the given - // display item types. - if (notFoundTypes.none()) { - return; - } - - // If there are any display item types that the nsIFrame doesn't have, we need - // to call the callback function for them respectively. - for (auto displayItemType : LayerAnimationInfo::sDisplayItemTypes) { - if (notFoundTypes[static_cast<uint32_t>(displayItemType)] && - !aCallback(Nothing(), displayItemType)) { - return; - } - } -} - -gfxSize FrameLayerBuilder::GetPaintedLayerScaleForFrame(nsIFrame* aFrame) { - MOZ_ASSERT(aFrame, "need a frame"); - - nsPresContext* presCtx = aFrame->PresContext()->GetRootPresContext(); - - if (!presCtx) { - presCtx = aFrame->PresContext(); - MOZ_ASSERT(presCtx); - } - - nsIFrame* root = presCtx->PresShell()->GetRootFrame(); - - MOZ_ASSERT(root); - - float resolution = presCtx->PresShell()->GetResolution(); - - Matrix4x4Flagged transform = Matrix4x4::Scaling(resolution, resolution, 1.0); - if (aFrame != root) { - // aTransform is applied first, then the scale is applied to the result - transform = nsLayoutUtils::GetTransformToAncestor(RelativeTo{aFrame}, - RelativeTo{root}) * - transform; - } - - Matrix transform2d; - if (transform.CanDraw2D(&transform2d)) { - return ThebesMatrix(transform2d).ScaleFactors(); - } - - return gfxSize(1.0, 1.0); -} - -#ifdef MOZ_DUMP_PAINTING -static void DebugPaintItem(DrawTarget& aDrawTarget, nsPresContext* aPresContext, - nsPaintedDisplayItem* aItem, - nsDisplayListBuilder* aBuilder) { - bool snap; - Rect bounds = NSRectToRect(aItem->GetBounds(aBuilder, &snap), - aPresContext->AppUnitsPerDevPixel()); - - const IntSize size = IntSize::Truncate(bounds.width, bounds.height); - if (size.IsEmpty()) { - return; - } - - RefPtr<DrawTarget> tempDT = - aDrawTarget.CreateSimilarDrawTarget(size, SurfaceFormat::B8G8R8A8); - RefPtr<gfxContext> context = gfxContext::CreateOrNull(tempDT); - if (!context) { - // Leave this as crash, it's in the debugging code, we want to know - gfxDevCrash(LogReason::InvalidContext) - << "DebugPaintItem context problem " << gfx::hexa(tempDT); - return; - } - context->SetMatrix(Matrix::Translation(-bounds.x, -bounds.y)); - - aItem->Paint(aBuilder, context); - RefPtr<SourceSurface> surface = tempDT->Snapshot(); - DumpPaintedImage(aItem, surface); - - aDrawTarget.DrawSurface(surface, bounds, Rect(Point(0, 0), bounds.Size())); - - aItem->SetPainted(); -} -#endif - -/* static */ -void FrameLayerBuilder::RecomputeVisibilityForItems( - std::vector<AssignedDisplayItem>& aItems, nsDisplayListBuilder* aBuilder, - const nsIntRegion& aRegionToDraw, nsRect& aPreviousRectToDraw, - const nsIntPoint& aOffset, int32_t aAppUnitsPerDevPixel, float aXScale, - float aYScale) { - // Update visible regions. We perform visibility analysis to take account - // of occlusion culling. - nsRegion visible = aRegionToDraw.ToAppUnits(aAppUnitsPerDevPixel); - visible.MoveBy(NSIntPixelsToAppUnits(aOffset.x, aAppUnitsPerDevPixel), - NSIntPixelsToAppUnits(aOffset.y, aAppUnitsPerDevPixel)); - visible.ScaleInverseRoundOut(aXScale, aYScale); - - // We're going to read from previousRectToDraw for every iteration, let's do - // that on the stack, and just update the heap allocated one now. By the end - // of this function {visible} will have been modified by occlusion culling. - nsRect previousRectToDraw = aPreviousRectToDraw; - aPreviousRectToDraw = visible.GetBounds(); - - for (uint32_t i = aItems.size(); i > 0; --i) { - AssignedDisplayItem* cdi = &aItems[i - 1]; - if (!cdi->mItem) { - continue; - } - - if (cdi->mHasPaintRect && - !cdi->mContentRect.Intersects(visible.GetBounds()) && - !cdi->mContentRect.Intersects(previousRectToDraw)) { - continue; - } - - if (IsEffectEndMarker(cdi->mType) || cdi->HasOpacity() || - cdi->HasTransform()) { - // The visibility calculations are skipped when the item is an effect end - // marker, or when the display item is within a flattened effect group. - // This is because RecomputeVisibility has already been called for the - // group item, and all the children. - continue; - } - - const DisplayItemClip& clip = cdi->mItem->GetClip(); - - NS_ASSERTION(AppUnitsPerDevPixel(cdi->mItem) == aAppUnitsPerDevPixel, - "a painted layer should contain items only at the same zoom"); - - MOZ_ASSERT(clip.HasClip() || clip.GetRoundedRectCount() == 0, - "If we have rounded rects, we must have a clip rect"); - - if (!clip.IsRectAffectedByClip(visible.GetBounds())) { - cdi->mItem->RecomputeVisibility(aBuilder, &visible); - continue; - } - - // Do a little dance to account for the fact that we're clipping - // to cdi->mClipRect - nsRegion clipped; - clipped.And(visible, clip.NonRoundedIntersection()); - nsRegion finalClipped = clipped; - cdi->mItem->RecomputeVisibility(aBuilder, &finalClipped); - // If we have rounded clip rects, don't subtract from the visible - // region since we aren't displaying everything inside the rect. - if (clip.GetRoundedRectCount() == 0) { - nsRegion removed; - removed.Sub(clipped, finalClipped); - nsRegion newVisible; - newVisible.Sub(visible, removed); - // Don't let the visible region get too complex. - if (newVisible.GetNumRects() <= 15) { - visible = std::move(newVisible); - } - } - } -} - -/** - * Tracks and caches the item clip. - */ -struct ItemClipTracker { - explicit ItemClipTracker(gfxContext* aContext, - const int32_t aAppUnitsPerDevPixel) - : mContext(aContext), - mHasClip(false), - mAppUnitsPerDevPixel(aAppUnitsPerDevPixel) {} - - /** - * Returns true if a clip is set. - */ - bool HasClip() const { return mHasClip; } - - /** - * Returns true if the given |aClip| is set. - */ - bool HasClip(const DisplayItemClip* aClip) const { - MOZ_ASSERT(aClip && aClip->HasClip()); - return mHasClip && mCurrentClip == *aClip; - } - - /** - * Removes the clip, if there is one. - */ - void Restore() { - if (mCurrentClip.HasClip()) { - mCurrentClip = DisplayItemClip::NoClip(); - } - - if (!HasClip()) { - return; - } - - mContext->Restore(); - mHasClip = false; - }; - - /** - * Sets the clip to |aClip|, if it is not set already. - */ - void ChangeClipIfNeeded(const DisplayItemClip* aClip) { - MOZ_ASSERT(aClip && aClip->HasClip()); - - if (HasClip(aClip)) { - // Reuse the old clip. - return; - } - - // Remove the previous clip and save the current state. - Restore(); - mContext->Save(); - - // Apply the new clip. - mHasClip = true; - mCurrentClip = *aClip; - mCurrentClip.ApplyTo(mContext, mAppUnitsPerDevPixel); - mContext->NewPath(); - } - - private: - gfxContext* mContext; - bool mHasClip; - const int32_t mAppUnitsPerDevPixel; - - DisplayItemClip mCurrentClip; -}; - -/** - * Tracks clips managed by |PushClip()| and |PopClip()|. - * If allowed by the caller, the top clip may be reused when a new clip that - * matches the previous one is pushed to the stack. - */ -struct ClipStack { - explicit ClipStack(gfxContext* aContext, const int32_t aAppUnitsPerDevPixel) - : mContext(aContext), - mAppUnitsPerDevPixel(aAppUnitsPerDevPixel), - mDeferredPopClip(false) {} - - ~ClipStack() { - MOZ_ASSERT(!mDeferredPopClip); - MOZ_ASSERT(!HasClips()); - } - - /** - * Returns true if there are clips set. - */ - bool HasClips() const { return mClips.Length() > 0; } - - /** - * Returns the clip at the top of the stack. - */ - const DisplayItemClip& TopClip() const { - MOZ_ASSERT(HasClips()); - return mClips.LastElement(); - } - - /** - * Returns true if the top clip matches the given |aClip|. - */ - bool TopClipMatches(const DisplayItemClip& aClip) { - return HasClips() && TopClip() == aClip; - } - - /** - * Pops the current top clip. If |aDeferPopClip| is true, the top clip will - * not be popped before the next call to |PopClip(false)|. - * This allows the previously set clip to be reused during the next - * |PushClip()| call, if the new clip is identical with the top clip. - */ - void PopClip(bool aDeferPopClip) { - MOZ_ASSERT(HasClips()); - - if (aDeferPopClip) { - // Do not allow reusing clip with nested effects. - MOZ_ASSERT(!mDeferredPopClip); - mDeferredPopClip = true; - return; - } - - if (TopClip().HasClip()) { - mContext->Restore(); - } - - mClips.RemoveLastElement(); - mDeferredPopClip = false; - } - - /** - * Pops the clip, if a call to |PopClip()| has been deferred. - */ - void PopDeferredClip() { - if (mDeferredPopClip) { - PopClip(false); - } - } - - /** - * Pushes the given |aClip| to the stack. - */ - void PushClip(const DisplayItemClip& aClip) { - if (mDeferredPopClip && TopClipMatches(aClip)) { - // Reuse this clip. Defer the decision to reuse it again until the next - // call to PopClip(). - mDeferredPopClip = false; - return; - } - - PopDeferredClip(); - - mClips.AppendElement(aClip); - - // Save the current state and apply new clip, if needed. - if (aClip.HasClip()) { - mContext->Save(); - aClip.ApplyTo(mContext, mAppUnitsPerDevPixel); - mContext->NewPath(); - } - } - - private: - gfxContext* mContext; - const int32_t mAppUnitsPerDevPixel; - AutoTArray<DisplayItemClip, 2> mClips; - bool mDeferredPopClip; -}; - -/** - * Returns a clip for the given |aItem|. If the clip can be simplified to not - * include rounded rects, |aOutClip| is used to store the simplified clip. - */ -static const DisplayItemClip* GetItemClip(const nsDisplayItem* aItem, - DisplayItemClip& aOutClip) { - const DisplayItemClip& clip = aItem->GetClip(); - - if (!clip.HasClip()) { - return nullptr; - } - - if (clip.GetRoundedRectCount() > 0 && - !clip.IsRectClippedByRoundedCorner(aItem->GetPaintRect())) { - aOutClip.SetTo(clip.GetClipRect()); - return &aOutClip; - } - - return &clip; -} - -/** - * Pushes a new opacity group for |aContext| based on |aItem|. - */ -static void PushOpacity(gfxContext* aContext, AssignedDisplayItem& aItem) { - MOZ_ASSERT(aItem.mType == DisplayItemEntryType::PushOpacity || - aItem.mType == DisplayItemEntryType::PushOpacityWithBg); - MOZ_ASSERT(aItem.mItem->GetType() == DisplayItemType::TYPE_OPACITY); - nsDisplayOpacity* item = static_cast<nsDisplayOpacity*>(aItem.mItem); - - const float opacity = item->GetOpacity(); - if (aItem.mType == DisplayItemEntryType::PushOpacityWithBg) { - aContext->PushGroupAndCopyBackground(gfxContentType::COLOR_ALPHA, opacity); - } else { - aContext->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, opacity); - } -} - -/** - * Pushes the transformation matrix of |aItem| into |aMatrixStack| and sets the - * accumulated transform as the current transformation matrix for |aContext|. - */ -static void PushTransform(gfxContext* aContext, AssignedDisplayItem& aItem, - nsDisplayListBuilder* aBuilder, - MatrixStack4x4& aMatrixStack, - const Matrix4x4Flagged& aBaseMatrix) { - MOZ_ASSERT(aItem.mType == DisplayItemEntryType::PushTransform); - MOZ_ASSERT(aItem.mItem->GetType() == DisplayItemType::TYPE_TRANSFORM); - - nsDisplayTransform* item = static_cast<nsDisplayTransform*>(aItem.mItem); - if (item->ShouldSkipTransform(aBuilder)) { - aMatrixStack.Push(Matrix4x4Flagged()); - } else { - aMatrixStack.Push(item->GetTransformForRendering()); - } - - gfx::Matrix4x4Flagged matrix = aMatrixStack.CurrentMatrix() * aBaseMatrix; - gfx::Matrix matrix2d; - DebugOnly<bool> ok = matrix.CanDraw2D(&matrix2d); - MOZ_ASSERT(ok); - - aContext->SetMatrix(matrix2d); -} - -static void UpdateEffectTracking(int& aOpacityLevel, int& aTransformLevel, - const DisplayItemEntryType aType) { - switch (aType) { - case DisplayItemEntryType::PushOpacity: - case DisplayItemEntryType::PushOpacityWithBg: - aOpacityLevel++; - break; - case DisplayItemEntryType::PopOpacity: - aOpacityLevel--; - break; - case DisplayItemEntryType::PushTransform: - aTransformLevel++; - break; - case DisplayItemEntryType::PopTransform: - aTransformLevel--; - break; - default: - break; - } - - MOZ_ASSERT(aOpacityLevel >= 0 && aTransformLevel >= 0); -} - -void FrameLayerBuilder::PaintItems(std::vector<AssignedDisplayItem>& aItems, - const nsIntRect& aRect, gfxContext* aContext, - nsDisplayListBuilder* aBuilder, - nsPresContext* aPresContext, - const nsIntPoint& aOffset, float aXScale, - float aYScale) { - DrawTarget& aDrawTarget = *aContext->GetDrawTarget(); - - int32_t appUnitsPerDevPixel = aPresContext->AppUnitsPerDevPixel(); - nsRect boundRect = ToAppUnits(aRect, appUnitsPerDevPixel); - boundRect.MoveBy(NSIntPixelsToAppUnits(aOffset.x, appUnitsPerDevPixel), - NSIntPixelsToAppUnits(aOffset.y, appUnitsPerDevPixel)); - boundRect.ScaleInverseRoundOut(aXScale, aYScale); - - if (boundRect.IsEmpty()) { - // Hack! This can happen if the conversion of |aRect| to scaled and offset - // app units overflowed. Ideally the conversion would detect this and handle - // such situations gracefully. For now, do nothing. - return; - } - -#ifdef DEBUG - // Tracks effect nesting level. These are used to track that every effect - // start marker has a corresponding end marker. - int opacityLevel = 0; - int transformLevel = 0; -#endif - - // Tracks effect nesting level for skipping items between effect markers, - // when the effect display item does not intersect with the invalidated area. - int emptyEffectLevel = 0; - - // Stores a simplified version of the item clip, if needed. - DisplayItemClip temporaryClip; - - // Two types of clips are used during PaintItems(): clips for items and clips - // for effects. Item clips are always the most recent clip set, and they are - // never nested. The previous item clip is reused, if the next item has the - // same clip. Item clips are removed when an effect starts or ends. - ItemClipTracker itemClipTracker(aContext, appUnitsPerDevPixel); - - // Since effects can be nested, the effect clips need to be nested as well. - // They are pushed for effect start marker, and popped for effect end marker. - // Effect clips are tracked by |effectClipStack|. If there are consecutive - // effects with the same clip, |effectClipStack| defers popping the clip for - // the first end marker, and tries to reuse the previously set clip, when - // processing the start marker for the next effect. - ClipStack effectClipStack(aContext, appUnitsPerDevPixel); - - MatrixStack4x4 matrixStack; - const Matrix4x4Flagged base = Matrix4x4::From2D(aContext->CurrentMatrix()); - - for (uint32_t i = 0; i < aItems.size(); ++i) { - AssignedDisplayItem& cdi = aItems[i]; - nsDisplayItem* item = cdi.mItem; - - const auto NextItemStartsEffect = [&]() { - const uint32_t next = i + 1; - return next < aItems.size() && IsEffectStartMarker(aItems[next].mType); - }; - - if (!item) { - MOZ_ASSERT(cdi.mType == DisplayItemEntryType::Item); - continue; - } - - nsRect visibleRect = item->GetPaintRect(); - - if (matrixStack.HasTransform()) { - MOZ_ASSERT(transformLevel > 0); - - if (IsEffectEndMarker(cdi.mType)) { - // Always process the effect end markers. - visibleRect = boundRect; - } else { - const Matrix4x4Flagged& matrix = matrixStack.CurrentMatrix(); - visibleRect = nsLayoutUtils::MatrixTransformRect(visibleRect, matrix, - appUnitsPerDevPixel); - } - } - - const nsRect paintRect = visibleRect.Intersect(boundRect); - - if (paintRect.IsEmpty() || emptyEffectLevel > 0) { - // In order for this branch to be hit, either this item has an empty paint - // rect and nothing would be drawn, or an effect marker before this - // item had an empty paint rect. In the latter case, the items are skipped - // until effect POP markers bring |emptyEffectLevel| back to 0. - UpdateEffectTracking(emptyEffectLevel, emptyEffectLevel, cdi.mType); - - // Sometimes the item that was going to reuse the previous clip is culled. - // Since |PushClip()| is never called for culled items, pop the clip now. - effectClipStack.PopDeferredClip(); - continue; - } - -#ifdef MOZ_DUMP_PAINTING - AUTO_PROFILER_LABEL_DYNAMIC_CSTR_NONSENSITIVE( - "FrameLayerBuilder::PaintItems", GRAPHICS_Rasterization, item->Name()); -#else - AUTO_PROFILER_LABEL("FrameLayerBuilder::PaintItems", - GRAPHICS_Rasterization); -#endif - - MOZ_ASSERT((opacityLevel == 0 && !cdi.HasOpacity()) || - (opacityLevel > 0 && cdi.HasOpacity()) || - (transformLevel == 0 && !cdi.HasTransform()) || - (transformLevel > 0 && cdi.HasTransform())); - - if (cdi.mType != DisplayItemEntryType::Item) { - // If we are processing an effect marker, remove the current item clip, if - // there is one. - itemClipTracker.Restore(); - } - - if (cdi.mType == DisplayItemEntryType::PushOpacity || - cdi.mType == DisplayItemEntryType::PushOpacityWithBg) { - // To avoid pushing large temporary surfaces, it is important to clip - // opacity group with both the paint rect and the actual opacity clip. - DisplayItemClip effectClip; - effectClip.SetTo(item->GetPaintRect()); - effectClip.IntersectWith(item->GetClip()); - effectClipStack.PushClip(effectClip); - PushOpacity(aContext, cdi); - } - - if (cdi.mType == DisplayItemEntryType::PopOpacity) { - MOZ_ASSERT(opacityLevel > 0); - aContext->PopGroupAndBlend(); - } - - if (cdi.mType == DisplayItemEntryType::PushTransform) { - effectClipStack.PushClip(item->GetClip()); - aContext->Save(); - PushTransform(aContext, cdi, aBuilder, matrixStack, base); - } - - if (cdi.mType == DisplayItemEntryType::PopTransform) { - MOZ_ASSERT(transformLevel > 0); - matrixStack.Pop(); - aContext->Restore(); - } - - if (IsEffectEndMarker(cdi.mType)) { - // Pop the clip for the effect. - MOZ_ASSERT(effectClipStack.HasClips()); - - // If the next item starts an effect, defer popping the current clip, and - // try to reuse it during the next call to |PushClip()|. Trying to reuse - // clips between nested effects would be difficult, for example due to - // possibly different coordinate system, so this optimization is limited - // to consecutive effects. - effectClipStack.PopClip(NextItemStartsEffect()); - } - - if (cdi.mType != DisplayItemEntryType::Item) { -#ifdef DEBUG - UpdateEffectTracking(opacityLevel, transformLevel, cdi.mType); -#endif - // Nothing more to do with effect markers. - continue; - } - - const bool paintAsLayer = cdi.mInactiveLayerData.get(); - nsPaintedDisplayItem* paintedItem = item->AsPaintedDisplayItem(); - MOZ_ASSERT(paintAsLayer || paintedItem, - "The display item does not support painting"); - - const DisplayItemClip* itemClip = GetItemClip(item, temporaryClip); - bool itemPaintsOwnClip = false; - - if (itemClip && !itemClipTracker.HasClip(itemClip)) { - // The clip has changed. Remove the previous clip. - itemClipTracker.Restore(); - - // Check if the item supports painting with clip. - itemPaintsOwnClip = - paintAsLayer ? false : paintedItem->CanPaintWithClip(*itemClip); - - if (!itemPaintsOwnClip) { - // Item does not support painting with clip, set the clip. - itemClipTracker.ChangeClipIfNeeded(itemClip); - } - } - - if (!itemClip) { - // Item does not need clipping, remove the clip if there is one. - itemClipTracker.Restore(); - } - - if (paintAsLayer) { - bool saved = aDrawTarget.GetPermitSubpixelAA(); - PaintInactiveLayer(aBuilder, cdi.mInactiveLayerData->mLayerManager, item, - aContext, aContext); - aDrawTarget.SetPermitSubpixelAA(saved); - continue; - } - - nsIFrame* frame = item->Frame(); - if (aBuilder->IsPaintingToWindow()) { - frame->AddStateBits(NS_FRAME_PAINTED_THEBES); - } - -#ifdef MOZ_DUMP_PAINTING - if (gfxEnv::DumpPaintItems()) { - DebugPaintItem(aDrawTarget, aPresContext, paintedItem, aBuilder); - continue; - } -#endif - - if (itemPaintsOwnClip) { - MOZ_ASSERT(itemClip); - paintedItem->PaintWithClip(aBuilder, aContext, *itemClip); - } else { - paintedItem->Paint(aBuilder, aContext); - } - } - - itemClipTracker.Restore(); - - MOZ_ASSERT(opacityLevel == 0); - MOZ_ASSERT(transformLevel == 0); - MOZ_ASSERT(emptyEffectLevel == 0); -} - -/** - * Returns true if it is preferred to draw the list of display - * items separately for each rect in the visible region rather - * than clipping to a complex region. - */ -static bool ShouldDrawRectsSeparately(DrawTarget* aDrawTarget, - DrawRegionClip aClip) { - if (!StaticPrefs::layout_paint_rects_separately_AtStartup() || - aClip == DrawRegionClip::NONE) { - return false; - } - - return !aDrawTarget->SupportsRegionClipping(); -} - -static void DrawForcedBackgroundColor(DrawTarget& aDrawTarget, - const IntRect& aBounds, - nscolor aBackgroundColor) { - if (NS_GET_A(aBackgroundColor) > 0) { - ColorPattern color(ToDeviceColor(aBackgroundColor)); - aDrawTarget.FillRect(Rect(aBounds), color); - } -} - -/* - * A note on residual transforms: - * - * In a transformed subtree we sometimes apply the PaintedLayer's - * "residual transform" when drawing content into the PaintedLayer. - * This is a translation by components in the range [-0.5,0.5) provided - * by the layer system; applying the residual transform followed by the - * transforms used by layer compositing ensures that the subpixel alignment - * of the content of the PaintedLayer exactly matches what it would be if - * we used cairo/Thebes to draw directly to the screen without going through - * retained layer buffers. - * - * The visible and valid regions of the PaintedLayer are computed without - * knowing the residual transform (because we don't know what the residual - * transform is going to be until we've built the layer tree!). So we have to - * consider whether content painted in the range [x, xmost) might be painted - * outside the visible region we computed for that content. The visible region - * would be [floor(x), ceil(xmost)). The content would be rendered at - * [x + r, xmost + r), where -0.5 <= r < 0.5. So some half-rendered pixels could - * indeed fall outside the computed visible region, which is not a big deal; - * similar issues already arise when we snap cliprects to nearest pixels. - * Note that if the rendering of the content is snapped to nearest pixels --- - * which it often is --- then the content is actually rendered at - * [snap(x + r), snap(xmost + r)). It turns out that floor(x) <= snap(x + r) - * and ceil(xmost) >= snap(xmost + r), so the rendering of snapped content - * always falls within the visible region we computed. - */ - -/* static */ -void FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer, - gfxContext* aContext, - const nsIntRegion& aRegionToDraw, - const nsIntRegion& aDirtyRegion, - DrawRegionClip aClip, - const nsIntRegion& aRegionToInvalidate, - void* aCallbackData) { - DrawTarget& aDrawTarget = *aContext->GetDrawTarget(); - - AUTO_PROFILER_LABEL("FrameLayerBuilder::DrawPaintedLayer", - GRAPHICS_Rasterization); - - nsDisplayListBuilder* builder = - static_cast<nsDisplayListBuilder*>(aCallbackData); - - FrameLayerBuilder* layerBuilder = aLayer->Manager()->GetLayerBuilder(); - NS_ASSERTION(layerBuilder, "Unexpectedly null layer builder!"); - - auto* userData = GetPaintedDisplayItemLayerUserData(aLayer); - NS_ASSERTION(userData, "where did our user data go?"); - if (!userData->mContainerLayerFrame) { - return; - } - - bool shouldDrawRectsSeparately = - ShouldDrawRectsSeparately(&aDrawTarget, aClip); - - if (!shouldDrawRectsSeparately) { - if (aClip == DrawRegionClip::DRAW) { - gfxUtils::ClipToRegion(aContext, aRegionToDraw); - } - - DrawForcedBackgroundColor(aDrawTarget, aRegionToDraw.GetBounds(), - userData->mForcedBackgroundColor); - } - - // make the origin of the context coincide with the origin of the - // PaintedLayer - gfxContextMatrixAutoSaveRestore saveMatrix(aContext); - nsIntPoint offset = GetTranslationForPaintedLayer(aLayer); - nsPresContext* presContext = userData->mContainerLayerFrame->PresContext(); - - if (!userData->mVisibilityComputedRegion.Contains(aDirtyRegion) && - !layerBuilder->GetContainingPaintedLayerData()) { - // Recompute visibility of items in our PaintedLayer, if required. Note - // that this recomputes visibility for all descendants of our display - // items too, so there's no need to do this for the items in inactive - // PaintedLayers. If aDirtyRegion has not changed since the previous call - // then we can skip this. - int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); - RecomputeVisibilityForItems(userData->mItems, builder, aDirtyRegion, - userData->mPreviousRecomputeVisibilityRect, - offset, appUnitsPerDevPixel, userData->mXScale, - userData->mYScale); - userData->mVisibilityComputedRegion = aDirtyRegion; - } - - if (shouldDrawRectsSeparately) { - for (auto iter = aRegionToDraw.RectIter(); !iter.Done(); iter.Next()) { - const nsIntRect& iterRect = iter.Get(); - gfxContextAutoSaveRestore save(aContext); - aContext->NewPath(); - aContext->Rectangle(ThebesRect(iterRect)); - aContext->Clip(); - - DrawForcedBackgroundColor(aDrawTarget, iterRect, - userData->mForcedBackgroundColor); - - // Apply the residual transform if it has been enabled, to ensure that - // snapping when we draw into aContext exactly matches the ideal - // transform. See above for why this is OK. - aContext->SetMatrixDouble( - aContext->CurrentMatrixDouble() - .PreTranslate(aLayer->GetResidualTranslation() - - gfxPoint(offset.x, offset.y)) - .PreScale(userData->mXScale, userData->mYScale)); - - layerBuilder->PaintItems(userData->mItems, iterRect, aContext, builder, - presContext, offset, userData->mXScale, - userData->mYScale); - if (StaticPrefs::gfx_logging_painted_pixel_count_enabled()) { - aLayer->Manager()->AddPaintedPixelCount(iterRect.Area()); - } - } - } else { - // Apply the residual transform if it has been enabled, to ensure that - // snapping when we draw into aContext exactly matches the ideal transform. - // See above for why this is OK. - aContext->SetMatrixDouble( - aContext->CurrentMatrixDouble() - .PreTranslate(aLayer->GetResidualTranslation() - - gfxPoint(offset.x, offset.y)) - .PreScale(userData->mXScale, userData->mYScale)); - - layerBuilder->PaintItems(userData->mItems, aRegionToDraw.GetBounds(), - aContext, builder, presContext, offset, - userData->mXScale, userData->mYScale); - if (StaticPrefs::gfx_logging_painted_pixel_count_enabled()) { - aLayer->Manager()->AddPaintedPixelCount(aRegionToDraw.GetBounds().Area()); - } - } - - bool isActiveLayerManager = !aLayer->Manager()->IsInactiveLayerManager(); - - if (presContext->GetPaintFlashing() && isActiveLayerManager) { - gfxContextAutoSaveRestore save(aContext); - if (shouldDrawRectsSeparately) { - if (aClip == DrawRegionClip::DRAW) { - gfxUtils::ClipToRegion(aContext, aRegionToDraw); - } - } - FlashPaint(aContext); - } - - if (presContext->GetDocShell() && isActiveLayerManager) { - nsDocShell* docShell = static_cast<nsDocShell*>(presContext->GetDocShell()); - RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get(); - - if (timelines && timelines->HasConsumer(docShell)) { - timelines->AddMarkerForDocShell( - docShell, MakeUnique<LayerTimelineMarker>(aRegionToDraw)); - } - } - - if (!aRegionToInvalidate.IsEmpty()) { - aLayer->AddInvalidRect(aRegionToInvalidate.GetBounds()); - } -} - -/* static */ -void FrameLayerBuilder::DumpRetainedLayerTree(LayerManager* aManager, - std::stringstream& aStream, - bool aDumpHtml) { - aManager->Dump(aStream, "", aDumpHtml); -} - -nsDisplayItemGeometry* FrameLayerBuilder::GetMostRecentGeometry( - nsDisplayItem* aItem) { - // Retrieve the array of DisplayItemData associated with our frame. - - // Find our display item data, if it exists, and return its geometry. - // We first check for ones with an inactive manager, since items that - // create inactive layers will create two DisplayItemData entries, - // and we want the outer one. - DisplayItemData* firstMatching = nullptr; - uint32_t itemPerFrameKey = aItem->GetPerFrameKey(); - - for (auto* did : GetDisplayItemDataArray(aItem->Frame())) { - auto* data = DisplayItemData::AssertDisplayItemData(did); - if (data->GetDisplayItemKey() == itemPerFrameKey) { - if (data->InactiveManager()) { - return data->GetGeometry(); - } - if (!firstMatching) { - firstMatching = data; - } - } - } - - if (firstMatching) { - return firstMatching->GetGeometry(); - } - - if (RefPtr<WebRenderFallbackData> data = - GetWebRenderUserData<WebRenderFallbackData>(aItem->Frame(), - itemPerFrameKey)) { - return data->GetGeometry(); - } - - return nullptr; -} - -static gfx::Rect CalculateBounds( - const nsTArray<DisplayItemClip::RoundedRect>& aRects, - int32_t aAppUnitsPerDevPixel) { - nsRect bounds = aRects[0].mRect; - for (uint32_t i = 1; i < aRects.Length(); ++i) { - bounds.UnionRect(bounds, aRects[i].mRect); - } - - return gfx::Rect(bounds.ToNearestPixels(aAppUnitsPerDevPixel)); -} - -void ContainerState::SetupMaskLayer(Layer* aLayer, - const DisplayItemClip& aClip) { - // don't build an unnecessary mask - if (aClip.GetRoundedRectCount() == 0) { - return; - } - - RefPtr<Layer> maskLayer = CreateMaskLayer(aLayer, aClip, Nothing()); - - if (!maskLayer) { - return; - } - - aLayer->SetMaskLayer(maskLayer); -} - -static MaskLayerUserData* GetMaskLayerUserData(Layer* aMaskLayer) { - if (!aMaskLayer) { - return nullptr; - } - - return static_cast<MaskLayerUserData*>( - aMaskLayer->GetUserData(&gMaskLayerUserData)); -} - -static void SetMaskLayerUserData(Layer* aMaskLayer) { - MOZ_ASSERT(aMaskLayer); - - aMaskLayer->SetUserData(&gMaskLayerUserData, new MaskLayerUserData()); -} - -already_AddRefed<Layer> ContainerState::CreateMaskLayer( - Layer* aLayer, const DisplayItemClip& aClip, - const Maybe<size_t>& aForAncestorMaskLayer) { - // aLayer will never be the container layer created by an - // nsDisplayMasksAndClipPaths because nsDisplayMasksAndClipPaths propagates - // the DisplayItemClip to its contents and is not clipped itself. - // This assertion will fail if that ever stops being the case. - MOZ_ASSERT(!aLayer->GetUserData(&gCSSMaskLayerUserData), - "A layer contains round clips should not have css-mask on it."); - - // check if we can re-use the mask layer - RefPtr<ImageLayer> maskLayer = CreateOrRecycleMaskImageLayerFor( - MaskLayerKey(aLayer, aForAncestorMaskLayer), GetMaskLayerUserData, - SetMaskLayerUserData); - MaskLayerUserData* userData = GetMaskLayerUserData(maskLayer.get()); - - int32_t A2D = mContainerFrame->PresContext()->AppUnitsPerDevPixel(); - MaskLayerUserData newData(aClip, A2D, mParameters); - if (*userData == newData) { - return maskLayer.forget(); - } - - gfx::Rect boundingRect = - CalculateBounds(newData.mRoundedClipRects, newData.mAppUnitsPerDevPixel); - boundingRect.Scale(mParameters.mXScale, mParameters.mYScale); - if (boundingRect.IsEmpty()) { - // Return early if we know that there is effectively no visible data. - return nullptr; - } - - uint32_t maxSize = mManager->GetMaxTextureSize(); - NS_ASSERTION(maxSize > 0, "Invalid max texture size"); -#ifdef MOZ_GFX_OPTIMIZE_MOBILE - // Make mask image width aligned to 4. See Bug 1245552. - gfx::Size surfaceSize( - std::min<gfx::Float>( - GetAlignedStride<4>(NSToIntCeil(boundingRect.Width()), 1), maxSize), - std::min<gfx::Float>(boundingRect.Height(), maxSize)); -#else - gfx::Size surfaceSize(std::min<gfx::Float>(boundingRect.Width(), maxSize), - std::min<gfx::Float>(boundingRect.Height(), maxSize)); -#endif - - // maskTransform is applied to the clip when it is painted into the mask (as a - // component of imageTransform), and its inverse used when the mask is used - // for masking. It is the transform from the masked layer's space to mask - // space - gfx::Matrix maskTransform = - Matrix::Scaling(surfaceSize.width / boundingRect.Width(), - surfaceSize.height / boundingRect.Height()); - if (surfaceSize.IsEmpty()) { - // Return early if we know that the size of this mask surface is empty. - return nullptr; - } - - gfx::Point p = boundingRect.TopLeft(); - maskTransform.PreTranslate(-p.x, -p.y); - // imageTransform is only used when the clip is painted to the mask - gfx::Matrix imageTransform = maskTransform; - imageTransform.PreScale(mParameters.mXScale, mParameters.mYScale); - - UniquePtr<MaskLayerImageCache::MaskLayerImageKey> newKey( - new MaskLayerImageCache::MaskLayerImageKey()); - - // copy and transform the rounded rects - for (uint32_t i = 0; i < newData.mRoundedClipRects.Length(); ++i) { - newKey->mRoundedClipRects.AppendElement( - MaskLayerImageCache::PixelRoundedRect(newData.mRoundedClipRects[i], - mContainerFrame->PresContext())); - newKey->mRoundedClipRects[i].ScaleAndTranslate(imageTransform); - } - newKey->mKnowsCompositor = mManager->AsKnowsCompositor(); - - const MaskLayerImageCache::MaskLayerImageKey* lookupKey = newKey.get(); - - // check to see if we can reuse a mask image - RefPtr<ImageContainer> container = - GetMaskLayerImageCache()->FindImageFor(&lookupKey); - - if (!container) { - IntSize surfaceSizeInt(NSToIntCeil(surfaceSize.width), - NSToIntCeil(surfaceSize.height)); - // no existing mask image, so build a new one - MaskImageData imageData(surfaceSizeInt, mManager); - RefPtr<DrawTarget> dt = imageData.CreateDrawTarget(); - - // fail if we can't get the right surface - if (!dt || !dt->IsValid()) { - NS_WARNING("Could not create DrawTarget for mask layer."); - return nullptr; - } - - RefPtr<gfxContext> context = gfxContext::CreateOrNull(dt); - MOZ_ASSERT(context); // already checked the draw target above - context->Multiply(ThebesMatrix(imageTransform)); - - // paint the clipping rects with alpha to create the mask - aClip.FillIntersectionOfRoundedRectClips( - context, DeviceColor::MaskOpaqueWhite(), newData.mAppUnitsPerDevPixel); - - // build the image and container - MOZ_ASSERT(aLayer->Manager() == mManager); - container = imageData.CreateImageAndImageContainer(); - NS_ASSERTION(container, "Could not create image container for mask layer."); - - if (!container) { - return nullptr; - } - - GetMaskLayerImageCache()->PutImage(newKey.release(), container); - } - - maskLayer->SetContainer(container); - - maskTransform.Invert(); - Matrix4x4 matrix = Matrix4x4::From2D(maskTransform); - matrix.PreTranslate(mParameters.mOffset.x, mParameters.mOffset.y, 0); - maskLayer->SetBaseTransform(matrix); - - // save the details of the clip in user data - *userData = std::move(newData); - userData->mImageKey.Reset(lookupKey); - - return maskLayer.forget(); -} - -} // namespace mozilla diff --git a/layout/painting/FrameLayerBuilder.h b/layout/painting/FrameLayerBuilder.h deleted file mode 100644 index 1060c70e282c8f97f456cb29dcfb091a1b1cbca9..0000000000000000000000000000000000000000 --- a/layout/painting/FrameLayerBuilder.h +++ /dev/null @@ -1,727 +0,0 @@ -/* -*- 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 FRAMELAYERBUILDER_H_ -#define FRAMELAYERBUILDER_H_ - -#include <cstddef> // for size_t -#include <cstdint> // for uint32_t, UINT32_MAX, int32_t, uint64_t, uint8_t -#include <iosfwd> // for stringstream -#include <vector> // for vector -#include "DisplayItemClip.h" // for DisplayItemClip -#include "LayerState.h" // for LayerState -#include "LayerUserData.h" // for LayerUserData -#include "Units.h" // for LayerIntPoint, LayoutDeviceToLayerScale2D -#include "gfxPoint.h" // for gfxSize -#include "mozilla/AlreadyAddRefed.h" // for already_AddRefed -#include "mozilla/Assertions.h" // for AssertionConditionType, MOZ_ASSERT_HELPER2 -#include "mozilla/FunctionRef.h" // for FunctionRef -#include "mozilla/RefPtr.h" // for RefPtr -#include "mozilla/UniquePtr.h" // for UniquePtr -#include "mozilla/gfx/Matrix.h" // for Matrix, Matrix4x4 -#include "mozilla/gfx/Point.h" // for Size -#include "mozilla/layers/LayerManager.h" // for LayerManager, LayerManager::NONE, LayerManager::PaintedLayerCreationHint, LayerMetricsW... -#include "mozilla/layers/LayersTypes.h" // for DrawRegionClip, EventRegions -#include "nsColor.h" // for NS_RGBA, nscolor -#include "nsDebug.h" // for NS_WARNING -#include "nsDisplayItemTypes.h" // for DisplayItemType -#include "nsISupports.h" // for NS_INLINE_DECL_REFCOUNTING, NS_LOG_ADDREF, NS_LOG_RELEASE -#include "nsPoint.h" // for nsIntPoint -#include "nsRect.h" // for nsRect (ptr only), nsIntRect -#include "nsRegion.h" // for nsIntRegion, nsRegion -#include "nsTArray.h" // for AutoTArray, nsTArray_Impl -#include "nscore.h" // for nsrefcnt - -class gfxContext; -class nsIFrame; -class nsPresContext; -class nsRootPresContext; - -namespace mozilla { -class nsDisplayItem; -class nsDisplayItemGeometry; -class nsDisplayList; -class nsDisplayListBuilder; -class nsDisplayMasksAndClipPaths; -class nsPaintedDisplayItem; - -struct ActiveScrolledRoot; -struct DisplayItemClipChain; -class TransformClipNode; -template <class T> -class Maybe; -template <typename T> -class SmallPointerArray; - -namespace layers { -class ContainerLayer; -class Layer; -class BasicLayerManager; -class PaintedLayer; -class ImageLayer; -struct LayerProperties; -} // namespace layers - -class FrameLayerBuilder; -class LayerManagerData; -class PaintedLayerData; -class ContainerState; -class PaintedDisplayItemLayerUserData; - -enum class DisplayItemEntryType : uint8_t { - Item, - PushOpacity, - PushOpacityWithBg, - PopOpacity, - PushTransform, - PopTransform, -}; - -/** - * Retained data storage: - * - * Each layer manager (widget, and inactive) stores a LayerManagerData object - * that keeps a hash-set of DisplayItemData items that were drawn into it. - * Each frame also keeps a list of DisplayItemData pointers that were - * created for that frame. DisplayItemData objects manage these lists - * automatically. - * - * During layer construction we update the data in the LayerManagerData object, - * marking items that are modified. At the end we sweep the LayerManagerData - * hash-set and remove all items that haven't been modified. - */ - -/** - * Retained data for a display item. - */ -class DisplayItemData final { - public: - friend class FrameLayerBuilder; - friend class ContainerState; - - uint32_t GetDisplayItemKey() { return mDisplayItemKey; } - layers::Layer* GetLayer() const { return mLayer; } - nsDisplayItemGeometry* GetGeometry() const { return mGeometry.get(); } - const DisplayItemClip& GetClip() const { return mClip; } - void Invalidate() { mIsInvalid = true; } - void NotifyRemoved(); - nsIFrame* FirstFrame() const { return mFrameList[0]; } - layers::BasicLayerManager* InactiveManager() const { - return mInactiveManager; - } - - bool HasMergedFrames() const { return mFrameList.Length() > 1; } - - static DisplayItemData* AssertDisplayItemData(DisplayItemData* aData); - - void* operator new(size_t sz, nsPresContext* aPresContext); - - nsrefcnt AddRef() { - if (mRefCnt == UINT32_MAX) { - NS_WARNING("refcount overflow, leaking object"); - return mRefCnt; - } - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "DisplayItemData", sizeof(DisplayItemData)); - return mRefCnt; - } - - nsrefcnt Release() { - if (mRefCnt == UINT32_MAX) { - NS_WARNING("refcount overflow, leaking object"); - return mRefCnt; - } - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "DisplayItemData"); - if (mRefCnt == 0) { - Destroy(); - return 0; - } - return mRefCnt; - } - - RefPtr<TransformClipNode> mTransform; - RefPtr<TransformClipNode> mOldTransform; - - private: - DisplayItemData(LayerManagerData* aParent, uint32_t aKey, - layers::Layer* aLayer, nsIFrame* aFrame = nullptr); - - /** - * Removes any references to this object from frames - * in mFrameList. - */ - ~DisplayItemData(); - - void Destroy(); - - /** - * Associates this DisplayItemData with a frame, and adds it - * to the LayerManagerDataProperty list on the frame. - */ - void AddFrame(nsIFrame* aFrame); - void RemoveFrame(nsIFrame* aFrame); - const nsRegion& GetChangedFrameInvalidations(); - - /** - * Updates the contents of this item to a new set of data, instead of - * allocating a new object. Set the passed in parameters, and clears the opt - * layer and inactive manager. Parent, and display item key are assumed to be - * the same. - * - * EndUpdate must be called before the end of the transaction to complete the - * update. - */ - void BeginUpdate(layers::Layer* aLayer, LayerState aState, bool aFirstUpdate, - nsPaintedDisplayItem* aItem = nullptr); - void BeginUpdate(layers::Layer* aLayer, LayerState aState, - nsPaintedDisplayItem* aItem, bool aIsReused, bool aIsMerged); - - /** - * Completes the update of this, and removes any references to data that won't - * live longer than the transaction. - * - * Updates the geometry, frame list and clip. - * For items within a PaintedLayer, a geometry object must be specified to - * retain until the next transaction. - * - */ - void EndUpdate(mozilla::UniquePtr<nsDisplayItemGeometry>&& aGeometry); - void EndUpdate(); - - uint32_t mRefCnt; - LayerManagerData* mParent; - RefPtr<layers::Layer> mLayer; - RefPtr<layers::Layer> mOptLayer; - RefPtr<layers::BasicLayerManager> mInactiveManager; - AutoTArray<nsIFrame*, 1> mFrameList; - mozilla::UniquePtr<nsDisplayItemGeometry> mGeometry; - DisplayItemClip mClip; - uint32_t mDisplayItemKey; - LayerState mLayerState; - - /** - * Temporary stoarage of the display item being referenced, only valid between - * BeginUpdate and EndUpdate. - */ - nsPaintedDisplayItem* mItem; - nsRegion mChangedFrameInvalidations; - - /** - * Used to track if data currently stored in mFramesWithLayers (from an - * existing paint) has been updated in the current paint. - */ - bool mUsed; - bool mIsInvalid; - bool mReusedItem; -}; - -class RefCountedRegion { - private: - ~RefCountedRegion() = default; - - public: - NS_INLINE_DECL_REFCOUNTING(RefCountedRegion) - - RefCountedRegion() : mIsInfinite(false) {} - nsRegion mRegion; - bool mIsInfinite; -}; - -struct AssignedDisplayItem; - -struct ContainerLayerParameters { - ContainerLayerParameters() - : mXScale(1), - mYScale(1), - mLayerContentsVisibleRect(nullptr), - mBackgroundColor(NS_RGBA(0, 0, 0, 0)), - mScrollMetadataASR(nullptr), - mCompositorASR(nullptr), - mInTransformedSubtree(false), - mInActiveTransformedSubtree(false), - mDisableSubpixelAntialiasingInDescendants(false), - mLayerCreationHint(layers::LayerManager::NONE) {} - ContainerLayerParameters(float aXScale, float aYScale) - : mXScale(aXScale), - mYScale(aYScale), - mLayerContentsVisibleRect(nullptr), - mItemVisibleRect(nullptr), - mBackgroundColor(NS_RGBA(0, 0, 0, 0)), - mScrollMetadataASR(nullptr), - mCompositorASR(nullptr), - mInTransformedSubtree(false), - mInActiveTransformedSubtree(false), - mDisableSubpixelAntialiasingInDescendants(false), - mLayerCreationHint(layers::LayerManager::NONE) {} - ContainerLayerParameters(float aXScale, float aYScale, - const nsIntPoint& aOffset, - const ContainerLayerParameters& aParent) - : mXScale(aXScale), - mYScale(aYScale), - mLayerContentsVisibleRect(nullptr), - mItemVisibleRect(nullptr), - mOffset(aOffset), - mBackgroundColor(aParent.mBackgroundColor), - mScrollMetadataASR(aParent.mScrollMetadataASR), - mCompositorASR(aParent.mCompositorASR), - mInTransformedSubtree(aParent.mInTransformedSubtree), - mInActiveTransformedSubtree(aParent.mInActiveTransformedSubtree), - mDisableSubpixelAntialiasingInDescendants( - aParent.mDisableSubpixelAntialiasingInDescendants), - mLayerCreationHint(aParent.mLayerCreationHint) {} - - float mXScale, mYScale; - - LayoutDeviceToLayerScale2D Scale() const { - return LayoutDeviceToLayerScale2D(mXScale, mYScale); - } - - /** - * If non-null, the rectangle in which BuildContainerLayerFor stores the - * visible rect of the layer, in the coordinate system of the created layer. - */ - nsIntRect* mLayerContentsVisibleRect; - - /** - * If non-null, the rectangle which stores the item's visible rect. - */ - nsRect* mItemVisibleRect; - - /** - * An offset to apply to all child layers created. - */ - nsIntPoint mOffset; - - LayerIntPoint Offset() const { - return LayerIntPoint::FromUnknownPoint(mOffset); - } - - nscolor mBackgroundColor; - const ActiveScrolledRoot* mScrollMetadataASR; - const ActiveScrolledRoot* mCompositorASR; - - bool mInTransformedSubtree; - bool mInActiveTransformedSubtree; - bool mDisableSubpixelAntialiasingInDescendants; - layers::LayerManager::PaintedLayerCreationHint mLayerCreationHint; - - /** - * When this is false, PaintedLayer coordinates are drawn to with an integer - * translation and the scale in mXScale/mYScale. - */ - bool AllowResidualTranslation() { - // If we're in a transformed subtree, but no ancestor transform is actively - // changing, we'll use the residual translation when drawing into the - // PaintedLayer to ensure that snapping exactly matches the ideal transform. - return mInTransformedSubtree && !mInActiveTransformedSubtree; - } -}; - -/** - * The FrameLayerBuilder is responsible for converting display lists - * into layer trees. Every LayerManager needs a unique FrameLayerBuilder - * to build layers. - * - * The most important API in this class is BuildContainerLayerFor. This - * method takes a display list as input and constructs a ContainerLayer - * with child layers that render the contents of the display list. It - * records the relationship between frames and layers. - * - * That data enables us to retain layer trees. When constructing a - * ContainerLayer, we first check to see if there's an existing - * ContainerLayer for the same frame that can be recycled. If we recycle - * it, we also try to reuse its existing PaintedLayer children to render - * the display items without layers of their own. The idea is that by - * recycling layers deterministically, we can ensure that when nothing - * changes in a display list, we will reuse the existing layers without - * changes. - * - * We expose a GetLeafLayerFor method that can be called by display items - * that make their own layers (e.g. canvas and video); this method - * locates the last layer used to render the display item, if any, and - * return it as a candidate for recycling. - * - * FrameLayerBuilder sets up PaintedLayers so that 0,0 in the Painted layer - * corresponds to the (pixel-snapped) top-left of the aAnimatedGeometryRoot. - * It sets up ContainerLayers so that 0,0 in the container layer - * corresponds to the snapped top-left of the display item reference frame. - * - * When we construct a container layer, we know the transform that will be - * applied to the layer. If the transform scales the content, we can get - * better results when intermediate buffers are used by pushing some scale - * from the container's transform down to the children. For PaintedLayer - * children, the scaling can be achieved by changing the size of the layer - * and drawing into it with increased or decreased resolution. By convention, - * integer types (nsIntPoint/nsIntSize/nsIntRect/nsIntRegion) are all in layer - * coordinates, post-scaling, whereas appunit types are all pre-scaling. - */ -class FrameLayerBuilder : public layers::LayerUserData { - public: - typedef layers::ContainerLayer ContainerLayer; - typedef layers::Layer Layer; - typedef layers::PaintedLayer PaintedLayer; - typedef layers::ImageLayer ImageLayer; - typedef layers::LayerManager LayerManager; - typedef layers::BasicLayerManager BasicLayerManager; - typedef layers::EventRegions EventRegions; - - FrameLayerBuilder(); - ~FrameLayerBuilder() override; - - static gfx::Size ChooseScale(nsIFrame* aContainerFrame, - nsDisplayItem* aContainerItem, - const nsRect& aVisibleRect, float aXScale, - float aYScale, const gfx::Matrix& aTransform2d, - bool aCanDraw2D); - - static void Shutdown(); - - void Init(nsDisplayListBuilder* aBuilder, LayerManager* aManager, - PaintedLayerData* aLayerData = nullptr, - bool aIsInactiveLayerManager = false, - const DisplayItemClip* aInactiveLayerClip = nullptr); - - /** - * Call this to notify that we have just started a transaction on the - * retained layer manager aManager. - */ - void DidBeginRetainedLayerTransaction(LayerManager* aManager); - - /** - * Call this just before we end a transaction. - */ - void WillEndTransaction(); - - /** - * Call this after we end a transaction. - */ - void DidEndTransaction(); - - enum { - /** - * Set this when pulling an opaque background color from behind the - * container layer into the container doesn't change the visual results, - * given the effects you're going to apply to the container layer. - * For example, this is compatible with opacity or clipping/masking, but - * not with non-OVER blend modes or filters. - */ - CONTAINER_ALLOW_PULL_BACKGROUND_COLOR = 0x01 - }; - /** - * Build a container layer for a display item that contains a child - * list, either reusing an existing one or creating a new one. It - * sets the container layer children to layers which together render - * the contents of the display list. It reuses existing layers from - * the retained layer manager if possible. - * aContainerItem may be null, in which case we construct a root layer. - * This gets called by display list code. It calls BuildLayer on the - * items in the display list, making items with their own layers - * children of the new container, and assigning all other items to - * PaintedLayer children created and managed by the FrameLayerBuilder. - * Returns a layer with clip rect cleared; it is the - * caller's responsibility to add any clip rect. The visible region - * is set based on what's in the layer. - * The container layer is transformed by aTransform (if non-null), and - * the result is transformed by the scale factors in aContainerParameters. - * aChildren is modified due to display item merging and flattening. - * The visible region of the returned layer is set only if aContainerItem - * is null. - */ - already_AddRefed<ContainerLayer> BuildContainerLayerFor( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - nsIFrame* aContainerFrame, nsDisplayItem* aContainerItem, - nsDisplayList* aChildren, - const ContainerLayerParameters& aContainerParameters, - const gfx::Matrix4x4* aTransform, uint32_t aFlags = 0); - - /** - * Get a retained layer for a display item that needs to create its own - * layer for rendering (i.e. under nsDisplayItem::BuildLayer). Returns - * null if no retained layer is available, which usually means that this - * display item didn't have a layer before so the caller will - * need to create one. - * Returns a layer with clip rect cleared; it is the - * caller's responsibility to add any clip rect and set the visible - * region. - */ - Layer* GetLeafLayerFor(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem); - - /** - * Call this to force all retained layers to be discarded and recreated at - * the next paint. - */ - static void InvalidateAllLayers(LayerManager* aManager); - static void InvalidateAllLayersForFrame(nsIFrame* aFrame); - - /** - * Call this to determine if a frame has a dedicated (non-Painted) layer - * for the given display item key. If there isn't one, we return null, - * otherwise we return the layer. - */ - static Layer* GetDedicatedLayer(nsIFrame* aFrame, - DisplayItemType aDisplayItemType); - - using AnimationGenerationCallback = FunctionRef<bool( - const Maybe<uint64_t>& aGeneration, DisplayItemType aDisplayItemType)>; - /** - * Enumerates layers for the all display item types that correspond to - * properties we can animate on layers and calls |aCallback| - * with the animation generation for the layer. If there is no corresponding - * layer for the display item or the layer has no animation, the animation - * generation is Nothing(). - * - * The enumeration stops if |aCallback| returns false. - */ - static void EnumerateGenerationForDedicatedLayers( - const nsIFrame* aFrame, AnimationGenerationCallback); - - /** - * This callback must be provided to EndTransaction. The callback data - * must be the nsDisplayListBuilder containing this FrameLayerBuilder. - * This function can be called multiple times in a row to draw - * different regions. This will occur when, for example, progressive paint is - * enabled. In these cases aDirtyRegion can be used to specify a larger region - * than aRegionToDraw that will be drawn during the transaction, possibly - * allowing the callback to make optimizations. - */ - static void DrawPaintedLayer(PaintedLayer* aLayer, gfxContext* aContext, - const nsIntRegion& aRegionToDraw, - const nsIntRegion& aDirtyRegion, - mozilla::layers::DrawRegionClip aClip, - const nsIntRegion& aRegionToInvalidate, - void* aCallbackData); - - /** - * Dumps this FrameLayerBuilder's retained layer manager's retained - * layer tree. Defaults to dumping to stdout in non-HTML format. - */ - static void DumpRetainedLayerTree(LayerManager* aManager, - std::stringstream& aStream, - bool aDumpHtml = false); - - /** - * Returns the most recently allocated geometry item for the given display - * item. - * - * XXX(seth): The current implementation must iterate through all display - * items allocated for this display item's frame. This may lead to O(n^2) - * behavior in some situations. - */ - static nsDisplayItemGeometry* GetMostRecentGeometry(nsDisplayItem* aItem); - - /******* PRIVATE METHODS to FrameLayerBuilder.cpp ********/ - /* These are only in the public section because they need - * to be called by file-scope helper functions in FrameLayerBuilder.cpp. - */ - - /** - * Record aItem as a display item that is rendered by the PaintedLayer - * aLayer, with aClipRect, where aContainerLayerFrame is the frame - * for the container layer this ThebesItem belongs to. - * aItem must have an underlying frame. - * @param aTopLeft offset from active scrolled root to reference frame - */ - void AddPaintedDisplayItem(PaintedLayerData* aLayerData, - AssignedDisplayItem& aAssignedDisplayItem, - Layer* aLayer); - - /** - * Calls GetOldLayerForFrame on the underlying frame of the display item, - * and each subsequent merged frame if no layer is found for the underlying - * frame. - */ - Layer* GetOldLayerFor(nsDisplayItem* aItem, - nsDisplayItemGeometry** aOldGeometry = nullptr, - DisplayItemClip** aOldClip = nullptr); - - static DisplayItemData* GetOldDataFor(nsDisplayItem* aItem); - - /** - * Destroy any stored LayerManagerDataProperty and the associated data for - * aFrame. - */ - static void DestroyDisplayItemDataFor(nsIFrame* aFrame); - - LayerManager* GetRetainingLayerManager() { return mRetainingManager; } - - /** - * Returns true if the given display item was rendered during the previous - * paint. Returns false otherwise. - */ - static bool HasRetainedDataFor(const nsIFrame* aFrame, - uint32_t aDisplayItemKey); - - /** - * Return the resolution at which we expect to render aFrame's contents, - * assuming they are being painted to retained layers. This takes into account - * the resolution the contents of the ContainerLayer containing aFrame are - * being rendered at, as well as any currently-inactive transforms between - * aFrame and that container layer. - */ - static gfxSize GetPaintedLayerScaleForFrame(nsIFrame* aFrame); - - static void RemoveFrameFromLayerManager(nsIFrame* aFrame); - - /** - * Given a frame and a display item key that uniquely identifies a - * display item for the frame, find the layer that was last used to - * render that display item. Returns null if there is no such layer. - * This could be a dedicated layer for the display item, or a PaintedLayer - * that renders many display items. - */ - DisplayItemData* GetOldLayerForFrame( - nsIFrame* aFrame, uint32_t aDisplayItemKey, - DisplayItemData* aOldData = nullptr, - LayerManager* aOldLayerManager = nullptr); - - /** - * Stores DisplayItemData associated with aFrame, stores the data in - * mNewDisplayItemData. - */ - DisplayItemData* StoreDataForFrame(nsPaintedDisplayItem* aItem, Layer* aLayer, - LayerState aState, DisplayItemData* aData); - void StoreDataForFrame(nsIFrame* aFrame, uint32_t aDisplayItemKey, - Layer* aLayer, LayerState aState); - - protected: - friend class LayerManagerData; - - // Flash the area within the context clip if paint flashing is enabled. - static void FlashPaint(gfxContext* aContext); - - /* - * Get the DisplayItemData array associated with this frame, or null if one - * doesn't exist. - * - * Note that the pointer returned here is only valid so long as you don't - * poke the LayerManagerData's mFramesWithLayers hashtable. - */ - DisplayItemData* GetDisplayItemData(nsIFrame* aFrame, uint32_t aKey); - - /* - * Get the DisplayItemData associated with this display item, - * using the LayerManager instead of FrameLayerBuilder. - */ - static DisplayItemData* GetDisplayItemDataForManager( - nsPaintedDisplayItem* aItem, LayerManager* aManager); - - /** - * We store one of these for each display item associated with a - * PaintedLayer, in a hashtable that maps each PaintedLayer to an array - * of ClippedDisplayItems. (PaintedLayerItemsEntry is the hash entry - * for that hashtable.) - * These are only stored during the paint process, so that the - * DrawPaintedLayer callback can figure out which items to draw for the - * PaintedLayer. - */ - - static void RecomputeVisibilityForItems( - std::vector<AssignedDisplayItem>& aItems, nsDisplayListBuilder* aBuilder, - const nsIntRegion& aRegionToDraw, nsRect& aPreviousRectToDraw, - const nsIntPoint& aOffset, int32_t aAppUnitsPerDevPixel, float aXScale, - float aYScale); - - void PaintItems(std::vector<AssignedDisplayItem>& aItems, - const nsIntRect& aRect, gfxContext* aContext, - nsDisplayListBuilder* aBuilder, nsPresContext* aPresContext, - const nsIntPoint& aOffset, float aXScale, float aYScale); - - /** - * We accumulate ClippedDisplayItem elements in a hashtable during - * the paint process. This is the hashentry for that hashtable. - */ - public: - /** - * Add the PaintedDisplayItemLayerUserData object as being used in this - * transaction so that we do some end-of-paint maintenance on it. - */ - void AddPaintedLayerItemsEntry(PaintedDisplayItemLayerUserData* aData); - - PaintedLayerData* GetContainingPaintedLayerData() { - return mContainingPaintedLayer; - } - - const DisplayItemClip* GetInactiveLayerClip() const { - return mInactiveLayerClip; - } - - /* - * If we're building layers for an item with an inactive layer tree, - * this function saves the item's clip, which will later be applied - * to the event regions. The clip should be relative to - * mContainingPaintedLayer->mReferenceFrame. - */ - void SetInactiveLayerClip(const DisplayItemClip* aClip) { - mInactiveLayerClip = aClip; - } - - bool IsBuildingRetainedLayers() { - return !mIsInactiveLayerManager && mRetainingManager; - } - - /** - * Attempt to build the most compressed layer tree possible, even if it means - * throwing away existing retained buffers. - */ - void SetLayerTreeCompressionMode() { mInLayerTreeCompressionMode = true; } - bool CheckInLayerTreeCompressionMode(); - - void ComputeGeometryChangeForItem(DisplayItemData* aData); - - // Defined and used only in dom/base/nsDOMWindowUtils.cpp - template <class T> - static T* GetDebugSingleOldLayerForFrame(nsIFrame* aFrame); - - protected: - /** - * The layer manager belonging to the widget that is being retained - * across paints. - */ - LayerManager* mRetainingManager; - /** - * The root prescontext for the display list builder reference frame - */ - RefPtr<nsRootPresContext> mRootPresContext; - - /** - * The display list builder being used. - */ - nsDisplayListBuilder* mDisplayListBuilder; - /** - * An array of PaintedLayer user data objects containing the - * list of display items (plus clipping data) to be rendered in the - * layer. We clean these up at the end of the transaction to - * remove references to display items. - */ - AutoTArray<RefPtr<PaintedDisplayItemLayerUserData>, 5> mPaintedLayerItems; - - /** - * When building layers for an inactive layer, this is where the - * inactive layer will be placed. - */ - PaintedLayerData* mContainingPaintedLayer; - - /** - * When building layers for an inactive layer, this stores the clip - * of the display item that built the inactive layer. - */ - const DisplayItemClip* mInactiveLayerClip; - - /** - * Indicates that the entire layer tree should be rerendered - * during this paint. - */ - bool mInvalidateAllLayers; - - bool mInLayerTreeCompressionMode; - - bool mIsInactiveLayerManager; -}; - -} // namespace mozilla - -#endif /* FRAMELAYERBUILDER_H_ */ diff --git a/layout/painting/HitTestInfo.cpp b/layout/painting/HitTestInfo.cpp index 7eab218e9fcaa406c5d28830566817cd707f76ac..7fde3e2d3c5cad5b6ecfef59f4da3143a455565c 100644 --- a/layout/painting/HitTestInfo.cpp +++ b/layout/painting/HitTestInfo.cpp @@ -8,6 +8,7 @@ #include "mozilla/webrender/WebRenderAPI.h" #include "nsDisplayList.h" #include "nsIFrame.h" +#include "mozilla/layers/ScrollableLayerGuid.h" namespace mozilla { @@ -44,7 +45,7 @@ ViewID HitTestInfo::GetViewId(wr::DisplayListBuilder& aBuilder, return aASR->GetViewId(); } - return ScrollableLayerGuid::NULL_SCROLL_ID; + return layers::ScrollableLayerGuid::NULL_SCROLL_ID; } void HitTestInfo::Initialize(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) { diff --git a/layout/painting/RetainedDisplayListBuilder.cpp b/layout/painting/RetainedDisplayListBuilder.cpp index ddf2c69bf52d64f4c37668db6b5af5b24b2c8208..a4ab2905e73e9153ad67bfa5fb8cbc52883f082a 100644 --- a/layout/painting/RetainedDisplayListBuilder.cpp +++ b/layout/painting/RetainedDisplayListBuilder.cpp @@ -81,12 +81,10 @@ static void MarkFramesWithItemsAndImagesModified(nsDisplayList* aList) { // If we have existing cached geometry for this item, then check that for // whether we need to invalidate for a sync decode. If we don't, then // use the item's flags. - DisplayItemData* data = FrameLayerBuilder::GetOldDataFor(i); - // XXX: handle webrender case + // XXX: handle webrender case by looking up retained data for the item + // and checking InvalidateForSyncDecodeImages bool invalidate = false; - if (data && data->GetGeometry()) { - invalidate = data->GetGeometry()->InvalidateForSyncDecodeImages(); - } else if (!(i->GetFlags() & TYPE_RENDERS_NO_IMAGES)) { + if (!(i->GetFlags() & TYPE_RENDERS_NO_IMAGES)) { invalidate = true; } diff --git a/layout/painting/moz.build b/layout/painting/moz.build index 67829f341587dfb4aba3643662eb907fae7e4b0e..c22ddab407102196082b6bc40f684552d7668920 100644 --- a/layout/painting/moz.build +++ b/layout/painting/moz.build @@ -12,7 +12,6 @@ EXPORTS += [ "DisplayItemClip.h", "DisplayItemClipChain.h", "DisplayListClipState.h", - "FrameLayerBuilder.h", "HitTestInfo.h", "LayerState.h", "MatrixStack.h", @@ -41,7 +40,6 @@ UNIFIED_SOURCES += [ "DisplayItemClipChain.cpp", "DisplayListClipState.cpp", "DottedCornerFinder.cpp", - "FrameLayerBuilder.cpp", "HitTestInfo.cpp", "MaskLayerImageCache.cpp", "nsCSSRendering.cpp", diff --git a/layout/painting/nsDisplayList.cpp b/layout/painting/nsDisplayList.cpp index 5edfd52bb529169690fc669b3d82bc9987216aa2..4568ca57ad8e71a4aac2244727d4913e505c4140 100644 --- a/layout/painting/nsDisplayList.cpp +++ b/layout/painting/nsDisplayList.cpp @@ -92,7 +92,6 @@ #include "nsPrintfCString.h" #include "UnitTransforms.h" #include "LayerAnimationInfo.h" -#include "FrameLayerBuilder.h" #include "mozilla/EventStateManager.h" #include "nsCaret.h" #include "nsDOMTokenList.h" @@ -123,20 +122,6 @@ using namespace layout; using namespace layers; using namespace image; -#ifdef DEBUG -static bool SpammyLayoutWarningsEnabled() { - static bool sValue = false; - static bool sValueInitialized = false; - - if (!sValueInitialized) { - Preferences::GetBool("layout.spammy_warnings.enabled", &sValue); - sValueInitialized = true; - } - - return sValue; -} -#endif - #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED void AssertUniqueItem(nsDisplayItem* aItem) { for (nsDisplayItem* i : aItem->Frame()->DisplayItems()) { @@ -2373,112 +2358,6 @@ Layer* GetLayerForRootMetadata(Layer* aRootLayer, return asyncZoomContainer ? asyncZoomContainer : aRootLayer; } -FrameLayerBuilder* nsDisplayList::BuildLayers(nsDisplayListBuilder* aBuilder, - LayerManager* aLayerManager, - uint32_t aFlags, - bool aIsWidgetTransaction) { - nsIFrame* frame = aBuilder->RootReferenceFrame(); - nsPresContext* presContext = frame->PresContext(); - PresShell* presShell = presContext->PresShell(); - - FrameLayerBuilder* layerBuilder = new FrameLayerBuilder(); - layerBuilder->Init(aBuilder, aLayerManager); - - if (aFlags & PAINT_COMPRESSED) { - layerBuilder->SetLayerTreeCompressionMode(); - } - - RefPtr<ContainerLayer> root; - { - AUTO_PROFILER_LABEL_CATEGORY_PAIR(GRAPHICS_LayerBuilding); - AUTO_PROFILER_TRACING_MARKER_DOCSHELL("Paint", "LayerBuilding", GRAPHICS, - presContext->GetDocShell()); - - if (XRE_IsContentProcess() && StaticPrefs::gfx_content_always_paint()) { - FrameLayerBuilder::InvalidateAllLayers(aLayerManager); - } - - if (aIsWidgetTransaction) { - layerBuilder->DidBeginRetainedLayerTransaction(aLayerManager); - } - - // Clear any ScrollMetadata that may have been set on the root layer on a - // previous paint. This paint will set new metrics if necessary, and if we - // don't clear the old one here, we may be left with extra metrics. - if (Layer* rootLayer = aLayerManager->GetRoot()) { - rootLayer->SetScrollMetadata(nsTArray<ScrollMetadata>()); - } - - float resolutionUniform = 1.0f; - float resolutionX = resolutionUniform; - float resolutionY = resolutionUniform; - - // If we are in a remote browser, then apply scaling from ancestor browsers - if (BrowserChild* browserChild = BrowserChild::GetFrom(presShell)) { - if (!browserChild->IsTopLevel()) { - resolutionX *= browserChild->GetEffectsInfo().mScaleX; - resolutionY *= browserChild->GetEffectsInfo().mScaleY; - } - } - - ContainerLayerParameters containerParameters(resolutionX, resolutionY); - - { - const auto start = TimeStamp::Now(); - - root = layerBuilder->BuildContainerLayerFor(aBuilder, aLayerManager, - frame, nullptr, this, - containerParameters, nullptr); - - aBuilder->NotifyAndClearScrollFrames(); - - if (StaticPrefs::layers_acceleration_draw_fps()) { - if (PaintTiming* pt = - ClientLayerManager::MaybeGetPaintTiming(aLayerManager)) { - pt->flbMs() = (TimeStamp::Now() - start).ToMilliseconds(); - } - } - } - - if (!root) { - return nullptr; - } - // Root is being scaled up by the X/Y resolution. Scale it back down. - root->SetPostScale(1.0f / resolutionX, 1.0f / resolutionY); - - auto callback = [root](ScrollableLayerGuid::ViewID aScrollId) -> bool { - return nsLayoutUtils::ContainsMetricsWithId(root, aScrollId); - }; - if (Maybe<ScrollMetadata> rootMetadata = nsLayoutUtils::GetRootMetadata( - aBuilder, root->Manager(), containerParameters, callback)) { - GetLayerForRootMetadata(root, rootMetadata->GetMetrics().GetScrollId()) - ->SetScrollMetadata(rootMetadata.value()); - } - - // NS_WARNING is debug-only, so don't even bother checking the conditions - // in a release build. -#ifdef DEBUG - bool usingDisplayport = false; - if (nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame()) { - nsIContent* content = rootScrollFrame->GetContent(); - if (content) { - usingDisplayport = DisplayPortUtils::HasDisplayPort(content); - } - } - if (usingDisplayport && - !(root->GetContentFlags() & Layer::CONTENT_OPAQUE) && - SpammyLayoutWarningsEnabled()) { - // See bug 693938, attachment 567017 - NS_WARNING("Transparent content with displayports can be expensive."); - } -#endif - - aLayerManager->SetRoot(root); - layerBuilder->WillEndTransaction(); - } - return layerBuilder; -} - void nsDisplayList::Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx, int32_t aAppUnitsPerDevPixel) { FlattenedDisplayListIterator iter(aBuilder, this); @@ -2680,26 +2559,9 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot( } if (!sent) { - if (renderer->AsFallback()) { - renderer->AsFallback()->EndTransactionWithList( - aBuilder, this, presContext->AppUnitsPerDevPixel(), flags); - } else { - const auto start = TimeStamp::Now(); - - FrameLayerBuilder* layerBuilder = - BuildLayers(aBuilder, layerManager, aFlags, widgetTransaction); - - Telemetry::AccumulateTimeDelta(Telemetry::PAINT_BUILD_LAYERS_TIME, start); - - if (!layerBuilder) { - layerManager->SetUserData(&gLayerManagerLayerBuilder, nullptr); - return nullptr; - } - - layerManager->EndTransaction(FrameLayerBuilder::DrawPaintedLayer, - aBuilder, flags); - layerBuilder->DidEndTransaction(); - } + MOZ_ASSERT(renderer->AsFallback()); + renderer->AsFallback()->EndTransactionWithList( + aBuilder, this, presContext->AppUnitsPerDevPixel(), flags); } if (widgetTransaction || @@ -3331,38 +3193,6 @@ nsRect nsDisplaySolidColor::GetBounds(nsDisplayListBuilder* aBuilder, return mBounds; } -LayerState nsDisplaySolidColor::GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - if (ForceActiveLayers()) { - return LayerState::LAYER_ACTIVE; - } - - return LayerState::LAYER_NONE; -} - -already_AddRefed<Layer> nsDisplaySolidColor::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - RefPtr<ColorLayer> layer = static_cast<ColorLayer*>( - aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this)); - if (!layer) { - layer = aManager->CreateColorLayer(); - if (!layer) { - return nullptr; - } - } - layer->SetColor(ToDeviceColor(mColor)); - - const int32_t appUnitsPerDevPixel = - mFrame->PresContext()->AppUnitsPerDevPixel(); - layer->SetBounds(mBounds.ToNearestPixels(appUnitsPerDevPixel)); - layer->SetBaseTransform(gfx::Matrix4x4::Translation( - aContainerParameters.mOffset.x, aContainerParameters.mOffset.y, 0)); - - return layer.forget(); -} - void nsDisplaySolidColor::Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) { int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel(); @@ -4061,75 +3891,6 @@ static void CheckForBorderItem(nsDisplayItem* aItem, uint32_t& aFlags) { } } -LayerState nsDisplayBackgroundImage::GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - mImageFlags = aBuilder->GetBackgroundPaintFlags(); - CheckForBorderItem(this, mImageFlags); - - ImageLayerization shouldLayerize = ShouldCreateOwnLayer(aBuilder, aManager); - if (shouldLayerize == NO_LAYER_NEEDED) { - // We can skip the call to CanOptimizeToImageLayer if we don't want a - // layer anyway. - return LayerState::LAYER_NONE; - } - - if (CanOptimizeToImageLayer(aManager, aBuilder)) { - if (shouldLayerize == WHENEVER_POSSIBLE) { - return LayerState::LAYER_ACTIVE; - } - - MOZ_ASSERT(shouldLayerize == ONLY_FOR_SCALING, - "unhandled ImageLayerization value?"); - - MOZ_ASSERT(mImage); - int32_t imageWidth; - int32_t imageHeight; - mImage->GetWidth(&imageWidth); - mImage->GetHeight(&imageHeight); - NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!"); - - int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel(); - LayoutDeviceRect destRect = - LayoutDeviceRect::FromAppUnits(GetDestRect(), appUnitsPerDevPixel); - - const LayerRect destLayerRect = destRect * aParameters.Scale(); - - // Calculate the scaling factor for the frame. - const gfxSize scale = gfxSize(destLayerRect.width / imageWidth, - destLayerRect.height / imageHeight); - - if ((scale.width != 1.0f || scale.height != 1.0f) && - (destLayerRect.width * destLayerRect.height >= 64 * 64)) { - // Separate this image into a layer. - // There's no point in doing this if we are not scaling at all or if the - // target size is pretty small. - return LayerState::LAYER_ACTIVE; - } - } - - return LayerState::LAYER_NONE; -} - -already_AddRefed<Layer> nsDisplayBackgroundImage::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - RefPtr<ImageLayer> layer = static_cast<ImageLayer*>( - aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this)); - if (!layer) { - layer = aManager->CreateImageLayer(); - if (!layer) { - return nullptr; - } - } - RefPtr<ImageContainer> imageContainer = GetContainer(aManager, aBuilder); - layer->SetContainer(imageContainer); - ConfigureLayer(layer, aParameters); - // ConfigureLayer doesn't know about our opacity, so apply it to layer here. - layer->SetOpacity(mOpacity); - return layer.forget(); -} - bool nsDisplayBackgroundImage::CanBuildWebRenderDisplayItems( LayerManager* aManager, nsDisplayListBuilder* aBuilder) { if (aBuilder) { @@ -4559,48 +4320,6 @@ nsRect nsDisplayThemedBackground::GetBoundsInternal() { return r + ToReferenceFrame(); } -void nsDisplayImageContainer::ConfigureLayer( - ImageLayer* aLayer, const ContainerLayerParameters& aParameters) { - aLayer->SetSamplingFilter(nsLayoutUtils::GetSamplingFilterForFrame(mFrame)); - - nsCOMPtr<imgIContainer> image = GetImage(); - MOZ_ASSERT(image); - int32_t imageWidth; - int32_t imageHeight; - image->GetWidth(&imageWidth); - image->GetHeight(&imageHeight); - NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!"); - - if (imageWidth > 0 && imageHeight > 0) { - // We're actually using the ImageContainer. Let our frame know that it - // should consider itself to have painted successfully. - UpdateDrawResult(ImgDrawResult::SUCCESS); - } - - // It's possible (for example, due to downscale-during-decode) that the - // ImageContainer this ImageLayer is holding has a different size from the - // intrinsic size of the image. For this reason we compute the transform using - // the ImageContainer's size rather than the image's intrinsic size. - // XXX(seth): In reality, since the size of the ImageContainer may change - // asynchronously, this is not enough. Bug 1183378 will provide a more - // complete fix, but this solution is safe in more cases than simply relying - // on the intrinsic size. - IntSize containerSize = aLayer->GetContainer() - ? aLayer->GetContainer()->GetCurrentSize() - : IntSize(imageWidth, imageHeight); - - const int32_t factor = mFrame->PresContext()->AppUnitsPerDevPixel(); - const LayoutDeviceRect destRect( - LayoutDeviceIntRect::FromAppUnitsToNearest(GetDestRect(), factor)); - - const LayoutDevicePoint p = destRect.TopLeft(); - Matrix transform = Matrix::Translation(p.x + aParameters.mOffset.x, - p.y + aParameters.mOffset.y); - transform.PreScale(destRect.width / containerSize.width, - destRect.height / containerSize.height); - aLayer->SetBaseTransform(gfx::Matrix4x4::From2D(transform)); -} - already_AddRefed<ImageContainer> nsDisplayImageContainer::GetContainer( LayerManager* aManager, nsDisplayListBuilder* aBuilder) { nsCOMPtr<imgIContainer> image = GetImage(); @@ -4697,54 +4416,6 @@ bool nsDisplayBackgroundColor::CanApplyOpacity() const { mFrame, DisplayItemType::TYPE_BACKGROUND_COLOR); } -LayerState nsDisplayBackgroundColor::GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - if (ForceActiveLayers() && !HasBackgroundClipText()) { - return LayerState::LAYER_ACTIVE; - } - - if (EffectCompositor::HasAnimationsForCompositor( - mFrame, DisplayItemType::TYPE_BACKGROUND_COLOR)) { - return LayerState::LAYER_ACTIVE_FORCE; - } - - return LayerState::LAYER_NONE; -} - -already_AddRefed<Layer> nsDisplayBackgroundColor::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - if (mColor == sRGBColor() && - !EffectCompositor::HasAnimationsForCompositor( - mFrame, DisplayItemType::TYPE_BACKGROUND_COLOR)) { - return nullptr; - } - - RefPtr<ColorLayer> layer = static_cast<ColorLayer*>( - aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this)); - if (!layer) { - layer = aManager->CreateColorLayer(); - if (!layer) { - return nullptr; - } - } - layer->SetColor(ToDeviceColor(mColor)); - - int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel(); - layer->SetBounds(mBackgroundRect.ToNearestPixels(appUnitsPerDevPixel)); - layer->SetBaseTransform(gfx::Matrix4x4::Translation( - aContainerParameters.mOffset.x, aContainerParameters.mOffset.y, 0)); - - // Both nsDisplayBackgroundColor and nsDisplayTableBackgroundColor use this - // function, but only nsDisplayBackgroundColor supports compositor animations. - if (GetType() == DisplayItemType::TYPE_BACKGROUND_COLOR) { - nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer( - layer, aBuilder, this, mFrame, GetType()); - } - return layer.forget(); -} - bool nsDisplayBackgroundColor::CreateWebRenderCommands( wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc, RenderRootStateManager* aManager, @@ -5161,12 +4832,6 @@ void nsDisplayBorder::ComputeInvalidationRegion( } } -LayerState nsDisplayBorder::GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - return LayerState::LAYER_NONE; -} - bool nsDisplayBorder::CreateWebRenderCommands( wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc, RenderRootStateManager* aManager, @@ -5674,62 +5339,6 @@ void nsDisplayWrapper::Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) { NS_ERROR("nsDisplayWrapper should have been flattened away for painting"); } -/** - * Returns true if all descendant display items can be placed in the same - * PaintedLayer --- GetLayerState returns LayerState::LAYER_INACTIVE or - * LayerState::LAYER_NONE, and they all have the expected animated geometry - * root. - */ -static LayerState RequiredLayerStateForChildren( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters, const nsDisplayList& aList, - const AnimatedGeometryRoot* aExpectedAGRForChildren, - const ActiveScrolledRoot* aExpectedASRForChildren) { - LayerState result = LayerState::LAYER_INACTIVE; - for (nsDisplayItem* i : aList) { - if (result == LayerState::LAYER_INACTIVE && - (i->GetAnimatedGeometryRoot() != aExpectedAGRForChildren || - i->GetActiveScrolledRoot() != aExpectedASRForChildren)) { - result = LayerState::LAYER_ACTIVE; - } - - LayerState state = i->GetLayerState(aBuilder, aManager, aParameters); - if (state == LayerState::LAYER_ACTIVE && - (i->GetType() == DisplayItemType::TYPE_BLEND_MODE || - i->GetType() == DisplayItemType::TYPE_TABLE_BLEND_MODE)) { - // nsDisplayBlendMode always returns LayerState::LAYER_ACTIVE to ensure - // that the blending operation happens in the intermediate surface of its - // parent display item (usually an nsDisplayBlendContainer). But this does - // not mean that it needs all its ancestor display items to become active. - // So we ignore its layer state and look at its children instead. - state = RequiredLayerStateForChildren( - aBuilder, aManager, aParameters, - *i->GetSameCoordinateSystemChildren(), i->GetAnimatedGeometryRoot(), - i->GetActiveScrolledRoot()); - } - if ((state == LayerState::LAYER_ACTIVE || - state == LayerState::LAYER_ACTIVE_FORCE) && - state > result) { - result = state; - } - if (state == LayerState::LAYER_ACTIVE_EMPTY && state > result) { - result = LayerState::LAYER_ACTIVE_FORCE; - } - if (state == LayerState::LAYER_NONE) { - nsDisplayList* list = i->GetSameCoordinateSystemChildren(); - if (list) { - LayerState childState = RequiredLayerStateForChildren( - aBuilder, aManager, aParameters, *list, aExpectedAGRForChildren, - aExpectedASRForChildren); - if (childState > result) { - result = childState; - } - } - } - } - return result; -} - nsRect nsDisplayWrapList::GetComponentAlphaBounds( nsDisplayListBuilder* aBuilder) const { return mListPtr->GetComponentAlphaBounds(aBuilder); @@ -5857,26 +5466,6 @@ nsRegion nsDisplayOpacity::GetOpaqueRegion(nsDisplayListBuilder* aBuilder, return nsRegion(); } -// nsDisplayOpacity uses layers for rendering -already_AddRefed<Layer> nsDisplayOpacity::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - MOZ_ASSERT(mChildOpacityState != ChildOpacityState::Applied); - - ContainerLayerParameters params = aContainerParameters; - RefPtr<Layer> container = aManager->GetLayerBuilder()->BuildContainerLayerFor( - aBuilder, aManager, mFrame, this, &mList, params, nullptr, - FrameLayerBuilder::CONTAINER_ALLOW_PULL_BACKGROUND_COLOR); - if (!container) { - return nullptr; - } - - container->SetOpacity(mOpacity); - nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer( - container, aBuilder, this, mFrame, GetType()); - return container.forget(); -} - void nsDisplayOpacity::Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) { if (GetOpacity() == 0.0f) { return; @@ -6099,28 +5688,6 @@ bool nsDisplayOpacity::ShouldFlattenAway(nsDisplayListBuilder* aBuilder) { return ApplyToChildren(aBuilder); } -LayerState nsDisplayOpacity::GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - // If we only created this item so that we'd get correct nsDisplayEventRegions - // for child frames, then force us to inactive to avoid unnecessary - // layerization changes for content that won't ever be painted. - if (mForEventsOnly) { - MOZ_ASSERT(mOpacity == 0); - return LayerState::LAYER_INACTIVE; - } - - if (mNeedsActiveLayer) { - // Returns LayerState::LAYER_ACTIVE_FORCE to avoid flatterning the layer for - // async animations. - return LayerState::LAYER_ACTIVE_FORCE; - } - - return RequiredLayerStateForChildren(aBuilder, aManager, aParameters, mList, - GetAnimatedGeometryRoot(), - GetActiveScrolledRoot()); -} - bool nsDisplayOpacity::ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion) { // Our children are translucent so we should not allow them to subtract @@ -6209,12 +5776,6 @@ nsRegion nsDisplayBlendMode::GetOpaqueRegion(nsDisplayListBuilder* aBuilder, return nsRegion(); } -LayerState nsDisplayBlendMode::GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - return LayerState::LAYER_ACTIVE; -} - bool nsDisplayBlendMode::CreateWebRenderCommands( wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc, RenderRootStateManager* aManager, @@ -6231,25 +5792,6 @@ bool nsDisplayBlendMode::CreateWebRenderCommands( aBuilder, aResources, sc, aManager, aDisplayListBuilder); } -// nsDisplayBlendMode uses layers for rendering -already_AddRefed<Layer> nsDisplayBlendMode::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - ContainerLayerParameters newContainerParameters = aContainerParameters; - newContainerParameters.mDisableSubpixelAntialiasingInDescendants = true; - - RefPtr<Layer> container = aManager->GetLayerBuilder()->BuildContainerLayerFor( - aBuilder, aManager, mFrame, this, &mList, newContainerParameters, - nullptr); - if (!container) { - return nullptr; - } - - container->SetMixBlendMode(nsCSSRendering::GetGFXBlendMode(mBlendMode)); - - return container.forget(); -} - void nsDisplayBlendMode::Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) { // This should be switched to use PushLayerWithBlend, once it's @@ -6352,34 +5894,6 @@ nsDisplayBlendContainer::nsDisplayBlendContainer( MOZ_COUNT_CTOR(nsDisplayBlendContainer); } -// nsDisplayBlendContainer uses layers for rendering -already_AddRefed<Layer> nsDisplayBlendContainer::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - // turn off anti-aliasing in the parent stacking context because it changes - // how the group is initialized. - ContainerLayerParameters newContainerParameters = aContainerParameters; - newContainerParameters.mDisableSubpixelAntialiasingInDescendants = true; - - RefPtr<Layer> container = aManager->GetLayerBuilder()->BuildContainerLayerFor( - aBuilder, aManager, mFrame, this, &mList, newContainerParameters, - nullptr); - if (!container) { - return nullptr; - } - - container->SetForceIsolatedGroup(true); - return container.forget(); -} - -LayerState nsDisplayBlendContainer::GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - return RequiredLayerStateForChildren(aBuilder, aManager, aParameters, mList, - GetAnimatedGeometryRoot(), - GetActiveScrolledRoot()); -} - void nsDisplayBlendContainer::Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) { aCtx->GetDrawTarget()->PushLayer(false, 1.0, nullptr, gfx::Matrix()); @@ -6425,18 +5939,6 @@ nsDisplayOwnLayer::nsDisplayOwnLayer( } } -LayerState nsDisplayOwnLayer::GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - if (mForceActive) { - return LayerState::LAYER_ACTIVE_FORCE; - } - - return RequiredLayerStateForChildren(aBuilder, aManager, aParameters, mList, - GetAnimatedGeometryRoot(), - GetActiveScrolledRoot()); -} - bool nsDisplayOwnLayer::IsScrollThumbLayer() const { return mScrollbarData.mScrollbarLayerType == ScrollbarLayerType::Thumb; } @@ -6477,25 +5979,6 @@ bool nsDisplayOwnLayer::HasDynamicToolbar() const { StaticPrefs::apz_fixed_margin_override_enabled(); } -// nsDisplayOpacity uses layers for rendering -already_AddRefed<Layer> nsDisplayOwnLayer::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - RefPtr<ContainerLayer> layer = - aManager->GetLayerBuilder()->BuildContainerLayerFor( - aBuilder, aManager, mFrame, this, &mList, aContainerParameters, - nullptr, FrameLayerBuilder::CONTAINER_ALLOW_PULL_BACKGROUND_COLOR); - - if (IsScrollThumbLayer() || IsScrollbarContainer()) { - layer->SetScrollbarData(mScrollbarData); - } - - if (mFlags & nsDisplayOwnLayerFlags::GenerateSubdocInvalidations) { - mFrame->PresContext()->SetNotifySubDocInvalidationData(layer); - } - return layer.forget(); -} - bool nsDisplayOwnLayer::CreateWebRenderCommands( wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc, RenderRootStateManager* aManager, @@ -6782,46 +6265,6 @@ void nsDisplayFixedPosition::Init(nsDisplayListBuilder* aBuilder) { } } -already_AddRefed<Layer> nsDisplayFixedPosition::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - RefPtr<Layer> layer = - nsDisplayOwnLayer::BuildLayer(aBuilder, aManager, aContainerParameters); - - layer->SetIsFixedPosition(true); - - nsPresContext* presContext = mFrame->PresContext(); - nsIFrame* fixedFrame = - mIsFixedBackground ? presContext->PresShell()->GetRootFrame() : mFrame; - - const nsIFrame* viewportFrame = fixedFrame->GetParent(); - // anchorRect will be in the container's coordinate system (aLayer's parent - // layer). This is the same as the display items' reference frame. - nsRect anchorRect; - if (viewportFrame) { - anchorRect.SizeTo(viewportFrame->GetSize()); - // Fixed position frames are reflowed into the scroll-port size if one has - // been set. - if (const ViewportFrame* viewport = do_QueryFrame(viewportFrame)) { - anchorRect.SizeTo( - viewport->AdjustViewportSizeForFixedPosition(anchorRect)); - } - } else { - // A display item directly attached to the viewport. - // For background-attachment:fixed items, the anchor point is always the - // top-left of the viewport currently. - viewportFrame = fixedFrame; - } - // The anchorRect top-left is always the viewport top-left. - anchorRect.MoveTo(viewportFrame->GetOffsetToCrossDoc(ReferenceFrame())); - - nsLayoutUtils::SetFixedPositionLayerData(layer, viewportFrame, anchorRect, - fixedFrame, presContext, - aContainerParameters); - - return layer.forget(); -} - ScrollableLayerGuid::ViewID nsDisplayFixedPosition::GetScrollTargetId() { if (mContainerASR && !nsLayoutUtils::IsReallyFixedPos(mFrame)) { return mContainerASR->GetViewId(); @@ -6932,49 +6375,6 @@ void nsDisplayStickyPosition::SetClipChain( } } -already_AddRefed<Layer> nsDisplayStickyPosition::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - RefPtr<Layer> layer = - nsDisplayOwnLayer::BuildLayer(aBuilder, aManager, aContainerParameters); - - StickyScrollContainer* stickyScrollContainer = - StickyScrollContainer::GetStickyScrollContainerForFrame(mFrame); - if (!stickyScrollContainer) { - return layer.forget(); - } - - nsIFrame* scrollFrame = do_QueryFrame(stickyScrollContainer->ScrollFrame()); - nsPresContext* presContext = scrollFrame->PresContext(); - - // Sticky position frames whose scroll frame is the root scroll frame are - // reflowed into the scroll-port size if one has been set. - nsSize scrollFrameSize = scrollFrame->GetSize(); - if (scrollFrame == presContext->PresShell()->GetRootScrollFrame() && - presContext->PresShell()->IsVisualViewportSizeSet()) { - scrollFrameSize = presContext->PresShell()->GetVisualViewportSize(); - } - - nsLayoutUtils::SetFixedPositionLayerData( - layer, scrollFrame, - nsRect(scrollFrame->GetOffsetToCrossDoc(ReferenceFrame()), - scrollFrameSize), - mFrame, presContext, aContainerParameters); - - ScrollableLayerGuid::ViewID scrollId = nsLayoutUtils::FindOrCreateIDFor( - stickyScrollContainer->ScrollFrame()->GetScrolledFrame()->GetContent()); - - float factor = presContext->AppUnitsPerDevPixel(); - LayerRectAbsolute stickyOuter; - LayerRectAbsolute stickyInner; - CalculateLayerScrollRanges( - stickyScrollContainer, factor, aContainerParameters.mXScale, - aContainerParameters.mYScale, stickyOuter, stickyInner); - layer->SetStickyPositionData(scrollId, stickyOuter, stickyInner); - - return layer.forget(); -} - // Returns the smallest distance from "0" to the range [min, max] where // min <= max. Despite the name, the return value is actually a 1-D vector, // and so may be negative if max < 0. @@ -7280,32 +6680,12 @@ nsDisplayScrollInfoLayer::nsDisplayScrollInfoLayer( #endif } -already_AddRefed<Layer> nsDisplayScrollInfoLayer::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - // In general for APZ with event-regions we no longer have a need for - // scrollinfo layers. However, in some cases, there might be content that - // cannot be layerized, and so needs to scroll synchronously. To handle those - // cases, we still want to generate scrollinfo layers. - - return aManager->GetLayerBuilder()->BuildContainerLayerFor( - aBuilder, aManager, mFrame, this, &mList, aContainerParameters, nullptr, - FrameLayerBuilder::CONTAINER_ALLOW_PULL_BACKGROUND_COLOR); -} - -LayerState nsDisplayScrollInfoLayer::GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - return LayerState::LAYER_ACTIVE_EMPTY; -} - UniquePtr<ScrollMetadata> nsDisplayScrollInfoLayer::ComputeScrollMetadata( - nsDisplayListBuilder* aBuilder, LayerManager* aLayerManager, - const ContainerLayerParameters& aContainerParameters) { + nsDisplayListBuilder* aBuilder, LayerManager* aLayerManager) { ScrollMetadata metadata = nsLayoutUtils::ComputeScrollMetadata( mScrolledFrame, mScrollFrame, mScrollFrame->GetContent(), ReferenceFrame(), aLayerManager, mScrollParentId, mScrollFrame->GetSize(), - Nothing(), false, Some(aContainerParameters)); + Nothing(), false); metadata.GetMetrics().SetIsScrollInfoLayer(true); nsIScrollableFrame* scrollableFrame = mScrollFrame->GetScrollTargetFrame(); if (scrollableFrame) { @@ -7318,8 +6698,8 @@ UniquePtr<ScrollMetadata> nsDisplayScrollInfoLayer::ComputeScrollMetadata( bool nsDisplayScrollInfoLayer::UpdateScrollData( WebRenderScrollData* aData, WebRenderLayerScrollData* aLayerData) { if (aLayerData) { - UniquePtr<ScrollMetadata> metadata = ComputeScrollMetadata( - aData->GetBuilder(), aData->GetManager(), ContainerLayerParameters()); + UniquePtr<ScrollMetadata> metadata = + ComputeScrollMetadata(aData->GetBuilder(), aData->GetManager()); MOZ_ASSERT(aData); MOZ_ASSERT(metadata); aLayerData->AppendScrollMetadata(*aData, *metadata); @@ -7444,26 +6824,6 @@ void nsDisplayAsyncZoom::HitTest(nsDisplayListBuilder* aBuilder, mList.HitTest(aBuilder, rect, aState, aOutFrames); } -already_AddRefed<Layer> nsDisplayAsyncZoom::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - PresShell* presShell = mFrame->PresShell(); - ContainerLayerParameters containerParameters( - presShell->GetResolution(), presShell->GetResolution(), nsIntPoint(), - aContainerParameters); - - RefPtr<Layer> layer = - nsDisplayOwnLayer::BuildLayer(aBuilder, aManager, containerParameters); - - layer->SetAsyncZoomContainerId(Some(mViewID)); - - layer->SetPostScale(1.0f / presShell->GetResolution(), - 1.0f / presShell->GetResolution()); - layer->AsContainerLayer()->SetScaleToResolution(presShell->GetResolution()); - - return layer.forget(); -} - bool nsDisplayAsyncZoom::UpdateScrollData( WebRenderScrollData* aData, WebRenderLayerScrollData* aLayerData) { bool ret = nsDisplayOwnLayer::UpdateScrollData(aData, aLayerData); @@ -8250,66 +7610,6 @@ bool nsDisplayTransform::ShouldSkipTransform( aBuilder->IsForGenerateGlyphMask(); } -already_AddRefed<Layer> nsDisplayTransform::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - // While generating a glyph mask, the transform vector of the root frame had - // been applied into the target context, so stop applying it again here. - const bool shouldSkipTransform = ShouldSkipTransform(aBuilder); - - /* For frames without transform, it would not be removed for - * backface hidden here. But, it would be removed by the init - * function of nsDisplayTransform. - */ - const Matrix4x4 newTransformMatrix = - shouldSkipTransform ? Matrix4x4() : GetTransformForRendering(); - - uint32_t flags = FrameLayerBuilder::CONTAINER_ALLOW_PULL_BACKGROUND_COLOR; - RefPtr<ContainerLayer> container = - aManager->GetLayerBuilder()->BuildContainerLayerFor( - aBuilder, aManager, mFrame, this, GetChildren(), aContainerParameters, - &newTransformMatrix, flags); - - if (!container) { - return nullptr; - } - - // Add the preserve-3d flag for this layer, BuildContainerLayerFor clears all - // flags, so we never need to explicitly unset this flag. - if (mFrame->Extend3DContext() && !mIsTransformSeparator) { - container->SetContentFlags(container->GetContentFlags() | - Layer::CONTENT_EXTEND_3D_CONTEXT); - } else { - container->SetContentFlags(container->GetContentFlags() & - ~Layer::CONTENT_EXTEND_3D_CONTEXT); - } - - if (CanUseAsyncAnimations(aBuilder)) { - mFrame->SetProperty(nsIFrame::RefusedAsyncAnimationProperty(), false); - } - - // We don't send animations for transform separator display items. - if (!mIsTransformSeparator) { - nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer( - container, aBuilder, this, mFrame, GetType()); - } - - if (CanUseAsyncAnimations(aBuilder) && MayBeAnimated(aBuilder)) { - // Only allow async updates to the transform if we're an animated layer, - // since that's what triggers us to set the correct AGR in the constructor - // and makes sure FrameLayerBuilder won't compute occlusions for this layer. - container->SetUserData(nsIFrame::LayerIsPrerenderedDataKey(), - /*the value is irrelevant*/ nullptr); - container->SetContentFlags(container->GetContentFlags() | - Layer::CONTENT_MAY_CHANGE_TRANSFORM); - } else { - container->RemoveUserData(nsIFrame::LayerIsPrerenderedDataKey()); - container->SetContentFlags(container->GetContentFlags() & - ~Layer::CONTENT_MAY_CHANGE_TRANSFORM); - } - return container.forget(); -} - void nsDisplayTransform::Collect3DTransformLeaves( nsDisplayListBuilder* aBuilder, nsTArray<nsDisplayTransform*>& aLeaves) { if (!IsParticipating3DContext() || IsLeafOf3DContext()) { @@ -8490,34 +7790,6 @@ bool nsDisplayTransform::MayBeAnimated(nsDisplayListBuilder* aBuilder, !(aEnforceMinimumSize && IsItemTooSmallForActiveLayer(mFrame))); } -LayerState nsDisplayTransform::GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - // If the transform is 3d, the layer takes part in preserve-3d - // sorting, or the layer is a separator then we *always* want this - // to be an active layer. - // Checking HasPerspective() is needed to handle perspective value 0 when - // the transform is 2D. - if (!GetTransform().Is2D() || Combines3DTransformWithAncestors() || - mIsTransformSeparator || mFrame->HasPerspective()) { - return LayerState::LAYER_ACTIVE_FORCE; - } - - if (MayBeAnimated(aBuilder)) { - // Returns LayerState::LAYER_ACTIVE_FORCE to avoid flatterning the layer for - // async animations. - return LayerState::LAYER_ACTIVE_FORCE; - } - - // Expect the child display items to have this frame as their animated - // geometry root (since it will be their reference frame). If they have a - // different animated geometry root, we'll make this an active layer so the - // animation can be accelerated. - return RequiredLayerStateForChildren( - aBuilder, aManager, aParameters, *GetChildren(), - mAnimatedGeometryRootForChildren, GetActiveScrolledRoot()); -} - bool nsDisplayTransform::ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion) { // nsDisplayTransform::GetBounds() returns an empty rect in nested 3d context. @@ -8961,60 +8233,6 @@ nsDisplayPerspective::nsDisplayPerspective(nsDisplayListBuilder* aBuilder, mFrame->GetClosestFlattenedTreeAncestorPrimaryFrame()); } -already_AddRefed<Layer> nsDisplayPerspective::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - float appUnitsPerPixel = mFrame->PresContext()->AppUnitsPerDevPixel(); - - Matrix4x4 perspectiveMatrix; - DebugOnly<bool> hasPerspective = nsDisplayTransform::ComputePerspectiveMatrix( - mFrame, appUnitsPerPixel, perspectiveMatrix); - MOZ_ASSERT(hasPerspective, "Why did we create nsDisplayPerspective?"); - - /* - * ClipListToRange can remove our child after we were created. - */ - if (!GetChildren()->GetTop()) { - return nullptr; - } - - /* - * The resulting matrix is still in the coordinate space of the transformed - * frame. Append a translation to the reference frame coordinates. - */ - nsDisplayTransform* transform = - static_cast<nsDisplayTransform*>(GetChildren()->GetTop()); - - Point3D newOrigin = - Point3D(NSAppUnitsToFloatPixels(transform->ToReferenceFrame().x, - appUnitsPerPixel), - NSAppUnitsToFloatPixels(transform->ToReferenceFrame().y, - appUnitsPerPixel), - 0.0f); - Point3D roundedOrigin(NS_round(newOrigin.x), NS_round(newOrigin.y), 0); - - perspectiveMatrix.PostTranslate(roundedOrigin); - - RefPtr<ContainerLayer> container = - aManager->GetLayerBuilder()->BuildContainerLayerFor( - aBuilder, aManager, mFrame, this, GetChildren(), aContainerParameters, - &perspectiveMatrix, 0); - - if (!container) { - return nullptr; - } - - // Sort of a lie, but we want to pretend that the perspective layer extends a - // 3d context so that it gets its transform combined with children. Might need - // a better name that reflects this use case and isn't specific to - // preserve-3d. - container->SetContentFlags(container->GetContentFlags() | - Layer::CONTENT_EXTEND_3D_CONTEXT); - container->SetTransformIsPerspective(true); - - return container.forget(); -} - void nsDisplayPerspective::Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) { // Just directly recurse into children, since we'll include the persepctive @@ -9023,12 +8241,6 @@ void nsDisplayPerspective::Paint(nsDisplayListBuilder* aBuilder, mFrame->PresContext()->AppUnitsPerDevPixel()); } -LayerState nsDisplayPerspective::GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - return LayerState::LAYER_ACTIVE_FORCE; -} - nsRegion nsDisplayPerspective::GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) const { if (!GetChildren()->GetTop()) { @@ -9595,21 +8807,6 @@ bool nsDisplayMasksAndClipPaths::IsValidMask() { SVGObserverUtils::eHasRefsSomeInvalid); } -already_AddRefed<Layer> nsDisplayMasksAndClipPaths::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - if (!IsValidMask()) { - return nullptr; - } - - RefPtr<ContainerLayer> container = - aManager->GetLayerBuilder()->BuildContainerLayerFor( - aBuilder, aManager, mFrame, this, &mList, aContainerParameters, - nullptr); - - return container.forget(); -} - bool nsDisplayMasksAndClipPaths::PaintMask(nsDisplayListBuilder* aBuilder, gfxContext* aMaskContext, bool* aMaskPainted) { @@ -9635,26 +8832,6 @@ bool nsDisplayMasksAndClipPaths::PaintMask(nsDisplayListBuilder* aBuilder, imgParams.result == ImgDrawResult::WRONG_SIZE); } -LayerState nsDisplayMasksAndClipPaths::GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - if (CanPaintOnMaskLayer(aManager)) { - LayerState result = RequiredLayerStateForChildren( - aBuilder, aManager, aParameters, mList, GetAnimatedGeometryRoot(), - GetActiveScrolledRoot()); - // When we're not active, FrameLayerBuilder will call PaintAsLayer() - // on us during painting. In that case we don't want a mask layer to - // be created, because PaintAsLayer() takes care of applying the mask. - // So we return LayerState::LAYER_SVG_EFFECTS instead of - // LayerState::LAYER_INACTIVE so that FrameLayerBuilder doesn't set a mask - // layer on our layer. - return result == LayerState::LAYER_INACTIVE ? LayerState::LAYER_SVG_EFFECTS - : result; - } - - return LayerState::LAYER_SVG_EFFECTS; -} - bool nsDisplayMasksAndClipPaths::CanPaintOnMaskLayer(LayerManager* aManager) { if (!aManager->IsWidgetLayerManager()) { return false; @@ -9722,33 +8899,6 @@ void nsDisplayMasksAndClipPaths::ComputeInvalidationRegion( } } -void nsDisplayMasksAndClipPaths::PaintAsLayer(nsDisplayListBuilder* aBuilder, - gfxContext* aCtx, - LayerManager* aManager) { - // Clip the drawing target by mVisibleRect, which contains the visible - // region of the target frame and its out-of-flow and inflow descendants. - gfxContext* context = aCtx; - - Rect bounds = NSRectToRect(GetPaintRect(), - mFrame->PresContext()->AppUnitsPerDevPixel()); - bounds.RoundOut(); - context->Clip(bounds); - - imgDrawingParams imgParams(aBuilder->GetImageDecodeFlags()); - nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize()); - SVGIntegrationUtils::PaintFramesParams params(*aCtx, mFrame, GetPaintRect(), - borderArea, aBuilder, aManager, - mHandleOpacity, imgParams); - - ComputeMaskGeometry(params); - - SVGIntegrationUtils::PaintMaskAndClipPath(params); - - context->PopClip(); - - nsDisplayMasksAndClipPathsGeometry::UpdateDrawResult(this, imgParams.result); -} - void nsDisplayMasksAndClipPaths::PaintWithContentsPaintCallback( nsDisplayListBuilder* aBuilder, gfxContext* aCtx, const std::function<void()>& aPaintChildren) { @@ -10043,18 +9193,6 @@ void nsDisplayMasksAndClipPaths::PrintEffects(nsACString& aTo) { } #endif -already_AddRefed<Layer> nsDisplayBackdropRootContainer::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - RefPtr<Layer> container = aManager->GetLayerBuilder()->BuildContainerLayerFor( - aBuilder, aManager, mFrame, this, &mList, aContainerParameters, nullptr); - if (!container) { - return nullptr; - } - - return container.forget(); -} - void nsDisplayBackdropRootContainer::Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) { aCtx->GetDrawTarget()->PushLayer(false, 1.0, nullptr, gfx::Matrix()); @@ -10063,14 +9201,6 @@ void nsDisplayBackdropRootContainer::Paint(nsDisplayListBuilder* aBuilder, aCtx->GetDrawTarget()->PopLayer(); } -LayerState nsDisplayBackdropRootContainer::GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - return RequiredLayerStateForChildren(aBuilder, aManager, aParameters, mList, - GetAnimatedGeometryRoot(), - GetActiveScrolledRoot()); -} - bool nsDisplayBackdropRootContainer::CreateWebRenderCommands( wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc, RenderRootStateManager* aManager, @@ -10150,44 +9280,6 @@ nsDisplayFilters::nsDisplayFilters(nsDisplayListBuilder* aBuilder, MOZ_COUNT_CTOR(nsDisplayFilters); } -already_AddRefed<Layer> nsDisplayFilters::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - if (!ValidateSVGFrame()) { - return nullptr; - } - - if (mFrame->StyleEffects()->mOpacity == 0.0f && mHandleOpacity) { - return nullptr; - } - - nsIFrame* firstFrame = - nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame); - - // We may exist for a mix of CSS filter functions and/or references to SVG - // filters. If we have invalid references to SVG filters then we paint - // nothing, so no need for a layer. - if (SVGObserverUtils::GetAndObserveFilters(firstFrame, nullptr) == - SVGObserverUtils::eHasRefsSomeInvalid) { - return nullptr; - } - - ContainerLayerParameters newContainerParameters = aContainerParameters; - newContainerParameters.mDisableSubpixelAntialiasingInDescendants = true; - - RefPtr<ContainerLayer> container = - aManager->GetLayerBuilder()->BuildContainerLayerFor( - aBuilder, aManager, mFrame, this, &mList, newContainerParameters, - nullptr); - return container.forget(); -} - -LayerState nsDisplayFilters::GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - return LayerState::LAYER_SVG_EFFECTS; -} - void nsDisplayFilters::Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) { PaintWithContentsPaintCallback(aBuilder, aCtx, [&](gfxContext* aContext) { GetChildren()->Paint(aBuilder, aContext, @@ -10228,18 +9320,6 @@ void nsDisplayFilters::ComputeInvalidationRegion( } } -void nsDisplayFilters::PaintAsLayer(nsDisplayListBuilder* aBuilder, - gfxContext* aCtx, LayerManager* aManager) { - PaintWithContentsPaintCallback(aBuilder, aCtx, [&](gfxContext* aContext) { - BasicLayerManager* basic = aManager->AsBasicLayerManager(); - RefPtr<gfxContext> oldCtx = basic->GetTarget(); - basic->SetTarget(aContext); - - aManager->EndTransaction(FrameLayerBuilder::DrawPaintedLayer, aBuilder); - basic->SetTarget(oldCtx); - }); -} - void nsDisplayFilters::PaintWithContentsPaintCallback( nsDisplayListBuilder* aBuilder, gfxContext* aCtx, const std::function<void(gfxContext* aContext)>& aPaintChildren) { @@ -10340,37 +9420,12 @@ nsDisplaySVGWrapper::nsDisplaySVGWrapper(nsDisplayListBuilder* aBuilder, MOZ_COUNT_CTOR(nsDisplaySVGWrapper); } -LayerState nsDisplaySVGWrapper::GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - RefPtr<LayerManager> layerManager = aBuilder->GetWidgetLayerManager(); - if (layerManager && - layerManager->GetBackendType() == LayersBackend::LAYERS_WR) { - return LayerState::LAYER_ACTIVE_FORCE; - } - return LayerState::LAYER_NONE; -} - bool nsDisplaySVGWrapper::ShouldFlattenAway(nsDisplayListBuilder* aBuilder) { RefPtr<LayerManager> layerManager = aBuilder->GetWidgetLayerManager(); return !(layerManager && layerManager->GetBackendType() == LayersBackend::LAYERS_WR); } -already_AddRefed<Layer> nsDisplaySVGWrapper::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - ContainerLayerParameters newContainerParameters = aContainerParameters; - newContainerParameters.mDisableSubpixelAntialiasingInDescendants = true; - - RefPtr<ContainerLayer> container = - aManager->GetLayerBuilder()->BuildContainerLayerFor( - aBuilder, aManager, mFrame, this, &mList, newContainerParameters, - nullptr); - - return container.forget(); -} - bool nsDisplaySVGWrapper::CreateWebRenderCommands( wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc, RenderRootStateManager* aManager, @@ -10392,37 +9447,12 @@ nsDisplayForeignObject::~nsDisplayForeignObject() { } #endif -LayerState nsDisplayForeignObject::GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - RefPtr<LayerManager> layerManager = aBuilder->GetWidgetLayerManager(); - if (layerManager && - layerManager->GetBackendType() == LayersBackend::LAYERS_WR) { - return LayerState::LAYER_ACTIVE_FORCE; - } - return LayerState::LAYER_NONE; -} - bool nsDisplayForeignObject::ShouldFlattenAway(nsDisplayListBuilder* aBuilder) { RefPtr<LayerManager> layerManager = aBuilder->GetWidgetLayerManager(); return !(layerManager && layerManager->GetBackendType() == LayersBackend::LAYERS_WR); } -already_AddRefed<Layer> nsDisplayForeignObject::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - ContainerLayerParameters newContainerParameters = aContainerParameters; - newContainerParameters.mDisableSubpixelAntialiasingInDescendants = true; - - RefPtr<ContainerLayer> container = - aManager->GetLayerBuilder()->BuildContainerLayerFor( - aBuilder, aManager, mFrame, this, &mList, newContainerParameters, - nullptr); - - return container.forget(); -} - bool nsDisplayForeignObject::CreateWebRenderCommands( wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc, RenderRootStateManager* aManager, diff --git a/layout/painting/nsDisplayList.h b/layout/painting/nsDisplayList.h index b0b2e7cfc51270c5aba5f8ca61a3c71c42aa4f0d..5d7397731447fa12dd8c15c1803bf0c78e847903 100644 --- a/layout/painting/nsDisplayList.h +++ b/layout/painting/nsDisplayList.h @@ -79,7 +79,6 @@ namespace mozilla { enum class nsDisplayOwnLayerFlags; class nsDisplayCompositorHitTestInfo; class nsDisplayScrollInfoLayer; -class FrameLayerBuilder; class PresShell; class StickyScrollContainer; @@ -2703,35 +2702,6 @@ class nsDisplayItem : public nsDisplayItemLink { */ static bool ForceActiveLayers(); - /** - * @return LAYER_NONE if BuildLayer will return null. In this case - * there is no layer for the item, and Paint should be called instead - * to paint the content using Thebes. - * Return LAYER_INACTIVE if there is a layer --- BuildLayer will - * not return null (unless there's an error) --- but the layer contents - * are not changing frequently. In this case it makes sense to composite - * the layer into a PaintedLayer with other content, so we don't have to - * recomposite it every time we paint. - * Note: GetLayerState is only allowed to return LAYER_INACTIVE if all - * descendant display items returned LAYER_INACTIVE or LAYER_NONE. Also, - * all descendant display item frames must have an active scrolled root - * that's either the same as this item's frame's active scrolled root, or - * a descendant of this item's frame. This ensures that the entire - * set of display items can be collapsed onto a single PaintedLayer. - * Return LAYER_ACTIVE if the layer is active, that is, its contents are - * changing frequently. In this case it makes sense to keep the layer - * as a separate buffer in VRAM and composite it into the destination - * every time we paint. - * - * Users of GetLayerState should check ForceActiveLayers() and if it returns - * true, change a returned value of LAYER_INACTIVE to LAYER_ACTIVE. - */ - virtual LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - return LayerState::LAYER_NONE; - } - #ifdef MOZ_DUMP_PAINTING /** * Mark this display item as being painted via @@ -3128,26 +3098,6 @@ class nsPaintedDisplayItem : public nsDisplayItem { MOZ_ASSERT(CanApplyOpacity(), "ApplyOpacity is not supported on this type"); } - /** - * Get the layer drawn by this display item. Call this only if - * GetLayerState() returns something other than LAYER_NONE. - * If GetLayerState returned LAYER_NONE then Paint will be called - * instead. - * This is called while aManager is in the construction phase. - * - * The caller (nsDisplayList) is responsible for setting the visible - * region of the layer. - * - * @param aContainerParameters should be passed to - * FrameLayerBuilder::BuildContainerLayerFor if a ContainerLayer is - * constructed. - */ - virtual already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - return nullptr; - } - /** * Returns true if this display item would return true from ApplyOpacity * without actually applying the opacity. Otherwise returns false. @@ -3599,10 +3549,6 @@ class nsDisplayList { nsDisplayListBuilder* aBuilder, gfxContext* aCtx, uint32_t aFlags, Maybe<double> aDisplayListBuildTime); - FrameLayerBuilder* BuildLayers(nsDisplayListBuilder* aBuilder, - layers::LayerManager* aLayerManager, - uint32_t aFlags, bool aIsWidgetTransaction); - void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx, int32_t aAppUnitsPerDevPixel); @@ -3957,8 +3903,6 @@ class nsDisplayImageContainer : public nsPaintedDisplayItem { already_AddRefed<layers::ImageContainer> GetContainer( LayerManager* aManager, nsDisplayListBuilder* aBuilder); - void ConfigureLayer(layers::ImageLayer* aLayer, - const ContainerLayerParameters& aParameters); virtual void UpdateDrawResult(image::ImgDrawResult aResult) = 0; virtual already_AddRefed<imgIContainer> GetImage() = 0; @@ -4154,9 +4098,6 @@ class nsDisplayBorder : public nsPaintedDisplayItem { bool IsInvisibleInRect(const nsRect& aRect) const override; nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override; - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override; bool CreateWebRenderCommands( wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc, @@ -4309,12 +4250,6 @@ class nsDisplaySolidColor : public nsDisplaySolidColorBase { NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR) nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override; - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override; - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override; void WriteDebugInfo(std::stringstream& aStream) override; bool CreateWebRenderCommands( @@ -4458,12 +4393,6 @@ class nsDisplayBackgroundImage : public nsDisplayImageContainer { Maybe<nsDisplayListBuilder::AutoBuildingDisplayList>* aAutoBuildingDisplayList = nullptr); - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override; - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override; bool CreateWebRenderCommands( wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc, @@ -4786,15 +4715,9 @@ class nsDisplayBackgroundColor : public nsPaintedDisplayItem { return mBottomLayerClip == StyleGeometryBox::Text; } - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override; void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override; void PaintWithClip(nsDisplayListBuilder* aBuilder, gfxContext* aCtx, const DisplayItemClip& aClip) override; - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; bool CreateWebRenderCommands( wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc, @@ -5487,12 +5410,6 @@ class nsDisplayOpacity : public nsDisplayWrapList { nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) const override; - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override; void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override; bool ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion) override; @@ -5605,9 +5522,6 @@ class nsDisplayBlendMode : public nsDisplayWrapList { nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) const override; - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, const nsDisplayItemGeometry* aGeometry, nsRegion* aInvalidRegion) const override { @@ -5615,9 +5529,6 @@ class nsDisplayBlendMode : public nsDisplayWrapList { // LayerTreeInvalidation } - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override; bool CreateWebRenderCommands( wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc, @@ -5708,12 +5619,6 @@ class nsDisplayBlendContainer : public nsDisplayWrapList { NS_DISPLAY_DECL_NAME("BlendContainer", TYPE_BLEND_CONTAINER) - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override; void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override; bool CreateWebRenderCommands( wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources, @@ -5862,9 +5767,6 @@ class nsDisplayOwnLayer : public nsDisplayWrapList { NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER) - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; bool CreateWebRenderCommands( wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc, @@ -5872,9 +5774,6 @@ class nsDisplayOwnLayer : public nsDisplayWrapList { nsDisplayListBuilder* aDisplayListBuilder) override; bool UpdateScrollData(layers::WebRenderScrollData* aData, layers::WebRenderLayerScrollData* aLayerData) override; - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override; void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override { GetChildren()->Paint(aBuilder, aCtx, mFrame->PresContext()->AppUnitsPerDevPixel()); @@ -5944,15 +5843,6 @@ class nsDisplaySubDocument : public nsDisplayOwnLayer { mShouldFlatten = aShouldFlatten; } - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override { - if (mShouldFlatten) { - return LayerState::LAYER_NONE; - } - return nsDisplayOwnLayer::GetLayerState(aBuilder, aManager, aParameters); - } - nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) const override; @@ -5994,15 +5884,7 @@ class nsDisplayStickyPosition : public nsDisplayOwnLayer { bool aStore) override; bool IsClippedToDisplayPort() const { return mClippedToDisplayPort; } - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; NS_DISPLAY_DECL_NAME("StickyPosition", TYPE_STICKY_POSITION) - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override { - return LayerState::LAYER_ACTIVE; - } void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override { GetChildren()->Paint(aBuilder, aCtx, mFrame->PresContext()->AppUnitsPerDevPixel()); @@ -6074,15 +5956,6 @@ class nsDisplayFixedPosition : public nsDisplayOwnLayer { NS_DISPLAY_DECL_NAME("FixedPosition", TYPE_FIXED_POSITION) - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; - - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override { - return LayerState::LAYER_ACTIVE_FORCE; - } void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override { GetChildren()->Paint(aBuilder, aCtx, mFrame->PresContext()->AppUnitsPerDevPixel()); @@ -6171,19 +6044,12 @@ class nsDisplayScrollInfoLayer : public nsDisplayWrapList { NS_DISPLAY_DECL_NAME("ScrollInfoLayer", TYPE_SCROLL_INFO_LAYER) - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; - nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) const override { *aSnap = false; return nsRegion(); } - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override; void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override { return; } @@ -6194,8 +6060,7 @@ class nsDisplayScrollInfoLayer : public nsDisplayWrapList { void WriteDebugInfo(std::stringstream& aStream) override; UniquePtr<layers::ScrollMetadata> ComputeScrollMetadata( - nsDisplayListBuilder* aBuilder, LayerManager* aLayerManager, - const ContainerLayerParameters& aContainerParameters); + nsDisplayListBuilder* aBuilder, LayerManager* aLayerManager); bool UpdateScrollData(layers::WebRenderScrollData* aData, layers::WebRenderLayerScrollData* aLayerData) override; bool CreateWebRenderCommands( @@ -6242,12 +6107,6 @@ class nsDisplayZoom : public nsDisplaySubDocument { HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override; bool ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion) override; - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override { - return LayerState::LAYER_ACTIVE; - } - // Get the app units per dev pixel ratio of the child document. int32_t GetChildAppUnitsPerDevPixel() { return mAPD; } // Get the app units per dev pixel ratio of the parent document. @@ -6284,14 +6143,6 @@ class nsDisplayAsyncZoom : public nsDisplayOwnLayer { void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override; - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override { - return LayerState::LAYER_ACTIVE_FORCE; - } bool UpdateScrollData(layers::WebRenderScrollData* aData, layers::WebRenderLayerScrollData* aLayerData) override; @@ -6400,12 +6251,6 @@ class nsDisplayMasksAndClipPaths : public nsDisplayEffectsBase { other->mEffectsBounds + other->mFrame->GetOffsetTo(mFrame)); } - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override; void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override; bool ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion) override; @@ -6424,9 +6269,6 @@ class nsDisplayMasksAndClipPaths : public nsDisplayEffectsBase { bool IsValidMask(); - void PaintAsLayer(nsDisplayListBuilder* aBuilder, gfxContext* aCtx, - LayerManager* aManager); - void PaintWithContentsPaintCallback( nsDisplayListBuilder* aBuilder, gfxContext* aCtx, const std::function<void()>& aPaintChildren); @@ -6478,12 +6320,6 @@ class nsDisplayBackdropRootContainer : public nsDisplayWrapList { NS_DISPLAY_DECL_NAME("BackdropRootContainer", TYPE_BACKDROP_ROOT_CONTAINER) - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override; void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override; bool CreateWebRenderCommands( @@ -6571,12 +6407,6 @@ class nsDisplayFilters : public nsDisplayEffectsBase { other->mEffectsBounds + other->mFrame->GetOffsetTo(mFrame)); } - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override; void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override; nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override { @@ -6599,9 +6429,6 @@ class nsDisplayFilters : public nsDisplayEffectsBase { void PrintEffects(nsACString& aTo); #endif - void PaintAsLayer(nsDisplayListBuilder* aBuilder, gfxContext* aCtx, - LayerManager* aManager); - void PaintWithContentsPaintCallback( nsDisplayListBuilder* aBuilder, gfxContext* aCtx, const std::function<void(gfxContext* aContext)>& aPaintChildren); @@ -6710,12 +6537,6 @@ class nsDisplayTransform : public nsPaintedDisplayItem { nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override; nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) const override; - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override; - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override; void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx, const Maybe<gfx::Polygon>& aPolygon); @@ -7063,18 +6884,12 @@ class nsDisplayPerspective : public nsPaintedDisplayItem { nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) const override; - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override; bool CreateWebRenderCommands( wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc, layers::RenderRootStateManager* aManager, nsDisplayListBuilder* aDisplayListBuilder) override; - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override; RetainedDisplayList* GetSameCoordinateSystemChildren() const override { @@ -7242,12 +7057,6 @@ class nsDisplaySVGWrapper : public nsDisplayWrapList { NS_DISPLAY_DECL_NAME("SVGWrapper", TYPE_SVG_WRAPPER) - already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override; void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override { GetChildren()->Paint(aBuilder, aCtx, mFrame->PresContext()->AppUnitsPerDevPixel()); @@ -7273,12 +7082,6 @@ class nsDisplayForeignObject : public nsDisplayWrapList { NS_DISPLAY_DECL_NAME("ForeignObject", TYPE_FOREIGN_OBJECT) - virtual already_AddRefed<Layer> BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; - virtual LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override; virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override; void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override { GetChildren()->Paint(aBuilder, aCtx, diff --git a/layout/painting/nsDisplayListInvalidation.cpp b/layout/painting/nsDisplayListInvalidation.cpp index c6e7395865b7195f9af3c1258972afe33ad85fbb..ba17158ce0aa4d825db32e7c9198e2a34964178c 100644 --- a/layout/painting/nsDisplayListInvalidation.cpp +++ b/layout/painting/nsDisplayListInvalidation.cpp @@ -31,6 +31,15 @@ bool ShouldSyncDecodeImages(nsDisplayListBuilder* aBuilder) { return aBuilder->ShouldSyncDecodeImages(); } +nsDisplayItemGeometry* GetPreviousGeometry(nsDisplayItem* aItem) { + if (RefPtr<layers::WebRenderFallbackData> data = + layers::GetWebRenderUserData<layers::WebRenderFallbackData>( + aItem->Frame(), aItem->GetPerFrameKey())) { + return data->GetGeometry(); + } + return nullptr; +} + void nsDisplayItemGenericGeometry::MoveBy(const nsPoint& aOffset) { nsDisplayItemGeometry::MoveBy(aOffset); mBorderRect.MoveBy(aOffset); diff --git a/layout/painting/nsDisplayListInvalidation.h b/layout/painting/nsDisplayListInvalidation.h index 7b1642ddaabd1276bf099adc16487687bb33fe8b..8458fc7d5a6e0f6134f5d107f2d41ce93c23b35a 100644 --- a/layout/painting/nsDisplayListInvalidation.h +++ b/layout/painting/nsDisplayListInvalidation.h @@ -8,7 +8,7 @@ #define NSDISPLAYLISTINVALIDATION_H_ #include "mozilla/Attributes.h" -#include "FrameLayerBuilder.h" +#include "mozilla/layers/WebRenderUserData.h" #include "ImgDrawResult.h" #include "nsRect.h" #include "nsColor.h" @@ -84,6 +84,8 @@ class nsDisplayItemGenericGeometry : public nsDisplayItemGeometry { bool ShouldSyncDecodeImages(nsDisplayListBuilder* aBuilder); +nsDisplayItemGeometry* GetPreviousGeometry(nsDisplayItem*); + /** * nsImageGeometryMixin is a mixin for geometry items that draw images. * Geometry items that include this mixin can track drawing results and use @@ -100,9 +102,7 @@ class nsImageGeometryMixin { : mLastDrawResult(mozilla::image::ImgDrawResult::NOT_READY), mWaitingForPaint(false) { // Transfer state from the previous version of this geometry item. - auto lastGeometry = static_cast<T*>( - mozilla::FrameLayerBuilder::GetMostRecentGeometry(aItem)); - if (lastGeometry) { + if (auto lastGeometry = static_cast<T*>(GetPreviousGeometry(aItem))) { mLastDrawResult = lastGeometry->mLastDrawResult; mWaitingForPaint = lastGeometry->mWaitingForPaint; } @@ -121,9 +121,7 @@ class nsImageGeometryMixin { MOZ_ASSERT(aResult != mozilla::image::ImgDrawResult::NOT_SUPPORTED, "ImgDrawResult::NOT_SUPPORTED should be handled already!"); - auto lastGeometry = static_cast<T*>( - mozilla::FrameLayerBuilder::GetMostRecentGeometry(aItem)); - if (lastGeometry) { + if (auto lastGeometry = static_cast<T*>(GetPreviousGeometry(aItem))) { lastGeometry->mLastDrawResult = aResult; lastGeometry->mWaitingForPaint = false; } diff --git a/layout/style/ImageLoader.cpp b/layout/style/ImageLoader.cpp index 16feb4b31c787c47d305d0cc23a1565d91504837..f999ac2cfa1b909cec304bdd16085920cde11165 100644 --- a/layout/style/ImageLoader.cpp +++ b/layout/style/ImageLoader.cpp @@ -20,7 +20,6 @@ #include "nsCanvasFrame.h" #include "nsDisplayList.h" #include "nsIFrameInlines.h" -#include "FrameLayerBuilder.h" #include "imgIContainer.h" #include "imgINotificationObserver.h" #include "Image.h" @@ -524,25 +523,6 @@ static void InvalidateImages(nsIFrame* aFrame, imgIRequest* aRequest, } bool invalidateFrame = aForcePaint; - if (auto* array = aFrame->DisplayItemData()) { - for (auto* did : *array) { - DisplayItemData* data = DisplayItemData::AssertDisplayItemData(did); - uint32_t displayItemKey = data->GetDisplayItemKey(); - - if (displayItemKey != 0 && !IsRenderNoImages(displayItemKey)) { - if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { - DisplayItemType type = GetDisplayItemTypeFromKey(displayItemKey); - printf_stderr( - "Invalidating display item(type=%d) based on frame %p \ - because it might contain an invalidated image\n", - static_cast<uint32_t>(type), aFrame); - } - - data->Invalidate(); - invalidateFrame = true; - } - } - } if (auto userDataTable = aFrame->GetProperty(layers::WebRenderUserDataProperty::Key())) { diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index 38919b6e45eebe194151a4563dfc75140d2711a4..2688c45853fb0f785025780de7aad381b69560fe 100644 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -22,7 +22,6 @@ #include "mozilla/dom/Element.h" #include "nsIFrame.h" #include "Layers.h" -#include "FrameLayerBuilder.h" #include "nsCSSProps.h" #include "nsCSSPseudoElements.h" #include "nsDisplayList.h" diff --git a/layout/svg/SVGIntegrationUtils.cpp b/layout/svg/SVGIntegrationUtils.cpp index b152f2c5b04f617c2c22d0ecdb8194b901ceadea..5380b5161a1b8b937e8b5f8d0c93d0fbe3c52e38 100644 --- a/layout/svg/SVGIntegrationUtils.cpp +++ b/layout/svg/SVGIntegrationUtils.cpp @@ -17,7 +17,6 @@ #include "nsLayoutUtils.h" #include "gfxContext.h" #include "SVGPaintServerFrame.h" -#include "FrameLayerBuilder.h" #include "BasicLayers.h" #include "mozilla/gfx/Point.h" #include "mozilla/gfx/gfxVars.h" @@ -1024,19 +1023,6 @@ void PaintMaskAndClipPathInternal(const PaintFramesParams& aParams, } } -void SVGIntegrationUtils::PaintMaskAndClipPath( - const PaintFramesParams& aParams) { - PaintMaskAndClipPathInternal(aParams, [&] { - gfxContext& context = aParams.ctx; - BasicLayerManager* basic = aParams.layerManager->AsBasicLayerManager(); - RefPtr<gfxContext> oldCtx = basic->GetTarget(); - basic->SetTarget(&context); - aParams.layerManager->EndTransaction(FrameLayerBuilder::DrawPaintedLayer, - aParams.builder); - basic->SetTarget(oldCtx); - }); -} - void SVGIntegrationUtils::PaintMaskAndClipPath( const PaintFramesParams& aParams, const std::function<void()>& aPaintChild) { diff --git a/layout/svg/SVGIntegrationUtils.h b/layout/svg/SVGIntegrationUtils.h index e2c095e7f8543d9b2371ec166634f86543c98691..4a585aa971d39b36847a14438b78ece05a7954f8 100644 --- a/layout/svg/SVGIntegrationUtils.h +++ b/layout/svg/SVGIntegrationUtils.h @@ -177,11 +177,6 @@ class SVGIntegrationUtils final { imgParams(aImgParams) {} }; - /** - * Paint non-SVG frame with mask, clipPath and opacity effect. - */ - static void PaintMaskAndClipPath(const PaintFramesParams& aParams); - // This should use FunctionRef instead of std::function because we don't need // to take ownership of the function. See bug 1490781. static void PaintMaskAndClipPath(const PaintFramesParams& aParams, diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp index afb60703df6fada44beb06d639b5fa16c7fd114b..f997f6320aa16c6043a6410510c88b840683c66d 100644 --- a/layout/tables/nsTableCellFrame.cpp +++ b/layout/tables/nsTableCellFrame.cpp @@ -28,7 +28,6 @@ #include "nsDisplayList.h" #include "nsLayoutUtils.h" #include "nsTextFrame.h" -#include "FrameLayerBuilder.h" #include <algorithm> // TABLECELL SELECTION diff --git a/layout/xul/nsBox.cpp b/layout/xul/nsBox.cpp index 5cc1af536b53f0d5a7d7ed70b19c9f95a557736f..65b6684847dce1fc66d017ef852ab43c4b51c1de 100644 --- a/layout/xul/nsBox.cpp +++ b/layout/xul/nsBox.cpp @@ -20,7 +20,6 @@ #include "nsITheme.h" #include "nsBoxLayout.h" #include "nsLayoutUtils.h" -#include "FrameLayerBuilder.h" #include "mozilla/dom/Attr.h" #include "mozilla/dom/Element.h" #include <algorithm> diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index 9e168755b2f28d675063ff4c5dfdae2f927a6cef..e6dfb0be167d3df7e6e5a0349fc1bf993dd2a53f 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -11,7 +11,6 @@ #include "BasicLayers.h" #include "ClientLayerManager.h" -#include "FrameLayerBuilder.h" #include "GLConsts.h" #include "InputData.h" #include "LiveResizeListener.h"