Failed to set an OpenGL version to 2.1 for Desktop
-
Hi,
I try to set an OpenGL version to 2.1 but the next example prints this result on my laptop:
OpenGL version: 3.1.0 - Build 9.17.10.4459 GLSL version: 1.40 - Intel Build 9.17.10.4459 Vendor: Intel
main.cpp
#include <QtGui/QOpenGLFunctions> #include <QtGui/QSurfaceFormat> #include <QtOpenGLWidgets/QOpenGLWidget> #include <QtWidgets/QApplication> class OpenGLWidget : public QOpenGLWidget, private QOpenGLFunctions { public: OpenGLWidget() { QSurfaceFormat surfaceFormat; surfaceFormat.setMajorVersion(2); surfaceFormat.setMinorVersion(1); setFormat(surfaceFormat); } private: void initializeGL() override { initializeOpenGLFunctions(); glClearColor(0.f, 1.f, 0.f, 1.f); qDebug() << "OpenGL version:" << (const char*) glGetString(GL_VERSION); qDebug() << "GLSL version:" << (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION); qDebug() << "Vendor:" << (const char*) glGetString(GL_VENDOR); } void paintGL() override { glClear(GL_COLOR_BUFFER_BIT); } }; int main(int argc, char *argv[]) { QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL); QApplication a(argc, argv); OpenGLWidget w; w.show(); return a.exec(); }
pro
QT += core gui openglwidgets widgets win32: LIBS += -lopengl32 CONFIG += c++17 SOURCES += \ main.cpp TARGET = app
I can activate the second video card (the discrete one) by adding this code on the top of the main.cpp file. The first line is for GeForce and the second one is for Radeon:
#ifdef _WIN32 #include <windows.h> extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; extern "C" __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001; #endif
The output is:
OpenGL version: 4.6.0 NVIDIA 391.35 GLSL version: 4.60 NVIDIA Vendor: NVIDIA Corporation
But I can set 3.0, 3.1, 3.2, and so on. For example:
QSurfaceFormat surfaceFormat; surfaceFormat.setMajorVersion(3); surfaceFormat.setMinorVersion(3); setFormat(surfaceFormat);
OpenGL version: 3.3.0 NVIDIA 391.35 GLSL version: 3.30 NVIDIA via Cg compiler Vendor: NVIDIA Corporation
Another question is: what is the strange version when I comment this line of code:
int main(int argc, char *argv[]) { // QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
OpenGL version: 3.0 Mesa 11.2.2 GLSL version: 1.30 Vendor: VMware, Inc.
-
Hi,
I try to set an OpenGL version to 2.1 but the next example prints this result on my laptop:
OpenGL version: 3.1.0 - Build 9.17.10.4459 GLSL version: 1.40 - Intel Build 9.17.10.4459 Vendor: Intel
main.cpp
#include <QtGui/QOpenGLFunctions> #include <QtGui/QSurfaceFormat> #include <QtOpenGLWidgets/QOpenGLWidget> #include <QtWidgets/QApplication> class OpenGLWidget : public QOpenGLWidget, private QOpenGLFunctions { public: OpenGLWidget() { QSurfaceFormat surfaceFormat; surfaceFormat.setMajorVersion(2); surfaceFormat.setMinorVersion(1); setFormat(surfaceFormat); } private: void initializeGL() override { initializeOpenGLFunctions(); glClearColor(0.f, 1.f, 0.f, 1.f); qDebug() << "OpenGL version:" << (const char*) glGetString(GL_VERSION); qDebug() << "GLSL version:" << (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION); qDebug() << "Vendor:" << (const char*) glGetString(GL_VENDOR); } void paintGL() override { glClear(GL_COLOR_BUFFER_BIT); } }; int main(int argc, char *argv[]) { QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL); QApplication a(argc, argv); OpenGLWidget w; w.show(); return a.exec(); }
pro
QT += core gui openglwidgets widgets win32: LIBS += -lopengl32 CONFIG += c++17 SOURCES += \ main.cpp TARGET = app
I can activate the second video card (the discrete one) by adding this code on the top of the main.cpp file. The first line is for GeForce and the second one is for Radeon:
#ifdef _WIN32 #include <windows.h> extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; extern "C" __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001; #endif
The output is:
OpenGL version: 4.6.0 NVIDIA 391.35 GLSL version: 4.60 NVIDIA Vendor: NVIDIA Corporation
But I can set 3.0, 3.1, 3.2, and so on. For example:
QSurfaceFormat surfaceFormat; surfaceFormat.setMajorVersion(3); surfaceFormat.setMinorVersion(3); setFormat(surfaceFormat);
OpenGL version: 3.3.0 NVIDIA 391.35 GLSL version: 3.30 NVIDIA via Cg compiler Vendor: NVIDIA Corporation
Another question is: what is the strange version when I comment this line of code:
int main(int argc, char *argv[]) { // QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
OpenGL version: 3.0 Mesa 11.2.2 GLSL version: 1.30 Vendor: VMware, Inc.
TL;DR - It's stupid but correct.
A longer version and a bit of a history of OpenGL:
Up to 2.1 OpenGL was additive and backward compatible. On Windows you used
wglCreateContext
and you got the highest the driver supported. Good times.3.0 introduced deprecation, meaning old stuff could be removed, so that simple model no longer worked. What they came up with was a WGL extension -
WGL_ARB_create_context
- it introducedwglCreateContextAttribsARB
to specify which version you want. Because it's an extension you first had to have a valid context to get the extension from it. So you create a dummy context just to see if you can get the function to create the higher context. Silly workaround but ok. Nothing was removed at this point yet.3.1 actually removed stuff, but people wanted both the old and the new stuff, so what they came up with was another extension
GL_ARB_compatibility
. Pure 3.1 would only be the new stuff and the old removed stuff was brought back as an extension. Even sillier, but ok.3.2 couldn't go on like this. Some people wanted the new lean stuff without the old crud, so what they came up with was profiles: the Core profile would be the new stuff and Compatibility profile would be the new stuff but with that
GL_ARB_compatibility
extension, bringing back the old stuff too. The profile thing continues on up to 4.6, which was the last released spec.So what you get is correct.
This gives you a Core 3.2 profile:surfaceFormat.setProfile(QSurfaceFormat::CoreProfile); surfaceFormat.setVersion(3, 2);
This gives you a Compatibility 3.2 profile:
surfaceFormat.setProfile(QSurfaceFormat::CompatibilityProfile); surfaceFormat.setVersion(3, 2);
This gives you 3.1 without the back compat extension:
surfaceFormat.setProfile(QSurfaceFormat::NoProfile); surfaceFormat.setOption(QSurfaceFormat::DeprecatedFunctions, false); surfaceFormat.setVersion(3, 1);
This gives you 3.1 with back compat extension:
surfaceFormat.setProfile(QSurfaceFormat::NoProfile); surfaceFormat.setOption(QSurfaceFormat::DeprecatedFunctions, true); surfaceFormat.setVersion(3, 1);
This gives you 3.0:
surfaceFormat.setProfile(QSurfaceFormat::NoProfile); surfaceFormat.setVersion(3, 0);
Anything below version 3.0 will revert back to the old behavior - it will give you the highest supported version that is compatible i.e. either 3.0, 3.1 with that back compat extension or 3.2 and higher in Compatibility profile.
In your case when requesting for 2.1 you get 3.1 with back compat extension on integrated Intel chip, 4.6 Compatibility profile on discrete NVIDIA gpu and 3.0 on MESA software driver.
Another question is: what is the strange version when I comment this line of code:
Qt supports multiple implementations of OpenGL - either provided by the driver, via ANGLE (OpenGL -> DirectX translation layer) or by software MESA library.
AA_UseDesktopOpenGL
means the hardware driver will be chosen if possible, otherwise you're getting the MESA software driver. -
8 8Observer8 has marked this topic as solved on
-
Thanks a lot for detailed explanation!
I rewrote my example to show OpenGL version on the window. I was build from one code base for Desktop, Redmi 4X, and Android Emulator:
Window 10:
Android on the physical device Redmi 4X. The device is connected by USB. It is faster way to run and debug than to run on Emulator. I use scrcpy to show a screen of device on laptop:
Android Emulator:
main.cpp
// #ifdef _WIN32 // #include <windows.h> // extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; // extern "C" __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001; // #endif #include <QtGui/QOpenGLFunctions> #include <QtGui/QSurfaceFormat> #include <QtOpenGLWidgets/QOpenGLWidget> #include <QtWidgets/QApplication> #include <QtWidgets/QLabel> #include <QtWidgets/QVBoxLayout> #include <QtWidgets/QWidget> class OpenGLWidget : public QOpenGLWidget, private QOpenGLFunctions { Q_OBJECT signals: void showInfoSignal(const QString &openGLVersion, const QString &shadingVersion, const QString &vendor); private: void initializeGL() override { initializeOpenGLFunctions(); glClearColor(0.f, 1.f, 0.f, 1.f); QString version(QString("OpenGL version: %1").arg((const char*) glGetString(GL_VERSION))); QString shadingLanguageVersion(QString("GLSL version: %1").arg((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION))); QString vendor(QString("Vendor: %1").arg((const char*) glGetString(GL_VENDOR))); emit showInfoSignal(version, shadingLanguageVersion, vendor); } void paintGL() override { glClear(GL_COLOR_BUFFER_BIT); } }; class MainWindow : public QWidget { Q_OBJECT public: MainWindow() { setWindowTitle("OpenGL Version"); resize(300, 300); m_openGLVersionLabel = new QLabel(); m_shadingLanguageVersionLabel = new QLabel(); m_vendorLabel = new QLabel(); OpenGLWidget *openGLWidget = new OpenGLWidget(); m_openGLVersionLabel->setSizePolicy(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed); m_shadingLanguageVersionLabel->setSizePolicy(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed); m_vendorLabel->setSizePolicy(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed); QVBoxLayout *layout = new QVBoxLayout(); layout->addWidget(m_openGLVersionLabel); layout->addWidget(m_shadingLanguageVersionLabel); layout->addWidget(m_vendorLabel); layout->addWidget(openGLWidget); setLayout(layout); connect(openGLWidget, &OpenGLWidget::showInfoSignal, this, &MainWindow::showInfoSlot); } private slots: void showInfoSlot(const QString &openGLVersion, const QString &shadingVersion, const QString &vendor) { m_openGLVersionLabel->setText(openGLVersion); m_shadingLanguageVersionLabel->setText(shadingVersion); m_vendorLabel->setText(vendor); } private: QLabel *m_openGLVersionLabel; QLabel *m_shadingLanguageVersionLabel; QLabel *m_vendorLabel; }; #include "main.moc" int main(int argc, char *argv[]) { // QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL); QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
pro
QT += core gui openglwidgets widgets win32: LIBS += -lopengl32 CONFIG += c++17 SOURCES += \ main.cpp TARGET = app