PDA

View Full Version : QPainter::end() slow when multiple QGLWidgets visible



cbamber85
4th November 2012, 11:38
Hi all,

In my MDI sub-window GUI I have two tabs: in one tab is a single large QGLWidget derived class, and in the other four QGLWidgets separated by splitters. They each have their own OpenGL contexts (for the actual painting), share another across all 5 (for geometry data), and share one application-wide (for shaders).

When drawing in the single viewport tab, it's very fast as expected; but when drawing in the quad view (each viewport is updated from a timer in creation order), the rendering speed plummets and gets worse with each viewport as the list is iterated through.

I began to profile and narrowed down the search to a Qt call that was taking so much longer in quad view than single view:


QPainter::end();
So when only the large single viewport is visible, I get QPainter::end() timings (in microseconds) like this:


Total time(us): 981
Number of calls: 32
Average call time(us): 30.656250
Quite reasonable. But when I switch to the quad view:


Viewport 1:
Total time(us): 196023
Number of calls: 32
Average call time(us): 6125.718750

Viewport 2:
Total time(us): 509769
Number of calls: 32
Average call time(us): 15930.281250

Viewport 3:
Total time(us): 518504
Number of calls: 32
Average call time(us): 16203.250000

Viewport 4:
Total time(us): 518226
Number of calls: 32
Average call time(us): 16194.562500
Vastly longer for what is supposed to be the same amount of work. Even stranger, is that it increases 200x(!), and then 2.5x for the next viewport before stabilising. If I run the tests for longer they give almost exactly the same readings - it doesn't increase any further.

The QPainter code in question is simply:


QPainter p;
p.begin( this );
p.beginNativePainting();
glUseProgram( program_ );

glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, buffer2d_->texture() );
glActiveTexture( GL_TEXTURE1 );
glBindTexture( GL_TEXTURE_2D, buffer3d_->texture() );

surfaceBuf_.bind();
glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
surfaceBuf_.unbind();

p.endNativePainting();
p.end();
I browsed through the source code of the QPainter::end() and QOpenGLPaintEngine::end(), but it just seems to be state reversion and making sure the draw queue has been flushed. Considering I don't set any state requests, or do any drawing through Qt (all my calls are raw OpenGL) - it shouldn't have anything to do.

Why does the time increase even though the QPainter instance is created on the stack, and each viewport is doing the same amount of work?