summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
authorFabian Bumberger <fbumberger@rim.com>2013-07-08 11:12:47 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-08-08 12:55:48 +0200
commitf5841521a43b3e3c3f60198079f253b2680ae0b8 (patch)
tree668386f3cca3b40969ae3ac83784763b92776129 /src/plugins/platforms
parent167a4447424de02372d3686bbeccde7234efc42b (diff)
QNX: Enable rendering on different displays using OpenGL
Change-Id: Ife9c090cff732aba42a5cbc04640721e8fdde69d Reviewed-by: Bernd Weimer <bweimer@blackberry.com> Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/qnx/qqnxglcontext.cpp154
-rw-r--r--src/plugins/platforms/qnx/qqnxglcontext.h15
-rw-r--r--src/plugins/platforms/qnx/qqnxscreen.cpp12
-rw-r--r--src/plugins/platforms/qnx/qqnxscreen.h1
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.cpp129
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.h17
6 files changed, 180 insertions, 148 deletions
diff --git a/src/plugins/platforms/qnx/qqnxglcontext.cpp b/src/plugins/platforms/qnx/qqnxglcontext.cpp
index ed959467ff..448509c69d 100644
--- a/src/plugins/platforms/qnx/qqnxglcontext.cpp
+++ b/src/plugins/platforms/qnx/qqnxglcontext.cpp
@@ -60,36 +60,10 @@ QT_BEGIN_NAMESPACE
EGLDisplay QQnxGLContext::ms_eglDisplay = EGL_NO_DISPLAY;
-static EGLenum checkEGLError(const char *msg)
-{
- static const char *errmsg[] =
- {
- "EGL function succeeded",
- "EGL is not initialized, or could not be initialized, for the specified display",
- "EGL cannot access a requested resource",
- "EGL failed to allocate resources for the requested operation",
- "EGL fail to access an unrecognized attribute or attribute value was passed in an attribute list",
- "EGLConfig argument does not name a valid EGLConfig",
- "EGLContext argument does not name a valid EGLContext",
- "EGL current surface of the calling thread is no longer valid",
- "EGLDisplay argument does not name a valid EGLDisplay",
- "EGL arguments are inconsistent",
- "EGLNativePixmapType argument does not refer to a valid native pixmap",
- "EGLNativeWindowType argument does not refer to a valid native window",
- "EGL one or more argument values are invalid",
- "EGLSurface argument does not name a valid surface configured for rendering",
- "EGL power management event has occurred",
- };
- EGLenum error = eglGetError();
- fprintf(stderr, "%s: %s\n", msg, errmsg[error - EGL_SUCCESS]);
- return error;
-}
-
QQnxGLContext::QQnxGLContext(QOpenGLContext *glContext)
: QPlatformOpenGLContext(),
m_glContext(glContext),
- m_eglSurface(EGL_NO_SURFACE),
- m_newSurfaceRequested(true) // Create a surface the first time makeCurrent() is called
+ m_currentEglSurface(EGL_NO_SURFACE)
{
qGLContextDebug() << Q_FUNC_INFO;
QSurfaceFormat format = m_glContext->format();
@@ -168,9 +142,31 @@ QQnxGLContext::~QQnxGLContext()
// Cleanup EGL context if it exists
if (m_eglContext != EGL_NO_CONTEXT)
eglDestroyContext(ms_eglDisplay, m_eglContext);
+}
- // Cleanup EGL surface if it exists
- destroySurface();
+EGLenum QQnxGLContext::checkEGLError(const char *msg)
+{
+ static const char *errmsg[] =
+ {
+ "EGL function succeeded",
+ "EGL is not initialized, or could not be initialized, for the specified display",
+ "EGL cannot access a requested resource",
+ "EGL failed to allocate resources for the requested operation",
+ "EGL fail to access an unrecognized attribute or attribute value was passed in an attribute list",
+ "EGLConfig argument does not name a valid EGLConfig",
+ "EGLContext argument does not name a valid EGLContext",
+ "EGL current surface of the calling thread is no longer valid",
+ "EGLDisplay argument does not name a valid EGLDisplay",
+ "EGL arguments are inconsistent",
+ "EGLNativePixmapType argument does not refer to a valid native pixmap",
+ "EGLNativeWindowType argument does not refer to a valid native window",
+ "EGL one or more argument values are invalid",
+ "EGLSurface argument does not name a valid surface configured for rendering",
+ "EGL power management event has occurred",
+ };
+ EGLenum error = eglGetError();
+ fprintf(stderr, "%s: %s\n", msg, errmsg[error - EGL_SUCCESS]);
+ return error;
}
void QQnxGLContext::initialize()
@@ -199,12 +195,6 @@ void QQnxGLContext::shutdown()
eglTerminate(ms_eglDisplay);
}
-void QQnxGLContext::requestSurfaceChange()
-{
- qGLContextDebug() << Q_FUNC_INFO;
- m_newSurfaceRequested.testAndSetRelease(false, true);
-}
-
bool QQnxGLContext::makeCurrent(QPlatformSurface *surface)
{
qGLContextDebug() << Q_FUNC_INFO;
@@ -216,14 +206,18 @@ bool QQnxGLContext::makeCurrent(QPlatformSurface *surface)
if (eglResult != EGL_TRUE)
qFatal("QQnxGLContext: failed to set EGL API, err=%d", eglGetError());
- if (m_newSurfaceRequested.testAndSetOrdered(true, false)) {
- qGLContextDebug() << "New EGL surface requested";
+ QQnxWindow *platformWindow = dynamic_cast<QQnxWindow*>(surface);
+ if (!platformWindow)
+ return false;
+
+ platformWindow->setPlatformOpenGLContext(this);
+
+ if (m_currentEglSurface == EGL_NO_SURFACE || m_currentEglSurface != platformWindow->getSurface()) {
+ m_currentEglSurface = platformWindow->getSurface();
doneCurrent();
- destroySurface();
- createSurface(surface);
}
- eglResult = eglMakeCurrent(ms_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
+ eglResult = eglMakeCurrent(ms_eglDisplay, m_currentEglSurface, m_currentEglSurface, m_eglContext);
if (eglResult != EGL_TRUE) {
checkEGLError("eglMakeCurrent");
qFatal("QQNX: failed to set current EGL context, err=%d", eglGetError());
@@ -248,18 +242,12 @@ void QQnxGLContext::doneCurrent()
void QQnxGLContext::swapBuffers(QPlatformSurface *surface)
{
- Q_UNUSED(surface);
qGLContextDebug() << Q_FUNC_INFO;
+ QQnxWindow *platformWindow = dynamic_cast<QQnxWindow*>(surface);
+ if (!platformWindow)
+ return;
- // 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(ms_eglDisplay, m_eglSurface);
- if (eglResult != EGL_TRUE)
- qFatal("QQNX: failed to swap EGL buffers, err=%d", eglGetError());
+ platformWindow->swapEGLBuffers();
}
QFunctionPointer QQnxGLContext::getProcAddress(const QByteArray &procName)
@@ -275,6 +263,10 @@ QFunctionPointer QQnxGLContext::getProcAddress(const QByteArray &procName)
return static_cast<QFunctionPointer>(eglGetProcAddress(procName.constData()));
}
+EGLDisplay QQnxGLContext::getEglDisplay() {
+ return ms_eglDisplay;
+}
+
EGLint *QQnxGLContext::contextAttrs()
{
qGLContextDebug() << Q_FUNC_INFO;
@@ -288,66 +280,4 @@ EGLint *QQnxGLContext::contextAttrs()
#endif
}
-bool QQnxGLContext::isCurrent() const
-{
- qGLContextDebug() << Q_FUNC_INFO;
- return (eglGetCurrentContext() == m_eglContext);
-}
-
-void QQnxGLContext::createSurface(QPlatformSurface *surface)
-{
- qGLContextDebug() << Q_FUNC_INFO;
-
- // Get a pointer to the corresponding platform window
- QQnxWindow *platformWindow = dynamic_cast<QQnxWindow*>(surface);
- if (!platformWindow)
- qFatal("QQNX: unable to create EGLSurface without a QQnxWindow");
-
- // Link the window and context
- platformWindow->setPlatformOpenGLContext(this);
-
- // Fetch the surface size from the window and update
- // the window's buffers before we create the EGL surface
- const QSize surfaceSize = platformWindow->requestedBufferSize();
- if (!surfaceSize.isValid()) {
- qFatal("QQNX: Trying to create 0 size EGL surface. "
- "Please set a valid window size before calling QOpenGLContext::makeCurrent()");
- }
- platformWindow->setBufferSize(surfaceSize);
-
- // Post root window, in case it hasn't been posted yet, to make it appear.
- platformWindow->screen()->onWindowPost(platformWindow);
-
- // Obtain the native handle for our window
- screen_window_t handle = platformWindow->nativeHandle();
-
- const EGLint eglSurfaceAttrs[] =
- {
- EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
- EGL_NONE
- };
-
- // Create EGL surface
- m_eglSurface = eglCreateWindowSurface(ms_eglDisplay, m_eglConfig, (EGLNativeWindowType) handle, eglSurfaceAttrs);
- if (m_eglSurface == EGL_NO_SURFACE) {
- checkEGLError("eglCreateWindowSurface");
- qFatal("QQNX: failed to create EGL surface, err=%d", eglGetError());
- }
-}
-
-void QQnxGLContext::destroySurface()
-{
- qGLContextDebug() << Q_FUNC_INFO;
-
- // Destroy EGL surface if it exists
- if (m_eglSurface != EGL_NO_SURFACE) {
- EGLBoolean eglResult = eglDestroySurface(ms_eglDisplay, m_eglSurface);
- if (eglResult != EGL_TRUE) {
- qFatal("QQNX: failed to destroy EGL surface, err=%d", eglGetError());
- }
- }
-
- m_eglSurface = EGL_NO_SURFACE;
-}
-
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxglcontext.h b/src/plugins/platforms/qnx/qqnxglcontext.h
index 6a7fca7df2..ff57861498 100644
--- a/src/plugins/platforms/qnx/qqnxglcontext.h
+++ b/src/plugins/platforms/qnx/qqnxglcontext.h
@@ -59,6 +59,8 @@ public:
QQnxGLContext(QOpenGLContext *glContext);
virtual ~QQnxGLContext();
+ static EGLenum checkEGLError(const char *msg);
+
static void initialize();
static void shutdown();
@@ -71,13 +73,10 @@ public:
virtual QSurfaceFormat format() const { return m_windowFormat; }
- bool isCurrent() const;
-
- void createSurface(QPlatformSurface *surface);
- void destroySurface();
-
+ static EGLDisplay getEglDisplay();
+ EGLConfig getEglConfig() const { return m_eglConfig;}
private:
- /** \todo Should this be non-static so we can use additional displays? */
+ //Can be static because different displays returne the same handle
static EGLDisplay ms_eglDisplay;
QSurfaceFormat m_windowFormat;
@@ -85,9 +84,7 @@ private:
EGLConfig m_eglConfig;
EGLContext m_eglContext;
- EGLSurface m_eglSurface;
-
- QAtomicInt m_newSurfaceRequested;
+ EGLSurface m_currentEglSurface;
static EGLint *contextAttrs();
};
diff --git a/src/plugins/platforms/qnx/qqnxscreen.cpp b/src/plugins/platforms/qnx/qqnxscreen.cpp
index 5aa1257f38..7959617443 100644
--- a/src/plugins/platforms/qnx/qqnxscreen.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreen.cpp
@@ -126,7 +126,6 @@ QQnxScreen::QQnxScreen(screen_context_t screenContext, screen_display_t display,
m_posted(false),
m_keyboardHeight(0),
m_nativeOrientation(Qt::PrimaryOrientation),
- m_platformContext(0),
m_cursor(new QQnxCursor())
{
qScreenDebug() << Q_FUNC_INFO;
@@ -482,9 +481,14 @@ void QQnxScreen::updateHierarchy()
int topZorder;
errno = 0;
- result = screen_get_window_property_iv(rootWindow()->nativeHandle(), SCREEN_PROPERTY_ZORDER, &topZorder);
- if (result != 0)
- qFatal("QQnxScreen: failed to query root window z-order, errno=%d", errno);
+ if (isPrimaryScreen()) {
+ result = screen_get_window_property_iv(rootWindow()->nativeHandle(), SCREEN_PROPERTY_ZORDER, &topZorder);
+ if (result != 0)
+ qFatal("QQnxScreen: failed to query root window z-order, errno=%d", errno);
+ } else {
+ topZorder = 0; //We do not need z ordering on the secondary screen, because only one window
+ //is supported there
+ }
topZorder++; // root window has the lowest z-order in the windowgroup
diff --git a/src/plugins/platforms/qnx/qqnxscreen.h b/src/plugins/platforms/qnx/qqnxscreen.h
index 6e8c2c6a60..e498d27c14 100644
--- a/src/plugins/platforms/qnx/qqnxscreen.h
+++ b/src/plugins/platforms/qnx/qqnxscreen.h
@@ -133,7 +133,6 @@ private:
Qt::ScreenOrientation m_nativeOrientation;
QRect m_initialGeometry;
QRect m_currentGeometry;
- QPlatformOpenGLContext *m_platformContext;
QList<QQnxWindow *> m_childWindows;
QList<screen_window_t> m_overlays;
diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp
index 2bd5cfd801..45e565f24f 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxwindow.cpp
@@ -72,13 +72,15 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context)
m_window(0),
m_currentBufferIndex(-1),
m_previousBufferIndex(-1),
-#if !defined(QT_NO_OPENGL)
- m_platformOpenGLContext(0),
-#endif
m_screen(0),
m_parentWindow(0),
m_visible(false),
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())
{
qWindowDebug() << Q_FUNC_INFO << "window =" << window << ", size =" << window->size();
@@ -86,7 +88,11 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context)
// Create child QNX window
errno = 0;
- result = screen_create_window_type(&m_window, m_screenContext, SCREEN_CHILD_WINDOW);
+ if (static_cast<QQnxScreen *>(window->screen()->handle())->isPrimaryScreen()) {
+ result = screen_create_window_type(&m_window, m_screenContext, SCREEN_CHILD_WINDOW);
+ } else {
+ result = screen_create_window(&m_window, m_screenContext);
+ }
if (result != 0)
qFatal("QQnxWindow: failed to create window, errno=%d", errno);
@@ -172,6 +178,11 @@ 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)
@@ -180,16 +191,16 @@ void QQnxWindow::setGeometry(const QRect &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. The surface will be recreated the
- // next time QQnxGLContext::makeCurrent() is called.
+ // 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_platformOpenGLContext->requestSurfaceChange();
+ if (m_platformOpenGLContext != 0 && bufferSize() != rect.size()) {
+ m_newSurfaceRequested.testAndSetRelease(false, true);
+ }
}
#endif
@@ -517,8 +528,12 @@ void QQnxWindow::setScreen(QQnxScreen *platformScreen)
if (m_screen == platformScreen)
return;
- if (m_screen)
+ if (m_screen) {
+ qWindowDebug() << Q_FUNC_INFO << "Moving window to different screen";
m_screen->removeWindow(this);
+ screen_leave_window_group(m_window);
+ }
+
platformScreen->addWindow(this);
m_screen = platformScreen;
@@ -529,17 +544,20 @@ void QQnxWindow::setScreen(QQnxScreen *platformScreen)
if (result != 0)
qFatal("QQnxWindow: failed to set window display, errno=%d", errno);
- // Add window to display's window group
- errno = 0;
- result = screen_join_window_group(m_window, platformScreen->windowGroupName());
- if (result != 0)
- qFatal("QQnxWindow: failed to join window group, errno=%d", errno);
- Q_FOREACH (QQnxWindow *childWindow, m_childWindows) {
- // Only subwindows and tooltips need necessarily be moved to another display with the window.
- if ((window()->type() & Qt::WindowType_Mask) == Qt::SubWindow ||
- (window()->type() & Qt::WindowType_Mask) == Qt::ToolTip)
- childWindow->setScreen(platformScreen);
+ if (m_screen->isPrimaryScreen()) {
+ // Add window to display's window group
+ errno = 0;
+ result = screen_join_window_group(m_window, platformScreen->windowGroupName());
+ if (result != 0)
+ qFatal("QQnxWindow: failed to join window group, errno=%d", errno);
+
+ Q_FOREACH (QQnxWindow *childWindow, m_childWindows) {
+ // Only subwindows and tooltips need necessarily be moved to another display with the window.
+ if ((window()->type() & Qt::WindowType_Mask) == Qt::SubWindow ||
+ (window()->type() & Qt::WindowType_Mask) == Qt::ToolTip)
+ childWindow->setScreen(platformScreen);
+ }
}
m_screen->updateHierarchy();
@@ -718,6 +736,79 @@ 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()
+{
+ // 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 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());
+}
+
+EGLSurface QQnxWindow::getSurface()
+{
+ if (m_newSurfaceRequested.testAndSetOrdered(true, false)) {
+ if (m_eglSurface != EGL_NO_SURFACE) {
+ platformOpenGLContext()->doneCurrent();
+ destroyEGLSurface();
+ }
+ createEGLSurface();
+ }
+
+ return m_eglSurface;
+}
+#endif
+
void QQnxWindow::updateZorder(int &topZorder)
{
errno = 0;
diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h
index e30a469be7..4fabccf4cb 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.h
+++ b/src/plugins/platforms/qnx/qqnxwindow.h
@@ -120,6 +120,13 @@ public:
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
+
private:
QRect setGeometryHelper(const QRect &rect);
void removeFromParent();
@@ -147,9 +154,6 @@ private:
QRegion m_previousDirty;
QRegion m_scrolled;
-#if !defined(QT_NO_OPENGL)
- QQnxGLContext *m_platformOpenGLContext;
-#endif
QQnxScreen *m_screen;
QList<QQnxWindow*> m_childWindows;
QQnxWindow *m_parentWindow;
@@ -164,6 +168,13 @@ private:
// 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;
};