I created a QML application based on Qt 5.2
that I deploy on Mac OS X and Windows (from XP to 8). My application has one main animation which rotates an image indefinitely while the user is live on air. This animation is a core part of the application and I cannot remove it.
Rotating the image takes too much CPU power and I am looking for a way to fix this. The reason behind it is that lots of users are not supporting OpenGL 2 (on Windows) and I will have to rely on MESA's DLL to do the rendering in software, making the application unusable on these machines while the animation is running.
Here is my current implementation of the Animation in QML:
Image {
id: imgBroadcastState
source: "images/broadcast_button.png"
anchors.horizontalCenter: parent.horizontalCenter
NumberAnimation on rotation {
from: 0
to: 360
running: rootWindow.isBroadcasting
loops: Animation.Infinite
duration: 7000
onRunningChanged:{
if(!running) {
imgBroadcastState.rotation = 0;
}
}
}
}
The first solution I tried was creating a huge sprite containing all the frames for my animation that I then loaded with AnimatedSprite. This decreased CPU but clearly not enough and more than tripled the RAM consumption, up to 300MB which is not a good solution for old Windows XP machine.
I also tried subclassing QQuickPaintedItem and manually call paint()
every 30ms (with a QTimer
) to rotate the image. This also decreases CPU but not enough either. Here is the code I used:
void MXPaintedItem::paint(QPainter *painter)
{
QTransform rot;
rot.rotate(m_angle);
painter->setRenderHint(QPainter::Antialiasing);
painter->setRenderHint(QPainter::SmoothPixmapTransform);
painter->translate(width() / 2, height() / 2);
painter->rotate(m_angle);
// Use preloaded QImage
painter->drawImage(QPoint(-width() / 2, -height() / 2), m_image);
m_angle += 2.5;
}
Is there any way to improve on this and decrease the CPU usage of rotation animations?
EDIT:
Of course I could change the animation or not use one but this is not a long term solution. In the end this image will have to be drawn/updated dynamically to reflect a VUMeter and represent the sound level. So I need to find a proper solution allowing me to update part of a QML view in real-time without having to redraw the whole UI and take so much CPU.
EDIT2:
I've discovered that the main CPU usage is not the rotation itself but the fact that it then has to redraw the whole UI everytime. You can make sure of this by just calling return
in the paint()
function instead of rotating anything. The CPU usage is the same doing this compared to animating the image itself which shows that the issue comes from updating the whole UI everytime one of the QML components in the scene is updated