Merge mozilla-central to autoland. CLOSED TREE
[gecko.git] / gfx / ipc / CanvasManagerParent.cpp
blob50fdb6e104e06f07f41ed1448f583678bcbceb7b
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());
34 auto manager =
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();
57 }));
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) {
68 actor->Close();
72 /* static */ void CanvasManagerParent::DisableRemoteCanvas() {
73 NS_DispatchToMainThread(
74 NS_NewRunnableFunction("CanvasManagerParent::DisableRemoteCanvas", [] {
75 if (XRE_IsGPUProcess()) {
76 GPUParent::GetSingleton()->NotifyDisableRemoteCanvas();
77 } else {
78 gfxPlatform::DisableRemoteCanvas();
80 }));
82 if (CanvasRenderThread::IsInCanvasRenderThread()) {
83 DisableRemoteCanvasInternal();
84 return;
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!");
117 return;
120 #ifdef DEBUG
121 for (CanvasManagerParent* i : sManagers) {
122 MOZ_ASSERT_IF(i->mContentId == mContentId,
123 i->OtherPidMaybeInvalid() == OtherPidMaybeInvalid());
125 #endif
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");
138 return nullptr;
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");
147 return nullptr;
150 return MakeAndAddRef<webgpu::WebGPUParent>();
153 mozilla::ipc::IPCResult CanvasManagerParent::RecvInitialize(
154 const uint32_t& aId) {
155 if (!aId) {
156 return IPC_FAIL(this, "invalid id");
158 if (mId) {
159 return IPC_FAIL(this, "already initialized");
161 mId = aId;
162 return IPC_OK();
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");
170 return nullptr;
172 if (NS_WARN_IF(!mId)) {
173 MOZ_ASSERT_UNREACHABLE("AllocPCanvasParent without ID");
174 return nullptr;
176 return MakeAndAddRef<layers::CanvasTranslator>(mSharedSurfacesHolder,
177 mContentId, mId);
180 mozilla::ipc::IPCResult CanvasManagerParent::RecvGetSnapshot(
181 const uint32_t& aManagerId, const int32_t& aProtocolId,
182 const Maybe<RemoteTextureOwnerId>& aOwnerId,
183 webgl::FrontBufferSnapshotIpc* aResult) {
184 if (!aManagerId) {
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);
192 break;
196 if (!actor) {
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);
209 if (!rv) {
210 return rv;
212 } break;
213 case ProtocolId::PWebGPUMsgStart: {
214 RefPtr<webgpu::WebGPUParent> webgpu =
215 static_cast<webgpu::WebGPUParent*>(actor);
216 IntSize size;
217 if (aOwnerId.isNothing()) {
218 return IPC_FAIL(this, "invalid OwnerId");
220 mozilla::ipc::IPCResult rv =
221 webgpu->GetFrontBufferSnapshot(this, *aOwnerId, buffer.shmem, size);
222 if (!rv) {
223 return rv;
225 buffer.surfSize.x = static_cast<uint32_t>(size.width);
226 buffer.surfSize.y = static_cast<uint32_t>(size.height);
227 } break;
228 default:
229 return IPC_FAIL(this, "unsupported protocol");
232 *aResult = std::move(buffer);
233 return IPC_OK();
236 } // namespace mozilla::gfx