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

Konstantin Tokarev annulen at yandex.ru
Tue Dec 12 16:52:46 CET 2017



12.12.2017, 16:53, "Denis Shienkov" <denis.shienkov at gmail.com>:
>  > Did you try QQuickItem::grabToImage?
>
> Of course, it is veeery slowly.

I guess your best bet then is hardware grabbing video output

>
> 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

-- 
Regards,
Konstantin




More information about the Development mailing list