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. -
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 falseSeems 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?