[vlc-commits] [Git][videolan/vlc][master] qt: get rid of `QSGRoundedRectangularImageNode`
Steve Lhomme (@robUx4)
gitlab at videolan.org
Sun Nov 16 10:57:04 UTC 2025
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
2ea91a27 by Fatih Uzunoglu at 2025-11-16T10:43:05+00:00
qt: get rid of `QSGRoundedRectangularImageNode`
There has been nothing that used this node since we started
to use SDF to draw rounded images (40dcb6a4).
Using this node would be beneficial where having a custom
geometry with triangle strips is more favorable than
having an expensive fragment shader. At the same time, if
MSAA is enabled, there would be anti-aliasing while keeping
the primitive opaque (which is important for effective
batching), where with the SDF approach this is not possible.
Currently we do not offer a way to enable MSAA, and without
MSAA, it lacked AA completely. Implementing AA with SDFs
is much easier than implementing "vertex" AA with custom
geometry.
Requesting MSAA by default is still on the table though,
because that way built-in Qt items would also not need to
use "vertex" AA, and as Qt docs noted, this would improve
batching overall. This is mostly relevant for round items,
such as `Rectangle` with `radius`.
- - - - -
4 changed files:
- modules/gui/qt/Makefile.am
- modules/gui/qt/meson.build
- − modules/gui/qt/util/qsgroundedrectangularimagenode.cpp
- − modules/gui/qt/util/qsgroundedrectangularimagenode.hpp
Changes:
=====================================
modules/gui/qt/Makefile.am
=====================================
@@ -328,8 +328,6 @@ libqt_plugin_la_SOURCES = \
util/fast_gaussian_blur_template.h \
util/effects_image_provider.cpp \
util/effects_image_provider.hpp \
- util/qsgroundedrectangularimagenode.cpp \
- util/qsgroundedrectangularimagenode.hpp \
util/qsgtextureview.cpp \
util/qsgtextureview.hpp \
util/dismiss_popup_event_filter.cpp \
=====================================
modules/gui/qt/meson.build
=====================================
@@ -476,8 +476,6 @@ qt_plugin_sources = files(
'util/fast_gaussian_blur_template.h',
'util/effects_image_provider.cpp',
'util/effects_image_provider.hpp',
- 'util/qsgroundedrectangularimagenode.cpp',
- 'util/qsgroundedrectangularimagenode.hpp',
'util/qsgtextureview.cpp',
'util/qsgtextureview.hpp',
'util/textureproviderobserver.cpp',
=====================================
modules/gui/qt/util/qsgroundedrectangularimagenode.cpp deleted
=====================================
@@ -1,290 +0,0 @@
-/*****************************************************************************
- * Copyright (C) 2022 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 "qsgroundedrectangularimagenode.hpp"
-
-#include <QSGTextureMaterial>
-#include <QSGOpaqueTextureMaterial>
-
-#include <QCache>
-#include <QVector>
-#include <QPainterPath>
-
-template<class T>
-T QSGRoundedRectangularImageNode::material_cast(QSGMaterial* const material)
-{
-#ifdef NDEBUG
- return static_cast<T>(material);
-#else
- const auto ret = dynamic_cast<T>(material);
- assert(ret); // incompatible material type
- return ret;
-#endif
-}
-
-QSGRoundedRectangularImageNode::QSGRoundedRectangularImageNode()
-{
- setFlags(QSGGeometryNode::OwnsMaterial |
- QSGGeometryNode::OwnsOpaqueMaterial |
- QSGGeometryNode::OwnsGeometry);
-
- setMaterial(new QSGTextureMaterial);
- setOpaqueMaterial(new QSGOpaqueTextureMaterial);
-
- setSmooth(m_smooth);
-
- // Useful for debugging:
-#ifdef QSG_RUNTIME_DESCRIPTION
- qsgnode_set_description(this, QStringLiteral("RoundedRectangularImage"));
-#endif
-}
-
-QSGTextureMaterial *QSGRoundedRectangularImageNode::material() const
-{
- return material_cast<QSGTextureMaterial*>(QSGGeometryNode::material());
-}
-
-QSGOpaqueTextureMaterial *QSGRoundedRectangularImageNode::opaqueMaterial() const
-{
- return material_cast<QSGOpaqueTextureMaterial*>(QSGGeometryNode::opaqueMaterial());
-}
-
-void QSGRoundedRectangularImageNode::setSmooth(const bool smooth)
-{
- if (m_smooth == smooth)
- return;
-
- {
- const enum QSGTexture::Filtering filtering = smooth ? QSGTexture::Linear : QSGTexture::Nearest;
- material()->setFiltering(filtering);
- opaqueMaterial()->setFiltering(filtering);
- }
-
- {
- const enum QSGTexture::Filtering mipmapFiltering = smooth ? QSGTexture::Linear : QSGTexture::None;
- material()->setMipmapFiltering(mipmapFiltering);
- opaqueMaterial()->setMipmapFiltering(mipmapFiltering);
- }
-
- markDirty(QSGNode::DirtyMaterial);
-}
-
-void QSGRoundedRectangularImageNode::setTexture(const std::shared_ptr<QSGTexture>& texture)
-{
- assert(texture);
-
- {
- const bool wasAtlas = (!m_texture || m_texture->isAtlasTexture());
-
- m_texture = texture;
-
- // Unless we operate on atlas textures, it should be
- // fine to not rebuild the geometry
- if (wasAtlas || texture->isAtlasTexture())
- rebuildGeometry(); // Texture coordinate mismatch
- }
-
- material()->setTexture(texture.get());
- opaqueMaterial()->setTexture(texture.get());
-
- markDirty(QSGNode::DirtyMaterial);
-}
-
-bool QSGRoundedRectangularImageNode::setShape(const Shape& shape)
-{
- if (m_shape == shape)
- return false;
-
- const bool ret = rebuildGeometry(shape);
-
- if (ret)
- m_shape = shape;
-
- return ret;
-}
-
-bool QSGRoundedRectangularImageNode::rebuildGeometry(const Shape& shape)
-{
- QSGGeometry* const geometry = this->geometry();
- QSGGeometry* const rebuiltGeometry = rebuildGeometry(shape,
- geometry,
- m_texture->isAtlasTexture() ? m_texture.get()
- : nullptr);
- if (!rebuiltGeometry)
- {
- return false;
- }
- else if (rebuiltGeometry == geometry)
- {
- // Was able to reconstruct old geometry instance
- markDirty(QSGNode::DirtyGeometry);
- }
- else
- {
- // - Dirty bit set implicitly
- // - No need to remove the old geometry
- setGeometry(rebuiltGeometry);
- }
-
- return true;
-}
-
-QSGGeometry* QSGRoundedRectangularImageNode::rebuildGeometry(const Shape& shape,
- QSGGeometry* geometry,
- const QSGTexture* const atlasTexture)
-{
- if (!shape.isValid())
- return nullptr;
-
- int vertexCount;
-
- QVector<QPointF> *path;
- std::unique_ptr<QVector<QPointF>> upPath;
-
- if (qFuzzyIsNull(shape.radius))
- {
- // 4 vertices are needed to construct
- // a rectangle using triangle strip.
- vertexCount = 4;
- path = nullptr; // unused
- }
- else
- {
- using SizePair = QPair<qreal, qreal>;
- using ShapePair = QPair<SizePair, qreal>;
-
- // We could cache QSGGeometry itself, but
- // it would not be really useful for atlas
- // textures.
- static QCache<ShapePair, QVector<QPointF>> paths;
-
- ShapePair key {{shape.rect.width(), shape.rect.height()}, {shape.radius}};
- if (paths.contains(key))
- {
- // There is no cache manipulation after this point,
- // so path is assumed to be valid within its scope
- path = paths.object(key);
- }
- else
- {
- QPainterPath painterPath;
- constexpr const short extrapolationFactor = 2;
- painterPath.addRoundedRect(0, 0,
- key.first.first * extrapolationFactor,
- key.first.second * extrapolationFactor,
- key.second * extrapolationFactor,
- key.second * extrapolationFactor);
- painterPath = painterPath.simplified();
-
- upPath = std::make_unique<QVector<QPointF>>(painterPath.elementCount());
- path = upPath.get();
-
- const int elementCount = painterPath.elementCount();
- for (int i = 0; i < elementCount; ++i)
- {
- // QPainterPath is not necessarily compatible with
- // with GPU primitives. However, simplified painter path
- // with rounded rectangle shape consists of painter path
- // elements of types which can be drawn using primitives.
- assert(painterPath.elementAt(i).type == QPainterPath::ElementType::MoveToElement
- || painterPath.elementAt(i).type == QPainterPath::ElementType::LineToElement);
-
- // Symmetry based triangulation based on ordered painter path.
- (*path)[i] = static_cast<QPointF>(painterPath.elementAt((i % 2) ? (i)
- : (elementCount - i - 1))) / extrapolationFactor;
- }
-
- paths.insert(key, new QVector<QPointF>(*path));
- }
-
- vertexCount = path->count();
- }
-
- if (!geometry)
- {
- geometry = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), vertexCount);
- geometry->setIndexDataPattern(QSGGeometry::StaticPattern); // Is this necessary? Indexing is not used
- geometry->setVertexDataPattern(QSGGeometry::StaticPattern);
- geometry->setDrawingMode(QSGGeometry::DrawingMode::DrawTriangleStrip);
- }
- else
- {
- // Size check is implicitly done:
- geometry->allocate(vertexCount);
-
- // Assume the passed geometry is not a stray one.
- // It is possible to check and create a new QSGGeometry
- // if it is incompatible, but it should not be necessary.
- // So instead, just pass QSGGeometry to this function that
- // is either inherently compatible, or that is created by
- // this function.
-
- // These two are not required for compatibility,
- // but lets still assert them for performance reasons.
- assert(geometry->indexDataPattern() == QSGGeometry::StaticPattern);
- assert(geometry->vertexDataPattern() == QSGGeometry::StaticPattern);
-
- assert(geometry->drawingMode() == QSGGeometry::DrawingMode::DrawTriangleStrip);
- assert(geometry->attributes() == QSGGeometry::defaultAttributes_TexturedPoint2D().attributes);
- assert(geometry->sizeOfVertex() == QSGGeometry::defaultAttributes_TexturedPoint2D().stride);
- }
-
- QRectF texNormalSubRect;
- if (atlasTexture)
- {
- // The texture might not be in the atlas, but it is okay.
- texNormalSubRect = atlasTexture->normalizedTextureSubRect();
- }
- else
- {
- // In case no texture is given at all:
- texNormalSubRect = {0.0, 0.0, 1.0, 1.0};
- }
-
- if (qFuzzyIsNull(shape.radius))
- {
- // Use the helper function to reconstruct the pure rectangular geometry:
- QSGGeometry::updateTexturedRectGeometry(geometry, shape.rect, texNormalSubRect);
- }
- else
- {
- const auto mapToAtlasTexture = [texNormalSubRect] (const QPointF& nPoint) -> QPointF {
- return {texNormalSubRect.x() + (texNormalSubRect.width() * nPoint.x()),
- texNormalSubRect.y() + (texNormalSubRect.height() * nPoint.y())};
- };
-
- QSGGeometry::TexturedPoint2D* const points = geometry->vertexDataAsTexturedPoint2D();
-
- const qreal dx = shape.rect.x();
- const qreal dy = shape.rect.y();
- for (int i = 0; i < geometry->vertexCount(); ++i)
- {
- const QPointF& pos = path->at(i);
- QPointF tPos = {pos.x() / shape.rect.width(), pos.y() / shape.rect.height()};
- if (atlasTexture)
- tPos = mapToAtlasTexture(tPos);
-
- points[i].set(pos.x() + dx, pos.y() + dy, tPos.x(), tPos.y());
- }
- }
-
- geometry->markIndexDataDirty();
- geometry->markVertexDataDirty();
-
- return geometry;
-}
=====================================
modules/gui/qt/util/qsgroundedrectangularimagenode.hpp deleted
=====================================
@@ -1,87 +0,0 @@
-/*****************************************************************************
- * Copyright (C) 2022 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 QSGROUNDEDRECTANGULARIMAGENODE_HPP
-#define QSGROUNDEDRECTANGULARIMAGENODE_HPP
-
-#include <QSGGeometryNode>
-
-#include <memory>
-#include <cmath>
-
-class QSGTextureMaterial;
-class QSGOpaqueTextureMaterial;
-class QSGTexture;
-
-class QSGRoundedRectangularImageNode : public QSGGeometryNode
-{
- template<class T>
- static T material_cast(QSGMaterial* const material);
-
-public:
- struct Shape
- {
- QRectF rect;
- qreal radius = 0.0;
-
- constexpr bool operator ==(const Shape& b) const
- {
- return (rect == b.rect && qFuzzyCompare(radius, b.radius));
- }
-
- constexpr bool isValid() const
- {
- return (!rect.isEmpty() && std::isgreaterequal(radius, 0.0));
- }
- };
-
- QSGRoundedRectangularImageNode();
-
- // For convenience:
- QSGTextureMaterial* material() const;
- QSGOpaqueTextureMaterial* opaqueMaterial() const;
-
- void setSmooth(const bool smooth);
- void setTexture(const std::shared_ptr<QSGTexture>& texture);
-
- inline constexpr Shape shape() const
- {
- return m_shape;
- }
-
- bool setShape(const Shape& shape);
-
- inline bool rebuildGeometry()
- {
- return rebuildGeometry(m_shape);
- }
-
- bool rebuildGeometry(const Shape& shape);
-
- // Constructs a geometry denoting rounded rectangle using QPainterPath
- static QSGGeometry* rebuildGeometry(const Shape& shape,
- QSGGeometry* geometry,
- const QSGTexture* const atlasTexture = nullptr);
-
-private:
- std::shared_ptr<QSGTexture> m_texture;
- Shape m_shape;
- bool m_smooth = true;
-};
-
-#endif // QSGROUNDEDRECTANGULARIMAGENODE_HPP
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/2ea91a278f5e89dd8c7b034c8d8f6ec0a33a44ec
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/2ea91a278f5e89dd8c7b034c8d8f6ec0a33a44ec
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list