Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce input lag by 36ms by separating frame rate limiting from update batching #166

Merged
merged 1 commit into from
Jun 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 38 additions & 11 deletions module/rdpClientCon.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ static int
rdpClientConDisconnect(rdpPtr dev, rdpClientCon *clientCon);
static CARD32
rdpDeferredIdleDisconnectCallback(OsTimerPtr timer, CARD32 now, pointer arg);
static void
rdpScheduleDeferredUpdate(rdpClientCon *clientCon);

#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 18, 5, 0, 0)

Expand Down Expand Up @@ -2424,6 +2426,7 @@ rdpDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg)
LLOGLN(10, ("rdpDeferredUpdateCallback:"));
clientCon = (rdpClientCon *) arg;
clientCon->updateScheduled = FALSE;
clientCon->lastUpdateTime = now;
if (clientCon->suppress_output)
{
LLOGLN(10, ("rdpDeferredUpdateCallback: suppress_output set"));
Expand All @@ -2436,10 +2439,7 @@ rdpDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg)
LLOGLN(10, ("rdpDeferredUpdateCallback: reschedule rect_id %d "
"rect_id_ack %d",
clientCon->rect_id, clientCon->rect_id_ack));
clientCon->updateTimer = TimerSet(clientCon->updateTimer, 0, 40,
rdpDeferredUpdateCallback,
clientCon);
clientCon->updateScheduled = TRUE;
rdpScheduleDeferredUpdate(clientCon);
return 0;
}
else
Expand Down Expand Up @@ -2532,14 +2532,43 @@ rdpDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg)
}
if (rdpRegionNotEmpty(clientCon->dirtyRegion))
{
clientCon->updateTimer = TimerSet(clientCon->updateTimer, 0, 40,
rdpDeferredUpdateCallback,
clientCon);
clientCon->updateScheduled = TRUE;
rdpScheduleDeferredUpdate(clientCon);
}
return 0;
}


/******************************************************************************/
#define MIN_MS_BETWEEN_FRAMES 40
#define MIN_MS_TO_WAIT_FOR_MORE_UPDATES 4
static void
rdpScheduleDeferredUpdate(rdpClientCon *clientCon)
{
uint32_t curTime;
uint32_t msToWait;
uint32_t minNextUpdateTime;

curTime = (uint32_t) GetTimeInMillis();
/* use two separate delays in order to limit the update rate and wait a bit
for more changes before sending an update. Always waiting the longer
delay would introduce unnecessarily much latency. */
msToWait = MIN_MS_TO_WAIT_FOR_MORE_UPDATES;
minNextUpdateTime = clientCon->lastUpdateTime + MIN_MS_BETWEEN_FRAMES;
/* the first check is to gracefully handle the infrequent case of
the time wrapping around */
if(clientCon->lastUpdateTime < curTime &&
minNextUpdateTime > curTime + msToWait)
{
msToWait = minNextUpdateTime - curTime;
}

clientCon->updateTimer = TimerSet(clientCon->updateTimer, 0,
(CARD32) msToWait,
rdpDeferredUpdateCallback,
clientCon);
clientCon->updateScheduled = TRUE;
}

/******************************************************************************/
int
rdpClientConAddDirtyScreenReg(rdpPtr dev, rdpClientCon *clientCon,
Expand All @@ -2549,9 +2578,7 @@ rdpClientConAddDirtyScreenReg(rdpPtr dev, rdpClientCon *clientCon,
rdpRegionUnion(clientCon->dirtyRegion, clientCon->dirtyRegion, reg);
if (clientCon->updateScheduled == FALSE)
{
clientCon->updateTimer = TimerSet(clientCon->updateTimer, 0, 40,
rdpDeferredUpdateCallback, clientCon);
clientCon->updateScheduled = TRUE;
rdpScheduleDeferredUpdate(clientCon);
}
return 0;
}
Expand Down
1 change: 1 addition & 0 deletions module/rdpClientCon.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ struct _rdpClientCon
int rect_id_ack;

OsTimerPtr updateTimer;
CARD32 lastUpdateTime; /* millisecond timestamp */
int updateScheduled; /* boolean */

RegionPtr dirtyRegion;
Expand Down