Search code examples
c++qtopengl-esopengl-es-3.0

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


The hellogles3 sample constructs the QGuiApplication before testing for desktop OpenGL. If you don't do this then QOpenGLContext::openGLModuleType() crashes.

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();
}

However, if you are using Qt::AA_ShareOpenGLContexts, then QSurfaceFormat::setDefaultFormat must be called before constructing 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.

Attempting to call create on a standalone QOpenGLContext instance to test OpenGL type before constructing QGuiApplication also crashes, because QGuiApplicationPrivate::platformIntegration() has not been created yet.

Is there any way around this?


Solution

  • It appears to be safe to instantiate a temporary QGuiApplication for the check. For example:

    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();
    }
    

    Note: my particular use case needed the fallback to OpenGL ES for remote desktop in Windows. However, this seems to be less necessary now that desktop OpenGL works over RDP in Windows 10, apparently due to updates in WDDM. There may be other cases that benefit from this check though.