CNAEXT catalogue: extension surfaces by namespace

CNA snapshot 009d40f5  ·  Deep Dives › Reference matrices  ·  source links pinned to 009d40f5

✓

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 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Marker counts were made at 009d40f5 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 009d40f5, 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 engine layer in depth, read CNAEXT Engine Layer.

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.

NameWhat it isWhat it is not
CNAEXTAn 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::* namespacesProject-owned namespaces for helpers, renderer and platform contracts, input and device services, diagnostics and engine-layer types that do not pretend to be Microsoft declarationsIndividually marked; they are identified by the namespace itself
CNA_CNAEXT and CNA::CnaExtA CMake option (default OFF) that compiles the CNA::Graphics engine layer, 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,843 times in 330 public headers under modules/*/include, and as a whole word including comments 2,279 times in 353 of the .hpp headers (2,320 times in 358 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

SurfaceExtension membersWhy it exists
GameWindowMinimizeEXT(), RestoreEXT(), GetNativeWindowHandleEXT() (a platform-neutral CNA::Platform::NativeWindowHandle, not an SDL pointer), the FileDropEXT and TextDropEXT events, SetLogicalSizeProviderEXT(), and the borderless accessors noted aboveDesktop window operations and drag-and-drop that XNA's console-era window contract never expressed
GraphicsDeviceManagerThe marked enum PresentationMode (Letterbox, Overscan, Stretch, NativeBackBuffer, FixedHeightDynamicWidth) with getPreferredPresentationModeProperty()/setPreferredPresentationModeProperty(), and a default constructorScaling policies layered around XNA's manager; the default is Letterbox, so the viewport keeps the back-buffer size whatever the window's shape
MatrixToColumnMajor(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)
ColorByte-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 classGetTypeName() overrides returning the fully qualified .NET nameA 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.

AreaRepresentative membersBoundary
Capability queries on GraphicsDeviceGetRendererCapabilityProfileEXT(), 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 drawsDrawInstancedPrimitivesBaseInstanceEXT(), DrawPrimitivesIndirectEXT(), DrawIndexedPrimitivesIndirectEXT()Refused where the renderer lacks the capability
Diagnostics and recoverySetStringMarkerEXT(), 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
EffectsShaderEffect; PbrEffect and SkinnedPbrEffect; ColorMatrixEffect; the shadow and image-based-light receiving types such as IShadowReceiverEXTShaderEffect does not make a renderer support the separate compiled-effect route; PBR support is renderer-qualified
Skeletal animationSkinningData and AnimationPlayer, modelled on the classic XNA skinned-model sample; a model's Tag carries the SkinningDataSample-derived, not framework-assembly API; separate from the avatar system
AvatarsSkinnedModelEXT with keyframed bone tracks (clip names follow AvatarAnimationPreset)Real rendering through the CNAEXT avatar path; XNA's own AvatarRenderer.Draw() stays inert, as in XNA
Morph targetsMorphTargetDataEXT (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 formatsTextureCube::DDSFromStreamEXT(), Texture::GetFormatSizeEXT() and GetBlockSizeSquaredEXT(), extra SurfaceFormat values such as Dxt5SrgbEXT, Bc7EXT and Bc7SrgbEXTPresence is not support on every renderer; ask the format-support query
Engine layer (CNA_CNAEXT=ON only)The CNA::Graphics module: render pipeline and post-processing, shadows, lights and image-based lighting, geometry throughput, compute resources, shader packages, observationSee below

Content extensions

SurfaceMembersBoundary
CNJ descriptorsContentManager::RegisterCnjLoader<T>(typeName, factory) and the built-in typed .cnj loadersA project-owned format with per-loader payload rules, not a universal schema; registration fails fast on an empty or duplicate name
Content introspectionRefreshContentManifest(), 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 typesReflectiveTypeReaderBuilder<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

AreaRepresentative extension surfaceWhy it is separate
InputGamePad: 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 typesModern controllers and SDL3 expose far more than XNA's Xbox 360 input model
AudioDynamicSoundEffectInstance::SubmitFloatBufferEXT()XNA's streaming instance accepts 16-bit PCM bytes only; the float path is CNA's
MediaVideo::FromUriEXT(), Video::SetAudioTrackEXT(), VideoPlayer::SetAudioTrackEXT() and SetVideoTrackEXT(), frame-generation queriesThe URI and track members mirror FNA's own extensions (present in FNA's Video.cs and VideoPlayer.cs) and are still outside XNA
DevicesCNA::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=ONKept apart from the always-built Microsoft::Devices::Sensors, which is Windows Phone API
SensorsAccelerometer::InjectSyntheticSensorUpdate() and the ...ForTesting() members, extra VibrateController members, operators on the reading structsTesting and platform bridges marked inside Microsoft-shaped classes; exactly these are what the strict harness avoids
StorageStorageDevice::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
GamerServicesGuide overlay helpers such as WasKeyboardInputCanceledEXT(), and ...ForTestingEXT() accessors for the pending keyboard requestThey make the local overlay behaviour testable without claiming Xbox LIVE services
NetworkingNetworkGamer: 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 engine layer at a glance

The graphics-ext module is an engine-oriented layer over GraphicsDevice: not another renderer, and not a turn towards an editor-led runtime. At this snapshot its public CNA/Graphics directory holds 98 headers and its test tree 92 C++ sources; those counts describe scope, not uniform execution. Its surfaces form six cooperating groups: materials and environments (PbrMaterial, glTF material bridge, environment processing, sky, light probes), lights and shadows (single, cube and cascaded shadow maps; the clustered-forward many-light path), the frame pipeline (RenderPipeline, target pooling, a depth-normal prepass and an ordered post-process chain), geometry scale (InstancedRendererEXT, FrustumCullerEXT, LodGroupEXT, GPU culling, particles, transparency ordering), modern resources (ComputeShader, storage and constant buffers, texture arrays, shader packages) and observation (GPU timers, pipeline diagnostics, debug draw).

The layer checks named GraphicsCapability values and validates resources where they are used. Some algorithms keep an intentional CPU path: clustered light assignment runs without compute through ClusteredLightAssignment, and ClusteredLightComputeTests.cpp compares the CPU and GPU assignments. Features that need GPU primitives refuse by name instead of substituting silently. Its tests must be read by kind: arithmetic, grid and material tests run against recording test doubles; shader-package tests prove that generated payloads are fresh; resource and interop tests need an engaged renderer; and visibility, shadow, post-process and readback tests reach pixels. So 92 test sources are not 92 renderer-qualified pixel suites, and no CI workflow configures CNA_CNAEXT=ON. Application repositories built on the layer add integrated observations, each for its own pinned revision and host. The full account, with per-renderer support and the degradation rules, is CNAEXT Engine Layer.

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:

  1. The positive direction. cna_strict_xna_api_check compiles StrictXnaApiSurfaceCheck.cpp with CNA_STRICT_XNA_API and -Werror=deprecated-declarations. The file exercises the genuine Microsoft::Devices and sensor API and its header lists every marked member it deliberately does not call. The CTest StrictXnaApiSurfaceCheck_Compile_Run runs the result (under Wine in a Direct3D cross-build tree).
  2. The negative direction. cna_strict_xna_api_leak_check is EXCLUDE_FROM_ALL, so it never takes part in an ordinary build. Its whole body is one deliberate violation:
    Microsoft::Devices::Sensors::Accelerometer accelerometer;
    accelerometer.InjectSyntheticSensorUpdate(1.0f, 0.0f, 0.0f); // CNAEXT -- must fail to compile here.
    The CTest StrictXnaApiSurfaceLeakCheck_MustFailToCompile runs cmake --build for that target with WILL_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.

The same subject is explained at several altitudes. These are the neighbouring pages at each one.

Tests and validation
Test architecture