gecko-dev/gfx/layers/ipc/ContentCompositorBridgePare...

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

694 строки
24 KiB
C++
Исходник Обычный вид История

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "mozilla/layers/ContentCompositorBridgeParent.h"
#include <stdint.h> // for uint64_t
#include "LayerTransactionParent.h" // for LayerTransactionParent
#include "apz/src/APZCTreeManager.h" // for APZCTreeManager
#include "gfxUtils.h"
#ifdef XP_WIN
# include "mozilla/gfx/DeviceManagerDx.h" // for DeviceManagerDx
# include "mozilla/layers/ImageDataSerializer.h"
#endif
#include "mozilla/dom/WebGLParent.h"
#include "mozilla/ipc/Transport.h" // for Transport
#include "mozilla/layers/AnimationHelper.h" // for CompositorAnimationStorage
#include "mozilla/layers/APZCTreeManagerParent.h" // for APZCTreeManagerParent
#include "mozilla/layers/APZUpdater.h" // for APZUpdater
#include "mozilla/layers/AsyncCompositionManager.h"
#include "mozilla/layers/CompositorOptions.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/LayerManagerComposite.h"
#include "mozilla/layers/LayerTreeOwnerTracker.h"
#include "mozilla/layers/PLayerTransactionParent.h"
#include "mozilla/layers/RemoteContentController.h"
#include "mozilla/layers/WebRenderBridgeParent.h"
#include "mozilla/layers/AsyncImagePipelineManager.h"
Bug 1575008 - WebGPU implementation basis r=baku,bzbarsky This change vendors `wgpu` library in-tree and hooks up the initialization bits. It implements adapter and device initialization and adds a simple test. Complementary ecosystem tracker - https://github.com/gfx-rs/wgpu/issues/374 Current status: - [x] General - [x] figure out the IPC story - [ ] move wgpu crates into a dedicated folder (postponed as https://bugzilla.mozilla.org/show_bug.cgi?id=1594182) - [x] neko rebasing disaster - [x] Linux - [x] avoid depending on spirv_cross - [x] macOS - [x] due to cross-compiling shaders - [x] need the dependency update - [x] stop using gcc - [x] unexpected SSL header collision - https://phabricator.services.mozilla.com/D51148 - [x] undefined Metal symbols - [x] missing webrtc headers for IPDL magic - https://phabricator.services.mozilla.com/D51558 - [x] spirv-cross linking failure in ASAN - https://phabricator.services.mozilla.com/D52688 - [x] Windows - [x] due to "ipc-channel" not supporting Windows yet - [x] due to some exceptional stuff - [x] undefined symbol: `D3D12CreateDevice` - [x] d3d12.dll is not found, dxgi1_4 doesn't present - [x] d3d11.dll and dxgi.dll need to be explicitly loaded on win32 mingw - [x] libbacktrace fails to link on win32 mingw - [x] cc mislinking C++ standard library - [x] Android - [x] spirv-cross fails to build due to exceptions Update-1: We decided to go with IPDL mechanism instead of Rust based ipc-channel (or any alternatives), which unblocks Windows build. Update-2: It appears that WebGPUThreading isn't needed any more as the child thread (and its event loop) is now managed by IPDL infrastructure. This PR removes it 🎉 . Update-3: InstanceProvider is also removed. Update-4: All set, the try is green, waiting for dependent changes to go in. Differential Revision: https://phabricator.services.mozilla.com/D49458 --HG-- rename : dom/webgpu/Adapter.cpp => dom/webgpu/ipc/WebGPUTypes.h rename : third_party/rust/blake2b_simd/Cargo.toml => third_party/rust/ash/Cargo.toml rename : third_party/rust/uluru/Cargo.toml => third_party/rust/atom/Cargo.toml rename : third_party/rust/core-graphics/Cargo.toml => third_party/rust/cocoa/Cargo.toml rename : third_party/rust/crossbeam-deque/LICENSE-MIT => third_party/rust/cocoa/LICENSE-MIT rename : third_party/rust/core-graphics/src/lib.rs => third_party/rust/cocoa/src/lib.rs rename : third_party/rust/uluru/Cargo.toml => third_party/rust/colorful/Cargo.toml rename : third_party/rust/uluru/Cargo.toml => third_party/rust/copyless/Cargo.toml rename : third_party/rust/crossbeam-utils/.cargo-checksum.json => third_party/rust/crossbeam-utils-0.6.5/.cargo-checksum.json rename : third_party/rust/crossbeam-utils/CHANGELOG.md => third_party/rust/crossbeam-utils-0.6.5/CHANGELOG.md rename : third_party/rust/crossbeam-utils/Cargo.toml => third_party/rust/crossbeam-utils-0.6.5/Cargo.toml rename : third_party/rust/crossbeam-deque/LICENSE-MIT => third_party/rust/crossbeam-utils-0.6.5/LICENSE-MIT rename : third_party/rust/crossbeam-utils/README.md => third_party/rust/crossbeam-utils-0.6.5/README.md rename : third_party/rust/crossbeam-utils/benches/atomic_cell.rs => third_party/rust/crossbeam-utils-0.6.5/benches/atomic_cell.rs rename : third_party/rust/crossbeam-utils/src/atomic/atomic_cell.rs => third_party/rust/crossbeam-utils-0.6.5/src/atomic/atomic_cell.rs rename : third_party/rust/crossbeam-utils/src/atomic/mod.rs => third_party/rust/crossbeam-utils-0.6.5/src/atomic/mod.rs rename : third_party/rust/crossbeam-utils/src/backoff.rs => third_party/rust/crossbeam-utils-0.6.5/src/backoff.rs rename : third_party/rust/crossbeam-utils/src/cache_padded.rs => third_party/rust/crossbeam-utils-0.6.5/src/cache_padded.rs rename : third_party/rust/crossbeam-utils/src/lib.rs => third_party/rust/crossbeam-utils-0.6.5/src/lib.rs rename : third_party/rust/crossbeam-utils/src/thread.rs => third_party/rust/crossbeam-utils-0.6.5/src/thread.rs rename : third_party/rust/crossbeam-utils/tests/atomic_cell.rs => third_party/rust/crossbeam-utils-0.6.5/tests/atomic_cell.rs rename : third_party/rust/crossbeam-utils/tests/parker.rs => third_party/rust/crossbeam-utils-0.6.5/tests/parker.rs rename : third_party/rust/crossbeam-utils/tests/sharded_lock.rs => third_party/rust/crossbeam-utils-0.6.5/tests/sharded_lock.rs rename : third_party/rust/crossbeam-utils/tests/thread.rs => third_party/rust/crossbeam-utils-0.6.5/tests/thread.rs rename : third_party/rust/blake2b_simd/Cargo.toml => third_party/rust/gfx-auxil/Cargo.toml rename : third_party/rust/blake2b_simd/Cargo.toml => third_party/rust/gfx-backend-empty/Cargo.toml rename : third_party/rust/blake2b_simd/Cargo.toml => third_party/rust/hibitset/Cargo.toml rename : third_party/rust/crossbeam-deque/LICENSE-MIT => third_party/rust/hibitset/LICENSE-MIT rename : third_party/rust/crossbeam-deque/LICENSE-MIT => third_party/rust/metal/LICENSE-MIT rename : third_party/rust/uluru/Cargo.toml => third_party/rust/range-alloc/Cargo.toml rename : third_party/rust/blake2b_simd/Cargo.toml => third_party/rust/raw-window-handle/Cargo.toml rename : third_party/rust/blake2b_simd/Cargo.toml => third_party/rust/relevant/Cargo.toml rename : third_party/rust/crossbeam-deque/LICENSE-MIT => third_party/rust/relevant/LICENSE-MIT rename : third_party/rust/blake2b_simd/Cargo.toml => third_party/rust/rendy-descriptor/Cargo.toml rename : third_party/rust/uluru/Cargo.toml => third_party/rust/shared_library/Cargo.toml rename : third_party/rust/crossbeam-deque/LICENSE-MIT => third_party/rust/shared_library/LICENSE-MIT rename : third_party/rust/blake2b_simd/Cargo.toml => third_party/rust/storage-map/Cargo.toml rename : third_party/rust/core-graphics/Cargo.toml => third_party/rust/x11/Cargo.toml extra : moz-landing-system : lando
2019-11-14 07:59:56 +03:00
#include "mozilla/webgpu/WebGPUParent.h"
#include "mozilla/mozalloc.h" // for operator new, etc
#include "nsDebug.h" // for NS_ASSERTION, etc
#include "nsTArray.h" // for nsTArray
#include "nsXULAppAPI.h" // for XRE_GetIOMessageLoop
#include "mozilla/Unused.h"
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/Telemetry.h"
#ifdef MOZ_GECKO_PROFILER
# include "mozilla/BaseProfilerMarkerTypes.h"
# include "GeckoProfiler.h"
#endif
namespace mozilla {
namespace layers {
// defined in CompositorBridgeParent.cpp
typedef std::map<LayersId, CompositorBridgeParent::LayerTreeState> LayerTreeMap;
extern LayerTreeMap sIndirectLayerTrees;
extern StaticAutoPtr<mozilla::Monitor> sIndirectLayerTreesLock;
void UpdateIndirectTree(LayersId aId, Layer* aRoot,
const TargetConfig& aTargetConfig);
void EraseLayerState(LayersId aId);
mozilla::ipc::IPCResult
ContentCompositorBridgeParent::RecvRequestNotifyAfterRemotePaint() {
mNotifyAfterRemotePaint = true;
return IPC_OK();
}
void ContentCompositorBridgeParent::ActorDestroy(ActorDestroyReason aWhy) {
mCanSend = false;
// We must keep this object alive untill the code handling message
// reception is finished on this thread.
GetCurrentSerialEventTarget()->Dispatch(NewRunnableMethod(
"layers::ContentCompositorBridgeParent::DeferredDestroy", this,
&ContentCompositorBridgeParent::DeferredDestroy));
}
PLayerTransactionParent*
ContentCompositorBridgeParent::AllocPLayerTransactionParent(
const nsTArray<LayersBackend>&, const LayersId& aId) {
MOZ_ASSERT(aId.IsValid());
// Check to see if this child process has access to this layer tree.
if (!LayerTreeOwnerTracker::Get()->IsMapped(aId, OtherPid())) {
NS_ERROR(
"Unexpected layers id in AllocPLayerTransactionParent; dropping "
"message...");
return nullptr;
}
MonitorAutoLock lock(*sIndirectLayerTreesLock);
CompositorBridgeParent::LayerTreeState* state = nullptr;
LayerTreeMap::iterator itr = sIndirectLayerTrees.find(aId);
if (sIndirectLayerTrees.end() != itr) {
state = &itr->second;
}
if (state && state->mLayerManager) {
state->mContentCompositorBridgeParent = this;
HostLayerManager* lm = state->mLayerManager;
CompositorAnimationStorage* animStorage =
state->mParent ? state->mParent->GetAnimationStorage() : nullptr;
TimeDuration vsyncRate =
state->mParent ? state->mParent->GetVsyncInterval() : TimeDuration();
LayerTransactionParent* p =
new LayerTransactionParent(lm, this, animStorage, aId, vsyncRate);
p->AddIPDLReference();
sIndirectLayerTrees[aId].mLayerTree = p;
return p;
}
NS_WARNING("Created child without a matching parent?");
LayerTransactionParent* p = new LayerTransactionParent(
/* aManager */ nullptr, this, /* aAnimStorage */ nullptr, aId,
TimeDuration());
p->AddIPDLReference();
return p;
}
bool ContentCompositorBridgeParent::DeallocPLayerTransactionParent(
PLayerTransactionParent* aLayers) {
LayerTransactionParent* slp = static_cast<LayerTransactionParent*>(aLayers);
EraseLayerState(slp->GetId());
static_cast<LayerTransactionParent*>(aLayers)->ReleaseIPDLReference();
return true;
}
PAPZCTreeManagerParent*
ContentCompositorBridgeParent::AllocPAPZCTreeManagerParent(
const LayersId& aLayersId) {
// Check to see if this child process has access to this layer tree.
if (!LayerTreeOwnerTracker::Get()->IsMapped(aLayersId, OtherPid())) {
NS_ERROR(
"Unexpected layers id in AllocPAPZCTreeManagerParent; dropping "
"message...");
return nullptr;
}
MonitorAutoLock lock(*sIndirectLayerTreesLock);
CompositorBridgeParent::LayerTreeState& state =
sIndirectLayerTrees[aLayersId];
// If the widget has shutdown its compositor, we may not have had a chance yet
// to unmap our layers id, and we could get here without a parent compositor.
// In this case return an empty APZCTM.
if (!state.mParent) {
// Note: we immediately call ClearTree since otherwise the APZCTM will
// retain a reference to itself, through the checkerboard observer.
LayersId dummyId{0};
const bool useWebRender = false;
RefPtr<APZCTreeManager> temp = new APZCTreeManager(dummyId, useWebRender);
RefPtr<APZUpdater> tempUpdater = new APZUpdater(temp, useWebRender);
tempUpdater->ClearTree(dummyId);
return new APZCTreeManagerParent(aLayersId, temp, tempUpdater);
}
state.mParent->AllocateAPZCTreeManagerParent(lock, aLayersId, state);
return state.mApzcTreeManagerParent;
}
bool ContentCompositorBridgeParent::DeallocPAPZCTreeManagerParent(
PAPZCTreeManagerParent* aActor) {
APZCTreeManagerParent* parent = static_cast<APZCTreeManagerParent*>(aActor);
MonitorAutoLock lock(*sIndirectLayerTreesLock);
auto iter = sIndirectLayerTrees.find(parent->GetLayersId());
if (iter != sIndirectLayerTrees.end()) {
CompositorBridgeParent::LayerTreeState& state = iter->second;
MOZ_ASSERT(state.mApzcTreeManagerParent == parent);
state.mApzcTreeManagerParent = nullptr;
}
delete parent;
return true;
}
PAPZParent* ContentCompositorBridgeParent::AllocPAPZParent(
const LayersId& aLayersId) {
// Check to see if this child process has access to this layer tree.
if (!LayerTreeOwnerTracker::Get()->IsMapped(aLayersId, OtherPid())) {
NS_ERROR("Unexpected layers id in AllocPAPZParent; dropping message...");
return nullptr;
}
RemoteContentController* controller = new RemoteContentController();
// Increment the controller's refcount before we return it. This will keep the
// controller alive until it is released by IPDL in DeallocPAPZParent.
controller->AddRef();
MonitorAutoLock lock(*sIndirectLayerTreesLock);
CompositorBridgeParent::LayerTreeState& state =
sIndirectLayerTrees[aLayersId];
MOZ_ASSERT(!state.mController);
state.mController = controller;
return controller;
}
bool ContentCompositorBridgeParent::DeallocPAPZParent(PAPZParent* aActor) {
RemoteContentController* controller =
static_cast<RemoteContentController*>(aActor);
controller->Release();
return true;
}
PWebRenderBridgeParent*
ContentCompositorBridgeParent::AllocPWebRenderBridgeParent(
const wr::PipelineId& aPipelineId, const LayoutDeviceIntSize& aSize,
const WindowKind& aWindowKind) {
LayersId layersId = wr::AsLayersId(aPipelineId);
// Check to see if this child process has access to this layer tree.
if (!LayerTreeOwnerTracker::Get()->IsMapped(layersId, OtherPid())) {
NS_ERROR(
"Unexpected layers id in AllocPWebRenderBridgeParent; dropping "
"message...");
return nullptr;
}
RefPtr<CompositorBridgeParent> cbp = nullptr;
RefPtr<WebRenderBridgeParent> root = nullptr;
{ // scope lock
MonitorAutoLock lock(*sIndirectLayerTreesLock);
MOZ_ASSERT(sIndirectLayerTrees.find(layersId) != sIndirectLayerTrees.end());
MOZ_ASSERT(sIndirectLayerTrees[layersId].mWrBridge == nullptr);
cbp = sIndirectLayerTrees[layersId].mParent;
if (cbp) {
root = sIndirectLayerTrees[cbp->RootLayerTreeId()].mWrBridge;
}
}
RefPtr<wr::WebRenderAPI> api;
if (root) {
api = root->GetWebRenderAPI();
}
if (!root || !api) {
// This could happen when this function is called after
// CompositorBridgeParent destruction. This was observed during Tab move
// between different windows.
NS_WARNING(
nsPrintfCString("Created child without a matching parent? root %p",
root.get())
.get());
nsCString error("NO_PARENT");
WebRenderBridgeParent* parent =
WebRenderBridgeParent::CreateDestroyed(aPipelineId, std::move(error));
parent->AddRef(); // IPDL reference
return parent;
}
api = api->Clone();
RefPtr<AsyncImagePipelineManager> holder = root->AsyncImageManager();
WebRenderBridgeParent* parent = new WebRenderBridgeParent(
this, aPipelineId, nullptr, root->CompositorScheduler(), std::move(api),
std::move(holder), cbp->GetVsyncInterval());
parent->AddRef(); // IPDL reference
{ // scope lock
MonitorAutoLock lock(*sIndirectLayerTreesLock);
sIndirectLayerTrees[layersId].mContentCompositorBridgeParent = this;
sIndirectLayerTrees[layersId].mWrBridge = parent;
}
return parent;
}
bool ContentCompositorBridgeParent::DeallocPWebRenderBridgeParent(
PWebRenderBridgeParent* aActor) {
WebRenderBridgeParent* parent = static_cast<WebRenderBridgeParent*>(aActor);
EraseLayerState(wr::AsLayersId(parent->PipelineId()));
parent->Release(); // IPDL reference
return true;
}
Bug 1575008 - WebGPU implementation basis r=baku,bzbarsky This change vendors `wgpu` library in-tree and hooks up the initialization bits. It implements adapter and device initialization and adds a simple test. Complementary ecosystem tracker - https://github.com/gfx-rs/wgpu/issues/374 Current status: - [x] General - [x] figure out the IPC story - [ ] move wgpu crates into a dedicated folder (postponed as https://bugzilla.mozilla.org/show_bug.cgi?id=1594182) - [x] neko rebasing disaster - [x] Linux - [x] avoid depending on spirv_cross - [x] macOS - [x] due to cross-compiling shaders - [x] need the dependency update - [x] stop using gcc - [x] unexpected SSL header collision - https://phabricator.services.mozilla.com/D51148 - [x] undefined Metal symbols - [x] missing webrtc headers for IPDL magic - https://phabricator.services.mozilla.com/D51558 - [x] spirv-cross linking failure in ASAN - https://phabricator.services.mozilla.com/D52688 - [x] Windows - [x] due to "ipc-channel" not supporting Windows yet - [x] due to some exceptional stuff - [x] undefined symbol: `D3D12CreateDevice` - [x] d3d12.dll is not found, dxgi1_4 doesn't present - [x] d3d11.dll and dxgi.dll need to be explicitly loaded on win32 mingw - [x] libbacktrace fails to link on win32 mingw - [x] cc mislinking C++ standard library - [x] Android - [x] spirv-cross fails to build due to exceptions Update-1: We decided to go with IPDL mechanism instead of Rust based ipc-channel (or any alternatives), which unblocks Windows build. Update-2: It appears that WebGPUThreading isn't needed any more as the child thread (and its event loop) is now managed by IPDL infrastructure. This PR removes it 🎉 . Update-3: InstanceProvider is also removed. Update-4: All set, the try is green, waiting for dependent changes to go in. Differential Revision: https://phabricator.services.mozilla.com/D49458 --HG-- rename : dom/webgpu/Adapter.cpp => dom/webgpu/ipc/WebGPUTypes.h rename : third_party/rust/blake2b_simd/Cargo.toml => third_party/rust/ash/Cargo.toml rename : third_party/rust/uluru/Cargo.toml => third_party/rust/atom/Cargo.toml rename : third_party/rust/core-graphics/Cargo.toml => third_party/rust/cocoa/Cargo.toml rename : third_party/rust/crossbeam-deque/LICENSE-MIT => third_party/rust/cocoa/LICENSE-MIT rename : third_party/rust/core-graphics/src/lib.rs => third_party/rust/cocoa/src/lib.rs rename : third_party/rust/uluru/Cargo.toml => third_party/rust/colorful/Cargo.toml rename : third_party/rust/uluru/Cargo.toml => third_party/rust/copyless/Cargo.toml rename : third_party/rust/crossbeam-utils/.cargo-checksum.json => third_party/rust/crossbeam-utils-0.6.5/.cargo-checksum.json rename : third_party/rust/crossbeam-utils/CHANGELOG.md => third_party/rust/crossbeam-utils-0.6.5/CHANGELOG.md rename : third_party/rust/crossbeam-utils/Cargo.toml => third_party/rust/crossbeam-utils-0.6.5/Cargo.toml rename : third_party/rust/crossbeam-deque/LICENSE-MIT => third_party/rust/crossbeam-utils-0.6.5/LICENSE-MIT rename : third_party/rust/crossbeam-utils/README.md => third_party/rust/crossbeam-utils-0.6.5/README.md rename : third_party/rust/crossbeam-utils/benches/atomic_cell.rs => third_party/rust/crossbeam-utils-0.6.5/benches/atomic_cell.rs rename : third_party/rust/crossbeam-utils/src/atomic/atomic_cell.rs => third_party/rust/crossbeam-utils-0.6.5/src/atomic/atomic_cell.rs rename : third_party/rust/crossbeam-utils/src/atomic/mod.rs => third_party/rust/crossbeam-utils-0.6.5/src/atomic/mod.rs rename : third_party/rust/crossbeam-utils/src/backoff.rs => third_party/rust/crossbeam-utils-0.6.5/src/backoff.rs rename : third_party/rust/crossbeam-utils/src/cache_padded.rs => third_party/rust/crossbeam-utils-0.6.5/src/cache_padded.rs rename : third_party/rust/crossbeam-utils/src/lib.rs => third_party/rust/crossbeam-utils-0.6.5/src/lib.rs rename : third_party/rust/crossbeam-utils/src/thread.rs => third_party/rust/crossbeam-utils-0.6.5/src/thread.rs rename : third_party/rust/crossbeam-utils/tests/atomic_cell.rs => third_party/rust/crossbeam-utils-0.6.5/tests/atomic_cell.rs rename : third_party/rust/crossbeam-utils/tests/parker.rs => third_party/rust/crossbeam-utils-0.6.5/tests/parker.rs rename : third_party/rust/crossbeam-utils/tests/sharded_lock.rs => third_party/rust/crossbeam-utils-0.6.5/tests/sharded_lock.rs rename : third_party/rust/crossbeam-utils/tests/thread.rs => third_party/rust/crossbeam-utils-0.6.5/tests/thread.rs rename : third_party/rust/blake2b_simd/Cargo.toml => third_party/rust/gfx-auxil/Cargo.toml rename : third_party/rust/blake2b_simd/Cargo.toml => third_party/rust/gfx-backend-empty/Cargo.toml rename : third_party/rust/blake2b_simd/Cargo.toml => third_party/rust/hibitset/Cargo.toml rename : third_party/rust/crossbeam-deque/LICENSE-MIT => third_party/rust/hibitset/LICENSE-MIT rename : third_party/rust/crossbeam-deque/LICENSE-MIT => third_party/rust/metal/LICENSE-MIT rename : third_party/rust/uluru/Cargo.toml => third_party/rust/range-alloc/Cargo.toml rename : third_party/rust/blake2b_simd/Cargo.toml => third_party/rust/raw-window-handle/Cargo.toml rename : third_party/rust/blake2b_simd/Cargo.toml => third_party/rust/relevant/Cargo.toml rename : third_party/rust/crossbeam-deque/LICENSE-MIT => third_party/rust/relevant/LICENSE-MIT rename : third_party/rust/blake2b_simd/Cargo.toml => third_party/rust/rendy-descriptor/Cargo.toml rename : third_party/rust/uluru/Cargo.toml => third_party/rust/shared_library/Cargo.toml rename : third_party/rust/crossbeam-deque/LICENSE-MIT => third_party/rust/shared_library/LICENSE-MIT rename : third_party/rust/blake2b_simd/Cargo.toml => third_party/rust/storage-map/Cargo.toml rename : third_party/rust/core-graphics/Cargo.toml => third_party/rust/x11/Cargo.toml extra : moz-landing-system : lando
2019-11-14 07:59:56 +03:00
webgpu::PWebGPUParent* ContentCompositorBridgeParent::AllocPWebGPUParent() {
webgpu::WebGPUParent* parent = new webgpu::WebGPUParent();
parent->AddRef(); // IPDL reference
return parent;
}
bool ContentCompositorBridgeParent::DeallocPWebGPUParent(
webgpu::PWebGPUParent* aActor) {
webgpu::WebGPUParent* parent = static_cast<webgpu::WebGPUParent*>(aActor);
parent->Release(); // IPDL reference
return true;
}
mozilla::ipc::IPCResult ContentCompositorBridgeParent::RecvNotifyChildCreated(
const LayersId& child, CompositorOptions* aOptions) {
MonitorAutoLock lock(*sIndirectLayerTreesLock);
for (LayerTreeMap::iterator it = sIndirectLayerTrees.begin();
it != sIndirectLayerTrees.end(); it++) {
CompositorBridgeParent::LayerTreeState* lts = &it->second;
if (lts->mParent && lts->mContentCompositorBridgeParent == this) {
lts->mParent->NotifyChildCreated(child);
*aOptions = lts->mParent->GetOptions();
return IPC_OK();
}
}
return IPC_FAIL_NO_REASON(this);
}
mozilla::ipc::IPCResult
ContentCompositorBridgeParent::RecvMapAndNotifyChildCreated(
const LayersId& child, const base::ProcessId& pid,
CompositorOptions* aOptions) {
// This can only be called from the browser process, as the mapping
// ensures proper window ownership of layer trees.
return IPC_FAIL_NO_REASON(this);
}
mozilla::ipc::IPCResult ContentCompositorBridgeParent::RecvCheckContentOnlyTDR(
const uint32_t& sequenceNum, bool* isContentOnlyTDR) {
*isContentOnlyTDR = false;
#ifdef XP_WIN
gfx::ContentDeviceData compositor;
gfx::DeviceManagerDx* dm = gfx::DeviceManagerDx::Get();
// Check that the D3D11 device sequence numbers match.
gfx::D3D11DeviceStatus status;
dm->ExportDeviceInfo(&status);
if (sequenceNum == status.sequenceNumber() && !dm->HasDeviceReset()) {
*isContentOnlyTDR = true;
}
#endif
return IPC_OK();
};
void ContentCompositorBridgeParent::ShadowLayersUpdated(
LayerTransactionParent* aLayerTree, const TransactionInfo& aInfo,
bool aHitTestUpdate) {
LayersId id = aLayerTree->GetId();
MOZ_ASSERT(id.IsValid());
CompositorBridgeParent::LayerTreeState* state =
CompositorBridgeParent::GetIndirectShadowTree(id);
if (!state) {
return;
}
MOZ_ASSERT(state->mParent);
state->mParent->ScheduleRotationOnCompositorThread(aInfo.targetConfig(),
aInfo.isFirstPaint());
Layer* shadowRoot = aLayerTree->GetRoot();
if (shadowRoot) {
CompositorBridgeParent::SetShadowProperties(shadowRoot);
}
UpdateIndirectTree(id, shadowRoot, aInfo.targetConfig());
state->mParent->NotifyShadowTreeTransaction(
id, aInfo.isFirstPaint(), aInfo.focusTarget(), aInfo.scheduleComposite(),
aInfo.paintSequenceNumber(), aInfo.isRepeatTransaction(), aHitTestUpdate);
// Send the 'remote paint ready' message to the content thread if it has
// already asked.
if (mNotifyAfterRemotePaint) {
Unused << SendRemotePaintIsReady();
mNotifyAfterRemotePaint = false;
}
if (aLayerTree->ShouldParentObserveEpoch()) {
// Note that we send this through the window compositor, since this needs
// to reach the widget owning the tab.
Unused << state->mParent->SendObserveLayersUpdate(
id, aLayerTree->GetChildEpoch(), true);
}
auto endTime = TimeStamp::Now();
#ifdef MOZ_GECKO_PROFILER
if (profiler_can_accept_markers()) {
profiler_add_marker(
"CONTENT_FULL_PAINT_TIME", geckoprofiler::category::GRAPHICS,
MarkerTiming::Interval(aInfo.transactionStart(), endTime),
baseprofiler::markers::ContentBuildMarker{});
}
#endif
Telemetry::Accumulate(
Telemetry::CONTENT_FULL_PAINT_TIME,
static_cast<uint32_t>(
(endTime - aInfo.transactionStart()).ToMilliseconds()));
RegisterPayloads(aLayerTree, aInfo.payload());
aLayerTree->SetPendingTransactionId(
aInfo.id(), aInfo.vsyncId(), aInfo.vsyncStart(), aInfo.refreshStart(),
aInfo.transactionStart(), endTime, aInfo.containsSVG(), aInfo.url(),
aInfo.fwdTime());
}
void ContentCompositorBridgeParent::DidCompositeLocked(
LayersId aId, const VsyncId& aVsyncId, TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd) {
sIndirectLayerTreesLock->AssertCurrentThreadOwns();
if (LayerTransactionParent* layerTree = sIndirectLayerTrees[aId].mLayerTree) {
TransactionId transactionId =
layerTree->FlushTransactionId(aVsyncId, aCompositeEnd);
if (transactionId.IsValid()) {
Unused << SendDidComposite(aId, transactionId, aCompositeStart,
aCompositeEnd);
}
} else if (sIndirectLayerTrees[aId].mWrBridge) {
MOZ_ASSERT(false); // this should never get called for a WR compositor
}
}
void ContentCompositorBridgeParent::ScheduleComposite(
LayerTransactionParent* aLayerTree) {
LayersId id = aLayerTree->GetId();
MOZ_ASSERT(id.IsValid());
CompositorBridgeParent* parent;
{ // scope lock
MonitorAutoLock lock(*sIndirectLayerTreesLock);
parent = sIndirectLayerTrees[id].mParent;
}
if (parent) {
parent->ScheduleComposite(aLayerTree);
}
}
void ContentCompositorBridgeParent::NotifyClearCachedResources(
LayerTransactionParent* aLayerTree) {
LayersId id = aLayerTree->GetId();
MOZ_ASSERT(id.IsValid());
const CompositorBridgeParent::LayerTreeState* state =
CompositorBridgeParent::GetIndirectShadowTree(id);
if (state && state->mParent) {
// Note that we send this through the window compositor, since this needs
// to reach the widget owning the tab.
Unused << state->mParent->SendObserveLayersUpdate(
id, aLayerTree->GetChildEpoch(), false);
}
}
bool ContentCompositorBridgeParent::SetTestSampleTime(const LayersId& aId,
const TimeStamp& aTime) {
MOZ_ASSERT(aId.IsValid());
const CompositorBridgeParent::LayerTreeState* state =
CompositorBridgeParent::GetIndirectShadowTree(aId);
if (!state) {
return false;
}
MOZ_ASSERT(state->mParent);
return state->mParent->SetTestSampleTime(aId, aTime);
}
void ContentCompositorBridgeParent::LeaveTestMode(const LayersId& aId) {
MOZ_ASSERT(aId.IsValid());
const CompositorBridgeParent::LayerTreeState* state =
CompositorBridgeParent::GetIndirectShadowTree(aId);
if (!state) {
return;
}
MOZ_ASSERT(state->mParent);
state->mParent->LeaveTestMode(aId);
}
void ContentCompositorBridgeParent::ApplyAsyncProperties(
LayerTransactionParent* aLayerTree, TransformsToSkip aSkip) {
LayersId id = aLayerTree->GetId();
MOZ_ASSERT(id.IsValid());
const CompositorBridgeParent::LayerTreeState* state =
CompositorBridgeParent::GetIndirectShadowTree(id);
if (!state) {
return;
}
MOZ_ASSERT(state->mParent);
state->mParent->ApplyAsyncProperties(aLayerTree, aSkip);
}
void ContentCompositorBridgeParent::SetTestAsyncScrollOffset(
const LayersId& aLayersId, const ScrollableLayerGuid::ViewID& aScrollId,
const CSSPoint& aPoint) {
MOZ_ASSERT(aLayersId.IsValid());
const CompositorBridgeParent::LayerTreeState* state =
CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
if (!state) {
return;
}
MOZ_ASSERT(state->mParent);
state->mParent->SetTestAsyncScrollOffset(aLayersId, aScrollId, aPoint);
}
void ContentCompositorBridgeParent::SetTestAsyncZoom(
const LayersId& aLayersId, const ScrollableLayerGuid::ViewID& aScrollId,
const LayerToParentLayerScale& aZoom) {
MOZ_ASSERT(aLayersId.IsValid());
const CompositorBridgeParent::LayerTreeState* state =
CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
if (!state) {
return;
}
MOZ_ASSERT(state->mParent);
state->mParent->SetTestAsyncZoom(aLayersId, aScrollId, aZoom);
}
void ContentCompositorBridgeParent::FlushApzRepaints(
const LayersId& aLayersId) {
MOZ_ASSERT(aLayersId.IsValid());
const CompositorBridgeParent::LayerTreeState* state =
CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
if (!state || !state->mParent) {
return;
}
state->mParent->FlushApzRepaints(aLayersId);
}
void ContentCompositorBridgeParent::GetAPZTestData(const LayersId& aLayersId,
APZTestData* aOutData) {
MOZ_ASSERT(aLayersId.IsValid());
const CompositorBridgeParent::LayerTreeState* state =
CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
if (!state || !state->mParent) {
return;
}
state->mParent->GetAPZTestData(aLayersId, aOutData);
}
void ContentCompositorBridgeParent::GetFrameUniformity(
const LayersId& aLayersId, FrameUniformityData* aOutData) {
MOZ_ASSERT(aLayersId.IsValid());
const CompositorBridgeParent::LayerTreeState* state =
CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
if (!state || !state->mParent) {
return;
}
state->mParent->GetFrameUniformity(aLayersId, aOutData);
}
void ContentCompositorBridgeParent::SetConfirmedTargetAPZC(
const LayersId& aLayersId, const uint64_t& aInputBlockId,
nsTArray<ScrollableLayerGuid>&& aTargets) {
MOZ_ASSERT(aLayersId.IsValid());
const CompositorBridgeParent::LayerTreeState* state =
CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
if (!state || !state->mParent) {
return;
}
state->mParent->SetConfirmedTargetAPZC(aLayersId, aInputBlockId,
std::move(aTargets));
}
AsyncCompositionManager* ContentCompositorBridgeParent::GetCompositionManager(
LayerTransactionParent* aLayerTree) {
LayersId id = aLayerTree->GetId();
const CompositorBridgeParent::LayerTreeState* state =
CompositorBridgeParent::GetIndirectShadowTree(id);
if (!state) {
return nullptr;
}
MOZ_ASSERT(state->mParent);
return state->mParent->GetCompositionManager(aLayerTree);
}
void ContentCompositorBridgeParent::DeferredDestroy() { mSelfRef = nullptr; }
ContentCompositorBridgeParent::~ContentCompositorBridgeParent() {
MOZ_ASSERT(XRE_GetIOMessageLoop());
}
PTextureParent* ContentCompositorBridgeParent::AllocPTextureParent(
const SurfaceDescriptor& aSharedData, const ReadLockDescriptor& aReadLock,
const LayersBackend& aLayersBackend, const TextureFlags& aFlags,
const LayersId& aId, const uint64_t& aSerial,
const wr::MaybeExternalImageId& aExternalImageId) {
CompositorBridgeParent::LayerTreeState* state = nullptr;
LayerTreeMap::iterator itr = sIndirectLayerTrees.find(aId);
if (sIndirectLayerTrees.end() != itr) {
state = &itr->second;
}
TextureFlags flags = aFlags;
LayersBackend actualBackend = LayersBackend::LAYERS_NONE;
if (state && state->mLayerManager) {
actualBackend = state->mLayerManager->GetBackendType();
}
if (!state) {
// The compositor was recreated, and we're receiving layers updates for a
// a layer manager that will soon be discarded or invalidated. We can't
// return null because this will mess up deserialization later and we'll
// kill the content process. Instead, we signal that the underlying
// TextureHost should not attempt to access the compositor.
flags |= TextureFlags::INVALID_COMPOSITOR;
} else if (actualBackend != LayersBackend::LAYERS_NONE &&
aLayersBackend != actualBackend) {
gfxDevCrash(gfx::LogReason::PAllocTextureBackendMismatch)
<< "Texture backend is wrong";
}
return TextureHost::CreateIPDLActor(this, aSharedData, aReadLock,
aLayersBackend, aFlags, aSerial,
aExternalImageId);
}
bool ContentCompositorBridgeParent::DeallocPTextureParent(
PTextureParent* actor) {
return TextureHost::DestroyIPDLActor(actor);
}
mozilla::ipc::IPCResult ContentCompositorBridgeParent::RecvInitPCanvasParent(
Endpoint<PCanvasParent>&& aEndpoint) {
MOZ_RELEASE_ASSERT(!mCanvasTranslator,
"mCanvasTranslator must be released before recreating.");
mCanvasTranslator = CanvasTranslator::Create(std::move(aEndpoint));
return IPC_OK();
}
mozilla::ipc::IPCResult
ContentCompositorBridgeParent::RecvReleasePCanvasParent() {
MOZ_RELEASE_ASSERT(mCanvasTranslator,
"mCanvasTranslator hasn't been created.");
mCanvasTranslator = nullptr;
return IPC_OK();
}
UniquePtr<SurfaceDescriptor>
ContentCompositorBridgeParent::LookupSurfaceDescriptorForClientTexture(
const int64_t aTextureId) {
return mCanvasTranslator->WaitForSurfaceDescriptor(aTextureId);
}
bool ContentCompositorBridgeParent::IsSameProcess() const {
return OtherPid() == base::GetCurrentProcId();
}
void ContentCompositorBridgeParent::UpdatePaintTime(
LayerTransactionParent* aLayerTree, const TimeDuration& aPaintTime) {
LayersId id = aLayerTree->GetId();
MOZ_ASSERT(id.IsValid());
CompositorBridgeParent::LayerTreeState* state =
CompositorBridgeParent::GetIndirectShadowTree(id);
if (!state || !state->mParent) {
return;
}
state->mParent->UpdatePaintTime(aLayerTree, aPaintTime);
}
void ContentCompositorBridgeParent::RegisterPayloads(
LayerTransactionParent* aLayerTree,
const nsTArray<CompositionPayload>& aPayload) {
LayersId id = aLayerTree->GetId();
MOZ_ASSERT(id.IsValid());
CompositorBridgeParent::LayerTreeState* state =
CompositorBridgeParent::GetIndirectShadowTree(id);
if (!state || !state->mParent) {
return;
}
state->mParent->RegisterPayloads(aLayerTree, aPayload);
}
void ContentCompositorBridgeParent::ObserveLayersUpdate(
LayersId aLayersId, LayersObserverEpoch aEpoch, bool aActive) {
MOZ_ASSERT(aLayersId.IsValid());
CompositorBridgeParent::LayerTreeState* state =
CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
if (!state || !state->mParent) {
return;
}
Unused << state->mParent->SendObserveLayersUpdate(aLayersId, aEpoch, aActive);
}
already_AddRefed<dom::PWebGLParent>
ContentCompositorBridgeParent::AllocPWebGLParent() {
RefPtr<dom::PWebGLParent> parent = new dom::WebGLParent();
return parent.forget();
}
} // namespace layers
} // namespace mozilla