From cb3c42a74878ccfd614f7db51875607b27471f61 Mon Sep 17 00:00:00 2001 From: Cosmin Sabou Date: Tue, 19 Mar 2024 09:42:20 +0200 Subject: [PATCH] Backed out changeset 0e250e45603a (bug 1886022) for causing build bustages on CanvasShutdownManager. CLOSED TREE --- dom/canvas/CanvasRenderingContext2D.cpp | 53 +++++++++++- dom/canvas/CanvasRenderingContext2D.h | 1 + gfx/ipc/CanvasManagerChild.cpp | 57 ++++++++++--- gfx/ipc/CanvasManagerChild.h | 8 +- gfx/ipc/CanvasShutdownManager.cpp | 108 ------------------------ gfx/ipc/CanvasShutdownManager.h | 45 ---------- gfx/ipc/moz.build | 2 - gfx/thebes/gfxPlatform.cpp | 6 +- 8 files changed, 105 insertions(+), 175 deletions(-) delete mode 100644 gfx/ipc/CanvasShutdownManager.cpp delete mode 100644 gfx/ipc/CanvasShutdownManager.h diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index 4ad484ec8a0b..4c7d5169685b 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -24,7 +24,7 @@ #include "mozilla/dom/HTMLCanvasElement.h" #include "mozilla/dom/GeneratePlaceholderCanvasData.h" #include "mozilla/dom/VideoFrame.h" -#include "mozilla/gfx/CanvasShutdownManager.h" +#include "mozilla/gfx/CanvasManagerChild.h" #include "nsPresContext.h" #include "nsIInterfaceRequestorUtils.h" @@ -872,6 +872,41 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CanvasGradient, mContext) NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CanvasPattern, mContext) +class CanvasShutdownObserver final : public nsIObserver { + public: + explicit CanvasShutdownObserver(CanvasRenderingContext2D* aCanvas) + : mCanvas(aCanvas) {} + + void OnShutdown() { + if (!mCanvas) { + return; + } + + mCanvas = nullptr; + nsContentUtils::UnregisterShutdownObserver(this); + } + + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + private: + ~CanvasShutdownObserver() = default; + + CanvasRenderingContext2D* mCanvas; +}; + +NS_IMPL_ISUPPORTS(CanvasShutdownObserver, nsIObserver) + +NS_IMETHODIMP +CanvasShutdownObserver::Observe(nsISupports* aSubject, const char* aTopic, + const char16_t* aData) { + if (mCanvas && strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) { + mCanvas->OnShutdown(); + OnShutdown(); + } + + return NS_OK; +} + NS_IMPL_CYCLE_COLLECTING_ADDREF(CanvasRenderingContext2D) NS_IMPL_CYCLE_COLLECTING_RELEASE(CanvasRenderingContext2D) @@ -1208,8 +1243,14 @@ void CanvasRenderingContext2D::OnShutdown() { } bool CanvasRenderingContext2D::AddShutdownObserver() { - auto* const canvasManager = CanvasShutdownManager::Get(); + auto* const canvasManager = CanvasManagerChild::Get(); if (NS_WARN_IF(!canvasManager)) { + if (NS_IsMainThread()) { + mShutdownObserver = new CanvasShutdownObserver(this); + nsContentUtils::RegisterShutdownObserver(mShutdownObserver); + return true; + } + mHasShutdown = true; return false; } @@ -1219,7 +1260,13 @@ bool CanvasRenderingContext2D::AddShutdownObserver() { } void CanvasRenderingContext2D::RemoveShutdownObserver() { - auto* const canvasManager = CanvasShutdownManager::MaybeGet(); + if (mShutdownObserver) { + mShutdownObserver->OnShutdown(); + mShutdownObserver = nullptr; + return; + } + + auto* const canvasManager = CanvasManagerChild::MaybeGet(); if (!canvasManager) { return; } diff --git a/dom/canvas/CanvasRenderingContext2D.h b/dom/canvas/CanvasRenderingContext2D.h index c42a94778ac3..6efa87c490b2 100644 --- a/dom/canvas/CanvasRenderingContext2D.h +++ b/dom/canvas/CanvasRenderingContext2D.h @@ -846,6 +846,7 @@ class CanvasRenderingContext2D : public nsICanvasRenderingContextInternal, // Whether or not we have already shutdown. bool mHasShutdown = false; + RefPtr mShutdownObserver; bool AddShutdownObserver(); void RemoveShutdownObserver(); bool AlreadyShutDown() const { return mHasShutdown; } diff --git a/gfx/ipc/CanvasManagerChild.cpp b/gfx/ipc/CanvasManagerChild.cpp index 493fde1013c6..4e9e2e6acfdc 100644 --- a/gfx/ipc/CanvasManagerChild.cpp +++ b/gfx/ipc/CanvasManagerChild.cpp @@ -10,7 +10,6 @@ #include "mozilla/dom/WorkerPrivate.h" #include "mozilla/dom/WorkerRef.h" #include "mozilla/gfx/2D.h" -#include "mozilla/gfx/CanvasShutdownManager.h" #include "mozilla/gfx/Swizzle.h" #include "mozilla/ipc/Endpoint.h" #include "mozilla/layers/ActiveResource.h" @@ -31,10 +30,7 @@ MOZ_THREAD_LOCAL(CanvasManagerChild*) CanvasManagerChild::sLocalManager; Atomic CanvasManagerChild::sNextId(1); -CanvasManagerChild::CanvasManagerChild(ThreadSafeWorkerRef* aWorkerRef, - uint32_t aId) - : mWorkerRef(aWorkerRef), mId(aId) {} - +CanvasManagerChild::CanvasManagerChild(uint32_t aId) : mId(aId) {} CanvasManagerChild::~CanvasManagerChild() = default; void CanvasManagerChild::ActorDestroy(ActorDestroyReason aReason) { @@ -46,6 +42,11 @@ void CanvasManagerChild::ActorDestroy(ActorDestroyReason aReason) { } void CanvasManagerChild::DestroyInternal() { + std::set activeCanvas = std::move(mActiveCanvas); + for (const auto& i : activeCanvas) { + i->OnShutdown(); + } + if (mActiveResourceTracker) { mActiveResourceTracker->AgeAllGenerations(); mActiveResourceTracker.reset(); @@ -66,6 +67,12 @@ void CanvasManagerChild::Destroy() { } /* static */ void CanvasManagerChild::Shutdown() { + MOZ_ASSERT(NS_IsMainThread()); + + // The worker threads should destroy their own CanvasManagerChild instances + // during their shutdown sequence. We just need to take care of the main + // thread. We need to init here because we may have never created a + // CanvasManagerChild for the main thread in the first place. if (sLocalManager.init()) { RefPtr manager = sLocalManager.get(); if (manager) { @@ -96,11 +103,6 @@ void CanvasManagerChild::Destroy() { return managerWeak; } - auto* shutdownManager = CanvasShutdownManager::Get(); - if (NS_WARN_IF(!shutdownManager)) { - return nullptr; - } - // We are only used on the main thread, or on worker threads. WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT_IF(!worker, NS_IsMainThread()); @@ -119,8 +121,29 @@ void CanvasManagerChild::Destroy() { return nullptr; } - auto manager = MakeRefPtr(shutdownManager->GetWorkerRef(), - sNextId++); + auto manager = MakeRefPtr(sNextId++); + + if (worker) { + // The ThreadSafeWorkerRef will let us know when the worker is shutting + // down. This will let us clear our threadlocal reference and close the + // actor. We rely upon an explicit shutdown for the main thread. + RefPtr workerRef = StrongWorkerRef::Create( + worker, "CanvasManager", [manager]() { manager->Destroy(); }); + if (NS_WARN_IF(!workerRef)) { + return nullptr; + } + + manager->mWorkerRef = new ThreadSafeWorkerRef(workerRef); + } else if (NS_IsMainThread()) { + if (NS_WARN_IF( + AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed))) { + return nullptr; + } + } else { + MOZ_ASSERT_UNREACHABLE("Can only be used on main or DOM worker threads!"); + return nullptr; + } + if (NS_WARN_IF(!childEndpoint.Bind(manager))) { return nullptr; } @@ -152,6 +175,16 @@ void CanvasManagerChild::Destroy() { return sLocalManager.get(); } +void CanvasManagerChild::AddShutdownObserver( + dom::CanvasRenderingContext2D* aCanvas) { + mActiveCanvas.insert(aCanvas); +} + +void CanvasManagerChild::RemoveShutdownObserver( + dom::CanvasRenderingContext2D* aCanvas) { + mActiveCanvas.erase(aCanvas); +} + void CanvasManagerChild::EndCanvasTransaction() { if (!mCanvasChild) { return; diff --git a/gfx/ipc/CanvasManagerChild.h b/gfx/ipc/CanvasManagerChild.h index c59ba7c50201..6369d87ada7a 100644 --- a/gfx/ipc/CanvasManagerChild.h +++ b/gfx/ipc/CanvasManagerChild.h @@ -10,6 +10,7 @@ #include "mozilla/gfx/PCanvasManagerChild.h" #include "mozilla/gfx/Types.h" #include "mozilla/ThreadLocal.h" +#include namespace mozilla { namespace dom { @@ -34,8 +35,7 @@ class CanvasManagerChild final : public PCanvasManagerChild { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CanvasManagerChild, override); - explicit CanvasManagerChild(dom::ThreadSafeWorkerRef* aWorkerRef, - uint32_t aId); + explicit CanvasManagerChild(uint32_t aId); uint32_t Id() const { return mId; } already_AddRefed GetSnapshot( uint32_t aManagerId, int32_t aProtocolId, @@ -49,6 +49,9 @@ class CanvasManagerChild final : public PCanvasManagerChild { static bool CreateParent( mozilla::ipc::Endpoint&& aEndpoint); + void AddShutdownObserver(dom::CanvasRenderingContext2D* aCanvas); + void RemoveShutdownObserver(dom::CanvasRenderingContext2D* aCanvas); + bool IsCanvasActive() { return mActive; } void EndCanvasTransaction(); void ClearCachedResources(); @@ -70,6 +73,7 @@ class CanvasManagerChild final : public PCanvasManagerChild { RefPtr mCanvasChild; RefPtr mWebGPUChild; UniquePtr mActiveResourceTracker; + std::set mActiveCanvas; const uint32_t mId; bool mActive = true; bool mBlocked = false; diff --git a/gfx/ipc/CanvasShutdownManager.cpp b/gfx/ipc/CanvasShutdownManager.cpp deleted file mode 100644 index 68839582469f..000000000000 --- a/gfx/ipc/CanvasShutdownManager.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "CanvasShutdownManager.h" -#include "mozilla/AppShutdown.h" -#include "mozilla/dom/CanvasRenderingContext2D.h" -#include "mozilla/dom/WorkerPrivate.h" -#include "mozilla/dom/WorkerRef.h" -#include "mozilla/gfx/CanvasManagerChild.h" - -using namespace mozilla::dom; - -namespace mozilla::gfx { - -// The owning thread will tell us to close when it is shutdown, either via -// CanvasShutdownManager::Shutdown for the main thread, or via a shutdown -// callback from ThreadSafeWorkerRef for worker threads. -MOZ_THREAD_LOCAL(CanvasShutdownManager*) CanvasShutdownManager::sLocalManager; - -CanvasShutdownManager::CanvasShutdownManager(StrongWorkerRef* aWorkerRef) - : mWorkerRef(new ThreadSafeWorkerRef(aWorkerRef)) {} - -CanvasShutdownManager::CanvasShutdownManager() = default; -CanvasShutdownManager::~CanvasShutdownManager() = default; - -void CanvasShutdownManager::Destroy() { - std::set activeCanvas = std::move(mActiveCanvas); - for (const auto& i : activeCanvas) { - i->OnShutdown(); - } - - CanvasManagerChild::Shutdown(); - mWorkerRef = nullptr; -} - -/* static */ void CanvasShutdownManager::Shutdown() { - auto* manager = MaybeGet(); - if (!manager) { - return; - } - - sLocalManager.set(nullptr); - manager->Destroy(); - delete manager; -} - -/* static */ CanvasShutdownManager* CanvasShutdownManager::MaybeGet() { - if (NS_WARN_IF(!sLocalManager.init())) { - return nullptr; - } - - return sLocalManager.get(); -} - -/* static */ CanvasShutdownManager* CanvasShutdownManager::Get() { - if (NS_WARN_IF(!sLocalManager.init())) { - return nullptr; - } - - CanvasShutdownManager* managerWeak = sLocalManager.get(); - if (managerWeak) { - return managerWeak; - } - - if (WorkerPrivate* worker = GetCurrentThreadWorkerPrivate()) { - // The ThreadSafeWorkerRef will let us know when the worker is shutting - // down. This will let us clear our threadlocal reference and close the - // actor. We rely upon an explicit shutdown for the main thread. - RefPtr workerRef = StrongWorkerRef::Create( - worker, "CanvasShutdownManager", []() { Shutdown(); }); - if (NS_WARN_IF(!workerRef)) { - return nullptr; - } - - CanvasShutdownManager* manager = new CanvasShutdownManager(workerRef); - sLocalManager.set(manager); - return manager; - } - - if (NS_IsMainThread()) { - if (NS_WARN_IF( - AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed))) { - return nullptr; - } - - CanvasShutdownManager* manager = new CanvasShutdownManager(); - sLocalManager.set(manager); - return manager; - } - - MOZ_ASSERT_UNREACHABLE("Can only be used on main or DOM worker threads!"); - return nullptr; -} - -void CanvasShutdownManager::AddShutdownObserver( - dom::CanvasRenderingContext2D* aCanvas) { - mActiveCanvas.insert(aCanvas); -} - -void CanvasShutdownManager::RemoveShutdownObserver( - dom::CanvasRenderingContext2D* aCanvas) { - mActiveCanvas.erase(aCanvas); -} - -} // namespace mozilla::gfx diff --git a/gfx/ipc/CanvasShutdownManager.h b/gfx/ipc/CanvasShutdownManager.h deleted file mode 100644 index 1794aeecde5c..000000000000 --- a/gfx/ipc/CanvasShutdownManager.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef _include_gfx_ipc_CanvasShutdownManager_h__ -#define _include_gfx_ipc_CanvasShutdownManager_h__ - -#include "mozilla/ThreadLocal.h" -#include - -namespace mozilla { -namespace dom { -class CanvasRenderingContext2D; -class StrongWorkerRef; -class ThreadSafeWorkerRef; -} // namespace dom - -namespace gfx { - -class CanvasShutdownManager final { - public: - static CanvasShutdownManager* Get(); - static CanvasShutdownManager* MaybeGet(); - static void Shutdown(); - - dom::ThreadSafeWorkerRef* GetWorkerRef() const { return mWorkerRef; } - void AddShutdownObserver(dom::CanvasRenderingContext2D* aCanvas); - void RemoveShutdownObserver(dom::CanvasRenderingContext2D* aCanvas); - - private: - explicit CanvasShutdownManager(dom::StrongWorkerRef* aWorkerRef); - CanvasShutdownManager(); - ~CanvasShutdownManager(); - void Destroy(); - - RefPtr mWorkerRef; - std::set mActiveCanvas; - static MOZ_THREAD_LOCAL(CanvasShutdownManager*) sLocalManager; -}; - -} // namespace gfx -} // namespace mozilla - -#endif // _include_gfx_ipc_CanvasShutdownManager_h__ diff --git a/gfx/ipc/moz.build b/gfx/ipc/moz.build index cc007a8193c3..b8a52079e417 100644 --- a/gfx/ipc/moz.build +++ b/gfx/ipc/moz.build @@ -13,7 +13,6 @@ EXPORTS.mozilla.gfx += [ "CanvasManagerChild.h", "CanvasManagerParent.h", "CanvasRenderThread.h", - "CanvasShutdownManager.h", "CrossProcessPaint.h", "FileHandleWrapper.h", "GPUChild.h", @@ -43,7 +42,6 @@ UNIFIED_SOURCES += [ "CanvasManagerChild.cpp", "CanvasManagerParent.cpp", "CanvasRenderThread.cpp", - "CanvasShutdownManager.cpp", "CompositorSession.cpp", "CompositorWidgetVsyncObserver.cpp", "CrossProcessPaint.cpp", diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index c57564b0547b..d1b05a2b821c 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -21,8 +21,8 @@ #include "mozilla/gfx/gfxVars.h" #include "mozilla/gfx/GPUProcessManager.h" #include "mozilla/gfx/GraphicsMessages.h" +#include "mozilla/gfx/CanvasManagerChild.h" #include "mozilla/gfx/CanvasRenderThread.h" -#include "mozilla/gfx/CanvasShutdownManager.h" #include "mozilla/ClearOnShutdown.h" #include "mozilla/DebugOnly.h" #include "mozilla/EnumTypeTraits.h" @@ -1343,7 +1343,7 @@ void gfxPlatform::ShutdownLayersIPC() { if (XRE_IsContentProcess()) { gfx::VRManagerChild::ShutDown(); - gfx::CanvasShutdownManager::Shutdown(); + gfx::CanvasManagerChild::Shutdown(); // cf bug 1215265. if (StaticPrefs::layers_child_process_shutdown()) { layers::CompositorManagerChild::Shutdown(); @@ -1354,7 +1354,7 @@ void gfxPlatform::ShutdownLayersIPC() { VideoBridgeParent::Shutdown(); RDDProcessManager::RDDProcessShutdown(); gfx::VRManagerChild::ShutDown(); - gfx::CanvasShutdownManager::Shutdown(); + gfx::CanvasManagerChild::Shutdown(); layers::CompositorManagerChild::Shutdown(); layers::ImageBridgeChild::ShutDown(); // This could be running on either the Compositor thread, the Renderer