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

Alon Levy alevy at redhat.com
Wed Jul 20 01:19:57 PDT 2011


This does the following, all to remove any referenced memory on the pci bars:
    flush_all_qxl_commands(worker);
    flush_all_surfaces(worker);
    red_wait_outgoing_item((RedChannel *)worker->display_channel);
    red_wait_outgoing_item((RedChannel *)worker->cursor_channel);

The added api is specifically async, i.e. it calls async_complete
when done.
---
 server/red_dispatcher.c  |   20 ++++++++++++++++++++
 server/red_worker.c      |   25 +++++++++++++++++++++----
 server/red_worker.h      |    2 ++
 server/spice-server.syms |    1 +
 server/spice.h           |    2 ++
 5 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index 7f3efe8..7792d90 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -541,6 +541,18 @@ static void qxl_worker_start(QXLWorker *qxl_worker)
     red_dispatcher_start((RedDispatcher*)qxl_worker);
 }
 
+static void red_dispatcher_flush_surfaces_async(RedDispatcher *dispatcher, uint64_t cookie)
+{
+    RedWorkerMessage message = red_dispatcher_async_start(dispatcher,
+                                                          RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC);
+
+    if (message == RED_WORKER_MESSAGE_NOP) {
+        return;
+    }
+    write_message(dispatcher->channel, &message);
+    send_data(dispatcher->channel, &cookie, sizeof(cookie));
+}
+
 static void red_dispatcher_stop(RedDispatcher *dispatcher)
 {
     RedWorkerMessage message = RED_WORKER_MESSAGE_STOP;
@@ -788,6 +800,12 @@ void spice_qxl_destroy_surface_async(QXLInstance *instance, uint32_t surface_id,
     red_dispatcher_destroy_surface_wait(instance->st->dispatcher, surface_id, 1, cookie);
 }
 
+SPICE_GNUC_VISIBLE
+void spice_qxl_flush_surfaces_async(QXLInstance *instance, uint64_t cookie)
+{
+    red_dispatcher_flush_surfaces_async(instance->st->dispatcher, cookie);
+}
+
 void red_dispatcher_async_complete(struct RedDispatcher *dispatcher, uint64_t cookie)
 {
     pthread_mutex_lock(&dispatcher->async_lock);
@@ -806,6 +824,8 @@ void red_dispatcher_async_complete(struct RedDispatcher *dispatcher, uint64_t co
         break;
     case RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC:
         break;
+    case RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC:
+        break;
     default:
         red_printf("unexpected message");
     }
diff --git a/server/red_worker.c b/server/red_worker.c
index 9b5d9cd..834c1c5 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -9675,18 +9675,31 @@ static inline void handle_dev_destroy_primary_surface(RedWorker *worker)
     red_cursor_reset(worker);
 }
 
-static void handle_dev_stop(RedWorker *worker)
+static void flush_all_surfaces(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);
         }
     }
+}
+
+static void handle_dev_flush_surfaces(RedWorker *worker)
+{
+    flush_all_qxl_commands(worker);
+    flush_all_surfaces(worker);
+    red_wait_outgoing_item((RedChannel *)worker->display_channel);
+    red_wait_outgoing_item((RedChannel *)worker->cursor_channel);
+}
+
+static void handle_dev_stop(RedWorker *worker)
+{
+    ASSERT(worker->running);
+    worker->running = FALSE;
+    red_display_clear_glz_drawables(worker->display_channel);
+    flush_all_surfaces(worker);
     red_wait_outgoing_item((RedChannel *)worker->display_channel);
     red_wait_outgoing_item((RedChannel *)worker->cursor_channel);
 }
@@ -9727,6 +9740,7 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
     case RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC:
     case RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC:
     case RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC:
+    case RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC:
         call_async_complete = 1;
         receive_data(worker->channel, &cookie, sizeof(cookie));
         break;
@@ -9936,6 +9950,9 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
         }
         break;
     }
+    case RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC:
+        handle_dev_flush_surfaces(worker);
+        break;
     default:
         red_error("message error");
     }
diff --git a/server/red_worker.h b/server/red_worker.h
index 604437b..15d5f82 100644
--- a/server/red_worker.h
+++ b/server/red_worker.h
@@ -77,6 +77,8 @@ enum {
     RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC,
     RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC,
     RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC,
+    /* suspend/windows resolution change command */
+    RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC,
 };
 
 typedef uint32_t RedWorkerMessage;
diff --git a/server/spice-server.syms b/server/spice-server.syms
index 28e6025..b908d85 100644
--- a/server/spice-server.syms
+++ b/server/spice-server.syms
@@ -79,6 +79,7 @@ global:
     spice_qxl_destroy_primary_surface_async;
     spice_qxl_create_primary_surface_async;
     spice_qxl_destroy_surface_async;
+    spice_qxl_flush_surfaces_async;
 } SPICE_SERVER_0.8.1;
 
 SPICE_SERVER_0.10.0 {
diff --git a/server/spice.h b/server/spice.h
index 3bd364d..1191e2c 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -152,6 +152,8 @@ void spice_qxl_destroy_primary_surface_async(QXLInstance *instance, uint32_t sur
 void spice_qxl_create_primary_surface_async(QXLInstance *instance, uint32_t surface_id,
                                 QXLDevSurfaceCreate *surface, uint64_t cookie);
 void spice_qxl_destroy_surface_async(QXLInstance *instance, uint32_t surface_id, uint64_t cookie);
+/* suspend and resolution change on windows drivers */
+void spice_qxl_flush_surfaces_async(QXLInstance *instance, uint64_t cookie);
 
 typedef struct QXLDrawArea {
     uint8_t *buf;
-- 
1.7.6



More information about the Spice-devel mailing list