mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-25 14:57:20 +00:00
[host] made DXGI ReInitialization more robust on mode changes
DXGI doesn't like to restart too fast, com exceptions are logged and the duplication device fails to create with an E_ACCESS_DENIED error. Adding a 200ms sleep between teardown and re-init resolves this issue.
This commit is contained in:
parent
32d61023e5
commit
9287ec97eb
@ -118,22 +118,23 @@ bool DXGI::Initialize()
|
|||||||
);
|
);
|
||||||
adapter.Release();
|
adapter.Release();
|
||||||
|
|
||||||
if (FAILED(status))
|
if (FAILED(status) || !m_device)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to create D3D11 device");
|
DEBUG_ERROR("Failed to create D3D11 device");
|
||||||
DeInitialize();
|
DeInitialize();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CComQIPtr<IDXGIDevice1> device1 = m_device;
|
// we try this twice just incase we still get an error
|
||||||
if (!device1)
|
// on re-initialization
|
||||||
|
for(int i = 0; i < 2; ++i)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to get IDXGIDevice1");
|
status = m_output->DuplicateOutput(m_device, &m_dup);
|
||||||
DeInitialize();
|
if (SUCCEEDED(status))
|
||||||
return false;
|
break;
|
||||||
|
Sleep(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = m_output->DuplicateOutput(m_device, &m_dup);
|
|
||||||
if (FAILED(status))
|
if (FAILED(status))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("DuplicateOutput Failed: %08x", status);
|
DEBUG_ERROR("DuplicateOutput Failed: %08x", status);
|
||||||
@ -181,6 +182,7 @@ void DXGI::DeInitialize()
|
|||||||
{
|
{
|
||||||
delete[] m_pointer;
|
delete[] m_pointer;
|
||||||
m_pointer = NULL;
|
m_pointer = NULL;
|
||||||
|
m_pointerBufSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_texture)
|
if (m_texture)
|
||||||
@ -204,6 +206,19 @@ void DXGI::DeInitialize()
|
|||||||
m_initialized = false;
|
m_initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DXGI::ReInitialize()
|
||||||
|
{
|
||||||
|
DeInitialize();
|
||||||
|
|
||||||
|
/*
|
||||||
|
DXGI needs some time when mode switches occur, failing to do so causes
|
||||||
|
failure to start and exceptions internal to DXGI
|
||||||
|
*/
|
||||||
|
Sleep(200);
|
||||||
|
|
||||||
|
return Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
FrameType DXGI::GetFrameType()
|
FrameType DXGI::GetFrameType()
|
||||||
{
|
{
|
||||||
if (!m_initialized)
|
if (!m_initialized)
|
||||||
@ -230,6 +245,9 @@ size_t DXGI::GetMaxFrameSize()
|
|||||||
|
|
||||||
bool DXGI::GrabFrame(FrameInfo & frame)
|
bool DXGI::GrabFrame(FrameInfo & frame)
|
||||||
{
|
{
|
||||||
|
if (!m_initialized)
|
||||||
|
return false;
|
||||||
|
|
||||||
DXGI_OUTDUPL_FRAME_INFO frameInfo;
|
DXGI_OUTDUPL_FRAME_INFO frameInfo;
|
||||||
CComPtr<IDXGIResource> res;
|
CComPtr<IDXGIResource> res;
|
||||||
|
|
||||||
@ -239,27 +257,31 @@ bool DXGI::GrabFrame(FrameInfo & frame)
|
|||||||
status = m_dup->AcquireNextFrame(INFINITE, &frameInfo, &res);
|
status = m_dup->AcquireNextFrame(INFINITE, &frameInfo, &res);
|
||||||
if (SUCCEEDED(status))
|
if (SUCCEEDED(status))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// desktop switch, mode change or switch DWM on or off
|
switch (status)
|
||||||
if (status == DXGI_ERROR_ACCESS_LOST)
|
{
|
||||||
{
|
case DXGI_ERROR_ACCESS_LOST: // desktop switch, mode change or switch DWM on or off
|
||||||
DeInitialize();
|
case WAIT_ABANDONED: // this can happen also during desktop switches, not documented by MS though
|
||||||
if (!Initialize())
|
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to re-initialize after access was lost");
|
if (!ReInitialize())
|
||||||
return false;
|
{
|
||||||
|
DEBUG_ERROR("Failed to re-initialize after access was lost");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// unknown failure
|
default:
|
||||||
DEBUG_INFO("AcquireNextFrame failed: %08x", status);
|
// unknown failure
|
||||||
return false;
|
DEBUG_INFO("AcquireNextFrame failed: %08x", status);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// retry count exceeded
|
// retry count exceeded
|
||||||
if (FAILED(status))
|
if (FAILED(status))
|
||||||
{
|
{
|
||||||
|
m_dup->ReleaseFrame();
|
||||||
DEBUG_ERROR("Failed to acquire next frame");
|
DEBUG_ERROR("Failed to acquire next frame");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -267,6 +289,7 @@ bool DXGI::GrabFrame(FrameInfo & frame)
|
|||||||
CComQIPtr<ID3D11Texture2D> src = res;
|
CComQIPtr<ID3D11Texture2D> src = res;
|
||||||
if (!src)
|
if (!src)
|
||||||
{
|
{
|
||||||
|
m_dup->ReleaseFrame();
|
||||||
DEBUG_ERROR("Failed to get src ID3D11Texture2D");
|
DEBUG_ERROR("Failed to get src ID3D11Texture2D");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -290,6 +313,7 @@ bool DXGI::GrabFrame(FrameInfo & frame)
|
|||||||
status = m_dup->GetFramePointerShape(m_pointerBufSize, m_pointer, &m_pointerSize, &m_shapeInfo);
|
status = m_dup->GetFramePointerShape(m_pointerBufSize, m_pointer, &m_pointerSize, &m_shapeInfo);
|
||||||
if (!SUCCEEDED(status))
|
if (!SUCCEEDED(status))
|
||||||
{
|
{
|
||||||
|
m_dup->ReleaseFrame();
|
||||||
DEBUG_ERROR("Failed to get the new pointer shape: %08x", status);
|
DEBUG_ERROR("Failed to get the new pointer shape: %08x", status);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,8 @@ namespace Capture
|
|||||||
bool GrabFrame(struct FrameInfo & frame);
|
bool GrabFrame(struct FrameInfo & frame);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool ReInitialize();
|
||||||
|
|
||||||
bool m_initialized;
|
bool m_initialized;
|
||||||
MTMemcpy m_memcpy;
|
MTMemcpy m_memcpy;
|
||||||
unsigned int m_width;
|
unsigned int m_width;
|
||||||
|
Loading…
Reference in New Issue
Block a user