[Spice-commits] 6 commits - server/dcc.c server/dcc.h server/dcc-send.c server/display-channel.c server/display-channel.h server/red-channel.c server/red-channel.h server/red-dispatcher.c server/red-dispatcher.h server/reds.c server/reds.h server/red-worker.c server/spice-qxl.h server/spice-server.syms
Frediano Ziglio
fziglio at kemper.freedesktop.org
Tue Feb 9 14:07:31 UTC 2016
server/dcc-send.c | 39 +++++++++++++++++++++++
server/dcc.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++
server/dcc.h | 14 ++++++++
server/display-channel.c | 34 ++++++++++++++++++++
server/display-channel.h | 8 ++++
server/red-channel.c | 19 +++++++----
server/red-channel.h | 2 -
server/red-dispatcher.c | 57 +++++++++++++++++++++++++++++++++
server/red-dispatcher.h | 2 +
server/red-worker.c | 27 ++++++++++++++++
server/reds.c | 2 +
server/reds.h | 3 +
server/spice-qxl.h | 10 +++++
server/spice-server.syms | 6 +++
14 files changed, 295 insertions(+), 7 deletions(-)
New commits:
commit 87778643119aa73e6df2dd690f03eb1c39b69cd4
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date: Tue Feb 9 14:35:06 2016 +0100
Handle GL_DRAW_DONE
When a client is done with drawing and sends
SPICE_MSGC_DISPLAY_GL_DRAW_DONE, or when it ends, update the number of
async counts.
Signed-off-by: Marc-André Lureau <marcandre.lureau at gmail.com>
[reduce critical message to a warning; do not reset gl_draw_ongoing
- Frediano Ziglio]
Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
diff --git a/server/dcc.c b/server/dcc.c
index 6972616..5ccbda1 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -494,6 +494,8 @@ static void dcc_destroy_stream_agents(DisplayChannelClient *dcc)
void dcc_stop(DisplayChannelClient *dcc)
{
+ DisplayChannel *dc = DCC_TO_DC(dcc);
+
pixmap_cache_unref(dcc->pixmap_cache);
dcc->pixmap_cache = NULL;
dcc_release_glz(dcc);
@@ -502,6 +504,10 @@ void dcc_stop(DisplayChannelClient *dcc)
free(dcc->send_data.free_list.res);
dcc_destroy_stream_agents(dcc);
dcc_encoders_free(dcc);
+
+ if (dcc->gl_draw_ongoing) {
+ display_channel_gl_draw_done(dc);
+ }
}
void dcc_stream_agent_clip(DisplayChannelClient* dcc, StreamAgent *agent)
@@ -1391,6 +1397,22 @@ static int dcc_handle_preferred_compression(DisplayChannelClient *dcc,
return TRUE;
}
+static int dcc_handle_gl_draw_done(DisplayChannelClient *dcc)
+{
+ DisplayChannel *display = DCC_TO_DC(dcc);
+
+ if (G_UNLIKELY(!dcc->gl_draw_ongoing)) {
+ g_warning("unexpected DRAW_DONE received\n");
+ /* close client connection */
+ return FALSE;
+ }
+
+ dcc->gl_draw_ongoing = FALSE;
+ display_channel_gl_draw_done(display);
+
+ return TRUE;
+}
+
int dcc_handle_message(RedChannelClient *rcc, uint32_t size, uint16_t type, void *msg)
{
DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
@@ -1403,6 +1425,8 @@ int dcc_handle_message(RedChannelClient *rcc, uint32_t size, uint16_t type, void
case SPICE_MSGC_DISPLAY_PREFERRED_COMPRESSION:
return dcc_handle_preferred_compression(dcc,
(SpiceMsgcDisplayPreferredCompression *)msg);
+ case SPICE_MSGC_DISPLAY_GL_DRAW_DONE:
+ return dcc_handle_gl_draw_done(dcc);
default:
return red_channel_client_handle_message(rcc, size, type, msg);
}
diff --git a/server/display-channel.c b/server/display-channel.c
index 936c74a..b4f7ede 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -2178,3 +2178,8 @@ void display_channel_gl_draw(DisplayChannel *display, SpiceMsgDisplayGlDraw *dra
num = red_channel_pipes_new_add_push(RED_CHANNEL(display), dcc_gl_draw_item_new, draw);
set_gl_draw_async_count(display, num);
}
+
+void display_channel_gl_draw_done(DisplayChannel *display)
+{
+ set_gl_draw_async_count(display, display->gl_draw_async_count - 1);
+}
diff --git a/server/display-channel.h b/server/display-channel.h
index 3d2a465..82fd663 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -313,6 +313,7 @@ void display_channel_update_compression (DisplayCha
void display_channel_gl_scanout (DisplayChannel *display);
void display_channel_gl_draw (DisplayChannel *display,
SpiceMsgDisplayGlDraw *draw);
+void display_channel_gl_draw_done (DisplayChannel *display);
static inline int validate_surface(DisplayChannel *display, uint32_t surface_id)
{
commit 381dc93ec0fd126992f5959305ded00987e10847
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date: Tue Feb 9 14:35:05 2016 +0100
Handle GL_DRAW messages
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>
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);
}
commit 5881b40ebdbcde4a09b0ec0ec47b9b2439d5f61e
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date: Tue Feb 9 14:35:04 2016 +0100
Send current GL scanout to new client
Signed-off-by: Marc-André Lureau <marcandre.lureau at gmail.com>
diff --git a/server/dcc.c b/server/dcc.c
index eb63ce6..58ae55c 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -445,6 +445,7 @@ void dcc_start(DisplayChannelClient *dcc)
{
DisplayChannel *display = DCC_TO_DC(dcc);
RedChannelClient *rcc = RED_CHANNEL_CLIENT(dcc);
+ QXLInstance *qxl = red_worker_get_qxl(COMMON_CHANNEL(display)->worker);
red_channel_client_push_set_ack(RED_CHANNEL_CLIENT(dcc));
@@ -464,6 +465,16 @@ void dcc_start(DisplayChannelClient *dcc)
red_pipe_add_verb(rcc, SPICE_MSG_DISPLAY_MARK);
dcc_create_all_streams(dcc);
}
+
+ if (qxl->st->scanout.drm_dma_buf_fd >= 0) {
+ if (reds_stream_is_plain_unix(rcc->stream) &&
+ red_channel_client_test_remote_cap(rcc, SPICE_DISPLAY_CAP_GL_SCANOUT)) {
+ red_channel_client_pipe_add(rcc, dcc_gl_scanout_item_new(rcc, NULL, 0));
+ dcc_push_monitors_config(dcc);
+ } else {
+ spice_printerr("FIXME: GL not supported on this kind of connection");
+ }
+ }
}
static void dcc_destroy_stream_agents(DisplayChannelClient *dcc)
commit 7a06efde1cc75482defea0a84b473b1c6b65afdd
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date: Tue Feb 9 14:35:03 2016 +0100
Handle GL_SCANOUT messages
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 at gmail.com>
diff --git a/server/dcc-send.c b/server/dcc-send.c
index 3cb50ba..a9cc19c 100644
--- a/server/dcc-send.c
+++ b/server/dcc-send.c
@@ -2299,6 +2299,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->drm_dma_buf_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);
@@ -2410,6 +2432,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 bf692f8..eb63ce6 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 &item->base;
+}
+
void dcc_destroy_surface(DisplayChannelClient *dcc, uint32_t surface_id)
{
DisplayChannel *display;
@@ -1527,6 +1546,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;
@@ -1601,6 +1621,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 f715792..4ef6073 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 f0d133a..bd8098e 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -2149,3 +2149,8 @@ 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-dispatcher.c b/server/red-dispatcher.c
index 009c377..26a153e 100644
--- a/server/red-dispatcher.c
+++ b/server/red-dispatcher.c
@@ -970,6 +970,8 @@ void spice_qxl_gl_scanout(QXLInstance *qxl,
spice_return_if_fail(qxl != NULL);
spice_return_if_fail(qxl->st->gl_draw_async == NULL);
+ pthread_mutex_lock(&qxl->st->scanout_mutex);
+
if (qxl->st->scanout.drm_dma_buf_fd != -1) {
close(qxl->st->scanout.drm_dma_buf_fd);
}
@@ -982,6 +984,12 @@ void spice_qxl_gl_scanout(QXLInstance *qxl,
.stride = stride,
.drm_fourcc_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 d99695d..cc60c10 100644
--- a/server/red-dispatcher.h
+++ b/server/red-dispatcher.h
@@ -88,6 +88,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 e70c9df..76ac41c 100644
--- a/server/red-worker.c
+++ b/server/red-worker.c
@@ -1159,6 +1159,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;
@@ -1396,6 +1404,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 5f370c0..a46c194 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -3185,6 +3185,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.drm_dma_buf_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 3182382..f141043 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -36,6 +36,7 @@ extern RedsState *reds;
struct QXLState {
QXLInterface *qif;
struct RedDispatcher *dispatcher;
+ pthread_mutex_t scanout_mutex;
SpiceMsgDisplayGlScanoutUnix scanout;
struct AsyncCommand *gl_draw_async;
};
commit ebf461b8e699536a600a15d600dc9a28e865cb90
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date: Tue Feb 9 14:35:02 2016 +0100
Add new spice-gl stubs API
- spice_qxl_gl_scanout() to take the current scanout
- spice_qxl_gl_draw_async() to draw the scanout, is like other Spice async
functions, it takes a cookie and will return in the
QXLInterface.async_complete()
Two new fields are also added to QXLState, in order to save the current
scanout, and the pending async.
A scanout can't be updated if there are pending draw atm. Discarding
outdated draws is left as a future improvement to allow updating the
scanout without waiting for draw async to be done.
Signed-off-by: Marc-André Lureau <marcandre.lureau at gmail.com>
[make QXL function names more coherent - Frediano Ziglio]
Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
diff --git a/server/red-dispatcher.c b/server/red-dispatcher.c
index 374d5a9..009c377 100644
--- a/server/red-dispatcher.c
+++ b/server/red-dispatcher.c
@@ -960,6 +960,41 @@ void spice_qxl_driver_unload(QXLInstance *instance)
red_dispatcher_driver_unload(instance->st->dispatcher);
}
+SPICE_GNUC_VISIBLE
+void spice_qxl_gl_scanout(QXLInstance *qxl,
+ int fd,
+ uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format,
+ int y_0_top)
+{
+ spice_return_if_fail(qxl != NULL);
+ spice_return_if_fail(qxl->st->gl_draw_async == NULL);
+
+ if (qxl->st->scanout.drm_dma_buf_fd != -1) {
+ close(qxl->st->scanout.drm_dma_buf_fd);
+ }
+
+ qxl->st->scanout = (SpiceMsgDisplayGlScanoutUnix) {
+ .flags = y_0_top ? SPICE_GL_SCANOUT_FLAGS_Y0TOP : 0,
+ .drm_dma_buf_fd = fd,
+ .width = width,
+ .height = height,
+ .stride = stride,
+ .drm_fourcc_format = format
+ };
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_gl_draw_async(QXLInstance *qxl,
+ uint32_t x, uint32_t y,
+ uint32_t w, uint32_t h,
+ uint64_t cookie)
+{
+ 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);
+}
+
void red_dispatcher_async_complete(struct RedDispatcher *dispatcher,
AsyncCommand *async_command)
{
diff --git a/server/reds.c b/server/reds.c
index 7ccf0f1..5f370c0 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -3185,6 +3185,7 @@ SPICE_GNUC_VISIBLE int spice_server_add_interface(SpiceServer *s,
qxl = SPICE_CONTAINEROF(sin, QXLInstance, base);
qxl->st = spice_new0(QXLState, 1);
+ qxl->st->scanout.drm_dma_buf_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 8ff4491..3182382 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -36,6 +36,8 @@ extern RedsState *reds;
struct QXLState {
QXLInterface *qif;
struct RedDispatcher *dispatcher;
+ SpiceMsgDisplayGlScanoutUnix scanout;
+ struct AsyncCommand *gl_draw_async;
};
struct TunnelWorker;
diff --git a/server/spice-qxl.h b/server/spice-qxl.h
index 3faa3a4..b8910bf 100644
--- a/server/spice-qxl.h
+++ b/server/spice-qxl.h
@@ -104,6 +104,16 @@ void spice_qxl_driver_unload(QXLInstance *instance);
/* since spice 0.12.6 */
void spice_qxl_set_max_monitors(QXLInstance *instance,
unsigned int max_monitors);
+/* since spice 0.13.1 */
+void spice_qxl_gl_scanout(QXLInstance *instance,
+ int fd,
+ uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format,
+ int y_0_top);
+void spice_qxl_gl_draw_async(QXLInstance *instance,
+ uint32_t x, uint32_t y,
+ uint32_t w, uint32_t h,
+ uint64_t cookie);
typedef struct QXLDrawArea {
uint8_t *buf;
diff --git a/server/spice-server.syms b/server/spice-server.syms
index 4137546..7987d51 100644
--- a/server/spice-server.syms
+++ b/server/spice-server.syms
@@ -167,3 +167,9 @@ SPICE_SERVER_0.12.7 {
global:
spice_server_set_keepalive_timeout;
} SPICE_SERVER_0.12.6;
+
+SPICE_SERVER_0.13.1 {
+global:
+ spice_qxl_gl_scanout;
+ spice_qxl_gl_draw_async;
+} SPICE_SERVER_0.12.7;
commit 9766619dfffaebc82728624e6d0a0c3083ee2906
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date: Tue Feb 9 14:35:01 2016 +0100
red-channel: return number of created pipe items
This is useful in the following patches to count the number of replies
to wait for.
Signed-off-by: Marc-André Lureau <marcandre.lureau at gmail.com>
diff --git a/server/red-channel.c b/server/red-channel.c
index 4bc2faa..f3a1cea 100644
--- a/server/red-channel.c
+++ b/server/red-channel.c
@@ -2245,15 +2245,17 @@ typedef int (*rcc_item_cond_t)(RedChannelClient *rcc, PipeItem *item);
* @creator: a callback to create pipe item (not null)
* @data: the data to pass to the creator
* @pipe_add: a callback to add non-null pipe items (not null)
+ *
+ * Returns: the number of added items
**/
-static void red_channel_pipes_create_batch(RedChannel *channel,
+static int red_channel_pipes_create_batch(RedChannel *channel,
new_pipe_item_t creator, void *data,
rcc_item_t pipe_add)
{
RingItem *link, *next;
RedChannelClient *rcc;
PipeItem *item;
- int num = 0;
+ int num = 0, n = 0;
spice_assert(creator != NULL);
spice_assert(pipe_add != NULL);
@@ -2263,16 +2265,21 @@ static void red_channel_pipes_create_batch(RedChannel *channel,
item = (*creator)(rcc, data, num++);
if (item) {
(*pipe_add)(rcc, item);
+ n++;
}
}
+
+ return n;
}
-void red_channel_pipes_new_add_push(RedChannel *channel,
- new_pipe_item_t creator, void *data)
+int red_channel_pipes_new_add_push(RedChannel *channel,
+ new_pipe_item_t creator, void *data)
{
- red_channel_pipes_create_batch(channel, creator, data,
- red_channel_client_pipe_add);
+ int n = red_channel_pipes_create_batch(channel, creator, data,
+ red_channel_client_pipe_add);
red_channel_push(channel);
+
+ return n;
}
void red_channel_pipes_new_add(RedChannel *channel, new_pipe_item_t creator, void *data)
diff --git a/server/red-channel.h b/server/red-channel.h
index 791bc5b..fbb93b7 100644
--- a/server/red-channel.h
+++ b/server/red-channel.h
@@ -478,7 +478,7 @@ void red_channel_pipe_item_init(RedChannel *channel, PipeItem *item, int type);
// helper to push a new item to all channels
typedef PipeItem *(*new_pipe_item_t)(RedChannelClient *rcc, void *data, int num);
-void red_channel_pipes_new_add_push(RedChannel *channel, new_pipe_item_t creator, void *data);
+int red_channel_pipes_new_add_push(RedChannel *channel, new_pipe_item_t creator, void *data);
void red_channel_pipes_new_add(RedChannel *channel, new_pipe_item_t creator, void *data);
void red_channel_pipes_new_add_tail(RedChannel *channel, new_pipe_item_t creator, void *data);
More information about the Spice-commits
mailing list