-
Notifications
You must be signed in to change notification settings - Fork 456
All public and glad specific symbols follow certain rules:
- All symbols contain the API (GL, GLES2, WGL, etc.), in the following this will be marked as
{API}
- All symbols are equally named across all APIs (e.g.
gladLoad{API}Simple
) - Functions are prefixed with
glad
- Structs are prefixed with
Glad
- Macros are prefixed with
GLAD_
- Constants/Globals are prefixed with
GLAD_
- Typedefs are prefixed with
GLAD
Everything generated by glad needs to be initialized through one loader function. Glad exposes two with similiar APIs by default:
typedef void* (* GLADloadproc)(const char *name, void* userptr);
typedef void* (* GLADsimpleloadproc)(const char *name);
GLAPI int gladLoad{API}(GLADloadproc load, void* userptr);
GLAPI int gladLoad{API}Simple(GLADsimpleloadproc load);
gladLoadGL
allows you to pass a userpointer which will be forwarded to your loader function,
this allows you to write a loader function which is independent of global state (useful for e.g. Qt).
In most cases you will be using gladLoad{API}Simple
, most libraries like GLFW or SDL already
provide a loader which is compatible with this function.
The return value of gladLoad{API}
and gladLoad{API}Simple
is the actual loaded version of the API.
To extract the major and minor version out of the return value you can use the GLAD_VERSION_MAJOR(version)
and GLAD_VERSION_MINOR(version)
macros. Currently the return value is calculated using the formula
major * 1000 + minor
but this may change in the future.
NOTE: since some APIs require additional information in order to be initialized the loader signature may vary depending on the API (e.g. WGL and EGL have different signatures).
NOTE: initializing an API more than once is undefined behaviour.
After glad was initialized a few variables will be populated. Glad creates a global boolean for every version and extension generated.
GLAPI int GLAD_{API}_VERSION_3_0;
GLAPI int GLAD_{API}_VERSION_3_1;
// ...
GLAPI int GLAD_{API}_EXT_texture_buffer_object;
GLAPI int GLAD_{API}_KHR_debug;
// ...
If a version/extension was successfully loaded the global will be set to true (1).
Sometimes you want to write glad agnostic code, for this glad generates and defines a few macros dependent on the generation options used.
#define GLAD_{API}
#define GLAD_OPTION_{API}_LOADER
#define GLAD_OPTION_{API}_ALIAS
Initializing glad with glfwGetProcAddress
and extracting the loaded major and minor versions:
int version = gladLoadGLSimple((GLADsimpleloadproc) glfwGetProcAddress);
if (version == 0)
{
std::cout << "Failed to initialize OpenGL context" << std::endl;
return -1;
}
// Successfully loaded OpenGL
std::cout << "Loaded OpenGL " << GLAD_VERSION_MAJOR(version) << "." << GLAD_VERSION_MINOR(version) << std::endl;
The header only option combines source and header into a single header file.
The implementation will be guarded by GLAD_{API}_IMPLEMENTATION
. In order to not end
up with missing symbols you need to define this macro ONE SOURCE file before including
glad.
Example for GL:
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
int main(void) {
// ...
if (!gladLoadGLSimple((GLADsimpleloadproc) glfwGetProcAddress)) {
return -1;
}
// ...
}
The loader option adds an internal loader into the generated files. This is useful if you are not using a library that cotains a loader (e.g. you're not using GLFW, SDL, Qt or similar).
The following function will be added:
GLAPI int gladLoad{API}InternalLoader();
Some APIs (egl
, gles1
, gles2
, glx
) should be unloaded at the end of the program, this can be done through:
GLAPI void gladUnload{API}InternalLoader();
NOTE: Even after multiple calls to gladLoad{API}InternalLoader()
only one call to gladUnload{API}InternalLoader()
is required.
The debugging option adds an additional layer of indirection allowing you to intercept and modify any call made.
Usually glad works like this glClear() -> glad_glClear()
using the debug option it looks like this
glClear() -> glad_debug_glClear() -> glad_glClear()
. glClear()
is a macro, glad_glClear()
contains the actual
function pointer.
By default the added indirection (glad_debug_glClear
) calls the "pre callback", then the actual function and afterwards the "post callback".
Callbacks can be set with the following functions:
typedef void (* GLADprecallback)(const char *name, void *funcptr, int len_args, ...);
typedef void (* GLADpostcallback)(void *ret, const char *name, void *funcptr, int len_args, ...);
void gladSet{API}PreCallback(GLADprecallback cb);
void gladSet{API}PostCallback(GLADpostcallback cb);
By default the "pre callback" clears all errors and the "post callback" checks for an error using glGetError
.
NOTE: the debug option cannot be used together with the multi context option.
Enables automatic alias resolution. A lot of OpenGL features exist in multiple extensions, and some of them have been moved into core. The result is a bunch of functions which are named differently but do the same.
Glad will automatically include all extensions which have an alias to a function you specified in the feature set and at runtime all functions (if not available) will be initialized using their aliases.
An excerpt of the generated code:
// executed after initial loading phase:
if (glVertexAttrib2sv == NULL && glVertexAttrib2svARB != NULL) glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC)glVertexAttrib2svARB;
if (glVertexAttrib2sv == NULL && glVertexAttrib2svNV != NULL) glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC)glVertexAttrib2svNV;
By default glad generates everything as a global variable, which works fine for most usecases.
But when you have to support multiple contexts it becomes basically impossible to do so.
If multi context is enabled all function pointers and variables are inside a struct
,
one instance per context.
Glad will generate a struct called Glad{API}Context
which can be passed to a loader function
which has been modified to accept the context as first parameter.
The symbols within the struct have their prefix stripped, e.g. glClear
turns into gl->Clear
,
this also applies to flags like GLAD_GL_EXT_framebuffer_multisample
which turns into
gl->EXT_framebuffer_multisample
.
By default glad does not generate global aliases. This can be turned on with the "mx global"
option. Next to the context struct a global instance of said struct will be generated, which can be
populated through gladSet{API}Context(struct Glad{API}Context *context)
and queried through struct Glad{API}Context* gladGet{API}Context()
. Using any loader function
will automatically set the global handle.
NOTE: the mx option can not be used together with the debug option.