From fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:14:29 +0200 Subject: Merging upstream version 125.0.1. Signed-off-by: Daniel Baumann --- gfx/layers/ipc/CanvasChild.cpp | 164 ++++++++++++++++++++++++------ gfx/layers/ipc/CanvasChild.h | 20 ++-- gfx/layers/ipc/CanvasTranslator.cpp | 32 ++++-- gfx/layers/ipc/CanvasTranslator.h | 3 + gfx/layers/ipc/CompositorManagerChild.cpp | 11 +- gfx/layers/ipc/LayersMessageUtils.h | 2 +- gfx/layers/ipc/PCanvas.ipdl | 6 +- gfx/layers/ipc/VideoBridgeParent.cpp | 5 +- 8 files changed, 185 insertions(+), 58 deletions(-) (limited to 'gfx/layers/ipc') diff --git a/gfx/layers/ipc/CanvasChild.cpp b/gfx/layers/ipc/CanvasChild.cpp index 553217d82b..515463cd8e 100644 --- a/gfx/layers/ipc/CanvasChild.cpp +++ b/gfx/layers/ipc/CanvasChild.cpp @@ -7,6 +7,9 @@ #include "CanvasChild.h" #include "MainThreadUtils.h" +#include "mozilla/dom/WorkerPrivate.h" +#include "mozilla/dom/WorkerRef.h" +#include "mozilla/dom/WorkerRunnable.h" #include "mozilla/gfx/CanvasManagerChild.h" #include "mozilla/gfx/DrawTargetRecording.h" #include "mozilla/gfx/Tools.h" @@ -18,6 +21,7 @@ #include "mozilla/layers/ImageDataSerializer.h" #include "mozilla/layers/SourceSurfaceSharedData.h" #include "mozilla/Maybe.h" +#include "mozilla/Mutex.h" #include "nsIObserverService.h" #include "RecordedCanvasEventImpl.h" @@ -33,9 +37,9 @@ class RecorderHelpers final : public CanvasDrawEventRecorder::Helpers { ~RecorderHelpers() override = default; - bool InitTranslator(TextureType aTextureType, gfx::BackendType aBackendType, - Handle&& aReadHandle, nsTArray&& aBufferHandles, - uint64_t aBufferSize, + bool InitTranslator(TextureType aTextureType, TextureType aWebglTextureType, + gfx::BackendType aBackendType, Handle&& aReadHandle, + nsTArray&& aBufferHandles, uint64_t aBufferSize, CrossProcessSemaphoreHandle&& aReaderSem, CrossProcessSemaphoreHandle&& aWriterSem) override { NS_ASSERT_OWNINGTHREAD(RecorderHelpers); @@ -43,7 +47,7 @@ class RecorderHelpers final : public CanvasDrawEventRecorder::Helpers { return false; } return mCanvasChild->SendInitTranslator( - aTextureType, aBackendType, std::move(aReadHandle), + aTextureType, aWebglTextureType, aBackendType, std::move(aReadHandle), std::move(aBufferHandles), aBufferSize, std::move(aReaderSem), std::move(aWriterSem)); } @@ -165,9 +169,104 @@ class SourceSurfaceCanvasRecording final : public gfx::SourceSurface { bool mDetached = false; }; -CanvasChild::CanvasChild() = default; +class CanvasDataShmemHolder { + public: + CanvasDataShmemHolder(ipc::SharedMemoryBasic* aShmem, + CanvasChild* aCanvasChild) + : mMutex("CanvasChild::DataShmemHolder::mMutex"), + mShmem(aShmem), + mCanvasChild(aCanvasChild) {} + + bool Init(dom::ThreadSafeWorkerRef* aWorkerRef) { + if (!aWorkerRef) { + return true; + } -CanvasChild::~CanvasChild() = default; + RefPtr workerRef = dom::StrongWorkerRef::Create( + aWorkerRef->Private(), "CanvasChild::DataShmemHolder", + [this]() { DestroyWorker(); }); + if (NS_WARN_IF(!workerRef)) { + return false; + } + + MutexAutoLock lock(mMutex); + mWorkerRef = new dom::ThreadSafeWorkerRef(workerRef); + return true; + } + + void Destroy() { + class DestroyRunnable final : public dom::WorkerRunnable { + public: + DestroyRunnable(dom::WorkerPrivate* aWorkerPrivate, + CanvasDataShmemHolder* aShmemHolder) + : dom::WorkerRunnable(aWorkerPrivate, + "CanvasDataShmemHolder::Destroy", + dom::WorkerRunnable::WorkerThread), + mShmemHolder(aShmemHolder) {} + + bool WorkerRun(JSContext* aCx, + dom::WorkerPrivate* aWorkerPrivate) override { + mShmemHolder->Destroy(); + return true; + } + + void PostRun(JSContext* aCx, dom::WorkerPrivate* aWorkerPrivate, + bool aRunResult) override {} + + bool PreDispatch(dom::WorkerPrivate* aWorkerPrivate) override { + return true; + } + + void PostDispatch(dom::WorkerPrivate* aWorkerPrivate, + bool aDispatchResult) override {} + + private: + CanvasDataShmemHolder* mShmemHolder; + }; + + mMutex.Lock(); + + if (mCanvasChild) { + if (mWorkerRef) { + if (!mWorkerRef->Private()->IsOnCurrentThread()) { + auto task = MakeRefPtr(mWorkerRef->Private(), this); + mMutex.Unlock(); + task->Dispatch(); + return; + } + } else if (!NS_IsMainThread()) { + mMutex.Unlock(); + NS_DispatchToMainThread(NS_NewRunnableFunction( + "CanvasDataShmemHolder::Destroy", [this]() { Destroy(); })); + return; + } + + mCanvasChild->ReturnDataSurfaceShmem(mShmem.forget()); + mCanvasChild = nullptr; + mWorkerRef = nullptr; + } + + mMutex.Unlock(); + delete this; + } + + void DestroyWorker() { + MutexAutoLock lock(mMutex); + mCanvasChild = nullptr; + mWorkerRef = nullptr; + } + + private: + Mutex mMutex; + RefPtr mShmem; + RefPtr mCanvasChild MOZ_GUARDED_BY(mMutex); + RefPtr mWorkerRef MOZ_GUARDED_BY(mMutex); +}; + +CanvasChild::CanvasChild(dom::ThreadSafeWorkerRef* aWorkerRef) + : mWorkerRef(aWorkerRef) {} + +CanvasChild::~CanvasChild() { MOZ_ASSERT(!mWorkerRef); } static void NotifyCanvasDeviceReset() { nsCOMPtr obs = services::GetObserverService(); @@ -207,14 +306,15 @@ ipc::IPCResult CanvasChild::RecvBlockCanvas() { } void CanvasChild::EnsureRecorder(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, - TextureType aTextureType) { + TextureType aTextureType, + TextureType aWebglTextureType) { NS_ASSERT_OWNINGTHREAD(CanvasChild); if (!mRecorder) { gfx::BackendType backendType = gfxPlatform::GetPlatform()->GetPreferredCanvasBackend(); - auto recorder = MakeRefPtr(); - if (!recorder->Init(aTextureType, backendType, + auto recorder = MakeRefPtr(mWorkerRef); + if (!recorder->Init(aTextureType, aWebglTextureType, backendType, MakeUnique(this))) { return; } @@ -242,6 +342,8 @@ void CanvasChild::Destroy() { if (CanSend()) { Send__delete__(this); } + + mWorkerRef = nullptr; } bool CanvasChild::EnsureBeginTransaction() { @@ -397,6 +499,10 @@ already_AddRefed CanvasChild::GetDataSurface( return nullptr; } + gfx::IntSize ssSize = aSurface->GetSize(); + gfx::SurfaceFormat ssFormat = aSurface->GetFormat(); + auto stride = ImageDataSerializer::ComputeRGBStride(ssFormat, ssSize.width); + // Shmem is only valid if the surface is the latest snapshot (not detached). if (!aDetached) { // If there is a shmem associated with this snapshot id, then we want to try @@ -411,20 +517,22 @@ already_AddRefed CanvasChild::GetDataSurface( if (NS_WARN_IF(!mRecorder->WaitForCheckpoint(checkpoint))) { return nullptr; } - gfx::IntSize size = aSurface->GetSize(); - gfx::SurfaceFormat format = aSurface->GetFormat(); - auto stride = ImageDataSerializer::ComputeRGBStride(format, size.width); + auto* closure = + new CanvasDataShmemHolder(it->second.mSnapshotShmem, this); + if (NS_WARN_IF(!closure->Init(mWorkerRef))) { + delete closure; + return nullptr; + } RefPtr dataSurface = - gfx::Factory::CreateWrappingDataSourceSurface(shmemPtr, stride, size, - format); + gfx::Factory::CreateWrappingDataSourceSurface( + shmemPtr, stride, ssSize, ssFormat, ReleaseDataShmemHolder, + closure); return dataSurface.forget(); } } RecordEvent(RecordedPrepareDataForSurface(aSurface)); - gfx::IntSize ssSize = aSurface->GetSize(); - gfx::SurfaceFormat ssFormat = aSurface->GetFormat(); if (!EnsureDataSurfaceShmem(ssSize, ssFormat)) { return nullptr; } @@ -435,15 +543,15 @@ already_AddRefed CanvasChild::GetDataSurface( return nullptr; } + auto* closure = new CanvasDataShmemHolder(mDataSurfaceShmem, this); + if (NS_WARN_IF(!closure->Init(mWorkerRef))) { + delete closure; + return nullptr; + } + mDataSurfaceShmemAvailable = false; - struct DataShmemHolder { - RefPtr shmem; - RefPtr canvasChild; - }; auto* data = static_cast(mDataSurfaceShmem->memory()); - auto* closure = new DataShmemHolder{do_AddRef(mDataSurfaceShmem), this}; - auto stride = ImageDataSerializer::ComputeRGBStride(ssFormat, ssSize.width); RefPtr dataSurface = gfx::Factory::CreateWrappingDataSourceSurface( @@ -452,16 +560,8 @@ already_AddRefed CanvasChild::GetDataSurface( } /* static */ void CanvasChild::ReleaseDataShmemHolder(void* aClosure) { - if (!NS_IsMainThread()) { - NS_DispatchToMainThread(NS_NewRunnableFunction( - "CanvasChild::ReleaseDataShmemHolder", - [aClosure]() { ReleaseDataShmemHolder(aClosure); })); - return; - } - - auto* shmemHolder = static_cast(aClosure); - shmemHolder->canvasChild->ReturnDataSurfaceShmem(shmemHolder->shmem.forget()); - delete shmemHolder; + auto* shmemHolder = static_cast(aClosure); + shmemHolder->Destroy(); } already_AddRefed CanvasChild::WrapSurface( diff --git a/gfx/layers/ipc/CanvasChild.h b/gfx/layers/ipc/CanvasChild.h index c99fe50bfb..e22109f406 100644 --- a/gfx/layers/ipc/CanvasChild.h +++ b/gfx/layers/ipc/CanvasChild.h @@ -15,6 +15,10 @@ namespace mozilla { +namespace dom { +class ThreadSafeWorkerRef; +} + namespace gfx { class DrawTargetRecording; class SourceSurface; @@ -28,7 +32,7 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr { public: NS_INLINE_DECL_REFCOUNTING(CanvasChild) - CanvasChild(); + explicit CanvasChild(dom::ThreadSafeWorkerRef* aWorkerRef); /** * @returns true if remote canvas has been deactivated due to failure. @@ -58,7 +62,7 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr { * @params aTextureType the TextureType to create in the CanvasTranslator. */ void EnsureRecorder(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, - TextureType aTextureType); + TextureType aTextureType, TextureType aWebglTextureType); /** * Clean up IPDL actor. @@ -147,6 +151,9 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr { void CleanupTexture(int64_t aTextureId); + void ReturnDataSurfaceShmem( + already_AddRefed aDataSurfaceShmem); + protected: void ActorDestroy(ActorDestroyReason aWhy) final; @@ -157,14 +164,6 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr { bool EnsureDataSurfaceShmem(gfx::IntSize aSize, gfx::SurfaceFormat aFormat); - void ReturnDataSurfaceShmem( - already_AddRefed aDataSurfaceShmem); - - struct DataShmemHolder { - RefPtr shmem; - RefPtr canvasChild; - }; - static void ReleaseDataShmemHolder(void* aClosure); void DropFreeBuffersWhenDormant(); @@ -173,6 +172,7 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr { static bool mDeactivated; + RefPtr mWorkerRef; RefPtr mRecorder; RefPtr mDataSurfaceShmem; diff --git a/gfx/layers/ipc/CanvasTranslator.cpp b/gfx/layers/ipc/CanvasTranslator.cpp index 08150d6952..4a184f48d8 100644 --- a/gfx/layers/ipc/CanvasTranslator.cpp +++ b/gfx/layers/ipc/CanvasTranslator.cpp @@ -13,6 +13,7 @@ #include "mozilla/gfx/DrawTargetWebgl.h" #include "mozilla/gfx/gfxVars.h" #include "mozilla/gfx/GPUParent.h" +#include "mozilla/gfx/GPUProcessManager.h" #include "mozilla/gfx/Logging.h" #include "mozilla/ipc/Endpoint.h" #include "mozilla/layers/BufferTexture.h" @@ -131,15 +132,17 @@ bool CanvasTranslator::EnsureSharedContextWebgl() { } mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator( - TextureType aTextureType, gfx::BackendType aBackendType, - Handle&& aReadHandle, nsTArray&& aBufferHandles, - uint64_t aBufferSize, CrossProcessSemaphoreHandle&& aReaderSem, + TextureType aTextureType, TextureType aWebglTextureType, + gfx::BackendType aBackendType, Handle&& aReadHandle, + nsTArray&& aBufferHandles, uint64_t aBufferSize, + CrossProcessSemaphoreHandle&& aReaderSem, CrossProcessSemaphoreHandle&& aWriterSem) { if (mHeaderShmem) { return IPC_FAIL(this, "RecvInitTranslator called twice."); } mTextureType = aTextureType; + mWebglTextureType = aWebglTextureType; mBackendType = aBackendType; mOtherPid = OtherPid(); @@ -637,7 +640,11 @@ bool CanvasTranslator::HandleExtensionEvent(int32_t aType) { } } -void CanvasTranslator::BeginTransaction() { mIsInTransaction = true; } +void CanvasTranslator::BeginTransaction() { + PROFILER_MARKER_TEXT("CanvasTranslator", GRAPHICS, {}, + "CanvasTranslator::BeginTransaction"_ns); + mIsInTransaction = true; +} void CanvasTranslator::Flush() { #if defined(XP_WIN) @@ -728,9 +735,15 @@ bool CanvasTranslator::CheckForFreshCanvasDevice(int aLineNumber) { NotifyDeviceChanged(); } - RefPtr runnable = NS_NewRunnableFunction( - "CanvasTranslator NotifyDeviceReset", - []() { gfx::GPUParent::GetSingleton()->NotifyDeviceReset(); }); + RefPtr runnable = + NS_NewRunnableFunction("CanvasTranslator NotifyDeviceReset", []() { + if (XRE_IsGPUProcess()) { + gfx::GPUParent::GetSingleton()->NotifyDeviceReset(); + } else { + gfx::GPUProcessManager::Get()->OnInProcessDeviceReset( + /* aTrackThreshold */ false); + } + }); // It is safe to wait here because only the Compositor thread waits on us and // the main thread doesn't wait on the compositor thread in the GPU process. @@ -1025,6 +1038,8 @@ bool CanvasTranslator::UnlockTexture(int64_t aTextureId) { } bool CanvasTranslator::PresentTexture(int64_t aTextureId, RemoteTextureId aId) { + AUTO_PROFILER_MARKER_TEXT("CanvasTranslator", GRAPHICS, {}, + "CanvasTranslator::PresentTexture"_ns); auto result = mTextureInfo.find(aTextureId); if (result == mTextureInfo.end()) { return false; @@ -1033,7 +1048,8 @@ bool CanvasTranslator::PresentTexture(int64_t aTextureId, RemoteTextureId aId) { RemoteTextureOwnerId ownerId = info.mRemoteTextureOwnerId; if (gfx::DrawTargetWebgl* webgl = info.GetDrawTargetWebgl()) { EnsureRemoteTextureOwner(ownerId); - if (webgl->CopyToSwapChain(aId, ownerId, mRemoteTextureOwner)) { + if (webgl->CopyToSwapChain(mWebglTextureType, aId, ownerId, + mRemoteTextureOwner)) { return true; } if (mSharedContext && mSharedContext->IsContextLost()) { diff --git a/gfx/layers/ipc/CanvasTranslator.h b/gfx/layers/ipc/CanvasTranslator.h index cf87b7ab53..5258e0c529 100644 --- a/gfx/layers/ipc/CanvasTranslator.h +++ b/gfx/layers/ipc/CanvasTranslator.h @@ -69,6 +69,7 @@ class CanvasTranslator final : public gfx::InlineTranslator, * CanvasEventRingBuffer. * * @param aTextureType the TextureType the translator will create + * @param aWebglTextureType the TextureType of any WebGL buffers * @param aBackendType the BackendType for texture data * @param aHeaderHandle handle for the control header * @param aBufferHandles handles for the initial buffers for translation @@ -77,6 +78,7 @@ class CanvasTranslator final : public gfx::InlineTranslator, * @param aWriterSem writing blocked semaphore for the CanvasEventRingBuffer */ ipc::IPCResult RecvInitTranslator(TextureType aTextureType, + TextureType aWebglTextureType, gfx::BackendType aBackendType, Handle&& aReadHandle, nsTArray&& aBufferHandles, @@ -358,6 +360,7 @@ class CanvasTranslator final : public gfx::InlineTranslator, UniquePtr mWriterSemaphore; UniquePtr mReaderSemaphore; TextureType mTextureType = TextureType::Unknown; + TextureType mWebglTextureType = TextureType::Unknown; UniquePtr mReferenceTextureData; dom::ContentParentId mContentId; uint32_t mManagerId; diff --git a/gfx/layers/ipc/CompositorManagerChild.cpp b/gfx/layers/ipc/CompositorManagerChild.cpp index 0e553745d3..8d89339373 100644 --- a/gfx/layers/ipc/CompositorManagerChild.cpp +++ b/gfx/layers/ipc/CompositorManagerChild.cpp @@ -10,6 +10,7 @@ #include "mozilla/layers/CompositorBridgeChild.h" #include "mozilla/layers/CompositorManagerParent.h" #include "mozilla/layers/CompositorThread.h" +#include "mozilla/gfx/CanvasShutdownManager.h" #include "mozilla/gfx/gfxVars.h" #include "mozilla/gfx/GPUProcessManager.h" #include "mozilla/dom/ContentChild.h" // for ContentChild @@ -67,7 +68,15 @@ bool CompositorManagerChild::Init(Endpoint&& aEndpoint, sInstance = new CompositorManagerChild(std::move(aEndpoint), aProcessToken, aNamespace); sOtherPid = sInstance->OtherPid(); - return sInstance->CanSend(); + if (!sInstance->CanSend()) { + return false; + } + + // If there are any canvases waiting on the recreation of the GPUProcess or + // CompositorManagerChild, then we need to notify them so that they can + // restore their contexts. + gfx::CanvasShutdownManager::OnCompositorManagerRestored(); + return true; } /* static */ diff --git a/gfx/layers/ipc/LayersMessageUtils.h b/gfx/layers/ipc/LayersMessageUtils.h index d869d4ed83..a4e9557ac3 100644 --- a/gfx/layers/ipc/LayersMessageUtils.h +++ b/gfx/layers/ipc/LayersMessageUtils.h @@ -520,7 +520,7 @@ template <> struct ParamTraits : public ContiguousEnumSerializerInclusive< mozilla::ScrollUpdateType, mozilla::ScrollUpdateType::Absolute, - mozilla::ScrollUpdateType::MergeableAbsolute> {}; + mozilla::ScrollUpdateType::PureRelative> {}; template <> struct ParamTraits diff --git a/gfx/layers/ipc/PCanvas.ipdl b/gfx/layers/ipc/PCanvas.ipdl index 5187e61d23..59896b72cf 100644 --- a/gfx/layers/ipc/PCanvas.ipdl +++ b/gfx/layers/ipc/PCanvas.ipdl @@ -32,9 +32,9 @@ parent: * each aBufferHandles' memory and the default size. aReaderSem and aWriterSem * are handles for the semaphores to handle waiting on either side. */ - async InitTranslator(TextureType aTextureType, BackendType aBackendType, - Handle aHeaderHandle, Handle[] aBufferHandles, - uint64_t aBufferSize, + async InitTranslator(TextureType aTextureType, TextureType aWebglTextureType, + BackendType aBackendType, Handle aHeaderHandle, + Handle[] aBufferHandles, uint64_t aBufferSize, CrossProcessSemaphoreHandle aReaderSem, CrossProcessSemaphoreHandle aWriterSem); diff --git a/gfx/layers/ipc/VideoBridgeParent.cpp b/gfx/layers/ipc/VideoBridgeParent.cpp index 6413c27bc1..50f0549e50 100644 --- a/gfx/layers/ipc/VideoBridgeParent.cpp +++ b/gfx/layers/ipc/VideoBridgeParent.cpp @@ -17,9 +17,8 @@ namespace mozilla::layers { using namespace mozilla::ipc; using namespace mozilla::gfx; -using VideoBridgeTable = - EnumeratedArray; +using VideoBridgeTable = EnumeratedArray; static StaticDataMutex sVideoBridgeFromProcess( "VideoBridges"); -- cgit v1.2.3