Software Renderer: Call QBackingStore::beginPaint with correct QRegion
When rendering into QBackingStores, it is important to let the backingstore know what region you intended to paint into before you start rendering. Previously we were calling QBackingStore::beginPaint on the whole window area, but then only rendering and flushing for a subset of that area. This causes issues on platforms that depend on QBackingStore::beginPaint to be all area that will be repainted before the next flush, so that they can for example clear those areas. This change required a bit of extra plumbing in the Software Renderer, but now it is possible to calculate the area that will be repainted before painting it, and pass that region to QBackingStore::beginPaint(). Change-Id: I90be1916ebbe8fc182cd13246bb6690cc7e16d27 Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
parent
c884f85863
commit
cc4954e964
|
@ -149,7 +149,7 @@ void QSGAbstractSoftwareRenderer::buildRenderList()
|
|||
QSGSoftwareRenderListBuilder(this).visitChildren(rootNode());
|
||||
}
|
||||
|
||||
void QSGAbstractSoftwareRenderer::optimizeRenderList()
|
||||
QRegion QSGAbstractSoftwareRenderer::optimizeRenderList()
|
||||
{
|
||||
// Iterate through the renderlist from front to back
|
||||
// Objective is to update the dirty status and rects.
|
||||
|
@ -212,9 +212,13 @@ void QSGAbstractSoftwareRenderer::optimizeRenderList()
|
|||
m_dirtyRegion += node->dirtyRegion();
|
||||
}
|
||||
|
||||
QRegion updateRegion = m_dirtyRegion;
|
||||
|
||||
// Empty dirtyRegion
|
||||
m_dirtyRegion = QRegion();
|
||||
m_obscuredRegion = QRegion();
|
||||
|
||||
return updateRegion;
|
||||
}
|
||||
|
||||
void QSGAbstractSoftwareRenderer::setBackgroundColor(const QColor &color)
|
||||
|
|
|
@ -78,7 +78,7 @@ public:
|
|||
protected:
|
||||
QRegion renderNodes(QPainter *painter);
|
||||
void buildRenderList();
|
||||
void optimizeRenderList();
|
||||
QRegion optimizeRenderList();
|
||||
|
||||
void setBackgroundColor(const QColor &color);
|
||||
void setBackgroundSize(const QSize &size);
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "qsgsoftwarerenderablenode_p.h"
|
||||
|
||||
#include <QtGui/QPaintDevice>
|
||||
#include <QtGui/QBackingStore>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
Q_LOGGING_CATEGORY(lcRenderer, "qt.scenegraph.softwarecontext.renderer")
|
||||
|
@ -53,6 +54,8 @@ QT_BEGIN_NAMESPACE
|
|||
|
||||
QSGSoftwareRenderer::QSGSoftwareRenderer(QSGRenderContext *context)
|
||||
: QSGAbstractSoftwareRenderer(context)
|
||||
, m_paintDevice(nullptr)
|
||||
, m_backingStore(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -63,6 +66,13 @@ QSGSoftwareRenderer::~QSGSoftwareRenderer()
|
|||
void QSGSoftwareRenderer::setCurrentPaintDevice(QPaintDevice *device)
|
||||
{
|
||||
m_paintDevice = device;
|
||||
m_backingStore = nullptr;
|
||||
}
|
||||
|
||||
void QSGSoftwareRenderer::setBackingStore(QBackingStore *backingStore)
|
||||
{
|
||||
m_backingStore = backingStore;
|
||||
m_paintDevice = nullptr;
|
||||
}
|
||||
|
||||
QRegion QSGSoftwareRenderer::flushRegion() const
|
||||
|
@ -82,18 +92,19 @@ void QSGSoftwareRenderer::renderScene(uint)
|
|||
|
||||
void QSGSoftwareRenderer::render()
|
||||
{
|
||||
if (!m_paintDevice)
|
||||
if (!m_paintDevice && !m_backingStore)
|
||||
return;
|
||||
|
||||
// If there is a backingstore, set the current paint device
|
||||
if (m_backingStore)
|
||||
m_paintDevice = m_backingStore->paintDevice();
|
||||
|
||||
QElapsedTimer renderTimer;
|
||||
|
||||
setBackgroundColor(clearColor());
|
||||
setBackgroundSize(QSize(m_paintDevice->width() / m_paintDevice->devicePixelRatio(),
|
||||
m_paintDevice->height() / m_paintDevice->devicePixelRatio()));
|
||||
|
||||
QPainter painter(m_paintDevice);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
// Build Renderlist
|
||||
// The renderlist is created by visiting each node in the tree and when a
|
||||
// renderable node is reach, we find the coorosponding RenderableNode object
|
||||
|
@ -113,13 +124,23 @@ void QSGSoftwareRenderer::render()
|
|||
// side effect of this is that additional nodes may need to be marked dirty to
|
||||
// force a repaint. It is also important that any item that needs to be
|
||||
// repainted only paints what is needed, via the use of clip regions.
|
||||
optimizeRenderList();
|
||||
const QRegion updateRegion = optimizeRenderList();
|
||||
qint64 optimizeRenderListTime = renderTimer.restart();
|
||||
|
||||
// If Rendering to a backingstore, prepare it to be updated
|
||||
if (m_backingStore != nullptr)
|
||||
m_backingStore->beginPaint(updateRegion);
|
||||
|
||||
QPainter painter(m_paintDevice);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
// Render the contents Renderlist
|
||||
m_flushRegion = renderNodes(&painter);
|
||||
qint64 renderTime = renderTimer.elapsed();
|
||||
|
||||
if (m_backingStore != nullptr)
|
||||
m_backingStore->endPaint();
|
||||
|
||||
qCDebug(lcRenderer) << "render" << m_flushRegion << buildRenderListTime << optimizeRenderListTime << renderTime;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QPaintDevice;
|
||||
class QBackingStore;
|
||||
|
||||
class Q_QUICK_PRIVATE_EXPORT QSGSoftwareRenderer : public QSGAbstractSoftwareRenderer
|
||||
{
|
||||
|
@ -64,6 +65,7 @@ public:
|
|||
virtual ~QSGSoftwareRenderer();
|
||||
|
||||
void setCurrentPaintDevice(QPaintDevice *device);
|
||||
void setBackingStore(QBackingStore *backingStore);
|
||||
QRegion flushRegion() const;
|
||||
|
||||
protected:
|
||||
|
@ -72,6 +74,7 @@ protected:
|
|||
|
||||
private:
|
||||
QPaintDevice* m_paintDevice;
|
||||
QBackingStore* m_backingStore;
|
||||
QRegion m_flushRegion;
|
||||
};
|
||||
|
||||
|
|
|
@ -156,11 +156,9 @@ void QSGSoftwareRenderLoop::renderWindow(QQuickWindow *window)
|
|||
//Tell the renderer about the windows backing store
|
||||
auto softwareRenderer = static_cast<QSGSoftwareRenderer*>(cd->renderer);
|
||||
if (softwareRenderer)
|
||||
softwareRenderer->setCurrentPaintDevice(m_backingStores[window]->paintDevice());
|
||||
softwareRenderer->setBackingStore(m_backingStores[window]);
|
||||
|
||||
m_backingStores[window]->beginPaint(QRect(0, 0, window->width(), window->height()));
|
||||
cd->renderSceneGraph(window->size());
|
||||
m_backingStores[window]->endPaint();
|
||||
|
||||
if (profileFrames)
|
||||
renderTime = renderTimer.nsecsElapsed();
|
||||
|
|
Loading…
Reference in New Issue