[Spice-devel] [RFC v4 24/62] server/red_worker: split Surfaces from RedWorker

Marc-André Lureau marcandre.lureau at gmail.com
Mon May 2 16:52:12 PDT 2011


On Tue, Apr 26, 2011 at 12:54 PM, Alon Levy <alevy at redhat.com> wrote:
> Split the tree (current_list) and the surfaces out from RedWorker.
> This patch is technical, basically a lot of propogation of "Surfaces
> *surfaces" parameter, and otherwise changing s/worker/worker->surfaces/.
>
> Another possible name for Surfaces is RenderingState.

That sounds better. Why did you prefer Surfaces?

> In later patches there will be a multiplicity of surfaces:
> 0        | 1
> n >=1    | n
>
> The first instance is embedded in RedWorker. The later are embdedded
> in the DisplayChannelClient which has not been introduced yet.

ok

> The surfaces backing store needs to be separate for the main Surfaces
> instance and for the rest. For the main it needs to be vram, since
> the guest will read from there after an UPDATE_AREA. For the others
> it will be host memory.
>
> A multiplicity of rendering trees and surfaces makes having a separate
> pipe easy, since we can replace a number of operations in the pipe with
> their equivalent without effecting the other clients. Such a replacement
> may require rendering the operations, so it requires the surfaces to be
> in sync with the tree for that client.
>
> It might be possible to avoid some of this overhead later - in particular,
> possibly having groups of clients associated with the same Surfaces, and
> only create a copy on change. The current implementation is the simplest,
> and it doesn't cost anything extra for a single client.
>
> Many function signatures are changed already to add Surfaces as an
> additional paramater instead of using worker->surfaces, this is in
> preparation for the next patches where Surfaces instances multiply.

Surfaces could reference the worker, that way we can make functions
only take a "Surfaces"


otherwise, ACK, the patch is straightforward.

> ---
>  server/red_worker.c |  536 ++++++++++++++++++++++++++++-----------------------
>  1 files changed, 295 insertions(+), 241 deletions(-)
>
> diff --git a/server/red_worker.c b/server/red_worker.c
> index ebeb4af..275bfca 100644
> --- a/server/red_worker.c
> +++ b/server/red_worker.c
> @@ -562,6 +562,7 @@ typedef struct CommonChannel {
>     uint8_t recv_buf[RECIVE_BUF_SIZE];
>  } CommonChannel;
>
> +typedef struct Surfaces Surfaces;
>
>  struct DisplayChannel {
>     CommonChannel common; // Must be the first thing
> @@ -806,6 +807,24 @@ typedef struct ItemTrace {
>  #define NUM_DRAWABLES 1000
>  #define NUM_CURSORS 100
>
> +struct Surfaces {
> +    Ring current_list;
> +    uint32_t current_size;
> +    uint32_t drawable_count;
> +    uint32_t transparent_count;
> +
> +    uint32_t shadows_count;
> +    uint32_t containers_count;
> +
> +    RedSurface surfaces[NUM_SURFACES];
> +    uint32_t n_surfaces;
> +    SpiceImageSurfaces image_surfaces;
> +
> +#ifdef PIPE_DEBUG
> +    uint32_t last_id;
> +#endif
> +};
> +
>  typedef struct RedWorker {
>     EventListener dev_listener;
>     DisplayChannel *display_channel;
> @@ -823,17 +842,7 @@ typedef struct RedWorker {
>     uint32_t renderers[RED_MAX_RENDERERS];
>     uint32_t renderer;
>
> -    RedSurface surfaces[NUM_SURFACES];
> -    uint32_t n_surfaces;
> -    SpiceImageSurfaces image_surfaces;
> -
> -    Ring current_list;
> -    uint32_t current_size;
> -    uint32_t drawable_count;
> -    uint32_t transparent_count;
> -
> -    uint32_t shadows_count;
> -    uint32_t containers_count;
> +    Surfaces surfaces;
>
>     uint32_t bits_unique;
>
> @@ -880,9 +889,6 @@ typedef struct RedWorker {
>     ZlibData zlib_data;
>     ZlibEncoder *zlib;
>
> -#ifdef PIPE_DEBUG
> -    uint32_t last_id;
> -#endif
>  #ifdef RED_WORKER_STAT
>     stat_info_t add_stat;
>     stat_info_t exclude_stat;
> @@ -911,17 +917,20 @@ typedef struct BitmapData {
>     SpiceRect lossy_rect;
>  } BitmapData;
>
> -static void red_draw_qxl_drawable(RedWorker *worker, Drawable *drawable);
> -static void red_current_flush(RedWorker *worker, int surface_id);
> +static void red_draw_qxl_drawable(RedWorker *worker, Surfaces *surfaces, Drawable *drawable);
> +static void red_current_flush(RedWorker *worker, Surfaces *surfaces, int surface_id);
>  #ifdef DRAW_ALL
>  #define red_update_area(worker, rect, surface_id)
> -#define red_draw_drawable(worker, item)
> +#define red_update_area_surfaces(worker, surfaces, rect, surface_id)
> +#define red_draw_drawable(worker, surfaces, item)
>  #else
> -static void red_draw_drawable(RedWorker *worker, Drawable *item);
> +static void red_draw_drawable(RedWorker *worker, Surfaces *surfaces, Drawable *item);
>  static void red_update_area(RedWorker *worker, const SpiceRect *area, int surface_id);
> +static void red_update_area_surfaces(RedWorker *worker, Surfaces *surfaces,
> +                            const SpiceRect *area, int surface_id);
>  #endif
>  static void red_release_cursor(RedWorker *worker, CursorItem *cursor);
> -static inline void release_drawable(RedWorker *worker, Drawable *item);
> +static inline void release_drawable(RedWorker *worker, Surfaces *surfaces, Drawable *item);
>  static void red_display_release_stream(DisplayChannel *display, StreamAgent *agent);
>  static inline void red_detach_stream(RedWorker *worker, Stream *stream);
>  static void red_stop_stream(RedWorker *worker, Stream *stream);
> @@ -1023,7 +1032,7 @@ static void print_compress_stats(DisplayChannel *display_channel)
>
>  #endif
>
> -static inline int is_primary_surface(RedWorker *worker, uint32_t surface_id)
> +static inline int is_primary_surface(uint32_t surface_id)
>  {
>     if (surface_id == 0) {
>         return TRUE;
> @@ -1031,15 +1040,15 @@ static inline int is_primary_surface(RedWorker *worker, uint32_t surface_id)
>     return FALSE;
>  }
>
> -static inline void __validate_surface(RedWorker *worker, uint32_t surface_id)
> +static inline void __validate_surface(Surfaces *surfaces, uint32_t surface_id)
>  {
> -    PANIC_ON(surface_id >= worker->n_surfaces);
> +    PANIC_ON(surface_id >= surfaces->n_surfaces);
>  }
>
> -static inline void validate_surface(RedWorker *worker, uint32_t surface_id)
> +static inline void validate_surface(Surfaces *surfaces, uint32_t surface_id)
>  {
> -    PANIC_ON(surface_id >= worker->n_surfaces);
> -    PANIC_ON(!worker->surfaces[surface_id].context.canvas);
> +    PANIC_ON(surface_id >= surfaces->n_surfaces);
> +    PANIC_ON(!surfaces->surfaces[surface_id].context.canvas);
>  }
>
>  char *draw_type_to_str(uint8_t type)
> @@ -1159,7 +1168,7 @@ static inline void red_handle_drawable_surfaces_client_synced(RedWorker *worker,
>                 continue;
>             }
>             red_create_surface_item(worker, surface_id);
> -            red_current_flush(worker, surface_id);
> +            red_current_flush(worker, &worker->surfaces, surface_id);
>             red_add_surface_image(worker, surface_id);
>         }
>     }
> @@ -1169,7 +1178,7 @@ static inline void red_handle_drawable_surfaces_client_synced(RedWorker *worker,
>     }
>
>     red_create_surface_item(worker, drawable->surface_id);
> -    red_current_flush(worker, drawable->surface_id);
> +    red_current_flush(worker, &worker->surfaces, drawable->surface_id);
>     red_add_surface_image(worker, drawable->surface_id);
>  }
>
> @@ -1230,7 +1239,7 @@ static inline PipeItem *red_pipe_get_tail(RedWorker *worker)
>     return (PipeItem*)ring_get_tail(&worker->display_channel->common.base.rcc->pipe);
>  }
>
> -static inline void red_destroy_surface(RedWorker *worker, uint32_t surface_id);
> +static inline void red_destroy_surface(RedWorker *worker, Surfaces *surfaces, uint32_t surface_id);
>
>  static inline void red_pipe_remove_drawable(RedWorker *worker, Drawable *drawable)
>  {
> @@ -1266,10 +1275,10 @@ static void release_image_item(ImageItem *item)
>     }
>  }
>
> -static void release_upgrade_item(RedWorker* worker, UpgradeItem *item)
> +static void release_upgrade_item(RedWorker* worker, Surfaces *surfaces, UpgradeItem *item)
>  {
>     if (!--item->refs) {
> -        release_drawable(worker, item->drawable);
> +        release_drawable(worker, surfaces, item->drawable);
>         free(item->rects);
>         free(item);
>     }
> @@ -1337,7 +1346,7 @@ static void drawables_init(RedWorker *worker)
>  }
>
>
> -static void red_reset_stream_trace(RedWorker *worker);
> +static void red_reset_stream_trace(RedWorker *worker, Surfaces *surfaces);
>
>  static SurfaceDestroyItem *get_surface_destroy_item(RedChannel *channel,
>                                                     uint32_t surface_id)
> @@ -1369,14 +1378,15 @@ static inline void red_destroy_surface_item(RedWorker *worker, uint32_t surface_
>     red_channel_client_pipe_add(channel->rcc, &destroy->pipe_item);
>  }
>
> -static inline void red_destroy_surface(RedWorker *worker, uint32_t surface_id)
> +static inline void red_destroy_surface(RedWorker *worker, Surfaces *surfaces,
> +                                       uint32_t surface_id)
>  {
> -    RedSurface *surface = &worker->surfaces[surface_id];
> +    RedSurface *surface = &surfaces->surfaces[surface_id];
>
>     if (!--surface->refs) {
>         // only primary surface streams are supported
>         if (surface_id == 0) {
> -            red_reset_stream_trace(worker);
> +            red_reset_stream_trace(worker, surfaces);
>         }
>         ASSERT(surface->context.canvas);
>
> @@ -1396,12 +1406,12 @@ static inline void red_destroy_surface(RedWorker *worker, uint32_t surface_id)
>     }
>  }
>
> -static inline void set_surface_release_info(RedWorker *worker, uint32_t surface_id, int is_create,
> +static inline void set_surface_release_info(Surfaces *surfaces, uint32_t surface_id, int is_create,
>                                             QXLReleaseInfo *release_info, uint32_t group_id)
>  {
>     RedSurface *surface;
>
> -    surface = &worker->surfaces[surface_id];
> +    surface = &surfaces->surfaces[surface_id];
>
>     if (is_create) {
>         surface->create.info = release_info;
> @@ -1435,7 +1445,8 @@ static void remove_depended_item(DependItem *item)
>     ring_remove(&item->ring_item);
>  }
>
> -static inline void red_dec_surfaces_drawable_dependencies(RedWorker *worker, Drawable *drawable)
> +static inline void red_dec_surfaces_drawable_dependencies(RedWorker *worker,
> +                                      Surfaces *surfaces, Drawable *drawable)
>  {
>     int x;
>     int surface_id;
> @@ -1445,7 +1456,7 @@ static inline void red_dec_surfaces_drawable_dependencies(RedWorker *worker, Dra
>         if (surface_id == -1) {
>             continue;
>         }
> -        red_destroy_surface(worker, surface_id);
> +        red_destroy_surface(worker, surfaces, surface_id);
>     }
>  }
>
> @@ -1462,7 +1473,7 @@ static void remove_drawable_dependencies(RedWorker *worker, Drawable *drawable)
>     }
>  }
>
> -static inline void release_drawable(RedWorker *worker, Drawable *item)
> +static inline void release_drawable(RedWorker *worker, Surfaces *surfaces, Drawable *item)
>  {
>     if (!--item->refs) {
>         ASSERT(!item->stream);
> @@ -1470,8 +1481,8 @@ static inline void release_drawable(RedWorker *worker, Drawable *item)
>         region_destroy(&item->tree_item.base.rgn);
>
>         remove_drawable_dependencies(worker, item);
> -        red_dec_surfaces_drawable_dependencies(worker, item);
> -        red_destroy_surface(worker, item->surface_id);
> +        red_dec_surfaces_drawable_dependencies(worker, surfaces, item);
> +        red_destroy_surface(worker, surfaces, item->surface_id);
>
>         if (item->red_glz_drawable) {
>             item->red_glz_drawable->drawable = NULL;
> @@ -1482,7 +1493,7 @@ static inline void release_drawable(RedWorker *worker, Drawable *item)
>     }
>  }
>
> -static inline void remove_shadow(RedWorker *worker, DrawItem *item)
> +static inline void remove_shadow(Surfaces *surfaces, DrawItem *item)
>  {
>     Shadow *shadow;
>
> @@ -1495,19 +1506,19 @@ static inline void remove_shadow(RedWorker *worker, DrawItem *item)
>     region_destroy(&shadow->base.rgn);
>     region_destroy(&shadow->on_hold);
>     free(shadow);
> -    worker->shadows_count--;
> +    surfaces->shadows_count--;
>  }
>
> -static inline void current_remove_container(RedWorker *worker, Container *container)
> +static inline void current_remove_container(Surfaces *surfaces, Container *container)
>  {
>     ASSERT(ring_is_empty(&container->items));
> -    worker->containers_count--;
> +    surfaces->containers_count--;
>     ring_remove(&container->base.siblings_link);
>     region_destroy(&container->base.rgn);
>     free(container);
>  }
>
> -static inline void container_cleanup(RedWorker *worker, Container *container)
> +static inline void container_cleanup(Surfaces *surfaces, Container *container)
>  {
>     while (container && container->items.next == container->items.prev) {
>         Container *next = container->base.container;
> @@ -1518,7 +1529,7 @@ static inline void container_cleanup(RedWorker *worker, Container *container)
>             ring_add_after(&item->siblings_link, &container->base.siblings_link);
>             item->container = container->base.container;
>         }
> -        current_remove_container(worker, container);
> +        current_remove_container(surfaces, container);
>         container = next;
>     }
>  }
> @@ -1541,12 +1552,12 @@ static inline void red_add_item_trace(RedWorker *worker, Drawable *item)
>     trace->dest_area = item->red_drawable->bbox;
>  }
>
> -static void surface_flush(RedWorker *worker, int surface_id, SpiceRect *rect)
> +static void surface_flush(RedWorker *worker, Surfaces *surfaces, int surface_id, SpiceRect *rect)
>  {
> -    red_update_area(worker, rect, surface_id);
> +    red_update_area_surfaces(worker, surfaces, rect, surface_id);
>  }
>
> -static void red_flush_source_surfaces(RedWorker *worker, Drawable *drawable)
> +static void red_flush_source_surfaces(RedWorker *worker, Surfaces *surfaces, Drawable *drawable)
>  {
>     int x;
>     int surface_id;
> @@ -1555,38 +1566,40 @@ static void red_flush_source_surfaces(RedWorker *worker, Drawable *drawable)
>         surface_id = drawable->surfaces_dest[x];
>         if (surface_id != -1 && drawable->depend_items[x].drawable) {
>             remove_depended_item(&drawable->depend_items[x]);
> -            surface_flush(worker, surface_id, &drawable->red_drawable->surfaces_rects[x]);
> +            surface_flush(worker, surfaces, surface_id,
> +                          &drawable->red_drawable->surfaces_rects[x]);
>         }
>     }
>  }
>
> -static inline void current_remove_drawable(RedWorker *worker, Drawable *item)
> +static inline void current_remove_drawable(RedWorker *worker, Surfaces *surfaces,
> +                                           Drawable *item)
>  {
> -    worker->drawable_count--;
> +    surfaces->drawable_count--;
>
>     if (item->tree_item.effect != QXL_EFFECT_OPAQUE) {
> -        worker->transparent_count--;
> +        surfaces->transparent_count--;
>     }
>     if (item->stream) {
>         red_detach_stream(worker, item->stream);
>     } else {
>         red_add_item_trace(worker, item);
>     }
> -    remove_shadow(worker, &item->tree_item);
> +    remove_shadow(surfaces, &item->tree_item);
>     ring_remove(&item->tree_item.base.siblings_link);
>     ring_remove(&item->list_link);
>     ring_remove(&item->surface_list_link);
> -    release_drawable(worker, item);
> -    worker->current_size--;
> +    release_drawable(worker, surfaces, item);
> +    surfaces->current_size--;
>  }
>
> -static void remove_drawable(RedWorker *worker, Drawable *item)
> +static void remove_drawable(RedWorker *worker, Surfaces *surfaces, Drawable *item)
>  {
>     red_pipe_remove_drawable(worker, item);
> -    current_remove_drawable(worker, item);
> +    current_remove_drawable(worker, surfaces, item);
>  }
>
> -static inline void current_remove(RedWorker *worker, TreeItem *item)
> +static inline void current_remove(RedWorker *worker, Surfaces *surfaces, TreeItem *item)
>  {
>     TreeItem *now = item;
>
> @@ -1596,7 +1609,7 @@ static inline void current_remove(RedWorker *worker, TreeItem *item)
>
>         if (now->type == TREE_ITEM_TYPE_DRAWABLE) {
>             ring_item = now->siblings_link.prev;
> -            remove_drawable(worker, SPICE_CONTAINEROF(now, Drawable, tree_item));
> +            remove_drawable(worker, surfaces, SPICE_CONTAINEROF(now, Drawable, tree_item));
>         } else {
>             Container *container = (Container *)now;
>
> @@ -1607,7 +1620,7 @@ static inline void current_remove(RedWorker *worker, TreeItem *item)
>                 continue;
>             }
>             ring_item = now->siblings_link.prev;
> -            current_remove_container(worker, container);
> +            current_remove_container(surfaces, container);
>         }
>         if (now == item) {
>             return;
> @@ -1659,13 +1672,13 @@ static void current_tree_for_each(RedWorker *worker, Ring *ring, void (*f)(TreeI
>     }
>  }
>
> -static void red_current_clear(RedWorker *worker, int surface_id)
> +static void red_current_clear(RedWorker *worker, Surfaces *surfaces, int surface_id)
>  {
>     RingItem *ring_item;
>
> -    while ((ring_item = ring_get_head(&worker->surfaces[surface_id].current))) {
> +    while ((ring_item = ring_get_head(&surfaces->surfaces[surface_id].current))) {
>         TreeItem *now = SPICE_CONTAINEROF(ring_item, TreeItem, siblings_link);
> -        current_remove(worker, now);
> +        current_remove(worker, surfaces, now);
>     }
>  }
>
> @@ -1923,7 +1936,8 @@ static inline void __exclude_region(RedWorker *worker, Ring *ring, TreeItem *ite
>     stat_add(&worker->__exclude_stat, start_time);
>  }
>
> -static void exclude_region(RedWorker *worker, Ring *ring, RingItem *ring_item, QRegion *rgn,
> +static void exclude_region(RedWorker *worker, Surfaces *surfaces, Ring *ring,
> +                           RingItem *ring_item, QRegion *rgn,
>                            TreeItem **last, Drawable *frame_candidate)
>  {
>  #ifdef RED_WORKER_STAT
> @@ -1952,7 +1966,7 @@ static void exclude_region(RedWorker *worker, Ring *ring, RingItem *ring_item, Q
>                 ASSERT(now->type != TREE_ITEM_TYPE_SHADOW);
>                 ring_item = now->siblings_link.prev;
>                 print_base_item("EXCLUDE_REMOVE", now);
> -                current_remove(worker, now);
> +                current_remove(worker, surfaces, now);
>                 if (last && *last == now) {
>                     *last = (TreeItem *)ring_next(ring, ring_item);
>                 }
> @@ -1985,12 +1999,12 @@ static void exclude_region(RedWorker *worker, Ring *ring, RingItem *ring_item, Q
>     }
>  }
>
> -static inline Container *__new_container(RedWorker *worker, DrawItem *item)
> +static inline Container *__new_container(Surfaces *surfaces, DrawItem *item)
>  {
>     Container *container = spice_new(Container, 1);
> -    worker->containers_count++;
> +    surfaces->containers_count++;
>  #ifdef PIPE_DEBUG
> -    container->base.id = ++worker->last_id;
> +    container->base.id = ++surfaces->last_id;
>  #endif
>     container->base.type = TREE_ITEM_TYPE_CONTAINER;
>     container->base.container = item->base.container;
> @@ -2012,15 +2026,16 @@ static inline int is_opaque_item(TreeItem *item)
>            (IS_DRAW_ITEM(item) && ((DrawItem *)item)->effect == QXL_EFFECT_OPAQUE);
>  }
>
> -static inline void __current_add_drawable(RedWorker *worker, Drawable *drawable, RingItem *pos)
> +static inline void __current_add_drawable(RedWorker *worker, Surfaces *surfaces,
> +                                          Drawable *drawable, RingItem *pos)
>  {
>     RedSurface *surface;
>     uint32_t surface_id = drawable->surface_id;
>
> -    surface = &worker->surfaces[surface_id];
> +    surface = &surfaces->surfaces[surface_id];
>     ring_add_after(&drawable->tree_item.base.siblings_link, pos);
> -    ring_add(&worker->current_list, &drawable->list_link);
> -    worker->drawable_count++;
> +    ring_add(&surfaces->current_list, &drawable->list_link);
> +    surfaces->drawable_count++;
>     ring_add(&surface->current_list, &drawable->surface_list_link);
>     drawable->refs++;
>  }
> @@ -2709,7 +2724,8 @@ static inline int is_drawable_independent_from_surfaces(Drawable *drawable)
>     return TRUE;
>  }
>
> -static inline int red_current_add_equal(RedWorker *worker, DrawItem *item, TreeItem *other)
> +static inline int red_current_add_equal(RedWorker *worker, Surfaces *surfaces,
> +                                        DrawItem *item, TreeItem *other)
>  {
>     DrawItem *other_draw_item;
>     Drawable *drawable;
> @@ -2730,13 +2746,13 @@ static inline int red_current_add_equal(RedWorker *worker, DrawItem *item, TreeI
>     if (item->effect == QXL_EFFECT_OPAQUE) {
>         int add_after = !!other_drawable->stream && is_drawable_independent_from_surfaces(drawable);
>         red_stream_maintenance(worker, drawable, other_drawable);
> -        __current_add_drawable(worker, drawable, &other->siblings_link);
> +        __current_add_drawable(worker, surfaces, drawable, &other->siblings_link);
>         if (add_after) {
>             red_pipe_add_drawable_after(worker, drawable, other_drawable);
>         } else {
>             red_pipe_add_drawable(worker, drawable);
>         }
> -        remove_drawable(worker, other_drawable);
> +        remove_drawable(worker, surfaces, other_drawable);
>         return TRUE;
>     }
>
> @@ -2746,14 +2762,14 @@ static inline int red_current_add_equal(RedWorker *worker, DrawItem *item, TreeI
>             if (!ring_item_is_linked(&other_drawable->pipe_item.link)) {
>                 red_pipe_add_drawable(worker, drawable);
>             }
> -            remove_drawable(worker, other_drawable);
> +            remove_drawable(worker, surfaces, other_drawable);
>             return TRUE;
>         }
>         break;
>     case QXL_EFFECT_OPAQUE_BRUSH:
>         if (is_same_geometry(worker, drawable, other_drawable)) {
> -            __current_add_drawable(worker, drawable, &other->siblings_link);
> -            remove_drawable(worker, other_drawable);
> +            __current_add_drawable(worker, surfaces, drawable, &other->siblings_link);
> +            remove_drawable(worker, surfaces, other_drawable);
>             red_pipe_add_drawable(worker, drawable);
>             return TRUE;
>         }
> @@ -2812,7 +2828,7 @@ static inline void red_use_stream_trace(RedWorker *worker, Drawable *drawable)
>     }
>  }
>
> -static void red_reset_stream_trace(RedWorker *worker)
> +static void red_reset_stream_trace(RedWorker *worker, Surfaces *surfaces)
>  {
>     Ring *ring = &worker->streams;
>     RingItem *item = ring_get_head(ring);
> @@ -2831,7 +2847,8 @@ static void red_reset_stream_trace(RedWorker *worker)
>     memset(worker->items_trace, 0, sizeof(worker->items_trace));
>  }
>
> -static inline int red_current_add(RedWorker *worker, Ring *ring, Drawable *drawable)
> +static inline int red_current_add(RedWorker *worker, Surfaces *surfaces,
> +                                  Ring *ring, Drawable *drawable)
>  {
>     DrawItem *item = &drawable->tree_item;
>  #ifdef RED_WORKER_STAT
> @@ -2843,7 +2860,7 @@ static inline int red_current_add(RedWorker *worker, Ring *ring, Drawable *drawa
>
>     print_base_item("ADD", &item->base);
>     ASSERT(!region_is_empty(&item->base.rgn));
> -    worker->current_size++;
> +    surfaces->current_size++;
>     region_init(&exclude_rgn);
>     now = ring_next(ring, ring);
>
> @@ -2863,8 +2880,8 @@ static inline int red_current_add(RedWorker *worker, Ring *ring, Drawable *drawa
>             continue;
>         } else if (sibling->type != TREE_ITEM_TYPE_SHADOW) {
>             if (!(test_res & REGION_TEST_RIGHT_EXCLUSIVE) &&
> -                                                   !(test_res & REGION_TEST_LEFT_EXCLUSIVE) &&
> -                                                   red_current_add_equal(worker, item, sibling)) {
> +                                       !(test_res & REGION_TEST_LEFT_EXCLUSIVE) &&
> +                                       red_current_add_equal(worker, surfaces, item, sibling)) {
>                 stat_add(&worker->add_stat, start_time);
>                 return FALSE;
>             }
> @@ -2877,7 +2894,8 @@ static inline int red_current_add(RedWorker *worker, Ring *ring, Drawable *drawa
>                 if ((shadow = __find_shadow(sibling))) {
>                     if (exclude_base) {
>                         TreeItem *next = sibling;
> -                        exclude_region(worker, ring, exclude_base, &exclude_rgn, &next, NULL);
> +                        exclude_region(worker, surfaces, ring, exclude_base,
> +                                       &exclude_rgn, &next, NULL);
>                         if (next != sibling) {
>                             now = next ? &next->siblings_link : NULL;
>                             exclude_base = NULL;
> @@ -2887,7 +2905,7 @@ static inline int red_current_add(RedWorker *worker, Ring *ring, Drawable *drawa
>                     region_or(&exclude_rgn, &shadow->on_hold);
>                 }
>                 now = now->prev;
> -                current_remove(worker, sibling);
> +                current_remove(worker, surfaces, sibling);
>                 now = ring_next(ring, now);
>                 if (shadow || skip) {
>                     exclude_base = now;
> @@ -2899,7 +2917,7 @@ static inline int red_current_add(RedWorker *worker, Ring *ring, Drawable *drawa
>                 Container *container;
>
>                 if (exclude_base) {
> -                    exclude_region(worker, ring, exclude_base, &exclude_rgn, NULL, NULL);
> +                    exclude_region(worker, surfaces, ring, exclude_base, &exclude_rgn, NULL, NULL);
>                     region_clear(&exclude_rgn);
>                     exclude_base = NULL;
>                 }
> @@ -2913,7 +2931,7 @@ static inline int red_current_add(RedWorker *worker, Ring *ring, Drawable *drawa
>                 }
>                 ASSERT(IS_DRAW_ITEM(sibling));
>                 if (!((DrawItem *)sibling)->container_root) {
> -                    container = __new_container(worker, (DrawItem *)sibling);
> +                    container = __new_container(surfaces, (DrawItem *)sibling);
>                     if (!container) {
>                         red_printf("create new container failed");
>                         region_destroy(&exclude_rgn);
> @@ -2931,7 +2949,7 @@ static inline int red_current_add(RedWorker *worker, Ring *ring, Drawable *drawa
>     }
>     if (item->effect == QXL_EFFECT_OPAQUE) {
>         region_or(&exclude_rgn, &item->base.rgn);
> -        exclude_region(worker, ring, exclude_base, &exclude_rgn, NULL, drawable);
> +        exclude_region(worker, surfaces, ring, exclude_base, &exclude_rgn, NULL, drawable);
>         red_use_stream_trace(worker, drawable);
>         red_streams_update_clip(worker, drawable);
>     } else {
> @@ -2940,7 +2958,7 @@ static inline int red_current_add(RedWorker *worker, Ring *ring, Drawable *drawa
>         }
>     }
>     region_destroy(&exclude_rgn);
> -    __current_add_drawable(worker, drawable, ring);
> +    __current_add_drawable(worker, surfaces, drawable, ring);
>     stat_add(&worker->add_stat, start_time);
>     return TRUE;
>  }
> @@ -2954,16 +2972,16 @@ static void add_clip_rects(QRegion *rgn, SpiceClipRects *data)
>     }
>  }
>
> -static inline Shadow *__new_shadow(RedWorker *worker, Drawable *item, SpicePoint *delta)
> +static inline Shadow *__new_shadow(Surfaces *surfaces, Drawable *item, SpicePoint *delta)
>  {
>     if (!delta->x && !delta->y) {
>         return NULL;
>     }
>
>     Shadow *shadow = spice_new(Shadow, 1);
> -    worker->shadows_count++;
> +    surfaces->shadows_count++;
>  #ifdef PIPE_DEBUG
> -    shadow->base.id = ++worker->last_id;
> +    shadow->base.id = ++surfaces->last_id;
>  #endif
>     shadow->base.type = TREE_ITEM_TYPE_SHADOW;
>     shadow->base.container = NULL;
> @@ -2976,19 +2994,20 @@ static inline Shadow *__new_shadow(RedWorker *worker, Drawable *item, SpicePoint
>     return shadow;
>  }
>
> -static inline int red_current_add_with_shadow(RedWorker *worker, Ring *ring, Drawable *item, SpicePoint *delta)
> +static inline int red_current_add_with_shadow(RedWorker *worker, Surfaces *surfaces,
> +                                            Ring *ring, Drawable *item, SpicePoint *delta)
>  {
>  #ifdef RED_WORKER_STAT
>     stat_time_t start_time = stat_now();
>  #endif
>
> -    Shadow *shadow = __new_shadow(worker, item, delta);
> +    Shadow *shadow = __new_shadow(surfaces, item, delta);
>     if (!shadow) {
>         stat_add(&worker->add_stat, start_time);
>         return FALSE;
>     }
>     print_base_item("ADDSHADOW", &item->tree_item.base);
> -    worker->current_size++;
> +    surfaces->current_size++;
>     // item and his shadow must initially be placed in the same container.
>     // for now putting them on root.
>
> @@ -2997,11 +3016,11 @@ static inline int red_current_add_with_shadow(RedWorker *worker, Ring *ring, Dra
>         red_detach_streams_behind(worker, &shadow->base.rgn);
>     }
>     ring_add(ring, &shadow->base.siblings_link);
> -    __current_add_drawable(worker, item, ring);
> +    __current_add_drawable(worker, surfaces, item, ring);
>     if (item->tree_item.effect == QXL_EFFECT_OPAQUE) {
>         QRegion exclude_rgn;
>         region_clone(&exclude_rgn, &item->tree_item.base.rgn);
> -        exclude_region(worker, ring, &shadow->base.siblings_link, &exclude_rgn, NULL, NULL);
> +        exclude_region(worker, surfaces, ring, &shadow->base.siblings_link, &exclude_rgn, NULL, NULL);
>         region_destroy(&exclude_rgn);
>         red_streams_update_clip(worker, item);
>     } else {
> @@ -3058,7 +3077,8 @@ static inline void red_update_streamable(RedWorker *worker, Drawable *drawable,
>     drawable->streamable = TRUE;
>  }
>
> -static inline int red_current_add_qxl(RedWorker *worker, Ring *ring, Drawable *drawable,
> +static inline int red_current_add_qxl(RedWorker *worker, Surfaces *surfaces,
> +                                      Ring *ring, Drawable *drawable,
>                                       RedDrawable *red_drawable)
>  {
>     int ret;
> @@ -3071,10 +3091,10 @@ static inline int red_current_add_qxl(RedWorker *worker, Ring *ring, Drawable *d
>  #endif
>         delta.x = red_drawable->u.copy_bits.src_pos.x - red_drawable->bbox.left;
>         delta.y = red_drawable->u.copy_bits.src_pos.y - red_drawable->bbox.top;
> -        ret = red_current_add_with_shadow(worker, ring, drawable, &delta);
> +        ret = red_current_add_with_shadow(worker, surfaces, ring, drawable, &delta);
>     } else {
>         red_update_streamable(worker, drawable, red_drawable);
> -        ret = red_current_add(worker, ring, drawable);
> +        ret = red_current_add(worker, surfaces, ring, drawable);
>     }
>  #ifdef RED_WORKER_STAT
>     if ((++worker->add_count % 100) == 0) {
> @@ -3103,15 +3123,16 @@ static inline int red_current_add_qxl(RedWorker *worker, Ring *ring, Drawable *d
>     return ret;
>  }
>
> -static void red_get_area(RedWorker *worker, int surface_id, const SpiceRect *area, uint8_t *dest,
> +static void red_get_area(RedWorker *worker, Surfaces *surfaces,
> +                         int surface_id, const SpiceRect *area, uint8_t *dest,
>                          int dest_stride, int update)
>  {
>     SpiceCanvas *canvas;
>     RedSurface *surface;
>
> -    surface = &worker->surfaces[surface_id];
> +    surface = &surfaces->surfaces[surface_id];
>     if (update) {
> -        red_update_area(worker, area, surface_id);
> +        red_update_area_surfaces(worker, surfaces, area, surface_id);
>     }
>
>     canvas = surface->context.canvas;
> @@ -3161,7 +3182,8 @@ static int rgb32_data_has_alpha(int width, int height, size_t stride,
>     return has_alpha;
>  }
>
> -static inline int red_handle_self_bitmap(RedWorker *worker, Drawable *drawable)
> +static inline int red_handle_self_bitmap(RedWorker *worker, Surfaces *surfaces,
> +                                         Drawable *drawable)
>  {
>     SpiceImage *image;
>     int32_t width;
> @@ -3176,8 +3198,7 @@ static inline int red_handle_self_bitmap(RedWorker *worker, Drawable *drawable)
>         return TRUE;
>     }
>
> -
> -    surface = &worker->surfaces[drawable->surface_id];
> +    surface = &surfaces->surfaces[drawable->surface_id];
>
>     bpp = SPICE_SURFACE_FMT_DEPTH(surface->context.format) / 8;
>
> @@ -3201,12 +3222,12 @@ static inline int red_handle_self_bitmap(RedWorker *worker, Drawable *drawable)
>     image->u.bitmap.data = spice_chunks_new_linear(dest, height * dest_stride);
>     image->u.bitmap.data->flags |= SPICE_CHUNKS_FLAGS_FREE;
>
> -    red_get_area(worker, drawable->surface_id,
> +    red_get_area(worker, surfaces, drawable->surface_id,
>                  &drawable->red_drawable->self_bitmap_area, dest, dest_stride, TRUE);
>
>     /* For 32bit non-primary surfaces we need to keep any non-zero
>        high bytes as the surface may be used as source to an alpha_blend */
> -    if (!is_primary_surface(worker, drawable->surface_id) &&
> +    if (!is_primary_surface(drawable->surface_id) &&
>         image->u.bitmap.format == SPICE_BITMAP_FMT_32BIT &&
>         rgb32_data_has_alpha(width, height, dest_stride, dest, &all_set)) {
>         if (all_set) {
> @@ -3220,9 +3241,9 @@ static inline int red_handle_self_bitmap(RedWorker *worker, Drawable *drawable)
>     return TRUE;
>  }
>
> -static void free_one_drawable(RedWorker *worker, int force_glz_free)
> +static void free_one_drawable(RedWorker *worker, Surfaces *surfaces, int force_glz_free)
>  {
> -    RingItem *ring_item = ring_get_tail(&worker->current_list);
> +    RingItem *ring_item = ring_get_tail(&surfaces->current_list);
>     Drawable *drawable;
>     Container *container;
>
> @@ -3232,28 +3253,28 @@ static void free_one_drawable(RedWorker *worker, int force_glz_free)
>         ASSERT(worker->display_channel);
>         red_display_free_glz_drawable(worker->display_channel, drawable->red_glz_drawable);
>     }
> -    red_draw_drawable(worker, drawable);
> +    red_draw_drawable(worker, surfaces, drawable);
>     container = drawable->tree_item.base.container;
>
> -    current_remove_drawable(worker, drawable);
> -    container_cleanup(worker, container);
> +    current_remove_drawable(worker, surfaces, drawable);
> +    container_cleanup(surfaces, container);
>  }
>
> -static Drawable *get_drawable(RedWorker *worker, uint8_t effect, RedDrawable *red_drawable,
> +static Drawable *get_drawable(RedWorker *worker, Surfaces *surfaces, uint8_t effect, RedDrawable *red_drawable,
>                               uint32_t group_id) {
>     Drawable *drawable;
>     struct timespec time;
>     int x;
>
>     while (!(drawable = alloc_drawable(worker))) {
> -        free_one_drawable(worker, FALSE);
> +        free_one_drawable(worker, surfaces, FALSE);
>     }
>     memset(drawable, 0, sizeof(Drawable));
>     drawable->refs = 1;
>     clock_gettime(CLOCK_MONOTONIC, &time);
>     drawable->creation_time = timespec_to_red_time(&time);
>  #ifdef PIPE_DEBUG
> -    drawable->tree_item.base.id = ++worker->last_id;
> +    drawable->tree_item.base.id = ++surfaces->last_id;
>  #endif
>     ring_item_init(&drawable->list_link);
>     ring_item_init(&drawable->surface_list_link);
> @@ -3270,35 +3291,36 @@ static Drawable *get_drawable(RedWorker *worker, uint8_t effect, RedDrawable *re
>     drawable->group_id = group_id;
>
>     drawable->surface_id = red_drawable->surface_id;
> -    validate_surface(worker, drawable->surface_id);
> +    validate_surface(surfaces, drawable->surface_id);
>     for (x = 0; x < 3; ++x) {
>         drawable->surfaces_dest[x] = red_drawable->surfaces_dest[x];
>         if (drawable->surfaces_dest[x] != -1) {
> -            validate_surface(worker, drawable->surfaces_dest[x]);
> +            validate_surface(surfaces, drawable->surfaces_dest[x]);
>         }
>     }
>
>     return drawable;
>  }
>
> -static inline int red_handle_depends_on_target_surface(RedWorker *worker, uint32_t surface_id)
> +static inline int red_handle_depends_on_target_surface(RedWorker *worker, Surfaces *surfaces,
> +                                                       uint32_t surface_id)
>  {
>     RedSurface *surface;
>     RingItem *ring_item;
>
> -    surface = &worker->surfaces[surface_id];
> +    surface = &surfaces->surfaces[surface_id];
>
>     while ((ring_item = ring_get_tail(&surface->depend_on_me))) {
>         Drawable *drawable;
>         DependItem *depended_item = SPICE_CONTAINEROF(ring_item, DependItem, ring_item);
>         drawable = depended_item->drawable;
> -        surface_flush(worker, drawable->surface_id, &drawable->red_drawable->bbox);
> +        surface_flush(worker, surfaces, drawable->surface_id, &drawable->red_drawable->bbox);
>     }
>
>     return TRUE;
>  }
>
> -static inline void add_to_surface_dependency(RedWorker *worker, int depend_on_surface_id,
> +static inline void add_to_surface_dependency(Surfaces *surfaces, int depend_on_surface_id,
>                                              DependItem *depend_item, Drawable *drawable)
>  {
>     RedSurface *surface;
> @@ -3308,13 +3330,14 @@ static inline void add_to_surface_dependency(RedWorker *worker, int depend_on_su
>         return;
>     }
>
> -    surface = &worker->surfaces[depend_on_surface_id];
> +    surface = &surfaces->surfaces[depend_on_surface_id];
>
>     depend_item->drawable = drawable;
>     ring_add(&surface->depend_on_me, &depend_item->ring_item);
>  }
>
> -static inline int red_handle_surfaces_dependencies(RedWorker *worker, Drawable *drawable)
> +static inline int red_handle_surfaces_dependencies(RedWorker *worker,
> +                               Surfaces *surfaces, Drawable *drawable)
>  {
>     int x;
>
> @@ -3322,7 +3345,7 @@ static inline int red_handle_surfaces_dependencies(RedWorker *worker, Drawable *
>         // surface self dependency is handled by shadows in "current", or by
>         // handle_self_bitmap
>         if (drawable->surfaces_dest[x] != drawable->surface_id) {
> -            add_to_surface_dependency(worker, drawable->surfaces_dest[x],
> +            add_to_surface_dependency(surfaces, drawable->surfaces_dest[x],
>                                       &drawable->depend_items[x], drawable);
>
>             if (drawable->surfaces_dest[x] == 0) {
> @@ -3337,7 +3360,7 @@ static inline int red_handle_surfaces_dependencies(RedWorker *worker, Drawable *
>     return TRUE;
>  }
>
> -static inline void red_inc_surfaces_drawable_dependencies(RedWorker *worker, Drawable *drawable)
> +static inline void red_inc_surfaces_drawable_dependencies(Surfaces *surfaces, Drawable *drawable)
>  {
>     int x;
>     int surface_id;
> @@ -3348,21 +3371,22 @@ static inline void red_inc_surfaces_drawable_dependencies(RedWorker *worker, Dra
>         if (surface_id == -1) {
>             continue;
>         }
> -        surface = &worker->surfaces[surface_id];
> +        surface = &surfaces->surfaces[surface_id];
>         surface->refs++;
>     }
>  }
>
> -static inline void red_process_drawable(RedWorker *worker, RedDrawable *drawable, uint32_t group_id)
> +static inline void red_process_drawable_surfaces(RedWorker *worker,
> +                    Surfaces *surfaces, RedDrawable *drawable, uint32_t group_id)
>  {
>     int surface_id;
> -    Drawable *item = get_drawable(worker, drawable->effect, drawable, group_id);
> +    Drawable *item = get_drawable(worker, surfaces, drawable->effect, drawable, group_id);
>
>     ASSERT(item);
>
>     surface_id = item->surface_id;
>
> -    worker->surfaces[surface_id].refs++;
> +    surfaces->surfaces[surface_id].refs++;
>
>     region_add(&item->tree_item.base.rgn, &drawable->bbox);
>  #ifdef PIPE_DEBUG
> @@ -3387,42 +3411,49 @@ static inline void red_process_drawable(RedWorker *worker, RedDrawable *drawable
>         However, surface->depend_on_me is affected by a drawable only
>         as long as it is in the current tree (hasn't been rendered yet).
>     */
> -    red_inc_surfaces_drawable_dependencies(worker, item);
> +    red_inc_surfaces_drawable_dependencies(surfaces, item);
>
>     if (region_is_empty(&item->tree_item.base.rgn)) {
> -        release_drawable(worker, item);
> +        release_drawable(worker, surfaces, item);
>         return;
>     }
>
> -    if (!red_handle_self_bitmap(worker, item)) {
> -        release_drawable(worker, item);
> +    if (!red_handle_self_bitmap(worker, surfaces, item)) {
> +        release_drawable(worker, surfaces, item);
>         return;
>     }
>
> -    if (!red_handle_depends_on_target_surface(worker, surface_id)) {
> -        release_drawable(worker, item);
> +    if (!red_handle_depends_on_target_surface(worker, surfaces, surface_id)) {
> +        release_drawable(worker, surfaces, item);
>         return;
>     }
>
> -    if (!red_handle_surfaces_dependencies(worker, item)) {
> -        release_drawable(worker, item);
> +    if (!red_handle_surfaces_dependencies(worker, surfaces, item)) {
> +        release_drawable(worker, surfaces, item);
>         return;
>     }
>
> -    if (red_current_add_qxl(worker, &worker->surfaces[surface_id].current, item,
> +    if (red_current_add_qxl(worker, surfaces,
> +                            &surfaces->surfaces[surface_id].current, item,
>                             drawable)) {
>         if (item->tree_item.effect != QXL_EFFECT_OPAQUE) {
> -            worker->transparent_count++;
> +            surfaces->transparent_count++;
>         }
>         red_pipe_add_drawable(worker, item);
>  #ifdef DRAW_ALL
> -        red_draw_qxl_drawable(worker, item);
> +        red_draw_qxl_drawable(worker, surfaces, item);
>  #endif
>     }
> -    release_drawable(worker, item);
> +    release_drawable(worker, surfaces, item);
>  }
>
> -static inline void red_create_surface(RedWorker *worker, uint32_t surface_id,uint32_t width,
> +static inline void red_process_drawable(RedWorker *worker, RedDrawable *drawable, uint32_t group_id)
> +{
> +    red_process_drawable_surfaces(worker, &worker->surfaces, drawable, group_id);
> +}
> +
> +static inline void red_create_surface(RedWorker *worker, Surfaces *surfaces,
> +                                      uint32_t surface_id, uint32_t width,
>                                       uint32_t height, int32_t stride, uint32_t format,
>                                       void *line_0, int data_is_valid);
>
> @@ -3431,11 +3462,12 @@ static inline void red_process_surface(RedWorker *worker, RedSurfaceCmd *surface
>     int surface_id;
>     RedSurface *red_surface;
>     uint8_t *data;
> +    Surfaces *surfaces = &worker->surfaces;
>
>     surface_id = surface->surface_id;
> -    __validate_surface(worker, surface_id);
> +    __validate_surface(surfaces, surface_id);
>
> -    red_surface = &worker->surfaces[surface_id];
> +    red_surface = &surfaces->surfaces[surface_id];
>
>     switch (surface->type) {
>     case QXL_SURFACE_CMD_CREATE: {
> @@ -3446,22 +3478,22 @@ static inline void red_process_surface(RedWorker *worker, RedSurfaceCmd *surface
>         if (stride < 0) {
>             data -= (int32_t)(stride * (height - 1));
>         }
> -        red_create_surface(worker, surface_id, surface->u.surface_create.width,
> +        red_create_surface(worker, surfaces, surface_id, surface->u.surface_create.width,
>                            height, stride, surface->u.surface_create.format, data,
>                            data_is_valid);
> -        set_surface_release_info(worker, surface_id, 1, surface->release_info, group_id);
> +        set_surface_release_info(&worker->surfaces, surface_id, 1, surface->release_info, group_id);
>         break;
>     }
>     case QXL_SURFACE_CMD_DESTROY:
>         PANIC_ON(!red_surface->context.canvas);
> -        set_surface_release_info(worker, surface_id, 0, surface->release_info, group_id);
> -        red_handle_depends_on_target_surface(worker, surface_id);
> +        set_surface_release_info(surfaces, surface_id, 0, surface->release_info, group_id);
> +        red_handle_depends_on_target_surface(worker, surfaces, surface_id);
>         /* note that red_handle_depends_on_target_surface must be called before red_current_clear.
>            otherwise "current" will hold items that other drawables may depend on, and then
>            red_current_clear will remove them from the pipe. */
> -        red_current_clear(worker, surface_id);
> +        red_current_clear(worker, surfaces, surface_id);
>         red_clear_surface_drawables_from_pipe(worker, surface_id, FALSE);
> -        red_destroy_surface(worker, surface_id);
> +        red_destroy_surface(worker, surfaces, surface_id);
>         break;
>     default:
>             red_error("unknown surface command");
> @@ -3470,24 +3502,24 @@ static inline void red_process_surface(RedWorker *worker, RedSurfaceCmd *surface
>     free(surface);
>  }
>
> -static SpiceCanvas *image_surfaces_get(SpiceImageSurfaces *surfaces,
> +static SpiceCanvas *image_surfaces_get(SpiceImageSurfaces *image_surfaces,
>                                        uint32_t surface_id)
>  {
> -    RedWorker *worker;
> +    Surfaces *surfaces;
>
> -    worker = SPICE_CONTAINEROF(surfaces, RedWorker, image_surfaces);
> -    validate_surface(worker, surface_id);
> +    surfaces = SPICE_CONTAINEROF(image_surfaces, Surfaces, image_surfaces);
> +    validate_surface(surfaces, surface_id);
>
> -    return worker->surfaces[surface_id].context.canvas;
> +    return surfaces->surfaces[surface_id].context.canvas;
>  }
>
> -static void image_surface_init(RedWorker *worker)
> +static void image_surface_init(Surfaces *surfaces)
>  {
>     static SpiceImageSurfacesOps image_surfaces_ops = {
>         image_surfaces_get,
>     };
>
> -    worker->image_surfaces.ops = &image_surfaces_ops;
> +    surfaces->image_surfaces.ops = &image_surfaces_ops;
>  }
>
>  static ImageCacheItem *image_cache_find(ImageCache *cache, uint64_t id)
> @@ -3680,13 +3712,13 @@ static void localize_mask(RedWorker *worker, SpiceQMask *mask, SpiceImage *image
>     }
>  }
>
> -static void red_draw_qxl_drawable(RedWorker *worker, Drawable *drawable)
> +static void red_draw_qxl_drawable(RedWorker *worker, Surfaces *surfaces, Drawable *drawable)
>  {
>     RedSurface *surface;
>     SpiceCanvas *canvas;
>     SpiceClip clip = drawable->red_drawable->clip;
>
> -    surface = &worker->surfaces[drawable->surface_id];
> +    surface = &surfaces->surfaces[drawable->surface_id];
>     canvas = surface->context.canvas;
>
>     image_cache_eaging(&worker->image_cache);
> @@ -3811,7 +3843,7 @@ static void red_draw_qxl_drawable(RedWorker *worker, Drawable *drawable)
>
>  #ifndef DRAW_ALL
>
> -static void red_draw_drawable(RedWorker *worker, Drawable *drawable)
> +static void red_draw_drawable(RedWorker *worker, Surfaces *surfaces, Drawable *drawable)
>  {
>  #ifdef UPDATE_AREA_BY_TREE
>     SpiceCanvas *canvas;
> @@ -3821,8 +3853,8 @@ static void red_draw_drawable(RedWorker *worker, Drawable *drawable)
>     canvas->ops->group_start(canvas,
>                              &drawable->tree_item.base.rgn);
>  #endif
> -    red_flush_source_surfaces(worker, drawable);
> -    red_draw_qxl_drawable(worker, drawable);
> +    red_flush_source_surfaces(worker, surfaces, drawable);
> +    red_draw_qxl_drawable(worker, surfaces, drawable);
>  #ifdef UPDATE_AREA_BY_TREE
>     canvas->ops->group_end(canvas);
>  #endif
> @@ -3832,7 +3864,7 @@ static void validate_area(RedWorker *worker, const SpiceRect *area, uint32_t sur
>  {
>     RedSurface *surface;
>
> -    surface = &worker->surfaces[surface_id];
> +    surface = &worker->surfaces.surfaces[surface_id];
>     if (!surface->context.canvas_draws_on_surface) {
>         SpiceCanvas *canvas = surface->context.canvas;
>         int h;
> @@ -3899,7 +3931,8 @@ static inline void __red_collect_for_update(RedWorker *worker, Ring *ring, RingI
>     }
>  }
>
> -static void red_update_area(RedWorker *worker, const SpiceRect *area, int surface_id)
> +static void red_update_area_surfaces(RedWorker *worker, Surfaces *surfaces,
> +                                     const SpiceRect *area, int surface_id)
>  {
>     RedSurface *surface;
>     Ring *ring;
> @@ -3907,7 +3940,7 @@ static void red_update_area(RedWorker *worker, const SpiceRect *area, int surfac
>     Ring items;
>     QRegion rgn;
>
> -    surface = &worker->surfaces[surface_id];
> +    surface = &surfaces->surfaces[surface_id];
>     ring = &surface->current;
>
>     if (!(ring_item = ring_get_head(ring))) {
> @@ -3930,7 +3963,7 @@ static void red_update_area(RedWorker *worker, const SpiceRect *area, int surfac
>         red_draw_drawable(worker, drawable);
>         container = drawable->tree_item.base.container;
>         current_remove_drawable(worker, drawable);
> -        container_cleanup(worker, container);
> +        container_cleanup(surfaces, container);
>     }
>     validate_area(worker, area, surface_id);
>  }
> @@ -3941,7 +3974,8 @@ static void red_update_area(RedWorker *worker, const SpiceRect *area, int surfac
>     Renders drawables for updating the requested area, but only drawables that are older
>     than 'last' (exclusive).
>  */
> -static void red_update_area_till(RedWorker *worker, const SpiceRect *area, int surface_id,
> +static void red_update_area_till(RedWorker *worker, Surfaces *surfaces,
> +                                 const SpiceRect *area, int surface_id,
>                                  Drawable *last)
>  {
>     // TODO: if we use UPDATE_AREA_BY_TREE, a corresponding red_update_area_till
> @@ -3957,11 +3991,11 @@ static void red_update_area_till(RedWorker *worker, const SpiceRect *area, int s
>     ASSERT(last);
>     ASSERT(ring_item_is_linked(&last->list_link));
>
> -    surface = &worker->surfaces[surface_id];
> +    surface = &surfaces->surfaces[surface_id];
>
>     if (surface_id != last->surface_id) {
>         // find the nearest older drawable from the appropriate surface
> -        ring = &worker->current_list;
> +        ring = &surfaces->current_list;
>         ring_item = &last->list_link;
>         while ((ring_item = ring_next(ring, ring_item))) {
>             now = SPICE_CONTAINEROF(ring_item, Drawable, list_link);
> @@ -3987,7 +4021,7 @@ static void red_update_area_till(RedWorker *worker, const SpiceRect *area, int s
>     region_init(&rgn);
>     region_add(&rgn, area);
>
> -    // find the first older drawable that intersects with the area
> +    // find the first older drawable that intersects with the area
>     do {
>         now = SPICE_CONTAINEROF(ring_item, Drawable, surface_list_link);
>         if (region_intersects(&rgn, &now->tree_item.base.rgn)) {
> @@ -3997,7 +4031,7 @@ static void red_update_area_till(RedWorker *worker, const SpiceRect *area, int s
>     } while ((ring_item = ring_next(ring, ring_item)));
>
>     region_destroy(&rgn);
> -
> +
>     if (!surface_last) {
>         return;
>     }
> @@ -4009,20 +4043,21 @@ static void red_update_area_till(RedWorker *worker, const SpiceRect *area, int s
>         now = SPICE_CONTAINEROF(ring_item, Drawable, surface_list_link);
>         now->refs++;
>         container = now->tree_item.base.container;
> -        current_remove_drawable(worker, now);
> -        container_cleanup(worker, container);
> +        current_remove_drawable(worker, surfaces, now);
> +        container_cleanup(surfaces, container);
>         /* red_draw_drawable may call red_update_area for the surfaces 'now' depends on. Notice,
>            that it is valid to call red_update_area in this case and not red_update_area_till:
>            It is impossible that there was newer item then 'last' in one of the surfaces
>            that red_update_area is called for, Otherwise, 'now' would have already been rendered.
>            See the call for red_handle_depends_on_target_surface in red_process_drawable */
> -        red_draw_drawable(worker, now);
> -        release_drawable(worker, now);
> +        red_draw_drawable(worker, surfaces, now);
> +        release_drawable(worker, surfaces, now);
>     } while (now != surface_last);
>     validate_area(worker, area, surface_id);
>  }
>
> -static void red_update_area(RedWorker *worker, const SpiceRect *area, int surface_id)
> +static void red_update_area_surfaces(RedWorker *worker, Surfaces *surfaces,
> +                            const SpiceRect *area, int surface_id)
>  {
>     RedSurface *surface;
>     Ring *ring;
> @@ -4034,7 +4069,7 @@ static void red_update_area(RedWorker *worker, const SpiceRect *area, int surfac
>     int gn;
>  #endif
>
> -    surface = &worker->surfaces[surface_id];
> +    surface = &surfaces->surfaces[surface_id];
>
>     last = NULL;
>  #ifdef ACYCLIC_SURFACE_DEBUG
> @@ -4066,10 +4101,10 @@ static void red_update_area(RedWorker *worker, const SpiceRect *area, int surfac
>         now = SPICE_CONTAINEROF(ring_item, Drawable, surface_list_link);
>         now->refs++;
>         container = now->tree_item.base.container;
> -        current_remove_drawable(worker, now);
> -        container_cleanup(worker, container);
> -        red_draw_drawable(worker, now);
> -        release_drawable(worker, now);
> +        current_remove_drawable(worker, surfaces, now);
> +        container_cleanup(surfaces, container);
> +        red_draw_drawable(worker, surfaces, now);
> +        release_drawable(worker, surfaces, now);
>  #ifdef ACYCLIC_SURFACE_DEBUG
>         if (gn != surface->current_gn) {
>             red_error("cyclic surface dependencies");
> @@ -4081,6 +4116,11 @@ static void red_update_area(RedWorker *worker, const SpiceRect *area, int surfac
>
>  #endif
>
> +static void red_update_area(RedWorker *worker, const SpiceRect *area, int surface_id)
> +{
> +    red_update_area_surfaces(worker, &worker->surfaces, area, surface_id);
> +}
> +
>  #endif
>
>  static inline void free_cursor_item(RedWorker *worker, CursorItem *item);
> @@ -4289,7 +4329,7 @@ static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size, int *
>
>             red_get_update_cmd(&worker->mem_slots, ext_cmd.group_id,
>                                &update, ext_cmd.cmd.data);
> -            validate_surface(worker, update.surface_id);
> +            validate_surface(&worker->surfaces, update.surface_id);
>             red_update_area(worker, &update.area, update.surface_id);
>             worker->qxl->st->qif->notify_update(worker->qxl, update.update_id);
>             release_info_ext.group_id = ext_cmd.group_id;
> @@ -4348,8 +4388,8 @@ static void red_free_some(RedWorker *worker)
>         n = red_display_free_some_independent_glz_drawables(worker->display_channel);
>     }
>
> -    while (!ring_is_empty(&worker->current_list) && n++ < RED_RELEASE_BUNCH_SIZE) {
> -        free_one_drawable(worker, TRUE);
> +    while (!ring_is_empty(&worker->surfaces.current_list) && n++ < RED_RELEASE_BUNCH_SIZE) {
> +        free_one_drawable(worker, &worker->surfaces, TRUE);
>     }
>
>     if (worker->display_channel && worker->display_channel->glz_dict) {
> @@ -4357,12 +4397,12 @@ static void red_free_some(RedWorker *worker)
>     }
>  }
>
> -static void red_current_flush(RedWorker *worker, int surface_id)
> +static void red_current_flush(RedWorker *worker, Surfaces *surfaces, int surface_id)
>  {
> -    while (!ring_is_empty(&worker->surfaces[surface_id].current_list)) {
> -        free_one_drawable(worker, FALSE);
> +    while (!ring_is_empty(&surfaces->surfaces[surface_id].current_list)) {
> +        free_one_drawable(worker, surfaces, FALSE);
>     }
> -    red_current_clear(worker, surface_id);
> +    red_current_clear(worker, surfaces, surface_id);
>  }
>
>  // adding the pipe item after pos. If pos == NULL, adding to head.
> @@ -4373,7 +4413,7 @@ static ImageItem *red_add_surface_area_image(RedWorker *worker, int surface_id,
>     int stride;
>     int width;
>     int height;
> -    RedSurface *surface = &worker->surfaces[surface_id];
> +    RedSurface *surface = &worker->surfaces.surfaces[surface_id];
>     SpiceCanvas *canvas = surface->context.canvas;
>     int bpp;
>     int all_set;
> @@ -4407,7 +4447,7 @@ static ImageItem *red_add_surface_area_image(RedWorker *worker, int surface_id,
>
>     /* For 32bit non-primary surfaces we need to keep any non-zero
>        high bytes as the surface may be used as source to an alpha_blend */
> -    if (!is_primary_surface(worker, surface_id) &&
> +    if (!is_primary_surface(surface_id) &&
>         item->image_format == SPICE_BITMAP_FMT_32BIT &&
>         rgb32_data_has_alpha(item->width, item->height, item->stride, item->data, &all_set)) {
>         if (all_set) {
> @@ -4433,7 +4473,7 @@ static void red_add_surface_image(RedWorker *worker, int surface_id)
>     SpiceRect area;
>     RedSurface *surface;
>
> -    surface = &worker->surfaces[surface_id];
> +    surface = &worker->surfaces.surfaces[surface_id];
>
>     if (!display_connected(worker) || !surface->context.canvas) {
>         return;
> @@ -5813,9 +5853,9 @@ static FillBitsType fill_bits(RedChannelClient *rcc, SpiceMarshaller *m,
>         RedSurface *surface;
>
>         surface_id = simage->u.surface.surface_id;
> -        validate_surface(worker, surface_id);
> +        validate_surface(&worker->surfaces, surface_id);
>
> -        surface = &worker->surfaces[surface_id];
> +        surface = &worker->surfaces.surfaces[surface_id];
>         image.descriptor.type = SPICE_IMAGE_TYPE_SURFACE;
>         image.descriptor.flags = 0;
>         image.descriptor.width = surface->context.width;
> @@ -5977,8 +6017,8 @@ static int is_surface_area_lossy(DisplayChannel *display_channel, uint32_t surfa
>     QRegion *surface_lossy_region;
>     QRegion lossy_region;
>
> -    validate_surface(display_channel->common.worker, surface_id);
> -    surface = &display_channel->common.worker->surfaces[surface_id];
> +    validate_surface(&display_channel->common.worker->surfaces, surface_id);
> +    surface = &display_channel->common.worker->surfaces.surfaces[surface_id];
>     surface_lossy_region = &display_channel->surface_client_lossy_region[surface_id];
>
>     if (!area) {
> @@ -6298,7 +6338,8 @@ static void red_add_lossless_drawable_dependencies(RedWorker *worker,
>     } else {
>         sync_rendered = FALSE;
>         for (i = 0; i < num_deps; i++) {
> -            red_update_area_till(worker, deps_areas[i], deps_surfaces_ids[i], item);
> +            red_update_area_till(worker, &worker->surfaces, deps_areas[i],
> +                                 deps_surfaces_ids[i], item);
>         }
>     }
>
> @@ -8073,7 +8114,7 @@ static void display_channel_send_item(RedChannelClient *rcc, PipeItem *pipe_item
>     case PIPE_ITEM_TYPE_DRAW: {
>         Drawable *drawable = SPICE_CONTAINEROF(pipe_item, Drawable, pipe_item);
>         marshall_qxl_drawable(rcc, m, drawable);
> -        release_drawable(worker, drawable);
> +        release_drawable(worker, &worker->surfaces, drawable);
>         break;
>     }
>     case PIPE_ITEM_TYPE_INVAL_ONE:
> @@ -8100,7 +8141,7 @@ static void display_channel_send_item(RedChannelClient *rcc, PipeItem *pipe_item
>     }
>     case PIPE_ITEM_TYPE_UPGRADE:
>         red_display_marshall_upgrade(rcc, m, (UpgradeItem *)pipe_item);
> -        release_upgrade_item(worker, (UpgradeItem *)pipe_item);
> +        release_upgrade_item(worker, &worker->surfaces, (UpgradeItem *)pipe_item);
>         break;
>     case PIPE_ITEM_TYPE_VERB:
>         red_marshall_verb(rcc, ((VerbItem*)pipe_item)->verb);
> @@ -8269,8 +8310,8 @@ void red_show_tree(RedWorker *worker)
>     show_tree_data.level = 0;
>     show_tree_data.container = NULL;
>     for (x = 0; x < NUM_SURFACES; ++x) {
> -        if (worker->surfaces[x].context.canvas) {
> -            current_tree_for_each(worker, &worker->surfaces[x].current, __show_tree_call,
> +        if (worker->surfaces.surfaces[x].context.canvas) {
> +            current_tree_for_each(worker, &worker->surfaces.surfaces[x].current, __show_tree_call,
>                                   &show_tree_data);
>         }
>     }
> @@ -8283,6 +8324,12 @@ static void red_disconnect_channel(RedChannel *channel)
>     red_unref_channel(channel);
>  }
>
> +static void init_surfaces(Surfaces *surfaces)
> +{
> +    ring_init(&surfaces->current_list);
> +    image_surface_init(surfaces);
> +}
> +
>  static void red_disconnect_display(RedChannelClient *rcc)
>  {
>     // TODO: MC: right now we assume single channel
> @@ -8391,7 +8438,8 @@ static SpiceCanvas *create_ogl_pixmap_context(RedWorker *worker, uint32_t width,
>  }
>  #endif
>
> -static inline void *create_canvas_for_surface(RedWorker *worker, RedSurface *surface,
> +static inline void *create_canvas_for_surface(RedWorker *worker, Surfaces *surfaces,
> +                                              RedSurface *surface,
>                                               uint32_t renderer, uint32_t width, uint32_t height,
>                                               int32_t stride, uint32_t format, void *line_0)
>  {
> @@ -8402,7 +8450,7 @@ static inline void *create_canvas_for_surface(RedWorker *worker, RedSurface *sur
>         canvas = canvas_create_for_data(width, height, format,
>                                         line_0, stride,
>                                         &worker->image_cache.base,
> -                                        &worker->image_surfaces, NULL, NULL, NULL);
> +                                        &surfaces->image_surfaces, NULL, NULL, NULL);
>         surface->context.top_down = TRUE;
>         surface->context.canvas_draws_on_surface = TRUE;
>         return canvas;
> @@ -8453,7 +8501,7 @@ static inline void __red_create_surface_item(RedWorker *worker, int surface_id,
>         return;
>     }
>
> -    surface = &worker->surfaces[surface_id];
> +    surface = &worker->surfaces.surfaces[surface_id];
>
>     create = get_surface_create_item(&worker->display_channel->common.base,
>             surface_id, surface->context.width, surface->context.height,
> @@ -8466,19 +8514,20 @@ static inline void __red_create_surface_item(RedWorker *worker, int surface_id,
>
>  static inline void red_create_surface_item(RedWorker *worker, int surface_id)
>  {
> -    if (is_primary_surface(worker, surface_id)) {
> +    if (is_primary_surface(surface_id)) {
>         __red_create_surface_item(worker, surface_id, SPICE_SURFACE_FLAGS_PRIMARY);
>     } else {
>         __red_create_surface_item(worker, surface_id, 0);
>     }
>  }
>
> -static inline void red_create_surface(RedWorker *worker, uint32_t surface_id, uint32_t width,
> +static inline void red_create_surface(RedWorker *worker, Surfaces *surfaces,
> +                                      uint32_t surface_id, uint32_t width,
>                                       uint32_t height, int32_t stride, uint32_t format,
>                                       void *line_0, int data_is_valid)
>  {
>     uint32_t i;
> -    RedSurface *surface = &worker->surfaces[surface_id];
> +    RedSurface *surface = &surfaces->surfaces[surface_id];
>     if (stride >= 0) {
>         PANIC("Untested path stride >= 0");
>     }
> @@ -8501,7 +8550,8 @@ static inline void red_create_surface(RedWorker *worker, uint32_t surface_id, ui
>     region_init(&surface->draw_dirty_region);
>     surface->refs = 1;
>     if (worker->renderer != RED_RENDERER_INVALID) {
> -        surface->context.canvas = create_canvas_for_surface(worker, surface, worker->renderer,
> +        surface->context.canvas = create_canvas_for_surface(worker, surfaces,
> +                                                            surface, worker->renderer,
>                                                             width, height, stride,
>                                                             surface->context.format, line_0);
>         if (!surface->context.canvas) {
> @@ -8513,7 +8563,8 @@ static inline void red_create_surface(RedWorker *worker, uint32_t surface_id, ui
>     }
>
>     for (i = 0; i < worker->num_renderers; i++) {
> -        surface->context.canvas = create_canvas_for_surface(worker, surface, worker->renderers[i],
> +        surface->context.canvas = create_canvas_for_surface(worker, surfaces,
> +                                                            surface, worker->renderers[i],
>                                                             width, height, stride,
>                                                             surface->context.format, line_0);
>         if (surface->context.canvas) { //no need canvas check
> @@ -8678,8 +8729,8 @@ static void on_new_display_channel(RedWorker *worker)
>         return;
>     }
>     red_channel_ack_zero_messages_window(&display_channel->common.base);
> -    if (worker->surfaces[0].context.canvas) {
> -        red_current_flush(worker, 0);
> +    if (worker->surfaces.surfaces[0].context.canvas) {
> +        red_current_flush(worker, &worker->surfaces, 0);
>         push_new_primary_surface(worker);
>         red_add_surface_image(worker, 0);
>         if (red_channel_is_connected(&display_channel->common.base)) {
> @@ -9167,18 +9218,20 @@ static void display_channel_release_item(RedChannelClient *rcc, PipeItem *item,
>  {
>     RedChannel *channel = rcc->channel;
>     CommonChannel *common = SPICE_CONTAINEROF(channel, CommonChannel, base);
> +    RedWorker *worker = common->worker;
>
>     ASSERT(item);
>     switch (item->type) {
>     case PIPE_ITEM_TYPE_DRAW:
>     case PIPE_ITEM_TYPE_STREAM_CREATE:
> -        release_drawable(common->worker, SPICE_CONTAINEROF(item, Drawable, pipe_item));
> +        release_drawable(common->worker, &common->worker->surfaces,
> +                         SPICE_CONTAINEROF(item, Drawable, pipe_item));
>         break;
>     case PIPE_ITEM_TYPE_STREAM_CLIP:
>         red_display_release_stream_clip((DisplayChannel *)channel, (StreamClipItem *)item);
>         break;
>     case PIPE_ITEM_TYPE_UPGRADE:
> -        release_upgrade_item(common->worker, (UpgradeItem *)item);
> +        release_upgrade_item(worker, &worker->surfaces, (UpgradeItem *)item);
>         break;
>     case PIPE_ITEM_TYPE_IMAGE:
>         release_image_item((ImageItem *)item);
> @@ -9351,7 +9404,7 @@ static void on_new_cursor_channel(RedWorker *worker)
>     ASSERT(channel);
>     red_channel_ack_zero_messages_window(&channel->common.base);
>     red_channel_push_set_ack(&channel->common.base);
> -    if (worker->surfaces[0].context.canvas && !channel->common.base.migrate) {
> +    if (worker->surfaces.surfaces[0].context.canvas && !channel->common.base.migrate) {
>         red_channel_client_pipe_add_type(worker->cursor_channel->common.base.rcc, PIPE_ITEM_TYPE_CURSOR_INIT);
>     }
>  }
> @@ -9559,10 +9612,10 @@ static inline void handle_dev_update(RedWorker *worker)
>
>     ASSERT(worker->running);
>
> -    validate_surface(worker, surface_id);
> +    validate_surface(&worker->surfaces, surface_id);
>     red_update_area(worker, rect, surface_id);
>
> -    surface = &worker->surfaces[surface_id];
> +    surface = &worker->surfaces.surfaces[surface_id];
>     region_ret_rects(&surface->draw_dirty_region, dirty_rects, num_dirty_rects);
>
>     if (clear_dirty_region) {
> @@ -9600,17 +9653,17 @@ static inline void handle_dev_del_memslot(RedWorker *worker)
>     red_memslot_info_del_slot(&worker->mem_slots, slot_group_id, slot_id);
>  }
>
> -static inline void destroy_surface_wait(RedWorker *worker, int surface_id)
> +static inline void destroy_surface_wait(RedWorker *worker, Surfaces *surfaces, int surface_id)
>  {
> -    if (!worker->surfaces[surface_id].context.canvas) {
> +    if (!surfaces->surfaces[surface_id].context.canvas) {
>         return;
>     }
>
> -    red_handle_depends_on_target_surface(worker, surface_id);
> +    red_handle_depends_on_target_surface(worker, surfaces, surface_id);
>     /* note that red_handle_depends_on_target_surface must be called before red_current_clear.
>        otherwise "current" will hold items that other drawables may depend on, and then
>        red_current_clear will remove them from the pipe. */
> -    red_current_clear(worker, surface_id);
> +    red_current_clear(worker, surfaces, surface_id);
>     red_clear_surface_drawables_from_pipe(worker, surface_id, TRUE);
>     // in case that the pipe didn't contain any item that is dependent on the surface, but
>     // there is one during sending.
> @@ -9631,8 +9684,8 @@ static inline void handle_dev_destroy_surface_wait(RedWorker *worker)
>
>     flush_all_qxl_commands(worker);
>
> -    if (worker->surfaces[0].context.canvas) {
> -        destroy_surface_wait(worker, 0);
> +    if (worker->surfaces.surfaces[0].context.canvas) {
> +        destroy_surface_wait(worker, &worker->surfaces, 0);
>     }
>
>     message = RED_WORKER_MESSAGE_READY;
> @@ -9642,18 +9695,20 @@ static inline void handle_dev_destroy_surface_wait(RedWorker *worker)
>  /* called upon device reset */
>  static inline void handle_dev_destroy_surfaces(RedWorker *worker)
>  {
> +    Surfaces *surfaces = &worker->surfaces;
>     int i;
>     RedWorkerMessage message;
> +
>     red_printf("");
>     flush_all_qxl_commands(worker);
>     //to handle better
>     for (i = 0; i < NUM_SURFACES; ++i) {
> -        if (worker->surfaces[i].context.canvas) {
> -            destroy_surface_wait(worker, i);
> -            if (worker->surfaces[i].context.canvas) {
> -                red_destroy_surface(worker, i);
> +        if (surfaces->surfaces[i].context.canvas) {
> +            destroy_surface_wait(worker, &worker->surfaces, i);
> +            if (surfaces->surfaces[i].context.canvas) {
> +                red_destroy_surface(worker, surfaces, i);
>             }
> -            ASSERT(!worker->surfaces[i].context.canvas);
> +            ASSERT(!surfaces->surfaces[i].context.canvas);
>         }
>     }
>     ASSERT(ring_is_empty(&worker->streams));
> @@ -9703,7 +9758,8 @@ static inline void handle_dev_create_primary_surface(RedWorker *worker)
>         line_0 -= (int32_t)(surface.stride * (surface.height -1));
>     }
>
> -    red_create_surface(worker, 0, surface.width, surface.height, surface.stride, surface.format,
> +    red_create_surface(worker, &worker->surfaces, 0, surface.width,
> +                       surface.height, surface.stride, surface.format,
>                        line_0, surface.flags & QXL_SURF_FLAG_KEEP_DATA);
>
>     if (worker->display_channel) {
> @@ -9727,7 +9783,7 @@ static inline void handle_dev_destroy_primary_surface(RedWorker *worker)
>     receive_data(worker->channel, &surface_id, sizeof(uint32_t));
>
>     PANIC_ON(surface_id != 0);
> -    PANIC_ON(!worker->surfaces[surface_id].context.canvas);
> +    PANIC_ON(!worker->surfaces.surfaces[surface_id].context.canvas);
>
>     if (worker->cursor) {
>         red_release_cursor(worker, worker->cursor);
> @@ -9744,11 +9800,11 @@ static inline void handle_dev_destroy_primary_surface(RedWorker *worker)
>     }
>
>     flush_all_qxl_commands(worker);
> -    destroy_surface_wait(worker, 0);
> -    red_destroy_surface(worker, 0);
> +    destroy_surface_wait(worker, &worker->surfaces, 0);
> +    red_destroy_surface(worker, &worker->surfaces, 0);
>     ASSERT(ring_is_empty(&worker->streams));
>
> -    ASSERT(!worker->surfaces[surface_id].context.canvas);
> +    ASSERT(!worker->surfaces.surfaces[surface_id].context.canvas);
>
>     worker->cursor_visible = TRUE;
>     worker->cursor_position.x = worker->cursor_position.y = 0;
> @@ -9782,7 +9838,7 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
>             red_channel_push(&worker->display_channel->common.base);
>         }
>         if (worker->qxl->st->qif->flush_resources(worker->qxl) == 0) {
> -            red_printf("oom current %u pipe %u", worker->current_size,
> +            red_printf("oom current %u pipe %u", worker->surfaces.current_size,
>                        worker->display_channel ?
>                        display_red_channel->rcc->pipe_size : 0);
>             red_free_some(worker);
> @@ -9864,8 +9920,8 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
>         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);
> +            if (worker->surfaces.surfaces[x].context.canvas) {
> +                red_current_flush(worker, &worker->surfaces, x);
>             }
>         }
>         red_cursor_flush(worker);
> @@ -10056,9 +10112,8 @@ static void red_init(RedWorker *worker, WorkerInitData *init_data)
>     worker->jpeg_state = init_data->jpeg_state;
>     worker->zlib_glz_state = init_data->zlib_glz_state;
>     worker->streaming_video = init_data->streaming_video;
> -    ring_init(&worker->current_list);
> +    init_surfaces(&worker->surfaces);
>     image_cache_init(&worker->image_cache);
> -    image_surface_init(worker);
>     drawables_init(worker);
>     cursor_items_init(worker);
>     red_init_streams(worker);
> @@ -10092,7 +10147,7 @@ static void red_init(RedWorker *worker, WorkerInitData *init_data)
>                           init_data->internal_groupslot_id);
>
>     PANIC_ON(init_data->n_surfaces > NUM_SURFACES);
> -    worker->n_surfaces = init_data->n_surfaces;
> +    worker->surfaces.n_surfaces = init_data->n_surfaces;
>
>     message = RED_WORKER_MESSAGE_READY;
>     write_message(worker->channel, &message);
> @@ -10320,4 +10375,3 @@ static void dump_bitmap(RedWorker *worker, SpiceBitmap *bitmap, uint32_t group_i
>  }
>
>  #endif
> -
> --
> 1.7.4.4
>
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
>



-- 
Marc-André Lureau


More information about the Spice-devel mailing list