From dcd5756f3870d9aed7f73c338cc8715d5fe35297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antti=20M=C3=A4=C3=A4tt=C3=A4?= Date: Wed, 2 Nov 2016 15:57:43 +0200 Subject: Update scene2d implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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ää Reviewed-by: Sean Harmer --- src/quick3d/quick3drender/scene2d/qscene2d.cpp | 178 ++++++++++++--------- src/quick3d/quick3drender/scene2d/qscene2d.h | 28 ++-- src/quick3d/quick3drender/scene2d/qscene2d_p.h | 31 ++-- src/quick3d/quick3drender/scene2d/scene2d.cpp | 213 ++++++++++++++----------- src/quick3d/quick3drender/scene2d/scene2d.pri | 5 + src/quick3d/quick3drender/scene2d/scene2d_p.h | 33 ++-- 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 @@ -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(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::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 +#include + #include #include -#include -#include -#include +#include + +#include 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 -#include - -#include -#include - #include #include #include @@ -64,6 +58,12 @@ #include #include +#include +#include + +#include +#include + QT_BEGIN_NAMESPACE namespace Qt3DRender { @@ -141,7 +141,7 @@ private: typedef QSharedPointer 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 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 #include #include - +#include +#include 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>(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(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(); - setTexture(textureId); + else if (propertyChange->propertyName() == QByteArrayLiteral("output")) { + Qt3DCore::QNodeId outputId = propertyChange->value().value(); + setOutput(outputId); + } else if (propertyChange->propertyName() == QByteArrayLiteral("sharedObject")) { + const Scene2DSharedObjectPtr sharedObject + = propertyChange->value().value(); + 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(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 -#include -#include - #include #include +#include +#include +#include +#include + 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 m_sharedObject; - AttachmentPack m_attachments; - Texture *m_texture; + Qt3DCore::QNodeId m_peerId; + QSharedPointer m_accessor; + Qt3DRender::Render::Attachment m_attachmentData; + + GLuint m_fbo; + GLuint m_rbo; + QSize m_textureSize; bool m_initialized; bool m_renderInitialized; -- cgit v1.2.3