mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2025-12-27 15:45:54 +00:00
Use more reference counting on RedPipeItem
This is the continuation of Christophe patches using reference counting for RedPipeItem. Extend it's usage. This for instance leads to the removal of release_item callback.
This commit is contained in:
commit
e72fec2289
@ -48,7 +48,6 @@ G_STATIC_ASSERT(sizeof(CursorItem) <= QXL_CURSUR_DEVICE_DATA_SIZE);
|
||||
typedef struct RedCursorPipeItem {
|
||||
RedPipeItem base;
|
||||
CursorItem *cursor_item;
|
||||
int refs;
|
||||
} RedCursorPipeItem;
|
||||
|
||||
struct CursorChannel {
|
||||
@ -82,6 +81,8 @@ struct CursorChannelClient {
|
||||
#include "cache-item.tmpl.c"
|
||||
#undef CLIENT_CURSOR_CACHE
|
||||
|
||||
static void cursor_pipe_item_free(RedCursorPipeItem *pipe_item);
|
||||
|
||||
static CursorItem *cursor_item_new(QXLInstance *qxl, RedCursorCmd *cmd)
|
||||
{
|
||||
CursorItem *cursor_item;
|
||||
@ -136,8 +137,8 @@ static RedPipeItem *new_cursor_pipe_item(RedChannelClient *rcc, void *data, int
|
||||
{
|
||||
RedCursorPipeItem *item = spice_malloc0(sizeof(RedCursorPipeItem));
|
||||
|
||||
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_CURSOR);
|
||||
item->refs = 1;
|
||||
red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_CURSOR,
|
||||
(GDestroyNotify)cursor_pipe_item_free);
|
||||
item->cursor_item = data;
|
||||
item->cursor_item->refs++;
|
||||
return &item->base;
|
||||
@ -203,15 +204,9 @@ void cursor_channel_disconnect(CursorChannel *cursor_channel)
|
||||
}
|
||||
|
||||
|
||||
static void put_cursor_pipe_item(CursorChannelClient *ccc,
|
||||
RedCursorPipeItem *pipe_item)
|
||||
static void cursor_pipe_item_free(RedCursorPipeItem *pipe_item)
|
||||
{
|
||||
spice_return_if_fail(pipe_item);
|
||||
spice_return_if_fail(pipe_item->refs > 0);
|
||||
|
||||
if (--pipe_item->refs) {
|
||||
return;
|
||||
}
|
||||
|
||||
spice_assert(!red_pipe_item_is_linked(&pipe_item->base));
|
||||
|
||||
@ -227,42 +222,6 @@ static void cursor_channel_client_on_disconnect(RedChannelClient *rcc)
|
||||
red_reset_cursor_cache(rcc);
|
||||
}
|
||||
|
||||
// TODO: share code between before/after_push since most of the items need the same
|
||||
// release
|
||||
static void cursor_channel_client_release_item_before_push(CursorChannelClient *ccc,
|
||||
RedPipeItem *item)
|
||||
{
|
||||
switch (item->type) {
|
||||
case RED_PIPE_ITEM_TYPE_CURSOR: {
|
||||
RedCursorPipeItem *cursor_pipe_item = SPICE_CONTAINEROF(item, RedCursorPipeItem, base);
|
||||
put_cursor_pipe_item(ccc, cursor_pipe_item);
|
||||
break;
|
||||
}
|
||||
case RED_PIPE_ITEM_TYPE_INVAL_ONE:
|
||||
case RED_PIPE_ITEM_TYPE_VERB:
|
||||
case RED_PIPE_ITEM_TYPE_CURSOR_INIT:
|
||||
case RED_PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE:
|
||||
free(item);
|
||||
break;
|
||||
default:
|
||||
spice_error("invalid pipe item type");
|
||||
}
|
||||
}
|
||||
|
||||
static void cursor_channel_client_release_item_after_push(CursorChannelClient *ccc,
|
||||
RedPipeItem *item)
|
||||
{
|
||||
switch (item->type) {
|
||||
case RED_PIPE_ITEM_TYPE_CURSOR: {
|
||||
RedCursorPipeItem *cursor_pipe_item = SPICE_CONTAINEROF(item, RedCursorPipeItem, base);
|
||||
put_cursor_pipe_item(ccc, cursor_pipe_item);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
spice_critical("invalid item type");
|
||||
}
|
||||
}
|
||||
|
||||
static void red_marshall_cursor_init(RedChannelClient *rcc, SpiceMarshaller *base_marshaller,
|
||||
RedPipeItem *pipe_item)
|
||||
{
|
||||
@ -354,7 +313,6 @@ static inline void red_marshall_inval(RedChannelClient *rcc,
|
||||
static void cursor_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
|
||||
{
|
||||
SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
|
||||
CursorChannelClient *ccc = RCC_TO_CCC(rcc);
|
||||
|
||||
switch (pipe_item->type) {
|
||||
case RED_PIPE_ITEM_TYPE_CURSOR:
|
||||
@ -378,16 +336,15 @@ static void cursor_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_it
|
||||
spice_error("invalid pipe item type");
|
||||
}
|
||||
|
||||
cursor_channel_client_release_item_before_push(ccc, pipe_item);
|
||||
red_pipe_item_unref(pipe_item);
|
||||
red_channel_client_begin_send_message(rcc);
|
||||
}
|
||||
|
||||
static RedCursorPipeItem *cursor_pipe_item_ref(RedCursorPipeItem *item)
|
||||
{
|
||||
spice_return_val_if_fail(item, NULL);
|
||||
spice_return_val_if_fail(item->refs > 0, NULL);
|
||||
|
||||
item->refs++;
|
||||
red_pipe_item_ref(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
@ -402,20 +359,6 @@ static void cursor_channel_hold_pipe_item(RedChannelClient *rcc, RedPipeItem *it
|
||||
cursor_pipe_item_ref(cursor_pipe_item);
|
||||
}
|
||||
|
||||
static void cursor_channel_release_item(RedChannelClient *rcc, RedPipeItem *item, int item_pushed)
|
||||
{
|
||||
CursorChannelClient *ccc = RCC_TO_CCC(rcc);
|
||||
|
||||
spice_assert(item);
|
||||
|
||||
if (item_pushed) {
|
||||
cursor_channel_client_release_item_after_push(ccc, item);
|
||||
} else {
|
||||
spice_debug("not pushed (%d)", item->type);
|
||||
cursor_channel_client_release_item_before_push(ccc, item);
|
||||
}
|
||||
}
|
||||
|
||||
CursorChannel* cursor_channel_new(RedWorker *worker)
|
||||
{
|
||||
CursorChannel *cursor_channel;
|
||||
@ -424,7 +367,6 @@ CursorChannel* cursor_channel_new(RedWorker *worker)
|
||||
.on_disconnect = cursor_channel_client_on_disconnect,
|
||||
.send_item = cursor_channel_send_item,
|
||||
.hold_item = cursor_channel_hold_pipe_item,
|
||||
.release_item = cursor_channel_release_item
|
||||
};
|
||||
|
||||
spice_info("create cursor channel");
|
||||
|
||||
@ -2383,8 +2383,8 @@ void dcc_send_item(DisplayChannelClient *dcc, RedPipeItem *pipe_item)
|
||||
marshall_inval_palette(rcc, m, (RedCacheItem *)pipe_item);
|
||||
break;
|
||||
case RED_PIPE_ITEM_TYPE_STREAM_CREATE: {
|
||||
StreamAgent *agent = SPICE_CONTAINEROF(pipe_item, StreamAgent, create_item);
|
||||
marshall_stream_start(rcc, m, agent);
|
||||
StreamCreateDestroyItem *item = SPICE_CONTAINEROF(pipe_item, StreamCreateDestroyItem, base);
|
||||
marshall_stream_start(rcc, m, item->agent);
|
||||
break;
|
||||
}
|
||||
case RED_PIPE_ITEM_TYPE_STREAM_CLIP: {
|
||||
@ -2393,8 +2393,8 @@ void dcc_send_item(DisplayChannelClient *dcc, RedPipeItem *pipe_item)
|
||||
break;
|
||||
}
|
||||
case RED_PIPE_ITEM_TYPE_STREAM_DESTROY: {
|
||||
StreamAgent *agent = SPICE_CONTAINEROF(pipe_item, StreamAgent, destroy_item);
|
||||
marshall_stream_end(rcc, m, agent);
|
||||
StreamCreateDestroyItem *item = SPICE_CONTAINEROF(pipe_item, StreamCreateDestroyItem, base);
|
||||
marshall_stream_end(rcc, m, item->agent);
|
||||
break;
|
||||
}
|
||||
case RED_PIPE_ITEM_TYPE_UPGRADE:
|
||||
@ -2455,7 +2455,7 @@ void dcc_send_item(DisplayChannelClient *dcc, RedPipeItem *pipe_item)
|
||||
spice_warn_if_reached();
|
||||
}
|
||||
|
||||
dcc_release_item(dcc, pipe_item, FALSE);
|
||||
red_pipe_item_unref(pipe_item);
|
||||
|
||||
// a message is pending
|
||||
if (red_channel_client_send_message_pending(rcc)) {
|
||||
|
||||
92
server/dcc.c
92
server/dcc.c
@ -288,7 +288,9 @@ void red_drawable_pipe_item_free(RedPipeItem *item)
|
||||
spice_assert(item->refcount == 0);
|
||||
|
||||
spice_warn_if_fail(!ring_item_is_linked(&item->link));
|
||||
spice_warn_if_fail(!ring_item_is_linked(&dpi->base));
|
||||
if (ring_item_is_linked(&dpi->base)) {
|
||||
ring_remove(&dpi->base);
|
||||
}
|
||||
drawable_unref(dpi->drawable);
|
||||
free(dpi);
|
||||
}
|
||||
@ -343,8 +345,6 @@ static void dcc_init_stream_agents(DisplayChannelClient *dcc)
|
||||
agent->stream = &display->streams_buf[i];
|
||||
region_init(&agent->vis_region);
|
||||
region_init(&agent->clip);
|
||||
red_pipe_item_init(&agent->create_item, RED_PIPE_ITEM_TYPE_STREAM_CREATE);
|
||||
red_pipe_item_init(&agent->destroy_item, RED_PIPE_ITEM_TYPE_STREAM_DESTROY);
|
||||
}
|
||||
dcc->use_video_encoder_rate_control =
|
||||
red_channel_client_test_remote_cap(RED_CHANNEL_CLIENT(dcc), SPICE_DISPLAY_CAP_STREAM_REPORT);
|
||||
@ -1607,89 +1607,3 @@ int dcc_handle_migrate_data(DisplayChannelClient *dcc, uint32_t size, void *mess
|
||||
red_channel_client_ack_zero_messages_window(RED_CHANNEL_CLIENT(dcc));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void release_item_after_push(RedPipeItem *item)
|
||||
{
|
||||
switch (item->type) {
|
||||
case RED_PIPE_ITEM_TYPE_DRAW:
|
||||
case RED_PIPE_ITEM_TYPE_IMAGE:
|
||||
case RED_PIPE_ITEM_TYPE_STREAM_CLIP:
|
||||
case RED_PIPE_ITEM_TYPE_MONITORS_CONFIG:
|
||||
case RED_PIPE_ITEM_TYPE_UPGRADE:
|
||||
red_pipe_item_unref(item);
|
||||
break;
|
||||
case RED_PIPE_ITEM_TYPE_GL_SCANOUT:
|
||||
case RED_PIPE_ITEM_TYPE_GL_DRAW:
|
||||
case RED_PIPE_ITEM_TYPE_VERB:
|
||||
free(item);
|
||||
break;
|
||||
default:
|
||||
spice_critical("invalid item type");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: share code between before/after_push since most of the items need the same
|
||||
// release
|
||||
static void release_item_before_push(DisplayChannelClient *dcc, RedPipeItem *item)
|
||||
{
|
||||
DisplayChannel *display = DCC_TO_DC(dcc);
|
||||
|
||||
spice_debug("item.type: %d", item->type);
|
||||
switch (item->type) {
|
||||
case RED_PIPE_ITEM_TYPE_DRAW: {
|
||||
RedDrawablePipeItem *dpi = SPICE_CONTAINEROF(item, RedDrawablePipeItem, dpi_pipe_item);
|
||||
ring_remove(&dpi->base);
|
||||
red_pipe_item_unref(item);
|
||||
break;
|
||||
}
|
||||
case RED_PIPE_ITEM_TYPE_STREAM_CREATE: {
|
||||
StreamAgent *agent = SPICE_CONTAINEROF(item, StreamAgent, create_item);
|
||||
stream_agent_unref(display, agent);
|
||||
break;
|
||||
}
|
||||
case RED_PIPE_ITEM_TYPE_STREAM_DESTROY: {
|
||||
StreamAgent *agent = SPICE_CONTAINEROF(item, StreamAgent, destroy_item);
|
||||
stream_agent_unref(display, agent);
|
||||
break;
|
||||
}
|
||||
case RED_PIPE_ITEM_TYPE_STREAM_CLIP:
|
||||
case RED_PIPE_ITEM_TYPE_UPGRADE:
|
||||
case RED_PIPE_ITEM_TYPE_IMAGE:
|
||||
case RED_PIPE_ITEM_TYPE_MONITORS_CONFIG:
|
||||
red_pipe_item_unref(item);
|
||||
break;
|
||||
case RED_PIPE_ITEM_TYPE_CREATE_SURFACE: {
|
||||
RedSurfaceCreateItem *surface_create = SPICE_CONTAINEROF(item, RedSurfaceCreateItem,
|
||||
pipe_item);
|
||||
free(surface_create);
|
||||
break;
|
||||
}
|
||||
case RED_PIPE_ITEM_TYPE_DESTROY_SURFACE: {
|
||||
RedSurfaceDestroyItem *surface_destroy = SPICE_CONTAINEROF(item, RedSurfaceDestroyItem,
|
||||
pipe_item);
|
||||
free(surface_destroy);
|
||||
break;
|
||||
}
|
||||
case RED_PIPE_ITEM_TYPE_INVAL_ONE:
|
||||
case RED_PIPE_ITEM_TYPE_VERB:
|
||||
case RED_PIPE_ITEM_TYPE_MIGRATE_DATA:
|
||||
case RED_PIPE_ITEM_TYPE_PIXMAP_SYNC:
|
||||
case RED_PIPE_ITEM_TYPE_PIXMAP_RESET:
|
||||
case RED_PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE:
|
||||
case RED_PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT:
|
||||
case RED_PIPE_ITEM_TYPE_GL_SCANOUT:
|
||||
case RED_PIPE_ITEM_TYPE_GL_DRAW:
|
||||
free(item);
|
||||
break;
|
||||
default:
|
||||
spice_critical("invalid item type");
|
||||
}
|
||||
}
|
||||
|
||||
void dcc_release_item(DisplayChannelClient *dcc, RedPipeItem *item, int item_pushed)
|
||||
{
|
||||
if (item_pushed)
|
||||
release_item_after_push(item);
|
||||
else
|
||||
release_item_before_push(dcc, item);
|
||||
}
|
||||
|
||||
@ -122,8 +122,8 @@ struct DisplayChannelClient {
|
||||
#define RCC_TO_DCC(rcc) SPICE_CONTAINEROF((rcc), DisplayChannelClient, common.base)
|
||||
|
||||
typedef struct RedSurfaceCreateItem {
|
||||
SpiceMsgSurfaceCreate surface_create;
|
||||
RedPipeItem pipe_item;
|
||||
SpiceMsgSurfaceCreate surface_create;
|
||||
} RedSurfaceCreateItem;
|
||||
|
||||
typedef struct RedGlScanoutUnixItem {
|
||||
@ -154,7 +154,6 @@ typedef struct RedDrawablePipeItem {
|
||||
RedPipeItem dpi_pipe_item; /* link for the client's pipe itself */
|
||||
Drawable *drawable;
|
||||
DisplayChannelClient *dcc;
|
||||
uint8_t refs;
|
||||
} RedDrawablePipeItem;
|
||||
|
||||
DisplayChannelClient* dcc_new (DisplayChannel *display,
|
||||
@ -204,9 +203,6 @@ void dcc_append_drawable (DisplayCha
|
||||
void dcc_add_drawable_after (DisplayChannelClient *dcc,
|
||||
Drawable *drawable,
|
||||
RedPipeItem *pos);
|
||||
void dcc_release_item (DisplayChannelClient *dcc,
|
||||
RedPipeItem *item,
|
||||
int item_pushed);
|
||||
void dcc_send_item (DisplayChannelClient *dcc,
|
||||
RedPipeItem *item);
|
||||
int dcc_clear_surface_drawables_from_pipe (DisplayChannelClient *dcc,
|
||||
|
||||
@ -1946,14 +1946,6 @@ static void hold_item(RedChannelClient *rcc, RedPipeItem *item)
|
||||
}
|
||||
}
|
||||
|
||||
static void release_item(RedChannelClient *rcc, RedPipeItem *item, int item_pushed)
|
||||
{
|
||||
DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
|
||||
|
||||
spice_return_if_fail(item != NULL);
|
||||
dcc_release_item(dcc, item, item_pushed);
|
||||
}
|
||||
|
||||
static int handle_migrate_flush_mark(RedChannelClient *rcc)
|
||||
{
|
||||
DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
|
||||
@ -1995,7 +1987,6 @@ DisplayChannel* display_channel_new(SpiceServer *reds, RedWorker *worker,
|
||||
.on_disconnect = on_disconnect,
|
||||
.send_item = send_item,
|
||||
.hold_item = hold_item,
|
||||
.release_item = release_item,
|
||||
.handle_migrate_flush_mark = handle_migrate_flush_mark,
|
||||
.handle_migrate_data = handle_migrate_data,
|
||||
.handle_migrate_data_get_serial = handle_migrate_data_get_serial
|
||||
|
||||
@ -241,8 +241,8 @@ static inline int get_stream_id(DisplayChannel *display, Stream *stream)
|
||||
}
|
||||
|
||||
typedef struct RedSurfaceDestroyItem {
|
||||
SpiceMsgSurfaceDestroy surface_destroy;
|
||||
RedPipeItem pipe_item;
|
||||
SpiceMsgSurfaceDestroy surface_destroy;
|
||||
} RedSurfaceDestroyItem;
|
||||
|
||||
typedef struct RedUpgradeItem {
|
||||
|
||||
@ -254,12 +254,6 @@ static void inputs_channel_send_migrate_data(RedChannelClient *rcc,
|
||||
spice_marshaller_add_uint16(m, icc->motion_count);
|
||||
}
|
||||
|
||||
static void inputs_channel_release_pipe_item(RedChannelClient *rcc,
|
||||
RedPipeItem *base, int item_pushed)
|
||||
{
|
||||
free(base);
|
||||
}
|
||||
|
||||
static void inputs_channel_send_item(RedChannelClient *rcc, RedPipeItem *base)
|
||||
{
|
||||
SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
|
||||
@ -627,7 +621,6 @@ InputsChannel* inputs_channel_new(RedsState *reds)
|
||||
channel_cbs.on_disconnect = inputs_channel_on_disconnect;
|
||||
channel_cbs.send_item = inputs_channel_send_item;
|
||||
channel_cbs.hold_item = inputs_channel_hold_pipe_item;
|
||||
channel_cbs.release_item = inputs_channel_release_pipe_item;
|
||||
channel_cbs.alloc_recv_buf = inputs_channel_alloc_msg_rcv_buf;
|
||||
channel_cbs.release_recv_buf = inputs_channel_release_msg_rcv_buf;
|
||||
channel_cbs.handle_migrate_data = inputs_channel_handle_migrate_data;
|
||||
|
||||
@ -165,9 +165,6 @@ enum NetTestStage {
|
||||
NET_TEST_STAGE_COMPLETE,
|
||||
};
|
||||
|
||||
static void main_channel_release_pipe_item(RedChannelClient *rcc,
|
||||
RedPipeItem *base, int item_pushed);
|
||||
|
||||
int main_channel_is_connected(MainChannel *main_chan)
|
||||
{
|
||||
return red_channel_is_connected(&main_chan->base);
|
||||
@ -250,13 +247,20 @@ static RedPipeItem *main_agent_tokens_item_new(RedChannelClient *rcc, uint32_t n
|
||||
return &item->base;
|
||||
}
|
||||
|
||||
static void main_agent_data_item_free(RedAgentDataPipeItem *item)
|
||||
{
|
||||
item->free_data(item->data, item->opaque);
|
||||
free(item);
|
||||
}
|
||||
|
||||
static RedPipeItem *main_agent_data_item_new(RedChannelClient *rcc, uint8_t* data, size_t len,
|
||||
spice_marshaller_item_free_func free_data,
|
||||
void *opaque)
|
||||
{
|
||||
RedAgentDataPipeItem *item = spice_malloc(sizeof(RedAgentDataPipeItem));
|
||||
|
||||
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_MAIN_AGENT_DATA);
|
||||
red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_MAIN_AGENT_DATA,
|
||||
(GDestroyNotify)main_agent_data_item_free);
|
||||
item->data = data;
|
||||
item->len = len;
|
||||
item->free_data = free_data;
|
||||
@ -302,12 +306,19 @@ static RedPipeItem *main_uuid_item_new(MainChannelClient *mcc, const uint8_t uui
|
||||
return &item->base;
|
||||
}
|
||||
|
||||
static void main_notify_item_free(RedNotifyPipeItem *data)
|
||||
{
|
||||
free(data->msg);
|
||||
free(data);
|
||||
}
|
||||
|
||||
static RedPipeItem *main_notify_item_new(RedChannelClient *rcc, void *data, int num)
|
||||
{
|
||||
RedNotifyPipeItem *item = spice_malloc(sizeof(RedNotifyPipeItem));
|
||||
const char *msg = data;
|
||||
|
||||
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_MAIN_NOTIFY);
|
||||
red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_MAIN_NOTIFY,
|
||||
(GDestroyNotify)main_notify_item_free);
|
||||
item->msg = spice_strdup(msg);
|
||||
return &item->base;
|
||||
}
|
||||
@ -712,7 +723,7 @@ static void main_channel_send_item(RedChannelClient *rcc, RedPipeItem *base)
|
||||
spice_printerr("Init msg for client %p was not sent yet "
|
||||
"(client is probably during semi-seamless migration). Ignoring msg type %d",
|
||||
rcc->client, base->type);
|
||||
main_channel_release_pipe_item(rcc, base, FALSE);
|
||||
red_pipe_item_unref(base);
|
||||
return;
|
||||
}
|
||||
switch (base->type) {
|
||||
@ -783,27 +794,6 @@ static void main_channel_send_item(RedChannelClient *rcc, RedPipeItem *base)
|
||||
red_channel_client_begin_send_message(rcc);
|
||||
}
|
||||
|
||||
static void main_channel_release_pipe_item(RedChannelClient *rcc,
|
||||
RedPipeItem *base, int item_pushed)
|
||||
{
|
||||
switch (base->type) {
|
||||
case RED_PIPE_ITEM_TYPE_MAIN_AGENT_DATA: {
|
||||
RedAgentDataPipeItem *data = (RedAgentDataPipeItem *)base;
|
||||
|
||||
data->free_data(data->data, data->opaque);
|
||||
break;
|
||||
}
|
||||
case RED_PIPE_ITEM_TYPE_MAIN_NOTIFY: {
|
||||
RedNotifyPipeItem *data = (RedNotifyPipeItem *)base;
|
||||
free(data->msg);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
free(base);
|
||||
}
|
||||
|
||||
static void main_channel_client_handle_migrate_connected(MainChannelClient *mcc,
|
||||
int success,
|
||||
int seamless)
|
||||
@ -1165,7 +1155,6 @@ MainChannel* main_channel_new(RedsState *reds)
|
||||
channel_cbs.on_disconnect = main_channel_client_on_disconnect;
|
||||
channel_cbs.send_item = main_channel_send_item;
|
||||
channel_cbs.hold_item = main_channel_hold_pipe_item;
|
||||
channel_cbs.release_item = main_channel_release_pipe_item;
|
||||
channel_cbs.alloc_recv_buf = main_channel_alloc_msg_rcv_buf;
|
||||
channel_cbs.release_recv_buf = main_channel_release_msg_rcv_buf;
|
||||
channel_cbs.handle_migrate_flush_mark = main_channel_handle_migrate_flush_mark;
|
||||
|
||||
@ -578,28 +578,13 @@ static void red_channel_client_send_item(RedChannelClient *rcc, RedPipeItem *ite
|
||||
rcc->channel->channel_cbs.send_item(rcc, item);
|
||||
return;
|
||||
}
|
||||
free(item);
|
||||
}
|
||||
|
||||
static void red_channel_client_release_item(RedChannelClient *rcc, RedPipeItem *item, int item_pushed)
|
||||
{
|
||||
switch (item->type) {
|
||||
case RED_PIPE_ITEM_TYPE_SET_ACK:
|
||||
case RED_PIPE_ITEM_TYPE_EMPTY_MSG:
|
||||
case RED_PIPE_ITEM_TYPE_MIGRATE:
|
||||
case RED_PIPE_ITEM_TYPE_PING:
|
||||
free(item);
|
||||
break;
|
||||
default:
|
||||
rcc->channel->channel_cbs.release_item(rcc, item, item_pushed);
|
||||
}
|
||||
red_pipe_item_unref(item);
|
||||
}
|
||||
|
||||
static inline void red_channel_client_release_sent_item(RedChannelClient *rcc)
|
||||
{
|
||||
if (rcc->send_data.item) {
|
||||
red_channel_client_release_item(rcc,
|
||||
rcc->send_data.item, TRUE);
|
||||
red_pipe_item_unref(rcc->send_data.item);
|
||||
rcc->send_data.item = NULL;
|
||||
}
|
||||
}
|
||||
@ -1030,7 +1015,7 @@ RedChannel *red_channel_create(int size,
|
||||
|
||||
spice_assert(size >= sizeof(*channel));
|
||||
spice_assert(channel_cbs->config_socket && channel_cbs->on_disconnect && handle_message &&
|
||||
channel_cbs->alloc_recv_buf && channel_cbs->release_item);
|
||||
channel_cbs->alloc_recv_buf);
|
||||
spice_assert(channel_cbs->handle_migrate_data ||
|
||||
!(migration_flags & SPICE_MIGRATE_NEED_DATA_TRANSFER));
|
||||
channel = spice_malloc0(size);
|
||||
@ -1663,7 +1648,7 @@ static inline gboolean client_pipe_add(RedChannelClient *rcc, RedPipeItem *item,
|
||||
spice_assert(rcc && item);
|
||||
if (SPICE_UNLIKELY(!red_channel_client_is_connected(rcc))) {
|
||||
spice_debug("rcc is disconnected %p", rcc);
|
||||
red_channel_client_release_item(rcc, item, FALSE);
|
||||
red_pipe_item_unref(item);
|
||||
return FALSE;
|
||||
}
|
||||
if (ring_is_empty(&rcc->pipe) && rcc->stream->watch) {
|
||||
@ -1770,12 +1755,9 @@ int red_channel_is_connected(RedChannel *channel)
|
||||
return channel && (channel->clients_num > 0);
|
||||
}
|
||||
|
||||
void red_channel_client_clear_sent_item(RedChannelClient *rcc)
|
||||
static void red_channel_client_clear_sent_item(RedChannelClient *rcc)
|
||||
{
|
||||
if (rcc->send_data.item) {
|
||||
red_channel_client_release_item(rcc, rcc->send_data.item, TRUE);
|
||||
rcc->send_data.item = NULL;
|
||||
}
|
||||
red_channel_client_release_sent_item(rcc);
|
||||
rcc->send_data.blocked = FALSE;
|
||||
rcc->send_data.size = 0;
|
||||
}
|
||||
@ -1789,7 +1771,7 @@ void red_channel_client_pipe_clear(RedChannelClient *rcc)
|
||||
}
|
||||
while ((item = (RedPipeItem *)ring_get_head(&rcc->pipe))) {
|
||||
ring_remove(&item->link);
|
||||
red_channel_client_release_item(rcc, item, FALSE);
|
||||
red_pipe_item_unref(item);
|
||||
}
|
||||
rcc->pipe_size = 0;
|
||||
}
|
||||
@ -2033,7 +2015,7 @@ void red_channel_client_pipe_remove_and_release(RedChannelClient *rcc,
|
||||
RedPipeItem *item)
|
||||
{
|
||||
red_channel_client_pipe_remove(rcc, item);
|
||||
red_channel_client_release_item(rcc, item, FALSE);
|
||||
red_pipe_item_unref(item);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2398,7 +2380,7 @@ int red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
|
||||
red_channel_client_push(rcc);
|
||||
}
|
||||
|
||||
red_channel_client_release_item(rcc, item, TRUE);
|
||||
red_pipe_item_unref(item);
|
||||
if (item_in_pipe) {
|
||||
spice_warning("timeout");
|
||||
return FALSE;
|
||||
|
||||
@ -159,8 +159,6 @@ typedef void (*channel_disconnect_proc)(RedChannelClient *rcc);
|
||||
typedef int (*channel_configure_socket_proc)(RedChannelClient *rcc);
|
||||
typedef void (*channel_send_pipe_item_proc)(RedChannelClient *rcc, RedPipeItem *item);
|
||||
typedef void (*channel_hold_pipe_item_proc)(RedChannelClient *rcc, RedPipeItem *item);
|
||||
typedef void (*channel_release_pipe_item_proc)(RedChannelClient *rcc,
|
||||
RedPipeItem *item, int item_pushed);
|
||||
typedef void (*channel_on_incoming_error_proc)(RedChannelClient *rcc);
|
||||
typedef void (*channel_on_outgoing_error_proc)(RedChannelClient *rcc);
|
||||
|
||||
@ -188,7 +186,6 @@ typedef struct {
|
||||
channel_disconnect_proc on_disconnect;
|
||||
channel_send_pipe_item_proc send_item;
|
||||
channel_hold_pipe_item_proc hold_item;
|
||||
channel_release_pipe_item_proc release_item;
|
||||
channel_alloc_msg_recv_buf_proc alloc_recv_buf;
|
||||
channel_release_msg_recv_buf_proc release_recv_buf;
|
||||
channel_handle_migrate_flush_mark_proc handle_migrate_flush_mark;
|
||||
|
||||
@ -504,16 +504,6 @@ static void smartcard_channel_send_item(RedChannelClient *rcc, RedPipeItem *item
|
||||
red_channel_client_begin_send_message(rcc);
|
||||
}
|
||||
|
||||
static void smartcard_channel_release_pipe_item(RedChannelClient *rcc,
|
||||
RedPipeItem *item, int item_pushed)
|
||||
{
|
||||
if (item->type == RED_PIPE_ITEM_TYPE_SMARTCARD_DATA) {
|
||||
red_pipe_item_unref(item);
|
||||
} else {
|
||||
free(item);
|
||||
}
|
||||
}
|
||||
|
||||
static void smartcard_channel_on_disconnect(RedChannelClient *rcc)
|
||||
{
|
||||
SmartCardChannelClient *scc = SPICE_CONTAINEROF(rcc, SmartCardChannelClient, base);
|
||||
@ -541,7 +531,6 @@ static void smartcard_push_error(RedChannelClient *rcc, uint32_t reader_id, VSCE
|
||||
|
||||
red_pipe_item_init(&error_item->base, RED_PIPE_ITEM_TYPE_ERROR);
|
||||
|
||||
error_item->base.type = RED_PIPE_ITEM_TYPE_ERROR;
|
||||
error_item->vheader.reader_id = reader_id;
|
||||
error_item->vheader.type = VSC_Error;
|
||||
error_item->vheader.length = sizeof(error_item->error);
|
||||
@ -797,7 +786,6 @@ static void smartcard_init(RedsState *reds)
|
||||
channel_cbs.on_disconnect = smartcard_channel_on_disconnect;
|
||||
channel_cbs.send_item = smartcard_channel_send_item;
|
||||
channel_cbs.hold_item = smartcard_channel_hold_pipe_item;
|
||||
channel_cbs.release_item = smartcard_channel_release_pipe_item;
|
||||
channel_cbs.alloc_recv_buf = smartcard_channel_alloc_msg_rcv_buf;
|
||||
channel_cbs.release_recv_buf = smartcard_channel_release_msg_rcv_buf;
|
||||
channel_cbs.handle_migrate_flush_mark = smartcard_channel_client_handle_migrate_flush_mark;
|
||||
|
||||
@ -431,23 +431,12 @@ static void spicevmc_red_channel_send_item(RedChannelClient *rcc,
|
||||
break;
|
||||
default:
|
||||
spice_error("bad pipe item %d", item->type);
|
||||
free(item);
|
||||
red_pipe_item_unref(item);
|
||||
return;
|
||||
}
|
||||
red_channel_client_begin_send_message(rcc);
|
||||
}
|
||||
|
||||
static void spicevmc_red_channel_release_pipe_item(RedChannelClient *rcc,
|
||||
RedPipeItem *item,
|
||||
int item_pushed)
|
||||
{
|
||||
if (item->type == RED_PIPE_ITEM_TYPE_SPICEVMC_DATA) {
|
||||
red_pipe_item_unref(item);
|
||||
} else {
|
||||
free(item);
|
||||
}
|
||||
}
|
||||
|
||||
static void spicevmc_connect(RedChannel *channel, RedClient *client,
|
||||
RedsStream *stream, int migration, int num_common_caps,
|
||||
uint32_t *common_caps, int num_caps, uint32_t *caps)
|
||||
@ -509,7 +498,6 @@ RedCharDevice *spicevmc_device_connect(RedsState *reds,
|
||||
channel_cbs.on_disconnect = spicevmc_red_channel_client_on_disconnect;
|
||||
channel_cbs.send_item = spicevmc_red_channel_send_item;
|
||||
channel_cbs.hold_item = spicevmc_red_channel_hold_pipe_item;
|
||||
channel_cbs.release_item = spicevmc_red_channel_release_pipe_item;
|
||||
channel_cbs.alloc_recv_buf = spicevmc_red_channel_alloc_msg_rcv_buf;
|
||||
channel_cbs.release_recv_buf = spicevmc_red_channel_release_msg_rcv_buf;
|
||||
channel_cbs.handle_migrate_flush_mark = spicevmc_channel_client_handle_migrate_flush_mark;
|
||||
|
||||
@ -63,6 +63,36 @@ void stream_agent_stats_print(StreamAgent *agent)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void stream_create_destroy_item_release(RedPipeItem *base)
|
||||
{
|
||||
StreamCreateDestroyItem *item = SPICE_CONTAINEROF(base, StreamCreateDestroyItem, base);
|
||||
DisplayChannel *display = (DisplayChannel*)item->agent->dcc->common.base.channel;
|
||||
stream_agent_unref(display, item->agent);
|
||||
free(item);
|
||||
}
|
||||
|
||||
static RedPipeItem *stream_create_destroy_item_new(StreamAgent *agent, gint type)
|
||||
{
|
||||
StreamCreateDestroyItem *item = spice_new0(StreamCreateDestroyItem, 1);
|
||||
|
||||
red_pipe_item_init_full(&item->base, type,
|
||||
(GDestroyNotify)stream_create_destroy_item_release);
|
||||
agent->stream->refs++;
|
||||
item->agent = agent;
|
||||
return &item->base;
|
||||
}
|
||||
|
||||
static RedPipeItem *stream_create_item_new(StreamAgent *agent)
|
||||
{
|
||||
return stream_create_destroy_item_new(agent, RED_PIPE_ITEM_TYPE_STREAM_CREATE);
|
||||
}
|
||||
|
||||
static RedPipeItem *stream_destroy_item_new(StreamAgent *agent)
|
||||
{
|
||||
return stream_create_destroy_item_new(agent, RED_PIPE_ITEM_TYPE_STREAM_DESTROY);
|
||||
}
|
||||
|
||||
|
||||
void stream_stop(DisplayChannel *display, Stream *stream)
|
||||
{
|
||||
DisplayChannelClient *dcc;
|
||||
@ -78,7 +108,6 @@ void stream_stop(DisplayChannel *display, Stream *stream)
|
||||
stream_agent = &dcc->stream_agents[get_stream_id(display, stream)];
|
||||
region_clear(&stream_agent->vis_region);
|
||||
region_clear(&stream_agent->clip);
|
||||
spice_assert(!red_pipe_item_is_linked(&stream_agent->destroy_item));
|
||||
if (stream_agent->video_encoder && dcc->use_video_encoder_rate_control) {
|
||||
uint64_t stream_bit_rate = stream_agent->video_encoder->get_bit_rate(stream_agent->video_encoder);
|
||||
|
||||
@ -89,8 +118,7 @@ void stream_stop(DisplayChannel *display, Stream *stream)
|
||||
dcc->streams_max_bit_rate = stream_bit_rate;
|
||||
}
|
||||
}
|
||||
stream->refs++;
|
||||
red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &stream_agent->destroy_item);
|
||||
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;
|
||||
@ -702,7 +730,6 @@ void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream)
|
||||
|
||||
spice_return_if_fail(region_is_empty(&agent->vis_region));
|
||||
|
||||
stream->refs++;
|
||||
if (stream->current) {
|
||||
agent->frames = 1;
|
||||
region_clone(&agent->vis_region, &stream->current->tree_item.base.rgn);
|
||||
@ -728,7 +755,7 @@ void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream)
|
||||
} else {
|
||||
agent->video_encoder = mjpeg_encoder_new(0, NULL);
|
||||
}
|
||||
red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &agent->create_item);
|
||||
red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), stream_create_item_new(agent));
|
||||
|
||||
if (red_channel_client_test_remote_cap(RED_CHANNEL_CLIENT(dcc), SPICE_DISPLAY_CAP_STREAM_REPORT)) {
|
||||
RedStreamActivateReportItem *report_pipe_item = spice_malloc0(sizeof(*report_pipe_item));
|
||||
|
||||
@ -82,8 +82,6 @@ typedef struct StreamAgent {
|
||||
vis_region will contain c2 and also the part of c1/c2 that still
|
||||
displays fragments of the video */
|
||||
|
||||
RedPipeItem create_item;
|
||||
RedPipeItem destroy_item;
|
||||
Stream *stream;
|
||||
uint64_t last_send_time;
|
||||
VideoEncoder *video_encoder;
|
||||
@ -109,6 +107,11 @@ typedef struct RedStreamClipItem {
|
||||
|
||||
RedStreamClipItem * red_stream_clip_item_new (StreamAgent *agent);
|
||||
|
||||
typedef struct StreamCreateDestroyItem {
|
||||
RedPipeItem base;
|
||||
StreamAgent *agent;
|
||||
} StreamCreateDestroyItem;
|
||||
|
||||
typedef struct ItemTrace {
|
||||
red_time_t time;
|
||||
red_time_t first_frame_time;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user