【发布时间】:2018-01-17 05:36:45
【问题描述】:
我在 RedHat Linux 上开发,cat /etc/redhat-release:
Red Hat Enterprise Linux Workstation release 7.2 (Maipo)
我正在使用 Qt Creator 4.3.1:
Based on Qt 5.9.1 (GCC 5.3.1 20160406 (Red Hat 5.3.1-6), 64 bit)
我正在开发的项目使用 Qt 5.6.2 GCC 64bit,该项目是使用源自 QWidget 的图形对象开发的,其中包括实时视频流。
不幸的是,我们在播放视频时经历了撕裂,这在视频周围显示的其他小部件中也很明显,我相信这是因为视频没有使用 vsync。
我相信使用 openGL 会纠正这种情况,目的是使用 openGL 重写包括视频播放在内的小部件。我花了几天的时间试图找到完整且可行的解决方案,但到目前为止未能找到完整且可行的解决方案。
我一直在研究在我用来测试的小部件中使用 QOpenGLWidget:
class clsElevStrip : public QOpenGLWidget, protected QOpenGLFunctions {
Q_OBJECT
在构造函数中,我设置了离屏渲染的格式:
//Create surface format for rendering offscreen
mobjFormat.setDepthBufferSize(24);
mobjFormat.setSamples(4);
mobjFormat.setVersion(3, 0);
mobjFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
setFormat(mobjFormat);
在paintGL方法中:
QOpenGLContext* pobjContext = context();
QSurface* pobjSurface = pobjContext->surface();
assert(pobjSurface != NULL);
int intSB1 = pobjSurface->format().swapBehavior();
qDebug() << (QString("paintGL:format: ")
+ QString::number(intSB1));
pobjContext->makeCurrent(pobjSurface);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glColor3f(1.0, 0.0, 0.0);
glVertex3f(-0.5, -0.5, 0);
glColor3f(0.0, 1.0, 0.0);
glVertex3f( 0.5, -0.5, 0);
glColor3f(0.0, 0.0, 1.0);
glVertex3f( 0.0, 0.5, 0);
glEnd();
pobjContext->swapBuffers(pobjSurface);
主显示屏上什么都看不到,调试语句将格式显示为 2(双缓冲)。
如果我在构造函数中注释掉该行:
setFormat(mobjFormat);
调试语句显示格式为 0 (DefaultSwapBehavior)。而且图形是可见的,我错过了什么?
【问题讨论】:
-
为了省去你以后在谷歌上搜索的麻烦:你的目标是双缓冲渲染,而不是离屏渲染。双缓冲是,当您在后缓冲区中准备图像并在垂直回扫间隔中将后缓冲区交换到屏幕扫描输出前缓冲区时。 离屏渲染是,如果您要渲染到不会直接在显示设备上显示的缓冲区,即您打算将渲染的图像保存到文件而不显示或生成中间图像在显示之前进行后处理。
-
@datenwolf,谢谢,我之前使用离屏渲染来准备图形,然后将 blit 到可见显示(不使用 Qt 或 openGL),对于我们的要求,目的是消除撕裂视频和图形以提供流畅的外观。
-
是的,这已经很清楚了。使用 OpenGL 及其交换间隔扩展 (khronos.org/opengl/wiki/Swap_Interval) 无疑是获得垂直同步正确显示更新的可行方法(但要小心合成 WM)。但是,如果您的目标是显示视频,那么您平台的专用视频演示 API 之一可能也是一个合适的选择。在 X11 上,它是 Xv 或 XVVA(VAAPI) 或 VDPAU 之一。它们都有 vsync 控制。
-
@datenwolf,谢谢,您能否举例说明您的意思,我在 RedHat 上使用 Qt 和 openGL,我不确定您所说的“在 X11 上会是什么意思” Xv 或 XVVA(VAAPI) 或 VDPAU 之一”?目前,当指定 DoubleBuffering 时,我没有任何可见视频。
-
这些只是替代 API,您可以使用它们来代替 OpenGL。
标签: c++ qt opengl double-buffering