Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
4#include "qsgtexture_p.h"
6#include <private/qqmlglobal_p.h>
7#include <private/qsgmaterialshader_p.h>
8#include <private/qsgrenderer_p.h>
9#include <private/qquickitem_p.h> // qquickwindow_p.h cannot be included on its own due to template nonsense
10#include <private/qquickwindow_p.h>
11#include <QtCore/private/qnativeinterface_p.h>
12#include <rhi/qrhi.h>
13
14#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && defined(__GLIBC__)
15#define CAN_BACKTRACE_EXECINFO
16#endif
17
18#if defined(Q_OS_MAC)
19#define CAN_BACKTRACE_EXECINFO
20#endif
21
22#if defined(QT_NO_DEBUG)
23#undef CAN_BACKTRACE_EXECINFO
24#endif
25
26#if defined(CAN_BACKTRACE_EXECINFO)
27#include <execinfo.h>
28#include <QHash>
29#endif
30
31#ifndef QT_NO_DEBUG
32Q_GLOBAL_STATIC(QSet<QSGTexture *>, qsg_valid_texture_set)
33Q_GLOBAL_STATIC(QMutex, qsg_valid_texture_mutex)
34#endif
35
37
39
40bool operator==(const QSGSamplerDescription &a, const QSGSamplerDescription &b) noexcept
41{
42 return a.filtering == b.filtering
43 && a.mipmapFiltering == b.mipmapFiltering
44 && a.horizontalWrap == b.horizontalWrap
45 && a.verticalWrap == b.verticalWrap
46 && a.anisotropylevel == b.anisotropylevel;
47}
48
50{
51 return !(a == b);
52}
53
54size_t qHash(const QSGSamplerDescription &s, size_t seed) noexcept
55{
56 const int f = s.filtering;
57 const int m = s.mipmapFiltering;
58 const int w = s.horizontalWrap;
59 const int a = s.anisotropylevel;
60 return (((f & 7) << 24) | ((m & 7) << 16) | ((w & 7) << 8) | (a & 7)) ^ seed;
61}
62
64{
66 s.filtering = t->filtering();
67 s.mipmapFiltering = t->mipmapFiltering();
68 s.horizontalWrap = t->horizontalWrapMode();
69 s.verticalWrap = t->verticalWrapMode();
70 s.anisotropylevel = t->anisotropyLevel();
71 return s;
72}
73
75 : wrapChanged(false)
76 , filteringChanged(false)
77 , anisotropyChanged(false)
78 , horizontalWrap(QSGTexture::ClampToEdge)
79 , verticalWrap(QSGTexture::ClampToEdge)
80 , mipmapMode(QSGTexture::None)
81 , filterMode(QSGTexture::Nearest)
82 , anisotropyLevel(QSGTexture::AnisotropyNone)
83#if QT_CONFIG(opengl)
84 , m_openglTextureAccessor(t)
85#endif
86#ifdef Q_OS_WIN
87 , m_d3d11TextureAccessor(t)
88 , m_d3d12TextureAccessor(t)
89#endif
90#if QT_CONFIG(metal)
91 , m_metalTextureAccessor(t)
92#endif
93#if QT_CONFIG(vulkan)
94 , m_vulkanTextureAccessor(t)
95#endif
96{
97#if !QT_CONFIG(opengl)
98 Q_UNUSED(t);
99#endif
100}
101
102#ifndef QT_NO_DEBUG
103
105
106#if (defined(Q_OS_LINUX) || defined (Q_OS_MAC)) && !defined(Q_OS_ANDROID)
107DEFINE_BOOL_CONFIG_OPTION(qmlDebugLeakBacktrace, QML_DEBUG_LEAK_BACKTRACE)
108
109#define BACKTRACE_SIZE 20
110class SGTextureTraceItem
111{
112public:
113 void *backTrace[BACKTRACE_SIZE];
114 size_t backTraceSize;
115};
116
117static QHash<QSGTexture*, SGTextureTraceItem*> qt_debug_allocated_textures;
118#endif
119
121{
122 qCDebug(lcQsgLeak, "Number of leaked textures: %i", qt_debug_texture_count);
124
125#if defined(CAN_BACKTRACE_EXECINFO)
126 if (qmlDebugLeakBacktrace()) {
127 while (!qt_debug_allocated_textures.isEmpty()) {
128 QHash<QSGTexture*, SGTextureTraceItem*>::Iterator it = qt_debug_allocated_textures.begin();
129 QSGTexture* texture = it.key();
130 SGTextureTraceItem* item = it.value();
131
132 qt_debug_allocated_textures.erase(it);
133
134 qDebug() << "------";
135 qDebug() << "Leaked" << texture << "backtrace:";
136
137 char** symbols = backtrace_symbols(item->backTrace, item->backTraceSize);
138
139 if (symbols) {
140 for (int i=0; i<(int) item->backTraceSize; i++)
141 qDebug("Backtrace <%02d>: %s", i, symbols[i]);
142 free(symbols);
143 }
144
145 qDebug() << "------";
146
147 delete item;
148 }
149 }
150#endif
151}
152
154{
155#if defined(CAN_BACKTRACE_EXECINFO)
156 if (qmlDebugLeakBacktrace()) {
157 SGTextureTraceItem* item = new SGTextureTraceItem;
158 item->backTraceSize = backtrace(item->backTrace, BACKTRACE_SIZE);
159 qt_debug_allocated_textures.insert(texture, item);
160 }
161#else
163#endif // Q_OS_LINUX
164
166
167 static bool atexit_registered = false;
168 if (!atexit_registered) {
170 atexit_registered = true;
171 }
172}
173
175{
176#if defined(CAN_BACKTRACE_EXECINFO)
177 if (qmlDebugLeakBacktrace()) {
178 SGTextureTraceItem* item = qt_debug_allocated_textures.value(texture, 0);
179 if (item) {
180 qt_debug_allocated_textures.remove(texture);
181 delete item;
182 }
183 }
184#else
186#endif
187
189
191 qDebug("Texture destroyed after qt_debug_print_texture_count() was called.");
192}
193
194#endif // QT_NO_DEBUG
195
306{
307#ifndef QT_NO_DEBUG
308 if (lcQsgLeak().isDebugEnabled())
310
311 QMutexLocker locker(qsg_valid_texture_mutex());
312 qsg_valid_texture_set()->insert(this);
313#endif
314}
315
320 : QObject(dd)
321{
322#ifndef QT_NO_DEBUG
323 if (lcQsgLeak().isDebugEnabled())
325
326 QMutexLocker locker(qsg_valid_texture_mutex());
327 qsg_valid_texture_set()->insert(this);
328#endif
329}
330
335{
336#ifndef QT_NO_DEBUG
337 if (lcQsgLeak().isDebugEnabled())
339
340 QMutexLocker locker(qsg_valid_texture_mutex());
341 qsg_valid_texture_set()->remove(this);
342#endif
343}
344
380{
381 Q_UNUSED(resourceUpdates);
382 Q_ASSERT_X(!isAtlasTexture(), "QSGTexture::removedFromAtlas()", "Called on a non-atlas texture");
383 return nullptr;
384}
385
392{
393 return false;
394}
395
435{
436 return QRectF(0, 0, 1, 1);
437}
438
460{
461 Q_D(QSGTexture);
462 if (d->mipmapMode != (uint) filter) {
463 d->mipmapMode = filter;
464 d->filteringChanged = true;
465 }
466}
467
472{
473 return (QSGTexture::Filtering) d_func()->mipmapMode;
474}
475
476
481{
482 Q_D(QSGTexture);
483 if (d->filterMode != (uint) filter) {
484 d->filterMode = filter;
485 d->filteringChanged = true;
486 }
487}
488
493{
494 return (QSGTexture::Filtering) d_func()->filterMode;
495}
496
508{
509 Q_D(QSGTexture);
510 if (d->anisotropyLevel != (uint) level) {
511 d->anisotropyLevel = level;
512 d->anisotropyChanged = true;
513 }
514}
515
522{
523 return (QSGTexture::AnisotropyLevel) d_func()->anisotropyLevel;
524}
525
526
527
533{
534 Q_D(QSGTexture);
535 if ((uint) hwrap != d->horizontalWrap) {
536 d->horizontalWrap = hwrap;
537 d->wrapChanged = true;
538 }
539}
540
545{
546 return (QSGTexture::WrapMode) d_func()->horizontalWrap;
547}
548
549
550
555{
556 Q_D(QSGTexture);
557 if ((uint) vwrap != d->verticalWrap) {
558 d->verticalWrap = vwrap;
559 d->wrapChanged = true;
560 }
561}
562
567{
568 return (QSGTexture::WrapMode) d_func()->verticalWrap;
569}
570
586{
587 return nullptr;
588}
589
606{
607 Q_UNUSED(rhi);
608 Q_UNUSED(resourceUpdates);
609}
610
615
620
655
660 = default;
661
679#if QT_CONFIG(opengl) || defined(Q_QDOC)
680namespace QNativeInterface {
696QT_DEFINE_NATIVE_INTERFACE(QSGOpenGLTexture);
697
724QSGTexture *QSGOpenGLTexture::fromNative(GLuint textureId,
726 const QSize &size,
727 QQuickWindow::CreateTextureOptions options)
728{
729 return QQuickWindowPrivate::get(window)->createTextureFromNativeTexture(quint64(textureId), 0, size, options);
730}
731
759QSGTexture *QSGOpenGLTexture::fromNativeExternalOES(GLuint textureId,
761 const QSize &size,
762 QQuickWindow::CreateTextureOptions options)
763{
764 return QQuickWindowPrivate::get(window)->createTextureFromNativeTexture(quint64(textureId),
765 0,
766 size,
767 options,
769}
770} // QNativeInterface
771
772GLuint QSGTexturePlatformOpenGL::nativeTexture() const
773{
774 if (auto *tex = m_texture->rhiTexture())
775 return GLuint(tex->nativeTexture().object);
776 return 0;
777}
778#endif // opengl
779
780#if defined(Q_OS_WIN) || defined(Q_QDOC)
781namespace QNativeInterface {
797QT_DEFINE_NATIVE_INTERFACE(QSGD3D11Texture);
798
824QSGTexture *QSGD3D11Texture::fromNative(void *texture,
826 const QSize &size,
827 QQuickWindow::CreateTextureOptions options)
828{
829 return QQuickWindowPrivate::get(window)->createTextureFromNativeTexture(quint64(texture), 0, size, options);
830}
831} // QNativeInterface
832
833void *QSGTexturePlatformD3D11::nativeTexture() const
834{
835 if (auto *tex = m_texture->rhiTexture())
836 return reinterpret_cast<void *>(quintptr(tex->nativeTexture().object));
837 return 0;
838}
839
840namespace QNativeInterface {
856QT_DEFINE_NATIVE_INTERFACE(QSGD3D12Texture);
857
887QSGTexture *QSGD3D12Texture::fromNative(void *texture,
888 int resourceState,
890 const QSize &size,
891 QQuickWindow::CreateTextureOptions options)
892{
893 return QQuickWindowPrivate::get(window)->createTextureFromNativeTexture(quint64(texture), resourceState, size, options);
894}
895} // QNativeInterface
896
897int QSGTexturePlatformD3D12::nativeResourceState() const
898{
899 if (auto *tex = m_texture->rhiTexture())
900 return tex->nativeTexture().layout;
901 return 0;
902}
903
904void *QSGTexturePlatformD3D12::nativeTexture() const
905{
906 if (auto *tex = m_texture->rhiTexture())
907 return reinterpret_cast<void *>(quintptr(tex->nativeTexture().object));
908 return 0;
909}
910
911#endif // win
912
913#if defined(__OBJC__) || defined(Q_QDOC)
914namespace QNativeInterface {
958} // QNativeInterface
959#endif // OBJC
960
961#if QT_CONFIG(vulkan) || defined(Q_QDOC)
962namespace QNativeInterface {
983QT_DEFINE_NATIVE_INTERFACE(QSGVulkanTexture);
984
1012QSGTexture *QSGVulkanTexture::fromNative(VkImage image,
1013 VkImageLayout layout,
1015 const QSize &size,
1016 QQuickWindow::CreateTextureOptions options)
1017{
1018 return QQuickWindowPrivate::get(window)->createTextureFromNativeTexture(quint64(image), layout, size, options);
1019}
1020} // QNativeInterface
1021
1022VkImage QSGTexturePlatformVulkan::nativeImage() const
1023{
1024 if (auto *tex = m_texture->rhiTexture())
1025 return VkImage(tex->nativeTexture().object);
1026 return VK_NULL_HANDLE;
1027}
1028
1029VkImageLayout QSGTexturePlatformVulkan::nativeImageLayout() const
1030{
1031 if (auto *tex = m_texture->rhiTexture())
1032 return VkImageLayout(tex->nativeTexture().layout);
1033 return VK_IMAGE_LAYOUT_UNDEFINED;
1034}
1035#endif // vulkan
1036
1037void *QSGTexture::resolveInterface(const char *name, int revision) const
1038{
1039 using namespace QNativeInterface;
1040 Q_UNUSED(name);
1041 Q_UNUSED(revision);
1042
1043 Q_D(const QSGTexture);
1044 auto *dd = const_cast<QSGTexturePrivate *>(d);
1045 Q_UNUSED(dd);
1046
1047#if QT_CONFIG(vulkan)
1048 QT_NATIVE_INTERFACE_RETURN_IF(QSGVulkanTexture, &dd->m_vulkanTextureAccessor);
1049#endif
1050#if QT_CONFIG(metal)
1051 QT_NATIVE_INTERFACE_RETURN_IF(QSGMetalTexture, &dd->m_metalTextureAccessor);
1052#endif
1053#if defined(Q_OS_WIN)
1054 QT_NATIVE_INTERFACE_RETURN_IF(QSGD3D11Texture, &dd->m_d3d11TextureAccessor);
1055 QT_NATIVE_INTERFACE_RETURN_IF(QSGD3D12Texture, &dd->m_d3d12TextureAccessor);
1056#endif
1057#if QT_CONFIG(opengl)
1058 QT_NATIVE_INTERFACE_RETURN_IF(QSGOpenGLTexture, &dd->m_openglTextureAccessor);
1059#endif
1060
1061 return nullptr;
1062}
1063
1065
1066#include "moc_qsgtexture.cpp"
\inmodule QtCore
Definition qhash.h:1103
\inmodule QtCore
Definition qmutex.h:313
\inmodule QtCore
Definition qmutex.h:281
\inmodule QtCore
Definition qobject.h:103
static QQuickWindowPrivate * get(QQuickWindow *c)
\qmltype Window \instantiates QQuickWindow \inqmlmodule QtQuick
\inmodule QtCore\reentrant
Definition qrect.h:484
\inmodule QtGui
Definition qrhi.h:1731
\inmodule QtGui
Definition qrhi.h:895
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:1804
~QSGDynamicTexture() override
QSGDynamicTexture()=default
void resetDirtySamplerOptions()
bool hasDirtySamplerOptions() const
QSGTexturePrivate(QSGTexture *t)
\inmodule QtQuick
Definition qsgtexture.h:20
virtual void commitTextureOperations(QRhi *rhi, QRhiResourceUpdateBatch *resourceUpdates)
Call this function to enqueue image upload operations to resourceUpdates, in case there are any pendi...
void setAnisotropyLevel(AnisotropyLevel level)
Sets the level of anisotropic filtering to level.
QSGTexture::Filtering mipmapFiltering() const
Returns whether mipmapping should be used when sampling from this texture.
virtual QRectF normalizedTextureSubRect() const
Returns the rectangle inside textureSize() that this texture represents in normalized coordinates.
void setHorizontalWrapMode(WrapMode hwrap)
Sets the horizontal wrap mode to hwrap.
virtual QSGTexture * removedFromAtlas(QRhiResourceUpdateBatch *resourceUpdates=nullptr) const
This function returns a copy of the current texture which is removed from its atlas.
void setFiltering(Filtering filter)
Sets the sampling mode to filter.
QSGTexture::WrapMode verticalWrapMode() const
Returns the vertical wrap mode to be used for this texture.
QSGTexture::Filtering filtering() const
Returns the sampling mode to be used for this texture.
QSGTexture::AnisotropyLevel anisotropyLevel() const
Returns the anisotropy level in use for filtering this texture.
void setMipmapFiltering(Filtering filter)
Sets the mipmap sampling mode to filter.
Filtering
Specifies how sampling of texels should filter when texture coordinates are not pixel aligned.
Definition qsgtexture.h:34
WrapMode
Specifies how the sampler should treat texture coordinates.
Definition qsgtexture.h:28
~QSGTexture() override
Destroys the QSGTexture.
QSGTexture()
Constructs the QSGTexture base class.
virtual bool isAtlasTexture() const
Returns whether this texture is part of an atlas or not.
AnisotropyLevel
Specifies the anisotropic filtering level to be used when the texture is not screen aligned.
Definition qsgtexture.h:40
QSGTexture::WrapMode horizontalWrapMode() const
Returns the horizontal wrap mode to be used for this texture.
virtual QRhiTexture * rhiTexture() const
void setVerticalWrapMode(WrapMode vwrap)
Sets the vertical wrap mode to vwrap.
iterator begin()
Definition qset.h:136
iterator erase(const_iterator i)
Definition qset.h:145
\inmodule QtCore
Definition qsize.h:25
#define this
Definition dialogs.cpp:9
QSet< QString >::iterator it
Combined button and popup list for selecting options.
Definition image.cpp:4
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
@ None
Definition qhash.cpp:531
#define qDebug
[1]
Definition qlogging.h:164
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
#define QT_NATIVE_INTERFACE_RETURN_IF(NativeInterface, baseType)
#define QT_DEFINE_NATIVE_INTERFACE(...)
GLboolean GLboolean GLboolean b
const GLfloat * m
GLenum GLuint GLint level
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLfloat GLfloat f
GLenum GLuint texture
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLuint name
GLdouble s
[6]
Definition qopenglext.h:235
GLdouble GLdouble t
Definition qopenglext.h:243
#define DEFINE_BOOL_CONFIG_OPTION(name, var)
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
Definition qrandom.cpp:196
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
#define GLuint
size_t qHash(const QSGSamplerDescription &s, size_t seed) noexcept
static void qt_debug_print_texture_count()
static void qt_debug_remove_texture(QSGTexture *texture)
static int qt_debug_texture_count
bool operator!=(const QSGSamplerDescription &a, const QSGSamplerDescription &b) noexcept
static void qt_debug_add_texture(QSGTexture *texture)
#define QT_CONFIG(feature)
#define Q_UNUSED(x)
size_t quintptr
Definition qtypes.h:167
unsigned long long quint64
Definition qtypes.h:61
unsigned int uint
Definition qtypes.h:34
if(qFloatDistance(a, b)<(1<< 7))
[0]
QVBoxLayout * layout
QGraphicsItem * item
aWidget window() -> setWindowTitle("New Window Title")
[2]
static QSGSamplerDescription fromTexture(QSGTexture *t)
QSGTexture::Filtering filtering