author | David Anderson <danderson@mozilla.com> |
Tue, 20 Sep 2016 01:16:03 -0700 | |
changeset 314601 | 5ac08fb77360da01e694dd3fb5fef07a64173298 |
parent 314600 | 320c9cc8fc52abac4589b185a1897b7270e5943e |
child 314602 | 9a6f5fac405ffd3ab59163bf4c5ec866a1bb142b |
push id | 30732 |
push user | cbook@mozilla.com |
push date | Wed, 21 Sep 2016 10:04:03 +0000 |
treeherder | mozilla-central@560b2c805bf7 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mattwoodrow |
bugs | 1300936 |
milestone | 52.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/gfx/ipc/GPUProcessManager.cpp +++ b/gfx/ipc/GPUProcessManager.cpp @@ -238,16 +238,28 @@ GPUProcessManager::OnProcessLaunchComple } void GPUProcessManager::OnProcessUnexpectedShutdown(GPUProcessHost* aHost) { MOZ_ASSERT(mProcess && mProcess == aHost); DestroyProcess(); + + // Build a list of sessions to notify, since notification might delete + // entries from the list. + nsTArray<RefPtr<RemoteCompositorSession>> sessions; + for (auto& session : mRemoteSessions) { + sessions.AppendElement(session); + } + + // Notify. + for (const auto& session : sessions) { + session->NotifySessionLost(); + } } void GPUProcessManager::NotifyRemoteActorDestroyed(const uint64_t& aProcessToken) { if (!NS_IsMainThread()) { RefPtr<Runnable> task = mTaskFactory.NewRunnableMethod( &GPUProcessManager::NotifyRemoteActorDestroyed, aProcessToken); @@ -259,17 +271,17 @@ GPUProcessManager::NotifyRemoteActorDest // This token is for an older process; we can safely ignore it. return; } // One of the bridged top-level actors for the GPU process has been // prematurely terminated, and we're receiving a notification. This // can happen if the ActorDestroy for a bridged protocol fires // before the ActorDestroy for PGPUChild. - DestroyProcess(); + OnProcessUnexpectedShutdown(mProcess); } void GPUProcessManager::CleanShutdown() { if (!mProcess) { return; } @@ -400,17 +412,17 @@ GPUProcessManager::CreateRemoteSession(n PAPZCTreeManagerChild* papz = child->SendPAPZCTreeManagerConstructor(0); if (!papz) { return nullptr; } apz = static_cast<APZCTreeManagerChild*>(papz); } RefPtr<RemoteCompositorSession> session = - new RemoteCompositorSession(child, widget, apz, aRootLayerTreeId); + new RemoteCompositorSession(aWidget, child, widget, apz, aRootLayerTreeId); return session.forget(); #else gfxCriticalNote << "Platform does not support out-of-process compositing"; return nullptr; #endif } bool @@ -584,10 +596,22 @@ GPUProcessManager::EnsureVsyncIOThread() } void GPUProcessManager::ShutdownVsyncIOThread() { mVsyncIOThread = nullptr; } +void +GPUProcessManager::RegisterSession(RemoteCompositorSession* aSession) +{ + mRemoteSessions.AppendElement(aSession); +} + +void +GPUProcessManager::UnregisterSession(RemoteCompositorSession* aSession) +{ + mRemoteSessions.RemoveElement(aSession); +} + } // namespace gfx } // namespace mozilla
--- a/gfx/ipc/GPUProcessManager.h +++ b/gfx/ipc/GPUProcessManager.h @@ -24,45 +24,49 @@ class nsBaseWidget; namespace mozilla { namespace layers { class IAPZCTreeManager; class CompositorSession; class ClientLayerManager; class CompositorUpdateObserver; class PCompositorBridgeChild; class PImageBridgeChild; +class RemoteCompositorSession; } // namespace layers namespace widget { class CompositorWidget; } // namespace widget namespace dom { class ContentParent; class TabParent; } // namespace dom namespace ipc { class GeckoChildProcessHost; } // namespace ipc namespace gfx { class GPUChild; +class PVRManagerChild; class VsyncBridgeChild; class VsyncIOThreadHolder; -class PVRManagerChild; // The GPUProcessManager is a singleton responsible for creating GPU-bound // objects that may live in another process. Currently, it provides access // to the compositor via CompositorBridgeParent. class GPUProcessManager final : public GPUProcessHost::Listener { + friend class layers::RemoteCompositorSession; + typedef layers::ClientLayerManager ClientLayerManager; typedef layers::CompositorSession CompositorSession; typedef layers::IAPZCTreeManager IAPZCTreeManager; typedef layers::CompositorUpdateObserver CompositorUpdateObserver; typedef layers::PCompositorBridgeChild PCompositorBridgeChild; typedef layers::PImageBridgeChild PImageBridgeChild; + typedef layers::RemoteCompositorSession RemoteCompositorSession; public: static void Initialize(); static void Shutdown(); static GPUProcessManager* Get(); ~GPUProcessManager(); @@ -128,16 +132,21 @@ private: bool CreateContentCompositorBridge(base::ProcessId aOtherProcess, ipc::Endpoint<PCompositorBridgeChild>* aOutEndpoint); bool CreateContentImageBridge(base::ProcessId aOtherProcess, ipc::Endpoint<PImageBridgeChild>* aOutEndpoint); bool CreateContentVRManager(base::ProcessId aOtherProcess, ipc::Endpoint<PVRManagerChild>* aOutEndpoint); + // Called from RemoteCompositorSession. We track remote sessions so we can + // notify their owning widgets that the session must be restarted. + void RegisterSession(RemoteCompositorSession* aSession); + void UnregisterSession(RemoteCompositorSession* aSession); + private: GPUProcessManager(); // Permanently disable the GPU process and record a message why. void DisableGPUProcess(const char* aMessage); // Shutdown the GPU process. void CleanShutdown(); @@ -174,16 +183,18 @@ private: friend class Observer; private: RefPtr<Observer> mObserver; ipc::TaskFactory<GPUProcessManager> mTaskFactory; RefPtr<VsyncIOThreadHolder> mVsyncIOThread; uint64_t mNextLayerTreeId; + nsTArray<RefPtr<RemoteCompositorSession>> mRemoteSessions; + // Fields that are associated with the current GPU process. GPUProcessHost* mProcess; MOZ_INIT_OUTSIDE_CTOR uint64_t mProcessToken; GPUChild* mGPUChild; RefPtr<VsyncBridgeChild> mVsyncBridge; }; } // namespace gfx
--- a/gfx/ipc/RemoteCompositorSession.cpp +++ b/gfx/ipc/RemoteCompositorSession.cpp @@ -1,32 +1,51 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=99: */ /* 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 "RemoteCompositorSession.h" - #include "mozilla/layers/APZChild.h" #include "mozilla/layers/APZCTreeManagerChild.h" +#include "nsBaseWidget.h" namespace mozilla { namespace layers { using namespace gfx; using namespace widget; -RemoteCompositorSession::RemoteCompositorSession(CompositorBridgeChild* aChild, +RemoteCompositorSession::RemoteCompositorSession(nsBaseWidget* aWidget, + CompositorBridgeChild* aChild, CompositorWidgetDelegate* aWidgetDelegate, APZCTreeManagerChild* aAPZ, const uint64_t& aRootLayerTreeId) - : CompositorSession(aWidgetDelegate, aChild, aRootLayerTreeId) - , mAPZ(aAPZ) + : CompositorSession(aWidgetDelegate, aChild, aRootLayerTreeId), + mWidget(aWidget), + mAPZ(aAPZ) +{ + GPUProcessManager::Get()->RegisterSession(this); +} + +RemoteCompositorSession::~RemoteCompositorSession() { + // This should have been shutdown first. + MOZ_ASSERT(!mCompositorBridgeChild); +} + +void +RemoteCompositorSession::NotifySessionLost() +{ + // Re-entrancy should be impossible: when we are being notified of a lost + // session, we have by definition not shut down yet. We will shutdown, but + // then will be removed from the notification list. + MOZ_ASSERT(mWidget); + mWidget->NotifyRemoteCompositorSessionLost(this); } CompositorBridgeParent* RemoteCompositorSession::GetInProcessBridge() const { return nullptr; } @@ -43,12 +62,14 @@ RemoteCompositorSession::GetAPZCTreeMana } void RemoteCompositorSession::Shutdown() { mCompositorBridgeChild->Destroy(); mCompositorBridgeChild = nullptr; mCompositorWidgetDelegate = nullptr; + mWidget = nullptr; + GPUProcessManager::Get()->UnregisterSession(this); } } // namespace layers } // namespace mozilla
--- a/gfx/ipc/RemoteCompositorSession.h +++ b/gfx/ipc/RemoteCompositorSession.h @@ -11,26 +11,31 @@ #include "Units.h" namespace mozilla { namespace layers { class RemoteCompositorSession final : public CompositorSession { public: - RemoteCompositorSession(CompositorBridgeChild* aChild, + RemoteCompositorSession(nsBaseWidget* aWidget, + CompositorBridgeChild* aChild, CompositorWidgetDelegate* aWidgetDelegate, APZCTreeManagerChild* aAPZ, const uint64_t& aRootLayerTreeId); + ~RemoteCompositorSession() override; CompositorBridgeParent* GetInProcessBridge() const override; void SetContentController(GeckoContentController* aController) override; RefPtr<IAPZCTreeManager> GetAPZCTreeManager() const override; void Shutdown() override; + void NotifySessionLost(); + private: + nsBaseWidget* mWidget; RefPtr<APZCTreeManagerChild> mAPZ; }; } // namespace layers } // namespace mozilla #endif // include_mozilla_gfx_ipc_RemoteCompositorSession_h
--- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -1365,16 +1365,22 @@ void nsBaseWidget::CreateCompositor(int if (mWindowType == eWindowType_toplevel) { // Only track compositors for top-level windows, since other window types // may use the basic compositor. gfxPlatform::GetPlatform()->NotifyCompositorCreated(mLayerManager->GetCompositorBackendType()); } } +void nsBaseWidget::NotifyRemoteCompositorSessionLost(CompositorSession* aSession) +{ + MOZ_ASSERT(aSession == mCompositorSession); + DestroyLayerManager(); +} + bool nsBaseWidget::ShouldUseOffMainThreadCompositing() { return gfxPlatform::UsesOffMainThreadCompositing(); } LayerManager* nsBaseWidget::GetLayerManager(PLayerTransactionChild* aShadowManager, LayersBackend aBackendHint, LayerManagerPersistence aPersistence)
--- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -187,16 +187,24 @@ public: nsIScreen* aScreen = nullptr) override; void InfallibleMakeFullScreen(bool aFullScreen, nsIScreen* aScreen = nullptr); virtual LayerManager* GetLayerManager(PLayerTransactionChild* aShadowManager = nullptr, LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE, LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT) override; + // A remote compositor session tied to this window has been lost and IPC + // messages will no longer work. The widget must clean up any lingering + // resources and possibly schedule another paint. + // + // A reference to the session object is held until this function has + // returned. + void NotifyRemoteCompositorSessionLost(mozilla::layers::CompositorSession* aSession); + mozilla::CompositorVsyncDispatcher* GetCompositorVsyncDispatcher(); void CreateCompositorVsyncDispatcher(); virtual void CreateCompositor(); virtual void CreateCompositor(int aWidth, int aHeight); virtual void PrepareWindowEffects() override {} virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) override {} virtual void SetModal(bool aModal) override {} virtual uint32_t GetMaxTouchPoints() const override;