plugins/screencast: Clean up cursor scale tracking

Poll the screen cast scale from the source rather have code on top of
ScreenCastStream and ScreenCastSource that figures out by itself how the
cursor should be scaled. It ensures that the cursor size will be
consistent and it makes the ScreenCastStream initialization code simpler.
This commit is contained in:
Vlad Zahorodnii 2024-07-04 21:45:47 +03:00
parent e4a272e166
commit 50717a2f9a
10 changed files with 32 additions and 18 deletions

View file

@ -47,6 +47,11 @@ QSize OutputScreenCastSource::textureSize() const
return m_output->pixelSize();
}
qreal OutputScreenCastSource::devicePixelRatio() const
{
return m_output->scale();
}
void OutputScreenCastSource::render(QImage *target)
{
const auto [outputTexture, colorDescription] = Compositor::self()->scene()->textureForOutput(m_output);

View file

@ -25,6 +25,7 @@ public:
uint refreshRate() const override;
QSize textureSize() const override;
qreal devicePixelRatio() const override;
quint32 drmFormat() const override;
void render(GLFramebuffer *target) override;

View file

@ -61,6 +61,11 @@ QSize RegionScreenCastSource::textureSize() const
return m_region.size() * m_scale;
}
qreal RegionScreenCastSource::devicePixelRatio() const
{
return m_scale;
}
quint32 RegionScreenCastSource::drmFormat() const
{
return DRM_FORMAT_ARGB8888;

View file

@ -39,6 +39,7 @@ public:
quint32 drmFormat() const override;
QSize textureSize() const override;
qreal devicePixelRatio() const override;
uint refreshRate() const override;
void render(GLFramebuffer *target) override;

View file

@ -48,7 +48,7 @@ void ScreencastManager::streamWindow(ScreencastStreamV1Interface *waylandStream,
auto stream = new ScreenCastStream(new WindowScreenCastSource(window), getPipewireConnection(), this);
stream->setObjectName(window->desktopFileName());
stream->setCursorMode(mode, 1);
stream->setCursorMode(mode);
integrateStreams(waylandStream, stream);
}
@ -84,11 +84,7 @@ void ScreencastManager::streamOutput(ScreencastStreamV1Interface *waylandStream,
auto stream = new ScreenCastStream(new OutputScreenCastSource(streamOutput), getPipewireConnection(), this);
stream->setObjectName(streamOutput->name());
stream->setCursorMode(mode, streamOutput->scale());
connect(streamOutput, &Output::changed, stream, [streamOutput, stream, mode]() {
stream->setCursorMode(mode, streamOutput->scale());
});
stream->setCursorMode(mode);
integrateStreams(waylandStream, stream);
}
@ -108,7 +104,7 @@ void ScreencastManager::streamRegion(ScreencastStreamV1Interface *waylandStream,
auto source = new RegionScreenCastSource(geometry, scale);
auto stream = new ScreenCastStream(source, getPipewireConnection(), this);
stream->setObjectName(rectToString(geometry));
stream->setCursorMode(mode, scale);
stream->setCursorMode(mode);
integrateStreams(waylandStream, stream);
}

View file

@ -27,6 +27,7 @@ public:
virtual uint refreshRate() const = 0;
virtual quint32 drmFormat() const = 0;
virtual QSize textureSize() const = 0;
virtual qreal devicePixelRatio() const = 0;
virtual void render(GLFramebuffer *target) = 0;
virtual void render(QImage *target) = 0;

View file

@ -720,13 +720,15 @@ void ScreenCastStream::addCursorMetadata(spa_buffer *spaBuffer, Cursor *cursor)
return;
}
m_cursor.visible = true;
const auto position = m_source->mapFromGlobal(cursor->pos()) * m_cursor.scale;
const qreal scale = m_source->devicePixelRatio();
const auto position = m_source->mapFromGlobal(cursor->pos()) * scale;
spaMetaCursor->id = 1;
spaMetaCursor->position.x = position.x();
spaMetaCursor->position.y = position.y();
spaMetaCursor->hotspot.x = cursor->hotspot().x() * m_cursor.scale;
spaMetaCursor->hotspot.y = cursor->hotspot().y() * m_cursor.scale;
spaMetaCursor->hotspot.x = cursor->hotspot().x() * scale;
spaMetaCursor->hotspot.y = cursor->hotspot().y() * scale;
spaMetaCursor->bitmap_offset = 0;
if (!m_cursor.invalid) {
@ -736,7 +738,7 @@ void ScreenCastStream::addCursorMetadata(spa_buffer *spaBuffer, Cursor *cursor)
m_cursor.invalid = false;
spaMetaCursor->bitmap_offset = sizeof(struct spa_meta_cursor);
const QSize targetSize = (cursor->rect().size() * m_cursor.scale).toSize();
const QSize targetSize = (cursor->rect().size() * scale).toSize();
struct spa_meta_bitmap *spaMetaBitmap = SPA_MEMBER(spaMetaCursor,
spaMetaCursor->bitmap_offset,
@ -771,12 +773,11 @@ QRegion ScreenCastStream::addCursorEmbedded(ScreenCastBuffer *buffer, Cursor *cu
return damage;
}
const QRectF cursorRect = scaledRect(m_source->mapFromGlobal(cursor->geometry()), m_cursor.scale);
const QRectF cursorRect = scaledRect(m_source->mapFromGlobal(cursor->geometry()), m_source->devicePixelRatio());
if (auto memfd = dynamic_cast<MemFdScreenCastBuffer *>(buffer)) {
QPainter painter(memfd->view.image());
const auto position = m_source->mapFromGlobal(cursor->pos() - cursor->hotspot()) * m_cursor.scale;
const PlatformCursorImage cursorImage = kwinApp()->cursorImage();
painter.drawImage(QRect{position.toPoint(), cursorImage.image().size()}, cursorImage.image());
painter.drawImage(cursorRect, cursorImage.image());
} else if (auto dmabuf = dynamic_cast<DmaBufScreenCastBuffer *>(buffer)) {
if (m_cursor.invalid) {
m_cursor.invalid = false;
@ -816,10 +817,9 @@ QRegion ScreenCastStream::addCursorEmbedded(ScreenCastBuffer *buffer, Cursor *cu
return damage;
}
void ScreenCastStream::setCursorMode(ScreencastV1Interface::CursorMode mode, qreal scale)
void ScreenCastStream::setCursorMode(ScreencastV1Interface::CursorMode mode)
{
m_cursor.mode = mode;
m_cursor.scale = scale;
}
std::optional<ScreenCastDmaBufTextureParams> ScreenCastStream::testCreateDmaBuf(const QSize &size, quint32 format, const QList<uint64_t> &modifiers)

View file

@ -68,7 +68,7 @@ public:
void scheduleRecord(const QRegion &damage, Contents contents = Content::Video);
void setCursorMode(ScreencastV1Interface::CursorMode mode, qreal scale);
void setCursorMode(ScreencastV1Interface::CursorMode mode);
public Q_SLOTS:
void invalidateCursor();
@ -121,7 +121,6 @@ private:
{
ScreencastV1Interface::CursorMode mode = ScreencastV1Interface::Hidden;
const QSize bitmapSize = QSize(256, 256);
qreal scale = 1;
QRectF lastRect;
std::unique_ptr<GLTexture> texture;
bool visible = false;

View file

@ -52,6 +52,11 @@ QSize WindowScreenCastSource::textureSize() const
return m_window->clientGeometry().size().toSize();
}
qreal WindowScreenCastSource::devicePixelRatio() const
{
return 1.0;
}
void WindowScreenCastSource::render(QImage *target)
{
const auto offscreenTexture = GLTexture::allocate(GL_RGBA8, textureSize());

View file

@ -25,6 +25,7 @@ public:
quint32 drmFormat() const override;
QSize textureSize() const override;
qreal devicePixelRatio() const override;
uint refreshRate() const override;
void render(GLFramebuffer *target) override;