Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
161743f3 by Fatih Uzunoglu at 2026-01-08T14:04:19+00:00
qt: make it possible to disable rendering in `ViewBlockingRectangle`

This allows to not create a scene graph node that is responsible for
rendering the color provided, which is also responsible for preventing*
things getting rendered behind due to depth test thanks to disabled
blending making the primitive treated as opaque by Qt batch renderer.

(*) only with rhi, in software mode we actually clear what is rendered
behind. This is the reason `ViewBlockingRectangle` is only functional
with depth buffer with rhi.

- - - - -
d212c67b by Fatih Uzunoglu at 2026-01-08T14:04:19+00:00
qml: disable rendering (view blocking) in `VideoSurface` of `Player`

- - - - -
b27332d3 by Fatih Uzunoglu at 2026-01-08T14:04:19+00:00
qt: make updating render position an opt-in feature in `ViewBlockingRectangle`

This is mostly relevant for `VideoSurface`, as it is totally unnecessary to
create a new scene graph node to update the render position otherwise at the
moment, such as with `AcrylicBackground` or threaded rendering is not active.

On the other hand, updating render size is trivial and it is continued to be
updated at all times.

- - - - -


4 changed files:

- modules/gui/qt/maininterface/videosurface.cpp
- modules/gui/qt/player/qml/Player.qml
- modules/gui/qt/widgets/native/viewblockingrectangle.cpp
- modules/gui/qt/widgets/native/viewblockingrectangle.hpp


Changes:

=====================================
modules/gui/qt/maininterface/videosurface.cpp
=====================================
@@ -430,5 +430,18 @@ QSGNode *VideoSurface::updatePaintNode(QSGNode *node, 
UpdatePaintNodeData *data)
         m_videoEnabledChanged = false;
     }
 
+    if (QThread::currentThread() == thread())
+    {
+        // As per `::synchronize()` we do not need `ViewBlockingRectangle` to 
provide the render position in this case:
+        setUpdateRenderPosition(false);
+        // Override `ViewBlockingRectangle`'s `ItemHasContents`, if it is 
unset (when both `renderEnabled` and
+        // `updateRenderPosition()` are false):
+        setFlag(ItemHasContents, true);
+    }
+    else
+    {
+        setUpdateRenderPosition(true);
+    }
+
     return ViewBlockingRectangle::updatePaintNode(node, data);
 }


=====================================
modules/gui/qt/player/qml/Player.qml
=====================================
@@ -195,6 +195,12 @@ FocusScope {
 
                     anchors.fill: parent
 
+                    // With regard to `ViewBlockingRectangle`, we
+                    // do not need to prevent painting anything
+                    // behind because there is already nothing
+                    // behind (unlike pip player):
+                    renderingEnabled: false
+
                     videoSurfaceProvider: MainCtx.videoSurfaceProvider
 
                     visible: MainCtx.hasEmbededVideo


=====================================
modules/gui/qt/widgets/native/viewblockingrectangle.cpp
=====================================
@@ -93,7 +93,8 @@ ViewBlockingRectangle::ViewBlockingRectangle(QQuickItem 
*parent)
     : QQuickItem(parent)
     , m_color(Qt::transparent)
 {
-    setFlag(QQuickItem::ItemHasContents);
+    if (m_renderingEnabled || m_updateRenderPosition)
+        setFlag(QQuickItem::ItemHasContents);
     connect(this, &ViewBlockingRectangle::colorChanged, this, 
&QQuickItem::update);
     connect(this, &ViewBlockingRectangle::windowChanged, this, [this] {
         if (window())
@@ -113,16 +114,33 @@ QSGNode *ViewBlockingRectangle::updatePaintNode(QSGNode 
*oldNode, UpdatePaintNod
     assert(window());
     const bool softwareMode = (window()->rendererInterface()->graphicsApi() == 
QSGRendererInterface::GraphicsApi::Software);
 
-    if (Q_UNLIKELY(oldNode && ((softwareMode && !softwareRenderNode)
-                               || (!softwareMode && !rectangleNode))))
+    if (m_renderingEnabled)
     {
-        delete oldNode;
-        oldNode = nullptr;
+        if (Q_UNLIKELY(oldNode && ((softwareMode && !softwareRenderNode)
+                                   || (!softwareMode && !rectangleNode))))
+        {
+            delete oldNode;
+            oldNode = nullptr;
+        }
     }
-
-    if (!oldNode)
+    else
     {
-        const auto observerNode = new MatrixChangeObserverNode([p = 
QPointer(this)](const QMatrix4x4& matrix) {
+        if (rectangleNode || softwareRenderNode || (!m_updateRenderPosition && 
oldNode))
+        {
+            // If `m_updateRenderPosition` is true, new node will be the 
observer node,
+            // otherwise, we early return as a scene graph node is not 
necessary.
+            // Currently we are not reparenting the observer node that could 
be reused
+            // otherwise.
+            delete oldNode;
+            oldNode = nullptr;
+        }
+
+        if (!m_updateRenderPosition)
+            return nullptr;
+    }
+
+    const auto createObserverNode = [this]() {
+        const auto node = new MatrixChangeObserverNode([p = 
QPointer(this)](const QMatrix4x4& matrix) {
             if (Q_LIKELY(p))
             {
                 p->m_renderPosition = {matrix.row(0)[3], // Viewport/scene X
@@ -130,35 +148,80 @@ QSGNode *ViewBlockingRectangle::updatePaintNode(QSGNode 
*oldNode, UpdatePaintNod
                 emit p->scenePositionHasChanged();
             }
         });
-        observerNode->setFlag(QSGNode::OwnedByParent);
+        node->setFlag(QSGNode::OwnedByParent);
+        return node;
+    };
 
-        // Initial position:
-        m_renderPosition = mapToScene(QPointF(0,0));
+    if (!oldNode)
+    {
+        MatrixChangeObserverNode *observerNode;
 
-        if (softwareMode)
+        if (m_updateRenderPosition)
         {
-            softwareRenderNode = new SoftwareRenderNode;
-            softwareRenderNode->setWindow(window());
-            softwareRenderNode->appendChildNode(observerNode);
+            observerNode = createObserverNode();
         }
         else
         {
-            rectangleNode = window()->createRectangleNode();
-            assert(rectangleNode);
-            rectangleNode->appendChildNode(observerNode);
+            observerNode = nullptr;
+        }
 
-            const auto material = rectangleNode->material();
-            if (!material ||
-                material == reinterpret_cast<QSGMaterial*>(1) /* Qt may 
explicitly set the material pointer to 1 in OpenVG */)
+        // Initial position:
+        m_renderPosition = mapToScene(QPointF(0,0));
+
+        if (m_renderingEnabled)
+        {
+            if (softwareMode)
             {
-                // Scene graph adaptation does not support shading
-                qmlDebug(this) << "ViewBlockingRectangle is being used under 
an incompatible scene graph adaptation.";
-                delete rectangleNode;
-                setFlag(QQuickItem::ItemHasContents, false);
-                return nullptr;
+                softwareRenderNode = new SoftwareRenderNode;
+                softwareRenderNode->setWindow(window());
+                if (observerNode)
+                    softwareRenderNode->appendChildNode(observerNode);
             }
+            else
+            {
+                rectangleNode = window()->createRectangleNode();
+                assert(rectangleNode);
+                if (observerNode)
+                    rectangleNode->appendChildNode(observerNode);
+
+                const auto material = rectangleNode->material();
+                if (!material ||
+                    material == reinterpret_cast<QSGMaterial*>(1) /* Qt may 
explicitly set the material pointer to 1 in OpenVG */)
+                {
+                    // Scene graph adaptation does not support shading
+                    qmlDebug(this) << "ViewBlockingRectangle is being used 
under an incompatible scene graph adaptation.";
+                    delete rectangleNode;
+                    setFlag(QQuickItem::ItemHasContents, false);
+                    return nullptr;
+                }
 
-            rectangleNode->material()->setFlag(QSGMaterial::Blending, false);
+                rectangleNode->material()->setFlag(QSGMaterial::Blending, 
false);
+            }
+        }
+        else if (observerNode)
+        {
+            oldNode = observerNode;
+        }
+    }
+    else if (m_renderingEnabled)
+    {
+        const auto observerNode = oldNode->childAtIndex(0);
+
+        if (m_updateRenderPosition)
+        {
+            if (!observerNode)
+            {
+                oldNode->appendChildNode(createObserverNode());
+            }
+        }
+        else
+        {
+            if (observerNode)
+            {
+                assert(dynamic_cast<MatrixChangeObserverNode*>(observerNode));
+                observerNode->setFlag(QSGNode::OwnedByParent, false); // this 
may not be necessary
+                delete observerNode;
+            }
         }
     }
 
@@ -166,32 +229,48 @@ QSGNode *ViewBlockingRectangle::updatePaintNode(QSGNode 
*oldNode, UpdatePaintNod
 
     m_renderSize = rect.size();
 
-    if (softwareMode)
+    if (m_renderingEnabled)
     {
-        softwareRenderNode->setRect(rect);
-        softwareRenderNode->setColor(m_color);
-
-        if (Q_UNLIKELY(m_windowChanged))
+        if (softwareMode)
         {
-            softwareRenderNode->setWindow(window());
-            m_windowChanged = false;
+            softwareRenderNode->setRect(rect);
+            softwareRenderNode->setColor(m_color);
+
+            if (Q_UNLIKELY(m_windowChanged))
+            {
+                softwareRenderNode->setWindow(window());
+                m_windowChanged = false;
+            }
+
+            return softwareRenderNode;
         }
+        else
+        {
+            if (rectangleNode->rect() != rect)
+                rectangleNode->setRect(rect);
 
-        return softwareRenderNode;
+            if (rectangleNode->color() != m_color)
+            {
+                rectangleNode->setColor(m_color);
+                assert(rectangleNode->material());
+                rectangleNode->material()->setFlag(QSGMaterial::Blending, 
false);
+            }
+
+            return rectangleNode;
+        }
     }
     else
     {
-        if (rectangleNode->rect() != rect)
-            rectangleNode->setRect(rect);
-
-        if (rectangleNode->color() != m_color)
+        if (m_updateRenderPosition)
         {
-            rectangleNode->setColor(m_color);
-            assert(rectangleNode->material());
-            rectangleNode->material()->setFlag(QSGMaterial::Blending, false);
+            assert(oldNode);
+            return oldNode; // observer node
+        }
+        else
+        {
+            setFlag(ItemHasContents, false);
+            return nullptr;
         }
-
-        return rectangleNode;
     }
 }
 
@@ -204,3 +283,49 @@ QPointF ViewBlockingRectangle::renderPosition() const
 {
     return m_renderPosition;
 }
+
+void ViewBlockingRectangle::setRenderingEnabled(bool enabled)
+{
+    if (m_renderingEnabled == enabled)
+        return;
+
+    m_renderingEnabled = enabled;
+
+    if (enabled)
+    {
+        setFlag(ItemHasContents, true);
+        if (isVisible())
+            update();
+    }
+    else if (!m_updateRenderPosition)
+    {
+        setFlag(ItemHasContents, false);
+    }
+
+    emit renderingEnabledChanged();
+}
+
+void ViewBlockingRectangle::setUpdateRenderPosition(bool _update)
+{
+    if (m_updateRenderPosition == _update)
+        return;
+
+    m_updateRenderPosition = _update;
+
+    if (_update)
+    {
+        setFlag(ItemHasContents, true);
+        if (isVisible())
+            update();
+    }
+    else if (!m_renderingEnabled)
+    {
+        setFlag(ItemHasContents, false);
+    }
+}
+
+bool ViewBlockingRectangle::updateRenderPosition() const
+{
+    return m_updateRenderPosition;
+}
+


=====================================
modules/gui/qt/widgets/native/viewblockingrectangle.hpp
=====================================
@@ -66,6 +66,7 @@ class ViewBlockingRectangle : public QQuickItem
     Q_OBJECT
 
     Q_PROPERTY(QColor color MEMBER m_color NOTIFY colorChanged FINAL)
+    Q_PROPERTY(bool renderingEnabled MEMBER m_renderingEnabled WRITE 
setRenderingEnabled NOTIFY renderingEnabledChanged FINAL)
 
 public:
     explicit ViewBlockingRectangle(QQuickItem *parent = nullptr);
@@ -77,11 +78,20 @@ protected:
     // These methods should only be called from the rendering thread.
     QSizeF renderSize() const;
     QPointF renderPosition() const;
+    void setRenderingEnabled(bool enabled);
+    void setUpdateRenderPosition(bool update);
+    bool updateRenderPosition() const;
 
 private:
     QColor m_color;
     bool m_windowChanged = false;
 
+    bool m_renderingEnabled = true;
+
+    // Updating the render position (`m_renderPosition`) requires an additional
+    // scene graph node, albeit lightweight, thus it is an opt-in feature:
+    bool m_updateRenderPosition = false;
+
     // Although these members belong to the class instance's thread, they
     // are updated in the rendering thread:
     QSizeF m_renderSize;
@@ -92,6 +102,7 @@ signals:
     //       and NOT during synchronization (meaning, GUI thread is not 
blocked):
     void scenePositionHasChanged();
     void colorChanged();
+    void renderingEnabledChanged();
 };
 
 #endif



View it on GitLab: 
https://code.videolan.org/videolan/vlc/-/compare/ae88d7206c802d3496f6cb41bab27e1871d1fef8...b27332d3980d4dee8a751d1e44bba3a479465b61

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


VideoLAN code repository instance
_______________________________________________
vlc-commits mailing list
[email protected]
https://mailman.videolan.org/listinfo/vlc-commits

Reply via email to