summaryrefslogtreecommitdiffstats
path: root/gfx/layers/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/ipc')
-rw-r--r--gfx/layers/ipc/CanvasChild.cpp27
-rw-r--r--gfx/layers/ipc/CanvasChild.h9
-rw-r--r--gfx/layers/ipc/CanvasTranslator.cpp66
-rw-r--r--gfx/layers/ipc/CanvasTranslator.h6
-rw-r--r--gfx/layers/ipc/CompositorBridgeChild.cpp14
-rw-r--r--gfx/layers/ipc/CompositorBridgeChild.h3
-rw-r--r--gfx/layers/ipc/CompositorBridgeParent.cpp20
-rw-r--r--gfx/layers/ipc/LayersMessageUtils.h31
-rw-r--r--gfx/layers/ipc/SharedSurfacesMemoryReport.h25
9 files changed, 131 insertions, 70 deletions
diff --git a/gfx/layers/ipc/CanvasChild.cpp b/gfx/layers/ipc/CanvasChild.cpp
index 515463cd8e..a25d5e6799 100644
--- a/gfx/layers/ipc/CanvasChild.cpp
+++ b/gfx/layers/ipc/CanvasChild.cpp
@@ -133,6 +133,16 @@ class SourceSurfaceCanvasRecording final : public gfx::SourceSurface {
void AttachSurface() { mDetached = false; }
void DetachSurface() { mDetached = true; }
+ void InvalidateDataSurface() {
+ if (mDataSourceSurface && mMayInvalidate) {
+ // This must be the only reference to the data left.
+ MOZ_ASSERT(mDataSourceSurface->hasOneRef());
+ mDataSourceSurface =
+ gfx::Factory::CopyDataSourceSurface(mDataSourceSurface);
+ mMayInvalidate = false;
+ }
+ }
+
already_AddRefed<gfx::SourceSurface> ExtractSubrect(
const gfx::IntRect& aRect) final {
return mRecordedSurface->ExtractSubrect(aRect);
@@ -142,8 +152,8 @@ class SourceSurfaceCanvasRecording final : public gfx::SourceSurface {
void EnsureDataSurfaceOnMainThread() {
// The data can only be retrieved on the main thread.
if (!mDataSourceSurface && NS_IsMainThread()) {
- mDataSourceSurface =
- mCanvasChild->GetDataSurface(mTextureId, mRecordedSurface, mDetached);
+ mDataSourceSurface = mCanvasChild->GetDataSurface(
+ mTextureId, mRecordedSurface, mDetached, mMayInvalidate);
}
}
@@ -167,6 +177,7 @@ class SourceSurfaceCanvasRecording final : public gfx::SourceSurface {
RefPtr<CanvasDrawEventRecorder> mRecorder;
RefPtr<gfx::DataSourceSurface> mDataSourceSurface;
bool mDetached = false;
+ bool mMayInvalidate = false;
};
class CanvasDataShmemHolder {
@@ -420,6 +431,7 @@ already_AddRefed<gfx::DrawTargetRecording> CanvasChild::CreateDrawTarget(
gfx::BackendType::SKIA, gfx::IntSize(1, 1), aFormat);
RefPtr<gfx::DrawTargetRecording> dt = MakeAndAddRef<gfx::DrawTargetRecording>(
mRecorder, aTextureId, aTextureOwnerId, dummyDt, aSize);
+ dt->SetOptimizeTransform(true);
mTextureInfo.insert({aTextureId, {}});
@@ -483,7 +495,8 @@ int64_t CanvasChild::CreateCheckpoint() {
}
already_AddRefed<gfx::DataSourceSurface> CanvasChild::GetDataSurface(
- int64_t aTextureId, const gfx::SourceSurface* aSurface, bool aDetached) {
+ int64_t aTextureId, const gfx::SourceSurface* aSurface, bool aDetached,
+ bool& aMayInvalidate) {
NS_ASSERT_OWNINGTHREAD(CanvasChild);
MOZ_ASSERT(aSurface);
@@ -527,6 +540,7 @@ already_AddRefed<gfx::DataSourceSurface> CanvasChild::GetDataSurface(
gfx::Factory::CreateWrappingDataSourceSurface(
shmemPtr, stride, ssSize, ssFormat, ReleaseDataShmemHolder,
closure);
+ aMayInvalidate = true;
return dataSurface.forget();
}
}
@@ -556,6 +570,7 @@ already_AddRefed<gfx::DataSourceSurface> CanvasChild::GetDataSurface(
RefPtr<gfx::DataSourceSurface> dataSurface =
gfx::Factory::CreateWrappingDataSourceSurface(
data, stride, ssSize, ssFormat, ReleaseDataShmemHolder, closure);
+ aMayInvalidate = false;
return dataSurface.forget();
}
@@ -593,10 +608,14 @@ void CanvasChild::AttachSurface(const RefPtr<gfx::SourceSurface>& aSurface) {
}
}
-void CanvasChild::DetachSurface(const RefPtr<gfx::SourceSurface>& aSurface) {
+void CanvasChild::DetachSurface(const RefPtr<gfx::SourceSurface>& aSurface,
+ bool aInvalidate) {
if (auto* surface =
static_cast<SourceSurfaceCanvasRecording*>(aSurface.get())) {
surface->DetachSurface();
+ if (aInvalidate) {
+ surface->InvalidateDataSurface();
+ }
}
}
diff --git a/gfx/layers/ipc/CanvasChild.h b/gfx/layers/ipc/CanvasChild.h
index e22109f406..a0cf22b0ec 100644
--- a/gfx/layers/ipc/CanvasChild.h
+++ b/gfx/layers/ipc/CanvasChild.h
@@ -22,7 +22,7 @@ class ThreadSafeWorkerRef;
namespace gfx {
class DrawTargetRecording;
class SourceSurface;
-}
+} // namespace gfx
namespace layers {
class CanvasDrawEventRecorder;
@@ -132,7 +132,8 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr {
/**
* The DrawTargetRecording is about to change, so detach the old snapshot.
*/
- void DetachSurface(const RefPtr<gfx::SourceSurface>& aSurface);
+ void DetachSurface(const RefPtr<gfx::SourceSurface>& aSurface,
+ bool aInvalidate = false);
/**
* Get DataSourceSurface from the translated equivalent version of aSurface in
@@ -141,11 +142,13 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr {
* @param aSurface the SourceSurface in this process for which we need a
* DataSourceSurface
* @param aDetached whether the surface is old
+ * @param aMayInvalidate whether the data may be invalidated by future changes
* @returns a DataSourceSurface created from data for aSurface retrieve from
* GPU process
*/
already_AddRefed<gfx::DataSourceSurface> GetDataSurface(
- int64_t aTextureId, const gfx::SourceSurface* aSurface, bool aDetached);
+ int64_t aTextureId, const gfx::SourceSurface* aSurface, bool aDetached,
+ bool& aMayInvalidate);
bool RequiresRefresh(int64_t aTextureId) const;
diff --git a/gfx/layers/ipc/CanvasTranslator.cpp b/gfx/layers/ipc/CanvasTranslator.cpp
index 4a184f48d8..3fd7a4c4c4 100644
--- a/gfx/layers/ipc/CanvasTranslator.cpp
+++ b/gfx/layers/ipc/CanvasTranslator.cpp
@@ -21,6 +21,7 @@
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/SharedSurfacesParent.h"
#include "mozilla/layers/TextureClient.h"
+#include "mozilla/layers/VideoBridgeParent.h"
#include "mozilla/StaticPrefs_gfx.h"
#include "mozilla/SyncRunnable.h"
#include "mozilla/TaskQueue.h"
@@ -112,6 +113,8 @@ static bool CreateAndMapShmem(RefPtr<ipc::SharedMemoryBasic>& aShmem,
return true;
}
+StaticRefPtr<gfx::SharedContextWebgl> CanvasTranslator::sSharedContext;
+
bool CanvasTranslator::EnsureSharedContextWebgl() {
if (!mSharedContext || mSharedContext->IsContextLost()) {
if (mSharedContext) {
@@ -121,7 +124,14 @@ bool CanvasTranslator::EnsureSharedContextWebgl() {
mRemoteTextureOwner->ClearRecycledTextures();
}
}
- mSharedContext = gfx::SharedContextWebgl::Create();
+ // Check if the global shared context is still valid. If not, instantiate
+ // a new one before we try to use it.
+ if (!sSharedContext || sSharedContext->IsContextLost()) {
+ sSharedContext = gfx::SharedContextWebgl::Create();
+ }
+ mSharedContext = sSharedContext;
+ // If we can't get a new context, then the only thing left to do is block
+ // new canvases.
if (!mSharedContext || mSharedContext->IsContextLost()) {
mSharedContext = nullptr;
BlockCanvas();
@@ -131,6 +141,13 @@ bool CanvasTranslator::EnsureSharedContextWebgl() {
return true;
}
+void CanvasTranslator::Shutdown() {
+ if (sSharedContext) {
+ gfx::CanvasRenderThread::Dispatch(NS_NewRunnableFunction(
+ "CanvasTranslator::Shutdown", []() { sSharedContext = nullptr; }));
+ }
+}
+
mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator(
TextureType aTextureType, TextureType aWebglTextureType,
gfx::BackendType aBackendType, Handle&& aReadHandle,
@@ -1144,6 +1161,13 @@ void CanvasTranslator::ClearTextureInfo() {
mTextureInfo.clear();
mDrawTargets.Clear();
mSharedContext = nullptr;
+ // If the global shared context's ref is the last ref left, then clear out
+ // any internal caches and textures from the context, but still keep it
+ // alive. This saves on startup costs while not contributing significantly
+ // to memory usage.
+ if (sSharedContext && sSharedContext->hasOneRef()) {
+ sSharedContext->ClearCaches();
+ }
mBaseDT = nullptr;
if (mReferenceTextureData) {
mReferenceTextureData->Unlock();
@@ -1163,6 +1187,46 @@ already_AddRefed<gfx::SourceSurface> CanvasTranslator::LookupExternalSurface(
return mSharedSurfacesHolder->Get(wr::ToExternalImageId(aKey));
}
+// Check if the surface descriptor describes a GPUVideo texture for which we
+// only have an opaque source/handle from SurfaceDescriptorRemoteDecoder to
+// derive the actual texture from.
+static bool SDIsNullRemoteDecoder(const SurfaceDescriptor& sd) {
+ return sd.type() == SurfaceDescriptor::TSurfaceDescriptorGPUVideo &&
+ sd.get_SurfaceDescriptorGPUVideo()
+ .get_SurfaceDescriptorRemoteDecoder()
+ .subdesc()
+ .type() == RemoteDecoderVideoSubDescriptor::Tnull_t;
+}
+
+already_AddRefed<gfx::SourceSurface>
+CanvasTranslator::LookupSourceSurfaceFromSurfaceDescriptor(
+ const SurfaceDescriptor& aDesc) {
+ if (!SDIsNullRemoteDecoder(aDesc)) {
+ return nullptr;
+ }
+
+ const auto& sdrd = aDesc.get_SurfaceDescriptorGPUVideo()
+ .get_SurfaceDescriptorRemoteDecoder();
+ RefPtr<VideoBridgeParent> parent =
+ VideoBridgeParent::GetSingleton(sdrd.source());
+ if (!parent) {
+ MOZ_ASSERT_UNREACHABLE("unexpected to be called");
+ gfxCriticalNote << "TexUnpackSurface failed to get VideoBridgeParent";
+ return nullptr;
+ }
+ RefPtr<TextureHost> texture =
+ parent->LookupTexture(mContentId, sdrd.handle());
+ if (!texture) {
+ MOZ_ASSERT_UNREACHABLE("unexpected to be called");
+ gfxCriticalNote << "TexUnpackSurface failed to get TextureHost";
+ return nullptr;
+ }
+
+ RefPtr<gfx::DataSourceSurface> surf = texture->GetAsSurface();
+
+ return surf.forget();
+}
+
void CanvasTranslator::CheckpointReached() { CheckAndSignalWriter(); }
void CanvasTranslator::PauseTranslation() {
diff --git a/gfx/layers/ipc/CanvasTranslator.h b/gfx/layers/ipc/CanvasTranslator.h
index 5258e0c529..e2b6c587b4 100644
--- a/gfx/layers/ipc/CanvasTranslator.h
+++ b/gfx/layers/ipc/CanvasTranslator.h
@@ -219,6 +219,9 @@ class CanvasTranslator final : public gfx::InlineTranslator,
already_AddRefed<gfx::SourceSurface> LookupExternalSurface(
uint64_t aKey) final;
+ already_AddRefed<gfx::SourceSurface> LookupSourceSurfaceFromSurfaceDescriptor(
+ const SurfaceDescriptor& aDesc) final;
+
/**
* Gets the cached DataSourceSurface, if it exists, associated with a
* SourceSurface from another process.
@@ -274,6 +277,8 @@ class CanvasTranslator final : public gfx::InlineTranslator,
void GetDataSurface(uint64_t aSurfaceRef);
+ static void Shutdown();
+
private:
~CanvasTranslator();
@@ -333,6 +338,7 @@ class CanvasTranslator final : public gfx::InlineTranslator,
#if defined(XP_WIN)
RefPtr<ID3D11Device> mDevice;
#endif
+ static StaticRefPtr<gfx::SharedContextWebgl> sSharedContext;
RefPtr<gfx::SharedContextWebgl> mSharedContext;
RefPtr<RemoteTextureOwnerClient> mRemoteTextureOwner;
diff --git a/gfx/layers/ipc/CompositorBridgeChild.cpp b/gfx/layers/ipc/CompositorBridgeChild.cpp
index 070e6d673e..83374e3d30 100644
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -18,8 +18,7 @@
#include "mozilla/layers/CanvasChild.h"
#include "mozilla/layers/WebRenderLayerManager.h"
#include "mozilla/layers/PTextureChild.h"
-#include "mozilla/layers/TextureClient.h" // for TextureClient
-#include "mozilla/layers/TextureClientPool.h" // for TextureClientPool
+#include "mozilla/layers/TextureClient.h" // for TextureClient
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/layers/SyncObject.h" // for SyncObjectClient
#include "mozilla/gfx/CanvasManagerChild.h"
@@ -135,10 +134,6 @@ void CompositorBridgeChild::Destroy() {
// happens.
RefPtr<CompositorBridgeChild> selfRef = this;
- for (size_t i = 0; i < mTexturePools.Length(); i++) {
- mTexturePools[i]->Destroy();
- }
-
if (mSectionAllocator) {
delete mSectionAllocator;
mSectionAllocator = nullptr;
@@ -275,9 +270,6 @@ bool CompositorBridgeChild::CompositorIsInGPUProcess() {
mozilla::ipc::IPCResult CompositorBridgeChild::RecvDidComposite(
const LayersId& aId, const nsTArray<TransactionId>& aTransactionIds,
const TimeStamp& aCompositeStart, const TimeStamp& aCompositeEnd) {
- // Hold a reference to keep texture pools alive. See bug 1387799
- const auto texturePools = mTexturePools.Clone();
-
for (const auto& id : aTransactionIds) {
if (mLayerManager) {
MOZ_ASSERT(!aId.IsValid());
@@ -293,10 +285,6 @@ mozilla::ipc::IPCResult CompositorBridgeChild::RecvDidComposite(
}
}
- for (size_t i = 0; i < texturePools.Length(); i++) {
- texturePools[i]->ReturnDeferredClients();
- }
-
return IPC_OK();
}
diff --git a/gfx/layers/ipc/CompositorBridgeChild.h b/gfx/layers/ipc/CompositorBridgeChild.h
index 7e0a4799fe..7ac7ccc197 100644
--- a/gfx/layers/ipc/CompositorBridgeChild.h
+++ b/gfx/layers/ipc/CompositorBridgeChild.h
@@ -45,7 +45,6 @@ class CompositorManagerChild;
class CompositorOptions;
class WebRenderLayerManager;
class TextureClient;
-class TextureClientPool;
struct FrameMetrics;
struct FwdTransactionCounter;
@@ -233,8 +232,6 @@ class CompositorBridgeChild final : public PCompositorBridgeChild,
nsCOMPtr<nsISerialEventTarget> mThread;
- AutoTArray<RefPtr<TextureClientPool>, 2> mTexturePools;
-
uint64_t mProcessToken;
FixedSizeSmallShmemSectionAllocator* mSectionAllocator;
diff --git a/gfx/layers/ipc/CompositorBridgeParent.cpp b/gfx/layers/ipc/CompositorBridgeParent.cpp
index 3982791357..767ea47b2f 100644
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -1777,20 +1777,20 @@ int32_t RecordContentFrameTime(
ContentFrameMarker{});
}
- mozilla::glean::gfx_content_frame_time::from_paint.AccumulateSamples(
- {static_cast<unsigned long long>(fracLatencyNorm)});
+ mozilla::glean::gfx_content_frame_time::from_paint.AccumulateSingleSample(
+ static_cast<unsigned long long>(fracLatencyNorm));
if (!(aTxnId == VsyncId()) && aVsyncStart) {
latencyMs = (aCompositeEnd - aVsyncStart).ToMilliseconds();
latencyNorm = latencyMs / aVsyncRate.ToMilliseconds();
fracLatencyNorm = lround(latencyNorm * 100.0);
int32_t result = fracLatencyNorm;
- mozilla::glean::gfx_content_frame_time::from_vsync.AccumulateSamples(
- {static_cast<unsigned long long>(fracLatencyNorm)});
+ mozilla::glean::gfx_content_frame_time::from_vsync.AccumulateSingleSample(
+ static_cast<unsigned long long>(fracLatencyNorm));
if (aContainsSVGGroup) {
- mozilla::glean::gfx_content_frame_time::with_svg.AccumulateSamples(
- {static_cast<unsigned long long>(fracLatencyNorm)});
+ mozilla::glean::gfx_content_frame_time::with_svg.AccumulateSingleSample(
+ static_cast<unsigned long long>(fracLatencyNorm));
}
// Record CONTENT_FRAME_TIME_REASON.
@@ -1889,8 +1889,8 @@ int32_t RecordContentFrameTime(
fracLatencyNorm = lround(latencyNorm * 100.0);
}
mozilla::glean::gfx_content_frame_time::without_resource_upload
- .AccumulateSamples(
- {static_cast<unsigned long long>(fracLatencyNorm)});
+ .AccumulateSingleSample(
+ static_cast<unsigned long long>(fracLatencyNorm));
if (aStats) {
latencyMs -= (double(aStats->gpu_cache_upload_time) / 1000000.0);
@@ -1898,8 +1898,8 @@ int32_t RecordContentFrameTime(
fracLatencyNorm = lround(latencyNorm * 100.0);
}
mozilla::glean::gfx_content_frame_time::without_resource_upload
- .AccumulateSamples(
- {static_cast<unsigned long long>(fracLatencyNorm)});
+ .AccumulateSingleSample(
+ static_cast<unsigned long long>(fracLatencyNorm));
}
return result;
}
diff --git a/gfx/layers/ipc/LayersMessageUtils.h b/gfx/layers/ipc/LayersMessageUtils.h
index a4e9557ac3..a0da6154d5 100644
--- a/gfx/layers/ipc/LayersMessageUtils.h
+++ b/gfx/layers/ipc/LayersMessageUtils.h
@@ -18,6 +18,7 @@
#include "ipc/IPCMessageUtils.h"
#include "mozilla/ScrollSnapInfo.h"
#include "mozilla/ServoBindings.h"
+#include "mozilla/dom/WebGLIpdl.h"
#include "mozilla/ipc/ByteBuf.h"
#include "mozilla/ipc/ProtocolMessageUtils.h"
#include "mozilla/layers/APZInputBridge.h"
@@ -48,15 +49,11 @@ namespace IPC {
template <>
struct ParamTraits<mozilla::layers::LayersId>
- : public PlainOldDataSerializer<mozilla::layers::LayersId> {};
+ : public ParamTraits_TiedFields<mozilla::layers::LayersId> {};
template <typename T>
struct ParamTraits<mozilla::layers::BaseTransactionId<T>>
- : public PlainOldDataSerializer<mozilla::layers::BaseTransactionId<T>> {};
-
-template <>
-struct ParamTraits<mozilla::VsyncId>
- : public PlainOldDataSerializer<mozilla::VsyncId> {};
+ : public ParamTraits_TiedFields<mozilla::layers::BaseTransactionId<T>> {};
template <>
struct ParamTraits<mozilla::VsyncEvent> {
@@ -419,7 +416,7 @@ struct ParamTraits<mozilla::StyleScrollSnapStop>
template <>
struct ParamTraits<mozilla::ScrollSnapTargetId>
- : public PlainOldDataSerializer<mozilla::ScrollSnapTargetId> {};
+ : public ParamTraits_IsEnumCase<mozilla::ScrollSnapTargetId> {};
template <>
struct ParamTraits<mozilla::SnapPoint> {
@@ -495,26 +492,12 @@ struct ParamTraits<mozilla::ScrollSnapInfo> {
};
template <>
-struct ParamTraits<mozilla::layers::OverscrollBehaviorInfo> {
- // Not using PlainOldDataSerializer so we get enum validation
- // for the members.
-
- typedef mozilla::layers::OverscrollBehaviorInfo paramType;
-
- static void Write(MessageWriter* aWriter, const paramType& aParam) {
- WriteParam(aWriter, aParam.mBehaviorX);
- WriteParam(aWriter, aParam.mBehaviorY);
- }
-
- static bool Read(MessageReader* aReader, paramType* aResult) {
- return (ReadParam(aReader, &aResult->mBehaviorX) &&
- ReadParam(aReader, &aResult->mBehaviorY));
- }
-};
+struct ParamTraits<mozilla::layers::OverscrollBehaviorInfo>
+ : public ParamTraits_TiedFields<mozilla::layers::OverscrollBehaviorInfo> {};
template <typename T>
struct ParamTraits<mozilla::ScrollGeneration<T>>
- : PlainOldDataSerializer<mozilla::ScrollGeneration<T>> {};
+ : public ParamTraits_TiedFields<mozilla::ScrollGeneration<T>> {};
template <>
struct ParamTraits<mozilla::ScrollUpdateType>
diff --git a/gfx/layers/ipc/SharedSurfacesMemoryReport.h b/gfx/layers/ipc/SharedSurfacesMemoryReport.h
index 81baf1349f..31e27bccad 100644
--- a/gfx/layers/ipc/SharedSurfacesMemoryReport.h
+++ b/gfx/layers/ipc/SharedSurfacesMemoryReport.h
@@ -12,6 +12,7 @@
#include "base/process.h"
#include "ipc/IPCMessageUtils.h"
#include "ipc/IPCMessageUtilsSpecializations.h"
+#include "mozilla/dom/WebGLIpdl.h"
#include "mozilla/gfx/Point.h" // for IntSize
namespace mozilla {
@@ -26,8 +27,16 @@ class SharedSurfacesMemoryReport final {
int32_t mStride;
uint32_t mConsumers;
bool mCreatorRef;
+ PaddingField<bool, 3> _padding;
+
+ auto MutTiedFields() {
+ return std::tie(mCreatorPid, mSize, mStride, mConsumers, mCreatorRef,
+ _padding);
+ }
};
+ auto MutTiedFields() { return std::tie(mSurfaces); }
+
std::unordered_map<uint64_t, SurfaceEntry> mSurfaces;
};
@@ -37,21 +46,13 @@ class SharedSurfacesMemoryReport final {
namespace IPC {
template <>
-struct ParamTraits<mozilla::layers::SharedSurfacesMemoryReport> {
- typedef mozilla::layers::SharedSurfacesMemoryReport paramType;
-
- static void Write(MessageWriter* aWriter, const paramType& aParam) {
- WriteParam(aWriter, aParam.mSurfaces);
- }
-
- static bool Read(MessageReader* aReader, paramType* aResult) {
- return ReadParam(aReader, &aResult->mSurfaces);
- }
-};
+struct ParamTraits<mozilla::layers::SharedSurfacesMemoryReport>
+ : public ParamTraits_TiedFields<
+ mozilla::layers::SharedSurfacesMemoryReport> {};
template <>
struct ParamTraits<mozilla::layers::SharedSurfacesMemoryReport::SurfaceEntry>
- : public PlainOldDataSerializer<
+ : public ParamTraits_TiedFields<
mozilla::layers::SharedSurfacesMemoryReport::SurfaceEntry> {};
} // namespace IPC