Now I tried to use the following code:
classBindableFbofinal:publicQSGBindable
{
public:
explicitBindableFbo(QOpenGLFramebufferObject*fbo)
:m_fbo(fbo)
{}
voidbind()constfinal{m_fbo->bind();}
private:
QOpenGLFramebufferObject*m_fbo=nullptr;
};
Grabber::Grabber(QQuickItem*parent)
:QQuickItem(parent)
{
setFlag(QQuickItem::ItemHasContents);
connect(this,&Grabber::windowChanged,
this,&Grabber::scheduleWindowChange);
}
voidGrabber::setSourceItem(QQuickItem*sourceItem)
{
if(sourceItem==m_sourceItem)
return;
m_sourceItem=sourceItem;
emitsourceItemChanged(m_sourceItem);
update();
}
QQuickItem*Grabber::sourceItem()const
{
returnm_sourceItem;
}
QSGNode*Grabber::updatePaintNode(QSGNode*oldNode,
UpdatePaintNodeData*updatePaintNodeData)
{
Q_UNUSED(updatePaintNodeData);
if(!m_sourceItem)
returnoldNode;
m_running=true;
constautoitemNode=QQuickItemPrivate::get(m_sourceItem)->itemNode();
constautoparentNode=itemNode->parent();
constautosiblingNode=itemNode->previousSibling();
if(parentNode)
parentNode->removeChildNode(itemNode);
constQScopedPointer<QSGRenderer>renderer(
QQuickItemPrivate::get(this)->
sceneGraphRenderContext()->createRenderer());
QSGRootNoderootNode;
rootNode.appendChildNode(itemNode);
renderer->setRootNode(&rootNode);
constQSizesize(m_sourceItem->width(),m_sourceItem->height());
renderer->setDeviceRect(size);
renderer->setViewportRect(size);
renderer->setProjectionMatrixToRect(QRectF(QPointF(),size));
renderer->setClearColor(Qt::transparent);
QOpenGLFramebufferObjectfbo(size);
renderer->renderScene(BindableFbo(&fbo));
fbo.release();
rootNode.removeChildNode(itemNode);
if(parentNode){
if(siblingNode){
parentNode->insertChildNodeAfter(itemNode,siblingNode);
}else{
parentNode->prependChildNode(itemNode);
}
}
QElapsedTimeret;
et.start();
constQImageimage=fbo.toImage();//TOOLONG!
staticintcount=0;
qDebug()<<"Elapsed:"<<et.elapsed()<<count;
++count;
//image.save(tr("test%1.png").arg(count++));
returnoldNode;
}
voidGrabber::scheduleWindowChange(QQuickWindow*window)
{
disconnect(m_updateConnection);
if(window){
m_updateConnection=connect(window,&QQuickWindow::afterRendering,
this,&Grabber::scheduleUpdate);
}
}
voidGrabber::scheduleUpdate()
{
if(!m_running)
update();
else
m_running=false;
}
Where for the 800x600 window, the elapsed time of fbo.toImage() is
around of ~8 msec
(with GPU rendering on Windows, as I assume). If try to expand a window
to full screen
(1920x1080 in my case), then this time increases up to ~30 msec.
I'm not sure, is this code correct? Is this values correct? Could
someone elaborate it?
12.12.2017 18:20, Shawn Rutledge пишет:
On 12 Dec 2017, at 14:53, Denis Shienkov <denis.shien...@gmail.com> wrote:
Did you try QQuickItem::grabToImage?
Of course, it is veeery slowly.
If the frame was rendered on the GPU, you have to download it from there, and
that is slower than if you had rendered into CPU memory, as widgets do by
default. Thus the note in the docs:
Note: This function will render the item to an offscreen surface and copy
that surface from the GPU's memory into the CPU's memory, which can be
quite costly. For "live" preview, use layers or ShaderEffectSource.
So, maybe try to get the GPU to do whatever comes next after you think you need
to grab the frame? grabToImage is more for archival, not for real-time effects
(although I did use it recently to record an animated GIF; I could only get
30FPS despite using a fairly powerful GPU, but that was good enough).
_______________________________________________
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development
_______________________________________________
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development