commit a34a997c6f431ae39fd15ef82782f8813a44e50a
parent f78cdbaff8a375d2b614c9434f2a59eeeabbb6ce
Author: Markus Stange <mstange.moz@gmail.com>
Date: Tue, 7 Oct 2025 15:49:45 +0000
Bug 1987056 - Keep IOSurface 'in use' as long as it is in mSurfaceToPresent. r=bradwerth
This plugs a small hole in the following time window:
1. The parent process receives the surface as an IOSurfacePort, stores it in
mSurfaceToPresent, and drops the IOSurfacePort.
2. The parent process puts the surface into a CALayer during commit.
During this time window, nobody is holding a mach_port for the surface, so the surface
won't automatically be "in use" by the port.
So this patch adds manual invocations IncrementUseCount / DecrementUseCount to
cover this time window.
This means that the GPU process's SurfacePoolCA will not recycle the surface by
accident if it checks IOSurfaceIsInUse during the above time window.
Differential Revision: https://phabricator.services.mozilla.com/D267492
Diffstat:
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/gfx/layers/NativeLayerCA.h b/gfx/layers/NativeLayerCA.h
@@ -467,6 +467,10 @@ class NativeLayerCA : public NativeLayer {
// Controls access to all fields of this class.
Mutex mMutex MOZ_UNANNOTATED;
+ // The IOSurface to use for this layer. Optional.
+ // If not present, we get use a surface from mSurfaceHandler or mTextureHost
+ // instead. We mark the surface as "in use" as long as it is in
+ // mSurfaceToPresent, to prevent other processes from recycling it.
CFTypeRefPtr<IOSurfaceRef> mSurfaceToPresent;
Maybe<NativeLayerMacSurfaceHandler> mSurfaceHandler;
diff --git a/gfx/layers/NativeLayerCA.mm b/gfx/layers/NativeLayerCA.mm
@@ -889,6 +889,10 @@ NativeLayerCA::~NativeLayerCA() {
this);
}
#endif
+
+ if (mSurfaceToPresent) {
+ IOSurfaceDecrementUseCount(mSurfaceToPresent.get());
+ }
}
void NativeLayerCA::AttachExternalImage(wr::RenderTextureHost* aExternalImage) {
@@ -1321,7 +1325,15 @@ void NativeLayerCA::SetSurfaceToPresent(CFTypeRefPtr<IOSurfaceRef> aSurfaceRef,
"Shouldn't call this for layers that get external surfaces.");
bool changedSurface = (mSurfaceToPresent != aSurfaceRef);
- mSurfaceToPresent = aSurfaceRef;
+ if (changedSurface) {
+ if (mSurfaceToPresent) {
+ IOSurfaceDecrementUseCount(mSurfaceToPresent.get());
+ }
+ mSurfaceToPresent = aSurfaceRef;
+ if (mSurfaceToPresent) {
+ IOSurfaceIncrementUseCount(mSurfaceToPresent.get());
+ }
+ }
bool changedSize = (mSize != aSize);
mSize = aSize;