Bug 1313199 - Sync a device reset from GPU process to main process. r=dvander

--HG--
extra : rebase_source : 4daf0427fee802cd986d7439c0e27eddbf671311
This commit is contained in:
Ryan Hunt 2016-11-06 13:01:52 -06:00
parent fec86bdccd
commit 8ee59ed7da
14 changed files with 97 additions and 0 deletions

View File

@ -7,6 +7,7 @@
#include "gfxConfig.h"
#include "gfxPrefs.h"
#include "GPUProcessHost.h"
#include "GPUProcessManager.h"
#include "mozilla/Telemetry.h"
#include "mozilla/dom/CheckerboardReportService.h"
#include "mozilla/gfx/gfxVars.h"
@ -151,6 +152,13 @@ GPUChild::RecvAccumulateChildKeyedHistogram(InfallibleTArray<KeyedAccumulation>&
return true;
}
bool
GPUChild::RecvNotifyDeviceReset()
{
mHost->mListener->OnProcessDeviceReset(mHost);
return true;
}
void
GPUChild::ActorDestroy(ActorDestroyReason aWhy)
{

View File

@ -43,6 +43,7 @@ public:
void ActorDestroy(ActorDestroyReason aWhy) override;
bool RecvGraphicsError(const nsCString& aError) override;
bool RecvNotifyUiObservers(const nsCString& aTopic) override;
bool RecvNotifyDeviceReset() override;
static void Destroy(UniquePtr<GPUChild>&& aChild);

View File

@ -114,6 +114,30 @@ GPUParent::Init(base::ProcessId aParentPid,
return true;
}
void
GPUParent::NotifyDeviceReset()
{
if (!NS_IsMainThread()) {
NS_DispatchToMainThread(NS_NewRunnableFunction([] () -> void {
GPUParent::GetSingleton()->NotifyDeviceReset();
}));
return;
}
// Reset and reinitialize the compositor devices
#ifdef XP_WIN
if (!DeviceManagerDx::Get()->MaybeResetAndReacquireDevices()) {
// If the device doesn't need to be reset then the device
// has already been reset by a previous NotifyDeviceReset message.
return;
}
#endif
// Notify the main process that there's been a device reset
// and that they should reset their compositors and repaint
Unused << SendNotifyDeviceReset();
}
bool
GPUParent::RecvInit(nsTArray<GfxPrefSetting>&& prefs,
nsTArray<GfxVarUpdate>&& vars,

View File

@ -25,6 +25,7 @@ public:
bool Init(base::ProcessId aParentPid,
MessageLoop* aIOLoop,
IPC::Channel* aChannel);
void NotifyDeviceReset();
bool RecvInit(nsTArray<GfxPrefSetting>&& prefs,
nsTArray<GfxVarUpdate>&& vars,

View File

@ -43,6 +43,9 @@ public:
// Shutdown().
virtual void OnProcessUnexpectedShutdown(GPUProcessHost* aHost)
{}
virtual void OnProcessDeviceReset(GPUProcessHost* aHost)
{}
};
public:

View File

@ -257,6 +257,14 @@ GPUProcessManager::OnProcessLaunchComplete(GPUProcessHost* aHost)
mGPUChild->SendAddLayerTreeIdMapping(mappings);
}
void
GPUProcessManager::OnProcessDeviceReset(GPUProcessHost* aHost)
{
for (auto& session : mRemoteSessions) {
session->NotifyDeviceReset();
}
}
void
GPUProcessManager::OnProcessUnexpectedShutdown(GPUProcessHost* aHost)
{

View File

@ -121,6 +121,7 @@ public:
void OnProcessLaunchComplete(GPUProcessHost* aHost) override;
void OnProcessUnexpectedShutdown(GPUProcessHost* aHost) override;
void OnProcessDeviceReset(GPUProcessHost* aHost) override;
// Notify the GPUProcessManager that a top-level PGPU protocol has been
// terminated. This may be called from any thread.

View File

@ -98,6 +98,8 @@ child:
// Messages for reporting telemetry to the UI process.
async AccumulateChildHistogram(Accumulation[] accumulations);
async AccumulateChildKeyedHistogram(KeyedAccumulation[] accumulations);
async NotifyDeviceReset();
};
} // namespace gfx

View File

@ -38,6 +38,13 @@ RemoteCompositorSession::~RemoteCompositorSession()
MOZ_ASSERT(!mCompositorBridgeChild);
}
void
RemoteCompositorSession::NotifyDeviceReset()
{
MOZ_ASSERT(mWidget);
mWidget->OnRenderingDeviceReset();
}
void
RemoteCompositorSession::NotifySessionLost()
{

View File

@ -31,6 +31,7 @@ public:
bool Reset(const nsTArray<LayersBackend>& aBackendHints, TextureFactoryIdentifier* aOutIdentifier) override;
void Shutdown() override;
void NotifyDeviceReset();
void NotifySessionLost();
private:

View File

@ -12,6 +12,7 @@
#include "nsIWidget.h"
#include "mozilla/gfx/D3D11Checks.h"
#include "mozilla/gfx/DeviceManagerDx.h"
#include "mozilla/gfx/GPUParent.h"
#include "mozilla/layers/ImageHost.h"
#include "mozilla/layers/ContentHost.h"
#include "mozilla/layers/Effects.h"
@ -992,6 +993,13 @@ CompositorD3D11::BeginFrame(const nsIntRegion& aInvalidRegion,
gfxCriticalNote << "GFX: D3D11 skip BeginFrame with device-removed.";
ReadUnlockTextures();
*aRenderBoundsOut = IntRect();
// If we are in the GPU process then the main process doesn't
// know that a device reset has happened and needs to be informed
if (XRE_IsGPUProcess()) {
GPUParent::GetSingleton()->NotifyDeviceReset();
}
return;
}

View File

@ -582,6 +582,32 @@ DeviceManagerDx::ResetDevices()
Factory::SetDirect3D11Device(nullptr);
}
bool
DeviceManagerDx::MaybeResetAndReacquireDevices()
{
DeviceResetReason resetReason;
if (!GetAnyDeviceRemovedReason(&resetReason)) {
return false;
}
Telemetry::Accumulate(Telemetry::DEVICE_RESET_REASON, uint32_t(resetReason));
bool createCompositorDevice = !!mCompositorDevice;
bool createContentDevice = !!mContentDevice;
ResetDevices();
if (createCompositorDevice && !CreateCompositorDevices()) {
// Just stop, don't try anything more
return true;
}
if (createContentDevice) {
CreateContentDevices();
}
return true;
}
bool
DeviceManagerDx::ContentAdapterIsParentAdapter(ID3D11Device* device)
{

View File

@ -80,6 +80,11 @@ public:
// a failure.
bool GetAnyDeviceRemovedReason(DeviceResetReason* aOutReason);
// Reset and reacquire the devices if a reset has happened.
// Returns whether a reset occurred not whether reacquiring
// was successful.
bool MaybeResetAndReacquireDevices();
// Test whether we can acquire a DXGI 1.2-compatible adapter. This should
// only be called on startup before devices are initialized.
bool CheckRemotePresentSupport();

View File

@ -58,6 +58,7 @@ class APZEventState;
class CompositorSession;
class ImageContainer;
struct ScrollableLayerGuid;
class RemoteCompositorSession;
} // namespace layers
namespace widget {
@ -112,6 +113,7 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference
friend class nsAutoRollup;
friend class DispatchWheelEventOnMainThread;
friend class mozilla::widget::InProcessCompositorWidget;
friend class mozilla::layers::RemoteCompositorSession;
protected:
typedef base::Thread Thread;