现在的位置: 首页 > 综合 > 正文

Qt 4.8 中OPenGl的线程特性

2018年04月08日 ⁄ 综合 ⁄ 共 1717字 ⁄ 字号 评论关闭

Qt 4.8 中OPenGl的线程特性,大家一起学习吧:

如果你曾经在Qt模块中使用过OpenGL,那么在某些情况下,你可能想在一个单独的线程中执行一些OpenGL命令,底层的OpenGL实现其自身是可重入的,所以没有什么能阻止你。事实上,waaay back 在第6期的 Qt 季刊中甚至有一篇文章描述了如何来实现它。这是人们花时间写纯OpenGL的代价,但是如果你想在一个单独的线程中使用一些Qt的便利类会怎么样呢?不幸的是这是不可能的,因为这些Qt类不是线程安全的。在Qt 4.8 中,这些都改进了,我们现在已经增加了几种最常见的情况支持。要在x11系统中使用这些新的函数,你应该开启Qt::AA
x11InitThreads 应用程序的属性,确保底层调用的GLX是线程安全的,但是对于windows 和 Macox来说,直接使用就可以了。

缓冲区交换线程
根据您的驱动程序和GPU,函数swapBuffers()的调用有时很费时(特别是在嵌入式处理器)。在许多情况下,这是告诉GPU去接受你所有的渲染命令,并执行它们以渲染当前帧。如果该操作是同步的,那么在GPU做工作的时候,你的主线程就被阻塞了。很不幸,因为你当前的线程有比等待GPU更重要的事情去做。例如,它可以返回到事件循环中来处理一些用户的输入,网络通讯或提前处理下一个动画场景。Qt 4.8的解决方案是提供一个单独的线程,其执行周期的唯一目的是通过调用swapBuffers等待GPU。在具体使用中,你可以像通常一样在主线程中绘制所有的物体,而不调用swapBuffers(),你可以在当前GL上下文中调用doneCurrent()。通知交换线程你已经完成了渲染工作,它接着会调用makeCurrent()激活当前上下文,然后调用swapBuffers(),然后调用doneCurrent()并通知主线程它已经完成了。应该注意的是,这里有一个上下文切换开销,实际上可能会比等待GPU执行完更慢一些,所以,你应该自己测试一下做出取舍和选择。

纹理上传线程
上传许多(或大的)纹理数据通常是一个昂贵的操作,因为有许多数据需要传递给GPU。这同样也是不必要阻塞主线程的操作 。在Qt 4.8中,你可以创建一对共享QGLWidgets来解决改该问题。在单独的线程中创建一个从不在屏幕上显示的 Widget,主线程通知上传线程哪些图像需要上传,上传线程调用每一个图像的bindTexture(),都完成后然后通知主线程时,就可以在屏幕上进行绘制了。

QPainter的线程

在Qt 4.8中可以在一个单独的线程中使用QPainter绘制到QGLWidget,QGLPixelBuffer和QGLFrameBufferObject假设您正在使用OpenGL[ ES] 2.0绘图引擎 。重要的是要注意,QGLWidget并不是移动到辅助线程中(它毕竟是一个QWidget)。而是它的上下文被用在别的地方,这就需要调用QGLWidget的 doneCurrent(),在主线程中释放上下文 。接下来,你应该创建一个单独的QObject子类,并可以移动到辅助的绘制线程中。这个QObject会在绘制线程中关联QGLWidget的上下文为当前上下文,并可以打开一个QPainter开始绘制。如果您正在使用QGLWidget作为绘制目标,那么你需要在QGLWidget中额外设置“QT::WA_PaintOutsidePaintEvent:”的属性
。此外,您将需重载该类,并重新实现QGLWidget resizeEvent()和paintEvent()函数 。这些默认实现将尝试使QGLWidget的上下文为当前上下文,因为这些功能都在主线程上(创建widget的地方),我们不希望这样的事情发生,因为我们正在使用的线程上下文调用 。在您重新实现这些功能,你应该通知QObject子类,它的渲染,这样可以调整视口或重绘现场,如果需要的话。这一切的结果可以看出以下称为一个新的演示 glhypnotizer运行的MDI子窗口包含一个单独的线程QGLWidget渲染

http://www.qtcn.org/bbs/simple/?t46999.html

抱歉!评论已关闭.