diff options
22 files changed, 996 insertions, 48 deletions
diff --git a/dist/changes-5.1.0 b/dist/changes-5.1.0 index f7984265ff..fdce43650e 100644 --- a/dist/changes-5.1.0 +++ b/dist/changes-5.1.0 @@ -29,7 +29,7 @@ General Improvements Third party components ---------------------- - - + - **************************************************************************** @@ -72,7 +72,9 @@ QtCore QtGui ----- - - + - QOffscreenSurface + * New class for rendering graphics using OpenGL in an arbitrary thread + without needing to use a hidden QWindow. QtNetwork diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index f766b5fbaf..eb87a8c31b 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -24,6 +24,7 @@ HEADERS += \ kernel/qplatformthemefactory_p.h \ kernel/qplatformthemeplugin.h \ kernel/qplatformwindow.h \ + kernel/qplatformoffscreensurface.h \ kernel/qplatformwindow_p.h \ kernel/qplatformcursor.h \ kernel/qplatformclipboard.h \ @@ -34,6 +35,7 @@ HEADERS += \ kernel/qguiapplication_p.h \ kernel/qwindow_p.h \ kernel/qwindow.h \ + kernel/qoffscreensurface.h \ kernel/qplatformsurface.h \ kernel/qsurface.h \ kernel/qclipboard.h \ @@ -81,6 +83,7 @@ SOURCES += \ kernel/qplatformthemefactory.cpp \ kernel/qplatformthemeplugin.cpp \ kernel/qplatformwindow.cpp \ + kernel/qplatformoffscreensurface.cpp \ kernel/qplatformcursor.cpp \ kernel/qplatformclipboard.cpp \ kernel/qplatformnativeinterface.cpp \ @@ -88,6 +91,7 @@ SOURCES += \ kernel/qsurfaceformat.cpp \ kernel/qguiapplication.cpp \ kernel/qwindow.cpp \ + kernel/qoffscreensurface.cpp \ kernel/qplatformsurface.cpp \ kernel/qsurface.cpp \ kernel/qclipboard.cpp \ diff --git a/src/gui/kernel/qoffscreensurface.cpp b/src/gui/kernel/qoffscreensurface.cpp new file mode 100644 index 0000000000..e2306050dd --- /dev/null +++ b/src/gui/kernel/qoffscreensurface.cpp @@ -0,0 +1,345 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module 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 "qoffscreensurface.h" + +#include "qguiapplication_p.h" +#include "qscreen.h" +#include "qplatformintegration.h" +#include "qplatformoffscreensurface.h" +#include "qwindow.h" +#include "qplatformwindow.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QOffscreenSurface + \inmodule QtGui + \since 5.1 + \brief The QOffscreenSurface class represents an offscreen surface in the underlying platform. + + QOffscreenSurface is intended to be used with QOpenGLContext to allow rendering with OpenGL in + an arbitrary thread without the need to create a QWindow. + + Even though the surface is renderable, the surface's pixels are not accessible. + QOffscreenSurface should only be used to create OpenGL resources such as textures + or framebuffer objects. + + An application will typically use QOffscreenSurface to perform some time-consuming tasks in a + separate thread in order to avoid stalling the main rendering thread. Resources created in the + QOffscreenSurface's context can be shared with the main OpenGL context. Some common use cases + are asynchronous texture uploads or rendering into a QOpenGLFramebufferObject. + + How the offscreen surface is implemented depends on the underlying platform, but it will + typically use a pixel buffer (pbuffer). If the platform doesn't implement or support + offscreen surfaces, QOffscreenSurface will use an invisible QWindow internally. +*/ +class Q_GUI_EXPORT QOffscreenSurfacePrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QOffscreenSurface) + +public: + QOffscreenSurfacePrivate() + : QObjectPrivate() + , surfaceType(QSurface::OpenGLSurface) + , platformOffscreenSurface(0) + , offscreenWindow(0) + , screen(0) + , size(1, 1) + { + } + + ~QOffscreenSurfacePrivate() + { + } + + QSurface::SurfaceType surfaceType; + QPlatformOffscreenSurface *platformOffscreenSurface; + QWindow *offscreenWindow; + QSurfaceFormat requestedFormat; + QScreen *screen; + QSize size; +}; + + +/*! + Creates an offscreen surface for the \a targetScreen. + + The underlying platform surface is not created until create() is called. + + \sa setScreen(), create() +*/ +QOffscreenSurface::QOffscreenSurface(QScreen *targetScreen) + : QObject(*new QOffscreenSurfacePrivate(), 0) + , QSurface(Offscreen) +{ + Q_D(QOffscreenSurface); + d->screen = targetScreen; + if (!d->screen) + d->screen = QGuiApplication::primaryScreen(); + + //if your applications aborts here, then chances are your creating a QOffscreenSurface before + //the screen list is populated. + Q_ASSERT(d->screen); + + connect(d->screen, SIGNAL(destroyed(QObject*)), this, SLOT(screenDestroyed(QObject*))); +} + + +/*! + Destroys the offscreen surface. +*/ +QOffscreenSurface::~QOffscreenSurface() +{ + destroy(); +} + +/*! + Returns the surface type of the offscreen surface. + + The surface type of an offscreen surface is always QSurface::OpenGLSurface. +*/ +QOffscreenSurface::SurfaceType QOffscreenSurface::surfaceType() const +{ + Q_D(const QOffscreenSurface); + return d->surfaceType; +} + +/*! + Allocates the platform resources associated with the offscreen surface. + + It is at this point that the surface format set using setFormat() gets resolved + into an actual native surface. + + Call destroy() to free the platform resources if necessary. + + \sa destroy() +*/ +void QOffscreenSurface::create() +{ + Q_D(QOffscreenSurface); + if (!d->platformOffscreenSurface && !d->offscreenWindow) { + d->platformOffscreenSurface = QGuiApplicationPrivate::platformIntegration()->createPlatformOffscreenSurface(this); + // No platform offscreen surface, fallback to an invisible window + if (!d->platformOffscreenSurface) { + d->offscreenWindow = new QWindow(d->screen); + d->offscreenWindow->setSurfaceType(QWindow::OpenGLSurface); + d->offscreenWindow->setFormat(d->requestedFormat); + d->offscreenWindow->setGeometry(0, 0, d->size.width(), d->size.height()); + d->offscreenWindow->create(); + } + } +} + +/*! + Releases the native platform resources associated with this offscreen surface. + + \sa create() +*/ +void QOffscreenSurface::destroy() +{ + Q_D(QOffscreenSurface); + delete d->platformOffscreenSurface; + d->platformOffscreenSurface = 0; + if (d->offscreenWindow) { + d->offscreenWindow->destroy(); + delete d->offscreenWindow; + d->offscreenWindow = 0; + } +} + +/*! + Returns \c true if this offscreen surface is valid; otherwise returns \c false. + + The offscreen surface is valid if the platform resources have been successfuly allocated. + + \sa create() +*/ +bool QOffscreenSurface::isValid() const +{ + Q_D(const QOffscreenSurface); + return (d->platformOffscreenSurface && d->platformOffscreenSurface->isValid()) + || (d->offscreenWindow && d->offscreenWindow->handle()); +} + +/*! + Sets the offscreen surface \a format. + + The surface format will be resolved in the create() function. Calling + this function after create() will not re-resolve the surface format of the native surface. + + \sa create(), destroy() +*/ +void QOffscreenSurface::setFormat(const QSurfaceFormat &format) +{ + Q_D(QOffscreenSurface); + d->requestedFormat = format; +} + +/*! + Returns the requested surfaceformat of this offscreen surface. + + If the requested format was not supported by the platform implementation, + the requestedFormat will differ from the actual offscreen surface format. + + This is the value set with setFormat(). + + \sa setFormat(), format() + */ +QSurfaceFormat QOffscreenSurface::requestedFormat() const +{ + Q_D(const QOffscreenSurface); + return d->requestedFormat; +} + +/*! + Returns the actual format of this offscreen surface. + + After the offscreen surface has been created, this function will return the actual + surface format of the surface. It might differ from the requested format if the requested + format could not be fulfilled by the platform. + + \sa create(), requestedFormat() +*/ +QSurfaceFormat QOffscreenSurface::format() const +{ + Q_D(const QOffscreenSurface); + if (d->platformOffscreenSurface) + return d->platformOffscreenSurface->format(); + if (d->offscreenWindow) + return d->offscreenWindow->format(); + return d->requestedFormat; +} + +/*! + Returns the size of the offscreen surface. +*/ +QSize QOffscreenSurface::size() const +{ + Q_D(const QOffscreenSurface); + return d->size; +} + +/*! + Returns the screen to which the offscreen surface is connected. + + \sa setScreen() +*/ +QScreen *QOffscreenSurface::screen() const +{ + Q_D(const QOffscreenSurface); + return d->screen; +} + +/*! + Sets the screen to which the offscreen surface is connected. + + If the offscreen surface has been created, it will be recreated on the \a newScreen. + + \sa screen() +*/ +void QOffscreenSurface::setScreen(QScreen *newScreen) +{ + Q_D(QOffscreenSurface); + if (!newScreen) + newScreen = QGuiApplication::primaryScreen(); + if (newScreen != d->screen) { + const bool wasCreated = d->platformOffscreenSurface != 0 || d->offscreenWindow != 0; + if (wasCreated) + destroy(); + if (d->screen) + disconnect(d->screen, SIGNAL(destroyed(QObject*)), this, SLOT(screenDestroyed(QObject*))); + d->screen = newScreen; + if (newScreen) { + connect(d->screen, SIGNAL(destroyed(QObject*)), this, SLOT(screenDestroyed(QObject*))); + if (wasCreated) + create(); + } + emit screenChanged(newScreen); + } +} + +/*! + Called when the offscreen surface's screen is destroyed. + + \internal +*/ +void QOffscreenSurface::screenDestroyed(QObject *object) +{ + Q_D(QOffscreenSurface); + if (object == static_cast<QObject *>(d->screen)) + setScreen(0); +} + +/*! + \fn QOffscreenSurface::screenChanged(QScreen *screen) + + This signal is emitted when an offscreen surface's \a screen changes, either + by being set explicitly with setScreen(), or automatically when + the window's screen is removed. +*/ + +/*! + Returns the platform offscreen surface corresponding to the offscreen surface. + + \internal +*/ +QPlatformOffscreenSurface *QOffscreenSurface::handle() const +{ + Q_D(const QOffscreenSurface); + return d->platformOffscreenSurface; +} + +/*! + Returns the platform surface corresponding to the offscreen surface. + + \internal +*/ +QPlatformSurface *QOffscreenSurface::surfaceHandle() const +{ + Q_D(const QOffscreenSurface); + if (d->offscreenWindow) + return d->offscreenWindow->handle(); + + return d->platformOffscreenSurface; +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qoffscreensurface.h b/src/gui/kernel/qoffscreensurface.h new file mode 100644 index 0000000000..a1b46f9b88 --- /dev/null +++ b/src/gui/kernel/qoffscreensurface.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module 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 QOFFSCREENSURFACE_H +#define QOFFSCREENSURFACE_H + +#include <QtCore/QObject> +#include <QtGui/qsurface.h> + +QT_BEGIN_NAMESPACE + +class QOffscreenSurfacePrivate; + +class QScreen; +class QPlatformOffscreenSurface; + +class Q_GUI_EXPORT QOffscreenSurface : public QObject, public QSurface +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QOffscreenSurface) + +public: + + explicit QOffscreenSurface(QScreen *screen = 0); + virtual ~QOffscreenSurface(); + + SurfaceType surfaceType() const; + + void create(); + void destroy(); + + bool isValid() const; + + void setFormat(const QSurfaceFormat &format); + QSurfaceFormat format() const; + QSurfaceFormat requestedFormat() const; + + QSize size() const; + + QScreen *screen() const; + void setScreen(QScreen *screen); + + QPlatformOffscreenSurface *handle() const; + +Q_SIGNALS: + void screenChanged(QScreen *screen); + +private Q_SLOTS: + void screenDestroyed(QObject *screen); + +private: + + QPlatformSurface *surfaceHandle() const; + + Q_DISABLE_COPY(QOffscreenSurface) +}; + +QT_END_NAMESPACE + +#endif // QOFFSCREENSURFACE_H diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp index 980e45742e..027b9fc9f1 100644 --- a/src/gui/kernel/qplatformintegration.cpp +++ b/src/gui/kernel/qplatformintegration.cpp @@ -360,4 +360,15 @@ class QPlatformTheme *QPlatformIntegration::createPlatformTheme(const QString &n return new QPlatformTheme; } +/*! + Factory function for QOffscreenSurface. An offscreen surface will typically be implemented with a + pixel buffer (pbuffer). If the platform doesn't support offscreen surfaces, an invisible window + will be used by QOffscreenSurface instead. +*/ +QPlatformOffscreenSurface *QPlatformIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const +{ + Q_UNUSED(surface) + return 0; +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h index 0b6cbb5a5c..6e10df9495 100644 --- a/src/gui/kernel/qplatformintegration.h +++ b/src/gui/kernel/qplatformintegration.h @@ -75,6 +75,8 @@ class QPlatformDialogHelper; class QPlatformSharedGraphicsCache; class QPlatformServices; class QKeyEvent; +class QPlatformOffscreenSurface; +class QOffscreenSurface; class Q_GUI_EXPORT QPlatformIntegration { @@ -146,6 +148,8 @@ public: virtual QStringList themeNames() const; virtual QPlatformTheme *createPlatformTheme(const QString &name) const; + virtual QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const; + protected: void screenAdded(QPlatformScreen *screen); }; diff --git a/src/gui/kernel/qplatformoffscreensurface.cpp b/src/gui/kernel/qplatformoffscreensurface.cpp new file mode 100644 index 0000000000..dd354f465e --- /dev/null +++ b/src/gui/kernel/qplatformoffscreensurface.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module 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 "qplatformoffscreensurface.h" + +#include "qoffscreensurface.h" +#include "qscreen.h" + +QT_BEGIN_NAMESPACE + +class QPlatformOffscreenSurfacePrivate +{ +public: +}; + +QPlatformOffscreenSurface::QPlatformOffscreenSurface(QOffscreenSurface *offscreenSurface) + : QPlatformSurface(offscreenSurface) + , d_ptr(new QPlatformOffscreenSurfacePrivate) +{ +} + +QPlatformOffscreenSurface::~QPlatformOffscreenSurface() +{ +} + +QOffscreenSurface *QPlatformOffscreenSurface::offscreenSurface() const +{ + return static_cast<QOffscreenSurface*>(m_surface); +} + +/*! + Returns the platform screen handle corresponding to this QPlatformOffscreenSurface. +*/ +QPlatformScreen *QPlatformOffscreenSurface::screen() const +{ + return offscreenSurface()->screen()->handle(); +} + +/*! + Returns the actual surface format of the offscreen surface. +*/ +QSurfaceFormat QPlatformOffscreenSurface::format() const +{ + return QSurfaceFormat(); +} + +/*! + Returns \c true if the platform offscreen surface has been allocated. +*/ +bool QPlatformOffscreenSurface::isValid() const +{ + return false; +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatformoffscreensurface.h b/src/gui/kernel/qplatformoffscreensurface.h new file mode 100644 index 0000000000..099d8ee94a --- /dev/null +++ b/src/gui/kernel/qplatformoffscreensurface.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module 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 QPLATFORMOFFSCREENSURFACE_H +#define QPLATFORMOFFSCREENSURFACE_H + +// +// W A R N I N G +// ------------- +// +// This file is part of the QPA API and is not meant to be used +// in applications. Usage of this API may make your code +// source and binary incompatible with future versions of Qt. +// + +#include "qplatformsurface.h" +#include <QtCore/qscopedpointer.h> + +QT_BEGIN_NAMESPACE + +class QOffscreenSurface; +class QPlatformScreen; +class QPlatformOffscreenSurfacePrivate; + +class Q_GUI_EXPORT QPlatformOffscreenSurface : public QPlatformSurface +{ + Q_DECLARE_PRIVATE(QPlatformOffscreenSurface) +public: + explicit QPlatformOffscreenSurface(QOffscreenSurface *offscreenSurface); + virtual ~QPlatformOffscreenSurface(); + + QOffscreenSurface *offscreenSurface() const; + + QPlatformScreen *screen() const; + + virtual QSurfaceFormat format() const; + virtual bool isValid() const; + +protected: + QScopedPointer<QPlatformOffscreenSurfacePrivate> d_ptr; +private: + Q_DISABLE_COPY(QPlatformOffscreenSurface) +}; + +QT_END_NAMESPACE + +#endif // QPLATFORMOFFSCREENSURFACE_H diff --git a/src/gui/kernel/qplatformsurface.h b/src/gui/kernel/qplatformsurface.h index 18af7927bf..b96e494f74 100644 --- a/src/gui/kernel/qplatformsurface.h +++ b/src/gui/kernel/qplatformsurface.h @@ -72,6 +72,7 @@ private: QSurface *m_surface; friend class QPlatformWindow; + friend class QPlatformOffscreenSurface; }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qsurface.cpp b/src/gui/kernel/qsurface.cpp index 97b8220124..a943639d5f 100644 --- a/src/gui/kernel/qsurface.cpp +++ b/src/gui/kernel/qsurface.cpp @@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE The SurfaceClass enum describes the actual subclass of the surface. \value Window The surface is an instance of QWindow. + \value Offscreen The surface is an instance of QOffscreenSurface. */ diff --git a/src/gui/kernel/qsurface.h b/src/gui/kernel/qsurface.h index a2589c733b..8dbc230c10 100644 --- a/src/gui/kernel/qsurface.h +++ b/src/gui/kernel/qsurface.h @@ -58,7 +58,8 @@ class Q_GUI_EXPORT QSurface { public: enum SurfaceClass { - Window + Window, + Offscreen }; enum SurfaceType { diff --git a/src/platformsupport/eglconvenience/eglconvenience.pri b/src/platformsupport/eglconvenience/eglconvenience.pri index 188eb1ce64..22ade42816 100644 --- a/src/platformsupport/eglconvenience/eglconvenience.pri +++ b/src/platformsupport/eglconvenience/eglconvenience.pri @@ -1,10 +1,12 @@ contains(QT_CONFIG,egl) { HEADERS += \ $$PWD/qeglconvenience_p.h \ - $$PWD/qeglplatformcontext_p.h + $$PWD/qeglplatformcontext_p.h \ + $$PWD/qeglpbuffer_p.h SOURCES += \ $$PWD/qeglconvenience.cpp \ - $$PWD/qeglplatformcontext.cpp + $$PWD/qeglplatformcontext.cpp \ + $$PWD/qeglpbuffer.cpp contains(QT_CONFIG,xlib) { HEADERS += \ diff --git a/src/platformsupport/eglconvenience/qeglpbuffer.cpp b/src/platformsupport/eglconvenience/qeglpbuffer.cpp new file mode 100644 index 0000000000..919314e9aa --- /dev/null +++ b/src/platformsupport/eglconvenience/qeglpbuffer.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 <QtGui/QOffscreenSurface> +#include "qeglpbuffer_p.h" +#include "qeglconvenience_p.h" + +QT_BEGIN_NAMESPACE + +QEGLPbuffer::QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface) + : QPlatformOffscreenSurface(offscreenSurface) + , m_format(format) + , m_display(display) + , m_pbuffer(EGL_NO_SURFACE) +{ + EGLConfig config = q_configFromGLFormat(m_display, m_format, false, EGL_PBUFFER_BIT); + + if (config) { + const EGLint attributes[] = { + EGL_WIDTH, offscreenSurface->size().width(), + EGL_HEIGHT, offscreenSurface->size().height(), + EGL_LARGEST_PBUFFER, EGL_FALSE, + EGL_NONE + }; + + m_pbuffer = eglCreatePbufferSurface(m_display, config, attributes); + + if (m_pbuffer != EGL_NO_SURFACE) + m_format = q_glFormatFromConfig(m_display, config); + } +} + +QEGLPbuffer::~QEGLPbuffer() +{ + eglDestroySurface(m_display, m_pbuffer); +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglpbuffer_p.h b/src/platformsupport/eglconvenience/qeglpbuffer_p.h new file mode 100644 index 0000000000..1b4ac6f991 --- /dev/null +++ b/src/platformsupport/eglconvenience/qeglpbuffer_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 QEGLPBUFFER_H +#define QEGLPBUFFER_H + +#include <EGL/egl.h> +#include <qpa/qplatformoffscreensurface.h> + +QT_BEGIN_NAMESPACE + +class QEGLPbuffer : public QPlatformOffscreenSurface +{ +public: + QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface); + ~QEGLPbuffer(); + + QSurfaceFormat format() const { return m_format; } + bool isValid() const { return m_pbuffer != EGL_NO_SURFACE; } + + EGLSurface pbuffer() const { return m_pbuffer; } + +private: + QSurfaceFormat m_format; + EGLDisplay m_display; + EGLSurface m_pbuffer; +}; + +QT_END_NAMESPACE + +#endif // QEGLPBUFFER_H diff --git a/src/plugins/platforms/eglfs/qeglfscontext.cpp b/src/plugins/platforms/eglfs/qeglfscontext.cpp index 1f0c373818..06db4e02db 100644 --- a/src/plugins/platforms/eglfs/qeglfscontext.cpp +++ b/src/plugins/platforms/eglfs/qeglfscontext.cpp @@ -45,6 +45,8 @@ #include "qeglfshooks.h" #include "qeglfsintegration.h" +#include <QtPlatformSupport/private/qeglpbuffer_p.h> +#include <QtGui/QSurface> #include <QtDebug> QT_BEGIN_NAMESPACE @@ -62,16 +64,20 @@ bool QEglFSContext::makeCurrent(QPlatformSurface *surface) EGLSurface QEglFSContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface) { - QEglFSWindow *window = static_cast<QEglFSWindow *>(surface); - return window->surface(); + if (surface->surface()->surfaceClass() == QSurface::Window) + return static_cast<QEglFSWindow *>(surface)->surface(); + else + return static_cast<QEGLPbuffer *>(surface)->pbuffer(); } void QEglFSContext::swapBuffers(QPlatformSurface *surface) { - QEglFSWindow *window = static_cast<QEglFSWindow *>(surface); - // draw the cursor - if (QEglFSCursor *cursor = static_cast<QEglFSCursor *>(window->screen()->cursor())) - cursor->paintOnScreen(); + if (surface->surface()->surfaceClass() == QSurface::Window) { + QEglFSWindow *window = static_cast<QEglFSWindow *>(surface); + // draw the cursor + if (QEglFSCursor *cursor = static_cast<QEglFSCursor *>(window->screen()->cursor())) + cursor->paintOnScreen(); + } QEGLPlatformContext::swapBuffers(surface); } diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index 9c48ba1575..dd212c80a0 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -51,6 +51,7 @@ #include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h> #include <QtPlatformSupport/private/qeglconvenience_p.h> #include <QtPlatformSupport/private/qeglplatformcontext_p.h> +#include <QtPlatformSupport/private/qeglpbuffer_p.h> #if !defined(QT_NO_EVDEV) #include <QtPlatformSupport/private/qevdevmousemanager_p.h> @@ -62,6 +63,7 @@ #include <QtGui/QSurfaceFormat> #include <QtGui/QOpenGLContext> #include <QtGui/QScreen> +#include <QtGui/QOffscreenSurface> #include <qpa/qplatformcursor.h> #include "qeglfscontext.h" @@ -154,6 +156,12 @@ QPlatformOpenGLContext *QEglFSIntegration::createPlatformOpenGLContext(QOpenGLCo return new QEglFSContext(hooks->surfaceFormatFor(context->format()), context->shareHandle(), mDisplay); } +QPlatformOffscreenSurface *QEglFSIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const +{ + QEglFSScreen *screen = static_cast<QEglFSScreen *>(surface->screen()->handle()); + return new QEGLPbuffer(screen->display(), hooks->surfaceFormatFor(surface->requestedFormat()), surface); +} + QPlatformFontDatabase *QEglFSIntegration::fontDatabase() const { return mFontDb; diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.h b/src/plugins/platforms/eglfs/qeglfsintegration.h index 9eae8d2703..e048c5d310 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.h +++ b/src/plugins/platforms/eglfs/qeglfsintegration.h @@ -61,6 +61,7 @@ public: QPlatformWindow *createPlatformWindow(QWindow *window) const; QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const; QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const; + QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const; QPlatformNativeInterface *nativeInterface() const; QPlatformFontDatabase *fontDatabase() const; diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp index 23bec15b48..5e2731430d 100644 --- a/src/plugins/platforms/xcb/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/qglxintegration.cpp @@ -50,6 +50,7 @@ #include <GL/glx.h> #include <QtGui/QOpenGLContext> +#include <QtGui/QOffscreenSurface> #include "qglxintegration.h" #include <QtPlatformSupport/private/qglxconvenience_p.h> @@ -270,6 +271,7 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat , m_screen(screen) , m_context(0) , m_format(format) + , m_isPBufferCurrent(false) { m_shareContext = 0; if (share) @@ -390,19 +392,35 @@ bool QGLXContext::makeCurrent(QPlatformSurface *surface) { Q_ASSERT(surface->surface()->surfaceType() == QSurface::OpenGLSurface); - GLXDrawable glxDrawable = static_cast<QXcbWindow *>(surface)->xcb_window(); - - return glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), glxDrawable, m_context); + QSurface::SurfaceClass surfaceClass = surface->surface()->surfaceClass(); + if (surfaceClass == QSurface::Window) { + m_isPBufferCurrent = false; + QXcbWindow *window = static_cast<QXcbWindow *>(surface); + return glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), window->xcb_window(), m_context); + } else if (surfaceClass == QSurface::Offscreen) { + m_isPBufferCurrent = true; + QGLXPbuffer *pbuffer = static_cast<QGLXPbuffer *>(surface); + return glXMakeContextCurrent(DISPLAY_FROM_XCB(m_screen), pbuffer->pbuffer(), pbuffer->pbuffer(), m_context); + } + return false; } void QGLXContext::doneCurrent() { - glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), 0, 0); + if (m_isPBufferCurrent) + glXMakeContextCurrent(DISPLAY_FROM_XCB(m_screen), 0, 0, 0); + else + glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), 0, 0); + m_isPBufferCurrent = false; } void QGLXContext::swapBuffers(QPlatformSurface *surface) { - GLXDrawable glxDrawable = static_cast<QXcbWindow *>(surface)->xcb_window(); + GLXDrawable glxDrawable = 0; + if (surface->surface()->surfaceClass() == QSurface::Offscreen) + glxDrawable = static_cast<QGLXPbuffer *>(surface)->pbuffer(); + else + glxDrawable = static_cast<QXcbWindow *>(surface)->xcb_window(); glXSwapBuffers(DISPLAY_FROM_XCB(m_screen), glxDrawable); } @@ -454,4 +472,36 @@ bool QGLXContext::isValid() const return m_context != 0; } + +QGLXPbuffer::QGLXPbuffer(QOffscreenSurface *offscreenSurface) + : QPlatformOffscreenSurface(offscreenSurface) + , m_format(offscreenSurface->requestedFormat()) + , m_screen(static_cast<QXcbScreen *>(offscreenSurface->screen()->handle())) + , m_pbuffer(0) +{ + GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(m_screen), m_screen->screenNumber(), m_format); + + if (config) { + const int attributes[] = { + GLX_PBUFFER_WIDTH, offscreenSurface->size().width(), + GLX_PBUFFER_HEIGHT, offscreenSurface->size().height(), + GLX_LARGEST_PBUFFER, False, + GLX_PRESERVED_CONTENTS, False, + GLX_NONE + }; + + m_pbuffer = glXCreatePbuffer(DISPLAY_FROM_XCB(m_screen), config, attributes); + + if (m_pbuffer) + m_format = qglx_surfaceFormatFromGLXFBConfig(DISPLAY_FROM_XCB(m_screen), config); + } +} + +QGLXPbuffer::~QGLXPbuffer() +{ + if (m_pbuffer) + glXDestroyPbuffer(DISPLAY_FROM_XCB(m_screen), m_pbuffer); +} + + QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qglxintegration.h b/src/plugins/platforms/xcb/qglxintegration.h index 78e9985334..d10b1d441b 100644 --- a/src/plugins/platforms/xcb/qglxintegration.h +++ b/src/plugins/platforms/xcb/qglxintegration.h @@ -46,6 +46,7 @@ #include "qxcbscreen.h" #include <qpa/qplatformopenglcontext.h> +#include <qpa/qplatformoffscreensurface.h> #include <QtGui/QSurfaceFormat> #include <QtCore/QMutex> @@ -89,6 +90,25 @@ private: GLXContext m_context; GLXContext m_shareContext; QSurfaceFormat m_format; + bool m_isPBufferCurrent; +}; + + +class QGLXPbuffer : public QPlatformOffscreenSurface +{ +public: + explicit QGLXPbuffer(QOffscreenSurface *offscreenSurface); + ~QGLXPbuffer(); + + QSurfaceFormat format() const { return m_format; } + bool isValid() const { return m_pbuffer != 0; } + + GLXPbuffer pbuffer() const { return m_pbuffer; } + +private: + QSurfaceFormat m_format; + QXcbScreen *m_screen; + GLXPbuffer m_pbuffer; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 1840dd1ce5..d0b0ab8d02 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -78,10 +78,12 @@ #elif defined(XCB_USE_EGL) #include "qxcbeglsurface.h" #include <QtPlatformSupport/private/qeglplatformcontext_p.h> +#include <QtPlatformSupport/private/qeglpbuffer_p.h> #endif #include <QtGui/QOpenGLContext> #include <QtGui/QScreen> +#include <QtGui/QOffscreenSurface> #ifndef QT_NO_ACCESSIBILITY #include <qpa/qplatformaccessibility.h> #ifndef QT_NO_ACCESSIBILITY_ATSPI_BRIDGE @@ -168,7 +170,10 @@ public: EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) { - return static_cast<QXcbWindow *>(surface)->eglSurface()->surface(); + if (surface->surface()->surfaceClass() == QSurface::Window) + return static_cast<QXcbWindow *>(surface)->eglSurface()->surface(); + else + return static_cast<QEGLPbuffer *>(surface)->pbuffer(); } private: @@ -205,6 +210,20 @@ QPlatformBackingStore *QXcbIntegration::createPlatformBackingStore(QWindow *wind return new QXcbBackingStore(window); } +QPlatformOffscreenSurface *QXcbIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const +{ +#if defined(XCB_USE_GLX) + return new QGLXPbuffer(surface); +#elif defined(XCB_USE_EGL) + QXcbScreen *screen = static_cast<QXcbScreen *>(surface->screen()->handle()); + return new QEGLPbuffer(screen->connection()->egl_display(), surface->requestedFormat(), surface); +#else + Q_UNUSED(surface); + qWarning("QXcbIntegration: Cannot create platform offscreen surface, neither GLX nor EGL are enabled"); + return 0; +#endif +} + bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const { switch (cap) { diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h index cd6c2fd73c..13b3b115ca 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.h +++ b/src/plugins/platforms/xcb/qxcbintegration.h @@ -68,6 +68,8 @@ public: #endif QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const; + QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const; + bool hasCapability(Capability cap) const; QAbstractEventDispatcher *guiThreadEventDispatcher() const; diff --git a/tests/auto/gui/qopengl/tst_qopengl.cpp b/tests/auto/gui/qopengl/tst_qopengl.cpp index 1d498773ae..97f3ec128d 100644 --- a/tests/auto/gui/qopengl/tst_qopengl.cpp +++ b/tests/auto/gui/qopengl/tst_qopengl.cpp @@ -47,6 +47,7 @@ #include <QtGui/QPainter> #include <QtGui/QScreen> #include <QtGui/QWindow> +#include <QtGui/QOffscreenSurface> #include <QtTest/QtTest> @@ -57,12 +58,18 @@ class tst_QOpenGL : public QObject Q_OBJECT private slots: + void sharedResourceCleanup_data(); void sharedResourceCleanup(); + void multiGroupSharedResourceCleanup_data(); void multiGroupSharedResourceCleanup(); + void multiGroupSharedResourceCleanupCustom_data(); void multiGroupSharedResourceCleanupCustom(); + void fboSimpleRendering_data(); void fboSimpleRendering(); + void fboRendering_data(); void fboRendering(); void fboHandleNulledAfterContextDestroyed(); + void openGLPaintDevice_data(); void openGLPaintDevice(); void aboutToBeDestroyed(); void QTBUG15621_triangulatingStrokerDivZero(); @@ -129,16 +136,43 @@ struct SharedResource : public QOpenGLSharedResource SharedResourceTracker *tracker; }; +static QSurface *createSurface(int surfaceClass) +{ + if (surfaceClass == int(QSurface::Window)) { + QWindow *window = new QWindow; + window->setSurfaceType(QWindow::OpenGLSurface); + window->setGeometry(0, 0, 10, 10); + window->create(); + return window; + } else if (surfaceClass == int(QSurface::Offscreen)) { + QOffscreenSurface *offscreenSurface = new QOffscreenSurface; + offscreenSurface->create(); + return offscreenSurface; + } + return 0; +} + +static void common_data() +{ + QTest::addColumn<int>("surfaceClass"); + + QTest::newRow("Using QWindow") << int(QSurface::Window); + QTest::newRow("Using QOffscreenSurface") << int(QSurface::Offscreen); +} + +void tst_QOpenGL::sharedResourceCleanup_data() +{ + common_data(); +} + void tst_QOpenGL::sharedResourceCleanup() { - QWindow window; - window.setSurfaceType(QWindow::OpenGLSurface); - window.setGeometry(0, 0, 10, 10); - window.create(); + QFETCH(int, surfaceClass); + QScopedPointer<QSurface> surface(createSurface(surfaceClass)); QOpenGLContext *ctx = new QOpenGLContext; ctx->create(); - ctx->makeCurrent(&window); + ctx->makeCurrent(surface.data()); SharedResourceTracker tracker; SharedResource *resource = new SharedResource(&tracker); @@ -165,7 +199,7 @@ void tst_QOpenGL::sharedResourceCleanup() QCOMPARE(tracker.freeResourceCalls, 0); QCOMPARE(tracker.destructorCalls, 0); - ctx2->makeCurrent(&window); + ctx2->makeCurrent(surface.data()); // freeResource() should now have been called QCOMPARE(tracker.invalidateResourceCalls, 0); @@ -192,17 +226,20 @@ void tst_QOpenGL::sharedResourceCleanup() QCOMPARE(tracker.destructorCalls, 1); } +void tst_QOpenGL::multiGroupSharedResourceCleanup_data() +{ + common_data(); +} + void tst_QOpenGL::multiGroupSharedResourceCleanup() { - QWindow window; - window.setSurfaceType(QWindow::OpenGLSurface); - window.setGeometry(0, 0, 10, 10); - window.create(); + QFETCH(int, surfaceClass); + QScopedPointer<QSurface> surface(createSurface(surfaceClass)); for (int i = 0; i < 10; ++i) { QOpenGLContext *gl = new QOpenGLContext(); gl->create(); - gl->makeCurrent(&window); + gl->makeCurrent(surface.data()); { // Cause QOpenGLMultiGroupSharedResource instantiation. QOpenGLFunctions func(gl); @@ -214,16 +251,19 @@ void tst_QOpenGL::multiGroupSharedResourceCleanup() // Shouldn't crash when application exits. } +void tst_QOpenGL::multiGroupSharedResourceCleanupCustom_data() +{ + common_data(); +} + void tst_QOpenGL::multiGroupSharedResourceCleanupCustom() { - QWindow window; - window.setSurfaceType(QWindow::OpenGLSurface); - window.setGeometry(0, 0, 10, 10); - window.create(); + QFETCH(int, surfaceClass); + QScopedPointer<QSurface> surface(createSurface(surfaceClass)); QOpenGLContext *ctx = new QOpenGLContext(); ctx->create(); - ctx->makeCurrent(&window); + ctx->makeCurrent(surface.data()); QOpenGLMultiGroupSharedResource multiGroupSharedResource; SharedResource *resource = multiGroupSharedResource.value<SharedResource>(ctx); @@ -350,17 +390,20 @@ void qt_opengl_check_test_pattern(const QImage& img) QFUZZY_COMPARE_PIXELS(img.pixel(192, 64), QColor(Qt::green).rgb()); } +void tst_QOpenGL::fboSimpleRendering_data() +{ + common_data(); +} void tst_QOpenGL::fboSimpleRendering() { - QWindow window; - window.setSurfaceType(QWindow::OpenGLSurface); - window.setGeometry(0, 0, 10, 10); - window.create(); + QFETCH(int, surfaceClass); + QScopedPointer<QSurface> surface(createSurface(surfaceClass)); + QOpenGLContext ctx; ctx.create(); - ctx.makeCurrent(&window); + ctx.makeCurrent(surface.data()); if (!QOpenGLFramebufferObject::hasOpenGLFramebufferObjects()) QSKIP("QOpenGLFramebufferObject not supported on this platform"); @@ -386,6 +429,11 @@ void tst_QOpenGL::fboSimpleRendering() delete fbo; } +void tst_QOpenGL::fboRendering_data() +{ + common_data(); +} + // NOTE: This tests that CombinedDepthStencil attachment works by assuming the // GL2 engine is being used and is implemented the same way as it was when // this autotest was written. If this is not the case, there may be some @@ -397,14 +445,13 @@ void tst_QOpenGL::fboRendering() QSKIP("QTBUG-22617"); #endif - QWindow window; - window.setSurfaceType(QWindow::OpenGLSurface); - window.setGeometry(0, 0, 10, 10); - window.create(); + QFETCH(int, surfaceClass); + QScopedPointer<QSurface> surface(createSurface(surfaceClass)); + QOpenGLContext ctx; ctx.create(); - ctx.makeCurrent(&window); + ctx.makeCurrent(surface.data()); if (!QOpenGLFramebufferObject::hasOpenGLFramebufferObjects()) QSKIP("QOpenGLFramebufferObject not supported on this platform"); @@ -461,16 +508,19 @@ void tst_QOpenGL::fboHandleNulledAfterContextDestroyed() QCOMPARE(fbo->handle(), 0U); } +void tst_QOpenGL::openGLPaintDevice_data() +{ + common_data(); +} + void tst_QOpenGL::openGLPaintDevice() { #if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(__x86_64__) QSKIP("QTBUG-22617"); #endif - QWindow window; - window.setSurfaceType(QWindow::OpenGLSurface); - window.setGeometry(0, 0, 128, 128); - window.create(); + QFETCH(int, surfaceClass); + QScopedPointer<QSurface> surface(createSurface(surfaceClass)); QOpenGLContext ctx; ctx.create(); @@ -478,7 +528,7 @@ void tst_QOpenGL::openGLPaintDevice() QSurfaceFormat format = ctx.format(); if (format.majorVersion() < 2) QSKIP("This test requires at least OpenGL 2.0"); - ctx.makeCurrent(&window); + ctx.makeCurrent(surface.data()); QImage image(128, 128, QImage::Format_RGB32); QPainter p(&image); |