Batch mouse movement events to reduce input lag with high polling rate mice

This commit is contained in:
Cameron Gutman 2017-06-23 16:43:10 -07:00
parent 59e3a104ba
commit 37387e151f
3 changed files with 21 additions and 6 deletions

View File

@ -51,6 +51,13 @@ static char GetModifierFlags(const pp::InputEvent& event) {
return flags;
}
void MoonlightInstance::ReportMouseMovement() {
if (m_MouseDeltaX != 0 || m_MouseDeltaY != 0) {
LiSendMouseMoveEvent(m_MouseDeltaX, m_MouseDeltaY);
m_MouseDeltaX = m_MouseDeltaY = 0;
}
}
bool MoonlightInstance::HandleInputEvent(const pp::InputEvent& event) {
switch (event.GetType()) {
case PP_INPUTEVENT_TYPE_MOUSEDOWN: {
@ -77,7 +84,10 @@ bool MoonlightInstance::HandleInputEvent(const pp::InputEvent& event) {
pp::MouseInputEvent mouseEvent(event);
pp::Point posDelta = mouseEvent.GetMovement();
LiSendMouseMoveEvent(posDelta.x(), posDelta.y());
// Wait to report mouse movement until the next input polling window
// to allow batching to occur which reduces overall input lag.
m_MouseDeltaX += posDelta.x();
m_MouseDeltaY += posDelta.y();
return true;
}

View File

@ -85,18 +85,19 @@ void* MoonlightInstance::StopThreadFunc(void* context) {
// We also need to stop this thread after the connection thread, because it depends
// on being initialized there.
pthread_join(g_Instance->m_GamepadThread, NULL);
pthread_join(g_Instance->m_InputThread, NULL);
// Stop the connection
LiStopConnection();
return NULL;
}
void* MoonlightInstance::GamepadThreadFunc(void* context) {
void* MoonlightInstance::InputThreadFunc(void* context) {
MoonlightInstance* me = (MoonlightInstance*)context;
while (me->m_Running) {
me->PollGamepads();
me->ReportMouseMovement();
// Poll every 10 ms
usleep(10 * 1000);
@ -135,7 +136,7 @@ void* MoonlightInstance::ConnectionThreadFunc(void* context) {
// Set running state before starting connection-specific threads
me->m_Running = true;
pthread_create(&me->m_GamepadThread, NULL, MoonlightInstance::GamepadThreadFunc, me);
pthread_create(&me->m_InputThread, NULL, MoonlightInstance::InputThreadFunc, me);
return NULL;
}

View File

@ -59,6 +59,8 @@ class MoonlightInstance : public pp::Instance, public pp::MouseLock {
m_MouseLocked(false),
m_WaitingForAllModifiersUp(false),
m_AccumulatedTicks(0),
m_MouseDeltaX(0),
m_MouseDeltaY(0),
openHttpThread(this) {
// This function MUST be used otherwise sockets don't work (nacl_io_init() doesn't work!)
nacl_io_init_ppapi(pp_instance(), pp::Module::Get()->get_browser_interface());
@ -85,6 +87,7 @@ class MoonlightInstance : public pp::Instance, public pp::MouseLock {
void PairCallback(int32_t /*result*/, int32_t callbackId, pp::VarArray args);
bool HandleInputEvent(const pp::InputEvent& event);
void ReportMouseMovement();
void PollGamepads();
@ -105,7 +108,7 @@ class MoonlightInstance : public pp::Instance, public pp::MouseLock {
static void ProfilerPrintWarning(const char* message);
static void* ConnectionThreadFunc(void* context);
static void* GamepadThreadFunc(void* context);
static void* InputThreadFunc(void* context);
static void* StopThreadFunc(void* context);
static void ClStageStarting(int stage);
@ -151,7 +154,7 @@ class MoonlightInstance : public pp::Instance, public pp::MouseLock {
bool m_Running;
pthread_t m_ConnectionThread;
pthread_t m_GamepadThread;
pthread_t m_InputThread;
pp::Graphics3D m_Graphics3D;
pp::VideoDecoder* m_VideoDecoder;
@ -173,6 +176,7 @@ class MoonlightInstance : public pp::Instance, public pp::MouseLock {
bool m_MouseLocked;
bool m_WaitingForAllModifiersUp;
float m_AccumulatedTicks;
int32_t m_MouseDeltaX, m_MouseDeltaY;
pp::SimpleThread openHttpThread;
};