在 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 内容

Mac OS X 上的 Qt 库和源代码安装在哪里?

在最小化到停靠后恢复 Qt 应用程序,使用 OS X 上的停靠快捷方式

SetRootPath 与 QT,Mac OS X 上的 QFileSystemModel

如何在 OS X 上的 Qt 应用程序中设置应用程序图标,足以分发?

Mac OS X 上的 Qt4Dotnet