From def92d1b8e9d373e2f6f27c366d578d97d8960c6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 15 May 2024 05:34:50 +0200 Subject: Merging upstream version 126.0. Signed-off-by: Daniel Baumann --- gfx/layers/ipc/CanvasChild.cpp | 27 ++++++++++-- gfx/layers/ipc/CanvasChild.h | 9 ++-- gfx/layers/ipc/CanvasTranslator.cpp | 66 ++++++++++++++++++++++++++++- gfx/layers/ipc/CanvasTranslator.h | 6 +++ gfx/layers/ipc/CompositorBridgeChild.cpp | 14 +----- gfx/layers/ipc/CompositorBridgeChild.h | 3 -- gfx/layers/ipc/CompositorBridgeParent.cpp | 20 ++++----- gfx/layers/ipc/LayersMessageUtils.h | 31 +++----------- gfx/layers/ipc/SharedSurfacesMemoryReport.h | 25 +++++------ 9 files changed, 131 insertions(+), 70 deletions(-) (limited to 'gfx/layers/ipc') 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 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 mRecorder; RefPtr mDataSourceSurface; bool mDetached = false; + bool mMayInvalidate = false; }; class CanvasDataShmemHolder { @@ -420,6 +431,7 @@ already_AddRefed CanvasChild::CreateDrawTarget( gfx::BackendType::SKIA, gfx::IntSize(1, 1), aFormat); RefPtr dt = MakeAndAddRef( mRecorder, aTextureId, aTextureOwnerId, dummyDt, aSize); + dt->SetOptimizeTransform(true); mTextureInfo.insert({aTextureId, {}}); @@ -483,7 +495,8 @@ int64_t CanvasChild::CreateCheckpoint() { } already_AddRefed 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 CanvasChild::GetDataSurface( gfx::Factory::CreateWrappingDataSourceSurface( shmemPtr, stride, ssSize, ssFormat, ReleaseDataShmemHolder, closure); + aMayInvalidate = true; return dataSurface.forget(); } } @@ -556,6 +570,7 @@ already_AddRefed CanvasChild::GetDataSurface( RefPtr dataSurface = gfx::Factory::CreateWrappingDataSourceSurface( data, stride, ssSize, ssFormat, ReleaseDataShmemHolder, closure); + aMayInvalidate = false; return dataSurface.forget(); } @@ -593,10 +608,14 @@ void CanvasChild::AttachSurface(const RefPtr& aSurface) { } } -void CanvasChild::DetachSurface(const RefPtr& aSurface) { +void CanvasChild::DetachSurface(const RefPtr& aSurface, + bool aInvalidate) { if (auto* surface = static_cast(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& aSurface); + void DetachSurface(const RefPtr& 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 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& aShmem, return true; } +StaticRefPtr 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 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 +CanvasTranslator::LookupSourceSurfaceFromSurfaceDescriptor( + const SurfaceDescriptor& aDesc) { + if (!SDIsNullRemoteDecoder(aDesc)) { + return nullptr; + } + + const auto& sdrd = aDesc.get_SurfaceDescriptorGPUVideo() + .get_SurfaceDescriptorRemoteDecoder(); + RefPtr parent = + VideoBridgeParent::GetSingleton(sdrd.source()); + if (!parent) { + MOZ_ASSERT_UNREACHABLE("unexpected to be called"); + gfxCriticalNote << "TexUnpackSurface failed to get VideoBridgeParent"; + return nullptr; + } + RefPtr texture = + parent->LookupTexture(mContentId, sdrd.handle()); + if (!texture) { + MOZ_ASSERT_UNREACHABLE("unexpected to be called"); + gfxCriticalNote << "TexUnpackSurface failed to get TextureHost"; + return nullptr; + } + + RefPtr 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 LookupExternalSurface( uint64_t aKey) final; + already_AddRefed 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 mDevice; #endif + static StaticRefPtr sSharedContext; RefPtr mSharedContext; RefPtr 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 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& 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 mThread; - AutoTArray, 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(fracLatencyNorm)}); + mozilla::glean::gfx_content_frame_time::from_paint.AccumulateSingleSample( + static_cast(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(fracLatencyNorm)}); + mozilla::glean::gfx_content_frame_time::from_vsync.AccumulateSingleSample( + static_cast(fracLatencyNorm)); if (aContainsSVGGroup) { - mozilla::glean::gfx_content_frame_time::with_svg.AccumulateSamples( - {static_cast(fracLatencyNorm)}); + mozilla::glean::gfx_content_frame_time::with_svg.AccumulateSingleSample( + static_cast(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(fracLatencyNorm)}); + .AccumulateSingleSample( + static_cast(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(fracLatencyNorm)}); + .AccumulateSingleSample( + static_cast(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 - : public PlainOldDataSerializer {}; + : public ParamTraits_TiedFields {}; template struct ParamTraits> - : public PlainOldDataSerializer> {}; - -template <> -struct ParamTraits - : public PlainOldDataSerializer {}; + : public ParamTraits_TiedFields> {}; template <> struct ParamTraits { @@ -419,7 +416,7 @@ struct ParamTraits template <> struct ParamTraits - : public PlainOldDataSerializer {}; + : public ParamTraits_IsEnumCase {}; template <> struct ParamTraits { @@ -495,26 +492,12 @@ struct ParamTraits { }; template <> -struct ParamTraits { - // 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 + : public ParamTraits_TiedFields {}; template struct ParamTraits> - : PlainOldDataSerializer> {}; + : public ParamTraits_TiedFields> {}; template <> struct ParamTraits 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 _padding; + + auto MutTiedFields() { + return std::tie(mCreatorPid, mSize, mStride, mConsumers, mCreatorRef, + _padding); + } }; + auto MutTiedFields() { return std::tie(mSurfaces); } + std::unordered_map mSurfaces; }; @@ -37,21 +46,13 @@ class SharedSurfacesMemoryReport final { namespace IPC { template <> -struct ParamTraits { - 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 + : public ParamTraits_TiedFields< + mozilla::layers::SharedSurfacesMemoryReport> {}; template <> struct ParamTraits - : public PlainOldDataSerializer< + : public ParamTraits_TiedFields< mozilla::layers::SharedSurfacesMemoryReport::SurfaceEntry> {}; } // namespace IPC -- cgit v1.2.3