> > 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; The sent field is never used in the code > +} 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; Frediano _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel