aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph/coreapi/qsgtexture.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/scenegraph/coreapi/qsgtexture.cpp')
-rw-r--r--src/quick/scenegraph/coreapi/qsgtexture.cpp810
1 files changed, 810 insertions, 0 deletions
diff --git a/src/quick/scenegraph/coreapi/qsgtexture.cpp b/src/quick/scenegraph/coreapi/qsgtexture.cpp
new file mode 100644
index 0000000000..cfd0cb9f06
--- /dev/null
+++ b/src/quick/scenegraph/coreapi/qsgtexture.cpp
@@ -0,0 +1,810 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgtexture_p.h"
+#if QT_CONFIG(opengl)
+# include <QtGui/qopenglcontext.h>
+# include <QtGui/qopenglfunctions.h>
+#endif
+#include <private/qqmlglobal_p.h>
+#include <private/qsgmaterialshader_p.h>
+#include <QtGui/private/qrhi_p.h>
+
+#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && defined(__GLIBC__)
+#define CAN_BACKTRACE_EXECINFO
+#endif
+
+#if defined(Q_OS_MAC)
+#define CAN_BACKTRACE_EXECINFO
+#endif
+
+#if defined(QT_NO_DEBUG)
+#undef CAN_BACKTRACE_EXECINFO
+#endif
+
+#if defined(CAN_BACKTRACE_EXECINFO)
+#include <execinfo.h>
+#include <QHash>
+#endif
+
+#ifndef QT_NO_DEBUG
+static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK");
+#endif
+
+QT_BEGIN_NAMESPACE
+
+bool operator==(const QSGSamplerDescription &a, const QSGSamplerDescription &b) Q_DECL_NOTHROW
+{
+ return a.filtering == b.filtering
+ && a.mipmapFiltering == b.mipmapFiltering
+ && a.horizontalWrap == b.horizontalWrap
+ && a.verticalWrap == b.verticalWrap
+ && a.anisotropylevel == b.anisotropylevel;
+}
+
+bool operator!=(const QSGSamplerDescription &a, const QSGSamplerDescription &b) Q_DECL_NOTHROW
+{
+ return !(a == b);
+}
+
+uint qHash(const QSGSamplerDescription &s, uint seed) Q_DECL_NOTHROW
+{
+ const int f = s.filtering;
+ const int m = s.mipmapFiltering;
+ const int w = s.horizontalWrap;
+ const int a = s.anisotropylevel;
+ return (((f & 7) << 24) | ((m & 7) << 16) | ((w & 7) << 8) | (a & 7)) ^ seed;
+}
+
+QSGSamplerDescription QSGSamplerDescription::fromTexture(QSGTexture *t)
+{
+ QSGSamplerDescription s;
+ s.filtering = t->filtering();
+ s.mipmapFiltering = t->mipmapFiltering();
+ s.horizontalWrap = t->horizontalWrapMode();
+ s.verticalWrap = t->verticalWrapMode();
+ s.anisotropylevel = t->anisotropyLevel();
+ return s;
+}
+
+#if QT_CONFIG(opengl)
+#ifndef QT_NO_DEBUG
+inline static bool isPowerOfTwo(int x)
+{
+ // Assumption: x >= 1
+ return x == (x & -x);
+}
+#endif
+#endif
+
+QSGTexturePrivate::QSGTexturePrivate()
+ : wrapChanged(false)
+ , filteringChanged(false)
+ , anisotropyChanged(false)
+ , horizontalWrap(QSGTexture::ClampToEdge)
+ , verticalWrap(QSGTexture::ClampToEdge)
+ , mipmapMode(QSGTexture::None)
+ , filterMode(QSGTexture::Nearest)
+ , anisotropyLevel(QSGTexture::AnisotropyNone)
+{
+}
+
+#ifndef QT_NO_DEBUG
+
+static int qt_debug_texture_count = 0;
+
+#if (defined(Q_OS_LINUX) || defined (Q_OS_MAC)) && !defined(Q_OS_ANDROID)
+DEFINE_BOOL_CONFIG_OPTION(qmlDebugLeakBacktrace, QML_DEBUG_LEAK_BACKTRACE)
+
+#define BACKTRACE_SIZE 20
+class SGTextureTraceItem
+{
+public:
+ void *backTrace[BACKTRACE_SIZE];
+ size_t backTraceSize;
+};
+
+static QHash<QSGTexture*, SGTextureTraceItem*> qt_debug_allocated_textures;
+#endif
+
+inline static void qt_debug_print_texture_count()
+{
+ qDebug("Number of leaked textures: %i", qt_debug_texture_count);
+ qt_debug_texture_count = -1;
+
+#if defined(CAN_BACKTRACE_EXECINFO)
+ if (qmlDebugLeakBacktrace()) {
+ while (!qt_debug_allocated_textures.isEmpty()) {
+ QHash<QSGTexture*, SGTextureTraceItem*>::Iterator it = qt_debug_allocated_textures.begin();
+ QSGTexture* texture = it.key();
+ SGTextureTraceItem* item = it.value();
+
+ qt_debug_allocated_textures.erase(it);
+
+ qDebug() << "------";
+ qDebug() << "Leaked" << texture << "backtrace:";
+
+ char** symbols = backtrace_symbols(item->backTrace, item->backTraceSize);
+
+ if (symbols) {
+ for (int i=0; i<(int) item->backTraceSize; i++)
+ qDebug("Backtrace <%02d>: %s", i, symbols[i]);
+ free(symbols);
+ }
+
+ qDebug() << "------";
+
+ delete item;
+ }
+ }
+#endif
+}
+
+inline static void qt_debug_add_texture(QSGTexture* texture)
+{
+#if defined(CAN_BACKTRACE_EXECINFO)
+ if (qmlDebugLeakBacktrace()) {
+ SGTextureTraceItem* item = new SGTextureTraceItem;
+ item->backTraceSize = backtrace(item->backTrace, BACKTRACE_SIZE);
+ qt_debug_allocated_textures.insert(texture, item);
+ }
+#else
+ Q_UNUSED(texture);
+#endif // Q_OS_LINUX
+
+ ++qt_debug_texture_count;
+
+ static bool atexit_registered = false;
+ if (!atexit_registered) {
+ atexit(qt_debug_print_texture_count);
+ atexit_registered = true;
+ }
+}
+
+static void qt_debug_remove_texture(QSGTexture* texture)
+{
+#if defined(CAN_BACKTRACE_EXECINFO)
+ if (qmlDebugLeakBacktrace()) {
+ SGTextureTraceItem* item = qt_debug_allocated_textures.value(texture, 0);
+ if (item) {
+ qt_debug_allocated_textures.remove(texture);
+ delete item;
+ }
+ }
+#else
+ Q_UNUSED(texture)
+#endif
+
+ --qt_debug_texture_count;
+
+ if (qt_debug_texture_count < 0)
+ qDebug("Texture destroyed after qt_debug_print_texture_count() was called.");
+}
+
+#endif // QT_NO_DEBUG
+
+/*!
+ \class QSGTexture
+
+ \inmodule QtQuick
+
+ \brief The QSGTexture class is a baseclass for textures used in
+ the scene graph.
+
+
+ Users can freely implement their own texture classes to support
+ arbitrary input textures, such as YUV video frames or 8 bit alpha
+ masks. The scene graph backend provides a default implementation
+ of normal color textures. As the implementation of these may be
+ hardware specific, they are constructed via the factory
+ function QQuickWindow::createTextureFromImage().
+
+ The texture is a wrapper around an OpenGL texture, which texture
+ id is given by textureId() and which size in pixels is given by
+ textureSize(). hasAlphaChannel() reports if the texture contains
+ opacity values and hasMipmaps() reports if the texture contains
+ mipmap levels.
+
+ To use a texture, call the bind() function. The texture parameters
+ specifying how the texture is bound, can be specified with
+ setMipmapFiltering(), setFiltering(), setHorizontalWrapMode() and
+ setVerticalWrapMode(). The texture will internally try to store
+ these values to minimize the OpenGL state changes when the texture
+ is bound.
+
+ \section1 Texture Atlasses
+
+ Some scene graph backends use texture atlasses, grouping multiple
+ small textures into one large texture. If this is the case, the
+ function isAtlasTexture() will return true. Atlasses are used to
+ aid the rendering algorithm to do better sorting which increases
+ performance. The location of the texture inside the atlas is
+ given with the normalizedTextureSubRect() function.
+
+ If the texture is used in such a way that atlas is not preferable,
+ the function removedFromAtlas() can be used to extract a
+ non-atlassed copy.
+
+ \note All classes with QSG prefix should be used solely on the scene graph's
+ rendering thread. See \l {Scene Graph and Rendering} for more information.
+
+ \sa {Scene Graph - Rendering FBOs}, {Scene Graph - Rendering FBOs in a thread}
+ */
+
+/*!
+ \enum QSGTexture::WrapMode
+
+ Specifies how the texture should treat texture coordinates.
+
+ \value Repeat Only the fractional part of the texture coordinate is
+ used, causing values above 1 and below 0 to repeat.
+
+ \value ClampToEdge Values above 1 are clamped to 1 and values
+ below 0 are clamped to 0.
+
+ \value MirroredRepeat When the texture coordinate is even, only the
+ fractional part is used. When odd, the texture coordinate is set to
+ \c{1 - fractional part}. This value has been introduced in Qt 5.10.
+ */
+
+/*!
+ \enum QSGTexture::Filtering
+
+ Specifies how sampling of texels should filter when texture
+ coordinates are not pixel aligned.
+
+ \value None No filtering should occur. This value is only used
+ together with setMipmapFiltering().
+
+ \value Nearest Sampling returns the nearest texel.
+
+ \value Linear Sampling returns a linear interpolation of the
+ neighboring texels.
+*/
+
+/*!
+ \enum QSGTexture::AnisotropyLevel
+
+ Specifies the anisotropic filtering level to be used when
+ the texture is not screen aligned.
+
+ \value AnisotropyNone No anisotropic filtering.
+
+ \value Anisotropy2x 2x anisotropic filtering.
+
+ \value Anisotropy4x 4x anisotropic filtering.
+
+ \value Anisotropy8x 8x anisotropic filtering.
+
+ \value Anisotropy16x 16x anisotropic filtering.
+
+ \since 5.9
+*/
+
+#ifndef QT_NO_DEBUG
+Q_QUICK_PRIVATE_EXPORT void qsg_set_material_failure();
+#endif
+
+#ifndef QT_NO_DEBUG
+Q_GLOBAL_STATIC(QSet<QSGTexture *>, qsg_valid_texture_set)
+Q_GLOBAL_STATIC(QMutex, qsg_valid_texture_mutex)
+
+bool qsg_safeguard_texture(QSGTexture *texture)
+{
+#if QT_CONFIG(opengl)
+ QMutexLocker locker(qsg_valid_texture_mutex());
+ if (!qsg_valid_texture_set()->contains(texture)) {
+ qWarning() << "Invalid texture accessed:" << (void *) texture;
+ qsg_set_material_failure();
+ QOpenGLContext::currentContext()->functions()->glBindTexture(GL_TEXTURE_2D, 0);
+ return false;
+ }
+#else
+ Q_UNUSED(texture)
+#endif
+ return true;
+}
+#endif
+
+/*!
+ Constructs the QSGTexture base class.
+ */
+QSGTexture::QSGTexture()
+ : QObject(*(new QSGTexturePrivate))
+{
+#ifndef QT_NO_DEBUG
+ if (qsg_leak_check)
+ qt_debug_add_texture(this);
+
+ QMutexLocker locker(qsg_valid_texture_mutex());
+ qsg_valid_texture_set()->insert(this);
+#endif
+}
+
+/*!
+ \internal
+ */
+QSGTexture::QSGTexture(QSGTexturePrivate &dd)
+ : QObject(dd)
+{
+#ifndef QT_NO_DEBUG
+ if (qsg_leak_check)
+ qt_debug_add_texture(this);
+
+ QMutexLocker locker(qsg_valid_texture_mutex());
+ qsg_valid_texture_set()->insert(this);
+#endif
+}
+
+/*!
+ Destroys the QSGTexture.
+ */
+QSGTexture::~QSGTexture()
+{
+#ifndef QT_NO_DEBUG
+ if (qsg_leak_check)
+ qt_debug_remove_texture(this);
+
+ QMutexLocker locker(qsg_valid_texture_mutex());
+ qsg_valid_texture_set()->remove(this);
+#endif
+}
+
+/*!
+ \fn void QSGTexture::bind()
+
+ Call this function to bind this texture to the current texture
+ target.
+
+ Binding a texture may also include uploading the texture data from
+ a previously set QImage.
+
+ \warning This function can only be called from the rendering thread.
+ */
+
+/*!
+ \fn QRectF QSGTexture::convertToNormalizedSourceRect(const QRectF &rect) const
+
+ Returns \a rect converted to normalized coordinates.
+
+ \sa normalizedTextureSubRect()
+ */
+
+/*!
+ This function returns a copy of the current texture which is removed
+ from its atlas.
+
+ The current texture remains unchanged, so texture coordinates do not
+ need to be updated.
+
+ Removing a texture from an atlas is primarily useful when passing
+ it to a shader that operates on the texture coordinates 0-1 instead
+ of the texture subrect inside the atlas.
+
+ If the texture is not part of a texture atlas, this function returns 0.
+
+ Implementations of this function are recommended to return the same instance
+ for multiple calls to limit memory usage.
+
+ \warning This function can only be called from the rendering thread.
+ */
+
+QSGTexture *QSGTexture::removedFromAtlas() const
+{
+ Q_ASSERT_X(!isAtlasTexture(), "QSGTexture::removedFromAtlas()", "Called on a non-atlas texture");
+ return nullptr;
+}
+
+/*!
+ Returns weither this texture is part of an atlas or not.
+
+ The default implementation returns false.
+ */
+bool QSGTexture::isAtlasTexture() const
+{
+ return false;
+}
+
+/*!
+ \fn int QSGTexture::textureId() const
+
+ Returns the OpenGL texture id for this texture.
+
+ The default value is 0, indicating that it is an invalid texture id.
+
+ The function should at all times return the correct texture id.
+
+ \warning This function can only be called from the rendering thread.
+ */
+
+/*!
+ Returns a key suitable for comparing textures. Typically used in
+ QSGMaterial::compare() implementations.
+
+ Just comparing QSGTexture pointers is not always sufficient because two
+ QSGTexture instances that refer to the same native texture object
+ underneath should also be considered equal. Hence this function.
+
+ \note Unlike textureId(), implementations of this function are not expected
+ to and should not create any graphics resources (so texture objects) in
+ case there is none yet.
+
+ A QSGTexture that does not have a native texture object underneath is
+ typically not equal to any other QSGTexture. There are exceptions to this,
+ in particular when atlasing is used (where multiple textures share the same
+ atlas texture under the hood), that is then up to the subclass
+ implementations to deal with as appropriate.
+
+ \warning This function can only be called from the rendering thread.
+
+ \since 5.14
+ */
+int QSGTexture::comparisonKey() const
+{
+ Q_D(const QSGTexture);
+ return d->comparisonKey();
+}
+
+/*!
+ \fn QSize QSGTexture::textureSize() const
+
+ Returns the size of the texture.
+ */
+
+/*!
+ Returns the rectangle inside textureSize() that this texture
+ represents in normalized coordinates.
+
+ The default implementation returns a rect at position (0, 0) with
+ width and height of 1.
+ */
+QRectF QSGTexture::normalizedTextureSubRect() const
+{
+ return QRectF(0, 0, 1, 1);
+}
+
+/*!
+ \fn bool QSGTexture::hasAlphaChannel() const
+
+ Returns true if the texture data contains an alpha channel.
+ */
+
+/*!
+ \fn bool QSGTexture::hasMipmaps() const
+
+ Returns true if the texture data contains mipmap levels.
+ */
+
+
+/*!
+ Sets the mipmap sampling mode to be used for the upcoming bind() call to \a filter.
+
+ Setting the mipmap filtering has no effect it the texture does not have mipmaps.
+
+ \sa hasMipmaps()
+ */
+void QSGTexture::setMipmapFiltering(Filtering filter)
+{
+ Q_D(QSGTexture);
+ if (d->mipmapMode != (uint) filter) {
+ d->mipmapMode = filter;
+ d->filteringChanged = true;
+ }
+}
+
+/*!
+ Returns whether mipmapping should be used when sampling from this texture.
+ */
+QSGTexture::Filtering QSGTexture::mipmapFiltering() const
+{
+ return (QSGTexture::Filtering) d_func()->mipmapMode;
+}
+
+
+/*!
+ Sets the sampling mode to be used for the upcoming bind() call to \a filter.
+ */
+void QSGTexture::setFiltering(QSGTexture::Filtering filter)
+{
+ Q_D(QSGTexture);
+ if (d->filterMode != (uint) filter) {
+ d->filterMode = filter;
+ d->filteringChanged = true;
+ }
+}
+
+/*!
+ Returns the sampling mode to be used for this texture.
+ */
+QSGTexture::Filtering QSGTexture::filtering() const
+{
+ return (QSGTexture::Filtering) d_func()->filterMode;
+}
+
+/*!
+ Sets the level of anisotropic filtering to be used for the upcoming bind() call to \a level.
+ The default value is QSGTexture::AnisotropyNone, which means no anisotropic filtering is enabled.
+
+ \since 5.9
+ */
+void QSGTexture::setAnisotropyLevel(AnisotropyLevel level)
+{
+ Q_D(QSGTexture);
+ if (d->anisotropyLevel != (uint) level) {
+ d->anisotropyLevel = level;
+ d->anisotropyChanged = true;
+ }
+}
+
+/*!
+ Returns the anisotropy level in use for filtering this texture.
+
+ \since 5.9
+ */
+QSGTexture::AnisotropyLevel QSGTexture::anisotropyLevel() const
+{
+ return (QSGTexture::AnisotropyLevel) d_func()->anisotropyLevel;
+}
+
+
+
+/*!
+ Sets the horizontal wrap mode to be used for the upcoming bind() call to \a hwrap
+ */
+
+void QSGTexture::setHorizontalWrapMode(WrapMode hwrap)
+{
+ Q_D(QSGTexture);
+ if ((uint) hwrap != d->horizontalWrap) {
+ d->horizontalWrap = hwrap;
+ d->wrapChanged = true;
+ }
+}
+
+/*!
+ Returns the horizontal wrap mode to be used for this texture.
+ */
+QSGTexture::WrapMode QSGTexture::horizontalWrapMode() const
+{
+ return (QSGTexture::WrapMode) d_func()->horizontalWrap;
+}
+
+
+
+/*!
+ Sets the vertical wrap mode to be used for the upcoming bind() call to \a vwrap
+ */
+void QSGTexture::setVerticalWrapMode(WrapMode vwrap)
+{
+ Q_D(QSGTexture);
+ if ((uint) vwrap != d->verticalWrap) {
+ d->verticalWrap = vwrap;
+ d->wrapChanged = true;
+ }
+}
+
+/*!
+ Returns the vertical wrap mode to be used for this texture.
+ */
+QSGTexture::WrapMode QSGTexture::verticalWrapMode() const
+{
+ return (QSGTexture::WrapMode) d_func()->verticalWrap;
+}
+
+
+/*!
+ Update the texture state to match the filtering, mipmap and wrap options
+ currently set.
+
+ If \a force is true, all properties will be updated regardless of weither
+ they have changed or not.
+ */
+void QSGTexture::updateBindOptions(bool force) // legacy (GL-only)
+{
+#if QT_CONFIG(opengl)
+ Q_D(QSGTexture);
+ QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
+ force |= isAtlasTexture();
+
+ if (force || d->filteringChanged) {
+ bool linear = d->filterMode == Linear;
+ GLint minFilter = linear ? GL_LINEAR : GL_NEAREST;
+ GLint magFilter = linear ? GL_LINEAR : GL_NEAREST;
+
+ if (hasMipmaps()) {
+ if (d->mipmapMode == Nearest)
+ minFilter = linear ? GL_LINEAR_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_NEAREST;
+ else if (d->mipmapMode == Linear)
+ minFilter = linear ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_LINEAR;
+ }
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
+ d->filteringChanged = false;
+ }
+
+ if (force || d->anisotropyChanged) {
+ d->anisotropyChanged = false;
+ if (QOpenGLContext::currentContext()->hasExtension(QByteArrayLiteral("GL_EXT_texture_filter_anisotropic")))
+ funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, float(1 << (d->anisotropyLevel)));
+ }
+
+ if (force || d->wrapChanged) {
+#ifndef QT_NO_DEBUG
+ if (d->horizontalWrap == Repeat || d->verticalWrap == Repeat
+ || d->horizontalWrap == MirroredRepeat || d->verticalWrap == MirroredRepeat)
+ {
+ bool npotSupported = QOpenGLFunctions(QOpenGLContext::currentContext()).hasOpenGLFeature(QOpenGLFunctions::NPOTTextures);
+ QSize size = textureSize();
+ bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height());
+ if (!npotSupported && isNpot)
+ qWarning("Scene Graph: This system does not support the REPEAT wrap mode for non-power-of-two textures.");
+ }
+#endif
+ GLenum wrapS = GL_CLAMP_TO_EDGE;
+ if (d->horizontalWrap == Repeat)
+ wrapS = GL_REPEAT;
+ else if (d->horizontalWrap == MirroredRepeat)
+ wrapS = GL_MIRRORED_REPEAT;
+ GLenum wrapT = GL_CLAMP_TO_EDGE;
+ if (d->verticalWrap == Repeat)
+ wrapT = GL_REPEAT;
+ else if (d->verticalWrap == MirroredRepeat)
+ wrapT = GL_MIRRORED_REPEAT;
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
+ d->wrapChanged = false;
+ }
+#else
+ Q_UNUSED(force)
+#endif
+}
+
+/*!
+ \return the QRhiTexture for this QSGTexture or null if there is none.
+
+ Unlike textureId(), this function is not expected to create a new
+ QRhiTexture in case there is none. Just return null in that case. The
+ expectation towards the renderer is that a null texture leads to using a
+ transparent, dummy texture instead.
+
+ \note This function is only used when running the graphics API independent
+ rendering path of the scene graph.
+
+ \warning This function can only be called from the rendering thread.
+
+ \since 5.14
+ */
+QRhiTexture *QSGTexture::rhiTexture() const
+{
+ Q_D(const QSGTexture);
+ return d->rhiTexture();
+}
+
+/*!
+ Call this function to enqueue image upload operations to \a
+ resourceUpdates, in case there are any pending ones. When there is no new
+ data (for example, because there was no setImage() since the last call to
+ this function), the function does nothing.
+
+ Materials involving textures are expected to call this function from their
+ updateSampledImage() implementation, typically without any conditions.
+
+ \note This function is only used when running the graphics API independent
+ rendering path of the scene graph.
+
+ \warning This function can only be called from the rendering thread.
+
+ \since 5.14
+ */
+void QSGTexture::updateRhiTexture(QRhi *rhi, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ Q_D(QSGTexture);
+ d->updateRhiTexture(rhi, resourceUpdates);
+}
+
+void QSGTexture::setWorkResourceUpdateBatch(QRhiResourceUpdateBatch *resourceUpdates)
+{
+ Q_D(QSGTexture);
+ d->workResourceUpdateBatch = resourceUpdates;
+}
+
+bool QSGTexturePrivate::hasDirtySamplerOptions() const
+{
+ return wrapChanged || filteringChanged || anisotropyChanged;
+}
+
+void QSGTexturePrivate::resetDirtySamplerOptions()
+{
+ wrapChanged = filteringChanged = anisotropyChanged = false;
+}
+
+int QSGTexturePrivate::comparisonKey() const
+{
+ // Must be overridden in subclasses but we cannot make this pure virtual
+ // before Qt 6 because the simple QSGTexture ctor must be kept working.
+ Q_Q(const QSGTexture);
+ return q->textureId(); // this is semantically wrong but at least compatible with existing, non-RHI-aware subclasses
+}
+
+QRhiTexture *QSGTexturePrivate::rhiTexture() const
+{
+ return nullptr;
+}
+
+void QSGTexturePrivate::updateRhiTexture(QRhi *rhi, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ Q_UNUSED(rhi);
+ Q_UNUSED(resourceUpdates);
+}
+
+/*!
+ \class QSGDynamicTexture
+ \brief The QSGDynamicTexture class serves as a baseclass for dynamically changing textures,
+ such as content that is rendered to FBO's.
+ \inmodule QtQuick
+
+ To update the content of the texture, call updateTexture() explicitly. Simply calling bind()
+ will not update the texture.
+
+ \note All classes with QSG prefix should be used solely on the scene graph's
+ rendering thread. See \l {Scene Graph and Rendering} for more information.
+ */
+
+
+/*!
+ \fn bool QSGDynamicTexture::updateTexture()
+
+ Call this function to explicitly update the dynamic texture. Calling bind() will bind
+ the content that was previously updated.
+
+ The function returns true if the texture was changed as a resul of the update; otherwise
+ returns false.
+ */
+
+/*!
+ \internal
+ */
+QSGDynamicTexture::QSGDynamicTexture(QSGTexturePrivate &dd)
+ : QSGTexture(dd)
+{
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qsgtexture.cpp"