commit c2bd9d2d0058f4b6db2914980bd9f50711922c5e
parent 93857df07b0ea4fe6240e74863be90c0afd9b144
Author: Markus Stange <mstange.moz@gmail.com>
Date: Thu, 2 Oct 2025 20:49:13 +0000
Bug 1987007 - Use NativeLayerRootSnapshotterCA for NativeLayerRootRemoteMacChild. r=bradwerth
This makes profiler screenshots and the window recorder work correctly.
Differential Revision: https://phabricator.services.mozilla.com/D267149
Diffstat:
4 files changed, 97 insertions(+), 5 deletions(-)
diff --git a/gfx/layers/NativeLayerRemoteMac.h b/gfx/layers/NativeLayerRemoteMac.h
@@ -11,6 +11,7 @@
#include "mozilla/layers/NativeLayer.h"
#include "mozilla/layers/NativeLayerCommandQueue.h"
#include "mozilla/layers/NativeLayerMacSurfaceHandler.h"
+#include "NativeLayerCA.h"
#include "nsRegion.h"
namespace mozilla {
@@ -72,10 +73,14 @@ class NativeLayerRemoteMac final : public NativeLayer {
// If dirty, add a CommandLayerInfo to the queue. Clear dirty flag.
void FlushDirtyLayerInfoToCommandQueue();
+ void UpdateSnapshotLayer();
+ CALayer* CALayerForSnapshot();
+
protected:
+ NativeLayerCARepresentation mSnapshotLayer;
Maybe<NativeLayerMacSurfaceHandler> mSurfaceHandler;
RefPtr<NativeLayerCommandQueue> mCommandQueue;
- const gfx::DeviceColor mColor;
+ const Maybe<gfx::DeviceColor> mColor;
const bool mIsOpaque = false;
bool mDirtyLayerInfo = true;
diff --git a/gfx/layers/NativeLayerRemoteMac.mm b/gfx/layers/NativeLayerRemoteMac.mm
@@ -8,6 +8,7 @@
#include <algorithm>
#include <utility>
+#include "CFTypeRefPtr.h"
#include "gfxUtils.h"
#include "GLBlitHelper.h"
#ifdef XP_MACOSX
@@ -20,6 +21,7 @@
#include "mozilla/gfx/Swizzle.h"
#include "mozilla/glean/GfxMetrics.h"
#include "mozilla/webrender/RenderMacIOSurfaceTextureHost.h"
+#include "NativeLayerCA.h"
#include "ScopedGLHelpers.h"
namespace mozilla {
@@ -43,7 +45,7 @@ NativeLayerRemoteMac::NativeLayerRemoteMac(bool aIsOpaque)
: mIsOpaque(aIsOpaque) {}
NativeLayerRemoteMac::NativeLayerRemoteMac(gfx::DeviceColor aColor)
- : mColor(aColor), mIsOpaque(aColor.a >= 1.0f) {}
+ : mColor(Some(aColor)), mIsOpaque(aColor.a >= 1.0f) {}
NativeLayerRemoteMac::~NativeLayerRemoteMac() {
if (mCommandQueue) {
@@ -72,6 +74,7 @@ void NativeLayerRemoteMac::AttachExternalImage(
mDisplayRect = displayRect;
bool isDRM = aExternalImage->IsFromDRMSource();
+ bool changedIsDRM = mIsDRM != isDRM;
mIsDRM = isDRM;
bool isHDR = false;
@@ -88,6 +91,10 @@ void NativeLayerRemoteMac::AttachExternalImage(
mIsHDR = isHDR;
mDirtyLayerInfo |= changedDisplayRect;
+ mSnapshotLayer.mMutatedFrontSurface = true;
+ mSnapshotLayer.mMutatedSize |= changedDisplayRect;
+ mSnapshotLayer.mMutatedDisplayRect |= changedDisplayRect;
+ mSnapshotLayer.mMutatedIsDRM |= changedIsDRM;
mDirtyChangedSurface = true;
}
@@ -103,6 +110,7 @@ IntSize NativeLayerRemoteMac::GetSize() {
void NativeLayerRemoteMac::SetPosition(const IntPoint& aPosition) {
if (mPosition != aPosition) {
mDirtyLayerInfo = true;
+ mSnapshotLayer.mMutatedPosition = true;
mPosition = aPosition;
}
}
@@ -114,6 +122,7 @@ void NativeLayerRemoteMac::SetTransform(const Matrix4x4& aTransform) {
if (mTransform != aTransform) {
mDirtyLayerInfo = true;
+ mSnapshotLayer.mMutatedTransform = true;
mTransform = aTransform;
}
}
@@ -122,6 +131,7 @@ void NativeLayerRemoteMac::SetSamplingFilter(
gfx::SamplingFilter aSamplingFilter) {
if (mSamplingFilter != aSamplingFilter) {
mDirtyLayerInfo = true;
+ mSnapshotLayer.mMutatedSamplingFilter = true;
mSamplingFilter = aSamplingFilter;
}
}
@@ -155,6 +165,7 @@ void NativeLayerRemoteMac::SetRoundedClipRect(
const Maybe<gfx::RoundedRect>& aRoundedClipRect) {
if (mRoundedClipRect != aRoundedClipRect) {
mDirtyLayerInfo = true;
+ mSnapshotLayer.mMutatedRoundedClipRect = true;
mRoundedClipRect = aRoundedClipRect;
}
}
@@ -173,6 +184,7 @@ gfx::IntRect NativeLayerRemoteMac::CurrentSurfaceDisplayRect() {
void NativeLayerRemoteMac::SetSurfaceIsFlipped(bool aIsFlipped) {
if (SurfaceIsFlipped() != aIsFlipped) {
mDirtyLayerInfo = true;
+ mSnapshotLayer.mMutatedSurfaceIsFlipped = true;
if (mSurfaceHandler) {
mSurfaceHandler->SetSurfaceIsFlipped(aIsFlipped);
} else {
@@ -223,6 +235,7 @@ void NativeLayerRemoteMac::NotifySurfaceReady() {
bool changedDisplayRect = mSurfaceHandler->NotifySurfaceReady();
mDirtyLayerInfo |= changedDisplayRect;
mDirtyChangedSurface = true;
+ mSnapshotLayer.mMutatedFrontSurface = true;
}
void NativeLayerRemoteMac::DiscardBackbuffers() {
@@ -258,5 +271,27 @@ void NativeLayerRemoteMac::FlushDirtyLayerInfoToCommandQueue() {
}
}
+void NativeLayerRemoteMac::UpdateSnapshotLayer() {
+ CFTypeRefPtr<IOSurfaceRef> surface;
+ if (auto frontSurface = FrontSurface()) {
+ surface = frontSurface->mSurface;
+ }
+
+ IntRect rect = GetRect();
+ IntRect displayRect = CurrentSurfaceDisplayRect();
+
+ bool specializeVideo = false;
+ bool isVideo = false;
+ mSnapshotLayer.ApplyChanges(
+ NativeLayerCAUpdateType::All, rect.Size(), mIsOpaque, rect.TopLeft(),
+ mTransform, displayRect, mClipRect, mRoundedClipRect, mBackingScale,
+ mSurfaceIsFlipped, mSamplingFilter, specializeVideo, surface, mColor,
+ mIsDRM, isVideo);
+}
+
+CALayer* NativeLayerRemoteMac::CALayerForSnapshot() {
+ return mSnapshotLayer.UnderlyingCALayer();
+}
+
} // namespace layers
} // namespace mozilla
diff --git a/gfx/layers/NativeLayerRootRemoteMacChild.h b/gfx/layers/NativeLayerRootRemoteMacChild.h
@@ -47,12 +47,32 @@ class NativeLayerRootRemoteMacChild final : public NativeLayerRoot {
virtual ~NativeLayerRootRemoteMacChild();
+ void CommitForSnapshot(CALayer* aRootCALayer);
+ void OnNativeLayerRootSnapshotterDestroyed(
+ NativeLayerRootSnapshotterCA* aNativeLayerRootSnapshotter);
+
+ // An implementation of SnapshotterCADelegate, backed by a
+ // NativeLayerRootRemoteMacChild.
+ struct SnapshotterDelegate final : public SnapshotterCADelegate {
+ explicit SnapshotterDelegate(NativeLayerRootRemoteMacChild* aLayerRoot);
+ virtual ~SnapshotterDelegate() override;
+ virtual void UpdateSnapshotterLayers(CALayer* aRootCALayer) override {
+ mLayerRoot->CommitForSnapshot(aRootCALayer);
+ }
+ virtual void OnSnapshotterDestroyed(
+ NativeLayerRootSnapshotterCA* aSnapshotter) override {
+ mLayerRoot->OnNativeLayerRootSnapshotterDestroyed(aSnapshotter);
+ }
+ RefPtr<NativeLayerRootRemoteMacChild> mLayerRoot;
+ };
+
RefPtr<NativeLayerRemoteChild> mRemoteChild;
RefPtr<NativeLayerCommandQueue> mCommandQueue;
nsTArray<RefPtr<NativeLayerRemoteMac>> mNativeLayers;
- NativeLayerRootSnapshotter* mWeakSnapshotter = nullptr;
+ NativeLayerRootSnapshotterCA* mWeakSnapshotter = nullptr;
bool mNativeLayersChanged = false;
+ bool mNativeLayersChangedForSnapshot = false;
bool ReadbackPixels(const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat,
const Range<uint8_t>& aBuffer);
diff --git a/gfx/layers/NativeLayerRootRemoteMacChild.mm b/gfx/layers/NativeLayerRootRemoteMacChild.mm
@@ -5,7 +5,6 @@
#include "mozilla/layers/NativeLayerRemoteMac.h"
#include "mozilla/layers/NativeLayerRootRemoteMacChild.h"
-#include "mozilla/layers/NativeLayerRootRemoteMacSnapshotter.h"
#include "mozilla/layers/SurfacePool.h"
namespace mozilla {
@@ -66,6 +65,7 @@ void NativeLayerRootRemoteMacChild::SetLayers(
}
mNativeLayersChanged = true;
+ mNativeLayersChangedForSnapshot = true;
mNativeLayers.Clear();
mNativeLayers.AppendElements(layers);
}
@@ -76,13 +76,20 @@ NativeLayerRootRemoteMacChild::CreateSnapshotter() {
"No NativeLayerRootSnapshotter for this NativeLayerRoot "
"should exist when this is called");
- auto cr = NativeLayerRootRemoteMacSnapshotter::Create(this);
+ auto cr = NativeLayerRootSnapshotterCA::Create(
+ MakeUnique<SnapshotterDelegate>(this));
if (cr) {
mWeakSnapshotter = cr.get();
}
return cr;
}
+void NativeLayerRootRemoteMacChild::OnNativeLayerRootSnapshotterDestroyed(
+ NativeLayerRootSnapshotterCA* aNativeLayerRootSnapshotter) {
+ MOZ_RELEASE_ASSERT(mWeakSnapshotter == aNativeLayerRootSnapshotter);
+ mWeakSnapshotter = nullptr;
+}
+
void NativeLayerRootRemoteMacChild::PrepareForCommit() {
// Intentionally ignored.
}
@@ -127,6 +134,25 @@ bool NativeLayerRootRemoteMacChild::CommitToScreen() {
return true;
}
+void NativeLayerRootRemoteMacChild::CommitForSnapshot(CALayer* aRootCALayer) {
+ [CATransaction begin];
+ [CATransaction setDisableActions:YES]; // disable cross-fade
+
+ NSMutableArray<CALayer*>* sublayers =
+ [NSMutableArray arrayWithCapacity:mNativeLayers.Length()];
+ for (const auto& layer : mNativeLayers) {
+ layer->UpdateSnapshotLayer();
+ if (CALayer* caLayer = layer->CALayerForSnapshot()) {
+ [sublayers addObject:caLayer];
+ }
+ }
+
+ aRootCALayer.sublayers = sublayers;
+ [CATransaction commit];
+
+ mNativeLayersChangedForSnapshot = false;
+}
+
bool NativeLayerRootRemoteMacChild::ReadbackPixels(
const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat,
const Range<uint8_t>& aBuffer) {
@@ -160,5 +186,11 @@ NativeLayerRootRemoteMacChild::NativeLayerRootRemoteMacChild()
NativeLayerRootRemoteMacChild::~NativeLayerRootRemoteMacChild() {}
+NativeLayerRootRemoteMacChild::SnapshotterDelegate::SnapshotterDelegate(
+ NativeLayerRootRemoteMacChild* aLayerRoot)
+ : mLayerRoot(aLayerRoot) {}
+NativeLayerRootRemoteMacChild::SnapshotterDelegate::~SnapshotterDelegate() =
+ default;
+
} // namespace layers
} // namespace mozilla