screencast: Address minor issues
parent
76b9fb15ea
commit
2103b999e7
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -49,8 +49,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "decorations/decoratedclient.h"
|
||||
#include <logging.h>
|
||||
|
||||
#include "abstract_wayland_output.h"
|
||||
#include "abstract_egl_backend.h"
|
||||
#include <KWaylandServer/buffer_interface.h>
|
||||
#include <KWaylandServer/subcompositor_interface.h>
|
||||
#include <KWaylandServer/surface_interface.h>
|
||||
|
|
|
@ -21,10 +21,15 @@
|
|||
*/
|
||||
|
||||
#include "pipewirecore.h"
|
||||
#include "kwinscreencast_logging.h"
|
||||
|
||||
#include <KLocalizedString>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QSocketNotifier>
|
||||
#include <KLocalizedString>
|
||||
#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<PipeWireCore*>(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
|
||||
|
|
|
@ -22,10 +22,14 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
#include <spa/utils/hook.h>
|
||||
#include <QObject>
|
||||
|
||||
#include <pipewire/pipewire.h>
|
||||
#include <spa/utils/hook.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class PipeWireCore : public QObject
|
||||
{
|
||||
|
@ -52,3 +56,5 @@ public:
|
|||
Q_SIGNALS:
|
||||
void pipewireFailed(const QString &message);
|
||||
};
|
||||
|
||||
} // namespace KWin
|
||||
|
|
|
@ -21,36 +21,39 @@
|
|||
*/
|
||||
|
||||
#include "pipewirestream.h"
|
||||
#include "cursor.h"
|
||||
#include "dmabuftexture.h"
|
||||
#include "kwineglimagetexture.h"
|
||||
#include "kwinscreencast_logging.h"
|
||||
#include "main.h"
|
||||
#include "pipewirecore.h"
|
||||
#include "platform.h"
|
||||
#include "platformsupport/scenes/opengl/drm_fourcc.h"
|
||||
#include "scenes/opengl/egl_dmabuf.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <gbm.h>
|
||||
#include <spa/buffer/meta.h>
|
||||
#include <KLocalizedString>
|
||||
|
||||
#include <QLoggingCategory>
|
||||
#include <QPainter>
|
||||
#include "utils.h"
|
||||
#include "cursor.h"
|
||||
#include "main.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 <KLocalizedString>
|
||||
#include <spa/buffer/meta.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
void PipeWireStream::onStreamStateChanged(void *data, pw_stream_state old, pw_stream_state state, const char *error_message)
|
||||
{
|
||||
PipeWireStream *pw = static_cast<PipeWireStream*>(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<PipeWireStream *>(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<KWin::DmaBufTexture> dmabuf (KWin::kwinApp()->platform()->createDmaBufTexture(stream->m_resolution));
|
||||
QSharedPointer<DmaBufTexture> 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
|
||||
|
|
|
@ -22,27 +22,27 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QSize>
|
||||
#include <QHash>
|
||||
#include <QSharedPointer>
|
||||
#include "config-kwin.h"
|
||||
#include "kwinglobals.h"
|
||||
|
||||
#include <KWaylandServer/screencast_interface.h>
|
||||
|
||||
#include "kwinglobals.h"
|
||||
#include "config-kwin.h"
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
#include <QSharedPointer>
|
||||
#include <QSize>
|
||||
|
||||
#include <pipewire/pipewire.h>
|
||||
#include <spa/param/format-utils.h>
|
||||
#include <spa/param/video/format-utils.h>
|
||||
#include <spa/param/props.h>
|
||||
|
||||
#undef Status
|
||||
#include <spa/param/video/format-utils.h>
|
||||
|
||||
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<PipeWireCore> 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<KWin::GLTexture> texture;
|
||||
QScopedPointer<KWin::GLTexture> lastFrameTexture;
|
||||
QScopedPointer<GLTexture> texture;
|
||||
QScopedPointer<GLTexture> lastFrameTexture;
|
||||
} m_cursor;
|
||||
bool m_repainting = false;
|
||||
QRect cursorGeometry(KWin::Cursor *cursor) const;
|
||||
QRect cursorGeometry(Cursor *cursor) const;
|
||||
|
||||
QHash<struct pw_buffer *, QSharedPointer<KWin::DmaBufTexture>> m_dmabufDataForPwBuffer;
|
||||
QHash<struct pw_buffer *, QSharedPointer<DmaBufTexture>> m_dmabufDataForPwBuffer;
|
||||
};
|
||||
|
||||
} // namespace KWin
|
||||
|
|
|
@ -36,7 +36,8 @@
|
|||
#include <KWaylandServer/display.h>
|
||||
#include <KWaylandServer/output_interface.h>
|
||||
|
||||
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
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
|
||||
#include <KWaylandServer/screencast_interface.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class PipeWireStream;
|
||||
|
||||
class ScreencastManager : public QObject
|
||||
|
@ -43,3 +46,4 @@ private:
|
|||
KWaylandServer::ScreencastInterface *m_screencast;
|
||||
};
|
||||
|
||||
} // namespace KWin
|
||||
|
|
Loading…
Reference in New Issue