[Spice-devel] [PATCH RFC 11/12] Handle remote 3d connections
Frediano Ziglio
fziglio at redhat.com
Fri Jul 15 13:49:36 UTC 2016
If a remote connection is detected extract raw data from texture
and pass to normal flow creating a dummy RedDrawable.
Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
---
server/display-channel.c | 52 +++++++++++++++++++++++++++++++++++++++++++++---
server/display-channel.h | 4 ++--
server/red-worker.c | 2 +-
3 files changed, 52 insertions(+), 6 deletions(-)
diff --git a/server/display-channel.c b/server/display-channel.c
index 2154878..967070c 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -19,12 +19,14 @@
#endif
#include "display-channel.h"
+#include "egl.h"
static void drawable_draw(DisplayChannel *display, Drawable *drawable);
static Drawable *display_channel_drawable_try_new(DisplayChannel *display,
int process_commands_generation);
static RedDrawable *get_dummy_drawable(DisplayChannel *display, int w, int h, int y_0_top,
uint8_t *data, uint32_t data_size);
+static RedDrawable *get_dummy_gl_drawable(DisplayChannel *display);
uint32_t display_channel_generate_uid(DisplayChannel *display)
{
@@ -2004,8 +2006,31 @@ void display_channel_update_compression(DisplayChannel *display, DisplayChannelC
spice_info("zlib-over-glz %s", display->enable_zlib_glz_wrap ? "enabled" : "disabled");
}
+static gboolean display_channel_gl_handle_remote(DisplayChannel *display, uint32_t process_commands_generation)
+{
+ RedChannelClient *rcc;
+ GList *link, *next;
+
+ // check if all channel are remote
+ FOREACH_CLIENT(display, link, next, rcc) {
+ if (!reds_stream_is_plain_unix(rcc->stream) ||
+ !red_channel_client_test_remote_cap(rcc, SPICE_DISPLAY_CAP_GL_SCANOUT)) {
+ RedDrawable *red_drawable = get_dummy_gl_drawable(display);
+ if (red_drawable) {
+ // FIXME no flow control, check pipe size!
+ display_channel_process_draw(display, red_drawable, process_commands_generation);
+ red_drawable_unref(red_drawable);
+ }
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
void display_channel_gl_scanout(DisplayChannel *display)
{
+ // don't call display_channel_gl_handle_remote, draw commands always follows
red_channel_pipes_new_add_push(RED_CHANNEL(display), dcc_gl_scanout_item_new, NULL);
}
@@ -2020,13 +2045,15 @@ static void set_gl_draw_async_count(DisplayChannel *display, int num)
}
}
-void display_channel_gl_draw(DisplayChannel *display, SpiceMsgDisplayGlDraw *draw)
+void display_channel_gl_draw(DisplayChannel *display, SpiceMsgDisplayGlDraw *draw, uint32_t process_commands_generation)
{
- int num;
+ int num = 0;
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);
+ if (!display_channel_gl_handle_remote(display, process_commands_generation)) {
+ num = red_channel_pipes_new_add_push(RED_CHANNEL(display), dcc_gl_draw_item_new, draw);
+ }
set_gl_draw_async_count(display, num);
}
@@ -2074,3 +2101,22 @@ static RedDrawable *get_dummy_drawable(DisplayChannel *display, int w, int h, in
return red;
}
+
+static RedDrawable *get_dummy_gl_drawable(DisplayChannel *display)
+{
+ RedDrawable *red_drawable = NULL;
+ QXLInstance* qxl = display->common.qxl;
+
+ RedGlTexture *texture = red_qxl_get_gl_texture(qxl);
+ if (texture != NULL) {
+ size_t size;
+ void *data = get_texture_raw_data(texture, &size);
+ spice_assert(data);
+ if (data) {
+ red_drawable = get_dummy_drawable(display, texture->width, texture->height, texture->flags, data, size);
+ spice_assert(red_drawable);
+ }
+ }
+ red_qxl_put_gl_texture(qxl, texture);
+ return red_drawable;
+}
diff --git a/server/display-channel.h b/server/display-channel.h
index f090d99..7f42dcd 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -280,8 +280,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);
+void display_channel_gl_draw(DisplayChannel *display, SpiceMsgDisplayGlDraw *draw,
+ uint32_t process_commands_generation);
void display_channel_gl_draw_done (DisplayChannel *display);
static inline int validate_surface(DisplayChannel *display, uint32_t surface_id)
diff --git a/server/red-worker.c b/server/red-worker.c
index 9eac0ad..c254b57 100644
--- a/server/red-worker.c
+++ b/server/red-worker.c
@@ -1133,7 +1133,7 @@ void handle_dev_gl_draw_async(void *opaque, void *payload)
RedWorker *worker = opaque;
SpiceMsgDisplayGlDraw *draw = payload;
- display_channel_gl_draw(worker->display_channel, draw);
+ display_channel_gl_draw(worker->display_channel, draw, worker->process_display_generation);
}
static int loadvm_command(RedWorker *worker, QXLCommandExt *ext)
--
2.7.4
More information about the Spice-devel
mailing list