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 for glXGetProcAddress
does not guarantee that an extension function is actually supported at runtime. The client must also query
glGetString(GL_EXTENSIONS)
or glXQueryExtensionsString
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)
and glXQueryVersion
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.