File indexing completed on 2024-11-10 04:57:07
0001 /* 0002 SPDX-FileCopyrightText: 2018-2020 Red Hat Inc 0003 SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez <aleixpol@kde.org> 0004 SPDX-FileContributor: Jan Grulich <jgrulich@redhat.com> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #pragma once 0010 0011 #include "config-kwin.h" 0012 0013 #include "wayland/screencast_v1.h" 0014 0015 #include <QDateTime> 0016 #include <QHash> 0017 #include <QObject> 0018 #include <QRegion> 0019 #include <QSocketNotifier> 0020 #include <QTimer> 0021 #include <chrono> 0022 #include <memory> 0023 #include <optional> 0024 0025 #include <pipewire/pipewire.h> 0026 #include <spa/param/format-utils.h> 0027 #include <spa/param/props.h> 0028 #include <spa/param/video/format-utils.h> 0029 0030 namespace KWin 0031 { 0032 0033 class Cursor; 0034 class ScreenCastDmaBufTexture; 0035 class EGLNativeFence; 0036 class GLTexture; 0037 class PipeWireCore; 0038 class ScreenCastSource; 0039 0040 struct ScreenCastDmaBufTextureParams 0041 { 0042 int planeCount = 0; 0043 int width = 0; 0044 int height = 0; 0045 uint32_t format = 0; 0046 uint64_t modifier = 0; 0047 }; 0048 0049 class KWIN_EXPORT ScreenCastStream : public QObject 0050 { 0051 Q_OBJECT 0052 public: 0053 explicit ScreenCastStream(ScreenCastSource *source, std::shared_ptr<PipeWireCore> pwCore, QObject *parent); 0054 ~ScreenCastStream(); 0055 0056 bool init(); 0057 uint framerate(); 0058 uint nodeId(); 0059 QString error() const 0060 { 0061 return m_error; 0062 } 0063 0064 void stop(); 0065 0066 /** 0067 * Renders @p frame into the current framebuffer into the stream 0068 * @p timestamp 0069 */ 0070 void recordFrame(const QRegion &damagedRegion); 0071 0072 void setCursorMode(ScreencastV1Interface::CursorMode mode, qreal scale, const QRectF &viewport); 0073 0074 public Q_SLOTS: 0075 void invalidateCursor(); 0076 void recordCursor(); 0077 bool includesCursor(Cursor *cursor) const; 0078 0079 Q_SIGNALS: 0080 void streamReady(quint32 nodeId); 0081 void startStreaming(); 0082 void stopStreaming(); 0083 0084 private: 0085 void onStreamParamChanged(uint32_t id, const struct spa_pod *format); 0086 void onStreamStateChanged(pw_stream_state old, pw_stream_state state, const char *error_message); 0087 void onStreamAddBuffer(pw_buffer *buffer); 0088 void onStreamRemoveBuffer(pw_buffer *buffer); 0089 void onStreamRenegotiateFormat(uint64_t); 0090 0091 bool createStream(); 0092 QList<const spa_pod *> buildFormats(bool fixate, char buffer[2048]); 0093 void updateParams(); 0094 void coreFailed(const QString &errorMessage); 0095 void sendCursorData(Cursor *cursor, spa_meta_cursor *spa_cursor); 0096 void addHeader(spa_buffer *spaBuffer); 0097 void addDamage(spa_buffer *spaBuffer, const QRegion &damagedRegion); 0098 void newStreamParams(); 0099 void tryEnqueue(pw_buffer *buffer); 0100 void enqueue(); 0101 spa_pod *buildFormat(struct spa_pod_builder *b, enum spa_video_format format, struct spa_rectangle *resolution, 0102 struct spa_fraction *defaultFramerate, struct spa_fraction *minFramerate, struct spa_fraction *maxFramerate, 0103 const QList<uint64_t> &modifiers, quint32 modifiersFlags); 0104 0105 std::optional<ScreenCastDmaBufTextureParams> testCreateDmaBuf(const QSize &size, quint32 format, const QList<uint64_t> &modifiers); 0106 std::shared_ptr<ScreenCastDmaBufTexture> createDmaBufTexture(const ScreenCastDmaBufTextureParams ¶ms); 0107 0108 std::shared_ptr<PipeWireCore> m_pwCore; 0109 std::unique_ptr<ScreenCastSource> m_source; 0110 struct pw_stream *m_pwStream = nullptr; 0111 struct spa_source *m_pwRenegotiate = nullptr; 0112 spa_hook m_streamListener; 0113 pw_stream_events m_pwStreamEvents = {}; 0114 0115 uint32_t m_pwNodeId = 0; 0116 0117 QSize m_resolution; 0118 bool m_stopped = false; 0119 bool m_streaming = false; 0120 0121 spa_video_info_raw m_videoFormat; 0122 QString m_error; 0123 QList<uint64_t> m_modifiers; 0124 std::optional<ScreenCastDmaBufTextureParams> m_dmabufParams; // when fixated 0125 0126 struct 0127 { 0128 ScreencastV1Interface::CursorMode mode = ScreencastV1Interface::Hidden; 0129 const QSize bitmapSize = QSize(256, 256); 0130 qreal scale = 1; 0131 QRectF viewport; 0132 QRectF lastRect; 0133 std::unique_ptr<GLTexture> texture; 0134 bool visible = false; 0135 bool invalid = true; 0136 } m_cursor; 0137 0138 QHash<struct pw_buffer *, std::shared_ptr<ScreenCastDmaBufTexture>> m_dmabufDataForPwBuffer; 0139 0140 pw_buffer *m_pendingBuffer = nullptr; 0141 std::unique_ptr<QSocketNotifier> m_pendingNotifier; 0142 std::unique_ptr<EGLNativeFence> m_pendingFence; 0143 quint64 m_sequential = 0; 0144 bool m_hasDmaBuf = false; 0145 bool m_waitForNewBuffers = false; 0146 quint32 m_drmFormat = 0; 0147 0148 QDateTime m_lastSent; 0149 QRegion m_pendingDamages; 0150 QTimer m_pendingFrame; 0151 }; 0152 0153 } // namespace KWin