summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntti Määttä <antti.maatta@qt.io>2016-11-02 15:57:43 +0200
committerAntti Määttä <antti.maatta@qt.io>2017-01-26 09:19:08 +0000
commitdcd5756f3870d9aed7f73c338cc8715d5fe35297 (patch)
treeae65407ca753fd41e8b50dcbee7a2d0fb2a69f98
parent6a7e0e2822875e8e532e3cd58f2263d5b3c12da4 (diff)
Update scene2d implementation
Add inline qml support with QQuickItem as default property. Change output to QRenderTargetOutput. Change backend node to use resource accessor and implement own fbo creation. Add event support. Change-Id: Ieb82b986696b00ba026ac9ab08c8dcbe87e84b1c Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io> Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
-rw-r--r--src/quick3d/quick3drender/scene2d/qscene2d.cpp178
-rw-r--r--src/quick3d/quick3drender/scene2d/qscene2d.h28
-rw-r--r--src/quick3d/quick3drender/scene2d/qscene2d_p.h31
-rw-r--r--src/quick3d/quick3drender/scene2d/scene2d.cpp213
-rw-r--r--src/quick3d/quick3drender/scene2d/scene2d.pri5
-rw-r--r--src/quick3d/quick3drender/scene2d/scene2d_p.h33
6 files changed, 280 insertions, 208 deletions
diff --git a/src/quick3d/quick3drender/scene2d/qscene2d.cpp b/src/quick3d/quick3drender/scene2d/qscene2d.cpp
index 5c20db184..2f4c12367 100644
--- a/src/quick3d/quick3drender/scene2d/qscene2d.cpp
+++ b/src/quick3d/quick3drender/scene2d/qscene2d.cpp
@@ -36,6 +36,7 @@
#include "qscene2d.h"
#include "qscene2d_p.h"
+#include "scene2d_p.h"
#include <Qt3DCore/QPropertyUpdatedChange>
@@ -75,8 +76,8 @@ namespace Quick {
*/
/*!
- \qmlproperty Qt3DRender::QAbstractTexture Qt3D.Render::Scene2D::texture
- Holds the texture being rendered to.
+ \qmlproperty RenderTargetOutput Qt3D.Render::Scene2D::output
+ Holds the RenderTargetOutput, which specifies where the Scene2D is rendering to.
*/
/*!
@@ -227,32 +228,25 @@ Scene2DManager::Scene2DManager(QScene2DPrivate *priv)
, m_qmlComponent(nullptr)
, m_rootItem(nullptr)
, m_source(nullptr)
- , m_texture(nullptr)
, m_requested(false)
, m_initialized(false)
, m_renderSyncRequested(false)
, m_sharedObject(new Scene2DSharedObject(this))
, m_renderOnce(false)
, m_backendInitialized(false)
+ , m_noSourceMode(false)
+ , m_item(nullptr)
{
- setFormat(QSurfaceFormat::defaultFormat());
-
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(this);
+ 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(true);
- m_sharedObject->m_quickWindow->setDefaultAlphaBuffer(true);
-
- // Create a QML engine.
- m_qmlEngine = new QQmlEngine;
- if (!m_qmlEngine->incubationController())
- m_qmlEngine->setIncubationController(m_sharedObject->m_quickWindow->incubationController());
+ m_sharedObject->m_quickWindow->setClearBeforeRendering(false);
connect(m_sharedObject->m_renderControl, &QQuickRenderControl::renderRequested,
this, &Scene2DManager::requestRender);
@@ -291,8 +285,14 @@ void Scene2DManager::requestRenderSync()
void Scene2DManager::startIfInitialized()
{
- if (!m_initialized) {
- if (m_backendInitialized && m_source.isValid()) {
+ if (!m_initialized && m_backendInitialized) {
+ if (m_source.isValid() && !m_noSourceMode) {
+ // Create a QML engine.
+ m_qmlEngine = new QQmlEngine;
+ if (!m_qmlEngine->incubationController())
+ m_qmlEngine->setIncubationController(m_sharedObject->m_quickWindow->incubationController());
+
+ // create component
m_qmlComponent = new QQmlComponent(m_qmlEngine, m_source);
if (m_qmlComponent->isLoading()) {
connect(m_qmlComponent, &QQmlComponent::statusChanged,
@@ -300,6 +300,17 @@ void Scene2DManager::startIfInitialized()
} else {
run();
}
+ } else if (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();
}
}
}
@@ -364,19 +375,19 @@ void Scene2DManager::updateSizes()
qWarning() << "QScene2D: Root item size not set.";
return;
}
- resize(width, height);
m_sharedObject->m_quickWindow->setGeometry(0, 0, width, height);
}
-void Scene2DManager::setTexture(QAbstractTexture *texture)
+void Scene2DManager::setSource(const QUrl &url)
{
- m_texture = texture;
+ m_source = url;
startIfInitialized();
}
-void Scene2DManager::setSource(const QUrl &url)
+void Scene2DManager::setItem(QQuickItem *item)
{
- m_source = url;
+ m_noSourceMode = true;
+ m_item = item;
startIfInitialized();
}
@@ -388,12 +399,6 @@ bool Scene2DManager::event(QEvent *e)
// just render request, don't need to call sync in render thread
QMutexLocker lock(&m_sharedObject->m_mutex);
m_sharedObject->requestRender(false);
-
- Qt3DCore::QPropertyUpdatedChangePtr change(new Qt3DCore::QPropertyUpdatedChange(m_priv->m_id));
- change->setPropertyName("dirty");
- change->setValue(QVariant::fromValue(true));
- m_priv->notifyObservers(change);
-
m_requested = false;
return true;
}
@@ -436,7 +441,34 @@ bool Scene2DManager::event(QEvent *e)
default:
break;
}
- return QWindow::event(e);
+ return QObject::event(e);
+}
+
+bool Scene2DManager::forwardEvent(QEvent *event)
+{
+ switch (event->type()) {
+
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease: {
+ QMouseEvent* me = static_cast<QMouseEvent *>(event);
+ QPointF pos = me->localPos();
+ pos = QPointF(pos.x() * m_rootItem->width(), pos.y() * m_rootItem->height());
+ QMouseEvent nme = QMouseEvent(me->type(), pos, pos, pos, me->button(), me->buttons(),
+ me->modifiers(), Qt::MouseEventSynthesizedByApplication);
+ QCoreApplication::sendEvent(m_sharedObject->m_quickWindow, &nme);
+ } break;
+
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease: {
+ QCoreApplication::sendEvent(m_sharedObject->m_quickWindow, event);
+ } break;
+
+ default:
+ break;
+ }
+ return false;
}
void Scene2DManager::doRenderSync()
@@ -446,12 +478,6 @@ void Scene2DManager::doRenderSync()
m_sharedObject->requestRender(true);
m_sharedObject->m_renderControl->polishItems();
- Qt3DCore::QPropertyUpdatedChangePtr change(new Qt3DCore::QPropertyUpdatedChange(m_priv->m_id));
-
- change->setPropertyName("dirty");
- change->setValue(QVariant::fromValue(true));
- m_priv->notifyObservers(change);
-
// begin waiting render thread
m_sharedObject->waitRender();
m_requested = false;
@@ -464,7 +490,7 @@ void Scene2DManager::cleanup()
QScene2DPrivate::QScene2DPrivate()
- : QFrameGraphNodePrivate()
+ : Qt3DCore::QNodePrivate()
, m_renderManager(new Scene2DManager(this))
{
}
@@ -476,26 +502,17 @@ QScene2DPrivate::~QScene2DPrivate()
}
-Scene2DSharedObject *QScene2DPrivate::getSharedObject(QScene2D *rqtt)
-{
- return rqtt->d_func()->m_renderManager->m_sharedObject.data();
-}
-
-
/*!
- The constructor creates an instance with the specified \a parent.
+ The constructor creates a new QScene2D instance with the specified \a parent.
*/
QScene2D::QScene2D(Qt3DCore::QNode *parent)
- : QFrameGraphNode(*new QScene2DPrivate, parent)
+ : Qt3DCore::QNode(*new QScene2DPrivate, parent)
{
Q_D(QScene2D);
connect(d->m_renderManager, &Scene2DManager::onLoadedChanged,
this, &QScene2D::sourceLoaded);
}
-/*!
- Destructor.
- */
QScene2D::~QScene2D()
{
}
@@ -532,6 +549,23 @@ void QScene2D::setSource(const QUrl &url)
emit sourceChanged(url);
}
+QQuickItem* QScene2D::item() const
+{
+ Q_D(const QScene2D);
+ return d->m_renderManager->m_rootItem;
+}
+
+void QScene2D::setItem(QQuickItem *item)
+{
+ Q_D(QScene2D);
+ if (d->m_renderManager->m_initialized) {
+ qWarning() << "Unable to set item after initialization.";
+ return;
+ }
+ d->m_renderManager->setItem(item);
+ emit itemChanged(item);
+}
+
/*!
\property QScene2D::renderOnce
\brief Property to specify if the texture will be rendered only once.
@@ -557,58 +591,47 @@ void QScene2D::setRenderOnce(bool once)
}
/*!
- \property QScene2D::texture
- \brief The texture being rendered to.
-
- This property specifies the texture being rendered to. Once the texture has been
- set and the rendering begins, the texture can not be changed anymore.
+ \property QScene2D::output
+ Holds the QRenderTargetOutput, which specifies where the QScene2D is
+ rendering to.
*/
-QAbstractTexture *QScene2D::texture() const
+Qt3DRender::QRenderTargetOutput *QScene2D::output() const
{
Q_D(const QScene2D);
- return d->m_renderManager->m_texture;
+ return d->m_output;
}
-void QScene2D::setTexture(QAbstractTexture *texture)
+void QScene2D::setOutput(Qt3DRender::QRenderTargetOutput *output)
{
Q_D(QScene2D);
- if (d->m_renderManager->m_initialized) {
- qWarning() << "Unable to set texture after initialization.";
- return;
- }
- if (d->m_renderManager->m_texture != texture) {
- if (d->m_renderManager->m_texture)
- QObject::disconnect(d->m_textureDestroyedConnection);
- if (texture && !texture->parent())
- texture->setParent(this);
- d->m_renderManager->setTexture(texture);
- if (texture)
- d->m_textureDestroyedConnection
- = QObject::connect(texture, &QAbstractTexture::destroyed,
- this, &QScene2D::textureDestroyed);
- emit textureChanged(texture);
+ 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);
}
}
-void QScene2D::textureDestroyed(QObject *object)
-{
- Q_D(QScene2D);
- Q_UNUSED(object);
- d->m_renderManager->setTexture(nullptr);
-}
-
Qt3DCore::QNodeCreatedChangeBasePtr QScene2D::createNodeCreationChange() const
{
auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QScene2DData>::create(this);
auto &data = creationChange->data;
Q_D(const QScene2D);
data.renderOnce = d->m_renderManager->m_renderOnce;
- data.textureId = d->m_renderManager->m_texture
- ? d->m_renderManager->m_texture->id() : Qt3DCore::QNodeId();
data.sharedObject = d->m_renderManager->m_sharedObject;
+ data.output = d->m_output ? d->m_output->id() : Qt3DCore::QNodeId();
return creationChange;
}
+bool QScene2D::event(QEvent *event)
+{
+ Q_D(QScene2D);
+ d->m_renderManager->forwardEvent(event);
+ return true;
+}
+
/*!
\internal
*/
@@ -618,7 +641,6 @@ void QScene2D::sourceLoaded()
}
} // namespace Quick
-
} // namespace Qt3DRender
QT_END_NAMESPACE
diff --git a/src/quick3d/quick3drender/scene2d/qscene2d.h b/src/quick3d/quick3drender/scene2d/qscene2d.h
index a00e7b06b..67871f161 100644
--- a/src/quick3d/quick3drender/scene2d/qscene2d.h
+++ b/src/quick3d/quick3drender/scene2d/qscene2d.h
@@ -37,12 +37,15 @@
#ifndef QT3DRENDER_QUICK3DRENDER_QSCENE2D_H
#define QT3DRENDER_QUICK3DRENDER_QSCENE2D_H
+#include <Qt3DQuickRender/qt3dquickrender_global.h>
+#include <Qt3DRender/qrendertargetoutput.h>
+
#include <QtCore/QUrl>
#include <QtCore/QEvent>
-#include <Qt3DRender/qframegraphnode.h>
-#include <Qt3DRender/qabstracttexture.h>
-#include <Qt3DQuickRender/qt3dquickrender_global.h>
+#include <Qt3DCore/qnode.h>
+
+#include <QtQuick/qquickitem.h>
QT_BEGIN_NAMESPACE
@@ -52,41 +55,46 @@ namespace Quick {
class QScene2DPrivate;
-class QT3DQUICKRENDERSHARED_EXPORT QScene2D : public Qt3DRender::QFrameGraphNode
+class QT3DQUICKRENDERSHARED_EXPORT QScene2D : public Qt3DCore::QNode
{
Q_OBJECT
- Q_PROPERTY(Qt3DRender::QAbstractTexture *texture READ texture WRITE setTexture NOTIFY textureChanged)
+ Q_PROPERTY(Qt3DRender::QRenderTargetOutput *output READ output WRITE setOutput NOTIFY outputChanged)
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(bool renderOnce READ renderOnce WRITE setRenderOnce NOTIFY renderOnceChanged)
Q_PROPERTY(bool loaded READ loaded NOTIFY loadedChanged)
+ Q_PROPERTY(QQuickItem *item READ item WRITE setItem NOTIFY itemChanged)
+
+ Q_CLASSINFO("DefaultProperty", "item")
public:
explicit QScene2D(Qt3DCore::QNode *parent = nullptr);
~QScene2D();
+ Qt3DRender::QRenderTargetOutput *output() const;
QUrl source() const;
- QAbstractTexture *texture() const;
bool loaded() const;
bool renderOnce() const;
-
+ QQuickItem *item() const;
+ bool event(QEvent *event) Q_DECL_OVERRIDE;
public Q_SLOTS:
+ void setOutput(Qt3DRender::QRenderTargetOutput *output);
void setSource(const QUrl &url);
- void setTexture(QAbstractTexture *texture);
void setRenderOnce(bool once);
+ void setItem(QQuickItem *item);
Q_SIGNALS:
+ void outputChanged(Qt3DRender::QRenderTargetOutput *output);
void sourceChanged(const QUrl &url);
- void textureChanged(QAbstractTexture *texture);
void loadedChanged(bool loaded);
void renderOnceChanged(bool once);
+ void itemChanged(QQuickItem *item);
protected:
Q_DECLARE_PRIVATE(QScene2D)
private:
Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE;
- void textureDestroyed(QObject *object);
void sourceLoaded();
};
diff --git a/src/quick3d/quick3drender/scene2d/qscene2d_p.h b/src/quick3d/quick3drender/scene2d/qscene2d_p.h
index 165a54b72..4fa65fb1b 100644
--- a/src/quick3d/quick3drender/scene2d/qscene2d_p.h
+++ b/src/quick3d/quick3drender/scene2d/qscene2d_p.h
@@ -48,12 +48,6 @@
// We mean it.
//
-#include <private/qobject_p.h>
-#include <private/qframegraphnode_p.h>
-
-#include <Qt3DQuickRender/qscene2d.h>
-#include <Qt3DRender/QAbstractTexture>
-
#include <QtQml/QQmlEngine>
#include <QtQml/QQmlComponent>
#include <QtQuick/QQuickItem>
@@ -64,6 +58,12 @@
#include <QtCore/QWaitCondition>
#include <QtCore/QThread>
+#include <Qt3DQuickRender/qscene2d.h>
+#include <Qt3DRender/qabstracttexture.h>
+
+#include <private/qobject_p.h>
+#include <private/qnode_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
@@ -141,7 +141,7 @@ private:
typedef QSharedPointer<Scene2DSharedObject> Scene2DSharedObjectPtr;
-class Q_AUTOTEST_EXPORT QScene2DPrivate : public QFrameGraphNodePrivate
+class Q_AUTOTEST_EXPORT QScene2DPrivate : public Qt3DCore::QNodePrivate
{
public:
Q_DECLARE_PUBLIC(QScene2D)
@@ -149,21 +149,19 @@ public:
QScene2DPrivate();
~QScene2DPrivate();
- static Scene2DSharedObject *getSharedObject(QScene2D *rqtt);
-
Scene2DManager *m_renderManager;
QMetaObject::Connection m_textureDestroyedConnection;
+ Qt3DRender::QRenderTargetOutput *m_output;
};
struct QScene2DData
{
bool renderOnce;
- Qt3DCore::QNodeId textureId;
Scene2DSharedObjectPtr sharedObject;
+ Qt3DCore::QNodeId output;
};
-
-class Scene2DManager : public QWindow
+class Scene2DManager : public QObject
{
Q_OBJECT
public:
@@ -173,11 +171,11 @@ public:
QQmlEngine *m_qmlEngine;
QQmlComponent *m_qmlComponent;
QQuickItem *m_rootItem;
+ QQuickItem *m_item;
QScene2DPrivate *m_priv;
QSharedPointer<Scene2DSharedObject> m_sharedObject;
- QAbstractTexture *m_texture;
QUrl m_source;
Qt3DCore::QNodeId m_id;
@@ -186,6 +184,7 @@ public:
bool m_renderSyncRequested;
bool m_renderOnce;
bool m_backendInitialized;
+ bool m_noSourceMode;
void requestRender();
void requestRenderSync();
@@ -195,10 +194,11 @@ public:
void run();
void updateSizes();
- void setTexture(QAbstractTexture *texture);
void setSource(const QUrl &url);
+ void setItem(QQuickItem *item);
bool event(QEvent *e) Q_DECL_OVERRIDE;
+ bool forwardEvent(QEvent *event);
Q_SIGNAL void onLoadedChanged();
@@ -206,9 +206,10 @@ public:
};
} // namespace Quick
-
} // namespace Qt3DRender
QT_END_NAMESPACE
+Q_DECLARE_METATYPE(Qt3DRender::Quick::Scene2DSharedObjectPtr)
+
#endif // QT3DRENDER_QUICK3DRENDER_QSCENE2D_P_H
diff --git a/src/quick3d/quick3drender/scene2d/scene2d.cpp b/src/quick3d/quick3drender/scene2d/scene2d.cpp
index 210cc5f0f..0ccf38fc7 100644
--- a/src/quick3d/quick3drender/scene2d/scene2d.cpp
+++ b/src/quick3d/quick3drender/scene2d/scene2d.cpp
@@ -42,10 +42,15 @@
#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>
QT_BEGIN_NAMESPACE
+#ifndef GL_DEPTH24_STENCIL8
+#define GL_DEPTH24_STENCIL8 0x88F0
+#endif
+
using namespace Qt3DRender::Quick;
namespace Qt3DRender {
@@ -87,15 +92,15 @@ bool RenderQmlEventHandler::event(QEvent *e)
}
Scene2D::Scene2D()
- : FrameGraphNode(FrameGraphNode::InvalidNodeType)
- , m_context(nullptr)
+ : m_context(nullptr)
+ , m_shareContext(nullptr)
, m_sharedObject(nullptr)
, m_renderThread(nullptr)
- , m_graphicsContext(nullptr)
- , m_texture(nullptr)
, m_initialized(false)
, m_renderInitialized(false)
, m_renderOnce(false)
+ , m_fbo(0)
+ , m_rbo(0)
{
}
@@ -109,16 +114,14 @@ Scene2D::~Scene2D()
}
}
-void Scene2D::setTexture(Qt3DCore::QNodeId textureId)
+void Scene2D::setOutput(Qt3DCore::QNodeId outputId)
{
- m_textureId = textureId;
- attach();
- checkInitialized();
+ m_outputId = outputId;
}
-void Scene2D::checkInitialized()
+void Scene2D::initializeSharedObject()
{
- if (!m_initialized && m_textureId != Qt3DCore::QNodeId()) {
+ if (!m_initialized) {
// Create render thread
m_renderThread = new QThread();
@@ -144,9 +147,11 @@ void Scene2D::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &chan
{
const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QScene2DData>>(change);
const auto &data = typedChange->data;
- m_renderOnce = m_renderOnce;
+ m_renderOnce = data.renderOnce;
setSharedObject(data.sharedObject);
- setTexture(data.textureId);
+ setOutput(data.output);
+ m_shareContext = renderer()->shareContext();
+ m_accessor = resourceAccessor();
}
void Scene2D::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
@@ -154,35 +159,31 @@ void Scene2D::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
if (e->type() == Qt3DCore::PropertyUpdated) {
Qt3DCore::QPropertyUpdatedChangePtr propertyChange
= qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("enabled"))
- setEnabled(propertyChange->value().toBool());
- else if (propertyChange->propertyName() == QByteArrayLiteral("dirty")) {
- // sent to trigger backend update when the texture gets rendered
- // so do nothing here
- }
- else if (propertyChange->propertyName() == QByteArrayLiteral("renderOnce"))
+ if (propertyChange->propertyName() == QByteArrayLiteral("renderOnce"))
m_renderOnce = propertyChange->value().toBool();
- else if (propertyChange->propertyName() == QByteArrayLiteral("texture")) {
- Qt3DCore::QNodeId textureId = propertyChange->value().value<Qt3DCore::QNodeId>();
- setTexture(textureId);
+ else if (propertyChange->propertyName() == QByteArrayLiteral("output")) {
+ Qt3DCore::QNodeId outputId = propertyChange->value().value<Qt3DCore::QNodeId>();
+ setOutput(outputId);
+ } else if (propertyChange->propertyName() == QByteArrayLiteral("sharedObject")) {
+ const Scene2DSharedObjectPtr sharedObject
+ = propertyChange->value().value<Scene2DSharedObjectPtr>();
+ setSharedObject(sharedObject);
}
- markDirty(AbstractRenderer::AllDirty);
}
- FrameGraphNode::sceneChangeEvent(e);
}
void Scene2D::setSharedObject(Qt3DRender::Quick::Scene2DSharedObjectPtr sharedObject)
{
m_sharedObject = sharedObject;
+ if (!m_initialized)
+ initializeSharedObject();
}
void Scene2D::initializeRender()
{
if (!m_renderInitialized) {
- Qt3DRender::Render::Renderer *renderer
- = static_cast<Qt3DRender::Render::Renderer *>(this->renderer());
- if (!renderer)
- return;
+
+ Q_ASSERT(m_shareContext);
QSurfaceFormat format;
format.setDepthBufferSize(24);
@@ -190,96 +191,124 @@ void Scene2D::initializeRender()
m_context = new QOpenGLContext();
m_context->setFormat(format);
-
- m_context->setShareContext(renderer->shareContext());
+ m_context->setShareContext(m_shareContext);
m_context->create();
- m_graphicsContext = new GraphicsContext();
- m_graphicsContext->setOpenGLContext(m_context);
- m_graphicsContext->setRenderer(renderer);
-
- m_graphicsContext->makeCurrent(m_sharedObject->m_surface);
+ m_context->makeCurrent(m_sharedObject->m_surface);
m_sharedObject->m_renderControl->initialize(m_context);
- m_graphicsContext->doneCurrent();
+ m_context->doneCurrent();
QCoreApplication::postEvent(m_sharedObject->m_renderManager, new QEvent(PREPARE));
m_renderInitialized = true;
}
}
-void Scene2D::attach()
+bool Scene2D::updateFbo(QOpenGLTexture *texture)
{
- m_attachments = AttachmentPack();
- Attachment attach;
- attach.m_mipLevel = 0;
- attach.m_textureUuid = m_textureId;
- attach.m_point = QRenderTargetOutput::AttachmentPoint::Color0;
+ 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_attachments.addAttachment(attach);
+ m_sharedObject->clearSyncRequest();
+
+ m_sharedObject->m_renderControl->sync();
+
+ // gui thread can now continue
+ m_sharedObject->wakeWaiting();
+ }
}
void Scene2D::render()
{
- if (m_initialized && m_sharedObject && this->isEnabled()) {
+ if (m_initialized && m_renderInitialized && m_sharedObject.data() != nullptr) {
QMutexLocker lock(&m_sharedObject->m_mutex);
- // Lookup backend texture
- if (m_texture == nullptr) {
- m_texture = renderer()->nodeManagers()->textureManager()->lookupResource(m_textureId);
- if (!m_texture) {
- qCDebug(Render::Framegraph) << Q_FUNC_INFO << "Texture not set";
+ QOpenGLTexture *texture = nullptr;
+ const Qt3DRender::Render::Attachment *attachmentData = nullptr;
+ QMutex *textureLock = nullptr;
+
+ m_context->makeCurrent(m_sharedObject->m_surface);
+ if (m_accessor->accessResource(m_outputId, (void**)&attachmentData, nullptr)) {
+ if (!m_accessor->accessResource(attachmentData->m_textureUuid, (void**)&texture, &textureLock)) {
+ // Need to call sync even if the texture is not in use
+ syncRenderControl();
+ m_context->doneCurrent();
+ // TODO: add logging category for scene2d
+ //qCWarning(Scene2D) << "Texture not in use.";
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(Scene2D) << "Fbo not initialized.";
+ return;
+ }
+ }
}
- m_graphicsContext->makeCurrent(m_sharedObject->m_surface);
-
- // Don't create the OpenGL texture in this thread.
- const bool canUseTexture = !m_texture->isTextureReset();
-
- if (canUseTexture) {
- // Activate fbo for the texture
- QOpenGLTexture *glTex = m_texture->getOrCreateGLTexture();
- const QSize textureSize = QSize(glTex->width(), glTex->height());
+ if (m_fbo != m_sharedObject->m_quickWindow->renderTargetId())
+ m_sharedObject->m_quickWindow->setRenderTarget(m_fbo, m_textureSize);
- GLuint fbo = 0; //m_graphicsContext->activateRenderTargetForQmlRender(this, m_attachments, 0);
-
- if (fbo != m_sharedObject->m_quickWindow->renderTargetId())
- m_sharedObject->m_quickWindow->setRenderTarget(fbo, textureSize);
-
- m_texture->textureLock()->lock();
- }
// Call disallow rendering while mutex is locked
- if (canUseTexture && m_renderOnce)
+ if (m_renderOnce)
m_sharedObject->disallowRender();
- // Need to call sync even if the texture is not in use
- if (m_sharedObject->isSyncRequested()) {
+ // Sync
+ syncRenderControl();
- m_sharedObject->clearSyncRequest();
+ // The lock is not needed anymore so release it before the following
+ // time comsuming operations
+ lock.unlock();
- m_sharedObject->m_renderControl->sync();
+ // Render
+ m_sharedObject->m_renderControl->render();
- // gui thread can now continue
- m_sharedObject->wakeWaiting();
- lock.unlock();
- }
+ // Tell main thread we are done so it can begin cleanup if this is final frame
+ if (m_renderOnce)
+ QCoreApplication::postEvent(m_sharedObject->m_renderManager, new QEvent(RENDERED));
- if (canUseTexture) {
-
- // Render
- m_sharedObject->m_renderControl->render();
-
- // Tell main thread we are done so it can begin cleanup
- if (m_renderOnce)
- QCoreApplication::postEvent(m_sharedObject->m_renderManager, new QEvent(RENDERED));
-
- m_sharedObject->m_quickWindow->resetOpenGLState();
- m_context->functions()->glFlush();
- m_texture->textureLock()->unlock();
- }
- m_graphicsContext->doneCurrent();
+ m_sharedObject->m_quickWindow->resetOpenGLState();
+ m_context->functions()->glFlush();
+ if (texture->isAutoMipMapGenerationEnabled())
+ texture->generateMipMaps();
+ textureLock->unlock();
+ m_context->doneCurrent();
}
}
@@ -288,6 +317,8 @@ 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_sharedObject->m_renderThread->quit();
delete m_sharedObject->m_renderObject;
@@ -295,17 +326,13 @@ void Scene2D::cleanup()
delete m_context;
m_context = nullptr;
m_sharedObject = nullptr;
- delete m_graphicsContext;
- m_graphicsContext = nullptr;
m_renderInitialized = false;
m_initialized = false;
}
}
} // namespace Quick
-
} // namespace Render
-
} // namespace Qt3DRender
QT_END_NAMESPACE
diff --git a/src/quick3d/quick3drender/scene2d/scene2d.pri b/src/quick3d/quick3drender/scene2d/scene2d.pri
index 05ab6b83f..4635c43e1 100644
--- a/src/quick3d/quick3drender/scene2d/scene2d.pri
+++ b/src/quick3d/quick3drender/scene2d/scene2d.pri
@@ -1,5 +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/quick3drender/scene2d/scene2d_p.h b/src/quick3d/quick3drender/scene2d/scene2d_p.h
index 950ddaa5b..769916fc9 100644
--- a/src/quick3d/quick3drender/scene2d/scene2d_p.h
+++ b/src/quick3d/quick3drender/scene2d/scene2d_p.h
@@ -50,12 +50,14 @@
#include <Qt3DCore/qnodeid.h>
-#include <private/framegraphnode_p.h>
-#include <private/qscene2d_p.h>
-
#include <QtCore/QCoreApplication>
#include <QtCore/QSemaphore>
+#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 {
@@ -79,30 +81,37 @@ private:
Scene2D *m_node;
};
-class Q_AUTOTEST_EXPORT Scene2D : public FrameGraphNode
+class Q_AUTOTEST_EXPORT Scene2D : public Qt3DRender::Render::BackendNode
{
public:
Scene2D();
~Scene2D();
- void attach();
void render();
void initializeRender();
void setSharedObject(Qt3DRender::Quick::Scene2DSharedObjectPtr sharedObject);
void cleanup();
- void setTexture(Qt3DCore::QNodeId textureId);
- void checkInitialized();
+ 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;
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
+
+ bool updateFbo(QOpenGLTexture *texture);
+ void syncRenderControl();
QOpenGLContext *m_context;
- GraphicsContext *m_graphicsContext;
+ QOpenGLContext *m_shareContext;
QThread *m_renderThread;
- Qt3DCore::QNodeId m_textureId;
+ Qt3DCore::QNodeId m_outputId;
QSharedPointer<Qt3DRender::Quick::Scene2DSharedObject> m_sharedObject;
- AttachmentPack m_attachments;
- Texture *m_texture;
+ Qt3DCore::QNodeId m_peerId;
+ QSharedPointer<RenderBackendResourceAccessor> m_accessor;
+ Qt3DRender::Render::Attachment m_attachmentData;
+
+ GLuint m_fbo;
+ GLuint m_rbo;
+ QSize m_textureSize;
bool m_initialized;
bool m_renderInitialized;