[Spice-devel] [PATCH 10/16] worker: move drawable to display

Frediano Ziglio fziglio at redhat.com
Wed Nov 11 02:05:23 PST 2015


> 
> On Tue, 2015-11-10 at 11:42 -0600, Jonathon Jongsma wrote:
> > I'd like to propose splitting out the changes related to UpgradeItem since
> > they're not really related. I'll post a split patch.
> 
> 
> Hmm, nevermind. Now that I look at it again, the only 'unrelated' UpgradeItem
> change is that release_upgrade_item() is renamed to upgrade_item_unref(). But
> the signature of this function needs to change to accept a DisplayChannel*
> instead of a RedWorker*, so I think it's OK to change the name at the same
> time.
> 
> So I'd ACK this patch.
> 
> 

Merged

Frediano

> 
> 
> > 
> > 
> > 
> > On Tue, 2015-11-10 at 14:16 +0000, Frediano Ziglio wrote:
> > > From: Marc-André Lureau <marcandre.lureau at gmail.com>
> > > 
> > > ---
> > >  server/display-channel.h |  24 ++++++++--
> > >  server/red_worker.c      | 118
> > >  ++++++++++++++++++++++----------------------
> > > --
> > > -
> > >  2 files changed, 74 insertions(+), 68 deletions(-)
> > > 
> > > diff --git a/server/display-channel.h b/server/display-channel.h
> > > index 898ff01..1566c21 100644
> > > --- a/server/display-channel.h
> > > +++ b/server/display-channel.h
> > > @@ -273,6 +273,15 @@ void                       monitors_config_unref
> > >   
> > >             (MonitorsCo
> > >  #define NUM_TRACE_ITEMS (1 << TRACE_ITEMS_SHIFT)
> > >  #define ITEMS_TRACE_MASK (NUM_TRACE_ITEMS - 1)
> > >  
> > > +#define NUM_DRAWABLES 1000
> > > +typedef struct _Drawable _Drawable;
> > > +struct _Drawable {
> > > +    union {
> > > +        Drawable drawable;
> > > +        _Drawable *next;
> > > +    } u;
> > > +};
> > > +
> > >  struct DisplayChannel {
> > >      CommonChannel common; // Must be the first thing
> > >  
> > > @@ -281,16 +290,17 @@ struct DisplayChannel {
> > >      uint32_t num_renderers;
> > >      uint32_t renderers[RED_RENDERER_LAST];
> > >      uint32_t renderer;
> > > -
> > > -    Ring current_list; // of TreeItem
> > > -    uint32_t current_size;
> > > -
> > >      int enable_jpeg;
> > >      int jpeg_quality;
> > >      int enable_zlib_glz_wrap;
> > >      int zlib_level;
> > >  
> > > -    RedCompressBuf *free_compress_bufs;
> > > +    Ring current_list; // of TreeItem
> > > +    uint32_t current_size;
> > > +
> > > +    uint32_t drawable_count;
> > > +    _Drawable drawables[NUM_DRAWABLES];
> > > +    _Drawable *free_drawables;
> > >  
> > >      int stream_video;
> > >      uint32_t stream_count;
> > > @@ -302,6 +312,7 @@ struct DisplayChannel {
> > >      uint64_t streams_size_total;
> > >  
> > >      ImageCache image_cache;
> > > +    RedCompressBuf *free_compress_bufs;
> > >  
> > >  #ifdef RED_STATISTICS
> > >      uint64_t *cache_hits_counter;
> > > @@ -344,5 +355,8 @@ void
> > > display_channel_attach_stream
> > >   
> > >            (DisplayCha
> > >  int                        display_channel_get_streams_timeout
> > >  (DisplayChannel *display);
> > >  void                       display_channel_compress_stats_print
> > >  (const
> > > DisplayChannel *display);
> > >  void                       display_channel_compress_stats_reset
> > >  (DisplayChannel *display);
> > > +void                       display_channel_drawable_unref
> > >  (DisplayChannel *display, Drawable *drawable);
> > > +
> > > +
> > >  
> > >  #endif /* DISPLAY_CHANNEL_H_ */
> > > diff --git a/server/red_worker.c b/server/red_worker.c
> > > index 86ce7a1..23c54e8 100644
> > > --- a/server/red_worker.c
> > > +++ b/server/red_worker.c
> > > @@ -300,14 +300,6 @@ struct RedGlzDrawable {
> > >  pthread_mutex_t glz_dictionary_list_lock = PTHREAD_MUTEX_INITIALIZER;
> > >  Ring glz_dictionary_list = {&glz_dictionary_list, &glz_dictionary_list};
> > >  
> > > -typedef struct _Drawable _Drawable;
> > > -struct _Drawable {
> > > -    union {
> > > -        Drawable drawable;
> > > -        _Drawable *next;
> > > -    } u;
> > > -};
> > > -
> > >  typedef struct DrawContext {
> > >      SpiceCanvas *canvas;
> > >      int canvas_draws_on_surface;
> > > @@ -332,8 +324,6 @@ typedef struct RedSurface {
> > >      QXLReleaseInfoExt create, destroy;
> > >  } RedSurface;
> > >  
> > > -#define NUM_DRAWABLES 1000
> > > -
> > >  typedef struct RedWorker {
> > >      pthread_t thread;
> > >      clockid_t clockid;
> > > @@ -354,14 +344,10 @@ typedef struct RedWorker {
> > >      uint32_t n_surfaces;
> > >      SpiceImageSurfaces image_surfaces;
> > >  
> > > -    uint32_t drawable_count;
> > >      uint32_t red_drawable_count;
> > >      uint32_t glz_drawable_count;
> > >      uint32_t bits_unique;
> > >  
> > > -    _Drawable drawables[NUM_DRAWABLES];
> > > -    _Drawable *free_drawables;
> > > -
> > >      RedMemSlotInfo mem_slots;
> > >  
> > >      SpiceImageCompression image_compression;
> > > @@ -435,7 +421,6 @@ static void red_draw_drawable(RedWorker *worker,
> > > Drawable
> > > *item);
> > >  static void red_update_area(RedWorker *worker, const SpiceRect *area,
> > >  int
> > > surface_id);
> > >  static void red_update_area_till(RedWorker *worker, const SpiceRect
> > >  *area,
> > > int surface_id,
> > >                                   Drawable *last);
> > > -static void red_worker_drawable_unref(RedWorker *worker, Drawable
> > > *drawable);
> > >  static void detach_stream(DisplayChannel *display, Stream *stream, int
> > > detach_sized);
> > >  static inline void display_channel_stream_maintenance(DisplayChannel
> > > *display, Drawable *candidate, Drawable *sect);
> > >  static inline void display_begin_send_message(RedChannelClient *rcc);
> > > @@ -635,7 +620,7 @@ DrawablePipeItem
> > > *drawable_pipe_item_ref(DrawablePipeItem
> > > *dpi)
> > >  
> > >  void drawable_pipe_item_unref(DrawablePipeItem *dpi)
> > >  {
> > > -    RedWorker *worker = DCC_TO_WORKER(dpi->dcc);
> > > +    DisplayChannel *display = DCC_TO_DC(dpi->dcc);
> > >  
> > >      if (--dpi->refs != 0) {
> > >          return;
> > > @@ -643,7 +628,7 @@ void drawable_pipe_item_unref(DrawablePipeItem *dpi)
> > >  
> > >      spice_warn_if_fail(!ring_item_is_linked(&dpi->dpi_pipe_item.link));
> > >      spice_warn_if_fail(!ring_item_is_linked(&dpi->base));
> > > -    red_worker_drawable_unref(worker, dpi->drawable);
> > > +    display_channel_drawable_unref(display, dpi->drawable);
> > >      free(dpi);
> > >  }
> > >  
> > > @@ -869,12 +854,12 @@ static void release_image_item(ImageItem *item)
> > >      }
> > >  }
> > >  
> > > -static void release_upgrade_item(RedWorker* worker, UpgradeItem *item)
> > > +static void upgrade_item_unref(DisplayChannel *display, UpgradeItem
> > > *item)
> > >  {
> > >      if (--item->refs != 0)
> > >          return;
> > >  
> > > -    red_worker_drawable_unref(worker, item->drawable);
> > > +    display_channel_drawable_unref(display, item->drawable);
> > >      free(item->rects);
> > >      free(item);
> > >  }
> > > @@ -912,30 +897,33 @@ static void
> > > red_reset_palette_cache(DisplayChannelClient
> > > *dcc)
> > >      red_palette_cache_reset(dcc, CLIENT_PALETTE_CACHE_SIZE);
> > >  }
> > >  
> > > -static inline Drawable *alloc_drawable(RedWorker *worker)
> > > +static Drawable* drawable_try_new(DisplayChannel *display)
> > >  {
> > >      Drawable *drawable;
> > > -    if (!worker->free_drawables) {
> > > +
> > > +    if (!display->free_drawables)
> > >          return NULL;
> > > -    }
> > > -    drawable = &worker->free_drawables->u.drawable;
> > > -    worker->free_drawables = worker->free_drawables->u.next;
> > > +
> > > +    drawable = &display->free_drawables->u.drawable;
> > > +    display->free_drawables = display->free_drawables->u.next;
> > > +    display->drawable_count++;
> > > +
> > >      return drawable;
> > >  }
> > >  
> > > -static inline void free_drawable(RedWorker *worker, Drawable *item)
> > > +static void drawable_free(DisplayChannel *display, Drawable *drawable)
> > >  {
> > > -    ((_Drawable *)item)->u.next = worker->free_drawables;
> > > -    worker->free_drawables = (_Drawable *)item;
> > > +    ((_Drawable *)drawable)->u.next = display->free_drawables;
> > > +    display->free_drawables = (_Drawable *)drawable;
> > >  }
> > >  
> > > -static void drawables_init(RedWorker *worker)
> > > +static void drawables_init(DisplayChannel *display)
> > >  {
> > >      int i;
> > >  
> > > -    worker->free_drawables = NULL;
> > > +    display->free_drawables = NULL;
> > >      for (i = 0; i < NUM_DRAWABLES; i++) {
> > > -        free_drawable(worker, &worker->drawables[i].u.drawable);
> > > +        drawable_free(display, &display->drawables[i].u.drawable);
> > >      }
> > >  }
> > >  
> > > @@ -1031,7 +1019,7 @@ static void remove_depended_item(DependItem *item)
> > >      ring_remove(&item->ring_item);
> > >  }
> > >  
> > > -static void drawable_unref_surface_deps(RedWorker *worker, Drawable
> > > *drawable)
> > > +static void drawable_unref_surface_deps(DisplayChannel *display,
> > > Drawable
> > > *drawable)
> > >  {
> > >      int x;
> > >      int surface_id;
> > > @@ -1041,11 +1029,11 @@ static void drawable_unref_surface_deps(RedWorker
> > > *worker, Drawable *drawable)
> > >          if (surface_id == -1) {
> > >              continue;
> > >          }
> > > -        red_surface_unref(worker, surface_id);
> > > +        red_surface_unref(COMMON_CHANNEL(display)->worker, surface_id);
> > >      }
> > >  }
> > >  
> > > -static void remove_drawable_dependencies(RedWorker *worker, Drawable
> > > *drawable)
> > > +static void drawable_remove_dependencies(DisplayChannel *display,
> > > Drawable
> > > *drawable)
> > >  {
> > >      int x;
> > >      int surface_id;
> > > @@ -1058,7 +1046,7 @@ static void remove_drawable_dependencies(RedWorker
> > > *worker, Drawable *drawable)
> > >      }
> > >  }
> > >  
> > > -static void red_worker_drawable_unref(RedWorker *worker, Drawable
> > > *drawable)
> > > +void display_channel_drawable_unref(DisplayChannel *display, Drawable
> > > *drawable)
> > >  {
> > >      RingItem *item, *next;
> > >  
> > > @@ -1069,21 +1057,21 @@ static void red_worker_drawable_unref(RedWorker
> > > *worker, Drawable *drawable)
> > >      spice_warn_if_fail(ring_is_empty(&drawable->pipes));
> > >  
> > >      if (drawable->stream) {
> > > -        detach_stream(worker->display_channel, drawable->stream, TRUE);
> > > +        detach_stream(display, drawable->stream, TRUE);
> > >      }
> > >      region_destroy(&drawable->tree_item.base.rgn);
> > >  
> > > -    remove_drawable_dependencies(worker, drawable);
> > > -    drawable_unref_surface_deps(worker, drawable);
> > > -    red_surface_unref(worker, drawable->surface_id);
> > > +    drawable_remove_dependencies(display, drawable);
> > > +    drawable_unref_surface_deps(display, drawable);
> > > +    red_surface_unref(COMMON_CHANNEL(display)->worker, drawable
> > > ->surface_id);
> > >  
> > >      RING_FOREACH_SAFE(item, next, &drawable->glz_ring) {
> > >          SPICE_CONTAINEROF(item, RedGlzDrawable, drawable_link)->drawable
> > >          =
> > > NULL;
> > >          ring_remove(item);
> > >      }
> > > -    red_drawable_unref(worker, drawable->red_drawable,
> > > drawable->group_id);
> > > -    free_drawable(worker, drawable);
> > > -    worker->drawable_count--;
> > > +    red_drawable_unref(COMMON_CHANNEL(display)->worker, drawable
> > > ->red_drawable, drawable->group_id);
> > > +    drawable_free(display, drawable);
> > > +    display->drawable_count--;
> > >  }
> > >  
> > >  static inline void remove_shadow(DrawItem *item)
> > > @@ -1172,7 +1160,7 @@ static inline void
> > > current_remove_drawable(RedWorker
> > > *worker, Drawable *item)
> > >      ring_remove(&item->tree_item.base.siblings_link);
> > >      ring_remove(&item->list_link);
> > >      ring_remove(&item->surface_list_link);
> > > -    red_worker_drawable_unref(worker, item);
> > > +    display_channel_drawable_unref(display, item);
> > >      display->current_size--;
> > >  }
> > >  
> > > @@ -2334,6 +2322,7 @@ static inline int
> > > is_drawable_independent_from_surfaces(Drawable *drawable)
> > >  
> > >  static inline int red_current_add_equal(RedWorker *worker, DrawItem
> > >  *item,
> > > TreeItem *other)
> > >  {
> > > +    DisplayChannel *display  = worker->display_channel;
> > >      DrawItem *other_draw_item;
> > >      Drawable *drawable;
> > >      Drawable *other_drawable;
> > > @@ -2363,7 +2352,7 @@ static inline int red_current_add_equal(RedWorker
> > > *worker, DrawItem *item, TreeI
> > >              red_pipes_add_drawable(worker, drawable);
> > >          }
> > >          red_pipes_remove_drawable(other_drawable);
> > > -        red_worker_drawable_unref(worker, other_drawable);
> > > +        display_channel_drawable_unref(display, other_drawable);
> > >          return TRUE;
> > >      }
> > >  
> > > @@ -2406,7 +2395,7 @@ static inline int red_current_add_equal(RedWorker
> > > *worker, DrawItem *item, TreeI
> > >              /* not sending other_drawable where possible */
> > >              red_pipes_remove_drawable(other_drawable);
> > >  
> > > -            red_worker_drawable_unref(worker, other_drawable);
> > > +            display_channel_drawable_unref(display, other_drawable);
> > >              return TRUE;
> > >          }
> > >          break;
> > > @@ -2879,6 +2868,7 @@ static bool free_one_drawable(RedWorker *worker,
> > > int
> > > force_glz_free)
> > >  static Drawable *get_drawable(RedWorker *worker, uint8_t effect,
> > > RedDrawable
> > > *red_drawable,
> > >                                uint32_t group_id)
> > >  {
> > > +    DisplayChannel *display = worker->display_channel;
> > >      Drawable *drawable;
> > >      int x;
> > >  
> > > @@ -2893,12 +2883,12 @@ static Drawable *get_drawable(RedWorker *worker,
> > > uint8_t effect, RedDrawable *re
> > >          }
> > >      }
> > >  
> > > -    while (!(drawable = alloc_drawable(worker))) {
> > > -        if (!free_one_drawable(worker, FALSE))
> > > +    while (!(drawable = drawable_try_new(display))) {
> > > +        if (!free_one_drawable(COMMON_CHANNEL(display)->worker, FALSE))
> > >              return NULL;
> > >      }
> > > -    worker->drawable_count++;
> > > -    memset(drawable, 0, sizeof(Drawable));
> > > +
> > > +    bzero(drawable, sizeof(Drawable));
> > >      drawable->refs = 1;
> > >      drawable->creation_time = red_get_monotonic_time();
> > >      ring_item_init(&drawable->list_link);
> > > @@ -2995,6 +2985,7 @@ static inline void
> > > red_inc_surfaces_drawable_dependencies(RedWorker *worker, Dra
> > >  static inline void red_process_draw(RedWorker *worker, RedDrawable
> > > *red_drawable,
> > >                                      uint32_t group_id)
> > >  {
> > > +    DisplayChannel *display = worker->display_channel;
> > >      int surface_id;
> > >      Drawable *drawable = get_drawable(worker, red_drawable->effect,
> > > red_drawable, group_id);
> > >  
> > > @@ -3045,7 +3036,7 @@ static inline void red_process_draw(RedWorker
> > > *worker,
> > > RedDrawable *red_drawable
> > >          red_pipes_add_drawable(worker, drawable);
> > >      }
> > >  cleanup:
> > > -    red_worker_drawable_unref(worker, drawable);
> > > +    display_channel_drawable_unref(display, drawable);
> > >  }
> > >  
> > >  static inline void red_create_surface(RedWorker *worker, uint32_t
> > > surface_id,uint32_t width,
> > > @@ -3374,13 +3365,14 @@ static void red_update_area_till(RedWorker
> > > *worker,
> > > const SpiceRect *area, int s
> > >             that red_update_area is called for, Otherwise, 'now' would
> > >             have
> > > already been rendered.
> > >             See the call for red_handle_depends_on_target_surface in
> > > red_process_draw */
> > >          red_draw_drawable(worker, now);
> > > -        red_worker_drawable_unref(worker, now);
> > > +        display_channel_drawable_unref(display, now);
> > >      } while (now != surface_last);
> > >      validate_area(worker, area, surface_id);
> > >  }
> > >  
> > >  static void red_update_area(RedWorker *worker, const SpiceRect *area,
> > >  int
> > > surface_id)
> > >  {
> > > +    DisplayChannel *display = worker->display_channel;
> > >      RedSurface *surface;
> > >      Ring *ring;
> > >      RingItem *ring_item;
> > > @@ -3427,7 +3419,7 @@ static void red_update_area(RedWorker *worker,
> > > const
> > > SpiceRect *area, int surfac
> > >          current_remove_drawable(worker, now);
> > >          container_cleanup(worker, container);
> > >          red_draw_drawable(worker, now);
> > > -        red_worker_drawable_unref(worker, now);
> > > +        display_channel_drawable_unref(display, now);
> > >      } while (now != last);
> > >      validate_area(worker, area, surface_id);
> > >  }
> > > @@ -3612,7 +3604,7 @@ static void red_free_some(RedWorker *worker)
> > >      DisplayChannelClient *dcc;
> > >      RingItem *item, *next;
> > >  
> > > -    spice_debug("#draw=%d, #red_draw=%d, #glz_draw=%d", worker
> > > ->drawable_count,
> > > +    spice_debug("#draw=%d, #red_draw=%d, #glz_draw=%d", display
> > > ->drawable_count,
> > >                  worker->red_drawable_count, worker->glz_drawable_count);
> > >      FOREACH_DCC(worker->display_channel, item, next, dcc) {
> > >          GlzSharedDictionary *glz_dict = dcc ? dcc->glz_dict : NULL;
> > > @@ -7579,7 +7571,7 @@ void red_show_tree(RedWorker *worker)
> > >  
> > >  static void display_channel_client_on_disconnect(RedChannelClient *rcc)
> > >  {
> > > -    DisplayChannel *display_channel;
> > > +    DisplayChannel *display;
> > >      DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
> > >      CommonChannel *common;
> > >      RedWorker *worker;
> > > @@ -7590,9 +7582,9 @@ static void
> > > display_channel_client_on_disconnect(RedChannelClient *rcc)
> > >      spice_info(NULL);
> > >      common = SPICE_CONTAINEROF(rcc->channel, CommonChannel, base);
> > >      worker = common->worker;
> > > -    display_channel = (DisplayChannel *)rcc->channel;
> > > -    spice_assert(display_channel == worker->display_channel);
> > > -    display_channel_compress_stats_print(display_channel);
> > > +    display = (DisplayChannel *)rcc->channel;
> > > +    spice_assert(display == worker->display_channel);
> > > +    display_channel_compress_stats_print(display);
> > >      pixmap_cache_unref(dcc->pixmap_cache);
> > >      dcc->pixmap_cache = NULL;
> > >      red_release_glz(dcc);
> > > @@ -7604,10 +7596,10 @@ static void
> > > display_channel_client_on_disconnect(RedChannelClient *rcc)
> > >  
> > >      // this was the last channel client
> > >      if (!red_channel_is_connected(rcc->channel)) {
> > > -        red_display_destroy_compress_bufs(display_channel);
> > > +        red_display_destroy_compress_bufs(display);
> > >      }
> > >      spice_debug("#draw=%d, #red_draw=%d, #glz_draw=%d",
> > > -                worker->drawable_count, worker->red_drawable_count,
> > > +                display->drawable_count, worker->red_drawable_count,
> > >                  worker->glz_drawable_count);
> > >  }
> > >  
> > > @@ -8658,7 +8650,7 @@ static void
> > > display_channel_client_release_item_after_push(DisplayChannelClient
> > >          display_stream_clip_unref(display, (StreamClipItem *)item);
> > >          break;
> > >      case PIPE_ITEM_TYPE_UPGRADE:
> > > -        release_upgrade_item(DCC_TO_WORKER(dcc), (UpgradeItem *)item);
> > > +        upgrade_item_unref(display, (UpgradeItem *)item);
> > >          break;
> > >      case PIPE_ITEM_TYPE_IMAGE:
> > >          release_image_item((ImageItem *)item);
> > > @@ -8706,7 +8698,7 @@ static void
> > > display_channel_client_release_item_before_push(DisplayChannelClient
> > >          break;
> > >      }
> > >      case PIPE_ITEM_TYPE_UPGRADE:
> > > -        release_upgrade_item(DCC_TO_WORKER(dcc), (UpgradeItem *)item);
> > > +        upgrade_item_unref(display, (UpgradeItem *)item);
> > >          break;
> > >      case PIPE_ITEM_TYPE_IMAGE:
> > >          release_image_item((ImageItem *)item);
> > > @@ -8818,6 +8810,7 @@ static void display_channel_create(RedWorker
> > > *worker,
> > > int migrate)
> > >      init_streams(display_channel);
> > >      image_cache_init(&display_channel->image_cache);
> > >      ring_init(&display_channel->current_list);
> > > +    drawables_init(display_channel);
> > >  }
> > >  
> > >  static void guest_set_client_capabilities(RedWorker *worker)
> > > @@ -9378,7 +9371,7 @@ static void handle_dev_oom(void *opaque, void
> > > *payload)
> > >      spice_assert(worker->running);
> > >      // streams? but without streams also leak
> > >      spice_debug("OOM1 #draw=%u, #red_draw=%u, #glz_draw=%u current %u
> > >      pipes
> > > %u",
> > > -                worker->drawable_count,
> > > +                display->drawable_count,
> > >                  worker->red_drawable_count,
> > >                  worker->glz_drawable_count,
> > >                  display->current_size,
> > > @@ -9392,7 +9385,7 @@ static void handle_dev_oom(void *opaque, void
> > > *payload)
> > >          worker->qxl->st->qif->flush_resources(worker->qxl);
> > >      }
> > >      spice_debug("OOM2 #draw=%u, #red_draw=%u, #glz_draw=%u current %u
> > >      pipes
> > > %u",
> > > -                worker->drawable_count,
> > > +                display->drawable_count,
> > >                  worker->red_drawable_count,
> > >                  worker->glz_drawable_count,
> > >                  display->current_size,
> > > @@ -9943,7 +9936,6 @@ RedWorker* red_worker_new(QXLInstance *qxl,
> > > RedDispatcher *red_dispatcher)
> > >      worker->zlib_glz_state = zlib_glz_state;
> > >      worker->driver_cap_monitors_config = 0;
> > >      image_surface_init(worker);
> > > -    drawables_init(worker);
> > >      stat_init(&worker->add_stat, add_stat_name);
> > >      stat_init(&worker->exclude_stat, exclude_stat_name);
> > >      stat_init(&worker->__exclude_stat, __exclude_stat_name);


More information about the Spice-devel mailing list