From 1350ba6c4b3d71e6a8942751bf0363df9c93017e Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Fri, 19 Oct 2018 20:14:00 +1100 Subject: [PATCH] [host] accumulate cursor updates rather then queue --- host/Capture/DXGI.cpp | 96 ++++++++++++++++++------------------------- host/Capture/DXGI.h | 12 +++--- host/ICapture.h | 5 ++- host/Service.cpp | 8 ++-- 4 files changed, 53 insertions(+), 68 deletions(-) diff --git a/host/Capture/DXGI.cpp b/host/Capture/DXGI.cpp index cd4cfe04c..77f545957 100644 --- a/host/Capture/DXGI.cpp +++ b/host/Capture/DXGI.cpp @@ -57,6 +57,13 @@ bool DXGI::Initialize(CaptureOptions * options) m_options = options; HRESULT status; + for (int i = 0; i < _countof(m_cursorRing); ++i) + { + m_cursorRing[i].visible = false; + m_cursorRing[i].hasPos = false; + m_cursorRing[i].hasShape = false; + } + status = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void **)(&m_dxgiFactory)); if (FAILED(status)) { @@ -315,12 +322,11 @@ void DXGI::DeInitialize() ReleaseFrame(); - while(m_cursorData.size()) + for(int i = 0; i < _countof(m_cursorRing); ++i) { - CursorBuffer * buf = m_cursorData.front(); - delete[] buf->buffer; - delete buf; - m_cursorData.pop_front(); + if (m_cursorRing[i].shape.buffer) + delete[] m_cursorRing[i].shape.buffer; + m_cursorRing[i].shape.buffer = NULL; } for(int i = 0; i < _countof(m_texture); ++i) @@ -355,7 +361,7 @@ unsigned int Capture::DXGI::Capture() if (!m_initialized) return GRAB_STATUS_ERROR; - CursorInfo cursor = { 0 }; + CursorInfo & cursor = m_cursorRing[m_cursorWPos]; DXGI_OUTDUPL_FRAME_INFO frameInfo; IDXGIResourcePtr res; unsigned int ret; @@ -392,38 +398,19 @@ unsigned int Capture::DXGI::Capture() // 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 + // resize the buffer if required + if (cursor.shape.bufferSize < frameInfo.PointerShapeBufferSize) { - // 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) - { - delete[] buf->buffer; - buf->buffer = new char[frameInfo.PointerShapeBufferSize]; - buf->bufferSize = frameInfo.PointerShapeBufferSize; - } + delete[] cursor.shape.buffer; + cursor.shape.buffer = new char[frameInfo.PointerShapeBufferSize]; + cursor.shape.bufferSize = frameInfo.PointerShapeBufferSize; } - buf->pointerSize = 0; - cursor.shape = buf; - ret |= GRAB_STATUS_CURSOR; + cursor.shape.pointerSize = 0; + ret |= GRAB_STATUS_CURSOR; DXGI_OUTDUPL_POINTER_SHAPE_INFO shapeInfo; - status = m_dup->GetFramePointerShape(buf->bufferSize, buf->buffer, &buf->pointerSize, &shapeInfo); + status = m_dup->GetFramePointerShape(cursor.shape.bufferSize, cursor.shape.buffer, &cursor.shape.pointerSize, &shapeInfo); if (FAILED(status)) { DEBUG_WINERROR("Failed to get the new pointer shape", status); @@ -440,11 +427,12 @@ unsigned int Capture::DXGI::Capture() return GRAB_STATUS_ERROR; } - cursor.w = shapeInfo.Width; - cursor.h = shapeInfo.Height; - cursor.pitch = shapeInfo.Pitch; - m_hotSpot.x = shapeInfo.HotSpot.x; - m_hotSpot.y = shapeInfo.HotSpot.y; + cursor.hasShape = true; + cursor.w = shapeInfo.Width; + cursor.h = shapeInfo.Height; + cursor.pitch = shapeInfo.Pitch; + m_hotSpot.x = shapeInfo.HotSpot.x; + m_hotSpot.y = shapeInfo.HotSpot.y; } // if we have a mouse update @@ -483,12 +471,10 @@ unsigned int Capture::DXGI::Capture() m_lastMouseVis = frameInfo.PointerPosition.Visible; cursor.visible = m_lastMouseVis == TRUE; - if (ret & GRAB_STATUS_CURSOR) + if (ret & GRAB_STATUS_CURSOR && m_cursorWPos == m_cursorRPos) { - // push the cursor update into the queue - EnterCriticalSection(&m_cursorCS); - m_cursorUpdates.push_back(cursor); - LeaveCriticalSection(&m_cursorCS); + // atomic advance so we don't have to worry about locking + m_cursorWPos = (m_cursorWPos + 1 == DXGI_CURSOR_RING_SIZE) ? 0 : m_cursorWPos + 1; } // if we don't have frame data @@ -729,23 +715,21 @@ GrabStatus DXGI::GetFrame(struct FrameInfo & frame) bool DXGI::GetCursor(CursorInfo & cursor) { - if (!m_cursorUpdates.size()) + if (m_cursorRPos == m_cursorWPos) return false; - EnterCriticalSection(&m_cursorCS); - cursor = m_cursorUpdates.front(); - m_cursorUpdates.pop_front(); - LeaveCriticalSection(&m_cursorCS); + cursor = m_cursorRing[m_cursorRPos]; return true; } -void DXGI::FreeCursor(CursorInfo & cursor) +void DXGI::FreeCursor() { - /* put the buffer back into the pool */ - if (cursor.shape) - { - EnterCriticalSection(&m_cursorDataCS); - m_cursorData.push_front(cursor.shape); - LeaveCriticalSection(&m_cursorDataCS); - } + assert(m_cursorRPos != m_cursorWPos); + + CursorInfo & cursor = m_cursorRing[m_cursorRPos]; + cursor.visible = false; + cursor.hasPos = false; + cursor.hasShape = false; + + m_cursorRPos = (m_cursorRPos + 1 == DXGI_CURSOR_RING_SIZE) ? 0 : m_cursorRPos + 1; } \ No newline at end of file diff --git a/host/Capture/DXGI.h b/host/Capture/DXGI.h index 4db6343a8..ac0a23939 100644 --- a/host/Capture/DXGI.h +++ b/host/Capture/DXGI.h @@ -31,6 +31,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include #include +#define DXGI_CURSOR_RING_SIZE 2 + namespace Capture { class DXGI : public ICapture @@ -59,21 +61,19 @@ namespace Capture enum FrameType GetFrameType(); size_t GetMaxFrameSize(); unsigned int Capture(); - GrabStatus GetFrame (struct FrameInfo & frame ); + GrabStatus GetFrame (struct FrameInfo & frame ); bool GetCursor(CursorInfo & cursor); - void FreeCursor(CursorInfo & cursor); + void FreeCursor(); GrabStatus DiscardFrame(); private: - typedef std::list CursorList; - typedef std::list CursorBufferPool; bool InitRawCapture(); bool InitYUV420Capture(); bool InitH264Capture(); - CursorList m_cursorUpdates; - CursorBufferPool m_cursorData; + CursorInfo m_cursorRing[DXGI_CURSOR_RING_SIZE]; + unsigned int m_cursorRPos, m_cursorWPos; CRITICAL_SECTION m_cursorCS; CRITICAL_SECTION m_cursorDataCS; diff --git a/host/ICapture.h b/host/ICapture.h index 9c0f0f728..0e4126c02 100644 --- a/host/ICapture.h +++ b/host/ICapture.h @@ -34,12 +34,13 @@ struct CursorInfo { bool visible; bool hasPos; + bool hasShape; int x, y; enum CursorType type; unsigned int w, h; unsigned int pitch; - CursorBuffer * shape; + CursorBuffer shape; }; struct FrameInfo @@ -78,6 +79,6 @@ class ICapture virtual unsigned int Capture() = 0; virtual enum GrabStatus GetFrame(struct FrameInfo & frame) = 0; virtual bool GetCursor(CursorInfo & cursor) = 0; - virtual void FreeCursor(CursorInfo & cursor) = 0; + virtual void FreeCursor() = 0; virtual enum GrabStatus DiscardFrame() = 0; }; diff --git a/host/Service.cpp b/host/Service.cpp index fa74b4956..00f6b2e03 100644 --- a/host/Service.cpp +++ b/host/Service.cpp @@ -362,9 +362,9 @@ DWORD Service::CursorThread() cursor->y = ci.y; } - if (ci.shape) + if (ci.hasShape) { - if (ci.shape->pointerSize > m_cursorDataSize) + if (ci.shape.pointerSize > m_cursorDataSize) DEBUG_ERROR("Cursor size exceeds allocated space"); else { @@ -378,7 +378,7 @@ DWORD Service::CursorThread() cursor->pitch = ci.pitch; cursor->dataPos = m_cursorOffset; - memcpy(m_cursorData, ci.shape->buffer, ci.shape->bufferSize); + memcpy(m_cursorData, ci.shape.buffer, ci.shape.bufferSize); } } @@ -387,7 +387,7 @@ DWORD Service::CursorThread() flags |= KVMFR_CURSOR_FLAG_UPDATE; cursor->flags = flags; - m_capture->FreeCursor(ci); + m_capture->FreeCursor(); } }