[Spice-devel] [PATCH] server: add QXLWorker.flush_surfaces_async for S3/S4 support

Alon Levy alevy at redhat.com
Wed Jul 6 04:39:36 PDT 2011


This does three things:
 flush both command rings
 stop (rendering everything)
 start

Pulled out start and stop to their own functions to do this easily.
The added api is specifically async, i.e. it calls async_complete
when done.
---
 server/red_dispatcher.c |   10 ++++++++
 server/red_worker.c     |   60 ++++++++++++++++++++++++++++++----------------
 server/red_worker.h     |    2 +
 server/spice.h          |    2 +
 4 files changed, 53 insertions(+), 21 deletions(-)

diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index 74c7af2..477dede 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -474,6 +474,14 @@ static void qxl_worker_oom_async(QXLWorker *qxl_worker)
     qxl_worker_oom_helper(qxl_worker, 1);
 }
 
+static void qxl_worker_flush_surfaces_async(QXLWorker *qxl_worker)
+{
+    RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
+    RedWorkerMessage message = RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC;
+
+    write_message(dispatcher->channel, &message);
+}
+
 static void qxl_worker_start(QXLWorker *qxl_worker)
 {
     RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
@@ -651,6 +659,8 @@ RedDispatcher *red_dispatcher_init(QXLInstance *qxl)
     dispatcher->base.destroy_surface_wait_async = qxl_worker_destroy_surface_wait_async;
     dispatcher->base.oom_async = qxl_worker_oom_async;
 
+    dispatcher->base.flush_surfaces_async = qxl_worker_flush_surfaces_async;
+
     qxl->st->qif->get_init_info(qxl, &init_info);
 
     init_data.memslot_id_bits = init_info.memslot_id_bits;
diff --git a/server/red_worker.c b/server/red_worker.c
index 1480218..86a5065 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -9615,11 +9615,41 @@ static inline void handle_dev_destroy_primary_surface(RedWorker *worker)
     red_cursor_reset(worker);
 }
 
+static void handle_dev_stop(RedWorker *worker)
+{
+    int x;
+
+    ASSERT(worker->running);
+    worker->running = FALSE;
+    red_display_clear_glz_drawables(worker->display_channel);
+    for (x = 0; x < NUM_SURFACES; ++x) {
+        if (worker->surfaces[x].context.canvas) {
+            red_current_flush(worker, x);
+        }
+    }
+    red_wait_outgoing_item((RedChannel *)worker->display_channel);
+    red_wait_outgoing_item((RedChannel *)worker->cursor_channel);
+}
+
+static void handle_dev_start(RedWorker *worker)
+{
+    RedChannel *cursor_red_channel = &worker->cursor_channel->common.base;
+    RedChannel *display_red_channel = &worker->display_channel->common.base;
+
+    ASSERT(!worker->running);
+    if (worker->cursor_channel) {
+        cursor_red_channel->migrate = FALSE;
+    }
+    if (worker->display_channel) {
+        display_red_channel->migrate = FALSE;
+    }
+    worker->running = TRUE;
+}
+
 static void handle_dev_input(EventListener *listener, uint32_t events)
 {
     RedWorker *worker = SPICE_CONTAINEROF(listener, RedWorker, dev_listener);
     RedWorkerMessage message;
-    RedChannel *cursor_red_channel = &worker->cursor_channel->common.base;
     RedChannel *display_red_channel = &worker->display_channel->common.base;
     int ring_is_empty;
     int async = 0;
@@ -9637,6 +9667,7 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
     case RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC:
     case RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC:
     case RED_WORKER_MESSAGE_OOM_ASYNC:
+    case RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC:
         async = 1;
         break;
     case RED_WORKER_MESSAGE_UPDATE:
@@ -9715,33 +9746,15 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
         red_disconnect_display((RedChannel *)worker->display_channel);
         break;
     case RED_WORKER_MESSAGE_STOP: {
-        int x;
-
         red_printf("stop");
-        ASSERT(worker->running);
-        worker->running = FALSE;
-        red_display_clear_glz_drawables(worker->display_channel);
-        for (x = 0; x < NUM_SURFACES; ++x) {
-            if (worker->surfaces[x].context.canvas) {
-                red_current_flush(worker, x);
-            }
-        }
-        red_wait_outgoing_item((RedChannel *)worker->display_channel);
-        red_wait_outgoing_item((RedChannel *)worker->cursor_channel);
+        handle_dev_stop(worker);
         message = RED_WORKER_MESSAGE_READY;
         write_message(worker->channel, &message);
         break;
     }
     case RED_WORKER_MESSAGE_START:
         red_printf("start");
-        ASSERT(!worker->running);
-        if (worker->cursor_channel) {
-            cursor_red_channel->migrate = FALSE;
-        }
-        if (worker->display_channel) {
-            display_red_channel->migrate = FALSE;
-        }
-        worker->running = TRUE;
+        handle_dev_start(worker);
         break;
     case RED_WORKER_MESSAGE_DISPLAY_MIGRATE:
         red_printf("migrate");
@@ -9866,6 +9879,11 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
         write_message(worker->channel, &message);
         break;
     }
+    case RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC:
+        flush_all_qxl_commands(worker);
+        handle_dev_stop(worker);
+        handle_dev_start(worker);
+        break;
     default:
         red_error("message error");
     }
diff --git a/server/red_worker.h b/server/red_worker.h
index 9ed7156..aae025b 100644
--- a/server/red_worker.h
+++ b/server/red_worker.h
@@ -78,6 +78,8 @@ enum {
     RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC,
     RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC,
     RED_WORKER_MESSAGE_OOM_ASYNC,
+    /* suspend command */
+    RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC,
 };
 
 typedef uint32_t RedWorkerMessage;
diff --git a/server/spice.h b/server/spice.h
index f0d5685..a715666 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -133,6 +133,8 @@ struct QXLWorker {
                                    QXLDevSurfaceCreate *surface);
     void (*destroy_surface_wait_async)(QXLWorker *worker, uint32_t surface_id);
     void (*oom_async)(QXLWorker *worker);
+    /* suspend support - stop+start+read_cmd_ring */
+    void (*flush_surfaces_async)(QXLWorker *worker);
 };
 
 typedef struct QXLDrawArea {
-- 
1.7.5.4



More information about the Spice-devel mailing list