[Spice-devel] [PATCH spice 17/18] Handle GL_DRAW messages
Marc-André Lureau
marcandre.lureau at gmail.com
Tue Dec 15 15:49:31 PST 2015
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 at gmail.com>
---
server/dcc-send.c | 14 ++++++++++++++
server/dcc.c | 23 +++++++++++++++++++++++
server/dcc.h | 9 +++++++++
server/display-channel.c | 21 +++++++++++++++++++++
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, 100 insertions(+)
diff --git a/server/dcc-send.c b/server/dcc-send.c
index 8cc2dda..fb5db72 100644
--- a/server/dcc-send.c
+++ b/server/dcc-send.c
@@ -2361,6 +2361,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);
@@ -2475,6 +2486,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 47084ca..5ed7bff 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 PIPE_ITEM(item);
}
+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 PIPE_ITEM(item);
+}
+
void dcc_destroy_surface(DisplayChannelClient *dcc, uint32_t surface_id)
{
DisplayChannel *display;
@@ -1586,6 +1607,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;
@@ -1661,6 +1683,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 22d236e..e878829 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 1f8f5af..2071587 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -2155,3 +2155,24 @@ 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 183a0d3..560a060 100644
--- a/server/red-dispatcher.c
+++ b/server/red-dispatcher.c
@@ -996,9 +996,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.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,
@@ -1018,6 +1031,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 e4ba79f..575b7bd 100644
--- a/server/red-dispatcher.h
+++ b/server/red-dispatcher.h
@@ -87,6 +87,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 7005166..64f89d0 100644
--- a/server/red-worker.c
+++ b/server/red-worker.c
@@ -1294,6 +1294,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;
@@ -1536,6 +1545,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 cffa57f..ee8caf9 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -36,6 +36,7 @@ struct QXLState {
pthread_mutex_t scanout_mutex;
SpiceMsgDisplayGlScanoutUnix scanout;
AsyncCommand *gl_draw_async;
+ int gl_draw_async_count;
};
struct TunnelWorker;
--
2.5.0
More information about the Spice-devel
mailing list