[Spice-devel] [RFCv5 32/47] server/red_worker: start using RENDER_FOREACH

Alon Levy alevy at redhat.com
Sun May 8 06:11:28 PDT 2011


handle_dev_destroy_surface_wait: all clients render state
handle_dev_destroy_surfaces: clear all surfaces
handle_dev_destroy_primary_surface: clear all primary copies
handle_dev_input RED_WORKER_MESSAGE_STOP: all clients
red_worker_main: call red_handle_streams_timeout for all clients
---
 server/red_worker.c |  119 +++++++++++++++++++++++++++++++++++---------------
 1 files changed, 83 insertions(+), 36 deletions(-)

diff --git a/server/red_worker.c b/server/red_worker.c
index 5295af5..aa77538 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -3629,7 +3629,12 @@ static inline void red_process_drawable_surfaces(RedRender *render, RedDrawable
 
 static inline void red_process_drawable(RedWorker *worker, RedDrawable *drawable, uint32_t group_id)
 {
-    red_process_drawable_surfaces(&worker->render, drawable, group_id);
+    RingItem *link;
+    RedRender *render;
+
+    RENDER_FOREACH(link, render, worker) {
+        red_process_drawable_surfaces(render, drawable, group_id);
+    }
 }
 
 static inline void red_create_surface(RedRender *render, uint32_t surface_id, uint32_t width,
@@ -4353,7 +4358,12 @@ static void red_render_update_area(RedRender *render, const SpiceRect *area, int
 
 static void red_update_area(RedWorker *worker, const SpiceRect *area, int surface_id)
 {
-    red_render_update_area(&worker->render, area, surface_id);
+    RedRender *render;
+    RingItem *link;
+
+    RENDER_FOREACH(link, render, worker) {
+        red_render_update_area(render, area, surface_id);
+    }
 }
 
 #endif
@@ -4632,25 +4642,41 @@ static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size, int *
 
 #define RED_RELEASE_BUNCH_SIZE 64
 
-static void red_free_some(RedWorker *worker)
+static void red_free_some_helper(RedWorker *worker, int *n)
 {
-    int n = 0;
-    DisplayChannelClient *dcc = worker->render.dcc;
-    GlzSharedDictionary *glz_dict = dcc ? dcc->glz_dict : NULL;
+    RingItem *link;
+    RedRender *render;
 
-    if (glz_dict) {
-        // encoding using the dictionary is prevented since the following operations might
-        // change the dictionary
-        pthread_rwlock_wrlock(&glz_dict->encode_lock);
-        n = red_display_free_some_independent_glz_drawables(dcc);
+    RENDER_FOREACH(link, render, worker) {
+        while (!ring_is_empty(&render->current_list) && *n++ < RED_RELEASE_BUNCH_SIZE) {
+            free_one_drawable(render, TRUE);
+        }
     }
+}
 
-    while (!ring_is_empty(&worker->render.current_list) && n++ < RED_RELEASE_BUNCH_SIZE) {
-        free_one_drawable(&worker->render, TRUE);
-    }
+static void red_free_some(RedWorker *worker)
+{
+    int n = 0;
+    RingItem *link;
+    DisplayChannelClient *dcc;
+    GlzSharedDictionary *glz_dict;
 
-    if (glz_dict) {
-        pthread_rwlock_unlock(&glz_dict->encode_lock);
+    if (!worker->display_channel) {
+        red_free_some_helper(worker, &n);
+        return;
+    }
+    DCC_FOREACH(link, dcc, &worker->display_channel->common.base) {
+        glz_dict = dcc->glz_dict;
+        if (glz_dict) {
+            // encoding using the dictionary is prevented since the following operations might
+            // change the dictionary
+            pthread_rwlock_wrlock(&glz_dict->encode_lock);
+            n += red_display_free_some_independent_glz_drawables(dcc);
+        }
+        red_free_some_helper(worker, &n);
+        if (glz_dict) {
+            pthread_rwlock_unlock(&glz_dict->encode_lock);
+        }
     }
 }
 
@@ -10101,15 +10127,19 @@ static inline void handle_dev_destroy_surface_wait(RedWorker *worker)
 {
     RedWorkerMessage message;
     uint32_t surface_id;
+    RingItem *link;
+    RedRender *render;
 
     receive_data(worker->channel, &surface_id, sizeof(uint32_t));
 
     ASSERT(surface_id == 0);
-    
+
     flush_all_qxl_commands(worker);
 
-    if (worker->render.surfaces[0].context.canvas) {
-        destroy_surface_wait(&worker->render, 0);
+    RENDER_FOREACH(link, render, worker) {
+        if (render->surfaces[0].context.canvas) {
+            destroy_surface_wait(render, 0);
+        }
     }
 
     message = RED_WORKER_MESSAGE_READY;
@@ -10117,16 +10147,10 @@ static inline void handle_dev_destroy_surface_wait(RedWorker *worker)
 }
 
 /* called upon device reset */
-
-/* TODO: split me*/
-static inline void handle_dev_destroy_surfaces(RedWorker *worker)
+static inline void red_render_handle_dev_destroy_surfaces(RedRender *render)
 {
-    RedRender *render = &worker->render;
     int i;
-    RedWorkerMessage message;
 
-    red_printf("");
-    flush_all_qxl_commands(worker);
     //to handle better
     for (i = 0; i < NUM_SURFACES; ++i) {
         if (render->surfaces[i].context.canvas) {
@@ -10138,7 +10162,19 @@ static inline void handle_dev_destroy_surfaces(RedWorker *worker)
         }
     }
     ASSERT(ring_is_empty(&render->streams));
+}
+
+static inline void handle_dev_destroy_surfaces(RedWorker *worker)
+{
+    RedWorkerMessage message;
+    RingItem *link;
+    RedRender *render;
 
+    red_printf("");
+    flush_all_qxl_commands(worker);
+    RENDER_FOREACH(link, render, worker) {
+        red_render_handle_dev_destroy_surfaces(render);
+    }
     if (cursor_is_connected(worker)) {
         red_wait_outgoing_items(&worker->cursor_channel->common.base);
         red_channel_pipes_add_type(&worker->cursor_channel->common.base,
@@ -10212,7 +10248,8 @@ static inline void handle_dev_destroy_primary_surface(RedWorker *worker)
 {
     RedWorkerMessage message;
     uint32_t surface_id;
-    RedRender *render = &worker->render;
+    RedRender *render;
+    RingItem *link;
     RedChannel *cursor_red_channel = &worker->cursor_channel->common.base;
 
     receive_data(worker->channel, &surface_id, sizeof(uint32_t));
@@ -10235,11 +10272,13 @@ static inline void handle_dev_destroy_primary_surface(RedWorker *worker)
     }
 
     flush_all_qxl_commands(worker);
-    destroy_surface_wait(render, 0);
-    red_destroy_surface(render, 0);
-    ASSERT(ring_is_empty(&render->streams));
+    RENDER_FOREACH(link, render, worker) {
+        destroy_surface_wait(render, 0);
+        red_destroy_surface(render, 0);
+        ASSERT(ring_is_empty(&render->streams));
+    }
 
-    ASSERT(!render->surfaces[surface_id].context.canvas);
+    ASSERT(!worker->render.surfaces[surface_id].context.canvas);
 
     worker->cursor_visible = TRUE;
     worker->cursor_position.x = worker->cursor_position.y = 0;
@@ -10256,6 +10295,8 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
     RedChannel *cursor_red_channel = &worker->cursor_channel->common.base;
     RedChannel *display_red_channel = &worker->display_channel->common.base;
     int ring_is_empty;
+    RingItem *link;
+    RedRender *render;
 
     read_message(worker->channel, &message);
 
@@ -10352,10 +10393,12 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
         red_printf("stop");
         ASSERT(worker->running);
         worker->running = FALSE;
-        red_display_client_clear_glz_drawables(worker->render.dcc);
-        for (x = 0; x < NUM_SURFACES; ++x) {
-            if (worker->render.surfaces[x].context.canvas) {
-                red_current_flush(&worker->render, x);
+        red_display_clear_glz_drawables(worker->display_channel);
+        RENDER_FOREACH(link, render, worker) {
+            for (x = 0; x < NUM_SURFACES; ++x) {
+                if (render->surfaces[x].context.canvas) {
+                    red_current_flush(render, x);
+                }
             }
         }
         red_cursor_flush(worker);
@@ -10597,6 +10640,8 @@ static void red_display_cc_free_glz_drawables(RedChannelClient *rcc)
 void *red_worker_main(void *arg)
 {
     RedWorker worker;
+    RedRender *render;
+    RingItem *link;
 
     red_printf("begin");
     ASSERT(MAX_PIPE_SIZE > WIDE_CLIENT_ACK_WINDOW &&
@@ -10622,7 +10667,9 @@ void *red_worker_main(void *arg)
 
         worker.epoll_timeout = MIN(red_get_streams_timout(&worker.render), worker.epoll_timeout);
         num_events = epoll_wait(worker.epoll, events, MAX_EPOLL_SOURCES, worker.epoll_timeout);
-        red_handle_streams_timout(&worker.render);
+        RENDER_FOREACH(link, render, &worker) {
+            red_handle_streams_timout(render);
+        }
 
         if (worker.display_channel) {
             /* during migration, in the dest, the display channel can be initialized
-- 
1.7.5.1



More information about the Spice-devel mailing list