Я пытаюсь сделать компонент QML, который будет выводить в реальном времени и масштабировать изображение 2000x2000 при 60 кадрах в секунду.
Я закончил с пользовательским QQuickItem, поскольку QQuickImageProvider, похоже, предназначен для других целей, а QQuickPaintedItem не дал мне желаемой производительности.
Так что я:
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;
}
Зарегистрировать это как
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);
}
и создание в 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
}
У меня это работает. ImageGenerator генерирует QImage 2000x2000 и отправляет его в MyItem, который является MyQuickItem.
И все равно очень медленно. Он потребляет около 30% процессора i5-4460 и «замораживает» другие компоненты пользовательского интерфейса.
Расследование:
Изменение QSGImageNode на QSGRectangleNode со сплошным цветом, но все еще выполняется
QSGTexture *texture = window()->createTextureFromImage(currentImg);
снизить загрузку процессора до 1-3%.
Но как только я добавлю
texture->bind();
привет 30% ЦП снова.
Таким образом, одна проблема заключается в том, что изображение размером 2000x2000 слишком медленно загружается в GPU.
С другой стороны
QSGTexture *texture = window()->createTextureFromImage(currentImg.scaled(boundingRect().size().toSize()));
без и с bind() дает одинаковые 30% ЦП.
другая проблема заключается в том, что масштабирование 2000 x 2000 для соответствия размеру компонента QML на ЦП выполняется слишком медленно.
Есть ли возможность уменьшить это отвратительное потребление процессора?
P.S. Я не могу сгенерировать QImage с другим размером, но могу использовать указатель для буфера для создания изображения.
Изначально этот генератор изображений использовался на QWidget и таких проблем не было: QImage создавался размером 2000x2000 и устанавливался как образ для QWidget. То же потребление процессора было вроде 2-3%.