Skip to content

Commit

Permalink
[host] accumulate cursor updates rather then queue
Browse files Browse the repository at this point in the history
  • Loading branch information
gnif committed Oct 19, 2018
1 parent 2692ccc commit 1350ba6
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 68 deletions.
96 changes: 40 additions & 56 deletions host/Capture/DXGI.cpp
Expand Up @@ -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))
{
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
12 changes: 6 additions & 6 deletions host/Capture/DXGI.h
Expand Up @@ -31,6 +31,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include <shlwapi.h>
#include <stdio.h>

#define DXGI_CURSOR_RING_SIZE 2

namespace Capture
{
class DXGI : public ICapture
Expand Down Expand Up @@ -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<CursorInfo > CursorList;
typedef std::list<CursorBuffer *> 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;

Expand Down
5 changes: 3 additions & 2 deletions host/ICapture.h
Expand Up @@ -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
Expand Down Expand Up @@ -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;
};
8 changes: 4 additions & 4 deletions host/Service.cpp
Expand Up @@ -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
{
Expand All @@ -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);
}
}

Expand All @@ -387,7 +387,7 @@ DWORD Service::CursorThread()

flags |= KVMFR_CURSOR_FLAG_UPDATE;
cursor->flags = flags;
m_capture->FreeCursor(ci);
m_capture->FreeCursor();
}
}

Expand Down

0 comments on commit 1350ba6

Please sign in to comment.