glew工作原理

2017-02-16

  在C/C++程序中使用OpenGL时,需要使用glew/glad这样的第三方库来加载OpenGL函数。不像一般的第三方lib,通过头文件,直接就能够找到函数的指针地址。很多同学不明白为什么需要这么做。本文,就来分析一下。
  因为gl.h这个头文件在windows平台是最原始的版本,微软并不更新,一些最新的函数接口并不能暴露出来,不知为何,在Linux上同样不更新了,最新的OpenGL函数原型在glext.h文件中被声明。Khronos官方解释如下

Because extensions vary from platform to platform and driver to driver, OpenGL developers can't expect interfaces for all extensions to be defined in the standard gl.hglx.h, and wgl.h header files supplied with the OS / graphics drivers. Additional header files are provided here, including:

  • <GL/glext.h> - OpenGL 1.2 and above compatibility profile and extension interfaces.
  • <GL/glcorearb.h> - OpenGL core profile and ARB extension interfaces, as described in appendix G.2 of the OpenGL 4.3 Specification. Does not include interfaces found only in the compatibility profile.
  • <GL/glxext.h> - GLX 1.3 and above API and GLX extension interfaces.
  • <GL/wglext.h> - WGL extension interfaces.

  在windows平台上,opengl无法做静态链接,opengl32.dll 是微软提供的。只能通过第三方的lib,动态的获取lib中这样的函数的指针地址。比如说,OpenGL 3 提供的glDrawElementsInstanced() 函数,原本是在glext.h中声明的,如果要使用glew,就不能在glew.h文件前include glext.h。在glew.h 中这个符号被定义为。,而#define GLEW_GET_FUN(x) x,所以,OpenGL的函数名字glDrawElementsInstanced,在内部就变为了__glewDrawElementsInstanced,在头文件中声明了这个函数指针的存在,这也是不需要使用glext.h的原因。所以,从这个时候开始,glDrawElementsInstanced这个函数的指针就存在了,只是值为NULL。在glew.c 中, ,这才是好的编程习惯,否则release 版本时,glDrawElementsInstanced这个函数的指针不一定指向哪儿去了。

这一句经过预处理就是: r = ((__glewDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsInstanced")) == NULL) || r;所以,到此时,glDrawElementsInstanced()这个3.0版本以后的函数就被天骄到OpenGL中了。,这个WINGDIAPI PROC  WINAPI wglGetProcAddress(LPCSTR); 是wingdi.h 定义的,应该是显卡driver 实现的,在显卡driver在中,保留了OpenGL 标准函数名字与其函数指针的表格。
其实,glew 也不是必需的,你也可以使用glcorearb.h这个文件,只是上面的类似的过程都需要手工来做一遍,这样并没有必要。

  因为OpenGL虽然是单核时代的产物,但是,OpenGL也支持多线程,只是这个特性被使用的场合较少。这个多线程支持的特性,就是由glew/glad这样的lib来负责的,
 在windows上,多线程使用OpenGL时,这个glewGetContext() 是需要自己来实现的,每个线程都有自己GLContext,每个GLContext必须要和一个窗口的handle绑定,那么需要自己写代码把每个GLContext和UI线程联系起来。单线程使用OpenGL时,glew和这个GLContext 就无关了,是窗口系统绑定的。

线程之间可以共享GLContext。

ref:

  1. http://stackoverflow.com/questions/38948159/about-function-loader-in-vulkan
  2. https://software.intel.com/en-us/articles/api-without-secrets-introduction-to-vulkan-part-1    ****
  3. http://stackoverflow.com/questions/17809237/what-does-glew-do-and-why-do-i-need-it
  4. https://khronos.org/registry/OpenGL/index_gl.php#headers
如果有任何意见,欢迎留言讨论。


[ 主页 ]
COMMENTS
POST A COMMENT

(optional)



(optional)