是否有方法从其他线程使用glwidget的qglcontext。因为我需要从其他线程上传一些纹理。然而,在纹理上传之后,甚至在上传期间,上下文也必须在我的渲染glwidget的服务中。是否有文件或可靠的(无假设的)答案?
glTexImage2D
,作为图像信息。要做到这一点,必须添加一些线程管理(信号e.t.c…)
有关更多信息,请参阅并发和OpenGL。
还有QGLWidget多线程示例?。
要在其他线程中工作,必须与它们创建单独的上下文或执行一些共享上下文管理。
来自官方Qt文档:
从Qt 4.8版本开始,对执行线程GL渲染的支持得到了改进。我们目前支持三种场景:
线程中的缓冲区交换。在双缓冲上下文中交换缓冲区可能是一种同步锁定调用,在某些GL实现中,这可能是一项成本高昂的操作。尤其是嵌入式设备。当GPU进行缓冲区交换时,让CPU空闲并不是最佳选择。在这些情况下,可以在主线程中进行渲染,并在单独的线程中进行实际的缓冲区交换。这可以通过以下步骤完成:
渲染完成后,在主线程中调用
doneCurrent()
。调用
QGLContext::moveToThread(swapThread)
将上下文的所有权转移到交换线程。通知交换线程它可以获取上下文。
使用
makeCurrent()
在交换线程中使渲染上下文为当前上下文,然后调用swapBuffers()
。在交换线程中调用
doneCurrent()
。调用
QGLContext::moveToThread(qApp->thread())
并通知主线程交换已完成。
这样做将释放主线程,以便它可以继续处理例如UI事件或网络请求。即使涉及上下文交换,与在GPU完成交换操作时让主线程等待相比,这可能是优选的。请注意,这高度依赖于实现。
线程中的纹理上传。在线程中进行纹理上传对于处理需要显示的大量图像的应用程序(例如照片库应用程序)可能非常有用。这是通过现有的
bindTexture()
API在Qt中支持的。一个简单的方法是创建两个共享QGLWidgets
。一个在主GUI线程中是最新的,而另一个在纹理上传线程中是当前的。上传线程中的小部件从未显示,它只用于与主线程共享纹理。对于通过bindTexture()
绑定的每个纹理,通知主线程,以便它可以开始使用该纹理。使用
QPainte
r绘制线程中的QGLWidget
。在Qt 4.8中,可以在单独的线程中使用QPainter
来绘制QGLWidget
。注意,这对于QGLPixelBuffers
和QGLFramebufferObjects
也是可能的。由于这仅在GL 2绘制引擎中受支持,因此需要OpenGL 2.0或OpenGL ES 2.0。
QGLWidgets
只能在主GUI线程中创建。这意味着需要调用doneCurrent()
才能从主线程释放GL上下文,然后才能由另一个线程将小部件引入。然后,您需要调用QGLContext::moveToThread()
来将上下文的所有权转移到要使其成为当前线程的线程。此外,当小部件被调整大小,或者它的一部分被暴露或需要重新绘制时,主GUI线程将向QGLWidget
调度调整大小和绘制事件。因此,有必要处理这些事件,因为QGLWidget
中的默认实现将尝试使QGLWidget
的上下文成为当前上下文,这将再次干扰呈现到小部件中的任何线程。重新实现QGLWidget::paintEvent()
和QGLWidget::resizeEvent()
,以通知渲染线程需要调整大小或更新,并注意不要调用基类实现。如果正在渲染动画,则可能根本不需要处理绘制事件,因为渲染线程正在进行定期更新。那么重新实现QGLWidget::paintEvent()
就足够了,什么都不做。
执行线程渲染时的一般规则是:请注意,不同线程中的绑定和释放上下文必须由用户同步。GL呈现上下文在任何时候都只能是一个线程中的当前上下文。如果您尝试在QGLWidget
上打开QPainter
,而小部件的呈现上下文在另一个线程中是当前的,那么它将失败。
除此之外,还支持在单独的线程中使用原始GL调用进行渲染。