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

Reply via email to