mirror of
https://github.com/lucannez64/darling-lol.git
synced 2026-10-26 19:47:42 +00:00
Address code review feedback on input handling, pacing, and runtime cleanup
This commit is contained in:
1 parent
d981cbe8c3
commit
0e2a2dde61
8 files changed
+68
-64
No files matched your search
@@ -2307,7 +2307,7 @@ index 18189404..c683f96a 100644
|
||||
+- (NSRect) frameForRootRect: (NSRect) rect;
|
||||
@end
|
||||
diff --git a/AppKit/X11.backend/X11Display.m b/AppKit/X11.backend/X11Display.m
|
||||
index 5ae29bf4..516decf3 100644
|
||||
index 5ae29bf4..d7fb09fc 100644
|
||||
--- a/AppKit/X11.backend/X11Display.m
|
||||
+++ b/AppKit/X11.backend/X11Display.m
|
||||
@@ -48,12 +48,271 @@
|
||||
@@ -3125,7 +3125,7 @@ index 5ae29bf4..516decf3 100644
|
||||
+ int xfd = ConnectionNumber(_display);
|
||||
+ struct pollfd pfd = { .fd = xfd, .events = POLLIN };
|
||||
+ int timeout_ms = (int)(slice * 1000.0);
|
||||
+ if (timeout_ms < 1) timeout_ms = 1;
|
||||
+ if (timeout_ms < 0) timeout_ms = 0;
|
||||
+ extern long __lolsys_syscall(long, long, long, long, long, long, int);
|
||||
+ __lolsys_syscall((long)&pfd, 1, timeout_ms, 0, 0, 0, 7 /* Linux poll */);
|
||||
+ }
|
||||
@@ -3391,7 +3391,7 @@ index 5ae29bf4..516decf3 100644
|
||||
[self postEvent: event atStart: NO];
|
||||
break;
|
||||
|
||||
@@ -1160,49 +1855,113 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1160,49 +1855,111 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
// ev->xmotion.x, ev->xmotion.y, ev->xmotion.x_root,
|
||||
// ev->xmotion.y_root);
|
||||
|
||||
@@ -3418,8 +3418,6 @@ index 5ae29bf4..516decf3 100644
|
||||
+ ev->xmotion.x = clampedX;
|
||||
+ ev->xmotion.y = clampedY;
|
||||
+ }
|
||||
+ } else if (!_relativeMouse.active && window != nil && !_confinedWindow) {
|
||||
+ [self updateMouseConfinementForWindow: window];
|
||||
+ }
|
||||
+
|
||||
CGPoint lastMotionPos = [window mouseLocationOutsideOfEventStream];
|
||||
@@ -3531,7 +3529,7 @@ index 5ae29bf4..516decf3 100644
|
||||
mouseEventWithType: type
|
||||
location: pos
|
||||
modifierFlags:
|
||||
@@ -1211,28 +1970,58 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1211,28 +1968,58 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
clickCount: 1
|
||||
deltaX: deltaX
|
||||
deltaY: deltaY];
|
||||
@@ -3592,7 +3590,7 @@ index 5ae29bf4..516decf3 100644
|
||||
NSLog(@"FocusIn");
|
||||
if ([delegate attachedSheet]) {
|
||||
[[delegate attachedSheet] makeKeyAndOrderFront: delegate];
|
||||
@@ -1243,28 +2032,59 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1243,28 +2030,61 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
checkForAppDeactivation: NO];
|
||||
lastFocusedWindow = nil;
|
||||
}
|
||||
@@ -3620,7 +3618,7 @@ index 5ae29bf4..516decf3 100644
|
||||
+ rclolFocusDetailName(ev->xfocus.detail), _relativeRequested, _relativeMouse.active,
|
||||
+ (unsigned long) _confinedWindow,
|
||||
+ [NSApp isActive]);
|
||||
+ if (ev->xfocus.detail == NotifyPointer || ev->xfocus.mode == NotifyGrab || ev->xfocus.mode == NotifyUngrab) {
|
||||
+ if (ev->xfocus.detail == NotifyPointer || ev->xfocus.detail == NotifyInferior || ev->xfocus.mode == NotifyGrab || ev->xfocus.mode == NotifyUngrab) {
|
||||
+ /* Pointer boundary crossing or grab transition in XWayland: do NOT release confinement or deactivate window */
|
||||
+ break;
|
||||
+ }
|
||||
@@ -3637,6 +3635,8 @@ index 5ae29bf4..516decf3 100644
|
||||
+ if (_confinedWindow) {
|
||||
+ XUngrabPointer(_display, CurrentTime);
|
||||
+ _confinedWindow = None;
|
||||
+ _confinedWidth = 0;
|
||||
+ _confinedHeight = 0;
|
||||
+ }
|
||||
+ _otherButtonsDown = 0;
|
||||
if (window != nil)
|
||||
|
||||
@@ -6949,7 +6949,7 @@ index ffd7fe054..a74ffc63f 100644
|
||||
+ uint64_t current=(uint64_t)now.tv_sec*1000000000ull+now.tv_nsec;
|
||||
+ uint64_t deadline=ctx->native_next_present_ns;
|
||||
+ static uint64_t paceNS = 0;
|
||||
+ if (!paceNS) { const char *hz = getenv("RCLOL_REFRESH_HZ"); int r = hz ? atoi(hz) : 0; paceNS = r > 0 ? 1000000000ull / (uint64_t)r : 1000000ull; }
|
||||
+ if (!paceNS) { const char *hz = getenv("RCLOL_REFRESH_HZ"); int r = hz ? atoi(hz) : 0; paceNS = (r > 0 && r <= 1000) ? 1000000000ull / (uint64_t)r : 1000000ull; if (paceNS < 1000000ull) paceNS = 1000000ull; }
|
||||
+ if(!deadline || (current>deadline && current-deadline>paceNS))deadline=current;
|
||||
+ if(deadline>current){
|
||||
+ struct timespec wake={deadline/1000000000ull,deadline%1000000000ull};
|
||||
@@ -8534,7 +8534,8 @@ new file mode 100644
|
||||
+ if (!refreshNS) {
|
||||
+ const char *hz = getenv("RCLOL_REFRESH_HZ");
|
||||
+ int rate = hz ? atoi(hz) : 0;
|
||||
+ refreshNS = rate > 0 ? 1000000000ull / (uint64_t)rate : 1000000ull;
|
||||
+ refreshNS = (rate > 0 && rate <= 1000) ? 1000000000ull / (uint64_t)rate : 1000000ull;
|
||||
+ if (refreshNS < 1000000ull) refreshNS = 1000000ull;
|
||||
+ }
|
||||
+ deadline += refreshNS;
|
||||
+ uint64_t now=nativeMonotonicNS();
|
||||
|
||||
@@ -7450,11 +7450,7 @@ new file mode 100644
|
||||
+ static constexpr VkDeviceSize BlockSize = 32ull << 20;
|
||||
+ static constexpr VkDeviceSize MaxPooledSize = 4ull << 20;
|
||||
+ static constexpr VkDeviceSize Granule = 256;
|
||||
+ // a freed range is not handed out again before this long: work already submitted to the GPU may still read it
|
||||
+ /* darling-lol perf: the old 1000ms quarantine caused pool exhaustion
|
||||
+ * and fallback OS allocations during high-churn gameplay. 50ms (~3
|
||||
+ * frames at 60Hz) is sufficient for in-flight GPU work to drain. */
|
||||
+ static constexpr std::chrono::milliseconds Quarantine {50};
|
||||
+ static constexpr std::chrono::milliseconds Quarantine {1000};
|
||||
+
|
||||
+ struct Block {
|
||||
+ VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
|
||||
+7
-4
@@ -5893,11 +5893,14 @@ index b998456..2783a4a 100644
|
||||
+ __linux_sched_yield_site("SWTCH");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -696,6 +1613,48 @@ kern_return_t syscall_thread_switch_impl(
|
||||
.tv_sec = 0,
|
||||
@@ -693,11 +1610,53 @@ kern_return_t syscall_thread_switch_impl(
|
||||
mach_msg_timeout_t option_time)
|
||||
{
|
||||
struct timespec tv = {
|
||||
- .tv_sec = 0,
|
||||
- .tv_nsec = 1000000
|
||||
+ .tv_nsec = option_time > 0 ? (long)option_time * 1000 : 1000000
|
||||
+ .tv_sec = option_time > 0 ? (time_t)(option_time / 1000000) : 0,
|
||||
+ .tv_nsec = option_time > 0 ? (long)((option_time % 1000000) * 1000) : 1000000
|
||||
};
|
||||
+
|
||||
+ /* darling-lol: opt-in trace (host file /tmp/rclol-select-trace) of who calls thread_switch and with which option:
|
||||
|
||||
@@ -14,7 +14,6 @@ export RIOT_LAUNCHER_HOST RCLOL_REGION
|
||||
# client fails under Darling, so start the installed client here.
|
||||
sh scripts/run.sh || true
|
||||
unset RIOT_LAUNCHER_HOST
|
||||
python3 build/runtime/tools/riot-desktop-entry.py || true
|
||||
prefix=${DPREFIX:-$HOME/.darling}
|
||||
if [ ! -d "$prefix/Users/Shared/Riot Games/Riot Client.app/Contents/MacOS" ]; then
|
||||
echo "The installer exited without installing the Riot Client. Its logs are in" >&2
|
||||
|
||||
@@ -1,47 +1,54 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Clear only a dead Darling server's stale PID marker before startup."""
|
||||
"""Clear only a dead Darling server's stale PID marker and buffers before startup."""
|
||||
import os
|
||||
from pathlib import Path
|
||||
import time
|
||||
|
||||
prefix = Path(os.environ.get('DPREFIX', str(Path.home() / '.darling')))
|
||||
marker = prefix / '.init.pid'
|
||||
try:
|
||||
pid = int(marker.read_text().strip())
|
||||
except (OSError, ValueError):
|
||||
raise SystemExit(0)
|
||||
if pid <= 0:
|
||||
raise SystemExit(0)
|
||||
status = Path('/proc') / str(pid) / 'status'
|
||||
try:
|
||||
state = next(line.split()[1] for line in status.read_text().splitlines() if line.startswith('State:'))
|
||||
dead = state == 'Z'
|
||||
except FileNotFoundError:
|
||||
dead = True
|
||||
except (OSError, StopIteration):
|
||||
dead = False
|
||||
if dead:
|
||||
os.replace(marker, prefix / f'.init.pid.stale-{pid}-{time.time_ns()}')
|
||||
print(f'Recovered stale Darling server marker for PID {pid}', flush=True)
|
||||
|
||||
# Clean up stale Riot temporary files and shared memory frames from previous crashes
|
||||
try:
|
||||
tmp_dir = prefix / 'private/tmp'
|
||||
if tmp_dir.is_dir():
|
||||
for f in tmp_dir.glob('.com.riotgames.*'):
|
||||
server_running = False
|
||||
if marker.exists():
|
||||
try:
|
||||
pid = int(marker.read_text().strip())
|
||||
if pid > 0:
|
||||
status = Path('/proc') / str(pid) / 'status'
|
||||
try:
|
||||
f.unlink(missing_ok=True)
|
||||
except OSError:
|
||||
pass
|
||||
except OSError:
|
||||
pass
|
||||
state = next(line.split()[1] for line in status.read_text().splitlines() if line.startswith('State:'))
|
||||
dead = state == 'Z'
|
||||
except FileNotFoundError:
|
||||
dead = True
|
||||
except (OSError, StopIteration):
|
||||
dead = False
|
||||
|
||||
try:
|
||||
shm_dir = Path('/dev/shm')
|
||||
if shm_dir.is_dir():
|
||||
for f in shm_dir.glob('darling-*'):
|
||||
try:
|
||||
f.unlink(missing_ok=True)
|
||||
except OSError:
|
||||
pass
|
||||
except OSError:
|
||||
pass
|
||||
if dead:
|
||||
os.replace(marker, prefix / f'.init.pid.stale-{pid}-{time.time_ns()}')
|
||||
print(f'Recovered stale Darling server marker for PID {pid}', flush=True)
|
||||
else:
|
||||
server_running = True
|
||||
except (OSError, ValueError):
|
||||
pass
|
||||
|
||||
# Only clean up stale Riot temporary files and shared memory frames if the server is NOT running
|
||||
if not server_running:
|
||||
try:
|
||||
tmp_dir = prefix / 'private/tmp'
|
||||
if tmp_dir.is_dir():
|
||||
for f in tmp_dir.glob('.com.riotgames.*'):
|
||||
try:
|
||||
f.unlink(missing_ok=True)
|
||||
except OSError:
|
||||
pass
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
try:
|
||||
shm_dir = Path('/dev/shm')
|
||||
if shm_dir.is_dir():
|
||||
for f in shm_dir.glob('darling-*'):
|
||||
try:
|
||||
f.unlink(missing_ok=True)
|
||||
except OSError:
|
||||
pass
|
||||
except OSError:
|
||||
pass
|
||||
@@ -135,10 +135,8 @@ static int drawFrame(Frame *f, Drawable target, GC gc, const void *pixels,
|
||||
(const char *)pixels + y * stride, f->width * 4);
|
||||
int result = XShmPutImage(f->display, target, f->privateGC, f->image, 0, 0, 0,
|
||||
0, f->width, f->height, False);
|
||||
/* darling-lol perf: XFlush is non-blocking - sends the request without waiting
|
||||
* for the server round-trip. The SHM segment is reused on the next tick anyway,
|
||||
* and the server processes requests in order. Saves 0.2-1.0ms per frame. */
|
||||
XFlush(f->display);
|
||||
/* Wait for server consumption before reusing the segment on the next tick. */
|
||||
XSync(f->display, False);
|
||||
pthread_mutex_unlock(&f->render);
|
||||
return result;
|
||||
}
|
||||
@@ -152,7 +150,7 @@ DarlingXShmPut(void *handle, Drawable target, GC gc, const void *pixels,
|
||||
pthread_mutex_lock(&f->render);
|
||||
int result = XShmPutImage(f->display, target, f->privateGC, f->image, 0, 0,
|
||||
0, 0, f->width, f->height, False);
|
||||
XFlush(f->display);
|
||||
XSync(f->display, False);
|
||||
pthread_mutex_unlock(&f->render);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ Type=Application
|
||||
Name=League of Legends
|
||||
GenericName=MOBA Game
|
||||
Comment=Play League of Legends on Linux with darling-lol
|
||||
Exec={run_script}
|
||||
Exec="{run_script}"
|
||||
Path={PROJECT_ROOT}
|
||||
Icon=league-of-legends
|
||||
Terminal=false
|
||||
|
||||
Reference in new issue
Block a user