Don't reset devices for each tab when the compositor resets. (bug 1316788, r=rhunt)

This commit is contained in:
David Anderson 2016-11-14 11:47:01 -08:00
Родитель c7859ea378
Коммит 2c5e03e62e
19 изменённых файлов: 94 добавлений и 41 удалений

Просмотреть файл

@ -3003,8 +3003,6 @@ TabChild::ReinitRendering()
void
TabChild::CompositorUpdated(const TextureFactoryIdentifier& aNewIdentifier)
{
gfxPlatform::GetPlatform()->CompositorUpdated();
RefPtr<LayerManager> lm = mPuppetWidget->GetLayerManager();
ClientLayerManager* clm = lm->AsClientLayerManager();
MOZ_ASSERT(clm);

Просмотреть файл

@ -45,6 +45,7 @@ public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorSession)
virtual bool Reset(const nsTArray<LayersBackend>& aBackendHints,
uint64_t aSeqNo,
TextureFactoryIdentifier* aOutIdentifier) = 0;
virtual void Shutdown() = 0;

Просмотреть файл

@ -60,6 +60,7 @@ GPUProcessManager::Shutdown()
GPUProcessManager::GPUProcessManager()
: mTaskFactory(this),
mNextLayerTreeId(0),
mNextResetSequenceNo(0),
mNumProcessAttempts(0),
mDeviceResetCount(0),
mProcess(nullptr),
@ -306,10 +307,12 @@ GPUProcessManager::OnProcessDeviceReset(GPUProcessHost* aHost)
HandleProcessLost();
return;
}
uint64_t seqNo = GetNextDeviceResetSequenceNumber();
// We're good, do a reset like normal
for (auto& session : mRemoteSessions) {
session->NotifyDeviceReset();
session->NotifyDeviceReset(seqNo);
}
}

Просмотреть файл

@ -148,6 +148,14 @@ public:
return mNumProcessAttempts > 0;
}
// Returns the next compositor reset sequence number, a monotonic counter
// for when the compositing device resets. Since content processes are
// notified of resets through each individual tab, this allows content to
// only re-acquire devices once for each reset.
uint64_t GetNextDeviceResetSequenceNumber() {
return ++mNextResetSequenceNo;
}
private:
// Called from our xpcom-shutdown observer.
void OnXPCOMShutdown();
@ -213,6 +221,7 @@ private:
ipc::TaskFactory<GPUProcessManager> mTaskFactory;
RefPtr<VsyncIOThreadHolder> mVsyncIOThread;
uint64_t mNextLayerTreeId;
uint64_t mNextResetSequenceNo;
uint32_t mNumProcessAttempts;
nsTArray<RefPtr<RemoteCompositorSession>> mRemoteSessions;

Просмотреть файл

@ -61,9 +61,11 @@ InProcessCompositorSession::GetAPZCTreeManager() const
}
bool
InProcessCompositorSession::Reset(const nsTArray<LayersBackend>& aBackendHints, TextureFactoryIdentifier* aOutIdentifier)
InProcessCompositorSession::Reset(const nsTArray<LayersBackend>& aBackendHints,
uint64_t aSeqNo,
TextureFactoryIdentifier* aOutIdentifier)
{
return mCompositorBridgeParent->ResetCompositor(aBackendHints, aOutIdentifier);
return mCompositorBridgeParent->ResetCompositor(aBackendHints, aSeqNo, aOutIdentifier);
}
void

Просмотреть файл

@ -30,7 +30,9 @@ public:
CompositorBridgeParent* GetInProcessBridge() const override;
void SetContentController(GeckoContentController* aController) override;
RefPtr<IAPZCTreeManager> GetAPZCTreeManager() const override;
bool Reset(const nsTArray<LayersBackend>& aBackendHints, TextureFactoryIdentifier* aOutIdentifier) override;
bool Reset(const nsTArray<LayersBackend>& aBackendHints,
uint64_t aSeqNo,
TextureFactoryIdentifier* aOutIdentifier) override;
void Shutdown() override;
private:

Просмотреть файл

@ -39,10 +39,10 @@ RemoteCompositorSession::~RemoteCompositorSession()
}
void
RemoteCompositorSession::NotifyDeviceReset()
RemoteCompositorSession::NotifyDeviceReset(uint64_t aSeqNo)
{
MOZ_ASSERT(mWidget);
mWidget->OnRenderingDeviceReset();
mWidget->OnRenderingDeviceReset(aSeqNo);
}
void
@ -87,10 +87,12 @@ RemoteCompositorSession::GetAPZCTreeManager() const
}
bool
RemoteCompositorSession::Reset(const nsTArray<LayersBackend>& aBackendHints, TextureFactoryIdentifier* aOutIdentifier)
RemoteCompositorSession::Reset(const nsTArray<LayersBackend>& aBackendHints,
uint64_t aSeqNo,
TextureFactoryIdentifier* aOutIdentifier)
{
bool didReset;
Unused << mCompositorBridgeChild->SendReset(aBackendHints, &didReset, aOutIdentifier);
Unused << mCompositorBridgeChild->SendReset(aBackendHints, aSeqNo, &didReset, aOutIdentifier);
return didReset;
}

Просмотреть файл

@ -28,10 +28,12 @@ public:
GeckoContentController* GetContentController();
nsIWidget* GetWidget();
RefPtr<IAPZCTreeManager> GetAPZCTreeManager() const override;
bool Reset(const nsTArray<LayersBackend>& aBackendHints, TextureFactoryIdentifier* aOutIdentifier) override;
bool Reset(const nsTArray<LayersBackend>& aBackendHints,
uint64_t aSeqNo,
TextureFactoryIdentifier* aOutIdentifier) override;
void Shutdown() override;
void NotifyDeviceReset();
void NotifyDeviceReset(uint64_t aSeqNo);
void NotifySessionLost();
private:

Просмотреть файл

@ -338,12 +338,21 @@ CompositorBridgeChild::RecvInvalidateLayers(const uint64_t& aLayersId)
bool
CompositorBridgeChild::RecvCompositorUpdated(const uint64_t& aLayersId,
const TextureFactoryIdentifier& aNewIdentifier)
const TextureFactoryIdentifier& aNewIdentifier,
const uint64_t& aSeqNo)
{
if (mLayerManager) {
// This case is handled directly by nsBaseWidget.
MOZ_ASSERT(aLayersId == 0);
} else if (aLayersId != 0) {
// Update gfxPlatform if this is the first time we're seeing this compositor
// update (we will get an update for each connected tab).
static uint64_t sLastSeqNo = 0;
if (sLastSeqNo != aSeqNo) {
gfxPlatform::GetPlatform()->CompositorUpdated();
sLastSeqNo = aSeqNo;
}
if (dom::TabChild* child = dom::TabChild::GetFrom(aLayersId)) {
child->CompositorUpdated(aNewIdentifier);
}

Просмотреть файл

@ -103,7 +103,8 @@ public:
virtual bool
RecvCompositorUpdated(const uint64_t& aLayersId,
const TextureFactoryIdentifier& aNewIdentifier) override;
const TextureFactoryIdentifier& aNewIdentifier,
const uint64_t& aSeqNo) override;
virtual bool
RecvOverfill(const uint32_t &aOverfill) override;

Просмотреть файл

@ -684,10 +684,13 @@ CompositorBridgeParent::Initialize()
}
bool
CompositorBridgeParent::RecvReset(nsTArray<LayersBackend>&& aBackendHints, bool* aResult, TextureFactoryIdentifier* aOutIdentifier)
CompositorBridgeParent::RecvReset(nsTArray<LayersBackend>&& aBackendHints,
const uint64_t& aSeqNo,
bool* aResult,
TextureFactoryIdentifier* aOutIdentifier)
{
Maybe<TextureFactoryIdentifier> newIdentifier;
ResetCompositorTask(aBackendHints, &newIdentifier);
ResetCompositorTask(aBackendHints, aSeqNo, &newIdentifier);
if (newIdentifier) {
*aResult = true;
@ -2054,6 +2057,7 @@ CompositorBridgeParent::InvalidateRemoteLayers()
bool
CompositorBridgeParent::ResetCompositor(const nsTArray<LayersBackend>& aBackendHints,
uint64_t aSeqNo,
TextureFactoryIdentifier* aOutIdentifier)
{
Maybe<TextureFactoryIdentifier> newIdentifier;
@ -2062,10 +2066,12 @@ CompositorBridgeParent::ResetCompositor(const nsTArray<LayersBackend>& aBackendH
CompositorLoop()->PostTask(NewRunnableMethod
<StoreCopyPassByConstLRef<nsTArray<LayersBackend>>,
Maybe<TextureFactoryIdentifier>*>(this,
&CompositorBridgeParent::ResetCompositorTask,
aBackendHints,
&newIdentifier));
uint64_t,
Maybe<TextureFactoryIdentifier>*>(this,
&CompositorBridgeParent::ResetCompositorTask,
aBackendHints,
aSeqNo,
&newIdentifier));
mResetCompositorMonitor.Wait();
}
@ -2082,6 +2088,7 @@ CompositorBridgeParent::ResetCompositor(const nsTArray<LayersBackend>& aBackendH
// monitor.
void
CompositorBridgeParent::ResetCompositorTask(const nsTArray<LayersBackend>& aBackendHints,
uint64_t aSeqNo,
Maybe<TextureFactoryIdentifier>* aOutNewIdentifier)
{
// Perform the reset inside a lock, so the main thread can wake up as soon as
@ -2108,7 +2115,7 @@ CompositorBridgeParent::ResetCompositorTask(const nsTArray<LayersBackend>& aBack
MonitorAutoLock lock(*sIndirectLayerTreesLock);
ForEachIndirectLayerTree([&] (LayerTreeState* lts, uint64_t layersId) -> void {
if (CrossProcessCompositorBridgeParent* cpcp = lts->mCrossProcessParent) {
Unused << cpcp->SendCompositorUpdated(layersId, newIdentifier.value());
Unused << cpcp->SendCompositorUpdated(layersId, newIdentifier.value(), aSeqNo);
if (LayerTransactionParent* ltp = lts->mLayerTree) {
ltp->AddPendingCompositorUpdate();

Просмотреть файл

@ -262,7 +262,10 @@ public:
bool Bind(Endpoint<PCompositorBridgeParent>&& aEndpoint);
virtual bool RecvInitialize(const uint64_t& aRootLayerTreeId) override;
virtual bool RecvReset(nsTArray<LayersBackend>&& aBackendHints, bool* aResult, TextureFactoryIdentifier* aOutIdentifier) override;
virtual bool RecvReset(nsTArray<LayersBackend>&& aBackendHints,
const uint64_t& aSeqNo,
bool* aResult,
TextureFactoryIdentifier* aOutIdentifier) override;
virtual bool RecvGetFrameUniformity(FrameUniformityData* aOutData) override;
virtual bool RecvRequestOverfill() override;
virtual bool RecvWillClose() override;
@ -349,6 +352,7 @@ public:
* minimize the amount of time the main thread is blocked.
*/
bool ResetCompositor(const nsTArray<LayersBackend>& aBackendHints,
uint64_t aSeqNo,
TextureFactoryIdentifier* aOutIdentifier);
/**
@ -584,6 +588,7 @@ protected:
RefPtr<Compositor> NewCompositor(const nsTArray<LayersBackend>& aBackendHints);
void ResetCompositorTask(const nsTArray<LayersBackend>& aBackendHints,
uint64_t aSeqNo,
Maybe<TextureFactoryIdentifier>* aOutNewIdentifier);
Maybe<TextureFactoryIdentifier> ResetCompositorImpl(const nsTArray<LayersBackend>& aBackendHints);

Просмотреть файл

@ -42,7 +42,11 @@ public:
// FIXME/bug 774388: work out what shutdown protocol we need.
virtual bool RecvInitialize(const uint64_t& aRootLayerTreeId) override { return false; }
virtual bool RecvReset(nsTArray<LayersBackend>&& aBackendHints, bool* aResult, TextureFactoryIdentifier* aOutIdentifier) override { return false; }
virtual bool RecvReset(nsTArray<LayersBackend>&& aBackendHints,
const uint64_t& aSeqNo,
bool* aResult,
TextureFactoryIdentifier* aOutIdentifier) override
{ return false; }
virtual bool RecvRequestOverfill() override { return true; }
virtual bool RecvWillClose() override { return true; }
virtual bool RecvPause() override { return true; }

Просмотреть файл

@ -62,8 +62,12 @@ child:
// The compositor type or device has changed, and a new texture factory
// identifier is available. Layers must be invalidated and the new identifier
// must be propagated.
async CompositorUpdated(uint64_t layersId, TextureFactoryIdentifier newIdentifier);
// must be propagated. The sequence number is a generation count for the
// compositor.
async CompositorUpdated(
uint64_t layersId,
TextureFactoryIdentifier newIdentifier,
uint64_t seqNo);
// The compositor completed a layers transaction. id is the layers id
// of the child layer tree that was composited (or 0 when notifying
@ -123,7 +127,8 @@ parent:
// When out-of-process, this must be called to finish initialization.
sync Initialize(uint64_t rootLayerTreeId);
sync Reset(LayersBackend[] aBackendHints) returns (bool aResult, TextureFactoryIdentifier aOutIdentifier);
sync Reset(LayersBackend[] aBackendHints, uint64_t aSeqNo)
returns (bool aResult, TextureFactoryIdentifier aOutIdentifier);
// Returns whether this Compositor has APZ enabled or not.
sync AsyncPanZoomEnabled(uint64_t layersId) returns (bool aHasAPZ);

Просмотреть файл

@ -313,7 +313,7 @@ void nsBaseWidget::DestroyLayerManager()
}
void
nsBaseWidget::OnRenderingDeviceReset()
nsBaseWidget::OnRenderingDeviceReset(uint64_t aSeqNo)
{
if (!mLayerManager || !mCompositorSession) {
return;
@ -337,7 +337,7 @@ nsBaseWidget::OnRenderingDeviceReset()
// Recreate the compositor.
TextureFactoryIdentifier identifier;
if (!mCompositorSession->Reset(backendHints, &identifier)) {
if (!mCompositorSession->Reset(backendHints, aSeqNo, &identifier)) {
// No action was taken, so we don't have to do anything.
return;
}

Просмотреть файл

@ -574,7 +574,7 @@ protected:
void EnsureTextEventDispatcher();
// Notify the compositor that a device reset has occurred.
void OnRenderingDeviceReset();
void OnRenderingDeviceReset(uint64_t aSeqNo);
bool UseAPZ();

Просмотреть файл

@ -1160,7 +1160,7 @@ nsWindow::EnumAllChildWindProc(HWND aWnd, LPARAM aParam)
{
nsWindow *wnd = WinUtils::GetNSWindowPtr(aWnd);
if (wnd) {
((nsWindow::WindowEnumCallback*)aParam)(wnd);
reinterpret_cast<nsTArray<nsWindow*>*>(aParam)->AppendElement(wnd);
}
return TRUE;
}
@ -1170,18 +1170,20 @@ nsWindow::EnumAllThreadWindowProc(HWND aWnd, LPARAM aParam)
{
nsWindow *wnd = WinUtils::GetNSWindowPtr(aWnd);
if (wnd) {
((nsWindow::WindowEnumCallback*)aParam)(wnd);
reinterpret_cast<nsTArray<nsWindow*>*>(aParam)->AppendElement(wnd);
}
EnumChildWindows(aWnd, EnumAllChildWindProc, aParam);
return TRUE;
}
void
nsWindow::EnumAllWindows(WindowEnumCallback aCallback)
/* static*/ nsTArray<nsWindow*>
nsWindow::EnumAllWindows()
{
nsTArray<nsWindow*> windows;
EnumThreadWindows(GetCurrentThreadId(),
EnumAllThreadWindowProc,
(LPARAM)aCallback);
reinterpret_cast<LPARAM>(&windows));
return windows;
}
static already_AddRefed<SourceSurface>

Просмотреть файл

@ -254,8 +254,7 @@ public:
WindowHook& GetWindowHook() { return mWindowHook; }
nsWindow* GetParentWindow(bool aIncludeOwner);
// Get an array of all nsWindow*s on the main thread.
typedef void (WindowEnumCallback)(nsWindow*);
static void EnumAllWindows(WindowEnumCallback aCallback);
static nsTArray<nsWindow*> EnumAllWindows();
/**
* Misc.

Просмотреть файл

@ -43,6 +43,7 @@ using mozilla::plugins::PluginInstanceParent;
#include "nsDebug.h"
#include "nsIXULRuntime.h"
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorBridgeChild.h"
#include "ClientLayerManager.h"
@ -172,16 +173,17 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t aNestingLevel)
DeviceResetReason resetReason = DeviceResetReason::OK;
if (gfxWindowsPlatform::GetPlatform()->DidRenderingDeviceReset(&resetReason)) {
gfxCriticalNote << "(nsWindow) Detected device reset: " << (int)resetReason;
gfxWindowsPlatform::GetPlatform()->UpdateRenderMode();
EnumAllWindows([] (nsWindow* aWindow) -> void {
aWindow->OnRenderingDeviceReset();
});
uint64_t resetSeqNo = GPUProcessManager::Get()->GetNextDeviceResetSequenceNumber();
nsTArray<nsWindow*> windows = EnumAllWindows();
for (nsWindow* window : windows) {
window->OnRenderingDeviceReset(resetSeqNo);
}
gfxCriticalNote << "(nsWindow) Finished device reset.";
return false;
}