mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2025-12-27 15:45:54 +00:00
worker: move dcc_add_drawable*
Acked-by: Fabiano Fidêncio <fidencio@redhat.com>
This commit is contained in:
parent
1549f751b8
commit
6df1558523
87
server/dcc.c
87
server/dcc.c
@ -155,6 +155,93 @@ void dcc_push_surface_image(DisplayChannelClient *dcc, int surface_id)
|
||||
red_channel_client_push(RED_CHANNEL_CLIENT(dcc));
|
||||
}
|
||||
|
||||
static void add_drawable_surface_images(DisplayChannelClient *dcc, Drawable *drawable)
|
||||
{
|
||||
DisplayChannel *display = DCC_TO_DC(dcc);
|
||||
int x;
|
||||
|
||||
for (x = 0; x < 3; ++x) {
|
||||
int surface_id;
|
||||
|
||||
surface_id = drawable->surface_deps[x];
|
||||
if (surface_id != -1) {
|
||||
if (dcc->surface_client_created[surface_id] == TRUE) {
|
||||
continue;
|
||||
}
|
||||
dcc_create_surface(dcc, surface_id);
|
||||
display_channel_current_flush(display, surface_id);
|
||||
dcc_push_surface_image(dcc, surface_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (dcc->surface_client_created[drawable->surface_id] == TRUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
dcc_create_surface(dcc, drawable->surface_id);
|
||||
display_channel_current_flush(display, drawable->surface_id);
|
||||
dcc_push_surface_image(dcc, drawable->surface_id);
|
||||
}
|
||||
|
||||
DrawablePipeItem *drawable_pipe_item_ref(DrawablePipeItem *dpi)
|
||||
{
|
||||
dpi->refs++;
|
||||
return dpi;
|
||||
}
|
||||
|
||||
void drawable_pipe_item_unref(DrawablePipeItem *dpi)
|
||||
{
|
||||
DisplayChannel *display = DCC_TO_DC(dpi->dcc);
|
||||
|
||||
if (--dpi->refs != 0)
|
||||
return;
|
||||
|
||||
spice_warn_if_fail(!ring_item_is_linked(&dpi->dpi_pipe_item.link));
|
||||
spice_warn_if_fail(!ring_item_is_linked(&dpi->base));
|
||||
display_channel_drawable_unref(display, dpi->drawable);
|
||||
free(dpi);
|
||||
}
|
||||
|
||||
static DrawablePipeItem *drawable_pipe_item_new(DisplayChannelClient *dcc, Drawable *drawable)
|
||||
{
|
||||
DrawablePipeItem *dpi;
|
||||
|
||||
dpi = spice_malloc0(sizeof(*dpi));
|
||||
dpi->drawable = drawable;
|
||||
dpi->dcc = dcc;
|
||||
ring_item_init(&dpi->base);
|
||||
ring_add(&drawable->pipes, &dpi->base);
|
||||
red_channel_pipe_item_init(RED_CHANNEL_CLIENT(dcc)->channel,
|
||||
&dpi->dpi_pipe_item, PIPE_ITEM_TYPE_DRAW);
|
||||
dpi->refs++;
|
||||
drawable->refs++;
|
||||
return dpi;
|
||||
}
|
||||
|
||||
void dcc_prepend_drawable(DisplayChannelClient *dcc, Drawable *drawable)
|
||||
{
|
||||
DrawablePipeItem *dpi = drawable_pipe_item_new(dcc, drawable);
|
||||
|
||||
add_drawable_surface_images(dcc, drawable);
|
||||
red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &dpi->dpi_pipe_item);
|
||||
}
|
||||
|
||||
void dcc_append_drawable(DisplayChannelClient *dcc, Drawable *drawable)
|
||||
{
|
||||
DrawablePipeItem *dpi = drawable_pipe_item_new(dcc, drawable);
|
||||
|
||||
add_drawable_surface_images(dcc, drawable);
|
||||
red_channel_client_pipe_add_tail(RED_CHANNEL_CLIENT(dcc), &dpi->dpi_pipe_item);
|
||||
}
|
||||
|
||||
void dcc_add_drawable_after(DisplayChannelClient *dcc, Drawable *drawable, PipeItem *pos)
|
||||
{
|
||||
DrawablePipeItem *dpi = drawable_pipe_item_new(dcc, drawable);
|
||||
|
||||
add_drawable_surface_images(dcc, drawable);
|
||||
red_channel_client_pipe_add_after(RED_CHANNEL_CLIENT(dcc), &dpi->dpi_pipe_item, pos);
|
||||
}
|
||||
|
||||
static void dcc_init_stream_agents(DisplayChannelClient *dcc)
|
||||
{
|
||||
int i;
|
||||
|
||||
18
server/dcc.h
18
server/dcc.h
@ -135,6 +135,17 @@ typedef struct ImageItem {
|
||||
uint8_t data[0];
|
||||
} ImageItem;
|
||||
|
||||
typedef struct DrawablePipeItem {
|
||||
RingItem base; /* link for a list of pipe items held by Drawable */
|
||||
PipeItem dpi_pipe_item; /* link for the client's pipe itself */
|
||||
Drawable *drawable;
|
||||
DisplayChannelClient *dcc;
|
||||
uint8_t refs;
|
||||
} DrawablePipeItem;
|
||||
|
||||
void drawable_pipe_item_unref (DrawablePipeItem *dpi);
|
||||
DrawablePipeItem* drawable_pipe_item_ref (DrawablePipeItem *dpi);
|
||||
|
||||
DisplayChannelClient* dcc_new (DisplayChannel *display,
|
||||
RedClient *client,
|
||||
RedsStream *stream,
|
||||
@ -172,6 +183,13 @@ void dcc_palette_cache_palette (DisplayCha
|
||||
uint8_t *flags);
|
||||
int dcc_pixmap_cache_unlocked_add (DisplayChannelClient *dcc,
|
||||
uint64_t id, uint32_t size, int lossy);
|
||||
void dcc_prepend_drawable (DisplayChannelClient *dcc,
|
||||
Drawable *drawable);
|
||||
void dcc_append_drawable (DisplayChannelClient *dcc,
|
||||
Drawable *drawable);
|
||||
void dcc_add_drawable_after (DisplayChannelClient *dcc,
|
||||
Drawable *drawable,
|
||||
PipeItem *pos);
|
||||
|
||||
typedef struct compress_send_data_t {
|
||||
void* comp_buf;
|
||||
|
||||
@ -325,6 +325,50 @@ static void streams_update_visible_region(DisplayChannel *display, Drawable *dra
|
||||
}
|
||||
}
|
||||
|
||||
static void pipes_add_drawable(DisplayChannel *display, Drawable *drawable)
|
||||
{
|
||||
DisplayChannelClient *dcc;
|
||||
RingItem *dcc_ring_item, *next;
|
||||
|
||||
spice_warn_if(!ring_is_empty(&drawable->pipes));
|
||||
FOREACH_DCC(display, dcc_ring_item, next, dcc) {
|
||||
dcc_prepend_drawable(dcc, drawable);
|
||||
}
|
||||
}
|
||||
|
||||
static void pipes_add_drawable_after(DisplayChannel *display,
|
||||
Drawable *drawable, Drawable *pos_after)
|
||||
{
|
||||
DrawablePipeItem *dpi_pos_after;
|
||||
RingItem *dpi_link, *dpi_next;
|
||||
DisplayChannelClient *dcc;
|
||||
int num_other_linked = 0;
|
||||
|
||||
DRAWABLE_FOREACH_DPI_SAFE(pos_after, dpi_link, dpi_next, dpi_pos_after) {
|
||||
num_other_linked++;
|
||||
dcc_add_drawable_after(dpi_pos_after->dcc, drawable, &dpi_pos_after->dpi_pipe_item);
|
||||
}
|
||||
if (num_other_linked == 0) {
|
||||
pipes_add_drawable(display, drawable);
|
||||
return;
|
||||
}
|
||||
if (num_other_linked != display->common.base.clients_num) {
|
||||
RingItem *item, *next;
|
||||
spice_debug("TODO: not O(n^2)");
|
||||
FOREACH_DCC(display, item, next, dcc) {
|
||||
int sent = 0;
|
||||
DRAWABLE_FOREACH_DPI_SAFE(pos_after, dpi_link, dpi_next, dpi_pos_after) {
|
||||
if (dpi_pos_after->dcc == dcc) {
|
||||
sent = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sent) {
|
||||
dcc_prepend_drawable(dcc, drawable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void current_add_drawable(DisplayChannel *display,
|
||||
Drawable *drawable, RingItem *pos)
|
||||
@ -366,9 +410,9 @@ static int current_add_equal(DisplayChannel *display, DrawItem *item, TreeItem *
|
||||
other_drawable->refs++;
|
||||
current_remove_drawable(display, other_drawable);
|
||||
if (add_after) {
|
||||
red_pipes_add_drawable_after(display, drawable, other_drawable);
|
||||
pipes_add_drawable_after(display, drawable, other_drawable);
|
||||
} else {
|
||||
red_pipes_add_drawable(display, drawable);
|
||||
pipes_add_drawable(display, drawable);
|
||||
}
|
||||
red_pipes_remove_drawable(other_drawable);
|
||||
display_channel_drawable_unref(display, other_drawable);
|
||||
@ -396,7 +440,7 @@ static int current_add_equal(DisplayChannel *display, DrawItem *item, TreeItem *
|
||||
common.base.channel_link);
|
||||
dpi = SPICE_CONTAINEROF(dpi_ring_item, DrawablePipeItem, base);
|
||||
while (worker_ring_item && (!dpi || dcc != dpi->dcc)) {
|
||||
dcc_add_drawable(dcc, drawable);
|
||||
dcc_prepend_drawable(dcc, drawable);
|
||||
worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
|
||||
worker_ring_item);
|
||||
dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
|
||||
@ -423,7 +467,7 @@ static int current_add_equal(DisplayChannel *display, DrawItem *item, TreeItem *
|
||||
current_add_drawable(display, drawable, &other->siblings_link);
|
||||
red_pipes_remove_drawable(other_drawable);
|
||||
current_remove_drawable(display, other_drawable);
|
||||
red_pipes_add_drawable(display, drawable);
|
||||
pipes_add_drawable(display, drawable);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
@ -788,25 +832,26 @@ void display_channel_print_stats(DisplayChannel *display)
|
||||
#endif
|
||||
}
|
||||
|
||||
int display_channel_add_drawable(DisplayChannel *display, Drawable *drawable)
|
||||
void display_channel_add_drawable(DisplayChannel *display, Drawable *drawable)
|
||||
{
|
||||
int ret = FALSE, surface_id = drawable->surface_id;
|
||||
int success = FALSE, surface_id = drawable->surface_id;
|
||||
RedDrawable *red_drawable = drawable->red_drawable;
|
||||
Ring *ring = &display->surfaces[surface_id].current;
|
||||
|
||||
if (has_shadow(red_drawable)) {
|
||||
ret = current_add_with_shadow(display, ring, drawable);
|
||||
success = current_add_with_shadow(display, ring, drawable);
|
||||
} else {
|
||||
drawable->streamable = drawable_can_stream(display, drawable);
|
||||
ret = current_add(display, ring, drawable);
|
||||
success = current_add(display, ring, drawable);
|
||||
}
|
||||
|
||||
if (success)
|
||||
pipes_add_drawable(display, drawable);
|
||||
|
||||
#ifdef RED_WORKER_STAT
|
||||
if ((++display->add_count % 100) == 0)
|
||||
display_channel_print_stats(display);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int display_channel_wait_for_migrate_data(DisplayChannel *display)
|
||||
|
||||
@ -109,19 +109,6 @@ enum {
|
||||
PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT,
|
||||
};
|
||||
|
||||
typedef struct DrawablePipeItem {
|
||||
RingItem base; /* link for a list of pipe items held by Drawable */
|
||||
PipeItem dpi_pipe_item; /* link for the client's pipe itself */
|
||||
Drawable *drawable;
|
||||
DisplayChannelClient *dcc;
|
||||
uint8_t refs;
|
||||
} DrawablePipeItem;
|
||||
|
||||
DrawablePipeItem* drawable_pipe_item_new (DisplayChannelClient *dcc,
|
||||
Drawable *drawable);
|
||||
void drawable_pipe_item_unref (DrawablePipeItem *dpi);
|
||||
DrawablePipeItem* drawable_pipe_item_ref (DrawablePipeItem *dpi);
|
||||
|
||||
typedef struct MonitorsConfig {
|
||||
int refs;
|
||||
int count;
|
||||
@ -271,7 +258,7 @@ void display_channel_surface_unref (DisplayCha
|
||||
uint32_t surface_id);
|
||||
bool display_channel_surface_has_canvas (DisplayChannel *display,
|
||||
uint32_t surface_id);
|
||||
int display_channel_add_drawable (DisplayChannel *display,
|
||||
void display_channel_add_drawable (DisplayChannel *display,
|
||||
Drawable *drawable);
|
||||
void display_channel_current_flush (DisplayChannel *display,
|
||||
int surface_id);
|
||||
@ -395,12 +382,8 @@ static inline void region_add_clip_rects(QRegion *rgn, SpiceClipRects *data)
|
||||
}
|
||||
}
|
||||
|
||||
void red_pipes_add_drawable(DisplayChannel *display, Drawable *drawable);
|
||||
void current_remove_drawable(DisplayChannel *display, Drawable *item);
|
||||
void red_pipes_add_drawable_after(DisplayChannel *display,
|
||||
Drawable *drawable, Drawable *pos_after);
|
||||
void red_pipes_remove_drawable(Drawable *drawable);
|
||||
void dcc_add_drawable(DisplayChannelClient *dcc, Drawable *drawable);
|
||||
void current_remove(DisplayChannel *display, TreeItem *item);
|
||||
void detach_streams_behind(DisplayChannel *display, QRegion *region, Drawable *drawable);
|
||||
void drawable_draw(DisplayChannel *display, Drawable *item);
|
||||
|
||||
@ -203,44 +203,6 @@ void attach_stream(DisplayChannel *display, Drawable *drawable, Stream *stream)
|
||||
}
|
||||
}
|
||||
|
||||
/* fixme: move to display channel */
|
||||
DrawablePipeItem *drawable_pipe_item_new(DisplayChannelClient *dcc,
|
||||
Drawable *drawable)
|
||||
{
|
||||
DrawablePipeItem *dpi;
|
||||
|
||||
dpi = spice_malloc0(sizeof(*dpi));
|
||||
dpi->drawable = drawable;
|
||||
dpi->dcc = dcc;
|
||||
ring_item_init(&dpi->base);
|
||||
ring_add(&drawable->pipes, &dpi->base);
|
||||
red_channel_pipe_item_init(RED_CHANNEL_CLIENT(dcc)->channel,
|
||||
&dpi->dpi_pipe_item, PIPE_ITEM_TYPE_DRAW);
|
||||
dpi->refs++;
|
||||
drawable->refs++;
|
||||
return dpi;
|
||||
}
|
||||
|
||||
DrawablePipeItem *drawable_pipe_item_ref(DrawablePipeItem *dpi)
|
||||
{
|
||||
dpi->refs++;
|
||||
return dpi;
|
||||
}
|
||||
|
||||
void drawable_pipe_item_unref(DrawablePipeItem *dpi)
|
||||
{
|
||||
DisplayChannel *display = DCC_TO_DC(dpi->dcc);
|
||||
|
||||
if (--dpi->refs != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
spice_warn_if_fail(!ring_item_is_linked(&dpi->dpi_pipe_item.link));
|
||||
spice_warn_if_fail(!ring_item_is_linked(&dpi->base));
|
||||
display_channel_drawable_unref(display, dpi->drawable);
|
||||
free(dpi);
|
||||
}
|
||||
|
||||
QXLInstance* red_worker_get_qxl(RedWorker *worker)
|
||||
{
|
||||
spice_return_val_if_fail(worker != NULL, NULL);
|
||||
@ -292,35 +254,6 @@ static inline int validate_surface(DisplayChannel *display, uint32_t surface_id)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline void red_handle_drawable_surfaces_client_synced(
|
||||
DisplayChannelClient *dcc, Drawable *drawable)
|
||||
{
|
||||
DisplayChannel *display = DCC_TO_DC(dcc);
|
||||
int x;
|
||||
|
||||
for (x = 0; x < 3; ++x) {
|
||||
int surface_id;
|
||||
|
||||
surface_id = drawable->surface_deps[x];
|
||||
if (surface_id != -1) {
|
||||
if (dcc->surface_client_created[surface_id] == TRUE) {
|
||||
continue;
|
||||
}
|
||||
dcc_create_surface(dcc, surface_id);
|
||||
display_channel_current_flush(display, surface_id);
|
||||
dcc_push_surface_image(dcc, surface_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (dcc->surface_client_created[drawable->surface_id] == TRUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
dcc_create_surface(dcc, drawable->surface_id);
|
||||
display_channel_current_flush(display, drawable->surface_id);
|
||||
dcc_push_surface_image(dcc, drawable->surface_id);
|
||||
}
|
||||
|
||||
static int display_is_connected(RedWorker *worker)
|
||||
{
|
||||
return (worker->display_channel && red_channel_is_connected(
|
||||
@ -333,76 +266,6 @@ static int cursor_is_connected(RedWorker *worker)
|
||||
red_channel_is_connected(RED_CHANNEL(worker->cursor_channel));
|
||||
}
|
||||
|
||||
void dcc_add_drawable(DisplayChannelClient *dcc, Drawable *drawable)
|
||||
{
|
||||
DrawablePipeItem *dpi;
|
||||
|
||||
red_handle_drawable_surfaces_client_synced(dcc, drawable);
|
||||
dpi = drawable_pipe_item_new(dcc, drawable);
|
||||
red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &dpi->dpi_pipe_item);
|
||||
}
|
||||
|
||||
void red_pipes_add_drawable(DisplayChannel *display, Drawable *drawable)
|
||||
{
|
||||
DisplayChannelClient *dcc;
|
||||
RingItem *dcc_ring_item, *next;
|
||||
|
||||
spice_warn_if(!ring_is_empty(&drawable->pipes));
|
||||
FOREACH_DCC(display, dcc_ring_item, next, dcc) {
|
||||
dcc_add_drawable(dcc, drawable);
|
||||
}
|
||||
}
|
||||
|
||||
static void dcc_add_drawable_to_tail(DisplayChannelClient *dcc, Drawable *drawable)
|
||||
{
|
||||
DrawablePipeItem *dpi;
|
||||
|
||||
if (!dcc) {
|
||||
return;
|
||||
}
|
||||
red_handle_drawable_surfaces_client_synced(dcc, drawable);
|
||||
dpi = drawable_pipe_item_new(dcc, drawable);
|
||||
red_channel_client_pipe_add_tail(RED_CHANNEL_CLIENT(dcc), &dpi->dpi_pipe_item);
|
||||
}
|
||||
|
||||
void red_pipes_add_drawable_after(DisplayChannel *display,
|
||||
Drawable *drawable, Drawable *pos_after)
|
||||
{
|
||||
DrawablePipeItem *dpi, *dpi_pos_after;
|
||||
RingItem *dpi_link, *dpi_next;
|
||||
DisplayChannelClient *dcc;
|
||||
int num_other_linked = 0;
|
||||
|
||||
DRAWABLE_FOREACH_DPI_SAFE(pos_after, dpi_link, dpi_next, dpi_pos_after) {
|
||||
num_other_linked++;
|
||||
dcc = dpi_pos_after->dcc;
|
||||
red_handle_drawable_surfaces_client_synced(dcc, drawable);
|
||||
dpi = drawable_pipe_item_new(dcc, drawable);
|
||||
red_channel_client_pipe_add_after(RED_CHANNEL_CLIENT(dcc), &dpi->dpi_pipe_item,
|
||||
&dpi_pos_after->dpi_pipe_item);
|
||||
}
|
||||
if (num_other_linked == 0) {
|
||||
red_pipes_add_drawable(display, drawable);
|
||||
return;
|
||||
}
|
||||
if (num_other_linked != display->common.base.clients_num) {
|
||||
RingItem *item, *next;
|
||||
spice_debug("TODO: not O(n^2)");
|
||||
FOREACH_DCC(display, item, next, dcc) {
|
||||
int sent = 0;
|
||||
DRAWABLE_FOREACH_DPI_SAFE(pos_after, dpi_link, dpi_next, dpi_pos_after) {
|
||||
if (dpi_pos_after->dcc == dcc) {
|
||||
sent = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sent) {
|
||||
dcc_add_drawable(dcc, drawable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static PipeItem *dcc_get_tail(DisplayChannelClient *dcc)
|
||||
{
|
||||
return (PipeItem*)ring_get_tail(&RED_CHANNEL_CLIENT(dcc)->pipe);
|
||||
@ -1179,9 +1042,8 @@ static inline void red_process_draw(RedWorker *worker, RedDrawable *red_drawable
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (display_channel_add_drawable(worker->display_channel, drawable)) {
|
||||
red_pipes_add_drawable(worker->display_channel, drawable);
|
||||
}
|
||||
display_channel_add_drawable(worker->display_channel, drawable);
|
||||
|
||||
cleanup:
|
||||
display_channel_drawable_unref(display, drawable);
|
||||
}
|
||||
@ -2338,7 +2200,7 @@ static void red_add_lossless_drawable_dependencies(RedChannelClient *rcc,
|
||||
|
||||
if (!sync_rendered) {
|
||||
// pushing the pipe item back to the pipe
|
||||
dcc_add_drawable_to_tail(dcc, item);
|
||||
dcc_append_drawable(dcc, item);
|
||||
// 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++) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user