August 18, 2011

mickaelP mickaelP
Lab Rat
6 posts

QGraphicsView with OpenGL backend

 

Hi,

I’m using a QGraphicsView to display QML items with OpenGL backend because in my case it’s faster than raster.
The application window is made translucent with :

  1.     DwmExtendFrameIntoClientArea(hwnd, &margins);
  2.  
  3.     QPalette p;
  4.  
  5.     p.setColor( QPalette::Base, Qt::transparent);
  6.     setPalette(p);
  7.     setAttribute(Qt::WA_TranslucentBackground ,true );

which works, but it seems the OpenGL buffer is not cleared properly on QML item state changes (different states are visible at the same time).

To get around this I reimplemented the GraphicsView drawBackground to manually clear the background like this :

  1. void FigureEditor::drawBackground ( QPainter * painter, const QRectF & rect )
  2. {
  3.     HDC hDC = GetDC(parentWidget()->winId());
  4.     HGLRC hRC = wglGetCurrentContext();
  5.  
  6.     wglMakeCurrent( hDC, hRC );
  7.  
  8.     QColor clearColor = paletteBackgroundColor();
  9.     glClearColor(clearColor.red(),clearColor.green(),clearColor.blue(),clearColor.alpha());
  10.     glClear(GL_COLOR_BUFFER_BIT);
  11.  
  12.     qDebug() << "clear background :" << rect;
  13.     QGraphicsView::drawBackground(painter, rect);
  14. }

where FigureEditor is a QGraphicsView, but items don’t repaint where it seems they should :

This a test case :

Clicking on the topmost square change it to blue and move it :

And leaves a hole when going back to first state:

I don’t get how the QML items are painted after states changes.
Do anybody know how to solve this problem.

Sorry for the lenghty post.

Mickael

[EDIT: fixed image links, Volker]

13 replies

August 18, 2011

VitorAMJ VitorAMJ
Lab Rat
89 posts

Did you try to clear the depth buffer also?

  1. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Regards,
VitorAMJ

August 18, 2011

mickaelP mickaelP
Lab Rat
6 posts

Thanks for the suggestion. I tried that but it doesn’t help. Changing states still produce holes.

One solution could be to force a full repaint every state changes but I think it could be expensive on the real application.

Mickael

August 18, 2011

VitorAMJ VitorAMJ
Lab Rat
89 posts

Did you enabled the GL_DEPTH_TEST?

August 18, 2011

VitorAMJ VitorAMJ
Lab Rat
89 posts

Check this page [doc.qt.nokia.com] also

August 18, 2011

VitorAMJ VitorAMJ
Lab Rat
89 posts

Maybe its not related, but there is also these [stackoverflow.com] clues

August 19, 2011

mickaelP mickaelP
Lab Rat
6 posts

Actually, I think QGraphicsView is not supposed to clear the entire screen on each paint event because it only paints portion of the screen beeing updated. By using glclear it breaks its way of painting and do not know it should repaint all objects and so leaves holes. This can be solved by setting :

  1. setViewportUpdateMode(QGraphicsView::FullViewportUpdate);

Finally, I think the real issue is how to clear updated regions with a transparent OpenGL background.

August 19, 2011

VitorAMJ VitorAMJ
Lab Rat
89 posts

Your problem, as the image shows, seems to be some sort of Z fight.
It is in fact panting the background (last image), but missing who comes first or something on that area of wrongly blue background.

Can you provide your code so that I can play with it?

Thanks,
VitorAMJ

August 22, 2011

mickaelP mickaelP
Lab Rat
6 posts

Thanks for your help.

You can download my test case here : http://www.megaupload.com/?d=51WDQWF1
Actualy, it’s a slight modification of the ported canvas example from QT SDK.
You’ll need at least windows vista to run it.

August 22, 2011

VitorAMJ VitorAMJ
Lab Rat
89 posts

That’s just bad. Same happening to me…

As you noticed, the behavior of the program changes when you change from

  1.     QApplication::setGraphicsSystem("opengl");

to
  1.     QApplication::setGraphicsSystem("raster");

This points to a bug. You can use JIRA to report it.

As you also point out, here the error also vanishes when setting

  1.     setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
at the cost of updating everything.

I have tried several things, that you probably have also tried. I have set a QGLWidget to the viewport of the GraphicsScene using:

  1.     QApplication::setGraphicsSystem("raster");

+
  1. setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));

But then there is no cool background anymore. Not supported, it seems.

I have tried to add states to the qml to force the updates of the rectangles, but it doesn’t work either.

I am trying some more stuff to get around the bug later,

Regards,
VitorAMJ

August 23, 2011

mickaelP mickaelP
Lab Rat
6 posts

Yes, it seems there is no clean solution to this issue.

Thanks anyway for trying.

Regards,
Mickael

August 24, 2011

VitorAMJ VitorAMJ
Lab Rat
89 posts

Mistery resolved, it is a known bug [developer.qt.nokia.com].
The bug was reported here [bugreports.qt.nokia.com]

August 24, 2011

mickaelP mickaelP
Lab Rat
6 posts

Well, I guess I’ll use the glClear + fullViewportUpdate option.

August 24, 2011

VitorAMJ VitorAMJ
Lab Rat
89 posts

if you have a not that complex scene (like few rectangle areas) raster might be an option. Otherwise (non-rectangular areas, rotated rectangles, and other stuff), OpenGL can be faster.

I hope they can solve this bug fast and with a good rendering solution. But I honestly don’t believe that it will be much faster ( maybe even not faster) than your workaround. That because if they change only parts of the screen, the bootleneck will still be in the driver sending stuff and possible context changes (considering that the user has a somewhat good GPU).

Let’s wait and see!

Regards,
VitorAMJ

 
  ‹‹ QTabWidget Question      About QScript ››

You must log in to post a reply. Not a member yet? Register here!