diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /dom/canvas/OffscreenCanvasRenderingContext2D.cpp | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/canvas/OffscreenCanvasRenderingContext2D.cpp')
-rw-r--r-- | dom/canvas/OffscreenCanvasRenderingContext2D.cpp | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/dom/canvas/OffscreenCanvasRenderingContext2D.cpp b/dom/canvas/OffscreenCanvasRenderingContext2D.cpp new file mode 100644 index 0000000000..7174d56710 --- /dev/null +++ b/dom/canvas/OffscreenCanvasRenderingContext2D.cpp @@ -0,0 +1,181 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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 "OffscreenCanvasRenderingContext2D.h" +#include "mozilla/CycleCollectedJSRuntime.h" +#include "mozilla/dom/OffscreenCanvasRenderingContext2DBinding.h" +#include "mozilla/dom/OffscreenCanvas.h" +#include "mozilla/dom/WorkerCommon.h" +#include "mozilla/dom/WorkerRef.h" + +using namespace mozilla; + +namespace mozilla::dom { + +class OffscreenCanvasShutdownObserver final { + NS_INLINE_DECL_REFCOUNTING(OffscreenCanvasShutdownObserver) + + public: + explicit OffscreenCanvasShutdownObserver( + OffscreenCanvasRenderingContext2D* aOwner) + : mOwner(aOwner) {} + + void OnShutdown() { + if (mOwner) { + mOwner->OnShutdown(); + mOwner = nullptr; + } + } + + void ClearOwner() { mOwner = nullptr; } + + private: + ~OffscreenCanvasShutdownObserver() = default; + + OffscreenCanvasRenderingContext2D* mOwner; +}; + +NS_IMPL_CYCLE_COLLECTION_INHERITED(OffscreenCanvasRenderingContext2D, + CanvasRenderingContext2D) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(OffscreenCanvasRenderingContext2D) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY +NS_INTERFACE_MAP_END_INHERITING(CanvasRenderingContext2D) + +// Need to use NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED +// and dummy trace since we're missing some _SKIPPABLE_ macros without +// SCRIPT_HOLDER. +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED( + OffscreenCanvasRenderingContext2D, CanvasRenderingContext2D) +NS_IMPL_CYCLE_COLLECTION_TRACE_END + +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(OffscreenCanvasRenderingContext2D) + return tmp->HasKnownLiveWrapper(); +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END + +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(OffscreenCanvasRenderingContext2D) + return tmp->HasKnownLiveWrapper(); +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END + +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(OffscreenCanvasRenderingContext2D) + return tmp->HasKnownLiveWrapper(); +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END + +NS_IMPL_ADDREF_INHERITED(OffscreenCanvasRenderingContext2D, + CanvasRenderingContext2D) +NS_IMPL_RELEASE_INHERITED(OffscreenCanvasRenderingContext2D, + CanvasRenderingContext2D) + +OffscreenCanvasRenderingContext2D::OffscreenCanvasRenderingContext2D( + layers::LayersBackend aCompositorBackend) + : CanvasRenderingContext2D(aCompositorBackend) {} + +OffscreenCanvasRenderingContext2D::~OffscreenCanvasRenderingContext2D() = + default; + +JSObject* OffscreenCanvasRenderingContext2D::WrapObject( + JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { + return OffscreenCanvasRenderingContext2D_Binding::Wrap(aCx, this, + aGivenProto); +} + +nsIGlobalObject* OffscreenCanvasRenderingContext2D::GetParentObject() const { + return mOffscreenCanvas->GetOwnerGlobal(); +} + +NS_IMETHODIMP OffscreenCanvasRenderingContext2D::InitializeWithDrawTarget( + nsIDocShell* aShell, NotNull<gfx::DrawTarget*> aTarget) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +void OffscreenCanvasRenderingContext2D::AddShutdownObserver() { + WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); + if (!workerPrivate) { + // We may be using OffscreenCanvas on the main thread. + CanvasRenderingContext2D::AddShutdownObserver(); + return; + } + + mOffscreenShutdownObserver = + MakeAndAddRef<OffscreenCanvasShutdownObserver>(this); + mWorkerRef = WeakWorkerRef::Create( + workerPrivate, + [observer = mOffscreenShutdownObserver] { observer->OnShutdown(); }); +} + +void OffscreenCanvasRenderingContext2D::RemoveShutdownObserver() { + WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); + if (!workerPrivate) { + // We may be using OffscreenCanvas on the main thread. + CanvasRenderingContext2D::RemoveShutdownObserver(); + return; + } + + if (mOffscreenShutdownObserver) { + mOffscreenShutdownObserver->ClearOwner(); + } + mOffscreenShutdownObserver = nullptr; + mWorkerRef = nullptr; +} + +void OffscreenCanvasRenderingContext2D::OnShutdown() { + if (mOffscreenShutdownObserver) { + mOffscreenShutdownObserver->ClearOwner(); + mOffscreenShutdownObserver = nullptr; + } + + CanvasRenderingContext2D::OnShutdown(); +} + +void OffscreenCanvasRenderingContext2D::Commit(ErrorResult& aRv) { + if (!mOffscreenCanvas->IsTransferredFromElement()) { + return; + } + + mOffscreenCanvas->CommitFrameToCompositor(); +} + +void OffscreenCanvasRenderingContext2D::AddZoneWaitingForGC() { + JSObject* wrapper = GetWrapperPreserveColor(); + if (wrapper) { + CycleCollectedJSRuntime::Get()->AddZoneWaitingForGC( + JS::GetObjectZone(wrapper)); + } +} + +void OffscreenCanvasRenderingContext2D::AddAssociatedMemory() { + JSObject* wrapper = GetWrapperMaybeDead(); + if (wrapper) { + JS::AddAssociatedMemory(wrapper, BindingJSObjectMallocBytes(this), + JS::MemoryUse::DOMBinding); + } +} + +void OffscreenCanvasRenderingContext2D::RemoveAssociatedMemory() { + JSObject* wrapper = GetWrapperMaybeDead(); + if (wrapper) { + JS::RemoveAssociatedMemory(wrapper, BindingJSObjectMallocBytes(this), + JS::MemoryUse::DOMBinding); + } +} + +size_t BindingJSObjectMallocBytes(OffscreenCanvasRenderingContext2D* aContext) { + gfx::IntSize size = aContext->GetSize(); + + // TODO: Bug 1552137: No memory will be allocated if either dimension is + // greater than gfxPrefs::gfx_canvas_max_size(). We should check this here + // too. + + CheckedInt<uint32_t> bytes = + CheckedInt<uint32_t>(size.width) * size.height * 4; + if (!bytes.isValid()) { + return 0; + } + + return bytes.value(); +} + +} // namespace mozilla::dom |