Render loops and timers in QtQuick

Recently I was testing one of my Qt Quick applications on a virtual machine and I noticed that the busy indicator which is displayed at startup was spinning much faster than it should. I quickly found the reason of the problem: QTBUG-42699. Luckily, there is a simple workaround. You just have to put the following lines near the top of your main() function:

#ifdef Q_OS_WIN
    qputenv( "QSG_RENDER_LOOP", "basic" );

So what the hell is a render loop? All you should ever need to know is that it's something that makes your Qt Quick application work. This article mentions two types of render loops: threaded and non-threaded, but in reality there are three types: threaded, basic and windows. I have no idea what is the difference between the basic one and the windows one (they are both non-threaded), and why the third type is called "windows". It's definitely not specific to the Windows platform, except that it's used on Windows by default. However, I also noticed that switching to the "threaded" render loop made the busy indicator… spin even faster, so I decided to dig a bit deeper into this problem.

I took the sample project attached to QTBUG-42699 and added a third button which enables or disables a BusyIndicator control placed in the main window. The results are quite strange:

  • On the physical machine (with Windows 8) with the "windows" render loop, the problem occurs when only the custom animation is enabled.
  • On the virtual machine (with Windows 7 running on VirtualBox) with the "windows" render loop, the problem occurs when the custom animation and/or the BusyIndicator is enabled.
  • On the same virtual machine with the "threaded" render loop, the custom animation works fine, but the SequentialAnimation and the BusyIndicator are broken.

In other words, only the "basic" render loop seems to work reliably, and both the "windows" and the "threaded" ones cause various problems depending both on the environment and the types of timers that are used by the application. It's definitely not a good sign that bugs like that not only slip into an official release of Qt, but also remain unresolved for months. The busy indicator is just a relatively harmless example, but just imagine what happens if all the objects in your game start moving three times too fast. Apparently there are plans to use the threaded render loop by default on Windows in Qt 5.5, and I hope that it will eventually be fixed before that version is released.

The important lesson is that if I didn't test my application in multiple environments, I wouldn't even discover this problem, because the busy indicator seems to work fine on the machine that I use for development. I realize that making such complex thing as Qt work reliably on so many different plaftorms and configurations must be very hard, but that's exactly one of the main reasons why developers use a toolkit like Qt!

Filed under: Blog