From 0f49ebb4c21007f62055c3390fe925a7d4d6b34c Mon Sep 17 00:00:00 2001 From: Thomas McGuire Date: Wed, 11 Jul 2012 16:41:32 +0200 Subject: QNX: Fix flushing the backing store to non-owner windows Multiple windows can share the same backing store, which we did not take into account. Don't ignore the window parameter in flush() to fix that. Change-Id: I4f98bba34d4da9134163e478cb78cab4ca0358d2 Reviewed-by: Rafael Roquetto Reviewed-by: Marc Mutz Reviewed-by: Kevin Krammer Reviewed-by: Giuseppe D'Angelo --- .../platforms/qnx/qqnxrasterbackingstore.cpp | 62 ++++++++++++++++------ src/plugins/platforms/qnx/qqnxrasterbackingstore.h | 1 + src/plugins/platforms/qnx/qqnxwindow.cpp | 13 +++++ src/plugins/platforms/qnx/qqnxwindow.h | 2 + 4 files changed, 63 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp b/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp index 70af4b3579..542b587bd7 100644 --- a/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp +++ b/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp @@ -55,7 +55,8 @@ QT_BEGIN_NAMESPACE QQnxRasterBackingStore::QQnxRasterBackingStore(QWindow *window) - : QPlatformBackingStore(window) + : QPlatformBackingStore(window), + m_hasUnflushedPaintOperations(false) { qRasterBackingStoreDebug() << Q_FUNC_INFO << "w =" << window; @@ -75,25 +76,54 @@ QPaintDevice *QQnxRasterBackingStore::paintDevice() void QQnxRasterBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) { - Q_UNUSED(window); - Q_UNUSED(offset); - qRasterBackingStoreDebug() << Q_FUNC_INFO << "w =" << this->window(); - // visit all pending scroll operations - for (int i = m_scrollOpList.size() - 1; i >= 0; i--) { + QQnxWindow *targetWindow = 0; + if (window) + targetWindow = static_cast(window->handle()); - // do the scroll operation - ScrollOp &op = m_scrollOpList[i]; - QRegion srcArea = op.totalArea.intersected( op.totalArea.translated(-op.dx, -op.dy) ); - m_platformWindow->scroll(srcArea, op.dx, op.dy); - } + if (!targetWindow || targetWindow == m_platformWindow) { - // clear all pending scroll operations - m_scrollOpList.clear(); + // visit all pending scroll operations + for (int i = m_scrollOpList.size() - 1; i >= 0; i--) { + + // do the scroll operation + ScrollOp &op = m_scrollOpList[i]; + QRegion srcArea = op.totalArea.intersected( op.totalArea.translated(-op.dx, -op.dy) ); + m_platformWindow->scroll(srcArea, op.dx, op.dy); + } + + // clear all pending scroll operations + m_scrollOpList.clear(); + + // update the display with newly rendered content + m_platformWindow->post(region); + } else if (targetWindow) { + + // The contents of the backing store should be flushed to a different window than the + // window which owns the buffer. + // This typically happens for child windows, since child windows share a backing store with + // their top-level window (TLW). + // Simply copy the buffer over to the child window, to emulate a painting operation, and + // then post the window. + // + // ### Note that because of the design in the QNX QPA plugin, each window has its own buffers, + // even though they might share a backing store. This is unneeded overhead, but I don't think + // libscreen allows to have windows without buffers, or does it? + + // We assume that the TLW has been flushed previously and that no changes were made to the + // backing store inbetween (### does Qt guarantee this?) + Q_ASSERT(!m_hasUnflushedPaintOperations); + + targetWindow->adjustBufferSize(); + targetWindow->blitFrom(m_platformWindow, offset, region); + targetWindow->post(region); + + } else { + qWarning() << Q_FUNC_INFO << "flush() called without a valid window!"; + } - // update the display with newly rendered content - m_platformWindow->post(region); + m_hasUnflushedPaintOperations = false; } void QQnxRasterBackingStore::resize(const QSize &size, const QRegion &staticContents) @@ -113,6 +143,7 @@ bool QQnxRasterBackingStore::scroll(const QRegion &area, int dx, int dy) // calculate entire region affected by scroll operation (src + dst) QRegion totalArea = area.translated(dx, dy); totalArea += area; + m_hasUnflushedPaintOperations = true; // visit all pending scroll operations for (int i = m_scrollOpList.size() - 1; i >= 0; i--) { @@ -141,6 +172,7 @@ void QQnxRasterBackingStore::beginPaint(const QRegion ®ion) Q_UNUSED(region); qRasterBackingStoreDebug() << Q_FUNC_INFO << "w =" << window(); + m_hasUnflushedPaintOperations = true; m_platformWindow->adjustBufferSize(); } diff --git a/src/plugins/platforms/qnx/qqnxrasterbackingstore.h b/src/plugins/platforms/qnx/qqnxrasterbackingstore.h index 6a559492e1..cbe9dc49c4 100644 --- a/src/plugins/platforms/qnx/qqnxrasterbackingstore.h +++ b/src/plugins/platforms/qnx/qqnxrasterbackingstore.h @@ -74,6 +74,7 @@ private: QQnxWindow *m_platformWindow; QList m_scrollOpList; + bool m_hasUnflushedPaintOperations; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp index 572dff7289..95604a5e22 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxwindow.cpp @@ -639,6 +639,19 @@ QQnxWindow *QQnxWindow::findWindow(screen_window_t windowHandle) return 0; } +void QQnxWindow::blitFrom(QQnxWindow *sourceWindow, const QPoint &sourceOffset, const QRegion &targetRegion) +{ + if (!sourceWindow || sourceWindow->m_previousBufferIndex == -1 || targetRegion.isEmpty()) + return; + + qWindowDebug() << Q_FUNC_INFO << window() << sourceWindow->window() << sourceOffset << targetRegion; + + QQnxBuffer &sourceBuffer = sourceWindow->m_buffers[sourceWindow->m_previousBufferIndex]; + QQnxBuffer &targetBuffer = renderBuffer(); + + blitHelper(sourceBuffer, targetBuffer, sourceOffset, QPoint(0, 0), targetRegion, true); +} + void QQnxWindow::updateZorder(int &topZorder) { errno = 0; diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h index 2ee15ab96b..091476edec 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.h +++ b/src/plugins/platforms/qnx/qqnxwindow.h @@ -115,6 +115,8 @@ public: QQnxWindow *findWindow(screen_window_t windowHandle); + void blitFrom(QQnxWindow *sourceWindow, const QPoint &sourceOffset, const QRegion &targetRegion); + private: void removeFromParent(); void setOffset(const QPoint &setOffset); -- cgit v1.2.3