Chapter 61 The Cross-Platform Contract
At v0.1.0-alpha.1, “platform” no longer means simply the target OS or “the SDL3 layer.” CNA has five related axes: target OS/toolchain; the selected CNA::Platform::IPlatform implementation; the compiled graphics-renderer set and active family; the selected audio implementation; and the XNA-shaped framework surface used by the game. They are composed, not collapsed into one backend name.
61.1 The five-axis model
| Axis | Selector or API | Responsibility |
|---|---|---|
| Target | CMake toolchain / OS | Object format, native SDKs, architecture and host admission. |
| Platform implementation | CNA_PLATFORM | Windows, events, input, time, system services, cameras, GL contexts, Vulkan surfaces and CPU-surface presentation. |
| Graphics | CNA_GRAPHICS_RENDERER(S) and GraphicsRendererSelection | How pixels are produced; a compiled set, configured default, runtime selection and first-device latch. |
| Audio implementation | CNA_AUDIO_PLATFORM | Playback/capture infrastructure, independent of both the window platform and graphics family. |
| Game/framework | Microsoft::Xna::Framework and optional CNAEXT | Stable application-facing shape above the three native-service axes. |
The separation permits meaningful combinations: HEADLESS platform with NULL audio and HEADLESS graphics for a server; SDL3 platform with NULL audio for a deterministic graphics test; TERMINAL platform with SOFTWARE graphics for a POSIX terminal application; or SDL2 platform/audio while retaining an otherwise current framework. It does not mean every Cartesian product is buildable. Capability and toolchain gates reject combinations that lack a native window, presentation route, SDK, ABI, or common target.
61.2 The platform contract is implemented
modules/platform now owns CNA::Platform. Its root IPlatform is created once by PlatformFactory and is not swapped while the process runs. The interface groups:
-
•
refcounted acquisition of video, audio, gamepad, haptic, and sensor subsystems;
-
•
window creation/adoption and native-window identity;
-
•
batched event polling into caller-owned storage;
-
•
monotonic counters, ticks, delay and system services;
-
•
keyboard, mouse, text, gamepad, joystick, haptics, sensors and camera services;
-
•
optional GL-context, Vulkan-surface and CPU-surface-presentation interfaces.
This is not a nominal wrapper around SDL types. Public platform headers do not expose SDL; the platform target links the selected toolkit privately on desktop, and a source ratchet rejects new direct SDL ownership outside the admitted boundary. Hot-path lint separately rejects platform calls inside per-pixel, vertex, fragment, sample and event loops. Capability queries are intended to be read once and cached, not dispatched repeatedly in a render loop.
The lifecycle also preserves host ownership. CNA production code acquires individual subsystems lazily; it does not seize the application’s global SDL initialization/shutdown policy. Unpaired release during partial cleanup is tolerated, while successful acquisitions are normally balanced.
61.3 Implemented, host-limited, and reserved choices
- SDL3
-
Default implementation. Owns current SDL3 window, event, input and system service adaptation. Mobile entrypoint glue is an explicit public-build exception.
- SDL2
-
Independent implementation selected and linked only when requested; it is not SDL3 operating in a compatibility mode.
- HEADLESS
-
No native windowing dependency. It supplies deterministic platform behavior and remains compiled as a conformance reference even when another implementation is selected.
- TERMINAL
-
POSIX termios/poll implementation with terminal input and a CPU surface presenter. It is implemented on non-Windows targets only and is not offered on Windows. Compatible renderer identities at the tag are SOFTWARE, SKIA, BLEND2D, PORTABLEGL, HEADLESS, and STUB.
SDL12, WIN32, and EMSCRIPTEN are reserved but unimplemented platform identifiers. On Windows, TERMINAL joins the refused set because no Windows console implementation exists. Selecting any reserved name is a hard configure error naming the implemented alternatives; there is no silent SDL3 fallback. Targeting Emscripten with an SDL platform is distinct from a future native CNA_PLATFORM=EMSCRIPTEN implementation.
61.4 Platform capabilities and renderer needs
A renderer descriptor declares requirements rather than assuming every platform supplies an SDL window. Windowed GPU routes may need a native window system, a GL context or a Vulkan surface. CPU rasterizers may instead hand a finished surface to IPlatformSurfacePresenter. HEADLESS and STUB need neither. The registry/combination gates evaluate these requirements before factory invocation, so a refused pair is configuration evidence rather than a runtime null dereference.
Runtime renderer selection does not relax those rules. Every family in CNA_GRAPHICS_RENDERERS must be buildable for the selected target and platform. Once the first device latches an active renderer, its windows, swapchain or CPU surface and every graphics resource belong to that choice. Fallback may try another compiled descriptor during initial creation only when the application enabled it; it cannot migrate a live resource graph.
61.5 Audio remains orthogonal
The implemented CNA_AUDIO_PLATFORM values are SDL3, SDL2 and NULL. OPENAL, WASAPI and ALSA are reserved and fail configuration. The axis is deliberately independent: a terminal or headless program may still use SDL3 audio, and an SDL3-windowed program may choose NULL. Chapter 45 describes what this changes in the sound route and what remains a shared XNA-shaped contract.
61.6 Target taxonomy is still useful, but different
CNA retains target vocabulary that distinguishes Desktop, Android, iOS and Web, with desktop OS values for Windows, Linux, macOS and Other. Those values answer where the binary is targeted. They do not answer which IPlatform, renderer, or audio implementation was composed. For example, Linux is compatible with SDL3, SDL2, HEADLESS or TERMINAL platform implementations; “Linux renderer” would still be underspecified.
61.7 A platform claim is an evidence vector
The useful progression remains:
-
1.
a target/platform/renderer/audio source path exists;
-
2.
configuration admits the exact combination;
-
3.
it compiles and links;
-
4.
the artifact executes on the named native, emulated or translated host;
-
5.
the selected platform and intended renderer/service engage; and
-
6.
behavior or pixels meet an identified oracle.
Later steps do not follow from earlier ones. A renderer descriptor may compile while its driver is unavailable; a PE artifact may execute without loading the intended DXVK DLL; a browser test may prove DOM state without compositor pixels; a platform conformance test can use HEADLESS without exercising SDL. This edition therefore reports each coordinate and preserves unsupported, blocked, and not-attempted states separately.
At the tag, Linux x86_64 has the strongest self-hosted evidence. Windows campaigns largely use MinGW plus Wine/DXVK/vkd3d; browser campaigns use Emscripten and Chromium; Android evidence is emulator-scoped; and Apple routes require their native toolchains and hosts. The new platform architecture makes these routes cleaner to compose and test, but does not retroactively promote historical compile evidence into hardware or oracle evidence.