diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp')
-rw-r--r-- | gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp | 578 |
1 files changed, 578 insertions, 0 deletions
diff --git a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp new file mode 100644 index 000000000..1bb6d046b --- /dev/null +++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp @@ -0,0 +1,578 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=2 et 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/CrossProcessCompositorBridgeParent.h" +#include <stdio.h> // for fprintf, stdout +#include <stdint.h> // for uint64_t +#include <map> // for _Rb_tree_iterator, etc +#include <utility> // for pair +#include "LayerTransactionParent.h" // for LayerTransactionParent +#include "RenderTrace.h" // for RenderTraceLayers +#include "base/message_loop.h" // for MessageLoop +#include "base/process.h" // for ProcessId +#include "base/task.h" // for CancelableTask, etc +#include "base/thread.h" // for Thread +#include "gfxContext.h" // for gfxContext +#include "gfxPlatform.h" // for gfxPlatform +#include "TreeTraversal.h" // for ForEachNode +#ifdef MOZ_WIDGET_GTK +#include "gfxPlatformGtk.h" // for gfxPlatform +#endif +#include "gfxPrefs.h" // for gfxPrefs +#include "mozilla/AutoRestore.h" // for AutoRestore +#include "mozilla/ClearOnShutdown.h" // for ClearOnShutdown +#include "mozilla/DebugOnly.h" // for DebugOnly +#include "mozilla/dom/ContentParent.h" +#include "mozilla/dom/TabParent.h" +#include "mozilla/gfx/2D.h" // for DrawTarget +#include "mozilla/gfx/Point.h" // for IntSize +#include "mozilla/gfx/Rect.h" // for IntSize +#include "VRManager.h" // for VRManager +#include "mozilla/ipc/Transport.h" // for Transport +#include "mozilla/layers/APZCTreeManager.h" // for APZCTreeManager +#include "mozilla/layers/APZCTreeManagerParent.h" // for APZCTreeManagerParent +#include "mozilla/layers/APZThreadUtils.h" // for APZCTreeManager +#include "mozilla/layers/AsyncCompositionManager.h" +#include "mozilla/layers/BasicCompositor.h" // for BasicCompositor +#include "mozilla/layers/Compositor.h" // for Compositor +#include "mozilla/layers/CompositorOGL.h" // for CompositorOGL +#include "mozilla/layers/CompositorThread.h" +#include "mozilla/layers/CompositorTypes.h" +#include "mozilla/layers/FrameUniformityData.h" +#include "mozilla/layers/ImageBridgeParent.h" +#include "mozilla/layers/LayerManagerComposite.h" +#include "mozilla/layers/LayerTreeOwnerTracker.h" +#include "mozilla/layers/LayersTypes.h" +#include "mozilla/layers/PLayerTransactionParent.h" +#include "mozilla/layers/RemoteContentController.h" +#include "mozilla/layout/RenderFrameParent.h" +#include "mozilla/media/MediaSystemResourceService.h" // for MediaSystemResourceService +#include "mozilla/mozalloc.h" // for operator new, etc +#include "mozilla/Telemetry.h" +#ifdef MOZ_WIDGET_GTK +#include "basic/X11BasicCompositor.h" // for X11BasicCompositor +#endif +#include "nsCOMPtr.h" // for already_AddRefed +#include "nsDebug.h" // for NS_ASSERTION, etc +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc +#include "nsIWidget.h" // for nsIWidget +#include "nsTArray.h" // for nsTArray +#include "nsThreadUtils.h" // for NS_IsMainThread +#include "nsXULAppAPI.h" // for XRE_GetIOMessageLoop +#ifdef XP_WIN +#include "mozilla/layers/CompositorD3D11.h" +#include "mozilla/layers/CompositorD3D9.h" +#endif +#include "GeckoProfiler.h" +#include "mozilla/ipc/ProtocolTypes.h" +#include "mozilla/Unused.h" +#include "mozilla/Hal.h" +#include "mozilla/HalTypes.h" +#include "mozilla/StaticPtr.h" +#include "mozilla/Telemetry.h" +#ifdef MOZ_ENABLE_PROFILER_SPS +#include "ProfilerMarkers.h" +#endif +#include "mozilla/VsyncDispatcher.h" +#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) +#include "VsyncSource.h" +#endif +#include "mozilla/widget/CompositorWidget.h" +#ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING +# include "mozilla/widget/CompositorWidgetParent.h" +#endif + +#include "LayerScope.h" + +namespace mozilla { + +namespace layers { + +// defined in CompositorBridgeParent.cpp +typedef map<uint64_t, CompositorBridgeParent::LayerTreeState> LayerTreeMap; +extern LayerTreeMap sIndirectLayerTrees; +extern StaticAutoPtr<mozilla::Monitor> sIndirectLayerTreesLock; + +bool +CrossProcessCompositorBridgeParent::RecvRequestNotifyAfterRemotePaint() +{ + mNotifyAfterRemotePaint = true; + return true; +} + +void +CrossProcessCompositorBridgeParent::ActorDestroy(ActorDestroyReason aWhy) +{ + // We must keep this object alive untill the code handling message + // reception is finished on this thread. + MessageLoop::current()->PostTask(NewRunnableMethod(this, &CrossProcessCompositorBridgeParent::DeferredDestroy)); +} + +PLayerTransactionParent* +CrossProcessCompositorBridgeParent::AllocPLayerTransactionParent( + const nsTArray<LayersBackend>&, + const uint64_t& aId, + TextureFactoryIdentifier* aTextureFactoryIdentifier, + bool *aSuccess) +{ + MOZ_ASSERT(aId != 0); + + // 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->mCrossProcessParent = this; + LayerManagerComposite* lm = state->mLayerManager; + *aTextureFactoryIdentifier = lm->GetCompositor()->GetTextureFactoryIdentifier(); + *aSuccess = true; + LayerTransactionParent* p = new LayerTransactionParent(lm, this, aId); + p->AddIPDLReference(); + sIndirectLayerTrees[aId].mLayerTree = p; + p->SetPendingCompositorUpdates(state->mPendingCompositorUpdates); + return p; + } + + NS_WARNING("Created child without a matching parent?"); + *aSuccess = false; + LayerTransactionParent* p = new LayerTransactionParent(nullptr, this, aId); + p->AddIPDLReference(); + return p; +} + +bool +CrossProcessCompositorBridgeParent::DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers) +{ + LayerTransactionParent* slp = static_cast<LayerTransactionParent*>(aLayers); + EraseLayerState(slp->GetId()); + static_cast<LayerTransactionParent*>(aLayers)->ReleaseIPDLReference(); + return true; +} + +bool +CrossProcessCompositorBridgeParent::RecvAsyncPanZoomEnabled(const uint64_t& aLayersId, bool* aHasAPZ) +{ + // 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 RecvAsyncPanZoomEnabled; dropping message..."); + return false; + } + + MonitorAutoLock lock(*sIndirectLayerTreesLock); + CompositorBridgeParent::LayerTreeState& state = sIndirectLayerTrees[aLayersId]; + + *aHasAPZ = state.mParent ? state.mParent->AsyncPanZoomEnabled() : false; + return true; +} + +PAPZCTreeManagerParent* +CrossProcessCompositorBridgeParent::AllocPAPZCTreeManagerParent(const uint64_t& 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]; + MOZ_ASSERT(state.mParent); + MOZ_ASSERT(!state.mApzcTreeManagerParent); + state.mApzcTreeManagerParent = new APZCTreeManagerParent(aLayersId, state.mParent->GetAPZCTreeManager()); + + return state.mApzcTreeManagerParent; +} +bool +CrossProcessCompositorBridgeParent::DeallocPAPZCTreeManagerParent(PAPZCTreeManagerParent* aActor) +{ + APZCTreeManagerParent* parent = static_cast<APZCTreeManagerParent*>(aActor); + + MonitorAutoLock lock(*sIndirectLayerTreesLock); + auto iter = sIndirectLayerTrees.find(parent->LayersId()); + if (iter != sIndirectLayerTrees.end()) { + CompositorBridgeParent::LayerTreeState& state = iter->second; + MOZ_ASSERT(state.mApzcTreeManagerParent == parent); + state.mApzcTreeManagerParent = nullptr; + } + + delete parent; + + return true; +} + +PAPZParent* +CrossProcessCompositorBridgeParent::AllocPAPZParent(const uint64_t& 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 +CrossProcessCompositorBridgeParent::DeallocPAPZParent(PAPZParent* aActor) +{ + RemoteContentController* controller = static_cast<RemoteContentController*>(aActor); + controller->Release(); + return true; +} + +bool +CrossProcessCompositorBridgeParent::RecvNotifyChildCreated(const uint64_t& child) +{ + MonitorAutoLock lock(*sIndirectLayerTreesLock); + for (LayerTreeMap::iterator it = sIndirectLayerTrees.begin(); + it != sIndirectLayerTrees.end(); it++) { + CompositorBridgeParent::LayerTreeState* lts = &it->second; + if (lts->mParent && lts->mCrossProcessParent == this) { + lts->mParent->NotifyChildCreated(child); + return true; + } + } + return false; +} + +void +CrossProcessCompositorBridgeParent::ShadowLayersUpdated( + LayerTransactionParent* aLayerTree, + const uint64_t& aTransactionId, + const TargetConfig& aTargetConfig, + const InfallibleTArray<PluginWindowData>& aPlugins, + bool aIsFirstPaint, + bool aScheduleComposite, + uint32_t aPaintSequenceNumber, + bool aIsRepeatTransaction, + int32_t /*aPaintSyncId: unused*/, + bool aHitTestUpdate) +{ + uint64_t id = aLayerTree->GetId(); + + MOZ_ASSERT(id != 0); + + CompositorBridgeParent::LayerTreeState* state = + CompositorBridgeParent::GetIndirectShadowTree(id); + if (!state) { + return; + } + MOZ_ASSERT(state->mParent); + state->mParent->ScheduleRotationOnCompositorThread(aTargetConfig, aIsFirstPaint); + + Layer* shadowRoot = aLayerTree->GetRoot(); + if (shadowRoot) { + CompositorBridgeParent::SetShadowProperties(shadowRoot); + } + UpdateIndirectTree(id, shadowRoot, aTargetConfig); + + // Cache the plugin data for this remote layer tree + state->mPluginData = aPlugins; + state->mUpdatedPluginDataAvailable = true; + + state->mParent->NotifyShadowTreeTransaction(id, aIsFirstPaint, aScheduleComposite, + aPaintSequenceNumber, aIsRepeatTransaction, 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->SendObserveLayerUpdate(id, aLayerTree->GetChildEpoch(), true); + } + + aLayerTree->SetPendingTransactionId(aTransactionId); +} + +void +CrossProcessCompositorBridgeParent::DidComposite( + uint64_t aId, + TimeStamp& aCompositeStart, + TimeStamp& aCompositeEnd) +{ + sIndirectLayerTreesLock->AssertCurrentThreadOwns(); + if (LayerTransactionParent *layerTree = sIndirectLayerTrees[aId].mLayerTree) { + Unused << SendDidComposite(aId, layerTree->GetPendingTransactionId(), aCompositeStart, aCompositeEnd); + layerTree->SetPendingTransactionId(0); + } +} + +void +CrossProcessCompositorBridgeParent::ForceComposite(LayerTransactionParent* aLayerTree) +{ + uint64_t id = aLayerTree->GetId(); + MOZ_ASSERT(id != 0); + CompositorBridgeParent* parent; + { // scope lock + MonitorAutoLock lock(*sIndirectLayerTreesLock); + parent = sIndirectLayerTrees[id].mParent; + } + if (parent) { + parent->ForceComposite(aLayerTree); + } +} + +void +CrossProcessCompositorBridgeParent::NotifyClearCachedResources(LayerTransactionParent* aLayerTree) +{ + uint64_t id = aLayerTree->GetId(); + MOZ_ASSERT(id != 0); + + 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->SendObserveLayerUpdate(id, aLayerTree->GetChildEpoch(), false); + } +} + +bool +CrossProcessCompositorBridgeParent::SetTestSampleTime( + LayerTransactionParent* aLayerTree, const TimeStamp& aTime) +{ + uint64_t id = aLayerTree->GetId(); + MOZ_ASSERT(id != 0); + const CompositorBridgeParent::LayerTreeState* state = + CompositorBridgeParent::GetIndirectShadowTree(id); + if (!state) { + return false; + } + + MOZ_ASSERT(state->mParent); + return state->mParent->SetTestSampleTime(aLayerTree, aTime); +} + +void +CrossProcessCompositorBridgeParent::LeaveTestMode(LayerTransactionParent* aLayerTree) +{ + uint64_t id = aLayerTree->GetId(); + MOZ_ASSERT(id != 0); + const CompositorBridgeParent::LayerTreeState* state = + CompositorBridgeParent::GetIndirectShadowTree(id); + if (!state) { + return; + } + + MOZ_ASSERT(state->mParent); + state->mParent->LeaveTestMode(aLayerTree); +} + +void +CrossProcessCompositorBridgeParent::ApplyAsyncProperties( + LayerTransactionParent* aLayerTree) +{ + uint64_t id = aLayerTree->GetId(); + MOZ_ASSERT(id != 0); + const CompositorBridgeParent::LayerTreeState* state = + CompositorBridgeParent::GetIndirectShadowTree(id); + if (!state) { + return; + } + + MOZ_ASSERT(state->mParent); + state->mParent->ApplyAsyncProperties(aLayerTree); +} + +void +CrossProcessCompositorBridgeParent::FlushApzRepaints(const LayerTransactionParent* aLayerTree) +{ + uint64_t id = aLayerTree->GetId(); + MOZ_ASSERT(id != 0); + const CompositorBridgeParent::LayerTreeState* state = + CompositorBridgeParent::GetIndirectShadowTree(id); + if (!state) { + return; + } + + MOZ_ASSERT(state->mParent); + state->mParent->FlushApzRepaints(aLayerTree); +} + +void +CrossProcessCompositorBridgeParent::GetAPZTestData( + const LayerTransactionParent* aLayerTree, + APZTestData* aOutData) +{ + uint64_t id = aLayerTree->GetId(); + MOZ_ASSERT(id != 0); + MonitorAutoLock lock(*sIndirectLayerTreesLock); + *aOutData = sIndirectLayerTrees[id].mApzTestData; +} + +void +CrossProcessCompositorBridgeParent::SetConfirmedTargetAPZC( + const LayerTransactionParent* aLayerTree, + const uint64_t& aInputBlockId, + const nsTArray<ScrollableLayerGuid>& aTargets) +{ + uint64_t id = aLayerTree->GetId(); + MOZ_ASSERT(id != 0); + const CompositorBridgeParent::LayerTreeState* state = + CompositorBridgeParent::GetIndirectShadowTree(id); + if (!state || !state->mParent) { + return; + } + + state->mParent->SetConfirmedTargetAPZC(aLayerTree, aInputBlockId, aTargets); +} + +AsyncCompositionManager* +CrossProcessCompositorBridgeParent::GetCompositionManager(LayerTransactionParent* aLayerTree) +{ + uint64_t id = aLayerTree->GetId(); + const CompositorBridgeParent::LayerTreeState* state = + CompositorBridgeParent::GetIndirectShadowTree(id); + if (!state) { + return nullptr; + } + + MOZ_ASSERT(state->mParent); + return state->mParent->GetCompositionManager(aLayerTree); +} + +bool +CrossProcessCompositorBridgeParent::RecvAcknowledgeCompositorUpdate(const uint64_t& aLayersId) +{ + MonitorAutoLock lock(*sIndirectLayerTreesLock); + CompositorBridgeParent::LayerTreeState& state = sIndirectLayerTrees[aLayersId]; + + if (LayerTransactionParent* ltp = state.mLayerTree) { + ltp->AcknowledgeCompositorUpdate(); + } + MOZ_ASSERT(state.mPendingCompositorUpdates > 0); + state.mPendingCompositorUpdates--; + return true; +} + +void +CrossProcessCompositorBridgeParent::DeferredDestroy() +{ + mCompositorThreadHolder = nullptr; + mSelfRef = nullptr; +} + +CrossProcessCompositorBridgeParent::~CrossProcessCompositorBridgeParent() +{ + MOZ_ASSERT(XRE_GetIOMessageLoop()); + MOZ_ASSERT(IToplevelProtocol::GetTransport()); +} + +PTextureParent* +CrossProcessCompositorBridgeParent::AllocPTextureParent(const SurfaceDescriptor& aSharedData, + const LayersBackend& aLayersBackend, + const TextureFlags& aFlags, + const uint64_t& aId, + const uint64_t& aSerial) +{ + CompositorBridgeParent::LayerTreeState* state = nullptr; + + LayerTreeMap::iterator itr = sIndirectLayerTrees.find(aId); + if (sIndirectLayerTrees.end() != itr) { + state = &itr->second; + } + + TextureFlags flags = aFlags; + + if (!state || state->mPendingCompositorUpdates) { + // 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 (state->mLayerManager && state->mLayerManager->GetCompositor() && + aLayersBackend != state->mLayerManager->GetCompositor()->GetBackendType()) { + gfxDevCrash(gfx::LogReason::PAllocTextureBackendMismatch) << "Texture backend is wrong"; + } + + return TextureHost::CreateIPDLActor(this, aSharedData, aLayersBackend, aFlags, aSerial); +} + +bool +CrossProcessCompositorBridgeParent::DeallocPTextureParent(PTextureParent* actor) +{ + return TextureHost::DestroyIPDLActor(actor); +} + +bool +CrossProcessCompositorBridgeParent::IsSameProcess() const +{ + return OtherPid() == base::GetCurrentProcId(); +} + +bool +CrossProcessCompositorBridgeParent::RecvClearApproximatelyVisibleRegions(const uint64_t& aLayersId, + const uint32_t& aPresShellId) +{ + CompositorBridgeParent* parent; + { // scope lock + MonitorAutoLock lock(*sIndirectLayerTreesLock); + parent = sIndirectLayerTrees[aLayersId].mParent; + } + if (parent) { + parent->ClearApproximatelyVisibleRegions(aLayersId, Some(aPresShellId)); + } + return true; +} + +bool +CrossProcessCompositorBridgeParent::RecvNotifyApproximatelyVisibleRegion(const ScrollableLayerGuid& aGuid, + const CSSIntRegion& aRegion) +{ + CompositorBridgeParent* parent; + { // scope lock + MonitorAutoLock lock(*sIndirectLayerTreesLock); + parent = sIndirectLayerTrees[aGuid.mLayersId].mParent; + } + if (parent) { + return parent->RecvNotifyApproximatelyVisibleRegion(aGuid, aRegion); + } + return true; +} + +void +CrossProcessCompositorBridgeParent::UpdatePaintTime(LayerTransactionParent* aLayerTree, const TimeDuration& aPaintTime) +{ + uint64_t id = aLayerTree->GetId(); + MOZ_ASSERT(id != 0); + + CompositorBridgeParent::LayerTreeState* state = + CompositorBridgeParent::GetIndirectShadowTree(id); + if (!state || !state->mParent) { + return; + } + + state->mParent->UpdatePaintTime(aLayerTree, aPaintTime); +} + +} // namespace layers +} // namespace mozilla |