1
0
mirror of https://invent.kde.org/network/krfb synced 2024-07-01 07:24:29 +00:00

pipewire: Support cursors

This commit is contained in:
Aleix Pol 2021-10-29 17:31:53 +02:00 committed by Aleix Pol Gonzalez
parent 775d3c7a97
commit 61d464676c
2 changed files with 59 additions and 13 deletions

View File

@ -175,6 +175,10 @@ private:
// sanity indicator
bool isValid = true;
QImage cursorTexture;
QPoint cursorPosition;
QPoint cursorHotspot;
#if HAVE_DMA_BUF
struct EGLStruct {
QList<QByteArray> extensions;
@ -556,6 +560,10 @@ void PWFrameBuffer::Private::onStreamStateChanged(void *data, pw_stream_state /*
}
}
#define CURSOR_BPP 4
#define CURSOR_META_SIZE(w,h) (sizeof(struct spa_meta_cursor) + \
sizeof(struct spa_meta_bitmap) + w * h * CURSOR_BPP)
/**
* @brief PWFrameBuffer::Private::onStreamFormatChanged - being executed after stream is set to active
* and after setup has been requested to connect to it. The actual video format is being negotiated here.
@ -583,7 +591,6 @@ void PWFrameBuffer::Private::onStreamParamChanged(void *data, uint32_t id, const
auto builder = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
// setup buffers and meta header for new format
const struct spa_pod *params[3];
#if HAVE_DMA_BUF
const auto bufferTypes = d->m_eglInitialized ? (1 << SPA_DATA_DmaBuf) | (1 << SPA_DATA_MemFd) | (1 << SPA_DATA_MemPtr) :
@ -592,23 +599,31 @@ void PWFrameBuffer::Private::onStreamParamChanged(void *data, uint32_t id, const
const auto bufferTypes = (1 << SPA_DATA_MemFd) | (1 << SPA_DATA_MemPtr);
#endif /* HAVE_DMA_BUF */
params[0] = reinterpret_cast<spa_pod *>(spa_pod_builder_add_object(&builder,
QVector<const struct spa_pod *> params = {
reinterpret_cast<spa_pod *>(spa_pod_builder_add_object(&builder,
SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
SPA_PARAM_BUFFERS_size, SPA_POD_Int(size),
SPA_PARAM_BUFFERS_stride, SPA_POD_Int(stride),
SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(8, 1, 32),
SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(1),
SPA_PARAM_BUFFERS_align, SPA_POD_Int(16),
SPA_PARAM_BUFFERS_dataType, SPA_POD_CHOICE_FLAGS_Int(bufferTypes)));
params[1] = reinterpret_cast<spa_pod *>(spa_pod_builder_add_object(&builder,
SPA_PARAM_BUFFERS_dataType, SPA_POD_CHOICE_FLAGS_Int(bufferTypes))),
reinterpret_cast<spa_pod *>(spa_pod_builder_add_object(&builder,
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header),
SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header))));
params[2] = reinterpret_cast<spa_pod*>(spa_pod_builder_add_object(&builder,
SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header)))),
reinterpret_cast<spa_pod*>(spa_pod_builder_add_object(&builder,
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type,
SPA_POD_Id(SPA_META_VideoCrop), SPA_PARAM_META_size,
SPA_POD_Int(sizeof(struct spa_meta_region))));
pw_stream_update_params(d->pwStream, params, 3);
SPA_POD_Int(sizeof(struct spa_meta_region)))),
reinterpret_cast<spa_pod*>(spa_pod_builder_add_object ( &builder,
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
SPA_PARAM_META_type, SPA_POD_Id (SPA_META_Cursor),
SPA_PARAM_META_size, SPA_POD_CHOICE_RANGE_Int (CURSOR_META_SIZE (64, 64),
CURSOR_META_SIZE (1, 1),
CURSOR_META_SIZE (1024, 1024)))),
};
pw_stream_update_params(d->pwStream, params.data(), params.size());
}
/**
@ -642,6 +657,13 @@ void PWFrameBuffer::Private::onStreamProcess(void *data)
pw_stream_queue_buffer(d->pwStream, buffer);
}
static QImage::Format spaToQImageFormat(quint32 format)
{
return format == SPA_VIDEO_FORMAT_BGR ? QImage::Format_BGR888
: format == SPA_VIDEO_FORMAT_RGBx ? QImage::Format_RGBX8888
: QImage::Format_RGB32;
}
void PWFrameBuffer::Private::handleFrame(pw_buffer *pwBuffer)
{
auto spaBuffer = pwBuffer->buffer;
@ -751,6 +773,28 @@ void PWFrameBuffer::Private::handleFrame(pw_buffer *pwBuffer)
}
#endif /* HAVE_DMA_BUF */
// process cursor
{
struct spa_meta_cursor *cursor = static_cast<struct spa_meta_cursor*>(spa_buffer_find_meta_data (spaBuffer, SPA_META_Cursor, sizeof (*cursor)));
if (spa_meta_cursor_is_valid (cursor)) {
struct spa_meta_bitmap *bitmap = nullptr;
if (cursor->bitmap_offset)
bitmap = SPA_MEMBER (cursor, cursor->bitmap_offset, struct spa_meta_bitmap);
if (bitmap && bitmap->size.width > 0 && bitmap->size.height > 0) {
const uint8_t *bitmap_data;
bitmap_data = SPA_MEMBER (bitmap, bitmap->offset, uint8_t);
cursorHotspot = { cursor->hotspot.x, cursor->hotspot.y };
cursorTexture = QImage(bitmap_data, bitmap->size.width, bitmap->size.height, bitmap->stride, spaToQImageFormat(bitmap->format));
}
cursorPosition = QPoint{ cursor->position.x, cursor->position.y };
}
}
struct spa_meta_region* videoMetadata =
static_cast<struct spa_meta_region*>(spa_buffer_find_meta_data(
spaBuffer, SPA_META_VideoCrop, sizeof(*videoMetadata)));
@ -828,11 +872,7 @@ void PWFrameBuffer::Private::handleFrame(pw_buffer *pwBuffer)
}
if (videoFormat->format != SPA_VIDEO_FORMAT_RGB) {
const QImage::Format format = videoFormat->format == SPA_VIDEO_FORMAT_BGR ? QImage::Format_BGR888
: videoFormat->format == SPA_VIDEO_FORMAT_RGBx ? QImage::Format_RGBX8888
: QImage::Format_RGB32;
QImage img((uchar*) q->fb, videoSize.width(), videoSize.height(), dstStride, format);
QImage img((uchar*) q->fb, videoSize.width(), videoSize.height(), dstStride, spaToQImageFormat(videoFormat->format));
img.convertTo(QImage::Format_RGB888);
}
@ -1002,3 +1042,8 @@ bool PWFrameBuffer::isValid() const
{
return d->isValid;
}
QPoint PWFrameBuffer::cursorPosition()
{
return d->cursorPosition;
}

View File

@ -43,6 +43,7 @@ public:
void getServerFormat(rfbPixelFormat &format) override;
void startMonitor() override;
void stopMonitor() override;
QPoint cursorPosition() override;
QVariant customProperty(const QString &property) const override;