[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