summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;