Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qsgcontextplugin.cpp
Go to the documentation of this file.
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// Qt-Security score:significant reason:default
4
6#include <QtQuick/private/qsgcontext_p.h>
7#include <QtGui/qguiapplication.h>
8#include <QtCore/private/qfactoryloader_p.h>
9#include <QtCore/qlibraryinfo.h>
10
11// Built-in adaptations
12#include <QtQuick/private/qsgsoftwareadaptation_p.h>
13#include <QtQuick/private/qsgdefaultcontext_p.h>
14
15#include <QtGui/private/qguiapplication_p.h>
16#include <QtGui/qpa/qplatformintegration.h>
17
19
20QSGContextPlugin::QSGContextPlugin(QObject *parent)
21 : QObject(parent)
22{
23}
24
25QSGContextPlugin::~QSGContextPlugin()
26{
27}
28
29#if QT_CONFIG(library)
30Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
31 (QSGContextFactoryInterface_iid, QLatin1String("/scenegraph")))
32#endif
33
49
51{
52 // Fill in the table with the built-in adaptations.
53 builtIns.append(new QSGSoftwareAdaptation);
54}
55
57{
58 qDeleteAll(builtIns);
59}
60
61Q_GLOBAL_STATIC(QSGAdaptationBackendData, qsg_adaptation_data)
62
63// This only works when the backend is loaded (contextFactory() was called),
64// otherwise the return value is 0.
65//
66// Note that the default (OpenGL) implementation always results in 0, custom flags
67// can only be returned from the other (either compiled-in or plugin-based) backends.
68QSGContextFactoryInterface::Flags qsg_backend_flags()
69{
70 return qsg_adaptation_data()->flags;
71}
72
73QSGAdaptationBackendData *contextFactory()
74{
75 QSGAdaptationBackendData *backendData = qsg_adaptation_data();
76
77 if (!backendData->tried) {
78 backendData->tried = true;
79
80 const QStringList args = QGuiApplication::arguments();
81 QString requestedBackend = backendData->quickWindowBackendRequest; // empty or set via QQuickWindow::setSceneGraphBackend()
82
83 for (int index = 0; index < args.size(); ++index) {
84 if (args.at(index).startsWith(QLatin1String("--device="))) {
85 requestedBackend = args.at(index).mid(9);
86 break;
87 }
88 }
89
90 if (requestedBackend.isEmpty())
91 requestedBackend = qEnvironmentVariable("QMLSCENE_DEVICE");
92
93 // A modern alternative. Scenegraph adaptations can represent backends
94 // for different graphics APIs as well, instead of being specific to
95 // some device or platform.
96 if (requestedBackend.isEmpty())
97 requestedBackend = qEnvironmentVariable("QT_QUICK_BACKEND");
98
99 // If this platform does not support OpenGL, Vulkan, D3D11, or Metal, and no
100 // backend has been set, default to the software renderer. We rely on the
101 // static, build time flags only. This is to prevent the inevitable confusion
102 // caused by run time hocus pocus. If one wants to use the software backend
103 // in a GL or Vulkan capable Qt build (or on Windows or Apple platforms), it
104 // has to be requested explicitly.
105#if !QT_CONFIG(opengl) && !QT_CONFIG(vulkan) && !QT_CONFIG(metal) && !defined(Q_OS_WIN)
106 if (requestedBackend.isEmpty())
107 requestedBackend = QLatin1String("software");
108#endif
109
110 // As an exception to the above, play nice with platform plugins like
111 // vnc or linuxfb: Trying to initialize a QRhi is futile on these, and
112 // Qt 5 had an explicit fallback to the software backend, based on the
113 // OpenGL capability. Replicate that behavior using the new
114 // RhiBasedRendering capability flag, which, on certain platforms,
115 // indicates that we should not even bother trying to initialize a QRhi
116 // as no 3D API can be expected work.
117 if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RhiBasedRendering)) {
118 if (requestedBackend.isEmpty())
119 requestedBackend = QLatin1String("software");
120 }
121
122 // This is handy if some of the logic above goes wrong and we select
123 // e.g. the software backend when it is not desired.
124 if (requestedBackend == QLatin1String("rhi"))
125 requestedBackend.clear(); // empty = no custom backend to load
126
127 if (!requestedBackend.isEmpty()) {
128 qCDebug(QSG_LOG_INFO, "Loading backend %s", qUtf8Printable(requestedBackend));
129
130 // First look for a built-in adaptation.
131 for (QSGContextFactoryInterface *builtInBackend : std::as_const(backendData->builtIns)) {
132 if (builtInBackend->keys().contains(requestedBackend)) {
133 backendData->factory = builtInBackend;
134 backendData->name = requestedBackend;
135 backendData->flags = backendData->factory->flags(requestedBackend);
136 break;
137 }
138 }
139
140#if QT_CONFIG(library)
141 // Then try the plugins.
142 if (!backendData->factory) {
143 const int index = loader()->indexOf(requestedBackend);
144 if (index != -1)
145 backendData->factory = qobject_cast<QSGContextFactoryInterface*>(loader()->instance(index));
146 if (backendData->factory) {
147 backendData->name = requestedBackend;
148 backendData->flags = backendData->factory->flags(requestedBackend);
149 }
150 if (!backendData->factory) {
151 qWarning("Could not create scene graph context for backend '%s'"
152 " - check that plugins are installed correctly in %s",
153 qPrintable(requestedBackend),
154 qPrintable(QLibraryInfo::path(QLibraryInfo::PluginsPath)));
155 }
156 }
157#endif // library
158 }
159 }
160
161 return backendData;
162}
163
164
165
166/*!
167 \fn QSGContext *QSGContext::createDefaultContext()
168
169 Creates a default scene graph context for the current hardware.
170 This may load a device-specific plugin.
171*/
172QSGContext *QSGContext::createDefaultContext()
173{
174 QSGAdaptationBackendData *backendData = contextFactory();
175 if (backendData->factory)
176 return backendData->factory->create(backendData->name);
177 return new QSGDefaultContext();
178}
179
180
181
182/*!
183 Calls into the scene graph adaptation if available and creates a texture
184 factory. The primary purpose of this function is to reimplement hardware
185 specific asynchronous texture frameskip-less uploads that can happen on
186 the image providers thread.
187 */
188
189QQuickTextureFactory *QSGContext::createTextureFactoryFromImage(const QImage &image)
190{
191 QSGAdaptationBackendData *backendData = contextFactory();
192 if (backendData->factory)
193 return backendData->factory->createTextureFactoryFromImage(image);
194 return nullptr;
195}
196
197
198/*!
199 Calls into the scene graph adaptation if available and creates a hardware
200 specific window manager.
201 */
202
203QSGRenderLoop *QSGContext::createWindowManager()
204{
205 QSGAdaptationBackendData *backendData = contextFactory();
206 if (backendData->factory)
207 return backendData->factory->createWindowManager();
208 return nullptr;
209}
210
211void QSGContext::setBackend(const QString &backend)
212{
213 QSGAdaptationBackendData *backendData = qsg_adaptation_data();
214 if (backendData->tried)
215 qWarning("Scenegraph already initialized, setBackend() request ignored");
216
217 backendData->quickWindowBackendRequest = backend;
218}
219
220QString QSGContext::backend()
221{
222 QSGAdaptationBackendData *backendData = qsg_adaptation_data();
223 if (backendData->tried)
224 return backendData->name;
225
226 return backendData->quickWindowBackendRequest;
227}
228
229QT_END_NAMESPACE
230
231#include "moc_qsgcontextplugin_p.cpp"
Combined button and popup list for selecting options.
QSGContextFactoryInterface * factory
QList< QSGContextFactoryInterface * > builtIns