Commit 276a3fcf by Jamie Madill Committed by Shannon Woods

Fix device removed handling for systems which do not

immediately allow recreating a new device. On Intel systems there's a cool-down period when you must wait before recreating the device. BUG=313210 Change-Id: I22cdf41eecf0eae5058b59e1b0863173d604d606
parent b66fd40e
......@@ -2115,7 +2115,7 @@ bool Renderer9::testDeviceResettable()
return (mDeviceEx != NULL);
case D3DERR_DEVICEREMOVED:
ASSERT(mDeviceEx != NULL);
return true;
return isRemovedDeviceResettable();
default:
return false;
}
......@@ -2129,23 +2129,26 @@ bool Renderer9::resetDevice()
HRESULT result = D3D_OK;
bool lost = testDeviceLost(false);
int attempts = 3;
bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED);
while (lost && attempts > 0)
// Device Removed is a feature which is only present with D3D9Ex
ASSERT(mDeviceEx != NULL || !removedDevice);
for (int attempts = 3; lost && attempts > 0; attempts--)
{
if (mDeviceEx)
if (removedDevice)
{
// Device removed, which may trigger on driver reinstallation,
// may cause a longer wait other reset attempts before the
// system is ready to handle creating a new device.
Sleep(800);
lost = !resetRemovedDevice();
}
else if (mDeviceEx)
{
Sleep(500); // Give the graphics driver some CPU time
if (removedDevice)
{
result = resetRemovedDevice();
}
else
{
result = mDeviceEx->ResetEx(&presentParameters, NULL);
}
result = mDeviceEx->ResetEx(&presentParameters, NULL);
lost = testDeviceLost(false);
}
else
{
......@@ -2160,10 +2163,8 @@ bool Renderer9::resetDevice()
{
result = mDevice->Reset(&presentParameters);
}
lost = testDeviceLost(false);
}
lost = testDeviceLost(false);
attempts --;
}
if (FAILED(result))
......@@ -2172,6 +2173,12 @@ bool Renderer9::resetDevice()
return false;
}
if (removedDevice && lost)
{
ERR("Device lost reset failed multiple times");
return false;
}
// If the device was removed, we already finished re-initialization in resetRemovedDevice
if (!removedDevice)
{
......@@ -2184,15 +2191,38 @@ bool Renderer9::resetDevice()
return true;
}
HRESULT Renderer9::resetRemovedDevice()
bool Renderer9::isRemovedDeviceResettable() const
{
bool success = false;
#ifdef ANGLE_ENABLE_D3D9EX
IDirect3D9Ex *d3d9Ex = NULL;
typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &d3d9Ex)))
{
D3DCAPS9 deviceCaps;
HRESULT result = d3d9Ex->GetDeviceCaps(mAdapter, mDeviceType, &deviceCaps);
success = SUCCEEDED(result);
}
SafeRelease(d3d9Ex);
#else
ASSERT(UNREACHABLE());
#endif
return success;
}
bool Renderer9::resetRemovedDevice()
{
// From http://msdn.microsoft.com/en-us/library/windows/desktop/bb172554(v=vs.85).aspx:
// The hardware adapter has been removed. Application must destroy the device, do enumeration of
// adapters and create another Direct3D device. If application continues rendering without
// calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only.
ASSERT(mDeviceEx != NULL);
deinitialize();
return (initialize() == EGL_SUCCESS ? S_OK : S_FALSE);
return (initialize() == EGL_SUCCESS);
}
DWORD Renderer9::getAdapterVendor() const
......
......@@ -221,7 +221,8 @@ class Renderer9 : public Renderer
void releaseDeviceResources();
HRESULT getDeviceStatusCode();
HRESULT resetRemovedDevice();
bool isRemovedDeviceResettable() const;
bool resetRemovedDevice();
UINT mAdapter;
D3DDEVTYPE mDeviceType;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment