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