[vlc-commits] [Git][videolan/vlc][master] 5 commits: qml: fix video surface scaling

Thomas Guillem (@tguillem) gitlab at videolan.org
Wed Jan 17 14:00:37 UTC 2024



Thomas Guillem pushed to branch master at VideoLAN / VLC


Commits:
32836475 by Pierre Lamot at 2024-01-17T13:34:48+00:00
qml: fix video surface scaling

QWindow::devicePixelRatio mixes QPlateformWindow::devicePixelRatio (scale factor
from the plateform) and QHighDpiScaling::factor (QT_SCALE_FACTOR,
QT_SCREEN_SCALE_FACTORS). Platform such as wayland may have a >1 scale factor,
surface are directly scaled by the compositor, so we shouln't re-apply this
scale factor

- - - - -
8d9907bd by Pierre Lamot at 2024-01-17T13:34:48+00:00
qt: fix CompositorVideo interface release order

m_videoWindowHandler references the window, so it needs to be released before the
window is destroyed

- - - - -
a290285a by Pierre Lamot at 2024-01-17T13:34:48+00:00
qt: don't include native interface headers using QPNI_HEADER macro

we have already fixed the private headers includes for QtQuick, this patch uses
the same mechanism

- - - - -
9dc025d0 by Pierre Lamot at 2024-01-17T13:34:48+00:00
qt: add wayland support

fixes #22156

- - - - -
3c622d4c by Pierre Lamot at 2024-01-17T13:34:48+00:00
qt: reorder compositor definitions in Makefile.am

no functionnal changes

- - - - -


16 changed files:

- configure.ac
- modules/gui/qt/Makefile.am
- modules/gui/qt/maininterface/compositor.cpp
- modules/gui/qt/maininterface/compositor.hpp
- modules/gui/qt/maininterface/compositor_dcomp.cpp
- modules/gui/qt/maininterface/compositor_dcomp_uisurface.cpp
- + 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/interface_window_handler.hpp
- modules/gui/qt/maininterface/mainctx_win32.cpp
- modules/gui/qt/maininterface/video_window_handler.hpp
- modules/gui/qt/maininterface/videosurface.cpp
- modules/gui/qt/maininterface/videosurface.hpp
- modules/gui/qt/qt.cpp


Changes:

=====================================
configure.ac
=====================================
@@ -3970,6 +3970,8 @@ AC_ARG_ENABLE([qt],
 have_qt5_x11="no"
 have_qt5_gtk="no"
 have_qt5_quick_test="no"
+have_qt5_declarative_private="no"
+have_qt5_gui_private="no"
 AS_IF([test "${enable_qt}" != "no"], [
   PKG_CHECK_MODULES([QT], [Qt5Core >= 5.12.0 Qt5Widgets Qt5Gui Qt5Quick Qt5QuickWidgets Qt5QuickControls2 Qt5Svg], [
       PKG_CHECK_MODULES([QT5_X11], [Qt5X11Extras], [
@@ -4037,7 +4039,9 @@ AS_IF([test "${enable_qt}" != "no"], [
 
       AC_LANG_PUSH([C++])
       AC_CHECK_HEADERS([private/qquickitem_p.h private/qquickwindow_p.h],
-         [have_declarative_private="yes"], [])
+         [have_qt5_declarative_private="yes"], [])
+      AC_CHECK_HEADERS([QtGui/qpa/qplatformnativeinterface.h],
+         [have_qt5_gui_private="yes"], [])
       AC_LANG_POP([C++])
       VLC_RESTORE_FLAGS
 
@@ -4110,7 +4114,8 @@ AM_CONDITIONAL([ENABLE_QT], [test "$enable_qt" != "no"])
 AM_CONDITIONAL([HAVE_QT5_X11], [test "${have_qt5_x11}" = "yes"])
 AM_CONDITIONAL([HAVE_QT5_WAYLAND], [test "${have_qt5_wayland}" = "yes"])
 AM_CONDITIONAL([HAVE_QT5_GTK], [test "${have_qt5_gtk}" = "yes"])
-AM_CONDITIONAL([HAVE_QT5_DECLARATIVE_PRIVATE], [test "${have_declarative_private}" = "yes"])
+AM_CONDITIONAL([HAVE_QT5_DECLARATIVE_PRIVATE], [test "${have_qt5_declarative_private}" = "yes"])
+AM_CONDITIONAL([HAVE_QT5_GUI_PRIVATE], [test "${have_qt5_gui_private}" = "yes"])
 AM_CONDITIONAL([HAVE_QT5_QUICK_TEST], [test "${have_qt5_quick_test}" = "yes"])
 
 dnl


=====================================
modules/gui/qt/Makefile.am
=====================================
@@ -51,29 +51,15 @@ if HAVE_XCB
 libqt_plugin_la_CXXFLAGS += $(XCB_CFLAGS)  -DQT5_HAS_X11
 libqt_plugin_la_LIBADD += $(XCB_LIBS) $(X_LIBS) $(X_PRE_LIB) -lX11
 vlc_qt_check_CXXFLAGS += $(XCB_CFLAGS) -DQT5_HAS_X11
-
-if HAVE_QT5_X11
-if HAVE_XCB_DAMAGE
-if HAVE_XCB_XFIXES
-libqt_plugin_la_CXXFLAGS += -DQT5_HAS_X11_COMPOSITOR \
-	$(QT5_X11_CFLAGS) $(XCB_RENDER_CFLAGS) $(XCB_COMPOSITE_CFLAGS) $(XLCB_DAMAGE_CFLAGS) $(XCB_XFIXES_CFLAGS)
-libqt_plugin_la_LIBADD += $(QT5_X11_LIBS) $(XCB_RENDER_LIBS) $(XCB_COMPOSITE_LIBS) $(XCB_DAMAGE_LIBS) $(XCB_XFIXES_LIBS)
-endif
-endif
-endif
 endif
 
-if HAVE_WAYLAND
-libqt_plugin_la_CPPFLAGS += -DQT5_HAS_WAYLAND
-libqt_plugin_la_CXXFLAGS += $(WAYLAND_CLIENT_CFLAGS)
-libqt_plugin_la_LIBADD += $(WAYLAND_CLIENT_LIBS)
-endif
 if HAVE_QT5_WAYLAND
 libqt_plugin_la_CPPFLAGS += $(QT5_WAYLAND_CFLAGS)
 libqt_plugin_la_LIBADD += $(QT5_WAYLAND_LIBS)
 vlc_qt_check_CPPFLAGS += $(QT5_WAYLAND_CFLAGS) -DQT5_HAS_WAYLAND
 vlc_qt_check_LDADD += $(QT5_WAYLAND_LIBS)
 endif
+
 if HAVE_WIN32
 libqt_plugin_la_CXXFLAGS += $(LIBCOMCXXFLAGS)
 libqt_plugin_la_LIBADD += $(LIBCOM) -lcomctl32 -luuid -ld3d11 -ldwmapi
@@ -87,6 +73,15 @@ endif
 if HAVE_QT5_GTK
 libqt_plugin_la_CPPFLAGS += -DQT5_HAS_GTK
 endif
+
+if HAVE_QT5_GUI_PRIVATE
+libqt_plugin_la_CPPFLAGS += -DQT5_GUI_PRIVATE \
+	-I$(QT_INCLUDE_DIRECTORY)/QtCore/$(QT_VERSION) \
+	-I$(QT_INCLUDE_DIRECTORY)/QtCore/$(QT_VERSION)/QtCore \
+	-I$(QT_INCLUDE_DIRECTORY)/QtGui/$(QT_VERSION) \
+	-I$(QT_INCLUDE_DIRECTORY)/QtGui/$(QT_VERSION)/QtGui
+endif
+
 if HAVE_QT5_DECLARATIVE_PRIVATE
 libqt_plugin_la_CPPFLAGS += -DQT5_DECLARATIVE_PRIVATE \
 	-I$(QT_INCLUDE_DIRECTORY)/QtCore/$(QT_VERSION) \
@@ -349,46 +344,6 @@ libqt_plugin_la_SOURCES = \
 	widgets/native/roundimage.cpp widgets/native/roundimage.hpp widgets/native/roundimage_p.hpp \
 	widgets/native/searchlineedit.cpp widgets/native/searchlineedit.hpp \
 	widgets/native/viewblockingrectangle.cpp widgets/native/viewblockingrectangle.hpp
-if HAVE_WIN32
-libqt_plugin_la_SOURCES += \
-	maininterface/mainctx_win32.cpp \
-	maininterface/mainctx_win32.hpp \
-	maininterface/compositor_win7.cpp \
-	maininterface/compositor_win7.hpp \
-	style/windowsthemeprovider.cpp
-
-if HAVE_DCOMP
-libqt_plugin_la_SOURCES += \
-	maininterface/compositor_dcomp.cpp \
-	maininterface/compositor_dcomp.hpp \
-	maininterface/compositor_dcomp_error.hpp \
-	maininterface/compositor_dcomp_acrylicsurface.hpp \
-	maininterface/compositor_dcomp_acrylicsurface.cpp \
-	maininterface/compositor_dcomp_uisurface.cpp \
-	maininterface/compositor_dcomp_uisurface.hpp
-endif
-
-endif
-
-if HAVE_QT5_X11
-if HAVE_XCB
-if HAVE_XCB_DAMAGE
-if HAVE_XCB_XFIXES
-libqt_plugin_la_SOURCES += \
-	maininterface/compositor_x11.cpp \
-	maininterface/compositor_x11.hpp \
-	maininterface/compositor_x11_renderclient.cpp \
-	maininterface/compositor_x11_renderclient.hpp \
-	maininterface/compositor_x11_renderwindow.cpp \
-	maininterface/compositor_x11_renderwindow.hpp \
-	maininterface/compositor_x11_uisurface.cpp \
-	maininterface/compositor_x11_uisurface.hpp \
-	maininterface/compositor_x11_utils.cpp \
-	maininterface/compositor_x11_utils.hpp
-endif
-endif
-endif
-endif
 
 # Meta-object compilation
 
@@ -531,57 +486,128 @@ nodist_libqt_plugin_la_SOURCES = \
 	widgets/native/searchlineedit.moc.cpp \
 	widgets/native/viewblockingrectangle.moc.cpp
 
+nodist_libqt_plugin_la_SOURCES += \
+	dialogs/extended/ui_equalizer.h \
+	dialogs/extended/ui_video_effects.h \
+	dialogs/fingerprint/ui_fingerprintdialog.h \
+	dialogs/firstrun/ui_firstrunwizard.h \
+	dialogs/help/ui_about.h \
+	dialogs/help/ui_update.h \
+	dialogs/messages/ui_messages_panel.h \
+	dialogs/open/ui_open.h \
+	dialogs/open/ui_open_capture.h \
+	dialogs/open/ui_open_disk.h \
+	dialogs/open/ui_open_file.h \
+	dialogs/open/ui_open_net.h \
+	dialogs/podcast/ui_podcast_configuration.h \
+	dialogs/preferences/ui_sprefs_audio.h \
+	dialogs/preferences/ui_sprefs_input.h \
+	dialogs/preferences/ui_sprefs_interface.h \
+	dialogs/preferences/ui_sprefs_medialibrary.h \
+	dialogs/preferences/ui_sprefs_subtitles.h \
+	dialogs/preferences/ui_sprefs_video.h \
+	dialogs/sout/ui_profiles.h \
+	dialogs/sout/ui_sout.h \
+	dialogs/vlm/ui_vlm.h
+
+
+# windows compositor
+
 if HAVE_WIN32
+
+libqt_plugin_la_SOURCES += \
+	maininterface/mainctx_win32.cpp \
+	maininterface/mainctx_win32.hpp \
+	maininterface/compositor_win7.cpp \
+	maininterface/compositor_win7.hpp \
+	style/windowsthemeprovider.cpp
+
 nodist_libqt_plugin_la_SOURCES += maininterface/mainctx_win32.moc.cpp \
 	maininterface/compositor_win7.moc.cpp
 
 if HAVE_DCOMP
+libqt_plugin_la_SOURCES += \
+	maininterface/compositor_dcomp.cpp \
+	maininterface/compositor_dcomp.hpp \
+	maininterface/compositor_dcomp_error.hpp \
+	maininterface/compositor_dcomp_acrylicsurface.hpp \
+	maininterface/compositor_dcomp_acrylicsurface.cpp \
+	maininterface/compositor_dcomp_uisurface.cpp \
+	maininterface/compositor_dcomp_uisurface.hpp
+
 nodist_libqt_plugin_la_SOURCES += \
 	maininterface/compositor_dcomp_acrylicsurface.moc.cpp \
 	maininterface/compositor_dcomp.moc.cpp \
 	maininterface/compositor_dcomp_uisurface.moc.cpp
-endif
 
 endif
+endif
+
+# X11 compositor
 
 if HAVE_QT5_X11
 if HAVE_XCB
 if HAVE_XCB_DAMAGE
 if HAVE_XCB_XFIXES
+
+libqt_plugin_la_CXXFLAGS += -DQT5_HAS_X11_COMPOSITOR \
+	$(QT5_X11_CFLAGS) $(XCB_RENDER_CFLAGS) $(XCB_COMPOSITE_CFLAGS) $(XLCB_DAMAGE_CFLAGS) $(XCB_XFIXES_CFLAGS)
+
+libqt_plugin_la_LIBADD += $(QT5_X11_LIBS) $(XCB_RENDER_LIBS) $(XCB_COMPOSITE_LIBS) $(XCB_DAMAGE_LIBS) $(XCB_XFIXES_LIBS)
+
+libqt_plugin_la_SOURCES += \
+	maininterface/compositor_x11.cpp \
+	maininterface/compositor_x11.hpp \
+	maininterface/compositor_x11_renderclient.cpp \
+	maininterface/compositor_x11_renderclient.hpp \
+	maininterface/compositor_x11_renderwindow.cpp \
+	maininterface/compositor_x11_renderwindow.hpp \
+	maininterface/compositor_x11_uisurface.cpp \
+	maininterface/compositor_x11_uisurface.hpp \
+	maininterface/compositor_x11_utils.cpp \
+	maininterface/compositor_x11_utils.hpp
+
 nodist_libqt_plugin_la_SOURCES += \
 	maininterface/compositor_x11.moc.cpp \
 	maininterface/compositor_x11_renderclient.moc.cpp \
 	maininterface/compositor_x11_renderwindow.moc.cpp \
 	maininterface/compositor_x11_uisurface.moc.cpp \
 	maininterface/compositor_x11_utils.moc.cpp
+
 endif
 endif
 endif
 endif
 
+# wayland compositor
+
+if HAVE_WAYLAND
+if HAVE_QT5_WAYLAND
+if HAVE_QT5_GUI_PRIVATE
+
+libqt_plugin_la_CPPFLAGS += -DQT5_HAS_WAYLAND_COMPOSITOR
+
+libqt_plugin_la_SOURCES += \
+	maininterface/compositor_wayland.cpp \
+	maininterface/compositor_wayland.hpp
+
+
 nodist_libqt_plugin_la_SOURCES += \
-	dialogs/extended/ui_equalizer.h \
-	dialogs/extended/ui_video_effects.h \
-	dialogs/fingerprint/ui_fingerprintdialog.h \
-	dialogs/firstrun/ui_firstrunwizard.h \
-	dialogs/help/ui_about.h \
-	dialogs/help/ui_update.h \
-	dialogs/messages/ui_messages_panel.h \
-	dialogs/open/ui_open.h \
-	dialogs/open/ui_open_capture.h \
-	dialogs/open/ui_open_disk.h \
-	dialogs/open/ui_open_file.h \
-	dialogs/open/ui_open_net.h \
-	dialogs/podcast/ui_podcast_configuration.h \
-	dialogs/preferences/ui_sprefs_audio.h \
-	dialogs/preferences/ui_sprefs_input.h \
-	dialogs/preferences/ui_sprefs_interface.h \
-	dialogs/preferences/ui_sprefs_medialibrary.h \
-	dialogs/preferences/ui_sprefs_subtitles.h \
-	dialogs/preferences/ui_sprefs_video.h \
-	dialogs/sout/ui_profiles.h \
-	dialogs/sout/ui_sout.h \
-	dialogs/vlm/ui_vlm.h
+	maininterface/compositor_wayland.moc.cpp
+
+libqt_wayland_plugin_la_CFLAGS = $(AM_CFLAGS) $(WAYLAND_CLIENT_CFLAGS)
+libqt_wayland_plugin_la_LIBADD =  $(WAYLAND_CLIENT_LIBS)
+libqt_wayland_plugin_la_SOURCES = \
+	maininterface/compositor_wayland_module.c \
+	maininterface/compositor_wayland_module.h
+
+if ENABLE_QT
+gui_LTLIBRARIES += libqt_wayland_plugin.la
+endif
+
+endif
+endif
+endif
 
 # User interface compilation
 


=====================================
modules/gui/qt/maininterface/compositor.cpp
=====================================
@@ -32,6 +32,10 @@
 #  include "compositor_win7.hpp"
 #endif
 
+#ifdef QT5_HAS_WAYLAND_COMPOSITOR
+#  include "compositor_wayland.hpp"
+#endif
+
 #ifdef QT5_HAS_X11_COMPOSITOR
 #  include "compositor_x11.hpp"
 #endif
@@ -61,6 +65,9 @@ struct {
 #endif
     {"win7", &instanciateCompositor<CompositorWin7>, &preInit<CompositorWin7> },
 #endif
+#ifdef QT5_HAS_WAYLAND_COMPOSITOR
+    {"wayland", &instanciateCompositor<CompositorWayland>, &preInit<CompositorWayland> },
+#endif
 #ifdef QT5_HAS_X11_COMPOSITOR
     {"x11", &instanciateCompositor<CompositorX11>, &preInit<CompositorX11> },
 #endif
@@ -309,7 +316,7 @@ void CompositorVideo::commonGUIDestroy()
 
 void CompositorVideo::commonIntfDestroy()
 {
-    unloadGUI();
     m_videoWindowHandler.reset();
     m_videoSurfaceProvider.reset();
+    unloadGUI();
 }


=====================================
modules/gui/qt/maininterface/compositor.hpp
=====================================
@@ -58,7 +58,8 @@ public:
         DummyCompositor,
         Win7Compositor,
         DirectCompositionCompositor,
-        X11Compositor
+        X11Compositor,
+        WaylandCompositor
     };
 
     typedef void (*VoutDestroyCb)(vlc_window_t *p_wnd);


=====================================
modules/gui/qt/maininterface/compositor_dcomp.cpp
=====================================
@@ -37,7 +37,11 @@
 #include <QOpenGLFramebufferObject>
 #include <QOpenGLExtraFunctions>
 
-#include QPNI_HEADER
+#ifndef QT5_GUI_PRIVATE
+#warning "qplatformnativeinterface.h header is required for DirectComposiiton compositor"
+#endif
+#include <QtGui/qpa/qplatformnativeinterface.h>
+
 #include "compositor_dcomp_error.hpp"
 #include "maininterface/interface_window_handler.hpp"
 


=====================================
modules/gui/qt/maininterface/compositor_dcomp_uisurface.cpp
=====================================
@@ -27,7 +27,10 @@
 #include <QQmlEngine>
 #include <QQuickItem>
 
-#include QPNI_HEADER
+#ifndef QT5_GUI_PRIVATE
+#warning "qplatformnativeinterface.h header is required for DirectComposiiton compositor"
+#endif
+#include <QtGui/qpa/qplatformnativeinterface.h>
 
 #include <d3d11_1.h>
 #include <d3dcompiler.h>


=====================================
modules/gui/qt/maininterface/compositor_wayland.cpp
=====================================
@@ -0,0 +1,207 @@
+/*****************************************************************************
+ * Copyright (C) 2023 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 "compositor_wayland.hpp"
+
+#include "maininterface/mainctx.hpp"
+#include "maininterface/interface_window_handler.hpp"
+
+#ifndef QT5_GUI_PRIVATE
+#warning "qplatformnativeinterface is requried for wayland compositor"
+#endif
+
+#include <QtGui/qpa/qplatformnativeinterface.h>
+#include <QtGui/qpa/qplatformwindow.h>
+
+#include <vlc_window.h>
+#include <vlc_modules.h>
+
+#include "compositor_wayland_module.h"
+
+namespace vlc {
+
+CompositorWayland::CompositorWayland(qt_intf_t *p_intf, QObject* parent)
+    : CompositorVideo(p_intf, parent)
+{
+}
+
+CompositorWayland::~CompositorWayland()
+{
+    if (m_waylandImpl)
+    {
+        if (m_waylandImpl->p_module)
+        {
+            m_waylandImpl->close(m_waylandImpl);
+            module_unneed(m_waylandImpl, m_waylandImpl->p_module);
+        }
+        vlc_object_delete(m_waylandImpl);
+    }
+}
+
+bool CompositorWayland::preInit(qt_intf_t *)
+{
+    return true;
+}
+
+bool CompositorWayland::init()
+{
+    QPlatformNativeInterface* native = QGuiApplication::platformNativeInterface();
+
+    //get "wl_display" and not "display", as "display" may refer to other concept in other QPA
+    //so this will fail if qt doesn't use wayland
+    void* qpni_display = native->nativeResourceForIntegration("wl_display");
+    if (!qpni_display)
+        return false;
+
+    /*
+     * a separate wayland module is used to perform direct wayland calls
+     * without requiring Qt module to be directly linked to wayland
+     */
+    m_waylandImpl = static_cast<qtwayland_t*>(vlc_object_create(m_intf, sizeof(qtwayland_t)));
+    if (!m_waylandImpl)
+        return false;
+
+    m_waylandImpl->p_module = module_need(m_waylandImpl, "qtwayland", nullptr, false);
+    if (!m_waylandImpl->p_module)
+    {
+        msg_Err(m_intf, "the qtwayland module is not available, wayland"
+                        "embedded video output will not be possible");
+        vlc_object_delete(m_waylandImpl);
+        m_waylandImpl = nullptr;
+
+        return false;
+    }
+
+    return m_waylandImpl->init(m_waylandImpl, qpni_display);
+}
+
+bool CompositorWayland::makeMainInterface(MainCtx* mainCtx)
+{
+    assert(mainCtx);
+    m_mainCtx = mainCtx;
+
+    m_qmlView = std::make_unique<QQuickView>();
+    if (m_mainCtx->useClientSideDecoration())
+        m_qmlView->setFlag(Qt::FramelessWindowHint);
+    m_qmlView->setResizeMode(QQuickView::SizeRootObjectToView);
+    m_qmlView->setClearBeforeRendering(true);
+    m_qmlView->setColor(QColor(Qt::transparent));
+
+    m_qmlView->show();
+
+    QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
+    void* interfaceSurface = nativeInterface->nativeResourceForWindow("surface", m_qmlView.get());
+    if (!interfaceSurface)
+        return false;
+
+    m_waylandImpl->setupInterface(m_waylandImpl, interfaceSurface);
+
+    return commonGUICreate(m_qmlView.get(), m_qmlView.get(),
+                    CompositorVideo::CAN_SHOW_PIP);
+}
+
+QWindow* CompositorWayland::interfaceMainWindow() const
+{
+    return m_qmlView.get();
+}
+
+void CompositorWayland::destroyMainInterface()
+{
+    unloadGUI();
+}
+
+void CompositorWayland::unloadGUI()
+{
+    //needs to be released before the window
+    m_interfaceWindowHandler.reset();
+
+    m_qmlView.reset();
+    commonGUIDestroy();
+}
+
+Compositor::Type CompositorWayland::type() const
+{
+    return Compositor::WaylandCompositor;
+}
+
+QQuickItem * CompositorWayland::activeFocusItem() const
+{
+    return m_qmlView->activeFocusItem();
+}
+
+// vout functions
+
+bool CompositorWayland::setupVoutWindow(vlc_window_t* p_wnd, VoutDestroyCb destroyCb)
+{
+    int ret = m_waylandImpl->setupVoutWindow(m_waylandImpl, p_wnd);
+    if (ret != VLC_SUCCESS)
+        return false;
+
+    commonSetupVoutWindow(p_wnd, destroyCb);
+
+    return true;
+}
+
+void CompositorWayland::windowDestroy()
+{
+    m_waylandImpl->teardownVoutWindow(m_waylandImpl);
+    CompositorVideo::windowDestroy();
+}
+
+int CompositorWayland::windowEnable(const vlc_window_cfg_t * cfg)
+{
+    m_waylandImpl->enable(m_waylandImpl, cfg);
+    commonWindowEnable();
+    return VLC_SUCCESS;
+}
+
+void CompositorWayland::windowDisable()
+{
+    m_waylandImpl->disable(m_waylandImpl);
+    commonWindowDisable();
+}
+
+static qreal dprForWindow(QQuickWindow* window)
+{
+    qreal dpr = window->devicePixelRatio();
+
+    QPlatformWindow* nativeWindow = window->handle();
+    if (nativeWindow)
+        dpr /= nativeWindow->devicePixelRatio();
+
+    return dpr;
+}
+
+void CompositorWayland::onSurfacePositionChanged(const QPointF& position)
+{
+    QMargins margins = m_qmlView->frameMargins();
+
+    qreal dpr = dprForWindow(m_qmlView.get());
+
+    m_waylandImpl->move(m_waylandImpl,
+        margins.left() * dpr + position.x(),
+        margins.top() * dpr + position.y());
+}
+
+void CompositorWayland::onSurfaceSizeChanged(const QSizeF& size)
+{
+    m_waylandImpl->resize(m_waylandImpl,
+                        size.width(),
+                        size.height());
+}
+
+}


=====================================
modules/gui/qt/maininterface/compositor_wayland.hpp
=====================================
@@ -0,0 +1,90 @@
+/*****************************************************************************
+ * Copyright (C) 2023 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 VLC_COMPOSITOR_WAYLAND
+#define VLC_COMPOSITOR_WAYLAND
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <memory>
+#include "compositor.hpp"
+
+class MainCtx;
+class QQuickView;
+class InterfaceWindowHandler;
+
+extern "C" {
+typedef struct qtwayland_t qtwayland_t;
+}
+
+namespace vlc {
+
+class CompositorWayland : public CompositorVideo
+{
+    Q_OBJECT
+public:
+    CompositorWayland(qt_intf_t *p_intf, QObject* parent = nullptr);
+    virtual ~CompositorWayland();
+
+    static bool preInit(qt_intf_t*);
+    virtual bool init() override;
+
+    virtual bool makeMainInterface(MainCtx*) override;
+
+    /**
+     * @brief release all resources used by the compositor.
+     * this includes the GUI and the video surfaces.
+     */
+    virtual void destroyMainInterface() override;
+
+    /**
+     * @brief unloadGUI unload the UI view from the composition
+     * video view might still be active
+     */
+    virtual void unloadGUI() override;
+
+
+    QWindow* interfaceMainWindow() const override;
+
+    Type type() const override;
+
+    QQuickItem * activeFocusItem() const override;
+
+    //video integration
+
+
+    bool setupVoutWindow(vlc_window_t *p_wnd, VoutDestroyCb destroyCb) override;
+    void windowDestroy() override;
+
+    virtual int windowEnable(const vlc_window_cfg_t *) override;
+    virtual void windowDisable() override;
+
+protected slots:
+    virtual void onSurfacePositionChanged(const QPointF&) override;
+    virtual void onSurfaceSizeChanged(const QSizeF&) override;
+
+
+protected:
+    std::unique_ptr<QQuickView> m_qmlView;
+    qtwayland_t* m_waylandImpl = nullptr;
+};
+
+}
+
+#endif // VLC_COMPOSITOR_WAYLAND


=====================================
modules/gui/qt/maininterface/compositor_wayland_module.c
=====================================
@@ -0,0 +1,244 @@
+/*****************************************************************************
+ * Copyright (C) 2023 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.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "compositor_wayland_module.h"
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <wayland-client.h>
+
+#include <assert.h>
+
+typedef struct
+{
+    struct wl_display* display;
+    struct wl_event_queue* queue;
+    struct wl_compositor* compositor;
+    struct wl_subcompositor* subcompositor;
+
+    struct wl_surface* interface_surface;
+
+    struct wl_surface* video_surface;
+    struct wl_subsurface* video_subsurface;
+} qtwayland_priv_t;
+
+static void registry_global_cb(void* data, struct wl_registry* registry,
+                               uint32_t id, const char* iface, uint32_t version)
+{
+    VLC_UNUSED(version);
+
+    qtwayland_t* obj = (qtwayland_t*)data;
+    qtwayland_priv_t* sys = (qtwayland_priv_t*)obj->p_sys;
+
+    if (!strcmp(iface, "wl_subcompositor"))
+        sys->subcompositor = (struct wl_subcompositor*)wl_registry_bind(registry, id, &wl_subcompositor_interface, version);
+    if (!strcmp(iface, "wl_compositor"))
+        sys->compositor = (struct wl_compositor*)wl_registry_bind(registry, id, &wl_compositor_interface, version);
+}
+
+static void registry_global_remove_cb(void* data, struct wl_registry* registry, uint32_t id)
+{
+    VLC_UNUSED(data);
+    VLC_UNUSED(registry);
+    VLC_UNUSED(id);
+}
+
+static const struct wl_registry_listener registry_cbs = {
+    registry_global_cb,
+    registry_global_remove_cb,
+};
+
+static int SetupInterface(qtwayland_t* obj, void* qpni_interface_surface)
+{
+    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;
+
+    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;
+
+    struct wl_region* region = wl_compositor_create_region(sys->compositor);
+    if (!region)
+    {
+        wl_surface_destroy(sys->video_surface);
+        sys->video_surface = NULL;
+        return VLC_EGENERIC;
+    }
+    wl_region_add(region, 0, 0, 0, 0);
+    wl_surface_set_input_region(sys->video_surface, region);
+
+    wl_region_destroy(region);
+    wl_surface_commit(sys->video_surface);
+
+    //setup vout window
+    wnd->type = VLC_WINDOW_TYPE_WAYLAND;
+    wnd->handle.wl = sys->video_surface;
+    wnd->display.wl = sys->display;
+
+    return VLC_SUCCESS;
+}
+
+static void TeardownVoutWindow(struct qtwayland_t* obj)
+{
+    qtwayland_priv_t* sys = (qtwayland_priv_t*)obj->p_sys;
+    vlc_assert(sys->video_surface);
+    wl_surface_destroy(sys->video_surface);
+    sys->video_surface = NULL;
+}
+
+static void Enable(qtwayland_t* obj, const vlc_window_cfg_t * conf)
+{
+    VLC_UNUSED(conf);
+
+    qtwayland_priv_t* sys = (qtwayland_priv_t*)obj->p_sys;
+
+    vlc_assert(sys->video_subsurface == NULL);
+    vlc_assert(sys->video_surface);
+    vlc_assert(sys->interface_surface);
+
+    sys->video_subsurface = wl_subcompositor_get_subsurface(sys->subcompositor, sys->video_surface, sys->interface_surface);
+    wl_subsurface_place_below(sys->video_subsurface, sys->interface_surface);
+    wl_subsurface_set_desync(sys->video_subsurface);
+    wl_surface_commit(sys->video_surface);
+}
+
+static void Disable(qtwayland_t* obj)
+{
+    qtwayland_priv_t* sys = (qtwayland_priv_t*)obj->p_sys;
+    vlc_assert(sys->video_subsurface);
+
+    wl_subsurface_destroy(sys->video_subsurface);
+    sys->video_subsurface = NULL;
+    wl_surface_commit(sys->video_surface);
+}
+
+static void Move(struct qtwayland_t* obj, int x, int y)
+{
+    qtwayland_priv_t* sys = (qtwayland_priv_t*)obj->p_sys;
+    wl_subsurface_set_position(sys->video_subsurface, x, y);
+    wl_surface_commit(sys->video_surface);
+}
+
+static void Resize(struct qtwayland_t* obj, size_t width, size_t height)
+{
+    VLC_UNUSED(obj);
+    VLC_UNUSED(width);
+    VLC_UNUSED(height);
+}
+
+static void Close(qtwayland_t* obj)
+{
+    qtwayland_priv_t* sys = (qtwayland_priv_t*)(obj->p_sys);
+    wl_display_flush(sys->display);
+    wl_event_queue_destroy(sys->queue);
+}
+
+static bool Init(qtwayland_t* obj, void* qpni_display)
+{
+    qtwayland_priv_t* sys = (qtwayland_priv_t*)(obj->p_sys);
+    struct wl_display* display = (struct wl_display*)(qpni_display);
+
+    sys->display = display;
+    if (!display)
+    {
+        msg_Err(obj, "wayland display is missing");
+        goto error;
+    }
+
+    sys->queue = wl_display_create_queue(display);
+    void* wrapper = wl_proxy_create_wrapper(display);
+    wl_proxy_set_queue((struct wl_proxy*)wrapper, sys->queue);
+
+    struct wl_registry* registry = wl_display_get_registry((struct wl_display*)wrapper);
+    wl_proxy_wrapper_destroy(wrapper);
+
+    wl_registry_add_listener(registry, &registry_cbs, obj);
+    wl_display_roundtrip_queue(display, sys->queue);
+
+    wl_registry_destroy(registry);
+
+    if (!sys->compositor || !sys->subcompositor )
+        goto error;
+
+    return true;
+
+error:
+    if (sys->queue)
+        wl_event_queue_destroy(sys->queue);
+    return false;
+}
+
+static int Open(vlc_object_t* p_this)
+{
+    qtwayland_t* obj = (qtwayland_t*)p_this;
+
+    struct wl_display *dpy = wl_display_connect( NULL );
+    if( dpy == NULL )
+    {
+        //not using wayland
+        return VLC_EGENERIC;
+    }
+
+    wl_display_disconnect( dpy );
+
+    qtwayland_priv_t* sys = (qtwayland_priv_t*)vlc_obj_calloc(p_this, 1, sizeof(qtwayland_priv_t));
+    if (!sys)
+        return VLC_ENOMEM;
+
+
+    //module functions
+    obj->init = Init;
+    obj->close = Close;
+
+    //interface functions
+    obj->setupInterface = SetupInterface;
+
+    //video functions
+    obj->setupVoutWindow = SetupVoutWindow;
+    obj->teardownVoutWindow = TeardownVoutWindow;
+    obj->enable = Enable;
+    obj->disable = Disable;
+    obj->move = Move;
+    obj->resize = Resize;
+
+    obj->p_sys = sys;
+
+    return VLC_SUCCESS;
+}
+
+vlc_module_begin()
+    set_shortname(N_("QtWayland"))
+    set_description(N_(" calls for compositing with Qt"))
+    set_capability("qtwayland", 10)
+    set_callback(Open)
+vlc_module_end()


=====================================
modules/gui/qt/maininterface/compositor_wayland_module.h
=====================================
@@ -0,0 +1,47 @@
+/*****************************************************************************
+ * Copyright (C) 2023 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 COMPOSITOR_WAYLAND_MODULE_H
+#define COMPOSITOR_WAYLAND_MODULE_H
+
+#include <vlc_window.h>
+
+typedef struct qtwayland_t
+{
+    struct vlc_object_t obj;
+
+    module_t* p_module;
+    void* p_sys;
+
+    bool (*init)(struct qtwayland_t*, void* display);
+
+    int (*setupInterface)(struct qtwayland_t*, void* video_surface );
+
+    int (*setupVoutWindow)(struct qtwayland_t*, vlc_window_t* p_wnd);
+    void (*teardownVoutWindow)(struct qtwayland_t*);
+
+    void (*enable)(struct qtwayland_t*, const vlc_window_cfg_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 (*close)(struct qtwayland_t*);
+} qtwayland_t;
+
+
+#endif // COMPOSITOR_WAYLAND_MODULE_H


=====================================
modules/gui/qt/maininterface/interface_window_handler.hpp
=====================================
@@ -22,6 +22,7 @@
 
 #include <QObject>
 #include <QWindow>
+#include <QPointer>
 
 class MainCtx;
 class InterfaceWindowHandler : public QObject
@@ -69,7 +70,7 @@ private:
 
 protected:
     qt_intf_t* p_intf = nullptr;
-    QWindow* m_window = nullptr;
+    QPointer<QWindow> m_window;
 
     MainCtx* m_mainCtx = nullptr;
 


=====================================
modules/gui/qt/maininterface/mainctx_win32.cpp
=====================================
@@ -40,8 +40,11 @@
 #include <cassert>
 
 #include <QWindow>
-#include QPNI_HEADER
 
+#ifndef QT5_GUI_PRIVATE
+#warning "qplatformnativeinterface.h header is required for MainCtxWin32"
+#endif
+#include <QtGui/qpa/qplatformnativeinterface.h>
 #include <dwmapi.h>
 
 #define WM_APPCOMMAND 0x0319


=====================================
modules/gui/qt/maininterface/video_window_handler.hpp
=====================================
@@ -26,6 +26,7 @@
 
 #include <QWindow>
 #include <QObject>
+#include <QPointer>
 
 #include "qt.hpp"
 
@@ -59,7 +60,7 @@ protected slots:
 
 private:
     qt_intf_t *m_intf = nullptr;
-    QWindow* m_window = nullptr;
+    QPointer<QWindow> m_window;
 
     bool m_videoFullScreen = false;
     bool m_autoresize = false;


=====================================
modules/gui/qt/maininterface/videosurface.cpp
=====================================
@@ -22,6 +22,11 @@
 #include <QThreadPool>
 #include <vlc_window.h>
 
+#include <QQuickRenderControl>
+#ifdef QT5_DECLARATIVE_PRIVATE
+#  include <QtGui/qpa/qplatformwindow.h>
+#endif
+
 WindowResizer::WindowResizer(vlc_window_t* window):
     m_requestedWidth(0),
     m_requestedHeight(0),
@@ -367,14 +372,34 @@ void VideoSurface::onProviderVideoChanged(bool hasVideo)
     updatePositionAndSize();
 }
 
+static qreal dprForWindow(QQuickWindow* quickWindow)
+{
+    if (!quickWindow)
+        return 1.0;
+
+    QWindow* window = QQuickRenderControl::renderWindowFor(quickWindow);
+    if (!window)
+        window = quickWindow;
+
+    qreal dpr = window->devicePixelRatio();
+
+#ifdef QT5_DECLARATIVE_PRIVATE
+    QPlatformWindow* nativeWindow = window->handle();
+    if (nativeWindow)
+        dpr /= nativeWindow->devicePixelRatio();
+#endif
+
+    return dpr;
+}
+
 void VideoSurface::onSurfaceSizeChanged()
 {
     if (!isEnabled())
         return;
-    QQuickWindow* window = this->window();
-    if (!window)
-        return;
-    emit surfaceSizeChanged(size() * window->effectiveDevicePixelRatio());
+
+    qreal dpr = dprForWindow(window());
+
+    emit surfaceSizeChanged(size() * dpr);
 }
 
 void VideoSurface::onSurfacePositionChanged()
@@ -382,11 +407,10 @@ void VideoSurface::onSurfacePositionChanged()
     if (!isEnabled())
         return;
 
+    qreal dpr = dprForWindow(window());
+
     QPointF scenePosition = this->mapToScene(QPointF(0,0));
-    QQuickWindow* window = this->window();
-    if (!window)
-        return;
-    qreal dpr = window->effectiveDevicePixelRatio();
+
     emit surfacePositionChanged(scenePosition * dpr);
 }
 
@@ -395,10 +419,8 @@ void VideoSurface::updatePositionAndSize()
     if (!isEnabled())
         return;
 
-    QQuickWindow* window = this->window();
-    if (!window)
-        return;
-    qreal dpr = window->effectiveDevicePixelRatio();
+    qreal dpr = dprForWindow(window());
+
     emit surfaceSizeChanged(size() * dpr);
     QPointF scenePosition = this->mapToScene(QPointF(0, 0));
     emit surfacePositionChanged(scenePosition * dpr);


=====================================
modules/gui/qt/maininterface/videosurface.hpp
=====================================
@@ -21,6 +21,7 @@
 #include "widgets/native/viewblockingrectangle.hpp"
 #include <QMutex>
 #include <QRunnable>
+#include <QPointer>
 #include "qt.hpp"
 
 #include <vlc_threads.h>
@@ -148,7 +149,7 @@ private:
 
     QPointF m_oldHoverPos;
 
-    VideoSurfaceProvider* m_provider = nullptr;
+    QPointer<VideoSurfaceProvider> m_provider;
 };
 
 #endif // VIDEOSURFACE_HPP


=====================================
modules/gui/qt/qt.cpp
=====================================
@@ -268,6 +268,9 @@ static const char *const compositor_vlc[] = {
 #endif
     "win7",
 #endif
+#ifdef QT5_HAS_WAYLAND_COMPOSITOR
+    "wayland",
+#endif
 #ifdef QT5_HAS_X11_COMPOSITOR
     "x11",
 #endif
@@ -281,6 +284,9 @@ static const char *const compositor_user[] = {
 #endif
     "Windows 7",
 #endif
+#ifdef QT5_HAS_WAYLAND_COMPOSITOR
+    "Wayland",
+#endif
 #ifdef QT5_HAS_X11_COMPOSITOR
     N_("X11"),
 #endif



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b2406ca91c882516324d1185ecf10ceed064b9e6...3c622d4cc240883cb4ac03ad8ec7a63ba2dff7d6

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b2406ca91c882516324d1185ecf10ceed064b9e6...3c622d4cc240883cb4ac03ad8ec7a63ba2dff7d6
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