[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

@@ -421,7 +421,7 @@ enum EGL_TexStatus egl_texture_bind(EGL_Texture * texture)
if (texture->tex[s.s].sync != 0)
{
switch(glClientWaitSync(texture->tex[s.s].sync, 0, 0))
switch(glClientWaitSync(texture->tex[s.s].sync, 0, 20000000))
{
case GL_ALREADY_SIGNALED:
case GL_CONDITION_SATISFIED:

View File

@@ -62,6 +62,7 @@ static int renderThread(void * unused);
static int frameThread (void * unused);
static LGEvent *e_startup = NULL;
static LGEvent *e_frame = NULL;
static LGThread *t_spice = NULL;
static LGThread *t_render = NULL;
static LGThread *t_cursor = NULL;
@@ -149,7 +150,7 @@ static int renderThread(void * unused)
unsigned int resyncCheck = 0;
struct timespec time;
clock_gettime(CLOCK_MONOTONIC, &time);
clock_gettime(CLOCK_REALTIME, &time);
while(state.running)
{
@@ -161,7 +162,7 @@ static int renderThread(void * unused)
resyncCheck = 0;
struct timespec tmp;
clock_gettime(CLOCK_MONOTONIC, &tmp);
clock_gettime(CLOCK_REALTIME, &tmp);
if (tmp.tv_nsec - time.tv_nsec < 0)
{
tmp.tv_sec -= time.tv_sec - 1;
@@ -172,12 +173,6 @@ static int renderThread(void * unused)
tmp.tv_sec -= time.tv_sec;
tmp.tv_nsec -= time.tv_nsec;
}
const unsigned long diff = tmp.tv_sec * 1000000000 + tmp.tv_nsec;
if (diff > state.frameTime)
{
DEBUG_INFO("Timer drift detected, %lu is > %lu", diff, state.frameTime);
clock_gettime(CLOCK_MONOTONIC, &time);
}
}
if (state.lgr->render_begin && !state.lgr->render_begin(state.lgrData,
@@ -227,19 +222,16 @@ static int renderThread(void * unused)
state.resizeDone = true;
}
if (state.frameTime > 0)
uint64_t nsec = time.tv_nsec + state.frameTime;
if(nsec > 1e9)
{
uint64_t nsec = time.tv_nsec + state.frameTime;
if (nsec > 1e9)
{
time.tv_nsec = nsec - 1e9;
++time.tv_sec;
}
else
time.tv_nsec = nsec;
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &time, NULL);
time.tv_nsec = nsec - 1e9;
++time.tv_sec;
}
else
time.tv_nsec = nsec;
lgWaitEventAbs(e_frame, &time);
}
state.running = false;
@@ -474,6 +466,7 @@ static int frameThread(void * unused)
}
lgmpClientMessageDone(queue);
++state.frameCount;
lgSignalEvent(e_frame);
}
lgmpClientUnsubscribe(&queue);
@@ -1443,6 +1436,13 @@ static int lg_run()
return -1;
}
// setup the new frame event
if (!(e_frame = lgCreateEvent(true, 0)))
{
DEBUG_ERROR("failed to create the frame event");
return -1;
}
// start the renderThread so we don't just display junk
if (!lgCreateThread("renderThread", renderThread, NULL, &t_render))
{
@@ -1555,11 +1555,18 @@ static void lg_shutdown()
if (t_render)
{
lgSignalEvent(e_startup);
lgSignalEvent(e_frame);
lgJoinThread(t_render, NULL);
}
lgmpClientFree(&state.lgmp);
if (e_frame)
{
lgFreeEvent(e_frame);
e_frame = NULL;
}
if (e_startup)
{
lgFreeEvent(e_startup);