Bug 626678. Try to handle docking station device resets better. r=bas,a=b
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Wed, 23 Feb 2011 09:18:00 -0800
changeset 62998 8dd9704f8d819f5c19a50e63c8ae47727e9665ce
parent 62997 6aaffde24c3b53cf621e09bd00b2451b9e1407cb
child 62999 004e15c38fa0292551157d9f02d2c8e026db8465
push idunknown
push userunknown
push dateunknown
reviewersbas, b
bugs626678
milestone2.0b13pre
Bug 626678. Try to handle docking station device resets better. r=bas,a=b Docking stations seem to cause DEVICELOST errors that never become DEVICERESET so we don't ever succeed in reseting the device. We now try to detect these situations and recreate the device.
gfx/layers/d3d9/DeviceManagerD3D9.cpp
gfx/layers/d3d9/DeviceManagerD3D9.h
--- a/gfx/layers/d3d9/DeviceManagerD3D9.cpp
+++ b/gfx/layers/d3d9/DeviceManagerD3D9.cpp
@@ -327,16 +327,24 @@ DeviceManagerD3D9::Init()
       return false;
     }
   }
 
   if (!VerifyCaps()) {
     return false;
   }
 
+  /* Grab the associated HMONITOR so that we can find out
+   * if it changed later */
+  D3DDEVICE_CREATION_PARAMETERS parameters;
+  if (FAILED(mDevice->GetCreationParameters(&parameters)))
+    return false;
+  mDeviceMonitor = mD3D9->GetAdapterMonitor(parameters.AdapterOrdinal);
+
+
   /* 
    * Do some post device creation setup 
    */ 
   if (mNv3DVUtils) { 
     IUnknown* devUnknown = NULL; 
     if (mDevice) { 
       mDevice->QueryInterface(IID_IUnknown, (void **)&devUnknown); 
     } 
@@ -555,17 +563,36 @@ DeviceManagerD3D9::VerifyReadyForRenderi
   pp.Windowed = TRUE;
   pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
   pp.hDeviceWindow = mFocusWnd;
 
   hr = mDevice->Reset(&pp);
   ++mDeviceResetCount;
 
   if (hr == D3DERR_DEVICELOST) {
-    return false;
+    /* It is not unusual for Reset to return DEVICELOST
+     * we're supposed to continue trying until we get
+     * DEVICENOTRESET and then Reset is supposed to succeed.
+     * Unfortunately, it seems like when we dock or undock
+     * DEVICELOST happens and we never get DEVICENOTRESET. */
+
+    HMONITOR hMonitorWindow;
+    hMonitorWindow = MonitorFromWindow(mFocusWnd, MONITOR_DEFAULTTOPRIMARY);
+    if (hMonitorWindow == mDeviceMonitor) {
+      /* The monitor has not changed. So, let's assume that the
+       * DEVICENOTRESET will be comming. */
+
+      /* jrmuizel: I'm not sure how to trigger this case. Usually, we get
+       * DEVICENOTRESET right away and Reset() succeeds without going through a
+       * set of DEVICELOSTs. This is presumeably because we don't call
+       * VerifyReadyForRendering when we don't have any reason to paint.
+       * Hopefully comparing HMONITORs is not overly aggressive. */
+      return false;
+    }
+    /* otherwise fall through and recreate the device */
   }
 
   if (FAILED(hr) || !CreateVertexBuffer()) {
     mDeviceWasRemoved = true;
     LayerManagerD3D9::OnDeviceManagerDestroy(this);
     return false;
   }
 
--- a/gfx/layers/d3d9/DeviceManagerD3D9.h
+++ b/gfx/layers/d3d9/DeviceManagerD3D9.h
@@ -228,16 +228,19 @@ private:
   /* Our vertex declaration */
   nsRefPtr<IDirect3DVertexDeclaration9> mVD;
 
   /* Our focus window - this is really a dummy window we can associate our
    * device with.
    */
   HWND mFocusWnd;
 
+  /* we use this to help track if our device temporarily or permanently lost */
+  HMONITOR mDeviceMonitor;
+
   PRUint32 mDeviceResetCount;
 
   /* If this device supports dynamic textures */
   bool mHasDynamicTextures;
 
   /* If this device was removed */
   bool mDeviceWasRemoved;