CNAEXT catalogue: extension surfaces by namespace
Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit c1c316b9; unless a sentence says otherwise, nothing here was built or executed. Marker counts were made at c1c316b9 by the two methods stated on the page. The strict-check CTests exist; no result is claimed for them here.
CNA adds a large surface that XNA 4.0 never had, and much of it lives inside the XNA namespaces next to faithful declarations. This page is a catalogue of that extension surface at snapshot c1c316b9, namespace by namespace, with the real member names, why each extension exists and where its boundary is; it also explains how much of it the CNAEXT marker actually covers and what the strict compile check does and does not prove. For the opt-in CNA::Graphics extensions (the retro post-process effects, DebugDraw and the shader-package types) in depth, read CNAEXT extensions.
Three mechanisms that share a name
"CNA extension" names three related but non-equivalent mechanisms. Keeping them apart prevents both API over-claiming and build confusion.
| Name | What it is | What it is not |
|---|---|---|
CNAEXT | An empty marker macro in CNAHelper.hpp, placed on a declaration inside an XNA-shaped namespace that is not part of XNA 4.0; under CNA_STRICT_XNA_API it becomes [[deprecated("CNAEXT: not part of the XNA 4.0 API surface")]] | A compile guard: everything it marks is compiled in every build |
CNA::* namespaces | Project-owned namespaces for helpers, renderer and platform contracts, input and device services, diagnostics and the opt-in graphics extensions, none of which pretends to be a Microsoft declaration | Individually marked; they are identified by the namespace itself |
CNA_CNAEXT and CNA::CnaExt | A CMake option (default OFF) that compiles the standalone CNA::Graphics extensions (ASCII, CRT and colour-depth effects, DebugDraw, the shader-package types), and an interface target, defined in modules/CMakeLists.txt, that composes cna_graphics_ext with cna_devices_ext (it carried a NoXna name before the CNAEXT naming was normalised in August 2026) | The declaration marker, or a promise that marked members disappear when the option is off |
The build-side switches (CNA_CNAEXT, CNA_DEVICES) and the fact that CNA_STRICT_XNA_API is a compile definition rather than a CMake option are tabulated on What CNAEXT is; Two things named CNAEXT is the maintainer's view.
How much of the surface is marked
The authoritative inventory is the source together with the reference-surface census, not a hand-copied list. How large the marked surface looks depends on how it is counted: at this snapshot the marker occurs as a code token (comments stripped) 1,840 times in 321 public headers under modules/*/include, and as a whole word including comments 2,248 times in 338 of the .hpp headers (2,280 times in 343 files if the C API's plain .h headers are included). Neither figure counts extension members, and both will move as APIs are classified. The CNA:: namespaces, which hold most of the non-XNA headers, are not tagged declaration by declaration.
The EXT suffix is a naming convention and is independent of the marker in both directions. Marked declarations without the suffix include ShaderEffect, BasicEffect::SetOwnedTexture and GraphicsDevice::SetContextRecoveryEnabled. Conversely, a few public suffixed members carry no marker at this snapshot: Texture::GetFormatSizeEXT and Texture::GetBlockSizeSquaredEXT, and the GameWindow::getIsBorderlessEXTProperty()/setIsBorderlessEXTProperty() pair. Strict mode does not flag those, which is one reason neither spelling can decide by itself what is an extension; compare against the reference surface instead.
Framework and math bridges
| Surface | Extension members | Why it exists |
|---|---|---|
GameWindow | MinimizeEXT(), RestoreEXT(), GetNativeWindowHandleEXT() (a platform-neutral CNA::Platform::NativeWindowHandle, not an SDL pointer), the FileDropEXT and TextDropEXT events, SetLogicalSizeProviderEXT(), and the borderless accessors noted above | Desktop window operations and drag-and-drop that XNA's console-era window contract never expressed |
GraphicsDeviceManager | The marked enum PresentationMode (Letterbox, Overscan, Stretch, NativeBackBuffer, FixedHeightDynamicWidth) with getPreferredPresentationModeProperty()/setPreferredPresentationModeProperty(), and a default constructor | Scaling policies layered around XNA's manager; the default is Letterbox, so the viewport keeps the back-buffer size whatever the window's shape |
Matrix | ToColumnMajor(float out[16]) | An explicit bridge from XNA's row-vector storage to shader APIs that want column-major uniform data, used with ShaderEffect (see Shader effects: setting uniforms) |
Color | Byte-component constructors Color(bytecs r, bytecs g, bytecs b) and with alpha, the commutative operator*(float, const Color&), and the public getDebugDisplayStringProperty() | C++ convenience; the commutative multiply exists in neither XNA nor FNA |
Every System::Object-derived class | GetTypeName() overrides returning the fully qualified .NET name | A runtime type-name bridge from sharp-runtime's object model, not an XNA member family |
Graphics and model extensions
Graphics extensions span three physical modules (graphics, content and graphics-ext); directory ownership and API classification are different axes. Everything in this table except the last row is compiled in every build.
| Area | Representative members | Boundary |
|---|---|---|
Capability queries on GraphicsDevice | GetRendererCapabilityProfileEXT(), SupportsRendererFeatureEXT(), GetRendererLimitEXT(), GetRendererSurfaceFormatSupportEXT(), GetRendererCapabilityReportEXT(), SupportsShaderLanguageEXT(), ExecutesShaderEffectSourceEXT(), SupportsShadowSamplingEXT(), SupportsImageBasedLightingEXT(), SupportsSurfaceFormatAsRenderTargetEXT(), the compute work-group limits, Get/SetDisplayColorSpaceEXT() | They report what the renderer's code declares; see the capability profile |
| Extra draws | DrawInstancedPrimitivesBaseInstanceEXT(); DrawPrimitivesIndirectEXT() and DrawIndexedPrimitivesIndirectEXT() are declared too | Refused where the renderer lacks the capability. The two indirect draws take a renderer-internal argument buffer that no public class creates, so game code cannot use them at this snapshot |
| Diagnostics and recovery | SetStringMarkerEXT(), SetContextRecoveryEnabled(), NotifyContentLostResourcesEXT(), SetGraphicsProfileEXT(), SetUnsupported3DGraphicsCallBehavior(), GetLogicalSizeEXT() | Simulating a lost context is an internal renderer hook (IGraphicsRenderer::DebugSimulateContextLoss), not public API; hook presence and host evidence are separate claims |
| Effects | ShaderEffect; PbrEffect and SkinnedPbrEffect; ColorMatrixEffect; the shadow and image-based-light receiving types IShadowReceiverEXT, ShadowCascadeStateEXT, PunctualLightEXT and ImageBasedLightEXT | ShaderEffect does not make a renderer support the separate compiled-effect route; PBR support is renderer-qualified. The receivers consume a shadow map or IBL textures the application renders or supplies itself; CNA does not generate them |
| Skeletal animation | SkinningData and AnimationPlayer, modelled on the classic XNA skinned-model sample; a model's Tag carries the SkinningData | Sample-derived, not framework-assembly API; separate from the avatar system |
| Skinned characters | SkinnedModelEXT: a GPU-skinnable mesh, skeleton and clip set with keyframed bone tracks (KeyframeEXT, BoneTrackEXT), for games that bring their own skinned characters | Deliberately not built on Model, whose bones form a rigid per-mesh hierarchy; unrelated to the avatar API, where XNA's own AvatarRenderer draws CNA's standard avatars with no extension involved |
| Morph targets | MorphTargetDataEXT (PositionDeltas, NormalDeltas, TangentDeltas), weight keyframes with CUBICSPLINE tangents, CPU blending by BlendMorphTargetsEXT() | Tangent deltas are blended too, as a direction only: the handedness w stays on the base vertex because interpolating +1 and −1 passes through 0 (MorphTargetEXT.cpp). Texture coordinates and skinning attributes are copied unchanged |
| Textures and formats | TextureCube::DDSFromStreamEXT(), Texture::GetFormatSizeEXT() and GetBlockSizeSquaredEXT(), extra SurfaceFormat values such as Dxt5SrgbEXT, Bc7EXT and Bc7SrgbEXT | Presence is not support on every renderer; ask the format-support query |
Graphics extensions (CNA_CNAEXT=ON only) | The CNA::Graphics module: the retro effects AsciiPostProcessEffect, CRTEffect and DepthEffect, DebugDraw, and ShaderCodeEXT/ShaderPackageEXT with the ShaderEffect constructors that take them | See below |
Content extensions
| Surface | Members | Boundary |
|---|---|---|
| CNJ descriptors | ContentManager::RegisterCnjLoader<T>(typeName, factory) and the built-in typed .cnj loaders | A project-owned format with per-loader payload rules, not a universal schema; registration fails fast on an empty or duplicate name |
| Content introspection | RefreshContentManifest(), GetContentManifest(), GetXnbReaderUsageSummary() | Enumerates discovered assets and the XNB reader names they use, for audits and tools; it neither resolves nor validates every asset |
| Reflective XNB types | ReflectiveTypeReaderBuilder<T>, ReflectiveTypeReader<T>, CanonicalReflectiveReaderNameEXT() | Replaces XNA's reflection-driven reader with a field list the game declares once, in wire order |
Input, audio, media and host services
| Area | Representative extension surface | Why it is separate |
|---|---|---|
| Input | GamePad: GetGUIDEXT(), GetNameEXT(), SetLightBarEXT(), SetTriggerVibrationEXT(), GetGyroEXT(), GetAccelerometerEXT(), GetPowerInfoEXT(), GetTouchpadFingerEXT(), GetSteamHandleEXT(); Keyboard: GetKeyFromScancodeEXT(), GetScancodeNameEXT(), GetModStateEXT(); Mouse: SetCaptureEXT(), GetGlobalPositionEXT(), relative mode; TextInputEXT; and the CNA::Input clipboard, joystick and haptics types | Modern controllers and SDL3 expose far more than XNA's Xbox 360 input model |
| Audio | DynamicSoundEffectInstance::SubmitFloatBufferEXT() | XNA's streaming instance accepts 16-bit PCM bytes only; the float path is CNA's |
| Media | Video::FromUriEXT(), Video::SetAudioTrackEXT(), VideoPlayer::SetAudioTrackEXT() and SetVideoTrackEXT(), frame-generation queries | The URI and track members mirror FNA's own extensions (present in FNA's Video.cs and VideoPlayer.cs) and are still outside XNA |
| Devices | CNA::Devices in the devices-ext module: camera, file dialogs, message boxes, locale, URL launching, system, display and power information, tray, clipboard; compiled only with CNA_DEVICES=ON | Kept apart from the always-built Microsoft::Devices::Sensors, which is Windows Phone API |
| Sensors | Accelerometer::InjectSyntheticSensorUpdate() and the ...ForTesting() members, extra VibrateController members, operators on the reading structs | Testing and platform bridges marked inside Microsoft-shaped classes; exactly these are what the strict harness avoids |
| Storage | StorageDevice::SetAppNameEXT(), StorageDevice::GetStorageRootEXT() | CNA needs a deterministic local root where XNA chose a storage device through platform UI; without SetAppNameEXT the application folder is the literal name game |
| GamerServices | Guide members such as WasKeyboardInputCanceledEXT(), ShowAchievementsEXT(), RenderPendingMessageBoxEXT() and RenderPendingKeyboardInputEXT() for games without a GamerServicesComponent, and ...ForTestingEXT() accessors for the pending keyboard request | They complete and test CNA's own Guide screens; neither they nor CNA's optional gamer-services service claim Xbox LIVE compatibility |
| Networking | NetworkGamer: SetId(), SetIsHost(), SetHasLeftSession(), SetRoundtripTime(); NetworkSession: SendNetworkEvent(), AddRemoteGamer(), RemoveGamer() and, private to the ENetBackend friend, SetHostFromTransport() and SetSessionPropertiesFromTransport(); LocalNetworkGamer::EnqueuePacket() and ClearPacketQueue(); AvailableNetworkSession::GetConnectAddress(), GetConnectPort(), GetSessionType(); CreateInternal() factories on the value types; and the lifetime counters GetOwnedGamerCountForTesting(), GetActiveActionInstanceCountForTesting(), GetInstanceCountForTesting() | Public and internal setters and delivery controls that the ENet-backed implementation needs where the reference keeps state private, internal or inert (the header comments record that FNA reports every gamer as id 0 and as host and never sets HasLeftSession); SendNetworkEvent() is public because a sibling class must enqueue events. The ...ForTesting() counters are the lifetime checks |
The marker says only "not original XNA". An extension still needs the same ownership, failure, hostile-input and host-evidence analysis as a faithful member, and several of these surfaces are host-dependent (camera, haptics, sensors). XNA compatibility: what CNA adds gives the user-level summary.
The graphics-ext module at a glance
The graphics-ext module holds the opt-in graphics extensions: small, standalone pieces over GraphicsDevice, not another renderer and not a frame pipeline. At this snapshot its public CNA/Graphics directory holds 11 headers (the master include CNAEXT.hpp among them), its src tree 9 C++ sources, its test tree 6 sources with 76 test definitions and its examples 6 programs; every declaration is wrapped in #ifdef CNA_CNAEXT. Its surfaces form three groups: the retro post-process effects (AsciiPostProcessEffect with AsciiQuantizeMode; CRTEffect with CRTMaskType; DepthEffect with DepthEffectMode and DitherMode, which reduces colour depth or maps to a palette and does not visualise the depth buffer), DebugDraw (lines, boxes, spheres, frustums and crosses drawn through the core BasicEffect), and the portable shader-package types ShaderCodeEXT and ShaderPackageEXT that the CRT and colour-depth effects and ShaderEffect's package constructors use.
The effects ship one shader package (post_process: GLSL ES, desktop GLSL, SPIR-V and WGSL, plus HLSL variants carried in a generated header), and the CTest PostProcessShaderPackageReproducibility proves that the generated payload is fresh. The six test sources cover the three effects, DebugDraw, the shader infrastructure and the master include; the six examples (the ASCII font atlas, quantizer and post-effect programs and the CRT and colour-depth demos) reach pixels only in a build with a renderer that runs them. No CI workflow configures CNA_CNAEXT=ON or the cnaext preset; CNA's own scope-reduction record reports the retained set built with the option on and off on OPENGLES3 and its 78 retained-effect and graphics-profile tests passing (2026-09-27, not reproduced here). Shadow-map rendering, image-based-lighting textures, instancing helpers and post-process chains are not part of the module: an application that wants them builds them itself from RenderTarget2D, the stock effects and the receiving types in the table above. The full account, with build switches and per-renderer notes, is CNAEXT extensions.
How the strict check proves itself
In a normal build CNAEXT expands to nothing. Two standalone targets in cmake/Harnesses.cmake give it force, and they are built only when CNA_BUILD_TESTS is on and the compiler is GCC or Clang:
- The positive direction.
cna_strict_xna_api_checkcompilesStrictXnaApiSurfaceCheck.cppwithCNA_STRICT_XNA_APIand-Werror=deprecated-declarations. The file exercises the genuineMicrosoft::Devicesand sensor API and its header lists every marked member it deliberately does not call. The CTestStrictXnaApiSurfaceCheck_Compile_Runruns the result (under Wine in a Direct3D cross-build tree). - The negative direction.
cna_strict_xna_api_leak_checkisEXCLUDE_FROM_ALL, so it never takes part in an ordinary build. Its whole body is one deliberate violation:
The CTestMicrosoft::Devices::Sensors::Accelerometer accelerometer; accelerometer.InjectSyntheticSensorUpdate(1.0f, 0.0f, 0.0f); // CNAEXT -- must fail to compile here.StrictXnaApiSurfaceLeakCheck_MustFailToCompilerunscmake --buildfor that target withWILL_FAIL TRUE, so it passes only if the build fails.
A positive-only check ("the real API still compiles") is equally consistent with a guard that never fires. The pair proves both acceptance and sensitivity for the slice it exercises: if a change to the macro or to the define's wiring ever let the leak compile, the negative test would turn red, catching a regression in the safety net itself. What the pair does not prove is that every addition elsewhere is marked, or that other namespaces are pure; that still takes comparison with the reference surface. (The comment in CNAHelper.hpp still names an old tests/Microsoft/Devices/ location for the positive check; the files live under tools/devices/.)
A game can use the same mechanism on its own code. Define the macro on the target to check and promote the warning:
target_compile_definitions(my_game PRIVATE CNA_STRICT_XNA_API)
target_compile_options(my_game PRIVATE -Werror=deprecated-declarations)
Passing -DCNA_STRICT_XNA_API=ON to the CMake configure step instead only creates an unused cache variable. Tutorial 115 walks through the marker, strict mode and the build gate with code.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- User guide
- CNAEXT extensions · What CNA adds beyond XNA
- Architecture
- Physical module graph
- Internals
- Graphics extension internals · Devices internals
- Maintainer workflow
- Two things named CNAEXT · Change public XNA behaviour: the marker
- Tests and validation
- Test architecture
- Reference
- Public header index