/**************************************************************************** ** ** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). ** Contact: http://www.qt-project.org/legal ** ** 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 Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qrenderaspect.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE namespace Qt3D { QRenderAspect::QRenderAspect(QObject *parent) : QAbstractAspect(QAbstractAspect::AspectRenderer, parent) , m_renderer(new Render::Renderer()) { // Won't return until the private RenderThread in Renderer has been created // The Renderer is set to wait the surface with a wait condition // Threads modifying the Renderer should be synchronized using the Renderer's mutex registerBackendType(QBackendNodeFunctorPtr(new Render::RenderEntityFunctor(m_renderer))); registerBackendType(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor(m_renderer->transformManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor(m_renderer->materialManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor(m_renderer->techniqueManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor(m_renderer->textureManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor(m_renderer->shaderManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor(m_renderer->effectManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor(m_renderer->criterionManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor(m_renderer->cameraManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor(m_renderer->lightManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor(m_renderer->layerManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::RenderMeshCreatorFunctor(m_renderer->meshManager(), m_renderer->meshDataManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor(m_renderer->renderPassManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::RenderSceneFunctor(m_renderer->sceneManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor(m_renderer->renderTargetManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor(m_renderer->attachmentManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor(m_renderer->sortCriterionManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::FrameGraphNodeFunctor(m_renderer->frameGraphManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::FrameGraphNodeFunctor(m_renderer->frameGraphManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::FrameGraphNodeFunctor(m_renderer->frameGraphManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::FrameGraphNodeFunctor(m_renderer->frameGraphManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::FrameGraphNodeFunctor(m_renderer->frameGraphManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::FrameGraphNodeFunctor(m_renderer->frameGraphManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::FrameGraphNodeFunctor(m_renderer->frameGraphManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::FrameGraphNodeFunctor(m_renderer->frameGraphManager()))); registerBackendType(QBackendNodeFunctorPtr(new Render::FrameGraphComponentFunctor(m_renderer))); registerBackendType(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor(m_renderer->parameterManager()))); } QVector QRenderAspect::jobsToExecute() { // Create jobs that will get exectued by the threadpool QVector jobs; // Create jobs to load in any meshes that are pending if (m_renderer != Q_NULLPTR) { QHash meshSources = m_renderer->meshDataManager()->meshesPending(); Q_FOREACH (const QNodeUuid &meshId, meshSources.keys()) { Render::LoadMeshDataJobPtr loadMeshJob(new Render::LoadMeshDataJob(meshSources[meshId], meshId)); loadMeshJob->setRenderer(m_renderer); jobs.append(loadMeshJob); } // 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) QVector sceneJobs = m_renderer->sceneManager()->pendingSceneLoaderJobs(); Q_FOREACH (Render::LoadSceneJobPtr job, sceneJobs) { job->setRenderer(m_renderer); jobs.append(job); } // Create jobs to update transforms and bounding volumes Render::UpdateWorldTransformJobPtr worldTransformJob(new Render::UpdateWorldTransformJob(m_renderer->renderSceneRoot())); Render::UpdateBoundingVolumeJobPtr boundingVolumeJob(new Render::UpdateBoundingVolumeJob(m_renderer->renderSceneRoot())); // We can only update bounding volumes once all world transforms are known boundingVolumeJob->addDependency(worldTransformJob); // Add all jobs to queue jobs.append(worldTransformJob); jobs.append(boundingVolumeJob); // Traverse the current framegraph and create jobs to populate // RenderBins with RenderCommands QVector renderBinJobs = m_renderer->createRenderBinJobs(); // TODO: Add wrapper around ThreadWeaver::Collection for (int i = 0; i < renderBinJobs.size(); ++i) { QAspectJobPtr renderBinJob = renderBinJobs.at(i); renderBinJob->addDependency(boundingVolumeJob); jobs.append(renderBinJob); } } return jobs; } void QRenderAspect::sceneNodeAdded(QSceneChangePtr &e) { QScenePropertyChangePtr propertyChange = e.staticCast(); QNodePtr nodePtr = propertyChange->value().value(); QNode *n = nodePtr.data(); QNodeVisitor visitor; visitor.traverse(n, this, &QRenderAspect::visitNode, &QRenderAspect::visitNode); } void QRenderAspect::sceneNodeRemoved(QSceneChangePtr &e) { QScenePropertyChangePtr propertyChange = e.staticCast(); QNodePtr nodePtr = propertyChange->value().value(); QNode *n = nodePtr.data(); QAbstractAspect::clearBackendNode(n); } void QRenderAspect::setRootEntity(QEntity *rootObject) { // setSceneGraphRoot is synchronized using the Renderer's mutex QNodeVisitor visitor; visitor.traverse(rootObject, this, &QRenderAspect::visitNode, &QRenderAspect::visitNode); m_renderer->setSceneGraphRoot(m_renderer->renderNodesManager()->lookupResource(rootObject->uuid())); } void QRenderAspect::onInitialize(QSurface *surface) { m_renderer->setQRenderAspect(this); m_renderer->createAllocators(); // setSurface is synchronized using the Renderer's mutex m_renderer->setSurface(surface); } void QRenderAspect::onCleanup() { delete m_renderer; //Render::Renderer *renderer = m_renderThread->renderer(); //QMetaObject::invokeMethod(renderer, "cleanup"); } void QRenderAspect::visitNode(QNode *node) { QAbstractAspect::createBackendNode(node); } } // Qt3D QT_END_NAMESPACE