/*****************************************************************************
* Copyright (C) 2024 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* ( at your option ) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef TEXTUREPROVIDERINDIRECTION_HPP
#define TEXTUREPROVIDERINDIRECTION_HPP
#include <QQuickItem>
#include <QSGTextureProvider>
#include <QMutex>
#include "util/qsgtextureview.hpp"
class QSGTextureViewProvider : public QSGTextureProvider
{
Q_OBJECT
mutable QSGTextureView m_textureView;
const QSGTextureProvider* m_textureProvider = nullptr;
private:
void adjustTexture();
public:
QSGTextureViewProvider();
QSGTexture *texture() const override;
void setTextureProvider(const QSGTextureProvider *textureProvider);
void setRect(const QRect& rect);
void setMipmapFiltering(QSGTexture::Filtering filter);
void setFiltering(QSGTexture::Filtering filter);
void setAnisotropyLevel(QSGTexture::AnisotropyLevel level);
void setHorizontalWrapMode(QSGTexture::WrapMode hwrap);
void setVerticalWrapMode(QSGTexture::WrapMode vwrap);
void requestDetachFromAtlas();
};
class TextureProviderIndirection : public QQuickItem
{
Q_OBJECT
// NOTE: source must be a texture provider item.
// NOTE: If source's texture provider changes, it is required to re-set the property.
Q_PROPERTY(const QQuickItem* source MEMBER m_source NOTIFY sourceChanged FINAL)
// NOTE: Although this is named as `textureSubRect`, it is allowed to provide a larger size than
// the texture size. In that case, the texture's wrap mode is going to be relevant, provided
// that the graphics backend supports it. Do note that if the source texture is already a
// sub-texture (such as a texture in the atlas), wrapping would only be applicable outside
// the boundaries of the whole texture and not the source sub-texture, and not considering
// this may expose irrelevant parts of the atlas (this means that wrap mode is effectively
// useless for sub- or atlas textures). In such a case, `detachAtlasTextures` can be used.
Q_PROPERTY(QRect textureSubRect MEMBER m_rect NOTIFY rectChanged RESET resetTextureSubRect FINAL)
Q_PROPERTY(bool detachAtlasTextures MEMBER m_detachAtlasTextures NOTIFY detachAtlasTexturesChanged FINAL)
Q_PROPERTY(QSGTexture::AnisotropyLevel anisotropyLevel MEMBER m_anisotropyLevel NOTIFY anisotropyLevelChanged FINAL)
Q_PROPERTY(QSGTexture::WrapMode horizontalWrapMode MEMBER m_horizontalWrapMode NOTIFY horizontalWrapModeChanged FINAL)
Q_PROPERTY(QSGTexture::WrapMode verticalWrapMode MEMBER m_verticalWrapMode NOTIFY verticalWrapModeChanged FINAL)
// Maybe we should use `Item::smooth` instead of these properties, or maybe not, as we should allow disabling filtering completely.
Q_PROPERTY(QSGTexture::Filtering filtering MEMBER m_filtering NOTIFY filteringChanged FINAL)
// WARNING: mipmap filtering is not respected if target texture has no mip maps:
Q_PROPERTY(QSGTexture::Filtering mipmapFiltering MEMBER m_mipmapFiltering NOTIFY mipmapFilteringChanged FINAL)
QML_ELEMENT
public:
explicit TextureProviderIndirection(QQuickItem *parent = nullptr);
~TextureProviderIndirection();
// These enumerations must be in sync with `QSGTexture`:
// It appears that MOC is not clever enough to consider foreign enumerations with `Q_ENUM` (I tried)...
enum _WrapMode {
Repeat,
ClampToEdge,
MirroredRepeat
};
Q_ENUM(_WrapMode);
enum _Filtering {
None,
Nearest,
Linear
};
Q_ENUM(_Filtering);
enum _AnisotropyLevel {
AnisotropyNone,
Anisotropy2x,
Anisotropy4x,
Anisotropy8x,
Anisotropy16x
};
Q_ENUM(_AnisotropyLevel);
bool isTextureProvider() const override;
QSGTextureProvider *textureProvider() const override;
void resetTextureSubRect();
public slots:
void invalidateSceneGraph();
signals:
void sourceChanged(const QQuickItem *source);
void rectChanged(const QRect& rect);
void anisotropyLevelChanged(QSGTexture::AnisotropyLevel);
void filteringChanged(QSGTexture::Filtering);
void mipmapFilteringChanged(QSGTexture::Filtering);
void horizontalWrapModeChanged(QSGTexture::WrapMode);
void verticalWrapModeChanged(QSGTexture::WrapMode);
void detachAtlasTexturesChanged(bool);
protected:
void releaseResources() override;
private:
QPointer<const QQuickItem> m_source;
QRect m_rect;
mutable QPointer<QSGTextureViewProvider> m_textureProvider;
std::atomic<QSGTexture::AnisotropyLevel> m_anisotropyLevel = QSGTexture::AnisotropyNone;
std::atomic<QSGTexture::Filtering> m_filtering = (smooth() ? QSGTexture::Linear : QSGTexture::Nearest);
std::atomic<QSGTexture::WrapMode> m_horizontalWrapMode = QSGTexture::ClampToEdge;
std::atomic<QSGTexture::WrapMode> m_verticalWrapMode = QSGTexture::ClampToEdge;
// When there are mip maps, no mip map filtering should be fine (unlike no mip maps with mip map filtering):
// But we want to have mip map filtering by default if the texture has mip maps (if not, it won't be respected):
std::atomic<QSGTexture::Filtering> m_mipmapFiltering = QSGTexture::Linear;
std::atomic<bool> m_detachAtlasTextures = false;
};
#endif // TEXTUREPROVIDERINDIRECTION_HPP
¤ Dauer der Verarbeitung: 0.0 Sekunden
(vorverarbeitet am 2026-11-04)
¤
*© Formatika GbR, Deutschland