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

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

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