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