[vlc-commits] [Git][videolan/vlc][master] 3 commits: qt: introduce `SGManipulator`

Felix Paul Kühne (@fkuehne) gitlab at videolan.org
Fri Mar 27 08:10:01 UTC 2026



Felix Paul Kühne pushed to branch master at VideoLAN / VLC


Commits:
06233dff by Fatih Uzunoglu at 2026-03-27T08:45:36+01:00
qt: introduce `SGManipulator`

This class provides explicit control over
qt scene graph nodes.

- - - - -
28d86a45 by Fatih Uzunoglu at 2026-03-27T08:45:36+01:00
qt: register qml type `SGManipulator`

- - - - -
c6762c24 by Fatih Uzunoglu at 2026-03-27T08:45:36+01:00
qml: disable blending for video surface fade rectangles

Ideally Qt should do this optimization itself for all
bottom-most nodes, since blending is irrelevant to them.
They have no target to blend into, and these nodes can
be considered quasi-opaque, even if they are not really
opaque (as the case with the video fade rectangles here).

- - - - -


6 changed files:

- modules/gui/qt/Makefile.am
- modules/gui/qt/maininterface/mainui.cpp
- modules/gui/qt/meson.build
- modules/gui/qt/player/qml/Player.qml
- + modules/gui/qt/util/sgmanipulator.cpp
- + modules/gui/qt/util/sgmanipulator.hpp


Changes:

=====================================
modules/gui/qt/Makefile.am
=====================================
@@ -349,6 +349,8 @@ libqt_plugin_la_SOURCES = \
 	util/kirigamiwheelhandler.hpp \
 	util/textureproviderindirection.cpp \
 	util/textureproviderindirection.hpp \
+	util/sgmanipulator.cpp \
+	util/sgmanipulator.hpp \
 	widgets/native/animators.cpp \
 	widgets/native/animators.hpp \
 	widgets/native/customwidgets.cpp widgets/native/customwidgets.hpp \
@@ -508,6 +510,7 @@ nodist_libqt_plugin_la_SOURCES = \
 	util/textureproviderobserver.moc.cpp \
 	util/kirigamiwheelhandler.moc.cpp \
 	util/textureproviderindirection.moc.cpp \
+	util/sgmanipulator.moc.cpp \
 	widgets/native/animators.moc.cpp \
 	widgets/native/csdthemeimage.moc.cpp \
 	widgets/native/customwidgets.moc.cpp \


=====================================
modules/gui/qt/maininterface/mainui.cpp
=====================================
@@ -51,6 +51,7 @@
 #include "util/ui_notifier.hpp"
 #include "util/textureproviderobserver.hpp"
 #include "util/textureproviderindirection.hpp"
+#include "util/sgmanipulator.hpp"
 
 #include "dialogs/help/aboutmodel.hpp"
 #include "dialogs/dialogs_provider.hpp"
@@ -397,6 +398,7 @@ void MainUI::registerQMLTypes()
         qmlRegisterType<DoubleClickIgnoringItem>( uri, versionMajor, versionMinor, "DoubleClickIgnoringItem" );
         qmlRegisterType<TextureProviderObserver>( uri, versionMajor, versionMinor, "TextureProviderObserver" );
         qmlRegisterType<TextureProviderIndirection>( uri, versionMajor, versionMinor, "TextureProviderIndirection" );
+        qmlRegisterType<SGManipulator>( uri, versionMajor, versionMinor, "SGManipulator" );
 
         qmlRegisterModule(uri, versionMajor, versionMinor);
         qmlProtectModule(uri, versionMajor);


=====================================
modules/gui/qt/meson.build
=====================================
@@ -155,6 +155,7 @@ moc_headers = files(
     'util/textureproviderobserver.hpp',
     'util/kirigamiwheelhandler.hpp',
     'util/textureproviderindirection.hpp',
+    'util/sgmanipulator.hpp',
     'widgets/native/animators.hpp',
     'widgets/native/csdthemeimage.hpp',
     'widgets/native/customwidgets.hpp',
@@ -500,6 +501,8 @@ qt_plugin_sources = files(
     'util/kirigamiwheelhandler.hpp',
     'util/textureproviderindirection.cpp',
     'util/textureproviderindirection.hpp',
+    'util/sgmanipulator.cpp',
+    'util/sgmanipulator.hpp',
     'widgets/native/animators.cpp',
     'widgets/native/animators.hpp',
     'widgets/native/customwidgets.cpp',


=====================================
modules/gui/qt/player/qml/Player.qml
=====================================
@@ -232,7 +232,19 @@ FocusScope {
                     }
                 }
 
-                Rectangle {
+                component FadeRectangle : Rectangle {
+                    implicitHeight: VLCStyle.dp(206, VLCStyle.scale)
+
+                    SGManipulator {
+                        // The rectangle is the bottom-most item in the interface,
+                        // it does not need blending even though it is not opaque.
+                        // Since `Rectangle` does not provide explicit control over
+                        // blending, we are using `SGManipulator`:
+                        blending: false
+                    }
+                }
+
+                FadeRectangle {
                     anchors.top: parent.top
                     anchors.left: parent.left
                     anchors.right: parent.right
@@ -248,7 +260,7 @@ FocusScope {
                     }
                 }
 
-                Rectangle {
+                FadeRectangle {
                     anchors.bottom: parent.bottom
                     anchors.left: parent.left
                     anchors.right: parent.right


=====================================
modules/gui/qt/util/sgmanipulator.cpp
=====================================
@@ -0,0 +1,119 @@
+/*****************************************************************************
+ * Copyright (C) 2026 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 "sgmanipulator.hpp"
+
+#include <QSGRenderNode>
+#include <QSGGeometryNode>
+#include <QSGTransformNode>
+#include <QSGMaterial>
+
+
+SGManipulator::SGManipulator(QQuickItem *parent)
+    : QQuickItem(parent)
+{
+    setFlag(QQuickItem::ItemHasContents);
+
+    connect(this, &SGManipulator::constantUpdateChanged, this, [this](bool constantUpdate) {
+        if (constantUpdate)
+            update();
+    });
+}
+
+QJSValue SGManipulator::blending() const
+{
+    if (m_blending)
+        return *m_blending;
+    else
+        return {};
+}
+
+void SGManipulator::setBlending(const QJSValue& blending)
+{
+    if ((!m_blending && blending.isNull()) || (m_blending == blending.toBool()))
+        return;
+
+    m_blending = blending.toBool();
+
+    emit blendingChanged(blending);
+
+    update();
+}
+
+void SGManipulator::resetBlending()
+{
+    m_blending.reset();
+}
+
+QSGNode *SGManipulator::updatePaintNode(QSGNode *, UpdatePaintNodeData *data)
+{
+    assert(data);
+
+    const auto transformNode = data->transformNode;
+    assert(transformNode);
+
+    QSGNode *targetNode = nullptr;
+    QSGGeometryNode *targetGeometryNode = nullptr;
+    QSGRenderNode *targetRenderNode = nullptr;
+
+    QSGNode *i = transformNode;
+    while (i)
+    {
+        // NOTE: The target node must not be a transform node.
+        // NOTE: The transform nodes parent sibling item's rendering nodes.
+        if (dynamic_cast<QSGTransformNode*>(i))
+        {
+            i = i->previousSibling();
+            continue;
+        }
+
+        targetNode = i;
+        targetGeometryNode = dynamic_cast<QSGGeometryNode*>(i);
+        targetRenderNode = dynamic_cast<QSGRenderNode*>(i);
+
+        break;
+    }
+
+    if (targetNode)
+    {
+        if (targetGeometryNode)
+        {
+            bool materialChangeMade = false;
+
+            if (const auto material = targetGeometryNode->material())
+            {
+                if (m_blending)
+                {
+                    if (*m_blending != material->flags().testFlag(QSGMaterial::Blending))
+                    {
+                        qDebug() << "SGManipulator: Blending is overridden as" << *m_blending << "for target material" << material;
+                        material->setFlag(QSGMaterial::Blending, *m_blending);
+                        materialChangeMade = true;
+                    }
+                }
+
+                if (materialChangeMade)
+                    targetGeometryNode->markDirty(QSGNode::DirtyMaterial);
+            }
+        }
+    }
+
+    if (m_constantUpdate)
+        update(); // re-schedule an update
+
+    return nullptr;
+}


=====================================
modules/gui/qt/util/sgmanipulator.hpp
=====================================
@@ -0,0 +1,67 @@
+/*****************************************************************************
+ * Copyright (C) 2026 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 SGMANIPULATOR_H
+#define SGMANIPULATOR_H
+
+#include <QQuickItem>
+#include <QJSValue>
+
+#include <optional>
+
+// This class allows manipulating the parent item's scene graph node.
+// Visibility can be set to to false to disable manipulation.
+// It is the user's responsibility to call `QQuickItem::update()`
+// to update the settings. Currently an update is scheduled as soon
+// as a manipulating property is changed. This means that if the
+// target node is altered without the control of this class, an
+// update should be scheduled (unless `constantUpdate` is set),
+// this can be for example `Image` switching from a opaque image
+// to a translucent one, or `Rectangle` switching from a opaque
+// color to a transparent one. The same applies when the target
+// node itself changes (such as due to re-parenting).
+class SGManipulator : public QQuickItem
+{
+    Q_OBJECT
+
+    // This is not really expensive, but still avoid constant updates if possible:
+    Q_PROPERTY(bool constantUpdate MEMBER m_constantUpdate NOTIFY constantUpdateChanged FINAL)
+
+    Q_PROPERTY(QJSValue blending READ blending WRITE setBlending RESET resetBlending NOTIFY blendingChanged FINAL)
+
+    QML_ELEMENT
+
+public:
+    explicit SGManipulator(QQuickItem* parent = nullptr);
+
+    QJSValue blending() const;
+    void setBlending(const QJSValue& blending);
+    void resetBlending();
+
+signals:
+    void blendingChanged(const QJSValue&);
+    void constantUpdateChanged(bool);
+
+protected:
+    QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) override;
+
+private:
+    std::optional<bool> m_blending;
+    bool m_constantUpdate = false;
+};
+
+#endif // SGMANIPULATOR_H



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/342a1575c077c478eaa5bfa522d35ed0f1e306dd...c6762c241fd2d6c4896fa17b4de0d1f5bec41afe

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/342a1575c077c478eaa5bfa522d35ed0f1e306dd...c6762c241fd2d6c4896fa17b4de0d1f5bec41afe
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list