summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/plugins/platforms/qnx/qnx.pro15
-rw-r--r--src/plugins/platforms/qnx/qqnxeglwindow.cpp204
-rw-r--r--src/plugins/platforms/qnx/qqnxeglwindow.h97
-rw-r--r--src/plugins/platforms/qnx/qqnxglcontext.cpp9
-rw-r--r--src/plugins/platforms/qnx/qqnxintegration.cpp18
-rw-r--r--src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp22
-rw-r--r--src/plugins/platforms/qnx/qqnxrasterbackingstore.h4
-rw-r--r--src/plugins/platforms/qnx/qqnxrasterwindow.cpp234
-rw-r--r--src/plugins/platforms/qnx/qqnxrasterwindow.h82
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.cpp433
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.h75
11 files changed, 718 insertions, 475 deletions
diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro
index 7c497b4434..c9d83272e8 100644
--- a/src/plugins/platforms/qnx/qnx.pro
+++ b/src/plugins/platforms/qnx/qnx.pro
@@ -41,7 +41,8 @@ CONFIG(blackberry) {
#DEFINES += QQNXWINDOW_DEBUG
#DEFINES += QQNXCURSOR_DEBUG
#DEFINES += QQNXFILEPICKER_DEBUG
-
+#DEFINES += QQNXEGLWINDOW_DEBUG
+#DEFINES += QQNXRASTERWINDOW_DEBUG
SOURCES = main.cpp \
qqnxbuffer.cpp \
@@ -56,7 +57,8 @@ SOURCES = main.cpp \
qqnxabstractnavigator.cpp \
qqnxabstractvirtualkeyboard.cpp \
qqnxservices.cpp \
- qqnxcursor.cpp
+ qqnxcursor.cpp \
+ qqnxrasterwindow.cpp
HEADERS = main.h \
qqnxbuffer.h \
@@ -72,7 +74,8 @@ HEADERS = main.h \
qqnxabstractnavigator.h \
qqnxabstractvirtualkeyboard.h \
qqnxservices.h \
- qqnxcursor.h
+ qqnxcursor.h \
+ qqnxrasterwindow.h
CONFIG(qqnx_screeneventthread) {
DEFINES += QQNX_SCREENEVENTTHREAD
@@ -83,9 +86,11 @@ CONFIG(qqnx_screeneventthread) {
LIBS += -lscreen
contains(QT_CONFIG, opengles2) {
- SOURCES += qqnxglcontext.cpp
+ SOURCES += qqnxglcontext.cpp \
+ qqnxeglwindow.cpp
- HEADERS += qqnxglcontext.h
+ HEADERS += qqnxglcontext.h \
+ qqnxeglwindow.h
LIBS += -lEGL
}
diff --git a/src/plugins/platforms/qnx/qqnxeglwindow.cpp b/src/plugins/platforms/qnx/qqnxeglwindow.cpp
new file mode 100644
index 0000000000..9a947d7fad
--- /dev/null
+++ b/src/plugins/platforms/qnx/qqnxeglwindow.cpp
@@ -0,0 +1,204 @@
+/***************************************************************************
+**
+** 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 "qqnxeglwindow.h"
+#include "qqnxscreen.h"
+
+#include <QDebug>
+
+#include <errno.h>
+
+#if defined(QQNXEGLWINDOW_DEBUG)
+#define qEglWindowDebug qDebug
+#else
+#define qEglWindowDebug QT_NO_QDEBUG_MACRO
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QQnxEglWindow::QQnxEglWindow(QWindow *window, screen_context_t context) :
+ QQnxWindow(window, context),
+ m_requestedBufferSize(window->geometry().size()),
+ m_platformOpenGLContext(0),
+ m_newSurfaceRequested(true),
+ m_eglSurface(EGL_NO_SURFACE)
+{
+ initWindow();
+}
+
+QQnxEglWindow::~QQnxEglWindow()
+{
+ // Cleanup EGL surface if it exists
+ destroyEGLSurface();
+}
+
+void QQnxEglWindow::createEGLSurface()
+{
+ // Fetch the surface size from the window and update
+ // the window's buffers before we create the EGL surface
+ const QSize surfaceSize = requestedBufferSize();
+ if (!surfaceSize.isValid()) {
+ qFatal("QQNX: Trying to create 0 size EGL surface. "
+ "Please set a valid window size before calling QOpenGLContext::makeCurrent()");
+ }
+ setBufferSize(surfaceSize);
+
+ const EGLint eglSurfaceAttrs[] =
+ {
+ EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
+ EGL_NONE
+ };
+
+ qEglWindowDebug() << "Creating EGL surface" << platformOpenGLContext()->getEglDisplay()
+ << platformOpenGLContext()->getEglConfig();
+ // Create EGL surface
+ m_eglSurface = eglCreateWindowSurface(platformOpenGLContext()->getEglDisplay()
+ , platformOpenGLContext()->getEglConfig(),
+ (EGLNativeWindowType) nativeHandle(), eglSurfaceAttrs);
+ if (m_eglSurface == EGL_NO_SURFACE) {
+ QQnxGLContext::checkEGLError("eglCreateWindowSurface");
+ qFatal("QQNX: failed to create EGL surface, err=%d", eglGetError());
+ }
+
+ screen()->onWindowPost(0);
+}
+
+void QQnxEglWindow::destroyEGLSurface()
+{
+ // Destroy EGL surface if it exists
+ if (m_eglSurface != EGL_NO_SURFACE) {
+ EGLBoolean eglResult = eglDestroySurface(platformOpenGLContext()->getEglDisplay(), m_eglSurface);
+ if (eglResult != EGL_TRUE)
+ qFatal("QQNX: failed to destroy EGL surface, err=%d", eglGetError());
+ }
+
+ m_eglSurface = EGL_NO_SURFACE;
+}
+
+void QQnxEglWindow::swapEGLBuffers()
+{
+ qEglWindowDebug() << Q_FUNC_INFO;
+ // Set current rendering API
+ EGLBoolean eglResult = eglBindAPI(EGL_OPENGL_ES_API);
+ if (eglResult != EGL_TRUE)
+ qFatal("QQNX: failed to set EGL API, err=%d", eglGetError());
+
+ // Post EGL surface to window
+ eglResult = eglSwapBuffers(m_platformOpenGLContext->getEglDisplay(), m_eglSurface);
+ if (eglResult != EGL_TRUE)
+ qFatal("QQNX: failed to swap EGL buffers, err=%d", eglGetError());
+}
+
+EGLSurface QQnxEglWindow::getSurface()
+{
+ if (m_newSurfaceRequested.testAndSetOrdered(true, false)) {
+ if (m_eglSurface != EGL_NO_SURFACE) {
+ platformOpenGLContext()->doneCurrent();
+ destroyEGLSurface();
+ }
+ createEGLSurface();
+ }
+
+ return m_eglSurface;
+}
+
+void QQnxEglWindow::setGeometry(const QRect &rect)
+{
+ //We need to request that the GL context updates
+ // the EGLsurface on which it is rendering.
+ {
+ // We want the setting of the atomic bool in the GL context to be atomic with
+ // setting m_requestedBufferSize and therefore extended the scope to include
+ // that test.
+ const QMutexLocker locker(&m_mutex);
+ m_requestedBufferSize = rect.size();
+ if (m_platformOpenGLContext != 0 && bufferSize() != rect.size())
+ m_newSurfaceRequested.testAndSetRelease(false, true);
+ }
+ QQnxWindow::setGeometry(rect);
+}
+
+QSize QQnxEglWindow::requestedBufferSize() const
+{
+ const QMutexLocker locker(&m_mutex);
+ return m_requestedBufferSize;
+}
+
+void QQnxEglWindow::setPlatformOpenGLContext(QQnxGLContext *platformOpenGLContext)
+{
+ // This function does not take ownership of the platform gl context.
+ // It is owned by the frontend QOpenGLContext
+ m_platformOpenGLContext = platformOpenGLContext;
+}
+
+int QQnxEglWindow::pixelFormat() const
+{
+ const QSurfaceFormat format = m_platformOpenGLContext->format();
+ // Extract size of color channels from window format
+ const int redSize = format.redBufferSize();
+ if (redSize == -1)
+ qFatal("QQnxWindow: red size not defined");
+
+ const int greenSize = format.greenBufferSize();
+ if (greenSize == -1)
+ qFatal("QQnxWindow: green size not defined");
+
+ const int blueSize = format.blueBufferSize();
+ if (blueSize == -1)
+ qFatal("QQnxWindow: blue size not defined");
+
+ // select matching native format
+ if (redSize == 5 && greenSize == 6 && blueSize == 5)
+ return SCREEN_FORMAT_RGB565;
+ else if (redSize == 8 && greenSize == 8 && blueSize == 8)
+ return SCREEN_FORMAT_RGBA8888;
+
+ qFatal("QQnxWindow: unsupported pixel format");
+}
+
+void QQnxEglWindow::resetBuffers()
+{
+ const QMutexLocker locker(&m_mutex);
+ m_requestedBufferSize = QSize();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxeglwindow.h b/src/plugins/platforms/qnx/qqnxeglwindow.h
new file mode 100644
index 0000000000..e7dae6a458
--- /dev/null
+++ b/src/plugins/platforms/qnx/qqnxeglwindow.h
@@ -0,0 +1,97 @@
+/***************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QQNXEGLWINDOW_H
+#define QQNXEGLWINDOW_H
+
+#include "qqnxwindow.h"
+#include "qqnxglcontext.h"
+
+#include <QtCore/QMutex>
+
+QT_BEGIN_NAMESPACE
+
+class QQnxGLContext;
+
+class QQnxEglWindow : public QQnxWindow
+{
+public:
+ QQnxEglWindow(QWindow *window, screen_context_t context);
+ ~QQnxEglWindow();
+
+ void createEGLSurface();
+ void destroyEGLSurface();
+ void swapEGLBuffers();
+ EGLSurface getSurface();
+
+ void setPlatformOpenGLContext(QQnxGLContext *platformOpenGLContext);
+ QQnxGLContext *platformOpenGLContext() const { return m_platformOpenGLContext; }
+
+ void setGeometry(const QRect &rect);
+
+ // Called by QQnxGLContext::createSurface()
+ QSize requestedBufferSize() const;
+
+ WindowType windowType() const Q_DECL_OVERRIDE { return EGL; }
+
+protected:
+ int pixelFormat() const;
+ void resetBuffers();
+
+private:
+ QSize m_requestedBufferSize;
+
+ // This mutex is used to protect access to the m_requestedBufferSize
+ // member. This member is used in conjunction with QQnxGLContext::requestNewSurface()
+ // to coordinate recreating the EGL surface which involves destroying any
+ // existing EGL surface; resizing the native window buffers; and creating a new
+ // EGL surface. All of this has to be done from the thread that is calling
+ // QQnxGLContext::makeCurrent()
+ mutable QMutex m_mutex;
+
+ QQnxGLContext *m_platformOpenGLContext;
+ QAtomicInt m_newSurfaceRequested;
+ EGLSurface m_eglSurface;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQNXEGLWINDOW_H
diff --git a/src/plugins/platforms/qnx/qqnxglcontext.cpp b/src/plugins/platforms/qnx/qqnxglcontext.cpp
index 448509c69d..355f52c46e 100644
--- a/src/plugins/platforms/qnx/qqnxglcontext.cpp
+++ b/src/plugins/platforms/qnx/qqnxglcontext.cpp
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2012 Research In Motion
+** Copyright (C) 2011 - 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -40,9 +40,8 @@
****************************************************************************/
#include "qqnxglcontext.h"
-#include "qqnxrootwindow.h"
#include "qqnxscreen.h"
-#include "qqnxwindow.h"
+#include "qqnxeglwindow.h"
#include "private/qeglconvenience_p.h"
@@ -206,7 +205,7 @@ bool QQnxGLContext::makeCurrent(QPlatformSurface *surface)
if (eglResult != EGL_TRUE)
qFatal("QQnxGLContext: failed to set EGL API, err=%d", eglGetError());
- QQnxWindow *platformWindow = dynamic_cast<QQnxWindow*>(surface);
+ QQnxEglWindow *platformWindow = dynamic_cast<QQnxEglWindow*>(surface);
if (!platformWindow)
return false;
@@ -243,7 +242,7 @@ void QQnxGLContext::doneCurrent()
void QQnxGLContext::swapBuffers(QPlatformSurface *surface)
{
qGLContextDebug() << Q_FUNC_INFO;
- QQnxWindow *platformWindow = dynamic_cast<QQnxWindow*>(surface);
+ QQnxEglWindow *platformWindow = dynamic_cast<QQnxEglWindow*>(surface);
if (!platformWindow)
return;
diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp
index fa9961ccce..bd627fef0b 100644
--- a/src/plugins/platforms/qnx/qqnxintegration.cpp
+++ b/src/plugins/platforms/qnx/qqnxintegration.cpp
@@ -53,6 +53,11 @@
#include "qqnxabstractvirtualkeyboard.h"
#include "qqnxservices.h"
+#include "qqnxrasterwindow.h"
+#if !defined(QT_NO_OPENGL)
+#include "qqnxeglwindow.h"
+#endif
+
#if defined(Q_OS_BLACKBERRY)
#include "qqnxbpseventfilter.h"
#include "qqnxnavigatorbps.h"
@@ -331,7 +336,18 @@ bool QQnxIntegration::hasCapability(QPlatformIntegration::Capability cap) const
QPlatformWindow *QQnxIntegration::createPlatformWindow(QWindow *window) const
{
qIntegrationDebug() << Q_FUNC_INFO;
- return new QQnxWindow(window, m_screenContext);
+ QSurface::SurfaceType surfaceType = window->surfaceType();
+ switch (surfaceType) {
+ case QSurface::RasterSurface:
+ return new QQnxRasterWindow(window, m_screenContext);
+#if !defined(QT_NO_OPENGL)
+ case QSurface::OpenGLSurface:
+ return new QQnxEglWindow(window, m_screenContext);
+#endif
+ default:
+ qFatal("QQnxWindow: unsupported window API");
+ }
+ return 0;
}
QPlatformBackingStore *QQnxIntegration::createPlatformBackingStore(QWindow *window) const
diff --git a/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp b/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp
index 5481b118e8..57914cf2fb 100644
--- a/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp
+++ b/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2012 Research In Motion
+** Copyright (C) 2011 - 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -40,7 +40,7 @@
****************************************************************************/
#include "qqnxrasterbackingstore.h"
-#include "qqnxwindow.h"
+#include "qqnxrasterwindow.h"
#include <QtCore/QDebug>
@@ -70,15 +70,16 @@ QQnxRasterBackingStore::~QQnxRasterBackingStore()
QPaintDevice *QQnxRasterBackingStore::paintDevice()
{
- QQnxWindow *platformWindow = this->platformWindow();
- if (platformWindow->hasBuffers())
- return platformWindow->renderBuffer().image();
+ if (platformWindow() && platformWindow()->hasBuffers())
+ return platformWindow()->renderBuffer().image();
return 0;
}
void QQnxRasterBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
{
+ Q_UNUSED(offset)
+
qRasterBackingStoreDebug() << Q_FUNC_INFO << "w =" << this->window();
// Sometimes this method is called even though there is nothing to be
@@ -96,8 +97,7 @@ void QQnxRasterBackingStore::flush(QWindow *window, const QRegion &region, const
// child windows, are performed; conceptually ,child windows have no buffers
// (actually they do have a 1x1 placeholder buffer due to libscreen limitations),
// since Qt will only draw to the backing store of the top-level window.
- QQnxWindow *platformWindow = this->platformWindow();
- if (!targetWindow || targetWindow == platformWindow) {
+ if (!targetWindow || targetWindow == platformWindow()) {
// visit all pending scroll operations
for (int i = m_scrollOpList.size() - 1; i >= 0; i--) {
@@ -105,14 +105,14 @@ void QQnxRasterBackingStore::flush(QWindow *window, const QRegion &region, const
// do the scroll operation
ScrollOp &op = m_scrollOpList[i];
QRegion srcArea = op.totalArea.intersected( op.totalArea.translated(-op.dx, -op.dy) );
- platformWindow->scroll(srcArea, op.dx, op.dy);
+ platformWindow()->scroll(srcArea, op.dx, op.dy);
}
// clear all pending scroll operations
m_scrollOpList.clear();
// update the display with newly rendered content
- platformWindow->post(region);
+ platformWindow()->post(region);
}
m_hasUnflushedPaintOperations = false;
@@ -174,10 +174,10 @@ void QQnxRasterBackingStore::endPaint()
qRasterBackingStoreDebug() << Q_FUNC_INFO << "w =" << window();
}
-QQnxWindow *QQnxRasterBackingStore::platformWindow() const
+QQnxRasterWindow *QQnxRasterBackingStore::platformWindow() const
{
Q_ASSERT(m_window->handle());
- return static_cast<QQnxWindow*>(m_window->handle());
+ return static_cast<QQnxRasterWindow*>(m_window->handle());
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxrasterbackingstore.h b/src/plugins/platforms/qnx/qqnxrasterbackingstore.h
index 4e682aa52d..35efd68571 100644
--- a/src/plugins/platforms/qnx/qqnxrasterbackingstore.h
+++ b/src/plugins/platforms/qnx/qqnxrasterbackingstore.h
@@ -48,7 +48,7 @@
QT_BEGIN_NAMESPACE
-class QQnxWindow;
+class QQnxRasterWindow;
class QQnxRasterBackingStore : public QPlatformBackingStore
{
@@ -72,7 +72,7 @@ private:
int dy;
};
- QQnxWindow *platformWindow() const;
+ QQnxRasterWindow *platformWindow() const;
QWindow *m_window;
QList<ScrollOp> m_scrollOpList;
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
diff --git a/src/plugins/platforms/qnx/qqnxrasterwindow.h b/src/plugins/platforms/qnx/qqnxrasterwindow.h
new file mode 100644
index 0000000000..8bd42bc320
--- /dev/null
+++ b/src/plugins/platforms/qnx/qqnxrasterwindow.h
@@ -0,0 +1,82 @@
+/***************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QQNXRASTERWINDOW_H
+#define QQNXRASTERWINDOW_H
+
+#include "qqnxwindow.h"
+#include "qqnxbuffer.h"
+
+QT_BEGIN_NAMESPACE
+
+class QQnxRasterWindow : public QQnxWindow
+{
+public:
+ QQnxRasterWindow(QWindow *window, screen_context_t context);
+
+ void post(const QRegion &dirty);
+
+ void scroll(const QRegion &region, int dx, int dy, bool flush=false);
+
+ QQnxBuffer &renderBuffer();
+
+ bool hasBuffers() const { return !bufferSize().isEmpty(); }
+
+ WindowType windowType() const Q_DECL_OVERRIDE { return Raster; }
+
+protected:
+ int pixelFormat() const;
+ void resetBuffers();
+
+ // Copies content from the previous buffer (back buffer) to the current buffer (front buffer)
+ void blitPreviousToCurrent(const QRegion &region, int dx, int dy, bool flush=false);
+
+private:
+ QRegion m_previousDirty;
+ QRegion m_scrolled;
+ int m_currentBufferIndex;
+ int m_previousBufferIndex;
+ QQnxBuffer m_buffers[MAX_BUFFER_COUNT];
+};
+
+QT_END_NAMESPACE
+
+#endif // QQNXRASTERWINDOW_H
diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp
index 61b13099fd..a5e899aa7e 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxwindow.cpp
@@ -70,19 +70,11 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context)
: QPlatformWindow(window),
m_screenContext(context),
m_window(0),
- m_currentBufferIndex(-1),
- m_previousBufferIndex(-1),
m_screen(0),
m_parentWindow(0),
m_visible(false),
m_exposed(true),
- m_windowState(Qt::WindowNoState),
-#if !defined(QT_NO_OPENGL)
- m_platformOpenGLContext(0),
- m_newSurfaceRequested(true),
- m_eglSurface(EGL_NO_SURFACE),
-#endif
- m_requestedBufferSize(window->geometry().size())
+ m_windowState(Qt::WindowNoState)
{
qWindowDebug() << Q_FUNC_INFO << "window =" << window << ", size =" << window->size();
int result;
@@ -96,70 +88,6 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context)
}
if (result != 0)
qFatal("QQnxWindow: failed to create window, errno=%d", errno);
-
- // Set window buffer usage based on rendering API
- int val;
- QSurface::SurfaceType surfaceType = window->surfaceType();
- switch (surfaceType) {
- case QSurface::RasterSurface:
- val = SCREEN_USAGE_NATIVE | SCREEN_USAGE_READ | SCREEN_USAGE_WRITE;
- break;
- case QSurface::OpenGLSurface:
- val = SCREEN_USAGE_OPENGL_ES2;
- break;
- default:
- qFatal("QQnxWindow: unsupported window API");
- break;
- }
-
- errno = 0;
- result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_USAGE, &val);
- if (result != 0)
- qFatal("QQnxWindow: failed to set window buffer usage, errno=%d", errno);
-
- // Alpha channel is always pre-multiplied if present
- errno = 0;
- val = SCREEN_PRE_MULTIPLIED_ALPHA;
- result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_ALPHA_MODE, &val);
- if (result != 0)
- qFatal("QQnxWindow: failed to set window alpha mode, errno=%d", errno);
-
- // Blend the window with Source Over Porter-Duff behavior onto whatever's
- // behind it.
- //
- // If the desired use-case is opaque, the Widget painting framework will
- // already fill in the alpha channel with full opacity.
- errno = 0;
- val = SCREEN_TRANSPARENCY_SOURCE_OVER;
- result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_TRANSPARENCY, &val);
- if (result != 0)
- qFatal("QQnxWindow: failed to set window transparency, errno=%d", errno);
-
- // Set the window swap interval
- errno = 0;
- val = 1;
- result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SWAP_INTERVAL, &val);
- if (result != 0)
- qFatal("QQnxWindow: failed to set window swap interval, errno=%d", errno);
-
- if (window->flags() & Qt::WindowDoesNotAcceptFocus) {
- errno = 0;
- val = SCREEN_SENSITIVITY_NO_FOCUS;
- result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SENSITIVITY, &val);
- if (result != 0)
- qFatal("QQnxWindow: failed to set window sensitivity, errno=%d", errno);
- }
-
- setScreen(static_cast<QQnxScreen *>(window->screen()->handle()));
-
- // Add window to plugin's window mapper
- QQnxIntegration::addWindow(m_window, window);
-
- // Qt never calls these setters after creating the window, so we need to do that ourselves here
- setWindowState(window->windowState());
- if (window->parent() && window->parent()->handle())
- setParent(window->parent()->handle());
- setGeometryHelper(window->geometry());
}
QQnxWindow::~QQnxWindow()
@@ -179,32 +107,12 @@ QQnxWindow::~QQnxWindow()
// Cleanup QNX window and its buffers
screen_destroy_window(m_window);
-
-#if !defined(QT_NO_OPENGL)
- // Cleanup EGL surface if it exists
- destroyEGLSurface();
-#endif
}
void QQnxWindow::setGeometry(const QRect &rect)
{
const QRect oldGeometry = setGeometryHelper(rect);
-#if !defined(QT_NO_OPENGL)
- // If this is an OpenGL window we need to request that the GL context updates
- // the EGLsurface on which it is rendering.
- {
- // We want the setting of the atomic bool in the GL context to be atomic with
- // setting m_requestedBufferSize and therefore extended the scope to include
- // that test.
- const QMutexLocker locker(&m_mutex);
- m_requestedBufferSize = rect.size();
- if (m_platformOpenGLContext != 0 && bufferSize() != rect.size()) {
- m_newSurfaceRequested.testAndSetRelease(false, true);
- }
- }
-#endif
-
// Send a geometry change event to Qt (triggers resizeEvent() in QWindow/QWidget).
// Calling flushWindowSystemEvents() here would flush input events which
@@ -350,12 +258,6 @@ bool QQnxWindow::isExposed() const
return m_visible && m_exposed;
}
-QSize QQnxWindow::requestedBufferSize() const
-{
- const QMutexLocker locker(&m_mutex);
- return m_requestedBufferSize;
-}
-
void QQnxWindow::adjustBufferSize()
{
if (m_parentWindow)
@@ -383,13 +285,7 @@ void QQnxWindow::setBufferSize(const QSize &size)
// Create window buffers if they do not exist
if (m_bufferSize.isEmpty()) {
- val[0] = m_screen->nativeFormat();
-#if !defined(QT_NO_OPENGL)
- // Get pixel format from EGL config if using OpenGL;
- // otherwise inherit pixel format of window's screen
- if (m_platformOpenGLContext != 0)
- val[0] = platformWindowFormatToNativeFormat(m_platformOpenGLContext->format());
-#endif
+ val[0] = pixelFormat();
errno = 0;
result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_FORMAT, val);
@@ -424,119 +320,7 @@ void QQnxWindow::setBufferSize(const QSize &size)
// Cache new buffer size
m_bufferSize = nonEmptySize;
-
- // Buffers were destroyed; reacquire them
- m_currentBufferIndex = -1;
- m_previousDirty = QRegion();
- m_scrolled = QRegion();
-
- const QMutexLocker locker(&m_mutex);
- m_requestedBufferSize = QSize();
-}
-
-QQnxBuffer &QQnxWindow::renderBuffer()
-{
- qWindowDebug() << 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(m_window, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)buffers);
- if (result != 0)
- qFatal("QQnxWindow: 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(m_screen->nativeContext(), buffers[i], bg);
- if (result != 0)
- qFatal("QQnxWindow: failed to clear window buffer, errno=%d", errno);
- }
-
- errno = 0;
- result = screen_flush_blits(m_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];
-}
-
-void QQnxWindow::scroll(const QRegion &region, int dx, int dy, bool flush)
-{
- qWindowDebug() << Q_FUNC_INFO << "window =" << window();
- blitPreviousToCurrent(region, dx, dy, flush);
- m_scrolled += region;
-}
-
-void QQnxWindow::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()) {
- qWindowDebug() << 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(m_window, 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 (m_screen != 0)
- m_screen->onWindowPost(this);
- }
+ resetBuffers();
}
void QQnxWindow::setScreen(QQnxScreen *platformScreen)
@@ -702,15 +486,6 @@ void QQnxWindow::gainedFocus()
QWindowSystemInterface::handleWindowActivated(window());
}
-#if !defined(QT_NO_OPENGL)
-void QQnxWindow::setPlatformOpenGLContext(QQnxGLContext *platformOpenGLContext)
-{
- // This function does not take ownership of the platform gl context.
- // It is owned by the frontend QOpenGLContext
- m_platformOpenGLContext = platformOpenGLContext;
-}
-#endif
-
QQnxWindow *QQnxWindow::findWindow(screen_window_t windowHandle)
{
if (m_window == windowHandle)
@@ -725,19 +500,6 @@ 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::minimize()
{
#if defined(Q_OS_BLACKBERRY) && !defined(Q_OS_BLACKBERRY_TABLET)
@@ -759,78 +521,53 @@ void QQnxWindow::minimize()
#endif
}
-#if !defined(QT_NO_OPENGL)
-void QQnxWindow::createEGLSurface()
-{
- // Fetch the surface size from the window and update
- // the window's buffers before we create the EGL surface
- const QSize surfaceSize = requestedBufferSize();
- if (!surfaceSize.isValid()) {
- qFatal("QQNX: Trying to create 0 size EGL surface. "
- "Please set a valid window size before calling QOpenGLContext::makeCurrent()");
- }
- setBufferSize(surfaceSize);
-
- // Post root window, in case it hasn't been posted yet, to make it appear.
- screen()->onWindowPost(0);
-
- const EGLint eglSurfaceAttrs[] =
- {
- EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
- EGL_NONE
- };
-
- qWindowDebug() << "Creating EGL surface" << platformOpenGLContext()->getEglDisplay()
- << platformOpenGLContext()->getEglConfig();
- // Create EGL surface
- m_eglSurface = eglCreateWindowSurface(platformOpenGLContext()->getEglDisplay()
- , platformOpenGLContext()->getEglConfig(),
- (EGLNativeWindowType) m_window, eglSurfaceAttrs);
- if (m_eglSurface == EGL_NO_SURFACE) {
- QQnxGLContext::checkEGLError("eglCreateWindowSurface");
- qFatal("QQNX: failed to create EGL surface, err=%d", eglGetError());
- }
-}
-
-void QQnxWindow::destroyEGLSurface()
+void QQnxWindow::initWindow()
{
- // Destroy EGL surface if it exists
- if (m_eglSurface != EGL_NO_SURFACE) {
- EGLBoolean eglResult = eglDestroySurface(platformOpenGLContext()->getEglDisplay(), m_eglSurface);
- if (eglResult != EGL_TRUE)
- qFatal("QQNX: failed to destroy EGL surface, err=%d", eglGetError());
- }
+ // Alpha channel is always pre-multiplied if present
+ errno = 0;
+ int val = SCREEN_PRE_MULTIPLIED_ALPHA;
+ int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_ALPHA_MODE, &val);
+ if (result != 0)
+ qFatal("QQnxWindow: failed to set window alpha mode, errno=%d", errno);
- m_eglSurface = EGL_NO_SURFACE;
-}
+ // Blend the window with Source Over Porter-Duff behavior onto whatever's
+ // behind it.
+ //
+ // If the desired use-case is opaque, the Widget painting framework will
+ // already fill in the alpha channel with full opacity.
+ errno = 0;
+ val = SCREEN_TRANSPARENCY_SOURCE_OVER;
+ result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_TRANSPARENCY, &val);
+ if (result != 0)
+ qFatal("QQnxWindow: failed to set window transparency, errno=%d", errno);
-void QQnxWindow::swapEGLBuffers()
-{
- qWindowDebug() << Q_FUNC_INFO;
- // Set current rendering API
- EGLBoolean eglResult = eglBindAPI(EGL_OPENGL_ES_API);
- if (eglResult != EGL_TRUE)
- qFatal("QQNX: failed to set EGL API, err=%d", eglGetError());
-
- // Post EGL surface to window
- eglResult = eglSwapBuffers(m_platformOpenGLContext->getEglDisplay(), m_eglSurface);
- if (eglResult != EGL_TRUE)
- qFatal("QQNX: failed to swap EGL buffers, err=%d", eglGetError());
-}
+ // Set the window swap interval
+ errno = 0;
+ val = 1;
+ result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SWAP_INTERVAL, &val);
+ if (result != 0)
+ qFatal("QQnxWindow: failed to set window swap interval, errno=%d", errno);
-EGLSurface QQnxWindow::getSurface()
-{
- if (m_newSurfaceRequested.testAndSetOrdered(true, false)) {
- if (m_eglSurface != EGL_NO_SURFACE) {
- platformOpenGLContext()->doneCurrent();
- destroyEGLSurface();
- }
- createEGLSurface();
+ if (window()->flags() & Qt::WindowDoesNotAcceptFocus) {
+ errno = 0;
+ val = SCREEN_SENSITIVITY_NO_FOCUS;
+ result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SENSITIVITY, &val);
+ if (result != 0)
+ qFatal("QQnxWindow: failed to set window sensitivity, errno=%d", errno);
}
- return m_eglSurface;
+ setScreen(static_cast<QQnxScreen *>(window()->screen()->handle()));
+
+ // Add window to plugin's window mapper
+ QQnxIntegration::addWindow(m_window, window());
+
+ // Qt never calls these setters after creating the window, so we need to do that ourselves here
+ setWindowState(window()->windowState());
+ if (window()->parent() && window()->parent()->handle())
+ setParent(window()->parent()->handle());
+ setGeometryHelper(window()->geometry());
}
-#endif
+
void QQnxWindow::updateZorder(int &topZorder)
{
@@ -876,89 +613,5 @@ void QQnxWindow::applyWindowState()
}
}
-void QQnxWindow::blitHelper(QQnxBuffer &source, QQnxBuffer &target, const QPoint &sourceOffset,
- const QPoint &targetOffset, const QRegion &region, bool flush)
-{
- // 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(target.rect());
-
- if (rect.isEmpty())
- continue;
-
- // Setup blit operation
- int attribs[] = { SCREEN_BLIT_SOURCE_X, rect.x() + sourceOffset.x(),
- SCREEN_BLIT_SOURCE_Y, rect.y() + sourceOffset.y(),
- SCREEN_BLIT_SOURCE_WIDTH, rect.width(),
- SCREEN_BLIT_SOURCE_HEIGHT, rect.height(),
- SCREEN_BLIT_DESTINATION_X, rect.x() + targetOffset.x(),
- SCREEN_BLIT_DESTINATION_Y, rect.y() + targetOffset.y(),
- 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, target.nativeBuffer(),
- source.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
- target.invalidateInCache();
- }
-}
-
-void QQnxWindow::blitPreviousToCurrent(const QRegion &region, int dx, int dy, bool flush)
-{
- qWindowDebug() << 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];
-
- blitHelper(previousBuffer, currentBuffer, QPoint(0, 0), QPoint(dx, dy), region, flush);
-}
-
-int QQnxWindow::platformWindowFormatToNativeFormat(const QSurfaceFormat &format)
-{
- qWindowDebug() << Q_FUNC_INFO;
- // Extract size of colour channels from window format
- int redSize = format.redBufferSize();
- if (redSize == -1)
- qFatal("QQnxWindow: red size not defined");
-
- int greenSize = format.greenBufferSize();
- if (greenSize == -1)
- qFatal("QQnxWindow: green size not defined");
-
- int blueSize = format.blueBufferSize();
- if (blueSize == -1)
- qFatal("QQnxWindow: blue size not defined");
-
- // select matching native format
- if (redSize == 5 && greenSize == 6 && blueSize == 5) {
- return SCREEN_FORMAT_RGB565;
- } else if (redSize == 8 && greenSize == 8 && blueSize == 8) {
- return SCREEN_FORMAT_RGBA8888;
- } else {
- qFatal("QQnxWindow: unsupported pixel format");
- return 0;
- }
-}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h
index cd1980d994..a63a215511 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.h
+++ b/src/plugins/platforms/qnx/qqnxwindow.h
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2012 Research In Motion
+** Copyright (C) 2011 - 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -44,11 +44,6 @@
#include <qpa/qplatformwindow.h>
-#include "qqnxbuffer.h"
-
-#include <QtGui/QImage>
-#include <QtCore/QMutex>
-
#if !defined(QT_NO_OPENGL)
#include <EGL/egl.h>
#endif
@@ -60,9 +55,6 @@ QT_BEGIN_NAMESPACE
// all surfaces double buffered
#define MAX_BUFFER_COUNT 2
-#if !defined(QT_NO_OPENGL)
-class QQnxGLContext;
-#endif
class QQnxScreen;
class QSurfaceFormat;
@@ -71,6 +63,11 @@ class QQnxWindow : public QPlatformWindow
{
friend class QQnxScreen;
public:
+ enum WindowType {
+ EGL,
+ Raster
+ };
+
QQnxWindow(QWindow *window, screen_context_t context);
virtual ~QQnxWindow();
@@ -83,17 +80,9 @@ public:
WId winId() const { return (WId)m_window; }
screen_window_t nativeHandle() const { return m_window; }
- // Called by QQnxGLContext::createSurface()
- QSize requestedBufferSize() const;
-
void adjustBufferSize();
void setBufferSize(const QSize &size);
QSize bufferSize() const { return m_bufferSize; }
- bool hasBuffers() const { return !m_bufferSize.isEmpty(); }
-
- QQnxBuffer &renderBuffer();
- void scroll(const QRegion &region, int dx, int dy, bool flush=false);
- void post(const QRegion &dirty);
void setScreen(QQnxScreen *platformScreen);
@@ -111,22 +100,18 @@ public:
QQnxScreen *screen() const { return m_screen; }
const QList<QQnxWindow*>& children() const { return m_childWindows; }
-#if !defined(QT_NO_OPENGL)
- void setPlatformOpenGLContext(QQnxGLContext *platformOpenGLContext);
- QQnxGLContext *platformOpenGLContext() const { return m_platformOpenGLContext; }
-#endif
-
QQnxWindow *findWindow(screen_window_t windowHandle);
- void blitFrom(QQnxWindow *sourceWindow, const QPoint &sourceOffset, const QRegion &targetRegion);
void minimize();
-#if !defined(QT_NO_OPENGL)
- void createEGLSurface();
- void destroyEGLSurface();
- void swapEGLBuffers();
- EGLSurface getSurface();
-#endif
+ virtual WindowType windowType() const = 0;
+protected:
+ virtual int pixelFormat() const = 0;
+ virtual void resetBuffers() = 0;
+
+ void initWindow();
+
+ screen_context_t m_screenContext;
private:
QRect setGeometryHelper(const QRect &rect);
@@ -136,24 +121,8 @@ private:
void updateZorder(int &topZorder);
void applyWindowState();
- void fetchBuffers();
-
- // Copies content from the previous buffer (back buffer) to the current buffer (front buffer)
- void blitPreviousToCurrent(const QRegion &region, int dx, int dy, bool flush=false);
-
- void blitHelper(QQnxBuffer &source, QQnxBuffer &target, const QPoint &sourceOffset,
- const QPoint &targetOffset, const QRegion &region, bool flush = false);
-
- static int platformWindowFormatToNativeFormat(const QSurfaceFormat &format);
-
- screen_context_t m_screenContext;
screen_window_t m_window;
QSize m_bufferSize;
- QQnxBuffer m_buffers[MAX_BUFFER_COUNT];
- int m_currentBufferIndex;
- int m_previousBufferIndex;
- QRegion m_previousDirty;
- QRegion m_scrolled;
QQnxScreen *m_screen;
QList<QQnxWindow*> m_childWindows;
@@ -162,22 +131,6 @@ private:
bool m_exposed;
QRect m_unmaximizedGeometry;
Qt::WindowState m_windowState;
-
- // This mutex is used to protect access to the m_requestedBufferSize
- // member. This member is used in conjunction with QQnxGLContext::requestNewSurface()
- // to coordinate recreating the EGL surface which involves destroying any
- // existing EGL surface; resizing the native window buffers; and creating a new
- // EGL surface. All of this has to be done from the thread that is calling
- // QQnxGLContext::makeCurrent()
- mutable QMutex m_mutex;
-
-#if !defined(QT_NO_OPENGL)
- QQnxGLContext *m_platformOpenGLContext;
- QAtomicInt m_newSurfaceRequested;
- EGLSurface m_eglSurface;
-#endif
-
- QSize m_requestedBufferSize;
};
QT_END_NAMESPACE