bool ClientTiledPaintedLayer::UseFastPath() { LayerMetricsWrapper scrollAncestor; GetAncestorLayers(&scrollAncestor, nullptr); if (!scrollAncestor) { return true; } const FrameMetrics& parentMetrics = scrollAncestor.Metrics(); bool multipleTransactionsNeeded = gfxPlatform::GetPlatform()->UseProgressivePaint() || gfxPrefs::UseLowPrecisionBuffer() || !parentMetrics.GetCriticalDisplayPort().IsEmpty(); bool isFixed = GetIsFixedPosition() || GetParent()->GetIsFixedPosition(); return !multipleTransactionsNeeded || isFixed || parentMetrics.GetDisplayPort().IsEmpty(); }
bool ClientTiledPaintedLayer::UseProgressiveDraw() { if (!gfxPlatform::GetPlatform()->UseProgressivePaint()) { // pref is disabled, so never do progressive return false; } if (!mContentClient->GetTiledBuffer()->SupportsProgressiveUpdate()) { return false; } if (ClientManager()->HasShadowTarget()) { // This condition is true when we are in a reftest scenario. We don't want // to draw progressively here because it can cause intermittent reftest // failures because the harness won't wait for all the tiles to be drawn. return false; } if (mPaintData.mCriticalDisplayPort.IsEmpty()) { // This catches three scenarios: // 1) This layer doesn't have a scrolling ancestor // 2) This layer is subject to OMTA transforms // 3) Low-precision painting is disabled // In all of these cases, we don't want to draw this layer progressively. return false; } if (GetIsFixedPosition() || GetParent()->GetIsFixedPosition()) { // This layer is fixed-position and so even if it does have a scrolling // ancestor it will likely be entirely on-screen all the time, so we // should draw it all at once return false; } if (ClientManager()->AsyncPanZoomEnabled()) { LayerMetricsWrapper scrollAncestor; GetAncestorLayers(&scrollAncestor, nullptr, nullptr); MOZ_ASSERT(scrollAncestor); // because mPaintData.mCriticalDisplayPort is non-empty const FrameMetrics& parentMetrics = scrollAncestor.Metrics(); if (!IsScrollingOnCompositor(parentMetrics)) { return false; } } return true; }
bool ClientTiledPaintedLayer::UseProgressiveDraw() { if (!gfxPrefs::ProgressivePaint()) { // pref is disabled, so never do progressive return false; } if (!mContentClient->GetTiledBuffer()->SupportsProgressiveUpdate()) { return false; } if (ClientManager()->HasShadowTarget()) { // This condition is true when we are in a reftest scenario. We don't want // to draw progressively here because it can cause intermittent reftest // failures because the harness won't wait for all the tiles to be drawn. return false; } if (GetIsFixedPosition() || GetParent()->GetIsFixedPosition()) { // This layer is fixed-position and so even if it does have a scrolling // ancestor it will likely be entirely on-screen all the time, so we // should draw it all at once return false; } if (mPaintData.mHasTransformAnimation) { // The compositor is going to animate this somehow, so we want it all // on the screen at once. return false; } if (ClientManager()->AsyncPanZoomEnabled()) { LayerMetricsWrapper scrollAncestor; GetAncestorLayers(&scrollAncestor, nullptr, nullptr); MOZ_ASSERT(scrollAncestor); // because mPaintData.mCriticalDisplayPort is set if (!scrollAncestor) { return false; } const FrameMetrics& parentMetrics = scrollAncestor.Metrics(); if (!IsScrollingOnCompositor(parentMetrics)) { return false; } } return true; }
bool ClientTiledPaintedLayer::UseFastPath() { LayerMetricsWrapper scrollAncestor; GetAncestorLayers(&scrollAncestor, nullptr); if (!scrollAncestor) { return true; } const FrameMetrics& parentMetrics = scrollAncestor.Metrics(); bool multipleTransactionsNeeded = gfxPlatform::GetPlatform()->UseProgressivePaint() || gfxPrefs::UseLowPrecisionBuffer() || !parentMetrics.GetCriticalDisplayPort().IsEmpty(); bool isFixed = GetIsFixedPosition() || GetParent()->GetIsFixedPosition(); bool isScrollable = parentMetrics.IsScrollable(); return !multipleTransactionsNeeded || isFixed || !isScrollable #if !defined(MOZ_WIDGET_ANDROID) || defined(MOZ_ANDROID_APZ) || !IsScrollingOnCompositor(parentMetrics) #endif ; }
void ClientTiledPaintedLayer::BeginPaint() { mPaintData.mLowPrecisionPaintCount = 0; mPaintData.mPaintFinished = false; mPaintData.mCompositionBounds.SetEmpty(); mPaintData.mCriticalDisplayPort.SetEmpty(); if (!GetBaseTransform().Is2D()) { // Give up if there is a complex CSS transform on the layer. We might // eventually support these but for now it's too complicated to handle // given that it's a pretty rare scenario. return; } // Get the metrics of the nearest scrollable layer and the nearest layer // with a displayport. LayerMetricsWrapper scrollAncestor; LayerMetricsWrapper displayPortAncestor; GetAncestorLayers(&scrollAncestor, &displayPortAncestor); if (!displayPortAncestor || !scrollAncestor) { // No displayport or scroll ancestor, so we can't do progressive rendering. #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_B2G) // Both Android and b2g are guaranteed to have a displayport set, so this // should never happen. NS_WARNING("Tiled PaintedLayer with no scrollable container ancestor"); #endif return; } TILING_LOG("TILING %p: Found scrollAncestor %p and displayPortAncestor %p\n", this, scrollAncestor.GetLayer(), displayPortAncestor.GetLayer()); const FrameMetrics& scrollMetrics = scrollAncestor.Metrics(); const FrameMetrics& displayportMetrics = displayPortAncestor.Metrics(); // Calculate the transform required to convert ParentLayer space of our // display port ancestor to the Layer space of this layer. gfx::Matrix4x4 transformDisplayPortToLayer = GetTransformToAncestorsParentLayer(this, displayPortAncestor); transformDisplayPortToLayer.Invert(); // Compute the critical display port that applies to this layer in the // LayoutDevice space of this layer. ParentLayerRect criticalDisplayPort = (displayportMetrics.GetCriticalDisplayPort() * displayportMetrics.GetZoom()) + displayportMetrics.mCompositionBounds.TopLeft(); mPaintData.mCriticalDisplayPort = RoundedOut( ApplyParentLayerToLayerTransform(transformDisplayPortToLayer, criticalDisplayPort)); TILING_LOG("TILING %p: Critical displayport %s\n", this, Stringify(mPaintData.mCriticalDisplayPort).c_str()); // Store the resolution from the displayport ancestor layer. Because this is Gecko-side, // before any async transforms have occurred, we can use the zoom for this. mPaintData.mResolution = displayportMetrics.GetZoom(); TILING_LOG("TILING %p: Resolution %f\n", this, mPaintData.mPresShellResolution.scale); // Store the applicable composition bounds in this layer's Layer units. mPaintData.mTransformToCompBounds = GetTransformToAncestorsParentLayer(this, scrollAncestor); gfx::Matrix4x4 transformToBounds = mPaintData.mTransformToCompBounds; transformToBounds.Invert(); mPaintData.mCompositionBounds = ApplyParentLayerToLayerTransform( transformToBounds, scrollMetrics.mCompositionBounds); TILING_LOG("TILING %p: Composition bounds %s\n", this, Stringify(mPaintData.mCompositionBounds).c_str()); // Calculate the scroll offset since the last transaction mPaintData.mScrollOffset = displayportMetrics.GetScrollOffset() * displayportMetrics.GetZoom(); TILING_LOG("TILING %p: Scroll offset %s\n", this, Stringify(mPaintData.mScrollOffset).c_str()); }
void ClientTiledPaintedLayer::BeginPaint() { mPaintData.ResetPaintData(); if (!GetBaseTransform().Is2D()) { // Give up if there is a complex CSS transform on the layer. We might // eventually support these but for now it's too complicated to handle // given that it's a pretty rare scenario. return; } // Get the metrics of the nearest scrollable layer and the nearest layer // with a displayport. LayerMetricsWrapper scrollAncestor; LayerMetricsWrapper displayPortAncestor; bool hasTransformAnimation; GetAncestorLayers(&scrollAncestor, &displayPortAncestor, &hasTransformAnimation); if (!displayPortAncestor || !scrollAncestor) { // No displayport or scroll ancestor, so we can't do progressive rendering. #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) // Both Android and b2g on phones are guaranteed to have a displayport set, so this // should never happen. NS_WARNING("Tiled PaintedLayer with no scrollable container ancestor"); #endif return; } TILING_LOG("TILING %p: Found scrollAncestor %p, displayPortAncestor %p, transform %d\n", this, scrollAncestor.GetLayer(), displayPortAncestor.GetLayer(), hasTransformAnimation); const FrameMetrics& scrollMetrics = scrollAncestor.Metrics(); const FrameMetrics& displayportMetrics = displayPortAncestor.Metrics(); // Calculate the transform required to convert ParentLayer space of our // display port ancestor to the Layer space of this layer. gfx::Matrix4x4 transformDisplayPortToLayer = GetTransformToAncestorsParentLayer(this, displayPortAncestor); transformDisplayPortToLayer.Invert(); LayerRect layerBounds = ViewAs<LayerPixel>(Rect(GetLayerBounds())); // Compute the critical display port that applies to this layer in the // LayoutDevice space of this layer, but only if there is no OMT animation // on this layer. If there is an OMT animation then we need to draw the whole // visible region of this layer as determined by layout, because we don't know // what parts of it might move into view in the compositor. if (!hasTransformAnimation && mContentClient->GetLowPrecisionTiledBuffer()) { ParentLayerRect criticalDisplayPort = (displayportMetrics.GetCriticalDisplayPort() * displayportMetrics.GetZoom()) + displayportMetrics.GetCompositionBounds().TopLeft(); Maybe<LayerRect> criticalDisplayPortTransformed = ApplyParentLayerToLayerTransform(transformDisplayPortToLayer, criticalDisplayPort, layerBounds); if (!criticalDisplayPortTransformed) { mPaintData.ResetPaintData(); return; } mPaintData.mCriticalDisplayPort = RoundedToInt(*criticalDisplayPortTransformed); } TILING_LOG("TILING %p: Critical displayport %s\n", this, Stringify(mPaintData.mCriticalDisplayPort).c_str()); // Store the resolution from the displayport ancestor layer. Because this is Gecko-side, // before any async transforms have occurred, we can use the zoom for this. mPaintData.mResolution = displayportMetrics.GetZoom(); TILING_LOG("TILING %p: Resolution %s\n", this, Stringify(mPaintData.mResolution).c_str()); // Store the applicable composition bounds in this layer's Layer units. mPaintData.mTransformToCompBounds = GetTransformToAncestorsParentLayer(this, scrollAncestor); gfx::Matrix4x4 transformToBounds = mPaintData.mTransformToCompBounds; transformToBounds.Invert(); Maybe<LayerRect> compositionBoundsTransformed = ApplyParentLayerToLayerTransform( transformToBounds, scrollMetrics.GetCompositionBounds(), layerBounds); if (!compositionBoundsTransformed) { mPaintData.ResetPaintData(); return; } mPaintData.mCompositionBounds = *compositionBoundsTransformed; TILING_LOG("TILING %p: Composition bounds %s\n", this, Stringify(mPaintData.mCompositionBounds).c_str()); // Calculate the scroll offset since the last transaction mPaintData.mScrollOffset = displayportMetrics.GetScrollOffset() * displayportMetrics.GetZoom(); TILING_LOG("TILING %p: Scroll offset %s\n", this, Stringify(mPaintData.mScrollOffset).c_str()); }