LoadGL.h

Here is a single header file one need to include to get hands on ALL OpenGL functionality from the very first version and up to the current:

LoadGL.h

The great simplification this header brings with it is an automatic function pointer initialization. User does not need to bother to initialize the function pointers manually. All known core function version pointers are declared in the LoadGL.h and each of them points to the corresponding loading function at program initialization. First time the function is called, it’s loader automatically searches for an entry point, mangles the pointer so that it points to that address, then calls it with the given arguments. After that the pointer points directly to the OpenGL function (if present; otherwise call has no effect). Simple magic. :slight_smile:

Be aware though, that the rendering context which has been set current when the function was called first time must be active all subsequent function call times, so it is not allowed to use the pointers with the rendering context different from what was bound first time the function was called.

So all you need to do in order to use any of the OpenGL function you have seen in the reference pages, is to place the LoadGL.h file into the directory with your project and include it:

#include "LoadGL.h"

After that you can call any of the OpenGL functions (make sure the rendering context created, though). As simple as that. :slight_smile: Of course, it is always a good practice to check if the given extension is available, but if it isn’t, call to unsupported function will be just ignored.

It is a time consuming work to update the header with each new version of OpenGL being published, but the header served me well for years, so I keep it updated and feel like sharing right now. :slight_smile: So feel free to use it and let me know if there is anything more you would like to see in it.

Where’s the core version of this header? If a client wants to remove non-core functionality, then they are forced to check every extension and function to verify its listing in the specification. I’d rather let the compiler enforce this for me instead of relying on my own fallible faculties. Libraries such as GL Load or even the glcorearb.h solve this problem.

There is no core version and there is no need for that. Jesse, in LoadGL.h every function initializes itself independently. The function you never called will not be initialized at all. User does not need to call any special function to initialize the pointers. You just include the header and call whichever function you need. Simply use the functions you see in the documentation and do not use any other if you are so concerned about that.

So how does the LoadGL.h works exactly?
Let’s take a look on some function you need to use in your application. Let it be the “glGenFramebuffers” for example.
The pointer to that function in LoadGL.h looks like this:

void (__stdcall *glGenFramebuffers) (GLsizei n, GLuint *framebuffers) = OpenGLFunctionLoaders::LOADglGenFramebuffers;

As you see, initially the pointer points to some LOADglGenFramebuffers function hidden inside OpenGLFunctionLoaders namespace. That function is declared above the pointer with exactly the same interface but defined at the bottom of the header:

void __stdcall LOADglGenFramebuffers (GLsizei n, GLuint *framebuffers){
 if(LoadFuncExt(&glGenFramebuffers,"glGenFramebuffers"))glGenFramebuffers(n, framebuffers);
}

So when your application calls glGenFramebuffers(…) for a very first time, the LOADglGenFramebuffers is actually called instead. That loading function attempts to retrieve the pointer to glGenFramebuffers function. On success the pointer glGenFramebuffers changes, referencing to the actual address of the target routine, which is called then with the same arguments the LOADglGenFramebuffers received. Any subsequent calls of glGenFramebuffers pointer will go directly where they suppose to. the auxilary function “LoadFuncExt” called by each of the loading routines is defined in LoadGL.h like this:

bool LoadFuncExt(void* PtrToFuncPtr, const char* FuncName){
 int ptr = (int)wglGetProcAddress(FuncName);
 if(ptr){ *((int*)PtrToFuncPtr)=ptr; return true; }
 char str[128];
 int len = strlen(FuncName); if(len>124)return false;
 memcpy(str,FuncName,len);
 str[len]='A'; str[len+1]='R'; str[len+2]='B'; str[len+3]=0;
 ptr = (int)wglGetProcAddress(str);
 if(ptr){ *((int*)PtrToFuncPtr)=ptr; return true; }
 str[len]='E'; str[len+1]='X'; str[len+2]='T'; str[len+3]=0;
 ptr = (int)wglGetProcAddress(str);
 if(ptr){ *((int*)PtrToFuncPtr)=ptr; return true; }
 return false;
}

As one can see, that function uses wglGetProcAddress to retrieve the address of the desired function and on success writes that address into the given function pointer. In the glGenFramebuffers example the LoadFuncExt requests the pointer for “glGenFramebuffers” routine (the core version), and if the wglGetProcAddress returns NULL, it appends “ARB” to the end requesting the address of “glGenFramebuffersARB” function. If even that attempt fails, the requested function name changes to “glGenFramebuffersEXT”. If none of that works, the pointer left unchanged and LoadFuncExt returns “false”. If so, next call to glGenFramebuffers will result in calling LOADglGenFramebuffers again and the whole procedure will repeat. So calling non-existing function will simply have no effect instead of causing system crash or something. So the whole process of function loading is completely transparent to the user - no effort need to be done to initialize the function pointers - it is done automatically, independently for each of the function you desire to use in your code, and none of the functions you didn’t used will be initialized ever.

Yes there is!

How else would you ensure that you don’t accidentally use some non-core features that may cause hard to track down runtime errors? I’d rather have those flagged at compile time!

[QUOTE=Nikki_k;1260362]How else would you ensure that you don’t accidentally use some non-core features that may cause hard to track down runtime errors?[/QUOTE]Well, using the Brain, instead of instincts, I guess?.. :slight_smile:
Seriously, how exactly is this should be done? Do I have to enclose the old functionality between the precompiller pair like this?:

#ifndef HIDE_LEGACY_STUFF
...legacy functions...
#endif

Or what whould you suggest?
I just never need a help from compiller to guide me, so please be more specific about the changes you would like to see, so I could edit the LoadGL.h to make you guys happy! :slight_smile:

[QUOTE=Yandersen;1260368]Well, using the Brain, instead of instincts, I guess?.. :slight_smile:
Seriously, how exactly is this should be done? Do I have to enclose the old functionality between the precompiller pair like this?:

#ifndef HIDE_LEGACY_STUFF
...legacy functions...
#endif

[/QUOTE]

Yes, precisely.

[QUOTE=Yandersen;1260368]Or what whould you suggest?
I just never need a help from compiller to guide me, so please be more specific about the changes you would like to see, so I could edit the LoadGL.h to make you guys happy! :)[/QUOTE]

[/quote]

I guess you never had to deal with really large projects, maintained by a group of people, containing code by other people that are no longer at yout disposal to help you.
In such cases you HAVE to rely on tools to make your work easier.
The problem here in particular is that the code will compile and link and appear to run normally, just to exhibit some odd traits that are very, very hard to find if you have no idea where to look - especially if you have not memorized every intricate detail of what is deprecated and what not.
For this particular reason we already have abandoned GLEW because it got no facilities to weed out non-core-GL constructs. We need a loader library where we can precisely specify up front what GL version to target and what extensions to support, not one that loads everything it can grab.

Understood.
Is it OK to leave ALL functions to be available by default, so defining some key just before the #include directive will hide legacy stuff?
If so, what preprocessor vulue would you suggest? Should there be multiple values for different versions so to hide all stuff up to the specified one? May I be dare enough to ask for an example?