[host] windows/nvfbc/common: strip out broken "enhanced" event logic

This so called "enhanced" event logic is completely flawed and can never
work correctly, better to strip it out and put our faith in windows to
handle the events for us.

And yes, I am fully aware I wrote the utter trash in the first place :)
This commit is contained in:
Geoffrey McRae 2021-07-09 10:19:55 +10:00
parent bfb47a0ae4
commit 041b95507d
3 changed files with 44 additions and 198 deletions

View File

@ -31,7 +31,6 @@ typedef struct LGEvent LGEvent;
LGEvent * lgCreateEvent(bool autoReset, unsigned int msSpinTime); LGEvent * lgCreateEvent(bool autoReset, unsigned int msSpinTime);
void lgFreeEvent (LGEvent * handle); void lgFreeEvent (LGEvent * handle);
bool lgWaitEvent (LGEvent * handle, unsigned int timeout); bool lgWaitEvent (LGEvent * handle, unsigned int timeout);
bool lgWaitEvents (LGEvent * handles[], int count, bool waitAll, unsigned int timeout);
bool lgSignalEvent(LGEvent * handle); bool lgSignalEvent(LGEvent * handle);
bool lgResetEvent (LGEvent * handle); bool lgResetEvent (LGEvent * handle);

View File

@ -25,132 +25,36 @@
#include <windows.h> #include <windows.h>
#include <stdatomic.h> #include <stdatomic.h>
struct LGEvent
{
volatile int lock;
bool reset;
HANDLE handle;
bool wrapped;
unsigned int msSpinTime;
_Atomic(bool) signaled;
};
LGEvent * lgCreateEvent(bool autoReset, unsigned int msSpinTime) LGEvent * lgCreateEvent(bool autoReset, unsigned int msSpinTime)
{ {
LGEvent * event = (LGEvent *)malloc(sizeof(LGEvent)); HANDLE handle = CreateEvent(NULL, autoReset ? FALSE : TRUE, FALSE, NULL);
if (!event) if (!handle)
{
DEBUG_ERROR("out of ram");
return NULL;
}
event->lock = 0;
event->reset = autoReset;
event->handle = CreateEvent(NULL, autoReset ? FALSE : TRUE, FALSE, NULL);
event->wrapped = false;
event->msSpinTime = msSpinTime;
atomic_store(&event->signaled, false);
if (!event->handle)
{ {
DEBUG_WINERROR("Failed to create the event", GetLastError()); DEBUG_WINERROR("Failed to create the event", GetLastError());
free(event);
return NULL; return NULL;
} }
return event; return (LGEvent *)handle;
} }
LGEvent * lgWrapEvent(void * handle) LGEvent * lgWrapEvent(void * handle)
{ {
LGEvent * event = (LGEvent *)malloc(sizeof(LGEvent)); return (LGEvent *)handle;
if (!event)
{
DEBUG_ERROR("out of ram");
return NULL;
}
event->lock = 0;
event->reset = false;
event->handle = (HANDLE)handle;
event->wrapped = true;
event->msSpinTime = 0;
atomic_store(&event->signaled, false);
return event;
} }
void lgFreeEvent(LGEvent * event) void lgFreeEvent(LGEvent * event)
{ {
CloseHandle(event->handle); CloseHandle((HANDLE)event);
} }
bool lgWaitEvent(LGEvent * event, unsigned int timeout) bool lgWaitEvent(LGEvent * event, unsigned int timeout)
{ {
// wrapped events can't be enahnced
if (!event->wrapped)
{
if (event->reset)
{
if (atomic_exchange(&event->signaled, false))
return true;
}
else
{
if (atomic_load(&event->signaled))
return true;
}
if (timeout == 0)
return false;
if (event->msSpinTime)
{
unsigned int spinTime = event->msSpinTime;
if (timeout != TIMEOUT_INFINITE)
{
if (timeout > event->msSpinTime)
timeout -= event->msSpinTime;
else
{
spinTime -= timeout;
timeout = 0;
}
}
uint64_t now = microtime();
uint64_t end = now + spinTime * 1000;
if (event->reset)
{
while(!atomic_exchange(&event->signaled, false))
{
now = microtime();
if (now >= end)
return false;
}
return true;
}
else
{
while(!atomic_load(&event->signaled))
{
now = microtime();
if (now >= end)
return false;
}
return true;
}
}
}
const DWORD to = (timeout == TIMEOUT_INFINITE) ? INFINITE : (DWORD)timeout; const DWORD to = (timeout == TIMEOUT_INFINITE) ? INFINITE : (DWORD)timeout;
while(true) do
{ {
switch(WaitForSingleObject(event->handle, to)) switch(WaitForSingleObject((HANDLE)event, to))
{ {
case WAIT_OBJECT_0: case WAIT_OBJECT_0:
if (!event->reset)
atomic_store(&event->signaled, true);
return true; return true;
case WAIT_ABANDONED: case WAIT_ABANDONED:
@ -159,7 +63,6 @@ bool lgWaitEvent(LGEvent * event, unsigned int timeout)
case WAIT_TIMEOUT: case WAIT_TIMEOUT:
if (timeout == TIMEOUT_INFINITE) if (timeout == TIMEOUT_INFINITE)
continue; continue;
return false; return false;
case WAIT_FAILED: case WAIT_FAILED:
@ -168,63 +71,18 @@ bool lgWaitEvent(LGEvent * event, unsigned int timeout)
} }
DEBUG_ERROR("Unknown wait event return code"); DEBUG_ERROR("Unknown wait event return code");
return false;
} }
} while(0);
bool lgWaitEvents(LGEvent * events[], int count, bool waitAll, unsigned int timeout) return false;
{
const DWORD to = (timeout == TIMEOUT_INFINITE) ? INFINITE : (DWORD)timeout;
HANDLE * handles = (HANDLE *)malloc(sizeof(HANDLE) * count);
for(int i = 0; i < count; ++i)
handles[i] = events[i]->handle;
while(true)
{
DWORD result = WaitForMultipleObjects(count, handles, waitAll, to);
if (result >= WAIT_OBJECT_0 && result < count)
{
// null non signaled events from the handle list
for(int i = 0; i < count; ++i)
if (i != result && !lgWaitEvent(events[i], 0))
events[i] = NULL;
free(handles);
return true;
}
if (result >= WAIT_ABANDONED_0 && result - WAIT_ABANDONED_0 < count)
continue;
switch(result)
{
case WAIT_TIMEOUT:
if (timeout == TIMEOUT_INFINITE)
continue;
free(handles);
return false;
case WAIT_FAILED:
DEBUG_WINERROR("Wait for event failed", GetLastError());
free(handles);
return false;
}
DEBUG_ERROR("Unknown wait event return code");
free(handles);
return false;
}
} }
bool lgSignalEvent(LGEvent * event) bool lgSignalEvent(LGEvent * event)
{ {
atomic_store(&event->signaled, true); return SetEvent((HANDLE)event);
return SetEvent(event->handle);
} }
bool lgResetEvent(LGEvent * event) bool lgResetEvent(LGEvent * event)
{ {
atomic_store(&event->signaled, false); return ResetEvent((HANDLE)event);
return ResetEvent(event->handle);
} }

View File

@ -58,7 +58,7 @@ struct iface
NvFBCFrameGrabInfo grabInfo; NvFBCFrameGrabInfo grabInfo;
LGEvent * frameEvent; LGEvent * frameEvent;
LGEvent * cursorEvents[2]; LGEvent * cursorEvent;
int mouseX, mouseY, mouseHotX, mouseHotY; int mouseX, mouseY, mouseHotX, mouseHotY;
bool mouseVisible, hasMousePosition; bool mouseVisible, hasMousePosition;
@ -92,8 +92,16 @@ static void on_mouseMove(int x, int y)
this->hasMousePosition = true; this->hasMousePosition = true;
this->mouseX = x; this->mouseX = x;
this->mouseY = y; this->mouseY = y;
if (this->cursorEvents[0])
lgSignalEvent(this->cursorEvents[0]); const CapturePointer pointer =
{
.positionUpdate = true,
.visible = this->mouseVisible,
.x = x - this->mouseHotX,
.y = y - this->mouseHotY
};
this->postPointerBufferFn(pointer);
} }
static const char * nvfbc_getName(void) static const char * nvfbc_getName(void)
@ -196,10 +204,8 @@ static bool nvfbc_init(void)
return false; return false;
} }
this->cursorEvents[0] = lgCreateEvent(true, 10);
if (this->seperateCursor) if (this->seperateCursor)
this->cursorEvents[1] = lgWrapEvent(event); this->cursorEvent = lgWrapEvent(event);
if (!this->mouseHookCreated) if (!this->mouseHookCreated)
{ {
@ -232,7 +238,7 @@ static void nvfbc_stop(void)
{ {
this->stop = true; this->stop = true;
lgSignalEvent(this->cursorEvents[0]); lgSignalEvent(this->cursorEvent);
lgSignalEvent(this->frameEvent); lgSignalEvent(this->frameEvent);
if (this->pointerThread) if (this->pointerThread)
@ -244,12 +250,7 @@ static void nvfbc_stop(void)
static bool nvfbc_deinit(void) static bool nvfbc_deinit(void)
{ {
if (this->cursorEvents[0]) this->cursorEvent = NULL;
{
lgFreeEvent(this->cursorEvents[0]);
this->cursorEvents[0] = NULL;
}
if (this->nvfbc) if (this->nvfbc)
{ {
NvFBCToSysRelease(&this->nvfbc); NvFBCToSysRelease(&this->nvfbc);
@ -378,13 +379,9 @@ static CaptureResult nvfbc_getFrame(FrameBuffer * frame,
static int pointerThread(void * unused) static int pointerThread(void * unused)
{ {
lgSignalEvent(this->cursorEvents[1]);
while(!this->stop) while(!this->stop)
{ {
LGEvent * events[2]; if (!lgWaitEvent(this->cursorEvent, 1000))
memcpy(&events, &this->cursorEvents, sizeof(LGEvent *) * 2);
if (!lgWaitEvents(events, this->seperateCursor ? 2 : 1, false, 1000))
continue; continue;
if (this->stop) if (this->stop)
@ -392,39 +389,31 @@ static int pointerThread(void * unused)
CaptureResult result; CaptureResult result;
CapturePointer pointer = { 0 }; CapturePointer pointer = { 0 };
bool hotspotUpdated = false;
if (this->seperateCursor && events[1]) void * data;
uint32_t size;
if (!this->getPointerBufferFn(&data, &size))
{ {
void * data; DEBUG_WARN("failed to get a pointer buffer");
uint32_t size; continue;
if (!this->getPointerBufferFn(&data, &size))
{
DEBUG_WARN("failed to get a pointer buffer");
continue;
}
result = NvFBCToSysGetCursor(this->nvfbc, &pointer, data, size);
if (result != CAPTURE_RESULT_OK)
{
DEBUG_WARN("NvFBCToSysGetCursor failed");
continue;
}
this->mouseVisible = pointer.visible;
this->mouseHotX = pointer.hx;
this->mouseHotY = pointer.hy;
hotspotUpdated = true;
} }
if (events[0] || (hotspotUpdated && this->hasMousePosition)) result = NvFBCToSysGetCursor(this->nvfbc, &pointer, data, size);
if (result != CAPTURE_RESULT_OK)
{ {
pointer.positionUpdate = true; DEBUG_WARN("NvFBCToSysGetCursor failed");
pointer.visible = this->mouseVisible; continue;
pointer.x = this->mouseX - this->mouseHotX;
pointer.y = this->mouseY - this->mouseHotY;
} }
this->mouseVisible = pointer.visible;
this->mouseHotX = pointer.hx;
this->mouseHotY = pointer.hy;
pointer.positionUpdate = true;
pointer.visible = this->mouseVisible;
pointer.x = this->mouseX - pointer.hx;
pointer.y = this->mouseY - pointer.hy;
this->postPointerBufferFn(pointer); this->postPointerBufferFn(pointer);
} }