[Spice-devel] [PATCH v4 5/6] Handle GL_DRAW messages
Marc-André Lureau
marcandre.lureau at gmail.com
Tue Feb 9 13:35:05 UTC 2016
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>
[removed unused sent field; move gl_draw_async_count to DisplayChannel
- Frediano Ziglio]
Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
---
server/dcc-send.c | 14 ++++++++++++++
server/dcc.c | 23 +++++++++++++++++++++++
server/dcc.h | 8 ++++++++
server/display-channel.c | 24 ++++++++++++++++++++++++
server/display-channel.h | 5 +++++
server/red-dispatcher.c | 14 ++++++++++++++
server/red-dispatcher.h | 1 +
server/red-worker.c | 14 ++++++++++++++
8 files changed, 103 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..a482938 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,11 @@ typedef struct GlScanoutUnixItem {
PipeItem base;
} GlScanoutUnixItem;
+typedef struct GlDrawItem {
+ PipeItem base;
+ SpiceMsgDisplayGlDraw draw;
+} GlDrawItem;
+
typedef struct ImageItem {
PipeItem link;
int refs;
@@ -213,6 +219,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..936c74a 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -2154,3 +2154,27 @@ 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(DisplayChannel *display, int num)
+{
+ RedWorker *worker = COMMON_CHANNEL(display)->worker;
+ QXLInstance *qxl = red_worker_get_qxl(worker);
+
+ display->gl_draw_async_count = num;
+
+ if (num == 0) {
+ struct AsyncCommand *async = qxl->st->gl_draw_async;
+ qxl->st->gl_draw_async = NULL;
+ red_dispatcher_async_complete(qxl->st->dispatcher, async);
+ }
+}
+
+void display_channel_gl_draw(DisplayChannel *display, SpiceMsgDisplayGlDraw *draw)
+{
+ int num;
+
+ spice_return_if_fail(display->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(display, num);
+}
diff --git a/server/display-channel.h b/server/display-channel.h
index 346e61a..3d2a465 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 {
@@ -201,6 +202,8 @@ struct DisplayChannel {
ImageCache image_cache;
RedCompressBuf *free_compress_bufs;
+ int gl_draw_async_count;
+
/* TODO: some day unify this, make it more runtime.. */
stat_info_t add_stat;
stat_info_t exclude_stat;
@@ -308,6 +311,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 26a153e..dce20c4 100644
--- a/server/red-dispatcher.c
+++ b/server/red-dispatcher.c
@@ -998,9 +998,22 @@ void spice_qxl_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,
@@ -1020,6 +1033,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 76ac41c..e7d0671 100644
--- a/server/red-worker.c
+++ b/server/red-worker.c
@@ -1167,6 +1167,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;
@@ -1409,6 +1418,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);
}
--
2.5.0
More information about the Spice-devel
mailing list