mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-08-06 18:52:33 +00:00
red-qxl: use RedGLScanout for multi plane support
Create a new scanout struct supporting multi plane. We'll use this struct to create different protocol message for clients with different capability. Signed-off-by: Qiang Yu <yuq825@gmail.com> Acked-by: Frediano Ziglio <freddy77@gmail.com>
This commit is contained in:
parent
bedd2e1bcb
commit
cf678836a9
@ -1788,15 +1788,23 @@ static void red_marshall_gl_draw_stream(DisplayChannelClient *dcc,
|
||||
}
|
||||
|
||||
QXLInstance* qxl = display->priv->qxl;
|
||||
SpiceMsgDisplayGlScanoutUnix *scanout = red_qxl_get_gl_scanout(qxl);
|
||||
RedGLScanout *scanout = red_qxl_get_gl_scanout(qxl);
|
||||
if (!scanout) {
|
||||
spice_warning("Cannot access scanout");
|
||||
delete dmabuf_data;
|
||||
return;
|
||||
}
|
||||
|
||||
dmabuf_data->drm_dma_buf_fd = scanout->drm_dma_buf_fd;
|
||||
dmabuf_data->drm_fourcc_format = scanout->drm_fourcc_format;
|
||||
/* TODO: add support for it */
|
||||
if (scanout->num_planes > 1) {
|
||||
spice_warning("Video encoder Does not support multi plane");
|
||||
red_qxl_put_gl_scanout(qxl, scanout);
|
||||
delete dmabuf_data;
|
||||
return;
|
||||
}
|
||||
|
||||
dmabuf_data->drm_dma_buf_fd = scanout->fd[0];
|
||||
dmabuf_data->drm_fourcc_format = scanout->fourcc;
|
||||
dmabuf_data->width = stream->width;
|
||||
dmabuf_data->height = stream->height;
|
||||
dmabuf_data->stride = stream->stride;
|
||||
@ -2370,10 +2378,22 @@ static void marshall_gl_scanout(DisplayChannelClient *dcc,
|
||||
DisplayChannel *display_channel = DCC_TO_DC(dcc);
|
||||
QXLInstance* qxl = display_channel->priv->qxl;
|
||||
|
||||
SpiceMsgDisplayGlScanoutUnix *scanout = red_qxl_get_gl_scanout(qxl);
|
||||
RedGLScanout *scanout = red_qxl_get_gl_scanout(qxl);
|
||||
if (scanout != nullptr) {
|
||||
dcc->init_send_data(SPICE_MSG_DISPLAY_GL_SCANOUT_UNIX);
|
||||
spice_marshall_msg_display_gl_scanout_unix(m, scanout);
|
||||
if (scanout->num_planes <= 1) {
|
||||
SpiceMsgDisplayGlScanoutUnix msg;
|
||||
msg.drm_dma_buf_fd = scanout->fd[0];
|
||||
msg.width = scanout->width;
|
||||
msg.height = scanout->height;
|
||||
msg.stride = scanout->stride[0];
|
||||
msg.drm_fourcc_format = scanout->fourcc;
|
||||
msg.flags = scanout->flags;
|
||||
|
||||
dcc->init_send_data(SPICE_MSG_DISPLAY_GL_SCANOUT_UNIX);
|
||||
spice_marshall_msg_display_gl_scanout_unix(m, &msg);
|
||||
} else {
|
||||
spice_error("gl scanout does not support multi plane");
|
||||
}
|
||||
}
|
||||
red_qxl_put_gl_scanout(qxl, scanout);
|
||||
}
|
||||
|
||||
@ -39,6 +39,13 @@
|
||||
|
||||
#include "red-qxl.h"
|
||||
|
||||
#ifdef HAVE_DRM_DRM_FOURCC_H
|
||||
#include <drm/drm_fourcc.h>
|
||||
#endif
|
||||
|
||||
#ifndef DRM_FORMAT_MOD_INVALID
|
||||
#define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1)
|
||||
#endif
|
||||
|
||||
#define MAX_MONITORS_COUNT 16
|
||||
|
||||
@ -61,7 +68,7 @@ struct QXLState {
|
||||
bool running;
|
||||
|
||||
pthread_mutex_t scanout_mutex;
|
||||
SpiceMsgDisplayGlScanoutUnix scanout;
|
||||
RedGLScanout scanout;
|
||||
uint64_t gl_draw_cookie;
|
||||
|
||||
template <typename T>
|
||||
@ -409,17 +416,17 @@ void spice_qxl_set_max_monitors(QXLInstance *instance, unsigned int max_monitors
|
||||
instance->st->max_monitors = MAX(1U, max_monitors);
|
||||
}
|
||||
|
||||
SpiceMsgDisplayGlScanoutUnix *red_qxl_get_gl_scanout(QXLInstance *qxl)
|
||||
RedGLScanout *red_qxl_get_gl_scanout(QXLInstance *qxl)
|
||||
{
|
||||
pthread_mutex_lock(&qxl->st->scanout_mutex);
|
||||
if (qxl->st->scanout.drm_dma_buf_fd >= 0) {
|
||||
if (qxl->st->scanout.fd[0] >= 0) {
|
||||
return &qxl->st->scanout;
|
||||
}
|
||||
pthread_mutex_unlock(&qxl->st->scanout_mutex);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void red_qxl_put_gl_scanout(QXLInstance *qxl, SpiceMsgDisplayGlScanoutUnix *scanout)
|
||||
void red_qxl_put_gl_scanout(QXLInstance *qxl, RedGLScanout *scanout)
|
||||
{
|
||||
if (scanout) {
|
||||
pthread_mutex_unlock(&qxl->st->scanout_mutex);
|
||||
@ -440,17 +447,22 @@ void spice_qxl_gl_scanout(QXLInstance *qxl,
|
||||
|
||||
pthread_mutex_lock(&qxl_state->scanout_mutex);
|
||||
|
||||
if (qxl_state->scanout.drm_dma_buf_fd >= 0) {
|
||||
close(qxl_state->scanout.drm_dma_buf_fd);
|
||||
RedGLScanout *scanout = &qxl_state->scanout;
|
||||
for (int i = 0; i < scanout->num_planes; i++) {
|
||||
if (scanout->fd[i] >= 0) {
|
||||
close(scanout->fd[i]);
|
||||
}
|
||||
}
|
||||
|
||||
qxl_state->scanout = (SpiceMsgDisplayGlScanoutUnix) {
|
||||
.drm_dma_buf_fd = fd,
|
||||
qxl_state->scanout = (RedGLScanout) {
|
||||
.fd = {fd, -1, -1, -1},
|
||||
.width = width,
|
||||
.height = height,
|
||||
.stride = stride,
|
||||
.drm_fourcc_format = format,
|
||||
.stride = {stride, 0, 0, 0},
|
||||
.fourcc = format,
|
||||
.num_planes = 1,
|
||||
.flags = y_0_top ? SPICE_GL_SCANOUT_FLAGS_Y0TOP : 0,
|
||||
.modifier = DRM_FORMAT_MOD_INVALID,
|
||||
};
|
||||
|
||||
pthread_mutex_unlock(&qxl_state->scanout_mutex);
|
||||
@ -478,7 +490,7 @@ void spice_qxl_gl_draw_async(QXLInstance *qxl,
|
||||
|
||||
spice_return_if_fail(qxl != nullptr);
|
||||
qxl_state = qxl->st;
|
||||
if (qxl_state->scanout.drm_dma_buf_fd < 0) {
|
||||
if (qxl_state->scanout.fd[0] < 0) {
|
||||
spice_warning("called spice_qxl_gl_draw_async without a buffer");
|
||||
red_qxl_async_complete(qxl, cookie);
|
||||
return;
|
||||
@ -576,9 +588,11 @@ void red_qxl_init(RedsState *reds, QXLInstance *qxl)
|
||||
qxl_state->reds = reds;
|
||||
qxl_state->qxl = qxl;
|
||||
pthread_mutex_init(&qxl_state->scanout_mutex, nullptr);
|
||||
qxl_state->scanout.drm_dma_buf_fd = -1;
|
||||
qxl_state->gl_draw_cookie = GL_DRAW_COOKIE_INVALID;
|
||||
qxl_state->dispatcher = red::make_shared<Dispatcher>(RED_WORKER_MESSAGE_COUNT);
|
||||
for (auto& fd : qxl_state->scanout.fd) {
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
qxl_state->max_monitors = UINT_MAX;
|
||||
qxl->st = qxl_state;
|
||||
@ -619,7 +633,7 @@ void red_qxl_clear_pending(QXLState *qxl_state, int pending)
|
||||
bool red_qxl_get_allow_client_mouse(QXLInstance *qxl, int *x_res, int *y_res, int *allow_now)
|
||||
{
|
||||
// try to get resolution when 3D enabled, since qemu did not create QXL primary surface
|
||||
SpiceMsgDisplayGlScanoutUnix *gl;
|
||||
RedGLScanout *gl;
|
||||
if ((gl = red_qxl_get_gl_scanout(qxl))) {
|
||||
*x_res = gl->width;
|
||||
*y_res = gl->height;
|
||||
|
||||
@ -23,6 +23,18 @@
|
||||
|
||||
SPICE_BEGIN_DECLS
|
||||
|
||||
struct RedGLScanout {
|
||||
int fd[4];
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t offset[4];
|
||||
uint32_t stride[4];
|
||||
uint32_t fourcc;
|
||||
uint32_t num_planes;
|
||||
uint32_t flags;
|
||||
uint64_t modifier;
|
||||
};
|
||||
|
||||
void red_qxl_init(SpiceServer *reds, QXLInstance *qxl);
|
||||
void red_qxl_destroy(QXLInstance *qxl);
|
||||
|
||||
@ -37,8 +49,8 @@ void red_qxl_start(QXLInstance *qxl);
|
||||
uint32_t red_qxl_get_ram_size(QXLInstance *qxl);
|
||||
gboolean red_qxl_client_monitors_config(QXLInstance *qxl, VDAgentMonitorsConfig *monitors_config);
|
||||
bool red_qxl_get_allow_client_mouse(QXLInstance *qxl, int *x_res, int *y_res, int *allow_now);
|
||||
SpiceMsgDisplayGlScanoutUnix *red_qxl_get_gl_scanout(QXLInstance *qxl);
|
||||
void red_qxl_put_gl_scanout(QXLInstance *qxl, SpiceMsgDisplayGlScanoutUnix *scanout);
|
||||
RedGLScanout *red_qxl_get_gl_scanout(QXLInstance *qxl);
|
||||
void red_qxl_put_gl_scanout(QXLInstance *qxl, RedGLScanout *scanout);
|
||||
void red_qxl_gl_draw_async_complete(QXLInstance *qxl);
|
||||
int red_qxl_check_qxl_version(QXLInstance *qxl, int major, int minor);
|
||||
SpiceServer* red_qxl_get_server(QXLState *qxl);
|
||||
|
||||
@ -441,7 +441,7 @@ static void display_channel_create_stream(DisplayChannel *display,
|
||||
bool display_channel_create_gl_draw_stream(DisplayChannel *display)
|
||||
{
|
||||
QXLInstance* qxl = display->priv->qxl;
|
||||
SpiceMsgDisplayGlScanoutUnix *scanout = red_qxl_get_gl_scanout(qxl);
|
||||
RedGLScanout *scanout = red_qxl_get_gl_scanout(qxl);
|
||||
DisplayChannelClient *dcc;
|
||||
VideoStream *stream;
|
||||
bool ret = false;
|
||||
@ -460,7 +460,7 @@ bool display_channel_create_gl_draw_stream(DisplayChannel *display)
|
||||
display_channel_surface_id_unref(display, 0);
|
||||
}
|
||||
if (!display_channel_create_surface(display, 0, scanout->width,
|
||||
scanout->height, scanout->stride,
|
||||
scanout->height, scanout->stride[0],
|
||||
SPICE_SURFACE_FMT_32_xRGB,
|
||||
nullptr, true, true)) {
|
||||
goto err;
|
||||
@ -478,7 +478,7 @@ bool display_channel_create_gl_draw_stream(DisplayChannel *display)
|
||||
ret = true;
|
||||
display_channel_init_stream(display, stream, nullptr, &dest_area);
|
||||
stream->top_down = (scanout->flags & SPICE_GL_SCANOUT_FLAGS_Y0TOP) ? 0 : 1;
|
||||
stream->stride = scanout->stride;
|
||||
stream->stride = scanout->stride[0];
|
||||
/* This is the upper bound; it should be possible to stream at 60 FPS
|
||||
* with a hardware based encoder.
|
||||
*/
|
||||
@ -501,7 +501,7 @@ bool is_new_stream_needed(DisplayChannel *display)
|
||||
}
|
||||
|
||||
QXLInstance* qxl = display->priv->qxl;
|
||||
SpiceMsgDisplayGlScanoutUnix *scanout = red_qxl_get_gl_scanout(qxl);
|
||||
RedGLScanout *scanout = red_qxl_get_gl_scanout(qxl);
|
||||
uint32_t width, height, top_down;
|
||||
|
||||
if (!scanout) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user