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