From a1fd5d02bd9d5efb4334dc6f9d393eaaaa377bab Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Thu, 28 Apr 2016 10:24:38 -0700 Subject: xcb: support nested paint operations in remote scenarios Recent changes to the xcb platform plugin added logic to paint to a server-side X Pixmap when the MIT-SHM extension is unavailable. Those changes also added logic to keep track of the dirty areas that need to be flushed to the server from the backing store when the backing store is flushed to a window. Because a single QRegion was used to track those areas, nested paint operations no longer accurately tracked all the dirty areas. Consider: void Widget::paintEvent(QPaintEvent *) { QPainter p1(this); for (int i = 0; longRunningOperationInProgress(); i++) { QPixmap pixmap(size()); QPainter p2(&pixmap); p2.drawText(pixmap.rect(), i & 1 ? "Working." : "Working.."); p2.end(); QBackingStore *bs = backingStore(); bs->beginPaint(rect()); p1.drawPixmap(0, 0, pixmap); bs->endPaint(); bs->flush(rect(), windowHandle()); } p1.fillRect(rect(), Qt::red); p1.drawText(rect(), "Done!"); } While this code could be restructured, it is a common pattern in legacy Qt applications which cannot be easily changed. Change-Id: I3b919266abe41c96a584cb02f41cafac3f9d1d7c Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbbackingstore.cpp | 16 ++++++++++++---- src/plugins/platforms/xcb/qxcbbackingstore.h | 3 ++- 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 51c6b198e5..a999fb0aa2 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -525,13 +525,13 @@ void QXcbBackingStore::beginPaint(const QRegion ®ion) if (!m_image) return; - m_paintRegion = region; - m_image->preparePaint(m_paintRegion); + m_paintRegions.push(region); + m_image->preparePaint(region); if (m_image->hasAlpha()) { QPainter p(paintDevice()); p.setCompositionMode(QPainter::CompositionMode_Source); - const QVector rects = m_paintRegion.rects(); + const QVector rects = region.rects(); const QColor blank = Qt::transparent; for (QVector::const_iterator it = rects.begin(); it != rects.end(); ++it) { p.fillRect(*it, blank); @@ -541,13 +541,21 @@ void QXcbBackingStore::beginPaint(const QRegion ®ion) void QXcbBackingStore::endPaint() { + if (Q_UNLIKELY(m_paintRegions.isEmpty())) { + qWarning("%s: paint regions empty!", Q_FUNC_INFO); + return; + } + + const QRegion region = m_paintRegions.pop(); + m_image->preparePaint(region); + QXcbWindow *platformWindow = static_cast(window()->handle()); if (!platformWindow || !platformWindow->imageNeedsRgbSwap()) return; // Slow path: the paint device was m_rgbImage. Now copy with swapping red // and blue into m_image. - const QVector rects = m_paintRegion.rects(); + const QVector rects = region.rects(); if (rects.isEmpty()) return; QPainter p(m_image->image()); diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.h b/src/plugins/platforms/xcb/qxcbbackingstore.h index 1f5652d918..5a8f385c1b 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.h +++ b/src/plugins/platforms/xcb/qxcbbackingstore.h @@ -41,6 +41,7 @@ #define QXCBBACKINGSTORE_H #include +#include #include @@ -75,7 +76,7 @@ public: private: QXcbShmImage *m_image; - QRegion m_paintRegion; + QStack m_paintRegions; QImage m_rgbImage; }; -- cgit v1.2.3