1 /****************************************************************************
2 **
3 ** Copyright (C) 2008-2012 NVIDIA Corporation.
4 ** Copyright (C) 2019 The Qt Company Ltd.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of Qt Quick 3D.
8 **
9 ** $QT_BEGIN_LICENSE:GPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU
20 ** General Public License version 3 or (at your option) any later version
21 ** approved by the KDE Free Qt Foundation. The licenses are as published by
22 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
23 ** included in the packaging of this file. Please review the following
24 ** information to ensure the GNU General Public License requirements will
25 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
26 **
27 ** $QT_END_LICENSE$
28 **
29 ****************************************************************************/
30 
31 #include "qssgrendercontextcore_p.h"
32 #include <QtQuick3DRuntimeRender/private/qssgrendernode_p.h>
33 #include <QtQuick3DRuntimeRender/private/qssgrenderbuffermanager_p.h>
34 #include <QtQuick3DRuntimeRender/private/qssgrenderer_p.h>
35 #include <QtQuick3DRuntimeRender/private/qssgrenderresourcemanager_p.h>
36 #include <QtQuick3DRender/private/qssgrendercontext_p.h>
37 #include <QtQuick3DRuntimeRender/private/qssgrenderinputstreamfactory_p.h>
38 #include <QtQuick3DRuntimeRender/private/qssgrendershadercache_p.h>
39 #include <QtQuick3DRender/private/qssgrenderframebuffer_p.h>
40 #include <QtQuick3DRender/private/qssgrenderrenderbuffer_p.h>
41 #include <QtQuick3DRender/private/qssgrendertexture2d_p.h>
42 #include <QtQuick3DRuntimeRender/private/qssgrendercamera_p.h>
43 #include <QtQuick3DRuntimeRender/private/qssgrenderthreadpool_p.h>
44 #include <QtQuick3DRuntimeRender/private/qssgrenderimagebatchloader_p.h>
45 #include <QtQuick3DRuntimeRender/private/qssgrenderdynamicobjectsystem_p.h>
46 #include <QtQuick3DRuntimeRender/private/qssgrendercustommaterialsystem_p.h>
47 #include <QtQuick3DRuntimeRender/private/qssgrendershadercodegeneratorv2_p.h>
48 #include <QtQuick3DRuntimeRender/private/qssgrenderdefaultmaterialshadergenerator_p.h>
49 #include <QtQuick3DRuntimeRender/private/qssgperframeallocator_p.h>
50 #include <QtQuick3DRuntimeRender/private/qssgrendererimpl_p.h>
51 #include <QtQuick3DRuntimeRender/private/qssgrendererutil_p.h>
52 
53 #include <QtCore/qthread.h>
54 
55 QT_BEGIN_NAMESPACE
56 
idealThreadCount()57 static int idealThreadCount()
58 {
59     static const int threads = qEnvironmentVariableIntValue("QT_QUICK3D_THREAD_COUNT");
60     return (threads > 0) ? threads : QThread::idealThreadCount();
61 }
62 
QSSGRenderContextInterface(const QSSGRef<QSSGRenderContext> & ctx,const QString & inApplicationDirectory)63 QSSGRenderContextInterface::QSSGRenderContextInterface(const QSSGRef<QSSGRenderContext> &ctx, const QString &inApplicationDirectory)
64     : m_renderContext(ctx)
65     , m_inputStreamFactory(new QSSGInputStreamFactory)
66     , m_bufferManager(new QSSGBufferManager(ctx, m_inputStreamFactory, &m_perfTimer))
67     , m_resourceManager(new QSSGResourceManager(ctx))
68     , m_renderer(QSSGRendererInterface::createRenderer(this))
69     , m_dynamicObjectSystem(new QSSGDynamicObjectSystem(this))
70     , m_effectSystem(new QSSGEffectSystem(this))
71     , m_shaderCache(QSSGShaderCache::createShaderCache(ctx, m_inputStreamFactory, &m_perfTimer))
72     , m_threadPool(QSSGAbstractThreadPool::createThreadPool(idealThreadCount()))
73     , m_customMaterialSystem(new QSSGMaterialSystem(this))
74     , m_shaderProgramGenerator(QSSGShaderProgramGeneratorInterface::createProgramGenerator(this))
75     , m_defaultMaterialShaderGenerator(QSSGDefaultMaterialShaderGeneratorInterface::createDefaultMaterialShaderGenerator(this))
76     , m_customMaterialShaderGenerator(QSSGMaterialShaderGeneratorInterface::createCustomMaterialShaderGenerator(this))
77 {
78     if (!inApplicationDirectory.isEmpty())
79         m_inputStreamFactory->addSearchDirectory(inApplicationDirectory);
80 
81     const_cast<QSSGRef<IImageBatchLoader> &>(m_imageBatchLoader) = IImageBatchLoader::createBatchLoader(m_inputStreamFactory, m_bufferManager, m_threadPool, &m_perfTimer);
82     m_customMaterialSystem->setRenderContextInterface(this);
83 
84 
85     const char *versionString = nullptr;
86     switch (ctx->renderContextType()) {
87     case QSSGRenderContextType::GLES2:
88         versionString = "gles2";
89         break;
90     case QSSGRenderContextType::GL2:
91         versionString = "gl2";
92         break;
93     case QSSGRenderContextType::GLES3:
94         versionString = "gles3";
95         break;
96     case QSSGRenderContextType::GL3:
97         versionString = "gl3";
98         break;
99     case QSSGRenderContextType::GLES3PLUS:
100         versionString = "gles3x";
101         break;
102     case QSSGRenderContextType::GL4:
103         versionString = "gl4";
104         break;
105     default:
106         Q_ASSERT(false);
107         break;
108     }
109 
110     dynamicObjectSystem()->setShaderCodeLibraryVersion(versionString);
111 #if defined(QSSG_SHADER_PLATFORM_LIBRARY_DIR)
112     const QString platformDirectory;
113 #if defined(_WIN32)
114     platformDirectory = QStringLiteral("res/platform/win");
115 #elif defined(_LINUX)
116     platformDirectory = QStringLiteral("res/platform/linux");
117 #elif defined(_MACOSX)
118     platformDirectory = QStringLiteral("res/platform/macos");
119 #endif
120     GetDynamicObjectSystem().setShaderCodeLibraryPlatformDirectory(platformDirectory);
121 #endif
122 }
123 
124 struct QSSGRenderContextInterfaceHandle
125 {
126     QSSGRenderContextInterface *ctx;
127     quintptr m_wid;
128 };
129 Q_DECLARE_TYPEINFO(QSSGRenderContextInterfaceHandle, Q_PRIMITIVE_TYPE);
130 
Q_GLOBAL_STATIC(QVector<QSSGRenderContextInterfaceHandle>,g_renderContexts)131 Q_GLOBAL_STATIC(QVector<QSSGRenderContextInterfaceHandle>, g_renderContexts)
132 
133 QSSGRenderContextInterface::~QSSGRenderContextInterface()
134 {
135     m_renderContext->releaseResources();
136     static_cast<QSSGRendererImpl *>(m_renderer.data())->releaseResources();
137 
138     for (int i = 0; i < g_renderContexts->size(); ++i) {
139         if (g_renderContexts->at(i).ctx == this) {
140             g_renderContexts->removeAt(i);
141             break;
142         }
143     }
144 }
145 
getRenderContextInterface(const QSSGRef<QSSGRenderContext> & ctx,const QString & inApplicationDirectory,quintptr wid)146 QSSGRef<QSSGRenderContextInterface> QSSGRenderContextInterface::getRenderContextInterface(const QSSGRef<QSSGRenderContext> &ctx, const QString &inApplicationDirectory, quintptr wid)
147 {
148     auto it = g_renderContexts->cbegin();
149     const auto end = g_renderContexts->cend();
150     for (; it != end; ++it) {
151         if (it->m_wid == wid)
152             break;
153     }
154 
155     if (it != end)
156         return it->ctx;
157 
158     const auto rci = QSSGRef<QSSGRenderContextInterface>(new QSSGRenderContextInterface(ctx, inApplicationDirectory));
159     g_renderContexts->push_back(QSSGRenderContextInterfaceHandle { rci.data(), wid });
160 
161     return rci;
162 }
163 
getRenderContextInterface(quintptr wid)164 QSSGRef<QSSGRenderContextInterface> QSSGRenderContextInterface::getRenderContextInterface(quintptr wid)
165 {
166     auto it = g_renderContexts->cbegin();
167     const auto end = g_renderContexts->cend();
168     for (; it != end; ++it) {
169         if (it->m_wid == wid)
170             break;
171     }
172 
173     if (it != end)
174         return it->ctx;
175 
176     return QSSGRef<QSSGRenderContextInterface>();
177 }
178 
renderer() const179 const QSSGRef<QSSGRendererInterface> &QSSGRenderContextInterface::renderer() const { return m_renderer; }
180 
bufferManager() const181 const QSSGRef<QSSGBufferManager> &QSSGRenderContextInterface::bufferManager() const { return m_bufferManager; }
182 
resourceManager() const183 const QSSGRef<QSSGResourceManager> &QSSGRenderContextInterface::resourceManager() const { return m_resourceManager; }
184 
renderContext() const185 const QSSGRef<QSSGRenderContext> &QSSGRenderContextInterface::renderContext() const { return m_renderContext; }
186 
inputStreamFactory() const187 const QSSGRef<QSSGInputStreamFactory> &QSSGRenderContextInterface::inputStreamFactory() const { return m_inputStreamFactory; }
188 
effectSystem() const189 const QSSGRef<QSSGEffectSystem> &QSSGRenderContextInterface::effectSystem() const { return m_effectSystem; }
190 
shaderCache() const191 const QSSGRef<QSSGShaderCache> &QSSGRenderContextInterface::shaderCache() const { return m_shaderCache; }
192 
threadPool() const193 const QSSGRef<QSSGAbstractThreadPool> &QSSGRenderContextInterface::threadPool() const { return m_threadPool; }
194 
imageBatchLoader() const195 const QSSGRef<IImageBatchLoader> &QSSGRenderContextInterface::imageBatchLoader() const { return m_imageBatchLoader; }
196 
dynamicObjectSystem() const197 const QSSGRef<QSSGDynamicObjectSystem> &QSSGRenderContextInterface::dynamicObjectSystem() const { return m_dynamicObjectSystem; }
198 
customMaterialSystem() const199 const QSSGRef<QSSGMaterialSystem> &QSSGRenderContextInterface::customMaterialSystem() const { return m_customMaterialSystem; }
200 
shaderProgramGenerator() const201 const QSSGRef<QSSGShaderProgramGeneratorInterface> &QSSGRenderContextInterface::shaderProgramGenerator() const
202 {
203     return m_shaderProgramGenerator;
204 }
205 
defaultMaterialShaderGenerator() const206 const QSSGRef<QSSGDefaultMaterialShaderGeneratorInterface> &QSSGRenderContextInterface::defaultMaterialShaderGenerator() const
207 {
208     return m_defaultMaterialShaderGenerator;
209 }
210 
customMaterialShaderGenerator() const211 const QSSGRef<QSSGMaterialShaderGeneratorInterface> &QSSGRenderContextInterface::customMaterialShaderGenerator() const
212 {
213     return m_customMaterialShaderGenerator;
214 }
215 
mousePickViewport() const216 QVector2D QSSGRenderContextInterface::mousePickViewport() const
217 {
218     return QVector2D((float)m_windowDimensions.width(), (float)m_windowDimensions.height());
219 }
220 
contextViewport() const221 QRect QSSGRenderContextInterface::contextViewport() const
222 {
223     QRect retval;
224     if (!m_viewport.isNull())
225         retval = m_viewport;
226     else
227         retval = QRect(0, 0, m_windowDimensions.width(), m_windowDimensions.height());
228 
229     return retval;
230 }
231 
mousePickMouseCoords(const QVector2D & inMouseCoords) const232 QVector2D QSSGRenderContextInterface::mousePickMouseCoords(const QVector2D &inMouseCoords) const
233 {
234     return inMouseCoords;
235 }
236 
237 
dumpGpuProfilerStats()238 void QSSGRenderContextInterface::dumpGpuProfilerStats()
239 {
240     m_renderer->dumpGpuProfilerStats();
241 }
242 
beginFrame()243 void QSSGRenderContextInterface::beginFrame()
244 {
245     m_perFrameAllocator.reset();
246     m_renderer->beginFrame();
247     m_imageBatchLoader->beginFrame();
248 }
249 
prepareLayerForRender(QSSGRenderLayer & inLayer)250 bool QSSGRenderContextInterface::prepareLayerForRender(QSSGRenderLayer &inLayer)
251 {
252     return renderer()->prepareLayerForRender(inLayer, m_windowDimensions);
253 }
254 
renderLayer(QSSGRenderLayer & inLayer,bool needsClear)255 void QSSGRenderContextInterface::renderLayer(QSSGRenderLayer &inLayer, bool needsClear)
256 {
257     renderer()->renderLayer(inLayer, m_windowDimensions, needsClear, m_sceneColor);
258 }
259 
endFrame()260 void QSSGRenderContextInterface::endFrame()
261 {
262     m_imageBatchLoader->endFrame();
263     m_renderer->endFrame();
264     m_customMaterialSystem->endFrame();
265     ++m_frameCount;
266 }
267 
268 QT_END_NAMESPACE
269 
270