summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/qnx/qqnxrasterwindow.cpp
diff options
context:
space:
mode:
authorFabian Bumberger <fbumberger@rim.com>2013-09-02 15:49:51 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-18 11:28:26 +0200
commitaed9a8d49b7470de6809c3bf747b14c7150d7ae6 (patch)
treefb566c75ccccf7623170629b61c0ac760c295d98 /src/plugins/platforms/qnx/qqnxrasterwindow.cpp
parente39d629ebe9044b505ac35eaae3ab9c214d452a2 (diff)
Split QQnxWindow into QQnxEglWindow and QQnxRasterWindow
Change-Id: I2fb4096ccca54fa6631aa16c9b8d1308b0a6b918 Reviewed-by: Sergio Ahumada <sergio.ahumada@digia.com> Reviewed-by: Rafael Roquetto <rafael.roquetto@kdab.com> Reviewed-by: Thomas McGuire <thomas.mcguire@kdab.com> Reviewed-by: Kevin Krammer <kevin.krammer@kdab.com>
Diffstat (limited to 'src/plugins/platforms/qnx/qqnxrasterwindow.cpp')
-rw-r--r--src/plugins/platforms/qnx/qqnxrasterwindow.cpp234
1 files changed, 234 insertions, 0 deletions
diff --git a/src/plugins/platforms/qnx/qqnxrasterwindow.cpp b/src/plugins/platforms/qnx/qqnxrasterwindow.cpp
new file mode 100644
index 0000000000..fa54b341a5
--- /dev/null
+++ b/src/plugins/platforms/qnx/qqnxrasterwindow.cpp
@@ -0,0 +1,234 @@
+/***************************************************************************
+**
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqnxrasterwindow.h"
+#include "qqnxscreen.h"
+
+#include <QDebug>
+
+#include <errno.h>
+
+#if defined(QQNXRASTERWINDOW_DEBUG)
+#define qRasterWindowDebug qDebug
+#else
+#define qRasterWindowDebug QT_NO_QDEBUG_MACRO
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QQnxRasterWindow::QQnxRasterWindow(QWindow *window, screen_context_t context) :
+ QQnxWindow(window, context),
+ m_currentBufferIndex(-1),
+ m_previousBufferIndex(-1)
+{
+ initWindow();
+}
+
+void QQnxRasterWindow::post(const QRegion &dirty)
+{
+ // How double-buffering works
+ // --------------------------
+ //
+ // The are two buffers, the previous one and the current one.
+ // The previous buffer always contains the complete, full image of the whole window when it
+ // was last posted.
+ // The current buffer starts with the complete, full image of the second to last posting
+ // of the window.
+ //
+ // During painting, Qt paints on the current buffer. Thus, when Qt has finished painting, the
+ // current buffer contains the second to last image plus the newly painted regions.
+ // Since the second to last image is too old, we copy over the image from the previous buffer, but
+ // only for those regions that Qt didn't paint (because that would overwrite what Qt has just
+ // painted). This is the copyPreviousToCurrent() call below.
+ //
+ // After the call to copyPreviousToCurrent(), the current buffer contains the complete, full image of the
+ // whole window in its current state, and we call screen_post_window() to make the new buffer
+ // available to libscreen (called "posting"). There, only the regions that Qt painted on are
+ // posted, as nothing else has changed.
+ //
+ // After that, the previous and the current buffers are swapped, and the whole cycle starts anew.
+
+ // Check if render buffer exists and something was rendered
+ if (m_currentBufferIndex != -1 && !dirty.isEmpty()) {
+ qRasterWindowDebug() << Q_FUNC_INFO << "window =" << window();
+ QQnxBuffer &currentBuffer = m_buffers[m_currentBufferIndex];
+
+ // Copy unmodified region from old render buffer to new render buffer;
+ // required to allow partial updates
+ QRegion preserve = m_previousDirty - dirty - m_scrolled;
+ blitPreviousToCurrent(preserve, 0, 0);
+
+ // Calculate region that changed
+ QRegion modified = preserve + dirty + m_scrolled;
+ QRect rect = modified.boundingRect();
+ int dirtyRect[4] = { rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height() };
+
+ // Update the display with contents of render buffer
+ errno = 0;
+ int result = screen_post_window(nativeHandle(), currentBuffer.nativeBuffer(), 1, dirtyRect, 0);
+ if (result != 0)
+ qFatal("QQnxWindow: failed to post window buffer, errno=%d", errno);
+
+ // Advance to next nender buffer
+ m_previousBufferIndex = m_currentBufferIndex++;
+ if (m_currentBufferIndex >= MAX_BUFFER_COUNT)
+ m_currentBufferIndex = 0;
+
+ // Save modified region and clear scrolled region
+ m_previousDirty = dirty;
+ m_scrolled = QRegion();
+ // Notify screen that window posted
+ if (screen() != 0)
+ screen()->onWindowPost(this);
+ }
+}
+
+void QQnxRasterWindow::scroll(const QRegion &region, int dx, int dy, bool flush)
+{
+ qRasterWindowDebug() << Q_FUNC_INFO << "window =" << window();
+ blitPreviousToCurrent(region, dx, dy, flush);
+ m_scrolled += region;
+}
+
+QQnxBuffer &QQnxRasterWindow::renderBuffer()
+{
+ qRasterWindowDebug() << Q_FUNC_INFO << "window =" << window();
+
+ // Check if render buffer is invalid
+ if (m_currentBufferIndex == -1) {
+ // Get all buffers available for rendering
+ errno = 0;
+ screen_buffer_t buffers[MAX_BUFFER_COUNT];
+ int result = screen_get_window_property_pv(nativeHandle(), SCREEN_PROPERTY_RENDER_BUFFERS, (void **)buffers);
+ if (result != 0)
+ qFatal("QQnxRasterWindow: failed to query window buffers, errno=%d", errno);
+
+ // Wrap each buffer and clear
+ for (int i = 0; i < MAX_BUFFER_COUNT; ++i) {
+ m_buffers[i] = QQnxBuffer(buffers[i]);
+
+ // Clear Buffer
+ errno = 0;
+ int bg[] = { SCREEN_BLIT_COLOR, 0x00000000, SCREEN_BLIT_END };
+ result = screen_fill(screen()->nativeContext(), buffers[i], bg);
+ if (result != 0)
+ qFatal("QQnxWindow: failed to clear window buffer, errno=%d", errno);
+ }
+
+ errno = 0;
+ result = screen_flush_blits(screen()->nativeContext(), 0);
+ if (result != 0)
+ qFatal("QQnxWindow: failed to flush blits, errno=%d", errno);
+
+ // Use the first available render buffer
+ m_currentBufferIndex = 0;
+ m_previousBufferIndex = -1;
+ }
+
+ return m_buffers[m_currentBufferIndex];
+}
+
+int QQnxRasterWindow::pixelFormat() const
+{
+ return screen()->nativeFormat();
+}
+
+void QQnxRasterWindow::resetBuffers()
+{
+ // Buffers were destroyed; reacquire them
+ m_currentBufferIndex = -1;
+ m_previousDirty = QRegion();
+ m_scrolled = QRegion();
+}
+
+void QQnxRasterWindow::blitPreviousToCurrent(const QRegion &region, int dx, int dy, bool flush)
+{
+ qRasterWindowDebug() << Q_FUNC_INFO << "window =" << window();
+
+ // Abort if previous buffer is invalid or if nothing to copy
+ if (m_previousBufferIndex == -1 || region.isEmpty())
+ return;
+
+ QQnxBuffer &currentBuffer = m_buffers[m_currentBufferIndex];
+ QQnxBuffer &previousBuffer = m_buffers[m_previousBufferIndex];
+
+ // Break down region into non-overlapping rectangles
+ const QVector<QRect> rects = region.rects();
+ for (int i = rects.size() - 1; i >= 0; i--) {
+ // Clip rectangle to bounds of target
+ const QRect rect = rects[i].intersected(currentBuffer.rect());
+
+ if (rect.isEmpty())
+ continue;
+
+ // Setup blit operation
+ int attribs[] = { SCREEN_BLIT_SOURCE_X, rect.x(),
+ SCREEN_BLIT_SOURCE_Y, rect.y(),
+ SCREEN_BLIT_SOURCE_WIDTH, rect.width(),
+ SCREEN_BLIT_SOURCE_HEIGHT, rect.height(),
+ SCREEN_BLIT_DESTINATION_X, rect.x() + dx,
+ SCREEN_BLIT_DESTINATION_Y, rect.y() + dy,
+ SCREEN_BLIT_DESTINATION_WIDTH, rect.width(),
+ SCREEN_BLIT_DESTINATION_HEIGHT, rect.height(),
+ SCREEN_BLIT_END };
+
+ // Queue blit operation
+ errno = 0;
+ const int result = screen_blit(m_screenContext, currentBuffer.nativeBuffer(),
+ previousBuffer.nativeBuffer(), attribs);
+ if (result != 0)
+ qFatal("QQnxWindow: failed to blit buffers, errno=%d", errno);
+ }
+
+ // Check if flush requested
+ if (flush) {
+ // Wait for all blits to complete
+ errno = 0;
+ const int result = screen_flush_blits(m_screenContext, SCREEN_WAIT_IDLE);
+ if (result != 0)
+ qFatal("QQnxWindow: failed to flush blits, errno=%d", errno);
+
+ // Buffer was modified outside the CPU
+ currentBuffer.invalidateInCache();
+ }
+}
+
+QT_END_NAMESPACE