OpenGL Context

OpenGL Context

OpenGL Context与窗口系统相关,所以在不同平台上创建方式都不一样。

  1. Windows上使用的是WGL
  2. Linux上有GLX和EGL两种,分别对应两种窗口系统XWindow和Wayland
  3. Mac上使用的是AEL
  4. IOS上使用的是EAGL,对应的是OpenGL ES
  5. Android上使用的是EGL

EGL 是OpenGL官方Khronos推出的,既可以使用用于OpenGL Context,也可以用于OpenGL ES Context。Google的ANGLE项目使用了EGL,支持各个平台,提供将OpenGL ES/WebGL转译为Vulkan、DirectX、Metal 等系统图形API,Chrome浏览器中的WebGL使用了ANGLE。

Context与线程

  1. 一条线程同时只能绑定一个OpenGL Context,Context也只能同时绑定到一个线程,OpenGL在绑定的线程当中相当于全局的。如果线程没有绑定Context,则不能调用OpenGL函数。
  2. OpenGL Context可以在任意线程创建,创建完成后可以将Context绑定到任意线程,也可以从线程解除绑定,然后从新绑定到新的线程。绑定和解绑需要使用MakeCurrent函数,WGL、GLX、EGL、AGL都有自己对应的MakeCurrent函数。WGL的MakeCurrent函数是wglMakeCurrent。
  3. OpenGL Context虽然创建的时候需要一个窗口,但实际上Context不要任何窗口相关,也就是说创建完成后可将Context绑定到其他窗口上,这样可以实现一个OpenGL Context在多个不同的窗口上渲染。
  4. EGL创建Context时可以使用pBuffer,使用eglCreatePbufferSurface函数。这让EGL可以在没有窗口系统的服务器系统,以及Docker中使用。

多线程使用OpenGL

消息队列

消息队列是简单直接的方法,通过创建一条线程,让后将OpenGL Context绑定到线程,其他线程通过发生消息的方式调用OpenGL函数,Android中OpenGL ES默认使用的是这种方法。消息队列可以是阻塞队列Blocking Queue实现。

优点:实现简单,使用方便直观,调试简单。

缺点:内存管理比较麻烦,例如主线程要更新UBO内存,要么等等渲染线程map一个指针回来,要么发生整个内存数据到渲染线程,但这时主线程不知道渲染线程什么时候更新完UBO,这导致难以回收和复用这内存。

例子:CppTest/openGL/OpenGLQueue.cpp · 小康6650/StudyProject - Gitee.com

在不同线程绑定Context

这种方式是每次需要使用OpenGL时则绑定Context,使用完后又解绑。为了防止多个线程同时绑定Context,绑定时需要加锁,解绑时需要解锁。因为同时只有一个线程可以使用OpenGL,一个线程在使用时另一个线程只能等待。所以如果渲染线程很快,可能会导致主线程等待绑定OpenGL而产生卡顿。这种方法适合帧率不高的情况,直播软件OBS Studio使用的就是这种方法。

例子:CppTest/openGL/OpenGLLock.cpp · 小康6650/StudyProject - Gitee.com

不同 context 之间共享数据

这种方式是为每个线程创建一个OpenGL Context,然后在不同Context之间共享OpenGL对象。

这种方式程序需要负责OpenGL同步,防止一个Context在渲染纹理,而另一个线程在读取纹理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值