Implemented recovering from a lost device by context recreation.

TRAC #13222 Singed-off-by: Daniel Koch Author: Nicolas Capens <nicolas@transgaming.com> git-svn-id: https://angleproject.googlecode.com/svn/trunk@406 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent d3bd0ad3
...@@ -17,7 +17,8 @@ ...@@ -17,7 +17,8 @@
#include "libEGL/main.h" #include "libEGL/main.h"
#define REF_RAST 0 // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros #define REF_RAST 0 // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
#define ENABLE_D3D9EX 1 // Enables use of the IDirect3D9Ex interface, when available
namespace egl namespace egl
{ {
...@@ -77,7 +78,7 @@ bool Display::initialize() ...@@ -77,7 +78,7 @@ bool Display::initialize()
// Use Direct3D9Ex if available. Among other things, this version is less // Use Direct3D9Ex if available. Among other things, this version is less
// inclined to report a lost context, for example when the user switches // inclined to report a lost context, for example when the user switches
// desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available. // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9ex))) if (ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9ex)))
{ {
ASSERT(mD3d9ex); ASSERT(mD3d9ex);
mD3d9ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9)); mD3d9ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
...@@ -102,6 +103,8 @@ bool Display::initialize() ...@@ -102,6 +103,8 @@ bool Display::initialize()
return error(EGL_BAD_ALLOC, false); return error(EGL_BAD_ALLOC, false);
} }
ASSERT(SUCCEEDED(result));
if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0)) if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0))
{ {
terminate(); terminate();
...@@ -183,13 +186,6 @@ bool Display::initialize() ...@@ -183,13 +186,6 @@ bool Display::initialize()
mConfigSet.mSet.insert(configuration); mConfigSet.mSet.insert(configuration);
} }
if (!createDevice())
{
terminate();
return false;
}
} }
if (!isInitialized()) if (!isInitialized())
...@@ -199,6 +195,11 @@ bool Display::initialize() ...@@ -199,6 +195,11 @@ bool Display::initialize()
return false; return false;
} }
static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
static const TCHAR className[] = TEXT("STATIC");
mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
return true; return true;
} }
...@@ -314,28 +315,7 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) ...@@ -314,28 +315,7 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
bool Display::createDevice() bool Display::createDevice()
{ {
static const TCHAR windowName[] = TEXT("AngleHiddenWindow"); D3DPRESENT_PARAMETERS presentParameters = getPresentParameters();
static const TCHAR className[] = TEXT("STATIC");
mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
D3DPRESENT_PARAMETERS presentParameters = {0};
// The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters.
presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
presentParameters.BackBufferCount = 1;
presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
presentParameters.BackBufferWidth = 1;
presentParameters.BackBufferHeight = 1;
presentParameters.EnableAutoDepthStencil = FALSE;
presentParameters.Flags = 0;
presentParameters.hDeviceWindow = mDeviceWindow;
presentParameters.MultiSampleQuality = 0;
presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
presentParameters.PresentationInterval = convertInterval(mMinSwapInterval);
presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
presentParameters.Windowed = TRUE;
DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES; DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
HRESULT result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); HRESULT result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
...@@ -377,6 +357,40 @@ Surface *Display::createWindowSurface(HWND window, EGLConfig config) ...@@ -377,6 +357,40 @@ Surface *Display::createWindowSurface(HWND window, EGLConfig config)
EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext) EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext)
{ {
if (!mDevice)
{
if (!createDevice())
{
return NULL;
}
}
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)
{
return error(EGL_BAD_ALLOC, (EGLContext)NULL);
}
ASSERT(SUCCEEDED(result));
// Restore any surfaces that may have been lost
for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
{
(*surface)->resetSwapChain();
}
}
const egl::Config *config = mConfigSet.get(configHandle); const egl::Config *config = mConfigSet.get(configHandle);
gl::Context *context = glCreateContext(config, shareContext); gl::Context *context = glCreateContext(config, shareContext);
...@@ -395,6 +409,14 @@ void Display::destroyContext(gl::Context *context) ...@@ -395,6 +409,14 @@ void Display::destroyContext(gl::Context *context)
{ {
glDestroyContext(context); glDestroyContext(context);
mContextSet.erase(context); mContextSet.erase(context);
if (mContextSet.empty() && mDevice && FAILED(mDevice->TestCooperativeLevel())) // Last context of a lost device
{
for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
{
(*surface)->release();
}
}
} }
bool Display::isInitialized() bool Display::isInitialized()
...@@ -461,6 +483,14 @@ DWORD Display::convertInterval(GLint interval) ...@@ -461,6 +483,14 @@ DWORD Display::convertInterval(GLint interval)
IDirect3DDevice9 *Display::getDevice() IDirect3DDevice9 *Display::getDevice()
{ {
if (!mDevice)
{
if (!createDevice())
{
return NULL;
}
}
return mDevice; return mDevice;
} }
...@@ -541,4 +571,26 @@ bool Display::getEventQuerySupport() ...@@ -541,4 +571,26 @@ bool Display::getEventQuerySupport()
return result != D3DERR_NOTAVAILABLE; return result != D3DERR_NOTAVAILABLE;
} }
D3DPRESENT_PARAMETERS Display::getPresentParameters()
{
D3DPRESENT_PARAMETERS presentParameters = {0};
// The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters.
presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
presentParameters.BackBufferCount = 1;
presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
presentParameters.BackBufferWidth = 1;
presentParameters.BackBufferHeight = 1;
presentParameters.EnableAutoDepthStencil = FALSE;
presentParameters.Flags = 0;
presentParameters.hDeviceWindow = mDeviceWindow;
presentParameters.MultiSampleQuality = 0;
presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
presentParameters.PresentationInterval = convertInterval(mMinSwapInterval);
presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
presentParameters.Windowed = TRUE;
return presentParameters;
} }
}
\ No newline at end of file
...@@ -68,6 +68,9 @@ class Display ...@@ -68,6 +68,9 @@ class Display
private: private:
DISALLOW_COPY_AND_ASSIGN(Display); DISALLOW_COPY_AND_ASSIGN(Display);
D3DPRESENT_PARAMETERS getPresentParameters();
const HDC mDc; const HDC mDc;
HMODULE mD3d9Module; HMODULE mD3d9Module;
......
...@@ -37,39 +37,51 @@ Surface::Surface(Display *display, const Config *config, HWND window) ...@@ -37,39 +37,51 @@ Surface::Surface(Display *display, const Config *config, HWND window)
Surface::~Surface() Surface::~Surface()
{ {
release();
}
void Surface::release()
{
if (mSwapChain) if (mSwapChain)
{ {
mSwapChain->Release(); mSwapChain->Release();
mSwapChain = NULL;
} }
if (mBackBuffer) if (mBackBuffer)
{ {
mBackBuffer->Release(); mBackBuffer->Release();
mBackBuffer = NULL;
} }
if (mRenderTarget) if (mRenderTarget)
{ {
mRenderTarget->Release(); mRenderTarget->Release();
mRenderTarget = NULL;
} }
if (mDepthStencil) if (mDepthStencil)
{ {
mDepthStencil->Release(); mDepthStencil->Release();
mDepthStencil = NULL;
} }
if (mFlipTexture) if (mFlipTexture)
{ {
mFlipTexture->Release(); mFlipTexture->Release();
mFlipTexture = NULL;
} }
if (mFlipState) if (mFlipState)
{ {
mFlipState->Release(); mFlipState->Release();
mFlipState = NULL;
} }
if (mPreFlipState) if (mPreFlipState)
{ {
mPreFlipState->Release(); mPreFlipState->Release();
mPreFlipState = NULL;
} }
} }
......
...@@ -29,6 +29,9 @@ class Surface ...@@ -29,6 +29,9 @@ class Surface
~Surface(); ~Surface();
void release();
void resetSwapChain();
HWND getWindowHandle(); HWND getWindowHandle();
bool swap(); bool swap();
...@@ -48,7 +51,6 @@ class Surface ...@@ -48,7 +51,6 @@ class Surface
IDirect3DSurface9 *mDepthStencil; IDirect3DSurface9 *mDepthStencil;
IDirect3DTexture9 *mFlipTexture; IDirect3DTexture9 *mFlipTexture;
void resetSwapChain();
bool checkForWindowResize(); bool checkForWindowResize();
void applyFlipState(IDirect3DDevice9 *device); void applyFlipState(IDirect3DDevice9 *device);
......
...@@ -825,7 +825,7 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface ...@@ -825,7 +825,7 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface
gl::Context *context = static_cast<gl::Context*>(ctx); gl::Context *context = static_cast<gl::Context*>(ctx);
IDirect3DDevice9 *device = display->getDevice(); IDirect3DDevice9 *device = display->getDevice();
if (!device || device->TestCooperativeLevel() != D3D_OK) if (!device || FAILED(device->TestCooperativeLevel()))
{ {
return error(EGL_CONTEXT_LOST, EGL_FALSE); return error(EGL_CONTEXT_LOST, EGL_FALSE);
} }
......
...@@ -382,6 +382,11 @@ bool Blit::setFormatConvertShaders(GLenum destFormat) ...@@ -382,6 +382,11 @@ bool Blit::setFormatConvertShaders(GLenum destFormat)
IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect) IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect)
{ {
if (!surface)
{
return NULL;
}
egl::Display *display = getDisplay(); egl::Display *display = getDisplay();
IDirect3DDevice9 *device = getDevice(); IDirect3DDevice9 *device = getDevice();
......
...@@ -303,7 +303,10 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface) ...@@ -303,7 +303,10 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
setFramebufferZero(framebufferZero); setFramebufferZero(framebufferZero);
defaultRenderTarget->Release(); if (defaultRenderTarget)
{
defaultRenderTarget->Release();
}
if (depthStencil) if (depthStencil)
{ {
...@@ -1585,6 +1588,12 @@ bool Context::applyRenderTarget(bool ignoreViewport) ...@@ -1585,6 +1588,12 @@ bool Context::applyRenderTarget(bool ignoreViewport)
} }
IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget(); IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
if (!renderTarget)
{
return false; // Context must be lost
}
IDirect3DSurface9 *depthStencil = NULL; IDirect3DSurface9 *depthStencil = NULL;
unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial(); unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial();
...@@ -2098,6 +2107,12 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum ...@@ -2098,6 +2107,12 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
} }
IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget(); IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
if (!renderTarget)
{
return; // Context must be lost, return silently
}
IDirect3DDevice9 *device = getDevice(); IDirect3DDevice9 *device = getDevice();
D3DSURFACE_DESC desc; D3DSURFACE_DESC desc;
...@@ -2396,6 +2411,11 @@ void Context::clear(GLbitfield mask) ...@@ -2396,6 +2411,11 @@ void Context::clear(GLbitfield mask)
IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget(); IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
if (!renderTarget)
{
return; // Context must be lost, return silently
}
D3DSURFACE_DESC desc; D3DSURFACE_DESC desc;
renderTarget->GetDesc(&desc); renderTarget->GetDesc(&desc);
......
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