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

Alon Levy alevy at redhat.com
Tue Jul 19 01:53:01 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 |   17 +++++++++++++++++
 server/red_worker.c     |   25 +++++++++++++++++++++----
 server/red_worker.h     |    2 ++
 server/spice.h          |    2 ++
 4 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index f0af364..fcdc4f7 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -512,6 +512,19 @@ static void qxl_worker_oom(QXLWorker *qxl_worker)
     }
 }
 
+static void qxl_worker_flush_surfaces_async(QXLWorker *qxl_worker, uint64_t cookie)
+{
+    RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
+    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 qxl_worker_start(QXLWorker *qxl_worker)
 {
     RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
@@ -642,6 +655,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");
     }
@@ -716,6 +731,8 @@ RedDispatcher *red_dispatcher_init(QXLInstance *qxl)
     dispatcher->base.create_primary_surface_async = qxl_worker_create_primary_surface_async;
     dispatcher->base.destroy_surface_wait_async = qxl_worker_destroy_surface_wait_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 e072994..ccd7de1 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -9673,18 +9673,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);
 }
@@ -9725,6 +9738,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;
@@ -9934,6 +9948,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.h b/server/spice.h
index 727507c..da147cd 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -132,6 +132,8 @@ struct QXLWorker {
     void (*create_primary_surface_async)(QXLWorker *worker, uint32_t surface_id,
                                    QXLDevSurfaceCreate *surface, uint64_t cookie);
     void (*destroy_surface_wait_async)(QXLWorker *worker, uint32_t surface_id, uint64_t cookie);
+    /* suspend and resolution change on windows drivers */
+    void (*flush_surfaces_async)(QXLWorker *worker, uint64_t cookie);
 };
 
 typedef struct QXLDrawArea {
-- 
1.7.6



More information about the Spice-devel mailing list