diff --git a/src/plugins/screencast/CMakeLists.txt b/src/plugins/screencast/CMakeLists.txt index 8434ff5546..9e78f23894 100644 --- a/src/plugins/screencast/CMakeLists.txt +++ b/src/plugins/screencast/CMakeLists.txt @@ -4,7 +4,7 @@ target_sources(screencast PRIVATE outputscreencastsource.cpp pipewirecore.cpp regionscreencastsource.cpp - screencastdmabuftexture.cpp + screencastbuffer.cpp screencastmanager.cpp screencastsource.cpp screencaststream.cpp diff --git a/src/plugins/screencast/outputscreencastsource.cpp b/src/plugins/screencast/outputscreencastsource.cpp index 853b22a957..c37f918f00 100644 --- a/src/plugins/screencast/outputscreencastsource.cpp +++ b/src/plugins/screencast/outputscreencastsource.cpp @@ -51,11 +51,11 @@ QSize OutputScreenCastSource::textureSize() const return m_output->pixelSize(); } -void OutputScreenCastSource::render(spa_data *spa, spa_video_format format) +void OutputScreenCastSource::render(QImage *target) { const auto [outputTexture, colorDescription] = Compositor::self()->scene()->textureForOutput(m_output); if (outputTexture) { - grabTexture(outputTexture.get(), spa, format); + grabTexture(outputTexture.get(), target); } } diff --git a/src/plugins/screencast/outputscreencastsource.h b/src/plugins/screencast/outputscreencastsource.h index a2b027e08e..6b795e0f60 100644 --- a/src/plugins/screencast/outputscreencastsource.h +++ b/src/plugins/screencast/outputscreencastsource.h @@ -29,7 +29,7 @@ public: quint32 drmFormat() const override; void render(GLFramebuffer *target) override; - void render(spa_data *spa, spa_video_format format) override; + void render(QImage *target) override; std::chrono::nanoseconds clock() const override; void resume() override; diff --git a/src/plugins/screencast/regionscreencastsource.cpp b/src/plugins/screencast/regionscreencastsource.cpp index d0afb6445e..1d4aa7226e 100644 --- a/src/plugins/screencast/regionscreencastsource.cpp +++ b/src/plugins/screencast/regionscreencastsource.cpp @@ -152,10 +152,10 @@ void RegionScreenCastSource::render(GLFramebuffer *target) GLFramebuffer::popFramebuffer(); } -void RegionScreenCastSource::render(spa_data *spa, spa_video_format format) +void RegionScreenCastSource::render(QImage *target) { ensureTexture(); - grabTexture(m_renderedTexture.get(), spa, format); + grabTexture(m_renderedTexture.get(), target); } uint RegionScreenCastSource::refreshRate() const diff --git a/src/plugins/screencast/regionscreencastsource.h b/src/plugins/screencast/regionscreencastsource.h index 7c31add177..5a1809aeb3 100644 --- a/src/plugins/screencast/regionscreencastsource.h +++ b/src/plugins/screencast/regionscreencastsource.h @@ -10,7 +10,6 @@ #include "opengl/gltexture.h" #include "opengl/glutils.h" -#include namespace KWin { @@ -44,7 +43,7 @@ public: uint refreshRate() const override; void render(GLFramebuffer *target) override; - void render(spa_data *spa, spa_video_format format) override; + void render(QImage *target) override; std::chrono::nanoseconds clock() const override; void update(Output *output, const QRegion &damage); diff --git a/src/plugins/screencast/screencastbuffer.cpp b/src/plugins/screencast/screencastbuffer.cpp new file mode 100644 index 0000000000..de87f18e38 --- /dev/null +++ b/src/plugins/screencast/screencastbuffer.cpp @@ -0,0 +1,121 @@ +/* + SPDX-FileCopyrightText: 2021 Vlad Zahorodnii + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#include "screencastbuffer.h" +#include "compositor.h" +#include "core/drmdevice.h" +#include "core/shmgraphicsbufferallocator.h" +#include "opengl/glframebuffer.h" +#include "platformsupport/scenes/opengl/abstract_egl_backend.h" + +namespace KWin +{ + +ScreenCastBuffer::ScreenCastBuffer(GraphicsBuffer *buffer) + : m_buffer(buffer) +{ +} + +ScreenCastBuffer::~ScreenCastBuffer() +{ + m_buffer->drop(); +} + +DmaBufScreenCastBuffer::DmaBufScreenCastBuffer(GraphicsBuffer *buffer, std::shared_ptr &&texture, std::unique_ptr &&framebuffer) + : ScreenCastBuffer(buffer) + , texture(std::move(texture)) + , framebuffer(std::move(framebuffer)) +{ +} + +DmaBufScreenCastBuffer *DmaBufScreenCastBuffer::create(pw_buffer *pwBuffer, const GraphicsBufferOptions &options) +{ + AbstractEglBackend *backend = dynamic_cast(Compositor::self()->backend()); + if (!backend || !backend->drmDevice()) { + return nullptr; + } + + GraphicsBuffer *buffer = backend->drmDevice()->allocator()->allocate(options); + if (!buffer) { + return nullptr; + } + + const DmaBufAttributes *attrs = buffer->dmabufAttributes(); + if (!attrs) { + buffer->drop(); + return nullptr; + } + + backend->makeCurrent(); + + auto texture = backend->importDmaBufAsTexture(*attrs); + if (!texture) { + buffer->drop(); + return nullptr; + } + + auto framebuffer = std::make_unique(texture.get()); + if (!framebuffer->valid()) { + buffer->drop(); + return nullptr; + } + + struct spa_data *spaData = pwBuffer->buffer->datas; + + Q_ASSERT(pwBuffer->buffer->n_datas >= uint(attrs->planeCount)); + for (int i = 0; i < attrs->planeCount; ++i) { + spaData[i].type = SPA_DATA_DmaBuf; + spaData[i].flags = SPA_DATA_FLAG_READWRITE; + spaData[i].mapoffset = 0; + spaData[i].maxsize = i == 0 ? attrs->pitch[i] * attrs->height : 0; // TODO: dmabufs don't have a well defined size, it should be zero but some clients check the size to see if the buffer is valid + spaData[i].fd = attrs->fd[i].get(); + spaData[i].data = nullptr; + spaData[i].chunk->offset = attrs->offset[i]; + spaData[i].chunk->size = spaData[i].maxsize; + spaData[i].chunk->stride = attrs->pitch[i]; + spaData[i].chunk->flags = SPA_CHUNK_FLAG_NONE; + }; + + return new DmaBufScreenCastBuffer(buffer, std::move(texture), std::move(framebuffer)); +} + +MemFdScreenCastBuffer::MemFdScreenCastBuffer(GraphicsBuffer *buffer, GraphicsBufferView &&view) + : ScreenCastBuffer(buffer) + , view(std::move(view)) +{ +} + +MemFdScreenCastBuffer *MemFdScreenCastBuffer::create(pw_buffer *pwBuffer, const GraphicsBufferOptions &options) +{ + GraphicsBuffer *buffer = ShmGraphicsBufferAllocator().allocate(options); + if (!buffer) { + return nullptr; + } + + GraphicsBufferView view(buffer, GraphicsBuffer::Read | GraphicsBuffer::Write); + if (view.isNull()) { + buffer->drop(); + return nullptr; + } + + const ShmAttributes *attributes = buffer->shmAttributes(); + + struct spa_data *spaData = pwBuffer->buffer->datas; + spaData->type = SPA_DATA_MemFd; + spaData->flags = SPA_DATA_FLAG_READWRITE; + spaData->mapoffset = 0; + spaData->maxsize = attributes->stride * attributes->size.height(); + spaData->fd = attributes->fd.get(); + spaData->data = view.image()->bits(); + spaData->chunk->offset = 0; + spaData->chunk->size = spaData->maxsize; + spaData->chunk->stride = attributes->stride; + spaData->chunk->flags = SPA_CHUNK_FLAG_NONE; + + return new MemFdScreenCastBuffer(buffer, std::move(view)); +} + +} // namespace KWin diff --git a/src/plugins/screencast/screencastbuffer.h b/src/plugins/screencast/screencastbuffer.h new file mode 100644 index 0000000000..a67dd5d91b --- /dev/null +++ b/src/plugins/screencast/screencastbuffer.h @@ -0,0 +1,54 @@ +/* + SPDX-FileCopyrightText: 2021 Vlad Zahorodnii + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#pragma once + +#include "core/graphicsbufferview.h" + +#include + +namespace KWin +{ + +class GLFramebuffer; +class GLTexture; +class GraphicsBuffer; +struct GraphicsBufferOptions; + +class ScreenCastBuffer +{ +public: + explicit ScreenCastBuffer(GraphicsBuffer *buffer); + virtual ~ScreenCastBuffer(); + +private: + GraphicsBuffer *m_buffer; +}; + +class DmaBufScreenCastBuffer : public ScreenCastBuffer +{ +public: + static DmaBufScreenCastBuffer *create(pw_buffer *pwBuffer, const GraphicsBufferOptions &options); + + std::shared_ptr texture; + std::unique_ptr framebuffer; + +private: + DmaBufScreenCastBuffer(GraphicsBuffer *buffer, std::shared_ptr &&texture, std::unique_ptr &&framebuffer); +}; + +class MemFdScreenCastBuffer : public ScreenCastBuffer +{ +public: + static MemFdScreenCastBuffer *create(pw_buffer *pwBuffer, const GraphicsBufferOptions &options); + + GraphicsBufferView view; + +private: + MemFdScreenCastBuffer(GraphicsBuffer *buffer, GraphicsBufferView &&view); +}; + +} // namespace KWin diff --git a/src/plugins/screencast/screencastdmabuftexture.cpp b/src/plugins/screencast/screencastdmabuftexture.cpp deleted file mode 100644 index ed5d9a4911..0000000000 --- a/src/plugins/screencast/screencastdmabuftexture.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez - - SPDX-License-Identifier: LGPL-2.0-or-later -*/ - -#include "plugins/screencast/screencastdmabuftexture.h" -#include "core/graphicsbuffer.h" -#include "opengl/glutils.h" - -namespace KWin -{ - -ScreenCastDmaBufTexture::ScreenCastDmaBufTexture(std::shared_ptr texture, std::unique_ptr &&framebuffer, GraphicsBuffer *buffer) - : m_texture(std::move(texture)) - , m_framebuffer(std::move(framebuffer)) - , m_buffer(buffer) -{ -} -ScreenCastDmaBufTexture::~ScreenCastDmaBufTexture() -{ - m_framebuffer.reset(); - m_texture.reset(); - m_buffer->drop(); -} - -GraphicsBuffer *ScreenCastDmaBufTexture::buffer() const -{ - return m_buffer; -} - -KWin::GLTexture *ScreenCastDmaBufTexture::texture() const -{ - return m_texture.get(); -} - -KWin::GLFramebuffer *ScreenCastDmaBufTexture::framebuffer() const -{ - return m_framebuffer.get(); -} - -} // namespace KWin diff --git a/src/plugins/screencast/screencastdmabuftexture.h b/src/plugins/screencast/screencastdmabuftexture.h deleted file mode 100644 index 3bb4d881ed..0000000000 --- a/src/plugins/screencast/screencastdmabuftexture.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez - - SPDX-License-Identifier: LGPL-2.0-or-later -*/ - -#pragma once - -#include - -namespace KWin -{ -class GLFramebuffer; -class GLTexture; -class GraphicsBuffer; - -class ScreenCastDmaBufTexture -{ -public: - explicit ScreenCastDmaBufTexture(std::shared_ptr texture, std::unique_ptr &&framebuffer, GraphicsBuffer *buffer); - virtual ~ScreenCastDmaBufTexture(); - - GraphicsBuffer *buffer() const; - GLTexture *texture() const; - GLFramebuffer *framebuffer() const; - -protected: - std::shared_ptr m_texture; - std::unique_ptr m_framebuffer; - GraphicsBuffer *m_buffer; -}; - -} diff --git a/src/plugins/screencast/screencastsource.h b/src/plugins/screencast/screencastsource.h index 241bc6e429..bb92497a9e 100644 --- a/src/plugins/screencast/screencastsource.h +++ b/src/plugins/screencast/screencastsource.h @@ -7,8 +7,8 @@ #pragma once #include -#include -#include + +class QImage; namespace KWin { @@ -29,7 +29,7 @@ public: virtual QSize textureSize() const = 0; virtual void render(GLFramebuffer *target) = 0; - virtual void render(spa_data *spa, spa_video_format format) = 0; + virtual void render(QImage *target) = 0; virtual std::chrono::nanoseconds clock() const = 0; virtual void resume() = 0; diff --git a/src/plugins/screencast/screencaststream.cpp b/src/plugins/screencast/screencaststream.cpp index 90d38c727f..c926ab5cd7 100644 --- a/src/plugins/screencast/screencaststream.cpp +++ b/src/plugins/screencast/screencaststream.cpp @@ -22,7 +22,7 @@ #include "platformsupport/scenes/opengl/abstract_egl_backend.h" #include "platformsupport/scenes/opengl/openglbackend.h" #include "scene/workspacescene.h" -#include "screencastdmabuftexture.h" +#include "screencastbuffer.h" #include "screencastsource.h" #include "utils/drm_format_helper.h" @@ -31,13 +31,8 @@ #include #include -#include - -#include -#include -#include - #include +#include namespace KWin { @@ -219,96 +214,44 @@ void ScreenCastStream::onStreamParamChanged(uint32_t id, const struct spa_pod *f m_streaming = true; } -void ScreenCastStream::onStreamAddBuffer(pw_buffer *buffer) +void ScreenCastStream::onStreamAddBuffer(pw_buffer *pwBuffer) { if (m_closed) { return; } - std::shared_ptr dmabuff; + m_waitForNewBuffers = false; - struct spa_data *spa_data = buffer->buffer->datas; + struct spa_data *spa_data = pwBuffer->buffer->datas; if (spa_data[0].type != SPA_ID_INVALID && spa_data[0].type & (1 << SPA_DATA_DmaBuf)) { Q_ASSERT(m_dmabufParams); - dmabuff = createDmaBufTexture(*m_dmabufParams); + if (auto dmabuf = DmaBufScreenCastBuffer::create(pwBuffer, GraphicsBufferOptions{ + .size = QSize(m_dmabufParams->width, m_dmabufParams->height), + .format = m_dmabufParams->format, + .modifiers = {m_dmabufParams->modifier}, + })) { + pwBuffer->user_data = dmabuf; + return; + } } - if (dmabuff) { - const DmaBufAttributes *dmabufAttribs = dmabuff->buffer()->dmabufAttributes(); - Q_ASSERT(buffer->buffer->n_datas >= uint(dmabufAttribs->planeCount)); - for (int i = 0; i < dmabufAttribs->planeCount; ++i) { - spa_data[i].type = SPA_DATA_DmaBuf; - spa_data[i].flags = SPA_DATA_FLAG_READWRITE; - spa_data[i].mapoffset = 0; - spa_data[i].maxsize = i == 0 ? dmabufAttribs->pitch[i] * dmabufAttribs->height : 0; // TODO: dmabufs don't have a well defined size, it should be zero but some clients check the size to see if the buffer is valid - spa_data[i].fd = dmabufAttribs->fd[i].get(); - spa_data[i].data = nullptr; - spa_data[i].chunk->offset = dmabufAttribs->offset[i]; - spa_data[i].chunk->size = spa_data[i].maxsize; - spa_data[i].chunk->stride = dmabufAttribs->pitch[i]; - spa_data[i].chunk->flags = SPA_CHUNK_FLAG_NONE; - } - m_dmabufDataForPwBuffer.insert(buffer, dmabuff); -#ifdef F_SEAL_SEAL // Disable memfd on systems that don't have it, like BSD < 12 - } else { - if (!(spa_data->type & (1 << SPA_DATA_MemFd))) { - qCCritical(KWIN_SCREENCAST) << objectName() << "memfd: Client doesn't support memfd buffer data type"; + if (spa_data->type & (1 << SPA_DATA_MemFd)) { + if (auto memfd = MemFdScreenCastBuffer::create(pwBuffer, GraphicsBufferOptions{ + .size = m_resolution, + .format = m_drmFormat, + .software = true, + })) { + pwBuffer->user_data = memfd; return; } - - const int bytesPerPixel = m_source->hasAlphaChannel() ? 4 : 3; - const int stride = SPA_ROUND_UP_N(m_resolution.width() * bytesPerPixel, 4); - spa_data->type = SPA_DATA_MemFd; - spa_data->flags = SPA_DATA_FLAG_READWRITE; - spa_data->mapoffset = 0; - spa_data->maxsize = stride * m_resolution.height(); - spa_data->fd = memfd_create("kwin-screencast-memfd", MFD_CLOEXEC | MFD_ALLOW_SEALING); - if (spa_data->fd == -1) { - qCCritical(KWIN_SCREENCAST) << objectName() << "memfd: Can't create memfd"; - return; - } - - if (ftruncate(spa_data->fd, spa_data->maxsize) < 0) { - qCCritical(KWIN_SCREENCAST) << objectName() << "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_SCREENCAST) << objectName() << "memfd: Failed to add seals"; - } - - 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_SCREENCAST) << objectName() << "memfd: Failed to mmap memory"; - } else { - qCDebug(KWIN_SCREENCAST) << objectName() << "memfd: created successfully" << spa_data->data << spa_data->maxsize; - } - - spa_data->chunk->offset = 0; - spa_data->chunk->size = spa_data->maxsize; - spa_data->chunk->stride = stride; - spa_data->chunk->flags = SPA_CHUNK_FLAG_NONE; -#endif } - - m_waitForNewBuffers = false; } -void ScreenCastStream::onStreamRemoveBuffer(pw_buffer *buffer) +void ScreenCastStream::onStreamRemoveBuffer(pw_buffer *pwBuffer) { - m_dmabufDataForPwBuffer.remove(buffer); - - struct spa_buffer *spa_buffer = buffer->buffer; - struct spa_data *spa_data = spa_buffer->datas; - if (spa_data && spa_data->type == SPA_DATA_MemFd) { - ::munmap(spa_data->data, spa_data->maxsize); - ::close(spa_data->fd); + if (ScreenCastBuffer *buffer = static_cast(pwBuffer->user_data)) { + delete buffer; + pwBuffer->user_data = nullptr; } } @@ -534,58 +477,38 @@ void ScreenCastStream::recordFrame(const QRegion &_damagedRegion) return; } - struct pw_buffer *buffer = pw_stream_dequeue_buffer(m_pwStream); - if (!buffer) { + struct pw_buffer *pwBuffer = pw_stream_dequeue_buffer(m_pwStream); + if (!pwBuffer) { return; } - struct spa_buffer *spa_buffer = buffer->buffer; + struct spa_buffer *spa_buffer = pwBuffer->buffer; struct spa_data *spa_data = spa_buffer->datas; + ScreenCastBuffer *buffer = static_cast(pwBuffer->user_data); + if (!buffer) { + qCWarning(KWIN_SCREENCAST) << objectName() << "Failed to record frame: invalid buffer type"; + corruptHeader(spa_buffer); + pw_stream_queue_buffer(m_pwStream, pwBuffer); + return; + } + EglContext *context = static_cast(Compositor::self()->backend())->openglContext(); context->makeCurrent(); spa_data->chunk->flags = SPA_CHUNK_FLAG_NONE; - if (spa_data[0].type == SPA_DATA_MemFd) { - uint8_t *data = static_cast(spa_data->data); - if (!data) { - qCWarning(KWIN_SCREENCAST) << objectName() << "Failed to record frame: invalid buffer data"; - corruptHeader(spa_buffer); - pw_stream_queue_buffer(m_pwStream, buffer); - return; - } - - const bool hasAlpha = m_source->hasAlphaChannel(); - const int bpp = data && !hasAlpha ? 3 : 4; - const uint stride = SPA_ROUND_UP_N(size.width() * bpp, 4); - - if ((stride * size.height()) > spa_data->maxsize) { - qCDebug(KWIN_SCREENCAST) << objectName() << "Failed to record frame: frame is too big"; - corruptHeader(spa_buffer); - pw_stream_queue_buffer(m_pwStream, buffer); - return; - } - - m_source->render(spa_data, m_videoFormat.format); + if (auto memfd = dynamic_cast(buffer)) { + m_source->render(memfd->view.image()); auto cursor = Cursors::self()->currentCursor(); if (m_cursor.mode == ScreencastV1Interface::Embedded && includesCursor(cursor)) { - QImage dest(data, size.width(), size.height(), stride, hasAlpha ? QImage::Format_RGBA8888_Premultiplied : QImage::Format_RGB888); - QPainter painter(&dest); + QPainter painter(memfd->view.image()); const auto position = (cursor->pos() - m_cursor.viewport.topLeft() - cursor->hotspot()) * m_cursor.scale; const PlatformCursorImage cursorImage = kwinApp()->cursorImage(); painter.drawImage(QRect{position.toPoint(), cursorImage.image().size()}, cursorImage.image()); } - } else if (spa_data[0].type == SPA_DATA_DmaBuf) { - auto dmabuf = m_dmabufDataForPwBuffer.constFind(buffer); - if (dmabuf == m_dmabufDataForPwBuffer.constEnd()) { - qCDebug(KWIN_SCREENCAST) << objectName() << "Failed to record frame: no dmabuf data"; - corruptHeader(spa_buffer); - pw_stream_queue_buffer(m_pwStream, buffer); - return; - } - - m_source->render((*dmabuf)->framebuffer()); + } else if (auto dmabuf = dynamic_cast(buffer)) { + m_source->render(dmabuf->framebuffer.get()); auto cursor = Cursors::self()->currentCursor(); if (m_cursor.mode == ScreencastV1Interface::Embedded && includesCursor(cursor)) { @@ -599,7 +522,7 @@ void ScreenCastStream::recordFrame(const QRegion &_damagedRegion) } } if (m_cursor.texture) { - GLFramebuffer::pushFramebuffer((*dmabuf)->framebuffer()); + GLFramebuffer::pushFramebuffer(dmabuf->framebuffer.get()); auto shader = ShaderManager::instance()->pushShader(ShaderTrait::MapTexture); @@ -632,11 +555,6 @@ void ScreenCastStream::recordFrame(const QRegion &_damagedRegion) } else { glFlush(); } - } else { - qCWarning(KWIN_SCREENCAST, "%s Failed to record frame: invalid buffer type: %d", objectName().toUtf8().constData(), spa_data[0].type); - corruptHeader(spa_buffer); - pw_stream_queue_buffer(m_pwStream, buffer); - return; } if (m_cursor.mode == ScreencastV1Interface::Metadata) { @@ -646,7 +564,7 @@ void ScreenCastStream::recordFrame(const QRegion &_damagedRegion) addDamage(spa_buffer, damagedRegion); addHeader(spa_buffer); - enqueue(buffer); + enqueue(pwBuffer); } void ScreenCastStream::addHeader(spa_buffer *spaBuffer) @@ -918,45 +836,6 @@ std::optional ScreenCastStream::testCreateDmaBuf( }; } -std::shared_ptr ScreenCastStream::createDmaBufTexture(const ScreenCastDmaBufTextureParams ¶ms) -{ - AbstractEglBackend *backend = dynamic_cast(Compositor::self()->backend()); - if (!backend) { - return nullptr; - } - - GraphicsBuffer *buffer = backend->drmDevice()->allocator()->allocate(GraphicsBufferOptions{ - .size = QSize(params.width, params.height), - .format = params.format, - .modifiers = {params.modifier}, - }); - if (!buffer) { - return nullptr; - } - - const DmaBufAttributes *attrs = buffer->dmabufAttributes(); - if (!attrs) { - buffer->drop(); - return nullptr; - } - - backend->makeCurrent(); - - std::shared_ptr texture = backend->importDmaBufAsTexture(*attrs); - if (!texture) { - buffer->drop(); - return nullptr; - } - - std::unique_ptr framebuffer = std::make_unique(texture.get()); - if (!framebuffer->valid()) { - buffer->drop(); - return nullptr; - } - - return std::make_shared(std::move(texture), std::move(framebuffer), buffer); -} - } // namespace KWin #include "moc_screencaststream.cpp" diff --git a/src/plugins/screencast/screencaststream.h b/src/plugins/screencast/screencaststream.h index 33073c9119..fd4d7c764c 100644 --- a/src/plugins/screencast/screencaststream.h +++ b/src/plugins/screencast/screencaststream.h @@ -8,8 +8,6 @@ #pragma once -#include "config-kwin.h" - #include "wayland/screencast_v1.h" #include @@ -30,7 +28,6 @@ namespace KWin { class Cursor; -class ScreenCastDmaBufTexture; class GLTexture; class PipeWireCore; class ScreenCastSource; @@ -100,7 +97,6 @@ private: const QList &modifiers, quint32 modifiersFlags); std::optional testCreateDmaBuf(const QSize &size, quint32 format, const QList &modifiers); - std::shared_ptr createDmaBufTexture(const ScreenCastDmaBufTextureParams ¶ms); std::shared_ptr m_pwCore; std::unique_ptr m_source; @@ -134,8 +130,6 @@ private: QMetaObject::Connection positionChangedConnection = QMetaObject::Connection(); } m_cursor; - QHash> m_dmabufDataForPwBuffer; - quint64 m_sequential = 0; bool m_hasDmaBuf = false; bool m_waitForNewBuffers = false; diff --git a/src/plugins/screencast/screencastutils.h b/src/plugins/screencast/screencastutils.h index 57289aeba0..d7f5439e14 100644 --- a/src/plugins/screencast/screencastutils.h +++ b/src/plugins/screencast/screencastutils.h @@ -9,8 +9,6 @@ #include "opengl/glplatform.h" #include "opengl/gltexture.h" #include "opengl/glutils.h" -#include -#include namespace KWin { @@ -28,18 +26,12 @@ static void mirrorVertically(uchar *data, int height, int stride) } } -static GLenum closestGLType(spa_video_format format) +static GLenum closestGLType(QImage::Format format) { switch (format) { - case SPA_VIDEO_FORMAT_RGB: - return GL_RGB; - case SPA_VIDEO_FORMAT_BGR: - return GL_BGR; - case SPA_VIDEO_FORMAT_RGBx: - case SPA_VIDEO_FORMAT_RGBA: - return GL_RGBA; - case SPA_VIDEO_FORMAT_BGRA: - case SPA_VIDEO_FORMAT_BGRx: + case QImage::Format_ARGB32: + case QImage::Format_ARGB32_Premultiplied: + case QImage::Format_RGB32: return GL_BGRA; default: qDebug() << "unknown format" << format; @@ -47,7 +39,7 @@ static GLenum closestGLType(spa_video_format format) } } -static void doGrabTexture(GLTexture *texture, spa_data *spa, spa_video_format format) +static void doGrabTexture(GLTexture *texture, QImage *target) { const auto context = OpenGlContext::currentContext(); const QSize size = texture->size(); @@ -65,12 +57,12 @@ static void doGrabTexture(GLTexture *texture, spa_data *spa, spa_video_format fo if (context->isOpenGLES() || context->glPlatform()->driver() == Driver_NVidia) { GLFramebuffer fbo(texture); GLFramebuffer::pushFramebuffer(&fbo); - glReadPixels(0, 0, size.width(), size.height(), closestGLType(format), GL_UNSIGNED_BYTE, spa->data); + glReadPixels(0, 0, size.width(), size.height(), closestGLType(target->format()), GL_UNSIGNED_BYTE, target->bits()); GLFramebuffer::popFramebuffer(); } else if (context->openglVersion() >= Version(4, 5)) { - glGetTextureImage(texture->texture(), 0, closestGLType(format), GL_UNSIGNED_BYTE, spa->chunk->size, spa->data); + glGetTextureImage(texture->texture(), 0, closestGLType(target->format()), GL_UNSIGNED_BYTE, target->sizeInBytes(), target->bits()); } else { - glGetTexImage(texture->target(), 0, closestGLType(format), GL_UNSIGNED_BYTE, spa->data); + glGetTexImage(texture->target(), 0, closestGLType(target->format()), GL_UNSIGNED_BYTE, target->bits()); } if (invertNeededAndSupported) { @@ -78,15 +70,15 @@ static void doGrabTexture(GLTexture *texture, spa_data *spa, spa_video_format fo glPixelStorei(GL_PACK_INVERT_MESA, prev); } } else if (invertNeeded) { - mirrorVertically(static_cast(spa->data), size.height(), spa->chunk->stride); + mirrorVertically(static_cast(target->bits()), size.height(), target->bytesPerLine()); } } -static void grabTexture(GLTexture *texture, spa_data *spa, spa_video_format format) +static void grabTexture(GLTexture *texture, QImage *target) { const OutputTransform contentTransform = texture->contentTransform(); if (contentTransform == OutputTransform::Normal || contentTransform == OutputTransform::FlipY) { - doGrabTexture(texture, spa, format); + doGrabTexture(texture, target); } else { const QSize size = contentTransform.map(texture->size()); const auto backingTexture = GLTexture::allocate(GL_RGBA8, size); @@ -105,7 +97,7 @@ static void grabTexture(GLTexture *texture, spa_data *spa, spa_video_format form GLFramebuffer::pushFramebuffer(&fbo); texture->render(size); GLFramebuffer::popFramebuffer(); - doGrabTexture(backingTexture.get(), spa, format); + doGrabTexture(backingTexture.get(), target); } } diff --git a/src/plugins/screencast/windowscreencastsource.cpp b/src/plugins/screencast/windowscreencastsource.cpp index a779ccd6ed..034c9d308a 100644 --- a/src/plugins/screencast/windowscreencastsource.cpp +++ b/src/plugins/screencast/windowscreencastsource.cpp @@ -56,7 +56,7 @@ QSize WindowScreenCastSource::textureSize() const return m_window->clientGeometry().size().toSize(); } -void WindowScreenCastSource::render(spa_data *spa, spa_video_format format) +void WindowScreenCastSource::render(QImage *target) { const auto offscreenTexture = GLTexture::allocate(hasAlphaChannel() ? GL_RGBA8 : GL_RGB8, textureSize()); if (!offscreenTexture) { @@ -66,7 +66,7 @@ void WindowScreenCastSource::render(spa_data *spa, spa_video_format format) GLFramebuffer offscreenTarget(offscreenTexture.get()); render(&offscreenTarget); - grabTexture(offscreenTexture.get(), spa, format); + grabTexture(offscreenTexture.get(), target); } void WindowScreenCastSource::render(GLFramebuffer *target) diff --git a/src/plugins/screencast/windowscreencastsource.h b/src/plugins/screencast/windowscreencastsource.h index 8f93b825ec..e87c352412 100644 --- a/src/plugins/screencast/windowscreencastsource.h +++ b/src/plugins/screencast/windowscreencastsource.h @@ -29,7 +29,7 @@ public: uint refreshRate() const override; void render(GLFramebuffer *target) override; - void render(spa_data *spa, spa_video_format format) override; + void render(QImage *target) override; std::chrono::nanoseconds clock() const override; void resume() override;