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@xxxxxxxxx> --- server/dcc-send.c | 25 +++++++++++++++++++++++++ server/dcc.c | 21 +++++++++++++++++++++ server/dcc.h | 6 ++++++ server/display-channel.c | 6 ++++++ server/display-channel.h | 2 ++ server/red-channel.h | 2 ++ server/red-dispatcher.c | 8 ++++++++ server/red-dispatcher.h | 1 + server/red-worker.c | 13 +++++++++++++ server/reds.c | 1 + server/reds.h | 1 + 11 files changed, 86 insertions(+) diff --git a/server/dcc-send.c b/server/dcc-send.c index c3f79ef..8cc2dda 100644 --- a/server/dcc-send.c +++ b/server/dcc-send.c @@ -2339,6 +2339,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->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); @@ -2450,6 +2472,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(); } diff --git a/server/dcc.c b/server/dcc.c index b2ee7a6..c56ceb6 100644 --- a/server/dcc.c +++ b/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 PIPE_ITEM(item); +} + void dcc_destroy_surface(DisplayChannelClient *dcc, uint32_t surface_id) { DisplayChannel *display; @@ -1555,6 +1574,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; @@ -1629,6 +1649,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: diff --git a/server/dcc.h b/server/dcc.h index 2a12226..22d236e 100644 --- a/server/dcc.h +++ b/server/dcc.h @@ -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; diff --git a/server/display-channel.c b/server/display-channel.c index ec4ca10..1f8f5af 100644 --- a/server/display-channel.c +++ b/server/display-channel.c @@ -2149,3 +2149,9 @@ 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); +} + diff --git a/server/display-channel.h b/server/display-channel.h index bf29cd3..346e61a 100644 --- a/server/display-channel.h +++ b/server/display-channel.h @@ -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) { diff --git a/server/red-channel.h b/server/red-channel.h index aa06416..eef22f1 100644 --- a/server/red-channel.h +++ b/server/red-channel.h @@ -157,6 +157,8 @@ static inline int pipe_item_is_linked(PipeItem *item) return ring_item_is_linked(&item->link); } +#define PIPE_ITEM(item) ((PipeItem*)(item)) + typedef uint8_t *(*channel_alloc_msg_recv_buf_proc)(RedChannelClient *channel, uint16_t type, uint32_t size); typedef int (*channel_handle_parsed_proc)(RedChannelClient *rcc, uint32_t size, uint16_t type, diff --git a/server/red-dispatcher.c b/server/red-dispatcher.c index a1e4e1e..183a0d3 100644 --- a/server/red-dispatcher.c +++ b/server/red-dispatcher.c @@ -968,6 +968,8 @@ void spice_gl_scanout(QXLInstance *qxl, { spice_return_if_fail(qxl != NULL); + pthread_mutex_lock(&qxl->st->scanout_mutex); + if (qxl->st->scanout.fd != -1) { close(qxl->st->scanout.fd); } @@ -980,6 +982,12 @@ void spice_gl_scanout(QXLInstance *qxl, .stride = stride, .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 diff --git a/server/red-dispatcher.h b/server/red-dispatcher.h index 7aabe44..e4ba79f 100644 --- a/server/red-dispatcher.h +++ b/server/red-dispatcher.h @@ -86,6 +86,7 @@ enum { RED_WORKER_MESSAGE_MONITORS_CONFIG_ASYNC, RED_WORKER_MESSAGE_DRIVER_UNLOAD, + RED_WORKER_MESSAGE_GL_SCANOUT, RED_WORKER_MESSAGE_COUNT // LAST }; diff --git a/server/red-worker.c b/server/red-worker.c index dfaf4ba..7005166 100644 --- a/server/red-worker.c +++ b/server/red-worker.c @@ -1286,6 +1286,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; @@ -1523,6 +1531,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); } diff --git a/server/reds.c b/server/reds.c index fafa135..e7edaff 100644 --- a/server/reds.c +++ b/server/reds.c @@ -3155,6 +3155,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.fd = -1; qxl->st->qif = SPICE_CONTAINEROF(interface, QXLInterface, base); red_dispatcher_init(qxl); diff --git a/server/reds.h b/server/reds.h index 07ad8f9..cffa57f 100644 --- a/server/reds.h +++ b/server/reds.h @@ -33,6 +33,7 @@ struct QXLState { QXLInterface *qif; struct RedDispatcher *dispatcher; + pthread_mutex_t scanout_mutex; SpiceMsgDisplayGlScanoutUnix scanout; AsyncCommand *gl_draw_async; }; -- 2.5.0 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel