commit dc5027c9f7485ed3e1e1615001e5ad2b2f975777
parent 450f330d6bc43e3ecc29e6be7d2873e71b6cde70
Author: Markus Stange <mstange.moz@gmail.com>
Date: Fri, 3 Oct 2025 12:45:26 +0000
Bug 1987007 - Fold HasExtent tracking into ApplyChanges. r=bradwerth
Differential Revision: https://phabricator.services.mozilla.com/D267143
Diffstat:
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,