Skip to content
Dav1dde edited this page May 5, 2018 · 10 revisions

Contents

  1. Basic API
  2. Header Only
  3. Loader
  4. Debugging
  5. Aliasing
  6. Multi Context

Basic API

All public and glad specific symbols follow certain rules:

  1. All symbols contain the API (GL, GLES2, WGL, etc.), in the following this will be marked as {API}
  2. All symbols are equally named across all APIs (e.g. gladLoad{API}Simple)
  3. Functions are prefixed with glad
  4. Structs are prefixed with Glad
  5. Macros are prefixed with GLAD_
  6. Constants/Globals are prefixed with GLAD_
  7. Typedefs are prefixed with GLAD

Initializing 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.

Runtime Checks

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).

Compiletime Checks

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

Examples

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;

Header Only

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;
    }
    // ...
}

Loader

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.

Debugging

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.

Aliasing

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;

Multi Context

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.

Clone this wiki locally