mirror of
https://github.com/gnif/LookingGlass.git
synced 2025-04-26 16:46:28 +00:00
[dxgi] cleaned up retry logic
This commit is contained in:
parent
9613127162
commit
fb37174e5f
@ -361,148 +361,147 @@ GrabStatus Capture::DXGI::Capture()
|
|||||||
IDXGIResourcePtr res;
|
IDXGIResourcePtr res;
|
||||||
|
|
||||||
HRESULT status;
|
HRESULT status;
|
||||||
for (int i = 0; i < 2; ++i)
|
for (int retryCount = 0; retryCount < 2; ++retryCount)
|
||||||
{
|
{
|
||||||
while (true)
|
GrabStatus ret = ReleaseFrame();
|
||||||
|
if (ret != GRAB_STATUS_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
status = m_dup->AcquireNextFrame(1000, &frameInfo, &res);
|
||||||
|
|
||||||
|
switch (status)
|
||||||
{
|
{
|
||||||
GrabStatus ret = ReleaseFrame();
|
case S_OK:
|
||||||
if (ret != GRAB_STATUS_OK)
|
m_releaseFrame = true;
|
||||||
return ret;
|
|
||||||
|
|
||||||
status = m_dup->AcquireNextFrame(1000, &frameInfo, &res);
|
|
||||||
if (status == DXGI_ERROR_WAIT_TIMEOUT)
|
|
||||||
return GRAB_STATUS_TIMEOUT;
|
|
||||||
|
|
||||||
if (FAILED(status))
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
m_releaseFrame = true;
|
case DXGI_ERROR_WAIT_TIMEOUT:
|
||||||
|
return GRAB_STATUS_TIMEOUT;
|
||||||
|
|
||||||
// if we have a mouse update
|
// desktop switch, mode change, switch DWM on or off or Secure Desktop
|
||||||
if (frameInfo.LastMouseUpdateTime.QuadPart)
|
case DXGI_ERROR_ACCESS_LOST:
|
||||||
{
|
case WAIT_ABANDONED:
|
||||||
if (
|
return GRAB_STATUS_REINIT;
|
||||||
m_lastCursorX != frameInfo.PointerPosition.Position.x ||
|
|
||||||
m_lastCursorY != frameInfo.PointerPosition.Position.y
|
|
||||||
) {
|
|
||||||
cursorUpdated = true;
|
|
||||||
cursor.hasPos = true;
|
|
||||||
cursor.x = m_lastCursorX = frameInfo.PointerPosition.Position.x;
|
|
||||||
cursor.y = m_lastCursorY = frameInfo.PointerPosition.Position.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_lastMouseVis != frameInfo.PointerPosition.Visible)
|
default:
|
||||||
{
|
// unknown failure
|
||||||
cursorUpdated = true;
|
DEBUG_WINERROR("AcquireNextFrame failed", status);
|
||||||
m_lastMouseVis = frameInfo.PointerPosition.Visible;
|
return GRAB_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor.visible = m_lastMouseVis == TRUE;
|
// if we have a mouse update
|
||||||
|
if (frameInfo.LastMouseUpdateTime.QuadPart)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
m_lastCursorX != frameInfo.PointerPosition.Position.x ||
|
||||||
|
m_lastCursorY != frameInfo.PointerPosition.Position.y
|
||||||
|
) {
|
||||||
|
cursorUpdated = true;
|
||||||
|
cursor.hasPos = true;
|
||||||
|
cursor.x = m_lastCursorX = frameInfo.PointerPosition.Position.x;
|
||||||
|
cursor.y = m_lastCursorY = frameInfo.PointerPosition.Position.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the pointer shape has changed
|
if (m_lastMouseVis != frameInfo.PointerPosition.Visible)
|
||||||
if (frameInfo.PointerShapeBufferSize > 0)
|
|
||||||
{
|
{
|
||||||
CursorBuffer * buf;
|
cursorUpdated = true;
|
||||||
|
m_lastMouseVis = frameInfo.PointerPosition.Visible;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_cursorData.size() == 0)
|
cursor.visible = m_lastMouseVis == TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the pointer shape has changed
|
||||||
|
if (frameInfo.PointerShapeBufferSize > 0)
|
||||||
|
{
|
||||||
|
CursorBuffer * buf;
|
||||||
|
|
||||||
|
if (m_cursorData.size() == 0)
|
||||||
|
{
|
||||||
|
// create a new buffer
|
||||||
|
buf = new CursorBuffer;
|
||||||
|
buf->buffer = new char[frameInfo.PointerShapeBufferSize];
|
||||||
|
buf->bufferSize = frameInfo.PointerShapeBufferSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// get an existing buffer from the pool
|
||||||
|
EnterCriticalSection(&m_cursorDataCS);
|
||||||
|
buf = m_cursorData.front();
|
||||||
|
m_cursorData.pop_front();
|
||||||
|
LeaveCriticalSection(&m_cursorDataCS);
|
||||||
|
|
||||||
|
// resize the buffer if required
|
||||||
|
if (buf->bufferSize < frameInfo.PointerShapeBufferSize)
|
||||||
{
|
{
|
||||||
// create a new buffer
|
delete[] buf->buffer;
|
||||||
buf = new CursorBuffer;
|
|
||||||
buf->buffer = new char[frameInfo.PointerShapeBufferSize];
|
buf->buffer = new char[frameInfo.PointerShapeBufferSize];
|
||||||
buf->bufferSize = frameInfo.PointerShapeBufferSize;
|
buf->bufferSize = frameInfo.PointerShapeBufferSize;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
// get an existing buffer from the pool
|
|
||||||
EnterCriticalSection(&m_cursorDataCS);
|
|
||||||
buf = m_cursorData.front();
|
|
||||||
m_cursorData.pop_front();
|
|
||||||
LeaveCriticalSection(&m_cursorDataCS);
|
|
||||||
|
|
||||||
// resize the buffer if required
|
buf->pointerSize = 0;
|
||||||
if (buf->bufferSize < frameInfo.PointerShapeBufferSize)
|
cursor.shape = buf;
|
||||||
{
|
cursorUpdated = true;
|
||||||
delete[] buf->buffer;
|
|
||||||
buf->buffer = new char[frameInfo.PointerShapeBufferSize];
|
|
||||||
buf->bufferSize = frameInfo.PointerShapeBufferSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buf->pointerSize = 0;
|
DXGI_OUTDUPL_POINTER_SHAPE_INFO shapeInfo;
|
||||||
cursor.shape = buf;
|
status = m_dup->GetFramePointerShape(buf->bufferSize, buf->buffer, &buf->pointerSize, &shapeInfo);
|
||||||
cursorUpdated = true;
|
if (FAILED(status))
|
||||||
|
{
|
||||||
|
DEBUG_WINERROR("Failed to get the new pointer shape", status);
|
||||||
|
return GRAB_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
DXGI_OUTDUPL_POINTER_SHAPE_INFO shapeInfo;
|
switch (shapeInfo.Type)
|
||||||
status = m_dup->GetFramePointerShape(buf->bufferSize, buf->buffer, &buf->pointerSize, &shapeInfo);
|
{
|
||||||
if (FAILED(status))
|
|
||||||
{
|
|
||||||
DEBUG_WINERROR("Failed to get the new pointer shape", status);
|
|
||||||
return GRAB_STATUS_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (shapeInfo.Type)
|
|
||||||
{
|
|
||||||
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR : cursor.type = CURSOR_TYPE_COLOR; break;
|
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR : cursor.type = CURSOR_TYPE_COLOR; break;
|
||||||
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR: cursor.type = CURSOR_TYPE_MASKED_COLOR; break;
|
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR: cursor.type = CURSOR_TYPE_MASKED_COLOR; break;
|
||||||
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME : cursor.type = CURSOR_TYPE_MONOCHROME; break;
|
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME : cursor.type = CURSOR_TYPE_MONOCHROME; break;
|
||||||
default:
|
default:
|
||||||
DEBUG_ERROR("Invalid cursor type");
|
DEBUG_ERROR("Invalid cursor type");
|
||||||
return GRAB_STATUS_ERROR;
|
return GRAB_STATUS_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
cursor.w = shapeInfo.Width;
|
|
||||||
cursor.h = shapeInfo.Height;
|
|
||||||
cursor.pitch = shapeInfo.Pitch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cursorUpdated)
|
cursor.w = shapeInfo.Width;
|
||||||
|
cursor.h = shapeInfo.Height;
|
||||||
|
cursor.pitch = shapeInfo.Pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursorUpdated)
|
||||||
|
{
|
||||||
|
// push the cursor update into the queue
|
||||||
|
EnterCriticalSection(&m_cursorCS);
|
||||||
|
m_cursorUpdates.push_back(cursor);
|
||||||
|
LeaveCriticalSection(&m_cursorCS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we don't have frame data
|
||||||
|
if (frameInfo.LastPresentTime.QuadPart == 0)
|
||||||
|
{
|
||||||
|
// if there is nothing to update, just start again
|
||||||
|
if (!cursorUpdated)
|
||||||
{
|
{
|
||||||
// push the cursor update into the queue
|
--retryCount;
|
||||||
EnterCriticalSection(&m_cursorCS);
|
continue;
|
||||||
m_cursorUpdates.push_back(cursor);
|
|
||||||
LeaveCriticalSection(&m_cursorCS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we also have frame data, break out to process it
|
|
||||||
if (frameInfo.LastPresentTime.QuadPart != 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
res = NULL;
|
res = NULL;
|
||||||
|
return GRAB_STATUS_CURSOR;
|
||||||
// if the cursor has been updated
|
|
||||||
if (cursorUpdated)
|
|
||||||
return GRAB_STATUS_CURSOR;
|
|
||||||
|
|
||||||
// otherwise just try again
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(status))
|
// success, break out of the retry loop
|
||||||
break;
|
break;
|
||||||
|
|
||||||
switch (status)
|
|
||||||
{
|
|
||||||
// desktop switch, mode change, switch DWM on or off or Secure Desktop
|
|
||||||
case DXGI_ERROR_ACCESS_LOST:
|
|
||||||
case WAIT_ABANDONED:
|
|
||||||
return GRAB_STATUS_REINIT;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// unknown failure
|
|
||||||
DEBUG_WINERROR("AcquireNextFrame failed", status);
|
|
||||||
return GRAB_STATUS_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// retry count exceeded
|
// ensure we have a frame
|
||||||
if (FAILED(status))
|
if (!m_releaseFrame)
|
||||||
{
|
{
|
||||||
DEBUG_WINERROR("Failed to acquire next frame", status);
|
DEBUG_WINERROR("Failed to acquire next frame", status);
|
||||||
return GRAB_STATUS_ERROR;
|
return GRAB_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get the texture
|
||||||
res.QueryInterface(IID_PPV_ARGS(&m_ftexture));
|
res.QueryInterface(IID_PPV_ARGS(&m_ftexture));
|
||||||
|
|
||||||
if (!m_ftexture)
|
if (!m_ftexture)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to get src ID3D11Texture2D");
|
DEBUG_ERROR("Failed to get src ID3D11Texture2D");
|
||||||
@ -565,12 +564,15 @@ GrabStatus Capture::DXGI::GrabFrameRaw(FrameInfo & frame)
|
|||||||
frame.pitch = m_width * 4;
|
frame.pitch = m_width * 4;
|
||||||
frame.stride = m_width;
|
frame.stride = m_width;
|
||||||
|
|
||||||
for(unsigned int y = 0; y < m_height; ++y)
|
if (frame.pitch == mapping.RowPitch)
|
||||||
memcpySSE(
|
memcpySSE(frame.buffer, mapping.pData, frame.pitch * m_height);
|
||||||
(uint32_t*)frame.buffer + (m_width * y),
|
else
|
||||||
(uint8_t *)mapping.pData + (mapping.RowPitch * y),
|
for(unsigned int y = 0; y < m_height; ++y)
|
||||||
m_width * 4
|
memcpySSE(
|
||||||
);
|
(uint8_t *)frame.buffer + (frame.pitch * y),
|
||||||
|
(uint8_t *)mapping.pData + (mapping.RowPitch * y),
|
||||||
|
frame.pitch
|
||||||
|
);
|
||||||
|
|
||||||
m_deviceContext->Unmap(m_texture[0], 0);
|
m_deviceContext->Unmap(m_texture[0], 0);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user