--- server/red_worker.c | 99 +++++++++++++++++++++++++++++--------------------- 1 files changed, 57 insertions(+), 42 deletions(-)
diff --git a/server/red_worker.c b/server/red_worker.c index 3fbc7d1..c2e1623 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -1194,7 +1194,7 @@ static void red_pipe_add_verb(RedChannelClient* rcc, uint16_t verb) } static inline void red_create_surface_item(DisplayChannelClient *dcc, int surface_id); -static void red_add_surface_image(RedWorker *worker, int surface_id); +static void red_push_surface_image(DisplayChannelClient *dcc, int surface_id); static void red_pipes_add_verb(RedChannel *channel, uint16_t verb) { RedChannelClient *rcc = channel->rcc; @@ -1230,7 +1230,7 @@ static inline void red_handle_drawable_surfaces_client_synced( } red_create_surface_item(dcc, surface_id); red_current_flush(&worker->render, surface_id); - red_add_surface_image(worker, surface_id); + red_push_surface_image(dcc, surface_id); } } @@ -1240,7 +1240,7 @@ static inline void red_handle_drawable_surfaces_client_synced( red_create_surface_item(dcc, drawable->surface_id); red_current_flush(&worker->render, drawable->surface_id); - red_add_surface_image(worker, drawable->surface_id); + red_push_surface_image(dcc, drawable->surface_id); } static int display_is_connected(RedWorker *worker) @@ -1310,23 +1310,23 @@ static inline void red_pipe_remove_drawable(DisplayChannelClient *dcc, Drawable } } -static inline void red_pipe_add_image_item(RedWorker *worker, ImageItem *item) +static inline void red_pipe_add_image_item(DisplayChannelClient *dcc, ImageItem *item) { - if (!display_is_connected(worker)) { + if (!dcc) { return; } item->refs++; - red_channel_client_pipe_add(worker->display_channel->common.base.rcc, &item->link); + red_channel_client_pipe_add(&dcc->common.base, &item->link); } -static inline void red_pipe_add_image_item_after(RedWorker *worker, ImageItem *item, +static inline void red_pipe_add_image_item_after(DisplayChannelClient *dcc, ImageItem *item, PipeItem *pos) { - if (!display_is_connected(worker)) { + if (!dcc) { return; } item->refs++; - red_channel_client_pipe_add_after(worker->display_channel->common.base.rcc, &item->link, pos); + red_channel_client_pipe_add_after(&dcc->common.base, &item->link, pos); } static void release_image_item(ImageItem *item) @@ -2655,27 +2655,23 @@ static void reset_rate(DisplayChannelClient *dcc, StreamAgent *stream_agent) /* MJpeg has no rate limiting anyway, so do nothing */ } -static int display_channel_is_low_bandwidth(DisplayChannel *display_channel) +static int display_channel_is_low_bandwidth(DisplayChannelClient *dcc) { - if (display_channel->common.base.rcc) { - if (main_channel_client_is_low_bandwidth( - red_client_get_main(display_channel->common.base.rcc->client))) { - return TRUE; - } - } - return FALSE; + RedChannelClient *rcc = &dcc->common.base; + + return dcc && main_channel_client_is_low_bandwidth( + red_client_get_main(red_channel_client_get_client(rcc))); } static inline void pre_stream_item_swap(RedRender *render, Stream *stream) { - RedWorker *worker = render->worker; DisplayChannelClient *dcc = render->dcc; int index; StreamAgent *agent; ASSERT(stream->current); - if (!dcc || !display_channel_is_low_bandwidth(worker->display_channel)) { + if (!dcc || !display_channel_is_low_bandwidth(dcc)) { return; } @@ -4286,6 +4282,14 @@ static CursorItem *get_cursor_item(RedWorker *worker, RedCursorCmd *cmd, uint32_ return cursor_item; } +static PipeItem *ref_cursor_pipe_item(RedChannelClient *rcc, void *data, int num) +{ + CursorItem *cursor_item = data; + + cursor_item->refs += (num != 0); /* we already reference the first use */ + return &cursor_item->pipe_data; +} + static void qxl_process_cursor(RedWorker *worker, RedCursorCmd *cursor_cmd, uint32_t group_id) { CursorItem *item; @@ -4320,9 +4324,10 @@ static void qxl_process_cursor(RedWorker *worker, RedCursorCmd *cursor_cmd, uint red_error("invalid cursor command %u", cursor_cmd->type); } - if (worker->cursor_channel && (worker->mouse_mode == SPICE_MOUSE_MODE_SERVER || + if (cursor_is_connected(worker) && (worker->mouse_mode == SPICE_MOUSE_MODE_SERVER || cursor_cmd->type != QXL_CURSOR_MOVE || cursor_show)) { - red_channel_client_pipe_add(worker->cursor_channel->common.base.rcc, &item->pipe_data); + red_channel_pipes_new_add(&worker->cursor_channel->common.base, ref_cursor_pipe_item, + (void*)item); } else { red_release_cursor(worker, item); } @@ -4497,29 +4502,35 @@ static void red_current_flush(RedRender *render, int surface_id) } // adding the pipe item after pos. If pos == NULL, adding to head. -static ImageItem *red_add_surface_area_image(RedWorker *worker, int surface_id, SpiceRect *area, +static ImageItem *red_add_surface_area_image(RedRender *render, int surface_id, SpiceRect *area, PipeItem *pos, int can_lossy) { + DisplayChannelClient *dcc = render->dcc; + RedWorker *worker = dcc ? DCC_TO_WORKER(dcc) : NULL; + DisplayChannel *display_channel = worker ? worker->display_channel : NULL; + RedChannel *channel = &display_channel->common.base; + RedSurface *surface = &render->surfaces[surface_id]; + SpiceCanvas *canvas = surface->context.canvas; ImageItem *item; int stride; int width; int height; - RedSurface *surface = &worker->render.surfaces[surface_id]; - SpiceCanvas *canvas = surface->context.canvas; int bpp; int all_set; ASSERT(area); + if (!dcc) { + return NULL; + } width = area->right - area->left; height = area->bottom - area->top; bpp = SPICE_SURFACE_FMT_DEPTH(surface->context.format) / 8; - stride = SPICE_ALIGN(width * bpp, 4); - + stride = SPICE_ALIGN(width * bpp, 4); + item = (ImageItem *)spice_malloc_n_m(height, stride, sizeof(ImageItem)); - red_channel_pipe_item_init(&worker->display_channel->common.base, - &item->link, PIPE_ITEM_TYPE_IMAGE); + red_channel_pipe_item_init(channel, &item->link, PIPE_ITEM_TYPE_IMAGE); item->refs = 1; item->surface_id = surface_id; @@ -4549,9 +4560,9 @@ static ImageItem *red_add_surface_area_image(RedWorker *worker, int surface_id, } if (!pos) { - red_pipe_add_image_item(worker, item); + red_pipe_add_image_item(dcc, item); } else { - red_pipe_add_image_item_after(worker, item, pos); + red_pipe_add_image_item_after(dcc, item, pos); } release_image_item(item); @@ -4559,25 +4570,28 @@ static ImageItem *red_add_surface_area_image(RedWorker *worker, int surface_id, return item; } -static void red_add_surface_image(RedWorker *worker, int surface_id) +static void red_push_surface_image(DisplayChannelClient *dcc, int surface_id) { SpiceRect area; RedSurface *surface; + RedRender *render; - surface = &worker->render.surfaces[surface_id]; - - if (!display_is_connected(worker) || !surface->context.canvas) { + if (!dcc) { + return; + } + render = dcc->common.render; + surface = &render->surfaces[surface_id]; + if (!surface->context.canvas) { return; } - area.top = area.left = 0; area.right = surface->context.width; area.bottom = surface->context.height; /* not allowing lossy compression because probably, especially if it is a primary surface, it combines both "picture-like" areas with areas that are more "artificial"*/ - red_add_surface_area_image(worker, surface_id, &area, NULL, FALSE); - red_channel_push(&worker->display_channel->common.base); + red_add_surface_area_image(render, surface_id, &area, NULL, FALSE); + red_channel_client_push(&dcc->common.base); } typedef struct { @@ -6376,8 +6390,10 @@ static void red_pipe_replace_rendered_drawables_with_images(RedWorker *worker, int first_surface_id, SpiceRect *first_area) { + /* TODO: can't have those statics with multiple clients */ static int resent_surface_ids[MAX_PIPE_SIZE]; static SpiceRect resent_areas[MAX_PIPE_SIZE]; // not pointers since drawbales may be released + RedRender *render = dcc->common.render; int num_resent; PipeItem *pipe_item; Ring *pipe; @@ -6411,7 +6427,7 @@ static void red_pipe_replace_rendered_drawables_with_images(RedWorker *worker, continue; } - image = red_add_surface_area_image(worker, drawable->red_drawable->surface_id, + image = red_add_surface_area_image(render, drawable->red_drawable->surface_id, &drawable->red_drawable->bbox, pipe_item, TRUE); resent_surface_ids[num_resent] = drawable->red_drawable->surface_id; resent_areas[num_resent] = drawable->red_drawable->bbox; @@ -6468,7 +6484,7 @@ static void red_add_lossless_drawable_dependencies(RedWorker *worker, // the surfaces areas will be sent as DRAW_COPY commands, that // will be executed before the current drawable for (i = 0; i < num_deps; i++) { - red_add_surface_area_image(worker, deps_surfaces_ids[i], deps_areas[i], + red_add_surface_area_image(render, deps_surfaces_ids[i], deps_areas[i], red_pipe_get_tail(dcc), FALSE); } @@ -6489,7 +6505,7 @@ static void red_add_lossless_drawable_dependencies(RedWorker *worker, &drawable->bbox); } - red_add_surface_area_image(worker, drawable->surface_id, &drawable->bbox, + red_add_surface_area_image(render, drawable->surface_id, &drawable->bbox, red_pipe_get_tail(dcc), TRUE); } } @@ -8824,7 +8840,6 @@ static int display_channel_wait_for_init(DisplayChannelClient *dcc) static void on_new_display_channel_client(DisplayChannelClient *dcc) { DisplayChannel *display_channel = DCC_TO_DC(dcc); - RedWorker *worker = display_channel->common.worker; RedRender *render = dcc->common.render; RedChannelClient *rcc = &dcc->common.base; @@ -8842,7 +8857,7 @@ static void on_new_display_channel_client(DisplayChannelClient *dcc) if (render->surfaces[0].context.canvas) { red_current_flush(render, 0); push_new_primary_surface(dcc); - red_add_surface_image(worker, 0); + red_push_surface_image(dcc, 0); if (red_channel_is_connected(&display_channel->common.base)) { red_pipe_add_verb(rcc, SPICE_MSG_DISPLAY_MARK); red_disply_start_streams(dcc); -- 1.7.5.1 _______________________________________________ Spice-devel mailing list Spice-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/spice-devel