diff options
author | Laszlo Agocs <laszlo.agocs@digia.com> | 2014-03-31 15:59:18 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@digia.com> | 2014-06-24 14:22:19 +0200 |
commit | 745a71196c8893a35a80a679674bee396606f79b (patch) | |
tree | f9bc32b7cfe88e65b54372987baf95fcd1db2ada /src/quick/items | |
parent | 8eafef976f2a53b5c05967de8b4fb8f01b8e9e7b (diff) | |
download | qtdeclarative-745a71196c8893a35a80a679674bee396606f79b.tar.gz |
Make QQuickRenderControl public
QQuickRenderControl allows rendering Qt Quick 2 scenes into framebuffer
objects which can then be used in arbitrary ways in Qt-based or 3rd party
OpenGL renderers.
[ChangeLog][QtQuick] Introduced QQuickRenderControl as a public API.
Task-number: QTBUG-37944
Change-Id: I84262243b261b35cefdf67ec6bba8127a0f29275
Reviewed-by: Paul Olav Tvete <paul.tvete@digia.com>
Diffstat (limited to 'src/quick/items')
-rw-r--r-- | src/quick/items/items.pri | 9 | ||||
-rw-r--r-- | src/quick/items/qquickrendercontrol.cpp | 239 | ||||
-rw-r--r-- | src/quick/items/qquickrendercontrol.h | 84 | ||||
-rw-r--r-- | src/quick/items/qquickrendercontrol_p.h | 68 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 18 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.h | 2 |
6 files changed, 284 insertions, 136 deletions
diff --git a/src/quick/items/items.pri b/src/quick/items/items.pri index add909d0cb..042ff80abc 100644 --- a/src/quick/items/items.pri +++ b/src/quick/items/items.pri @@ -10,7 +10,6 @@ HEADERS += \ $$PWD/qquickrectangle_p_p.h \ $$PWD/qquickwindow.h \ $$PWD/qquickwindow_p.h \ - $$PWD/qquickrendercontrol_p.h \ $$PWD/qquickfocusscope_p.h \ $$PWD/qquickitemsmodule_p.h \ $$PWD/qquickpainteditem.h \ @@ -76,7 +75,9 @@ HEADERS += \ $$PWD/qquickscreen_p.h \ $$PWD/qquickwindowmodule_p.h \ $$PWD/qquickframebufferobject.h \ - $$PWD/qquickitemgrabresult.h + $$PWD/qquickitemgrabresult.h \ + $$PWD/qquickrendercontrol.h \ + $$PWD/qquickrendercontrol_p.h SOURCES += \ $$PWD/qquickevents.cpp \ @@ -84,7 +85,6 @@ SOURCES += \ $$PWD/qquickitem.cpp \ $$PWD/qquickrectangle.cpp \ $$PWD/qquickwindow.cpp \ - $$PWD/qquickrendercontrol.cpp \ $$PWD/qquickfocusscope.cpp \ $$PWD/qquickitemsmodule.cpp \ $$PWD/qquickpainteditem.cpp \ @@ -130,7 +130,8 @@ SOURCES += \ $$PWD/qquickwindowmodule.cpp \ $$PWD/qquickscreen.cpp \ $$PWD/qquickframebufferobject.cpp \ - $$PWD/qquickitemgrabresult.cpp + $$PWD/qquickitemgrabresult.cpp \ + $$PWD/qquickrendercontrol.cpp SOURCES += \ $$PWD/qquickshadereffect.cpp \ diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp index b8d572114a..311a1b95f8 100644 --- a/src/quick/items/qquickrendercontrol.cpp +++ b/src/quick/items/qquickrendercontrol.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtQuick module of the Qt Toolkit. @@ -39,6 +39,7 @@ ** ****************************************************************************/ +#include "qquickrendercontrol.h" #include "qquickrendercontrol_p.h" #include <QtCore/QCoreApplication> @@ -53,7 +54,6 @@ #include <QtQuick/QQuickWindow> #include <QtQuick/private/qquickwindow_p.h> -#include <QtQuick/private/qsgcontext_p.h> #include <private/qqmlprofilerservice_p.h> #include <QtCore/private/qobject_p.h> @@ -61,59 +61,139 @@ QT_BEGIN_NAMESPACE extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha); -class QQuickRenderControlPrivate : public QObjectPrivate -{ -public: - QQuickRenderControlPrivate() - : window(0) - { - sg = QSGContext::createDefaultContext(); - rc = new QSGRenderContext(sg); - } +/*! + \class QQuickRenderControl - ~QQuickRenderControlPrivate() - { - delete rc; - delete sg; - } + \brief The QQuickRenderControl class provides a mechanism for rendering the Qt + Quick scenegraph onto an offscreen render target in a fully + application-controlled manner. - QQuickWindow *window; - QSGContext *sg; - QSGRenderContext *rc; -}; + \since 5.4 -/*! - \class QQuickRenderControl - \brief The QQuickRenderControl class provides a mechanism for rendering the Qt Quick scenegraph. + QQuickWindow and QQuickView and their associated internal render loops render + the Qt Quick scene onto a native window. In some cases, for example when + integrating with 3rd party OpenGL renderers, it might be beneficial to get the + scene into a texture that can then be used in arbitrary ways by the external + rendering engine. QQuickRenderControl makes this possible in a hardware + accelerated manner, unlike the performance-wise limited alternative of using + QQuickWindow::grabWindow() + + When using a QQuickRenderControl, the QQuickWindow does not have to be shown + or even created at all. This means there will not be an underlying native + window for it. Instead, the QQuickWindow instance is associated with the + render control, using the overload of the QQuickWindow constructor, and an + OpenGL framebuffer object by calling QQuickWindow::setRenderTarget(). + + Management of the context and framebuffer object is up to the application. The + context that will be used by Qt Quick must be created before calling + initialize(). The creation of the framebuffer object can be deferred, see + below. Qt 5.4 introduces the ability for QOpenGLContext to adopt existing + native contexts. Together with QQuickRenderControl this makes it possible to + create a QOpenGLContext that shares with an external rendering engine's + existing context. This new QOpenGLContext can then be used to render the Qt + Quick scene into a texture that is accessible by the other engine's context + too. + + Loading and instantiation of the QML components happen by using a + QQmlEngine. Once the root object is created, it will need to be parented to + the QQuickWindow's contentItem(). + + Applications will usually have to connect to 4 important signals: - \internal + \list + + \li QQuickWindow::sceneGraphInitialized() Emitted at some point after calling + QQuickRenderControl::initialize(). Upon this signal, the application is + expected to create its framebuffer object and associate it with the + QQuickWindow. + + \li QQuickWindow::sceneGraphInvalidated() When the scenegraph resources are + released, the framebuffer object can be destroyed too. + + \li QQuickRenderControl::renderRequested() Indicates that the scene has to be + rendered by calling render(). After making the context current, applications + are expected to call render(). + + \li QQuickRenderControl::sceneChanged() Inidcates that the scene has changed + meaning that, before rendering, polishing and synchronizing is also necessary. + + \endlist + + To send events, for example mouse or keyboard events, to the scene, use + QCoreApplication::sendEvent() with the QQuickWindow instance as the receiver. \inmodule QtQuick */ -QQuickRenderControl::QQuickRenderControl() - : QObject(*(new QQuickRenderControlPrivate), 0) +QSGContext *QQuickRenderControlPrivate::sg = 0; + +QQuickRenderControlPrivate::QQuickRenderControlPrivate() + : initialized(0), + window(0) { + if (!sg) { + qAddPostRoutine(cleanup); + sg = QSGContext::createDefaultContext(); + } + rc = new QSGRenderContext(sg); } -QQuickRenderControl::~QQuickRenderControl() +QQuickRenderControlPrivate::~QQuickRenderControlPrivate() { + delete rc; } -void QQuickRenderControl::windowDestroyed() +void QQuickRenderControlPrivate::cleanup() +{ + delete sg; + sg = 0; +} + +QQuickRenderControl::QQuickRenderControl(QObject *parent) + : QObject(*(new QQuickRenderControlPrivate), parent) +{ +} + +/*! + Destroys the instance. Releases all scenegraph resources. + + \sa stop() + */ +QQuickRenderControl::~QQuickRenderControl() { Q_D(QQuickRenderControl); - if (d->window == 0) { - d->rc->invalidate(); + + stop(); + + if (d->window) + QQuickWindowPrivate::get(d->window)->renderControl = 0; +} + +void QQuickRenderControlPrivate::windowDestroyed() +{ + if (window == 0) { + rc->invalidate(); QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); } } +/*! + Initializes the scene graph resources. The context \a gl has to + be the current context. + */ void QQuickRenderControl::initialize(QOpenGLContext *gl) { Q_D(QQuickRenderControl); - if (!d->window) + + if (!d->window) { + qWarning("QQuickRenderControl::initialize called with no associated window"); + return; + } + + if (QOpenGLContext::currentContext() != gl) { + qWarning("QQuickRenderControl::initialize called with incorrect current context"); return; + } // It is the caller's responsiblity to make a context/surface current. // It cannot be done here since the surface to use may not be the @@ -121,17 +201,14 @@ void QQuickRenderControl::initialize(QOpenGLContext *gl) // window/surface at all. d->rc->initialize(gl); -} -void QQuickRenderControl::invalidate() -{ - Q_D(QQuickRenderControl); - d->rc->invalidate(); + d->initialized = true; } /*! This function should be called as late as possible before - sync(). In a threaded scenario, rendering can happen in parallel with this function. + sync(). In a threaded scenario, rendering can happen in parallel + with this function. */ void QQuickRenderControl::polishItems() { @@ -147,9 +224,13 @@ void QQuickRenderControl::polishItems() } /*! - Synchronize GUI and scenegraph. Returns true if the scene graph was changed. + This function is used to synchronize the QML scene with the rendering scene + graph. - This function is a synchronization point. Rendering can not happen in parallel. + If a dedicated render thread is used, the GUI thread should be blocked for the + duration of this call. + + \return \e true if the synchronization changed the scene graph. */ bool QQuickRenderControl::sync() { @@ -165,15 +246,36 @@ bool QQuickRenderControl::sync() } /*! - Stop rendering and release resources. This function is typically - called when the window is hidden. Requires a current context. + Stop rendering and release resources. Requires a current context. + + This is the equivalent of the cleanup operations that happen with a + real QQuickWindow when the window becomes hidden. + + This function takes QQuickWindow::persistentSceneGraph() into + account, meaning that context-specific resources are not released + when persistency is enabled. + + This function is called from the destructor. Therefore there will + typically be no need to call it directly. Pay attention however to + the fact that this requires the context, that was passed to + initialize(), to be the current one at the time of destroying the + QQuickRenderControl instance. + + Once stop() has been called, it is possible to reuse the + QQuickRenderControl instance by calling initialize() again. */ void QQuickRenderControl::stop() { Q_D(QQuickRenderControl); + if (!d->initialized) + return; + if (!d->window) return; + if (!QOpenGLContext::currentContext()) + return; + QQuickWindowPrivate *cd = QQuickWindowPrivate::get(d->window); cd->fireAboutToStop(); cd->cleanupNodesOnShutdown(); @@ -182,10 +284,12 @@ void QQuickRenderControl::stop() d->rc->invalidate(); QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); } + + d->initialized = false; } /*! - Render the scenegraph using the current context. + Renders the scenegraph using the current context. */ void QQuickRenderControl::render() { @@ -197,7 +301,6 @@ void QQuickRenderControl::render() cd->renderSceneGraph(d->window->size()); } - /*! \fn void QQuickRenderControl::renderRequested() @@ -212,7 +315,9 @@ void QQuickRenderControl::render() true, then render() needs to be called. */ - +/*! + Grabs the contents of the scene and returns it as an image. + */ QImage QQuickRenderControl::grab() { Q_D(QQuickRenderControl); @@ -224,47 +329,16 @@ QImage QQuickRenderControl::grab() return grabContent; } -QSGContext *QQuickRenderControl::sceneGraphContext() const -{ - Q_D(const QQuickRenderControl); - return d->sg; -} - -QSGRenderContext *QQuickRenderControl::renderContext(QSGContext *) const +void QQuickRenderControlPrivate::update() { - Q_D(const QQuickRenderControl); - return d->rc; + Q_Q(QQuickRenderControl); + emit q->renderRequested(); } -void QQuickRenderControl::setWindow(QQuickWindow *window) +void QQuickRenderControlPrivate::maybeUpdate() { - Q_D(QQuickRenderControl); - d->window = window; -} - -/*! - Returns the offscreen window. - */ - -QQuickWindow *QQuickRenderControl::window() const -{ - Q_D(const QQuickRenderControl); - return d->window; -} - -/*! - Create an offscreen QQuickWindow for this render control, - unless the render control already has a window(). - - Returns the offscreen window if one is created, otherwise returns null. - The caller takes ownership of the window, and is responsible for deleting it. - */ -QQuickWindow *QQuickRenderControl::createOffscreenWindow() -{ - Q_D(QQuickRenderControl); - if (!d->window) - return new QQuickWindow(this); - return 0; + Q_Q(QQuickRenderControl); + emit q->sceneChanged(); } /*! @@ -284,7 +358,6 @@ QQuickWindow *QQuickRenderControl::createOffscreenWindow() inside its window. */ - QWindow *QQuickRenderControl::renderWindowFor(QQuickWindow *win, QPoint *offset) { if (!win) @@ -295,6 +368,4 @@ QWindow *QQuickRenderControl::renderWindowFor(QQuickWindow *win, QPoint *offset) return 0; } - - QT_END_NAMESPACE diff --git a/src/quick/items/qquickrendercontrol.h b/src/quick/items/qquickrendercontrol.h new file mode 100644 index 0000000000..e5c04fee23 --- /dev/null +++ b/src/quick/items/qquickrendercontrol.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQuick 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 QQUICKRENDERCONTROL_H +#define QQUICKRENDERCONTROL_H + +#include <QtQuick/qtquickglobal.h> +#include <QtGui/QImage> + +QT_BEGIN_NAMESPACE + +class QQuickWindow; +class QOpenGLContext; +class QQuickRenderControlPrivate; + +class Q_QUICK_EXPORT QQuickRenderControl : public QObject +{ + Q_OBJECT + +public: + QQuickRenderControl(QObject *parent = 0); + ~QQuickRenderControl(); + + void initialize(QOpenGLContext *gl); + void stop(); + + void polishItems(); + void render(); + bool sync(); + + QImage grab(); + + static QWindow *renderWindowFor(QQuickWindow *win, QPoint *offset = 0); + virtual QWindow *renderWindow(QPoint *offset) { Q_UNUSED(offset); return 0; } + +Q_SIGNALS: + void renderRequested(); + void sceneChanged(); + +private: + Q_DECLARE_PRIVATE(QQuickRenderControl) +}; + +QT_END_NAMESPACE + +#endif // QQUICKRENDERCONTROL_H diff --git a/src/quick/items/qquickrendercontrol_p.h b/src/quick/items/qquickrendercontrol_p.h index cc30e37724..18b1b370b3 100644 --- a/src/quick/items/qquickrendercontrol_p.h +++ b/src/quick/items/qquickrendercontrol_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtQuick module of the Qt Toolkit. @@ -42,55 +42,45 @@ #ifndef QQUICKRENDERCONTROL_P_H #define QQUICKRENDERCONTROL_P_H -#include <QtGui/QImage> -#include <private/qtquickglobal_p.h> +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// -QT_BEGIN_NAMESPACE +#include "qquickrendercontrol.h" +#include <QtQuick/private/qsgcontext_p.h> -class QQuickWindow; -class QSGContext; -class QSGRenderContext; -class QAnimationDriver; -class QOpenGLContext; -class QQuickRenderControlPrivate; +QT_BEGIN_NAMESPACE -class Q_QUICK_PRIVATE_EXPORT QQuickRenderControl : public QObject +class QQuickRenderControlPrivate : public QObjectPrivate { - Q_OBJECT - Q_DECLARE_PRIVATE(QQuickRenderControl) public: - QQuickRenderControl(); - ~QQuickRenderControl(); + Q_DECLARE_PUBLIC(QQuickRenderControl) - QQuickWindow *window() const; - QQuickWindow *createOffscreenWindow(); - virtual QWindow *renderWindow(QPoint *offset) { Q_UNUSED(offset); return 0; } - static QWindow *renderWindowFor(QQuickWindow *win, QPoint *offset = 0); + QQuickRenderControlPrivate(); + ~QQuickRenderControlPrivate(); - void windowDestroyed(); + static QQuickRenderControlPrivate *get(QQuickRenderControl *renderControl) { + return renderControl->d_func(); + } - void initialize(QOpenGLContext *gl); - void invalidate(); - void polishItems(); - void render(); - bool sync(); - void stop(); + static void cleanup(); - QImage grab(); - -Q_SIGNALS: - void renderRequested(); - void sceneChanged(); + void windowDestroyed(); -private: - friend class QQuickWindowPrivate; - friend class QQuickWindow; - void setWindow(QQuickWindow *window); - inline void update() { /*emit*/ renderRequested(); } - inline void maybeUpdate() { /*emit*/ sceneChanged(); } + void update(); + void maybeUpdate(); - QSGContext *sceneGraphContext() const; - QSGRenderContext *renderContext(QSGContext *) const; + bool initialized; + QQuickWindow *window; + static QSGContext *sg; + QSGRenderContext *rc; }; QT_END_NAMESPACE diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 82897b3f5e..de8eb115dc 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -287,7 +287,7 @@ void QQuickWindow::update() if (d->windowManager) d->windowManager->update(this); else if (d->renderControl) - d->renderControl->update(); + QQuickRenderControlPrivate::get(d->renderControl)->update(); } void forcePolishHelper(QQuickItem *item) @@ -438,7 +438,7 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control) customRenderMode = qgetenv("QSG_VISUALIZE"); renderControl = control; if (renderControl) - renderControl->setWindow(q); + QQuickRenderControlPrivate::get(renderControl)->window = q; if (!renderControl) windowManager = QSGRenderLoop::instance(); @@ -447,8 +447,9 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control) QSGContext *sg; if (renderControl) { - sg = renderControl->sceneGraphContext(); - context = renderControl->renderContext(sg); + QQuickRenderControlPrivate *renderControlPriv = QQuickRenderControlPrivate::get(renderControl); + sg = renderControlPriv->sg; + context = renderControlPriv->rc; } else { windowManager->addWindow(q); sg = windowManager->sceneGraphContext(); @@ -1087,7 +1088,7 @@ QQuickWindow::~QQuickWindow() d->animationController->deleteLater(); if (d->renderControl) { - d->renderControl->windowDestroyed(); + QQuickRenderControlPrivate::get(d->renderControl)->windowDestroyed(); } else if (d->windowManager) { d->windowManager->removeWindow(this); d->windowManager->windowDestroyed(this); @@ -1125,8 +1126,9 @@ void QQuickWindow::releaseResources() /*! - Sets whether the OpenGL context can be released to \a - persistent. The default value is true. + Sets whether the OpenGL context should be preserved, and cannot be + released until the last window is deleted, to \a persistent. The + default value is true. The OpenGL context can be released to free up graphics resources when the window is obscured, hidden or not rendering. When this @@ -2798,7 +2800,7 @@ void QQuickWindow::maybeUpdate() { Q_D(QQuickWindow); if (d->renderControl) - d->renderControl->maybeUpdate(); + QQuickRenderControlPrivate::get(d->renderControl)->maybeUpdate(); else if (d->windowManager) d->windowManager->maybeUpdate(this); } diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h index c95ec5b46d..4ed663ee6e 100644 --- a/src/quick/items/qquickwindow.h +++ b/src/quick/items/qquickwindow.h @@ -87,6 +87,7 @@ public: Q_ENUMS(SceneGraphError) QQuickWindow(QWindow *parent = 0); + explicit QQuickWindow(QQuickRenderControl *renderControl); virtual ~QQuickWindow(); @@ -201,7 +202,6 @@ private: friend class QQuickWidget; friend class QQuickRenderControl; friend class QQuickAnimatorController; - explicit QQuickWindow(QQuickRenderControl*); Q_DISABLE_COPY(QQuickWindow) }; |