如何在具有共享 OpenGL 上下文的 Qt 应用程序中有条件地指定 OpenGL ES 版本?

How do I conditionally specify OpenGL ES version in a Qt application with shared OpenGL contexts?

hellogles3 sample 在测试桌面 OpenGL 之前构建 QGuiApplication。如果您不这样做,那么 QOpenGLContext::openGLModuleType() 会崩溃。

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QSurfaceFormat fmt;
    fmt.setDepthBufferSize(24);

    // Request OpenGL 3.3 core or OpenGL ES 3.0.
    if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
        qDebug("Requesting 3.3 core context");
        fmt.setVersion(3, 3);
        fmt.setProfile(QSurfaceFormat::CoreProfile);
    } else {
        qDebug("Requesting 3.0 context");
        fmt.setVersion(3, 0);
    }

    QSurfaceFormat::setDefaultFormat(fmt);

    GLWindow glWindow;
    glWindow.showMaximized();

    return app.exec();
}

但是,如果您正在使用 Qt::AA_ShareOpenGLContexts,那么 QSurfaceFormat::setDefaultFormat 必须在 之前 构造 QGuiApplication:

Note: When setting Qt::AA_ShareOpenGLContexts, it is strongly recommended to place the call to this function before the construction of the QGuiApplication or QApplication. Otherwise format will not be applied to the global share context and therefore issues may arise with context sharing afterwards.

尝试在独立 QOpenGLContext 实例上调用创建以在构建 QGuiApplication 之前测试 OpenGL 类型也会崩溃,因为 QGuiApplicationPrivate::platformIntegration() 尚未创建。

有什么解决办法吗?

为检查实例化一个临时 QGuiApplication 似乎是安全的。例如:

int main(int argc, char *argv[])
{
    {
        QGuiApplication tempapp(argc, argv);

        QSurfaceFormat fmt;
        fmt.setDepthBufferSize(24);

        // Request OpenGL 3.3 core or OpenGL ES 3.0.
        if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
            qDebug("Requesting 3.3 core context");
            fmt.setVersion(3, 3);
            fmt.setProfile(QSurfaceFormat::CoreProfile);
        } else {
            qDebug("Requesting 3.0 context");
            fmt.setVersion(3, 0);
        }

        QSurfaceFormat::setDefaultFormat(fmt);
    }
    QCoreApplication::setAttribute( Qt::AA_ShareOpenGLContexts );
    
    QGuiApplication app(argc, argv);

    GLWindow glWindow;
    glWindow.showMaximized();

    return app.exec();
}

注意:我的特定用例需要在 Windows 中为远程桌面回退到 OpenGL ES。但是,现在桌面 OpenGL 在 Windows 10 中通过 RDP 工作似乎没那么必要了,这显然是由于 WDDM 中的更新。不过,可能还有其他情况会受益于此检查。