Commit a5ddde91 by apatrick@chromium.org

Move Context::sync to Display::sync.

This is a workaround for an Intel bug. The crash looks like this: 0x5f816c53 [d3d9.dll + 0x00036c53] CQuery::~CQuery() 0x5f816bec [d3d9.dll + 0x00036bec] CQuery::`vector deleting destructor'(unsigned int) 0x5f7e8129 [d3d9.dll + 0x00008129] CBaseObject::~CBaseObject() 0x5f9e19c7 [libglesv2.dll + 0x000319c7] gl::Fence::`vector deleting destructor'(unsigned int) 0x5f9de78e [libglesv2.dll - context.cpp:975] gl::Context::deleteFence(unsigned int) 0x5f9e1491 [libglesv2.dll - context.cpp:198] gl::Context::~Context() 0x5f9e182f [libglesv2.dll - context.cpp:3936] glDestroyContext 0x717654ec [libegl.dll - display.cpp:749] egl::Display::destroyContext(gl::Context *) 0x7176a3da [libegl.dll - libegl.cpp:907] eglDestroyContext 0x64fbaf33 [chrome.dll - gl_context_egl.cc:75] gfx::GLContextEGL::Destroy() This is a crash in deleteFence but the same could happen in flush. Fix for the former to follow. The vendor ID is always 8086 (Intel). Not an XP issue - it's happening on Win 7. Tested by stepping through a call to glFinish in the debugger and ensuring that it sleeps but eventually returns. Review URL: http://codereview.appspot.com/5503094 git-svn-id: https://angleproject.googlecode.com/svn/trunk@940 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 89c9813b
#define MAJOR_VERSION 1 #define MAJOR_VERSION 1
#define MINOR_VERSION 0 #define MINOR_VERSION 0
#define BUILD_VERSION 0 #define BUILD_VERSION 0
#define BUILD_REVISION 939 #define BUILD_REVISION 940
#define STRINGIFY(x) #x #define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x) #define MACRO_STRINGIFY(x) STRINGIFY(x)
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "common/debug.h" #include "common/debug.h"
#include "libGLESv2/mathutil.h" #include "libGLESv2/mathutil.h"
#include "libGLESv2/utilities.h"
#include "libEGL/main.h" #include "libEGL/main.h"
...@@ -75,6 +76,7 @@ Display::Display(EGLNativeDisplayType displayId, HDC deviceContext, bool softwar ...@@ -75,6 +76,7 @@ Display::Display(EGLNativeDisplayType displayId, HDC deviceContext, bool softwar
mDevice = NULL; mDevice = NULL;
mDeviceEx = NULL; mDeviceEx = NULL;
mDeviceWindow = NULL; mDeviceWindow = NULL;
mEventQuery = NULL;
mAdapter = D3DADAPTER_DEFAULT; mAdapter = D3DADAPTER_DEFAULT;
...@@ -302,6 +304,12 @@ void Display::terminate() ...@@ -302,6 +304,12 @@ void Display::terminate()
destroyContext(*mContextSet.begin()); destroyContext(*mContextSet.begin());
} }
if (mEventQuery)
{
mEventQuery->Release();
mEventQuery = NULL;
}
if (mDevice) if (mDevice)
{ {
// If the device is lost, reset it first to prevent leaving the driver in an unstable state // If the device is lost, reset it first to prevent leaving the driver in an unstable state
...@@ -461,6 +469,12 @@ void Display::initializeDevice() ...@@ -461,6 +469,12 @@ void Display::initializeDevice()
mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE); mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE);
// Leave mEventQuery null if CreateQuery fails. This will prevent sync from
// working correctly but otherwise mEventQuery is expected to be null when
// queries are not supported.
ASSERT(!mEventQuery);
mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &mEventQuery);
mSceneStarted = false; mSceneStarted = false;
} }
...@@ -723,6 +737,12 @@ bool Display::restoreLostDevice() ...@@ -723,6 +737,12 @@ bool Display::restoreLostDevice()
(*surface)->release(); (*surface)->release();
} }
if (mEventQuery)
{
mEventQuery->Release();
mEventQuery = NULL;
}
if (!resetDevice()) if (!resetDevice())
{ {
return false; return false;
...@@ -868,6 +888,43 @@ bool Display::testDeviceResettable() ...@@ -868,6 +888,43 @@ bool Display::testDeviceResettable()
} }
} }
void Display::sync(bool block)
{
HRESULT result;
if (!mEventQuery)
{
return;
}
result = mEventQuery->Issue(D3DISSUE_END);
ASSERT(SUCCEEDED(result));
do
{
result = mEventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
if(block && result == S_FALSE)
{
// Keep polling, but allow other threads to do something useful first
Sleep(0);
// explicitly check for device loss
// some drivers seem to return S_FALSE even if the device is lost
// instead of D3DERR_DEVICELOST like they should
if (testDeviceLost())
{
result = D3DERR_DEVICELOST;
}
}
}
while(block && result == S_FALSE);
if (isDeviceLostError(result))
{
notifyDeviceLost();
}
}
void Display::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray) void Display::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
{ {
for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++) for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
......
...@@ -63,6 +63,7 @@ class Display ...@@ -63,6 +63,7 @@ class Display
virtual D3DADAPTER_IDENTIFIER9 *getAdapterIdentifier(); virtual D3DADAPTER_IDENTIFIER9 *getAdapterIdentifier();
virtual bool testDeviceLost(); virtual bool testDeviceLost();
virtual bool testDeviceResettable(); virtual bool testDeviceResettable();
virtual void sync(bool block);
virtual void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray); virtual void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray);
virtual bool getDXT1TextureSupport(); virtual bool getDXT1TextureSupport();
virtual bool getDXT3TextureSupport(); virtual bool getDXT3TextureSupport();
...@@ -103,6 +104,8 @@ class Display ...@@ -103,6 +104,8 @@ class Display
IDirect3D9Ex *mD3d9Ex; // Might be null if D3D9Ex is not supported. IDirect3D9Ex *mD3d9Ex; // Might be null if D3D9Ex is not supported.
IDirect3DDevice9 *mDevice; IDirect3DDevice9 *mDevice;
IDirect3DDevice9Ex *mDeviceEx; // Might be null if D3D9Ex is not supported. IDirect3DDevice9Ex *mDeviceEx; // Might be null if D3D9Ex is not supported.
IDirect3DQuery9 *mEventQuery;
D3DCAPS9 mDeviceCaps; D3DCAPS9 mDeviceCaps;
D3DADAPTER_IDENTIFIER9 mAdapterIdentifier; D3DADAPTER_IDENTIFIER9 mAdapterIdentifier;
HWND mDeviceWindow; HWND mDeviceWindow;
......
...@@ -2859,56 +2859,7 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void * ...@@ -2859,56 +2859,7 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *
// Implements glFlush when block is false, glFinish when block is true // Implements glFlush when block is false, glFinish when block is true
void Context::sync(bool block) void Context::sync(bool block)
{ {
egl::Display *display = getDisplay(); mDisplay->sync(block);
IDirect3DQuery9 *eventQuery = NULL;
HRESULT result;
result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
if (FAILED(result))
{
ERR("CreateQuery failed hr=%x\n", result);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
{
return error(GL_OUT_OF_MEMORY);
}
ASSERT(false);
return;
}
result = eventQuery->Issue(D3DISSUE_END);
if (FAILED(result))
{
ERR("eventQuery->Issue(END) failed hr=%x\n", result);
ASSERT(false);
eventQuery->Release();
return;
}
do
{
result = eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
if(block && result == S_FALSE)
{
// Keep polling, but allow other threads to do something useful first
Sleep(0);
// explicitly check for device loss
// some drivers seem to return S_FALSE even if the device is lost
// instead of D3DERR_DEVICELOST like they should
if (display->testDeviceLost())
{
result = D3DERR_DEVICELOST;
}
}
}
while(block && result == S_FALSE);
eventQuery->Release();
if (checkDeviceLost(result))
{
error(GL_OUT_OF_MEMORY);
}
} }
void Context::drawClosingLine(unsigned int first, unsigned int last, int minIndex) void Context::drawClosingLine(unsigned int first, unsigned int last, int minIndex)
......
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