Create an async, and marshall the GL_DRAW message. Count number of clients, and wait until gl_draw_async_count is 0 to complete the async. The count is going to be updated in the following patch when the client is done with the draw. Signed-off-by: Marc-André Lureau <marcandre.lureau@xxxxxxxxx> --- server/dcc-send.c | 14 ++++++++++++++ server/dcc.c | 23 +++++++++++++++++++++++ server/dcc.h | 9 +++++++++ server/display-channel.c | 22 ++++++++++++++++++++++ server/display-channel.h | 3 +++ server/red-dispatcher.c | 14 ++++++++++++++ server/red-dispatcher.h | 1 + server/red-worker.c | 14 ++++++++++++++ server/reds.h | 1 + 9 files changed, 101 insertions(+) diff --git a/server/dcc-send.c b/server/dcc-send.c index a9cc19c..3af5760 100644 --- a/server/dcc-send.c +++ b/server/dcc-send.c @@ -2321,6 +2321,17 @@ end: pthread_mutex_unlock(&qxl->st->scanout_mutex); } +static void marshall_gl_draw(RedChannelClient *rcc, + SpiceMarshaller *m, + PipeItem *item) +{ + GlDrawItem *p = SPICE_CONTAINEROF(item, GlDrawItem, base); + + red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_GL_DRAW, NULL); + spice_marshall_msg_display_gl_draw(m, &p->draw); +} + + static void begin_send_message(RedChannelClient *rcc) { DisplayChannelClient *dcc = RCC_TO_DCC(rcc); @@ -2435,6 +2446,9 @@ void dcc_send_item(DisplayChannelClient *dcc, PipeItem *pipe_item) case PIPE_ITEM_TYPE_GL_SCANOUT: marshall_gl_scanout(rcc, m, pipe_item); break; + case PIPE_ITEM_TYPE_GL_DRAW: + marshall_gl_draw(rcc, m, pipe_item); + break; default: spice_warn_if_reached(); } diff --git a/server/dcc.c b/server/dcc.c index 58ae55c..6972616 100644 --- a/server/dcc.c +++ b/server/dcc.c @@ -586,6 +586,27 @@ PipeItem *dcc_gl_scanout_item_new(RedChannelClient *rcc, void *data, int num) return &item->base; } +PipeItem *dcc_gl_draw_item_new(RedChannelClient *rcc, void *data, int num) +{ + DisplayChannelClient *dcc = RCC_TO_DCC(rcc); + const SpiceMsgDisplayGlDraw *draw = data; + GlDrawItem *item = spice_new(GlDrawItem, 1); + spice_return_val_if_fail(item != NULL, NULL); + + if (!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; + } + + dcc->gl_draw_ongoing = TRUE; + item->draw = *draw; + red_channel_pipe_item_init(rcc->channel, &item->base, + PIPE_ITEM_TYPE_GL_DRAW); + + return &item->base; +} + void dcc_destroy_surface(DisplayChannelClient *dcc, uint32_t surface_id) { DisplayChannel *display; @@ -1558,6 +1579,7 @@ static void release_item_after_push(DisplayChannelClient *dcc, PipeItem *item) image_item_unref((ImageItem *)item); break; case PIPE_ITEM_TYPE_GL_SCANOUT: + case PIPE_ITEM_TYPE_GL_DRAW: case PIPE_ITEM_TYPE_VERB: free(item); break; @@ -1633,6 +1655,7 @@ static void release_item_before_push(DisplayChannelClient *dcc, PipeItem *item) case PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE: case PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT: case PIPE_ITEM_TYPE_GL_SCANOUT: + case PIPE_ITEM_TYPE_GL_DRAW: free(item); break; default: diff --git a/server/dcc.h b/server/dcc.h index 4ef6073..842b7d4 100644 --- a/server/dcc.h +++ b/server/dcc.h @@ -111,6 +111,7 @@ struct DisplayChannelClient { int use_mjpeg_encoder_rate_control; uint32_t streams_max_latency; uint64_t streams_max_bit_rate; + bool gl_draw_ongoing; }; #define DCC_TO_WORKER(dcc) \ @@ -128,6 +129,12 @@ typedef struct GlScanoutUnixItem { PipeItem base; } GlScanoutUnixItem; +typedef struct GlDrawItem { + PipeItem base; + SpiceMsgDisplayGlDraw draw; + int sent; +} GlDrawItem; + typedef struct ImageItem { PipeItem link; int refs; @@ -213,6 +220,8 @@ int dcc_drawable_is_in_pipe (DisplayCha Drawable *drawable); PipeItem * dcc_gl_scanout_item_new (RedChannelClient *rcc, void *data, int num); +PipeItem * dcc_gl_draw_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 bd8098e..0f962a7 100644 --- a/server/display-channel.c +++ b/server/display-channel.c @@ -2154,3 +2154,25 @@ void display_channel_gl_scanout(DisplayChannel *display) { red_channel_pipes_new_add_push(RED_CHANNEL(display), dcc_gl_scanout_item_new, NULL); } + +static void set_gl_draw_async_count(QXLInstance *qxl, int num) +{ + qxl->st->gl_draw_async_count = num; + + if (num == 0) { + red_dispatcher_async_complete(qxl->st->dispatcher, qxl->st->gl_draw_async); + qxl->st->gl_draw_async = NULL; + } +} + +void display_channel_gl_draw(DisplayChannel *display, SpiceMsgDisplayGlDraw *draw) +{ + RedWorker *worker = COMMON_CHANNEL(display)->worker; + QXLInstance *qxl = red_worker_get_qxl(worker); + int num; + + spice_return_if_fail(qxl->st->gl_draw_async_count == 0); + + num = red_channel_pipes_new_add_push(RED_CHANNEL(display), dcc_gl_draw_item_new, draw); + set_gl_draw_async_count(qxl, num); +} diff --git a/server/display-channel.h b/server/display-channel.h index 346e61a..6eb947a 100644 --- a/server/display-channel.h +++ b/server/display-channel.h @@ -107,6 +107,7 @@ enum { PIPE_ITEM_TYPE_MONITORS_CONFIG, PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT, PIPE_ITEM_TYPE_GL_SCANOUT, + PIPE_ITEM_TYPE_GL_DRAW, }; typedef struct MonitorsConfig { @@ -308,6 +309,8 @@ void display_channel_process_surface_cmd (DisplayCha void display_channel_update_compression (DisplayChannel *display, DisplayChannelClient *dcc); void display_channel_gl_scanout (DisplayChannel *display); +void display_channel_gl_draw (DisplayChannel *display, + SpiceMsgDisplayGlDraw *draw); static inline int validate_surface(DisplayChannel *display, uint32_t surface_id) { diff --git a/server/red-dispatcher.c b/server/red-dispatcher.c index 6d705fc..cf36a42 100644 --- a/server/red-dispatcher.c +++ b/server/red-dispatcher.c @@ -997,9 +997,22 @@ void spice_gl_draw_async(QXLInstance *qxl, uint32_t w, uint32_t h, uint64_t cookie) { + RedDispatcher *dispatcher; + RedWorkerMessage message = RED_WORKER_MESSAGE_GL_DRAW_ASYNC; + SpiceMsgDisplayGlDraw draw = { + .x = x, + .y = y, + .w = w, + .h = h + }; + spice_return_if_fail(qxl != NULL); spice_return_if_fail(qxl->st->scanout.drm_dma_buf_fd != -1); spice_return_if_fail(qxl->st->gl_draw_async == NULL); + + dispatcher = qxl->st->dispatcher; + qxl->st->gl_draw_async = async_command_alloc(dispatcher, message, cookie); + dispatcher_send_message(&dispatcher->dispatcher, message, &draw); } void red_dispatcher_async_complete(struct RedDispatcher *dispatcher, @@ -1019,6 +1032,7 @@ void red_dispatcher_async_complete(struct RedDispatcher *dispatcher, case RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC: case RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC: case RED_WORKER_MESSAGE_MONITORS_CONFIG_ASYNC: + case RED_WORKER_MESSAGE_GL_DRAW_ASYNC: break; case RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC: red_dispatcher_create_primary_surface_complete(dispatcher); diff --git a/server/red-dispatcher.h b/server/red-dispatcher.h index cc60c10..11a4f2a 100644 --- a/server/red-dispatcher.h +++ b/server/red-dispatcher.h @@ -89,6 +89,7 @@ enum { RED_WORKER_MESSAGE_MONITORS_CONFIG_ASYNC, RED_WORKER_MESSAGE_DRIVER_UNLOAD, RED_WORKER_MESSAGE_GL_SCANOUT, + RED_WORKER_MESSAGE_GL_DRAW_ASYNC, RED_WORKER_MESSAGE_COUNT // LAST }; diff --git a/server/red-worker.c b/server/red-worker.c index 266014d..065771b 100644 --- a/server/red-worker.c +++ b/server/red-worker.c @@ -1291,6 +1291,15 @@ void handle_dev_gl_scanout(void *opaque, void *payload) display_channel_gl_scanout(worker->display_channel); } +static +void handle_dev_gl_draw_async(void *opaque, void *payload) +{ + RedWorker *worker = opaque; + SpiceMsgDisplayGlDraw *draw = payload; + + display_channel_gl_draw(worker->display_channel, draw); +} + static int loadvm_command(RedWorker *worker, QXLCommandExt *ext) { RedCursorCmd *cursor_cmd; @@ -1533,6 +1542,11 @@ static void register_callbacks(Dispatcher *dispatcher) handle_dev_gl_scanout, 0, DISPATCHER_NONE); + dispatcher_register_handler(dispatcher, + RED_WORKER_MESSAGE_GL_DRAW_ASYNC, + handle_dev_gl_draw_async, + sizeof(SpiceMsgDisplayGlDraw), + DISPATCHER_NONE); } diff --git a/server/reds.h b/server/reds.h index 308edea..c4d8bda 100644 --- a/server/reds.h +++ b/server/reds.h @@ -39,6 +39,7 @@ struct QXLState { pthread_mutex_t scanout_mutex; SpiceMsgDisplayGlScanoutUnix scanout; struct AsyncCommand *gl_draw_async; + int gl_draw_async_count; }; struct TunnelWorker; -- 2.5.0 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel