Reset a lost device before releasing it

TRAC #13622 This prevents the driver from getting stuck in an undefined state and returning errors when trying to create a new device or querying capabilities. Signed-off-by: Daniel Koch Author: Nicolas Capens git-svn-id: https://angleproject.googlecode.com/svn/trunk@436 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 677a1517
......@@ -95,12 +95,22 @@ bool Display::initialize()
// UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to
}
HRESULT result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
HRESULT result;
do
{
result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
if (result == D3DERR_NOTAVAILABLE)
{
Sleep(0); // Give the driver some time to initialize/recover
}
else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from
{
return error(EGL_BAD_ALLOC, false);
}
}
while(result == D3DERR_NOTAVAILABLE);
ASSERT(SUCCEEDED(result));
......@@ -216,6 +226,12 @@ void Display::terminate()
if (mDevice)
{
// If the device is lost, reset it first to prevent leaving the driver in an unstable state
if (FAILED(mDevice->TestCooperativeLevel()))
{
resetDevice();
}
mDevice->Release();
mDevice = NULL;
}
......@@ -314,7 +330,7 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
bool Display::createDevice()
{
D3DPRESENT_PARAMETERS presentParameters = getPresentParameters();
D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
HRESULT result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
......@@ -343,6 +359,29 @@ bool Display::createDevice()
return true;
}
bool Display::resetDevice()
{
D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
HRESULT result;
do
{
Sleep(0); // Give the graphics driver some CPU time
result = mDevice->Reset(&presentParameters);
}
while (result == D3DERR_DEVICELOST);
if (FAILED(result))
{
return error(EGL_BAD_ALLOC, false);
}
ASSERT(SUCCEEDED(result));
return true;
}
Surface *Display::createWindowSurface(HWND window, EGLConfig config)
{
const Config *configuration = mConfigSet.get(config);
......@@ -364,24 +403,11 @@ EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *sha
}
else if (FAILED(mDevice->TestCooperativeLevel())) // Lost device
{
D3DPRESENT_PARAMETERS presentParameters = getPresentParameters();
HRESULT result;
do
{
Sleep(0); // Give the graphics driver some CPU time
result = mDevice->Reset(&presentParameters);
}
while (result == D3DERR_DEVICELOST);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICEREMOVED || result == D3DERR_DRIVERINTERNALERROR)
if (!resetDevice())
{
return error(EGL_BAD_ALLOC, (EGLContext)NULL);
return NULL;
}
ASSERT(SUCCEEDED(result));
// Restore any surfaces that may have been lost
for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
{
......@@ -565,7 +591,7 @@ bool Display::getEventQuerySupport()
return result != D3DERR_NOTAVAILABLE;
}
D3DPRESENT_PARAMETERS Display::getPresentParameters()
D3DPRESENT_PARAMETERS Display::getDefaultPresentParameters()
{
D3DPRESENT_PARAMETERS presentParameters = {0};
......
......@@ -68,7 +68,7 @@ class Display
private:
DISALLOW_COPY_AND_ASSIGN(Display);
D3DPRESENT_PARAMETERS getPresentParameters();
D3DPRESENT_PARAMETERS getDefaultPresentParameters();
const HDC mDc;
......@@ -95,6 +95,7 @@ class Display
ContextSet mContextSet;
bool createDevice();
bool resetDevice();
};
}
......
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