1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qsgdefaultcontext_p.h"
5
6#include <QtQuick/private/qsgdefaultinternalrectanglenode_p.h>
7#include <QtQuick/private/qsgdefaultinternalimagenode_p.h>
8#include <QtQuick/private/qsgdefaultpainternode_p.h>
9#include <QtQuick/private/qsgdefaultglyphnode_p.h>
10#include <QtQuick/private/qsgdistancefieldglyphnode_p.h>
11#include <QtQuick/private/qsgdistancefieldglyphnode_p_p.h>
12#include <QtQuick/private/qsgrhisupport_p.h>
13#include <QtQuick/private/qsgrhilayer_p.h>
14#include <QtQuick/private/qsgdefaultrendercontext_p.h>
15#include <QtQuick/private/qsgdefaultrectanglenode_p.h>
16#include <QtQuick/private/qsgdefaultimagenode_p.h>
17#include <QtQuick/private/qsgdefaultninepatchnode_p.h>
18#if QT_CONFIG(quick_sprite)
19#include <QtQuick/private/qsgdefaultspritenode_p.h>
20#endif
21#include <QtQuick/private/qsgrhishadereffectnode_p.h>
22
23#include <QOpenGLContext>
24
25#include <QtQuick/private/qquickwindow_p.h>
26#include <QtQuick/private/qquickitem_p.h>
27
28#include <private/qqmlglobal_p.h>
29
30#include <algorithm>
31
32#include <rhi/qrhi.h>
33
34QT_BEGIN_NAMESPACE
35
36namespace QSGMultisampleAntialiasing {
37 class ImageNode : public QSGDefaultInternalImageNode {
38 public:
39 ImageNode(QSGDefaultRenderContext *rc) : QSGDefaultInternalImageNode(rc) { }
40 void setAntialiasing(bool) override { }
41 };
42
43 class RectangleNode : public QSGDefaultInternalRectangleNode {
44 public:
45 void setAntialiasing(bool) override { }
46 };
47}
48
49DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
50
51QSGDefaultContext::QSGDefaultContext(QObject *parent)
52 : QSGContext (parent)
53 , m_antialiasingMethod(QSGContext::UndecidedAntialiasing)
54 , m_distanceFieldDisabled(qmlDisableDistanceField())
55 , m_distanceFieldAntialiasing(QSGGlyphNode::HighQualitySubPixelAntialiasing)
56 , m_distanceFieldAntialiasingDecided(false)
57{
58 if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("QSG_DISTANCEFIELD_ANTIALIASING"))) {
59 const QByteArray mode = qgetenv(varName: "QSG_DISTANCEFIELD_ANTIALIASING");
60 m_distanceFieldAntialiasingDecided = true;
61 if (mode == "subpixel")
62 m_distanceFieldAntialiasing = QSGGlyphNode::HighQualitySubPixelAntialiasing;
63 else if (mode == "subpixel-lowq")
64 m_distanceFieldAntialiasing = QSGGlyphNode::LowQualitySubPixelAntialiasing;
65 else if (mode == "gray")
66 m_distanceFieldAntialiasing = QSGGlyphNode::GrayAntialiasing;
67 }
68
69 // Adds compatibility with Qt 5.3 and earlier's QSG_RENDER_TIMING
70 if (qEnvironmentVariableIsSet(varName: "QSG_RENDER_TIMING")) {
71 const_cast<QLoggingCategory &>(QSG_LOG_TIME_GLYPH()).setEnabled(type: QtDebugMsg, enable: true);
72 const_cast<QLoggingCategory &>(QSG_LOG_TIME_TEXTURE()).setEnabled(type: QtDebugMsg, enable: true);
73 const_cast<QLoggingCategory &>(QSG_LOG_TIME_RENDERER()).setEnabled(type: QtDebugMsg, enable: true);
74 const_cast<QLoggingCategory &>(QSG_LOG_TIME_RENDERLOOP()).setEnabled(type: QtDebugMsg, enable: true);
75 const_cast<QLoggingCategory &>(QSG_LOG_TIME_COMPILATION()).setEnabled(type: QtDebugMsg, enable: true);
76 }
77}
78
79QSGDefaultContext::~QSGDefaultContext()
80{
81
82}
83
84void QSGDefaultContext::renderContextInitialized(QSGRenderContext *renderContext)
85{
86 m_mutex.lock();
87
88 auto rc = static_cast<const QSGDefaultRenderContext *>(renderContext);
89 if (m_antialiasingMethod == UndecidedAntialiasing) {
90 if (Q_UNLIKELY(qEnvironmentVariableIsSet("QSG_ANTIALIASING_METHOD"))) {
91 const QByteArray aaType = qgetenv(varName: "QSG_ANTIALIASING_METHOD");
92 if (aaType == "msaa")
93 m_antialiasingMethod = MsaaAntialiasing;
94 else if (aaType == "vertex")
95 m_antialiasingMethod = VertexAntialiasing;
96 }
97 if (m_antialiasingMethod == UndecidedAntialiasing)
98 m_antialiasingMethod = rc->msaaSampleCount() > 1 ? MsaaAntialiasing : VertexAntialiasing;
99 }
100
101#if QT_CONFIG(opengl)
102 // With OpenGL ES, use GrayAntialiasing, unless
103 // some value had been requested explicitly. This could not be decided
104 // before without a context. Now the context is ready.
105 if (!m_distanceFieldAntialiasingDecided) {
106 m_distanceFieldAntialiasingDecided = true;
107 Q_ASSERT(rc->rhi());
108 if (rc->rhi()->backend() == QRhi::OpenGLES2
109 && static_cast<const QRhiGles2NativeHandles *>(rc->rhi()->nativeHandles())->context->isOpenGLES())
110 {
111 m_distanceFieldAntialiasing = QSGGlyphNode::GrayAntialiasing;
112 }
113 }
114#endif
115
116 m_mutex.unlock();
117}
118
119void QSGDefaultContext::renderContextInvalidated(QSGRenderContext *)
120{
121}
122
123QSGRenderContext *QSGDefaultContext::createRenderContext()
124{
125 return new QSGDefaultRenderContext(this);
126}
127
128QSGInternalRectangleNode *QSGDefaultContext::createInternalRectangleNode()
129{
130 return m_antialiasingMethod == MsaaAntialiasing
131 ? new QSGMultisampleAntialiasing::RectangleNode
132 : new QSGDefaultInternalRectangleNode;
133}
134
135QSGInternalImageNode *QSGDefaultContext::createInternalImageNode(QSGRenderContext *renderContext)
136{
137 return m_antialiasingMethod == MsaaAntialiasing
138 ? new QSGMultisampleAntialiasing::ImageNode(static_cast<QSGDefaultRenderContext *>(renderContext))
139 : new QSGDefaultInternalImageNode(static_cast<QSGDefaultRenderContext *>(renderContext));
140}
141
142QSGPainterNode *QSGDefaultContext::createPainterNode(QQuickPaintedItem *item)
143{
144 return new QSGDefaultPainterNode(item);
145}
146
147QSGGlyphNode *QSGDefaultContext::createGlyphNode(QSGRenderContext *rc,
148 bool preferNativeGlyphNode,
149 int renderTypeQuality)
150{
151 if (m_distanceFieldDisabled || preferNativeGlyphNode) {
152 return new QSGDefaultGlyphNode(rc);
153 } else {
154 QSGDistanceFieldGlyphNode *node = new QSGDistanceFieldGlyphNode(rc);
155 node->setPreferredAntialiasingMode(m_distanceFieldAntialiasing);
156 node->setRenderTypeQuality(renderTypeQuality);
157 return node;
158 }
159}
160
161QSGLayer *QSGDefaultContext::createLayer(QSGRenderContext *renderContext)
162{
163 return new QSGRhiLayer(renderContext);
164}
165
166QSurfaceFormat QSGDefaultContext::defaultSurfaceFormat() const
167{
168 QSurfaceFormat format = QSurfaceFormat::defaultFormat();
169 // These depend solely on the env.vars., not QQuickGraphicsConfiguration
170 // since that does not have a flag that maps 100% to QSG_NO_xx_BUFFER.
171 static bool useDepth = qEnvironmentVariableIsEmpty(varName: "QSG_NO_DEPTH_BUFFER");
172 static bool useStencil = qEnvironmentVariableIsEmpty(varName: "QSG_NO_STENCIL_BUFFER");
173 static bool enableDebug = qEnvironmentVariableIsSet(varName: "QSG_OPENGL_DEBUG");
174 static bool disableVSync = qEnvironmentVariableIsSet(varName: "QSG_NO_VSYNC");
175 if (useDepth && format.depthBufferSize() == -1)
176 format.setDepthBufferSize(24);
177 else if (!useDepth)
178 format.setDepthBufferSize(0);
179 if (useStencil && format.stencilBufferSize() == -1)
180 format.setStencilBufferSize(8);
181 else if (!useStencil)
182 format.setStencilBufferSize(0);
183 if (enableDebug)
184 format.setOption(option: QSurfaceFormat::DebugContext);
185 if (QQuickWindow::hasDefaultAlphaBuffer())
186 format.setAlphaBufferSize(8);
187 format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
188 if (disableVSync) // swapInterval defaults to 1, it has no -1 special value
189 format.setSwapInterval(0);
190 return format;
191}
192
193void QSGDefaultContext::setDistanceFieldEnabled(bool enabled)
194{
195 m_distanceFieldDisabled = !enabled;
196}
197
198bool QSGDefaultContext::isDistanceFieldEnabled() const
199{
200 return !m_distanceFieldDisabled;
201}
202
203QSGRendererInterface *QSGDefaultContext::rendererInterface(QSGRenderContext *renderContext)
204{
205 Q_UNUSED(renderContext);
206 return this;
207}
208
209QSGRectangleNode *QSGDefaultContext::createRectangleNode()
210{
211 return new QSGDefaultRectangleNode;
212}
213
214QSGImageNode *QSGDefaultContext::createImageNode()
215{
216 return new QSGDefaultImageNode;
217}
218
219QSGNinePatchNode *QSGDefaultContext::createNinePatchNode()
220{
221 return new QSGDefaultNinePatchNode;
222}
223
224#if QT_CONFIG(quick_sprite)
225QSGSpriteNode *QSGDefaultContext::createSpriteNode()
226{
227 return new QSGDefaultSpriteNode;
228}
229#endif
230
231QSGGuiThreadShaderEffectManager *QSGDefaultContext::createGuiThreadShaderEffectManager()
232{
233 return new QSGRhiGuiThreadShaderEffectManager;
234}
235
236QSGShaderEffectNode *QSGDefaultContext::createShaderEffectNode(QSGRenderContext *renderContext)
237{
238 return new QSGRhiShaderEffectNode(static_cast<QSGDefaultRenderContext *>(renderContext));
239}
240
241QSGRendererInterface::GraphicsApi QSGDefaultContext::graphicsApi() const
242{
243 return QSGRhiSupport::instance()->graphicsApi();
244}
245
246void *QSGDefaultContext::getResource(QQuickWindow *window, Resource resource) const
247{
248 if (!window)
249 return nullptr;
250
251 // Unlike the graphicsApi and shaderType and similar queries, getting a
252 // native resource is only possible when there is an initialized
253 // rendercontext, or rather, only within rendering a frame, as per
254 // QSGRendererInterface docs. This is good since getting some things is
255 // only possible within a beginFrame - endFrame with the RHI.
256
257 const QSGDefaultRenderContext *rc = static_cast<const QSGDefaultRenderContext *>(
258 QQuickWindowPrivate::get(c: window)->context);
259 QSGRhiSupport *rhiSupport = QSGRhiSupport::instance();
260
261#if QT_CONFIG(vulkan)
262 if (resource == VulkanInstanceResource)
263 return window->vulkanInstance();
264#endif
265 return const_cast<void *>(rhiSupport->rifResource(res: resource, rc, w: window));
266}
267
268QSGRendererInterface::ShaderType QSGDefaultContext::shaderType() const
269{
270 return RhiShader;
271}
272
273QSGRendererInterface::ShaderCompilationTypes QSGDefaultContext::shaderCompilationType() const
274{
275 return OfflineCompilation;
276}
277
278QSGRendererInterface::ShaderSourceTypes QSGDefaultContext::shaderSourceType() const
279{
280 return ShaderSourceFile;
281}
282
283QT_END_NAMESPACE
284
285static void initResources()
286{
287 Q_INIT_RESOURCE(scenegraph_shaders);
288}
289
290Q_CONSTRUCTOR_FUNCTION(initResources)
291

source code of qtdeclarative/src/quick/scenegraph/qsgdefaultcontext.cpp