mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-10 08:38:20 +00:00
[host] dxgi: don't release the frame until we need a new one
Per Microsoft spec we should not release the frame until we are about to acquire another frame, this pervents additional GPU overhead on the guest.
This commit is contained in:
parent
49acc6ec0b
commit
8dec59f3ff
@ -184,6 +184,12 @@ bool DXGI::Initialize(CaptureOptions * options)
|
|||||||
|
|
||||||
void DXGI::DeInitialize()
|
void DXGI::DeInitialize()
|
||||||
{
|
{
|
||||||
|
if (m_releaseFrame)
|
||||||
|
{
|
||||||
|
m_releaseFrame = false;
|
||||||
|
m_dup->ReleaseFrame();
|
||||||
|
}
|
||||||
|
|
||||||
if (m_pointer)
|
if (m_pointer)
|
||||||
{
|
{
|
||||||
delete[] m_pointer;
|
delete[] m_pointer;
|
||||||
@ -237,6 +243,20 @@ size_t DXGI::GetMaxFrameSize()
|
|||||||
return (m_width * m_height * 4);
|
return (m_width * m_height * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DXGI::WaitForDesktop()
|
||||||
|
{
|
||||||
|
HDESK desktop;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
desktop = OpenInputDesktop(0, TRUE, GENERIC_READ);
|
||||||
|
if (desktop)
|
||||||
|
break;
|
||||||
|
Sleep(100);
|
||||||
|
}
|
||||||
|
while (!desktop);
|
||||||
|
CloseDesktop(desktop);
|
||||||
|
}
|
||||||
|
|
||||||
GrabStatus DXGI::GrabFrame(FrameInfo & frame)
|
GrabStatus DXGI::GrabFrame(FrameInfo & frame)
|
||||||
{
|
{
|
||||||
if (!m_initialized)
|
if (!m_initialized)
|
||||||
@ -251,6 +271,25 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
|
|||||||
{
|
{
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
|
if (m_releaseFrame)
|
||||||
|
{
|
||||||
|
m_releaseFrame = false;
|
||||||
|
status = m_dup->ReleaseFrame();
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case S_OK:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_ERROR_INVALID_CALL:
|
||||||
|
DEBUG_ERROR("Frame was already released");
|
||||||
|
return GRAB_STATUS_ERROR;
|
||||||
|
|
||||||
|
case DXGI_ERROR_ACCESS_LOST:
|
||||||
|
WaitForDesktop();
|
||||||
|
return GRAB_STATUS_REINIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
status = m_dup->AcquireNextFrame(1000, &frameInfo, &res);
|
status = m_dup->AcquireNextFrame(1000, &frameInfo, &res);
|
||||||
if (status == DXGI_ERROR_WAIT_TIMEOUT)
|
if (status == DXGI_ERROR_WAIT_TIMEOUT)
|
||||||
{
|
{
|
||||||
@ -271,6 +310,8 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
|
|||||||
if (!SUCCEEDED(status))
|
if (!SUCCEEDED(status))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
m_releaseFrame = true;
|
||||||
|
|
||||||
// if we have a mouse update
|
// if we have a mouse update
|
||||||
if (frameInfo.LastMouseUpdateTime.QuadPart)
|
if (frameInfo.LastMouseUpdateTime.QuadPart)
|
||||||
{
|
{
|
||||||
@ -311,7 +352,6 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
|
|||||||
status = m_dup->GetFramePointerShape(m_pointerBufSize, m_pointer, &m_pointerSize, &shapeInfo);
|
status = m_dup->GetFramePointerShape(m_pointerBufSize, m_pointer, &m_pointerSize, &shapeInfo);
|
||||||
if (!SUCCEEDED(status))
|
if (!SUCCEEDED(status))
|
||||||
{
|
{
|
||||||
m_dup->ReleaseFrame();
|
|
||||||
DEBUG_ERROR("Failed to get the new pointer shape: %08x", (int)status);
|
DEBUG_ERROR("Failed to get the new pointer shape: %08x", (int)status);
|
||||||
return GRAB_STATUS_ERROR;
|
return GRAB_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
@ -334,10 +374,9 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
|
|||||||
frame.cursor.dataSize = m_pointerSize;
|
frame.cursor.dataSize = m_pointerSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frameInfo.AccumulatedFrames > 0)
|
if (frameInfo.LastPresentTime.QuadPart != 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
m_dup->ReleaseFrame();
|
|
||||||
res.Release();
|
res.Release();
|
||||||
|
|
||||||
if (cursorUpdate)
|
if (cursorUpdate)
|
||||||
@ -352,28 +391,8 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
|
|||||||
{
|
{
|
||||||
// desktop switch, mode change, switch DWM on or off or Secure Desktop
|
// desktop switch, mode change, switch DWM on or off or Secure Desktop
|
||||||
case DXGI_ERROR_ACCESS_LOST:
|
case DXGI_ERROR_ACCESS_LOST:
|
||||||
// see if we can open the desktop, if so request a reinit
|
|
||||||
// if not the secure desktop is active so just wait for it
|
|
||||||
// instead of aborting out
|
|
||||||
desktop = OpenInputDesktop(0, TRUE, GENERIC_READ);
|
|
||||||
if (desktop)
|
|
||||||
{
|
|
||||||
// open suceeded, not on the secure desktop, return to reinit
|
|
||||||
CloseDesktop(desktop);
|
|
||||||
return GRAB_STATUS_REINIT;
|
|
||||||
}
|
|
||||||
// fall through
|
|
||||||
|
|
||||||
// this can happen during desktop switches also, not documented by MS though
|
|
||||||
case WAIT_ABANDONED:
|
case WAIT_ABANDONED:
|
||||||
do
|
WaitForDesktop();
|
||||||
{
|
|
||||||
desktop = OpenInputDesktop(0, TRUE, GENERIC_READ);
|
|
||||||
if (desktop)
|
|
||||||
break;
|
|
||||||
Sleep(100);
|
|
||||||
} while (!desktop);
|
|
||||||
CloseDesktop(desktop);
|
|
||||||
return GRAB_STATUS_REINIT;
|
return GRAB_STATUS_REINIT;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -386,7 +405,6 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
|
|||||||
// 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 GRAB_STATUS_ERROR;
|
return GRAB_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
@ -394,7 +412,6 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
|
|||||||
ID3D11Texture2DPtr src(res);
|
ID3D11Texture2DPtr src(res);
|
||||||
if (!src)
|
if (!src)
|
||||||
{
|
{
|
||||||
m_dup->ReleaseFrame();
|
|
||||||
DEBUG_ERROR("Failed to get src ID3D11Texture2D");
|
DEBUG_ERROR("Failed to get src ID3D11Texture2D");
|
||||||
return GRAB_STATUS_ERROR;
|
return GRAB_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
@ -403,7 +420,6 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
|
|||||||
|
|
||||||
m_deviceContext->CopyResource(m_texture, src);
|
m_deviceContext->CopyResource(m_texture, src);
|
||||||
|
|
||||||
m_dup->ReleaseFrame();
|
|
||||||
res.Release();
|
res.Release();
|
||||||
src.Release();
|
src.Release();
|
||||||
|
|
||||||
|
@ -67,6 +67,8 @@ namespace Capture
|
|||||||
enum GrabStatus GrabFrame(struct FrameInfo & frame);
|
enum GrabStatus GrabFrame(struct FrameInfo & frame);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void WaitForDesktop();
|
||||||
|
|
||||||
CaptureOptions * m_options;
|
CaptureOptions * m_options;
|
||||||
|
|
||||||
bool m_initialized;
|
bool m_initialized;
|
||||||
@ -79,6 +81,7 @@ namespace Capture
|
|||||||
ID3D11DeviceContextPtr m_deviceContext;
|
ID3D11DeviceContextPtr m_deviceContext;
|
||||||
IDXGIOutput1Ptr m_output;
|
IDXGIOutput1Ptr m_output;
|
||||||
IDXGIOutputDuplicationPtr m_dup;
|
IDXGIOutputDuplicationPtr m_dup;
|
||||||
|
bool m_releaseFrame;
|
||||||
ID3D11Texture2DPtr m_texture;
|
ID3D11Texture2DPtr m_texture;
|
||||||
IDXGISurface1Ptr m_surface;
|
IDXGISurface1Ptr m_surface;
|
||||||
D3D11_TEXTURE2D_DESC m_desc;
|
D3D11_TEXTURE2D_DESC m_desc;
|
||||||
|
Loading…
Reference in New Issue
Block a user