[Development] How fast grab a QML item's content to image when it updates?

Denis Shienkov denis.shienkov at gmail.com
Tue Dec 12 14:53:09 CET 2017


 > Did you try QQuickItem::grabToImage?

Of course, it is veeery slowly.


12.12.2017 16:40, Konstantin Tokarev пишет:
>
> 12.12.2017, 16:13, "Denis Shienkov" <denis.shienkov at gmail.com>:
>> Hi all...
>>
>> Is it possible to grab a QQuickItem content (e.g. with all sub-items)
>> when an item changes?
> Did you try QQuickItem::grabToImage?
>
>> E.g. with widgets I use the following code:
>>
>> bool MyWidget::event(QEvent *event)
>> {
>>       if (event->type() == QEvent::UpdateRequest)
>>           myGrab();
>>       return QWidget::event(event);
>> }
>>
>> void MyWidget::myGrab()
>> {
>>       ...
>>       QBackingStore *store = backingStore();
>>       Q_ASSERT(store);
>>
>>       QPaintDevice *pdev = store->paintDevice();
>>       const auto image = dynamic_cast<QImage *>(pdev);
>>       ...
>> }
>>
>> it is very fast (as I know)...
>>
>> But with the QML I got a troubles: I can 'grab' the sourceItem, using
>> the FBO and private functions, but the fbo::toImage() is too slow (~24
>> msecs),
>> and I don't know how to intercept the signal when a watched item updates:
>>
>> Grabber::Grabber(QQuickItem *parent)
>>       : QQuickItem(parent)
>> {
>>       setFlag(QQuickItem::ItemHasContents);
>> }
>>
>> // Where sourceItem - is a watched item.
>> void Grabber::setSourceItem(QQuickItem *sourceItem)
>> {
>>       if (sourceItem == m_sourceItem)
>>           return;
>>       m_sourceItem = sourceItem;
>>       emit sourceItemChanged(m_sourceItem);
>>       update();
>> }
>>
>> QSGNode *Grabber::updatePaintNode(QSGNode *oldNode,
>>                                     UpdatePaintNodeData *updatePaintNodeData)
>> {
>>       Q_UNUSED(updatePaintNodeData);
>>
>>       if (!m_sourceItem)
>>           return oldNode;
>>
>>       QSGRootNode root;
>> root.appendChildNode(QQuickItemPrivate::get(m_sourceItem)->itemNode());
>>
>>       const QScopedPointer<QSGRenderer> renderer(
>>                   QQuickItemPrivate::get(this)->
>>                   sceneGraphRenderContext()->createRenderer());
>>
>>       renderer->setRootNode(&root);
>>
>>       const QSize size(m_sourceItem->width(), m_sourceItem->height());
>>       renderer->setDeviceRect(size);
>>       renderer->setViewportRect(size);
>>       renderer->setProjectionMatrixToRect(QRectF(QPointF(), size));
>>       renderer->setClearColor(Qt::transparent);
>>
>>       QOpenGLFramebufferObject fbo(size);
>>       renderer->renderScene(BindableFbo(&fbo));
>>       fbo.release();
>>
>>       QElapsedTimer et;
>>       et.start();
>>       const QImage image = fbo.toImage(); // TOO LONG ~24 msec!
>>       qDebug() << "Elapsed:" << et.elapsed();
>>
>>       return oldNode;
>> }
>>
>> it is very fast (as I know).
>>
>> But with the QML I got a troubles: I can 'grub' an item, using the FBO,
>>
>> but the toImage() method is too slow (~24 msecs), and I don't know how
>>
>> to intercept a signal when the watched item updates:
>>
>> Grabber::Grabber(QQuickItem *parent)
>>       : QQuickItem(parent)
>> {
>>       setFlag(QQuickItem::ItemHasContents);
>> }
>>
>> QSGNode *Grabber::updatePaintNode(QSGNode *oldNode,
>>                                     UpdatePaintNodeData *updatePaintNodeData)
>> {
>>       Q_UNUSED(updatePaintNodeData);
>>
>>       if (!m_sourceItem)
>>           return oldNode;
>>
>>       QSGRootNode root;
>> root.appendChildNode(QQuickItemPrivate::get(m_sourceItem)->itemNode());
>>
>>       const QScopedPointer<QSGRenderer> renderer(
>>                   QQuickItemPrivate::get(this)->
>>                   sceneGraphRenderContext()->createRenderer());
>>
>>       renderer->setRootNode(&root);
>>
>>       const QSize size(m_sourceItem->width(), m_sourceItem->height());
>>       renderer->setDeviceRect(size);
>>       renderer->setViewportRect(size);
>>       renderer->setProjectionMatrixToRect(QRectF(QPointF(), size));
>>       renderer->setClearColor(Qt::transparent);
>>
>>       QOpenGLFramebufferObject fbo(size);
>>       renderer->renderScene(BindableFbo(&fbo));
>>       fbo.release();
>>
>>       QElapsedTimer et;
>>       et.start();
>>       const QImage image = fbo.toImage(); // TOO LONG!
>>       qDebug() << "Elapsed:" << et.elapsed();
>>
>>       return oldNode;
>> }
>>
>> _______________________________________________
>> Development mailing list
>> Development at qt-project.org
>> http://lists.qt-project.org/mailman/listinfo/development




More information about the Development mailing list