[vlc-commits] [Git][videolan/vlc][master] 2 commits: qt: make video surface report scale changes

Steve Lhomme (@robUx4) gitlab at videolan.org
Sat Jan 18 13:57:20 UTC 2025



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
a5efdf49 by Fatih Uzunoglu at 2025-01-18T13:44:05+00:00
qt: make video surface report scale changes

- - - - -
6151e45a by Fatih Uzunoglu at 2025-01-18T13:44:05+00:00
qt: do not use viewporter protocol if scale is not fractional and react to scale changes

- If the scale is not fractional, it is not necessary to use the viewporter protocol.
- React to scale change after initialization.

- - - - -


8 changed files:

- modules/gui/qt/maininterface/compositor.cpp
- modules/gui/qt/maininterface/compositor.hpp
- modules/gui/qt/maininterface/compositor_wayland.cpp
- modules/gui/qt/maininterface/compositor_wayland.hpp
- modules/gui/qt/maininterface/compositor_wayland_module.c
- modules/gui/qt/maininterface/compositor_wayland_module.h
- modules/gui/qt/maininterface/videosurface.cpp
- modules/gui/qt/maininterface/videosurface.hpp


Changes:

=====================================
modules/gui/qt/maininterface/compositor.cpp
=====================================
@@ -206,6 +206,8 @@ void CompositorVideo::commonSetupVoutWindow(vlc_window_t* p_wnd, VoutDestroyCb d
             this, &CompositorVideo::onSurfacePositionChanged, Qt::UniqueConnection);
     connect(m_videoSurfaceProvider.get(), &VideoSurfaceProvider::surfaceSizeChanged,
             this, &CompositorVideo::onSurfaceSizeChanged, Qt::UniqueConnection);
+    connect(m_videoSurfaceProvider.get(), &VideoSurfaceProvider::surfaceScaleChanged,
+            this, &CompositorVideo::onSurfaceScaleChanged, Qt::UniqueConnection);
 }
 
 void CompositorVideo::windowDestroy()
@@ -217,6 +219,8 @@ void CompositorVideo::windowDestroy()
                this, &CompositorVideo::onSurfacePositionChanged);
     disconnect(m_videoSurfaceProvider.get(), &VideoSurfaceProvider::surfaceSizeChanged,
                this, &CompositorVideo::onSurfaceSizeChanged);
+    disconnect(m_videoSurfaceProvider.get(), &VideoSurfaceProvider::surfaceScaleChanged,
+               this, &CompositorVideo::onSurfaceScaleChanged);
 
     if (m_destroyCb)
         m_destroyCb(m_wnd);


=====================================
modules/gui/qt/maininterface/compositor.hpp
=====================================
@@ -173,6 +173,7 @@ private slots:
 protected slots:
     virtual void onSurfacePositionChanged(const QPointF&) {}
     virtual void onSurfaceSizeChanged(const QSizeF&) {}
+    virtual void onSurfaceScaleChanged(qreal) {}
 
 protected:
     qt_intf_t *m_intf = nullptr;


=====================================
modules/gui/qt/maininterface/compositor_wayland.cpp
=====================================
@@ -17,8 +17,6 @@
  *****************************************************************************/
 #include "compositor_wayland.hpp"
 
-#include <cmath>
-
 #include "maininterface/mainctx.hpp"
 #include "maininterface/interface_window_handler.hpp"
 
@@ -117,7 +115,7 @@ bool CompositorWayland::makeMainInterface(MainCtx* mainCtx)
     if (!interfaceSurface)
         return false;
 
-    m_waylandImpl->setupInterface(m_waylandImpl, interfaceSurface, std::ceil(dprForWindow(m_qmlView.get())));
+    m_waylandImpl->setupInterface(m_waylandImpl, interfaceSurface, dprForWindow(m_qmlView.get()));
 
     CompositorVideo::Flags flags = CompositorVideo::CAN_SHOW_PIP | CompositorVideo::HAS_ACRYLIC;
 
@@ -238,6 +236,13 @@ void CompositorWayland::onSurfaceSizeChanged(const QSizeF& size)
                         size.height() / nativeDpr);
 }
 
+void CompositorWayland::onSurfaceScaleChanged(qreal dpr)
+{
+    assert(m_waylandImpl);
+
+    m_waylandImpl->rescale(m_waylandImpl, dpr);
+}
+
 #ifdef QT_WAYLAND_HAS_CUSTOM_MARGIN_SUPPORT
 void CompositorWayland::adjustQuickWindowMask()
 {


=====================================
modules/gui/qt/maininterface/compositor_wayland.hpp
=====================================
@@ -81,6 +81,7 @@ public:
 protected slots:
     void onSurfacePositionChanged(const QPointF&) override;
     void onSurfaceSizeChanged(const QSizeF&) override;
+    void onSurfaceScaleChanged(qreal) override;
 #ifdef QT_WAYLAND_HAS_CUSTOM_MARGIN_SUPPORT
     void adjustQuickWindowMask();
 #endif


=====================================
modules/gui/qt/maininterface/compositor_wayland_module.c
=====================================
@@ -29,7 +29,9 @@
 #include "viewporter-client-protocol.h"
 #endif
 
+#include <math.h>
 #include <assert.h>
+#include <float.h>
 
 typedef struct
 {
@@ -49,6 +51,13 @@ typedef struct
     struct wl_subsurface* video_subsurface;
 
     int buffer_scale;
+    bool fractional_scale;
+
+    // Store the size, because we need them
+    // if the scale changes (if fractional)
+    // to update the viewport:
+    int width;
+    int height;
 
     uint32_t compositor_interface_version;
 } qtwayland_priv_t;
@@ -84,43 +93,97 @@ static const struct wl_registry_listener registry_cbs = {
     registry_global_remove_cb,
 };
 
-static int SetupInterface(qtwayland_t* obj, void* qpni_interface_surface, int scale)
+static void SetSize(struct qtwayland_t* obj, size_t width, size_t height)
 {
-    qtwayland_priv_t* sys = (qtwayland_priv_t*)obj->p_sys;
+    assert(obj);
+    qtwayland_priv_t* const sys = (qtwayland_priv_t*)obj->p_sys;
+    assert(sys);
 
-    if (! qpni_interface_surface)
-        return VLC_EGENERIC;
+    sys->width = width;
+    sys->height = height;
+}
 
-    sys->interface_surface = (struct wl_surface*)qpni_interface_surface;
-    sys->buffer_scale = scale;
+static void CommitSize(struct qtwayland_t* obj)
+{
+#ifdef QT_HAS_WAYLAND_FRACTIONAL_SCALING
+    assert(obj);
+    const qtwayland_priv_t* const sys = (qtwayland_priv_t*)obj->p_sys;
+    assert(sys);
+    if (!sys->video_surface)
+        return;
+    if (sys->viewport)
+    {
+        // Non-positive size (except (-1, -1) pair) causes protocol error:
+        assert((sys->width > 0 && sys->height > 0) ||
+               (sys->height == -1 && sys->width == -1));
 
-    return VLC_SUCCESS;
+        // width and height here represent the final size, after scaling
+        // is taken into account. The fractional scaling protocol is not
+        // necessary, because the (fractional) scale is retrieved from the
+        // Qt Quick window which uses the fractional scale protocol itself
+        // to determine the device pixel ratio.
+        wp_viewport_set_destination(sys->viewport, sys->width, sys->height);
+        wl_surface_commit(sys->video_surface);
+    }
+#endif
 }
 
-
-static int SetupVoutWindow(qtwayland_t* obj, vlc_window_t* wnd)
+static void SetScale(struct qtwayland_t* obj, double scale)
 {
+    assert(obj);
     qtwayland_priv_t* sys = (qtwayland_priv_t*)obj->p_sys;
+    assert(sys);
 
-    sys->video_surface = wl_compositor_create_surface(sys->compositor);
-    if (!sys->video_surface)
-        return VLC_EGENERIC;
+    // Determine if scale is fractional:
+    assert(scale > 0.0);
+    sys->buffer_scale = ceil(scale);
 
-#ifdef QT_HAS_WAYLAND_FRACTIONAL_SCALING
-    if (sys->viewporter)
-        sys->viewport = wp_viewporter_get_viewport(sys->viewporter, sys->video_surface);
+    if ((sys->buffer_scale - scale) < DBL_EPSILON)
+        sys->fractional_scale = false;
     else
-#endif
+        sys->fractional_scale = true;
+}
+
+static void CommitScale(struct qtwayland_t* obj)
+{
+    assert(obj);
+    qtwayland_priv_t* const sys = (qtwayland_priv_t*)obj->p_sys;
+    assert(sys);
+
+    // Once the scale becomes fractional, viewport is used.
+    // If the scale becomes an integer number after that,
+    // viewport is still used.
+    if (sys->fractional_scale)
     {
-        // The buffer scale must remain 1 when fractional scaling is used
-        if (sys->buffer_scale != 1)
+#ifdef QT_HAS_WAYLAND_FRACTIONAL_SCALING
+        if (sys->viewporter)
+        {
+            if (!sys->viewport)
+            {
+                sys->viewport = wp_viewporter_get_viewport(sys->viewporter, sys->video_surface);
+
+                // The buffer scale must remain 1 when fractional scaling is used:
+                // If compositor has viewport support, it should be at least version 3:
+                if (likely(sys->compositor_interface_version >= 3))
+                {
+                    wl_surface_set_buffer_scale(sys->video_surface, 1);
+                    wl_surface_commit(sys->video_surface);
+                }
+
+                // Started using viewport, commit size so that viewport destination is set:
+                CommitSize(obj);
+            }
+        }
+        else
+#endif
         {
             msg_Dbg(obj, "Viewporter protocol is not available or Qt version is less than " \
-                         "6.5.0, and scale is not 1. Only integer scaling may be possible.");
+                         "6.5.0, and scale is fractional. Only integer scaling may be possible.");
 
             if (sys->compositor_interface_version >= 3)
             {
                 wl_surface_set_buffer_scale(sys->video_surface, sys->buffer_scale);
+                wl_surface_commit(sys->video_surface);
             }
             else
             {
@@ -129,6 +192,51 @@ static int SetupVoutWindow(qtwayland_t* obj, vlc_window_t* wnd)
             }
         }
     }
+    else
+    {
+#ifdef QT_HAS_WAYLAND_FRACTIONAL_SCALING
+        // Scale is not fractional, but if viewport has been initialized before, keep using it:
+        if (!sys->viewport)
+#endif
+        {
+            if (sys->compositor_interface_version >= 3)
+            {
+                wl_surface_set_buffer_scale(sys->video_surface, sys->buffer_scale);
+                wl_surface_commit(sys->video_surface);
+            }
+            else
+            {
+                msg_Dbg(obj, "Compositor interface version is below 3, integer scaling " \
+                             "is not possible.");
+            }
+        }
+    }
+}
+
+static int SetupInterface(qtwayland_t* obj, void* qpni_interface_surface, double scale)
+{
+    qtwayland_priv_t* sys = (qtwayland_priv_t*)obj->p_sys;
+
+    if (! qpni_interface_surface)
+        return VLC_EGENERIC;
+
+    sys->interface_surface = (struct wl_surface*)qpni_interface_surface;
+
+    SetScale(obj, scale);
+
+    return VLC_SUCCESS;
+}
+
+
+static int SetupVoutWindow(qtwayland_t* obj, vlc_window_t* wnd)
+{
+    qtwayland_priv_t* sys = (qtwayland_priv_t*)obj->p_sys;
+
+    sys->video_surface = wl_compositor_create_surface(sys->compositor);
+    if (!sys->video_surface)
+        return VLC_EGENERIC;
+
+    CommitScale(obj);
 
     struct wl_region* region = wl_compositor_create_region(sys->compositor);
     if (!region)
@@ -205,22 +313,52 @@ static void Move(struct qtwayland_t* obj, int x, int y)
 
 static void Resize(struct qtwayland_t* obj, size_t width, size_t height)
 {
-#ifdef QT_HAS_WAYLAND_FRACTIONAL_SCALING
+    assert(obj);
     qtwayland_priv_t* sys = (qtwayland_priv_t*)obj->p_sys;
     assert(sys);
-    if (!sys->video_surface)
-        return;
-    if (sys->viewport)
+
+    bool commitNecessary = false;
+
     {
-        // width and height here represent the final size, after scaling
-        // is taken into account. The fractional scaling protocol is not
-        // necessary, because the (fractional) scale is retrieved from the
-        // Qt Quick window which uses the fractional scale protocol itself
-        // to determine the device pixel ratio.
-        wp_viewport_set_destination(sys->viewport, width, height);
-        wl_surface_commit(sys->video_surface);
+        // Do not directly compare, because SetSize may not directly use size as is
+        const int oldWidth = sys->width;
+        const int oldHeight = sys->height;
+
+        SetSize(obj, width, height);
+
+        if (oldWidth != sys->width)
+            commitNecessary = true;
+        else if (oldHeight != sys->height)
+            commitNecessary = true;
     }
-#endif
+
+    if (commitNecessary)
+        CommitSize(obj);
+}
+
+
+static void Rescale(struct qtwayland_t* obj, double scale)
+{
+    assert(obj);
+    qtwayland_priv_t* sys = (qtwayland_priv_t*)obj->p_sys;
+    assert(sys);
+
+    bool commitNecessary = false;
+
+    {
+        const int oldBufferScale = sys->buffer_scale;
+        const bool oldFractionalScale = sys->fractional_scale;
+
+        SetScale(obj, scale);
+
+        if (oldBufferScale != sys->buffer_scale)
+            commitNecessary = true;
+        else if (oldFractionalScale != sys->fractional_scale)
+            commitNecessary = true;
+    }
+
+    if (commitNecessary)
+        CommitScale(obj);
 }
 
 static void Close(qtwayland_t* obj)
@@ -318,6 +456,7 @@ int OpenCompositor(vlc_object_t* p_this)
     obj->disable = Disable;
     obj->move = Move;
     obj->resize = Resize;
+    obj->rescale = Rescale;
 
     obj->p_sys = sys;
 


=====================================
modules/gui/qt/maininterface/compositor_wayland_module.h
=====================================
@@ -30,7 +30,7 @@ typedef struct qtwayland_t
 
     bool (*init)(struct qtwayland_t*, void* display);
 
-    int (*setupInterface)(struct qtwayland_t*, void* video_surface, int scale);
+    int (*setupInterface)(struct qtwayland_t*, void* video_surface, double scale);
 
     int (*setupVoutWindow)(struct qtwayland_t*, vlc_window_t* p_wnd);
     void (*teardownVoutWindow)(struct qtwayland_t*);
@@ -39,6 +39,7 @@ typedef struct qtwayland_t
     void (*disable)(struct qtwayland_t*);
     void (*move)(struct qtwayland_t*, int x, int y);
     void (*resize)(struct qtwayland_t*, size_t width, size_t height);
+    void (*rescale)(struct qtwayland_t*, double scale);
 
     void (*close)(struct qtwayland_t*);
 } qtwayland_t;


=====================================
modules/gui/qt/maininterface/videosurface.cpp
=====================================
@@ -327,7 +327,9 @@ void VideoSurface::updatePolish()
 {
     QQuickItem::updatePolish();
 
-    if (m_sizeDirty)
+    assert(window());
+
+    if (m_sizeDirty && !size().isEmpty())
     {
         emit surfaceSizeChanged(size() * window()->effectiveDevicePixelRatio());
         m_sizeDirty = false;
@@ -340,6 +342,22 @@ void VideoSurface::updatePolish()
         emit surfacePositionChanged(scenePosition * window()->effectiveDevicePixelRatio());
         m_positionDirty = false;
     }
+
+    if (m_scaleDirty)
+    {
+        emit surfaceScaleChanged(window()->effectiveDevicePixelRatio());
+        m_scaleDirty = false;
+    }
+}
+
+void VideoSurface::itemChange(ItemChange change, const ItemChangeData &value)
+{
+    if (change == ItemDevicePixelRatioHasChanged || change == ItemSceneChange)
+    {
+        updateSurfaceScale();
+    }
+
+    QQuickItem::itemChange(change, value);
 }
 
 void VideoSurface::updateSurfacePosition()
@@ -354,10 +372,17 @@ void VideoSurface::updateSurfaceSize()
     polish();
 }
 
-void VideoSurface::updateSurfacePositionAndSize()
+void VideoSurface::updateSurfaceScale()
+{
+    m_scaleDirty = true;
+    polish();
+}
+
+void VideoSurface::updateSurface()
 {
     updateSurfacePosition();
     updateSurfaceSize();
+    updateSurfaceScale();
 }
 
 void VideoSurface::setVideoSurfaceProvider(VideoSurfaceProvider *newVideoSurfaceProvider)
@@ -381,12 +406,13 @@ void VideoSurface::setVideoSurfaceProvider(VideoSurfaceProvider *newVideoSurface
         connect(this, &VideoSurface::keyPressed, m_provider, &VideoSurfaceProvider::onKeyPressed);
         connect(this, &VideoSurface::surfaceSizeChanged, m_provider, &VideoSurfaceProvider::onSurfaceSizeChanged);
         connect(this, &VideoSurface::surfacePositionChanged, m_provider, &VideoSurfaceProvider::surfacePositionChanged);
+        connect(this, &VideoSurface::surfaceScaleChanged, m_provider, &VideoSurfaceProvider::surfaceScaleChanged);
 
         connect(m_wheelEventConverter, &WheelToVLCConverter::vlcWheelKey, m_provider, &VideoSurfaceProvider::onMouseWheeled);
-        connect(m_provider, &VideoSurfaceProvider::videoEnabledChanged, this, &VideoSurface::updateSurfacePositionAndSize);
+        connect(m_provider, &VideoSurfaceProvider::videoEnabledChanged, this, &VideoSurface::updateSurface);
 
         setFlag(ItemHasContents, true);
-        updateSurfacePositionAndSize(); // Polish is queued anyway, updatePolish() should be called when the initial size is set.
+        updateSurface(); // Polish is queued anyway, updatePolish() should be called when the initial size is set.
     }
     else
     {


=====================================
modules/gui/qt/maininterface/videosurface.hpp
=====================================
@@ -77,6 +77,7 @@ signals:
     bool hasVideoEmbedChanged(bool);
     void surfacePositionChanged(QPointF position);
     void surfaceSizeChanged(QSizeF size);
+    void surfaceScaleChanged(qreal);
 
 public slots:
     void onWindowClosed();
@@ -126,9 +127,12 @@ protected:
 
     void updatePolish() override;
 
+    void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) override;
+
 signals:
     void surfaceSizeChanged(QSizeF);
     void surfacePositionChanged(QPointF);
+    void surfaceScaleChanged(qreal);
 
     void mousePressed( int vlcButton );
     void mouseReleased( int vlcButton );
@@ -141,7 +145,8 @@ signals:
 protected slots:
     void updateSurfacePosition();
     void updateSurfaceSize();
-    void updateSurfacePositionAndSize();
+    void updateSurfaceScale();
+    void updateSurface();
 
     void updateParentChanged();
 
@@ -156,6 +161,7 @@ private:
 
     bool m_sizeDirty = false;
     bool m_positionDirty = false;
+    bool m_scaleDirty = false;
 };
 
 #endif // VIDEOSURFACE_HPP



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/c978d50db67ad19d3739bc184d07ff1af47cd3c0...6151e45a15958f7a804ea3f3245591b211975be1

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/c978d50db67ad19d3739bc184d07ff1af47cd3c0...6151e45a15958f7a804ea3f3245591b211975be1
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