Expand description
Supported Features:
global_loader
: Include all mechanisms necessary for calling GL using global functions.struct_loader
: Include all mechanisms necessary for calling GL as methods on a struct.debug_trace_calls
: if cfg!(debug_assertions), any call to a GL function willtrace!
what was called and with what args.debug_automatic_glGetError
: If cfg!(debug_assertions), this will automatically callglGetError
after every call to any other GL function. If an error code occurs it’s shown viaerror!
along with the name of the fn that had the error.log
: importstrace!
anderror!
macros from thelog
crate. Otherwise they just callprintln!
andeprintln!
respectively.chlorine
: gets all C types from thechlorine
crate (which isno_std
friendly). Otherwise they will be imported fromstd::os::raw
.bytemuck
: Adds support for thebytemuck
crate, mostly in the form ofbytemuck::Zeroable
onGlFns
.inline
: Tags all GL calls as#[inline]
.inline_always
: Tags all GL calls as#[inline(always)]
. This will effectively override theinline
feature.
The crate is no_std
friendly by default, but features above can end up
requiring std
to be available.
GL Loaders
The docs for this crate hosted on docs.rs generate both the
global_loader
and struct_loader
documentation for sake of completeness.
However, you are generally expected to use only one loader style in any particular project.
Each loader style has its own small advantages:
- The
global_loader
stores the GL fn pointers in staticAtomicPtr
values.- Call
load_global_gl_with
to initialize the pointers. - Each GL fn is available as a global fn under its standard
name, eg
glGetError()
. - This lets you call GL functions from anywhere at all, and it’s how you might expect to use GL if you have a C background.
- Being able to call GL from anywhere makes it easy to write Drop impls,
among other things.
In both styles, if you call a fn that isn’t loaded you will get a
panic. This generally only happens if the context doesn’t fully support
the GL version. You can check if a GL command is loaded or not before
actually calling it by adding
_is_loaded
to the name of the command. In other words,glGetError_is_loaded
to check ifglGetError
is globally loaded, andgl.GetError_is_loaded
to check if it’s loaded in aGlFns
. All of the “_is_loaded
” functions are hidden in the generated docs just to keep things tidy, but they’re there.
- Call
Safety
In general, there’s many ways that GL can go wrong.
For the purposes of this library, it’s important to focus on the fact that:
- Initially all functions are None pointers. If a fn is called when it’s in a None state then you’ll get a panic (reminder: a panic is safe).
- You can load pointers from the current GL context (described above).
- These pointers are technically context specific, though in practice different contexts for the same graphics driver often all share the same fn pointers.
- The loader has no way to verify that pointers it gets are actually pointers to the correct functions, it just trusts what you tell it.
- Since loading a fn pointer transitions the world from “it will definitely (safely) panic to call that GL command” to “it might be UB to call that GL command (even with the correct arguments)”, the act of simply loading a fn pointer is itself considered to be
unsafe
. - Individual GL commands are generally safe to use once they’ve been properly loaded for the current context, but this crate doesn’t attempt to sort out what is safe and what’s not. All GL commands are blanket marked as being
unsafe
. It’s up to you to try and manage this unsafety! Sorry, but this crate just does what you tell it to.
Re-exports
pub use global_commands::*;
Modules
Contains functions for using the global GL loader.