Fix rendercontrol grabs with the software backend
Calling grabWindow recurses (since that is implemented via QQuickRenderControl::grab...) so it's not an option. Instead, call directly in the software renderer implementation. Fix also the size of the offscreen QQuickWindow when using QQuickWidget in combination with the software backend. Change-Id: I857a2cc0aebbbaa5d52d809aeaec37c15b0787b9 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
parent
12de7bbc1e
commit
c2414e16ab
|
@ -56,9 +56,9 @@
|
|||
|
||||
#include <QtQuick/QQuickWindow>
|
||||
#include <QtQuick/private/qquickwindow_p.h>
|
||||
#include <QtQuick/private/qsgsoftwarerenderer_p.h>
|
||||
#include <QtCore/private/qobject_p.h>
|
||||
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
#ifndef QT_NO_OPENGL
|
||||
extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
|
||||
|
@ -369,12 +369,31 @@ QImage QQuickRenderControl::grab()
|
|||
if (!d->window)
|
||||
return QImage();
|
||||
|
||||
render();
|
||||
QImage grabContent;
|
||||
|
||||
if (d->window->rendererInterface()->graphicsApi() == QSGRendererInterface::OpenGL) {
|
||||
#ifndef QT_NO_OPENGL
|
||||
QImage grabContent = qt_gl_read_framebuffer(d->window->size() * d->window->effectiveDevicePixelRatio(), false, false);
|
||||
#else
|
||||
QImage grabContent = d->window->grabWindow();
|
||||
render();
|
||||
grabContent = qt_gl_read_framebuffer(d->window->size() * d->window->effectiveDevicePixelRatio(), false, false);
|
||||
#endif
|
||||
} else if (d->window->rendererInterface()->graphicsApi() == QSGRendererInterface::Software) {
|
||||
QQuickWindowPrivate *cd = QQuickWindowPrivate::get(d->window);
|
||||
QSGSoftwareRenderer *softwareRenderer = static_cast<QSGSoftwareRenderer *>(cd->renderer);
|
||||
if (softwareRenderer) {
|
||||
const qreal dpr = d->window->effectiveDevicePixelRatio();
|
||||
const QSize imageSize = d->window->size() * dpr;
|
||||
grabContent = QImage(imageSize, QImage::Format_ARGB32_Premultiplied);
|
||||
grabContent.setDevicePixelRatio(dpr);
|
||||
QPaintDevice *prevDev = softwareRenderer->currentPaintDevice();
|
||||
softwareRenderer->setCurrentPaintDevice(&grabContent);
|
||||
softwareRenderer->markDirty();
|
||||
render();
|
||||
softwareRenderer->setCurrentPaintDevice(prevDev);
|
||||
}
|
||||
} else {
|
||||
qWarning("QQuickRenderControl: grabs are not supported with the current Qt Quick backend");
|
||||
}
|
||||
|
||||
return grabContent;
|
||||
}
|
||||
|
||||
|
|
|
@ -236,7 +236,7 @@ void QSGAbstractSoftwareRenderer::setBackgroundSize(const QSize &size)
|
|||
m_background->setRect(0.0f, 0.0f, size.width(), size.height());
|
||||
renderableNode(m_background)->markGeometryDirty();
|
||||
// Invalidate the whole scene when the background is resized
|
||||
m_dirtyRegion = QRegion(m_background->rect().toRect());
|
||||
markDirty();
|
||||
}
|
||||
|
||||
QColor QSGAbstractSoftwareRenderer::backgroundColor()
|
||||
|
@ -322,4 +322,9 @@ void QSGAbstractSoftwareRenderer::nodeOpacityUpdated(QSGNode *node)
|
|||
m_nodeUpdater->updateNodes(node);
|
||||
}
|
||||
|
||||
void QSGAbstractSoftwareRenderer::markDirty()
|
||||
{
|
||||
m_dirtyRegion = QRegion(m_background->rect().toRect());
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
@ -75,6 +75,8 @@ public:
|
|||
|
||||
void nodeChanged(QSGNode *node, QSGNode::DirtyState state) override;
|
||||
|
||||
void markDirty();
|
||||
|
||||
protected:
|
||||
QRegion renderNodes(QPainter *painter);
|
||||
void buildRenderList();
|
||||
|
|
|
@ -69,6 +69,11 @@ void QSGSoftwareRenderer::setCurrentPaintDevice(QPaintDevice *device)
|
|||
m_backingStore = nullptr;
|
||||
}
|
||||
|
||||
QPaintDevice *QSGSoftwareRenderer::currentPaintDevice() const
|
||||
{
|
||||
return m_paintDevice;
|
||||
}
|
||||
|
||||
void QSGSoftwareRenderer::setBackingStore(QBackingStore *backingStore)
|
||||
{
|
||||
m_backingStore = backingStore;
|
||||
|
|
|
@ -65,6 +65,7 @@ public:
|
|||
virtual ~QSGSoftwareRenderer();
|
||||
|
||||
void setCurrentPaintDevice(QPaintDevice *device);
|
||||
QPaintDevice *currentPaintDevice() const;
|
||||
void setBackingStore(QBackingStore *backingStore);
|
||||
QRegion flushRegion() const;
|
||||
|
||||
|
|
|
@ -894,6 +894,12 @@ void QQuickWidget::createFramebufferObject()
|
|||
if (size().isEmpty())
|
||||
return;
|
||||
|
||||
// Even though this is just an offscreen window we should set the position on it, as it might be
|
||||
// useful for an item to know the actual position of the scene.
|
||||
// Note: The position will be update when we get a move event (see: updatePosition()).
|
||||
const QPoint &globalPos = mapToGlobal(QPoint(0, 0));
|
||||
d->offscreenWindow->setGeometry(globalPos.x(), globalPos.y(), width(), height());
|
||||
|
||||
if (d->useSoftwareRenderer) {
|
||||
const QSize imageSize = size() * devicePixelRatio();
|
||||
d->softwareImage = QImage(imageSize, QImage::Format_ARGB32_Premultiplied);
|
||||
|
@ -961,11 +967,6 @@ void QQuickWidget::createFramebufferObject()
|
|||
}
|
||||
#endif
|
||||
|
||||
// Even though this is just an offscreen window we should set the position on it, as it might be
|
||||
// useful for an item to know the actual position of the scene.
|
||||
// Note: The position will be update when we get a move event (see: updatePosition()).
|
||||
const QPoint &globalPos = mapToGlobal(QPoint(0, 0));
|
||||
d->offscreenWindow->setGeometry(globalPos.x(), globalPos.y(), width(), height());
|
||||
d->offscreenWindow->setRenderTarget(d->fbo);
|
||||
|
||||
if (samples > 0)
|
||||
|
|
Loading…
Reference in New Issue