easy-gl › Architecture
Architecture
Two-layer design
easy-gl is built on top of meta-gl, not directly on raw OpenGL. Understanding this layering is important for knowing where to add new features and why certain design choices were made.
Procedural, type-safe wrapper. Replaces raw enums with
enum class, provides typed handles,
exposes std::span-based APIs. No RAII, no ownership.
OOP RAII layer. Each resource class owns a GPU handle. Move-only. Convenience methods that delegate to meta-gl. Device class for global render state.
Why meta-gl as the intermediary?
Raw OpenGL uses integers for nearly everything: handles, enums, targets, formats. meta-gl wraps all of these into strongly typed C++ types. easy-gl inherits this type safety automatically by reusing meta-gl types in its own API.
When easy-gl needs to call OpenGL, it calls a meta-gl function rather than gl* directly. This means:
- If meta-gl gains new features, easy-gl benefits without changes.
- Type errors are caught at compile time, not at runtime.
- easy-gl code is readable because enum values have meaningful names.
// easy-gl calls meta-gl, not raw OpenGL:
meta::bindTexture(meta::TextureTarget::Texture2D, handle_);
// NOT this:
glBindTexture(GL_TEXTURE_2D, handle_);
gl* call is used but meta-gl already wraps it, that is a bug worth fixing.Types re-exported from meta-gl
easy-gl's Types.hpp re-exports all meta-gl enum types under the easygl namespace using type aliases. You never need to use the metagl:: namespace in application code — use easygl:: for everything.
// Types.hpp — partial list
using BufferTarget = metagl::BufferTarget;
using TextureTarget = metagl::TextureTarget;
using ShaderType = metagl::ShaderType;
using PrimitiveType = metagl::PrimitiveType;
// ... and many more
Device vs resource classes
easy-gl separates two kinds of concerns:
| Kind | Class | Responsibility |
|---|---|---|
| Global state | Device | Viewport, blend, depth, stencil, cull, draw calls, compute, debug, error query. |
| GPU resource | Buffer, Texture, Program, … | Own a single GPU handle. Create, bind, upload data, destroy. |
There is no global state hidden in resource classes. You explicitly call device.set_viewport(), device.set_blend_enabled(), etc.
Namespace
Everything in easy-gl lives in the easygl namespace. There are no sub-namespaces except easygl::detail, which contains internal helpers not part of the public API.
Header structure
| Header | Contents |
|---|---|
easygl/easygl.hpp | Umbrella header — includes everything. |
easygl/Types.hpp | Type aliases for all meta-gl enums used by easy-gl. |
easygl/Device.hpp | Device class. |
easygl/Config.hpp | Configuration struct. |
easygl/Capabilities.hpp | Capability detection. |
easygl/ContextInfo.hpp | GL vendor/version query result. |
easygl/Feature.hpp | Feature enum. |
easygl/Exception.hpp | Exception type. |
easygl/Buffer.hpp | Buffer resource class. |
easygl/Texture.hpp | Texture resource class. |
easygl/Shader.hpp | Shader resource class. |
easygl/Program.hpp | Program resource class. |
easygl/VertexArray.hpp | VertexArray resource class. |
easygl/Framebuffer.hpp | Framebuffer resource class. |
easygl/Renderbuffer.hpp | Renderbuffer resource class. |
easygl/Sampler.hpp | Sampler object resource class. |
easygl/Query.hpp | Query resource class. |
easygl/Sync.hpp | Sync fence resource class. |
easygl/TransformFeedback.hpp | TransformFeedback resource class. |
easygl/detail/NonCopyable.hpp | Internal base for move-only resources. |