Commit 9f0d91d1 by apatrick@chromium.org

Fix crash after reseting device.

After calling Reset in testDeviceLost to acknowledge a display mode change, D3D sometimes crashes on the next Present call on an existing swap chain. I couldn't get it to happen with nVidia. The stack looks like this with the debug runtime: ntdll.dll!_ZwRaiseException@12() + 0x12 bytes ntdll.dll!_ZwRaiseException@12() + 0x12 bytes d3d9d.dll!__DDAssert() + 0x1ca bytes d3d9d.dll!CSwapChain::PresentMain() + 0xf52 bytes d3d9d.dll!CSwapChain::Present() + 0x24 bytes libEGL.dll!egl::Surface::swapRect(int x, int y, int width, int height) Line 458 + 0x2a bytes C++ > libEGL.dll!egl::Surface::swap() Line 605 C++ libEGL.dll!eglSwapBuffers(void * dpy, void * surface) Line 1063 + 0x8 bytes C++ gl_wrapper.dll!gfx::EGLApiBase::eglSwapBuffersFn(void * dpy, void * surface) Line 813 + 0x18 bytes C++ gl_wrapper.dll!gfx::NativeViewGLSurfaceEGL::SwapBuffers() Line 363 + 0x35 bytes C++ gl_wrapper.dll!gfx::GLSurfaceAdapter::SwapBuffers() Line 201 + 0x1d bytes C++ content.dll!content::PassThroughImageTransportSurface::SwapBuffers() Line 216 + 0xb bytes C++ The error is "BitBlt or StretchBlt failed in Present". With the release runtime either Present continually fails with E_INVALIDARG or, less commonly, crashes. It seems that by recreating all the swap chains after reset, it recovers. I didn't call resetSwapChain because there is no need to recreate all the other surfaces. As far as I know, this should not be necessary with WDDM. Review URL: https://codereview.appspot.com/7567045 git-svn-id: https://angleproject.googlecode.com/svn/trunk@1993 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent ce2d4025
......@@ -920,6 +920,12 @@ bool Display::testDeviceLost()
D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
mDeviceEx->Reset(&presentParameters);
// Existing swap chains sometimes crash on the next present after a reset.
for (SurfaceSet::iterator it = mSurfaceSet.begin(); it != mSurfaceSet.end(); ++it)
{
(*it)->recreateAdditionalSwapChain();
}
// Reset will not always cause the device loss to be reported so issue a dummy present.
mDeviceEx->Present(NULL, NULL, NULL, NULL);
......
......@@ -343,6 +343,38 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
return true;
}
void Surface::recreateAdditionalSwapChain()
{
if (!mSwapChain)
{
return;
}
IDirect3DDevice9 *device = mDisplay->getDevice();
if (device == NULL)
{
return;
}
D3DPRESENT_PARAMETERS presentParameters;
HRESULT result = mSwapChain->GetPresentParameters(&presentParameters);
ASSERT(SUCCEEDED(result));
IDirect3DSwapChain9* newSwapChain = NULL;
result = device->CreateAdditionalSwapChain(&presentParameters, &newSwapChain);
if (FAILED(result))
{
return;
}
mSwapChain->Release();
mSwapChain = newSwapChain;
mBackBuffer->Release();
result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
ASSERT(SUCCEEDED(result));
}
bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
{
if (!mSwapChain)
......
......@@ -64,6 +64,8 @@ class Surface
virtual void setBoundTexture(gl::Texture2D *texture);
virtual gl::Texture2D *getBoundTexture() const;
void recreateAdditionalSwapChain();
private:
DISALLOW_COPY_AND_ASSIGN(Surface);
......
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