When CheckDeviceStats returns S_PRESENT_MODE_CHANGED, reset display mode and retest for device lost.

Unless the display mode is reset, CheckDeviceLost can keep returning S_PRESENT_MODE_CHANGED, potentially masking a device lost on account of a GPU hang, causing ANGLE to fail to report context lost.
Review URL: https://codereview.appspot.com/7381061

git-svn-id: http://angleproject.googlecode.com/svn/trunk@1986 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/common/version.h b/src/common/version.h
index af92aa5..26ea517 100644
--- a/src/common/version.h
+++ b/src/common/version.h
@@ -1,7 +1,7 @@
 #define MAJOR_VERSION 1
 #define MINOR_VERSION 0
 #define BUILD_VERSION 0
-#define BUILD_REVISION 1985
+#define BUILD_REVISION 1986
 
 #define STRINGIFY(x) #x
 #define MACRO_STRINGIFY(x) STRINGIFY(x)
diff --git a/src/libEGL/Display.cpp b/src/libEGL/Display.cpp
index 0d40ad7..db88ffb 100644
--- a/src/libEGL/Display.cpp
+++ b/src/libEGL/Display.cpp
@@ -908,16 +908,32 @@
 
 bool Display::testDeviceLost()
 {
+    bool isLost = false;
+
     if (mDeviceEx)
     {
-        return FAILED(mDeviceEx->CheckDeviceState(NULL));
+        HRESULT hr = mDeviceEx->CheckDeviceState(NULL);
+        if (hr == S_PRESENT_MODE_CHANGED)
+        {
+            // Reset the device so that D3D stops reporting S_PRESENT_MODE_CHANGED. Otherwise it will report
+            // it continuously, potentially masking a lost device. D3D resources are not lost on a mode change with WDDM.
+            D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
+            mDeviceEx->Reset(&presentParameters);
+
+            // Reset will not always cause the device loss to be reported so issue a dummy present.
+            mDeviceEx->Present(NULL, NULL, NULL, NULL);
+
+            // Retest the device status to see if the mode change really indicated a lost device.
+            hr = mDeviceEx->CheckDeviceState(NULL);
+        }
+        isLost = FAILED(hr);
     }
     else if (mDevice)
     {
-        return FAILED(mDevice->TestCooperativeLevel());
+        isLost = FAILED(mDevice->TestCooperativeLevel());
     }
 
-    return false;   // No device yet, so no reset required
+    return isLost;
 }
 
 bool Display::testDeviceResettable()