diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 128b4532464..50caa03c4e4 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -192,6 +192,7 @@ #include "mozilla/widget/PuppetBidiKeyboard.h" #include "mozilla/RemoteSpellCheckEngineChild.h" #include "GMPServiceChild.h" +#include "gfxPlatform.h" using namespace mozilla; using namespace mozilla::docshell; @@ -2905,6 +2906,15 @@ ContentChild::RecvEndDragSession(const bool& aDoneDrag, return true; } +bool +ContentChild::RecvTestGraphicsDeviceReset(const uint32_t& aResetReason) +{ +#if defined(XP_WIN) + gfxPlatform::GetPlatform()->TestDeviceReset(DeviceResetReason(aResetReason)); +#endif + return true; +} + } // namespace dom } // namespace mozilla diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 806d12fb694..94963c61fdc 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -469,6 +469,8 @@ public: virtual bool RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent) override; + virtual bool RecvTestGraphicsDeviceReset(const uint32_t& aResetReason) override; + private: virtual void ActorDestroy(ActorDestroyReason why) override; diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index d7b596b7225..ee2f39cf810 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -650,6 +650,12 @@ child: * Send gamepad status update to child. */ GamepadUpdate(GamepadChangeEvent aGamepadEvent); + + /** + * Tell the child that for testing purposes, a graphics device reset has + * occurred. + */ + async TestGraphicsDeviceReset(uint32_t aReason); parent: /** * Tell the content process some attributes of itself. This is diff --git a/gfx/thebes/gfxPlatform.h b/gfx/thebes/gfxPlatform.h index 23a57cebdd8..1fd51509ffc 100644 --- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -642,6 +642,10 @@ public: return mCompositorBackend; } + // Trigger a test-driven graphics device reset. + virtual void TestDeviceReset(DeviceResetReason aReason) + {} + protected: gfxPlatform(); virtual ~gfxPlatform(); diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h index bc97d6de2b4..d326ca3966b 100644 --- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -242,6 +242,7 @@ private: // Note that "gfx.logging.level" is defined in Logging.h DECL_GFX_PREF(Once, "gfx.logging.crash.length", GfxLoggingCrashLength, uint32_t, 6); DECL_GFX_PREF(Live, "gfx.perf-warnings.enabled", PerfWarnings, bool, false); + DECL_GFX_PREF(Live, "gfx.testing.device-reset", DeviceResetForTesting, int32_t, 0); DECL_GFX_PREF(Once, "gfx.touch.resample", TouchResampling, bool, false); // These times should be in milliseconds diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index 79c5fcb34b5..14803f9ae65 100755 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -74,6 +74,7 @@ #include "VsyncSource.h" #include "DriverInitCrashDetection.h" +#include "mozilla/dom/ContentParent.h" using namespace mozilla; using namespace mozilla::gfx; @@ -376,6 +377,7 @@ gfxWindowsPlatform::gfxWindowsPlatform() : mRenderMode(RENDER_GDI) , mIsWARP(false) , mHasDeviceReset(false) + , mHasFakeDeviceReset(false) , mDoesD3D11TextureSharingWork(false) , mAcceleration(FeatureStatus::Unused) , mD3D11Status(FeatureStatus::Unused) @@ -482,7 +484,19 @@ gfxWindowsPlatform::HandleDeviceReset() return false; } - Telemetry::Accumulate(Telemetry::DEVICE_RESET_REASON, uint32_t(resetReason)); + if (mHasFakeDeviceReset) { + if (XRE_IsParentProcess()) { + // Notify child processes that we got a device reset. + nsTArray processes; + dom::ContentParent::GetAll(processes); + + for (size_t i = 0; i < processes.Length(); i++) { + processes[i]->SendTestGraphicsDeviceReset(uint32_t(resetReason)); + } + } + } else { + Telemetry::Accumulate(Telemetry::DEVICE_RESET_REASON, uint32_t(resetReason)); + } // Remove devices and adapters. mD3D10Device = nullptr; @@ -497,6 +511,7 @@ gfxWindowsPlatform::HandleDeviceReset() // will be recomputed by InitializeDevices(). mIsWARP = false; mHasDeviceReset = false; + mHasFakeDeviceReset = false; mDoesD3D11TextureSharingWork = false; mDeviceResetReason = DeviceResetReason::OK; @@ -1109,6 +1124,17 @@ gfxWindowsPlatform::IsDeviceReset(HRESULT hr, DeviceResetReason* aResetReason) return false; } +void +gfxWindowsPlatform::TestDeviceReset(DeviceResetReason aReason) +{ + if (mHasDeviceReset) { + return; + } + mHasDeviceReset = true; + mHasFakeDeviceReset = true; + mDeviceResetReason = aReason; +} + bool gfxWindowsPlatform::DidRenderingDeviceReset(DeviceResetReason* aResetReason) { @@ -1140,6 +1166,14 @@ gfxWindowsPlatform::DidRenderingDeviceReset(DeviceResetReason* aResetReason) return true; } } + if (XRE_IsParentProcess() && gfxPrefs::DeviceResetForTesting()) { + TestDeviceReset((DeviceResetReason)gfxPrefs::DeviceResetForTesting()); + if (aResetReason) { + *aResetReason = mDeviceResetReason; + } + gfxPrefs::SetDeviceResetForTesting(0); + return true; + } return false; } diff --git a/gfx/thebes/gfxWindowsPlatform.h b/gfx/thebes/gfxWindowsPlatform.h index 127e7189f39..388bed8aac8 100644 --- a/gfx/thebes/gfxWindowsPlatform.h +++ b/gfx/thebes/gfxWindowsPlatform.h @@ -275,6 +275,8 @@ public: mozilla::gfx::FeatureStatus GetD2D1Status() const; unsigned GetD3D11Version(); + void TestDeviceReset(DeviceResetReason aReason) override; + virtual already_AddRefed CreateHardwareVsyncSource() override; static mozilla::Atomic sD3D11MemoryUsed; static mozilla::Atomic sD3D9MemoryUsed; @@ -334,6 +336,7 @@ private: mozilla::RefPtr mD3D11ReadbackManager; bool mIsWARP; bool mHasDeviceReset; + bool mHasFakeDeviceReset; bool mDoesD3D11TextureSharingWork; DeviceResetReason mDeviceResetReason;