QGLWidget and Threads [SOLVED]



  • Hi there,

    I just googled my problem but I cannot find exactly what i want.

    Description:

    I have a class deriving from QGLWidget which handles user inputs and is responsible for drawing my scene.
    I overloaded the paintGL() method and let it send a signal:
    @void MyWidget::paintGL()
    {
    emit sigReadyPaint(); //that's all
    }@

    The signal will be received by a Worker object which has been moved to another thread.
    This worker just recieves the sigReadyPaint() signal from MyWidget and simply calls the startFrame() method of MyWidget like so:
    @void MyWorker::slotReadyPaint()
    {
    if(_widget != NULL) //_widget (MyWidget) is a private member of MyWorker
    {
    _widget->makeCurrent();
    _widget->startFrame();
    }
    }

    void MyWidget::init()
    {
    if(!_initialized) //_initialized (bool) is a private member of MyWidget and is false by default
    {
    QGLShaderProgram* shader= new QGLShaderProgram(); //shader (QGLShaderProgram) is a private member of MyWidget

    //the following lines are causing the "Shaders are not supported" error. But only if i call it from a thread!!
    if(!shader->addShaderFromSourceFile(QGLShader::Vertex, "myVertexShaderFile"))
    {
    cout<<"Failed to compile vertex shader!"<<endl;
    return;
    }

    if(!shader->addShaderFromSourceFile(QGLShader::Fragment, "myFragmentShaderFile"))
    {
    cout<<"Failed to compile fragment shader!"<<endl;
    return;
    }

    if(!shaderProgram->link())
    {
    cout<<"Failed to link shader!"<<endl;
    return;
    }

    vertex = shader->attributeLocation("vertex"); //vertex(int) is a private member of MyWidget

    _initialized = true;
    }
    }

    void MyWidget::startFrame()
    {
    init();

    shader->enableAttributeArray(vertex); //crash(segmentation fault) in this line

    //....
    }
    @

    Now when I reach the line shader->enableAttributeArray(vertex) I get a segmentation fault.
    If i do not move my worker to a thread it all works fine! And it works also fine if i set the SIGNAL/SLOT connection type to Qt::DirectConnection which is not what i need, because it is not asynchronous.

    I know that QGLContext is not thread safe (as OpenGL isn't) but I have only ONE THREAD executing openGL commands and shader commands!

    Thanks in advance

    [EDIT: I updated my last sentences because that statement was wrong. My Qt didn't really build my changes. Now it describes the real situation as it is.]



  • makeCurrent() is not the problem, because when i call it i get the following message from Qt:
    QGLContext::makeCurrent() : wglMakeCurrent failed: The requested resource is aleary in use (translated)
    Which means that my widget is already the current, i guess.



  • Hello Seraph !

    Why do You initialize shader to 0 ?



  • I'm sorry. I usually wanted to add a //.... comment between line 14 and 15.

    I edited the code



  • OK. I now have put all openGL code into my render step. So only the thread is calling them.
    I now get the following error:

    QGLShaderProgram: shader programs are not supported
    (Internal error: pc 0x0 in read in psymtab, but not in symtab.)
    (Internal error: pc 0x0 in read in psymtab, but not in symtab.)
    (Internal error: pc 0x0 in read in psymtab, but not in symtab.)
    (Internal error: pc 0x0 in read in psymtab, but not in symtab.)
    ...
    ...

    The "shader programs are not supported" error happens after calling
    QGLShaderProgram::addShaderFromSourceFile() which returns false

    Seems to me like i get a wrong context. But why is it working without the thread?

    I printed my format version, it is at 4!

    What could cause this error?



  • No idea anybody? Is there no default solution for that?

    I just had a look at this "article ":http://doc.qt.digia.com/qq/qq06-glimpsing.html#writingmultithreadedglapplications which is 10 years old! This cannot be state of the art!

    As far as I understand it is not necessary to create the gl context in a new thread, right?
    Is it necessary to have all open gl commands called by the thread? I don't think so, because only one context can be current at the same time right? And if i call makeCurrent() and execute some openGl commands they will be executed on the (new) current context. If i call it from the thread or not shouldn't be important, right?
    But how can it happen, that i get the error: "Shaders are not supportet" once i move my render worker to a thread?
    If not everything works fine!

    Please can anyone help me out with this?



  • OK i did it like the article said. It is not state of the art but it's working with QT4.8.4

    Thanks.


Log in to reply
 

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