import { app } from 'electron'; import type { AppConfig } from './config'; export type Platform = 'win32' | 'linux' | 'darwin'; export type GpuBackend = 'angle' | 'opengl' | 'vulkan' | 'default'; export interface PlatformInfo { os: Platform; isWindows: boolean; isLinux: boolean; useNativeTitlebar: boolean; gpuBackend: GpuBackend; } export function detectPlatform(): PlatformInfo { const os = process.platform as Platform; const isWindows = os === 'win32'; const isLinux = os === 'linux'; return { os, isWindows, isLinux, useNativeTitlebar: isLinux, gpuBackend: isWindows ? 'angle' : 'default', }; } export function applyPlatformFlags(info: PlatformInfo, advanced: AppConfig['advanced'], performance: AppConfig['performance']): void { // ── FPS uncap ── // disable-frame-rate-limit causes compositor CPU spin on Chromium 84+, starving // input events. On Electron 42 (Chromium 147), this is fixed by a patch to // cc/scheduler/scheduler.cc in our custom Electron build. The latency recovery // flags below are no-ops on Chromium 94+ (features were removed), but are // harmless to keep — Chromium ignores unknown feature flags. if (performance.fpsUnlocked) { app.commandLine.appendSwitch('disable-frame-rate-limit'); app.commandLine.appendSwitch('disable-gpu-vsync'); app.commandLine.appendSwitch('max-gum-fps', '9999'); app.commandLine.appendSwitch('enable-features', 'ImplLatencyRecovery,MainLatencyRecovery'); } // ── Always-on platform flags ── app.commandLine.appendSwitch('disable-backgrounding-occluded-windows'); app.commandLine.appendSwitch('disable-threaded-scrolling'); app.commandLine.appendSwitch('overscroll-history-navigation', '0'); app.commandLine.appendSwitch('pull-to-refresh', '0'); // WebGL is mandatory for Krunker — force it past any GPU blocklist. // On Chromium 134+ the blocklist is stricter and silently disables WebGL on many Linux GPUs. app.commandLine.appendSwitch('ignore-gpu-blocklist'); // ── ANGLE backend ── // 'default' means platform default: D3D11 on Windows, no override on Linux if (advanced.angleBackend && advanced.angleBackend !== 'default') { app.commandLine.appendSwitch('use-angle', advanced.angleBackend); } else if (info.isWindows) { app.commandLine.appendSwitch('use-angle', 'd3d11'); } if (info.isWindows) { app.commandLine.appendSwitch('disable-features', 'CalculateNativeWinOcclusion,HardwareMediaKeyHandling'); } if (info.isLinux) { app.commandLine.appendSwitch('ozone-platform-hint', 'auto'); // GPU sandbox can fail inside AppImage FUSE mounts and on certain Mesa driver versions, // causing the GPU process to crash and leaving a black screen. app.commandLine.appendSwitch('disable-gpu-sandbox'); } // ── Remove useless features ── if (advanced.removeUselessFeatures) { app.commandLine.appendSwitch('disable-breakpad'); app.commandLine.appendSwitch('disable-crash-reporter'); app.commandLine.appendSwitch('disable-crashpad-forwarding'); app.commandLine.appendSwitch('disable-print-preview'); app.commandLine.appendSwitch('disable-metrics-reporting'); app.commandLine.appendSwitch('disable-metrics'); app.commandLine.appendSwitch('disable-2d-canvas-clip-aa'); app.commandLine.appendSwitch('disable-logging'); app.commandLine.appendSwitch('disable-hang-monitor'); app.commandLine.appendSwitch('disable-component-update'); app.commandLine.appendSwitch('disable-bundled-ppapi-flash'); app.commandLine.appendSwitch('disable-nacl'); app.commandLine.appendSwitch('disable-features', 'NativeNotifications,MediaRouter,PerformanceInterventionUI,HappinessTrackingSurveysForDesktopDemo'); } // ── GPU rasterization ── // OOP rasterization is always-on when GPU rasterization is enabled (Chromium 100+) if (advanced.gpuRasterizing) { app.commandLine.appendSwitch('enable-gpu-rasterization'); app.commandLine.appendSwitch('disable-zero-copy'); app.commandLine.appendSwitch('disable-software-rasterizer'); app.commandLine.appendSwitch('disable-gpu-driver-bug-workarounds'); } // ── Helpful flags ── if (advanced.helpfulFlags) { app.commandLine.appendSwitch('enable-javascript-harmony'); app.commandLine.appendSwitch('enable-future-v8-vm-features'); app.commandLine.appendSwitch('enable-webgl'); app.commandLine.appendSwitch('disable-background-timer-throttling'); app.commandLine.appendSwitch('disable-renderer-backgrounding'); app.commandLine.appendSwitch('disable-best-effort-tasks'); app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required'); app.commandLine.appendSwitch('enable-features', 'V8VmFuture,WebAssemblyBaseline,WebAssemblyTiering,WebAssemblyLazyCompilation'); } // ── Disable accelerated 2D canvas ── if (advanced.disableAccelerated2D) { app.commandLine.appendSwitch('disable-accelerated-2d-canvas'); } // ── Increase limits ── if (advanced.increaseLimits) { app.commandLine.appendSwitch('renderer-process-limit', '100'); app.commandLine.appendSwitch('max-active-webgl-contexts', '100'); app.commandLine.appendSwitch('webrtc-max-cpu-consumption-percentage', '100'); app.commandLine.appendSwitch('ignore-gpu-blocklist'); } // ── Low latency ── // High-res timers and QUIC are default on Chromium 100+. Accelerated 2D canvas // is default on Chromium 42+. These enable flags were removed from the source. if (advanced.lowLatency) { app.commandLine.appendSwitch('force-high-performance-gpu'); app.commandLine.appendSwitch('enable-quic'); app.commandLine.appendSwitch('quic-max-packet-length', '1460'); app.commandLine.appendSwitch('raise-timer-frequency'); } // ── Experimental flags ── // Removed dead flags: enable-accelerated-video-decode (default since Chromium 132), // enable-native-gpu-memory-buffers (Linux-only), high-dpi-support (removed in ~M54, // HiDPI is default since M108). Renamed ignore-gpu-blacklist → ignore-gpu-blocklist. if (advanced.experimentalFlags) { app.commandLine.appendSwitch('disable-low-end-device-mode'); app.commandLine.appendSwitch('disable-gpu-watchdog'); app.commandLine.appendSwitch('ignore-gpu-blocklist'); app.commandLine.appendSwitch('no-pings'); app.commandLine.appendSwitch('no-proxy-server'); app.commandLine.appendSwitch('enable-features', 'BlinkCompositorUseDisplayThreadPriority,GpuUseDisplayThreadPriority'); } }