[vlc-devel] [RFC 48/82] qt: add wayland video renderer
Pierre Lamot
pierre at videolabs.io
Fri Feb 1 14:01:52 CET 2019
From: Alexandre Janniaux <alexandre.janniaux at gmail.com>
---
modules/gui/qt/Makefile.am | 9 +
.../video_renderer/videorendererwayland.cpp | 154 ++++++++++++++++++
.../video_renderer/videorendererwayland.hpp | 63 +++++++
3 files changed, 226 insertions(+)
create mode 100644 modules/gui/qt/components/video_renderer/videorendererwayland.cpp
create mode 100644 modules/gui/qt/components/video_renderer/videorendererwayland.hpp
diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
index 7d0132c6a1..e9cd3e61d4 100644
--- a/modules/gui/qt/Makefile.am
+++ b/modules/gui/qt/Makefile.am
@@ -166,6 +166,11 @@ if HAVE_WIN32
libqt_plugin_la_SOURCES += \
gui/qt/main_interface_win32.cpp gui/qt/main_interface_win32.hpp
endif
+if HAVE_WAYLAND
+libqt_plugin_la_SOURCES += \
+ gui/qt/components/video_renderer/videorendererwayland.hpp \
+ gui/qt/components/video_renderer/videorendererwayland.cpp
+endif
# Meta-object compilation
@@ -260,6 +265,10 @@ if HAVE_WIN32
nodist_libqt_plugin_la_SOURCES += gui/qt/main_interface_win32.moc.cpp
endif
+if HAVE_WAYLAND
+nodist_libqt_plugin_la_SOURCES += gui/qt/components/video_renderer/videorendererwayland.moc.cpp
+endif
+
nodist_libqt_plugin_la_SOURCES += \
gui/qt/ui/equalizer.h \
gui/qt/ui/video_effects.h \
diff --git a/modules/gui/qt/components/video_renderer/videorendererwayland.cpp b/modules/gui/qt/components/video_renderer/videorendererwayland.cpp
new file mode 100644
index 0000000000..120bb9a24c
--- /dev/null
+++ b/modules/gui/qt/components/video_renderer/videorendererwayland.cpp
@@ -0,0 +1,154 @@
+#include "videorendererwayland.hpp"
+#include <QtQuick/QSGImageNode>
+#include <QtQuick/QSGRectangleNode>
+#include <QtQuick/QQuickWindow>
+#include <vlc_vout_window.h>
+#include "main_interface.hpp"
+
+#include QPNI_HEADER
+#include <wayland-client.h>
+#include <wayland-client-protocol.h>
+
+void VideoRendererWayland::registry_global( void *data, wl_registry *registry,
+ uint32_t name, const char *intf,
+ uint32_t version )
+{
+ VideoRendererWayland *renderer = static_cast<VideoRendererWayland*>( data );
+
+ if( !strcmp(intf, "wl_compositor") )
+ renderer->m_compositor = static_cast<wl_compositor*>(
+ wl_registry_bind( registry, name,
+ &wl_compositor_interface,
+ version ));
+
+ else
+ if( !strcmp(intf, "wl_subcompositor") )
+ renderer->m_subcompositor = static_cast<wl_subcompositor*>(
+ wl_registry_bind( registry, name,
+ &wl_subcompositor_interface,
+ version ));
+}
+
+void VideoRendererWayland::registry_global_remove( void *, wl_registry *, uint32_t )
+{
+ // nothing to do
+}
+
+VideoRendererWayland::VideoRendererWayland( MainInterface* p_mi, QObject* parent )
+ : VideoRenderer( parent )
+ , m_mainInterface( p_mi )
+{
+ assert( m_mainInterface );
+ m_surfaceProvider = new VideoSurfaceWayland( this, this );
+}
+
+VideoRendererWayland::~VideoRendererWayland()
+{
+ if( m_subsurface )
+ wl_subsurface_destroy( m_subsurface );
+ if( m_surface )
+ wl_surface_destroy( m_surface );
+ if( m_compositor )
+ wl_compositor_destroy( m_compositor );
+ if( m_subcompositor )
+ wl_subcompositor_destroy( m_subcompositor );
+}
+
+void VideoRendererWayland::enableVideo(unsigned width, unsigned height, bool fullscreen)
+{
+ VideoRenderer::enableVideo(width, height, fullscreen);
+ if (!m_hasVideo) //no window out has been set
+ return;
+
+ m_voutWindow->type = VOUT_WINDOW_TYPE_WAYLAND;
+
+ QPlatformNativeInterface *qni = qApp->platformNativeInterface();
+
+ m_voutWindow->display.wl = static_cast<wl_display *>(
+ qni->nativeResourceForIntegration(QByteArrayLiteral("wl_display")));
+
+ const wl_registry_listener registry_cbs =
+ {
+ registry_global,
+ registry_global_remove,
+ };
+
+ wl_registry *registry = wl_display_get_registry( m_voutWindow->display.wl );
+ wl_registry_add_listener( registry, ®istry_cbs, this );
+ wl_display_roundtrip( m_voutWindow->display.wl );
+ wl_registry_destroy( registry );
+
+ if( !m_compositor || !m_subcompositor )
+ return; // TODO: what to do
+
+ QWindow *root_window = m_mainInterface->window()->windowHandle();
+ wl_surface *root_surface = static_cast<wl_surface *>(
+ qni->nativeResourceForWindow( QByteArrayLiteral("surface"),
+ root_window ));
+
+ m_surface =
+ m_voutWindow->handle.wl = wl_compositor_create_surface( m_compositor );
+ m_subsurface = wl_subcompositor_get_subsurface( m_subcompositor,
+ m_voutWindow->handle.wl,
+ root_surface );
+
+ wl_subsurface_place_below( m_subsurface, root_surface );
+ wl_subsurface_set_desync( m_subsurface );
+
+ /* HACK: disable event input on surface, so that Qt don't try
+ * to cast it's userdata */
+ wl_region *region = wl_compositor_create_region( m_compositor );
+ wl_region_add( region, 0, 0, 0, 0 );
+ wl_surface_set_input_region( m_voutWindow->handle.wl, region );
+ wl_region_destroy( region );
+}
+
+
+void VideoRendererWayland::disableVideo()
+{
+ VideoRenderer::disableVideo();
+ if( m_subsurface )
+ wl_subsurface_destroy( m_subsurface );
+ if( m_surface )
+ wl_surface_destroy( m_surface );
+ if( m_subcompositor )
+ wl_subcompositor_destroy( m_subcompositor );
+ if( m_compositor )
+ wl_compositor_destroy( m_compositor );
+ m_subsurface = nullptr; m_surface = nullptr;
+ m_compositor = nullptr; m_subcompositor = nullptr;
+}
+
+VideoSurfaceProvider *VideoRendererWayland::getVideoSurfaceProvider()
+{
+ return m_surfaceProvider;
+}
+
+VideoSurfaceWayland::VideoSurfaceWayland(VideoRendererWayland* renderer, QObject* parent)
+ : VideoSurfaceProvider( parent )
+ , m_renderer(renderer)
+{
+ connect(this, &VideoSurfaceWayland::mouseMoved, m_renderer, &VideoRenderer::onMouseMoved, Qt::QueuedConnection);
+ connect(this, &VideoSurfaceWayland::mousePressed, m_renderer, &VideoRenderer::onMousePressed, Qt::QueuedConnection);
+ connect(this, &VideoSurfaceWayland::mouseDblClicked, m_renderer, &VideoRenderer::onMouseDoubleClick, Qt::QueuedConnection);
+ connect(this, &VideoSurfaceWayland::mouseReleased, m_renderer, &VideoRenderer::onMouseReleased, Qt::QueuedConnection);
+
+ connect(this, &VideoSurfaceWayland::surfaceSizeChanged, m_renderer, &VideoRenderer::onSurfaceSizeChanged);
+
+ connect(m_renderer, &VideoRendererWayland::updated, this, &VideoSurfaceWayland::update, Qt::QueuedConnection);
+}
+
+QSGNode* VideoSurfaceWayland::updatePaintNode(QQuickItem* item, QSGNode* oldNode, QQuickItem::UpdatePaintNodeData*)
+{
+ QSGRectangleNode* node = static_cast<QSGRectangleNode*>(oldNode);
+
+ if (!node)
+ {
+ node = item->window()->createRectangleNode();
+ node->setColor(Qt::transparent);
+ }
+ node->setRect(item->boundingRect());
+
+ return node;
+}
+
diff --git a/modules/gui/qt/components/video_renderer/videorendererwayland.hpp b/modules/gui/qt/components/video_renderer/videorendererwayland.hpp
new file mode 100644
index 0000000000..c3c3462368
--- /dev/null
+++ b/modules/gui/qt/components/video_renderer/videorendererwayland.hpp
@@ -0,0 +1,63 @@
+#ifndef VLC_QT_VIDEORENDERERWL_HPP
+#define VLC_QT_VIDEORENDERERWL_HPP
+
+#include <inttypes.h>
+#include <QtQuick/QQuickItem>
+#include <QMutex>
+#include <QtQuick/QSGRectangleNode>
+#include <components/qml_main_context.hpp>
+#include "qt.hpp"
+
+#include "videorenderer.hpp"
+
+class MainInterface;
+class VideoSurfaceWayland;
+
+struct wl_compositor;
+struct wl_subcompositor;
+struct wl_subsurface;
+struct wl_registry;
+
+class VideoRendererWayland: public VideoRenderer
+{
+ Q_OBJECT
+public:
+ VideoRendererWayland(MainInterface* p_mi, QObject *parent = nullptr);
+ ~VideoRendererWayland() override;
+
+ void enableVideo(unsigned int width, unsigned int height, bool fullscreen);
+ void disableVideo();
+
+ VideoSurfaceProvider *getVideoSurfaceProvider() override;
+
+signals:
+ void updated();
+
+private:
+ /* wayland registry callbacks */
+ static void registry_global( void *, wl_registry *, uint32_t,
+ const char *, uint32_t );
+ static void registry_global_remove( void *, wl_registry *, uint32_t );
+
+ MainInterface *m_mainInterface;
+ VideoSurfaceWayland *m_surfaceProvider = nullptr;
+ wl_compositor *m_compositor = nullptr;
+ wl_subcompositor *m_subcompositor = nullptr;
+ wl_subsurface *m_subsurface = nullptr;
+ wl_surface *m_surface = nullptr;
+};
+
+class VideoSurfaceWayland : public VideoSurfaceProvider
+{
+ Q_OBJECT
+public:
+ VideoSurfaceWayland(VideoRendererWayland* renderer, QObject* parent = nullptr);
+
+private:
+ QSGNode *updatePaintNode(QQuickItem* item, QSGNode *, QQuickItem::UpdatePaintNodeData *) override;
+
+private:
+ VideoRendererWayland* m_renderer = nullptr;
+};
+
+#endif // VLC_QT_VIDEORENDERERWL_HPP
--
2.19.1
More information about the vlc-devel
mailing list