From 1f040d401d322cec9dc56c93e78899a429cb6e5a Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 16 Sep 2014 14:12:54 +0200 Subject: eglfs: Add support for systems without pbuffer support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use a small native window and window surface in case the hooks indicate that pbuffer support is not available. Change-Id: I6515309041f0e1e2f5321d59941f35d6ee16dca7 Reviewed-by: Louai Al-Khanji Reviewed-by: Jørgen Lind --- src/plugins/platforms/eglfs/eglfs.pri | 6 +- src/plugins/platforms/eglfs/qeglfscontext.cpp | 30 +++++++- src/plugins/platforms/eglfs/qeglfscontext.h | 5 ++ src/plugins/platforms/eglfs/qeglfshooks.h | 3 + src/plugins/platforms/eglfs/qeglfshooks_kms.cpp | 19 +++++ src/plugins/platforms/eglfs/qeglfshooks_stub.cpp | 11 +++ src/plugins/platforms/eglfs/qeglfsintegration.cpp | 13 +++- .../platforms/eglfs/qeglfsoffscreenwindow.cpp | 85 ++++++++++++++++++++++ .../platforms/eglfs/qeglfsoffscreenwindow.h | 68 +++++++++++++++++ src/plugins/platforms/qnx/qqnxglcontext.cpp | 4 +- src/plugins/platforms/qnx/qqnxglcontext.h | 4 +- src/plugins/platforms/qnx/qqnxintegration.cpp | 4 +- 12 files changed, 240 insertions(+), 12 deletions(-) create mode 100644 src/plugins/platforms/eglfs/qeglfsoffscreenwindow.cpp create mode 100644 src/plugins/platforms/eglfs/qeglfsoffscreenwindow.h (limited to 'src/plugins') diff --git a/src/plugins/platforms/eglfs/eglfs.pri b/src/plugins/platforms/eglfs/eglfs.pri index 6f463ba7d9..182539d8fe 100644 --- a/src/plugins/platforms/eglfs/eglfs.pri +++ b/src/plugins/platforms/eglfs/eglfs.pri @@ -17,13 +17,15 @@ SOURCES += $$PWD/qeglfsintegration.cpp \ $$PWD/qeglfswindow.cpp \ $$PWD/qeglfsscreen.cpp \ $$PWD/qeglfshooks_stub.cpp \ - $$PWD/qeglfscontext.cpp + $$PWD/qeglfscontext.cpp \ + $$PWD/qeglfsoffscreenwindow.cpp HEADERS += $$PWD/qeglfsintegration.h \ $$PWD/qeglfswindow.h \ $$PWD/qeglfsscreen.h \ $$PWD/qeglfshooks.h \ - $$PWD/qeglfscontext.h + $$PWD/qeglfscontext.h \ + $$PWD/qeglfsoffscreenwindow.h QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF diff --git a/src/plugins/platforms/eglfs/qeglfscontext.cpp b/src/plugins/platforms/eglfs/qeglfscontext.cpp index 802699bbd7..310b460087 100644 --- a/src/plugins/platforms/eglfs/qeglfscontext.cpp +++ b/src/plugins/platforms/eglfs/qeglfscontext.cpp @@ -45,7 +45,8 @@ QT_BEGIN_NAMESPACE QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLConfig *config, const QVariant &nativeHandle) - : QEGLPlatformContext(format, share, display, config, nativeHandle) + : QEGLPlatformContext(format, share, display, config, nativeHandle), + m_tempWindow(0) { } @@ -57,6 +58,33 @@ EGLSurface QEglFSContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface return static_cast(surface)->pbuffer(); } +EGLSurface QEglFSContext::createTemporaryOffscreenSurface() +{ + if (QEglFSHooks::hooks()->supportsPBuffers()) + return QEGLPlatformContext::createTemporaryOffscreenSurface(); + + if (!m_tempWindow) { + m_tempWindow = QEglFSHooks::hooks()->createNativeOffscreenWindow(format()); + if (!m_tempWindow) { + qWarning("QEglFSContext: Failed to create temporary native window"); + return EGL_NO_SURFACE; + } + } + EGLConfig config = q_configFromGLFormat(eglDisplay(), format()); + return eglCreateWindowSurface(eglDisplay(), config, m_tempWindow, 0); +} + +void QEglFSContext::destroyTemporaryOffscreenSurface(EGLSurface surface) +{ + if (QEglFSHooks::hooks()->supportsPBuffers()) { + QEGLPlatformContext::destroyTemporaryOffscreenSurface(surface); + } else { + eglDestroySurface(eglDisplay(), surface); + QEglFSHooks::hooks()->destroyNativeWindow(m_tempWindow); + m_tempWindow = 0; + } +} + void QEglFSContext::swapBuffers(QPlatformSurface *surface) { // draw the cursor diff --git a/src/plugins/platforms/eglfs/qeglfscontext.h b/src/plugins/platforms/eglfs/qeglfscontext.h index fcdad5ed22..a656a50e2f 100644 --- a/src/plugins/platforms/eglfs/qeglfscontext.h +++ b/src/plugins/platforms/eglfs/qeglfscontext.h @@ -45,7 +45,12 @@ public: QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLConfig *config, const QVariant &nativeHandle); EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) Q_DECL_OVERRIDE; + EGLSurface createTemporaryOffscreenSurface() Q_DECL_OVERRIDE; + void destroyTemporaryOffscreenSurface(EGLSurface surface) Q_DECL_OVERRIDE; void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE; + +private: + EGLNativeWindowType m_tempWindow; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfshooks.h b/src/plugins/platforms/eglfs/qeglfshooks.h index 3fba6409a1..078a174a16 100644 --- a/src/plugins/platforms/eglfs/qeglfshooks.h +++ b/src/plugins/platforms/eglfs/qeglfshooks.h @@ -62,6 +62,7 @@ public: virtual EGLNativeWindowType createNativeWindow(QPlatformWindow *platformWindow, const QSize &size, const QSurfaceFormat &format); + virtual EGLNativeWindowType createNativeOffscreenWindow(const QSurfaceFormat &format); virtual void destroyNativeWindow(EGLNativeWindowType window); virtual bool hasCapability(QPlatformIntegration::Capability cap) const; virtual QPlatformCursor *createCursor(QPlatformScreen *screen) const; @@ -72,6 +73,8 @@ public: virtual QByteArray fbDeviceName() const; virtual int framebufferIndex() const; + virtual bool supportsPBuffers() const; + static QEglFSHooks *hooks() { #ifdef EGLFS_PLATFORM_HOOKS diff --git a/src/plugins/platforms/eglfs/qeglfshooks_kms.cpp b/src/plugins/platforms/eglfs/qeglfshooks_kms.cpp index e9eec7fdc7..61a1ee7a87 100644 --- a/src/plugins/platforms/eglfs/qeglfshooks_kms.cpp +++ b/src/plugins/platforms/eglfs/qeglfshooks_kms.cpp @@ -108,10 +108,12 @@ public: EGLNativeWindowType createNativeWindow(QPlatformWindow *platformWindow, const QSize &size, const QSurfaceFormat &format) Q_DECL_OVERRIDE; + EGLNativeWindowType createNativeOffscreenWindow(const QSurfaceFormat &format) Q_DECL_OVERRIDE; void destroyNativeWindow(EGLNativeWindowType window) Q_DECL_OVERRIDE; bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; QPlatformCursor *createCursor(QPlatformScreen *screen) const Q_DECL_OVERRIDE; void presentBuffer() Q_DECL_OVERRIDE; + bool supportsPBuffers() const Q_DECL_OVERRIDE; private: bool setup_kms(); @@ -259,6 +261,18 @@ EGLNativeWindowType QEglKmsHooks::createNativeWindow(QPlatformWindow *platformWi return reinterpret_cast(m_gbm_surface); } +EGLNativeWindowType QEglKmsHooks::createNativeOffscreenWindow(const QSurfaceFormat &format) +{ + Q_UNUSED(format); + + gbm_surface *surface = gbm_surface_create(m_gbm_device, + 1, 1, + GBM_FORMAT_XRGB8888, + GBM_BO_USE_RENDERING); + + return reinterpret_cast(surface); +} + void QEglKmsHooks::destroyNativeWindow(EGLNativeWindowType window) { gbm_surface *surface = reinterpret_cast(window); @@ -413,6 +427,11 @@ void QEglKmsHooks::presentBuffer() } } +bool QEglKmsHooks::supportsPBuffers() const +{ + return false; +} + bool QEglKmsHooks::setup_kms() { drmModeRes *resources; diff --git a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp index d216b015d3..04acc4c759 100644 --- a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp +++ b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp @@ -162,6 +162,12 @@ EGLNativeWindowType QEglFSHooks::createNativeWindow(QPlatformWindow *platformWin return 0; } +EGLNativeWindowType QEglFSHooks::createNativeOffscreenWindow(const QSurfaceFormat &format) +{ + Q_UNUSED(format); + return 0; +} + void QEglFSHooks::destroyNativeWindow(EGLNativeWindowType window) { Q_UNUSED(window); @@ -194,6 +200,11 @@ void QEglFSHooks::presentBuffer() { } +bool QEglFSHooks::supportsPBuffers() const +{ + return true; +} + #ifndef EGLFS_PLATFORM_HOOKS QEglFSHooks stubHooks; #endif diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index 6fe3893922..16a113691f 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -36,6 +36,7 @@ #include "qeglfswindow.h" #include "qeglfshooks.h" #include "qeglfscontext.h" +#include "qeglfsoffscreenwindow.h" #include @@ -116,9 +117,9 @@ QEGLPlatformContext *QEglFSIntegration::createContext(const QSurfaceFormat &form QSurfaceFormat adjustedFormat = QEglFSHooks::hooks()->surfaceFormatFor(format); if (!nativeHandle || nativeHandle->isNull()) { EGLConfig config = QEglFSIntegration::chooseConfig(display, adjustedFormat); - ctx = new QEglFSContext(adjustedFormat, shareContext, display, &config, QVariant()); + ctx = new QEglFSContext(adjustedFormat, shareContext, display, &config, QVariant()); } else { - ctx = new QEglFSContext(adjustedFormat, shareContext, display, 0, *nativeHandle); + ctx = new QEglFSContext(adjustedFormat, shareContext, display, 0, *nativeHandle); } *nativeHandle = QVariant::fromValue(QEGLNativeContext(ctx->eglContext(), display)); return ctx; @@ -128,7 +129,13 @@ QPlatformOffscreenSurface *QEglFSIntegration::createOffscreenSurface(EGLDisplay const QSurfaceFormat &format, QOffscreenSurface *surface) const { - return new QEGLPbuffer(display, QEglFSHooks::hooks()->surfaceFormatFor(format), surface); + QSurfaceFormat fmt = QEglFSHooks::hooks()->surfaceFormatFor(format); + if (QEglFSHooks::hooks()->supportsPBuffers()) + return new QEGLPbuffer(display, fmt, surface); + else + return new QEglFSOffscreenWindow(display, fmt, surface); + + // Never return null. Multiple QWindows are not supported by this plugin. } QVariant QEglFSIntegration::styleHint(QPlatformIntegration::StyleHint hint) const diff --git a/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.cpp b/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.cpp new file mode 100644 index 0000000000..0e8e3957d0 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** 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 "qeglfsoffscreenwindow.h" +#include "qeglfshooks.h" +#include +#include + +QT_BEGIN_NAMESPACE + +/* + In some cases pbuffers are not available. Triggering QtGui's built-in + fallback for a hidden QWindow is not suitable for eglfs since this would be + treated as an attempt to create multiple top-level, native windows. + + Therefore this class is provided as an alternative to QEGLPbuffer. + + This class requires the hooks to implement createNativeOffscreenWindow(). +*/ + +QEglFSOffscreenWindow::QEglFSOffscreenWindow(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface) + : QPlatformOffscreenSurface(offscreenSurface) + , m_format(format) + , m_display(display) + , m_surface(EGL_NO_SURFACE) + , m_window(0) +{ + m_window = QEglFSHooks::hooks()->createNativeOffscreenWindow(format); + if (!m_window) { + qWarning("QEglFSOffscreenWindow: Failed to create native window"); + return; + } + EGLConfig config = q_configFromGLFormat(m_display, m_format); + m_surface = eglCreateWindowSurface(m_display, config, m_window, 0); + if (m_surface != EGL_NO_SURFACE) + m_format = q_glFormatFromConfig(m_display, config); +} + +QEglFSOffscreenWindow::~QEglFSOffscreenWindow() +{ + if (m_surface != EGL_NO_SURFACE) + eglDestroySurface(m_display, m_surface); + if (m_window) + QEglFSHooks::hooks()->destroyNativeWindow(m_window); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.h b/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.h new file mode 100644 index 0000000000..8bd4089c34 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** 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 QEGLFSOFFSCREENWINDOW_H +#define QEGLFSOFFSCREENWINDOW_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QEglFSOffscreenWindow : public QPlatformOffscreenSurface +{ +public: + QEglFSOffscreenWindow(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface); + ~QEglFSOffscreenWindow(); + + QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; } + bool isValid() const Q_DECL_OVERRIDE { return m_surface != EGL_NO_SURFACE; } + +private: + QSurfaceFormat m_format; + EGLDisplay m_display; + EGLSurface m_surface; + EGLNativeWindowType m_window; +}; + +QT_END_NAMESPACE + +#endif // QEGLFSOFFSCREENWINDOW_H diff --git a/src/plugins/platforms/qnx/qqnxglcontext.cpp b/src/plugins/platforms/qnx/qqnxglcontext.cpp index 09736304e1..7133d01e87 100644 --- a/src/plugins/platforms/qnx/qqnxglcontext.cpp +++ b/src/plugins/platforms/qnx/qqnxglcontext.cpp @@ -164,7 +164,7 @@ EGLenum QQnxGLContext::checkEGLError(const char *msg) return error; } -void QQnxGLContext::initialize() +void QQnxGLContext::initializeContext() { qGLContextDebug() << Q_FUNC_INFO; @@ -182,7 +182,7 @@ void QQnxGLContext::initialize() } } -void QQnxGLContext::shutdown() +void QQnxGLContext::shutdownContext() { qGLContextDebug() << Q_FUNC_INFO; diff --git a/src/plugins/platforms/qnx/qqnxglcontext.h b/src/plugins/platforms/qnx/qqnxglcontext.h index 090c7ed49d..a91a89901f 100644 --- a/src/plugins/platforms/qnx/qqnxglcontext.h +++ b/src/plugins/platforms/qnx/qqnxglcontext.h @@ -53,8 +53,8 @@ public: static EGLenum checkEGLError(const char *msg); - static void initialize(); - static void shutdown(); + static void initializeContext(); + static void shutdownContext(); void requestSurfaceChange(); diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp index 34b79b61da..6a3cd902af 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.cpp +++ b/src/plugins/platforms/qnx/qqnxintegration.cpp @@ -182,7 +182,7 @@ QQnxIntegration::QQnxIntegration(const QStringList ¶mList) #if !defined(QT_NO_OPENGL) // Initialize global OpenGL resources - QQnxGLContext::initialize(); + QQnxGLContext::initializeContext(); #endif // Create/start event thread @@ -306,7 +306,7 @@ QQnxIntegration::~QQnxIntegration() #if !defined(QT_NO_OPENGL) // Cleanup global OpenGL resources - QQnxGLContext::shutdown(); + QQnxGLContext::shutdownContext(); #endif #if defined(QQNX_PPS) -- cgit v1.2.3