在 OS X 上的 Qt 4.8.6 中更改 QGLWidgets 的 OpenGL 上下文版本
Posted
技术标签:
【中文标题】在 OS X 上的 Qt 4.8.6 中更改 QGLWidgets 的 OpenGL 上下文版本【英文标题】:Changing the OpenGL Context Version for QGLWidgets in Qt 4.8.6 on OS X 【发布时间】:2014-07-21 19:52:57 【问题描述】:我想使用 Qt 4.8.6 通过 QGLWidget 渲染 OpenGL 内容。我正在使用的机器是带有 OS X 10.9.4 的 macbook pro。
QGLWidget 是通过传递一个带有请求的 3.2 核心配置文件格式版本的 QGLFormat 对象来创建的。我遇到的问题是,无论我指定什么 GLFormat,QGLContext 报告的 OpenGL 版本仍然是 1.0。
在研究了该主题后,我找到了Qt OpenGL Core Profile Tutorial。然而,示例源代码报告了与之前相同的 OpenGL 版本 1.0。奇怪的是电话
qDebug() << "Widget OpenGl: " << format().majorVersion() << "." << format().minorVersion();
qDebug() << "Context valid: " << context()->isValid();
qDebug() << "Really used OpenGl: " << context()->format().majorVersion() << "." << context()->format().minorVersion();
qDebug() << "OpenGl information: VENDOR: " << (const char*)glGetString(GL_VENDOR);
qDebug() << " RENDERDER: " << (const char*)glGetString(GL_RENDERER);
qDebug() << " VERSION: " << (const char*)glGetString(GL_VERSION);
qDebug() << " GLSL VERSION: " << (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
报告了2.1的版本字符串
Widget OpenGl: 1 . 0
Context valid: true
Really used OpenGl: 1 . 0
OpenGl information: VENDOR: NVIDIA Corporation
RENDERDER: NVIDIA GeForce GT 750M OpenGL Engine
VERSION: 2.1 NVIDIA-8.26.26 310.40.45f01
GLSL VERSION: 1.20
使用 2011 年 this OS X opengl context discussion 中建议的 Cocoa 代码,版本号的输出更改为
Widget OpenGl: 1 . 0
Context valid: true
Really used OpenGl: 1 . 0
OpenGl information: VENDOR: NVIDIA Corporation
RENDERDER: NVIDIA GeForce GT 750M OpenGL Engine
VERSION: 4.1 NVIDIA-8.26.26 310.40.45f01
GLSL VERSION: 4.10
虽然驱动程序现在报告预期的 OpenGL 版本号,但我仍然只能获得 1.0 QGLWidget 上下文。传递给 QGLWidget 构造函数的 QGLFormat 对象是使用
QGLFormat fmt;
fmt.setProfile(QGLFormat::CoreProfile);
fmt.setVersion(3, 2);
fmt.setSampleBuffers(true);
对于为什么我仍然只获得 1.0 版本的上下文,我有些茫然。即使没有 Cocoa 框架生成的 OpenGL 上下文,也应该可以将上下文版本增加到 2.1,但不管传递给构造函数的 QGLFormat 是什么,它都保持在 1.0。
非常感谢任何关于为什么 QGLWidget 上下文保持在 1.0 版的指针。
更新 1
进一步的实验表明,该代码在 Ubuntu 13.04 Linux 上返回了请求的 OpenGL 版本。这个问题似乎是 OS X 特有的。
更新 2
我构建了一个最小的非/工作示例
#include <QtOpenGL/QGLFormat>
#include <QtOpenGL/QGLWidget>
#include <QtGui/QApplication>
#include <QtCore/QDebug>
int main(int argc, char **argv)
QApplication app(argc, argv);
QGLFormat fmt = QGLFormat::defaultFormat();
fmt.setVersion(3,2);
fmt.setProfile(QGLFormat::CoreProfile);
fmt.setSampleBuffers(true);
QGLWidget c(fmt);
c.show();
qDebug() << c.context()->requestedFormat();
qDebug() << c.context()->format();
return app.exec();
可以在 Ubuntu 中使用
g++ main.cpp -I/usr/include/qt4 -lQtGui -lQtCore -lQtOpenGL -lGL -o test
或在 OS X 下
g++ main.cpp -framework OpenGL -framework QtGui -framework QtCore -framework QtOpenGL -o test
它打印两行 QGLFormat 调试输出。第一行是请求的格式,第二行是实际的上下文格式。两者都应该显示 3.2 的 major.minor 版本号。它似乎在 Ubuntu Linux 下工作,但在使用 OS X 时失败。
更新 3
欢乐时光。这可能是 Qt4.8.6 中的一个错误,因为在再次编译 Qt5.3.1 时不会出现该问题。一个bug report has been filed.
其他人可以验证这种行为吗?
【问题讨论】:
【参考方案1】:是的。那是平台特定的。请找到解决方案here。
重写 QGLContex::chooseMacVisual 以指定特定于平台的初始化。
CustomGLContext.hpp:
#ifdef Q_WS_MAC
void* select_3_2_mac_visual(GDHandle handle);
#endif // Q_WS_MAC
class CustomGLContext : public QGlContext
...
#ifdef Q_WS_MAC
void* chooseMacVisual(GDHandle handle) override
return select_3_2_mac_visual(handle); // call cocoa code
#endif // Q_WS_MAC
;
gl_mac_specific.mm:
void* select_3_2_mac_visual(GDHandle handle)
static const int Max = 40;
NSOpenGLPixelFormatAttribute attribs[Max];
int cnt = 0;
attribs[cnt++] = NSOpenGLPFAOpenGLProfile;
attribs[cnt++] = NSOpenGLProfileVersion3_2Core;
attribs[cnt++] = NSOpenGLPFADoubleBuffer;
attribs[cnt++] = NSOpenGLPFADepthSize;
attribs[cnt++] = (NSOpenGLPixelFormatAttribute)16;
attribs[cnt] = 0;
Q_ASSERT(cnt < Max);
return [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
【讨论】:
欢迎提供解决方案链接,但请确保您的答案在没有它的情况下有用:add context around the link 这样您的其他用户就会知道它是什么以及为什么会出现,然后引用最相关的您链接到的页面的一部分,以防目标页面不可用。 Answers that are little more than a link may be deleted.以上是关于在 OS X 上的 Qt 4.8.6 中更改 QGLWidgets 的 OpenGL 上下文版本的主要内容,如果未能解决你的问题,请参考以下文章
Qt:在 Mac OS X 上更改应用程序 QMenuBar 内容
在最小化到停靠后恢复 Qt 应用程序,使用 OS X 上的停靠快捷方式
SetRootPath 与 QT,Mac OS X 上的 QFileSystemModel