bool ClientTiledThebesLayer::UseFastPath() { const FrameMetrics& parentMetrics = GetParent()->GetFrameMetrics(); bool multipleTransactionsNeeded = gfxPrefs::UseProgressiveTilePainting() || gfxPrefs::UseLowPrecisionBuffer() || !parentMetrics.mCriticalDisplayPort.IsEmpty(); bool isFixed = GetIsFixedPosition() || GetParent()->GetIsFixedPosition(); return !multipleTransactionsNeeded || isFixed || parentMetrics.mDisplayPort.IsEmpty(); }
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::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 ClientTiledThebesLayer::RenderLayer() { LayerManager::DrawThebesLayerCallback callback = ClientManager()->GetThebesLayerCallback(); void *data = ClientManager()->GetThebesLayerCallbackData(); if (!callback) { ClientManager()->SetTransactionIncomplete(); return; } if (!mContentClient) { mContentClient = new TiledContentClient(this, ClientManager()); mContentClient->Connect(); ClientManager()->AsShadowForwarder()->Attach(mContentClient, this); MOZ_ASSERT(mContentClient->GetForwarder()); } if (mContentClient->mTiledBuffer.HasFormatChanged()) { mValidRegion = nsIntRegion(); } TILING_PRLOG_OBJ(("TILING 0x%p: Initial visible region %s\n", this, tmpstr.get()), mVisibleRegion); TILING_PRLOG_OBJ(("TILING 0x%p: Initial valid region %s\n", this, tmpstr.get()), mValidRegion); nsIntRegion invalidRegion = mVisibleRegion; invalidRegion.Sub(invalidRegion, mValidRegion); if (invalidRegion.IsEmpty()) { EndPaint(true); return; } // Only paint the mask layer on the first transaction. if (GetMaskLayer() && !ClientManager()->IsRepeatTransaction()) { ToClientLayer(GetMaskLayer())->RenderLayer(); } bool isFixed = GetIsFixedPosition() || GetParent()->GetIsFixedPosition(); // Fast path for no progressive updates, no low-precision updates and no // critical display-port set, or no display-port set, or this is a fixed // position layer/contained in a fixed position layer const FrameMetrics& parentMetrics = GetParent()->GetFrameMetrics(); if ((!gfxPrefs::UseProgressiveTilePainting() && !gfxPrefs::UseLowPrecisionBuffer() && parentMetrics.mCriticalDisplayPort.IsEmpty()) || parentMetrics.mDisplayPort.IsEmpty() || isFixed) { mValidRegion = mVisibleRegion; NS_ASSERTION(!ClientManager()->IsRepeatTransaction(), "Didn't paint our mask layer"); mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion, callback, data); ClientManager()->Hold(this); mContentClient->UseTiledLayerBuffer(TiledContentClient::TILED_BUFFER); return; } // Calculate everything we need to perform the paint. BeginPaint(); if (mPaintData.mPaintFinished) { return; } TILING_PRLOG_OBJ(("TILING 0x%p: Valid region %s\n", this, tmpstr.get()), mValidRegion); TILING_PRLOG_OBJ(("TILING 0x%p: Visible region %s\n", this, tmpstr.get()), mVisibleRegion); // Make sure that tiles that fall outside of the visible region are // discarded on the first update. if (!ClientManager()->IsRepeatTransaction()) { mValidRegion.And(mValidRegion, mVisibleRegion); if (!mPaintData.mCriticalDisplayPort.IsEmpty()) { // Make sure that tiles that fall outside of the critical displayport are // discarded on the first update. mValidRegion.And(mValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort)); } } nsIntRegion lowPrecisionInvalidRegion; if (!mPaintData.mCriticalDisplayPort.IsEmpty()) { if (gfxPrefs::UseLowPrecisionBuffer()) { // Calculate the invalid region for the low precision buffer lowPrecisionInvalidRegion.Sub(mVisibleRegion, mLowPrecisionValidRegion); // Remove the valid region from the low precision valid region (we don't // validate this part of the low precision buffer). lowPrecisionInvalidRegion.Sub(lowPrecisionInvalidRegion, mValidRegion); } // Clip the invalid region to the critical display-port invalidRegion.And(invalidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort)); if (invalidRegion.IsEmpty() && lowPrecisionInvalidRegion.IsEmpty()) { EndPaint(true); return; } } TILING_PRLOG_OBJ(("TILING 0x%p: Invalid region %s\n", this, tmpstr.get()), invalidRegion); if (!invalidRegion.IsEmpty() && mPaintData.mLowPrecisionPaintCount == 0) { bool updatedBuffer = false; // Only draw progressively when the resolution is unchanged. if (gfxPrefs::UseProgressiveTilePainting() && !ClientManager()->HasShadowTarget() && mContentClient->mTiledBuffer.GetFrameResolution() == mPaintData.mResolution) { // Store the old valid region, then clear it before painting. // We clip the old valid region to the visible region, as it only gets // used to decide stale content (currently valid and previously visible) nsIntRegion oldValidRegion = mContentClient->mTiledBuffer.GetValidRegion(); oldValidRegion.And(oldValidRegion, mVisibleRegion); if (!mPaintData.mCriticalDisplayPort.IsEmpty()) { oldValidRegion.And(oldValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort)); } TILING_PRLOG_OBJ(("TILING 0x%p: Progressive update with old valid region %s\n", this, tmpstr.get()), oldValidRegion); updatedBuffer = mContentClient->mTiledBuffer.ProgressiveUpdate(mValidRegion, invalidRegion, oldValidRegion, &mPaintData, callback, data); } else { updatedBuffer = true; mValidRegion = mVisibleRegion; if (!mPaintData.mCriticalDisplayPort.IsEmpty()) { mValidRegion.And(mValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort)); } TILING_PRLOG_OBJ(("TILING 0x%p: Painting: valid region %s\n", this, tmpstr.get()), mValidRegion); TILING_PRLOG_OBJ(("TILING 0x%p: and invalid region %s\n", this, tmpstr.get()), invalidRegion); mContentClient->mTiledBuffer.SetFrameResolution(mPaintData.mResolution); mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion, callback, data); } if (updatedBuffer) { ClientManager()->Hold(this); mContentClient->UseTiledLayerBuffer(TiledContentClient::TILED_BUFFER); // If there are low precision updates, mark the paint as unfinished and // request a repeat transaction. if (!lowPrecisionInvalidRegion.IsEmpty() && mPaintData.mPaintFinished) { ClientManager()->SetRepeatTransaction(); mPaintData.mLowPrecisionPaintCount = 1; mPaintData.mPaintFinished = false; } // Return so that low precision updates aren't performed in the same // transaction as high-precision updates. EndPaint(false); return; } } TILING_PRLOG_OBJ(("TILING 0x%p: Low-precision valid region is %s\n", this, tmpstr.get()), mLowPrecisionValidRegion); TILING_PRLOG_OBJ(("TILING 0x%p: Low-precision invalid region is %s\n", this, tmpstr.get()), lowPrecisionInvalidRegion); // Render the low precision buffer, if there's area to invalidate and the // visible region is larger than the critical display port. bool updatedLowPrecision = false; if (!lowPrecisionInvalidRegion.IsEmpty() && !nsIntRegion(LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort)).Contains(mVisibleRegion)) { nsIntRegion oldValidRegion = mContentClient->mLowPrecisionTiledBuffer.GetValidRegion(); oldValidRegion.And(oldValidRegion, mVisibleRegion); // If the frame resolution or format have changed, invalidate the buffer if (mContentClient->mLowPrecisionTiledBuffer.GetFrameResolution() != mPaintData.mResolution || mContentClient->mLowPrecisionTiledBuffer.HasFormatChanged()) { if (!mLowPrecisionValidRegion.IsEmpty()) { updatedLowPrecision = true; } oldValidRegion.SetEmpty(); mLowPrecisionValidRegion.SetEmpty(); mContentClient->mLowPrecisionTiledBuffer.SetFrameResolution(mPaintData.mResolution); lowPrecisionInvalidRegion = mVisibleRegion; } // Invalidate previously valid content that is no longer visible if (mPaintData.mLowPrecisionPaintCount == 1) { mLowPrecisionValidRegion.And(mLowPrecisionValidRegion, mVisibleRegion); } mPaintData.mLowPrecisionPaintCount++; // Remove the valid high-precision region from the invalid low-precision // region. We don't want to spend time drawing things twice. lowPrecisionInvalidRegion.Sub(lowPrecisionInvalidRegion, mValidRegion); if (!lowPrecisionInvalidRegion.IsEmpty()) { updatedLowPrecision = mContentClient->mLowPrecisionTiledBuffer .ProgressiveUpdate(mLowPrecisionValidRegion, lowPrecisionInvalidRegion, oldValidRegion, &mPaintData, callback, data); } } else if (!mLowPrecisionValidRegion.IsEmpty()) { // Clear the low precision tiled buffer updatedLowPrecision = true; mLowPrecisionValidRegion.SetEmpty(); mContentClient->mLowPrecisionTiledBuffer.ResetPaintedAndValidState(); } // We send a Painted callback if we clear the valid region of the low // precision buffer, so that the shadow buffer's valid region can be updated // and the associated resources can be freed. if (updatedLowPrecision) { ClientManager()->Hold(this); mContentClient->UseTiledLayerBuffer(TiledContentClient::LOW_PRECISION_TILED_BUFFER); } EndPaint(false); }
nsACString& Layer::PrintInfo(nsACString& aTo, const char* aPrefix) { aTo += aPrefix; aTo += nsPrintfCString("%s%s (0x%p)", mManager->Name(), Name(), this); layers::PrintInfo(aTo, AsLayerComposite()); if (mUseClipRect) { AppendToString(aTo, mClipRect, " [clip=", "]"); } if (1.0 != mPostXScale || 1.0 != mPostYScale) { aTo.AppendPrintf(" [postScale=%g, %g]", mPostXScale, mPostYScale); } if (!mTransform.IsIdentity()) { AppendToString(aTo, mTransform, " [transform=", "]"); } if (!mVisibleRegion.IsEmpty()) { AppendToString(aTo, mVisibleRegion, " [visible=", "]"); } else { aTo += " [not visible]"; } if (!mEventRegions.mHitRegion.IsEmpty()) { AppendToString(aTo, mEventRegions.mHitRegion, " [hitregion=", "]"); } if (!mEventRegions.mDispatchToContentHitRegion.IsEmpty()) { AppendToString(aTo, mEventRegions.mDispatchToContentHitRegion, " [dispatchtocontentregion=", "]"); } if (1.0 != mOpacity) { aTo.AppendPrintf(" [opacity=%g]", mOpacity); } if (GetContentFlags() & CONTENT_OPAQUE) { aTo += " [opaqueContent]"; } if (GetContentFlags() & CONTENT_COMPONENT_ALPHA) { aTo += " [componentAlpha]"; } if (GetScrollbarDirection() == VERTICAL) { aTo.AppendPrintf(" [vscrollbar=%lld]", GetScrollbarTargetContainerId()); } if (GetScrollbarDirection() == HORIZONTAL) { aTo.AppendPrintf(" [hscrollbar=%lld]", GetScrollbarTargetContainerId()); } if (GetIsFixedPosition()) { aTo.AppendPrintf(" [isFixedPosition anchor=%f,%f margin=%f,%f,%f,%f]", mAnchor.x, mAnchor.y, mMargins.top, mMargins.right, mMargins.bottom, mMargins.left); } if (GetIsStickyPosition()) { aTo.AppendPrintf(" [isStickyPosition scrollId=%d outer=%f,%f %fx%f " "inner=%f,%f %fx%f]", mStickyPositionData->mScrollId, mStickyPositionData->mOuter.x, mStickyPositionData->mOuter.y, mStickyPositionData->mOuter.width, mStickyPositionData->mOuter.height, mStickyPositionData->mInner.x, mStickyPositionData->mInner.y, mStickyPositionData->mInner.width, mStickyPositionData->mInner.height); } if (mMaskLayer) { aTo.AppendPrintf(" [mMaskLayer=%p]", mMaskLayer.get()); } return aTo; }