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

FunctionReturnsDescription
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

WebGL Notes