[PATCH 02/10] Add DisplayChannelPrivate struct

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Move all of the DisplayChannel data memembers into a private struct to
encapsulate things better. This necessitated a few new 'public' methods
and a small bit of refactoring to avoid poking into DisplayChannel
internals from too many places. The DisplayChannel and the
DisplayChannelClient are still far too intertwined to completely avoid
accessing private data, so at the moment the private struct is defined
in a display-channel-private.h header and the DisplayChannelClient
implementation includes this header.
---
 server/Makefile.am               |   1 +
 server/dcc-send.c                |  34 ++--
 server/dcc.c                     |  35 ++--
 server/display-channel-private.h |  76 +++++++++
 server/display-channel.c         | 360 +++++++++++++++++++++++----------------
 server/display-channel.h         |  85 +++------
 server/red-worker.c              |  50 ++----
 server/stream.c                  |  73 ++++----
 8 files changed, 395 insertions(+), 319 deletions(-)
 create mode 100644 server/display-channel-private.h

diff --git a/server/Makefile.am b/server/Makefile.am
index d31a9e8..18d6ccf 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -118,6 +118,7 @@ libserver_la_SOURCES =				\
 	red-worker.h				\
 	display-channel.c			\
 	display-channel.h			\
+	display-channel-private.h		\
 	cursor-channel-client.c			\
 	cursor-channel-client.h			\
 	cursor-channel.c			\
diff --git a/server/dcc-send.c b/server/dcc-send.c
index 521e6a2..972ccc6 100644
--- a/server/dcc-send.c
+++ b/server/dcc-send.c
@@ -20,7 +20,7 @@
 #endif
 
 #include "dcc-private.h"
-#include "display-channel.h"
+#include "display-channel-private.h"
 #include "red-channel-client-private.h"
 
 #include <common/marshaller.h>
@@ -94,9 +94,9 @@ static int is_surface_area_lossy(DisplayChannelClient *dcc, uint32_t surface_id,
     QRegion lossy_region;
     DisplayChannel *display = DCC_TO_DC(dcc);
 
-    spice_return_val_if_fail(validate_surface(display, surface_id), FALSE);
+    spice_return_val_if_fail(display_channel_validate_surface(display, surface_id), FALSE);
 
-    surface = &display->surfaces[surface_id];
+    surface = &display->priv->surfaces[surface_id];
     surface_lossy_region = &dcc->priv->surface_client_lossy_region[surface_id];
 
     if (!area) {
@@ -208,13 +208,13 @@ static void red_display_add_image_to_pixmap_cache(RedChannelClient *rcc,
                 io_image->descriptor.flags |= SPICE_IMAGE_FLAGS_CACHE_ME;
                 dcc->priv->send_data.pixmap_cache_items[dcc->priv->send_data.num_pixmap_cache_items++] =
                                                                                image->descriptor.id;
-                stat_inc_counter(reds, display_channel->add_to_cache_counter, 1);
+                stat_inc_counter(reds, display_channel->priv->add_to_cache_counter, 1);
             }
         }
     }
 
     if (!(io_image->descriptor.flags & SPICE_IMAGE_FLAGS_CACHE_ME)) {
-        stat_inc_counter(reds, display_channel->non_cache_counter, 1);
+        stat_inc_counter(reds, display_channel->priv->non_cache_counter, 1);
     }
 }
 
@@ -385,7 +385,7 @@ static FillBitsType fill_bits(DisplayChannelClient *dcc, SpiceMarshaller *m,
             dcc->priv->send_data.pixmap_cache_items[dcc->priv->send_data.num_pixmap_cache_items++] =
                 image.descriptor.id;
             if (can_lossy || !lossy_cache_item) {
-                if (!display->enable_jpeg || lossy_cache_item) {
+                if (!display->priv->enable_jpeg || lossy_cache_item) {
                     image.descriptor.type = SPICE_IMAGE_TYPE_FROM_CACHE;
                 } else {
                     // making sure, in multiple monitor scenario, that lossy items that
@@ -397,7 +397,7 @@ static FillBitsType fill_bits(DisplayChannelClient *dcc, SpiceMarshaller *m,
                                      &bitmap_palette_out, &lzplt_palette_out);
                 spice_assert(bitmap_palette_out == NULL);
                 spice_assert(lzplt_palette_out == NULL);
-                stat_inc_counter(reds, display->cache_hits_counter, 1);
+                stat_inc_counter(reds, display->priv->cache_hits_counter, 1);
                 pthread_mutex_unlock(&dcc->priv->pixmap_cache->lock);
                 return FILL_BITS_TYPE_CACHE;
             } else {
@@ -414,13 +414,13 @@ static FillBitsType fill_bits(DisplayChannelClient *dcc, SpiceMarshaller *m,
         RedSurface *surface;
 
         surface_id = simage->u.surface.surface_id;
-        if (!validate_surface(display, surface_id)) {
+        if (!display_channel_validate_surface(display, surface_id)) {
             spice_warning("Invalid surface in SPICE_IMAGE_TYPE_SURFACE");
             pthread_mutex_unlock(&dcc->priv->pixmap_cache->lock);
             return FILL_BITS_TYPE_SURFACE;
         }
 
-        surface = &display->surfaces[surface_id];
+        surface = &display->priv->surfaces[surface_id];
         image.descriptor.type = SPICE_IMAGE_TYPE_SURFACE;
         image.descriptor.flags = 0;
         image.descriptor.width = surface->context.width;
@@ -1706,7 +1706,7 @@ static int red_marshall_stream_data(RedChannelClient *rcc,
         return FALSE;
     }
 
-    StreamAgent *agent = &dcc->priv->stream_agents[get_stream_id(display, stream)];
+    StreamAgent *agent = &dcc->priv->stream_agents[display_channel_get_stream_id(display, stream)];
     uint64_t time_now = spice_get_monotonic_time_ns();
 
     if (!dcc->priv->use_video_encoder_rate_control) {
@@ -1752,7 +1752,7 @@ static int red_marshall_stream_data(RedChannelClient *rcc,
 
         red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_DATA, NULL);
 
-        stream_data.base.id = get_stream_id(display, stream);
+        stream_data.base.id = display_channel_get_stream_id(display, stream);
         stream_data.base.multi_media_time = frame_mm_time;
         stream_data.data_size = outbuf->size;
 
@@ -1762,7 +1762,7 @@ static int red_marshall_stream_data(RedChannelClient *rcc,
 
         red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_DATA_SIZED, NULL);
 
-        stream_data.base.id = get_stream_id(display, stream);
+        stream_data.base.id = display_channel_get_stream_id(display, stream);
         stream_data.base.multi_media_time = frame_mm_time;
         stream_data.data_size = outbuf->size;
         stream_data.width = copy->src_area.right - copy->src_area.left;
@@ -1862,7 +1862,7 @@ static void display_channel_marshall_migrate_data(RedChannelClient *rcc,
     spice_marshaller_add(base_marshaller,
                          (uint8_t *)&display_data, sizeof(display_data) - sizeof(uint32_t));
     display_channel_marshall_migrate_data_surfaces(dcc, base_marshaller,
-                                                   display_channel->enable_jpeg);
+                                                   display_channel->priv->enable_jpeg);
 }
 
 static void display_channel_marshall_pixmap_sync(RedChannelClient *rcc,
@@ -2148,7 +2148,7 @@ static void marshall_qxl_drawable(RedChannelClient *rcc,
     if (item->stream && red_marshall_stream_data(rcc, m, item)) {
         return;
     }
-    if (display->enable_jpeg)
+    if (display->priv->enable_jpeg)
         marshall_lossy_qxl_drawable(rcc, m, dpi);
     else
         marshall_lossless_qxl_drawable(rcc, m, dpi);
@@ -2171,7 +2171,7 @@ static void marshall_stream_start(RedChannelClient *rcc,
     SpiceClipRects clip_rects;
 
     stream_create.surface_id = 0;
-    stream_create.id = get_stream_id(DCC_TO_DC(dcc), stream);
+    stream_create.id = display_channel_get_stream_id(DCC_TO_DC(dcc), stream);
     stream_create.flags = stream->top_down ? SPICE_STREAM_FLAGS_TOP_DOWN : 0;
     stream_create.codec_type = agent->video_encoder->codec_type;
 
@@ -2207,7 +2207,7 @@ static void marshall_stream_clip(RedChannelClient *rcc,
     red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_CLIP, &item->base);
     SpiceMsgDisplayStreamClip stream_clip;
 
-    stream_clip.id = get_stream_id(DCC_TO_DC(dcc), agent->stream);
+    stream_clip.id = display_channel_get_stream_id(DCC_TO_DC(dcc), agent->stream);
     stream_clip.clip.type = item->clip_type;
     stream_clip.clip.rects = item->rects;
 
@@ -2221,7 +2221,7 @@ static void marshall_stream_end(RedChannelClient *rcc,
     SpiceMsgDisplayStreamDestroy destroy;
 
     red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_DESTROY, NULL);
-    destroy.id = get_stream_id(DCC_TO_DC(dcc), agent->stream);
+    destroy.id = display_channel_get_stream_id(DCC_TO_DC(dcc), agent->stream);
     stream_agent_stop(agent);
     spice_marshall_msg_display_stream_destroy(base_marshaller, &destroy);
 }
diff --git a/server/dcc.c b/server/dcc.c
index 36c9c1d..9fea119 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -20,7 +20,8 @@
 #endif
 
 #include "dcc-private.h"
-#include "display-channel.h"
+#include "display-channel-private.h"
+#include "dcc.h"
 #include "red-channel-client-private.h"
 
 #define DISPLAY_CLIENT_SHORT_TIMEOUT 15000000000ULL //nano
@@ -157,7 +158,7 @@ void dcc_create_surface(DisplayChannelClient *dcc, int surface_id)
         dcc->priv->surface_client_created[surface_id]) {
         return;
     }
-    surface = &display->surfaces[surface_id];
+    surface = &display->priv->surfaces[surface_id];
     create = red_surface_create_item_new(RED_CHANNEL(display),
                                          surface_id, surface->context.width,
                                          surface->context.height,
@@ -174,7 +175,7 @@ RedImageItem *dcc_add_surface_area_image(DisplayChannelClient *dcc,
                                          int can_lossy)
 {
     DisplayChannel *display = DCC_TO_DC(dcc);
-    RedSurface *surface = &display->surfaces[surface_id];
+    RedSurface *surface = &display->priv->surfaces[surface_id];
     SpiceCanvas *canvas = surface->context.canvas;
     RedImageItem *item;
     int stride;
@@ -240,7 +241,7 @@ void dcc_push_surface_image(DisplayChannelClient *dcc, int surface_id)
     }
 
     display = DCC_TO_DC(dcc);
-    surface = &display->surfaces[surface_id];
+    surface = &display->priv->surfaces[surface_id];
     if (!surface->context.canvas) {
         return;
     }
@@ -343,7 +344,7 @@ static void dcc_init_stream_agents(DisplayChannelClient *dcc)
 
     for (i = 0; i < NUM_STREAMS; i++) {
         StreamAgent *agent = &dcc->priv->stream_agents[i];
-        agent->stream = &display->streams_buf[i];
+        agent->stream = &display->priv->streams_buf[i];
         region_init(&agent->vis_region);
         region_init(&agent->clip);
     }
@@ -392,14 +393,14 @@ DisplayChannelClient *dcc_new(DisplayChannel *display,
 
     dcc_init_stream_agents(dcc);
 
-    image_encoders_init(&dcc->priv->encoders, &display->encoder_shared_data);
+    image_encoders_init(&dcc->priv->encoders, &display->priv->encoder_shared_data);
 
     return dcc;
 }
 
 static void dcc_create_all_streams(DisplayChannelClient *dcc)
 {
-    Ring *ring = &DCC_TO_DC(dcc)->streams;
+    Ring *ring = &DCC_TO_DC(dcc)->priv->streams;
     RingItem *item = ring;
 
     while ((item = ring_next(ring, item))) {
@@ -451,7 +452,7 @@ void dcc_start(DisplayChannelClient *dcc)
         return;
 
     red_channel_client_ack_zero_messages_window(RED_CHANNEL_CLIENT(dcc));
-    if (display->surfaces[0].context.canvas) {
+    if (display->priv->surfaces[0].context.canvas) {
         display_channel_current_flush(display, 0);
         red_channel_client_pipe_add_type(rcc, RED_PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE);
         dcc_create_surface(dcc, 0);
@@ -538,7 +539,7 @@ static RedMonitorsConfigItem *red_monitors_config_item_new(RedChannel* channel,
 void dcc_push_monitors_config(DisplayChannelClient *dcc)
 {
     DisplayChannel *dc = DCC_TO_DC(dcc);
-    MonitorsConfig *monitors_config = dc->monitors_config;
+    MonitorsConfig *monitors_config = dc->priv->monitors_config;
     RedMonitorsConfigItem *mci;
 
     if (monitors_config == NULL) {
@@ -552,7 +553,7 @@ void dcc_push_monitors_config(DisplayChannelClient *dcc)
     }
 
     mci = red_monitors_config_item_new(red_channel_client_get_channel(RED_CHANNEL_CLIENT(dcc)),
-                                       monitors_config_ref(dc->monitors_config));
+                                       monitors_config_ref(dc->priv->monitors_config));
     red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &mci->pipe_item);
     red_channel_client_push(RED_CHANNEL_CLIENT(dcc));
 }
@@ -724,14 +725,14 @@ int dcc_compress_image(DisplayChannelClient *dcc,
     stat_start_time_t start_time;
     int success = FALSE;
 
-    stat_start_time_init(&start_time, &display_channel->encoder_shared_data.off_stat);
+    stat_start_time_init(&start_time, &display_channel->priv->encoder_shared_data.off_stat);
 
     image_compression = get_compression_for_bitmap(src, dcc->priv->image_compression, drawable);
     switch (image_compression) {
     case SPICE_IMAGE_COMPRESSION_OFF:
         break;
     case SPICE_IMAGE_COMPRESSION_QUIC:
-        if (can_lossy && display_channel->enable_jpeg &&
+        if (can_lossy && display_channel->priv->enable_jpeg &&
             (src->format != SPICE_BITMAP_FMT_RGBA || !bitmap_has_extra_stride(src))) {
             success = image_encoders_compress_jpeg(&dcc->priv->encoders, dest, src, o_comp_data);
             break;
@@ -742,7 +743,7 @@ int dcc_compress_image(DisplayChannelClient *dcc,
         success = image_encoders_compress_glz(&dcc->priv->encoders, dest, src,
                                               drawable->red_drawable, &drawable->glz_retention,
                                               o_comp_data,
-                                              display_channel->enable_zlib_glz_wrap);
+                                              display_channel->priv->enable_zlib_glz_wrap);
         if (success) {
             break;
         }
@@ -768,7 +769,7 @@ lz_compress:
 
     if (!success) {
         uint64_t image_size = src->stride * src->y;
-        stat_compress_add(&display_channel->encoder_shared_data.off_stat, start_time, image_size, image_size);
+        stat_compress_add(&display_channel->priv->encoder_shared_data.off_stat, start_time, image_size, image_size);
     }
 
     return success;
@@ -1115,15 +1116,15 @@ int dcc_handle_migrate_data(DisplayChannelClient *dcc, uint32_t size, void *mess
     if (migrate_data->low_bandwidth_setting) {
         red_channel_client_ack_set_client_window(RED_CHANNEL_CLIENT(dcc), WIDE_CLIENT_ACK_WINDOW);
         if (dcc->priv->jpeg_state == SPICE_WAN_COMPRESSION_AUTO) {
-            display->enable_jpeg = TRUE;
+            display->priv->enable_jpeg = TRUE;
         }
         if (dcc->priv->zlib_glz_state == SPICE_WAN_COMPRESSION_AUTO) {
-            display->enable_zlib_glz_wrap = TRUE;
+            display->priv->enable_zlib_glz_wrap = TRUE;
         }
     }
 
     surfaces = (uint8_t *)message + migrate_data->surfaces_at_client_ptr;
-    surfaces_restored = display->enable_jpeg ?
+    surfaces_restored = display->priv->enable_jpeg ?
         restore_surfaces_lossy(dcc, (MigrateDisplaySurfacesAtClientLossy *)surfaces) :
         restore_surfaces_lossless(dcc, (MigrateDisplaySurfacesAtClientLossless*)surfaces);
 
diff --git a/server/display-channel-private.h b/server/display-channel-private.h
new file mode 100644
index 0000000..38330da
--- /dev/null
+++ b/server/display-channel-private.h
@@ -0,0 +1,76 @@
+/*
+   Copyright (C) 2009-2015 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef DISPLAY_CHANNEL_PRIVATE_H_
+#define DISPLAY_CHANNEL_PRIVATE_H_
+
+#include "display-channel.h"
+
+struct DisplayChannelPrivate
+{
+    DisplayChannel *pub;
+
+    uint32_t bits_unique;
+
+    MonitorsConfig *monitors_config;
+
+    uint32_t renderer;
+    int enable_jpeg;
+    int enable_zlib_glz_wrap;
+
+    Ring current_list; // of TreeItem
+    uint32_t current_size;
+
+    uint32_t drawable_count;
+    _Drawable drawables[NUM_DRAWABLES];
+    _Drawable *free_drawables;
+
+    int stream_video;
+    GArray *video_codecs;
+    uint32_t stream_count;
+    Stream streams_buf[NUM_STREAMS];
+    Stream *free_streams;
+    Ring streams;
+    ItemTrace items_trace[NUM_TRACE_ITEMS];
+    uint32_t next_item_trace;
+    uint64_t streams_size_total;
+
+    RedSurface surfaces[NUM_SURFACES];
+    uint32_t n_surfaces;
+    SpiceImageSurfaces image_surfaces;
+
+    ImageCache image_cache;
+
+    int gl_draw_async_count;
+
+/* TODO: some day unify this, make it more runtime.. */
+    stat_info_t add_stat;
+    stat_info_t exclude_stat;
+    stat_info_t __exclude_stat;
+#ifdef RED_WORKER_STAT
+    uint32_t add_count;
+    uint32_t add_with_shadow_count;
+#endif
+#ifdef RED_STATISTICS
+    uint64_t *cache_hits_counter;
+    uint64_t *add_to_cache_counter;
+    uint64_t *non_cache_counter;
+#endif
+    ImageEncoderSharedData encoder_shared_data;
+};
+
+#endif /* DISPLAY_CHANNEL_PRIVATE_H_ */
diff --git a/server/display-channel.c b/server/display-channel.c
index 108e69b..34e0099 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -20,7 +20,7 @@
 
 #include <common/sw_canvas.h>
 
-#include "display-channel.h"
+#include "display-channel-private.h"
 
 static void drawable_draw(DisplayChannel *display, Drawable *drawable);
 static Drawable *display_channel_drawable_try_new(DisplayChannel *display,
@@ -30,7 +30,7 @@ uint32_t display_channel_generate_uid(DisplayChannel *display)
 {
     spice_return_val_if_fail(display != NULL, 0);
 
-    return ++display->bits_unique;
+    return ++display->priv->bits_unique;
 }
 
 #define stat_start(stat, var)                                        \
@@ -40,7 +40,7 @@ void display_channel_compress_stats_reset(DisplayChannel *display)
 {
     spice_return_if_fail(display);
 
-    image_encoder_shared_stat_reset(&display->encoder_shared_data);
+    image_encoder_shared_stat_reset(&display->priv->encoder_shared_data);
 }
 
 void display_channel_compress_stats_print(const DisplayChannel *display_channel)
@@ -49,7 +49,7 @@ void display_channel_compress_stats_print(const DisplayChannel *display_channel)
     spice_return_if_fail(display_channel);
 
     spice_info("==> Compression stats for display %u", display_channel->common.base.id);
-    image_encoder_shared_stat_print(&display_channel->encoder_shared_data);
+    image_encoder_shared_stat_print(&display_channel->priv->encoder_shared_data);
 #endif
 }
 
@@ -101,7 +101,7 @@ MonitorsConfig* monitors_config_new(QXLHead *heads, ssize_t nheads, ssize_t max)
 int display_channel_get_streams_timeout(DisplayChannel *display)
 {
     int timeout = INT_MAX;
-    Ring *ring = &display->streams;
+    Ring *ring = &display->priv->streams;
     RingItem *item = ring;
 
     red_time_t now = spice_get_monotonic_time_ns();
@@ -139,20 +139,20 @@ void display_channel_set_stream_video(DisplayChannel *display, int stream_video)
         return;
     }
 
-    display->stream_video = stream_video;
+    display->priv->stream_video = stream_video;
 }
 
 void display_channel_set_video_codecs(DisplayChannel *display, GArray *video_codecs)
 {
     spice_return_if_fail(display);
 
-    g_array_unref(display->video_codecs);
-    display->video_codecs = g_array_ref(video_codecs);
+    g_array_unref(display->priv->video_codecs);
+    display->priv->video_codecs = g_array_ref(video_codecs);
 }
 
 static void stop_streams(DisplayChannel *display)
 {
-    Ring *ring = &display->streams;
+    Ring *ring = &display->priv->streams;
     RingItem *item = ring_get_head(ring);
 
     while (item) {
@@ -165,13 +165,13 @@ static void stop_streams(DisplayChannel *display)
         }
     }
 
-    display->next_item_trace = 0;
-    memset(display->items_trace, 0, sizeof(display->items_trace));
+    display->priv->next_item_trace = 0;
+    memset(display->priv->items_trace, 0, sizeof(display->priv->items_trace));
 }
 
 void display_channel_surface_unref(DisplayChannel *display, uint32_t surface_id)
 {
-    RedSurface *surface = &display->surfaces[surface_id];
+    RedSurface *surface = &display->priv->surfaces[surface_id];
     QXLInstance *qxl = display->common.qxl;
     DisplayChannelClient *dcc;
     GList *link, *next;
@@ -203,6 +203,13 @@ void display_channel_surface_unref(DisplayChannel *display, uint32_t surface_id)
     spice_warn_if_fail(ring_is_empty(&surface->depend_on_me));
 }
 
+/* TODO: perhaps rename to "ready" or "realized" ? */
+bool display_channel_surface_has_canvas(DisplayChannel *display,
+                                        uint32_t surface_id)
+{
+    return display->priv->surfaces[surface_id].context.canvas != NULL;
+}
+
 static void streams_update_visible_region(DisplayChannel *display, Drawable *drawable)
 {
     Ring *ring;
@@ -218,7 +225,7 @@ static void streams_update_visible_region(DisplayChannel *display, Drawable *dra
         return;
     }
 
-    ring = &display->streams;
+    ring = &display->priv->streams;
     item = ring_get_head(ring);
 
     while (item) {
@@ -232,7 +239,7 @@ static void streams_update_visible_region(DisplayChannel *display, Drawable *dra
         }
 
         FOREACH_CLIENT(display, link, next, dcc) {
-            agent = dcc_get_stream_agent(dcc, get_stream_id(display, stream));
+            agent = dcc_get_stream_agent(dcc, display_channel_get_stream_id(display, stream));
 
             if (region_intersects(&agent->vis_region, &drawable->tree_item.base.rgn)) {
                 region_exclude(&agent->vis_region, &drawable->tree_item.base.rgn);
@@ -294,11 +301,11 @@ static void current_add_drawable(DisplayChannel *display,
     RedSurface *surface;
     uint32_t surface_id = drawable->surface_id;
 
-    surface = &display->surfaces[surface_id];
+    surface = &display->priv->surfaces[surface_id];
     ring_add_after(&drawable->tree_item.base.siblings_link, pos);
-    ring_add(&display->current_list, &drawable->list_link);
+    ring_add(&display->priv->current_list, &drawable->list_link);
     ring_add(&surface->current_list, &drawable->surface_list_link);
-    display->current_size++;
+    display->priv->current_size++;
     drawable->refs++;
 }
 
@@ -311,7 +318,7 @@ static void current_remove_drawable(DisplayChannel *display, Drawable *item)
     ring_remove(&item->list_link);
     ring_remove(&item->surface_list_link);
     drawable_unref(item);
-    display->current_size--;
+    display->priv->current_size--;
 }
 
 static void drawable_remove_from_pipes(Drawable *drawable)
@@ -368,7 +375,7 @@ static void current_remove(DisplayChannel *display, TreeItem *item)
 
 static void current_remove_all(DisplayChannel *display, int surface_id)
 {
-    Ring *ring = &display->surfaces[surface_id].current;
+    Ring *ring = &display->priv->surfaces[surface_id].current;
     RingItem *ring_item;
 
     while ((ring_item = ring_get_head(ring))) {
@@ -463,7 +470,7 @@ static void __exclude_region(DisplayChannel *display, Ring *ring, TreeItem *item
                              Ring **top_ring, Drawable *frame_candidate)
 {
     QRegion and_rgn;
-    stat_start(&display->__exclude_stat, start_time);
+    stat_start(&display->priv->__exclude_stat, start_time);
 
     region_clone(&and_rgn, rgn);
     region_and(&and_rgn, &item->rgn);
@@ -525,14 +532,14 @@ static void __exclude_region(DisplayChannel *display, Ring *ring, TreeItem *item
         }
     }
     region_destroy(&and_rgn);
-    stat_add(&display->__exclude_stat, start_time);
+    stat_add(&display->priv->__exclude_stat, start_time);
 }
 
 static void exclude_region(DisplayChannel *display, Ring *ring, RingItem *ring_item,
                            QRegion *rgn, TreeItem **last, Drawable *frame_candidate)
 {
     Ring *top_ring;
-    stat_start(&display->exclude_stat, start_time);
+    stat_start(&display->priv->exclude_stat, start_time);
 
     if (!ring_item) {
         return;
@@ -568,7 +575,7 @@ static void exclude_region(DisplayChannel *display, Ring *ring, RingItem *ring_i
             }
 
             if (region_is_empty(rgn)) {
-                stat_add(&display->exclude_stat, start_time);
+                stat_add(&display->priv->exclude_stat, start_time);
                 return;
             }
         }
@@ -577,7 +584,7 @@ static void exclude_region(DisplayChannel *display, Ring *ring, RingItem *ring_i
         while ((last && *last == (TreeItem *)ring_item) ||
                !(ring_item = ring_next(ring, ring_item))) {
             if (ring == top_ring) {
-                stat_add(&display->exclude_stat, start_time);
+                stat_add(&display->priv->exclude_stat, start_time);
                 return;
             }
             ring_item = &container->base.siblings_link;
@@ -589,9 +596,9 @@ static void exclude_region(DisplayChannel *display, Ring *ring, RingItem *ring_i
 
 static int current_add_with_shadow(DisplayChannel *display, Ring *ring, Drawable *item)
 {
-    stat_start(&display->add_stat, start_time);
+    stat_start(&display->priv->add_stat, start_time);
 #ifdef RED_WORKER_STAT
-    ++display->add_with_shadow_count;
+    ++display->priv->add_with_shadow_count;
 #endif
 
     RedDrawable *red_drawable = item->red_drawable;
@@ -602,7 +609,7 @@ static int current_add_with_shadow(DisplayChannel *display, Ring *ring, Drawable
 
     Shadow *shadow = shadow_new(&item->tree_item, &delta);
     if (!shadow) {
-        stat_add(&display->add_stat, start_time);
+        stat_add(&display->priv->add_stat, start_time);
         return FALSE;
     }
     // item and his shadow must initially be placed in the same container.
@@ -626,7 +633,7 @@ static int current_add_with_shadow(DisplayChannel *display, Ring *ring, Drawable
             stream_detach_behind(display, &item->tree_item.base.rgn, item);
         }
     }
-    stat_add(&display->add_stat, start_time);
+    stat_add(&display->priv->add_stat, start_time);
     return TRUE;
 }
 
@@ -636,7 +643,7 @@ static int current_add(DisplayChannel *display, Ring *ring, Drawable *drawable)
     RingItem *now;
     QRegion exclude_rgn;
     RingItem *exclude_base = NULL;
-    stat_start(&display->add_stat, start_time);
+    stat_start(&display->priv->add_stat, start_time);
 
     spice_assert(!region_is_empty(&item->base.rgn));
     region_init(&exclude_rgn);
@@ -658,7 +665,7 @@ static int current_add(DisplayChannel *display, Ring *ring, Drawable *drawable)
             if (!(test_res & REGION_TEST_RIGHT_EXCLUSIVE) &&
                                                    !(test_res & REGION_TEST_LEFT_EXCLUSIVE) &&
                                                    current_add_equal(display, item, sibling)) {
-                stat_add(&display->add_stat, start_time);
+                stat_add(&display->priv->add_stat, start_time);
                 return FALSE;
             }
 
@@ -744,7 +751,7 @@ static int current_add(DisplayChannel *display, Ring *ring, Drawable *drawable)
         }
     }
     region_destroy(&exclude_rgn);
-    stat_add(&display->add_stat, start_time);
+    stat_add(&display->priv->add_stat, start_time);
     return TRUE;
 }
 
@@ -753,7 +760,7 @@ static bool drawable_can_stream(DisplayChannel *display, Drawable *drawable)
     RedDrawable *red_drawable = drawable->red_drawable;
     SpiceImage *image;
 
-    if (display->stream_video == SPICE_STREAM_VIDEO_OFF) {
+    if (display->priv->stream_video == SPICE_STREAM_VIDEO_OFF) {
         return FALSE;
     }
 
@@ -773,7 +780,7 @@ static bool drawable_can_stream(DisplayChannel *display, Drawable *drawable)
         return FALSE;
     }
 
-    if (display->stream_video == SPICE_STREAM_VIDEO_FILTER) {
+    if (display->priv->stream_video == SPICE_STREAM_VIDEO_FILTER) {
         SpiceRect* rect;
         int size;
 
@@ -790,26 +797,26 @@ static bool drawable_can_stream(DisplayChannel *display, Drawable *drawable)
 #ifdef RED_WORKER_STAT
 static void display_channel_print_stats(DisplayChannel *display)
 {
-    stat_time_t total = display->add_stat.total;
+    stat_time_t total = display->priv->add_stat.total;
     spice_info("add with shadow count %u",
-               display->add_with_shadow_count);
-    display->add_with_shadow_count = 0;
+               display->priv->add_with_shadow_count);
+    display->priv->add_with_shadow_count = 0;
     spice_info("add[%u] %f exclude[%u] %f __exclude[%u] %f",
-               display->add_stat.count,
+               display->priv->add_stat.count,
                stat_cpu_time_to_sec(total),
-               display->exclude_stat.count,
-               stat_cpu_time_to_sec(display->exclude_stat.total),
-               display->__exclude_stat.count,
-               stat_cpu_time_to_sec(display->__exclude_stat.total));
+               display->priv->exclude_stat.count,
+               stat_cpu_time_to_sec(display->priv->exclude_stat.total),
+               display->priv->__exclude_stat.count,
+               stat_cpu_time_to_sec(display->priv->__exclude_stat.total));
     spice_info("add %f%% exclude %f%% exclude2 %f%% __exclude %f%%",
-               (double)(total - display->exclude_stat.total) / total * 100,
-               (double)(display->exclude_stat.total) / total * 100,
-               (double)(display->exclude_stat.total -
-                        display->__exclude_stat.total) / display->exclude_stat.total * 100,
-               (double)(display->__exclude_stat.total) / display->exclude_stat.total * 100);
-    stat_reset(&display->add_stat);
-    stat_reset(&display->exclude_stat);
-    stat_reset(&display->__exclude_stat);
+               (double)(total - display->priv->exclude_stat.total) / total * 100,
+               (double)(display->priv->exclude_stat.total) / total * 100,
+               (double)(display->priv->exclude_stat.total -
+                        display->priv->__exclude_stat.total) / display->priv->exclude_stat.total * 100,
+               (double)(display->priv->__exclude_stat.total) / display->priv->exclude_stat.total * 100);
+    stat_reset(&display->priv->add_stat);
+    stat_reset(&display->priv->exclude_stat);
+    stat_reset(&display->priv->__exclude_stat);
 }
 #endif
 
@@ -824,7 +831,7 @@ static void drawable_ref_surface_deps(DisplayChannel *display, Drawable *drawabl
         if (surface_id == -1) {
             continue;
         }
-        surface = &display->surfaces[surface_id];
+        surface = &display->priv->surfaces[surface_id];
         surface->refs++;
     }
 }
@@ -833,7 +840,7 @@ static void surface_read_bits(DisplayChannel *display, int surface_id,
                               const SpiceRect *area, uint8_t *dest, int dest_stride)
 {
     SpiceCanvas *canvas;
-    RedSurface *surface = &display->surfaces[surface_id];
+    RedSurface *surface = &display->priv->surfaces[surface_id];
 
     canvas = surface->context.canvas;
     canvas->ops->read_bits(canvas, dest, dest_stride, area);
@@ -851,7 +858,7 @@ static void handle_self_bitmap(DisplayChannel *display, Drawable *drawable)
     int bpp;
     int all_set;
 
-    surface = &display->surfaces[drawable->surface_id];
+    surface = &display->priv->surfaces[drawable->surface_id];
 
     bpp = SPICE_SURFACE_FMT_DEPTH(surface->context.format) / 8;
     width = red_drawable->self_bitmap_area.right - red_drawable->self_bitmap_area.left;
@@ -903,7 +910,7 @@ static void surface_add_reverse_dependency(DisplayChannel *display, int surface_
         return;
     }
 
-    surface = &display->surfaces[surface_id];
+    surface = &display->priv->surfaces[surface_id];
 
     depend_item->drawable = drawable;
     ring_add(&surface->depend_on_me, &depend_item->ring_item);
@@ -937,7 +944,7 @@ static void draw_depend_on_me(DisplayChannel *display, uint32_t surface_id)
     RedSurface *surface;
     RingItem *ring_item;
 
-    surface = &display->surfaces[surface_id];
+    surface = &display->priv->surfaces[surface_id];
 
     while ((ring_item = ring_get_tail(&surface->depend_on_me))) {
         Drawable *drawable;
@@ -955,10 +962,10 @@ static int validate_drawable_bbox(DisplayChannel *display, RedDrawable *drawable
         /* surface_id must be validated before calling into
          * validate_drawable_bbox
          */
-        if (!validate_surface(display, drawable->surface_id)) {
+        if (!display_channel_validate_surface(display, drawable->surface_id)) {
             return FALSE;
         }
-        context = &display->surfaces[surface_id].context;
+        context = &display->priv->surfaces[surface_id].context;
 
         if (drawable->bbox.top < 0)
                 return FALSE;
@@ -998,7 +1005,7 @@ static Drawable *display_channel_get_drawable(DisplayChannel *display, uint8_t e
     }
     for (x = 0; x < 3; ++x) {
         if (red_drawable->surface_deps[x] != -1
-            && !validate_surface(display, red_drawable->surface_deps[x])) {
+            && !display_channel_validate_surface(display, red_drawable->surface_deps[x])) {
             return NULL;
         }
     }
@@ -1012,7 +1019,7 @@ static Drawable *display_channel_get_drawable(DisplayChannel *display, uint8_t e
     drawable->red_drawable = red_drawable_ref(red_drawable);
 
     drawable->surface_id = red_drawable->surface_id;
-    display->surfaces[drawable->surface_id].refs++;
+    display->priv->surfaces[drawable->surface_id].refs++;
 
     memcpy(drawable->surface_deps, red_drawable->surface_deps, sizeof(drawable->surface_deps));
     /*
@@ -1062,7 +1069,7 @@ static void display_channel_add_drawable(DisplayChannel *display, Drawable *draw
         return;
     }
 
-    Ring *ring = &display->surfaces[surface_id].current;
+    Ring *ring = &display->priv->surfaces[surface_id].current;
     int add_to_pipe;
     if (has_shadow(red_drawable)) {
         add_to_pipe = current_add_with_shadow(display, ring, drawable);
@@ -1075,7 +1082,7 @@ static void display_channel_add_drawable(DisplayChannel *display, Drawable *draw
         pipes_add_drawable(display, drawable);
 
 #ifdef RED_WORKER_STAT
-    if ((++display->add_count % 100) == 0)
+    if ((++display->priv->add_count % 100) == 0)
         display_channel_print_stats(display);
 #endif
 }
@@ -1139,7 +1146,7 @@ void display_channel_flush_all_surfaces(DisplayChannel *display)
     int x;
 
     for (x = 0; x < NUM_SURFACES; ++x) {
-        if (display->surfaces[x].context.canvas) {
+        if (display->priv->surfaces[x].context.canvas) {
             display_channel_current_flush(display, x);
         }
     }
@@ -1171,7 +1178,7 @@ void display_channel_free_glz_drawables(DisplayChannel *display)
 
 static bool free_one_drawable(DisplayChannel *display, int force_glz_free)
 {
-    RingItem *ring_item = ring_get_tail(&display->current_list);
+    RingItem *ring_item = ring_get_tail(&display->priv->current_list);
     Drawable *drawable;
     Container *container;
 
@@ -1193,7 +1200,7 @@ static bool free_one_drawable(DisplayChannel *display, int force_glz_free)
 
 void display_channel_current_flush(DisplayChannel *display, int surface_id)
 {
-    while (!ring_is_empty(&display->surfaces[surface_id].current_list)) {
+    while (!ring_is_empty(&display->priv->surfaces[surface_id].current_list)) {
         free_one_drawable(display, FALSE);
     }
     current_remove_all(display, surface_id);
@@ -1205,8 +1212,8 @@ void display_channel_free_some(DisplayChannel *display)
     DisplayChannelClient *dcc;
     GList *link, *next;
 
-    spice_debug("#draw=%d, #glz_draw=%d", display->drawable_count,
-                display->encoder_shared_data.glz_drawable_count);
+    spice_debug("#draw=%d, #glz_draw=%d", display->priv->drawable_count,
+                display->priv->encoder_shared_data.glz_drawable_count);
     FOREACH_CLIENT(display, link, next, dcc) {
         ImageEncoders *encoders = dcc_get_encoders(dcc);
 
@@ -1217,7 +1224,7 @@ void display_channel_free_some(DisplayChannel *display)
         }
     }
 
-    while (!ring_is_empty(&display->current_list) && n++ < RED_RELEASE_BUNCH_SIZE) {
+    while (!ring_is_empty(&display->priv->current_list) && n++ < RED_RELEASE_BUNCH_SIZE) {
         free_one_drawable(display, TRUE);
     }
 
@@ -1232,29 +1239,29 @@ static Drawable* drawable_try_new(DisplayChannel *display)
 {
     Drawable *drawable;
 
-    if (!display->free_drawables)
+    if (!display->priv->free_drawables)
         return NULL;
 
-    drawable = &display->free_drawables->u.drawable;
-    display->free_drawables = display->free_drawables->u.next;
-    display->drawable_count++;
+    drawable = &display->priv->free_drawables->u.drawable;
+    display->priv->free_drawables = display->priv->free_drawables->u.next;
+    display->priv->drawable_count++;
 
     return drawable;
 }
 
 static void drawable_free(DisplayChannel *display, Drawable *drawable)
 {
-    ((_Drawable *)drawable)->u.next = display->free_drawables;
-    display->free_drawables = (_Drawable *)drawable;
+    ((_Drawable *)drawable)->u.next = display->priv->free_drawables;
+    display->priv->free_drawables = (_Drawable *)drawable;
 }
 
 static void drawables_init(DisplayChannel *display)
 {
     int i;
 
-    display->free_drawables = NULL;
+    display->priv->free_drawables = NULL;
     for (i = 0; i < NUM_DRAWABLES; i++) {
-        drawable_free(display, &display->drawables[i].u.drawable);
+        drawable_free(display, &display->priv->drawables[i].u.drawable);
     }
 }
 
@@ -1353,7 +1360,7 @@ void drawable_unref(Drawable *drawable)
         red_drawable_unref(drawable->red_drawable);
     }
     drawable_free(display, drawable);
-    display->drawable_count--;
+    display->priv->drawable_count--;
 }
 
 static void drawable_deps_draw(DisplayChannel *display, Drawable *drawable)
@@ -1378,11 +1385,11 @@ static void drawable_draw(DisplayChannel *display, Drawable *drawable)
 
     drawable_deps_draw(display, drawable);
 
-    surface = &display->surfaces[drawable->surface_id];
+    surface = &display->priv->surfaces[drawable->surface_id];
     canvas = surface->context.canvas;
     spice_return_if_fail(canvas);
 
-    image_cache_aging(&display->image_cache);
+    image_cache_aging(&display->priv->image_cache);
 
     region_add(&surface->draw_dirty_region, &drawable->red_drawable->bbox);
 
@@ -1390,8 +1397,8 @@ static void drawable_draw(DisplayChannel *display, Drawable *drawable)
     case QXL_DRAW_FILL: {
         SpiceFill fill = drawable->red_drawable->u.fill;
         SpiceImage img1, img2;
-        image_cache_localize_brush(&display->image_cache, &fill.brush, &img1);
-        image_cache_localize_mask(&display->image_cache, &fill.mask, &img2);
+        image_cache_localize_brush(&display->priv->image_cache, &fill.brush, &img1);
+        image_cache_localize_mask(&display->priv->image_cache, &fill.mask, &img2);
         canvas->ops->draw_fill(canvas, &drawable->red_drawable->bbox,
                                &clip, &fill);
         break;
@@ -1399,17 +1406,17 @@ static void drawable_draw(DisplayChannel *display, Drawable *drawable)
     case QXL_DRAW_OPAQUE: {
         SpiceOpaque opaque = drawable->red_drawable->u.opaque;
         SpiceImage img1, img2, img3;
-        image_cache_localize_brush(&display->image_cache, &opaque.brush, &img1);
-        image_cache_localize(&display->image_cache, &opaque.src_bitmap, &img2, drawable);
-        image_cache_localize_mask(&display->image_cache, &opaque.mask, &img3);
+        image_cache_localize_brush(&display->priv->image_cache, &opaque.brush, &img1);
+        image_cache_localize(&display->priv->image_cache, &opaque.src_bitmap, &img2, drawable);
+        image_cache_localize_mask(&display->priv->image_cache, &opaque.mask, &img3);
         canvas->ops->draw_opaque(canvas, &drawable->red_drawable->bbox, &clip, &opaque);
         break;
     }
     case QXL_DRAW_COPY: {
         SpiceCopy copy = drawable->red_drawable->u.copy;
         SpiceImage img1, img2;
-        image_cache_localize(&display->image_cache, &copy.src_bitmap, &img1, drawable);
-        image_cache_localize_mask(&display->image_cache, &copy.mask, &img2);
+        image_cache_localize(&display->priv->image_cache, &copy.src_bitmap, &img1, drawable);
+        image_cache_localize_mask(&display->priv->image_cache, &copy.mask, &img2);
         canvas->ops->draw_copy(canvas, &drawable->red_drawable->bbox,
                                &clip, &copy);
         break;
@@ -1417,7 +1424,7 @@ static void drawable_draw(DisplayChannel *display, Drawable *drawable)
     case QXL_DRAW_TRANSPARENT: {
         SpiceTransparent transparent = drawable->red_drawable->u.transparent;
         SpiceImage img1;
-        image_cache_localize(&display->image_cache, &transparent.src_bitmap, &img1, drawable);
+        image_cache_localize(&display->priv->image_cache, &transparent.src_bitmap, &img1, drawable);
         canvas->ops->draw_transparent(canvas,
                                       &drawable->red_drawable->bbox, &clip, &transparent);
         break;
@@ -1425,7 +1432,7 @@ static void drawable_draw(DisplayChannel *display, Drawable *drawable)
     case QXL_DRAW_ALPHA_BLEND: {
         SpiceAlphaBlend alpha_blend = drawable->red_drawable->u.alpha_blend;
         SpiceImage img1;
-        image_cache_localize(&display->image_cache, &alpha_blend.src_bitmap, &img1, drawable);
+        image_cache_localize(&display->priv->image_cache, &alpha_blend.src_bitmap, &img1, drawable);
         canvas->ops->draw_alpha_blend(canvas,
                                       &drawable->red_drawable->bbox, &clip, &alpha_blend);
         break;
@@ -1438,8 +1445,8 @@ static void drawable_draw(DisplayChannel *display, Drawable *drawable)
     case QXL_DRAW_BLEND: {
         SpiceBlend blend = drawable->red_drawable->u.blend;
         SpiceImage img1, img2;
-        image_cache_localize(&display->image_cache, &blend.src_bitmap, &img1, drawable);
-        image_cache_localize_mask(&display->image_cache, &blend.mask, &img2);
+        image_cache_localize(&display->priv->image_cache, &blend.src_bitmap, &img1, drawable);
+        image_cache_localize_mask(&display->priv->image_cache, &blend.mask, &img2);
         canvas->ops->draw_blend(canvas, &drawable->red_drawable->bbox,
                                 &clip, &blend);
         break;
@@ -1447,7 +1454,7 @@ static void drawable_draw(DisplayChannel *display, Drawable *drawable)
     case QXL_DRAW_BLACKNESS: {
         SpiceBlackness blackness = drawable->red_drawable->u.blackness;
         SpiceImage img1;
-        image_cache_localize_mask(&display->image_cache, &blackness.mask, &img1);
+        image_cache_localize_mask(&display->priv->image_cache, &blackness.mask, &img1);
         canvas->ops->draw_blackness(canvas,
                                     &drawable->red_drawable->bbox, &clip, &blackness);
         break;
@@ -1455,7 +1462,7 @@ static void drawable_draw(DisplayChannel *display, Drawable *drawable)
     case QXL_DRAW_WHITENESS: {
         SpiceWhiteness whiteness = drawable->red_drawable->u.whiteness;
         SpiceImage img1;
-        image_cache_localize_mask(&display->image_cache, &whiteness.mask, &img1);
+        image_cache_localize_mask(&display->priv->image_cache, &whiteness.mask, &img1);
         canvas->ops->draw_whiteness(canvas,
                                     &drawable->red_drawable->bbox, &clip, &whiteness);
         break;
@@ -1463,7 +1470,7 @@ static void drawable_draw(DisplayChannel *display, Drawable *drawable)
     case QXL_DRAW_INVERS: {
         SpiceInvers invers = drawable->red_drawable->u.invers;
         SpiceImage img1;
-        image_cache_localize_mask(&display->image_cache, &invers.mask, &img1);
+        image_cache_localize_mask(&display->priv->image_cache, &invers.mask, &img1);
         canvas->ops->draw_invers(canvas,
                                  &drawable->red_drawable->bbox, &clip, &invers);
         break;
@@ -1471,9 +1478,9 @@ static void drawable_draw(DisplayChannel *display, Drawable *drawable)
     case QXL_DRAW_ROP3: {
         SpiceRop3 rop3 = drawable->red_drawable->u.rop3;
         SpiceImage img1, img2, img3;
-        image_cache_localize_brush(&display->image_cache, &rop3.brush, &img1);
-        image_cache_localize(&display->image_cache, &rop3.src_bitmap, &img2, drawable);
-        image_cache_localize_mask(&display->image_cache, &rop3.mask, &img3);
+        image_cache_localize_brush(&display->priv->image_cache, &rop3.brush, &img1);
+        image_cache_localize(&display->priv->image_cache, &rop3.src_bitmap, &img2, drawable);
+        image_cache_localize_mask(&display->priv->image_cache, &rop3.mask, &img3);
         canvas->ops->draw_rop3(canvas, &drawable->red_drawable->bbox,
                                &clip, &rop3);
         break;
@@ -1481,9 +1488,9 @@ static void drawable_draw(DisplayChannel *display, Drawable *drawable)
     case QXL_DRAW_COMPOSITE: {
         SpiceComposite composite = drawable->red_drawable->u.composite;
         SpiceImage src, mask;
-        image_cache_localize(&display->image_cache, &composite.src_bitmap, &src, drawable);
+        image_cache_localize(&display->priv->image_cache, &composite.src_bitmap, &src, drawable);
         if (composite.mask_bitmap)
-            image_cache_localize(&display->image_cache, &composite.mask_bitmap, &mask, drawable);
+            image_cache_localize(&display->priv->image_cache, &composite.mask_bitmap, &mask, drawable);
         canvas->ops->draw_composite(canvas, &drawable->red_drawable->bbox,
                                     &clip, &composite);
         break;
@@ -1491,7 +1498,7 @@ static void drawable_draw(DisplayChannel *display, Drawable *drawable)
     case QXL_DRAW_STROKE: {
         SpiceStroke stroke = drawable->red_drawable->u.stroke;
         SpiceImage img1;
-        image_cache_localize_brush(&display->image_cache, &stroke.brush, &img1);
+        image_cache_localize_brush(&display->priv->image_cache, &stroke.brush, &img1);
         canvas->ops->draw_stroke(canvas,
                                  &drawable->red_drawable->bbox, &clip, &stroke);
         break;
@@ -1499,8 +1506,8 @@ static void drawable_draw(DisplayChannel *display, Drawable *drawable)
     case QXL_DRAW_TEXT: {
         SpiceText text = drawable->red_drawable->u.text;
         SpiceImage img1, img2;
-        image_cache_localize_brush(&display->image_cache, &text.fore_brush, &img1);
-        image_cache_localize_brush(&display->image_cache, &text.back_brush, &img2);
+        image_cache_localize_brush(&display->priv->image_cache, &text.fore_brush, &img1);
+        image_cache_localize_brush(&display->priv->image_cache, &text.back_brush, &img2);
         canvas->ops->draw_text(canvas, &drawable->red_drawable->bbox,
                                &clip, &text);
         break;
@@ -1592,11 +1599,11 @@ void display_channel_draw_until(DisplayChannel *display, const SpiceRect *area,
     spice_return_if_fail(last);
     spice_return_if_fail(ring_item_is_linked(&last->list_link));
 
-    surface = &display->surfaces[surface_id];
+    surface = &display->priv->surfaces[surface_id];
 
     if (surface_id != last->surface_id) {
         // find the nearest older drawable from the appropriate surface
-        ring = &display->current_list;
+        ring = &display->priv->current_list;
         ring_item = &last->list_link;
         while ((ring_item = ring_next(ring, ring_item))) {
             now = SPICE_CONTAINEROF(ring_item, Drawable, list_link);
@@ -1637,7 +1644,7 @@ void display_channel_draw(DisplayChannel *display, const SpiceRect *area, int su
     spice_return_if_fail(area->left >= 0 && area->top >= 0 &&
                          area->left < area->right && area->top < area->bottom);
 
-    surface = &display->surfaces[surface_id];
+    surface = &display->priv->surfaces[surface_id];
 
     last = current_find_intersects_rect(&surface->current_list, NULL, area);
     if (last)
@@ -1669,12 +1676,12 @@ void display_channel_update(DisplayChannel *display,
     SpiceRect rect;
     RedSurface *surface;
 
-    spice_return_if_fail(validate_surface(display, surface_id));
+    spice_return_if_fail(display_channel_validate_surface(display, surface_id));
 
     red_get_rect_ptr(&rect, area);
     display_channel_draw(display, &rect, surface_id);
 
-    surface = &display->surfaces[surface_id];
+    surface = &display->priv->surfaces[surface_id];
     if (*qxl_dirty_rects == NULL) {
         *num_dirty_rects = pixman_region32_n_rects(&surface->draw_dirty_region);
         *qxl_dirty_rects = spice_new0(QXLRect, *num_dirty_rects);
@@ -1712,9 +1719,9 @@ static void display_channel_destroy_surface(DisplayChannel *display, uint32_t su
 
 void display_channel_destroy_surface_wait(DisplayChannel *display, uint32_t surface_id)
 {
-    if (!validate_surface(display, surface_id))
+    if (!display_channel_validate_surface(display, surface_id))
         return;
-    if (!display->surfaces[surface_id].context.canvas)
+    if (!display->priv->surfaces[surface_id].context.canvas)
         return;
 
     draw_depend_on_me(display, surface_id);
@@ -1734,15 +1741,15 @@ void display_channel_destroy_surfaces(DisplayChannel *display)
     spice_debug(NULL);
     //to handle better
     for (i = 0; i < NUM_SURFACES; ++i) {
-        if (display->surfaces[i].context.canvas) {
+        if (display->priv->surfaces[i].context.canvas) {
             display_channel_destroy_surface_wait(display, i);
-            if (display->surfaces[i].context.canvas) {
+            if (display->priv->surfaces[i].context.canvas) {
                 display_channel_surface_unref(display, i);
             }
-            spice_assert(!display->surfaces[i].context.canvas);
+            spice_assert(!display->priv->surfaces[i].context.canvas);
         }
     }
-    spice_warn_if_fail(ring_is_empty(&display->streams));
+    spice_warn_if_fail(ring_is_empty(&display->priv->streams));
 
     if (red_channel_is_connected(RED_CHANNEL(display))) {
         red_channel_pipes_add_type(RED_CHANNEL(display), RED_PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE);
@@ -1773,8 +1780,8 @@ create_canvas_for_surface(DisplayChannel *display, RedSurface *surface, uint32_t
     case RED_RENDERER_SW:
         canvas = canvas_create_for_data(surface->context.width, surface->context.height, surface->context.format,
                                         surface->context.line_0, surface->context.stride,
-                                        &display->image_cache.base,
-                                        &display->image_surfaces, NULL, NULL, NULL);
+                                        &display->priv->image_cache.base,
+                                        &display->priv->image_surfaces, NULL, NULL, NULL);
         surface->context.top_down = TRUE;
         surface->context.canvas_draws_on_surface = TRUE;
         return canvas;
@@ -1789,7 +1796,7 @@ void display_channel_create_surface(DisplayChannel *display, uint32_t surface_id
                                     uint32_t height, int32_t stride, uint32_t format,
                                     void *line_0, int data_is_valid, int send_client)
 {
-    RedSurface *surface = &display->surfaces[surface_id];
+    RedSurface *surface = &display->priv->surfaces[surface_id];
 
     spice_warn_if_fail(!surface->context.canvas);
 
@@ -1814,7 +1821,7 @@ void display_channel_create_surface(DisplayChannel *display, uint32_t surface_id
     region_init(&surface->draw_dirty_region);
     surface->refs = 1;
 
-    if (display->renderer == RED_RENDERER_INVALID) {
+    if (display->priv->renderer == RED_RENDERER_INVALID) {
         int i;
         QXLInstance *qxl = display->common.qxl;
         RedsState *reds = red_qxl_get_server(qxl->st);
@@ -1823,12 +1830,12 @@ void display_channel_create_surface(DisplayChannel *display, uint32_t surface_id
             uint32_t renderer = g_array_index(renderers, uint32_t, i);
             surface->context.canvas = create_canvas_for_surface(display, surface, renderer);
             if (surface->context.canvas) {
-                display->renderer = renderer;
+                display->priv->renderer = renderer;
                 break;
             }
         }
     } else {
-        surface->context.canvas = create_canvas_for_surface(display, surface, display->renderer);
+        surface->context.canvas = create_canvas_for_surface(display, surface, display->priv->renderer);
     }
 
     spice_return_if_fail(surface->context.canvas);
@@ -1852,8 +1859,8 @@ static void on_disconnect(RedChannelClient *rcc)
 
     // this was the last channel client
     spice_debug("#draw=%d, #glz_draw=%d",
-                display->drawable_count,
-                display->encoder_shared_data.glz_drawable_count);
+                display->priv->drawable_count,
+                display->priv->encoder_shared_data.glz_drawable_count);
 }
 
 static int handle_migrate_flush_mark(RedChannelClient *rcc)
@@ -1880,11 +1887,12 @@ static int handle_migrate_data(RedChannelClient *rcc, uint32_t size, void *messa
 
 static SpiceCanvas *image_surfaces_get(SpiceImageSurfaces *surfaces, uint32_t surface_id)
 {
-    DisplayChannel *display = SPICE_CONTAINEROF(surfaces, DisplayChannel, image_surfaces);
+    DisplayChannelPrivate *p = SPICE_CONTAINEROF(surfaces, DisplayChannelPrivate, image_surfaces);
+    DisplayChannel *display = p->pub;
 
-    spice_return_val_if_fail(validate_surface(display, surface_id), NULL);
+    spice_return_val_if_fail(display_channel_validate_surface(display, surface_id), NULL);
 
-    return display->surfaces[surface_id].context.canvas;
+    return display->priv->surfaces[surface_id].context.canvas;
 }
 
 DisplayChannel* display_channel_new(SpiceServer *reds, RedWorker *worker, 
@@ -1912,31 +1920,33 @@ DisplayChannel* display_channel_new(SpiceServer *reds, RedWorker *worker,
         SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER,
         &cbs, dcc_handle_message);
     spice_return_val_if_fail(display, NULL);
+    display->priv = g_new0(DisplayChannelPrivate, 1);
+    display->priv->pub = display;
 
     clockid_t stat_clock = CLOCK_THREAD_CPUTIME_ID;
-    stat_init(&display->add_stat, "add", stat_clock);
-    stat_init(&display->exclude_stat, "exclude", stat_clock);
-    stat_init(&display->__exclude_stat, "__exclude", stat_clock);
+    stat_init(&display->priv->add_stat, "add", stat_clock);
+    stat_init(&display->priv->exclude_stat, "exclude", stat_clock);
+    stat_init(&display->priv->__exclude_stat, "__exclude", stat_clock);
 #ifdef RED_STATISTICS
     RedChannel *channel = RED_CHANNEL(display);
-    display->cache_hits_counter = stat_add_counter(reds, channel->stat,
-                                                   "cache_hits", TRUE);
-    display->add_to_cache_counter = stat_add_counter(reds, channel->stat,
-                                                     "add_to_cache", TRUE);
-    display->non_cache_counter = stat_add_counter(reds, channel->stat,
-                                                  "non_cache", TRUE);
+    display->priv->cache_hits_counter = stat_add_counter(reds, channel->stat,
+                                                         "cache_hits", TRUE);
+    display->priv->add_to_cache_counter = stat_add_counter(reds, channel->stat,
+                                                           "add_to_cache", TRUE);
+    display->priv->non_cache_counter = stat_add_counter(reds, channel->stat,
+                                                        "non_cache", TRUE);
 #endif
-    image_encoder_shared_init(&display->encoder_shared_data);
+    image_encoder_shared_init(&display->priv->encoder_shared_data);
 
-    display->n_surfaces = n_surfaces;
-    display->renderer = RED_RENDERER_INVALID;
+    display->priv->n_surfaces = n_surfaces;
+    display->priv->renderer = RED_RENDERER_INVALID;
 
-    ring_init(&display->current_list);
-    display->image_surfaces.ops = &image_surfaces_ops;
+    ring_init(&display->priv->current_list);
+    display->priv->image_surfaces.ops = &image_surfaces_ops;
     drawables_init(display);
-    image_cache_init(&display->image_cache);
-    display->stream_video = stream_video;
-    display->video_codecs = g_array_ref(video_codecs);
+    image_cache_init(&display->priv->image_cache);
+    display->priv->stream_video = stream_video;
+    display->priv->video_codecs = g_array_ref(video_codecs);
     display_channel_init_streams(display);
 
     return display;
@@ -1950,11 +1960,11 @@ void display_channel_process_surface_cmd(DisplayChannel *display, RedSurfaceCmd
     uint8_t *data;
 
     surface_id = surface->surface_id;
-    if SPICE_UNLIKELY(surface_id >= display->n_surfaces) {
+    if SPICE_UNLIKELY(surface_id >= display->priv->n_surfaces) {
         return;
     }
 
-    red_surface = &display->surfaces[surface_id];
+    red_surface = &display->priv->surfaces[surface_id];
 
     switch (surface->type) {
     case QXL_SURFACE_CMD_CREATE: {
@@ -1994,18 +2004,18 @@ void display_channel_process_surface_cmd(DisplayChannel *display, RedSurfaceCmd
 void display_channel_update_compression(DisplayChannel *display, DisplayChannelClient *dcc)
 {
     if (dcc_get_jpeg_state(dcc) == SPICE_WAN_COMPRESSION_AUTO) {
-        display->enable_jpeg = dcc_is_low_bandwidth(dcc);
+        display->priv->enable_jpeg = dcc_is_low_bandwidth(dcc);
     } else {
-        display->enable_jpeg = (dcc_get_jpeg_state(dcc) == SPICE_WAN_COMPRESSION_ALWAYS);
+        display->priv->enable_jpeg = (dcc_get_jpeg_state(dcc) == SPICE_WAN_COMPRESSION_ALWAYS);
     }
 
     if (dcc_get_zlib_glz_state(dcc) == SPICE_WAN_COMPRESSION_AUTO) {
-        display->enable_zlib_glz_wrap = dcc_is_low_bandwidth(dcc);
+        display->priv->enable_zlib_glz_wrap = dcc_is_low_bandwidth(dcc);
     } else {
-        display->enable_zlib_glz_wrap = (dcc_get_zlib_glz_state(dcc) == SPICE_WAN_COMPRESSION_ALWAYS);
+        display->priv->enable_zlib_glz_wrap = (dcc_get_zlib_glz_state(dcc) == SPICE_WAN_COMPRESSION_ALWAYS);
     }
-    spice_info("jpeg %s", display->enable_jpeg ? "enabled" : "disabled");
-    spice_info("zlib-over-glz %s", display->enable_zlib_glz_wrap ? "enabled" : "disabled");
+    spice_info("jpeg %s", display->priv->enable_jpeg ? "enabled" : "disabled");
+    spice_info("zlib-over-glz %s", display->priv->enable_zlib_glz_wrap ? "enabled" : "disabled");
 }
 
 void display_channel_gl_scanout(DisplayChannel *display)
@@ -2017,7 +2027,7 @@ static void set_gl_draw_async_count(DisplayChannel *display, int num)
 {
     QXLInstance *qxl = display->common.qxl;
 
-    display->gl_draw_async_count = num;
+    display->priv->gl_draw_async_count = num;
 
     if (num == 0) {
         red_qxl_gl_draw_async_complete(qxl);
@@ -2028,7 +2038,7 @@ void display_channel_gl_draw(DisplayChannel *display, SpiceMsgDisplayGlDraw *dra
 {
     int num;
 
-    spice_return_if_fail(display->gl_draw_async_count == 0);
+    spice_return_if_fail(display->priv->gl_draw_async_count == 0);
 
     num = red_channel_pipes_new_add_push(RED_CHANNEL(display), dcc_gl_draw_item_new, draw);
     set_gl_draw_async_count(display, num);
@@ -2036,5 +2046,57 @@ void display_channel_gl_draw(DisplayChannel *display, SpiceMsgDisplayGlDraw *dra
 
 void display_channel_gl_draw_done(DisplayChannel *display)
 {
-    set_gl_draw_async_count(display, display->gl_draw_async_count - 1);
+    set_gl_draw_async_count(display, display->priv->gl_draw_async_count - 1);
+}
+
+int display_channel_get_stream_id(DisplayChannel *display, Stream *stream)
+{
+    return (int)(stream - display->priv->streams_buf);
+}
+
+gboolean display_channel_validate_surface(DisplayChannel *display, uint32_t surface_id)
+{
+    if SPICE_UNLIKELY(surface_id >= display->priv->n_surfaces) {
+        spice_warning("invalid surface_id %u", surface_id);
+        return 0;
+    }
+    if (!display->priv->surfaces[surface_id].context.canvas) {
+        spice_warning("canvas address is %p for %d (and is NULL)\n",
+                   &(display->priv->surfaces[surface_id].context.canvas), surface_id);
+        spice_warning("failed on %d", surface_id);
+        return 0;
+    }
+    return 1;
+}
+
+void display_channel_update_monitors_config(DisplayChannel *display,
+                                            QXLMonitorsConfig *config,
+                                            uint16_t count, uint16_t max_allowed)
+{
+
+    if (display->priv->monitors_config)
+        monitors_config_unref(display->priv->monitors_config);
+
+    display->priv->monitors_config =
+        monitors_config_new(config->heads, count, max_allowed);
+}
+
+void set_monitors_config_to_primary(DisplayChannel *display)
+{
+    DrawContext *context = &display->priv->surfaces[0].context;
+    QXLHead head = { 0, };
+
+    spice_return_if_fail(display->priv->surfaces[0].context.canvas);
+
+    if (display->priv->monitors_config)
+        monitors_config_unref(display->priv->monitors_config);
+
+    head.width = context->width;
+    head.height = context->height;
+    display->priv->monitors_config = monitors_config_new(&head, 1, 1);
+}
+
+void display_channel_reset_image_cache(DisplayChannel *self)
+{
+    image_cache_reset(&self->priv->image_cache);
 }
diff --git a/server/display-channel.h b/server/display-channel.h
index 7b71480..b8ba05a 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -157,61 +157,24 @@ struct _Drawable {
     } u;
 };
 
+typedef struct DisplayChannelPrivate DisplayChannelPrivate;
+
 struct DisplayChannel {
     CommonGraphicsChannel common; // Must be the first thing
-    uint32_t bits_unique;
-
-    MonitorsConfig *monitors_config;
 
-    uint32_t renderer;
-    int enable_jpeg;
-    int enable_zlib_glz_wrap;
-
-    Ring current_list; // of TreeItem
-    uint32_t current_size;
-
-    uint32_t drawable_count;
-    _Drawable drawables[NUM_DRAWABLES];
-    _Drawable *free_drawables;
-
-    int stream_video;
-    GArray *video_codecs;
-    uint32_t stream_count;
-    Stream streams_buf[NUM_STREAMS];
-    Stream *free_streams;
-    Ring streams;
-    ItemTrace items_trace[NUM_TRACE_ITEMS];
-    uint32_t next_item_trace;
-    uint64_t streams_size_total;
-
-    RedSurface surfaces[NUM_SURFACES];
-    uint32_t n_surfaces;
-    SpiceImageSurfaces image_surfaces;
-
-    ImageCache image_cache;
-
-    int gl_draw_async_count;
-
-/* TODO: some day unify this, make it more runtime.. */
-    stat_info_t add_stat;
-    stat_info_t exclude_stat;
-    stat_info_t __exclude_stat;
-#ifdef RED_WORKER_STAT
-    uint32_t add_count;
-    uint32_t add_with_shadow_count;
-#endif
-#ifdef RED_STATISTICS
-    uint64_t *cache_hits_counter;
-    uint64_t *add_to_cache_counter;
-    uint64_t *non_cache_counter;
-#endif
-    ImageEncoderSharedData encoder_shared_data;
+    DisplayChannelPrivate *priv;
 };
 
-static inline int get_stream_id(DisplayChannel *display, Stream *stream)
-{
-    return (int)(stream - display->streams_buf);
-}
+#define FOREACH_DCC(channel, _link, _next, _data)                   \
+    for (_link = (channel ? RED_CHANNEL(channel)->clients : NULL), \
+         _next = (_link ? _link->next : NULL), \
+         _data = (_link ? _link->data : NULL); \
+         _link; \
+         _link = _next, \
+         _next = (_link ? _link->next : NULL), \
+         _data = (_link ? _link->data : NULL))
+
+int display_channel_get_stream_id(DisplayChannel *display, Stream *stream);
 
 typedef struct RedSurfaceDestroyItem {
     RedPipeItem pipe_item;
@@ -258,6 +221,8 @@ void                       display_channel_compress_stats_print      (const Disp
 void                       display_channel_compress_stats_reset      (DisplayChannel *display);
 void                       display_channel_surface_unref             (DisplayChannel *display,
                                                                       uint32_t surface_id);
+bool                       display_channel_surface_has_canvas        (DisplayChannel *display,
+                                                                      uint32_t surface_id);
 void                       display_channel_current_flush             (DisplayChannel *display,
                                                                       int surface_id);
 int                        display_channel_wait_for_migrate_data     (DisplayChannel *display);
@@ -281,20 +246,12 @@ void                       display_channel_gl_draw                   (DisplayCha
                                                                       SpiceMsgDisplayGlDraw *draw);
 void                       display_channel_gl_draw_done              (DisplayChannel *display);
 
-static inline int validate_surface(DisplayChannel *display, uint32_t surface_id)
-{
-    if SPICE_UNLIKELY(surface_id >= display->n_surfaces) {
-        spice_warning("invalid surface_id %u", surface_id);
-        return 0;
-    }
-    if (!display->surfaces[surface_id].context.canvas) {
-        spice_warning("canvas address is %p for %d (and is NULL)\n",
-                   &(display->surfaces[surface_id].context.canvas), surface_id);
-        spice_warning("failed on %d", surface_id);
-        return 0;
-    }
-    return 1;
-}
+void display_channel_update_monitors_config(DisplayChannel *display, QXLMonitorsConfig *config,
+                                            uint16_t count, uint16_t max_allowed);
+void set_monitors_config_to_primary(DisplayChannel *display);
+
+gboolean display_channel_validate_surface(DisplayChannel *display, uint32_t surface_id);
+void display_channel_reset_image_cache(DisplayChannel *self);
 
 static inline int is_equal_path(SpicePath *path1, SpicePath *path2)
 {
diff --git a/server/red-worker.c b/server/red-worker.c
index 590412b..92ab59c 100644
--- a/server/red-worker.c
+++ b/server/red-worker.c
@@ -247,7 +247,7 @@ static int red_process_display(RedWorker *worker, int *ring_is_empty)
                                    &update, ext_cmd.cmd.data)) {
                 break;
             }
-            if (!validate_surface(worker->display_channel, update.surface_id)) {
+            if (!display_channel_validate_surface(worker->display_channel, update.surface_id)) {
                 spice_warning("Invalid surface in QXL_CMD_UPDATE");
             } else {
                 display_channel_draw(worker->display_channel, &update.area, update.surface_id);
@@ -587,18 +587,6 @@ static void handle_dev_destroy_surfaces(void *opaque, void *payload)
     cursor_channel_reset(worker->cursor_channel);
 }
 
-static void display_update_monitors_config(DisplayChannel *display,
-                                           QXLMonitorsConfig *config,
-                                           uint16_t count, uint16_t max_allowed)
-{
-
-    if (display->monitors_config)
-        monitors_config_unref(display->monitors_config);
-
-    display->monitors_config =
-        monitors_config_new(config->heads, count, max_allowed);
-}
-
 static void red_worker_push_monitors_config(RedWorker *worker)
 {
     DisplayChannelClient *dcc;
@@ -609,21 +597,6 @@ static void red_worker_push_monitors_config(RedWorker *worker)
     }
 }
 
-static void set_monitors_config_to_primary(DisplayChannel *display)
-{
-    DrawContext *context = &display->surfaces[0].context;
-    QXLHead head = { 0, };
-
-    spice_return_if_fail(display->surfaces[0].context.canvas);
-
-    if (display->monitors_config)
-        monitors_config_unref(display->monitors_config);
-
-    head.width = context->width;
-    head.height = context->height;
-    display->monitors_config = monitors_config_new(&head, 1, 1);
-}
-
 static void dev_create_primary_surface(RedWorker *worker, uint32_t surface_id,
                                        QXLDevSurfaceCreate surface)
 {
@@ -689,12 +662,12 @@ static void destroy_primary_surface(RedWorker *worker, uint32_t surface_id)
 {
     DisplayChannel *display = worker->display_channel;
 
-    if (!validate_surface(display, surface_id))
+    if (!display_channel_validate_surface(display, surface_id))
         return;
     spice_warn_if_fail(surface_id == 0);
 
     spice_debug(NULL);
-    if (!display->surfaces[surface_id].context.canvas) {
+    if (!display_channel_surface_has_canvas(display, surface_id)) {
         spice_warning("double destroy of primary surface");
         return;
     }
@@ -703,8 +676,10 @@ static void destroy_primary_surface(RedWorker *worker, uint32_t surface_id)
     display_channel_destroy_surface_wait(display, 0);
     display_channel_surface_unref(display, 0);
 
+    /* FIXME: accessing private data only for warning purposes...
     spice_warn_if_fail(ring_is_empty(&display->streams));
-    spice_warn_if_fail(!display->surfaces[surface_id].context.canvas);
+    */
+    spice_warn_if_fail(!display_channel_surface_has_canvas(display, surface_id));
 
     cursor_channel_reset(worker->cursor_channel);
 }
@@ -798,11 +773,13 @@ static void handle_dev_oom(void *opaque, void *payload)
 
     spice_return_if_fail(worker->running);
     // streams? but without streams also leak
+#if FIXME
     spice_debug("OOM1 #draw=%u, #glz_draw=%u current %u pipes %u",
                 display->drawable_count,
                 display->encoder_shared_data.glz_drawable_count,
                 display->current_size,
                 red_channel_sum_pipes_size(display_red_channel));
+#endif
     while (red_process_display(worker, &ring_is_empty)) {
         red_channel_push(display_red_channel);
     }
@@ -810,11 +787,13 @@ static void handle_dev_oom(void *opaque, void *payload)
         display_channel_free_some(worker->display_channel);
         red_qxl_flush_resources(worker->qxl);
     }
+#if FIXME
     spice_debug("OOM2 #draw=%u, #glz_draw=%u current %u pipes %u",
                 display->drawable_count,
                 display->encoder_shared_data.glz_drawable_count,
                 display->current_size,
                 red_channel_sum_pipes_size(display_red_channel));
+#endif
     red_qxl_clear_pending(worker->qxl->st, RED_DISPATCHER_PENDING_OOM);
 }
 
@@ -828,9 +807,8 @@ static void handle_dev_reset_cursor(void *opaque, void *payload)
 static void handle_dev_reset_image_cache(void *opaque, void *payload)
 {
     RedWorker *worker = opaque;
-    DisplayChannel *display = worker->display_channel;
 
-    image_cache_reset(&display->image_cache);
+    display_channel_reset_image_cache(worker->display_channel);
 }
 
 static void handle_dev_destroy_surface_wait_async(void *opaque, void *payload)
@@ -950,9 +928,9 @@ static void handle_dev_monitors_config_async(void *opaque, void *payload)
         /* TODO: raise guest bug (requires added QXL interface) */
         return;
     }
-    display_update_monitors_config(worker->display_channel, dev_monitors_config,
-                                   MIN(count, msg->max_monitors),
-                                   MIN(max_allowed, msg->max_monitors));
+    display_channel_update_monitors_config(worker->display_channel, dev_monitors_config,
+                                           MIN(count, msg->max_monitors),
+                                           MIN(max_allowed, msg->max_monitors));
     red_worker_push_monitors_config(worker);
 }
 
diff --git a/server/stream.c b/server/stream.c
index 4819723..8558eec 100644
--- a/server/stream.c
+++ b/server/stream.c
@@ -19,13 +19,14 @@
 #endif
 
 #include "stream.h"
-#include "display-channel.h"
+#include "display-channel-private.h"
+#include "main-channel-client.h"
 
 #define FPS_TEST_INTERVAL 1
 #define FOREACH_STREAMS(display, item)                  \
-    for (item = ring_get_head(&(display)->streams);     \
+    for (item = ring_get_head(&(display)->priv->streams);     \
          item != NULL;                                  \
-         item = ring_next(&(display)->streams, item))
+         item = ring_next(&(display)->priv->streams, item))
 
 static void stream_agent_stats_print(StreamAgent *agent)
 {
@@ -101,11 +102,11 @@ void stream_stop(DisplayChannel *display, Stream *stream)
     spice_return_if_fail(ring_item_is_linked(&stream->link));
     spice_return_if_fail(!stream->current);
 
-    spice_debug("stream %d", get_stream_id(display, stream));
+    spice_debug("stream %d", display_channel_get_stream_id(display, stream));
     FOREACH_CLIENT(display, link, next, dcc) {
         StreamAgent *stream_agent;
 
-        stream_agent = dcc_get_stream_agent(dcc, get_stream_id(display, stream));
+        stream_agent = dcc_get_stream_agent(dcc, display_channel_get_stream_id(display, stream));
         region_clear(&stream_agent->vis_region);
         region_clear(&stream_agent->clip);
         if (stream_agent->video_encoder && dcc_use_video_encoder_rate_control(dcc)) {
@@ -121,25 +122,25 @@ void stream_stop(DisplayChannel *display, Stream *stream)
         red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), stream_destroy_item_new(stream_agent));
         stream_agent_stats_print(stream_agent);
     }
-    display->streams_size_total -= stream->width * stream->height;
+    display->priv->streams_size_total -= stream->width * stream->height;
     ring_remove(&stream->link);
     stream_unref(display, stream);
 }
 
 static void stream_free(DisplayChannel *display, Stream *stream)
 {
-    stream->next = display->free_streams;
-    display->free_streams = stream;
+    stream->next = display->priv->free_streams;
+    display->priv->free_streams = stream;
 }
 
 void display_channel_init_streams(DisplayChannel *display)
 {
     int i;
 
-    ring_init(&display->streams);
-    display->free_streams = NULL;
+    ring_init(&display->priv->streams);
+    display->priv->free_streams = NULL;
     for (i = 0; i < NUM_STREAMS; i++) {
-        Stream *stream = &display->streams_buf[i];
+        Stream *stream = &display->priv->streams_buf[i];
         ring_item_init(&stream->link);
         stream_free(display, stream);
     }
@@ -153,7 +154,7 @@ void stream_unref(DisplayChannel *display, Stream *stream)
     spice_warn_if_fail(!ring_item_is_linked(&stream->link));
 
     stream_free(display, stream);
-    display->stream_count--;
+    display->priv->stream_count--;
 }
 
 void stream_agent_unref(DisplayChannel *display, StreamAgent *agent)
@@ -197,7 +198,7 @@ static void update_copy_graduality(DisplayChannel *display, Drawable *drawable)
     SpiceBitmap *bitmap;
     spice_return_if_fail(drawable->red_drawable->type == QXL_DRAW_COPY);
 
-    if (display->stream_video != SPICE_STREAM_VIDEO_FILTER) {
+    if (display->priv->stream_video != SPICE_STREAM_VIDEO_FILTER) {
         drawable->copy_bitmap_graduality = BITMAP_GRADUAL_INVALID;
         return;
     }
@@ -302,7 +303,7 @@ static void attach_stream(DisplayChannel *display, Drawable *drawable, Stream *s
         StreamAgent *agent;
         QRegion clip_in_draw_dest;
 
-        agent = dcc_get_stream_agent(dcc, get_stream_id(display, stream));
+        agent = dcc_get_stream_agent(dcc, display_channel_get_stream_id(display, stream));
         region_or(&agent->vis_region, &drawable->tree_item.base.rgn);
 
         region_init(&clip_in_draw_dest);
@@ -349,7 +350,7 @@ static void before_reattach_stream(DisplayChannel *display,
         return;
     }
 
-    index = get_stream_id(display, stream);
+    index = display_channel_get_stream_id(display, stream);
     DRAWABLE_FOREACH_DPI_SAFE(stream->current, ring_item, next, dpi) {
         dcc = dpi->dcc;
         agent = dcc_get_stream_agent(dcc, index);
@@ -406,11 +407,11 @@ static void before_reattach_stream(DisplayChannel *display,
 static Stream *display_channel_stream_try_new(DisplayChannel *display)
 {
     Stream *stream;
-    if (!display->free_streams) {
+    if (!display->priv->free_streams) {
         return NULL;
     }
-    stream = display->free_streams;
-    display->free_streams = display->free_streams->next;
+    stream = display->priv->free_streams;
+    display->priv->free_streams = display->priv->free_streams->next;
     return stream;
 }
 
@@ -430,7 +431,7 @@ static void display_channel_create_stream(DisplayChannel *display, Drawable *dra
     spice_assert(drawable->red_drawable->type == QXL_DRAW_COPY);
     src_rect = &drawable->red_drawable->u.copy.src_area;
 
-    ring_add(&display->streams, &stream->link);
+    ring_add(&display->priv->streams, &stream->link);
     stream->current = drawable;
     stream->last_time = drawable->creation_time;
     stream->width = src_rect->right - src_rect->left;
@@ -452,13 +453,13 @@ static void display_channel_create_stream(DisplayChannel *display, Drawable *dra
     }
     stream->num_input_frames = 0;
     stream->input_fps_start_time = drawable->creation_time;
-    display->streams_size_total += stream->width * stream->height;
-    display->stream_count++;
+    display->priv->streams_size_total += stream->width * stream->height;
+    display->priv->stream_count++;
     FOREACH_CLIENT(display, link, next, dcc) {
         dcc_create_stream(dcc, stream);
     }
     spice_debug("stream %d %dx%d (%d, %d) (%d, %d) %u fps",
-                (int)(stream - display->streams_buf), stream->width,
+                (int)(stream - display->priv->streams_buf), stream->width,
                 stream->height, stream->dest_area.left, stream->dest_area.top,
                 stream->dest_area.right, stream->dest_area.bottom,
                 stream->input_fps);
@@ -530,7 +531,7 @@ void stream_trace_update(DisplayChannel *display, Drawable *drawable)
         }
     }
 
-    trace = display->items_trace;
+    trace = display->priv->items_trace;
     trace_end = trace + NUM_TRACE_ITEMS;
     for (; trace < trace_end; trace++) {
         if (is_next_stream_frame(display, drawable, trace->width, trace->height,
@@ -597,7 +598,7 @@ static void dcc_update_streams_max_latency(DisplayChannelClient *dcc, StreamAgen
     }
 
     dcc_set_max_stream_latency(dcc, 0);
-    if (DCC_TO_DC(dcc)->stream_count == 1) {
+    if (DCC_TO_DC(dcc)->priv->stream_count == 1) {
         return;
     }
     for (i = 0; i < NUM_STREAMS; i++) {
@@ -656,7 +657,7 @@ static uint64_t get_initial_bit_rate(DisplayChannelClient *dcc, Stream *stream)
     /* dividing the available bandwidth among the active streams, and saving
      * (1-RED_STREAM_CHANNEL_CAPACITY) of it for other messages */
     return (RED_STREAM_CHANNEL_CAPACITY * bit_rate *
-            stream->width * stream->height) / DCC_TO_DC(dcc)->streams_size_total;
+            stream->width * stream->height) / DCC_TO_DC(dcc)->priv->streams_size_total;
 }
 
 static uint32_t get_roundtrip_ms(void *opaque)
@@ -729,8 +730,8 @@ static VideoEncoder* dcc_create_video_encoder(DisplayChannelClient *dcc,
     int client_has_multi_codec = red_channel_client_test_remote_cap(rcc, SPICE_DISPLAY_CAP_MULTI_CODEC);
     int i;
 
-    for (i = 0; i < display->video_codecs->len; i++) {
-        RedVideoCodec* video_codec = &g_array_index (display->video_codecs, RedVideoCodec, i);
+    for (i = 0; i < display->priv->video_codecs->len; i++) {
+        RedVideoCodec* video_codec = &g_array_index (display->priv->video_codecs, RedVideoCodec, i);
 
         if (!client_has_multi_codec &&
             video_codec->type != SPICE_VIDEO_CODEC_TYPE_MJPEG) {
@@ -759,7 +760,7 @@ static VideoEncoder* dcc_create_video_encoder(DisplayChannelClient *dcc,
 
 void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream)
 {
-    StreamAgent *agent = dcc_get_stream_agent(dcc, get_stream_id(DCC_TO_DC(dcc), stream));
+    StreamAgent *agent = dcc_get_stream_agent(dcc, display_channel_get_stream_id(DCC_TO_DC(dcc), stream));
 
     spice_return_if_fail(region_is_empty(&agent->vis_region));
 
@@ -796,7 +797,7 @@ void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream)
         agent->report_id = rand();
         red_pipe_item_init(&report_pipe_item->pipe_item,
                            RED_PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT);
-        report_pipe_item->stream_id = get_stream_id(DCC_TO_DC(dcc), stream);
+        report_pipe_item->stream_id = display_channel_get_stream_id(DCC_TO_DC(dcc), stream);
         red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &report_pipe_item->pipe_item);
     }
 #ifdef STREAM_STATS
@@ -839,7 +840,7 @@ static void dcc_detach_stream_gracefully(DisplayChannelClient *dcc,
                                          Drawable *update_area_limit)
 {
     DisplayChannel *display = DCC_TO_DC(dcc);
-    int stream_id = get_stream_id(display, stream);
+    int stream_id = display_channel_get_stream_id(display, stream);
     StreamAgent *agent = dcc_get_stream_agent(dcc, stream_id);
 
     /* stopping the client from playing older frames at once*/
@@ -924,7 +925,7 @@ static void detach_stream_gracefully(DisplayChannel *display, Stream *stream,
  */
 void stream_detach_behind(DisplayChannel *display, QRegion *region, Drawable *drawable)
 {
-    Ring *ring = &display->streams;
+    Ring *ring = &display->priv->streams;
     RingItem *item = ring_get_head(ring);
     GList *link, *next;
     DisplayChannelClient *dcc;
@@ -936,12 +937,12 @@ void stream_detach_behind(DisplayChannel *display, QRegion *region, Drawable *dr
         item = ring_next(ring, item);
 
         FOREACH_CLIENT(display, link, next, dcc) {
-            StreamAgent *agent = dcc_get_stream_agent(dcc, get_stream_id(display, stream));
+            StreamAgent *agent = dcc_get_stream_agent(dcc, display_channel_get_stream_id(display, stream));
 
             if (region_intersects(&agent->vis_region, region)) {
                 dcc_detach_stream_gracefully(dcc, stream, drawable);
                 detach = 1;
-                spice_debug("stream %d", get_stream_id(display, stream));
+                spice_debug("stream %d", display_channel_get_stream_id(display, stream));
             }
         }
         if (detach && stream->current) {
@@ -960,7 +961,7 @@ void stream_detach_and_stop(DisplayChannel *display)
     RingItem *stream_item;
 
     spice_debug(NULL);
-    while ((stream_item = ring_get_head(&display->streams))) {
+    while ((stream_item = ring_get_head(&display->priv->streams))) {
         Stream *stream = SPICE_CONTAINEROF(stream_item, Stream, link);
 
         detach_stream_gracefully(display, stream, NULL);
@@ -970,7 +971,7 @@ void stream_detach_and_stop(DisplayChannel *display)
 
 void stream_timeout(DisplayChannel *display)
 {
-    Ring *ring = &display->streams;
+    Ring *ring = &display->priv->streams;
     RingItem *item;
 
     red_time_t now = spice_get_monotonic_time_ns();
@@ -993,7 +994,7 @@ void stream_trace_add_drawable(DisplayChannel *display, Drawable *item)
         return;
     }
 
-    trace = &display->items_trace[display->next_item_trace++ & ITEMS_TRACE_MASK];
+    trace = &display->priv->items_trace[display->priv->next_item_trace++ & ITEMS_TRACE_MASK];
     trace->time = item->creation_time;
     trace->first_frame_time = item->first_frame_time;
     trace->frames_count = item->frames_count;
-- 
2.7.4

_______________________________________________
Spice-devel mailing list
Spice-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/spice-devel





[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]     [Monitors]