diff options
Diffstat (limited to 'src/quick3d/quick3drender/scene2d/scene2d.cpp')
-rw-r--r-- | src/quick3d/quick3drender/scene2d/scene2d.cpp | 213 |
1 files changed, 120 insertions, 93 deletions
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 |