[client] allow frame updates to be triggered by a timed event

This is a major change to how the LG client performs it's updates. In
the past LG would operate a fixed FPS regardless of incoming update
speed and/or frequency. This change allows LG to dynamically increase
it's FPS in order to better sync with the guest as it's rate changes.
This commit is contained in:
Geoffrey McRae
2020-05-21 13:41:59 +10:00
parent 756b57400b
commit e31f38eadc
5 changed files with 72 additions and 33 deletions

View File

@@ -20,6 +20,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#pragma once
#include <stdbool.h>
#include <time.h>
#define TIMEOUT_INFINITE ((unsigned int)~0)
@@ -34,4 +35,8 @@ bool lgResetEvent (LGEvent * handle);
// os specific method to wrap/convert a native event into a LGEvent
// for windows this is an event HANDLE
LGEvent * lgWrapEvent(void * handle);
LGEvent * lgWrapEvent(void * handle);
// Posix specific, not implmented/possible in windows
bool lgWaitEventAbs(LGEvent * handle, struct timespec * ts);
bool lgWaitEventNS (LGEvent * handle, unsigned int timeout);

View File

@@ -72,7 +72,7 @@ void lgFreeEvent(LGEvent * handle)
free(handle);
}
bool lgWaitEvent(LGEvent * handle, unsigned int timeout)
bool lgWaitEventAbs(LGEvent * handle, struct timespec * ts)
{
assert(handle);
@@ -82,29 +82,32 @@ bool lgWaitEvent(LGEvent * handle, unsigned int timeout)
return false;
}
while(!atomic_load(&handle->flag))
bool ret = true;
while(ret && !atomic_load(&handle->flag))
{
if (timeout == TIMEOUT_INFINITE)
if (!ts)
{
if (pthread_cond_wait(&handle->cond, &handle->mutex) != 0)
{
DEBUG_ERROR("Wait to wait on the condition");
return false;
ret = false;
}
}
else
{
struct timespec ts;
ts.tv_sec = timeout / 1000;
ts.tv_nsec = (timeout % 1000) * 1000000;
switch(pthread_cond_timedwait(&handle->cond, &handle->mutex, &ts))
switch(pthread_cond_timedwait(&handle->cond, &handle->mutex, ts))
{
case 0:
break;
case ETIMEDOUT:
return false;
ret = false;
break;
default:
ret = false;
DEBUG_ERROR("Timed wait failed");
return false;
break;
}
}
}
@@ -118,7 +121,31 @@ bool lgWaitEvent(LGEvent * handle, unsigned int timeout)
return false;
}
return true;
return ret;
}
bool lgWaitEventNS(LGEvent * handle, unsigned int timeout)
{
if (timeout == TIMEOUT_INFINITE)
return lgWaitEventAbs(handle, NULL);
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
uint64_t nsec = ts.tv_nsec + timeout;
if(nsec > 1e9)
{
ts.tv_nsec = nsec - 1e9;
++ts.tv_sec;
}
else
ts.tv_nsec = nsec;
return lgWaitEventAbs(handle, &ts);
}
bool lgWaitEvent(LGEvent * handle, unsigned int timeout)
{
return lgWaitEventNS(handle, timeout * 1000000);
}
bool lgSignalEvent(LGEvent * handle)