The GLIDE renderer is a 32-bit Windows-only, dynamically loaded implementation of the historical 3dfx
Glide 3.x API. It is deliberately not an SDL renderer facade: CNA opens a real Glide context
through grSstWinOpen, batches compatible SpriteBatch quads through
grDrawVertexArrayContiguous, uploads texture data
through the Glide TMU API, swaps with grBufferSwap, and reads pixels with grLfbReadRegion.
It is intended for an emulator runtime such as dgVoodoo2.
glide3x.dll is external to CNA: this repository neither contains nor copies it. Place a compatible
DLL beside the executable, or set CNA_GLIDE3X_DLL to the DLL's full Windows path before launching.
Use PresentationMode::NativeBackBuffer and a swap interval of either 0 or 1. Glide has no
faithful CNA logical-surface scaling path; other presentation modes and intervals above one are
rejected rather than silently ignored. A later virtual-resolution change is accepted only while it
fits the Glide mode selected at startup, so GraphicsDevice retains its previous public size if
the renderer rejects it.
CNA links no Glide library and carries no third-party Glide source or binary. Its only reproducible dependency contract is the hand-declared 32-bit Glide 3.x ABI: an independent x86 fake DLL exercises all 39 required exports. The production DLL is deliberately caller-supplied and unpinned; CNA does not select a dgVoodoo2 version/commit, build it, patch it, redistribute it, or claim its license as CNA's. Consult the selected runtime's own license and redistribution terms. CNA's renderer source is covered by the repository's Ms-PL license.
The 2026-08-08 post-audit host had no physical Voodoo hardware and no compatible glide3x.dll.
Validation is therefore build-only for the production renderer, plus a fake-wrapper ABI contract
under Wine. It is not emulator image validation and not native-hardware validation. Full CNA i686
linkage was externally blocked in the sibling sharp-runtime dependency path; the renderer itself
passed i686 whole-translation-unit syntax, 78 portable tests, and the same 78 tests under linked
ASan/UBSan runtimes. Five OPENGLES3 pixel/state tests provided the shared-interface control.
Set CNA_GLIDE_DIAGNOSTICS=1 to print the loaded runtime path, selected virtual/native mode,
TMU count, texture limits and usable TMU0 bytes at startup. The report contains no native pointer
values and is intended for emulator/hardware bug reports.
The renderer is hard-gated to the native 32-bit Windows ABI. From Linux, use the i686 MinGW-w64 toolchain and keep global build parallelism at two jobs or fewer:
cmake -S . -B cmake-build-glide -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/mingw-w64-i686.cmake \
-DCNA_GRAPHICS_RENDERER=GLIDE \
-DCNA_BUILD_TESTS=ON
cmake --build cmake-build-glide --target cna_glide_smoke -j2The loader ABI can be checked independently of CNA, SDL, sharp-runtime and dgVoodoo:
cmake --build cmake-build-glide --target cna_glide_abi_loader_test -j2
cd cmake-build-glide && wine cna_glide_abi_loader_test.exeThat target builds a deliberately tiny x86 fake DLL and verifies undecorated and MinGW stdcall export lookup, plus the error path for a missing export. It is a loader-contract test, not a replacement for the full fake-DLL render-call capture or a visual runtime test.
Copy a compatible 32-bit glide3x.dll (and its required dgVoodoo companion files) beside
cna_glide_smoke.exe, configure dgVoodoo for the machine, then run the executable under Windows
or Wine. Alternatively, set CNA_GLIDE3X_DLL before launching. The smoke program verifies a green
clear, a red one-pixel texture drawn with SpriteBatch, a native Gouraud-shaded
VertexPositionColor triangle, and direct backbuffer readback. It is not a
normal CTest because CNA cannot provide or configure the external emulator.
Clear,Present,SpriteBatch, full and partialTexture2D::SetDatauploads on every declared mip level, point/bilinear filtering, and clamp/wrap/mirror addressing. The shared texture layer supplies Glide a complete updated mip image after a rectangle write; Glide retains explicit lower levels and rebuilds its tiled ARGB4444 pyramid after FIFO completion. Runtime image capture of this path remains part of the hardware/emulator release gate.- Fixed-function 3D
VertexPositionColor,VertexPositionTexture,VertexPositionColorTexture, and vertex-litVertexPositionNormalTexturetriangle lists/strips,LineList,LineStrip, andPointListEXT, indexed or non-indexed. Triangles useGR_TRIANGLES; points useGR_POINTS; and independent or clipped line-strip runs useGR_LINES, so clipping cannot join disjoint visible runs. Compatible customVertexDeclarations may placePosition0(Vector3),Color0(Color),Normal0(Vector3), andTextureCoordinate0(Vector2) at arbitrary offsets in the declared stride; all other semantics/formats are rejected rather than misread. CNA CPU-transforms and clips triangles, lines and points in homogeneous XNA space; Glide then rasterizes the resulting primitives with its native depth, TMU, alpha-test and blending pipeline. The point/line implementation has portable clip tests, while its native image capture remains a release-validation item. Texture parameters are submitted as perspective-corrects/w,t/w,1/w.ViewportXY, depth range and the intersection of viewport/scissor are applied before native rasterization. - Unlit BasicEffect material/vertex colour, and the documented per-vertex directional BasicEffect
subset (ambient, emissive, and three-light Blinn-Phong specular included). Per-pixel lighting
is rejected. CNA computes vertex lighting and its
fogVectoron the CPU, then hands the iterated RGB to Glide; this is required because Glide's depth-table fog cannot represent an arbitrary XNA fog vector. The CPU specular arithmetic has deterministic unit coverage; image capture on a real Glide runtime remains a release-validation item, not a fallback renderer. - Color-only and color-plus-depth clears, native depth-test/depth-write/depth-compare, native
culling, AlphaTestEffect's discrete alpha comparisons, and blend enable/disable. Glide has a
depth buffer but no stencil buffer: common
GraphicsDevice::Clear(Color)clears colour and depth, while stencil-only portions are masked by the shared clear routing. RGB and alpha write masks are independently supported; a mask that separates R/G/B or requests a sample mask is rejected. - Textures are converted from CNA RGBA8 to native Glide ARGB4444, padded to power-of-two tiles,
and receive complete generated ARGB4444 mip chains. The renderer queries the runtime texture and
aspect limits and tiles larger logical images rather than downsampling them. For 3D draws, the
CPU partitions clipped geometry at logical tile and
Wrap/Clamp/Mirrorboundaries, then Glide TMU0 performs the final filtered sample from each tile. Tile padding is regenerated from the retained RGBA source when the address mode changes, and an internal one-texel neighbour gutter preserves level-0 linear filtering at a tile boundary. A single logical ARGB4444 mip pyramid supplies every tile LOD, so minification does not derive colours from isolated tile padding. SpriteBatch source rectangles are split per tile directly. The remaining fidelity item is only a possible sub-texel LOD phase at a tile edge; it requires visual validation on a real Glide runtime before any compensation is added. - The native context uses
grQueryResolutionsand selects the smallest supported historical Glide double-buffered depth mode that contains CNA's virtual resolution, rather than assuming a fixed 640×480/800×600 capability. It also queries texture/TMU limits throughgrGet. GetBackBufferDatareads the Glide backbuffer as RGB565; alpha reads back as fully opaque, matching the native color-buffer format.
- The 3D path is deliberately fixed-function: arbitrary shader Effects, environment mapping, PBR,
skinning, instancing and per-pixel lighting remain unsupported and report that explicitly. A
narrow
DualTextureEffectsubset uses two real TMUs when the runtime reports them: both textures must be same-sized, single-tile triangle textures sharing address modes and one texture-coordinate channel; their filter and LOD-bias sampler state remains independent. It is not a shader-emulation layer. - Render targets, multisampling, texture cubes/volumes, stencil, occlusion queries, and custom SpriteBatch effects are unsupported by this native Glide scope and report that explicitly.
- Only additive blend equations are available in this scope. The standard source/destination blend factors supported by Glide are mapped; XNA constant blend-color factors are rejected.
- There is no fallback to SDL, Direct3D, OpenGL, or software rendering. A missing or incompatible
glide3x.dllis a startup error by design.
| Current capability | GLIDE result |
|---|---|
ThreeD |
Supported by the documented fixed-function subset; runtime build-covered on this host |
DepthStencilBuffer |
False: default backbuffer has depth but no stencil |
MultiSampleAntiAliasing, MultipleRenderTargets |
Unsupported and rejected |
AnisotropicFiltering |
Unsupported; anisotropic filters reject |
WireFrame |
Unsupported; only solid fill is accepted |
OcclusionQuery, CustomEffects, Texture3D |
Unsupported and rejected |
MultiStreamVertexInput, Instancing |
Unsupported and rejected |
One ordinary vertex stream is accepted. Its VertexBufferBinding::VertexOffset reaches Glide only
through the current shared layer's folded vertexStart/baseVertex; startIndex is an index-element
offset and baseVertex is added once to each decoded index. Residual per-stream offsets, instance
frequency, duplicate semantics, unsupported declaration elements, or a second stream fail before
native submission. DrawInstancedPrimitives remains unsupported.
Texture width/height are texels; RGBA row length, source pitch, retained storage, and destination
storage are bytes. Pitched copies validate dimensions, arithmetic, and row extent, including
nontrivial widths. The normal destination is ARGB4444; opt-in alpha classification can select
RGB565 or ARGB1555. The renderer keeps its own retained image and never changes Texture2D's shared
CPU/GPU cache-authority contract.
For emulator installation and redistribution conditions, consult dgVoodoo2's own documentation. CNA does not package that runtime.