diff --git a/CMakeLists.txt b/CMakeLists.txt index eee10b5dad..f6945c5d90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -759,11 +759,11 @@ set(kwin_WAYLAND_SRCS ) ecm_qt_declare_logging_category(kwin_WAYLAND_SRCS HEADER - kwinpipewire_logging.h + kwinscreencast_logging.h IDENTIFIER - KWIN_PIPEWIRE + KWIN_SCREENCAST CATEGORY_NAME - kwin_pipewire + kwin_screencast DEFAULT_SEVERITY Warning ) diff --git a/data/org_kde_kwin.categories b/data/org_kde_kwin.categories index 8e788077e1..ec9b3aa673 100644 --- a/data/org_kde_kwin.categories +++ b/data/org_kde_kwin.categories @@ -21,3 +21,4 @@ kwin_qpa_plugin KWin QtPlatformAbstraction plugin DEFAULT_SEVERITY [CRITICAL] ID kwin_scene_xrender KWin XRender based compositor scene plugin DEFAULT_SEVERITY [CRITICAL] IDENTIFIER [KWIN_XRENDER] kwin_scene_qpainter KWin QPainter based compositor scene plugin DEFAULT_SEVERITY [CRITICAL] IDENTIFIER [KWIN_QPAINTER] kwin_scene_opengl KWin OpenGL based compositor scene plugins DEFAULT_SEVERITY [CRITICAL] IDENTIFIER [KWIN_OPENGL] +kwin_screencast KWin Screen Cast Service DEFAULT_SEVERITY [WARNING] IDENTIFIER [KWIN_SCREENCAST] diff --git a/plugins/scenes/opengl/scene_opengl.cpp b/plugins/scenes/opengl/scene_opengl.cpp index 950890830e..855a261faa 100644 --- a/plugins/scenes/opengl/scene_opengl.cpp +++ b/plugins/scenes/opengl/scene_opengl.cpp @@ -49,8 +49,6 @@ along with this program. If not, see . #include "decorations/decoratedclient.h" #include -#include "abstract_wayland_output.h" -#include "abstract_egl_backend.h" #include #include #include diff --git a/screencast/pipewirecore.cpp b/screencast/pipewirecore.cpp index 592aec872d..207aa233e1 100644 --- a/screencast/pipewirecore.cpp +++ b/screencast/pipewirecore.cpp @@ -21,10 +21,15 @@ */ #include "pipewirecore.h" +#include "kwinscreencast_logging.h" + +#include + #include #include -#include -#include "kwinpipewire_logging.h" + +namespace KWin +{ PipeWireCore::PipeWireCore() { @@ -56,7 +61,7 @@ void PipeWireCore::onCoreError(void* data, uint32_t id, int seq, int res, const { Q_UNUSED(seq) - qCWarning(KWIN_PIPEWIRE) << "PipeWire remote error: " << message; + qCWarning(KWIN_SCREENCAST) << "PipeWire remote error: " << message; if (id == PW_ID_CORE && res == -EPIPE) { PipeWireCore *pw = static_cast(data); Q_EMIT pw->pipewireFailed(QString::fromUtf8(message)); @@ -72,26 +77,26 @@ bool PipeWireCore::init() connect(notifier, &QSocketNotifier::activated, this, [this] { int result = pw_loop_iterate (pwMainLoop, 0); if (result < 0) - qCWarning(KWIN_PIPEWIRE) << "pipewire_loop_iterate failed: " << result; + qCWarning(KWIN_SCREENCAST) << "pipewire_loop_iterate failed: " << result; } ); pwContext = pw_context_new(pwMainLoop, nullptr, 0); if (!pwContext) { - qCWarning(KWIN_PIPEWIRE) << "Failed to create PipeWire context"; + qCWarning(KWIN_SCREENCAST) << "Failed to create PipeWire context"; m_error = i18n("Failed to create PipeWire context"); return false; } pwCore = pw_context_connect(pwContext, nullptr, 0); if (!pwCore) { - qCWarning(KWIN_PIPEWIRE) << "Failed to connect PipeWire context"; + qCWarning(KWIN_SCREENCAST) << "Failed to connect PipeWire context"; m_error = i18n("Failed to connect PipeWire context"); return false; } if (pw_loop_iterate(pwMainLoop, 0) < 0) { - qCWarning(KWIN_PIPEWIRE) << "Failed to start main PipeWire loop"; + qCWarning(KWIN_SCREENCAST) << "Failed to start main PipeWire loop"; m_error = i18n("Failed to start main PipeWire loop"); return false; } @@ -113,3 +118,5 @@ QSharedPointer< PipeWireCore > PipeWireCore::self() } return ret; } + +} // namespace KWin diff --git a/screencast/pipewirecore.h b/screencast/pipewirecore.h index ccf1ab1222..0deb10d700 100644 --- a/screencast/pipewirecore.h +++ b/screencast/pipewirecore.h @@ -22,10 +22,14 @@ #pragma once -#include #include -#include +#include + #include +#include + +namespace KWin +{ class PipeWireCore : public QObject { @@ -52,3 +56,5 @@ public: Q_SIGNALS: void pipewireFailed(const QString &message); }; + +} // namespace KWin diff --git a/screencast/pipewirestream.cpp b/screencast/pipewirestream.cpp index 87bfaa2ed6..a7a6705206 100644 --- a/screencast/pipewirestream.cpp +++ b/screencast/pipewirestream.cpp @@ -21,36 +21,39 @@ */ #include "pipewirestream.h" - -#include -#include -#include -#include -#include - -#include -#include -#include "utils.h" #include "cursor.h" +#include "dmabuftexture.h" +#include "kwineglimagetexture.h" +#include "kwinscreencast_logging.h" #include "main.h" +#include "pipewirecore.h" #include "platform.h" -#include "scenes/opengl/egl_dmabuf.h" #include "platformsupport/scenes/opengl/drm_fourcc.h" -#include "kwineglimagetexture.h" -#include "dmabuftexture.h" -#include "pipewirecore.h" -#include "kwinpipewire_logging.h" +#include "scenes/opengl/egl_dmabuf.h" +#include "utils.h" #include +#include +#include + +#include + +#include +#include +#include + +namespace KWin +{ + void PipeWireStream::onStreamStateChanged(void *data, pw_stream_state old, pw_stream_state state, const char *error_message) { PipeWireStream *pw = static_cast(data); - qCDebug(KWIN_PIPEWIRE) << "state changed"<< pw_stream_state_as_string(old) << " -> " << pw_stream_state_as_string(state) << error_message; + qCDebug(KWIN_SCREENCAST) << "state changed"<< pw_stream_state_as_string(old) << " -> " << pw_stream_state_as_string(state) << error_message; switch (state) { case PW_STREAM_STATE_ERROR: - qCWarning(KWIN_PIPEWIRE) << "Stream error: " << error_message; + qCWarning(KWIN_SCREENCAST) << "Stream error: " << error_message; break; case PW_STREAM_STATE_PAUSED: if (pw->nodeId() == 0 && pw->pwStream) { @@ -84,7 +87,7 @@ void PipeWireStream::newStreamParams() spa_pod_builder pod_builder = SPA_POD_BUILDER_INIT (paramsBuffer, sizeof (paramsBuffer)); spa_rectangle resolution = SPA_RECTANGLE(uint32_t(m_resolution.width()), uint32_t(m_resolution.height())); - const auto cursorSize = KWin::Cursors::self()->currentCursor()->themeSize(); + const auto cursorSize = Cursors::self()->currentCursor()->themeSize(); const spa_pod *params[] = { (spa_pod*) spa_pod_builder_add_object(&pod_builder, SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers, @@ -110,7 +113,7 @@ void PipeWireStream::onStreamParamChanged(void *data, uint32_t id, const struct PipeWireStream *pw = static_cast(data); spa_format_video_raw_parse (format, &pw->videoFormat); - qCDebug(KWIN_PIPEWIRE) << "Stream format changed" << pw << pw->videoFormat.format; + qCDebug(KWIN_SCREENCAST) << "Stream format changed" << pw << pw->videoFormat.format; pw->newStreamParams(); } @@ -122,11 +125,11 @@ void PipeWireStream::onStreamAddBuffer(void *data, pw_buffer *buffer) spa_data->mapoffset = 0; spa_data->flags = SPA_DATA_FLAG_READWRITE; - QSharedPointer dmabuf (KWin::kwinApp()->platform()->createDmaBufTexture(stream->m_resolution)); + QSharedPointer dmabuf(kwinApp()->platform()->createDmaBufTexture(stream->m_resolution)); if (dmabuf) { spa_data->type = SPA_DATA_DmaBuf; spa_data->fd = dmabuf->fd(); - spa_data->data = NULL; + spa_data->data = nullptr; spa_data->maxsize = dmabuf->stride() * stream->m_resolution.height(); stream->m_dmabufDataForPwBuffer.insert(buffer, dmabuf); @@ -138,30 +141,30 @@ void PipeWireStream::onStreamAddBuffer(void *data, pw_buffer *buffer) spa_data->type = SPA_DATA_MemFd; spa_data->fd = memfd_create("kwin-screencast-memfd", MFD_CLOEXEC | MFD_ALLOW_SEALING); if (spa_data->fd == -1) { - qCCritical(KWIN_PIPEWIRE) << "memfd: Can't create memfd"; + qCCritical(KWIN_SCREENCAST) << "memfd: Can't create memfd"; return; } spa_data->mapoffset = 0; if (ftruncate (spa_data->fd, spa_data->maxsize) < 0) { - qCCritical(KWIN_PIPEWIRE) << "memfd: Can't truncate to" << spa_data->maxsize; + qCCritical(KWIN_SCREENCAST) << "memfd: Can't truncate to" << spa_data->maxsize; return; } unsigned int seals = F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL; if (fcntl(spa_data->fd, F_ADD_SEALS, seals) == -1) - qCWarning(KWIN_PIPEWIRE) << "memfd: Failed to add seals"; + qCWarning(KWIN_SCREENCAST) << "memfd: Failed to add seals"; - spa_data->data = mmap(NULL, + spa_data->data = mmap(nullptr, spa_data->maxsize, PROT_READ | PROT_WRITE, MAP_SHARED, spa_data->fd, spa_data->mapoffset); if (spa_data->data == MAP_FAILED) - qCCritical(KWIN_PIPEWIRE) << "memfd: Failed to mmap memory"; + qCCritical(KWIN_SCREENCAST) << "memfd: Failed to mmap memory"; else - qCDebug(KWIN_PIPEWIRE) << "memfd: created successfully" << spa_data->data << spa_data->maxsize; + qCDebug(KWIN_SCREENCAST) << "memfd: created successfully" << spa_data->data << spa_data->maxsize; #endif } } @@ -212,7 +215,7 @@ bool PipeWireStream::init() connect(pwCore.data(), &PipeWireCore::pipewireFailed, this, &PipeWireStream::coreFailed); if (!createStream()) { - qCWarning(KWIN_PIPEWIRE) << "Failed to create PipeWire stream"; + qCWarning(KWIN_SCREENCAST) << "Failed to create PipeWire stream"; m_error = i18n("Failed to create PipeWire stream"); return false; } @@ -247,7 +250,7 @@ bool PipeWireStream::createStream() spa_rectangle resolution = SPA_RECTANGLE(uint32_t(m_resolution.width()), uint32_t(m_resolution.height())); - const auto format = m_hasAlpha || m_gbmDevice ? SPA_VIDEO_FORMAT_BGRA : SPA_VIDEO_FORMAT_BGR; + const auto format = m_hasAlpha ? SPA_VIDEO_FORMAT_BGRA : SPA_VIDEO_FORMAT_BGR; const spa_pod *param = (spa_pod*)spa_pod_builder_add_object(&podBuilder, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, @@ -262,16 +265,16 @@ bool PipeWireStream::createStream() auto flags = pw_stream_flags(PW_STREAM_FLAG_DRIVER | PW_STREAM_FLAG_ALLOC_BUFFERS); if (pw_stream_connect(pwStream, PW_DIRECTION_OUTPUT, SPA_ID_INVALID, flags, ¶m, 1) != 0) { - qCWarning(KWIN_PIPEWIRE) << "Could not connect to stream"; + qCWarning(KWIN_SCREENCAST) << "Could not connect to stream"; pw_stream_destroy(pwStream); return false; } if (m_cursor.mode == KWaylandServer::ScreencastInterface::Embedded) { - connect(KWin::Cursors::self(), &KWin::Cursors::positionChanged, this, [this] { + connect(Cursors::self(), &Cursors::positionChanged, this, [this] { if (m_cursor.lastFrameTexture) { m_repainting = true; - recordFrame(m_cursor.lastFrameTexture.data(), QRegion{m_cursor.lastRect} | cursorGeometry(KWin::Cursors::self()->currentCursor())); + recordFrame(m_cursor.lastFrameTexture.data(), QRegion{m_cursor.lastRect} | cursorGeometry(Cursors::self()->currentCursor())); m_repainting = false; } }); @@ -291,9 +294,9 @@ void PipeWireStream::stop() delete this; } -static KWin::GLTexture *copyTexture(KWin::GLTexture *texture) +static GLTexture *copyTexture(GLTexture *texture) { - KWin::GLTexture *copy = new KWin::GLTexture(texture->internalFormat(), texture->size()); + GLTexture *copy = new GLTexture(texture->internalFormat(), texture->size()); copy->setFilter(GL_LINEAR); copy->setWrapMode(GL_CLAMP_TO_EDGE); @@ -305,7 +308,7 @@ static KWin::GLTexture *copyTexture(KWin::GLTexture *texture) return copy; } -void PipeWireStream::recordFrame(KWin::GLTexture* frameTexture, const QRegion &damagedRegion) +void PipeWireStream::recordFrame(GLTexture *frameTexture, const QRegion &damagedRegion) { Q_ASSERT(!m_stopped); Q_ASSERT(frameTexture); @@ -320,7 +323,7 @@ void PipeWireStream::recordFrame(KWin::GLTexture* frameTexture, const QRegion &d auto state = pw_stream_get_state(pwStream, &error); if (state != PW_STREAM_STATE_STREAMING) { if (error) { - qCWarning(KWIN_PIPEWIRE) << "Failed to record frame: stream is not active" << error; + qCWarning(KWIN_SCREENCAST) << "Failed to record frame: stream is not active" << error; } return; } @@ -336,7 +339,7 @@ void PipeWireStream::recordFrame(KWin::GLTexture* frameTexture, const QRegion &d uint8_t *data = (uint8_t *) spa_data->data; if (!data && spa_buffer->datas->type != SPA_DATA_DmaBuf) { - qCWarning(KWIN_PIPEWIRE) << "Failed to record frame: invalid buffer data"; + qCWarning(KWIN_SCREENCAST) << "Failed to record frame: invalid buffer data"; pw_stream_queue_buffer(pwStream, buffer); return; } @@ -349,7 +352,7 @@ void PipeWireStream::recordFrame(KWin::GLTexture* frameTexture, const QRegion &d const uint bufferSize = stride * size.height(); if (bufferSize > spa_data->maxsize) { - qCDebug(KWIN_PIPEWIRE) << "Failed to record frame: frame is too big"; + qCDebug(KWIN_SCREENCAST) << "Failed to record frame: frame is too big"; pw_stream_queue_buffer(pwStream, buffer); return; } @@ -359,7 +362,7 @@ void PipeWireStream::recordFrame(KWin::GLTexture* frameTexture, const QRegion &d frameTexture->bind(); glGetTextureImage(frameTexture->texture(), 0, m_hasAlpha ? GL_BGRA : GL_BGR, GL_UNSIGNED_BYTE, bufferSize, data); - auto cursor = KWin::Cursors::self()->currentCursor(); + auto cursor = Cursors::self()->currentCursor(); if (m_cursor.mode == KWaylandServer::ScreencastInterface::Embedded && m_cursor.viewport.contains(cursor->pos())) { QImage dest(data, size.width(), size.height(), QImage::Format_RGBA8888_Premultiplied); QPainter painter(&dest); @@ -390,13 +393,13 @@ void PipeWireStream::recordFrame(KWin::GLTexture* frameTexture, const QRegion &d frameTexture->render(damagedRegion, r, true); - auto cursor = KWin::Cursors::self()->currentCursor(); + auto cursor = Cursors::self()->currentCursor(); if (m_cursor.mode == KWaylandServer::ScreencastInterface::Embedded && m_cursor.viewport.contains(cursor->pos())) { if (!m_repainting) //We need to copy the last version of the stream to render the moved cursor on top m_cursor.lastFrameTexture.reset(copyTexture(frameTexture)); if (!m_cursor.texture || m_cursor.lastKey != cursor->image().cacheKey()) - m_cursor.texture.reset(new KWin::GLTexture(cursor->image())); + m_cursor.texture.reset(new GLTexture(cursor->image())); m_cursor.texture->setYInverted(false); m_cursor.texture->bind(); @@ -418,20 +421,20 @@ void PipeWireStream::recordFrame(KWin::GLTexture* frameTexture, const QRegion &d frameTexture->unbind(); if (m_cursor.mode == KWaylandServer::ScreencastInterface::Metadata) { - sendCursorData(KWin::Cursors::self()->currentCursor(), + sendCursorData(Cursors::self()->currentCursor(), (spa_meta_cursor *) spa_buffer_find_meta_data (spa_buffer, SPA_META_Cursor, sizeof (spa_meta_cursor))); } pw_stream_queue_buffer(pwStream, buffer); } -QRect PipeWireStream::cursorGeometry(KWin::Cursor *cursor) const +QRect PipeWireStream::cursorGeometry(Cursor *cursor) const { const auto position = (cursor->pos() - m_cursor.viewport.topLeft() - cursor->hotspot()) * m_cursor.scale; return QRect{position, m_cursor.texture->size()}; } -void PipeWireStream::sendCursorData(KWin::Cursor* cursor, spa_meta_cursor *spa_meta_cursor) +void PipeWireStream::sendCursorData(Cursor *cursor, spa_meta_cursor *spa_meta_cursor) { if (!cursor || !spa_meta_cursor) { return; @@ -476,3 +479,5 @@ void PipeWireStream::setCursorMode(KWaylandServer::ScreencastInterface::CursorMo m_cursor.scale = scale; m_cursor.viewport = viewport; } + +} // namespace KWin diff --git a/screencast/pipewirestream.h b/screencast/pipewirestream.h index 7402f68961..565c89511d 100644 --- a/screencast/pipewirestream.h +++ b/screencast/pipewirestream.h @@ -22,27 +22,27 @@ #pragma once -#include -#include +#include "config-kwin.h" +#include "kwinglobals.h" + +#include + #include +#include #include -#include +#include -#include "kwinglobals.h" -#include "config-kwin.h" #include #include -#include #include - -#undef Status +#include namespace KWin { - class Cursor; - class GLTexture; - class DmaBufTexture; -} + +class Cursor; +class DmaBufTexture; +class GLTexture; class PipeWireCore; class KWIN_EXPORT PipeWireStream : public QObject @@ -62,7 +62,7 @@ public: void stop(); /** Renders @p frame into the current framebuffer into the stream */ - void recordFrame(KWin::GLTexture *frame, const QRegion &damagedRegion); + void recordFrame(GLTexture *frame, const QRegion &damagedRegion); void setCursorMode(KWaylandServer::ScreencastInterface::CursorMode mode, qreal scale, const QRect &viewport); @@ -80,7 +80,7 @@ private: bool createStream(); void updateParams(); void coreFailed(const QString &errorMessage); - void sendCursorData(KWin::Cursor* cursor, spa_meta_cursor *spa_cursor); + void sendCursorData(Cursor *cursor, spa_meta_cursor *spa_cursor); void newStreamParams(); QSharedPointer pwCore; @@ -96,7 +96,6 @@ private: spa_video_info_raw videoFormat; QString m_error; const bool m_hasAlpha; - struct gbm_device *m_gbmDevice = nullptr; struct { KWaylandServer::ScreencastInterface::CursorMode mode = KWaylandServer::ScreencastInterface::Hidden; @@ -104,11 +103,13 @@ private: QRect viewport; qint64 lastKey = 0; QRect lastRect; - QScopedPointer texture; - QScopedPointer lastFrameTexture; + QScopedPointer texture; + QScopedPointer lastFrameTexture; } m_cursor; bool m_repainting = false; - QRect cursorGeometry(KWin::Cursor *cursor) const; + QRect cursorGeometry(Cursor *cursor) const; - QHash> m_dmabufDataForPwBuffer; + QHash> m_dmabufDataForPwBuffer; }; + +} // namespace KWin diff --git a/screencast/screencastmanager.cpp b/screencast/screencastmanager.cpp index 627634d13e..6d108a5541 100644 --- a/screencast/screencastmanager.cpp +++ b/screencast/screencastmanager.cpp @@ -36,7 +36,8 @@ #include #include -using namespace KWin; +namespace KWin +{ ScreencastManager::ScreencastManager(QObject *parent) : QObject(parent) @@ -53,7 +54,7 @@ class EGLFence : public QObject public: EGLFence(EGLDisplay eglDisplay) : m_eglDisplay(eglDisplay) - , m_sync(eglCreateSync(eglDisplay, EGL_SYNC_FENCE_KHR, NULL)) + , m_sync(eglCreateSync(eglDisplay, EGL_SYNC_FENCE_KHR, nullptr)) { Q_ASSERT(m_sync); glFinish(); @@ -80,7 +81,7 @@ private: class WindowStream : public PipeWireStream { public: - WindowStream(KWin::Toplevel *toplevel, QObject *parent) + WindowStream(Toplevel *toplevel, QObject *parent) : PipeWireStream(toplevel->hasAlpha(), toplevel->clientSize() * toplevel->bufferScale(), parent) , m_toplevel(toplevel) { @@ -93,14 +94,14 @@ public: private: void startFeeding() { - auto scene = KWin::Compositor::self()->scene(); + auto scene = Compositor::self()->scene(); connect(scene, &Scene::frameRendered, this, &WindowStream::bufferToStream); connect(m_toplevel, &Toplevel::damaged, this, &WindowStream::includeDamage); m_toplevel->damaged(m_toplevel, m_toplevel->frameGeometry()); } - void includeDamage(KWin::Toplevel *toplevel, const QRect &damage) { + void includeDamage(Toplevel *toplevel, const QRect &damage) { Q_ASSERT(m_toplevel == toplevel); m_damagedRegion |= damage; } @@ -122,12 +123,12 @@ private: } QRegion m_damagedRegion; - KWin::Toplevel *m_toplevel; + Toplevel *m_toplevel; }; void ScreencastManager::streamWindow(KWaylandServer::ScreencastStreamInterface *waylandStream, const QString &winid) { - auto *toplevel = KWin::Workspace::self()->findToplevel(winid); + auto *toplevel = Workspace::self()->findToplevel(winid); if (!toplevel) { waylandStream->sendFailed(i18n("Could not find window id %1", winid)); @@ -166,7 +167,7 @@ void ScreencastManager::streamOutput(KWaylandServer::ScreencastStreamInterface * stream->setCursorMode(mode, streamOutput->scale(), streamOutput->geometry()); connect(streamOutput, &QObject::destroyed, stream, &PipeWireStream::stopStreaming); auto bufferToStream = [streamOutput, stream] (const QRegion &damagedRegion) { - auto scene = KWin::Compositor::self()->scene(); + auto scene = Compositor::self()->scene(); auto texture = scene->textureForOutput(streamOutput); const QRect frame({}, streamOutput->modeSize()); @@ -174,7 +175,7 @@ void ScreencastManager::streamOutput(KWaylandServer::ScreencastStreamInterface * stream->recordFrame(texture.data(), region); }; connect(stream, &PipeWireStream::startStreaming, waylandStream, [streamOutput, stream, bufferToStream] { - KWin::Compositor::self()->addRepaint(streamOutput->geometry()); + Compositor::self()->addRepaint(streamOutput->geometry()); connect(streamOutput, &AbstractWaylandOutput::outputChange, stream, bufferToStream); }); integrateStreams(waylandStream, stream); @@ -195,3 +196,5 @@ void ScreencastManager::integrateStreams(KWaylandServer::ScreencastStreamInterfa delete stream; } } + +} // namespace KWin diff --git a/screencast/screencastmanager.h b/screencast/screencastmanager.h index d4de04f545..5e2b2933a9 100644 --- a/screencast/screencastmanager.h +++ b/screencast/screencastmanager.h @@ -23,6 +23,9 @@ #include +namespace KWin +{ + class PipeWireStream; class ScreencastManager : public QObject @@ -43,3 +46,4 @@ private: KWaylandServer::ScreencastInterface *m_screencast; }; +} // namespace KWin