| /**************************************************************************** |
| ** |
| ** Copyright (C) 2008-2012 NVIDIA Corporation. |
| ** Copyright (C) 2019 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of Qt Quick 3D. |
| ** |
| ** $QT_BEGIN_LICENSE:GPL$ |
| ** 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 General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 3 or (at your option) 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.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-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qssgrendercontextcore_p.h" |
| #include <QtQuick3DRuntimeRender/private/qssgrendernode_p.h> |
| #include <QtQuick3DRuntimeRender/private/qssgrenderbuffermanager_p.h> |
| #include <QtQuick3DRuntimeRender/private/qssgrenderer_p.h> |
| #include <QtQuick3DRuntimeRender/private/qssgrenderresourcemanager_p.h> |
| #include <QtQuick3DRender/private/qssgrendercontext_p.h> |
| #include <QtQuick3DRuntimeRender/private/qssgrenderinputstreamfactory_p.h> |
| #include <QtQuick3DRuntimeRender/private/qssgrendershadercache_p.h> |
| #include <QtQuick3DRender/private/qssgrenderframebuffer_p.h> |
| #include <QtQuick3DRender/private/qssgrenderrenderbuffer_p.h> |
| #include <QtQuick3DRender/private/qssgrendertexture2d_p.h> |
| #include <QtQuick3DRuntimeRender/private/qssgrendercamera_p.h> |
| #include <QtQuick3DRuntimeRender/private/qssgrenderthreadpool_p.h> |
| #include <QtQuick3DRuntimeRender/private/qssgrenderimagebatchloader_p.h> |
| #include <QtQuick3DRuntimeRender/private/qssgrenderdynamicobjectsystem_p.h> |
| #include <QtQuick3DRuntimeRender/private/qssgrendercustommaterialsystem_p.h> |
| #include <QtQuick3DRuntimeRender/private/qssgrendershadercodegeneratorv2_p.h> |
| #include <QtQuick3DRuntimeRender/private/qssgrenderdefaultmaterialshadergenerator_p.h> |
| #include <QtQuick3DRuntimeRender/private/qssgperframeallocator_p.h> |
| #include <QtQuick3DRuntimeRender/private/qssgrendererimpl_p.h> |
| #include <QtQuick3DRuntimeRender/private/qssgrendererutil_p.h> |
| |
| #include <QtCore/qthread.h> |
| |
| QT_BEGIN_NAMESPACE |
| |
| static int idealThreadCount() |
| { |
| static const int threads = qEnvironmentVariableIntValue("QT_QUICK3D_THREAD_COUNT"); |
| return (threads > 0) ? threads : QThread::idealThreadCount(); |
| } |
| |
| QSSGRenderContextInterface::QSSGRenderContextInterface(const QSSGRef<QSSGRenderContext> &ctx, const QString &inApplicationDirectory) |
| : m_renderContext(ctx) |
| , m_inputStreamFactory(new QSSGInputStreamFactory) |
| , m_bufferManager(new QSSGBufferManager(ctx, m_inputStreamFactory, &m_perfTimer)) |
| , m_resourceManager(new QSSGResourceManager(ctx)) |
| , m_renderer(QSSGRendererInterface::createRenderer(this)) |
| , m_dynamicObjectSystem(new QSSGDynamicObjectSystem(this)) |
| , m_effectSystem(new QSSGEffectSystem(this)) |
| , m_shaderCache(QSSGShaderCache::createShaderCache(ctx, m_inputStreamFactory, &m_perfTimer)) |
| , m_threadPool(QSSGAbstractThreadPool::createThreadPool(idealThreadCount())) |
| , m_customMaterialSystem(new QSSGMaterialSystem(this)) |
| , m_shaderProgramGenerator(QSSGShaderProgramGeneratorInterface::createProgramGenerator(this)) |
| , m_defaultMaterialShaderGenerator(QSSGDefaultMaterialShaderGeneratorInterface::createDefaultMaterialShaderGenerator(this)) |
| , m_customMaterialShaderGenerator(QSSGMaterialShaderGeneratorInterface::createCustomMaterialShaderGenerator(this)) |
| { |
| if (!inApplicationDirectory.isEmpty()) |
| m_inputStreamFactory->addSearchDirectory(inApplicationDirectory); |
| |
| const_cast<QSSGRef<IImageBatchLoader> &>(m_imageBatchLoader) = IImageBatchLoader::createBatchLoader(m_inputStreamFactory, m_bufferManager, m_threadPool, &m_perfTimer); |
| m_customMaterialSystem->setRenderContextInterface(this); |
| |
| |
| const char *versionString = nullptr; |
| switch (ctx->renderContextType()) { |
| case QSSGRenderContextType::GLES2: |
| versionString = "gles2"; |
| break; |
| case QSSGRenderContextType::GL2: |
| versionString = "gl2"; |
| break; |
| case QSSGRenderContextType::GLES3: |
| versionString = "gles3"; |
| break; |
| case QSSGRenderContextType::GL3: |
| versionString = "gl3"; |
| break; |
| case QSSGRenderContextType::GLES3PLUS: |
| versionString = "gles3x"; |
| break; |
| case QSSGRenderContextType::GL4: |
| versionString = "gl4"; |
| break; |
| default: |
| Q_ASSERT(false); |
| break; |
| } |
| |
| dynamicObjectSystem()->setShaderCodeLibraryVersion(versionString); |
| #if defined(QSSG_SHADER_PLATFORM_LIBRARY_DIR) |
| const QString platformDirectory; |
| #if defined(_WIN32) |
| platformDirectory = QStringLiteral("res/platform/win"); |
| #elif defined(_LINUX) |
| platformDirectory = QStringLiteral("res/platform/linux"); |
| #elif defined(_MACOSX) |
| platformDirectory = QStringLiteral("res/platform/macos"); |
| #endif |
| GetDynamicObjectSystem().setShaderCodeLibraryPlatformDirectory(platformDirectory); |
| #endif |
| } |
| |
| struct QSSGRenderContextInterfaceHandle |
| { |
| QSSGRenderContextInterface *ctx; |
| quintptr m_wid; |
| }; |
| Q_DECLARE_TYPEINFO(QSSGRenderContextInterfaceHandle, Q_PRIMITIVE_TYPE); |
| |
| Q_GLOBAL_STATIC(QVector<QSSGRenderContextInterfaceHandle>, g_renderContexts) |
| |
| QSSGRenderContextInterface::~QSSGRenderContextInterface() |
| { |
| m_renderContext->releaseResources(); |
| static_cast<QSSGRendererImpl *>(m_renderer.data())->releaseResources(); |
| |
| for (int i = 0; i < g_renderContexts->size(); ++i) { |
| if (g_renderContexts->at(i).ctx == this) { |
| g_renderContexts->removeAt(i); |
| break; |
| } |
| } |
| } |
| |
| QSSGRef<QSSGRenderContextInterface> QSSGRenderContextInterface::getRenderContextInterface(const QSSGRef<QSSGRenderContext> &ctx, const QString &inApplicationDirectory, quintptr wid) |
| { |
| auto it = g_renderContexts->cbegin(); |
| const auto end = g_renderContexts->cend(); |
| for (; it != end; ++it) { |
| if (it->m_wid == wid) |
| break; |
| } |
| |
| if (it != end) |
| return it->ctx; |
| |
| const auto rci = QSSGRef<QSSGRenderContextInterface>(new QSSGRenderContextInterface(ctx, inApplicationDirectory)); |
| g_renderContexts->push_back(QSSGRenderContextInterfaceHandle { rci.data(), wid }); |
| |
| return rci; |
| } |
| |
| QSSGRef<QSSGRenderContextInterface> QSSGRenderContextInterface::getRenderContextInterface(quintptr wid) |
| { |
| auto it = g_renderContexts->cbegin(); |
| const auto end = g_renderContexts->cend(); |
| for (; it != end; ++it) { |
| if (it->m_wid == wid) |
| break; |
| } |
| |
| if (it != end) |
| return it->ctx; |
| |
| return QSSGRef<QSSGRenderContextInterface>(); |
| } |
| |
| const QSSGRef<QSSGRendererInterface> &QSSGRenderContextInterface::renderer() const { return m_renderer; } |
| |
| const QSSGRef<QSSGBufferManager> &QSSGRenderContextInterface::bufferManager() const { return m_bufferManager; } |
| |
| const QSSGRef<QSSGResourceManager> &QSSGRenderContextInterface::resourceManager() const { return m_resourceManager; } |
| |
| const QSSGRef<QSSGRenderContext> &QSSGRenderContextInterface::renderContext() const { return m_renderContext; } |
| |
| const QSSGRef<QSSGInputStreamFactory> &QSSGRenderContextInterface::inputStreamFactory() const { return m_inputStreamFactory; } |
| |
| const QSSGRef<QSSGEffectSystem> &QSSGRenderContextInterface::effectSystem() const { return m_effectSystem; } |
| |
| const QSSGRef<QSSGShaderCache> &QSSGRenderContextInterface::shaderCache() const { return m_shaderCache; } |
| |
| const QSSGRef<QSSGAbstractThreadPool> &QSSGRenderContextInterface::threadPool() const { return m_threadPool; } |
| |
| const QSSGRef<IImageBatchLoader> &QSSGRenderContextInterface::imageBatchLoader() const { return m_imageBatchLoader; } |
| |
| const QSSGRef<QSSGDynamicObjectSystem> &QSSGRenderContextInterface::dynamicObjectSystem() const { return m_dynamicObjectSystem; } |
| |
| const QSSGRef<QSSGMaterialSystem> &QSSGRenderContextInterface::customMaterialSystem() const { return m_customMaterialSystem; } |
| |
| const QSSGRef<QSSGShaderProgramGeneratorInterface> &QSSGRenderContextInterface::shaderProgramGenerator() const |
| { |
| return m_shaderProgramGenerator; |
| } |
| |
| const QSSGRef<QSSGDefaultMaterialShaderGeneratorInterface> &QSSGRenderContextInterface::defaultMaterialShaderGenerator() const |
| { |
| return m_defaultMaterialShaderGenerator; |
| } |
| |
| const QSSGRef<QSSGMaterialShaderGeneratorInterface> &QSSGRenderContextInterface::customMaterialShaderGenerator() const |
| { |
| return m_customMaterialShaderGenerator; |
| } |
| |
| QVector2D QSSGRenderContextInterface::mousePickViewport() const |
| { |
| return QVector2D((float)m_windowDimensions.width(), (float)m_windowDimensions.height()); |
| } |
| |
| QRect QSSGRenderContextInterface::contextViewport() const |
| { |
| QRect retval; |
| if (!m_viewport.isNull()) |
| retval = m_viewport; |
| else |
| retval = QRect(0, 0, m_windowDimensions.width(), m_windowDimensions.height()); |
| |
| return retval; |
| } |
| |
| QVector2D QSSGRenderContextInterface::mousePickMouseCoords(const QVector2D &inMouseCoords) const |
| { |
| return inMouseCoords; |
| } |
| |
| |
| void QSSGRenderContextInterface::dumpGpuProfilerStats() |
| { |
| m_renderer->dumpGpuProfilerStats(); |
| } |
| |
| void QSSGRenderContextInterface::beginFrame() |
| { |
| m_perFrameAllocator.reset(); |
| m_renderer->beginFrame(); |
| m_imageBatchLoader->beginFrame(); |
| } |
| |
| bool QSSGRenderContextInterface::prepareLayerForRender(QSSGRenderLayer &inLayer) |
| { |
| return renderer()->prepareLayerForRender(inLayer, m_windowDimensions); |
| } |
| |
| void QSSGRenderContextInterface::renderLayer(QSSGRenderLayer &inLayer, bool needsClear) |
| { |
| renderer()->renderLayer(inLayer, m_windowDimensions, needsClear, m_sceneColor); |
| } |
| |
| void QSSGRenderContextInterface::endFrame() |
| { |
| m_imageBatchLoader->endFrame(); |
| m_renderer->endFrame(); |
| m_customMaterialSystem->endFrame(); |
| ++m_frameCount; |
| } |
| |
| QT_END_NAMESPACE |
| |