1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "CanvasManagerParent.h"
8 #include "gfxPlatform.h"
9 #include "mozilla/dom/WebGLParent.h"
10 #include "mozilla/gfx/CanvasRenderThread.h"
11 #include "mozilla/gfx/gfxVars.h"
12 #include "mozilla/gfx/GPUParent.h"
13 #include "mozilla/ipc/Endpoint.h"
14 #include "mozilla/layers/CanvasTranslator.h"
15 #include "mozilla/layers/CompositorThread.h"
16 #include "mozilla/layers/ISurfaceAllocator.h"
17 #include "mozilla/layers/SharedSurfacesParent.h"
18 #include "mozilla/StaticPrefs_gfx.h"
19 #include "mozilla/StaticPrefs_webgl.h"
20 #include "mozilla/webgpu/WebGPUParent.h"
21 #include "nsIThread.h"
22 #include "nsThreadUtils.h"
24 namespace mozilla::gfx
{
26 CanvasManagerParent::ManagerSet
CanvasManagerParent::sManagers
;
28 /* static */ void CanvasManagerParent::Init(
29 Endpoint
<PCanvasManagerParent
>&& aEndpoint
,
30 layers::SharedSurfacesHolder
* aSharedSurfacesHolder
,
31 const dom::ContentParentId
& aContentId
) {
32 MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread());
35 MakeRefPtr
<CanvasManagerParent
>(aSharedSurfacesHolder
, aContentId
);
37 nsCOMPtr
<nsIThread
> owningThread
=
38 gfx::CanvasRenderThread::GetCanvasRenderThread();
39 MOZ_ASSERT(owningThread
);
41 owningThread
->Dispatch(NewRunnableMethod
<Endpoint
<PCanvasManagerParent
>&&>(
42 "CanvasManagerParent::Bind", manager
, &CanvasManagerParent::Bind
,
43 std::move(aEndpoint
)));
46 /* static */ void CanvasManagerParent::Shutdown() {
47 MOZ_ASSERT(NS_IsMainThread());
49 nsCOMPtr
<nsIThread
> owningThread
=
50 gfx::CanvasRenderThread::GetCanvasRenderThread();
51 MOZ_ASSERT(owningThread
);
53 NS_DispatchAndSpinEventLoopUntilComplete(
54 "CanvasManagerParent::Shutdown"_ns
, owningThread
,
55 NS_NewRunnableFunction("CanvasManagerParent::Shutdown", []() -> void {
56 CanvasManagerParent::ShutdownInternal();
60 /* static */ void CanvasManagerParent::ShutdownInternal() {
61 nsTArray
<RefPtr
<CanvasManagerParent
>> actors(sManagers
.Count());
62 // Do a copy since Close will remove the entry from the set.
63 for (const auto& actor
: sManagers
) {
64 actors
.AppendElement(actor
);
67 for (auto const& actor
: actors
) {
72 /* static */ void CanvasManagerParent::DisableRemoteCanvas() {
73 NS_DispatchToMainThread(
74 NS_NewRunnableFunction("CanvasManagerParent::DisableRemoteCanvas", [] {
75 if (XRE_IsGPUProcess()) {
76 GPUParent::GetSingleton()->NotifyDisableRemoteCanvas();
78 gfxPlatform::DisableRemoteCanvas();
82 if (CanvasRenderThread::IsInCanvasRenderThread()) {
83 DisableRemoteCanvasInternal();
87 CanvasRenderThread::Dispatch(NS_NewRunnableFunction(
88 "CanvasManagerParent::DisableRemoteCanvas",
89 [] { CanvasManagerParent::DisableRemoteCanvasInternal(); }));
92 /* static */ void CanvasManagerParent::DisableRemoteCanvasInternal() {
93 MOZ_ASSERT(CanvasRenderThread::IsInCanvasRenderThread());
95 AutoTArray
<RefPtr
<layers::CanvasTranslator
>, 16> actors
;
96 for (const auto& manager
: sManagers
) {
97 for (const auto& canvas
: manager
->ManagedPCanvasParent()) {
98 actors
.AppendElement(static_cast<layers::CanvasTranslator
*>(canvas
));
102 for (const auto& actor
: actors
) {
103 Unused
<< NS_WARN_IF(!actor
->SendDeactivate());
107 CanvasManagerParent::CanvasManagerParent(
108 layers::SharedSurfacesHolder
* aSharedSurfacesHolder
,
109 const dom::ContentParentId
& aContentId
)
110 : mSharedSurfacesHolder(aSharedSurfacesHolder
), mContentId(aContentId
) {}
112 CanvasManagerParent::~CanvasManagerParent() = default;
114 void CanvasManagerParent::Bind(Endpoint
<PCanvasManagerParent
>&& aEndpoint
) {
115 if (!aEndpoint
.Bind(this)) {
116 NS_WARNING("Failed to bind CanvasManagerParent!");
121 for (CanvasManagerParent
* i
: sManagers
) {
122 MOZ_ASSERT_IF(i
->mContentId
== mContentId
,
123 i
->OtherPidMaybeInvalid() == OtherPidMaybeInvalid());
127 sManagers
.Insert(this);
130 void CanvasManagerParent::ActorDestroy(ActorDestroyReason aWhy
) {
131 sManagers
.Remove(this);
134 already_AddRefed
<dom::PWebGLParent
> CanvasManagerParent::AllocPWebGLParent() {
135 if (NS_WARN_IF(!gfxVars::AllowWebglOop() &&
136 !StaticPrefs::webgl_out_of_process_force())) {
137 MOZ_ASSERT_UNREACHABLE("AllocPWebGLParent without remote WebGL");
140 return MakeAndAddRef
<dom::WebGLParent
>(mContentId
);
143 already_AddRefed
<webgpu::PWebGPUParent
>
144 CanvasManagerParent::AllocPWebGPUParent() {
145 if (NS_WARN_IF(!gfxVars::AllowWebGPU())) {
146 MOZ_ASSERT_UNREACHABLE("AllocPWebGPUParent without WebGPU");
150 return MakeAndAddRef
<webgpu::WebGPUParent
>();
153 mozilla::ipc::IPCResult
CanvasManagerParent::RecvInitialize(
154 const uint32_t& aId
) {
156 return IPC_FAIL(this, "invalid id");
159 return IPC_FAIL(this, "already initialized");
165 already_AddRefed
<layers::PCanvasParent
>
166 CanvasManagerParent::AllocPCanvasParent() {
167 if (NS_WARN_IF(!gfx::gfxVars::RemoteCanvasEnabled() &&
168 !gfx::gfxVars::UseAcceleratedCanvas2D())) {
169 MOZ_ASSERT_UNREACHABLE("AllocPCanvasParent without remote canvas");
172 if (NS_WARN_IF(!mId
)) {
173 MOZ_ASSERT_UNREACHABLE("AllocPCanvasParent without ID");
176 return MakeAndAddRef
<layers::CanvasTranslator
>(mSharedSurfacesHolder
,
180 mozilla::ipc::IPCResult
CanvasManagerParent::RecvGetSnapshot(
181 const uint32_t& aManagerId
, const int32_t& aProtocolId
,
182 const Maybe
<RemoteTextureOwnerId
>& aOwnerId
,
183 webgl::FrontBufferSnapshotIpc
* aResult
) {
185 return IPC_FAIL(this, "invalid id");
188 IProtocol
* actor
= nullptr;
189 for (CanvasManagerParent
* i
: sManagers
) {
190 if (i
->mContentId
== mContentId
&& i
->mId
== aManagerId
) {
191 actor
= i
->Lookup(aProtocolId
);
197 return IPC_FAIL(this, "invalid actor");
200 if (actor
->GetSide() != mozilla::ipc::Side::ParentSide
) {
201 return IPC_FAIL(this, "unsupported actor");
204 webgl::FrontBufferSnapshotIpc buffer
;
205 switch (actor
->GetProtocolId()) {
206 case ProtocolId::PWebGLMsgStart
: {
207 RefPtr
<dom::WebGLParent
> webgl
= static_cast<dom::WebGLParent
*>(actor
);
208 mozilla::ipc::IPCResult rv
= webgl
->GetFrontBufferSnapshot(&buffer
, this);
213 case ProtocolId::PWebGPUMsgStart
: {
214 RefPtr
<webgpu::WebGPUParent
> webgpu
=
215 static_cast<webgpu::WebGPUParent
*>(actor
);
217 if (aOwnerId
.isNothing()) {
218 return IPC_FAIL(this, "invalid OwnerId");
220 mozilla::ipc::IPCResult rv
=
221 webgpu
->GetFrontBufferSnapshot(this, *aOwnerId
, buffer
.shmem
, size
);
225 buffer
.surfSize
.x
= static_cast<uint32_t>(size
.width
);
226 buffer
.surfSize
.y
= static_cast<uint32_t>(size
.height
);
229 return IPC_FAIL(this, "unsupported protocol");
232 *aResult
= std::move(buffer
);
236 } // namespace mozilla::gfx