1 | // Copyright (C) 2020 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 "qquickgraphicsdevice_p.h" |
5 | |
6 | QT_BEGIN_NAMESPACE |
7 | |
8 | /*! |
9 | \class QQuickGraphicsDevice |
10 | \since 6.0 |
11 | \inmodule QtQuick |
12 | |
13 | \brief The QQuickGraphicsDevice class provides an opaque container for |
14 | native graphics objects representing graphics devices or contexts. |
15 | |
16 | \sa QQuickWindow::setGraphicsDevice(), QQuickRenderTarget |
17 | */ |
18 | |
19 | /*! |
20 | Constructs a default QQuickGraphicsDevice that does not reference any native |
21 | objects. |
22 | */ |
23 | QQuickGraphicsDevice::QQuickGraphicsDevice() |
24 | : d(new QQuickGraphicsDevicePrivate) |
25 | { |
26 | } |
27 | |
28 | /*! |
29 | \internal |
30 | */ |
31 | void QQuickGraphicsDevice::detach() |
32 | { |
33 | qAtomicDetach(d); |
34 | } |
35 | |
36 | /*! |
37 | \internal |
38 | */ |
39 | QQuickGraphicsDevice::QQuickGraphicsDevice(const QQuickGraphicsDevice &other) |
40 | : d(other.d) |
41 | { |
42 | d->ref.ref(); |
43 | } |
44 | |
45 | /*! |
46 | \internal |
47 | */ |
48 | QQuickGraphicsDevice &QQuickGraphicsDevice::operator=(const QQuickGraphicsDevice &other) |
49 | { |
50 | qAtomicAssign(d, x: other.d); |
51 | return *this; |
52 | } |
53 | |
54 | /*! |
55 | Destructor. |
56 | */ |
57 | QQuickGraphicsDevice::~QQuickGraphicsDevice() |
58 | { |
59 | if (!d->ref.deref()) |
60 | delete d; |
61 | } |
62 | |
63 | /*! |
64 | \return true if this is a default constructed graphics device that |
65 | does not reference any native objects. |
66 | */ |
67 | bool QQuickGraphicsDevice::isNull() const |
68 | { |
69 | return d->type == QQuickGraphicsDevicePrivate::Type::Null; |
70 | } |
71 | |
72 | /*! |
73 | \return a new QQuickGraphicsDevice referencing an existing OpenGL \a context. |
74 | |
75 | This factory function is suitable for OpenGL. |
76 | |
77 | \note It is up the caller to ensure that \a context is going to be |
78 | compatible and usable with the QQuickWindow. Platform-specific mismatches in |
79 | the associated QSurfaceFormat, or threading issues due to attempting to use |
80 | \a context on multiple threads are up to the caller to avoid. |
81 | */ |
82 | #if QT_CONFIG(opengl) || defined(Q_QDOC) |
83 | QQuickGraphicsDevice QQuickGraphicsDevice::fromOpenGLContext(QOpenGLContext *context) |
84 | { |
85 | QQuickGraphicsDevice dev; |
86 | QQuickGraphicsDevicePrivate *d = QQuickGraphicsDevicePrivate::get(p: &dev); |
87 | d->type = QQuickGraphicsDevicePrivate::Type::OpenGLContext; |
88 | d->u.context = context; |
89 | return dev; |
90 | } |
91 | #endif |
92 | |
93 | /*! |
94 | \return a new QQuickGraphicsDevice describing a DXGI adapter and D3D feature level. |
95 | |
96 | This factory function is suitable for Direct3D 11 and 12, particularly in |
97 | combination with OpenXR. \a adapterLuidLow and \a adapterLuidHigh together |
98 | specify a LUID, while a featureLevel specifies a \c{D3D_FEATURE_LEVEL_} |
99 | value. \a featureLevel can be set to 0 if it is not intended to be |
100 | specified, in which case the scene graph's defaults will be used. |
101 | |
102 | \note With Direct 3D 12 \a featureLevel specifies the \c minimum feature |
103 | level passed on to D3D12CreateDevice(). |
104 | */ |
105 | #if defined(Q_OS_WIN) || defined(Q_QDOC) |
106 | QQuickGraphicsDevice QQuickGraphicsDevice::fromAdapter(quint32 adapterLuidLow, |
107 | qint32 adapterLuidHigh, |
108 | int featureLevel) |
109 | { |
110 | QQuickGraphicsDevice dev; |
111 | QQuickGraphicsDevicePrivate *d = QQuickGraphicsDevicePrivate::get(&dev); |
112 | d->type = QQuickGraphicsDevicePrivate::Type::Adapter; |
113 | d->u.adapter = { adapterLuidLow, adapterLuidHigh, featureLevel }; |
114 | return dev; |
115 | } |
116 | #endif |
117 | |
118 | /*! |
119 | \return a new QQuickGraphicsDevice referencing a native device and context |
120 | object. |
121 | |
122 | This factory function is suitable for Direct3D 11. \a device is expected to |
123 | be a \c{ID3D11Device*}, \a context is expected to be a |
124 | \c{ID3D11DeviceContext*}. |
125 | |
126 | It also supports Direct 3D 12, if that is the 3D API used at run time. With |
127 | D3D12 \a context is unused and can be set to null. \a device is expected to |
128 | be a \c{ID3D12Device*}. |
129 | |
130 | \note the resulting QQuickGraphicsDevice does not own any native resources, |
131 | it merely contains references. It is the caller's responsibility to ensure |
132 | that the native resource exists as long as necessary. |
133 | */ |
134 | #if defined(Q_OS_WIN) || defined(Q_QDOC) |
135 | QQuickGraphicsDevice QQuickGraphicsDevice::fromDeviceAndContext(void *device, void *context) |
136 | { |
137 | QQuickGraphicsDevice dev; |
138 | QQuickGraphicsDevicePrivate *d = QQuickGraphicsDevicePrivate::get(&dev); |
139 | d->type = QQuickGraphicsDevicePrivate::Type::DeviceAndContext; |
140 | d->u.deviceAndContext = { device, context }; |
141 | return dev; |
142 | } |
143 | #endif |
144 | |
145 | /*! |
146 | \return a new QQuickGraphicsDevice referencing an existing \a device and |
147 | \a commandQueue object. |
148 | |
149 | This factory function is suitable for Metal. |
150 | |
151 | \note the resulting QQuickGraphicsDevice does not own any native resources, |
152 | it merely contains references. It is the caller's responsibility to ensure |
153 | that the native resource exists as long as necessary. |
154 | |
155 | */ |
156 | #if defined(Q_OS_MACOS) || defined(Q_OS_IOS) || defined(Q_QDOC) |
157 | QQuickGraphicsDevice QQuickGraphicsDevice::fromDeviceAndCommandQueue(MTLDevice *device, |
158 | MTLCommandQueue *commandQueue) |
159 | { |
160 | QQuickGraphicsDevice dev; |
161 | QQuickGraphicsDevicePrivate *d = QQuickGraphicsDevicePrivate::get(&dev); |
162 | d->type = QQuickGraphicsDevicePrivate::Type::DeviceAndCommandQueue; |
163 | d->u.deviceAndCommandQueue = { device, commandQueue }; |
164 | return dev; |
165 | } |
166 | #endif |
167 | |
168 | /*! |
169 | \return a new QQuickGraphicsDevice referencing an existing \a physicalDevice. |
170 | |
171 | This factory function is suitable for Vulkan, particularly in combination |
172 | with OpenXR. |
173 | |
174 | \note the resulting QQuickGraphicsDevice does not own any native resources, |
175 | it merely contains references. It is the caller's responsibility to ensure |
176 | that the native resource exists as long as necessary. |
177 | */ |
178 | #if QT_CONFIG(vulkan) || defined(Q_QDOC) |
179 | QQuickGraphicsDevice QQuickGraphicsDevice::fromPhysicalDevice(VkPhysicalDevice physicalDevice) |
180 | { |
181 | QQuickGraphicsDevice dev; |
182 | QQuickGraphicsDevicePrivate *d = QQuickGraphicsDevicePrivate::get(p: &dev); |
183 | d->type = QQuickGraphicsDevicePrivate::Type::PhysicalDevice; |
184 | d->u.physicalDevice = { .physicalDevice: physicalDevice }; |
185 | return dev; |
186 | } |
187 | #endif |
188 | |
189 | /*! |
190 | \return a new QQuickGraphicsDevice referencing an existing \a device object. |
191 | |
192 | This factory function is suitable for Vulkan. \a physicalDevice, \a device |
193 | and \a queueFamilyIndex must always be provided. \a queueIndex is optional |
194 | since the default value of 0 is often suitable. |
195 | |
196 | \note the resulting QQuickGraphicsDevice does not own any native resources, |
197 | it merely contains references. It is the caller's responsibility to ensure |
198 | that the native resource exists as long as necessary. |
199 | */ |
200 | #if QT_CONFIG(vulkan) || defined(Q_QDOC) |
201 | QQuickGraphicsDevice QQuickGraphicsDevice::fromDeviceObjects(VkPhysicalDevice physicalDevice, |
202 | VkDevice device, |
203 | int queueFamilyIndex, |
204 | int queueIndex) |
205 | { |
206 | QQuickGraphicsDevice dev; |
207 | QQuickGraphicsDevicePrivate *d = QQuickGraphicsDevicePrivate::get(p: &dev); |
208 | d->type = QQuickGraphicsDevicePrivate::Type::DeviceObjects; |
209 | d->u.deviceObjects = { .physicalDevice: physicalDevice, .device: device, .queueFamilyIndex: queueFamilyIndex, .queueIndex: queueIndex }; |
210 | return dev; |
211 | } |
212 | #endif |
213 | |
214 | /*! |
215 | \return a new QQuickGraphicsDevice referencing an existing \a rhi object. |
216 | |
217 | \note Similarly to fromOpenGLContext(), the caller must be careful to only |
218 | share a QRhi (and so the underlying graphics context or device) between |
219 | QQuickWindows that are known to be compatible, not breaking the underlying |
220 | graphics API's rules when it comes to threading, pixel formats, etc. |
221 | |
222 | \since 6.6 |
223 | */ |
224 | QQuickGraphicsDevice QQuickGraphicsDevice::fromRhi(QRhi *rhi) |
225 | { |
226 | QQuickGraphicsDevice dev; |
227 | QQuickGraphicsDevicePrivate *d = QQuickGraphicsDevicePrivate::get(p: &dev); |
228 | d->type = QQuickGraphicsDevicePrivate::Type::Rhi; |
229 | d->u.rhi = rhi; |
230 | return dev; |
231 | } |
232 | |
233 | QQuickGraphicsDevicePrivate::QQuickGraphicsDevicePrivate() |
234 | : ref(1) |
235 | { |
236 | } |
237 | |
238 | QQuickGraphicsDevicePrivate::QQuickGraphicsDevicePrivate(const QQuickGraphicsDevicePrivate *other) |
239 | : ref(1), |
240 | type(other->type), |
241 | u(other->u) |
242 | { |
243 | } |
244 | |
245 | QT_END_NAMESPACE |
246 | |