summaryrefslogtreecommitdiffstats
path: root/src/quick3d/quick3dscene2d/items
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick3d/quick3dscene2d/items')
-rw-r--r--src/quick3d/quick3dscene2d/items/items.pri17
-rw-r--r--src/quick3d/quick3dscene2d/items/qscene2d.cpp365
-rw-r--r--src/quick3d/quick3dscene2d/items/qscene2d.h112
-rw-r--r--src/quick3d/quick3dscene2d/items/qscene2d_p.h99
-rw-r--r--src/quick3d/quick3dscene2d/items/qt3dquick3dscene2d.cpp100
-rw-r--r--src/quick3d/quick3dscene2d/items/qt3dquick3dscene2d_p.h93
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2d.cpp516
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2d.pri10
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2d_p.h134
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2devent_p.h84
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2dmanager.cpp248
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2dmanager_p.h112
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp162
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2dsharedobject_p.h130
14 files changed, 2182 insertions, 0 deletions
diff --git a/src/quick3d/quick3dscene2d/items/items.pri b/src/quick3d/quick3dscene2d/items/items.pri
new file mode 100644
index 000000000..45d18dc40
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/items.pri
@@ -0,0 +1,17 @@
+HEADERS += \
+ $$PWD/scene2d_p.h \
+ $$PWD/qscene2d_p.h \
+ $$PWD/qscene2d.h \
+ $$PWD/scene2dmanager_p.h \
+ $$PWD/scene2dsharedobject_p.h \
+ $$PWD/scene2devent_p.h \
+ $$PWD/qt3dquick3dscene2d_p.h
+
+SOURCES += \
+ $$PWD/qscene2d.cpp \
+ $$PWD/scene2d.cpp \
+ $$PWD/scene2dmanager.cpp \
+ $$PWD/scene2dsharedobject.cpp \
+ $$PWD/qt3dquick3dscene2d.cpp
+
+INCLUDEPATH += $$PWD
diff --git a/src/quick3d/quick3dscene2d/items/qscene2d.cpp b/src/quick3d/quick3dscene2d/items/qscene2d.cpp
new file mode 100644
index 000000000..52e2be094
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/qscene2d.cpp
@@ -0,0 +1,365 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscene2d.h"
+#include "qscene2d_p.h"
+#include "scene2d_p.h"
+#include "scene2dmanager_p.h"
+#include "scene2devent_p.h"
+
+#include <Qt3DCore/qentity.h>
+#include <Qt3DCore/qpropertynodeaddedchange.h>
+#include <Qt3DCore/qpropertynoderemovedchange.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt3DCore;
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+/*!
+ \class Qt3DRender::Quick::QScene2D
+ \inmodule Qt3DScene2D
+
+ \brief This class enables rendering qml into a texture, which then can be
+ used as a part of 3D scene.
+
+ This class uses QQuickRenderControl to render the given QQuickItem into an
+ offscreen surface, which is attached to a texture provided by the user. This allows the
+ component to directly render into the texture without intermediate copy and the user to
+ freely specify how the texture is used in the 3D scene.
+
+ The entities using the QScene2D can be associated with the class to enable interaction
+ with the item; if an entity has a QObjectPicker component, the pick events from that picker
+ are sent to the QScene2D and converted to mouse events and finally sent to the item.
+
+ \since 5.9
+*/
+
+/*!
+ \qmltype Scene2D
+ \inqmlmodule Qt3D.Scene2D
+ \since 5.9
+ \instantiates Qt3DRender::Quick::QScene2D
+
+ \brief This type enables rendering qml into a texture, which then can be
+ used as a part of 3D scene.
+
+ This object uses RenderControl to render the given Item into an
+ offscreen surface, which is attached to a texture provided by the user. This allows the
+ component to directly render into the texture without intermediate copy and the user to
+ freely specify how the texture is used in the 3D scene.
+
+ The entities using the Scene2D can be associated with the type to enable interaction
+ with the item; if an entity has an ObjectPicker component, the pick events from that picker
+ are sent to the Scene2D and converted to mouse events and finally sent to the item.
+
+ Usage:
+ \qml
+ Entity {
+ id: sceneRoot
+
+ // specify Scene2D inside the entity hierarchy
+ Scene2D {
+ // specify output
+ output: RenderTargetOutput {
+ attachmentPoint: RenderTargetOutput.Color0
+ texture: Texture2D {
+ id: textureId
+ width: 1024
+ height: 1024
+ format: Texture.RGBA8_UNorm
+ }
+ }
+ // specify entities
+ entities: [entityId]
+
+ // specify rendered content
+ Rectangle {
+ color: "red"
+ }
+ }
+
+ Entity {
+ id: entityId
+
+ property Material material: TextureMaterial {
+ texture: textureId
+ }
+ property ObjectPicker picker: ObjectPicker {
+ hoverEnabled: true
+ dragEnabled: true
+ }
+ ...
+
+ \endqml
+ */
+
+/*!
+ \enum QScene2D::RenderPolicy
+
+ This enum type describes types of render policies available.
+ \value Continuous The Scene2D is rendering continuously. This is the default render policy.
+ \value SingleShot The Scene2D renders to the texture only once after which the resources
+ allocated for rendering are released.
+*/
+
+/*!
+ \qmlproperty RenderTargetOutput Qt3D.Render::Scene2D::output
+ Holds the RenderTargetOutput, which specifies where the Scene2D is rendering to.
+ */
+
+/*!
+ \qmlproperty enumeration Qt3D.Render::Scene2D::renderPolicy
+ Holds the render policy of this Scene2D.
+
+ \list
+ \li Continuous The Scene2D is rendering continuously. This is the default render policy.
+ \li SingleShot The Scene2D renders to the texture only once after which the resources
+ allocated for rendering are released.
+ \endlist
+ */
+/*!
+ \qmlproperty Item Qt3D.Render::Scene2D::item
+ Holds the Item, which is rendered by Scene2D to the texture.
+ */
+
+/*!
+ \qmlproperty bool Qt3D.Render::Scene2D::mouseEnabled
+ Holds whether mouse events are enabled for the rendered item. The mouse events are
+ generated from object picking events of the entities added to the Scene2D.
+ Mouse is enabled by default.
+
+ \note Events sent to items are delayed by one frame due to object picking
+ happening in the backend.
+ */
+/*!
+ \qmlproperty list<Entity> Qt3D.Render::Scene2D::entities
+ Holds the list of entities which are associated with the Scene2D object. If the
+ entities have ObjectPicker, the pick events from that entity are sent to Scene2D
+ and converted to mouse events.
+ */
+
+QScene2DPrivate::QScene2DPrivate()
+ : Qt3DCore::QNodePrivate()
+ , m_renderManager(new Scene2DManager(this))
+ , m_output(nullptr)
+{
+}
+
+QScene2DPrivate::~QScene2DPrivate()
+{
+ m_renderManager->cleanup();
+ delete m_renderManager;
+}
+
+void QScene2DPrivate::setScene(Qt3DCore::QScene *scene)
+{
+ Q_Q(QScene2D);
+ QNodePrivate::setScene(scene);
+ const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(q->id());
+ change->setPropertyName("sceneInitialized");
+ notifyObservers(change);
+}
+
+
+/*!
+ The constructor creates a new QScene2D instance with the specified \a parent.
+ */
+QScene2D::QScene2D(Qt3DCore::QNode *parent)
+ : Qt3DCore::QNode(*new QScene2DPrivate, parent)
+{
+}
+
+/*!
+ \property QScene2D::item
+ Holds the QQuickItem, which is rendered by QScene2D to the texture.
+ */
+QQuickItem* QScene2D::item() const
+{
+ Q_D(const QScene2D);
+ return d->m_renderManager->m_item;
+}
+
+void QScene2D::setItem(QQuickItem *item)
+{
+ Q_D(QScene2D);
+ if (d->m_renderManager->m_initialized) {
+ qWarning() << "Unable to set item after initialization.";
+ return;
+ }
+ if (d->m_renderManager->m_item != item) {
+ d->m_renderManager->setItem(item);
+ emit itemChanged(item);
+ }
+}
+
+/*!
+ \property QScene2D::renderPolicy
+
+ Holds the render policy of this Scene2D.
+ */
+QScene2D::RenderPolicy QScene2D::renderPolicy() const
+{
+ Q_D(const QScene2D);
+ return d->m_renderManager->m_renderPolicy;
+}
+
+void QScene2D::setRenderPolicy(QScene2D::RenderPolicy renderPolicy)
+{
+ Q_D(const QScene2D);
+ if (d->m_renderManager->m_renderPolicy != renderPolicy) {
+ d->m_renderManager->m_renderPolicy = renderPolicy;
+ emit renderPolicyChanged(renderPolicy);
+ }
+}
+
+/*!
+ \property QScene2D::output
+ Holds the QRenderTargetOutput, which specifies where the QScene2D is
+ rendering to.
+ */
+Qt3DRender::QRenderTargetOutput *QScene2D::output() const
+{
+ Q_D(const QScene2D);
+ return d->m_output;
+}
+
+void QScene2D::setOutput(Qt3DRender::QRenderTargetOutput *output)
+{
+ Q_D(QScene2D);
+ if (d->m_output != output) {
+ if (d->m_output)
+ d->unregisterDestructionHelper(d->m_output);
+ d->m_output = output;
+ if (output)
+ d->registerDestructionHelper(output, &QScene2D::setOutput, d->m_output);
+ emit outputChanged(output);
+ }
+}
+
+Qt3DCore::QNodeCreatedChangeBasePtr QScene2D::createNodeCreationChange() const
+{
+ auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QScene2DData>::create(this);
+ auto &data = creationChange->data;
+ Q_D(const QScene2D);
+ data.renderPolicy = d->m_renderManager->m_renderPolicy;
+ data.sharedObject = d->m_renderManager->m_sharedObject;
+ data.output = d->m_output ? d->m_output->id() : Qt3DCore::QNodeId();
+ for (Qt3DCore::QEntity *e : d->m_entities)
+ data.entityIds.append(e->id());
+ data.mouseEnabled = d->m_renderManager->m_mouseEnabled;
+ return creationChange;
+}
+
+bool QScene2D::isMouseEnabled() const
+{
+ Q_D(const QScene2D);
+ return d->m_renderManager->m_mouseEnabled;
+}
+
+/*!
+ Retrieve entities associated with the QScene2D.
+ */
+QVector<Qt3DCore::QEntity*> QScene2D::entities()
+{
+ Q_D(const QScene2D);
+ return d->m_entities;
+}
+
+/*!
+ Adds an \a entity to the the QScene2D object. If the entities have QObjectPicker,
+ the pick events from that entity are sent to QScene2D and converted to mouse events.
+*/
+void QScene2D::addEntity(Qt3DCore::QEntity *entity)
+{
+ Q_D(QScene2D);
+ if (!d->m_entities.contains(entity)) {
+ d->m_entities.append(entity);
+
+ d->registerDestructionHelper(entity, &QScene2D::removeEntity, d->m_entities);
+
+ if (d->m_changeArbiter != nullptr) {
+ const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), entity);
+ change->setPropertyName("entities");
+ d->notifyObservers(change);
+ }
+ }
+}
+
+/*!
+ Removes an \a entity from the the QScene2D object.
+*/
+void QScene2D::removeEntity(Qt3DCore::QEntity *entity)
+{
+ Q_D(QScene2D);
+ if (d->m_entities.contains(entity)) {
+ d->m_entities.removeAll(entity);
+
+ d->unregisterDestructionHelper(entity);
+
+ if (d->m_changeArbiter != nullptr) {
+ const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), entity);
+ change->setPropertyName("entities");
+ d->notifyObservers(change);
+ }
+ }
+}
+
+/*!
+ \property QScene2D::mouseEnabled
+ Holds whether mouse events are enabled for the rendered item. The mouse events are
+ generated from object picking events of the entities added to the QScene2D.
+ Mouse is enabled by default.
+
+ \note Events are delayed by one frame due to object picking happening in the backend.
+ */
+void QScene2D::setMouseEnabled(bool enabled)
+{
+ Q_D(QScene2D);
+ if (d->m_renderManager->m_mouseEnabled != enabled) {
+ d->m_renderManager->m_mouseEnabled = enabled;
+ emit mouseEnabledChanged(enabled);
+ }
+}
+
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dscene2d/items/qscene2d.h b/src/quick3d/quick3dscene2d/items/qscene2d.h
new file mode 100644
index 000000000..73322a9e9
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/qscene2d.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QUICK3DSCENE2D_QSCENE2D_H
+#define QT3DRENDER_QUICK3DSCENE2D_QSCENE2D_H
+
+#include <Qt3DQuickScene2D/qt3dquickscene2d_global.h>
+#include <Qt3DRender/qrendertargetoutput.h>
+
+#include <QtCore/QUrl>
+#include <QtCore/QEvent>
+
+#include <Qt3DCore/qnode.h>
+
+#include <QtQuick/qquickitem.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+class QScene2DPrivate;
+
+class QT3DQUICKSCENE2DSHARED_EXPORT QScene2D : public Qt3DCore::QNode
+{
+ Q_OBJECT
+
+ Q_PROPERTY(Qt3DRender::QRenderTargetOutput *output READ output WRITE setOutput NOTIFY outputChanged)
+ Q_PROPERTY(QScene2D::RenderPolicy renderPolicy READ renderPolicy WRITE setRenderPolicy NOTIFY renderPolicyChanged)
+ Q_PROPERTY(QQuickItem *item READ item WRITE setItem NOTIFY itemChanged)
+ Q_PROPERTY(bool mouseEnabled READ isMouseEnabled WRITE setMouseEnabled NOTIFY mouseEnabledChanged)
+
+ Q_CLASSINFO("DefaultProperty", "item")
+
+public:
+
+ enum RenderPolicy {
+ Continuous,
+ SingleShot
+ };
+ Q_ENUM(RenderPolicy)
+
+ explicit QScene2D(Qt3DCore::QNode *parent = nullptr);
+
+ Qt3DRender::QRenderTargetOutput *output() const;
+ QScene2D::RenderPolicy renderPolicy() const;
+ QQuickItem *item() const;
+ bool isMouseEnabled() const;
+
+ QVector<Qt3DCore::QEntity *> entities();
+ void addEntity(Qt3DCore::QEntity *entity);
+ void removeEntity(Qt3DCore::QEntity *entity);
+
+public Q_SLOTS:
+ void setOutput(Qt3DRender::QRenderTargetOutput *output);
+ void setRenderPolicy(QScene2D::RenderPolicy policy);
+ void setItem(QQuickItem *item);
+ void setMouseEnabled(bool enabled);
+
+Q_SIGNALS:
+ void outputChanged(Qt3DRender::QRenderTargetOutput *output);
+ void renderPolicyChanged(QScene2D::RenderPolicy policy);
+ void itemChanged(QQuickItem *item);
+ void mouseEnabledChanged(bool enabled);
+
+protected:
+ Q_DECLARE_PRIVATE(QScene2D)
+
+private:
+ Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE;
+};
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QUICK3DSCENE2D_QSCENE2D_H
diff --git a/src/quick3d/quick3dscene2d/items/qscene2d_p.h b/src/quick3d/quick3dscene2d/items/qscene2d_p.h
new file mode 100644
index 000000000..217058f5c
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/qscene2d_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QUICK3DSCENE2D_QSCENE2D_P_H
+#define QT3DRENDER_QUICK3DSCENE2D_QSCENE2D_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DQuickScene2D/qscene2d.h>
+
+#include <private/qnode_p.h>
+#include <private/scene2dsharedobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+class QScene;
+}
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+class QScene2D;
+class Scene2DManager;
+
+class Q_AUTOTEST_EXPORT QScene2DPrivate : public Qt3DCore::QNodePrivate
+{
+public:
+ Q_DECLARE_PUBLIC(QScene2D)
+
+ QScene2DPrivate();
+ ~QScene2DPrivate();
+
+ void setScene(Qt3DCore::QScene *scene) Q_DECL_OVERRIDE;
+
+ Scene2DManager *m_renderManager;
+ QMetaObject::Connection m_textureDestroyedConnection;
+ Qt3DRender::QRenderTargetOutput *m_output;
+ QVector<Qt3DCore::QEntity *> m_entities;
+};
+
+struct QScene2DData
+{
+ QScene2D::RenderPolicy renderPolicy;
+ Scene2DSharedObjectPtr sharedObject;
+ Qt3DCore::QNodeId output;
+ QVector<Qt3DCore::QNodeId> entityIds;
+ bool mouseEnabled;
+};
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QUICK3DSCENE2D_QSCENE2D_P_H
diff --git a/src/quick3d/quick3dscene2d/items/qt3dquick3dscene2d.cpp b/src/quick3d/quick3dscene2d/items/qt3dquick3dscene2d.cpp
new file mode 100644
index 000000000..83cbefc59
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/qt3dquick3dscene2d.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qt3dquick3dscene2d_p.h"
+#include <Qt3DCore/qentity.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+namespace Quick {
+
+QQuick3DScene2D::QQuick3DScene2D(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QQmlListProperty<Qt3DCore::QEntity> QQuick3DScene2D::entities()
+{
+ return QQmlListProperty<Qt3DCore::QEntity>(this, 0,
+ &QQuick3DScene2D::appendEntity,
+ &QQuick3DScene2D::entityCount,
+ &QQuick3DScene2D::entityAt,
+ &QQuick3DScene2D::clearEntities);
+}
+
+void QQuick3DScene2D::appendEntity(QQmlListProperty<Qt3DCore::QEntity> *list,
+ Qt3DCore::QEntity *entity)
+{
+ QQuick3DScene2D *scene2d = qobject_cast<QQuick3DScene2D *>(list->object);
+ if (scene2d)
+ scene2d->parentScene2D()->addEntity(entity);
+}
+
+int QQuick3DScene2D::entityCount(QQmlListProperty<Qt3DCore::QEntity> *list)
+{
+ QQuick3DScene2D *scene2d = qobject_cast<QQuick3DScene2D *>(list->object);
+ if (scene2d)
+ return scene2d->parentScene2D()->entities().count();
+ return 0;
+}
+
+Qt3DCore::QEntity *QQuick3DScene2D::entityAt(QQmlListProperty<Qt3DCore::QEntity> *list, int index)
+{
+ QQuick3DScene2D *scene2d = qobject_cast<QQuick3DScene2D *>(list->object);
+ if (scene2d) {
+ return qobject_cast<Qt3DCore::QEntity *>(
+ scene2d->parentScene2D()->entities().at(index));
+ }
+ return nullptr;
+}
+
+void QQuick3DScene2D::clearEntities(QQmlListProperty<Qt3DCore::QEntity> *list)
+{
+ QQuick3DScene2D *scene2d = qobject_cast<QQuick3DScene2D *>(list->object);
+ if (scene2d) {
+ QVector<Qt3DCore::QEntity*> entities = scene2d->parentScene2D()->entities();
+ for (Qt3DCore::QEntity *e : entities)
+ scene2d->parentScene2D()->removeEntity(e);
+ }
+}
+
+} // namespace Quick
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dscene2d/items/qt3dquick3dscene2d_p.h b/src/quick3d/quick3dscene2d/items/qt3dquick3dscene2d_p.h
new file mode 100644
index 000000000..57734223b
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/qt3dquick3dscene2d_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DSCENE2D_QUICK_QUICK3DSCENE2D_P_H
+#define QT3DSCENE2D_QUICK_QUICK3DSCENE2D_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/qqmllist.h>
+
+#include <Qt3DQuickScene2D/qscene2d.h>
+
+#include <private/qt3dquickscene2d_global_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+namespace Quick {
+
+class QT3DQUICKSCENE2DSHARED_EXPORT QQuick3DScene2D : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<Qt3DCore::QEntity> entities READ entities)
+
+public:
+ QQuick3DScene2D(QObject *parent = nullptr);
+
+ inline Qt3DRender::Quick::QScene2D *parentScene2D() const
+ {
+ return qobject_cast<Qt3DRender::Quick::QScene2D *>(parent());
+ }
+
+ QQmlListProperty<Qt3DCore::QEntity> entities();
+
+private:
+
+ static void appendEntity(QQmlListProperty<Qt3DCore::QEntity> *list, Qt3DCore::QEntity *entity);
+ static Qt3DCore::QEntity *entityAt(QQmlListProperty<Qt3DCore::QEntity> *list, int index);
+ static int entityCount(QQmlListProperty<Qt3DCore::QEntity> *list);
+ static void clearEntities(QQmlListProperty<Qt3DCore::QEntity> *list);
+};
+
+} // namespace Quick
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_QUICK_QUICK3DMORPHINGANIMATION_P_H
+
diff --git a/src/quick3d/quick3dscene2d/items/scene2d.cpp b/src/quick3d/quick3dscene2d/items/scene2d.cpp
new file mode 100644
index 000000000..b0c58c6c5
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/scene2d.cpp
@@ -0,0 +1,516 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/qpropertynodeaddedchange.h>
+#include <Qt3DCore/qpropertynoderemovedchange.h>
+#include <Qt3DQuickScene2D/qscene2d.h>
+#include <Qt3DRender/qpicktriangleevent.h>
+
+#include <QtCore/qthread.h>
+#include <QtCore/qatomic.h>
+#include <QtGui/qevent.h>
+
+#include <private/qscene2d_p.h>
+#include <private/scene2d_p.h>
+#include <private/scene2dmanager_p.h>
+#include <private/scene2devent_p.h>
+#include <private/graphicscontext_p.h>
+#include <private/texture_p.h>
+#include <private/nodemanagers_p.h>
+#include <private/resourceaccessor_p.h>
+#include <private/attachmentpack_p.h>
+#include <private/qt3dquickscene2d_logging_p.h>
+#include <private/qbackendnode_p.h>
+#include <private/qpickevent_p.h>
+#include <private/entity_p.h>
+#include <private/platformsurfacefilter_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef GL_DEPTH24_STENCIL8
+#define GL_DEPTH24_STENCIL8 0x88F0
+#endif
+
+using namespace Qt3DRender::Quick;
+
+namespace Qt3DRender {
+
+namespace Render {
+
+namespace Quick {
+
+Q_GLOBAL_STATIC(QThread, renderThread)
+Q_GLOBAL_STATIC(QAtomicInt, renderThreadClientCount)
+
+RenderQmlEventHandler::RenderQmlEventHandler(Scene2D *node)
+ : QObject()
+ , m_node(node)
+{
+}
+
+// Event handler for the RenderQmlToTexture::renderThread
+bool RenderQmlEventHandler::event(QEvent *e)
+{
+ switch (static_cast<Scene2DEvent::Type>(e->type())) {
+
+ case Scene2DEvent::Render: {
+ m_node->render();
+ return true;
+ }
+
+ case Scene2DEvent::Initialize: {
+ m_node->initializeRender();
+ return true;
+ }
+
+ case Scene2DEvent::Quit: {
+ m_node->cleanup();
+ return true;
+ }
+
+ default:
+ break;
+ }
+ return QObject::event(e);
+}
+
+Scene2D::Scene2D()
+ : Qt3DRender::Render::BackendNode(Qt3DCore::QBackendNode::ReadWrite)
+ , m_context(nullptr)
+ , m_shareContext(nullptr)
+ , m_renderThread(nullptr)
+ , m_sharedObject(nullptr)
+ , m_fbo(0)
+ , m_rbo(0)
+ , m_initialized(false)
+ , m_renderInitialized(false)
+ , m_mouseEnabled(true)
+ , m_renderPolicy(Qt3DRender::Quick::QScene2D::Continuous)
+{
+ renderThreadClientCount->fetchAndAddAcquire(1);
+}
+
+Scene2D::~Scene2D()
+{
+ stopGrabbing();
+}
+
+void Scene2D::setOutput(Qt3DCore::QNodeId outputId)
+{
+ m_outputId = outputId;
+}
+
+void Scene2D::initializeSharedObject()
+{
+ if (!m_initialized) {
+
+ // bail out if we're running autotests
+ if (!m_sharedObject->m_renderManager
+ || m_sharedObject->m_renderManager->thread() == QThread::currentThread()) {
+ return;
+ }
+
+ renderThread->setObjectName(QStringLiteral("Scene2D::renderThread"));
+ m_renderThread = renderThread;
+ m_sharedObject->m_renderThread = m_renderThread;
+
+ // Create event handler for the render thread
+ m_sharedObject->m_renderObject = new RenderQmlEventHandler(this);
+ m_sharedObject->m_renderObject->moveToThread(m_sharedObject->m_renderThread);
+ if (!m_sharedObject->m_renderThread->isRunning())
+ m_sharedObject->m_renderThread->start();
+
+ // Notify main thread we have been initialized
+ QCoreApplication::postEvent(m_sharedObject->m_renderManager,
+ new Scene2DEvent(Scene2DEvent::Initialized));
+ // Initialize render thread
+ QCoreApplication::postEvent(m_sharedObject->m_renderObject,
+ new Scene2DEvent(Scene2DEvent::Initialize));
+
+ m_initialized = true;
+ }
+}
+
+void Scene2D::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+{
+ const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QScene2DData>>(change);
+ const auto &data = typedChange->data;
+ m_renderPolicy = data.renderPolicy;
+ setSharedObject(data.sharedObject);
+ setOutput(data.output);
+ m_entities = data.entityIds;
+ m_mouseEnabled = data.mouseEnabled;
+}
+
+void Scene2D::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+{
+ switch (e->type()) {
+
+ case Qt3DCore::PropertyUpdated: {
+
+ Qt3DCore::QPropertyUpdatedChangePtr propertyChange
+ = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
+ if (propertyChange->propertyName() == QByteArrayLiteral("renderPolicy")) {
+ m_renderPolicy = propertyChange->value().value<QScene2D::RenderPolicy>();
+ } else if (propertyChange->propertyName() == QByteArrayLiteral("output")) {
+ Qt3DCore::QNodeId outputId = propertyChange->value().value<Qt3DCore::QNodeId>();
+ setOutput(outputId);
+ } else if (propertyChange->propertyName() == QByteArrayLiteral("pressed")) {
+ QPickEventPtr ev = propertyChange->value().value<QPickEventPtr>();
+ handlePickEvent(QEvent::MouseButtonPress, ev);
+ } else if (propertyChange->propertyName() == QByteArrayLiteral("released")) {
+ QPickEventPtr ev = propertyChange->value().value<QPickEventPtr>();
+ handlePickEvent(QEvent::MouseButtonRelease, ev);
+ } else if (propertyChange->propertyName() == QByteArrayLiteral("moved")) {
+ QPickEventPtr ev = propertyChange->value().value<QPickEventPtr>();
+ handlePickEvent(QEvent::MouseMove, ev);
+ } else if (propertyChange->propertyName() == QByteArrayLiteral("mouseEnabled")) {
+ m_mouseEnabled = propertyChange->value().toBool();
+ if (m_mouseEnabled && !m_cachedPickEvent.isNull()) {
+ handlePickEvent(QEvent::MouseButtonPress, m_cachedPickEvent);
+ m_cachedPickEvent.clear();
+ }
+ } else if (propertyChange->propertyName() == QByteArrayLiteral("sceneInitialized")) {
+ startGrabbing();
+ }
+ break;
+ }
+
+ case Qt3DCore::PropertyValueAdded: {
+ const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e);
+ if (change->propertyName() == QByteArrayLiteral("entities")) {
+ m_entities.push_back(change->addedNodeId());
+ registerObjectPickerEvents(change->addedNodeId());
+ }
+ break;
+ }
+
+ case Qt3DCore::PropertyValueRemoved: {
+ const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e);
+ if (change->propertyName() == QByteArrayLiteral("entities")) {
+ m_entities.removeOne(change->removedNodeId());
+ unregisterObjectPickerEvents(change->removedNodeId());
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ BackendNode::sceneChangeEvent(e);
+}
+
+void Scene2D::setSharedObject(Qt3DRender::Quick::Scene2DSharedObjectPtr sharedObject)
+{
+ m_sharedObject = sharedObject;
+ if (!m_initialized)
+ initializeSharedObject();
+}
+
+void Scene2D::initializeRender()
+{
+ if (!m_renderInitialized && m_sharedObject.data() != nullptr) {
+ m_shareContext = renderer()->shareContext();
+ if (!m_shareContext){
+ qCDebug(Qt3DRender::Quick::Scene2D) << Q_FUNC_INFO << "Renderer not initialized.";
+ QCoreApplication::postEvent(m_sharedObject->m_renderObject,
+ new Scene2DEvent(Scene2DEvent::Initialize));
+ return;
+ }
+ m_context = new QOpenGLContext();
+#ifdef Q_OS_MACOS
+ m_context->setFormat(m_shareContext->format());
+#else
+ QSurfaceFormat format;
+ format.setDepthBufferSize(24);
+ format.setStencilBufferSize(8);
+ m_context->setFormat(format);
+#endif
+ m_context->setShareContext(m_shareContext);
+ m_context->create();
+
+ m_context->makeCurrent(m_sharedObject->m_surface);
+ m_sharedObject->m_renderControl->initialize(m_context);
+ m_context->doneCurrent();
+
+ QCoreApplication::postEvent(m_sharedObject->m_renderManager,
+ new Scene2DEvent(Scene2DEvent::Prepare));
+ m_renderInitialized = true;
+ }
+}
+
+bool Scene2D::updateFbo(QOpenGLTexture *texture)
+{
+ QOpenGLFunctions *gl = m_context->functions();
+ if (m_fbo == 0) {
+ gl->glGenFramebuffers(1, &m_fbo);
+ gl->glGenRenderbuffers(1, &m_rbo);
+ }
+ // TODO: Add another codepath when GL_DEPTH24_STENCIL8 is not supported
+ gl->glBindRenderbuffer(GL_RENDERBUFFER, m_rbo);
+ gl->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
+ m_textureSize.width(), m_textureSize.height());
+ gl->glBindRenderbuffer(GL_RENDERBUFFER, 0);
+
+ gl->glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
+ gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, texture->textureId(), 0);
+ gl->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_rbo);
+ GLenum status = gl->glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ gl->glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE)
+ return false;
+ return true;
+}
+
+void Scene2D::syncRenderControl()
+{
+ if (m_sharedObject->isSyncRequested()) {
+
+ m_sharedObject->clearSyncRequest();
+
+ m_sharedObject->m_renderControl->sync();
+
+ // gui thread can now continue
+ m_sharedObject->wake();
+ }
+}
+
+void Scene2D::render()
+{
+ if (m_initialized && m_renderInitialized && m_sharedObject.data() != nullptr) {
+
+ QMutexLocker lock(&m_sharedObject->m_mutex);
+
+ QOpenGLTexture *texture = nullptr;
+ const Qt3DRender::Render::Attachment *attachmentData = nullptr;
+ QMutex *textureLock = nullptr;
+
+#ifdef QT_OPENGL_ES_2_ANGLE
+ SurfaceLocker surfaceLocker(m_sharedObject->m_surface);
+#endif
+ m_context->makeCurrent(m_sharedObject->m_surface);
+
+ if (resourceAccessor()->accessResource(RenderBackendResourceAccessor::OutputAttachment,
+ m_outputId, (void**)&attachmentData, nullptr)) {
+ if (!resourceAccessor()->accessResource(RenderBackendResourceAccessor::OGLTexture,
+ attachmentData->m_textureUuid,
+ (void**)&texture, &textureLock)) {
+ // Need to call sync even if the texture is not in use
+ syncRenderControl();
+ m_context->doneCurrent();
+ qCDebug(Qt3DRender::Quick::Scene2D) << Q_FUNC_INFO << "Texture not in use.";
+ QCoreApplication::postEvent(m_sharedObject->m_renderObject,
+ new Scene2DEvent(Scene2DEvent::Render));
+ return;
+ }
+ textureLock->lock();
+ const QSize textureSize = QSize(texture->width(), texture->height());
+ if (m_attachmentData.m_textureUuid != attachmentData->m_textureUuid
+ || m_attachmentData.m_point != attachmentData->m_point
+ || m_attachmentData.m_face != attachmentData->m_face
+ || m_attachmentData.m_layer != attachmentData->m_layer
+ || m_attachmentData.m_mipLevel != attachmentData->m_mipLevel
+ || m_textureSize != textureSize) {
+ m_textureSize = textureSize;
+ m_attachmentData = *attachmentData;
+ if (!updateFbo(texture)) {
+ // Need to call sync even if the fbo is not usable
+ syncRenderControl();
+ textureLock->unlock();
+ m_context->doneCurrent();
+ qCWarning(Qt3DRender::Quick::Scene2D) << Q_FUNC_INFO << "Fbo not initialized.";
+ return;
+ }
+ }
+ }
+
+ if (m_fbo != m_sharedObject->m_quickWindow->renderTargetId())
+ m_sharedObject->m_quickWindow->setRenderTarget(m_fbo, m_textureSize);
+
+ // Call disallow rendering while mutex is locked
+ if (m_renderPolicy == QScene2D::SingleShot)
+ m_sharedObject->disallowRender();
+
+ // Sync
+ if (m_sharedObject->isSyncRequested()) {
+
+ m_sharedObject->clearSyncRequest();
+
+ m_sharedObject->m_renderControl->sync();
+ }
+
+ // Render
+ m_sharedObject->m_renderControl->render();
+
+ // Tell main thread we are done so it can begin cleanup if this is final frame
+ if (m_renderPolicy == QScene2D::SingleShot)
+ QCoreApplication::postEvent(m_sharedObject->m_renderManager,
+ new Scene2DEvent(Scene2DEvent::Rendered));
+
+ m_sharedObject->m_quickWindow->resetOpenGLState();
+ m_context->functions()->glFlush();
+ if (texture->isAutoMipMapGenerationEnabled())
+ texture->generateMipMaps();
+ textureLock->unlock();
+ m_context->doneCurrent();
+
+ // gui thread can now continue
+ m_sharedObject->wake();
+ }
+}
+
+// this function gets called while the main thread is waiting
+void Scene2D::cleanup()
+{
+ if (m_renderInitialized && m_initialized) {
+ m_context->makeCurrent(m_sharedObject->m_surface);
+ m_sharedObject->m_renderControl->invalidate();
+ m_context->functions()->glDeleteFramebuffers(1, &m_fbo);
+ m_context->functions()->glDeleteRenderbuffers(1, &m_rbo);
+ m_context->doneCurrent();
+ m_renderInitialized = false;
+ }
+ if (m_initialized) {
+ delete m_sharedObject->m_renderObject;
+ m_sharedObject->m_renderObject = nullptr;
+ delete m_context;
+ m_context = nullptr;
+ m_initialized = false;
+ }
+ if (m_sharedObject) {
+ // wake up the main thread
+ m_sharedObject->wake();
+ m_sharedObject = nullptr;
+ }
+
+ renderThreadClientCount->fetchAndSubAcquire(1);
+ if (renderThreadClientCount->load() == 0)
+ renderThread->quit();
+}
+
+
+bool Scene2D::registerObjectPickerEvents(Qt3DCore::QNodeId entityId)
+{
+ Entity *entity = nullptr;
+ if (!resourceAccessor()->accessResource(RenderBackendResourceAccessor::EntityHandle,
+ entityId, (void**)&entity, nullptr)) {
+ return false;
+ }
+ if (!entity->containsComponentsOfType<ObjectPicker>() ||
+ !entity->containsComponentsOfType<GeometryRenderer>()) {
+ qCWarning(Qt3DRender::Quick::Scene2D) << Q_FUNC_INFO
+ << "Entity does not contain required components: ObjectPicker and GeometryRenderer";
+ return false;
+ }
+ Qt3DCore::QBackendNodePrivate *priv = Qt3DCore::QBackendNodePrivate::get(this);
+ Qt3DCore::QChangeArbiter *arbiter = static_cast<Qt3DCore::QChangeArbiter*>(priv->m_arbiter);
+ arbiter->registerObserver(d_ptr, entity->componentUuid<ObjectPicker>());
+ return true;
+}
+
+void Scene2D::unregisterObjectPickerEvents(Qt3DCore::QNodeId entityId)
+{
+ Entity *entity = nullptr;
+ if (!resourceAccessor()->accessResource(RenderBackendResourceAccessor::EntityHandle,
+ entityId, (void**)&entity, nullptr)) {
+ return;
+ }
+ Qt3DCore::QBackendNodePrivate *priv = Qt3DCore::QBackendNodePrivate::get(this);
+ Qt3DCore::QChangeArbiter *arbiter = static_cast<Qt3DCore::QChangeArbiter*>(priv->m_arbiter);
+ arbiter->unregisterObserver(d_ptr, entity->componentUuid<ObjectPicker>());
+}
+
+void Scene2D::handlePickEvent(int type, const Qt3DRender::QPickEventPtr &ev)
+{
+ if (!isEnabled())
+ return;
+ if (m_mouseEnabled) {
+ QPickTriangleEvent *pickTriangle = static_cast<QPickTriangleEvent *>(ev.data());
+ Entity *entity = nullptr;
+ if (!resourceAccessor()->accessResource(RenderBackendResourceAccessor::EntityHandle,
+ QPickEventPrivate::get(pickTriangle)->m_entity,
+ (void**)&entity, nullptr)) {
+ return;
+ }
+ CoordinateReader reader(renderer()->nodeManagers());
+ if (reader.setGeometry(entity->renderComponent<GeometryRenderer>(),
+ QAttribute::defaultTextureCoordinateAttributeName())) {
+ QVector4D c0 = reader.getCoordinate(pickTriangle->vertex1Index());
+ QVector4D c1 = reader.getCoordinate(pickTriangle->vertex2Index());
+ QVector4D c2 = reader.getCoordinate(pickTriangle->vertex3Index());
+ QVector4D ci = c0 * pickTriangle->uvw().x()
+ + c1 * pickTriangle->uvw().y() + c2 * pickTriangle->uvw().z();
+ ci.setW(1.0f);
+
+ const QSize size = m_sharedObject->m_quickWindow->size();
+ QPointF pos = QPointF(ci.x() * size.width(), (1.0f - ci.y()) * size.height());
+ QMouseEvent *mouseEvent
+ = new QMouseEvent(static_cast<QEvent::Type>(type),
+ pos, pos, pos,
+ static_cast<Qt::MouseButton>(pickTriangle->button()),
+ static_cast<Qt::MouseButtons>(pickTriangle->buttons()),
+ static_cast<Qt::KeyboardModifiers>(pickTriangle->modifiers()),
+ Qt::MouseEventSynthesizedByApplication);
+
+ QCoreApplication::postEvent(m_sharedObject->m_quickWindow, mouseEvent);
+ }
+ } else if (type == QEvent::MouseButtonPress) {
+ m_cachedPickEvent = ev;
+ } else {
+ m_cachedPickEvent.clear();
+ }
+}
+
+void Scene2D::startGrabbing()
+{
+ for (Qt3DCore::QNodeId e : qAsConst(m_entities))
+ registerObjectPickerEvents(e);
+}
+
+void Scene2D::stopGrabbing()
+{
+ for (Qt3DCore::QNodeId e : qAsConst(m_entities))
+ unregisterObjectPickerEvents(e);
+}
+
+} // namespace Quick
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dscene2d/items/scene2d.pri b/src/quick3d/quick3dscene2d/items/scene2d.pri
new file mode 100644
index 000000000..4635c43e1
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/scene2d.pri
@@ -0,0 +1,10 @@
+HEADERS += \
+ $$PWD/qscene2d.h \
+ $$PWD/qscene2d_p.h \
+ $$PWD/scene2d_p.h
+
+SOURCES += \
+ $$PWD/qscene2d.cpp \
+ $$PWD/scene2d.cpp
+
+INCLUDEPATH += $$PWD
diff --git a/src/quick3d/quick3dscene2d/items/scene2d_p.h b/src/quick3d/quick3dscene2d/items/scene2d_p.h
new file mode 100644
index 000000000..b42089306
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/scene2d_p.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_QUICK3DSCENE2D_SCENE2D_P_H
+#define QT3DRENDER_RENDER_QUICK3DSCENE2D_SCENE2D_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DCore/qnodeid.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DRender/qpickevent.h>
+#include <Qt3DQuickScene2D/qscene2d.h>
+
+#include <private/qscene2d_p.h>
+#include <private/qrendertargetoutput_p.h>
+#include <private/backendnode_p.h>
+#include <private/attachmentpack_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+class GraphicsContext;
+
+namespace Quick {
+
+class Scene2D;
+
+class RenderQmlEventHandler : public QObject
+{
+ Q_OBJECT
+public:
+ RenderQmlEventHandler(Scene2D *node);
+ bool event(QEvent *e) Q_DECL_OVERRIDE;
+
+private:
+ Scene2D *m_node;
+};
+
+class QT3DQUICKSCENE2DSHARED_EXPORT Scene2D : public Qt3DRender::Render::BackendNode
+{
+public:
+ Scene2D();
+ ~Scene2D();
+
+ void render();
+ void initializeRender();
+ void setSharedObject(Qt3DRender::Quick::Scene2DSharedObjectPtr sharedObject);
+ void cleanup();
+ void setOutput(Qt3DCore::QNodeId outputId);
+ void initializeSharedObject();
+
+ void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_OVERRIDE;
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
+
+ bool updateFbo(QOpenGLTexture *texture);
+ void syncRenderControl();
+ void startGrabbing();
+ void stopGrabbing();
+ bool registerObjectPickerEvents(Qt3DCore::QNodeId entityId);
+ void unregisterObjectPickerEvents(Qt3DCore::QNodeId entityId);
+ void handlePickEvent(int type, const Qt3DRender::QPickEventPtr &ev);
+
+ QOpenGLContext *m_context;
+ QOpenGLContext *m_shareContext;
+ QThread *m_renderThread;
+ Qt3DCore::QNodeId m_outputId;
+ QSharedPointer<Qt3DRender::Quick::Scene2DSharedObject> m_sharedObject;
+ Qt3DCore::QNodeId m_peerId;
+ Qt3DRender::Render::Attachment m_attachmentData;
+
+ GLuint m_fbo;
+ GLuint m_rbo;
+ QSize m_textureSize;
+
+ bool m_initialized;
+ bool m_renderInitialized;
+ bool m_mouseEnabled;
+ Qt3DRender::Quick::QScene2D::RenderPolicy m_renderPolicy;
+ QVector<Qt3DCore::QNodeId> m_entities;
+ Qt3DRender::QPickEventPtr m_cachedPickEvent;
+};
+
+} // Quick
+} // Render
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_QUICK3DSCENE2D_SCENE2D_P_H
diff --git a/src/quick3d/quick3dscene2d/items/scene2devent_p.h b/src/quick3d/quick3dscene2d/items/scene2devent_p.h
new file mode 100644
index 000000000..bcc808a4d
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/scene2devent_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QUICK3DRENDER_SCENE2DEVENT_P_H
+#define QT3DRENDER_QUICK3DRENDER_SCENE2DEVENT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DQuickScene2D/qt3dquickscene2d_global.h>
+
+#include <QtCore/QEvent>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+class Scene2DEvent : public QEvent
+{
+public:
+ enum Type {
+ Initialize = QEvent::User + 1,
+ Render,
+ RenderSync,
+ Prepare,
+ Initialized,
+ Rendered,
+ Quit
+ };
+ Scene2DEvent(Type type)
+ : QEvent(static_cast<QEvent::Type>(type))
+ {
+ }
+};
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QUICK3DRENDER_SCENE2DEVENT_P_H
diff --git a/src/quick3d/quick3dscene2d/items/scene2dmanager.cpp b/src/quick3d/quick3dscene2d/items/scene2dmanager.cpp
new file mode 100644
index 000000000..20c080dec
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/scene2dmanager.cpp
@@ -0,0 +1,248 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscene2d.h"
+#include "qscene2d_p.h"
+#include "scene2d_p.h"
+#include "scene2dmanager_p.h"
+#include "scene2devent_p.h"
+
+#include <Qt3DCore/QPropertyUpdatedChange>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt3DCore;
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+class RenderControl : public QQuickRenderControl
+{
+public:
+ RenderControl(QWindow *w) : m_window(w) { }
+ QWindow *renderWindow(QPoint *offset) Q_DECL_OVERRIDE;
+
+private:
+ QWindow *m_window;
+};
+
+QWindow *RenderControl::renderWindow(QPoint *offset)
+{
+ if (offset)
+ *offset = QPoint(0, 0);
+ return m_window;
+}
+
+/*!
+ \internal
+ Constructs qml render manager.
+ */
+Scene2DManager::Scene2DManager(QScene2DPrivate *priv)
+ : m_rootItem(nullptr)
+ , m_item(nullptr)
+ , m_priv(priv)
+ , m_sharedObject(new Scene2DSharedObject(this))
+ , m_renderPolicy(QScene2D::Continuous)
+ , m_requested(false)
+ , m_initialized(false)
+ , m_renderSyncRequested(false)
+ , m_backendInitialized(false)
+ , m_mouseEnabled(true)
+{
+ m_sharedObject->m_surface = new QOffscreenSurface;
+ m_sharedObject->m_surface->setFormat(QSurfaceFormat::defaultFormat());
+ m_sharedObject->m_surface->create();
+
+ // Create render control
+ m_sharedObject->m_renderControl = new RenderControl(nullptr);
+
+ // Create window to render the QML with
+ m_sharedObject->m_quickWindow = new QQuickWindow(m_sharedObject->m_renderControl);
+ m_sharedObject->m_quickWindow->setClearBeforeRendering(false);
+
+ connect(m_sharedObject->m_renderControl, &QQuickRenderControl::renderRequested,
+ this, &Scene2DManager::requestRender);
+ connect(m_sharedObject->m_renderControl, &QQuickRenderControl::sceneChanged,
+ this, &Scene2DManager::requestRenderSync);
+}
+
+Scene2DManager::~Scene2DManager()
+{
+ m_sharedObject = nullptr;
+}
+
+void Scene2DManager::requestRender()
+{
+ // Don't request render until the backend is initialized.
+ if (m_sharedObject->canRender()) {
+ if (!m_requested) {
+ m_requested = true;
+ QCoreApplication::postEvent(this, new Scene2DEvent(Scene2DEvent::Render));
+ }
+ }
+}
+
+void Scene2DManager::requestRenderSync()
+{
+ // Don't request render until the backed is initialized.
+ if (m_sharedObject->canRender()) {
+ if (!m_requested) {
+ m_requested = true;
+ QCoreApplication::postEvent(this, new Scene2DEvent(Scene2DEvent::RenderSync));
+ }
+ } else {
+ m_renderSyncRequested = true;
+ }
+}
+
+void Scene2DManager::startIfInitialized()
+{
+ if (!m_initialized && m_backendInitialized && m_item != nullptr) {
+ m_rootItem = m_item;
+
+ // Associate root item with the window.
+ m_rootItem->setParentItem(m_sharedObject->m_quickWindow->contentItem());
+
+ // Update window size.
+ updateSizes();
+
+ m_initialized = true;
+ m_sharedObject->setInitialized();
+ }
+}
+
+void Scene2DManager::stopAndClean()
+{
+ if (m_sharedObject->isInitialized()) {
+ QMutexLocker lock(&m_sharedObject->m_mutex);
+ m_sharedObject->requestQuit();
+ m_sharedObject->wait();
+ m_sharedObject->cleanup();
+ }
+}
+
+void Scene2DManager::updateSizes()
+{
+ const int width = m_rootItem->width();
+ const int height = m_rootItem->height();
+ if (width == 0 || height == 0) {
+ qWarning() << "QScene2D: Root item size not set.";
+ return;
+ }
+ m_sharedObject->m_quickWindow->setGeometry(0, 0, width, height);
+}
+
+void Scene2DManager::setItem(QQuickItem *item)
+{
+ m_item = item;
+ startIfInitialized();
+}
+
+bool Scene2DManager::event(QEvent *e)
+{
+ switch (static_cast<Scene2DEvent::Type>(e->type())) {
+
+ case Scene2DEvent::Render: {
+ // just render request, don't need to call sync in render thread
+ QMutexLocker lock(&m_sharedObject->m_mutex);
+ m_sharedObject->requestRender(false);
+ m_requested = false;
+ return true;
+ }
+
+ case Scene2DEvent::RenderSync: {
+ // sync and render request, main and render threads must be synchronized
+ if (!m_sharedObject->isQuit())
+ doRenderSync();
+ m_requested = false;
+ return true;
+ }
+
+ case Scene2DEvent::Prepare: {
+ m_sharedObject->m_renderControl->prepareThread(m_sharedObject->m_renderThread);
+ m_sharedObject->setPrepared();
+
+ if (m_renderSyncRequested) {
+ if (!m_requested) {
+ m_requested = true;
+ QCoreApplication::postEvent(this, new Scene2DEvent(Scene2DEvent::RenderSync));
+ }
+ m_renderSyncRequested = false;
+ }
+ return true;
+ }
+
+ case Scene2DEvent::Initialized: {
+ // backend is initialized, start the qml
+ m_backendInitialized = true;
+ startIfInitialized();
+ return true;
+ }
+
+ case Scene2DEvent::Rendered: {
+ // render is done, excellent, now clean anything not needed anymore.
+ stopAndClean();
+ return true;
+ }
+
+ default:
+ break;
+ }
+ return QObject::event(e);
+}
+
+void Scene2DManager::doRenderSync()
+{
+ QMutexLocker lock(&m_sharedObject->m_mutex);
+
+ m_sharedObject->requestRender(true);
+ m_sharedObject->m_renderControl->polishItems();
+
+ // begin waiting render thread
+ m_sharedObject->wait();
+ m_requested = false;
+}
+
+void Scene2DManager::cleanup()
+{
+ stopAndClean();
+}
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dscene2d/items/scene2dmanager_p.h b/src/quick3d/quick3dscene2d/items/scene2dmanager_p.h
new file mode 100644
index 000000000..821616f47
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/scene2dmanager_p.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QUICK3DRENDER_SCENE2DMANAGER_P_H
+#define QT3DRENDER_QUICK3DRENDER_SCENE2DMANAGER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DQuickScene2D/qt3dquickscene2d_global.h>
+#include <Qt3DQuickScene2D/qscene2d.h>
+
+#include <QtQml/QQmlEngine>
+#include <QtQml/QQmlComponent>
+#include <QtQuick/QQuickItem>
+
+#include <private/qnode_p.h>
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+class QScene2DPrivate;
+class Scene2DSharedObject;
+
+class Scene2DManager : public QObject
+{
+ Q_OBJECT
+public:
+ Scene2DManager(QScene2DPrivate *priv);
+ ~Scene2DManager();
+
+ QQuickItem *m_rootItem;
+ QQuickItem *m_item;
+
+ QScene2DPrivate *m_priv;
+ QSharedPointer<Scene2DSharedObject> m_sharedObject;
+
+ Qt3DCore::QNodeId m_id;
+ QScene2D::RenderPolicy m_renderPolicy;
+
+ bool m_requested;
+ bool m_initialized;
+ bool m_renderSyncRequested;
+ bool m_backendInitialized;
+ bool m_mouseEnabled;
+
+ void requestRender();
+ void requestRenderSync();
+ void doRenderSync();
+ void startIfInitialized();
+ void stopAndClean();
+ void updateSizes();
+
+ void setItem(QQuickItem *item);
+
+ bool event(QEvent *e) Q_DECL_OVERRIDE;
+
+ void cleanup();
+};
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QUICK3DRENDER_SCENE2DMANAGER_P_H
diff --git a/src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp b/src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp
new file mode 100644
index 000000000..1dd798d94
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscene2d.h"
+#include "qscene2d_p.h"
+#include "scene2d_p.h"
+#include "scene2dmanager_p.h"
+#include "scene2devent_p.h"
+#include "scene2dsharedobject_p.h"
+
+#include <Qt3DCore/QPropertyUpdatedChange>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt3DCore;
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+
+/*!
+ \internal
+ Constructs object shared by the front-end and back-end to synchronize the rendering.
+ */
+Scene2DSharedObject::Scene2DSharedObject(Scene2DManager *manager)
+ : m_renderControl(nullptr)
+ , m_quickWindow(nullptr)
+ , m_renderManager(manager)
+ , m_surface(nullptr)
+ , m_renderObject(nullptr)
+ , m_disallowed(false)
+ , m_quit(false)
+ , m_requestSync(false)
+ , m_prepared(false)
+ , m_initialized(false)
+{
+}
+
+Scene2DSharedObject::~Scene2DSharedObject()
+{
+}
+
+void Scene2DSharedObject::cleanup()
+{
+ delete m_renderControl;
+ delete m_quickWindow;
+ delete m_surface;
+ m_renderControl = nullptr;
+ m_quickWindow = nullptr;
+ m_surface = nullptr;
+ m_initialized = false;
+}
+
+bool Scene2DSharedObject::canRender() const
+{
+ return m_initialized && m_prepared && !m_disallowed;
+}
+
+bool Scene2DSharedObject::isInitialized() const
+{
+ return m_initialized;
+}
+
+void Scene2DSharedObject::disallowRender()
+{
+ m_disallowed = true;
+}
+
+void Scene2DSharedObject::setInitialized()
+{
+ m_initialized = true;
+}
+
+bool Scene2DSharedObject::isPrepared() const
+{
+ return m_prepared;
+}
+
+void Scene2DSharedObject::setPrepared()
+{
+ m_prepared = true;
+}
+
+// not protected, call only from main thread
+bool Scene2DSharedObject::isQuit() const
+{
+ Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread());
+ return m_quit;
+}
+
+// not protected, call only from main thread
+void Scene2DSharedObject::requestQuit()
+{
+ Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread());
+ m_quit = true;
+ QCoreApplication::postEvent(m_renderObject, new Scene2DEvent(Scene2DEvent::Quit));
+}
+
+bool Scene2DSharedObject::isSyncRequested() const
+{
+ return m_requestSync;
+}
+
+void Scene2DSharedObject::requestRender(bool sync)
+{
+ m_requestSync = sync;
+ QCoreApplication::postEvent(m_renderObject, new Scene2DEvent(Scene2DEvent::Render));
+}
+
+void Scene2DSharedObject::wait()
+{
+ m_cond.wait(&m_mutex);
+}
+
+void Scene2DSharedObject::wake()
+{
+ m_cond.wakeOne();
+}
+
+void Scene2DSharedObject::clearSyncRequest()
+{
+ m_requestSync = false;
+}
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dscene2d/items/scene2dsharedobject_p.h b/src/quick3d/quick3dscene2d/items/scene2dsharedobject_p.h
new file mode 100644
index 000000000..83863be20
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/scene2dsharedobject_p.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QUICK3DRENDER_SCENE2DSHAREDOBJECT_P_H
+#define QT3DRENDER_QUICK3DRENDER_SCENE2DSHAREDOBJECT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DQuickScene2D/qt3dquickscene2d_global.h>
+#include <Qt3DQuickScene2D/qscene2d.h>
+
+#include <QtQuick/QQuickWindow>
+#include <QtQuick/QQuickRenderControl>
+#include <QtGui/QOffscreenSurface>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QWaitCondition>
+#include <QtCore/QThread>
+
+#include <private/qnode_p.h>
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+class Scene2DManager;
+
+class Q_AUTOTEST_EXPORT Scene2DSharedObject
+{
+public:
+ Scene2DSharedObject(Scene2DManager *manager);
+ ~Scene2DSharedObject();
+
+ QQuickRenderControl *m_renderControl;
+ QQuickWindow *m_quickWindow;
+ Scene2DManager *m_renderManager;
+ QOffscreenSurface *m_surface;
+
+ QThread *m_renderThread;
+ QObject *m_renderObject;
+
+ QWaitCondition m_cond;
+ QMutex m_mutex;
+
+ bool isInitialized() const;
+ void setInitialized();
+
+ void requestQuit();
+ bool isQuit() const;
+
+ void requestRender(bool sync);
+
+ bool isSyncRequested() const;
+ void clearSyncRequest();
+
+ void wait();
+ void wake();
+
+ bool isPrepared() const;
+ void setPrepared();
+
+ void disallowRender();
+ bool canRender() const;
+
+ void cleanup();
+
+private:
+
+ bool m_disallowed;
+ bool m_quit;
+ bool m_requestSync;
+ bool m_prepared;
+ bool m_initialized;
+};
+
+typedef QSharedPointer<Scene2DSharedObject> Scene2DSharedObjectPtr;
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(Qt3DRender::Quick::Scene2DSharedObjectPtr)
+
+#endif // QT3DRENDER_QUICK3DRENDER_SCENE2DSHAREDOBJECT_P_H