tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CanvasManagerParent.cpp (8947B)


      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/. */
      6 
      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"
     23 
     24 namespace mozilla::gfx {
     25 
     26 MOZ_RUNINIT CanvasManagerParent::ManagerSet CanvasManagerParent::sManagers;
     27 
     28 /* static */ void CanvasManagerParent::Init(
     29    Endpoint<PCanvasManagerParent>&& aEndpoint,
     30    layers::SharedSurfacesHolder* aSharedSurfacesHolder,
     31    const dom::ContentParentId& aContentId) {
     32  MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread());
     33 
     34  auto manager =
     35      MakeRefPtr<CanvasManagerParent>(aSharedSurfacesHolder, aContentId);
     36 
     37  nsCOMPtr<nsIThread> owningThread =
     38      gfx::CanvasRenderThread::GetCanvasRenderThread();
     39  MOZ_ASSERT(owningThread);
     40 
     41  owningThread->Dispatch(NewRunnableMethod<Endpoint<PCanvasManagerParent>&&>(
     42      "CanvasManagerParent::Bind", manager, &CanvasManagerParent::Bind,
     43      std::move(aEndpoint)));
     44 }
     45 
     46 /* static */ void CanvasManagerParent::Shutdown() {
     47  MOZ_ASSERT(NS_IsMainThread());
     48 
     49  nsCOMPtr<nsIThread> owningThread =
     50      gfx::CanvasRenderThread::GetCanvasRenderThread();
     51  MOZ_ASSERT(owningThread);
     52 
     53  NS_DispatchAndSpinEventLoopUntilComplete(
     54      "CanvasManagerParent::Shutdown"_ns, owningThread,
     55      NS_NewRunnableFunction("CanvasManagerParent::Shutdown", []() -> void {
     56        CanvasManagerParent::ShutdownInternal();
     57      }));
     58 }
     59 
     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);
     65  }
     66 
     67  for (auto const& actor : actors) {
     68    actor->Close();
     69  }
     70 }
     71 
     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();
     79        }
     80      }));
     81 
     82  if (CanvasRenderThread::IsInCanvasRenderThread()) {
     83    DisableRemoteCanvasInternal();
     84    return;
     85  }
     86 
     87  CanvasRenderThread::Dispatch(NS_NewRunnableFunction(
     88      "CanvasManagerParent::DisableRemoteCanvas",
     89      [] { CanvasManagerParent::DisableRemoteCanvasInternal(); }));
     90 }
     91 
     92 /* static */ void CanvasManagerParent::DisableRemoteCanvasInternal() {
     93  MOZ_ASSERT(CanvasRenderThread::IsInCanvasRenderThread());
     94 
     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));
     99    }
    100  }
    101 
    102  for (const auto& actor : actors) {
    103    (void)NS_WARN_IF(!actor->SendDeactivate());
    104  }
    105 }
    106 
    107 CanvasManagerParent::CanvasManagerParent(
    108    layers::SharedSurfacesHolder* aSharedSurfacesHolder,
    109    const dom::ContentParentId& aContentId)
    110    : mSharedSurfacesHolder(aSharedSurfacesHolder), mContentId(aContentId) {}
    111 
    112 CanvasManagerParent::~CanvasManagerParent() = default;
    113 
    114 void CanvasManagerParent::Bind(Endpoint<PCanvasManagerParent>&& aEndpoint) {
    115  if (!aEndpoint.Bind(this)) {
    116    NS_WARNING("Failed to bind CanvasManagerParent!");
    117    return;
    118  }
    119 
    120 #ifdef DEBUG
    121  for (CanvasManagerParent* i : sManagers) {
    122    MOZ_ASSERT_IF(i->mContentId == mContentId,
    123                  i->OtherPidMaybeInvalid() == OtherPidMaybeInvalid());
    124  }
    125 #endif
    126 
    127  sManagers.Insert(this);
    128 }
    129 
    130 void CanvasManagerParent::ActorDestroy(ActorDestroyReason aWhy) {
    131  sManagers.Remove(this);
    132 }
    133 
    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;
    139  }
    140  return MakeAndAddRef<dom::WebGLParent>(mSharedSurfacesHolder, mContentId);
    141 }
    142 
    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;
    148  }
    149 
    150  return MakeAndAddRef<webgpu::WebGPUParent>(mContentId);
    151 }
    152 
    153 mozilla::ipc::IPCResult CanvasManagerParent::RecvInitialize(
    154    const uint32_t& aId) {
    155  if (!aId) {
    156    return IPC_FAIL(this, "invalid id");
    157  }
    158  if (mId) {
    159    return IPC_FAIL(this, "already initialized");
    160  }
    161  mId = aId;
    162  return IPC_OK();
    163 }
    164 
    165 already_AddRefed<layers::PCanvasParent>
    166 CanvasManagerParent::AllocPCanvasParent() {
    167  if (NS_WARN_IF(!gfx::gfxVars::UseAcceleratedCanvas2D())) {
    168    MOZ_ASSERT_UNREACHABLE("AllocPCanvasParent without remote canvas");
    169    return nullptr;
    170  }
    171  if (NS_WARN_IF(!mId)) {
    172    MOZ_ASSERT_UNREACHABLE("AllocPCanvasParent without ID");
    173    return nullptr;
    174  }
    175  return MakeAndAddRef<layers::CanvasTranslator>(mSharedSurfacesHolder,
    176                                                 mContentId, mId);
    177 }
    178 
    179 mozilla::ipc::IPCResult CanvasManagerParent::RecvGetSnapshot(
    180    const uint32_t& aManagerId, const ActorId& aProtocolId,
    181    const Maybe<RemoteTextureOwnerId>& aOwnerId,
    182    const Maybe<RawId>& aCommandEncoderId, const Maybe<RawId>& aCommandBufferId,
    183    webgl::FrontBufferSnapshotIpc* aResult) {
    184  if (!aManagerId) {
    185    return IPC_FAIL(this, "invalid id");
    186  }
    187 
    188  IProtocol* actor = nullptr;
    189  for (CanvasManagerParent* i : sManagers) {
    190    if (i->mContentId == mContentId && i->mId == aManagerId) {
    191      actor = i->Lookup(aProtocolId);
    192      break;
    193    }
    194  }
    195 
    196  if (!actor) {
    197    return IPC_FAIL(this, "invalid actor");
    198  }
    199 
    200  if (actor->GetSide() != mozilla::ipc::Side::ParentSide) {
    201    return IPC_FAIL(this, "unsupported actor");
    202  }
    203 
    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;
    211      }
    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");
    219      }
    220      if (aCommandEncoderId.isNothing()) {
    221        return IPC_FAIL(this, "invalid CommandEncoderId");
    222      }
    223      if (aCommandBufferId.isNothing()) {
    224        return IPC_FAIL(this, "invalid CommandBufferId");
    225      }
    226      uint32_t stride = 0;
    227      mozilla::ipc::IPCResult rv = webgpu->GetFrontBufferSnapshot(
    228          this, *aOwnerId, *aCommandEncoderId, *aCommandBufferId, buffer.shmem,
    229          size, stride);
    230      if (!rv) {
    231        return rv;
    232      }
    233      buffer.surfSize.x = static_cast<uint32_t>(size.width);
    234      buffer.surfSize.y = static_cast<uint32_t>(size.height);
    235      buffer.byteStride = stride;
    236    } break;
    237    default:
    238      return IPC_FAIL(this, "unsupported protocol");
    239  }
    240 
    241  *aResult = std::move(buffer);
    242  return IPC_OK();
    243 }
    244 
    245 /* static */ mozilla::ipc::IProtocol* CanvasManagerParent::GetCanvasActor(
    246    dom::ContentParentId aContentId, uint32_t aManagerId, ActorId aCanvasId) {
    247  IProtocol* actor = nullptr;
    248  for (CanvasManagerParent* i : sManagers) {
    249    if (i->mContentId == aContentId && i->mId == aManagerId) {
    250      actor = i->Lookup(aCanvasId);
    251      break;
    252    }
    253  }
    254  return actor;
    255 }
    256 
    257 /* static */ already_AddRefed<SourceSurface>
    258 CanvasManagerParent::GetCanvasSurface(dom::ContentParentId aContentId,
    259                                      uint32_t aManagerId, ActorId aCanvasId,
    260                                      uintptr_t aSurfaceId,
    261                                      Maybe<layers::SurfaceDescriptor>* aDesc) {
    262  IProtocol* actor = GetCanvasActor(aContentId, aManagerId, aCanvasId);
    263  if (!actor) {
    264    return nullptr;
    265  }
    266  switch (actor->GetProtocolId()) {
    267    case ProtocolId::PCanvasMsgStart:
    268      return static_cast<layers::CanvasTranslator*>(actor)->WaitForSurface(
    269          aSurfaceId, aDesc);
    270    default:
    271      MOZ_ASSERT_UNREACHABLE("Unsupported protocol");
    272      break;
    273  }
    274  return nullptr;
    275 }
    276 
    277 }  // namespace mozilla::gfx