QNX: Fix flushing the backing store to non-owner windows
authorThomas McGuire <thomas.mcguire.qnx@kdab.com>
Wed, 11 Jul 2012 14:41:32 +0000 (16:41 +0200)
committerQt by Nokia <qt-info@nokia.com>
Fri, 13 Jul 2012 07:55:18 +0000 (09:55 +0200)
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 <rafael.roquetto@kdab.com>
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
Reviewed-by: Kevin Krammer <kevin.krammer@kdab.com>
Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp
src/plugins/platforms/qnx/qqnxrasterbackingstore.h
src/plugins/platforms/qnx/qqnxwindow.cpp
src/plugins/platforms/qnx/qqnxwindow.h

index 70af4b3..542b587 100644 (file)
@@ -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 &region, 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<QQnxWindow *>(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 &region)
     Q_UNUSED(region);
 
     qRasterBackingStoreDebug() << Q_FUNC_INFO << "w =" << window();
+    m_hasUnflushedPaintOperations = true;
 
     m_platformWindow->adjustBufferSize();
 }
index 6a55949..cbe9dc4 100644 (file)
@@ -74,6 +74,7 @@ private:
 
     QQnxWindow *m_platformWindow;
     QList<ScrollOp> m_scrollOpList;
+    bool m_hasUnflushedPaintOperations;
 };
 
 QT_END_NAMESPACE
index 572dff7..95604a5 100644 (file)
@@ -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;
index 2ee15ab..091476e 100644 (file)
@@ -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);