Remove input batching to replace with common-c implementation

This commit is contained in:
Cameron Gutman
2023-02-20 13:19:59 -06:00
parent de15ec666f
commit b47f3ef397
2 changed files with 6 additions and 98 deletions
+2 -8
View File
@@ -247,7 +247,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
View backgroundTouchView = findViewById(R.id.backgroundTouchView); View backgroundTouchView = findViewById(R.id.backgroundTouchView);
backgroundTouchView.setOnTouchListener(this); backgroundTouchView.setOnTouchListener(this);
boolean needsInputBatching = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// Request unbuffered input event dispatching for all input classes we handle here. // Request unbuffered input event dispatching for all input classes we handle here.
// Without this, input events are buffered to be delivered in lock-step with VBlank, // Without this, input events are buffered to be delivered in lock-step with VBlank,
@@ -266,10 +265,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
InputDevice.SOURCE_CLASS_POSITION | // Touchpads InputDevice.SOURCE_CLASS_POSITION | // Touchpads
InputDevice.SOURCE_CLASS_TRACKBALL // Mice (pointer capture) InputDevice.SOURCE_CLASS_TRACKBALL // Mice (pointer capture)
); );
// Since the OS isn't going to batch for us, we have to batch mouse events to
// avoid triggering a bug in GeForce Experience that can lead to massive latency.
needsInputBatching = true;
} }
notificationOverlayView = findViewById(R.id.notificationOverlay); notificationOverlayView = findViewById(R.id.notificationOverlay);
@@ -481,8 +476,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
conn = new NvConnection(getApplicationContext(), conn = new NvConnection(getApplicationContext(),
new ComputerDetails.AddressTuple(host, port), new ComputerDetails.AddressTuple(host, port),
httpsPort, uniqueId, config, httpsPort, uniqueId, config,
PlatformBinding.getCryptoProvider(this), serverCert, PlatformBinding.getCryptoProvider(this), serverCert);
needsInputBatching);
controllerHandler = new ControllerHandler(this, conn, this, prefConfig); controllerHandler = new ControllerHandler(this, conn, this, prefConfig);
keyboardTranslator = new KeyboardTranslator(); keyboardTranslator = new KeyboardTranslator();
@@ -1816,7 +1810,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
@Override @Override
public boolean onTouch(View view, MotionEvent event) { public boolean onTouch(View view, MotionEvent event) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (event.getAction() == MotionEvent.ACTION_DOWN) { if (event.getAction() == MotionEvent.ACTION_DOWN) {
// Tell the OS not to buffer input events for us // Tell the OS not to buffer input events for us
// //
@@ -47,21 +47,13 @@ public class NvConnection {
private ConnectionContext context; private ConnectionContext context;
private static Semaphore connectionAllowed = new Semaphore(1); private static Semaphore connectionAllowed = new Semaphore(1);
private final boolean isMonkey; private final boolean isMonkey;
private final boolean batchMouseInput;
private final Context appContext; private final Context appContext;
private static final int MOUSE_BATCH_PERIOD_MS = 5; public NvConnection(Context appContext, ComputerDetails.AddressTuple host, int httpsPort, String uniqueId, StreamConfiguration config, LimelightCryptoProvider cryptoProvider, X509Certificate serverCert)
private Timer mouseInputTimer;
private final Object mouseInputLock = new Object();
private short relMouseX, relMouseY, relMouseWidth, relMouseHeight;
private short absMouseX, absMouseY, absMouseWidth, absMouseHeight;
public NvConnection(Context appContext, ComputerDetails.AddressTuple host, int httpsPort, String uniqueId, StreamConfiguration config, LimelightCryptoProvider cryptoProvider, X509Certificate serverCert, boolean batchMouseInput)
{ {
this.appContext = appContext; this.appContext = appContext;
this.cryptoProvider = cryptoProvider; this.cryptoProvider = cryptoProvider;
this.uniqueId = uniqueId; this.uniqueId = uniqueId;
this.batchMouseInput = batchMouseInput;
this.context = new ConnectionContext(); this.context = new ConnectionContext();
this.context.serverAddress = host; this.context.serverAddress = host;
@@ -95,11 +87,6 @@ public class NvConnection {
} }
public void stop() { public void stop() {
// Stop sending additional input
if (mouseInputTimer != null) {
mouseInputTimer.cancel();
}
// Interrupt any pending connection. This is thread-safe. // Interrupt any pending connection. This is thread-safe.
MoonBridge.interruptConnection(); MoonBridge.interruptConnection();
@@ -114,24 +101,6 @@ public class NvConnection {
connectionAllowed.release(); connectionAllowed.release();
} }
private void flushMousePosition() {
synchronized (mouseInputLock) {
if (relMouseX != 0 || relMouseY != 0) {
if (relMouseWidth != 0 || relMouseHeight != 0) {
MoonBridge.sendMouseMoveAsMousePosition(relMouseX, relMouseY, relMouseWidth, relMouseHeight);
}
else {
MoonBridge.sendMouseMove(relMouseX, relMouseY);
}
relMouseX = relMouseY = relMouseWidth = relMouseHeight = 0;
}
if (absMouseX != 0 || absMouseY != 0 || absMouseWidth != 0 || absMouseHeight != 0) {
MoonBridge.sendMousePosition(absMouseX, absMouseY, absMouseWidth, absMouseHeight);
absMouseX = absMouseY = absMouseWidth = absMouseHeight = 0;
}
}
}
private InetAddress resolveServerAddress() throws IOException { private InetAddress resolveServerAddress() throws IOException {
// Try to find an address that works for this host // Try to find an address that works for this host
InetAddress[] addrs = InetAddress.getAllByName(context.serverAddress.address); InetAddress[] addrs = InetAddress.getAllByName(context.serverAddress.address);
@@ -473,20 +442,6 @@ public class NvConnection {
connectionAllowed.release(); connectionAllowed.release();
return; return;
} }
if (batchMouseInput) {
// High polling rate mice can cause GeForce Experience's input queue to get backed up,
// causing massive input latency. We counter this by limiting our mouse events to 200 Hz
// which appears to avoid triggering the issue on all known configurations.
mouseInputTimer = new Timer("MouseInput", true);
mouseInputTimer.schedule(new TimerTask() {
@Override
public void run() {
// Flush the mouse position every 5 ms
flushMousePosition();
}
}, MOUSE_BATCH_PERIOD_MS, MOUSE_BATCH_PERIOD_MS);
}
} }
} }
}).start(); }).start();
@@ -495,65 +450,27 @@ public class NvConnection {
public void sendMouseMove(final short deltaX, final short deltaY) public void sendMouseMove(final short deltaX, final short deltaY)
{ {
if (!isMonkey) { if (!isMonkey) {
synchronized (mouseInputLock) { MoonBridge.sendMouseMove(deltaX, deltaY);
relMouseX += deltaX;
relMouseY += deltaY;
// Reset these to ensure we don't send this as a position update
relMouseWidth = 0;
relMouseHeight = 0;
}
if (!batchMouseInput) {
flushMousePosition();
}
} }
} }
public void sendMousePosition(short x, short y, short referenceWidth, short referenceHeight) public void sendMousePosition(short x, short y, short referenceWidth, short referenceHeight)
{ {
if (!isMonkey) { if (!isMonkey) {
synchronized (mouseInputLock) { MoonBridge.sendMousePosition(x, y, referenceWidth, referenceHeight);
absMouseX = x;
absMouseY = y;
absMouseWidth = referenceWidth;
absMouseHeight = referenceHeight;
}
if (!batchMouseInput) {
flushMousePosition();
}
} }
} }
public void sendMouseMoveAsMousePosition(short deltaX, short deltaY, short referenceWidth, short referenceHeight) public void sendMouseMoveAsMousePosition(short deltaX, short deltaY, short referenceWidth, short referenceHeight)
{ {
if (!isMonkey) { if (!isMonkey) {
synchronized (mouseInputLock) { MoonBridge.sendMouseMoveAsMousePosition(deltaX, deltaY, referenceWidth, referenceHeight);
// Only accumulate the delta if the reference size is the same
if (relMouseWidth == referenceWidth && relMouseHeight == referenceHeight) {
relMouseX += deltaX;
relMouseY += deltaY;
}
else {
relMouseX = deltaX;
relMouseY = deltaY;
}
relMouseWidth = referenceWidth;
relMouseHeight = referenceHeight;
}
if (!batchMouseInput) {
flushMousePosition();
}
} }
} }
public void sendMouseButtonDown(final byte mouseButton) public void sendMouseButtonDown(final byte mouseButton)
{ {
if (!isMonkey) { if (!isMonkey) {
flushMousePosition();
MoonBridge.sendMouseButton(MouseButtonPacket.PRESS_EVENT, mouseButton); MoonBridge.sendMouseButton(MouseButtonPacket.PRESS_EVENT, mouseButton);
} }
} }
@@ -561,7 +478,6 @@ public class NvConnection {
public void sendMouseButtonUp(final byte mouseButton) public void sendMouseButtonUp(final byte mouseButton)
{ {
if (!isMonkey) { if (!isMonkey) {
flushMousePosition();
MoonBridge.sendMouseButton(MouseButtonPacket.RELEASE_EVENT, mouseButton); MoonBridge.sendMouseButton(MouseButtonPacket.RELEASE_EVENT, mouseButton);
} }
} }
@@ -597,14 +513,12 @@ public class NvConnection {
public void sendMouseScroll(final byte scrollClicks) { public void sendMouseScroll(final byte scrollClicks) {
if (!isMonkey) { if (!isMonkey) {
flushMousePosition();
MoonBridge.sendMouseScroll(scrollClicks); MoonBridge.sendMouseScroll(scrollClicks);
} }
} }
public void sendMouseHighResScroll(final short scrollAmount) { public void sendMouseHighResScroll(final short scrollAmount) {
if (!isMonkey) { if (!isMonkey) {
flushMousePosition();
MoonBridge.sendMouseHighResScroll(scrollAmount); MoonBridge.sendMouseHighResScroll(scrollAmount);
} }
} }