好吧,从正确性的角度来看,您观察到的行为是合规的。您不能断定(或其他)的非NULL
返回值glXGetProcAddress
意味着该函数存在或可以使用。您必须始终查询扩展字符串。尝试获取扩展字符串未通告的函数的函数指针(或上下文的核心 GL 版本所暗示的函数的存在)在概念上将是未定义的行为。
您确实引用了 上的参考页glXGetProcAddress
。不幸的是,这些参考页面出了名的不精确、不完整,有时甚至是完全错误的。在这种情况下,措辞至少是不幸的。
我通常建议使用官方规范来查找此类详细信息。在这种情况下,GLX 1.4 规范将是相关文档。第 3.3.12 节“获取扩展函数指针”说明了这一点glXGetProcAddress
(强调我的):
返回值NULL
指示不存在用于实现的指定函数。
非NULL
返回值glXGetProcAddress
不保证在运行时实际支持扩展函数。客户端还必须查询
glGetString(GL_EXTENSIONS)
或glXQueryExtensionsString
确定特定上下文是否支持扩展。
[...]
glXGetProcAddress
可以查询以下所有功能:
- 实现支持的所有 GL 和 GLX 扩展功能(无论当前上下文是否支持这些扩展)。
- GL 和 GLX 中的所有核心(非扩展)功能,从 1.0 版到并包括由实现支持的那些规范的版本,由
glGetString(GL_VERSION)
和glXQueryVersion
查询确定。
看起来 Mesa3D 实现实际上能够为每个以gl
.
查看当前版本的/src/mapi/glapi/glapi_getproc.c
揭示了_glapi_get_proc_address()
执行此操作的函数:
/**
* 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;
}
所以它实际上检查gl
前缀,如果函数未知,它会动态地为它创建一个存根。稍后,当加载一个硬件后端驱动程序时,它可能会注册 gl 函数,并且存根代码会将调用转发给驱动程序,如果它提供了一个实现。