macOS: Track painted area of backingstore buffer via its dirty region
When introducing support for scrolling the backingstore it doesn't make sense to track the painted region explicitly. Pick-to: 6.2 Change-Id: I370932f02490ac526fb049908f99af678884e807 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
This commit is contained in:
parent
38130406ca
commit
5190e77d87
@ -85,7 +85,6 @@ private:
|
||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
|
||||
QSize m_requestedSize;
|
||||
QRegion m_paintedRegion;
|
||||
|
||||
class GraphicsBuffer : public QIOSurfaceGraphicsBuffer
|
||||
{
|
||||
@ -96,12 +95,16 @@ private:
|
||||
QRegion dirtyRegion; // In unscaled coordinates
|
||||
QImage *asImage();
|
||||
qreal devicePixelRatio() const { return m_devicePixelRatio; }
|
||||
bool isDirty() const { return !dirtyRegion.isEmpty(); }
|
||||
QRegion validRegion() const;
|
||||
|
||||
private:
|
||||
qreal m_devicePixelRatio;
|
||||
QImage m_image;
|
||||
};
|
||||
|
||||
void updateDirtyStates(const QRegion &paintedRegion);
|
||||
|
||||
void ensureBackBuffer();
|
||||
bool recreateBackBufferIfNeeded();
|
||||
bool prepareForFlush();
|
||||
|
@ -140,7 +140,8 @@ void QCALayerBackingStore::beginPaint(const QRegion ®ion)
|
||||
painter.fillRect(rect, Qt::transparent);
|
||||
}
|
||||
|
||||
m_paintedRegion += region;
|
||||
// We assume the client is going to paint the entire region
|
||||
updateDirtyStates(region);
|
||||
}
|
||||
|
||||
void QCALayerBackingStore::ensureBackBuffer()
|
||||
@ -242,7 +243,7 @@ QPaintDevice *QCALayerBackingStore::paintDevice()
|
||||
|
||||
void QCALayerBackingStore::endPaint()
|
||||
{
|
||||
qCInfo(lcQpaBackingStore) << "Paint ended with painted region" << m_paintedRegion;
|
||||
qCInfo(lcQpaBackingStore) << "Paint ended. Back buffer valid region is now" << m_buffers.back()->validRegion();
|
||||
m_buffers.back()->unlock();
|
||||
}
|
||||
|
||||
@ -259,7 +260,7 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion ®ion,
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_buffers.front()->isInUse() && m_buffers.front()->dirtyRegion.isEmpty()) {
|
||||
if (m_buffers.front()->isInUse() && !m_buffers.front()->isDirty()) {
|
||||
qCInfo(lcQpaBackingStore) << "Asked to flush, but front buffer is up to date. Ignoring.";
|
||||
return;
|
||||
}
|
||||
@ -414,6 +415,20 @@ QPlatformGraphicsBuffer *QCALayerBackingStore::graphicsBuffer() const
|
||||
return m_buffers.back().get();
|
||||
}
|
||||
|
||||
void QCALayerBackingStore::updateDirtyStates(const QRegion &paintedRegion)
|
||||
{
|
||||
// Update dirty state of buffers based on what was painted. The back buffer will be
|
||||
// less dirty, since we painted to it, while other buffers will become more dirty.
|
||||
// This allows us to minimize copies between front and back buffers on swap in the
|
||||
// cases where the painted region overlaps with the previous frame (front buffer).
|
||||
for (const auto &buffer : m_buffers) {
|
||||
if (buffer == m_buffers.back())
|
||||
buffer->dirtyRegion -= paintedRegion;
|
||||
else
|
||||
buffer->dirtyRegion += paintedRegion;
|
||||
}
|
||||
}
|
||||
|
||||
bool QCALayerBackingStore::prepareForFlush()
|
||||
{
|
||||
if (!m_buffers.back()) {
|
||||
@ -421,21 +436,10 @@ bool QCALayerBackingStore::prepareForFlush()
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update dirty state of buffers based on what was painted. The back buffer will be
|
||||
// less dirty, since we painted to it, while other buffers will become more dirty.
|
||||
// This allows us to minimize copies between front and back buffers on swap in the
|
||||
// cases where the painted region overlaps with the previous frame (front buffer).
|
||||
for (const auto &buffer : m_buffers) {
|
||||
if (buffer == m_buffers.back())
|
||||
buffer->dirtyRegion -= m_paintedRegion;
|
||||
else
|
||||
buffer->dirtyRegion += m_paintedRegion;
|
||||
}
|
||||
|
||||
// After painting, the back buffer is only guaranteed to have content for the painted
|
||||
// region, and may still have dirty areas that need to be synced up with the front buffer,
|
||||
// if we have one. We know that the front buffer is always up to date.
|
||||
if (!m_buffers.back()->dirtyRegion.isEmpty() && m_buffers.front() != m_buffers.back()) {
|
||||
if (m_buffers.back()->isDirty() && m_buffers.front() != m_buffers.back()) {
|
||||
QRegion preserveRegion = m_buffers.back()->dirtyRegion;
|
||||
qCDebug(lcQpaBackingStore) << "Preserving" << preserveRegion << "from front to back buffer";
|
||||
|
||||
@ -473,9 +477,6 @@ bool QCALayerBackingStore::prepareForFlush()
|
||||
m_buffers.back()->dirtyRegion = QRegion();
|
||||
}
|
||||
|
||||
// Prepare for another round of painting
|
||||
m_paintedRegion = QRegion();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -484,12 +485,19 @@ bool QCALayerBackingStore::prepareForFlush()
|
||||
QCALayerBackingStore::GraphicsBuffer::GraphicsBuffer(const QSize &size, qreal devicePixelRatio,
|
||||
const QPixelFormat &format, QCFType<CGColorSpaceRef> colorSpace)
|
||||
: QIOSurfaceGraphicsBuffer(size, format)
|
||||
, dirtyRegion(0, 0, size.width() / devicePixelRatio, size.height() / devicePixelRatio)
|
||||
, dirtyRegion(QRect(QPoint(0, 0), size / devicePixelRatio))
|
||||
, m_devicePixelRatio(devicePixelRatio)
|
||||
{
|
||||
setColorSpace(colorSpace);
|
||||
}
|
||||
|
||||
QRegion QCALayerBackingStore::GraphicsBuffer::validRegion() const
|
||||
{
|
||||
|
||||
QRegion fullRegion = QRect(QPoint(0, 0), size() / m_devicePixelRatio);
|
||||
return fullRegion - dirtyRegion;
|
||||
}
|
||||
|
||||
QImage *QCALayerBackingStore::GraphicsBuffer::asImage()
|
||||
{
|
||||
if (m_image.isNull()) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user