diff --git a/src/client/protocols/wayland-eglstream-controller.xml b/src/client/protocols/wayland-eglstream-controller.xml new file mode 100644 index 0000000..2c3a635 --- /dev/null +++ b/src/client/protocols/wayland-eglstream-controller.xml @@ -0,0 +1,87 @@ + + + + Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + + + - dont_care: Using this enum will tell the server to make its own + decisions regarding present mode. + + - fifo: Tells the server to use a fifo present mode. The decision to + use fifo synchronous is left up to the server. + + - mailbox: Tells the server to use a mailbox present mode. + + + + + + + + + - present_mode: Must be one of wl_eglstream_controller_present_mode. Tells the + server the desired present mode that should be used. + + - fifo_length: Only valid when the present_mode attrib is provided and its + value is specified as fifo. Tells the server the desired fifo + length to be used when the desired present_mode is fifo. + + + + + + + + Creates the corresponding server side EGLStream from the given wl_buffer + and attaches a consumer to it. + + + + + + + + Creates the corresponding server side EGLStream from the given wl_buffer + and attaches a consumer to it using the given attributes. + + + + + + It contains key-value pairs compatible with intptr_t type. A key must + be one of wl_eglstream_controller_attrib enumeration values. What a value + represents is attribute-specific. + + + + + diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index 7566ef3..cebdbe7 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -1,355 +1,363 @@ set(SERVER_LIB_SRCS appmenu_interface.cpp buffer_interface.cpp clientconnection.cpp compositor_interface.cpp datadevice_interface.cpp datadevicemanager_interface.cpp dataoffer_interface.cpp datasource_interface.cpp display.cpp dpms_interface.cpp filtered_display.cpp global.cpp idle_interface.cpp idleinhibit_interface.cpp idleinhibit_interface_v1.cpp fakeinput_interface.cpp keyboard_interface.cpp remote_access_interface.cpp outputconfiguration_interface.cpp outputchangeset.cpp outputmanagement_interface.cpp outputdevice_interface.cpp output_interface.cpp pointer_interface.cpp plasmashell_interface.cpp plasmavirtualdesktop_interface.cpp plasmawindowmanagement_interface.cpp pointerconstraints_interface.cpp pointerconstraints_interface_v1.cpp pointergestures_interface.cpp pointergestures_interface_v1.cpp qtsurfaceextension_interface.cpp region_interface.cpp relativepointer_interface.cpp relativepointer_interface_v1.cpp resource.cpp seat_interface.cpp slide_interface.cpp shadow_interface.cpp blur_interface.cpp contrast_interface.cpp server_decoration_interface.cpp server_decoration_palette_interface.cpp shell_interface.cpp surface_interface.cpp subcompositor_interface.cpp touch_interface.cpp textinput_interface.cpp textinput_interface_v0.cpp textinput_interface_v2.cpp xdgdecoration_interface.cpp xdgshell_interface.cpp xdgshell_v5_interface.cpp xdgforeign_v2_interface.cpp xdgforeign_interface.cpp xdgshell_v5_interface.cpp xdgshell_v6_interface.cpp xdgshell_stable_interface.cpp xdgoutput_interface.cpp + eglstream_controller_interface.cpp ../compat/wayland-xdg-shell-v5-protocol.c ) ecm_qt_declare_logging_category(SERVER_LIB_SRCS HEADER logging.h IDENTIFIER KWAYLAND_SERVER CATEGORY_NAME kwayland-server DEFAULT_SEVERITY Critical) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/output-management.xml BASENAME output-management ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/outputdevice.xml BASENAME org_kde_kwin_outputdevice ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/plasma-shell.xml BASENAME plasma-shell ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/plasma-virtual-desktop.xml BASENAME plasma-virtual-desktop ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/plasma-window-management.xml BASENAME plasma-window-management ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/surface-extension.xml BASENAME qt-surface-extension ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/idle.xml BASENAME idle ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/fake-input.xml BASENAME fake-input ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/shadow.xml BASENAME shadow ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/dpms.xml BASENAME dpms ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/blur.xml BASENAME blur ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/contrast.xml BASENAME contrast ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/relative-pointer-unstable-v1.xml BASENAME relativepointer-unstable-v1 ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/slide.xml BASENAME slide ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/server-decoration.xml BASENAME server_decoration ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/text-input.xml BASENAME text ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/text-input-unstable-v2.xml BASENAME text-input-unstable-v2 ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/xdg-shell-unstable-v6.xml BASENAME xdg-shell-v6 ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/pointer-gestures-unstable-v1.xml BASENAME pointer-gestures-unstable-v1 ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/pointer-constraints-unstable-v1.xml BASENAME pointer-constraints-unstable-v1 ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/xdg-foreign-unstable-v2.xml BASENAME xdg-foreign-unstable-v2 ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/idle-inhibit-unstable-v1.xml BASENAME idle-inhibit-unstable-v1 ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/appmenu.xml BASENAME appmenu ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/server-decoration-palette.xml BASENAME server_decoration_palette ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/remote-access.xml BASENAME remote-access ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/xdg-output-unstable-v1.xml BASENAME xdg-output ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/xdg-shell.xml BASENAME xdg-shell ) ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/xdg-decoration-unstable-v1.xml BASENAME xdg-decoration ) +ecm_add_wayland_server_protocol(SERVER_LIB_SRCS + PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/wayland-eglstream-controller.xml + BASENAME eglstream-controller +) + set(SERVER_GENERATED_SRCS ${CMAKE_CURRENT_BINARY_DIR}/wayland-output-management-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-output-management-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-org_kde_kwin_outputdevice-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-org_kde_kwin_outputdevice-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-plasma-shell-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-plasma-shell-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-plasma-shell-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-plasma-virtual-desktop-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-plasma-virtual-desktop-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-plasma-window-management-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-plasma-window-management-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-qt-surface-extension-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-qt-surface-extension-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-idle-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-idle-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-fake-input-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-fake-input-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-shadow-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-shadow-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-dpms-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-dpms-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-blur-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-blur-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-contrast-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-contrast-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-relativepointer-unstable-v1-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-relativepointer-unstable-v1-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-slide-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-slide-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-server_decoration-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-server_decoration-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-server_decoration_palette-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-server_decoration_palette-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-text-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-text-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-text-input-unstable-v2-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-text-input-unstable-v2-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-xdg-shell-v6-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-xdg-shell-v6-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-xdg-shell-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-xdg-shell-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-pointer-gestures-unstable-v1-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-pointer-gestures-unstable-v1-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-pointer-constraints-unstable-v1-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-pointer-constraints-unstable-v1-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-xdg-foreign-unstable-v2-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-xdg-foreign-unstable-v2-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-idle-inhibit-unstable-v1-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-idle-inhibit-unstable-v1-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-output-unstable-v1-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-output-unstable-v1-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-output-unstable-v1-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-xdg-decoration-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-xdg-decoration-client-protocol.h + ${CMAKE_CURRENT_BINARY_DIR}/wayland-eglstream-controller-server-protocol.h ) set_source_files_properties(${SERVER_GENERATED_SRCS} PROPERTIES SKIP_AUTOMOC ON) add_library(KF5WaylandServer ${SERVER_LIB_SRCS}) generate_export_header(KF5WaylandServer BASE_NAME KWaylandServer EXPORT_FILE_NAME KWayland/Server/kwaylandserver_export.h ) add_library(KF5::WaylandServer ALIAS KF5WaylandServer) target_include_directories(KF5WaylandServer INTERFACE "$") target_link_libraries(KF5WaylandServer PUBLIC Qt5::Gui PRIVATE Wayland::Server EGL::EGL Qt5::Concurrent ) set_target_properties(KF5WaylandServer PROPERTIES VERSION ${KWAYLAND_VERSION_STRING} SOVERSION ${KWAYLAND_SOVERSION} EXPORT_NAME WaylandServer ) install(TARGETS KF5WaylandServer EXPORT KF5WaylandTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) set(SERVER_LIB_HEADERS ${CMAKE_CURRENT_BINARY_DIR}/KWayland/Server/kwaylandserver_export.h appmenu_interface.h blur_interface.h contrast_interface.h buffer_interface.h clientconnection.h compositor_interface.h datadevice_interface.h datadevicemanager_interface.h dataoffer_interface.h datasource_interface.h display.h dpms_interface.h + eglstream_controller_interface.h filtered_display.h fakeinput_interface.h global.h idle_interface.h idleinhibit_interface.h keyboard_interface.h remote_access_interface.h outputdevice_interface.h outputchangeset.h outputconfiguration_interface.h outputmanagement_interface.h output_interface.h pointer_interface.h pointerconstraints_interface.h pointergestures_interface.h plasmashell_interface.h plasmavirtualdesktop_interface.h plasmawindowmanagement_interface.h qtsurfaceextension_interface.h region_interface.h relativepointer_interface.h resource.h seat_interface.h server_decoration_interface.h server_decoration_palette_interface.h shadow_interface.h shell_interface.h slide_interface.h subcompositor_interface.h surface_interface.h textinput_interface.h touch_interface.h xdgdecoration_interface.h xdgshell_interface.h xdgforeign_interface.h xdgoutput_interface.h ) install(FILES ${SERVER_LIB_HEADERS} DESTINATION ${KF5_INCLUDE_INSTALL_DIR}/KWayland/Server COMPONENT Devel ) # make available to ecm_add_qch in parent folder set(KWaylandServer_APIDOX_SRCS ${SERVER_LIB_HEADERS} PARENT_SCOPE) include(ECMGeneratePriFile) ecm_generate_pri_file(BASE_NAME KWaylandServer LIB_NAME KF5WaylandServer DEPS "core" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF5}) install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) diff --git a/src/server/display.cpp b/src/server/display.cpp index 693f08b..6862645 100644 --- a/src/server/display.cpp +++ b/src/server/display.cpp @@ -1,633 +1,641 @@ /******************************************************************** Copyright 2014 Martin Gräßlin Copyright 2018 David Edmundson This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . *********************************************************************/ #include "display.h" #include "compositor_interface.h" #include "datadevicemanager_interface.h" #include "dpms_interface.h" #include "outputconfiguration_interface.h" #include "outputmanagement_interface.h" #include "outputdevice_interface.h" #include "idle_interface.h" #include "idleinhibit_interface_p.h" #include "remote_access_interface.h" #include "fakeinput_interface.h" #include "logging.h" #include "output_interface.h" #include "plasmashell_interface.h" #include "plasmawindowmanagement_interface.h" #include "pointerconstraints_interface_p.h" #include "pointergestures_interface_p.h" #include "qtsurfaceextension_interface.h" #include "seat_interface.h" #include "shadow_interface.h" #include "blur_interface.h" #include "contrast_interface.h" #include "relativepointer_interface_p.h" #include "server_decoration_interface.h" #include "slide_interface.h" #include "shell_interface.h" #include "subcompositor_interface.h" #include "textinput_interface_p.h" #include "xdgshell_v5_interface_p.h" #include "xdgforeign_interface.h" #include "xdgshell_v6_interface_p.h" #include "xdgshell_stable_interface_p.h" #include "appmenu_interface.h" #include "server_decoration_palette_interface.h" #include "plasmavirtualdesktop_interface.h" #include "xdgoutput_interface.h" #include "xdgdecoration_interface.h" +#include "eglstream_controller_interface.h" #include #include #include #include #include #include #include namespace KWayland { namespace Server { class Display::Private { public: Private(Display *q); void flush(); void dispatch(); void setRunning(bool running); void installSocketNotifier(); wl_display *display = nullptr; wl_event_loop *loop = nullptr; QString socketName = QStringLiteral("wayland-0"); bool running = false; bool automaticSocketNaming = false; QList outputs; QList outputdevices; QVector seats; QVector clients; EGLDisplay eglDisplay = EGL_NO_DISPLAY; private: Display *q; }; Display::Private::Private(Display *q) : q(q) { } void Display::Private::installSocketNotifier() { if (!QThread::currentThread()) { return; } int fd = wl_event_loop_get_fd(loop); if (fd == -1) { qCWarning(KWAYLAND_SERVER) << "Did not get the file descriptor for the event loop"; return; } QSocketNotifier *m_notifier = new QSocketNotifier(fd, QSocketNotifier::Read, q); QObject::connect(m_notifier, &QSocketNotifier::activated, q, [this] { dispatch(); } ); QObject::connect(QThread::currentThread()->eventDispatcher(), &QAbstractEventDispatcher::aboutToBlock, q, [this] { flush(); }); setRunning(true); } Display::Display(QObject *parent) : QObject(parent) , d(new Private(this)) { } Display::~Display() { terminate(); if (d->display) { wl_display_destroy(d->display); } } void Display::Private::flush() { if (!display || !loop) { return; } wl_display_flush_clients(display); } void Display::Private::dispatch() { if (!display || !loop) { return; } if (wl_event_loop_dispatch(loop, 0) != 0) { qCWarning(KWAYLAND_SERVER) << "Error on dispatching Wayland event loop"; } } void Display::setSocketName(const QString &name) { if (d->socketName == name) { return; } d->socketName = name; emit socketNameChanged(d->socketName); } QString Display::socketName() const { return d->socketName; } void Display::setAutomaticSocketNaming(bool automaticSocketNaming) { if (d->automaticSocketNaming == automaticSocketNaming) { return; } d->automaticSocketNaming = automaticSocketNaming; emit automaticSocketNamingChanged(automaticSocketNaming); } bool Display::automaticSocketNaming() const { return d->automaticSocketNaming; } void Display::start(StartMode mode) { Q_ASSERT(!d->running); Q_ASSERT(!d->display); d->display = wl_display_create(); if (mode == StartMode::ConnectToSocket) { if (d->automaticSocketNaming) { const char *socket = wl_display_add_socket_auto(d->display); if (socket == nullptr) { qCWarning(KWAYLAND_SERVER) << "Failed to create Wayland socket"; return; } const QString newEffectiveSocketName = QString::fromUtf8(socket); if (d->socketName != newEffectiveSocketName) { d->socketName = newEffectiveSocketName; emit socketNameChanged(d->socketName); } } else if (wl_display_add_socket(d->display, qPrintable(d->socketName)) != 0) { qCWarning(KWAYLAND_SERVER) << "Failed to create Wayland socket"; return; } } d->loop = wl_display_get_event_loop(d->display); d->installSocketNotifier(); } void Display::startLoop() { Q_ASSERT(!d->running); Q_ASSERT(d->display); d->installSocketNotifier(); } void Display::dispatchEvents(int msecTimeout) { Q_ASSERT(d->display); if (d->running) { d->dispatch(); } else if (d->loop) { wl_event_loop_dispatch(d->loop, msecTimeout); wl_display_flush_clients(d->display); } } void Display::terminate() { if (!d->running) { return; } emit aboutToTerminate(); wl_display_terminate(d->display); wl_display_destroy(d->display); d->display = nullptr; d->loop = nullptr; d->setRunning(false); } void Display::Private::setRunning(bool r) { Q_ASSERT(running != r); running = r; emit q->runningChanged(running); } OutputInterface *Display::createOutput(QObject *parent) { OutputInterface *output = new OutputInterface(this, parent); connect(output, &QObject::destroyed, this, [this,output] { d->outputs.removeAll(output); }); connect(this, &Display::aboutToTerminate, output, [this,output] { removeOutput(output); }); d->outputs << output; return output; } CompositorInterface *Display::createCompositor(QObject *parent) { CompositorInterface *compositor = new CompositorInterface(this, parent); connect(this, &Display::aboutToTerminate, compositor, [this,compositor] { delete compositor; }); return compositor; } ShellInterface *Display::createShell(QObject *parent) { ShellInterface *shell = new ShellInterface(this, parent); connect(this, &Display::aboutToTerminate, shell, [this,shell] { delete shell; }); return shell; } OutputDeviceInterface *Display::createOutputDevice(QObject *parent) { OutputDeviceInterface *output = new OutputDeviceInterface(this, parent); connect(output, &QObject::destroyed, this, [this,output] { d->outputdevices.removeAll(output); }); connect(this, &Display::aboutToTerminate, output, [this,output] { removeOutputDevice(output); }); d->outputdevices << output; return output; } OutputManagementInterface *Display::createOutputManagement(QObject *parent) { OutputManagementInterface *om = new OutputManagementInterface(this, parent); connect(this, &Display::aboutToTerminate, om, [this,om] { delete om; }); return om; } SeatInterface *Display::createSeat(QObject *parent) { SeatInterface *seat = new SeatInterface(this, parent); connect(seat, &QObject::destroyed, this, [this, seat] { d->seats.removeAll(seat); }); connect(this, &Display::aboutToTerminate, seat, [this,seat] { delete seat; }); d->seats << seat; return seat; } SubCompositorInterface *Display::createSubCompositor(QObject *parent) { auto c = new SubCompositorInterface(this, parent); connect(this, &Display::aboutToTerminate, c, [this,c] { delete c; }); return c; } DataDeviceManagerInterface *Display::createDataDeviceManager(QObject *parent) { auto m = new DataDeviceManagerInterface(this, parent); connect(this, &Display::aboutToTerminate, m, [this,m] { delete m; }); return m; } PlasmaShellInterface *Display::createPlasmaShell(QObject* parent) { auto s = new PlasmaShellInterface(this, parent); connect(this, &Display::aboutToTerminate, s, [this, s] { delete s; }); return s; } PlasmaWindowManagementInterface *Display::createPlasmaWindowManagement(QObject *parent) { auto wm = new PlasmaWindowManagementInterface(this, parent); connect(this, &Display::aboutToTerminate, wm, [this, wm] { delete wm; }); return wm; } QtSurfaceExtensionInterface *Display::createQtSurfaceExtension(QObject *parent) { auto s = new QtSurfaceExtensionInterface(this, parent); connect(this, &Display::aboutToTerminate, s, [this, s] { delete s; }); return s; } RemoteAccessManagerInterface *Display::createRemoteAccessManager(QObject *parent) { auto i = new RemoteAccessManagerInterface(this, parent); connect(this, &Display::aboutToTerminate, i, [this, i] { delete i; }); return i; } IdleInterface *Display::createIdle(QObject *parent) { auto i = new IdleInterface(this, parent); connect(this, &Display::aboutToTerminate, i, [this, i] { delete i; }); return i; } FakeInputInterface *Display::createFakeInput(QObject *parent) { auto i = new FakeInputInterface(this, parent); connect(this, &Display::aboutToTerminate, i, [this, i] { delete i; }); return i; } ShadowManagerInterface *Display::createShadowManager(QObject *parent) { auto s = new ShadowManagerInterface(this, parent); connect(this, &Display::aboutToTerminate, s, [this, s] { delete s; }); return s; } BlurManagerInterface *Display::createBlurManager(QObject *parent) { auto b = new BlurManagerInterface(this, parent); connect(this, &Display::aboutToTerminate, b, [this, b] { delete b; }); return b; } ContrastManagerInterface *Display::createContrastManager(QObject *parent) { auto b = new ContrastManagerInterface(this, parent); connect(this, &Display::aboutToTerminate, b, [this, b] { delete b; }); return b; } SlideManagerInterface *Display::createSlideManager(QObject *parent) { auto b = new SlideManagerInterface(this, parent); connect(this, &Display::aboutToTerminate, b, [this, b] { delete b; }); return b; } DpmsManagerInterface *Display::createDpmsManager(QObject *parent) { auto d = new DpmsManagerInterface(this, parent); connect(this, &Display::aboutToTerminate, d, [this, d] { delete d; }); return d; } ServerSideDecorationManagerInterface *Display::createServerSideDecorationManager(QObject *parent) { auto d = new ServerSideDecorationManagerInterface(this, parent); connect(this, &Display::aboutToTerminate, d, [d] { delete d; }); return d; } TextInputManagerInterface *Display::createTextInputManager(const TextInputInterfaceVersion &version, QObject *parent) { TextInputManagerInterface *t = nullptr; switch (version) { case TextInputInterfaceVersion::UnstableV0: t = new TextInputManagerUnstableV0Interface(this, parent); break; case TextInputInterfaceVersion::UnstableV1: // unsupported return nullptr; case TextInputInterfaceVersion::UnstableV2: t = new TextInputManagerUnstableV2Interface(this, parent); } connect(this, &Display::aboutToTerminate, t, [t] { delete t; }); return t; } XdgShellInterface *Display::createXdgShell(const XdgShellInterfaceVersion &version, QObject *parent) { XdgShellInterface *x = nullptr; switch (version) { case XdgShellInterfaceVersion::UnstableV5: x = new XdgShellV5Interface(this, parent); break; case XdgShellInterfaceVersion::UnstableV6: x = new XdgShellV6Interface(this, parent); break; case XdgShellInterfaceVersion::Stable: x = new XdgShellStableInterface(this, parent); break; } connect(this, &Display::aboutToTerminate, x, [x] { delete x; }); return x; } RelativePointerManagerInterface *Display::createRelativePointerManager(const RelativePointerInterfaceVersion &version, QObject *parent) { RelativePointerManagerInterface *r = nullptr; switch (version) { case RelativePointerInterfaceVersion::UnstableV1: r = new RelativePointerManagerUnstableV1Interface(this, parent); break; } connect(this, &Display::aboutToTerminate, r, [r] { delete r; }); return r; } PointerGesturesInterface *Display::createPointerGestures(const PointerGesturesInterfaceVersion &version, QObject *parent) { PointerGesturesInterface *p = nullptr; switch (version) { case PointerGesturesInterfaceVersion::UnstableV1: p = new PointerGesturesUnstableV1Interface(this, parent); break; } connect(this, &Display::aboutToTerminate, p, [p] { delete p; }); return p; } PointerConstraintsInterface *Display::createPointerConstraints(const PointerConstraintsInterfaceVersion &version, QObject *parent) { PointerConstraintsInterface *p = nullptr; switch (version) { case PointerConstraintsInterfaceVersion::UnstableV1: p = new PointerConstraintsUnstableV1Interface(this, parent); break; } connect(this, &Display::aboutToTerminate, p, [p] { delete p; }); return p; } XdgForeignInterface *Display::createXdgForeignInterface(QObject *parent) { XdgForeignInterface *foreign = new XdgForeignInterface(this, parent); connect(this, &Display::aboutToTerminate, foreign, [this,foreign] { delete foreign; }); return foreign; } IdleInhibitManagerInterface *Display::createIdleInhibitManager(const IdleInhibitManagerInterfaceVersion &version, QObject *parent) { IdleInhibitManagerInterface *i = nullptr; switch (version) { case IdleInhibitManagerInterfaceVersion::UnstableV1: i = new IdleInhibitManagerUnstableV1Interface(this, parent); break; } connect(this, &Display::aboutToTerminate, i, [this,i] { delete i; }); return i; } AppMenuManagerInterface *Display::createAppMenuManagerInterface(QObject *parent) { auto b = new AppMenuManagerInterface(this, parent); connect(this, &Display::aboutToTerminate, b, [this, b] { delete b; }); return b; } ServerSideDecorationPaletteManagerInterface *Display::createServerSideDecorationPaletteManager(QObject *parent) { auto b = new ServerSideDecorationPaletteManagerInterface(this, parent); connect(this, &Display::aboutToTerminate, b, [this, b] { delete b; }); return b; } PlasmaVirtualDesktopManagementInterface *Display::createPlasmaVirtualDesktopManagement(QObject *parent) { auto b = new PlasmaVirtualDesktopManagementInterface(this, parent); connect(this, &Display::aboutToTerminate, b, [this, b] { delete b; }); return b; } XdgOutputManagerInterface *Display::createXdgOutputManager(QObject *parent) { auto b = new XdgOutputManagerInterface(this, parent); connect(this, &Display::aboutToTerminate, b, [this, b] { delete b; }); return b; } XdgDecorationManagerInterface *Display::createXdgDecorationManager(XdgShellInterface *shellInterface, QObject *parent) { auto d = new XdgDecorationManagerInterface(this, shellInterface, parent); connect(this, &Display::aboutToTerminate, d, [d] { delete d; }); return d; } +EglStreamControllerInterface *Display::createEglStreamControllerInterface(QObject *parent) +{ + EglStreamControllerInterface *e = new EglStreamControllerInterface(this, parent); + connect(this, &Display::aboutToTerminate, e, [e] { delete e; }); + return e; +} + void Display::createShm() { Q_ASSERT(d->display); wl_display_init_shm(d->display); } void Display::removeOutput(OutputInterface *output) { d->outputs.removeAll(output); delete output; } void Display::removeOutputDevice(OutputDeviceInterface *output) { d->outputdevices.removeAll(output); delete output; } quint32 Display::nextSerial() { return wl_display_next_serial(d->display); } quint32 Display::serial() { return wl_display_get_serial(d->display); } bool Display::isRunning() const { return d->running; } Display::operator wl_display*() { return d->display; } Display::operator wl_display*() const { return d->display; } QList< OutputInterface* > Display::outputs() const { return d->outputs; } QList< OutputDeviceInterface* > Display::outputDevices() const { return d->outputdevices; } QVector Display::seats() const { return d->seats; } ClientConnection *Display::getConnection(wl_client *client) { Q_ASSERT(client); auto it = std::find_if(d->clients.constBegin(), d->clients.constEnd(), [client](ClientConnection *c) { return c->client() == client; } ); if (it != d->clients.constEnd()) { return *it; } // no ConnectionData yet, create it auto c = new ClientConnection(client, this); d->clients << c; connect(c, &ClientConnection::disconnected, this, [this] (ClientConnection *c) { const int index = d->clients.indexOf(c); Q_ASSERT(index != -1); d->clients.remove(index); Q_ASSERT(d->clients.indexOf(c) == -1); emit clientDisconnected(c); } ); emit clientConnected(c); return c; } QVector< ClientConnection* > Display::connections() const { return d->clients; } ClientConnection *Display::createClient(int fd) { Q_ASSERT(fd != -1); Q_ASSERT(d->display); wl_client *c = wl_client_create(d->display, fd); if (!c) { return nullptr; } return getConnection(c); } void Display::setEglDisplay(void *display) { if (d->eglDisplay != EGL_NO_DISPLAY) { qCWarning(KWAYLAND_SERVER) << "EGLDisplay cannot be changed"; return; } d->eglDisplay = (EGLDisplay)display; } void *Display::eglDisplay() const { return d->eglDisplay; } } } diff --git a/src/server/display.h b/src/server/display.h index a375357..d6a5f47 100644 --- a/src/server/display.h +++ b/src/server/display.h @@ -1,347 +1,356 @@ /******************************************************************** Copyright 2014 Martin Gräßlin Copyright 2018 David Edmundson This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . *********************************************************************/ #ifndef WAYLAND_SERVER_DISPLAY_H #define WAYLAND_SERVER_DISPLAY_H #include #include #include #include "clientconnection.h" struct wl_client; struct wl_display; struct wl_event_loop; namespace KWayland { /** * @short KWayland Server. * * This namespace groups all classes related to the Server module. * * The main entry point into the KWayland::Server API is the Display class. * It allows to create a Wayland server and create various global objects on it. * * KWayland::Server is an API to easily create a head-less Wayland server with a * Qt style API. * * @see Display **/ namespace Server { class CompositorInterface; class DataDeviceManagerInterface; class DpmsManagerInterface; class IdleInterface; enum class IdleInhibitManagerInterfaceVersion; class RemoteAccessManagerInterface; class IdleInhibitManagerInterface; class FakeInputInterface; class OutputInterface; class OutputDeviceInterface; class OutputConfigurationInterface; class OutputManagementInterface; class PlasmaShellInterface; class PlasmaWindowManagementInterface; class QtSurfaceExtensionInterface; class SeatInterface; class ShadowManagerInterface; class BlurManagerInterface; class ContrastManagerInterface; class ServerSideDecorationManagerInterface; class SlideManagerInterface; class ShellInterface; class SubCompositorInterface; enum class TextInputInterfaceVersion; class TextInputManagerInterface; class XdgShellV5Interface; enum class XdgShellInterfaceVersion; class XdgShellInterface; enum class RelativePointerInterfaceVersion; class RelativePointerManagerInterface; enum class PointerGesturesInterfaceVersion; class PointerGesturesInterface; enum class PointerConstraintsInterfaceVersion; class PointerConstraintsInterface; class XdgForeignInterface; class AppMenuManagerInterface; class ServerSideDecorationPaletteManagerInterface; class PlasmaVirtualDesktopManagementInterface; class XdgOutputManagerInterface; class XdgDecorationManagerInterface; +class EglStreamControllerInterface; /** * @brief Class holding the Wayland server display loop. * * @todo Improve documentation **/ class KWAYLANDSERVER_EXPORT Display : public QObject { Q_OBJECT Q_PROPERTY(QString socketName READ socketName WRITE setSocketName NOTIFY socketNameChanged) Q_PROPERTY(bool automaticSocketNaming READ automaticSocketNaming WRITE setAutomaticSocketNaming NOTIFY automaticSocketNamingChanged) Q_PROPERTY(bool running READ isRunning NOTIFY runningChanged) public: explicit Display(QObject *parent = nullptr); virtual ~Display(); /** * Sets the basename of the socket to @p name. If @p name is empty, it will use * wl_display_add_socket_auto to get a free socket with a filename "wayland-%d". **/ void setSocketName(const QString &name); QString socketName() const; /** * If automaticSocketNaming is true, the manually set socketName is ignored * and it will use wl_display_add_socket_auto on start to get a free socket with * a filename "wayland-%d" instead. The effective socket is written into socketName. * @since 5.55 **/ void setAutomaticSocketNaming(bool automaticSocketNaming); bool automaticSocketNaming() const; quint32 serial(); quint32 nextSerial(); /** * How to setup the server connection. * @li ConnectToSocket: the server will open the socket identified by the socket name * @li ConnectClientsOnly: only connections through createClient are possible **/ enum class StartMode { ConnectToSocket, ConnectClientsOnly }; void start(StartMode mode = StartMode::ConnectToSocket); void terminate(); /** * Starts the event loop for the server socket. * This method should only be used if start() is used before creating the * QCoreApplication. In that case start() cannot fully setup the event processing * and the loop needs to be started after the QCoreApplication got created. * @see start * @see dispatchEvents **/ void startLoop(); /** * Dispatches pending events in a blocking way. May only be used if the Display is * created and started before the QCoreApplication is created. Once the QCoreApplication * is created and the event loop is started this method delegates to the normal dispatch * handling. * @see startLoop **/ void dispatchEvents(int msecTimeout = -1); /** * Create a client for the given file descriptor. * * The client is created as if it connected through the normal server * socket. This method can be used to create a connection bypassing the * normal socket connection. It's recommended to use together with * socketpair and pass the other side of the socket to the client. * * @param fd The file descriptor for the socket to the client * @returns The new ClientConnection or @c null on failure. **/ ClientConnection *createClient(int fd); operator wl_display*(); operator wl_display*() const; bool isRunning() const; OutputInterface *createOutput(QObject *parent = nullptr); void removeOutput(OutputInterface *output); QList outputs() const; OutputDeviceInterface *createOutputDevice(QObject *parent = nullptr); void removeOutputDevice(OutputDeviceInterface *output); QList outputDevices() const; CompositorInterface *createCompositor(QObject *parent = nullptr); void createShm(); ShellInterface *createShell(QObject *parent = nullptr); SeatInterface *createSeat(QObject *parent = nullptr); /** * @returns All SeatInterface currently managed on the Display. * @since 5.6 **/ QVector seats() const; SubCompositorInterface *createSubCompositor(QObject *parent = nullptr); DataDeviceManagerInterface *createDataDeviceManager(QObject *parent = nullptr); OutputManagementInterface *createOutputManagement(QObject *parent = nullptr); PlasmaShellInterface *createPlasmaShell(QObject *parent = nullptr); PlasmaWindowManagementInterface *createPlasmaWindowManagement(QObject *parent = nullptr); QtSurfaceExtensionInterface *createQtSurfaceExtension(QObject *parent = nullptr); IdleInterface *createIdle(QObject *parent = nullptr); RemoteAccessManagerInterface *createRemoteAccessManager(QObject *parent = nullptr); FakeInputInterface *createFakeInput(QObject *parent = nullptr); ShadowManagerInterface *createShadowManager(QObject *parent = nullptr); BlurManagerInterface *createBlurManager(QObject *parent = nullptr); ContrastManagerInterface *createContrastManager(QObject *parent = nullptr); SlideManagerInterface *createSlideManager(QObject *parent = nullptr); DpmsManagerInterface *createDpmsManager(QObject *parent = nullptr); /** * @since 5.6 **/ ServerSideDecorationManagerInterface *createServerSideDecorationManager(QObject *parent = nullptr); /** * Create the text input manager in interface @p version. * @returns The created manager object * @since 5.23 **/ TextInputManagerInterface *createTextInputManager(const TextInputInterfaceVersion &version, QObject *parent = nullptr); /** * Creates the XdgShell in interface @p version. * * @since 5.25 **/ XdgShellInterface *createXdgShell(const XdgShellInterfaceVersion &version, QObject *parent = nullptr); /** * Creates the RelativePointerManagerInterface in interface @p version * * @returns The created manager object * @since 5.28 **/ RelativePointerManagerInterface *createRelativePointerManager(const RelativePointerInterfaceVersion &version, QObject *parent = nullptr); /** * Creates the PointerGesturesInterface in interface @p version * * @returns The created manager object * @since 5.29 **/ PointerGesturesInterface *createPointerGestures(const PointerGesturesInterfaceVersion &version, QObject *parent = nullptr); /** * Creates the PointerConstraintsInterface in interface @p version * * @returns The created manager object * @since 5.29 **/ PointerConstraintsInterface *createPointerConstraints(const PointerConstraintsInterfaceVersion &version, QObject *parent = nullptr); /** * Creates the XdgForeignInterface in interface @p version * * @returns The created manager object * @since 5.40 **/ XdgForeignInterface *createXdgForeignInterface(QObject *parent = nullptr); /** * Creates the IdleInhibitManagerInterface in interface @p version. * * @returns The created manager object * @since 5.41 **/ IdleInhibitManagerInterface *createIdleInhibitManager(const IdleInhibitManagerInterfaceVersion &version, QObject *parent = nullptr); /** * Creates the AppMenuManagerInterface in interface @p version. * * @returns The created manager object * @since 5.42 **/ AppMenuManagerInterface *createAppMenuManagerInterface(QObject *parent = nullptr); /** * Creates the ServerSideDecorationPaletteManagerInterface in interface @p version. * * @returns The created manager object * @since 5.42 **/ ServerSideDecorationPaletteManagerInterface *createServerSideDecorationPaletteManager(QObject *parent = nullptr); /** * Creates the XdgOutputManagerInterface * * @return the created manager * @since 5.47 */ XdgOutputManagerInterface *createXdgOutputManager(QObject *parent = nullptr); /** * Creates the PlasmaVirtualDesktopManagementInterface in interface @p version. * * @returns The created manager object * @since 5.52 **/ PlasmaVirtualDesktopManagementInterface *createPlasmaVirtualDesktopManagement(QObject *parent = nullptr); /** * Creates the XdgDecorationManagerInterface * @arg shellInterface A created XdgShellInterface based on XDG_WM_BASE * * @return the created manager * @since 5.54 */ XdgDecorationManagerInterface *createXdgDecorationManager(XdgShellInterface *shellInterface, QObject *parent = nullptr); + /** + * Creates the EglStreamControllerInterface + * + * @return the created EGL Stream controller + * @since 5.58 + */ + EglStreamControllerInterface *createEglStreamControllerInterface(QObject *parent = nullptr); + /** * Gets the ClientConnection for the given @p client. * If there is no ClientConnection yet for the given @p client, it will be created. * @param client The native client for which the ClientConnection is retrieved * @return The ClientConnection for the given native client **/ ClientConnection *getConnection(wl_client *client); QVector connections() const; /** * Set the EGL @p display for this Wayland display. * The EGLDisplay can only be set once and must be alive as long as the Wayland display * is alive. The user should have set up the binding between the EGLDisplay and the * Wayland display prior to calling this method. * * @see eglDisplay * @since 5.3 **/ void setEglDisplay(void *display); /** * @returns the EGLDisplay used for this Wayland display or EGL_NO_DISPLAY if not set. * @see setEglDisplay * @since 5.3 **/ void *eglDisplay() const; Q_SIGNALS: void socketNameChanged(const QString&); void automaticSocketNamingChanged(bool); void runningChanged(bool); void aboutToTerminate(); void clientConnected(KWayland::Server::ClientConnection*); void clientDisconnected(KWayland::Server::ClientConnection*); private: class Private; QScopedPointer d; }; } } #endif diff --git a/src/server/eglstream_controller_interface.cpp b/src/server/eglstream_controller_interface.cpp new file mode 100644 index 0000000..0196454 --- /dev/null +++ b/src/server/eglstream_controller_interface.cpp @@ -0,0 +1,107 @@ +/**************************************************************************** +Copyright 2019 NVIDIA Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +****************************************************************************/ +#include "eglstream_controller_interface_p.h" +#include "clientconnection.h" +#include "display.h" +#include "logging.h" + +#include +#include + +namespace KWayland +{ +namespace Server +{ + +const quint32 EglStreamControllerInterface::Private::s_version = 1; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +const struct wl_eglstream_controller_interface EglStreamControllerInterface::Private::s_interface = { + attachStreamConsumer, + attachStreamConsumerAttribs +}; +#endif + +void EglStreamControllerInterface::Private::attachStreamConsumer(wl_client *client, + wl_resource *resource, + wl_resource *surface, + wl_resource *eglStream) +{ + wl_array noAttribs = { 0, 0, nullptr }; + attachStreamConsumerAttribs(client, resource, surface, eglStream, &noAttribs); +} + +void EglStreamControllerInterface::Private::attachStreamConsumerAttribs(wl_client *client, + wl_resource *resource, + wl_resource *surface, + wl_resource *eglStream, + wl_array *attribs) +{ + Q_UNUSED(client); + Private *p = reinterpret_cast(wl_resource_get_user_data(resource)); + emit p->q->streamConsumerAttached(SurfaceInterface::get(surface), eglStream, attribs); +} + +EglStreamControllerInterface::Private::Private(EglStreamControllerInterface *q, Display *display) + // libnvidia-egl-wayland.so.1 may not be present on all systems, so we load it dynamically + : Global::Private(display, + (wl_interface *)QLibrary::resolve(QLatin1String("libnvidia-egl-wayland.so.1"), + "wl_eglstream_controller_interface"), + s_version) + , q(q) +{ +} + +void EglStreamControllerInterface::Private::create() +{ + // bail out early if we were unable to load the interface + if (m_interface == nullptr) { + qCWarning(KWAYLAND_SERVER) << "failed to resolve wl_eglstream_controller_interface"; + return; + } + + Global::Private::create(); +} + +void EglStreamControllerInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id) +{ + wl_resource *r = display->getConnection(client)->createResource(m_interface, version, id); + if (r == nullptr) { + wl_client_post_no_memory(client); + return; + } + + wl_resource_set_implementation(r, &s_interface, this, nullptr); +} + +EglStreamControllerInterface::~EglStreamControllerInterface() = default; + +EglStreamControllerInterface::EglStreamControllerInterface(Display *display, QObject *parent) + : Global(new Private(this, display), parent) +{ +} + +void EglStreamControllerInterface::create() +{ + static_cast(*d).create(); +} + +} +} diff --git a/src/server/eglstream_controller_interface.h b/src/server/eglstream_controller_interface.h new file mode 100644 index 0000000..175114a --- /dev/null +++ b/src/server/eglstream_controller_interface.h @@ -0,0 +1,67 @@ +/**************************************************************************** +Copyright 2019 NVIDIA Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +****************************************************************************/ +#ifndef WAYLAND_SERVER_EGLSTREAM_CONTROLLER_INTERFACE_H +#define WAYLAND_SERVER_EGLSTREAM_CONTROLLER_INTERFACE_H + +#include "global.h" +#include "surface_interface.h" + +#include +#include +#include + +namespace KWayland +{ +namespace Server +{ + +class Display; + +/** + * @brief Represents the Global for the wl_eglstream_controller interface. + * + * This class handles requests (typically from the NVIDIA EGL driver) to attach + * a newly created EGL Stream to a Wayland surface, facilitating the sharing + * of buffer contents between client and compositor. + * + */ +class KWAYLANDSERVER_EXPORT EglStreamControllerInterface : public Global +{ + Q_OBJECT +public: + ~EglStreamControllerInterface() override; + void create(); + +Q_SIGNALS: + /** + * Emitted when a new stream attach request is received. + */ + void streamConsumerAttached(SurfaceInterface *surface, void *eglStream, wl_array *attribs); +private: + explicit EglStreamControllerInterface(Display *display, QObject *parent = nullptr); + + class Private; + friend class Display; +}; + +} +} + +#endif diff --git a/src/server/eglstream_controller_interface_p.h b/src/server/eglstream_controller_interface_p.h new file mode 100644 index 0000000..386f55d --- /dev/null +++ b/src/server/eglstream_controller_interface_p.h @@ -0,0 +1,58 @@ +/**************************************************************************** +Copyright 2019 NVIDIA Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +****************************************************************************/ +#ifndef WAYLAND_SERVER_EGLSTREAM_CONTROLLER_INTERFACE_P_H +#define WAYLAND_SERVER_EGLSTREAM_CONTROLLER_INTERFACE_P_H + +#include "eglstream_controller_interface.h" +#include "global_p.h" + +#include + +namespace KWayland +{ +namespace Server +{ + +class Q_DECL_HIDDEN EglStreamControllerInterface::Private : public Global::Private +{ +public: + Private(EglStreamControllerInterface *controller, Display *display); + void create(); + +private: + static void attachStreamConsumer(wl_client *client, + wl_resource *resource, + wl_resource *surface, + wl_resource *eglStream); + static void attachStreamConsumerAttribs(wl_client *client, + wl_resource *resource, + wl_resource *surface, + wl_resource *eglStream, + wl_array *attribs); + static const struct wl_eglstream_controller_interface s_interface; + static const quint32 s_version; + void bind(wl_client *client, uint32_t version, uint32_t id) override; + EglStreamControllerInterface *q; +}; + +} +} + +#endif