I am trying to make QML component that would live output and scale image 2000x2000@60 fps.
I ended up with custom QQuickItem as QQuickImageProvider seems to be designed for other purposes and QQuickPaintedItem did not gave me performance desidered.
So I have:
MyQuickItem.cpp
MyQuickItem::MyQuickItem(QQuickItem *parent)
: QQuickItem(parent)
{
setFlag(ItemHasContents, true);
}
void MyQuickItem::setImage(QImage image)
{
if (!image.isNull()) {
currentImg = image;
update();
}
}
QSGNode* MyQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
{
QSGImageNode * node;
if (!oldNode) {
node = window()->createImageNode();
oldNode = node;
} else {
node = static_cast<QSGImageNode *>(oldNode);
}
QSGTexture *texture = window()->createTextureFromImage(currentImg);
node->setRect(boundingRect());
node->setSourceRect(QRectF(QPointF(0.0, 0.0), texture->textureSize()));
node->setTexture(texture);
node->setOwnsTexture(true);
return node;
}
Registring this as
qmlRegisterType<MyQuickItem>("MyItem", 1, 0, "MyItem");
QQmlComponent* component = new QQmlComponent(engine, ":/test.qml");
MyQuickItem* myItem = quickItem->findChild<MyQuickItem*>("myItem");
if (myItem ) {
connect(this, &ImageGenerator::newFrame, radarItem, &MyQuickItem::setImage);
}
and creating in QML:
import MyItem1.0
import QtQuick 2.3
Item {
MyItem{
id: myImage
objectName: "myItem"
visible: true
anchors.fill: parent
anchors.centerIn: parent
}
Rectangle {
id: boundingRect
border.color: "blue"
border.width: 3
color: "transparent"
anchors.fill: parent
}
anchors.fill: parent
}
I've got this working. ImageGenerator generates 2000x2000 QImage and sends it to MyItem that is MyQuickItem.
And it is still very slow. It consumes approx 30% of i5-4460 and "freezes" other UI components.
Investigation:
Changing QSGImageNode to QSGRectangleNode with solid color, but still doing
QSGTexture *texture = window()->createTextureFromImage(currentImg);
decrease CPU usage down to 1-3%.
But as soon as I add
texture->bind();
hello 30% CPU again.
So, one problem is that 2000x2000 image is too slow to be uploaded to GPU.
On the other hand
QSGTexture *texture = window()->createTextureFromImage(currentImg.scaled(boundingRect().size().toSize()));
without and with bind() gives same 30% CPU.
other problem is that scaling 2000x2000 to fit QML component size on CPU is too slow.
Any possibility to decrese this disgusting CPU consumption?
P.S. I can not generate QImage with other size but can use poiner to buffer to generate image to.
Originally this image generator was used on QWidget and there were no such problems: QImage was created 2000x2000 and set as image to QWidget. Same CPU consumption was like 2-3%.