Context API
Declared in include/metagl/Context.hpp. The Context API tracks the
lifecycle of the host-provided OpenGL ES context. meta-gl does not create or
destroy contexts; it only observes and reports their state.
Overview
When you call metagl::Initialize(), it loads all GL function pointers,
detects the API kind (OpenGL ES vs WebGL) and version, fills a ContextInfo
snapshot, and marks the context as Current. A monotonically-increasing
generation counter is bumped each time — this lets resource managers detect
stale handles after context loss.
ApiKind
enum class ApiKind : std::uint8_t { Unknown, OpenGLES, // EGL / ANGLE / native GLES WebGL // Emscripten WebGL 1 or 2 };
ContextStatus
enum class ContextStatus : std::uint8_t { NotCreated, // Initialize() has never been called Current, // Context is active and rendering is possible Lost, // Context was lost; all GL handles are invalid Restored // Context restored; resources must be recreated };
ContextInfo
struct ContextInfo { ApiKind api = ApiKind::Unknown; int major = 0; int minor = 0; std::string vendor; std::string renderer; // OpenGL ES version flags bool gles2 = false; bool gles3 = false; bool gles31 = false; bool gles32 = false; // WebGL flags (Emscripten builds only) bool webgl = false; bool webgl1 = false; bool webgl2 = false; /// Monotonically increasing. Bumped by each Initialize() call. std::uint64_t generation = 0; ContextStatus status = ContextStatus::NotCreated; };
API Functions
| Function | Returns | Description |
|---|---|---|
GetContextInfo() |
ContextInfo (copy) |
Full snapshot of context state |
GetContextGeneration() |
uint64_t |
Current generation counter |
GetContextStatus() |
ContextStatus |
Current lifecycle status |
IsContextLost() |
bool |
True when status == Lost |
MarkContextLost() |
void |
Call from platform lost-callback |
MarkContextRestored() |
void |
Call after re-initialize (or it's done automatically) |
SetContextInfo(ContextInfo) |
void |
Internal — used by Initialize() |
All query functions are marked [[nodiscard]] and noexcept.
Lifecycle Diagram
[ App startup ]
│
▼
┌────────────────┐
│ NotCreated │◄───────────────────────┐
└───────┬────────┘ │
│ Initialize(loader) │
▼ │
┌────────────────┐ │
│ Current │─────────────┐ │
└───────┬────────┘ │ │
│ MarkContextLost() │ │
│ (platform callback) │ │
▼ │ │
┌────────────────┐ │ │
│ Lost │ │ │
└───────┬────────┘ │ │
│ Initialize(loader) │ │
▼ │ │
┌────────────────┐ │ │
│ Restored │─────────────┘ │
└───────┬────────┘ (rendering resumes) │
│ app fully reloads resources │
└──────────────────────────────────┘
Handling Context Loss
After context loss, all GPU object handles (textures, buffers, programs, VAOs) are invalid. You must recreate everything. The generation counter makes it easy to track which resources belong to which context instance:
struct ManagedTexture { GLuint id = 0; uint64_t gen = 0; // generation when this was created bool isValid() const { return id != 0 && gen == metagl::GetContextGeneration(); } void upload(/* ... */) { if (!isValid()) { metagl::glGenTextures(1, &id); gen = metagl::GetContextGeneration(); } // upload data ... } }; // In render loop: if (metagl::IsContextLost()) return; texture.upload(data); // automatically recreates if generation changed
Android Notes
- Call
metagl::Initialize()fromGLSurfaceView.Renderer::onSurfaceCreated()via JNI or from the SDL/EGL context-creation path. - Call it again from
onSurfaceCreated()— it always recreates from scratch. - After context loss: old textures, buffers, shaders are gone. Do not call
glDelete*on them — the driver already freed them. - The generation counter is the idiomatic way to detect this situation.
WebGL Notes
- Register the Emscripten
HTMLELEMENT_EVENT_WEBGLCONTEXTLOSTcallback and callmetagl::MarkContextLost()from it. - Register
HTMLELEMENT_EVENT_WEBGLCONTEXTRESTOREDand callmetagl::Initialize(emscripten_GetProcAddress). - On WebGL,
GetContextInfo().api == ApiKind::WebGLandGetContextInfo().webgl2 == truefor WebGL 2.