PDA

View Full Version : QWidget::update() and paintGL() slot lost.



Paradox
29th June 2013, 11:50
Hi

I've noticed a strange behaviour in my application and I'm not able to understand if this is my implementation problem or not and who I can resolve this problem.

I'm using Kubuntu 12.10 with QT 4.8.2 from repositories packages.

The situation is the follows:

I have a widget which extends QGLWidget. I make some graphics operations and when I done I call the QWidget::update() to force an override paintGL() slot to repaint the widget. At random times, happens that the QWidget::update() DON'T calls the paintGL(), so, there is not 1:1 correspondance between update() and paintGL() slot.

In general this can't be a problem, but in my case I use a semaphore release inside the paintGL(): if the paintGL() is lost, the semaphore release don't comes and my application freezes. I have to use this semaphore because others my application modules have to wait until paintGL() is finished: paintGL() have to work on a graphics shared structure which can't be modified from others component until paintGL() are done, because race-condition (if I don't use the semaphore the application crash because the slot paintGL() can be called when another module works on shared structure).

There is a trick to force 1:1 update() and paintGL(), or there are some advices to engineer this situation in a different and secure way?

Many thanks!

Bye

saman_artorious
29th June 2013, 13:30
Do you have the same problem when you use updateGL() instead of update() ? if yes, plz paste your code.

Paradox
29th June 2013, 13:42
I'll try as soon (I think monday) and let you know, I don't remember if I've already tried the updateGL() directly....

Paradox
1st July 2013, 10:34
hummm...using updateGL() instead of update(), I receive a "QGLContext::makeCurrent(): Failed." and application segfault....

saman_artorious
2nd July 2013, 07:16
hummm...using updateGL() instead of update(), I receive a "QGLContext::makeCurrent(): Failed." and application segfault....

Are you sure you bind the shader program before you render inside paintGL()?

wysota
2nd July 2013, 08:17
update() does not have to call paintGL(). Releasing a semaphore in paintGL() is a really Bad idea. paintGL() is for painting, not for managing resources.

Paradox
3rd July 2013, 17:14
wysota, I agree with you about paintGL(), but in my situation I'm not able to find another way.

Follows me:

I'm using OSG (OpenSceneGraph) which have to call a frame() method to generate a new frame at each time. This frame() must be called inside paintGL(): if I don't call the frame() inside paintGL() there are a lot of errors about openGL, shaders and graphics context.

So, I assume to have to call the frame() only inside the paintGL(). This is the main assumption and can be wrong but for now I have no other idea.

Now, if the 3D OSG scene is static there are no problems! The problems happens when the 3D OSG scene is dynamic and the reason is the next: if we modify the 3D OSG scene WHEN the frame() method running we probably receive a segmentation fault because we can't modify the OSG 3D tree when OSG designs it.

So, I need to implement a methodology to avoid this situation. So, when I have finished to modify the OSG 3D tree, I have to force the paintGL() method to call the frame() method and then return to modify the OSG 3D tree.
If I'm not able to understand when the frame() is finished (this means "when paintGL() is finished") I can't able to procede with 3D tree modifications. This is the reason for the semaphore inside paintGL().

Now, if you understand this situation, I think that the problem is inside the first assumption: we have to don't call the frame() inside paintGL() but I don't understand how.

This is a problem between QT and OSG and is diffult for me to find a solution.

Many thanks for any ideas.

Bye

wysota
3rd July 2013, 17:36
wysota, I agree with you about paintGL(), but in my situation I'm not able to find another way.
You have to find another way :)


I'm using OSG (OpenSceneGraph) which have to call a frame() method to generate a new frame at each time. This frame() must be called inside paintGL(): if I don't call the frame() inside paintGL() there are a lot of errors about openGL, shaders and graphics context.
You have to be aware that not every call to paintGL() should result with a new frame being generated.


So, I assume to have to call the frame() only inside the paintGL().
No. You have to call frame() after you make sure the proper GL context is made current (e.g. by calling makeCurrent() on the context).


Now, if the 3D OSG scene is static there are no problems! The problems happens when the 3D OSG scene is dynamic and the reason is the next: if we modify the 3D OSG scene WHEN the frame() method running we probably receive a segmentation fault because we can't modify the OSG 3D tree when OSG designs it.
Unless you have some worker threads in your code this will never happen.


So, I need to implement a methodology to avoid this situation. So, when I have finished to modify the OSG 3D tree, I have to force the paintGL() method to call the frame() method and then return to modify the OSG 3D tree.
If I'm not able to understand when the frame() is finished (this means "when paintGL() is finished") I can't able to procede with 3D tree modifications. This is the reason for the semaphore inside paintGL().

In general I would render the OSG frame to an FBO and then render that FBO to the target device in Qt's paintGL() (or a regular paintEvent since you don't have to use a GL canvas anymore). This way you can separate the two without any problems (provided that your hardware supports FBOs -- every modern hardware does). Apart from that your OSG engine should only modify the graph when you tell it to and not when it feels like doing so thus you should have total control over what happens when without any mutexes.