Add a pref to force TDRs for graphics testing. (bug 1183910 part 2, r=mattwoodrow)
authorDavid Anderson <danderson@mozilla.com>
Thu, 30 Jul 2015 00:23:53 -0700
changeset 287088 1199933ae78ca2294d7e19015d566b23bc8e52b2
parent 287087 b9cc2c3f8bda29fbc48f9772dd9c7fef2f634280
child 287089 e590bfd26a09ef153d681eaafcfb285006b4305e
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1183910
milestone42.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
Add a pref to force TDRs for graphics testing. (bug 1183910 part 2, r=mattwoodrow)
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/PContent.ipdl
gfx/thebes/gfxPlatform.h
gfx/thebes/gfxPrefs.h
gfx/thebes/gfxWindowsPlatform.cpp
gfx/thebes/gfxWindowsPlatform.h
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -187,16 +187,17 @@
 #include "mozilla/dom/DataStoreService.h"
 #include "mozilla/dom/telephony/PTelephonyChild.h"
 #include "mozilla/dom/time/DateCacheCleaner.h"
 #include "mozilla/dom/voicemail/VoicemailIPCService.h"
 #include "mozilla/net/NeckoMessageUtils.h"
 #include "mozilla/widget/PuppetBidiKeyboard.h"
 #include "mozilla/RemoteSpellCheckEngineChild.h"
 #include "GMPServiceChild.h"
+#include "gfxPlatform.h"
 
 using namespace mozilla;
 using namespace mozilla::docshell;
 using namespace mozilla::dom::bluetooth;
 using namespace mozilla::dom::cellbroadcast;
 using namespace mozilla::dom::devicestorage;
 using namespace mozilla::dom::icc;
 using namespace mozilla::dom::ipc;
@@ -2900,16 +2901,25 @@ ContentChild::RecvEndDragSession(const b
         dragSession->UserCancelled();
       }
     }
     dragService->EndDragSession(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
 
 extern "C" {
 
 #if defined(MOZ_NUWA_PROCESS)
 NS_EXPORT void
 GetProtoFdInfos(NuwaProtoFdInfo* aInfoList,
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -464,16 +464,18 @@ public:
     AllocPContentPermissionRequestChild(const InfallibleTArray<PermissionRequest>& aRequests,
                                         const IPC::Principal& aPrincipal,
                                         const TabId& aTabId) override;
     virtual bool
     DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor) override;
 
     virtual bool RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent) override;
 
+    virtual bool RecvTestGraphicsDeviceReset(const uint32_t& aResetReason) override;
+
 private:
     virtual void ActorDestroy(ActorDestroyReason why) override;
 
     virtual void ProcessingError(Result aCode, const char* aReason) override;
 
     /**
      * Exit *now*.  Do not shut down XPCOM, do not pass Go, do not run
      * static destructors, do not collect $200.
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -645,16 +645,22 @@ child:
      * a Windows specific call.
      */
     async UpdateWindow(uintptr_t aChildId);
 
     /**
      * 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
      * among the first information queried by content processes after
      * startup.  (The message is sync to allow the content process to
      * control when it receives the information.)
      *
      * |id| is a unique ID among all subprocesses.  When |isForApp &&
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -637,16 +637,20 @@ public:
      */
     static bool PerfWarnings();
 
     void NotifyCompositorCreated(mozilla::layers::LayersBackend aBackend);
     mozilla::layers::LayersBackend GetCompositorBackend() const {
       return mCompositorBackend;
     }
 
+    // Trigger a test-driven graphics device reset.
+    virtual void TestDeviceReset(DeviceResetReason aReason)
+    {}
+
 protected:
     gfxPlatform();
     virtual ~gfxPlatform();
 
     void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen,
                             eFontPrefLang aCharLang, eFontPrefLang aPageLang);
 
     /**
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -237,16 +237,17 @@ private:
   DECL_GFX_PREF(Live, "gfx.driver-init.status",                DriverInitStatus, int32_t, 0);
   DECL_GFX_PREF(Once, "gfx.font_rendering.directwrite.enabled", DirectWriteFontRenderingEnabled, bool, false);
   DECL_GFX_PREF(Live, "gfx.gralloc.fence-with-readpixels",     GrallocFenceWithReadPixels, bool, false);
   DECL_GFX_PREF(Live, "gfx.layerscope.enabled",                LayerScopeEnabled, bool, false);
   DECL_GFX_PREF(Live, "gfx.layerscope.port",                   LayerScopePort, int32_t, 23456);
   // 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
   DECL_GFX_PREF(Once, "gfx.touch.resample.delay-threshold",    TouchResampleVsyncDelayThreshold, int32_t, 20);
   DECL_GFX_PREF(Once, "gfx.touch.resample.max-predict",        TouchResampleMaxPredict, int32_t, 8);
   DECL_GFX_PREF(Once, "gfx.touch.resample.old-touch-threshold",TouchResampleOldTouchThreshold, int32_t, 17);
   DECL_GFX_PREF(Once, "gfx.touch.resample.vsync-adjust",       TouchVsyncSampleAdjust, int32_t, 5);
 
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -69,16 +69,17 @@
 #include <winternl.h>
 #include "d3dkmtQueryStatistics.h"
 
 #include "SurfaceCache.h"
 #include "gfxPrefs.h"
 
 #include "VsyncSource.h"
 #include "DriverInitCrashDetection.h"
+#include "mozilla/dom/ContentParent.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 using namespace mozilla::widget;
 using namespace mozilla::image;
 
 DCFromDrawTarget::DCFromDrawTarget(DrawTarget& aDrawTarget)
@@ -371,16 +372,17 @@ public:
 };
 
 NS_IMPL_ISUPPORTS(D3D9SharedTextureReporter, nsIMemoryReporter)
 
 gfxWindowsPlatform::gfxWindowsPlatform()
   : mRenderMode(RENDER_GDI)
   , mIsWARP(false)
   , mHasDeviceReset(false)
+  , mHasFakeDeviceReset(false)
   , mDoesD3D11TextureSharingWork(false)
   , mAcceleration(FeatureStatus::Unused)
   , mD3D11Status(FeatureStatus::Unused)
   , mD2DStatus(FeatureStatus::Unused)
   , mD2D1Status(FeatureStatus::Unused)
 {
     mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
     mUseClearTypeAlways = UNINITIALIZED_VALUE;
@@ -477,31 +479,44 @@ gfxWindowsPlatform::InitDWriteSupport()
 bool
 gfxWindowsPlatform::HandleDeviceReset()
 {
   DeviceResetReason resetReason = DeviceResetReason::OK;
   if (!DidRenderingDeviceReset(&resetReason)) {
     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<dom::ContentParent*> 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;
   mD3D11Device = nullptr;
   mD3D11ContentDevice = nullptr;
   mD3D11ImageBridgeDevice = nullptr;
   mAdapter = nullptr;
   Factory::SetDirect3D11Device(nullptr);
   Factory::SetDirect3D10Device(nullptr);
 
   // Reset local state. Note: we leave feature status variables as-is. They
   // will be recomputed by InitializeDevices().
   mIsWARP = false;
   mHasDeviceReset = false;
+  mHasFakeDeviceReset = false;
   mDoesD3D11TextureSharingWork = false;
   mDeviceResetReason = DeviceResetReason::OK;
 
   imgLoader::Singleton()->ClearCache(true);
   imgLoader::Singleton()->ClearCache(false);
   gfxAlphaBoxBlur::ShutdownBlurCache();
 
   InitializeDevices();
@@ -1104,16 +1119,27 @@ gfxWindowsPlatform::IsDeviceReset(HRESUL
     if (aResetReason) {
       *aResetReason = mDeviceResetReason;
     }
     return true;
   }
   return false;
 }
 
+void
+gfxWindowsPlatform::TestDeviceReset(DeviceResetReason aReason)
+{
+  if (mHasDeviceReset) {
+    return;
+  }
+  mHasDeviceReset = true;
+  mHasFakeDeviceReset = true;
+  mDeviceResetReason = aReason;
+}
+
 bool
 gfxWindowsPlatform::DidRenderingDeviceReset(DeviceResetReason* aResetReason)
 {
   if (mHasDeviceReset) {
     if (aResetReason) {
       *aResetReason = mDeviceResetReason;
     }
     return true;
@@ -1135,16 +1161,24 @@ gfxWindowsPlatform::DidRenderingDeviceRe
     }
   }
   if (GetD3D10Device()) {
     HRESULT hr = GetD3D10Device()->GetDeviceRemovedReason();
     if (IsDeviceReset(hr, aResetReason)) {
       return true;
     }
   }
+  if (XRE_IsParentProcess() && gfxPrefs::DeviceResetForTesting()) {
+    TestDeviceReset((DeviceResetReason)gfxPrefs::DeviceResetForTesting());
+    if (aResetReason) {
+      *aResetReason = mDeviceResetReason;
+    }
+    gfxPrefs::SetDeviceResetForTesting(0);
+    return true;
+  }
   return false;
 }
 
 void
 gfxWindowsPlatform::GetPlatformCMSOutputProfile(void* &mem, size_t &mem_size)
 {
     WCHAR str[MAX_PATH];
     DWORD size = MAX_PATH;
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -270,16 +270,18 @@ public:
     // Return the diagnostic status of DirectX initialization. If
     // initialization has not been attempted, this returns
     // FeatureStatus::Unused.
     mozilla::gfx::FeatureStatus GetD3D11Status() const;
     mozilla::gfx::FeatureStatus GetD2DStatus() const;
     mozilla::gfx::FeatureStatus GetD2D1Status() const;
     unsigned GetD3D11Version();
 
+    void TestDeviceReset(DeviceResetReason aReason) override;
+
     virtual already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource() override;
     static mozilla::Atomic<size_t> sD3D11MemoryUsed;
     static mozilla::Atomic<size_t> sD3D9MemoryUsed;
     static mozilla::Atomic<size_t> sD3D9SurfaceImageUsed;
     static mozilla::Atomic<size_t> sD3D9SharedTextureUsed;
 
 protected:
     bool AccelerateLayersByDefault() override {
@@ -329,16 +331,17 @@ private:
     nsRefPtr<mozilla::layers::DeviceManagerD3D9> mDeviceManager;
     mozilla::RefPtr<ID3D10Device1> mD3D10Device;
     mozilla::RefPtr<ID3D11Device> mD3D11Device;
     mozilla::RefPtr<ID3D11Device> mD3D11ContentDevice;
     mozilla::RefPtr<ID3D11Device> mD3D11ImageBridgeDevice;
     mozilla::RefPtr<mozilla::layers::ReadbackManagerD3D11> mD3D11ReadbackManager;
     bool mIsWARP;
     bool mHasDeviceReset;
+    bool mHasFakeDeviceReset;
     bool mDoesD3D11TextureSharingWork;
     DeviceResetReason mDeviceResetReason;
 
     // These should not be accessed directly. Use the Get[Feature]Status
     // accessors instead.
     mozilla::gfx::FeatureStatus mAcceleration;
     mozilla::gfx::FeatureStatus mD3D11Status;
     mozilla::gfx::FeatureStatus mD2DStatus;