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
qsgtexture.cpp
Go to the documentation of this file.
1// Copyright (C) 2019 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
5#include "qsgtexture_p.h"
7#include <private/qqmlglobal_p.h>
8#include <private/qsgmaterialshader_p.h>
9#include <private/qsgrenderer_p.h>
10#include <private/qquickitem_p.h> // qquickwindow_p.h cannot be included on its own due to template nonsense
11#include <private/qquickwindow_p.h>
12#include <QtCore/private/qnativeinterface_p.h>
13#include <rhi/qrhi.h>
14
15#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && defined(__GLIBC__)
16#define CAN_BACKTRACE_EXECINFO
17#endif
18
19#if defined(Q_OS_APPLE)
20#define CAN_BACKTRACE_EXECINFO
21#endif
22
23#if defined(QT_NO_DEBUG)
24#undef CAN_BACKTRACE_EXECINFO
25#endif
26
27#if defined(CAN_BACKTRACE_EXECINFO)
28#include <execinfo.h>
29#include <QHash>
30#endif
31
32#ifndef QT_NO_DEBUG
33Q_GLOBAL_STATIC(QSet<QSGTexture *>, qsg_valid_texture_set)
34Q_GLOBAL_STATIC(QMutex, qsg_valid_texture_mutex)
35#endif
36
37QT_BEGIN_NAMESPACE
38
39bool operator==(const QSGSamplerDescription &a, const QSGSamplerDescription &b) noexcept
40{
41 return a.filtering == b.filtering
42 && a.mipmapFiltering == b.mipmapFiltering
43 && a.horizontalWrap == b.horizontalWrap
44 && a.verticalWrap == b.verticalWrap
45 && a.anisotropylevel == b.anisotropylevel;
46}
47
48bool operator!=(const QSGSamplerDescription &a, const QSGSamplerDescription &b) noexcept
49{
50 return !(a == b);
51}
52
53size_t qHash(const QSGSamplerDescription &s, size_t seed) noexcept
54{
55 const int f = s.filtering;
56 const int m = s.mipmapFiltering;
57 const int w = s.horizontalWrap;
58 const int a = s.anisotropylevel;
59 return (((f & 7) << 24) | ((m & 7) << 16) | ((w & 7) << 8) | (a & 7)) ^ seed;
60}
61
62QSGSamplerDescription QSGSamplerDescription::fromTexture(QSGTexture *t)
63{
64 QSGSamplerDescription s;
65 s.filtering = t->filtering();
66 s.mipmapFiltering = t->mipmapFiltering();
67 s.horizontalWrap = t->horizontalWrapMode();
68 s.verticalWrap = t->verticalWrapMode();
69 s.anisotropylevel = t->anisotropyLevel();
70 return s;
71}
72
73QSGTexturePrivate::QSGTexturePrivate(QSGTexture *t)
74 : wrapChanged(false)
75 , filteringChanged(false)
76 , anisotropyChanged(false)
77 , horizontalWrap(QSGTexture::ClampToEdge)
78 , verticalWrap(QSGTexture::ClampToEdge)
79 , mipmapMode(QSGTexture::None)
80 , filterMode(QSGTexture::Nearest)
81 , anisotropyLevel(QSGTexture::AnisotropyNone)
82#if QT_CONFIG(opengl)
83 , m_openglTextureAccessor(t)
84#endif
85#ifdef Q_OS_WIN
86 , m_d3d11TextureAccessor(t)
87 , m_d3d12TextureAccessor(t)
88#endif
89#if QT_CONFIG(metal)
90 , m_metalTextureAccessor(t)
91#endif
92#if QT_CONFIG(vulkan)
93 , m_vulkanTextureAccessor(t)
94#endif
95{
96#if !QT_CONFIG(opengl)
97 Q_UNUSED(t);
98#endif
99}
100
101#ifndef QT_NO_DEBUG
102
103static int qt_debug_texture_count = 0;
104
105#if (defined(Q_OS_LINUX) || defined (Q_OS_APPLE)) && !defined(Q_OS_ANDROID)
106DEFINE_BOOL_CONFIG_OPTION(qmlDebugLeakBacktrace, QML_DEBUG_LEAK_BACKTRACE)
107
108#define BACKTRACE_SIZE 20
109class SGTextureTraceItem
110{
111public:
112 void *backTrace[BACKTRACE_SIZE];
113 size_t backTraceSize;
114};
115
116static QHash<QSGTexture*, SGTextureTraceItem*> qt_debug_allocated_textures;
117#endif
118
120{
121 qCDebug(lcQsgLeak, "Number of leaked textures: %i", qt_debug_texture_count);
122 qt_debug_texture_count = -1;
123
124#if defined(CAN_BACKTRACE_EXECINFO)
125 if (qmlDebugLeakBacktrace()) {
126 while (!qt_debug_allocated_textures.isEmpty()) {
127 QHash<QSGTexture*, SGTextureTraceItem*>::Iterator it = qt_debug_allocated_textures.begin();
128 QSGTexture* texture = it.key();
129 SGTextureTraceItem* item = it.value();
130
131 qt_debug_allocated_textures.erase(it);
132
133 qDebug() << "------";
134 qDebug() << "Leaked" << texture << "backtrace:";
135
136 char** symbols = backtrace_symbols(item->backTrace, item->backTraceSize);
137
138 if (symbols) {
139 for (int i=0; i<(int) item->backTraceSize; i++)
140 qDebug("Backtrace <%02d>: %s", i, symbols[i]);
141 free(symbols);
142 }
143
144 qDebug() << "------";
145
146 delete item;
147 }
148 }
149#endif
150}
151
152inline static void qt_debug_add_texture(QSGTexture* texture)
153{
154#if defined(CAN_BACKTRACE_EXECINFO)
155 if (qmlDebugLeakBacktrace()) {
156 SGTextureTraceItem* item = new SGTextureTraceItem;
157 item->backTraceSize = backtrace(item->backTrace, BACKTRACE_SIZE);
158 qt_debug_allocated_textures.insert(texture, item);
159 }
160#else
161 Q_UNUSED(texture);
162#endif // Q_OS_LINUX
163
164 ++qt_debug_texture_count;
165
166 static bool atexit_registered = false;
167 if (!atexit_registered) {
168 atexit(qt_debug_print_texture_count);
169 atexit_registered = true;
170 }
171}
172
173static void qt_debug_remove_texture(QSGTexture* texture)
174{
175#if defined(CAN_BACKTRACE_EXECINFO)
176 if (qmlDebugLeakBacktrace()) {
177 SGTextureTraceItem* item = qt_debug_allocated_textures.value(texture, 0);
178 if (item) {
179 qt_debug_allocated_textures.remove(texture);
180 delete item;
181 }
182 }
183#else
184 Q_UNUSED(texture);
185#endif
186
187 --qt_debug_texture_count;
188
189 if (qt_debug_texture_count < 0)
190 qDebug("Texture destroyed after qt_debug_print_texture_count() was called.");
191}
192
193#endif // QT_NO_DEBUG
194
195/*!
196 \class QSGTexture
197
198 \inmodule QtQuick
199
200 \brief The QSGTexture class is the base class for textures used in
201 the scene graph.
202
203 Users can freely implement their own texture classes to support arbitrary
204 input textures, such as YUV video frames or 8 bit alpha masks. The scene
205 graph provides a default implementation for RGBA textures.The default
206 implementation is not instantiated directly, rather they are constructed
207 via factory functions, such as QQuickWindow::createTextureFromImage().
208
209 With the default implementation, each QSGTexture is backed by a
210 QRhiTexture, which in turn contains a native texture object, such as an
211 OpenGL texture or a Vulkan image.
212
213 The size in pixels is given by textureSize(). hasAlphaChannel() reports if
214 the texture contains opacity values and hasMipmaps() reports if the texture
215 contains mipmap levels.
216
217 \l{QSGMaterial}{Materials} that work with textures reimplement
218 \l{QSGMaterialShader::updateSampledImage()}{updateSampledImage()} to
219 provide logic that decides which QSGTexture's underlying native texture
220 should be exposed at a given shader resource binding point.
221
222 QSGTexture does not separate image (texture) and sampler objects. The
223 parameters for filtering and wrapping can be specified with
224 setMipmapFiltering(), setFiltering(), setHorizontalWrapMode() and
225 setVerticalWrapMode(). The scene graph and Qt's graphics abstraction takes
226 care of creating separate sampler objects, when applicable.
227
228 \section1 Texture Atlases
229
230 Some scene graph backends use texture atlasses, grouping multiple small
231 textures into one large texture. If this is the case, the function
232 isAtlasTexture() will return true. Atlases are used to aid the rendering
233 algorithm to do better sorting which increases performance. Atlases are
234 also essential for batching (merging together geometry to reduce the number
235 of draw calls), because two instances of the same material using two
236 different QSGTextures are not batchable, whereas if both QSGTextures refer
237 to the same atlas, batching can happen, assuming the materials are
238 otherwise compatible.
239
240 The location of the texture inside the atlas is given with the
241 normalizedTextureSubRect() function.
242
243 If the texture is used in such a way that atlas is not preferable, the
244 function removedFromAtlas() can be used to extract a non-atlased copy.
245
246 \note All classes with QSG prefix should be used solely on the scene graph's
247 rendering thread. See \l {Scene Graph and Rendering} for more information.
248 */
249
250/*!
251 \enum QSGTexture::WrapMode
252
253 Specifies how the sampler should treat texture coordinates.
254
255 \value Repeat Only the fractional part of the texture coordinate is
256 used, causing values above 1 and below 0 to repeat.
257
258 \value ClampToEdge Values above 1 are clamped to 1 and values
259 below 0 are clamped to 0.
260
261 \value MirroredRepeat When the texture coordinate is even, only the
262 fractional part is used. When odd, the texture coordinate is set to
263 \c{1 - fractional part}. This value has been introduced in Qt 5.10.
264 */
265
266/*!
267 \enum QSGTexture::Filtering
268
269 Specifies how sampling of texels should filter when texture
270 coordinates are not pixel aligned.
271
272 \value None No filtering should occur. This value is only used
273 together with setMipmapFiltering().
274
275 \value Nearest Sampling returns the nearest texel.
276
277 \value Linear Sampling returns a linear interpolation of the
278 neighboring texels.
279*/
280
281/*!
282 \enum QSGTexture::AnisotropyLevel
283
284 Specifies the anisotropic filtering level to be used when
285 the texture is not screen aligned.
286
287 \value AnisotropyNone No anisotropic filtering.
288
289 \value Anisotropy2x 2x anisotropic filtering.
290
291 \value Anisotropy4x 4x anisotropic filtering.
292
293 \value Anisotropy8x 8x anisotropic filtering.
294
295 \value Anisotropy16x 16x anisotropic filtering.
296
297 \since 5.9
298*/
299
300/*!
301 Constructs the QSGTexture base class.
302 */
303QSGTexture::QSGTexture()
304 : QObject(*(new QSGTexturePrivate(this)))
305{
306#ifndef QT_NO_DEBUG
307 if (lcQsgLeak().isDebugEnabled())
308 qt_debug_add_texture(this);
309
310 QMutexLocker locker(qsg_valid_texture_mutex());
311 qsg_valid_texture_set()->insert(this);
312#endif
313}
314
315/*!
316 \internal
317 */
318QSGTexture::QSGTexture(QSGTexturePrivate &dd)
319 : QObject(dd)
320{
321#ifndef QT_NO_DEBUG
322 if (lcQsgLeak().isDebugEnabled())
323 qt_debug_add_texture(this);
324
325 QMutexLocker locker(qsg_valid_texture_mutex());
326 qsg_valid_texture_set()->insert(this);
327#endif
328}
329
330/*!
331 Destroys the QSGTexture.
332 */
333QSGTexture::~QSGTexture()
334{
335#ifndef QT_NO_DEBUG
336 if (lcQsgLeak().isDebugEnabled())
337 qt_debug_remove_texture(this);
338
339 QMutexLocker locker(qsg_valid_texture_mutex());
340 qsg_valid_texture_set()->remove(this);
341#endif
342}
343
344/*!
345 \fn QRectF QSGTexture::convertToNormalizedSourceRect(const QRectF &rect) const
346
347 Returns \a rect converted to normalized coordinates.
348
349 \sa normalizedTextureSubRect()
350 */
351
352/*!
353 This function returns a copy of the current texture which is removed
354 from its atlas.
355
356 The current texture remains unchanged, so texture coordinates do not
357 need to be updated.
358
359 Removing a texture from an atlas is primarily useful when passing
360 it to a shader that operates on the texture coordinates 0-1 instead
361 of the texture subrect inside the atlas.
362
363 If the texture is not part of a texture atlas, this function returns 0.
364
365 Implementations of this function are recommended to return the same instance
366 for multiple calls to limit memory usage.
367
368 \a resourceUpdates is an optional resource update batch, on which texture
369 operations, if any, are enqueued. Materials can retrieve an instance from
370 QSGMaterialShader::RenderState. When null, the removedFromAtlas()
371 implementation creates its own batch and submit it right away. However,
372 when a valid instance is specified, this function will not submit the
373 update batch.
374
375 \warning This function can only be called from the rendering thread.
376 */
377
378QSGTexture *QSGTexture::removedFromAtlas(QRhiResourceUpdateBatch *resourceUpdates) const
379{
380 Q_UNUSED(resourceUpdates);
381 Q_ASSERT_X(!isAtlasTexture(), "QSGTexture::removedFromAtlas()", "Called on a non-atlas texture");
382 return nullptr;
383}
384
385/*!
386 Returns whether this texture is part of an atlas or not.
387
388 The default implementation returns false.
389 */
390bool QSGTexture::isAtlasTexture() const
391{
392 return false;
393}
394
395/*!
396 \fn qint64 QSGTexture::comparisonKey() const
397
398 Returns a key suitable for comparing textures. Typically used in
399 QSGMaterial::compare() implementations.
400
401 Just comparing QSGTexture pointers is not always sufficient because two
402 QSGTexture instances that refer to the same native texture object
403 underneath should also be considered equal. Hence the need for this function.
404
405 Implementations of this function are not expected to, and should not create
406 any graphics resources (native texture objects) in case there are none yet.
407
408 A QSGTexture that does not have a native texture object underneath is
409 typically \b not equal to any other QSGTexture, so the return value has to
410 be crafted accordingly. There are exceptions to this, in particular when
411 atlasing is used (where multiple textures share the same atlas texture
412 under the hood), that is then up to the subclass implementations to deal
413 with as appropriate.
414
415 \warning This function can only be called from the rendering thread.
416
417 \since 5.14
418 */
419
420/*!
421 \fn QSize QSGTexture::textureSize() const
422
423 Returns the size of the texture in pixels.
424 */
425
426/*!
427 Returns the rectangle inside textureSize() that this texture
428 represents in normalized coordinates.
429
430 The default implementation returns a rect at position (0, 0) with
431 width and height of 1.
432 */
433QRectF QSGTexture::normalizedTextureSubRect() const
434{
435 return QRectF(0, 0, 1, 1);
436}
437
438/*!
439 \fn bool QSGTexture::hasAlphaChannel() const
440
441 Returns true if the texture data contains an alpha channel.
442 */
443
444/*!
445 \fn bool QSGTexture::hasMipmaps() const
446
447 Returns true if the texture data contains mipmap levels.
448 */
449
450
451/*!
452 Sets the mipmap sampling mode to \a filter.
453
454 Setting the mipmap filtering has no effect it the texture does not have mipmaps.
455
456 \sa hasMipmaps()
457 */
458void QSGTexture::setMipmapFiltering(Filtering filter)
459{
460 Q_D(QSGTexture);
461 if (d->mipmapMode != (uint) filter) {
462 d->mipmapMode = filter;
463 d->filteringChanged = true;
464 }
465}
466
467/*!
468 Returns whether mipmapping should be used when sampling from this texture.
469 */
470QSGTexture::Filtering QSGTexture::mipmapFiltering() const
471{
472 return (QSGTexture::Filtering) d_func()->mipmapMode;
473}
474
475
476/*!
477 Sets the sampling mode to \a filter.
478 */
479void QSGTexture::setFiltering(QSGTexture::Filtering filter)
480{
481 Q_D(QSGTexture);
482 if (d->filterMode != (uint) filter) {
483 d->filterMode = filter;
484 d->filteringChanged = true;
485 }
486}
487
488/*!
489 Returns the sampling mode to be used for this texture.
490 */
491QSGTexture::Filtering QSGTexture::filtering() const
492{
493 return (QSGTexture::Filtering) d_func()->filterMode;
494}
495
496/*!
497 Sets the level of anisotropic filtering to \a level. The default value is
498 QSGTexture::AnisotropyNone, which means no anisotropic filtering is
499 enabled.
500
501 \note The request may be ignored depending on the graphics API in use.
502 There is no guarantee anisotropic filtering is supported at run time.
503
504 \since 5.9
505 */
506void QSGTexture::setAnisotropyLevel(AnisotropyLevel level)
507{
508 Q_D(QSGTexture);
509 if (d->anisotropyLevel != (uint) level) {
510 d->anisotropyLevel = level;
511 d->anisotropyChanged = true;
512 }
513}
514
515/*!
516 Returns the anisotropy level in use for filtering this texture.
517
518 \since 5.9
519 */
520QSGTexture::AnisotropyLevel QSGTexture::anisotropyLevel() const
521{
522 return (QSGTexture::AnisotropyLevel) d_func()->anisotropyLevel;
523}
524
525
526
527/*!
528 Sets the horizontal wrap mode to \a hwrap
529 */
530
531void QSGTexture::setHorizontalWrapMode(WrapMode hwrap)
532{
533 Q_D(QSGTexture);
534 if ((uint) hwrap != d->horizontalWrap) {
535 d->horizontalWrap = hwrap;
536 d->wrapChanged = true;
537 }
538}
539
540/*!
541 Returns the horizontal wrap mode to be used for this texture.
542 */
543QSGTexture::WrapMode QSGTexture::horizontalWrapMode() const
544{
545 return (QSGTexture::WrapMode) d_func()->horizontalWrap;
546}
547
548
549
550/*!
551 Sets the vertical wrap mode to \a vwrap
552 */
553void QSGTexture::setVerticalWrapMode(WrapMode vwrap)
554{
555 Q_D(QSGTexture);
556 if ((uint) vwrap != d->verticalWrap) {
557 d->verticalWrap = vwrap;
558 d->wrapChanged = true;
559 }
560}
561
562/*!
563 Returns the vertical wrap mode to be used for this texture.
564 */
565QSGTexture::WrapMode QSGTexture::verticalWrapMode() const
566{
567 return (QSGTexture::WrapMode) d_func()->verticalWrap;
568}
569
570/*!
571 \return the QRhiTexture for this QSGTexture or null if there is none (either
572 because a valid texture has not been created internally yet, or because the
573 concept is not applicable to the scenegraph backend in use).
574
575 This function is not expected to create a new QRhiTexture in case there is
576 none. It should return null in that case. The expectation towards the
577 renderer is that a null texture leads to using a transparent, dummy texture
578 instead.
579
580 \warning This function can only be called from the rendering thread.
581
582 \since 6.0
583 */
584QRhiTexture *QSGTexture::rhiTexture() const
585{
586 return nullptr;
587}
588
589/*!
590 Call this function to enqueue image upload operations to \a
591 resourceUpdates, in case there are any pending ones. When there is no new
592 data (for example, because there was no setImage() since the last call to
593 this function), the function does nothing.
594
595 Materials involving \a rhi textures are expected to call this function from
596 their \l{QSGMaterialShader::updateSampledImage()}{updateSampledImage()}
597 implementation, typically without any conditions, passing \c{state.rhi()}
598 and \c{state.resourceUpdateBatch()} from the QSGMaterialShader::RenderState.
599
600 \warning This function can only be called from the rendering thread.
601
602 \since 6.0
603 */
604void QSGTexture::commitTextureOperations(QRhi *rhi, QRhiResourceUpdateBatch *resourceUpdates)
605{
606 Q_UNUSED(rhi);
607 Q_UNUSED(resourceUpdates);
608}
609
610bool QSGTexturePrivate::hasDirtySamplerOptions() const
611{
612 return wrapChanged || filteringChanged || anisotropyChanged;
613}
614
615void QSGTexturePrivate::resetDirtySamplerOptions()
616{
617 wrapChanged = filteringChanged = anisotropyChanged = false;
618}
619
620/*!
621 \class QSGDynamicTexture
622 \brief The QSGDynamicTexture class serves as a baseclass for dynamically changing textures,
623 such as content that is rendered to FBO's.
624 \inmodule QtQuick
625
626 To update the content of the texture, call updateTexture() explicitly.
627
628 \note All classes with QSG prefix should be used solely on the scene graph's
629 rendering thread. See \l {Scene Graph and Rendering} for more information.
630 */
631
632
633/*!
634 \fn bool QSGDynamicTexture::updateTexture()
635
636 Call this function to explicitly update the dynamic texture.
637
638 The function returns true if the texture was changed as a resul of the update; otherwise
639 returns false.
640
641 \note This function is typically called from QQuickItem::updatePaintNode()
642 or QSGNode::preprocess(), meaning during the \c{synchronization} or the
643 \c{node preprocessing} phases of the scenegraph. Calling it at other times
644 is discouraged and can lead to unexpected behavior.
645 */
646
647/*!
648 \internal
649 */
650QSGDynamicTexture::QSGDynamicTexture(QSGTexturePrivate &dd)
651 : QSGTexture(dd)
652{
653}
654
655/*!
656 \internal
657 */
658QSGDynamicTexture::~QSGDynamicTexture()
659 = default;
660
661/*!
662 \fn template <typename QNativeInterface> NativeInterface *QSGTexture::nativeInterface() const
663
664 Returns a native interface of the given type for the texture.
665
666 This function provides access to platform specific functionality of
667 QSGTexture, as declared in the QNativeInterface namespace:
668
669 \annotatedlist native-interfaces-qsgtexture
670
671 This allows accessing the underlying native texture object, such as, the \c GLuint
672 texture ID with OpenGL, or the \c VkImage handle with Vulkan.
673
674 If the requested interface is not available a \nullptr is returned.
675 */
676
677
678#if QT_CONFIG(opengl) || defined(Q_QDOC)
679namespace QNativeInterface {
680/*!
681 \class QNativeInterface::QSGOpenGLTexture
682 \inmodule QtQuick
683 \ingroup native-interfaces
684 \ingroup native-interfaces-qsgtexture
685 \inheaderfile QSGTexture
686 \brief Provides access to and enables adopting OpenGL texture objects.
687 \since 6.0
688*/
689
690/*!
691 \fn VkImage QNativeInterface::QSGOpenGLTexture::nativeTexture() const
692 \return the OpenGL texture ID.
693 */
694
695QT_DEFINE_NATIVE_INTERFACE(QSGOpenGLTexture);
696
697/*!
698 Creates a new QSGTexture wrapping an existing OpenGL texture object for
699 \a window.
700
701 The native object specified in \a textureId is wrapped, but not owned, by
702 the resulting QSGTexture. The caller of the function is responsible for
703 deleting the returned QSGTexture, but that will not destroy the underlying
704 native object.
705
706 This function is currently suitable for 2D RGBA textures only.
707
708 \warning This function will return null if the scenegraph has not yet been
709 initialized.
710
711 Use \a options to customize the texture attributes. Only the
712 TextureHasAlphaChannel and TextureHasMipmaps are taken into account here.
713
714 \a size specifies the size in pixels.
715
716 \note This function must be called on the scenegraph rendering thread.
717
718 \sa QQuickWindow::sceneGraphInitialized(), QSGTexture,
719 {Scene Graph - Metal Texture Import}, {Scene Graph - Vulkan Texture Import}
720
721 \since 6.0
722 */
723QSGTexture *QSGOpenGLTexture::fromNative(GLuint textureId,
724 QQuickWindow *window,
725 const QSize &size,
726 QQuickWindow::CreateTextureOptions options)
727{
728 return QQuickWindowPrivate::get(window)->createTextureFromNativeTexture(quint64(textureId), 0, size, options);
729}
730
731/*!
732 Creates a new QSGTexture wrapping an existing OpenGL ES texture object for
733 \a window.
734
735 The native object specified in \a textureId is wrapped, but not owned, by
736 the resulting QSGTexture. The caller of the function is responsible for
737 deleting the returned QSGTexture, but that will not destroy the underlying
738 native object.
739
740 This function is suitable only for textures that are meant to be
741 used with the \c{GL_TEXTURE_EXTERNAL_OES} target: usually textures
742 to which another device (such as a camera) writes data.
743
744 \warning This function will return null if the scenegraph has not yet been
745 initialized.
746
747 Use \a options to customize the texture attributes. Only the
748 TextureHasAlphaChannel and TextureHasMipmaps are taken into account here.
749
750 \a size specifies the size in pixels.
751
752 \note This function must be called on the scenegraph rendering thread.
753
754 \since 6.1
755
756 \sa fromNative()
757 */
758QSGTexture *QSGOpenGLTexture::fromNativeExternalOES(GLuint textureId,
759 QQuickWindow *window,
760 const QSize &size,
761 QQuickWindow::CreateTextureOptions options)
762{
763 return QQuickWindowPrivate::get(window)->createTextureFromNativeTexture(quint64(textureId),
764 0,
765 size,
766 options,
767 QQuickWindowPrivate::NativeTextureIsExternalOES);
768}
769} // QNativeInterface
770
771GLuint QSGTexturePlatformOpenGL::nativeTexture() const
772{
773 if (auto *tex = m_texture->rhiTexture())
774 return GLuint(tex->nativeTexture().object);
775 return 0;
776}
777#endif // opengl
778
779#if defined(Q_OS_WIN) || defined(Q_QDOC)
780namespace QNativeInterface {
781/*!
782 \class QNativeInterface::QSGD3D11Texture
783 \inmodule QtQuick
784 \ingroup native-interfaces
785 \ingroup native-interfaces-qsgtexture
786 \inheaderfile QSGTexture
787 \brief Provides access to and enables adopting Direct3D 11 texture objects.
788 \since 6.0
789*/
790
791/*!
792 \fn void *QNativeInterface::QSGD3D11Texture::nativeTexture() const
793 \return the ID3D11Texture2D object.
794 */
795
796QT_DEFINE_NATIVE_INTERFACE(QSGD3D11Texture);
797
798/*!
799 Creates a new QSGTexture wrapping an existing Direct 3D 11 \a texture object
800 for \a window.
801
802 The native object is wrapped, but not owned, by the resulting QSGTexture.
803 The caller of the function is responsible for deleting the returned
804 QSGTexture, but that will not destroy the underlying native object.
805
806 This function is currently suitable for 2D RGBA textures only.
807
808 \warning This function will return null if the scene graph has not yet been
809 initialized.
810
811 Use \a options to customize the texture attributes. Only the
812 TextureHasAlphaChannel and TextureHasMipmaps are taken into account here.
813
814 \a size specifies the size in pixels.
815
816 \note This function must be called on the scene graph rendering thread.
817
818 \sa QQuickWindow::sceneGraphInitialized(), QSGTexture,
819 {Scene Graph - Metal Texture Import}, {Scene Graph - Vulkan Texture Import}
820
821 \since 6.0
822 */
823QSGTexture *QSGD3D11Texture::fromNative(void *texture,
824 QQuickWindow *window,
825 const QSize &size,
826 QQuickWindow::CreateTextureOptions options)
827{
828 return QQuickWindowPrivate::get(window)->createTextureFromNativeTexture(quint64(texture), 0, size, options);
829}
830} // QNativeInterface
831
832void *QSGTexturePlatformD3D11::nativeTexture() const
833{
834 if (auto *tex = m_texture->rhiTexture())
835 return reinterpret_cast<void *>(quintptr(tex->nativeTexture().object));
836 return 0;
837}
838
839namespace QNativeInterface {
840/*!
841 \class QNativeInterface::QSGD3D12Texture
842 \inmodule QtQuick
843 \ingroup native-interfaces
844 \ingroup native-interfaces-qsgtexture
845 \inheaderfile QSGTexture
846 \brief Provides access to and enables adopting Direct3D 12 texture objects.
847 \since 6.6
848*/
849
850/*!
851 \fn void *QNativeInterface::QSGD3D12Texture::nativeTexture() const
852 \return the ID3D12Texture object.
853 */
854
855QT_DEFINE_NATIVE_INTERFACE(QSGD3D12Texture);
856
857/*!
858 Creates a new QSGTexture wrapping an existing Direct 3D 12 \a texture object
859 for \a window.
860
861 The native object is wrapped, but not owned, by the resulting QSGTexture.
862 The caller of the function is responsible for deleting the returned
863 QSGTexture, but that will not destroy the underlying native object.
864
865 This function is currently suitable for 2D RGBA textures only.
866
867 \warning This function will return null if the scene graph has not yet been
868 initialized.
869
870 Use \a options to customize the texture attributes. Only the
871 TextureHasAlphaChannel and TextureHasMipmaps are taken into account here.
872
873 \a size specifies the size in pixels.
874
875 \a resourceState must specify the
876 \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_resource_states}{current state}
877 of the texture resource.
878
879 \note This function must be called on the scene graph rendering thread.
880
881 \sa QQuickWindow::sceneGraphInitialized(), QSGTexture,
882 {Scene Graph - Metal Texture Import}, {Scene Graph - Vulkan Texture Import}
883
884 \since 6.6
885 */
886QSGTexture *QSGD3D12Texture::fromNative(void *texture,
887 int resourceState,
888 QQuickWindow *window,
889 const QSize &size,
890 QQuickWindow::CreateTextureOptions options)
891{
892 return QQuickWindowPrivate::get(window)->createTextureFromNativeTexture(quint64(texture), resourceState, size, options);
893}
894} // QNativeInterface
895
896int QSGTexturePlatformD3D12::nativeResourceState() const
897{
898 if (auto *tex = m_texture->rhiTexture())
899 return tex->nativeTexture().layout;
900 return 0;
901}
902
903void *QSGTexturePlatformD3D12::nativeTexture() const
904{
905 if (auto *tex = m_texture->rhiTexture())
906 return reinterpret_cast<void *>(quintptr(tex->nativeTexture().object));
907 return 0;
908}
909
910#endif // win
911
912#if defined(__OBJC__) || defined(Q_QDOC)
913namespace QNativeInterface {
914/*!
915 \class QNativeInterface::QSGMetalTexture
916 \inmodule QtQuick
917 \ingroup native-interfaces
918 \ingroup native-interfaces-qsgtexture
919 \inheaderfile QSGTexture
920 \brief Provides access to and enables adopting Metal texture objects.
921 \since 6.0
922*/
923
924/*!
925 \fn id<MTLTexture> QNativeInterface::QSGMetalTexture::nativeTexture() const
926 \return the Metal texture object.
927 */
928
929/*!
930 \fn QSGTexture *QNativeInterface::QSGMetalTexture::fromNative(id<MTLTexture> texture, QQuickWindow *window, const QSize &size, QQuickWindow::CreateTextureOptions options)
931
932 Creates a new QSGTexture wrapping an existing Metal \a texture object for
933 \a window.
934
935 The native object is wrapped, but not owned, by the resulting QSGTexture.
936 The caller of the function is responsible for deleting the returned
937 QSGTexture, but that will not destroy the underlying native object.
938
939 This function is currently suitable for 2D RGBA textures only.
940
941 \warning This function will return null if the scene graph has not yet been
942 initialized.
943
944 Use \a options to customize the texture attributes. Only the
945 TextureHasAlphaChannel and TextureHasMipmaps are taken into account here.
946
947 \a size specifies the size in pixels.
948
949 \note This function must be called on the scene graph rendering thread.
950
951 \sa QQuickWindow::sceneGraphInitialized(), QSGTexture,
952 {Scene Graph - Metal Texture Import}, {Scene Graph - Vulkan Texture Import}
953
954 \since 6.0
955 */
956
957} // QNativeInterface
958#endif // OBJC
959
960#if QT_CONFIG(vulkan) || defined(Q_QDOC)
961namespace QNativeInterface {
962/*!
963 \class QNativeInterface::QSGVulkanTexture
964 \inmodule QtQuick
965 \ingroup native-interfaces
966 \ingroup native-interfaces-qsgtexture
967 \inheaderfile QSGTexture
968 \brief Provides access to and enables adopting Vulkan image objects.
969 \since 6.0
970*/
971
972/*!
973 \fn VkImage QNativeInterface::QSGVulkanTexture::nativeImage() const
974 \return the VkImage handle.
975 */
976
977/*!
978 \fn VkImageLayout QNativeInterface::QSGVulkanTexture::nativeImageLayout() const
979 \return the image layout.
980 */
981
982QT_DEFINE_NATIVE_INTERFACE(QSGVulkanTexture);
983
984/*!
985 Creates a new QSGTexture wrapping an existing Vulkan \a image object for
986 \a window.
987
988 The native object is wrapped, but not owned, by the resulting QSGTexture.
989 The caller of the function is responsible for deleting the returned
990 QSGTexture, but that will not destroy the underlying native object.
991
992 This function is currently suitable for 2D RGBA textures only.
993
994 \warning This function will return null if the scene graph has not yet been
995 initialized.
996
997 \a layout must specify the current layout of the image.
998
999 Use \a options to customize the texture attributes. Only the
1000 TextureHasAlphaChannel and TextureHasMipmaps are taken into account here.
1001
1002 \a size specifies the size in pixels.
1003
1004 \note This function must be called on the scene graph rendering thread.
1005
1006 \sa QQuickWindow::sceneGraphInitialized(), QSGTexture,
1007 {Scene Graph - Metal Texture Import}, {Scene Graph - Vulkan Texture Import}
1008
1009 \since 6.0
1010 */
1011QSGTexture *QSGVulkanTexture::fromNative(VkImage image,
1012 VkImageLayout layout,
1013 QQuickWindow *window,
1014 const QSize &size,
1015 QQuickWindow::CreateTextureOptions options)
1016{
1017 return QQuickWindowPrivate::get(window)->createTextureFromNativeTexture(quint64(image), layout, size, options);
1018}
1019} // QNativeInterface
1020
1021VkImage QSGTexturePlatformVulkan::nativeImage() const
1022{
1023 if (auto *tex = m_texture->rhiTexture())
1024 return VkImage(tex->nativeTexture().object);
1025 return VK_NULL_HANDLE;
1026}
1027
1028VkImageLayout QSGTexturePlatformVulkan::nativeImageLayout() const
1029{
1030 if (auto *tex = m_texture->rhiTexture())
1031 return VkImageLayout(tex->nativeTexture().layout);
1032 return VK_IMAGE_LAYOUT_UNDEFINED;
1033}
1034#endif // vulkan
1035
1036void *QSGTexture::resolveInterface(const char *name, int revision) const
1037{
1038 using namespace QNativeInterface;
1039 Q_UNUSED(name);
1040 Q_UNUSED(revision);
1041
1042 Q_D(const QSGTexture);
1043 auto *dd = const_cast<QSGTexturePrivate *>(d);
1044 Q_UNUSED(dd);
1045
1046#if QT_CONFIG(vulkan)
1047 QT_NATIVE_INTERFACE_RETURN_IF(QSGVulkanTexture, &dd->m_vulkanTextureAccessor);
1048#endif
1049#if QT_CONFIG(metal)
1050 QT_NATIVE_INTERFACE_RETURN_IF(QSGMetalTexture, &dd->m_metalTextureAccessor);
1051#endif
1052#if defined(Q_OS_WIN)
1053 QT_NATIVE_INTERFACE_RETURN_IF(QSGD3D11Texture, &dd->m_d3d11TextureAccessor);
1054 QT_NATIVE_INTERFACE_RETURN_IF(QSGD3D12Texture, &dd->m_d3d12TextureAccessor);
1055#endif
1056#if QT_CONFIG(opengl)
1057 QT_NATIVE_INTERFACE_RETURN_IF(QSGOpenGLTexture, &dd->m_openglTextureAccessor);
1058#endif
1059
1060 return nullptr;
1061}
1062
1063QT_END_NAMESPACE
1064
1065#include "moc_qsgtexture.cpp"
static void qt_debug_print_texture_count()
static void qt_debug_remove_texture(QSGTexture *texture)
static void qt_debug_add_texture(QSGTexture *texture)