ContentCompositorBridgeParent.cpp (16393B)
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 "mozilla/layers/ContentCompositorBridgeParent.h" 8 9 #include <stdint.h> // for uint64_t 10 11 #include "apz/src/APZCTreeManager.h" // for APZCTreeManager 12 #include "gfxUtils.h" 13 #ifdef XP_WIN 14 # include "mozilla/gfx/DeviceManagerDx.h" // for DeviceManagerDx 15 # include "mozilla/layers/ImageDataSerializer.h" 16 #endif 17 #include "mozilla/layers/AnimationHelper.h" // for CompositorAnimationStorage 18 #include "mozilla/layers/APZCTreeManagerParent.h" // for APZCTreeManagerParent 19 #include "mozilla/layers/APZUpdater.h" // for APZUpdater 20 #include "mozilla/layers/CompositorManagerParent.h" 21 #include "mozilla/layers/CompositorOptions.h" 22 #include "mozilla/layers/CompositorThread.h" 23 #include "mozilla/layers/LayerTreeOwnerTracker.h" 24 #include "mozilla/layers/RemoteContentController.h" 25 #include "mozilla/layers/WebRenderBridgeParent.h" 26 #include "mozilla/layers/AsyncImagePipelineManager.h" 27 #include "mozilla/mozalloc.h" // for operator new, etc 28 #include "nsDebug.h" // for NS_ASSERTION, etc 29 #include "nsTArray.h" // for nsTArray 30 #include "nsXULAppAPI.h" // for XRE_GetAsyncIOEventTarget 31 #include "mozilla/StaticPrefs_dom.h" 32 #include "mozilla/StaticPtr.h" 33 #include "mozilla/BaseProfilerMarkerTypes.h" 34 #include "GeckoProfiler.h" 35 36 namespace mozilla::layers { 37 38 void EraseLayerState(LayersId aId); 39 40 void ContentCompositorBridgeParent::ActorDestroy(ActorDestroyReason aWhy) { 41 mCanSend = false; 42 43 // We must keep this object alive untill the code handling message 44 // reception is finished on this thread. 45 GetCurrentSerialEventTarget()->Dispatch(NewRunnableMethod( 46 "layers::ContentCompositorBridgeParent::DeferredDestroy", this, 47 &ContentCompositorBridgeParent::DeferredDestroy)); 48 } 49 50 PAPZCTreeManagerParent* 51 ContentCompositorBridgeParent::AllocPAPZCTreeManagerParent( 52 const LayersId& aLayersId) { 53 // Check to see if this child process has access to this layer tree. 54 if (!LayerTreeOwnerTracker::Get()->IsMapped(aLayersId, OtherPid())) { 55 NS_ERROR( 56 "Unexpected layers id in AllocPAPZCTreeManagerParent; dropping " 57 "message..."); 58 return nullptr; 59 } 60 61 StaticMonitorAutoLock lock(CompositorBridgeParent::sIndirectLayerTreesLock); 62 CompositorBridgeParent::LayerTreeState& state = 63 CompositorBridgeParent::sIndirectLayerTrees[aLayersId]; 64 65 // If the widget has shutdown its compositor, we may not have had a chance yet 66 // to unmap our layers id, and we could get here without a parent compositor. 67 // In this case return an empty APZCTM. 68 if (!state.mParent) { 69 // Note: we immediately call ClearTree since otherwise the APZCTM will 70 // retain a reference to itself, through the checkerboard observer. 71 LayersId dummyId{0}; 72 const bool connectedToWebRender = false; 73 RefPtr<APZCTreeManager> temp = APZCTreeManager::Create(dummyId); 74 RefPtr<APZUpdater> tempUpdater = new APZUpdater(temp, connectedToWebRender); 75 tempUpdater->ClearTree(dummyId); 76 return new APZCTreeManagerParent(aLayersId, temp, tempUpdater); 77 } 78 79 // If we do not have APZ enabled, we should gracefully fail. 80 if (!state.mParent->GetOptions().UseAPZ()) { 81 return nullptr; 82 } 83 84 state.mParent->AllocateAPZCTreeManagerParent(lock, aLayersId, state); 85 return state.mApzcTreeManagerParent; 86 } 87 88 bool ContentCompositorBridgeParent::DeallocPAPZCTreeManagerParent( 89 PAPZCTreeManagerParent* aActor) { 90 APZCTreeManagerParent* parent = static_cast<APZCTreeManagerParent*>(aActor); 91 92 StaticMonitorAutoLock lock(CompositorBridgeParent::sIndirectLayerTreesLock); 93 auto iter = 94 CompositorBridgeParent::sIndirectLayerTrees.find(parent->GetLayersId()); 95 if (iter != CompositorBridgeParent::sIndirectLayerTrees.end()) { 96 CompositorBridgeParent::LayerTreeState& state = iter->second; 97 MOZ_ASSERT(state.mApzcTreeManagerParent == parent); 98 state.mApzcTreeManagerParent = nullptr; 99 } 100 101 delete parent; 102 103 return true; 104 } 105 106 PAPZParent* ContentCompositorBridgeParent::AllocPAPZParent( 107 const LayersId& aLayersId) { 108 // Check to see if this child process has access to this layer tree. 109 if (!LayerTreeOwnerTracker::Get()->IsMapped(aLayersId, OtherPid())) { 110 NS_ERROR("Unexpected layers id in AllocPAPZParent; dropping message..."); 111 return nullptr; 112 } 113 114 RemoteContentController* controller = new RemoteContentController(); 115 116 // Increment the controller's refcount before we return it. This will keep the 117 // controller alive until it is released by IPDL in DeallocPAPZParent. 118 controller->AddRef(); 119 120 StaticMonitorAutoLock lock(CompositorBridgeParent::sIndirectLayerTreesLock); 121 CompositorBridgeParent::LayerTreeState& state = 122 CompositorBridgeParent::sIndirectLayerTrees[aLayersId]; 123 MOZ_ASSERT(!state.mController); 124 state.mController = controller; 125 126 return controller; 127 } 128 129 bool ContentCompositorBridgeParent::DeallocPAPZParent(PAPZParent* aActor) { 130 RemoteContentController* controller = 131 static_cast<RemoteContentController*>(aActor); 132 controller->Release(); 133 return true; 134 } 135 136 PWebRenderBridgeParent* 137 ContentCompositorBridgeParent::AllocPWebRenderBridgeParent( 138 const wr::PipelineId& aPipelineId, const LayoutDeviceIntSize& aSize, 139 const WindowKind& aWindowKind) { 140 LayersId layersId = wr::AsLayersId(aPipelineId); 141 // Check to see if this child process has access to this layer tree. 142 if (!LayerTreeOwnerTracker::Get()->IsMapped(layersId, OtherPid())) { 143 NS_ERROR( 144 "Unexpected layers id in AllocPWebRenderBridgeParent; dropping " 145 "message..."); 146 return nullptr; 147 } 148 149 RefPtr<CompositorBridgeParent> cbp = nullptr; 150 RefPtr<WebRenderBridgeParent> root = nullptr; 151 152 { // scope lock 153 StaticMonitorAutoLock lock(CompositorBridgeParent::sIndirectLayerTreesLock); 154 MOZ_ASSERT(CompositorBridgeParent::sIndirectLayerTrees.find(layersId) != 155 CompositorBridgeParent::sIndirectLayerTrees.end()); 156 MOZ_ASSERT( 157 CompositorBridgeParent::sIndirectLayerTrees[layersId].mWrBridge == 158 nullptr); 159 cbp = CompositorBridgeParent::sIndirectLayerTrees[layersId].mParent; 160 if (cbp) { 161 root = CompositorBridgeParent::sIndirectLayerTrees[cbp->RootLayerTreeId()] 162 .mWrBridge; 163 } 164 } 165 166 RefPtr<wr::WebRenderAPI> api; 167 if (root) { 168 api = root->GetWebRenderAPI(); 169 } 170 171 if (!root || !api) { 172 // This could happen when this function is called after 173 // CompositorBridgeParent destruction. This was observed during Tab move 174 // between different windows. 175 NS_WARNING( 176 nsPrintfCString("Created child without a matching parent? root %p", 177 root.get()) 178 .get()); 179 nsCString error("NO_PARENT"); 180 WebRenderBridgeParent* parent = 181 WebRenderBridgeParent::CreateDestroyed(aPipelineId, std::move(error)); 182 parent->AddRef(); // IPDL reference 183 return parent; 184 } 185 186 api = api->Clone(); 187 RefPtr<AsyncImagePipelineManager> holder = root->AsyncImageManager(); 188 WebRenderBridgeParent* parent = new WebRenderBridgeParent( 189 this, aPipelineId, nullptr, root->CompositorScheduler(), std::move(api), 190 std::move(holder), cbp->GetVsyncInterval()); 191 parent->AddRef(); // IPDL reference 192 193 { // scope lock 194 StaticMonitorAutoLock lock(CompositorBridgeParent::sIndirectLayerTreesLock); 195 CompositorBridgeParent::sIndirectLayerTrees[layersId] 196 .mContentCompositorBridgeParent = this; 197 CompositorBridgeParent::sIndirectLayerTrees[layersId].mWrBridge = parent; 198 } 199 200 return parent; 201 } 202 203 bool ContentCompositorBridgeParent::DeallocPWebRenderBridgeParent( 204 PWebRenderBridgeParent* aActor) { 205 WebRenderBridgeParent* parent = static_cast<WebRenderBridgeParent*>(aActor); 206 EraseLayerState(wr::AsLayersId(parent->PipelineId())); 207 parent->Release(); // IPDL reference 208 return true; 209 } 210 211 mozilla::ipc::IPCResult ContentCompositorBridgeParent::RecvNotifyChildCreated( 212 const LayersId& child, CompositorOptions* aOptions) { 213 StaticMonitorAutoLock lock(CompositorBridgeParent::sIndirectLayerTreesLock); 214 for (auto it = CompositorBridgeParent::sIndirectLayerTrees.begin(); 215 it != CompositorBridgeParent::sIndirectLayerTrees.end(); it++) { 216 CompositorBridgeParent::LayerTreeState& lts = it->second; 217 if (lts.mParent && lts.mContentCompositorBridgeParent == this) { 218 lts.mParent->NotifyChildCreated(child); 219 *aOptions = lts.mParent->GetOptions(); 220 return IPC_OK(); 221 } 222 } 223 return IPC_FAIL_NO_REASON(this); 224 } 225 226 mozilla::ipc::IPCResult 227 ContentCompositorBridgeParent::RecvMapAndNotifyChildCreated( 228 const LayersId& child, const base::ProcessId& pid, 229 CompositorOptions* aOptions) { 230 // This can only be called from the browser process, as the mapping 231 // ensures proper window ownership of layer trees. 232 return IPC_FAIL_NO_REASON(this); 233 } 234 235 mozilla::ipc::IPCResult 236 ContentCompositorBridgeParent::RecvNotifyMemoryPressure() { 237 // This can only be called from the browser process. 238 return IPC_FAIL_NO_REASON(this); 239 } 240 241 mozilla::ipc::IPCResult ContentCompositorBridgeParent::RecvCheckContentOnlyTDR( 242 const uint32_t& sequenceNum, bool* isContentOnlyTDR) { 243 *isContentOnlyTDR = false; 244 #ifdef XP_WIN 245 gfx::ContentDeviceData compositor; 246 247 gfx::DeviceManagerDx* dm = gfx::DeviceManagerDx::Get(); 248 249 // Check that the D3D11 device sequence numbers match. 250 gfx::D3D11DeviceStatus status; 251 dm->ExportDeviceInfo(&status); 252 253 if (sequenceNum == static_cast<uint32_t>(status.sequenceNumber()) && 254 !dm->HasDeviceReset()) { 255 *isContentOnlyTDR = true; 256 } 257 258 #endif 259 return IPC_OK(); 260 }; 261 262 void ContentCompositorBridgeParent::DidCompositeLocked( 263 LayersId aId, const VsyncId& aVsyncId, TimeStamp& aCompositeStart, 264 TimeStamp& aCompositeEnd) { 265 CompositorBridgeParent::sIndirectLayerTreesLock.AssertCurrentThreadOwns(); 266 if (CompositorBridgeParent::sIndirectLayerTrees[aId].mWrBridge) { 267 MOZ_ASSERT(false); // this should never get called for a WR compositor 268 } 269 } 270 271 bool ContentCompositorBridgeParent::SetTestSampleTime(const LayersId& aId, 272 const TimeStamp& aTime) { 273 MOZ_ASSERT(aId.IsValid()); 274 const CompositorBridgeParent::LayerTreeState* state = 275 CompositorBridgeParent::GetIndirectShadowTree(aId); 276 if (!state) { 277 return false; 278 } 279 280 MOZ_ASSERT(state->mParent); 281 return state->mParent->SetTestSampleTime(aId, aTime); 282 } 283 284 void ContentCompositorBridgeParent::LeaveTestMode(const LayersId& aId) { 285 MOZ_ASSERT(aId.IsValid()); 286 const CompositorBridgeParent::LayerTreeState* state = 287 CompositorBridgeParent::GetIndirectShadowTree(aId); 288 if (!state) { 289 return; 290 } 291 292 MOZ_ASSERT(state->mParent); 293 state->mParent->LeaveTestMode(aId); 294 } 295 296 void ContentCompositorBridgeParent::SetTestAsyncScrollOffset( 297 const LayersId& aLayersId, const ScrollableLayerGuid::ViewID& aScrollId, 298 const CSSPoint& aPoint) { 299 MOZ_ASSERT(aLayersId.IsValid()); 300 const CompositorBridgeParent::LayerTreeState* state = 301 CompositorBridgeParent::GetIndirectShadowTree(aLayersId); 302 if (!state) { 303 return; 304 } 305 306 MOZ_ASSERT(state->mParent); 307 state->mParent->SetTestAsyncScrollOffset(aLayersId, aScrollId, aPoint); 308 } 309 310 void ContentCompositorBridgeParent::SetTestAsyncZoom( 311 const LayersId& aLayersId, const ScrollableLayerGuid::ViewID& aScrollId, 312 const LayerToParentLayerScale& aZoom) { 313 MOZ_ASSERT(aLayersId.IsValid()); 314 const CompositorBridgeParent::LayerTreeState* state = 315 CompositorBridgeParent::GetIndirectShadowTree(aLayersId); 316 if (!state) { 317 return; 318 } 319 320 MOZ_ASSERT(state->mParent); 321 state->mParent->SetTestAsyncZoom(aLayersId, aScrollId, aZoom); 322 } 323 324 void ContentCompositorBridgeParent::FlushApzRepaints( 325 const LayersId& aLayersId) { 326 MOZ_ASSERT(aLayersId.IsValid()); 327 const CompositorBridgeParent::LayerTreeState* state = 328 CompositorBridgeParent::GetIndirectShadowTree(aLayersId); 329 if (!state || !state->mParent) { 330 return; 331 } 332 333 state->mParent->FlushApzRepaints(aLayersId); 334 } 335 336 void ContentCompositorBridgeParent::GetAPZTestData(const LayersId& aLayersId, 337 APZTestData* aOutData) { 338 MOZ_ASSERT(aLayersId.IsValid()); 339 const CompositorBridgeParent::LayerTreeState* state = 340 CompositorBridgeParent::GetIndirectShadowTree(aLayersId); 341 if (!state || !state->mParent) { 342 return; 343 } 344 345 state->mParent->GetAPZTestData(aLayersId, aOutData); 346 } 347 348 void ContentCompositorBridgeParent::GetFrameUniformity( 349 const LayersId& aLayersId, FrameUniformityData* aOutData) { 350 MOZ_ASSERT(aLayersId.IsValid()); 351 const CompositorBridgeParent::LayerTreeState* state = 352 CompositorBridgeParent::GetIndirectShadowTree(aLayersId); 353 if (!state || !state->mParent) { 354 return; 355 } 356 357 state->mParent->GetFrameUniformity(aLayersId, aOutData); 358 } 359 360 void ContentCompositorBridgeParent::SetConfirmedTargetAPZC( 361 const LayersId& aLayersId, const uint64_t& aInputBlockId, 362 nsTArray<ScrollableLayerGuid>&& aTargets) { 363 MOZ_ASSERT(aLayersId.IsValid()); 364 const CompositorBridgeParent::LayerTreeState* state = 365 CompositorBridgeParent::GetIndirectShadowTree(aLayersId); 366 if (!state || !state->mParent) { 367 return; 368 } 369 370 state->mParent->SetConfirmedTargetAPZC(aLayersId, aInputBlockId, 371 std::move(aTargets)); 372 } 373 374 void ContentCompositorBridgeParent::EndWheelTransaction( 375 const LayersId& aLayersId, 376 PWebRenderBridgeParent::EndWheelTransactionResolver&& aResolve) { 377 MOZ_ASSERT(aLayersId.IsValid()); 378 const CompositorBridgeParent::LayerTreeState* state = 379 CompositorBridgeParent::GetIndirectShadowTree(aLayersId); 380 if (!state || !state->mParent) { 381 return; 382 } 383 384 state->mParent->EndWheelTransaction(aLayersId, std::move(aResolve)); 385 } 386 387 void ContentCompositorBridgeParent::DeferredDestroy() { mSelfRef = nullptr; } 388 389 ContentCompositorBridgeParent::~ContentCompositorBridgeParent() { 390 MOZ_ASSERT(XRE_GetAsyncIOEventTarget()); 391 } 392 393 PTextureParent* ContentCompositorBridgeParent::AllocPTextureParent( 394 const SurfaceDescriptor& aSharedData, ReadLockDescriptor& aReadLock, 395 const LayersBackend& aLayersBackend, const TextureFlags& aFlags, 396 const LayersId& aId, const uint64_t& aSerial, 397 const wr::MaybeExternalImageId& aExternalImageId) { 398 CompositorBridgeParent::LayerTreeState* state = nullptr; 399 400 StaticMonitorAutoLock lock(CompositorBridgeParent::sIndirectLayerTreesLock); 401 auto itr = CompositorBridgeParent::sIndirectLayerTrees.find(aId); 402 if (CompositorBridgeParent::sIndirectLayerTrees.end() != itr) { 403 state = &itr->second; 404 } 405 406 TextureFlags flags = aFlags; 407 408 LayersBackend actualBackend = LayersBackend::LAYERS_NONE; 409 if (!state) { 410 // The compositor was recreated, and we're receiving layers updates for a 411 // a layer manager that will soon be discarded or invalidated. We can't 412 // return null because this will mess up deserialization later and we'll 413 // kill the content process. Instead, we signal that the underlying 414 // TextureHost should not attempt to access the compositor. 415 flags |= TextureFlags::INVALID_COMPOSITOR; 416 } else if (actualBackend != LayersBackend::LAYERS_NONE && 417 aLayersBackend != actualBackend) { 418 gfxDevCrash(gfx::LogReason::PAllocTextureBackendMismatch) 419 << "Texture backend is wrong"; 420 } 421 422 return TextureHost::CreateIPDLActor( 423 this, aSharedData, std::move(aReadLock), aLayersBackend, aFlags, 424 mCompositorManager->GetContentId(), aSerial, aExternalImageId); 425 } 426 427 bool ContentCompositorBridgeParent::DeallocPTextureParent( 428 PTextureParent* actor) { 429 return TextureHost::DestroyIPDLActor(actor); 430 } 431 432 bool ContentCompositorBridgeParent::IsSameProcess() const { 433 return OtherPid() == base::GetCurrentProcId(); 434 } 435 436 void ContentCompositorBridgeParent::ObserveLayersUpdate(LayersId aLayersId, 437 bool aActive) { 438 MOZ_ASSERT(aLayersId.IsValid()); 439 440 CompositorBridgeParent::LayerTreeState* state = 441 CompositorBridgeParent::GetIndirectShadowTree(aLayersId); 442 if (!state || !state->mParent) { 443 return; 444 } 445 446 (void)state->mParent->SendObserveLayersUpdate(aLayersId, aActive); 447 } 448 449 } // namespace mozilla::layers