Skip to content
The CNA BibleCNA 0.1.0-alpha.1 Edition

Chapter 21 OpenGL I: The Independent
Compatibility Ladder

CNA does not have one OpenGL renderer with a version switch. It has several independent families that happen to speak related APIs. This chapter follows the compatibility ladder: desktop OpenGL 1.x through OPENGL1, the GLSL 1.10 transition through OPENGL2, mobile fixed function through OPENGLES1, and the CPU TINYGL family. Chapter 22 then covers the five-profile EasyGL family, OPENGL4, and PORTABLEGL.

That distinction matters operationally. Selecting a newer identity does not mutate an older implementation, and a fix in one family does not automatically reach another. The renderer contract is shared; context creation, resource ownership, draw submission, and evidence are not.

21.1 Four identities, four implementation families

Identity Pipeline Shader delivery Deliberate boundary
OPENGL1 desktop fixed function none OpenGL 1.x concepts; optional FBO and query entry points are detected at runtime
OPENGL2 programmable compatibility profile GLSL 1.10 source compiled by the driver compatibility-profile state plus shaders; MRT and queries depend on loaded functions
OPENGLES1 mobile fixed function none OpenGL ES 1.1; no MRT and no occlusion-query contract
TINYGL CPU fixed function none one software framebuffer; no render targets, cube/volume textures, or queries

All four implement CNA directly. None routes through EasyGL, and none is an alias for an EasyGL profile. The apparently similar names therefore describe API eras, not modes of one code base.

21.2 OPENGL1: a modern contract on a fixed pipeline

OPENGL1 is available only on Linux or Windows and links the system OpenGL library. There is no shader stage to compile, cache, or bind. CNA state is translated into texture environment, matrix, lighting, fog, alpha, blend, depth, stencil, and client-array state that the fixed pipeline understands.

This is not equivalent to a 2D fallback. Both extended primitive entry points are native overrides and submit fixed-function geometry. A GpuDrawParams packet must be reduced to the subset expressible by the pipeline rather than silently falling through the base colored path. The result can draw 3D geometry, but custom programmable effects are an architectural impossibility, not a missing weekend task.

21.2.1 Optional extensions are part of the public truth

OpenGL 1.x predates framebuffer objects and standardized occlusion queries. The renderer therefore treats both as runtime discoveries:

  • RenderTarget2D is available only when the required FBO entry points were resolved. Binding the default backbuffer remains valid without them.

  • multiple render targets are not implemented;

  • occlusion queries are available only when the ARB or later core query functions can be loaded.

This conditional shape is more honest than returning an unconditional capability bit based only on the build identity. An executable can be built successfully and still meet a driver whose OpenGL 1.x extension surface is narrower.

The platform gate and system-library dependency are build facts; the FBO and query clauses are runtime facts. A build matrix can prove the former, but only execution against the selected driver can prove the latter.

21.3 OPENGL2: the GLSL 1.10 bridge

OPENGL2 is the transition renderer. Its context remains a compatibility-profile world, while vertex and fragment work is expressed as GLSL 1.10. That combination makes it materially different from both neighbours: it is programmable unlike OPENGL1, but cannot be served by EasyGL’s ES-oriented shader rewriting and profile macros.

The renderer owns real extended primitive paths, render targets, and effect-aware submission. Its optional ceiling again follows loaded functions rather than the name alone:

  • 2D render targets are supported;

  • MRT is conditional on glDrawBuffers;

  • occlusion queries are conditional on query creation being available.

GLSL 1.10 also explains why shader source is an integration boundary. A shader written only for modern core GLSL cannot simply be handed to this renderer, and an ES shader is not made desktop-compatible merely by changing its version line. Attribute syntax, fragment outputs, precision qualifiers, and built-ins belong to the selected language profile.

21.3.1 Why keep this renderer beside EasyGL?

Compatibility hardware and virtualized drivers can expose a usable OpenGL 2.x path without providing the ES or modern-core environment expected elsewhere. Keeping this implementation separate preserves that deployment option and makes its compromises reviewable. Folding it into EasyGL would hide a different shader language and a different context contract behind a single selector.

21.4 OPENGLES1: fixed function on the mobile branch

OPENGLES1 targets libGLESv1_CM and GLES/gl.h. The dependency is not vendored, and the module refuses configuration when the system library is absent. Stock Mesa builds commonly disable GLES1, so the repository supplies a dedicated ES1-enabled Mesa environment script for this renderer’s evidence path.

Like OPENGL1, it has no shaders. Unlike OPENGL1, its API ceiling is the smaller ES 1.1 fixed-function surface. It implements 2D targets but neither MRT nor occlusion queries.

21.4.1 A hybrid draw route, not unconditional effect parity

The extended draw methods are overridden, so classifying this renderer as a base fallback would be wrong. Their internal dispatch is nevertheless hybrid. Combinations the fixed pipeline can represent are handled natively; skinning, PBR, custom effects, instancing, and other unavailable combinations are sent to the colored tail. The call may therefore draw geometry while losing the semantic content of GpuDrawParams.

This is narrower than the unconditional downgrade described for DIRECTX10 in Chapter 19: supported fixed-function cases remain native here. It is still a crucial portability warning: successful submission does not prove that the requested effect model survived dispatch.

21.5 TINYGL: fixed function as a CPU rasterizer

TINYGL fetches the pinned C-Chads TinyGL revision and renders a fixed-function OpenGL 1.x-style pipeline into its own CPU framebuffer. It owns ordinary and indexed extended draws, including colored, textured, colored-textured, normal-textured and skinned layouts. It reports only ThreeD and WireFrame among the graphics capabilities.

The single-context framebuffer is also the hard boundary: there is no FBO model, so RenderTarget2D, cube targets and MRT are unavailable; texture cubes, volume textures, occlusion queries, programmable effects, instancing, multi-stream input, MSAA and anisotropic filtering are refused. This is a real CPU 3D renderer, not the SOFTWARE family and not a native OpenGL context. The tag contains fourteen TinyGL suites with 113 named checks and a dedicated workflow; this edition records their presence rather than claiming a fresh workflow run.

21.6 The same contract does not imply the same proof

The three families require different verification environments.

Identity Strongest practical path Remaining evidence boundary
OPENGL1 native Linux or Windows system OpenGL, including extension-dependent cases driver variation in FBO and query availability
OPENGL2 compatibility-profile desktop OpenGL with real shader compilation loaded-function and GLSL-driver variation
OPENGLES1 custom Mesa build with GLES1 enabled specialized environment is not the stock developer path
TINYGL native CPU execution with framebuffer readback fixed-function subset and fetched dependency

Registration totals are deliberately omitted here. They drift as cases are split or merged and do not measure assertion quality. The useful question is whether a test reaches a real context, submits pixels through the family-specific path, and observes the result.

21.7 Choosing among the compatibility identities

Choose OPENGL1 only when fixed-function desktop compatibility is itself a goal. Choose OPENGL2 when GLSL 1.10 and compatibility contexts match the deployment target. Choose OPENGLES1 when the ES 1.1 environment is intentional and its fixed-function ceiling is acceptable. For a broader programmable profile set, continue with Chapter 22. Choose TINYGL when a CPU-only fixed pipeline is the intended deployment; a similar API surname does not erase the implementation boundary.

Before shipping on any of the four, verify four things on the target implementation:

  1. 1.

    the selected identity reported at runtime is the one configured at build time;

  2. 2.

    the render-target and query features actually used by the game are available;

  3. 3.

    representative effect-aware draws retain their intended semantics rather than taking a reduced path;

  4. 4.

    pixel evidence is collected from the real context, not only from a construction or no-throw smoke test.

That checklist is the recurring lesson of the compatibility ladder: an old API can implement a surprising amount of CNA, but its limits must be stated as limits of a particular path, not blurred into the capabilities of the OpenGL family as a whole.

Type at least three characters. Results are ranked by how often and where the words occur.