tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 4780d8eb2e94a18d5e0297057f08f7c2df8bad97
parent db48e85b637a4bb7da82773fcc94df7dc714a5c9
Author: Markus Stange <mstange.moz@gmail.com>
Date:   Thu,  2 Oct 2025 20:49:11 +0000

Bug 1987007 - Fold HasExtent tracking into ApplyChanges. r=bradwerth

Differential Revision: https://phabricator.services.mozilla.com/D267143

Diffstat:
Mgfx/layers/NativeLayerCA.h | 12++++++++----
Mgfx/layers/NativeLayerCA.mm | 76++++++++++++++++++++++++++++++++++------------------------------------------
2 files changed, 42 insertions(+), 46 deletions(-)

diff --git a/gfx/layers/NativeLayerCA.h b/gfx/layers/NativeLayerCA.h @@ -338,8 +338,6 @@ class NativeLayerCA : public NativeLayer { bool IsVideo(const MutexAutoLock& aProofOfLock); bool ShouldSpecializeVideo(const MutexAutoLock& aProofOfLock); - bool HasExtent() const { return mHasExtent; } - void SetHasExtent(bool aHasExtent) { mHasExtent = aHasExtent; } // This function returns a CGRect if a clip should be applied to the layer. // If set, the CGRect has the scaled position of the clip relative to the @@ -354,7 +352,10 @@ class NativeLayerCA : public NativeLayer { Representation(); ~Representation(); - CALayer* UnderlyingCALayer() { return mWrappingCALayer; } + // Returns null if the layer is currently completely clipped out. + CALayer* UnderlyingCALayer() { + return mWrappingCALayerHasExtent ? mWrappingCALayer : nullptr; + } bool EnqueueSurface(IOSurfaceRef aSurfaceRef); @@ -397,6 +398,9 @@ class NativeLayerCA : public NativeLayer { bool mLogNextVideoSurface = false; #endif + bool mWrappingCALayerHasExtent : 1; + + // These are all initialized to true by the constructor. bool mMutatedPosition : 1; bool mMutatedTransform : 1; bool mMutatedDisplayRect : 1; @@ -409,6 +413,7 @@ class NativeLayerCA : public NativeLayer { bool mMutatedSamplingFilter : 1; bool mMutatedSpecializeVideo : 1; bool mMutatedIsDRM : 1; + // Don't forget to update the constructor when you add a field here. }; Representation& GetRepresentation(WhichRepresentation aRepresentation); @@ -441,7 +446,6 @@ class NativeLayerCA : public NativeLayer { const bool mIsOpaque = false; bool mRootWindowIsFullscreen = false; bool mSpecializeVideo = false; - bool mHasExtent = false; bool mIsDRM = false; bool mIsHDR = false; diff --git a/gfx/layers/NativeLayerCA.mm b/gfx/layers/NativeLayerCA.mm @@ -485,41 +485,21 @@ void NativeLayerRootCA::CommitRepresentation( } // We're going to do a full update now, which requires a transaction. Update - // all of the sublayers. Afterwards, only continue processing the sublayers - // which have an extent. + // all of the sublayers. We collect all sublayers with non-zero extents into + // the sublayers array - layers which are completely clipped out will return + // null from UndelyingCALayer. AutoCATransaction transaction; - nsTArray<NativeLayerCA*> sublayersWithExtent; - for (auto layer : aSublayers) { + NSMutableArray<CALayer*>* sublayers = + [NSMutableArray arrayWithCapacity:aSublayers.Length()]; + for (const auto& layer : aSublayers) { layer->ApplyChanges(aRepresentation, NativeLayerCA::UpdateType::All, &mustRebuild); - CALayer* caLayer = layer->UnderlyingCALayer(aRepresentation); - if (!caLayer.masksToBounds || !CGRectIsEmpty(caLayer.bounds)) { - // This layer has an extent. If it didn't before, we need to rebuild. - mustRebuild |= !layer->HasExtent(); - layer->SetHasExtent(true); - sublayersWithExtent.AppendElement(layer); - } else { - // This layer has no extent. If it did before, we need to rebuild. - mustRebuild |= layer->HasExtent(); - layer->SetHasExtent(false); + if (CALayer* caLayer = layer->UnderlyingCALayer(aRepresentation)) { + [sublayers addObject:caLayer]; } - - // One other reason we may need to rebuild is if the caLayer is not part of - // the root layer's sublayers. This might happen if the caLayer was rebuilt. - // We construct this check in a way that maximizes the boolean - // short-circuit, because we don't want to call containsObject unless - // absolutely necessary. - mustRebuild = - mustRebuild || ![aRootCALayer.sublayers containsObject:caLayer]; } if (mustRebuild) { - uint32_t sublayersCount = sublayersWithExtent.Length(); - NSMutableArray<CALayer*>* sublayers = - [NSMutableArray arrayWithCapacity:sublayersCount]; - for (auto layer : sublayersWithExtent) { - [sublayers addObject:layer->UnderlyingCALayer(aRepresentation)]; - } aRootCALayer.sublayers = sublayers; } } @@ -622,22 +602,25 @@ VideoLowPowerType NativeLayerRootCA::CheckVideoLowPower( // determine more detail. uint32_t videoLayerCount = 0; - NativeLayerCA* topLayer = nullptr; + DebugOnly<RefPtr<NativeLayerCA>> topLayer; CALayer* topCALayer = nil; CALayer* secondCALayer = nil; bool topLayerIsVideo = false; for (auto layer : mSublayers) { // Only layers with extent are contributing to our sublayers. - if (layer->HasExtent()) { - topLayer = layer; - - secondCALayer = topCALayer; - topCALayer = topLayer->UnderlyingCALayer(WhichRepresentation::ONSCREEN); - topLayerIsVideo = topLayer->IsVideo(aProofOfLock); - if (topLayerIsVideo) { + CALayer* caLayer = layer->UnderlyingCALayer(WhichRepresentation::ONSCREEN); + if (caLayer) { + bool isVideo = layer->IsVideo(aProofOfLock); + if (isVideo) { ++videoLayerCount; } + + secondCALayer = topCALayer; + + topLayer = layer; + topCALayer = caLayer; + topLayerIsVideo = isVideo; } } @@ -1369,7 +1352,8 @@ void NativeLayerCA::SetSurfaceToPresent(CFTypeRefPtr<IOSurfaceRef> aSurfaceRef, } NativeLayerCA::Representation::Representation() - : mMutatedPosition(true), + : mWrappingCALayerHasExtent(false), + mMutatedPosition(true), mMutatedTransform(true), mMutatedDisplayRect(true), mMutatedClipRect(true), @@ -1514,13 +1498,19 @@ bool NativeLayerCA::ApplyChanges(WhichRepresentation aRepresentation, } auto& r = GetRepresentation(aRepresentation); - if (r.mMutatedSpecializeVideo || !r.UnderlyingCALayer()) { + if (r.mMutatedSpecializeVideo) { + *aMustRebuild = true; + } + bool hadExtentBeforeUpdate = r.UnderlyingCALayer() != nullptr; + bool updateSucceeded = r.ApplyChanges( + aUpdate, size, mIsOpaque, mPosition, mTransform, displayRect, mClipRect, + mRoundedClipRect, mBackingScale, surfaceIsFlipped, mSamplingFilter, + mSpecializeVideo, surface, mColor, mIsDRM, IsVideo(lock)); + bool hasExtentAfterUpdate = r.UnderlyingCALayer() != nullptr; + if (hasExtentAfterUpdate != hadExtentBeforeUpdate) { *aMustRebuild = true; } - return r.ApplyChanges(aUpdate, size, mIsOpaque, mPosition, mTransform, - displayRect, mClipRect, mRoundedClipRect, mBackingScale, - surfaceIsFlipped, mSamplingFilter, mSpecializeVideo, - surface, mColor, mIsDRM, IsVideo(lock)); + return updateSucceeded; } CALayer* NativeLayerCA::UnderlyingCALayer(WhichRepresentation aRepresentation) { @@ -1919,6 +1909,8 @@ bool NativeLayerCA::Representation::ApplyChanges( mWrappingCALayer.bounds = CGRectMake(0, 0, useClipRect.size.width, useClipRect.size.height); mWrappingCALayer.masksToBounds = scaledClipRect.isSome(); + mWrappingCALayerHasExtent = + scaledClipRect.isNothing() || !CGRectIsEmpty(useClipRect); // Default the clip rect for the rounded rect clip layer to be the // same as the wrapping layer clip. This ensures that if it's not used,