summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2016-01-18 18:32:22 +0000
committerSean Harmer <sean.harmer@kdab.com>2016-01-18 23:28:50 +0000
commit550a9173f56c2c4a536f2003c232fb5f2b04a158 (patch)
tree4355e86a9b5b037a0b6294c169bbf311f6bc29c1 /src
parentce8e5ed4a6b2c4b1e1b26a33b74e92c3edc8bfd1 (diff)
Refactor the scene3d classes into one class per pair of files
No functional changes. Change-Id: I5895e3bcaf65fb7524e6adb10bca1f8c6fdb6c44 Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
Diffstat (limited to 'src')
-rw-r--r--src/quick3d/imports/scene3d/importsscene3d.pro14
-rw-r--r--src/quick3d/imports/scene3d/scene3dcleaner.cpp72
-rw-r--r--src/quick3d/imports/scene3d/scene3dcleaner_p.h79
-rw-r--r--src/quick3d/imports/scene3d/scene3ditem.cpp547
-rw-r--r--src/quick3d/imports/scene3d/scene3drenderer.cpp294
-rw-r--r--src/quick3d/imports/scene3d/scene3drenderer_p.h113
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgmaterial.cpp65
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgmaterial_p.h83
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp169
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgmaterialshader_p.h79
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgnode.cpp86
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgnode_p.h89
12 files changed, 1144 insertions, 546 deletions
diff --git a/src/quick3d/imports/scene3d/importsscene3d.pro b/src/quick3d/imports/scene3d/importsscene3d.pro
index 4c0724e20..2812b15b0 100644
--- a/src/quick3d/imports/scene3d/importsscene3d.pro
+++ b/src/quick3d/imports/scene3d/importsscene3d.pro
@@ -7,12 +7,22 @@ QT += qml quick 3dcore 3drender 3dinput
HEADERS += \
qtquickscene3dplugin.h \
scene3dlogging_p.h \
- scene3ditem_p.h
+ scene3ditem_p.h \
+ scene3dcleaner_p.h \
+ scene3drenderer_p.h \
+ scene3dsgnode_p.h \
+ scene3dsgmaterialshader_p.h \
+ scene3dsgmaterial_p.h
SOURCES += \
qtquickscene3dplugin.cpp \
scene3ditem.cpp \
- scene3dlogging.cpp
+ scene3dlogging.cpp \
+ scene3dcleaner.cpp \
+ scene3drenderer.cpp \
+ scene3dsgnode.cpp \
+ scene3dsgmaterialshader.cpp \
+ scene3dsgmaterial.cpp
OTHER_FILES += qmldir
diff --git a/src/quick3d/imports/scene3d/scene3dcleaner.cpp b/src/quick3d/imports/scene3d/scene3dcleaner.cpp
new file mode 100644
index 000000000..fd4ebe50d
--- /dev/null
+++ b/src/quick3d/imports/scene3d/scene3dcleaner.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 "scene3dcleaner_p.h"
+#include "scene3dlogging_p.h"
+#include "scene3drenderer_p.h"
+
+#include <Qt3DCore/qaspectengine.h>
+
+#include <QtCore/qthread.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+Scene3DCleaner::Scene3DCleaner(QObject *parent)
+ : QObject(parent)
+ , m_renderer(Q_NULLPTR)
+{
+}
+
+Scene3DCleaner::~Scene3DCleaner()
+{
+ qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread();
+}
+
+void Scene3DCleaner::cleanup()
+{
+ Q_ASSERT(m_renderer);
+ delete m_renderer->m_aspectEngine; // also deletes m_renderer->m_renderAspect
+ m_renderer->m_aspectEngine = Q_NULLPTR;
+ m_renderer->m_renderAspect = Q_NULLPTR;
+ m_renderer->deleteLater();
+ deleteLater();
+}
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/imports/scene3d/scene3dcleaner_p.h b/src/quick3d/imports/scene3d/scene3dcleaner_p.h
new file mode 100644
index 000000000..135a1c4aa
--- /dev/null
+++ b/src/quick3d/imports/scene3d/scene3dcleaner_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** 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_SCENE3DCLEANER_P_H
+#define QT3DRENDER_SCENE3DCLEANER_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.
+//
+
+#include <QObject>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class Scene3DRenderer;
+
+class Scene3DCleaner : public QObject
+{
+ Q_OBJECT
+public:
+ explicit Scene3DCleaner(QObject *parent = 0);
+ ~Scene3DCleaner();
+
+ void setRenderer(Scene3DRenderer *renderer) { m_renderer = renderer; }
+
+public Q_SLOTS:
+ void cleanup();
+
+private:
+ Scene3DRenderer *m_renderer;
+};
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_SCENE3DCLEANER_H
diff --git a/src/quick3d/imports/scene3d/scene3ditem.cpp b/src/quick3d/imports/scene3d/scene3ditem.cpp
index ef839ae87..4166b1ddf 100644
--- a/src/quick3d/imports/scene3d/scene3ditem.cpp
+++ b/src/quick3d/imports/scene3d/scene3ditem.cpp
@@ -35,418 +35,19 @@
****************************************************************************/
#include "scene3ditem_p.h"
+#include "scene3dcleaner_p.h"
#include "scene3dlogging_p.h"
+#include "scene3drenderer_p.h"
+#include "scene3dsgnode_p.h"
#include <Qt3DCore/QAspectEngine>
#include <Qt3DRender/QRenderAspect>
#include <Qt3DInput/QInputAspect>
-#include <QOpenGLContext>
-#include <QOpenGLFramebufferObject>
-#include <QOpenGLFramebufferObjectFormat>
-#include <QSurface>
-#include <QQuickWindow>
-
-#include <QSGTexture>
-#include <QSGMaterial>
-#include <QSGNode>
-#include <QOpenGLFunctions>
-#include <QThread>
-
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-class ContextSaver
-{
-public:
- explicit ContextSaver(QOpenGLContext *context = QOpenGLContext::currentContext())
- : m_context(context),
- m_surface(context ? context->surface() : Q_NULLPTR)
- {
- }
-
- ~ContextSaver()
- {
- if (m_context)
- m_context->makeCurrent(m_surface);
- }
-
- QOpenGLContext *context() const { return m_context; }
- QSurface *surface() const { return m_surface; }
-
-private:
- QOpenGLContext * const m_context;
- QSurface * const m_surface;
-};
-
-class Scene3DSGNode;
-
-/*!
- \class Qt3DCore::Scene3DRenderer
- \internal
-
- \brief The Qt3DCore::Scene3DRenderer class takes care of rendering a Qt3D scene
- within a Framebuffer object to be used by the QtQuick 2 renderer.
-
- The Qt3DCore::Scene3DRenderer class renders a Qt3D scene as provided by a Qt3DCore::Scene3DItem.
- It owns the aspectEngine even though it doesn't instantiate it.
-
- The shutdown procedure is a two steps process that goes as follow:
-
- \li The window is closed
-
- \li This triggers the windowsChanged signal which the Scene3DRenderer
- uses to perform the necessary cleanups in the QSGRenderThread (destroys
- DebugLogger ...) with the shutdown slot (queued connection).
-
- \li The destroyed signal of the window is also connected to the
- Scene3DRenderer. When triggered in the context of the main thread, the
- cleanup slot is called.
-
- There is an alternate shutdown procedure in case the QQuickItem is
- destroyed with an active window which can happen in the case where the
- Scene3D is used with a QtQuick Loader
-
- In that case the shutdown procedure goes the same except that the destroyed
- signal of the window is not called. Therefore the cleanup method is invoked
- to properly destroy the aspect engine.
- */
-
-// Lives in the main thread
-// Used to delete the Qt3D aspect engine in the main thread
-class Scene3DCleaner : public QObject
-{
- Q_OBJECT
-public:
- Scene3DCleaner()
- : QObject()
- , m_renderer(Q_NULLPTR)
- {}
-
- ~Scene3DCleaner()
- {
- qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread();
- }
-
- void setRenderer(Scene3DRenderer *renderer)
- {
- m_renderer = renderer;
- }
-
-public Q_SLOTS:
- void cleanup();
-
-private:
- Scene3DRenderer *m_renderer;
-};
-
-// Lives in the aspect thread (QSGRenderThread)
-class Scene3DRenderer : public QObject
-{
- Q_OBJECT
-public:
- Scene3DRenderer(Scene3DItem *item,
- Qt3DCore::QAspectEngine *aspectEngine,
- QRenderAspect *renderAspect)
- : QObject()
- , m_item(item)
- , m_aspectEngine(aspectEngine)
- , m_renderAspect(renderAspect)
- , m_multisampledFBO(Q_NULLPTR)
- , m_finalFBO(Q_NULLPTR)
- , m_texture(Q_NULLPTR)
- , m_multisample(false) // this value is not used, will be synced from the Scene3DItem instead
- , m_lastMultisample(false)
- {
- Q_CHECK_PTR(m_item);
- Q_CHECK_PTR(m_item->window());
-
- QObject::connect(m_item->window(), &QQuickWindow::beforeRendering, this, &Scene3DRenderer::render, Qt::DirectConnection);
- QObject::connect(m_item, &QQuickItem::windowChanged, this, &Scene3DRenderer::onWindowChangedQueued, Qt::QueuedConnection);
-
- ContextSaver saver;
-
- QVariantMap data;
- data.insert(QStringLiteral("surface"), QVariant::fromValue(saver.surface()));
- m_aspectEngine->setData(data);
-
- m_renderAspect->renderInitialize(saver.context());
- scheduleRootEntityChange();
- }
-
- // The Scene3DRender is delete by itself with the cleanup slot
- ~Scene3DRenderer()
- {
- qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread();
- }
-
- QOpenGLFramebufferObject *createMultisampledFramebufferObject(const QSize &size)
- {
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
- format.setSamples(4);
- return new QOpenGLFramebufferObject(size, format);
- }
-
- QOpenGLFramebufferObject *createFramebufferObject(const QSize &size)
- {
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::Depth);
- return new QOpenGLFramebufferObject(size, format);
- }
-
- void scheduleRootEntityChange()
- {
- QMetaObject::invokeMethod(m_item, "applyRootEntityChange", Qt::QueuedConnection);
- }
-
- void setSGNode(Scene3DSGNode *node) Q_DECL_NOEXCEPT;
-
- void setCleanerHelper(Scene3DCleaner *cleaner)
- {
- m_cleaner = cleaner;
- if (m_cleaner) {
- // Window closed case
- QObject::connect(m_item->window(), &QQuickWindow::destroyed, m_cleaner, &Scene3DCleaner::cleanup);
- m_cleaner->setRenderer(this);
- }
- }
-
- void synchronize();
-
-public Q_SLOTS:
- void render();
-
- // Executed in the QtQuick render thread.
- void shutdown()
- {
- qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread();
-
- // Set to null so that subsequent calls to render
- // would return early
- m_item = Q_NULLPTR;
-
- // Shutdown the Renderer Aspect while the OpenGL context
- // is still valid
- if (m_renderAspect)
- m_renderAspect->renderShutdown();
- }
-
- // SGThread
- void onWindowChangedQueued(QQuickWindow *w)
- {
- if (w == Q_NULLPTR) {
- qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread();
- shutdown();
- // Will only trigger something with the Loader case
- // The window closed cases is handled by the window's destroyed
- // signal
- QMetaObject::invokeMethod(m_cleaner, "cleanup");
- }
- }
-
-private:
- Scene3DItem *m_item; // Will be released by the QQuickWindow/QML Engine
- Qt3DCore::QAspectEngine *m_aspectEngine; // Will be released by the Scene3DRendererCleaner
- QRenderAspect *m_renderAspect; // Will be released by the aspectEngine
- QScopedPointer<QOpenGLFramebufferObject> m_multisampledFBO;
- QScopedPointer<QOpenGLFramebufferObject> m_finalFBO;
- QScopedPointer<QSGTexture> m_texture;
- Scene3DSGNode *m_node; // Will be released by the QtQuick SceneGraph
- Scene3DCleaner *m_cleaner;
- QSize m_lastSize;
- bool m_multisample;
- bool m_lastMultisample;
-
- friend class Scene3DCleaner;
-};
-
-/*!
- \class Qt3DCore::SCene3DMaterialShader
- \internal
-
- \brief The Qt3DCore::Scene3DSGMaterialShader class is a custom
- QSGMaterialShader subclass instantiated by a Qt3DCore::Scene3DSGMateria1
-
- The Qt3DCore::Scene3DSGMaterialShader provides a shader that renders a texture
- using premultiplied alpha.
- */
-class Scene3DSGMaterialShader : public QSGMaterialShader
-{
-public:
- void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) Q_DECL_FINAL;
-
- const char * const *attributeNames() const Q_DECL_FINAL
- {
- static char const *const attr[] = { "qt_VertexPosition", "qt_VertexTexCoord", 0 };
- return attr;
- }
-
- static QSGMaterialType type;
-
-protected:
- const char *vertexShader() const Q_DECL_FINAL
- {
- QOpenGLContext *ctx = QOpenGLContext::currentContext();
- if (ctx->format().version() >= qMakePair(3, 2) && ctx->format().profile() == QSurfaceFormat::CoreProfile) {
- return ""
- "#version 150 core \n"
- "uniform mat4 qt_Matrix; \n"
- "in vec4 qt_VertexPosition; \n"
- "in vec2 qt_VertexTexCoord; \n"
- "out vec2 qt_TexCoord; \n"
- "void main() { \n"
- " qt_TexCoord = qt_VertexTexCoord; \n"
- " gl_Position = qt_Matrix * qt_VertexPosition; \n"
- "}";
- } else {
- return ""
- "uniform highp mat4 qt_Matrix; \n"
- "attribute highp vec4 qt_VertexPosition; \n"
- "attribute highp vec2 qt_VertexTexCoord; \n"
- "varying highp vec2 qt_TexCoord; \n"
- "void main() { \n"
- " qt_TexCoord = qt_VertexTexCoord; \n"
- " gl_Position = qt_Matrix * qt_VertexPosition; \n"
- "}";
- }
- }
-
- const char *fragmentShader() const Q_DECL_FINAL
- {
- QOpenGLContext *ctx = QOpenGLContext::currentContext();
- if (ctx->format().version() >= qMakePair(3, 2) && ctx->format().profile() == QSurfaceFormat::CoreProfile) {
- return ""
- "#version 150 core \n"
- "uniform sampler2D source; \n"
- "uniform float qt_Opacity; \n"
- "in vec2 qt_TexCoord; \n"
- "out vec4 fragColor; \n"
- "void main() { \n"
- " vec4 p = texture(source, qt_TexCoord); \n"
- " fragColor = vec4(p.rgb * p.a, qt_Opacity * p.a); \n"
- "}";
- } else {
- return ""
- "uniform highp sampler2D source; \n"
- "uniform highp float qt_Opacity; \n"
- "varying highp vec2 qt_TexCoord; \n"
- "void main() { \n"
- " highp vec4 p = texture2D(source, qt_TexCoord); \n"
- " gl_FragColor = vec4(p.rgb * p.a, qt_Opacity * p.a); \n"
- "}";
- }
- }
-
- void initialize() Q_DECL_FINAL
- {
- m_matrixId = program()->uniformLocation("qt_Matrix");
- m_opacityId = program()->uniformLocation("qt_Opacity");
- }
-
-private:
- int m_matrixId;
- int m_opacityId;
-};
-
-QSGMaterialType Scene3DSGMaterialShader::type;
-
-/*!
- \class Qt3DCore::Scene3DSGMaterial
- \internal
- \inherit QSGMaterial
-
- \brief The Qt3DCore::Scene3DSGMaterial class is a custom QSGMaterial subclass used to
- render a Qt3DCore::Scene3DSGNode
-
- The Qt3DCore::Scene3DSGMaterial class renders a texture using premultiplied
- alpha unlike the QSGSimpleTextureMaterial.
-
- This is needed to properly integrate alpha blending from a Qt3D scene
- within a QtQuick 2 scene.
- */
-class Scene3DSGMaterial : public QSGMaterial
-{
-public:
- Scene3DSGMaterial()
- : QSGMaterial()
- , m_texture(Q_NULLPTR)
- {}
-
- void setTexture(QSGTexture *texture) Q_DECL_NOEXCEPT
- {
- m_texture = texture;
- setFlag(Blending, m_texture ? m_texture->hasAlphaChannel() : false);
- }
-
- QSGTexture *texture() const Q_DECL_NOEXCEPT { return m_texture; }
- QSGMaterialType *type() const Q_DECL_FINAL { return &Scene3DSGMaterialShader::type; }
- QSGMaterialShader *createShader() const Q_DECL_FINAL { return new Scene3DSGMaterialShader(); }
-
-private:
- QSGTexture *m_texture;
-};
-
-/*!
- \class Qt3DCore::Scene3DSGNode
- \internal
-
- \brief The Qt3DCore::Scene3DSGNode class is a simple QSGeometryNode subclass that
- uses a Qt3DCore::Scene3DMaterial
-
- The Qt3DCore::Scene3DSGNode allows to render a simple rect texture with
- premultiplied alpha.
- */
-class Scene3DSGNode : public QSGGeometryNode
-{
-public:
- Scene3DSGNode()
- : QSGGeometryNode()
- , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
- {
- setMaterial(&m_material);
- setOpaqueMaterial(&m_opaqueMaterial);
- setGeometry(&m_geometry);
- qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread();
- }
-
- ~Scene3DSGNode()
- {
- qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread();
- // The Scene3DSGNode is deleted by the QSGRenderThread when the SceneGraph
- // is terminated.
- }
-
- void setTexture(QSGTexture *texture) Q_DECL_NOEXCEPT
- {
- m_material.setTexture(texture);
- m_opaqueMaterial.setTexture(texture);
- markDirty(DirtyMaterial);
- }
-
- QSGTexture *texture() const Q_DECL_NOEXCEPT { return m_material.texture(); }
-
- void setRect(const QRectF &rect)
- {
- if (rect != m_rect) {
- m_rect = rect;
- // Map the item's bounding rect to normalized texture coordinates
- const QRectF sourceRect(0.0f, 1.0f, 1.0f, -1.0f);
- QSGGeometry::updateTexturedRectGeometry(&m_geometry, m_rect, sourceRect);
- markDirty(DirtyGeometry);
- }
- }
-
- QRectF rect() const Q_DECL_NOEXCEPT { return m_rect; }
-
-private:
- Scene3DSGMaterial m_material;
- Scene3DSGMaterial m_opaqueMaterial;
- QSGGeometry m_geometry;
- QRectF m_rect;
-};
-
/*!
\class Qt3DCore::Scene3DItem
\internal
@@ -459,7 +60,6 @@ private:
multisampled Framebuffer object to be then renderer through the use of a
Qt3DCore::Scene3DSGNode with premultiplied alpha.
*/
-
Scene3DItem::Scene3DItem(QQuickItem *parent)
: QQuickItem(parent)
, m_entity(Q_NULLPTR)
@@ -589,147 +189,6 @@ QSGNode *Scene3DItem::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNode
return fboNode;
}
-void Scene3DRenderer::synchronize()
-{
- m_multisample = m_item->multisample();
-}
-
-void Scene3DRenderer::setSGNode(Scene3DSGNode *node) Q_DECL_NOEXCEPT
-{
- m_node = node;
- if (!m_texture.isNull())
- node->setTexture(m_texture.data());
-}
-
-void Scene3DRenderer::render()
-{
- if (!m_item || !m_item->window())
- return;
-
- QQuickWindow *window = m_item->window();
-
- if (m_aspectEngine->rootEntity() != m_item->entity())
- scheduleRootEntityChange();
-
- ContextSaver saver;
-
- const QSize currentSize = m_item->boundingRect().size().toSize() * window->effectiveDevicePixelRatio();
- const bool forceRecreate = currentSize != m_lastSize || m_multisample != m_lastMultisample;
-
- // Rebuild FBO and textures if never created or a resize has occurred
- if ((m_multisampledFBO.isNull() || forceRecreate) && m_multisample) {
- qCDebug(Scene3D) << Q_FUNC_INFO << "Creating multisample framebuffer";
- m_multisampledFBO.reset(createMultisampledFramebufferObject(currentSize));
- if (m_multisampledFBO->format().samples() == 0 || !QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) {
- qCDebug(Scene3D) << Q_FUNC_INFO << "Failed to create multisample framebuffer";
- m_multisample = false;
- m_multisampledFBO.reset(Q_NULLPTR);
- }
- }
-
- if (m_finalFBO.isNull() || forceRecreate) {
- m_finalFBO.reset(createFramebufferObject(currentSize));
- m_texture.reset(window->createTextureFromId(m_finalFBO->texture(), m_finalFBO->size(), QQuickWindow::TextureHasAlphaChannel));
- m_node->setTexture(m_texture.data());
- }
-
- // Store the current size as a comparison
- // point for the next frame
- m_lastSize = currentSize;
- m_lastMultisample = m_multisample;
-
- //Only try to use MSAA when available
- if (m_multisample) {
- // Bind FBO
- m_multisampledFBO->bind();
-
- // Render Qt3D Scene
- m_renderAspect->renderSynchronous();
-
- // We may have called doneCurrent() so restore the context.
- if (saver.context()->surface() != saver.surface())
- saver.context()->makeCurrent(saver.surface());
-
- // Blit multisampled FBO with non multisampled FBO with texture attachment
- QOpenGLFramebufferObject::blitFramebuffer(m_finalFBO.data(), m_multisampledFBO.data());
-
- // Restore QtQuick FBO
- m_multisampledFBO->bindDefault();
- } else {
- // Bind FBO
- m_finalFBO->bind();
-
- // Render Qt3D Scene
- m_renderAspect->renderSynchronous();
-
- // We may have called doneCurrent() so restore the context.
- if (saver.context()->surface() != saver.surface())
- saver.context()->makeCurrent(saver.surface());
-
- // Restore QtQuick FBO
- m_finalFBO->bindDefault();
- }
-
- // Reset the state used by the Qt Quick scenegraph to avoid any
- // interference when rendering the rest of the UI.
- window->resetOpenGLState();
-
- // Mark material as dirty to request a new frame
- m_node->markDirty(QSGNode::DirtyMaterial);
-
- // Request next frame
- window->update();
-}
-
-inline static bool isPowerOfTwo(int x)
-{
- // Assumption: x >= 1
- return x == (x & -x);
-}
-
-void Scene3DSGMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
-{
- Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
- Scene3DSGMaterial *tx = static_cast<Scene3DSGMaterial *>(newEffect);
- Scene3DSGMaterial *oldTx = static_cast<Scene3DSGMaterial *>(oldEffect);
-
- QSGTexture *t = tx->texture();
-
- bool npotSupported = const_cast<QOpenGLContext *>(state.context())
- ->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat);
- if (!npotSupported) {
- QSize size = t->textureSize();
- const bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height());
- if (isNpot) {
- t->setHorizontalWrapMode(QSGTexture::ClampToEdge);
- t->setVerticalWrapMode(QSGTexture::ClampToEdge);
- }
- }
-
- if (oldTx == 0 || oldTx->texture()->textureId() != t->textureId())
- t->bind();
- else
- t->updateBindOptions();
-
- if (state.isMatrixDirty())
- program()->setUniformValue(m_matrixId, state.combinedMatrix());
-
- if (state.isOpacityDirty())
- program()->setUniformValue(m_opacityId, state.opacity());
-}
-
-void Scene3DCleaner::cleanup()
-{
- Q_ASSERT(m_renderer);
- delete m_renderer->m_aspectEngine; // also deletes m_renderer->m_renderAspect
- m_renderer->m_aspectEngine = Q_NULLPTR;
- m_renderer->m_renderAspect = Q_NULLPTR;
- m_renderer->deleteLater();
- deleteLater();
-}
-
} // namespace Qt3DRender
QT_END_NAMESPACE
-
-#include "scene3ditem.moc"
diff --git a/src/quick3d/imports/scene3d/scene3drenderer.cpp b/src/quick3d/imports/scene3d/scene3drenderer.cpp
new file mode 100644
index 000000000..6d69e72d6
--- /dev/null
+++ b/src/quick3d/imports/scene3d/scene3drenderer.cpp
@@ -0,0 +1,294 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 "scene3drenderer_p.h"
+#include "scene3dcleaner_p.h"
+#include "scene3ditem_p.h"
+#include "scene3dlogging_p.h"
+#include "scene3dsgnode_p.h"
+
+#include <Qt3DRender/qrenderaspect.h>
+#include <Qt3DCore/qaspectengine.h>
+
+#include <QtQuick/qquickwindow.h>
+
+#include <QtGui/qopenglcontext.h>
+#include <QtGui/qopenglframebufferobject.h>
+
+#include <QtCore/qthread.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class ContextSaver
+{
+public:
+ explicit ContextSaver(QOpenGLContext *context = QOpenGLContext::currentContext())
+ : m_context(context),
+ m_surface(context ? context->surface() : Q_NULLPTR)
+ {
+ }
+
+ ~ContextSaver()
+ {
+ if (m_context)
+ m_context->makeCurrent(m_surface);
+ }
+
+ QOpenGLContext *context() const { return m_context; }
+ QSurface *surface() const { return m_surface; }
+
+private:
+ QOpenGLContext * const m_context;
+ QSurface * const m_surface;
+};
+
+/*!
+ \class Qt3DCore::Scene3DRenderer
+ \internal
+
+ \brief The Qt3DCore::Scene3DRenderer class takes care of rendering a Qt3D scene
+ within a Framebuffer object to be used by the QtQuick 2 renderer.
+
+ The Qt3DCore::Scene3DRenderer class renders a Qt3D scene as provided by a Qt3DCore::Scene3DItem.
+ It owns the aspectEngine even though it doesn't instantiate it.
+
+ The shutdown procedure is a two steps process that goes as follow:
+
+ \li The window is closed
+
+ \li This triggers the windowsChanged signal which the Scene3DRenderer
+ uses to perform the necessary cleanups in the QSGRenderThread (destroys
+ DebugLogger ...) with the shutdown slot (queued connection).
+
+ \li The destroyed signal of the window is also connected to the
+ Scene3DRenderer. When triggered in the context of the main thread, the
+ cleanup slot is called.
+
+ There is an alternate shutdown procedure in case the QQuickItem is
+ destroyed with an active window which can happen in the case where the
+ Scene3D is used with a QtQuick Loader
+
+ In that case the shutdown procedure goes the same except that the destroyed
+ signal of the window is not called. Therefore the cleanup method is invoked
+ to properly destroy the aspect engine.
+ */
+Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *aspectEngine, QRenderAspect *renderAspect)
+ : QObject()
+ , m_item(item)
+ , m_aspectEngine(aspectEngine)
+ , m_renderAspect(renderAspect)
+ , m_multisampledFBO(Q_NULLPTR)
+ , m_finalFBO(Q_NULLPTR)
+ , m_texture(Q_NULLPTR)
+ , m_multisample(false) // this value is not used, will be synced from the Scene3DItem instead
+ , m_lastMultisample(false)
+{
+ Q_CHECK_PTR(m_item);
+ Q_CHECK_PTR(m_item->window());
+
+ QObject::connect(m_item->window(), &QQuickWindow::beforeRendering, this, &Scene3DRenderer::render, Qt::DirectConnection);
+ QObject::connect(m_item, &QQuickItem::windowChanged, this, &Scene3DRenderer::onWindowChangedQueued, Qt::QueuedConnection);
+
+ ContextSaver saver;
+
+ QVariantMap data;
+ data.insert(QStringLiteral("surface"), QVariant::fromValue(saver.surface()));
+ m_aspectEngine->setData(data);
+
+ m_renderAspect->renderInitialize(saver.context());
+ scheduleRootEntityChange();
+}
+
+Scene3DRenderer::~Scene3DRenderer()
+{
+ qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread();
+}
+
+QOpenGLFramebufferObject *Scene3DRenderer::createMultisampledFramebufferObject(const QSize &size)
+{
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ format.setSamples(4);
+ return new QOpenGLFramebufferObject(size, format);
+}
+
+QOpenGLFramebufferObject *Scene3DRenderer::createFramebufferObject(const QSize &size)
+{
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::Depth);
+ return new QOpenGLFramebufferObject(size, format);
+}
+
+void Scene3DRenderer::scheduleRootEntityChange()
+{
+ QMetaObject::invokeMethod(m_item, "applyRootEntityChange", Qt::QueuedConnection);
+}
+
+void Scene3DRenderer::setCleanerHelper(Scene3DCleaner *cleaner)
+{
+ m_cleaner = cleaner;
+ if (m_cleaner) {
+ // Window closed case
+ QObject::connect(m_item->window(), &QQuickWindow::destroyed, m_cleaner, &Scene3DCleaner::cleanup);
+ m_cleaner->setRenderer(this);
+ }
+}
+
+// Executed in the QtQuick render thread.
+void Scene3DRenderer::shutdown()
+{
+ qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread();
+
+ // Set to null so that subsequent calls to render
+ // would return early
+ m_item = Q_NULLPTR;
+
+ // Shutdown the Renderer Aspect while the OpenGL context
+ // is still valid
+ if (m_renderAspect)
+ m_renderAspect->renderShutdown();
+}
+
+// SGThread
+void Scene3DRenderer::onWindowChangedQueued(QQuickWindow *w)
+{
+ if (w == Q_NULLPTR) {
+ qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread();
+ shutdown();
+ // Will only trigger something with the Loader case
+ // The window closed cases is handled by the window's destroyed
+ // signal
+ QMetaObject::invokeMethod(m_cleaner, "cleanup");
+ }
+}
+
+void Scene3DRenderer::synchronize()
+{
+ m_multisample = m_item->multisample();
+}
+
+void Scene3DRenderer::setSGNode(Scene3DSGNode *node) Q_DECL_NOEXCEPT
+{
+ m_node = node;
+ if (!m_texture.isNull())
+ node->setTexture(m_texture.data());
+}
+
+void Scene3DRenderer::render()
+{
+ if (!m_item || !m_item->window())
+ return;
+
+ QQuickWindow *window = m_item->window();
+
+ if (m_aspectEngine->rootEntity() != m_item->entity())
+ scheduleRootEntityChange();
+
+ ContextSaver saver;
+
+ const QSize currentSize = m_item->boundingRect().size().toSize() * window->effectiveDevicePixelRatio();
+ const bool forceRecreate = currentSize != m_lastSize || m_multisample != m_lastMultisample;
+
+ // Rebuild FBO and textures if never created or a resize has occurred
+ if ((m_multisampledFBO.isNull() || forceRecreate) && m_multisample) {
+ qCDebug(Scene3D) << Q_FUNC_INFO << "Creating multisample framebuffer";
+ m_multisampledFBO.reset(createMultisampledFramebufferObject(currentSize));
+ if (m_multisampledFBO->format().samples() == 0 || !QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) {
+ qCDebug(Scene3D) << Q_FUNC_INFO << "Failed to create multisample framebuffer";
+ m_multisample = false;
+ m_multisampledFBO.reset(Q_NULLPTR);
+ }
+ }
+
+ if (m_finalFBO.isNull() || forceRecreate) {
+ m_finalFBO.reset(createFramebufferObject(currentSize));
+ m_texture.reset(window->createTextureFromId(m_finalFBO->texture(), m_finalFBO->size(), QQuickWindow::TextureHasAlphaChannel));
+ m_node->setTexture(m_texture.data());
+ }
+
+ // Store the current size as a comparison
+ // point for the next frame
+ m_lastSize = currentSize;
+ m_lastMultisample = m_multisample;
+
+ //Only try to use MSAA when available
+ if (m_multisample) {
+ // Bind FBO
+ m_multisampledFBO->bind();
+
+ // Render Qt3D Scene
+ m_renderAspect->renderSynchronous();
+
+ // We may have called doneCurrent() so restore the context.
+ if (saver.context()->surface() != saver.surface())
+ saver.context()->makeCurrent(saver.surface());
+
+ // Blit multisampled FBO with non multisampled FBO with texture attachment
+ QOpenGLFramebufferObject::blitFramebuffer(m_finalFBO.data(), m_multisampledFBO.data());
+
+ // Restore QtQuick FBO
+ m_multisampledFBO->bindDefault();
+ } else {
+ // Bind FBO
+ m_finalFBO->bind();
+
+ // Render Qt3D Scene
+ m_renderAspect->renderSynchronous();
+
+ // We may have called doneCurrent() so restore the context.
+ if (saver.context()->surface() != saver.surface())
+ saver.context()->makeCurrent(saver.surface());
+
+ // Restore QtQuick FBO
+ m_finalFBO->bindDefault();
+ }
+
+ // Reset the state used by the Qt Quick scenegraph to avoid any
+ // interference when rendering the rest of the UI.
+ window->resetOpenGLState();
+
+ // Mark material as dirty to request a new frame
+ m_node->markDirty(QSGNode::DirtyMaterial);
+
+ // Request next frame
+ window->update();
+}
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/imports/scene3d/scene3drenderer_p.h b/src/quick3d/imports/scene3d/scene3drenderer_p.h
new file mode 100644
index 000000000..ebed27e15
--- /dev/null
+++ b/src/quick3d/imports/scene3d/scene3drenderer_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** 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_SCENE3DRENDERER_P_H
+#define QT3DRENDER_SCENE3DRENDERER_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.
+//
+
+#include <QObject>
+
+#include <QtCore/qsize.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickWindow;
+class QSGTexture;
+class QOpenGLFramebufferObject;
+
+namespace Qt3DCore {
+class QAspectEngine;
+}
+
+namespace Qt3DRender {
+
+class QRenderAspect;
+class Scene3DCleaner;
+class Scene3DItem;
+class Scene3DSGNode;
+
+class Scene3DRenderer : public QObject
+{
+ Q_OBJECT
+public:
+ Scene3DRenderer(Scene3DItem *item,
+ Qt3DCore::QAspectEngine *aspectEngine,
+ QRenderAspect *renderAspect);
+ ~Scene3DRenderer();
+
+ QOpenGLFramebufferObject *createMultisampledFramebufferObject(const QSize &size);
+ QOpenGLFramebufferObject *createFramebufferObject(const QSize &size);
+ void scheduleRootEntityChange();
+ void setSGNode(Scene3DSGNode *node) Q_DECL_NOEXCEPT;
+ void setCleanerHelper(Scene3DCleaner *cleaner);
+ void synchronize();
+
+public Q_SLOTS:
+ void render();
+ void shutdown();
+ void onWindowChangedQueued(QQuickWindow *w);
+
+private:
+ Scene3DItem *m_item; // Will be released by the QQuickWindow/QML Engine
+ Qt3DCore::QAspectEngine *m_aspectEngine; // Will be released by the Scene3DRendererCleaner
+ QRenderAspect *m_renderAspect; // Will be released by the aspectEngine
+ QScopedPointer<QOpenGLFramebufferObject> m_multisampledFBO;
+ QScopedPointer<QOpenGLFramebufferObject> m_finalFBO;
+ QScopedPointer<QSGTexture> m_texture;
+ Scene3DSGNode *m_node; // Will be released by the QtQuick SceneGraph
+ Scene3DCleaner *m_cleaner;
+ QSize m_lastSize;
+ bool m_multisample;
+ bool m_lastMultisample;
+
+ friend class Scene3DCleaner;
+};
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_SCENE3DRENDERER_P_H
diff --git a/src/quick3d/imports/scene3d/scene3dsgmaterial.cpp b/src/quick3d/imports/scene3d/scene3dsgmaterial.cpp
new file mode 100644
index 000000000..f3724295f
--- /dev/null
+++ b/src/quick3d/imports/scene3d/scene3dsgmaterial.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 "scene3dsgmaterial_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+/*!
+ \class Qt3DCore::Scene3DSGMaterial
+ \internal
+ \inherit QSGMaterial
+
+ \brief The Qt3DRender::Scene3DSGMaterial class is a custom QSGMaterial subclass used to
+ render a Qt3DRender::Scene3DSGNode
+
+ The Qt3DRender::Scene3DSGMaterial class renders a texture using premultiplied
+ alpha unlike the QSGSimpleTextureMaterial.
+
+ This is needed to properly integrate alpha blending from a Qt3D scene
+ within a QtQuick 2 scene.
+ */
+Scene3DSGMaterial::Scene3DSGMaterial()
+ : QSGMaterial()
+ , m_texture(Q_NULLPTR)
+{
+}
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/imports/scene3d/scene3dsgmaterial_p.h b/src/quick3d/imports/scene3d/scene3dsgmaterial_p.h
new file mode 100644
index 000000000..2a968337d
--- /dev/null
+++ b/src/quick3d/imports/scene3d/scene3dsgmaterial_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 SCENE3DSGMATERIAL_H
+#define SCENE3DSGMATERIAL_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.
+//
+
+#include <QtQuick/QSGMaterial>
+#include "scene3dsgmaterialshader_p.h"
+
+#include <QtQuick/qsgtexture.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class Scene3DSGMaterial : public QSGMaterial
+{
+public:
+ Scene3DSGMaterial();
+
+ void setTexture(QSGTexture *texture) Q_DECL_NOEXCEPT
+ {
+ m_texture = texture;
+ setFlag(Blending, m_texture ? m_texture->hasAlphaChannel() : false);
+ }
+
+ QSGTexture *texture() const Q_DECL_NOEXCEPT { return m_texture; }
+ QSGMaterialType *type() const Q_DECL_FINAL { return &Scene3DSGMaterialShader::type; }
+ QSGMaterialShader *createShader() const Q_DECL_FINAL { return new Scene3DSGMaterialShader(); }
+
+private:
+ QSGTexture *m_texture;
+};
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // SCENE3DSGMATERIAL_H
diff --git a/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp b/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp
new file mode 100644
index 000000000..db8f80dee
--- /dev/null
+++ b/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 "scene3dsgmaterialshader_p.h"
+#include "scene3dsgmaterial_p.h"
+
+#include <QtGui/qopenglcontext.h>
+#include <QtGui/qopenglfunctions.h>
+#include <QtGui/qsurfaceformat.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+
+inline bool isPowerOfTwo(int x)
+{
+ // Assumption: x >= 1
+ return x == (x & -x);
+}
+
+}
+
+namespace Qt3DRender {
+
+/*!
+ \class Qt3DCore::SCene3DMaterialShader
+ \internal
+
+ \brief The Qt3DRender::Scene3DSGMaterialShader class is a custom
+ QSGMaterialShader subclass instantiated by a Qt3DRender::Scene3DSGMateria1
+
+ The Qt3DRender::Scene3DSGMaterialShader provides a shader that renders a texture
+ using premultiplied alpha.
+ */
+
+QSGMaterialType Scene3DSGMaterialShader::type;
+
+const char * const *Scene3DSGMaterialShader::attributeNames() const
+{
+ static char const *const attr[] = { "qt_VertexPosition", "qt_VertexTexCoord", 0 };
+ return attr;
+}
+
+const char *Scene3DSGMaterialShader::vertexShader() const
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (ctx->format().version() >= qMakePair(3, 2) && ctx->format().profile() == QSurfaceFormat::CoreProfile) {
+ return ""
+ "#version 150 core \n"
+ "uniform mat4 qt_Matrix; \n"
+ "in vec4 qt_VertexPosition; \n"
+ "in vec2 qt_VertexTexCoord; \n"
+ "out vec2 qt_TexCoord; \n"
+ "void main() { \n"
+ " qt_TexCoord = qt_VertexTexCoord; \n"
+ " gl_Position = qt_Matrix * qt_VertexPosition; \n"
+ "}";
+ } else {
+ return ""
+ "uniform highp mat4 qt_Matrix; \n"
+ "attribute highp vec4 qt_VertexPosition; \n"
+ "attribute highp vec2 qt_VertexTexCoord; \n"
+ "varying highp vec2 qt_TexCoord; \n"
+ "void main() { \n"
+ " qt_TexCoord = qt_VertexTexCoord; \n"
+ " gl_Position = qt_Matrix * qt_VertexPosition; \n"
+ "}";
+ }
+}
+
+const char *Scene3DSGMaterialShader::fragmentShader() const
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (ctx->format().version() >= qMakePair(3, 2) && ctx->format().profile() == QSurfaceFormat::CoreProfile) {
+ return ""
+ "#version 150 core \n"
+ "uniform sampler2D source; \n"
+ "uniform float qt_Opacity; \n"
+ "in vec2 qt_TexCoord; \n"
+ "out vec4 fragColor; \n"
+ "void main() { \n"
+ " vec4 p = texture(source, qt_TexCoord); \n"
+ " fragColor = vec4(p.rgb * p.a, qt_Opacity * p.a); \n"
+ "}";
+ } else {
+ return ""
+ "uniform highp sampler2D source; \n"
+ "uniform highp float qt_Opacity; \n"
+ "varying highp vec2 qt_TexCoord; \n"
+ "void main() { \n"
+ " highp vec4 p = texture2D(source, qt_TexCoord); \n"
+ " gl_FragColor = vec4(p.rgb * p.a, qt_Opacity * p.a); \n"
+ "}";
+ }
+}
+
+void Scene3DSGMaterialShader::initialize()
+{
+ m_matrixId = program()->uniformLocation("qt_Matrix");
+ m_opacityId = program()->uniformLocation("qt_Opacity");
+}
+
+void Scene3DSGMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
+{
+ Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
+ Scene3DSGMaterial *tx = static_cast<Scene3DSGMaterial *>(newEffect);
+ Scene3DSGMaterial *oldTx = static_cast<Scene3DSGMaterial *>(oldEffect);
+
+ QSGTexture *t = tx->texture();
+
+ bool npotSupported = const_cast<QOpenGLContext *>(state.context())
+ ->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat);
+ if (!npotSupported) {
+ QSize size = t->textureSize();
+ const bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height());
+ if (isNpot) {
+ t->setHorizontalWrapMode(QSGTexture::ClampToEdge);
+ t->setVerticalWrapMode(QSGTexture::ClampToEdge);
+ }
+ }
+
+ if (oldTx == 0 || oldTx->texture()->textureId() != t->textureId())
+ t->bind();
+ else
+ t->updateBindOptions();
+
+ if (state.isMatrixDirty())
+ program()->setUniformValue(m_matrixId, state.combinedMatrix());
+
+ if (state.isOpacityDirty())
+ program()->setUniformValue(m_opacityId, state.opacity());
+}
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/imports/scene3d/scene3dsgmaterialshader_p.h b/src/quick3d/imports/scene3d/scene3dsgmaterialshader_p.h
new file mode 100644
index 000000000..24b6e202e
--- /dev/null
+++ b/src/quick3d/imports/scene3d/scene3dsgmaterialshader_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** 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_SCENE3DSGMATERIALSHADER_P_H
+#define QT3DRENDER_SCENE3DSGMATERIALSHADER_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.
+//
+
+#include <QtQuick/QSGMaterialShader>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class Scene3DSGMaterialShader : public QSGMaterialShader
+{
+public:
+ void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) Q_DECL_FINAL;
+ const char * const *attributeNames() const Q_DECL_FINAL;
+
+ static QSGMaterialType type;
+
+protected:
+ const char *vertexShader() const Q_DECL_FINAL;
+ const char *fragmentShader() const Q_DECL_FINAL;
+ void initialize() Q_DECL_FINAL;
+
+private:
+ int m_matrixId;
+ int m_opacityId;
+};
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_SCENE3DSGMATERIALSHADER_P_H
diff --git a/src/quick3d/imports/scene3d/scene3dsgnode.cpp b/src/quick3d/imports/scene3d/scene3dsgnode.cpp
new file mode 100644
index 000000000..66d42de7c
--- /dev/null
+++ b/src/quick3d/imports/scene3d/scene3dsgnode.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 "scene3dsgnode_p.h"
+#include "scene3dlogging_p.h"
+
+#include <QtCore/qthread.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+/*!
+ \class Qt3DCore::Scene3DSGNode
+ \internal
+
+ \brief The Qt3DCore::Scene3DSGNode class is a simple QSGeometryNode subclass that
+ uses a Qt3DCore::Scene3DMaterial
+
+ The Qt3DCore::Scene3DSGNode allows to render a simple rectangle textured with a
+ texture using premultiplied alpha.
+ */
+Scene3DSGNode::Scene3DSGNode()
+ : QSGGeometryNode()
+ , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
+{
+ setMaterial(&m_material);
+ setOpaqueMaterial(&m_opaqueMaterial);
+ setGeometry(&m_geometry);
+ qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread();
+}
+
+Scene3DSGNode::~Scene3DSGNode()
+{
+ qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread();
+ // The Scene3DSGNode is deleted by the QSGRenderThread when the SceneGraph
+ // is terminated.
+}
+
+void Scene3DSGNode::setRect(const QRectF &rect)
+{
+ if (rect != m_rect) {
+ m_rect = rect;
+ // Map the item's bounding rect to normalized texture coordinates
+ const QRectF sourceRect(0.0f, 1.0f, 1.0f, -1.0f);
+ QSGGeometry::updateTexturedRectGeometry(&m_geometry, m_rect, sourceRect);
+ markDirty(DirtyGeometry);
+ }
+}
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/imports/scene3d/scene3dsgnode_p.h b/src/quick3d/imports/scene3d/scene3dsgnode_p.h
new file mode 100644
index 000000000..011beed6b
--- /dev/null
+++ b/src/quick3d/imports/scene3d/scene3dsgnode_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** 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_SCENE3DSGNODE_P_H
+#define QT3DRENDER_SCENE3DSGNODE_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.
+//
+
+#include <QtQuick/QSGGeometryNode>
+
+#include "scene3dsgmaterial_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QSGTexture;
+
+namespace Qt3DRender {
+
+class Scene3DSGNode : public QSGGeometryNode
+{
+public:
+ Scene3DSGNode();
+ ~Scene3DSGNode();
+
+ void setTexture(QSGTexture *texture) Q_DECL_NOEXCEPT
+ {
+ m_material.setTexture(texture);
+ m_opaqueMaterial.setTexture(texture);
+ markDirty(DirtyMaterial);
+ }
+ QSGTexture *texture() const Q_DECL_NOEXCEPT { return m_material.texture(); }
+
+ void setRect(const QRectF &rect);
+ QRectF rect() const Q_DECL_NOEXCEPT { return m_rect; }
+
+private:
+ Scene3DSGMaterial m_material;
+ Scene3DSGMaterial m_opaqueMaterial;
+ QSGGeometry m_geometry;
+ QRectF m_rect;
+};
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_SCENE3DSGNODE_P_H