summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlon Levy <alevy@redhat.com>2011-07-07 17:25:19 +0200
committerAlon Levy <alevy@redhat.com>2011-07-21 15:09:29 +0300
commit32d2817ef0c7f1dba4e4c012d3b7580b55e6b3be (patch)
treedb5ec43d530bec3afe5d39b8a4c98a0a06bd32eb
parentc72dc24756e57c283bf3d03e5b795c49022f901e (diff)
downloadspice-32d2817ef0c7f1dba4e4c012d3b7580b55e6b3be.tar.gz
spice-32d2817ef0c7f1dba4e4c012d3b7580b55e6b3be.tar.xz
spice-32d2817ef0c7f1dba4e4c012d3b7580b55e6b3be.zip
server: add QXLWorker.flush_surfaces_async for S3/S4 support
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. (cherry picked from commit 2a4d97fb780cf3ce2d9060751d0bec2fdc9800a9)
-rw-r--r--server/red_dispatcher.c20
-rw-r--r--server/red_worker.c25
-rw-r--r--server/red_worker.h2
-rw-r--r--server/spice-server.syms1
-rw-r--r--server/spice.h2
5 files changed, 46 insertions, 4 deletions
diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index cda88987..1dfb5517 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -538,6 +538,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;
@@ -785,6 +797,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);
@@ -803,6 +821,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 3b0f4618..1630ca2b 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -9867,18 +9867,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);
}
@@ -9919,6 +9932,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;
@@ -10127,6 +10141,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 961da939..e65ab19a 100644
--- a/server/red_worker.h
+++ b/server/red_worker.h
@@ -75,6 +75,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 1d427820..826c562a 100644
--- a/server/spice-server.syms
+++ b/server/spice-server.syms
@@ -79,4 +79,5 @@ 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;
diff --git a/server/spice.h b/server/spice.h
index 4085ebf4..95626c84 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -153,6 +153,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;