Fast Timer Updates vs. Monitor Refresh Rates
I need to create a rapidly refreshing widget, updating at around 60Hz.
I have a prototype, and it seems to lag (skip a frame) every 5-20 frames.
I would guess that one of two things is happening:
- The monitor refresh rate of 60Hz is not synchronized with the applications refresh, or
- The widget does not actually update every 6ms
The application is meant to flicker between two gradients rapidly. I have made the paintEvent as simple as possible:
Code:
{
p->begin(this);
if(showingG1)
p->drawPixmap(*rect, *buffer1);
else
p->drawPixmap(*rect, *buffer2);
p->end();
}
A link to the prototype, if it will help (use preset 2 @ 30-60Hz).
How can I make the lag go away? Is there a way to synchronize to the screen's refresh? Or is there a method faster than drawPixmap()? Perhaps having two widgets, then just showing/hiding one of them on every update?
Thanks!
Re: Fast Timer Updates vs. Monitor Refresh Rates
Maybe you have already read this blog post?
http://labs.qt.nokia.com/2010/12/02/...l-scene-graph/
It is about QML but you can take the general guidelines for regular qt widgets too.
I think the idea is to use some of the OpenGL functions to synchronize with the refresh rate of the screen.
Re: Fast Timer Updates vs. Monitor Refresh Rates
I hadn't actually, thank you!
I had begun this using OpenGL but figured I needed double buffering, which requires GLUT, which conflicts with Qt (or so I read), so I had to switch to Qt-native functions to get automatic double buffering.
Looks like I'll be going back to OpenGL and testing out swapBuffers.
Thanks! I'll update this thread on how it goes (for legacy purposes).
-Armin
Re: Fast Timer Updates vs. Monitor Refresh Rates
Hi,
I switched over to a GLWidget, but OpenGl gives the same results. So I tested out the function noted in the link you posted:
Code:
fmt.setSwapInterval(60); // Should update once per second (but updates faster)
this->setFormat(fmt);
But the setSwapInterval seems to have no effect. I tried setting the timerInterval to 0 and that didn't work either.
How do I sync the timer to update with the swapInterval?
Re: Fast Timer Updates vs. Monitor Refresh Rates
It may sound as a dumb question but why do you want to update the widget every 6ms? This gives about 167 frames per second, I can hardly think of a reason why anyone would want so many ui updates per second. Especially with a 60Hz display. I can't even think of a hardware that would be capable of doing as many updates and still be able to provide some data to update the ui with.
Re: Fast Timer Updates vs. Monitor Refresh Rates
Quote:
Originally Posted by
wysota
It may sound as a dumb question but why do you want to update the widget every 6ms? This gives about 167 frames per second, I can hardly think of a reason why anyone would want so many ui updates per second. Especially with a 60Hz display. I can't even think of a hardware that would be capable of doing as many updates and still be able to provide some data to update the ui with.
Haha, silly typo, my bad-
I meant 16ms, or more precisely, 16.666...ms.
I need 60Hz, meaning refresh every time the screen refreshes.
Re: Fast Timer Updates vs. Monitor Refresh Rates
Ok, so how exactly do you force your widget to redraw?
Re: Fast Timer Updates vs. Monitor Refresh Rates
I'm using a QTimer...is there another way, maybe blocking until a vertical sync event? I've tried using swapBuffers but I can't get it to work without a timer.
Re: Fast Timer Updates vs. Monitor Refresh Rates
Quote:
Originally Posted by
artoonie
I'm using a QTimer...
Show us the code.
Re: Fast Timer Updates vs. Monitor Refresh Rates
Quote:
Originally Posted by
artoonie
I would guess that one of two things is happening:
- The monitor refresh rate of 60Hz is not synchronized with the applications refresh, or
- The widget does not actually update every 6ms
Both of these things are happening.
QTimer can be set in whole milliseconds only. Approximating a 1/60 seconds rate with 16 msecs will lead a whole frame difference in time after 24 or 25 frames even if the timer events were perfectly spaced. A 17 msec approximation will extend the sync out to around 48-50 frames. QTimer events are processed when the program returns to the event loop after the time has expired. Depending on what else the program is doing, like rendering your gradient, this might be a significant delay. The combination of the two will lead to a mismatch that is variable with activity.
MythTV can use timers to maintain video refresh sync, but I believe it also has extensive frame counting over relatively long periods to determine the average frame rate and drops/duplicates frames to realign things periodically. The preferred method in MythTV is to use the OpenGL vsync. I don't know how this can be accessed.
Re: Fast Timer Updates vs. Monitor Refresh Rates
Quote:
Originally Posted by
wysota
Quote:
Originally Posted by
artoonie
I'm using a QTimer...QUOTE]
Show us the code.
It's been established that timers are not the way to go, but I'll paste what I have:
Code:
Flickerer
::Flickerer(int timerInterval,
QWidget *parent
) { connect( m_timer, SIGNAL(timeout()), this, SLOT(timeOutSlot()) );
m_timer->start( timerInterval );
}
void Flickerer::timeOutSlot()
{
showingG1 = !showingG1;
updateGL();
}
void Flickerer::paintGL()
{
if(showingG1) /* paints gradient 1 */ else /* paints gradient 2 */
}
Quote:
QTimer can be set in whole milliseconds only. Approximating a 1/60 seconds rate with 16 msecs will lead a whole frame difference in time after 24 or 25 frames even if the timer events were perfectly spaced. A 17 msec approximation will extend the sync out to around 48-50 frames. QTimer events are processed when the program returns to the event loop after the time has expired. Depending on what else the program is doing, like rendering your gradient, this might be a significant delay. The combination of the two will lead to a mismatch that is variable with activity.
MythTV can use timers to maintain video refresh sync, but I believe it also has extensive frame counting over relatively long periods to determine the average frame rate and drops/duplicates frames to realign things periodically. The preferred method in MythTV is to use the OpenGL vsync. I don't know how this can be accessed.
I agree- I need to use OpenGL vsync but I don't know how to get a signal from the display so I'd know when to update.
Thanks you.
Re: Fast Timer Updates vs. Monitor Refresh Rates
You do not need to get the signal from the display. OpenGl has a function that does that for you.
What I would try to do:
Create a graphicsview that contains the user interface. Make it so that everything inside the graphicsview is painted via OpenGl
There are lots of tutorials in the Qt labs and documentation.
And then use the information from the blog post about blocking the eventloop and synchronising the eventloop to the refresh rate of the monitor.
If you use a graphicsview and opengl, the effects possible with your user interface are infinite, although limited to the contents of the graphicsview.
Edit:
Here's a nice example:
http://labs.qt.nokia.com/2008/06/27/...s-with-opengl/
Edit 2:
You need this function:
http://doc.qt.nokia.com/latest/qglfo...etSwapInterval
Set it to 1
Tip:
QML does this out of the box. It's worth studying the code.
Re: Fast Timer Updates vs. Monitor Refresh Rates
[Deleted...]
Added after 59 minutes:
I've narrowed my problems down to here:
Code:
fmt.setSwapInterval(1);
w->setFormat(fmt);
qDebug("Swap interval: %d", fmt.swapInterval()); // Prints 1
qDebug("Swap interval: %d", w->format().swapInterval()); // Prints -1
Why is the swap interval not being accepted by the widget? Or am I doing something else wrong here?
--Update--
Okay, this is odd. The docs have a format() method, but the setFormat() method (which is linked from the format() description) does not exist, even in the list of all members.
Re: Fast Timer Updates vs. Monitor Refresh Rates
And this code was compiling? There is a constructor to QGLWidget that takes a format parameter.
Re: Fast Timer Updates vs. Monitor Refresh Rates
Both ways are equivalent. I get the same behavior with
Code:
fmt.setSwapInterval(1);
Also, quote from here:
Quote:
Returns the currently set swap interval. -1 is returned if setting the swap interval isn't supported in the system GL implementation.
Possibly it's just my system?
Re: Fast Timer Updates vs. Monitor Refresh Rates
Quote:
Originally Posted by
artoonie
Possibly it's just my system?
Hard to believe that unless you have some really broken OpenGL implementation.
Check for this:
Quote:
Under Windows the WGL_EXT_swap_control extension has to be present, and under X11 the GLX_SGI_video_sync extension has to be present.
Re: Fast Timer Updates vs. Monitor Refresh Rates
...looks like that's my problem? My hardware supports OpenGL 1.1 and 10% of OpenGL 1.2. WGL_SWAP_LAYER_BUFFERS_ARB is set to false and WGL_EXT_SWAP_CONTROL is grayed out on the OpenGL Extensions Viewer.
Guess I'll be testing it elsewhere and let you know.
Re: Fast Timer Updates vs. Monitor Refresh Rates
So that turned out to be the problem- perhaps vertex and fragment shaders are also needed?
I'm using a different computer and I get a message saying the shaders are linked.
HOWEVER, it still isn't updating without a QTimer...I do remove tearing with fmt->setSwapInterval(1) (whereas tearing is horrid with that line commented out). Is this the expected behavior?
Re: Fast Timer Updates vs. Monitor Refresh Rates
Quote:
Originally Posted by
artoonie
HOWEVER, it still isn't updating without a QTimer...
Why would it? Read what the swap interval does. It doesn't cause any periodic updates.
Re: Fast Timer Updates vs. Monitor Refresh Rates
Right, right, I naively assumed some magic might happen without a timer.
Thank you so much for your help, I really appreciate it.
-Armin