openQ4 Platform And Architecture Roadmap

June 22, 2026 ยท View on GitHub

This document defines the long-term platform direction for openQ4 and how SDL3 + Meson are used to get there.

Target End State

  • First-class support on modern desktop operating systems:
    • Windows
    • Linux
    • macOS
  • First-class support for modern 64-bit desktop architecture:
    • x64 (x86_64)
    • arm64 (aarch64)
  • Keep original Quake 4 gameplay/module behavior compatible while modernizing platform and build layers.

Current Baseline (0.1.010 beta line)

  • Primary actively validated build targets: Windows x64, Linux x64/arm64, and macOS arm64 through hosted CI/package generation.
  • Windows arm64 remains package-validated during bring-up, with runtime validation still required on hardware.
  • Manual macOS release artifacts are Apple Silicon/arm64 only. Credentialed release runs publish signed/notarized DMGs; runs without Apple Developer ID signing and notarization credentials publish clearly labeled unsigned/unnotarized -unsigned.tar.gz archives. Intel Mac and universal2 packages are intentionally not claimed until the project adds a dedicated Intel validation runner or a universal packaging lane with architecture-specific launch checks.
  • Build system: Meson + Ninja.
  • Dependency model: Meson subprojects/wraps.
  • Platform backend direction: SDL3-first (legacy Win32 backend is transitional only).
  • Language baseline target: C++23 semantics (vc++latest on current MSVC Meson front-end).
  • Toolchain baseline direction: MSVC 19.46+ (Visual Studio 2026 generation), with compatibility fallback permitted during migration.
  • As of March 30, 2026, Linux and macOS default to the SDL3 backend and keep -Dplatform_backend=native as a fallback/comparison path.
  • Steam Deck and SteamOS support is delivered through the explicit openQ4-steamdeck launcher/profile, plus direct-client host auto-detection when com_platformProfile is still default.
  • Native Wayland is supported through the SDL3 backend. The shared SDL3 path logs the selected video driver, active Wayland hints, display content scale, orientation, current/desktop display modes, exact refresh details when SDL reports them, and compositor-accepted window state after screen changes; applies Wayland-aware defaults; avoids persisting compositor-owned window positions; keeps relative mouse-look usable when pointer confinement is unavailable; synchronizes compositor-negotiated size/fullscreen changes before refreshing renderer placement; and tries SDL's unversioned OpenGL compatibility fallback first when r_glTier is auto on native Wayland. CI now exercises native Wayland SDL3 window lifecycle, relative mouse-capture, and display-diagnostics cases under Weston, including fullscreen/windowed vid_restart transitions and the optional blocking window-operation synchronization path.
  • SDL3 Linux VRAM autodetection can enumerate DRM card/render-node sysfs before legacy /proc/dri fallback, and native Wayland skips optional XNVCtrl/X11 probing, so native Wayland and minimal X11-free sessions are less dependent on optional X11 helpers.
  • SDL3 Linux and macOS desktop-resolution queries fall back from desktop mode to current mode and display bounds, improving startup robustness on compositors or display bridges that do not report a conventional desktop mode.
  • Windows, Linux, and macOS SDL3 builds share the same r_screen, r_multiScreen, fullscreen, exclusive-mode, borderless, windowed-placement, high-DPI drawable, display-change, selected-display spanned-UI viewport, and diagnostic display-list code paths. Native Wayland keeps compositor-owned placement semantics and falls back from multi-display spanning to the selected display when absolute placement is unavailable. The shared SDL3 renderer path also verifies a live, current OpenGL context before screen changes, swaps, deactivation, and teardown, validates extension lookups, uses overflow-safe selected-display viewport math, clamps malformed mouse movement, wheel, controller, and rumble values before integer conversion and event queuing, normalizes unusual app-entry argument state, guards POSIX clipboard/console command/input allocation, terminal and desktop-console cursor and scroll state, pthread setup and initialization state, requires error-checking mutex attributes before enabling critical sections, checks thread/event indexing, signal reporting, process handoff, and fatal-error/print formatting paths, and makes the macOS display selector fall back from requested display to main display to first active display before returning a null display id.
  • Windows, Linux, and macOS keyboard, mouse, and controller input are routed through the shared SDL3 backend. Linux and macOS explicitly keep SDL's HIDAPI controller stack, enhanced reports, hotplug events, rumble, battery diagnostics, gyro, touchpad, and touchscreen routing available at the same feature level as the Windows SDL3 path while preserving user/SDL environment overrides.
  • XWayland remains available as an explicit fallback by setting OPENQ4_FORCE_X11=1 or an SDL video-driver override such as SDL_VIDEO_DRIVER=x11.
  • The Linux X11/Xvfb fallback lane also runs an SDL3 display-diagnostics smoke in CI so native Wayland and explicit X11 driver paths both prove display enumeration, scale/orientation reporting, and selected-display diagnostics.
  • The project-level OPENQ4_FORCE_X11=1 fallback is runtime-validated separately from raw SDL driver overrides; CI launches the staged client under Xvfb with that flag and checks that SDL reports the X11 driver plus normal display diagnostics.
  • If a native Wayland compositor has decoration, resize, or window-control issues, OPENQ4_WAYLAND_PREFER_LIBDECOR=1 asks SDL to prefer libdecor without changing the default path for other sessions.
  • If libdecor itself causes startup or decoration issues on a compositor stack, OPENQ4_WAYLAND_DISABLE_LIBDECOR=1 asks SDL to keep libdecor disabled for that launch.
  • If a compositor applies window changes too asynchronously for diagnosis, OPENQ4_WAYLAND_SYNC_WINDOW_OPS=1 asks SDL to synchronize every window operation. Use it only as a troubleshooting option because some compositors may block during window animations.
  • macOS arm64 release packages are built and validated in both OpenGL and Metal bridge variants, with .app metadata, executable bits, runtime dependency roots, and architecture-matched .dylib game modules checked before release publication. Credentialed runs add final compressed DMG creation, hdiutil image verification, Developer ID signing, and DMG notarization/stapling. Release runs without Apple signing/notary credentials publish -unsigned.tar.gz archives instead, ad-hoc signed only for bundle validity and clearly marked as unsigned/unnotarized. The current release line does not publish Intel Mac or universal2 artifacts; those remain future support-policy decisions rather than implied compatibility. The SDL3 release path links Cocoa/OpenGL/ApplicationServices and keeps the legacy Carbon framework isolated to -Dplatform_backend=native. The Metal bridge keeps the stock-compatible OpenGL renderer path, links Metal/QuartzCore for the SDL3/Cocoa host surface, applies the bridge define consistently across C/C++/Objective-C/Objective-C++ sources, logs failed SDL Metal hint setup, requires valid SDL window IDs before splash/system-console renderer creation, lets those support windows try the Metal/default renderer before falling back to software, and reports failed splash event requeues during startup/error UI draining.
  • macOS audio still defaults to Apple's OpenAL framework for release stability. The -Dmacos_openal_provider=system build option is available for local OpenAL Soft migration testing with a system openal dependency and AL/... headers, but it is not yet the packaged release default.
  • macOS release signing uses the Hardened Runtime without custom entitlements by default. Optional entitlement files are validated as plist dictionaries and App Sandbox or get-task-allow entitlements are rejected until the project has a reviewed sandbox/file-access design for user-selected Quake 4 assets, saves, logs, and staged runtime overlays.
  • The native macOS Cocoa/OpenGL fallback is kept crash-resistant for comparison testing: it now stores a valid CGL context pointer, validates pixel-format/context/window setup before use, releases created contexts if final make-current fails, fails cleanly when fullscreen display capture/mode/context setup cannot complete, unwinds partial display captures, treats missing or invalid-display VRAM telemetry as non-fatal, guards mouse capture, scroll-wheel overflow, nil event entry points, display/gamma-table, stack-free extension lookup, verified-current context swap/activation/pause/resume, and shutdown lifetime paths, returns deterministic unsupported status from legacy render-thread and screen-change stubs, uses the engine allocator for clipboard text, owns UTF-8 strings handed back from Cocoa key-name, clipboard, and fatal-error alert paths, keeps obsolete Carbon/Xcode-era macOS sources out of the Meson build manifest, and validates that live macOS backend sources do not reintroduce raw strcpy/strcat/sprintf/alloca string builders.
  • Windows arm64 currently uses a custom OpenAL Soft package path during bring-up because the in-repo bundled Windows runtime payload is still x64-only.

Runtime Baselines

  • Windows packaged compatibility floor: Windows 7 or later.
  • Windows validation focus: current Windows 11 releases first, with Windows 10 retained as a practical compatibility target even though Microsoft's general Windows 10 servicing ended on October 14, 2025.
  • Windows 7/8/8.1 are no longer hard-blocked by the current x64 binaries, but they are legacy and outside the actively validated support matrix.
  • macOS packaged compatibility floor for the Apple Silicon/arm64 release line: macOS 11 or later. Meson now pins the deployment target to 11.0 so the binary floor matches the documented floor. Intel Mac and universal2 package floors are not published because those packages are not part of the current release matrix.
  • Linux packaged compatibility floor: release archives are built on pinned Ubuntu 24.04 runners and should be treated as targeting a comparable modern 64-bit desktop userspace with OpenGL plus SDL3 Wayland/EGL or X11/GLX available.
  • Steam Deck support assumes a SteamOS 3.x style environment. The explicit openQ4-steamdeck launcher remains the preferred shipping path, while raw openQ4-client_<arch> launches can auto-select the steamdeck profile from Deck/SteamOS host signals unless disabled by environment.

SDL3 Direction

  • SDL3 is the default backend path and the portability layer for:
    • window lifecycle
    • input event handling
    • context/window interop glue
  • New platform-facing work should prefer SDL3 abstractions first.
  • Platform-specific code should be isolated under src/sys/<platform>/ when SDL3 cannot cover a requirement directly.
  • OpenGL context selection now uses the shared renderer ladder across SDL3, native GLX, and native NSOpenGL paths. macOS remains capped at OpenGL 4.1 core by the platform OpenGL stack, while Linux and Windows can continue down through core and compatibility-profile fallbacks according to r_glTier.
  • macOS startup validates both advertised OpenGL extensions and the callable entry points behind the multitexture, ARB2, VBO upload, PBO readback, and GLSL paths. If Apple's OpenGL 2.1 compatibility fallback reports an incomplete loader state, openQ4 now downgrades optional upload/readback paths to CPU-backed fallbacks or fails through the normal missing-feature path instead of continuing into a SIGSEGV.

Meson Direction

  • Meson is the canonical build system going forward.
  • External dependencies should be consumed via Meson dependency resolution and subprojects/wraps.
  • New build logic should be host-aware and architecture-aware, with x64 as the active compatibility baseline.
  • Meson configuration defaults to cpp_std=vc++latest (C++23-targeting mode on MSVC).
  • Meson currently adds /Zc:strictStrings- on MSVC to preserve compatibility with legacy string-literal usage while the codebase is modernized.
  • tools/build/meson_setup.ps1 prefers VS 2026+ (major 18) when present; strict minimum enforcement can be enabled with -Denforce_msvc_2026=true.

Bring-Up Staging

  1. Keep Windows x64 stable with SDL3 default backend.
  2. Keep Linux on the SDL3 backend by default and validate both x64 and arm64 release paths.
  3. Validate Windows arm64 beyond compile/package bring-up, especially runtime audio and in-game coverage.
  4. Continue macOS Apple Silicon hardware signoff for input devices, audio devices, and in-game renderer coverage on real Macs while keeping the CI build/package path first-class.
  5. Add an explicit Intel Mac or universal2 release lane only after the project has architecture-specific CI, lipo/install-name validation, and launch evidence for both packaged architectures.

SDL3 Migration Staging (Linux/macOS)

  • Linux and macOS now use the shared SDL3 runtime path when -Dplatform_backend=sdl3 is selected, and that is the default configuration as of March 30, 2026.
  • macOS SDL3 builds select src/sys/osx/macosx_sdl3.cpp and src/sys/osx/macosx_sdl3_main.cpp with the shared SDL3 window, input, controller, and OpenGL context path.
  • The native Linux X11/GLX and macOS Cocoa/OpenGL backends remain available through -Dplatform_backend=native for comparison and rollback while SDL3 remains the release path. On SteamOS, the SDL3 path also watches application lifecycle events so suspend/resume and foreground/background transitions flow through the same input release, rumble stop, config write, and controller reacquire behavior used by the normal event pump.

Definition Of Done For First-Class Platform Support

  • Clean configure + build in Meson.
  • Engine initializes and reaches map/session startup with stock Quake 4 assets.
  • Core input, rendering, audio, and networking paths work without platform-specific content hacks.
  • Regressions are tracked in docs and fixed in engine/platform code, not with asset overrides.