[client] implemented better clock drift correction

This commit is contained in:
Geoffrey McRae 2020-05-22 20:45:59 +10:00
parent f5da432d38
commit 4441427943
3 changed files with 50 additions and 30 deletions

View File

@ -1 +1 @@
B2-rc1-6-g60f665a65c+1 B2-rc1-7-gf5da432d38+1

View File

@ -154,29 +154,24 @@ static int renderThread(void * unused)
while(state.running) while(state.running)
{ {
if (state.frameTime > 0)
{
tsAdd(&time, state.frameTime);
// if our clock is too far out of sync, resync it // if our clock is too far out of sync, resync it
// this can happen when switching to/from a TTY, or due to clock drift // this can happen when switching to/from a TTY, or due to clock drift
// we only check this once every 100 frames // we only check this once every 100 frames
if (state.frameTime > 0 && ++resyncCheck == 100) if (++resyncCheck == 100)
{ {
resyncCheck = 0; resyncCheck = 0;
struct timespec tmp; struct timespec end, diff;
clock_gettime(CLOCK_REALTIME, &tmp); clock_gettime(CLOCK_REALTIME, &end);
if (tmp.tv_nsec - time.tv_nsec < 0) tsDiff(&diff, &time, &end);
{ if (diff.tv_sec > 0 || diff.tv_nsec > 1000000000) // 100ms
tmp.tv_sec -= time.tv_sec - 1;
tmp.tv_nsec = 1000000000 + tmp.tv_nsec - time.tv_nsec;
}
else
{
tmp.tv_sec -= time.tv_sec;
tmp.tv_nsec -= time.tv_nsec;
}
if (tmp.tv_sec > 1)
clock_gettime(CLOCK_REALTIME, &time); clock_gettime(CLOCK_REALTIME, &time);
} }
}
if (state.lgrResize) if (state.lgrResize)
{ {
@ -218,19 +213,8 @@ static int renderThread(void * unused)
} }
if (state.frameTime > 0) if (state.frameTime > 0)
{
uint64_t nsec = time.tv_nsec + state.frameTime;
if(nsec > 1e9)
{
time.tv_nsec = nsec - 1e9;
++time.tv_sec;
}
else
time.tv_nsec = nsec;
lgWaitEventAbs(e_frame, &time); lgWaitEventAbs(e_frame, &time);
} }
}
state.running = false; state.running = false;

View File

@ -66,6 +66,42 @@ static inline void nsleep(uint64_t ns)
}; };
nanosleep(&ts, NULL); nanosleep(&ts, NULL);
} }
static inline void tsDiff(struct timespec *diff, const struct timespec *left,
const struct timespec *right)
{
diff->tv_sec = left->tv_sec - right->tv_sec;
diff->tv_nsec = left->tv_nsec - right->tv_nsec;
if (diff->tv_nsec < 0)
{
--diff->tv_sec;
diff->tv_nsec += 1000000000;
}
}
static inline uint32_t __iter_div_u64_rem(uint64_t dividend, uint32_t divisor, uint64_t *remainder)
{
uint32_t ret = 0;
while (dividend >= divisor) {
/* The following asm() prevents the compiler from
optimising this loop into a modulo operation. */
asm("" : "+rm"(dividend));
dividend -= divisor;
ret++;
}
*remainder = dividend;
return ret;
}
static inline void tsAdd(struct timespec *a, uint64_t ns)
{
a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, 1000000000L, &ns);
a->tv_nsec = ns;
}
#endif #endif
typedef bool (*LGTimerFn)(void * udata); typedef bool (*LGTimerFn)(void * udata);