зеркало из https://github.com/mozilla/gecko-dev.git
182 строки
5.8 KiB
C++
182 строки
5.8 KiB
C++
/* -*- 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
|