mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2025-12-27 07:29:32 +00:00
Handle GL_SCANOUT messages
Go through dispatcher and marshall scanout message. Since the marshaller and the QXL state are manipulated from different threads, add a mutex to protect the current scanout. Signed-off-by: Marc-André Lureau <marcandre.lureau@gmail.com>
This commit is contained in:
parent
ebf461b8e6
commit
7a06efde1c
@ -2299,6 +2299,28 @@ static void marshall_stream_activate_report(RedChannelClient *rcc,
|
||||
spice_marshall_msg_display_stream_activate_report(base_marshaller, &msg);
|
||||
}
|
||||
|
||||
static void marshall_gl_scanout(RedChannelClient *rcc,
|
||||
SpiceMarshaller *m,
|
||||
PipeItem *item)
|
||||
{
|
||||
DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
|
||||
DisplayChannel *display_channel = DCC_TO_DC(dcc);
|
||||
RedWorker *worker = display_channel->common.worker;
|
||||
QXLInstance* qxl = red_worker_get_qxl(worker);
|
||||
SpiceMsgDisplayGlScanoutUnix *so = &qxl->st->scanout;
|
||||
|
||||
pthread_mutex_lock(&qxl->st->scanout_mutex);
|
||||
|
||||
if (so->drm_dma_buf_fd == -1)
|
||||
goto end;
|
||||
|
||||
red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_GL_SCANOUT_UNIX, NULL);
|
||||
spice_marshall_msg_display_gl_scanout_unix(m, so);
|
||||
|
||||
end:
|
||||
pthread_mutex_unlock(&qxl->st->scanout_mutex);
|
||||
}
|
||||
|
||||
static void begin_send_message(RedChannelClient *rcc)
|
||||
{
|
||||
DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
|
||||
@ -2410,6 +2432,9 @@ void dcc_send_item(DisplayChannelClient *dcc, PipeItem *pipe_item)
|
||||
marshall_stream_activate_report(rcc, m, report_item->stream_id);
|
||||
break;
|
||||
}
|
||||
case PIPE_ITEM_TYPE_GL_SCANOUT:
|
||||
marshall_gl_scanout(rcc, m, pipe_item);
|
||||
break;
|
||||
default:
|
||||
spice_warn_if_reached();
|
||||
}
|
||||
|
||||
21
server/dcc.c
21
server/dcc.c
@ -556,6 +556,25 @@ static SurfaceDestroyItem *surface_destroy_item_new(RedChannel *channel,
|
||||
return destroy;
|
||||
}
|
||||
|
||||
PipeItem *dcc_gl_scanout_item_new(RedChannelClient *rcc, void *data, int num)
|
||||
{
|
||||
GlScanoutUnixItem *item = spice_new(GlScanoutUnixItem, 1);
|
||||
spice_return_val_if_fail(item != NULL, NULL);
|
||||
|
||||
/* FIXME: on !unix peer, start streaming with a video codec */
|
||||
if (!reds_stream_is_plain_unix(rcc->stream) ||
|
||||
!red_channel_client_test_remote_cap(rcc, SPICE_DISPLAY_CAP_GL_SCANOUT)) {
|
||||
spice_printerr("FIXME: client does not support GL scanout");
|
||||
red_channel_client_disconnect(rcc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
red_channel_pipe_item_init(rcc->channel, &item->base,
|
||||
PIPE_ITEM_TYPE_GL_SCANOUT);
|
||||
|
||||
return &item->base;
|
||||
}
|
||||
|
||||
void dcc_destroy_surface(DisplayChannelClient *dcc, uint32_t surface_id)
|
||||
{
|
||||
DisplayChannel *display;
|
||||
@ -1527,6 +1546,7 @@ static void release_item_after_push(DisplayChannelClient *dcc, PipeItem *item)
|
||||
case PIPE_ITEM_TYPE_IMAGE:
|
||||
image_item_unref((ImageItem *)item);
|
||||
break;
|
||||
case PIPE_ITEM_TYPE_GL_SCANOUT:
|
||||
case PIPE_ITEM_TYPE_VERB:
|
||||
free(item);
|
||||
break;
|
||||
@ -1601,6 +1621,7 @@ static void release_item_before_push(DisplayChannelClient *dcc, PipeItem *item)
|
||||
case PIPE_ITEM_TYPE_PIXMAP_RESET:
|
||||
case PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE:
|
||||
case PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT:
|
||||
case PIPE_ITEM_TYPE_GL_SCANOUT:
|
||||
free(item);
|
||||
break;
|
||||
default:
|
||||
|
||||
@ -124,6 +124,10 @@ typedef struct SurfaceCreateItem {
|
||||
PipeItem pipe_item;
|
||||
} SurfaceCreateItem;
|
||||
|
||||
typedef struct GlScanoutUnixItem {
|
||||
PipeItem base;
|
||||
} GlScanoutUnixItem;
|
||||
|
||||
typedef struct ImageItem {
|
||||
PipeItem link;
|
||||
int refs;
|
||||
@ -207,6 +211,8 @@ int dcc_clear_surface_drawables_from_pipe (DisplayCha
|
||||
int wait_if_used);
|
||||
int dcc_drawable_is_in_pipe (DisplayChannelClient *dcc,
|
||||
Drawable *drawable);
|
||||
PipeItem * dcc_gl_scanout_item_new (RedChannelClient *rcc,
|
||||
void *data, int num);
|
||||
|
||||
typedef struct compress_send_data_t {
|
||||
void* comp_buf;
|
||||
|
||||
@ -2149,3 +2149,8 @@ void display_channel_update_compression(DisplayChannel *display, DisplayChannelC
|
||||
spice_info("jpeg %s", display->enable_jpeg ? "enabled" : "disabled");
|
||||
spice_info("zlib-over-glz %s", display->enable_zlib_glz_wrap ? "enabled" : "disabled");
|
||||
}
|
||||
|
||||
void display_channel_gl_scanout(DisplayChannel *display)
|
||||
{
|
||||
red_channel_pipes_new_add_push(RED_CHANNEL(display), dcc_gl_scanout_item_new, NULL);
|
||||
}
|
||||
|
||||
@ -106,6 +106,7 @@ enum {
|
||||
PIPE_ITEM_TYPE_DESTROY_SURFACE,
|
||||
PIPE_ITEM_TYPE_MONITORS_CONFIG,
|
||||
PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT,
|
||||
PIPE_ITEM_TYPE_GL_SCANOUT,
|
||||
};
|
||||
|
||||
typedef struct MonitorsConfig {
|
||||
@ -306,6 +307,7 @@ void display_channel_process_surface_cmd (DisplayCha
|
||||
int loadvm);
|
||||
void display_channel_update_compression (DisplayChannel *display,
|
||||
DisplayChannelClient *dcc);
|
||||
void display_channel_gl_scanout (DisplayChannel *display);
|
||||
|
||||
static inline int validate_surface(DisplayChannel *display, uint32_t surface_id)
|
||||
{
|
||||
|
||||
@ -970,6 +970,8 @@ void spice_qxl_gl_scanout(QXLInstance *qxl,
|
||||
spice_return_if_fail(qxl != NULL);
|
||||
spice_return_if_fail(qxl->st->gl_draw_async == NULL);
|
||||
|
||||
pthread_mutex_lock(&qxl->st->scanout_mutex);
|
||||
|
||||
if (qxl->st->scanout.drm_dma_buf_fd != -1) {
|
||||
close(qxl->st->scanout.drm_dma_buf_fd);
|
||||
}
|
||||
@ -982,6 +984,12 @@ void spice_qxl_gl_scanout(QXLInstance *qxl,
|
||||
.stride = stride,
|
||||
.drm_fourcc_format = format
|
||||
};
|
||||
|
||||
pthread_mutex_unlock(&qxl->st->scanout_mutex);
|
||||
|
||||
/* FIXME: find a way to coallesce all pending SCANOUTs */
|
||||
dispatcher_send_message(&qxl->st->dispatcher->dispatcher,
|
||||
RED_WORKER_MESSAGE_GL_SCANOUT, NULL);
|
||||
}
|
||||
|
||||
SPICE_GNUC_VISIBLE
|
||||
|
||||
@ -88,6 +88,7 @@ enum {
|
||||
|
||||
RED_WORKER_MESSAGE_MONITORS_CONFIG_ASYNC,
|
||||
RED_WORKER_MESSAGE_DRIVER_UNLOAD,
|
||||
RED_WORKER_MESSAGE_GL_SCANOUT,
|
||||
|
||||
RED_WORKER_MESSAGE_COUNT // LAST
|
||||
};
|
||||
|
||||
@ -1159,6 +1159,14 @@ static void handle_dev_driver_unload(void *opaque, void *payload)
|
||||
worker->driver_cap_monitors_config = 0;
|
||||
}
|
||||
|
||||
static
|
||||
void handle_dev_gl_scanout(void *opaque, void *payload)
|
||||
{
|
||||
RedWorker *worker = opaque;
|
||||
|
||||
display_channel_gl_scanout(worker->display_channel);
|
||||
}
|
||||
|
||||
static int loadvm_command(RedWorker *worker, QXLCommandExt *ext)
|
||||
{
|
||||
RedCursorCmd *cursor_cmd;
|
||||
@ -1396,6 +1404,11 @@ static void register_callbacks(Dispatcher *dispatcher)
|
||||
handle_dev_driver_unload,
|
||||
sizeof(RedWorkerMessageDriverUnload),
|
||||
DISPATCHER_NONE);
|
||||
dispatcher_register_handler(dispatcher,
|
||||
RED_WORKER_MESSAGE_GL_SCANOUT,
|
||||
handle_dev_gl_scanout,
|
||||
0,
|
||||
DISPATCHER_NONE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -3185,6 +3185,7 @@ SPICE_GNUC_VISIBLE int spice_server_add_interface(SpiceServer *s,
|
||||
|
||||
qxl = SPICE_CONTAINEROF(sin, QXLInstance, base);
|
||||
qxl->st = spice_new0(QXLState, 1);
|
||||
pthread_mutex_init(&qxl->st->scanout_mutex, NULL);
|
||||
qxl->st->scanout.drm_dma_buf_fd = -1;
|
||||
qxl->st->qif = SPICE_CONTAINEROF(interface, QXLInterface, base);
|
||||
red_dispatcher_init(qxl);
|
||||
|
||||
@ -36,6 +36,7 @@ extern RedsState *reds;
|
||||
struct QXLState {
|
||||
QXLInterface *qif;
|
||||
struct RedDispatcher *dispatcher;
|
||||
pthread_mutex_t scanout_mutex;
|
||||
SpiceMsgDisplayGlScanoutUnix scanout;
|
||||
struct AsyncCommand *gl_draw_async;
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user