tor-browser

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

commit 4c982435788b70ad8361c83b15a6702eb18ec8d4
parent 016fd8b67add34175acc53f160f82c39fd0a4936
Author: Markus Stange <mstange.moz@gmail.com>
Date:   Thu,  2 Oct 2025 20:49:11 +0000

Bug 1987007 - Inline-away NativeLayerRootCA::Representation. r=bradwerth

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

Diffstat:
Mgfx/layers/NativeLayerCA.h | 36++++++++++++++++++++----------------
Mgfx/layers/NativeLayerCA.mm | 74++++++++++++++++++++++++++++++++++----------------------------------------
2 files changed, 54 insertions(+), 56 deletions(-)

diff --git a/gfx/layers/NativeLayerCA.h b/gfx/layers/NativeLayerCA.h @@ -158,22 +158,22 @@ class NativeLayerRootCA : public NativeLayerRoot { explicit NativeLayerRootCA(CALayer* aLayer); ~NativeLayerRootCA() override; - struct Representation { - explicit Representation(CALayer* aRootCALayer); - ~Representation(); - void Commit(WhichRepresentation aRepresentation, - const nsTArray<RefPtr<NativeLayerCA>>& aSublayers, - bool aWindowIsFullscreen); - CALayer* mRootCALayer = nullptr; // strong - bool mMutatedLayerStructure = false; - }; - - template <typename F> - void ForAllRepresentations(F aFn); - - Mutex mMutex MOZ_UNANNOTATED; // protects all other fields - Representation mOnscreenRepresentation; - Representation mOffscreenRepresentation; + // Do a commit of the pending changes to the CALayers. This is used for both + // onscreen commits (modifying the CALayers attached to the NSView), and for + // "offscreen" commits. + // "Offscreen" commits are updating a separate copy of the CALayer tree for + // use with CARenderer by the snapshotter. + void CommitRepresentation(WhichRepresentation aRepresentation, + CALayer* aRootCALayer, + const nsTArray<RefPtr<NativeLayerCA>>& aSublayers, + bool aMutatedLayerStructure, + bool aWindowIsFullscreen); + + void SetMutatedLayerStructure(); + + Mutex mMutex MOZ_UNANNOTATED; // protects all other fields + CALayer* mOnscreenRootCALayer = nullptr; // strong + CALayer* mOffscreenRootCALayer = nullptr; // strong #ifdef XP_MACOSX NativeLayerRootSnapshotterCA* mWeakSnapshotter = nullptr; #endif @@ -197,6 +197,10 @@ class NativeLayerRootCA : public NativeLayerRoot { // of that window. bool mWindowIsFullscreen = false; + // Whether mSublayers has changed since the last onscreen / offscreen commit. + bool mMutatedOnscreenLayerStructure = false; + bool mMutatedOffscreenLayerStructure = false; + // How many times have we committed since the last time we emitted // telemetry? unsigned int mTelemetryCommitCount = 0; diff --git a/gfx/layers/NativeLayerCA.mm b/gfx/layers/NativeLayerCA.mm @@ -227,13 +227,24 @@ static CALayer* MakeOffscreenRootCALayer() { NativeLayerRootCA::NativeLayerRootCA(CALayer* aLayer) : mMutex("NativeLayerRootCA"), - mOnscreenRepresentation(aLayer), - mOffscreenRepresentation(MakeOffscreenRootCALayer()) {} + mOnscreenRootCALayer([aLayer retain]), + mOffscreenRootCALayer([MakeOffscreenRootCALayer() retain]) {} NativeLayerRootCA::~NativeLayerRootCA() { MOZ_RELEASE_ASSERT( mSublayers.IsEmpty(), "Please clear all layers before destroying the layer root."); + + if (mMutatedOnscreenLayerStructure || mMutatedOffscreenLayerStructure) { + // Clear the root layer's sublayers. At this point the window is usually + // closed, so this transaction does not cause any screen updates. + AutoCATransaction transaction; + mOnscreenRootCALayer.sublayers = @[]; + mOffscreenRootCALayer.sublayers = @[]; + } + + [mOnscreenRootCALayer release]; + [mOffscreenRootCALayer release]; } already_AddRefed<NativeLayer> NativeLayerRootCA::CreateLayer( @@ -272,8 +283,7 @@ void NativeLayerRootCA::AppendLayer(NativeLayer* aLayer) { mSublayers.AppendElement(layerCA); layerCA->SetBackingScale(mBackingScale); layerCA->SetRootWindowIsFullscreen(mWindowIsFullscreen); - ForAllRepresentations( - [&](Representation& r) { r.mMutatedLayerStructure = true; }); + SetMutatedLayerStructure(); } void NativeLayerRootCA::RemoveLayer(NativeLayer* aLayer) { @@ -283,8 +293,7 @@ void NativeLayerRootCA::RemoveLayer(NativeLayer* aLayer) { MOZ_RELEASE_ASSERT(layerCA); mSublayers.RemoveElement(layerCA); - ForAllRepresentations( - [&](Representation& r) { r.mMutatedLayerStructure = true; }); + SetMutatedLayerStructure(); } void NativeLayerRootCA::SetLayers( @@ -309,8 +318,7 @@ void NativeLayerRootCA::SetLayers( if (layersCA != mSublayers) { mSublayers = std::move(layersCA); - ForAllRepresentations( - [&](Representation& r) { r.mMutatedLayerStructure = true; }); + SetMutatedLayerStructure(); } } @@ -353,8 +361,10 @@ bool NativeLayerRootCA::CommitToScreen() { return false; } - mOnscreenRepresentation.Commit(WhichRepresentation::ONSCREEN, mSublayers, - mWindowIsFullscreen); + CommitRepresentation(WhichRepresentation::ONSCREEN, mOnscreenRootCALayer, + mSublayers, mMutatedOnscreenLayerStructure, + mWindowIsFullscreen); + mMutatedOnscreenLayerStructure = false; mCommitPending = false; @@ -401,8 +411,7 @@ UniquePtr<NativeLayerRootSnapshotter> NativeLayerRootCA::CreateSnapshotter() { "No NativeLayerRootSnapshotter for this NativeLayerRoot " "should exist when this is called"); - auto cr = NativeLayerRootSnapshotterCA::Create( - this, mOffscreenRepresentation.mRootCALayer); + auto cr = NativeLayerRootSnapshotterCA::Create(this, mOffscreenRootCALayer); if (cr) { mWeakSnapshotter = cr.get(); } @@ -423,35 +432,22 @@ void NativeLayerRootCA::OnNativeLayerRootSnapshotterDestroyed( void NativeLayerRootCA::CommitOffscreen() { MutexAutoLock lock(mMutex); - mOffscreenRepresentation.Commit(WhichRepresentation::OFFSCREEN, mSublayers, - mWindowIsFullscreen); + CommitRepresentation(WhichRepresentation::OFFSCREEN, mOffscreenRootCALayer, + mSublayers, mMutatedOffscreenLayerStructure, + mWindowIsFullscreen); + mMutatedOffscreenLayerStructure = false; } -template <typename F> -void NativeLayerRootCA::ForAllRepresentations(F aFn) { - aFn(mOnscreenRepresentation); - aFn(mOffscreenRepresentation); +void NativeLayerRootCA::SetMutatedLayerStructure() { + mMutatedOnscreenLayerStructure = true; + mMutatedOffscreenLayerStructure = true; } -NativeLayerRootCA::Representation::Representation(CALayer* aRootCALayer) - : mRootCALayer([aRootCALayer retain]) {} - -NativeLayerRootCA::Representation::~Representation() { - if (mMutatedLayerStructure) { - // Clear the root layer's sublayers. At this point the window is usually - // closed, so this transaction does not cause any screen updates. - AutoCATransaction transaction; - mRootCALayer.sublayers = @[]; - } - - [mRootCALayer release]; -} - -void NativeLayerRootCA::Representation::Commit( - WhichRepresentation aRepresentation, +void NativeLayerRootCA::CommitRepresentation( + WhichRepresentation aRepresentation, CALayer* aRootCALayer, const nsTArray<RefPtr<NativeLayerCA>>& aSublayers, - bool aWindowIsFullscreen) { - bool mustRebuild = mMutatedLayerStructure; + bool aMutatedLayerStructure, bool aWindowIsFullscreen) { + bool mustRebuild = aMutatedLayerStructure; if (!mustRebuild) { // Check which type of update we need to do, if any. NativeLayerCA::UpdateType updateRequired = NativeLayerCA::UpdateType::None; @@ -512,7 +508,7 @@ void NativeLayerRootCA::Representation::Commit( // short-circuit, because we don't want to call containsObject unless // absolutely necessary. mustRebuild = - mustRebuild || ![mRootCALayer.sublayers containsObject:caLayer]; + mustRebuild || ![aRootCALayer.sublayers containsObject:caLayer]; } if (mustRebuild) { @@ -522,10 +518,8 @@ void NativeLayerRootCA::Representation::Commit( for (auto layer : sublayersWithExtent) { [sublayers addObject:layer->UnderlyingCALayer(aRepresentation)]; } - mRootCALayer.sublayers = sublayers; + aRootCALayer.sublayers = sublayers; } - - mMutatedLayerStructure = false; } #ifdef XP_MACOSX