144 lines
5.9 KiB
Diff
144 lines
5.9 KiB
Diff
--- a/src/InputStream.c
|
|
+++ b/src/InputStream.c
|
|
@@ -86,11 +86,16 @@
|
|
int deltaX, deltaY;
|
|
bool dirty; // Update ready to send (queued packet holder in packetQueue)
|
|
} currentRelativeMouseState;
|
|
-static struct {
|
|
- int x, y;
|
|
- int width, height;
|
|
- bool dirty; // Update ready to send (queued packet holder in packetQueue)
|
|
-} currentAbsoluteMouseState;
|
|
+// Only this packet may absorb newer positions. A button event seals the batch.
|
|
+static PPACKET_HOLDER currentQueuedAbsoluteMousePacket;
|
|
+
|
|
+static void latchAbsoluteMousePacket(PPACKET_HOLDER holder) {
|
|
+ PltLockMutex(&batchedInputMutex);
|
|
+ if (currentQueuedAbsoluteMousePacket == holder) {
|
|
+ currentQueuedAbsoluteMousePacket = NULL;
|
|
+ }
|
|
+ PltUnlockMutex(&batchedInputMutex);
|
|
+}
|
|
|
|
// Initializes the input stream
|
|
int initializeInputStream(void) {
|
|
@@ -120,7 +125,7 @@
|
|
|
|
memset(currentGamepadSensorState, 0, sizeof(currentGamepadSensorState));
|
|
memset(¤tRelativeMouseState, 0, sizeof(currentRelativeMouseState));
|
|
- memset(¤tAbsoluteMouseState, 0, sizeof(currentAbsoluteMouseState));
|
|
+ currentQueuedAbsoluteMousePacket = NULL;
|
|
PltCreateMutex(&batchedInputMutex);
|
|
|
|
return 0;
|
|
@@ -444,24 +449,9 @@
|
|
now = PltGetMillis();
|
|
}
|
|
|
|
- PltLockMutex(&batchedInputMutex);
|
|
-
|
|
- // Populate the packet with the latest state
|
|
- holder->packet.mouseMoveAbs.x = BE16(currentAbsoluteMouseState.x);
|
|
- holder->packet.mouseMoveAbs.y = BE16(currentAbsoluteMouseState.y);
|
|
-
|
|
- // There appears to be a rounding error in GFE's scaling calculation which prevents
|
|
- // the cursor from reaching the far edge of the screen when streaming at smaller
|
|
- // resolutions with a higher desktop resolution (like streaming 720p with a desktop
|
|
- // resolution of 1080p, or streaming 720p/1080p with a desktop resolution of 4K).
|
|
- // Subtracting one from the reference dimensions seems to work around this issue.
|
|
- holder->packet.mouseMoveAbs.width = BE16(currentAbsoluteMouseState.width - 1);
|
|
- holder->packet.mouseMoveAbs.height = BE16(currentAbsoluteMouseState.height - 1);
|
|
-
|
|
- // The state change is no longer pending
|
|
- currentAbsoluteMouseState.dirty = false;
|
|
-
|
|
- PltUnlockMutex(&batchedInputMutex);
|
|
+ // Payload was filled by the producer under the same mutex. Latch
|
|
+ // only our packet; a later batch may already be queued after a click.
|
|
+ latchAbsoluteMousePacket(holder);
|
|
|
|
lastMousePacketTime = now;
|
|
}
|
|
@@ -780,52 +770,37 @@
|
|
}
|
|
|
|
PltLockMutex(&batchedInputMutex);
|
|
-
|
|
- // Overwrite the previous mouse location with the new one
|
|
- currentAbsoluteMouseState.x = x;
|
|
- currentAbsoluteMouseState.y = y;
|
|
- currentAbsoluteMouseState.width = referenceWidth;
|
|
- currentAbsoluteMouseState.height = referenceHeight;
|
|
-
|
|
- // Queue a packet holder if this is the only pending absolute mouse event
|
|
- if (!currentAbsoluteMouseState.dirty) {
|
|
- // Set the dirty flag to claim ownership of inserting the packet holder
|
|
- // and unlock to allow other threads to enqueue or process input.
|
|
- currentAbsoluteMouseState.dirty = true;
|
|
- PltUnlockMutex(&batchedInputMutex);
|
|
-
|
|
+ holder = currentQueuedAbsoluteMousePacket;
|
|
+ bool newPacket = holder == NULL;
|
|
+ if (newPacket) {
|
|
holder = allocatePacketHolder(0);
|
|
if (holder == NULL) {
|
|
- currentAbsoluteMouseState.dirty = false;
|
|
+ PltUnlockMutex(&batchedInputMutex);
|
|
return -1;
|
|
}
|
|
-
|
|
holder->channelId = CTRL_CHANNEL_MOUSE;
|
|
-
|
|
- // TODO: Send this as unreliable sequenced when we have a delayed reliable retransmission thread
|
|
holder->enetPacketFlags = ENET_PACKET_FLAG_RELIABLE;
|
|
-
|
|
holder->packet.mouseMoveAbs.header.size = BE32(sizeof(NV_ABS_MOUSE_MOVE_PACKET) - sizeof(uint32_t));
|
|
holder->packet.mouseMoveAbs.header.magic = LE32(MOUSE_MOVE_ABS_MAGIC);
|
|
holder->packet.mouseMoveAbs.unused = 0;
|
|
-
|
|
- // Remaining fields are set in the input thread based on the latest currentAbsoluteMouseState values
|
|
-
|
|
+ }
|
|
+ holder->packet.mouseMoveAbs.x = BE16(x);
|
|
+ holder->packet.mouseMoveAbs.y = BE16(y);
|
|
+ // Preserve upstream's far-edge rounding workaround.
|
|
+ holder->packet.mouseMoveAbs.width = BE16(referenceWidth - 1);
|
|
+ holder->packet.mouseMoveAbs.height = BE16(referenceHeight - 1);
|
|
+ err = 0;
|
|
+ if (newPacket) {
|
|
+ currentQueuedAbsoluteMousePacket = holder;
|
|
err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry);
|
|
if (err != LBQ_SUCCESS) {
|
|
+ currentQueuedAbsoluteMousePacket = NULL;
|
|
LC_ASSERT(err == LBQ_BOUND_EXCEEDED);
|
|
Limelog("Input queue reached maximum size limit\n");
|
|
freePacketHolder(holder);
|
|
-
|
|
- // We weren't able to insert the entry, so let the next call try again
|
|
- currentAbsoluteMouseState.dirty = false;
|
|
- }
|
|
- }
|
|
- else {
|
|
- // There's already a packet holder queued to send this event
|
|
- PltUnlockMutex(&batchedInputMutex);
|
|
- err = 0;
|
|
- }
|
|
+ }
|
|
+ }
|
|
+ PltUnlockMutex(&batchedInputMutex);
|
|
|
|
// This is not thread safe, but it's not a big deal because callers that want to
|
|
// use LiSendRelativeMotionAsMousePositionEvent() must not mix these function
|
|
@@ -872,7 +847,11 @@
|
|
holder->packet.mouseButton.header.magic = LE32(holder->packet.mouseButton.header.magic);
|
|
holder->packet.mouseButton.button = (uint8_t)button;
|
|
|
|
+ PltLockMutex(&batchedInputMutex);
|
|
+ // Do not let a later position overwrite the move preceding this click.
|
|
+ currentQueuedAbsoluteMousePacket = NULL;
|
|
err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry);
|
|
+ PltUnlockMutex(&batchedInputMutex);
|
|
if (err != LBQ_SUCCESS) {
|
|
LC_ASSERT(err == LBQ_BOUND_EXCEEDED);
|
|
Limelog("Input queue reached maximum size limit\n");
|