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