blob: 5784b35f491128662da776971fe55b998e1ce22b [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qrenderaspect.h"
#include "qrenderaspect_p.h"
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DRender/private/scenemanager_p.h>
#include <Qt3DRender/private/geometryrenderermanager_p.h>
#include <Qt3DRender/qsceneloader.h>
#include <Qt3DRender/qcamera.h>
#include <Qt3DRender/qcameraselector.h>
#include <Qt3DRender/qlayer.h>
#include <Qt3DRender/qlayerfilter.h>
#include <Qt3DRender/qlevelofdetail.h>
#include <Qt3DRender/qlevelofdetailswitch.h>
#include <Qt3DRender/qmaterial.h>
#include <Qt3DRender/qmesh.h>
#include <Qt3DRender/qparameter.h>
#include <Qt3DRender/qrenderpassfilter.h>
#include <Qt3DRender/qrendertargetselector.h>
#include <Qt3DRender/qtechniquefilter.h>
#include <Qt3DRender/qviewport.h>
#include <Qt3DRender/qrendertarget.h>
#include <Qt3DRender/qclearbuffers.h>
#include <Qt3DRender/qtexture.h>
#include <Qt3DRender/qeffect.h>
#include <Qt3DRender/qshaderdata.h>
#include <Qt3DRender/qrenderstateset.h>
#include <Qt3DRender/qnodraw.h>
#include <Qt3DRender/qnopicking.h>
#include <Qt3DRender/qcameralens.h>
#include <Qt3DRender/qattribute.h>
#include <Qt3DRender/qbuffer.h>
#include <Qt3DRender/qgeometry.h>
#include <Qt3DRender/qgeometryrenderer.h>
#include <Qt3DRender/qobjectpicker.h>
#include <Qt3DRender/qraycaster.h>
#include <Qt3DRender/qscreenraycaster.h>
#include <Qt3DRender/qfrustumculling.h>
#include <Qt3DRender/qabstractlight.h>
#include <Qt3DRender/qenvironmentlight.h>
#include <Qt3DRender/qdispatchcompute.h>
#include <Qt3DRender/qcomputecommand.h>
#include <Qt3DRender/qrendersurfaceselector.h>
#include <Qt3DRender/qrendersettings.h>
#include <Qt3DRender/qrendercapture.h>
#include <Qt3DRender/qbuffercapture.h>
#include <Qt3DRender/qmemorybarrier.h>
#include <Qt3DRender/qproximityfilter.h>
#include <Qt3DRender/qshaderprogrambuilder.h>
#include <Qt3DRender/qblitframebuffer.h>
#include <Qt3DRender/qsetfence.h>
#include <Qt3DRender/qwaitfence.h>
#include <Qt3DRender/qshaderimage.h>
#include <Qt3DRender/qsubtreeenabler.h>
#include <Qt3DCore/qarmature.h>
#include <Qt3DCore/qjoint.h>
#include <Qt3DCore/qskeletonloader.h>
#include <Qt3DRender/private/backendnode_p.h>
#include <Qt3DRender/private/cameraselectornode_p.h>
#include <Qt3DRender/private/layerfilternode_p.h>
#include <Qt3DRender/private/cameralens_p.h>
#include <Qt3DRender/private/filterkey_p.h>
#include <Qt3DRender/private/entity_p.h>
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DRender/private/shaderdata_p.h>
#include <Qt3DRender/private/renderpassfilternode_p.h>
#include <Qt3DRender/private/rendertargetselectornode_p.h>
#include <Qt3DRender/private/techniquefilternode_p.h>
#include <Qt3DRender/private/viewportnode_p.h>
#include <Qt3DRender/private/rendertarget_p.h>
#include <Qt3DRender/private/scenemanager_p.h>
#include <Qt3DRender/private/clearbuffers_p.h>
#include <Qt3DRender/private/sortpolicy_p.h>
#include <Qt3DRender/private/renderlogging_p.h>
#include <Qt3DRender/private/nodefunctor_p.h>
#include <Qt3DRender/private/framegraphnode_p.h>
#include <Qt3DRender/private/textureimage_p.h>
#include <Qt3DRender/private/statesetnode_p.h>
#include <Qt3DRender/private/nodraw_p.h>
#include <Qt3DRender/private/nopicking_p.h>
#include <Qt3DRender/private/vsyncframeadvanceservice_p.h>
#include <Qt3DRender/private/attribute_p.h>
#include <Qt3DRender/private/buffer_p.h>
#include <Qt3DRender/private/geometry_p.h>
#include <Qt3DRender/private/geometryrenderer_p.h>
#include <Qt3DRender/private/objectpicker_p.h>
#include <Qt3DRender/private/raycaster_p.h>
#include <Qt3DRender/private/boundingvolumedebug_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/calcgeometrytrianglevolumes_p.h>
#include <Qt3DRender/private/handle_types_p.h>
#include <Qt3DRender/private/buffermanager_p.h>
#include <Qt3DRender/private/geometryrenderermanager_p.h>
#include <Qt3DRender/private/loadgeometryjob_p.h>
#include <Qt3DRender/private/qsceneimportfactory_p.h>
#include <Qt3DRender/private/qsceneimporter_p.h>
#include <Qt3DRender/private/frustumculling_p.h>
#include <Qt3DRender/private/light_p.h>
#include <Qt3DRender/private/environmentlight_p.h>
#include <Qt3DRender/private/dispatchcompute_p.h>
#include <Qt3DRender/private/computecommand_p.h>
#include <Qt3DRender/private/rendersurfaceselector_p.h>
#include <Qt3DRender/private/rendersettings_p.h>
#include <Qt3DRender/private/backendnode_p.h>
#include <Qt3DRender/private/rendercapture_p.h>
#include <Qt3DRender/private/buffercapture_p.h>
#include <Qt3DRender/private/technique_p.h>
#include <Qt3DRender/private/offscreensurfacehelper_p.h>
#include <Qt3DRender/private/memorybarrier_p.h>
#include <Qt3DRender/private/shaderbuilder_p.h>
#include <Qt3DRender/private/blitframebuffer_p.h>
#include <Qt3DRender/private/subtreeenabler_p.h>
#include <Qt3DRender/private/armature_p.h>
#include <Qt3DRender/private/skeleton_p.h>
#include <Qt3DRender/private/joint_p.h>
#include <Qt3DRender/private/loadskeletonjob_p.h>
#include <Qt3DRender/private/proximityfilter_p.h>
#include <Qt3DRender/private/setfence_p.h>
#include <Qt3DRender/private/waitfence_p.h>
#include <Qt3DRender/private/shaderimage_p.h>
#include <private/qrenderpluginfactory_p.h>
#include <private/qrenderplugin_p.h>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qtransform.h>
#include <Qt3DCore/qnode.h>
#include <Qt3DCore/QAspectEngine>
#include <Qt3DCore/private/qservicelocator_p.h>
#include <QThread>
#include <QOpenGLContext>
QT_BEGIN_NAMESPACE
using namespace Qt3DCore;
namespace Qt3DRender {
/*!
* \class Qt3DRender::QRenderAspect
* \inheaderfile Qt3DRender/QRenderAspect
* \brief The QRenderAspect class.
* \since 5.7
* \inmodule Qt3DRender
*/
/*!
\namespace Qt3DRender::Render
\inmodule Qt3DRender
\brief Namespace used for accessing the classes
Renderer and QRenderPlugin.
*/
/*! \internal */
QRenderAspectPrivate::QRenderAspectPrivate(QRenderAspect::RenderType type)
: QAbstractAspectPrivate()
, m_nodeManagers(nullptr)
, m_renderer(nullptr)
, m_initialized(false)
, m_renderAfterJobs(false)
, m_renderType(type)
, m_offscreenHelper(nullptr)
{
m_instances.append(this);
loadSceneParsers();
if (m_renderType == QRenderAspect::Threaded && !QOpenGLContext::supportsThreadedOpenGL()) {
m_renderType = QRenderAspect::Synchronous;
m_renderAfterJobs = true;
}
}
/*! \internal */
QRenderAspectPrivate::~QRenderAspectPrivate()
{
// The renderer should have been shutdown as part of onUnregistered().
// If it still exists then this aspect is being deleted before the aspect
// engine is finished with it.
if (m_renderer != nullptr)
qWarning() << Q_FUNC_INFO << "The renderer should have been deleted when reaching this point (this warning may be normal when running tests)";
delete m_nodeManagers;
m_instances.removeAll(this);
qDeleteAll(m_sceneImporter);
}
QRenderAspectPrivate *QRenderAspectPrivate::findPrivate(Qt3DCore::QAspectEngine *engine)
{
const QVector<QAbstractAspect*> aspects = engine->aspects();
for (QAbstractAspect* aspect : aspects) {
QRenderAspect *renderAspect = qobject_cast<QRenderAspect *>(aspect);
if (renderAspect)
return static_cast<QRenderAspectPrivate *>(renderAspect->d_ptr.data());
}
return nullptr;
}
void QRenderAspectPrivate::syncDirtyFrontEndNode(QNode *node, QBackendNode *backend, bool firstTime) const
{
Render::BackendNode *renderBackend = static_cast<Render::BackendNode *>(backend);
renderBackend->syncFromFrontEnd(node, firstTime);
}
void QRenderAspectPrivate::jobsDone()
{
if (m_renderAfterJobs)
m_renderer->doRender(true);
}
/*! \internal */
void QRenderAspectPrivate::registerBackendTypes()
{
Q_Q(QRenderAspect);
qRegisterMetaType<Qt3DRender::QBuffer*>();
qRegisterMetaType<Qt3DRender::QEffect*>();
qRegisterMetaType<Qt3DRender::QFrameGraphNode *>();
qRegisterMetaType<Qt3DRender::QCamera*>();
qRegisterMetaType<Qt3DRender::QShaderProgram*>();
qRegisterMetaType<Qt3DRender::QViewport*>();
qRegisterMetaType<Qt3DCore::QJoint*>();
registerBackendType<Qt3DCore::QEntity, true>(QSharedPointer<Render::RenderEntityFunctor>::create(m_renderer, m_nodeManagers));
registerBackendType<Qt3DCore::QTransform, true>(QSharedPointer<Render::NodeFunctor<Render::Transform, Render::TransformManager> >::create(m_renderer));
registerBackendType<Qt3DRender::QCameraLens, true>(QSharedPointer<Render::CameraLensFunctor>::create(m_renderer, q));
registerBackendType<QLayer, true>(QSharedPointer<Render::NodeFunctor<Render::Layer, Render::LayerManager> >::create(m_renderer));
registerBackendType<QLevelOfDetail, true>(QSharedPointer<Render::NodeFunctor<Render::LevelOfDetail, Render::LevelOfDetailManager> >::create(m_renderer));
registerBackendType<QLevelOfDetailSwitch, true>(QSharedPointer<Render::NodeFunctor<Render::LevelOfDetail, Render::LevelOfDetailManager> >::create(m_renderer));
registerBackendType<QSceneLoader, true>(QSharedPointer<Render::RenderSceneFunctor>::create(m_renderer, m_nodeManagers->sceneManager()));
registerBackendType<QRenderTarget, true>(QSharedPointer<Render::NodeFunctor<Render::RenderTarget, Render::RenderTargetManager> >::create(m_renderer));
registerBackendType<QRenderTargetOutput, true>(QSharedPointer<Render::NodeFunctor<Render::RenderTargetOutput, Render::AttachmentManager> >::create(m_renderer));
registerBackendType<QRenderSettings, true>(QSharedPointer<Render::RenderSettingsFunctor>::create(m_renderer));
registerBackendType<QRenderState, true>(QSharedPointer<Render::NodeFunctor<Render::RenderStateNode, Render::RenderStateManager> >::create(m_renderer));
// Geometry + Compute
registerBackendType<QAttribute, true>(QSharedPointer<Render::NodeFunctor<Render::Attribute, Render::AttributeManager> >::create(m_renderer));
registerBackendType<QBuffer, true>(QSharedPointer<Render::BufferFunctor>::create(m_renderer, m_nodeManagers->bufferManager()));
registerBackendType<QComputeCommand, true>(QSharedPointer<Render::NodeFunctor<Render::ComputeCommand, Render::ComputeCommandManager> >::create(m_renderer));
registerBackendType<QGeometry, true>(QSharedPointer<Render::NodeFunctor<Render::Geometry, Render::GeometryManager> >::create(m_renderer));
registerBackendType<QGeometryRenderer, true>(QSharedPointer<Render::GeometryRendererFunctor>::create(m_renderer, m_nodeManagers->geometryRendererManager()));
registerBackendType<Qt3DCore::QArmature, true>(QSharedPointer<Render::NodeFunctor<Render::Armature, Render::ArmatureManager>>::create(m_renderer));
registerBackendType<Qt3DCore::QAbstractSkeleton, true>(QSharedPointer<Render::SkeletonFunctor>::create(m_renderer, m_nodeManagers->skeletonManager(), m_nodeManagers->jointManager()));
registerBackendType<Qt3DCore::QJoint, true>(QSharedPointer<Render::JointFunctor>::create(m_renderer, m_nodeManagers->jointManager(), m_nodeManagers->skeletonManager()));
// Textures
registerBackendType<QAbstractTexture, true>(QSharedPointer<Render::TextureFunctor>::create(m_renderer, m_nodeManagers->textureManager()));
registerBackendType<QAbstractTextureImage, true>(QSharedPointer<Render::TextureImageFunctor>::create(m_renderer,
m_nodeManagers->textureImageManager()));
// Material system
registerBackendType<QEffect, true>(QSharedPointer<Render::NodeFunctor<Render::Effect, Render::EffectManager> >::create(m_renderer));
registerBackendType<QFilterKey, true>(QSharedPointer<Render::NodeFunctor<Render::FilterKey, Render::FilterKeyManager> >::create(m_renderer));
registerBackendType<QAbstractLight, true>(QSharedPointer<Render::RenderLightFunctor>::create(m_renderer, m_nodeManagers));
registerBackendType<QEnvironmentLight, true>(QSharedPointer<Render::NodeFunctor<Render::EnvironmentLight, Render::EnvironmentLightManager> >::create(m_renderer));
registerBackendType<QMaterial, true>(QSharedPointer<Render::NodeFunctor<Render::Material, Render::MaterialManager> >::create(m_renderer));
registerBackendType<QParameter, true>(QSharedPointer<Render::NodeFunctor<Render::Parameter, Render::ParameterManager> >::create(m_renderer));
registerBackendType<QRenderPass, true>(QSharedPointer<Render::NodeFunctor<Render::RenderPass, Render::RenderPassManager> >::create(m_renderer));
registerBackendType<QShaderData, true>(QSharedPointer<Render::RenderShaderDataFunctor>::create(m_renderer, m_nodeManagers));
registerBackendType<QShaderProgram, true>(QSharedPointer<Render::NodeFunctor<Render::Shader, Render::ShaderManager> >::create(m_renderer));
registerBackendType<QShaderProgramBuilder, true>(QSharedPointer<Render::NodeFunctor<Render::ShaderBuilder, Render::ShaderBuilderManager> >::create(m_renderer));
registerBackendType<QTechnique, true>(QSharedPointer<Render::TechniqueFunctor>::create(m_renderer, m_nodeManagers));
registerBackendType<QShaderImage, true>(QSharedPointer<Render::NodeFunctor<Render::ShaderImage, Render::ShaderImageManager>>::create(m_renderer));
// Framegraph
registerBackendType<QFrameGraphNode, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::FrameGraphNode, QFrameGraphNode> >::create(m_renderer));
registerBackendType<QCameraSelector, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::CameraSelector, QCameraSelector> >::create(m_renderer));
registerBackendType<QClearBuffers, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::ClearBuffers, QClearBuffers> >::create(m_renderer));
registerBackendType<QDispatchCompute, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::DispatchCompute, QDispatchCompute> >::create(m_renderer));
registerBackendType<QFrustumCulling, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::FrustumCulling, QFrustumCulling> >::create(m_renderer));
registerBackendType<QLayerFilter, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::LayerFilterNode, QLayerFilter> >::create(m_renderer));
registerBackendType<QNoDraw, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::NoDraw, QNoDraw> >::create(m_renderer));
registerBackendType<QRenderPassFilter, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderPassFilter, QRenderPassFilter> >::create(m_renderer));
registerBackendType<QRenderStateSet, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::StateSetNode, QRenderStateSet> >::create(m_renderer));
registerBackendType<QRenderSurfaceSelector, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderSurfaceSelector, QRenderSurfaceSelector> >::create(m_renderer));
registerBackendType<QRenderTargetSelector, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderTargetSelector, QRenderTargetSelector> >::create(m_renderer));
registerBackendType<QSortPolicy, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::SortPolicy, QSortPolicy> >::create(m_renderer));
registerBackendType<QTechniqueFilter, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::TechniqueFilter, QTechniqueFilter> >::create(m_renderer));
registerBackendType<QViewport, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::ViewportNode, QViewport> >::create(m_renderer));
registerBackendType<QRenderCapture, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderCapture, QRenderCapture> >::create(m_renderer));
registerBackendType<QBufferCapture, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::BufferCapture, QBufferCapture> >::create(m_renderer));
registerBackendType<QMemoryBarrier, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::MemoryBarrier, QMemoryBarrier> >::create(m_renderer));
registerBackendType<QProximityFilter, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::ProximityFilter, QProximityFilter> >::create(m_renderer));
registerBackendType<QBlitFramebuffer, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::BlitFramebuffer, QBlitFramebuffer> >::create(m_renderer));
registerBackendType<QSetFence, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::SetFence, QSetFence> >::create(m_renderer));
registerBackendType<QWaitFence, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::WaitFence, QWaitFence> >::create(m_renderer));
registerBackendType<QNoPicking, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::NoPicking, QNoPicking> >::create(m_renderer));
registerBackendType<QSubtreeEnabler, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::SubtreeEnabler, QSubtreeEnabler> >::create(m_renderer));
// Picking
registerBackendType<QObjectPicker, true>(QSharedPointer<Render::NodeFunctor<Render::ObjectPicker, Render::ObjectPickerManager> >::create(m_renderer));
registerBackendType<QRayCaster, true>(QSharedPointer<Render::NodeFunctor<Render::RayCaster, Render::RayCasterManager> >::create(m_renderer));
registerBackendType<QScreenRayCaster, true>(QSharedPointer<Render::NodeFunctor<Render::RayCaster, Render::RayCasterManager> >::create(m_renderer));
// Plugins
for (const QString &plugin : qAsConst(m_pluginConfig))
loadRenderPlugin(plugin);
}
/*! \internal */
void QRenderAspectPrivate::unregisterBackendTypes()
{
Q_Q(QRenderAspect);
unregisterBackendType<Qt3DCore::QEntity>();
unregisterBackendType<Qt3DCore::QTransform>();
unregisterBackendType<Qt3DRender::QCameraLens>();
unregisterBackendType<QLayer>();
unregisterBackendType<QSceneLoader>();
unregisterBackendType<QRenderTarget>();
unregisterBackendType<QRenderTargetOutput>();
unregisterBackendType<QRenderSettings>();
unregisterBackendType<QRenderState>();
// Geometry + Compute
unregisterBackendType<QAttribute>();
unregisterBackendType<QBuffer>();
unregisterBackendType<QComputeCommand>();
unregisterBackendType<QGeometry>();
unregisterBackendType<QGeometryRenderer>();
unregisterBackendType<Qt3DCore::QArmature>();
unregisterBackendType<Qt3DCore::QAbstractSkeleton>();
unregisterBackendType<Qt3DCore::QJoint>();
// Textures
unregisterBackendType<QAbstractTexture>();
unregisterBackendType<QAbstractTextureImage>();
// Material system
unregisterBackendType<QEffect>();
unregisterBackendType<QFilterKey>();
unregisterBackendType<QAbstractLight>();
unregisterBackendType<QEnvironmentLight>();
unregisterBackendType<QMaterial>();
unregisterBackendType<QParameter>();
unregisterBackendType<QRenderPass>();
unregisterBackendType<QShaderData>();
unregisterBackendType<QShaderProgram>();
unregisterBackendType<QShaderProgramBuilder>();
unregisterBackendType<QTechnique>();
unregisterBackendType<QShaderImage>();
// Framegraph
unregisterBackendType<QCameraSelector>();
unregisterBackendType<QClearBuffers>();
unregisterBackendType<QDispatchCompute>();
unregisterBackendType<QFrustumCulling>();
unregisterBackendType<QLayerFilter>();
unregisterBackendType<QNoDraw>();
unregisterBackendType<QRenderPassFilter>();
unregisterBackendType<QRenderStateSet>();
unregisterBackendType<QRenderSurfaceSelector>();
unregisterBackendType<QRenderTargetSelector>();
unregisterBackendType<QSortPolicy>();
unregisterBackendType<QTechniqueFilter>();
unregisterBackendType<QViewport>();
unregisterBackendType<QRenderCapture>();
unregisterBackendType<QBufferCapture>();
unregisterBackendType<QMemoryBarrier>();
unregisterBackendType<QSetFence>();
unregisterBackendType<QWaitFence>();
unregisterBackendType<QSubtreeEnabler>();
// Picking
unregisterBackendType<QObjectPicker>();
unregisterBackendType<QRayCaster>();
unregisterBackendType<QScreenRayCaster>();
// Plugins
for (Render::QRenderPlugin *plugin : qAsConst(m_renderPlugins))
plugin->unregisterBackendTypes(q);
}
/*!
* The constructor creates a new QRenderAspect::QRenderAspect instance with the
* specified \a parent.
* \param parent
*/
QRenderAspect::QRenderAspect(QObject *parent)
: QRenderAspect(Threaded, parent) {}
/*!
* The constructor creates a new QRenderAspect::QRenderAspect instance with the
* specified \a type and \a parent.
* \param type
* \param parent
*/
QRenderAspect::QRenderAspect(QRenderAspect::RenderType type, QObject *parent)
: QRenderAspect(*new QRenderAspectPrivate(type), parent) {}
/*! \internal */
QRenderAspect::QRenderAspect(QRenderAspectPrivate &dd, QObject *parent)
: QAbstractAspect(dd, parent)
{
setObjectName(QStringLiteral("Render Aspect"));
}
/*! \internal */
QRenderAspect::~QRenderAspect()
{
}
// Called by Scene3DRenderer only
void QRenderAspectPrivate::renderInitialize(QOpenGLContext *context)
{
if (m_renderer->api() == Render::AbstractRenderer::OpenGL)
m_renderer->setOpenGLContext(context);
m_renderer->initialize();
}
/*! \internal */
void QRenderAspectPrivate::renderSynchronous(bool swapBuffers)
{
m_renderer->doRender(swapBuffers);
}
/*
* \internal
* Only called when rendering with QtQuick 2 and a Scene3D item
*/
void QRenderAspectPrivate::renderShutdown()
{
m_renderer->shutdown();
}
QVector<Qt3DCore::QAspectJobPtr> QRenderAspect::jobsToExecute(qint64 time)
{
Q_D(QRenderAspect);
d->m_renderer->setTime(time);
#if defined(QT3D_RENDER_DUMP_BACKEND_NODES)
d->m_renderer->dumpInfo();
#endif
// Create jobs that will get executed by the threadpool
QVector<QAspectJobPtr> jobs;
// 1 LoadBufferJobs, GeometryJobs, SceneLoaderJobs, LoadTextureJobs
// 2 CalculateBoundingVolumeJob (depends on LoadBuffer)
// 3 WorldTransformJob
// 4 UpdateBoundingVolume, FramePreparationJob (depend on WorlTransformJob)
// 5 CalcGeometryTriangleVolumes (frame preparation job), RenderViewJobs
// 6 PickBoundingVolumeJob
// 7 Cleanup Job (depends on RV)
// Ensure we have a settings object. It may get deleted by the call to
// QChangeArbiter::syncChanges() that happens just before the render aspect is
// asked for jobs to execute (this function). If that is the case, the RenderSettings will
// be null and we should not generate any jobs.
if (d->m_renderer->isRunning() && d->m_renderer->settings()) {
Render::NodeManagers *manager = d->m_renderer->nodeManagers();
QAspectJobPtr loadingJobSync = d->m_renderer->syncLoadingJobs();
loadingJobSync->removeDependency(QWeakPointer<QAspectJob>());
// Launch skeleton loader jobs once all loading jobs have completed.
const QVector<Render::HSkeleton> skeletonsToLoad =
manager->skeletonManager()->takeDirtySkeletons(Render::SkeletonManager::SkeletonDataDirty);
for (const auto &skeletonHandle : skeletonsToLoad) {
auto loadSkeletonJob = Render::LoadSkeletonJobPtr::create(skeletonHandle);
loadSkeletonJob->setNodeManagers(manager);
loadingJobSync->addDependency(loadSkeletonJob);
jobs.append(loadSkeletonJob);
}
// TO DO: Have 2 jobs queue
// One for urgent jobs that are mandatory for the rendering of a frame
// Another for jobs that can span across multiple frames (Scene/Mesh loading)
const QVector<Render::LoadSceneJobPtr> sceneJobs = manager->sceneManager()->takePendingSceneLoaderJobs();
for (const Render::LoadSceneJobPtr &job : sceneJobs) {
job->setNodeManagers(d->m_nodeManagers);
job->setSceneImporters(d->m_sceneImporter);
jobs.append(job);
}
const QVector<QAspectJobPtr> geometryJobs = d->createGeometryRendererJobs();
jobs.append(geometryJobs);
const QVector<QAspectJobPtr> preRenderingJobs = d->m_renderer->preRenderingJobs();
jobs.append(preRenderingJobs);
// Don't spawn any rendering jobs, if the renderer decides to skip this frame
// Note: this only affects rendering jobs (jobs that load buffers,
// perform picking,... must still be run)
if (!d->m_renderer->shouldRender()) {
d->m_renderer->skipNextFrame();
QThread::msleep(1);
return jobs;
}
// Traverse the current framegraph and create jobs to populate
// RenderBins with RenderCommands
// All jobs needed to create the frame and their dependencies are set by
// renderBinJobs()
const QVector<QAspectJobPtr> renderBinJobs = d->m_renderer->renderBinJobs();
jobs.append(renderBinJobs);
}
return jobs;
}
QVariant QRenderAspect::executeCommand(const QStringList &args)
{
Q_D(QRenderAspect);
return d->m_renderer->executeCommand(args);
}
void QRenderAspect::onEngineStartup()
{
Q_D(QRenderAspect);
if (d->m_renderAfterJobs) // synchronous rendering but using QWindow
d->m_renderer->initialize();
Render::NodeManagers *managers = d->m_renderer->nodeManagers();
Render::Entity *rootEntity = managers->lookupResource<Render::Entity, Render::EntityManager>(rootEntityId());
Q_ASSERT(rootEntity);
d->m_renderer->setSceneRoot(rootEntity);
}
void QRenderAspect::onRegistered()
{
// Create a renderer each time as this is destroyed in onUnregistered below. If
// using a threaded renderer, this blocks until the render thread has been created
// and started.
Q_D(QRenderAspect);
d->m_nodeManagers = new Render::NodeManagers();
// TO DO: Load proper Renderer class based on Qt configuration preferences
d->m_renderer = new Render::Renderer(d->m_renderType);
d->m_renderer->setScreen(d->m_screen);
d->m_renderer->setNodeManagers(d->m_nodeManagers);
// Create a helper for deferring creation of an offscreen surface used during cleanup
// to the main thread, after we know what the surface format in use is.
d->m_offscreenHelper = new Render::OffscreenSurfaceHelper(d->m_renderer);
d->m_offscreenHelper->moveToThread(QCoreApplication::instance()->thread());
d->m_renderer->setOffscreenSurfaceHelper(d->m_offscreenHelper);
// Register backend types now that we have a renderer
d->registerBackendTypes();
if (!d->m_initialized) {
// Register the VSyncFrameAdvanceService to drive the aspect manager loop
// depending on the vsync
if (d->m_aspectManager) {
QAbstractFrameAdvanceService *advanceService = d->m_renderer->frameAdvanceService();
if (advanceService)
d->services()->registerServiceProvider(Qt3DCore::QServiceLocator::FrameAdvanceService,
advanceService);
}
if (d->services())
d->m_renderer->setServices(d->services());
d->m_initialized = true;
}
if (d->m_aspectManager)
d->m_renderer->registerEventFilter(d->services()->eventFilterService());
}
void QRenderAspect::onUnregistered()
{
Q_D(QRenderAspect);
if (d->m_renderer) {
// Request the renderer shuts down. In the threaded renderer case, the
// Renderer destructor is the synchronization point where we wait for the
// thread to join (see below).
d->m_renderer->shutdown();
}
d->unregisterBackendTypes();
delete d->m_nodeManagers;
d->m_nodeManagers = nullptr;
// Waits for the render thread to join (if using threaded renderer)
delete d->m_renderer;
d->m_renderer = nullptr;
// Queue the offscreen surface helper for deletion on the main thread.
// That will take care of deleting the offscreen surface itself.
d->m_offscreenHelper->deleteLater();
d->m_offscreenHelper = nullptr;
}
QVector<Qt3DCore::QAspectJobPtr> QRenderAspectPrivate::createGeometryRendererJobs()
{
Render::GeometryRendererManager *geomRendererManager = m_nodeManagers->geometryRendererManager();
const QVector<QNodeId> dirtyGeometryRenderers = geomRendererManager->dirtyGeometryRenderers();
QVector<QAspectJobPtr> dirtyGeometryRendererJobs;
dirtyGeometryRendererJobs.reserve(dirtyGeometryRenderers.size());
for (const QNodeId geoRendererId : dirtyGeometryRenderers) {
Render::HGeometryRenderer geometryRendererHandle = geomRendererManager->lookupHandle(geoRendererId);
if (!geometryRendererHandle.isNull()) {
auto job = Render::LoadGeometryJobPtr::create(geometryRendererHandle);
job->setNodeManagers(m_nodeManagers);
dirtyGeometryRendererJobs.push_back(job);
}
}
return dirtyGeometryRendererJobs;
}
void QRenderAspectPrivate::loadSceneParsers()
{
const QStringList keys = QSceneImportFactory::keys();
for (const QString &key : keys) {
QSceneImporter *sceneIOHandler = QSceneImportFactory::create(key, QStringList());
if (sceneIOHandler != nullptr)
m_sceneImporter.append(sceneIOHandler);
}
}
void QRenderAspectPrivate::loadRenderPlugin(const QString &pluginName)
{
Q_Q(QRenderAspect);
const QStringList keys = Render::QRenderPluginFactory::keys();
if (!keys.contains(pluginName))
return;
if (m_pluginConfig.contains(pluginName) && !m_loadedPlugins.contains(pluginName)) {
Render::QRenderPlugin *plugin
= Render::QRenderPluginFactory::create(pluginName, QStringList());
if (plugin != nullptr) {
m_loadedPlugins.append(pluginName);
m_renderPlugins.append(plugin);
plugin->registerBackendTypes(q, m_renderer);
}
}
}
QVector<QString> QRenderAspectPrivate::m_pluginConfig;
QMutex QRenderAspectPrivate::m_pluginLock;
QVector<QRenderAspectPrivate *> QRenderAspectPrivate::m_instances;
void QRenderAspectPrivate::configurePlugin(const QString &plugin)
{
QMutexLocker lock(&m_pluginLock);
if (!m_pluginConfig.contains(plugin)) {
m_pluginConfig.append(plugin);
for (QRenderAspectPrivate *instance : qAsConst(m_instances))
instance->loadRenderPlugin(plugin);
}
}
} // namespace Qt3DRender
QT_END_NAMESPACE
QT3D_REGISTER_NAMESPACED_ASPECT("render", QT_PREPEND_NAMESPACE(Qt3DRender), QRenderAspect)