diff options
author | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2021-11-04 13:29:05 +0100 |
---|---|---|
committer | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2021-11-08 19:04:59 +0100 |
commit | 5190e77d87d743a75362ecf933adb466199e8958 (patch) | |
tree | 862c734531bb08507d1109446ae38efa725e1f2f /src/plugins/platforms | |
parent | 38130406ca806799ba812af1dbc849f57af1f64c (diff) |
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>
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoabackingstore.h | 5 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoabackingstore.mm | 40 |
2 files changed, 28 insertions, 17 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h index 374dc97f7d..28adbaee41 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.h +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h @@ -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(); diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index e4a7a3d8af..21ccbcbb00 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -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,28 +415,31 @@ QPlatformGraphicsBuffer *QCALayerBackingStore::graphicsBuffer() const return m_buffers.back().get(); } -bool QCALayerBackingStore::prepareForFlush() +void QCALayerBackingStore::updateDirtyStates(const QRegion &paintedRegion) { - if (!m_buffers.back()) { - qCWarning(lcQpaBackingStore) << "Tried to flush backingstore without painting to it first"; - 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; + buffer->dirtyRegion -= paintedRegion; else - buffer->dirtyRegion += m_paintedRegion; + buffer->dirtyRegion += paintedRegion; + } +} + +bool QCALayerBackingStore::prepareForFlush() +{ + if (!m_buffers.back()) { + qCWarning(lcQpaBackingStore) << "Tried to flush backingstore without painting to it first"; + return false; } // 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()) { |