I was very surprised when I discovered that the following code, and a lot of its variations, produce a non-null memory address. The variations that I tried include:
glXGetProcAddressARB
instead of glXGetProcAddress
.Using the cross-platform alternative provided with GLFW: glfwGetProcAddress
.
#include <GL/glx.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
void *ptr;
ptr = glXGetProcAddress((const GLubyte *)"glottis");
printf("ptr: %x\n", ptr);
return 0;
}
The programs is compiled with -lGL
(and -lglfw
when required) and there are no warnings nor errors.
The only way to obtain a 0
output, the NULL
pointer, is by asking the address of a function whose name does not start with gl
, for instance manny
.
I am quite surprised by this behaviour because glottis
and manny
should be equally non-existing, and I would have expected both to produce a NULL
pointer.
This is an excerpt from glXGetProcAddress
documentation.
Notes
A NULL pointer is returned if function requested is not suported in the implementation being queried.
GLU functions are not queryable due to the fact that the library may not be loaded at the time of the query.
Full document
More info on this topic
Well, from a correctness point of view, the behaviour you observe is compliant. You cannot conclude that a non-NULL
return value of glXGetProcAddress
(or the others) implies that the function is there or can be used. You must always query the extension string. Trying to get function pointers for function not advertised by the extension string (or its presence implied by the core GL version of your context) will conceptually be undefined behavior.
You did quote from the reference page on glXGetProcAddress
. Unfortunately, those reference pages are notorioulsy imprecise, incomplete, and sometimes even flat-out wrong. In this case, the wording is at least unfortunate.
I generally recommend using the official specifications for looking up such details. In this case, the GLX 1.4 specification will be the relevant document. Section 3.3.12 "Obtaining Extension Function Pointers" states this about glXGetProcAddress
(emphasis mine):
A return value of
NULL
indicates that the specified function does not exist for the implementation.A non-
NULL
return value forglXGetProcAddress
does not guarantee that an extension function is actually supported at runtime. The client must also queryglGetString(GL_EXTENSIONS)
orglXQueryExtensionsString
to determine if an extension is supported by a particular context. [...]
glXGetProcAddress
may be queried for all of the following functions:
- All GL and GLX extension functions supported by the implementation (whether those extensions are supported by the current context or not).
- All core (non-extension) functions in GL and GLX from version 1.0 up to and including the versions of those specifications supported by the implementation, as determined by
glGetString(GL_VERSION)
andglXQueryVersion
queries.
It looks like the Mesa3D implementation is actually capable of generating some stubs dynamically for every queried function starting with gl
.
Looking at the current version of /src/mapi/glapi/glapi_getproc.c
reveals the function _glapi_get_proc_address()
doing this:
/**
* Return pointer to the named function. If the function name isn't found
* in the name of static functions, try generating a new API entrypoint on
* the fly with assembly language.
*/
_glapi_proc
_glapi_get_proc_address(const char *funcName)
{
_glapi_proc func;
struct _glapi_function * entry;
init_glapi_relocs_once();
#ifdef MANGLE
/* skip the prefix on the name */
if (funcName[1] != 'g' || funcName[2] != 'l')
return NULL;
#else
if (funcName[0] != 'g' || funcName[1] != 'l')
return NULL;
#endif
/* search extension functions first */
func = get_extension_proc_address(funcName);
if (func)
return func;
/* search static functions */
func = get_static_proc_address(funcName);
if (func)
return func;
/* generate entrypoint, dispatch offset must be filled in by the driver */
entry = add_function_name(funcName);
if (entry == NULL)
return NULL;
return entry->dispatch_stub;
}
So it actually checks for the gl
prefix, and if the function is then not known, it dynamically creates a stub for it. Later, when a hw backend driver is loaded, it might register the gl functions, and the stub code will forward the call to the driver, if it provides an implementation for it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With