summaryrefslogtreecommitdiffstats
path: root/dom/canvas/OffscreenCanvasRenderingContext2D.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /dom/canvas/OffscreenCanvasRenderingContext2D.cpp
parentInitial commit. (diff)
downloadthunderbird-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.cpp181
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