[gl] loading OpenGL functions

[gl] loading OpenGL functions

source: https://www.khronos.org/opengl/wiki/Load_OpenGL_Functions

Windows #

wglGetProcAddress is defined in wingdi.h and needs to link with Opengl32.lib or dynamically with Opengl32.dll.

void *GetAnyGLFuncAddress(const char *name) {
    void *p = (void *)wglGetProcAddress(name);
    if(p == 0 ||
       (p == (void*)0x1) || (p == (void*)0x2) || (p == (void*)0x3) ||
       (p == (void*)-1) )
    {
        HMODULE module = LoadLibraryA("opengl32.dll");
        p = (void *)GetProcAddress(module, name);
    }

    return p;
}

From the windows docs:

The system maintains a per-process reference count on all loaded modules. Calling LoadLibrary increments the reference count. Calling the FreeLibrary or FreeLibraryAndExitThread function decrements the reference count. The system unloads a module when its reference count reaches zero or when the process terminates (regardless of the reference count).

So maybe only load the library once at startup?

Linux #

glXGetProcAddress or glXGetProcAddressARB get the function pointer by the (ascii) string name of the funciton. Function pointers are returned even if the context does not support them. The supported functionallity still has to be queried separately.

glXGetProcAddress will return valid function pointers for OpenGL extensions and all core versions.

Function prototypes #

  • Needed to store the function pointers in variables to call them later.

glext.h contains function pointer definitions for every extension and every core function for version 1.2 and above. The functions for versions before that are provided by Windows’ gl.h. There are also glxext.h for GLX and wglext.h for WGL.

The ext.h headers do not define actual function pointers but only typdef the function pointer type. Example for glUseProgram:

typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);

PFN as in Pointer to Function and a suffix of PROC. A variable of this type (to hold the respective function) can then be created as:

PFNGLUSEPROGRAMPROC glUseProgram;

Actually loading the functions #

When creating the opengl context you can specify the OpenGL version at creation time (supposedly) and if you get it you are using that version.

To query for the exact open gl version you can use glGetString(GL_VERSION) for opengl versions < 3.0 and glGetIntegerv(GL_MAJOR_VERSION) (and GL_MINOR_VERSION) for versions >= 3.0. This allows us to safely load core functions where we know they are supported in various versions.

If we want to load extension functions, we also need to check if the extension is supported. In OpenGL versions < 3.0 this is done with glGetString(GL_EXTENSIONS) This returned a large string of space-separated extension names. This is removed since version 3.1. Instead, in versions >= 3.0 you can call glGetIntegerv(GL_NUM_EXTENSIONS) to get the number of of supported extensions and then call glGetStringi(GL_EXTENSIONS, i) where i is the number of extension names to query (between 0 and num_extensions-1).

Once you know a function is supported on the current machine, you can load it as described at the top.

Calendar October 22, 2023