[Spice-devel] [PATCH 02/10] Add DisplayChannelPrivate struct
Jonathon Jongsma
jjongsma at redhat.com
Fri Sep 9 14:54:37 UTC 2016
On Fri, 2016-09-09 at 09:37 +0200, Pavel Grunt wrote:
> Hi,
>
> I guess the "1-element array trick" can be used to avoid leak of
> "priv" in these patches as well.
>
> Pavel
Indeed, I forgot to change these. Thanks.
>
> On Thu, 2016-09-08 at 11:52 -0500, Jonathon Jongsma wrote:
> >
> > 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(disp
> > l
> > ay, 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_CHA
> > N
> > NEL_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_CLIEN
> > T
> > (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.or
> > g
> > /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_equ
> > a
> > l(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,
> > ©.src_bitmap, &img1, drawable);
> > - image_cache_localize_mask(&display->image_cache,
> > ©.mask, &img2);
> > + image_cache_localize(&display->priv->image_cache,
> > ©.src_bitmap, &img1, drawable);
> > + image_cache_localize_mask(&display->priv->image_cache,
> > ©.mask, &img2);
> > canvas->ops->draw_copy(canvas, &drawable->red_drawable-
> > >
> > > bbox,
> > &clip, ©);
> > 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(disp
> > l
> > ay, 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_hi
> > t
> > s", 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_REPO
> > R
> > T);
> > - 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;
> >
More information about the Spice-devel
mailing list