QOpenGLWidget shared context not working



  • Hello,

    I have some problem with sharing context for my second QOpenGLWidget window.
    My project works more than 1 year (was on QGLWidget, migrated on 5.4 release) I had some troubles with it, somehow I solved it, but same tactic is not working on my next window. What I'm trying to do is simple render whole stuff without editing tools etc. Just for preview. Seems QOpenGLShaderProgram is main problematic in my case *"QOpenGLShaderProgram::bind: program is not valid in the current context."

    My QApplication class constructor:
    @Application::Application(int& argc, char** argv)
    : QApplication(argc, argv)
    {
    setAttribute(Qt::AA_ShareOpenGLContexts);

    setOrganizationDomain(QString(VER_COMPANYDOMAIN_STR));
    setOrganizationName(QString(VER_COMPANYNAME_STR));
    setApplicationName(QString(VER_PRODUCTNAME_STR));
    setApplicationVersion(QString(VER_FILEVERSION_STR));
    
    settings = new QSettings(this);
    
    translator = new QTranslator(this);
    translator->load(getSetting("language", QLocale::system().name()).toString(), ":/languages/", QString(), ".qlg");
    
    installTranslator(translator);
    
    qsrand((uint)QTime::currentTime().msec());
    
    mainWindow = new MainWindow();
    mainWindow->showMaximized();
    

    }@

    in mainWindow I set as centralWidget my main QOpenGLWidget called MapView.

    MapView constructor:
    @MapView::MapView(World* mWorld,..., QWidget* parent)
    : QOpenGLWidget(parent)
    , world(mWorld)
    , camera(new Camera(this))
    , ...
    {
    setFocusPolicy(Qt::StrongFocus);
    setMouseTracking(true);

    QSurfaceFormat format;
    format.setDepthBufferSize(24);
    format.setMajorVersion(4);
    format.setMinorVersion(3);
    format.setSamples(4);
    format.setProfile(QSurfaceFormat::CoreProfile);
    
    QSurfaceFormat::setDefaultFormat(format);
    
    camera->setPosition(QVector3D(250.0f, 10.0f, 250.0f));
    camera->setViewCenter(QVector3D(250.0f, 10.0f, 249.0f));
    camera->setUpVector(QVector3D(0.0f, 1.0f, 0.0f));
    
    world->setCamera(camera);
    
    startTimer(16);
    

    }@

    MapView initializeGL:
    @void MapView::initializeGL()
    {
    this->makeCurrent();

    initializeOpenGLFunctions();
    
    QSurfaceFormat format;
    format.setDepthBufferSize(24);
    format.setMajorVersion(4);
    format.setMinorVersion(3);
    format.setSamples(4);
    format.setProfile(QSurfaceFormat::CoreProfile);
    
    this->context()->setFormat(format);
    
    world->initialize(this->context(), size());
    
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    
    glDepthFunc(GL_LEQUAL); // just testing new depth func
    
    glClearColor(0.65f, 0.77f, 1.0f, 1.0f);
    

    }@

    World initialize:
    @void World::initialize(QOpenGLContext* context, QSize fboSize)
    {
    GLfuncs = context->versionFunctions<QOpenGLFunctions_4_2_Core>();

    if(!GLfuncs)
    {
        qFatal(QObject::tr("Requires OpenGL >= 4.2").toLatin1().data());
    
        exit(1);
    }
    
    GLfuncs->initializeOpenGLFunctions();
    
    ....
    

    }@

    and now second QOpenGLWidget (problematic one)
    @MapExplorer::MapExplorer(World* mWorld, QWidget* parent)
    : QOpenGLWidget(parent)
    , world(mWorld)
    , camera(new Camera(this))
    , ...
    {
    setFocusPolicy(Qt::StrongFocus);
    setMouseTracking(true);

    QSurfaceFormat format;
    format.setDepthBufferSize(24);
    format.setMajorVersion(4);
    format.setMinorVersion(3);
    format.setSamples(4);
    format.setProfile&#40;QSurfaceFormat::CoreProfile&#41;;
    
    QSurfaceFormat::setDefaultFormat(format);
    
    camera->setPosition(QVector3D(250.0f, 10.0f, 250.0f));
    camera->setViewCenter(QVector3D(250.0f, 10.0f, 249.0f));
    camera->setUpVector(QVector3D(0.0f, 1.0f, 0.0f));
    
    startTimer(16);
    

    }@

    MapExplorer initializeGL:
    @void MapExplorer::initializeGL()
    {
    this->makeCurrent();

    initializeOpenGLFunctions();
    
    QSurfaceFormat format;
    format.setDepthBufferSize(24);
    format.setMajorVersion(4);
    format.setMinorVersion(3);
    format.setSamples(4);
    format.setProfile&#40;QSurfaceFormat::CoreProfile&#41;;
    
    this->context()->setFormat(format);
    
    qDebug() << (QOpenGLContext::currentContext() == this->context()); // return true
    
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    
    glDepthFunc(GL_LEQUAL); // just testing new depth func
    
    glClearColor(0.65f, 0.77f, 1.0f, 1.0f);
    

    }@

    QOpenGLShaderProgram's are created inside World class, I can't find problem where is my context is not sharing, I didn't find how to set manual created context or how to assign him to second one (take context from first set to second).

    Thanks for any idea!

    Regards, glararan.



  • Do the widgets belong to different top-level windows? In that case set Qt::AA_ShareOpenGLContexts on the QApplication in main().



  • main() create Application app; app.exec();

    Application create main window
    Main window create MapView (QOpenGLWidget) and also MapExplorer (QOpenGLWidget) so they should have same parent (main window) but mapview is central widget of main window and MapExplorer is in second window created from main window by

    @MapExplorer m = new MapExplorer(world, this);
    m.show();@



  • I suppose they are different native windows then. So AA_ShareOpenGLContexts is necessary.



  • It's in Application class constructor (first code in main post) which inherits from QApplication, so where is the problem?

    EDIT: tested with testAttribute, returns true, still not works :/



  • Post bump



  • I get an idea how to solve this. I will use QOpenGLContext for World and call that context->makeCurrent() but makeCurrent need argument QSurface, any idea how to get it from QOpenGLWidget? If I pass mapView->context()->surface() it gets bugged somehow and my QOpenGLFunctions stops working correct, it dont get correct pointer.



  • Hi, once again

    I made progress! Currently main problem is that MapView is just black screen I think its caused by different context.

    I changed mapView->context()->surface() to new QOffscreenSurface for MapView, so its running, I can see FPS counter etc, just not see objects which should be rendered.

    Application class unchanged...

    MapView constructor:
    @MapView::MapView(World* mWorld, QWidget* parent)
    : QOpenGLWidget(parent)
    , world(mWorld)
    , camera(new Camera(this))
    , ...
    {
    setFocusPolicy(Qt::StrongFocus);
    setMouseTracking(true);

    QSurfaceFormat format;
    format.setDepthBufferSize(24);
    format.setMajorVersion(4);
    format.setMinorVersion(3);
    format.setSamples(4);
    format.setProfile&#40;QSurfaceFormat::CoreProfile&#41;;
    format.setOption(QSurfaceFormat::DebugContext&#41;;
    
    QSurfaceFormat::setDefaultFormat(format);
    
    surface = new QOffscreenSurface();
    surface->setFormat(format);
    surface->create();
    
    qDebug() << "surface validation:" << surface->isValid(); // return true
    
    // Initialize the camera position and orientation
    camera->setPosition(QVector3D(250.0f, 10.0f, 250.0f));
    camera->setViewCenter(QVector3D(250.0f, 10.0f, 249.0f));
    camera->setUpVector(QVector3D(0.0f, 1.0f, 0.0f));
    
    // Assign camera to World
    world->setCamera(camera);
    
    startTimer(16);
    

    }@

    MapView intializeGL:
    @void MapView::initializeGL()
    {
    QOpenGLContext* _context = world->getContext();

    qDebug() << _context->makeCurrent(surface); // return true
    qDebug() << _context->isValid() << (QOpenGLContext::currentContext() == _context); // return true true
    
    initializeOpenGLFunctions(); // its still working? or have I call gl funcs from world?
    
    // Initialize World
    world->initialize(/*this->context(),*/ size(), worldCoords);
    
    // Initialize camera shader
    camera->initialize();
    
    // Enable depth testing
    world->getGLFunctions()->glEnable(GL_DEPTH_TEST);
    world->getGLFunctions()->glEnable(GL_CULL_FACE);
    
    world->getGLFunctions()->glDepthFunc(GL_LEQUAL); // just testing new depth func
    
    world->getGLFunctions()->glClearColor(0.65f, 0.77f, 1.0f, 1.0f);
    

    }@

    MapView paintGL: I think there is some problem
    @void MapView::paintGL()
    {
    world->getContext()->makeCurrent(surface);

    world->getGLFunctions()->glDrawBuffer(GL_FRONT);
    world->getGLFunctions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    world->draw(...);
    
    //world->getContext()->swapBuffers(surface); // not working even uncommented
    

    }@

    World initialize:
    @void World::initialize(/QOpenGLContext context,/ QSize fboSize, bool* mapCoords)
    {
    GLfuncs = context->versionFunctions<QOpenGLFunctions_4_2_Core>();

    if(!GLfuncs)
    {
        qDebug() << QObject::tr("Requires OpenGL >= 4.2");
    
        qFatal(QObject::tr("Requires OpenGL >= 4.2").toLatin1().data());
    
        exit(1);
    }
    
    GLfuncs->initializeOpenGLFunctions();
    ...
    

    }@

    I don't know what next to do.

    Thanks for help!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.