Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/VLC/modules/gui/qt/util/   (VLC Media Plyer ©)  Datei vom 23.9.2026 mit Größe 9 kB image not shown  

Quelle  textureproviderindirection.cpp   Sprache: C

 

/*****************************************************************************
 * 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.
 *****************************************************************************/

#include "textureproviderindirection.hpp"

#include <QSGTextureProvider>
#include <QRunnable>
#include <QMutexLocker>

class TextureProviderCleaner : public QRunnable
{
public:
    explicit TextureProviderCleaner(QSGTextureProvider *textureProvider)
        : m_textureProvider(textureProvider) { }

    void run() override
    {
        delete m_textureProvider;
    }

private:
    const QPointer<QSGTextureProvider> m_textureProvider;
};

TextureProviderIndirection::TextureProviderIndirection(QQuickItem *parent)
    : QQuickItem(parent)
{

}

TextureProviderIndirection::~TextureProviderIndirection()
{
    {
        if (m_textureProvider)
        {
            // https://doc.qt.io/qt-6/qquickitem.html#graphics-resource-handling

            // `QQuickItem::releaseResources()` is called before the item is disassociated from its window:
            // "This happens when the item is about to be removed from the window it was previously rendering to."
            // Therefore, we can not have a texture provider during destruction, but not the window:
            assert(window());
            window()->scheduleRenderJob(new TextureProviderCleaner(m_textureProvider), QQuickWindow::BeforeSynchronizingStage);
            m_textureProvider = nullptr;
        }
    }
}

bool TextureProviderIndirection::isTextureProvider() const
{
    return true;
}

QSGTextureProvider *TextureProviderIndirection::textureProvider() const
{
    // This method is called from the rendering thread.

    if (!m_textureProvider)
    {
        m_textureProvider = new QSGTextureViewProvider;

        const auto adjustSource = [provider = m_textureProvider](const QQuickItem *source) {
            if (source)
            {
                assert(source->isTextureProvider() &&
                       "TextureProviderIndirection: " \
                       "TextureProviderIndirection's source item is not a texture provider. " \
                       "Layering can be enabled for the source item in order to make " \
                       "it a texture provider.");

                provider->setTextureProvider(source->textureProvider());
            }
            else
            {
                provider->setTextureProvider(nullptr);
            }
        };

        const auto synchronizeState = [weakThis = QPointer(this), provider = m_textureProvider]() {
            if (Q_UNLIKELY(!weakThis))
                return;

            provider->setFiltering(weakThis->m_filtering);
            provider->setMipmapFiltering(weakThis->m_mipmapFiltering);
            provider->setAnisotropyLevel(weakThis->m_anisotropyLevel);
            provider->setHorizontalWrapMode(weakThis->m_horizontalWrapMode);
            provider->setVerticalWrapMode(weakThis->m_verticalWrapMode);

            if (weakThis->m_detachAtlasTextures)
                provider->requestDetachFromAtlas();
        };

        // These are going to be queued when necessary:
        connect(this, &TextureProviderIndirection::sourceChanged, m_textureProvider, adjustSource);
        connect(this, &TextureProviderIndirection::rectChanged, m_textureProvider, &QSGTextureViewProvider::setRect, Qt::DirectConnection);

        connect(this, &TextureProviderIndirection::filteringChanged, m_textureProvider, &QSGTextureViewProvider::setFiltering);
        connect(this, &TextureProviderIndirection::mipmapFilteringChanged, m_textureProvider, &QSGTextureViewProvider::setMipmapFiltering);
        connect(this, &TextureProviderIndirection::anisotropyLevelChanged, m_textureProvider, &QSGTextureViewProvider::setAnisotropyLevel);
        connect(this, &TextureProviderIndirection::horizontalWrapModeChanged, m_textureProvider, &QSGTextureViewProvider::setHorizontalWrapMode);
        connect(this, &TextureProviderIndirection::verticalWrapModeChanged, m_textureProvider, &QSGTextureViewProvider::setVerticalWrapMode);

        connect(this, &TextureProviderIndirection::detachAtlasTexturesChanged, m_textureProvider, [provider = m_textureProvider](bool detach) {
            if (detach)
                provider->requestDetachFromAtlas();
        });

        // When the target texture changes, the texture view may reset its state, so we need to synchronize in that case:
        connect(m_textureProvider, &QSGTextureProvider::textureChanged, m_textureProvider, synchronizeState); // Executed in texture provider's thread

        // Initial adjustments:
        adjustSource(m_source);
        if (m_rect.isValid())
            m_textureProvider->setRect(m_rect);
        synchronizeState();
    }
    return m_textureProvider;
}

void TextureProviderIndirection::resetTextureSubRect()
{
    m_rect = {};
    emit rectChanged({});
}

void TextureProviderIndirection::invalidateSceneGraph()
{
    // https://doc.qt.io/qt-6/qquickitem.html#graphics-resource-handling

    // This slot is called from the rendering thread.
    {
        if (m_textureProvider)
        {
            delete m_textureProvider;
        }
    }
}

void TextureProviderIndirection::releaseResources()
{
    // https://doc.qt.io/qt-6/qquickitem.html#graphics-resource-handling

    // This method is called from the GUI thread.

    // QQuickItem::releaseResources() is guaranteed to have a valid window when it is called:
    assert(window());
    {
        if (m_textureProvider)
        {
            window()->scheduleRenderJob(new TextureProviderCleaner(m_textureProvider), QQuickWindow::BeforeSynchronizingStage);
            m_textureProvider = nullptr;
        }
    }

    QQuickItem::releaseResources();
}

void QSGTextureViewProvider::adjustTexture()
{
    if (m_textureProvider)
        m_textureView.setTexture(m_textureProvider->texture());
    else
        m_textureView.setTexture(nullptr);

    // `textureChanged()` is emitted implicitly, no need to emit here explicitly again.
}

QSGTextureViewProvider::QSGTextureViewProvider()
    : QSGTextureProvider()
{
    connect(&m_textureView, &QSGTextureView::updateRequested, this, &QSGTextureProvider::textureChanged);
}

QSGTexture *QSGTextureViewProvider::texture() const
{
    if (m_textureProvider && m_textureView.texture())
        return &m_textureView;
    else
        return nullptr;
}

void QSGTextureViewProvider::setTextureProvider(const QSGTextureProvider *textureProvider)
{
    if (m_textureProvider == textureProvider)
        return;

    if (m_textureProvider)
        disconnect(m_textureProvider, &QSGTextureProvider::textureChanged, this, &QSGTextureViewProvider::adjustTexture);

    m_textureProvider = textureProvider;

    if (m_textureProvider)
    {
        connect(m_textureProvider, &QSGTextureProvider::textureChanged, this, &QSGTextureViewProvider::adjustTexture);
        connect(m_textureProvider, &QObject::destroyed, this, [this]() { setTextureProvider(nullptr); });
    }

    adjustTexture();
}

void QSGTextureViewProvider::setRect(const QRect &rect)
{
    m_textureView.setRect(rect);
    // `textureChanged()` is emitted implicitly, no need to emit here explicitly again
}

void QSGTextureViewProvider::setMipmapFiltering(QSGTexture::Filtering filter)
{
    if (m_textureView.mipmapFiltering() == filter)
        return;

    if (filter != QSGTexture::Filtering::None)
    {
        const auto targetTexture = m_textureView.texture();
        // If there is no target texture, we can accept mipmap filtering. When there becomes a target texture, `QSGTextureView` should
        // consider this itself anyway if the new target texture has no mipmaps. Workarounds should probably not be over-conservative,
        // we should not dismiss the case if there is no target texture now but the upcoming texture has mip maps.
        if (targetTexture && !targetTexture->hasMipmaps())
        {
            // Having mip map filtering when there are no mip maps may be problematic with certain graphics backends (like OpenGL).
            return;
        }
    }

    m_textureView.setMipmapFiltering(filter);
    emit textureChanged();
}

void QSGTextureViewProvider::setFiltering(QSGTexture::Filtering filter)
{
    if (m_textureView.filtering() == filter)
        return;

    m_textureView.setFiltering(filter);
    emit textureChanged();
}

void QSGTextureViewProvider::setAnisotropyLevel(QSGTexture::AnisotropyLevel level)
{
    if (m_textureView.anisotropyLevel() == level)
        return;

    m_textureView.setAnisotropyLevel(level);
    emit textureChanged();
}

void QSGTextureViewProvider::setHorizontalWrapMode(QSGTexture::WrapMode hwrap)
{
    if (m_textureView.horizontalWrapMode() == hwrap)
        return;

    m_textureView.setHorizontalWrapMode(hwrap);
    emit textureChanged();
}

void QSGTextureViewProvider::setVerticalWrapMode(QSGTexture::WrapMode vwrap)
{
    if (m_textureView.verticalWrapMode() == vwrap)
        return;

    m_textureView.setVerticalWrapMode(vwrap);
    emit textureChanged();
}

void QSGTextureViewProvider::requestDetachFromAtlas()
{
    m_textureView.requestDetachFromAtlas();
}

Messung
CHZG
8510010095

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.