mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-01-10 06:56:06 +00:00
worker: move DisplayChannel/DisplayChannelClient functions together
Signed-off-by: Marc-André Lureau <marcandre.lureau@gmail.com> Signed-off-by: Frediano Ziglio <fziglio@redhat.com> Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
This commit is contained in:
parent
921ec344bc
commit
5a216d2eb1
@ -526,6 +526,138 @@ static void display_channel_client_release_item_after_push(DisplayChannelClient
|
||||
SAFE_FOREACH(link, next, drawable, &(drawable)->glz_ring, glz, LINK_TO_GLZ(link))
|
||||
|
||||
|
||||
static inline int get_stream_id(RedWorker *worker, Stream *stream)
|
||||
{
|
||||
return (int)(stream - worker->streams_buf);
|
||||
}
|
||||
|
||||
static inline void red_free_stream(RedWorker *worker, Stream *stream)
|
||||
{
|
||||
stream->next = worker->free_streams;
|
||||
worker->free_streams = stream;
|
||||
}
|
||||
|
||||
static void red_release_stream(RedWorker *worker, Stream *stream)
|
||||
{
|
||||
if (!--stream->refs) {
|
||||
spice_assert(!ring_item_is_linked(&stream->link));
|
||||
red_free_stream(worker, stream);
|
||||
worker->stream_count--;
|
||||
}
|
||||
}
|
||||
|
||||
static void red_display_release_stream(RedWorker *worker, StreamAgent *agent)
|
||||
{
|
||||
spice_assert(agent->stream);
|
||||
red_release_stream(worker, agent->stream);
|
||||
}
|
||||
|
||||
static void red_display_release_stream_clip(RedWorker *worker, StreamClipItem *item)
|
||||
{
|
||||
if (!--item->refs) {
|
||||
red_display_release_stream(worker, item->stream_agent);
|
||||
free(item->rects);
|
||||
free(item);
|
||||
}
|
||||
}
|
||||
|
||||
static void dcc_push_stream_agent_clip(DisplayChannelClient* dcc, StreamAgent *agent)
|
||||
{
|
||||
StreamClipItem *item = stream_clip_item_new(dcc, agent);
|
||||
int n_rects;
|
||||
|
||||
if (!item) {
|
||||
spice_critical("alloc failed");
|
||||
}
|
||||
item->clip_type = SPICE_CLIP_TYPE_RECTS;
|
||||
|
||||
n_rects = pixman_region32_n_rects(&agent->clip);
|
||||
|
||||
item->rects = spice_malloc_n_m(n_rects, sizeof(SpiceRect), sizeof(SpiceClipRects));
|
||||
item->rects->num_rects = n_rects;
|
||||
region_ret_rects(&agent->clip, item->rects->rects, n_rects);
|
||||
red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), (PipeItem *)item);
|
||||
}
|
||||
|
||||
|
||||
static void red_attach_stream(RedWorker *worker, Drawable *drawable, Stream *stream)
|
||||
{
|
||||
DisplayChannelClient *dcc;
|
||||
RingItem *item, *next;
|
||||
|
||||
spice_assert(!drawable->stream && !stream->current);
|
||||
spice_assert(drawable && stream);
|
||||
stream->current = drawable;
|
||||
drawable->stream = stream;
|
||||
stream->last_time = drawable->creation_time;
|
||||
|
||||
uint64_t duration = drawable->creation_time - stream->input_fps_start_time;
|
||||
if (duration >= RED_STREAM_INPUT_FPS_TIMEOUT) {
|
||||
/* Round to the nearest integer, for instance 24 for 23.976 */
|
||||
stream->input_fps = ((uint64_t)stream->num_input_frames * 1000 * 1000 * 1000 + duration / 2) / duration;
|
||||
spice_debug("input-fps=%u", stream->input_fps);
|
||||
stream->num_input_frames = 0;
|
||||
stream->input_fps_start_time = drawable->creation_time;
|
||||
} else {
|
||||
stream->num_input_frames++;
|
||||
}
|
||||
|
||||
FOREACH_DCC(worker->display_channel, item, next, dcc) {
|
||||
StreamAgent *agent;
|
||||
QRegion clip_in_draw_dest;
|
||||
|
||||
agent = &dcc->stream_agents[get_stream_id(worker, stream)];
|
||||
region_or(&agent->vis_region, &drawable->tree_item.base.rgn);
|
||||
|
||||
region_init(&clip_in_draw_dest);
|
||||
region_add(&clip_in_draw_dest, &drawable->red_drawable->bbox);
|
||||
region_and(&clip_in_draw_dest, &agent->clip);
|
||||
|
||||
if (!region_is_equal(&clip_in_draw_dest, &drawable->tree_item.base.rgn)) {
|
||||
region_remove(&agent->clip, &drawable->red_drawable->bbox);
|
||||
region_or(&agent->clip, &drawable->tree_item.base.rgn);
|
||||
dcc_push_stream_agent_clip(dcc, agent);
|
||||
}
|
||||
#ifdef STREAM_STATS
|
||||
agent->stats.num_input_frames++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void red_stop_stream(RedWorker *worker, Stream *stream)
|
||||
{
|
||||
DisplayChannelClient *dcc;
|
||||
RingItem *item, *next;
|
||||
|
||||
spice_assert(ring_item_is_linked(&stream->link));
|
||||
spice_assert(!stream->current);
|
||||
spice_debug("stream %d", get_stream_id(worker, stream));
|
||||
FOREACH_DCC(worker->display_channel, item, next, dcc) {
|
||||
StreamAgent *stream_agent;
|
||||
|
||||
stream_agent = &dcc->stream_agents[get_stream_id(worker, stream)];
|
||||
region_clear(&stream_agent->vis_region);
|
||||
region_clear(&stream_agent->clip);
|
||||
spice_assert(!pipe_item_is_linked(&stream_agent->destroy_item));
|
||||
if (stream_agent->mjpeg_encoder && dcc->use_mjpeg_encoder_rate_control) {
|
||||
uint64_t stream_bit_rate = mjpeg_encoder_get_bit_rate(stream_agent->mjpeg_encoder);
|
||||
|
||||
if (stream_bit_rate > dcc->streams_max_bit_rate) {
|
||||
spice_debug("old max-bit-rate=%.2f new=%.2f",
|
||||
dcc->streams_max_bit_rate / 8.0 / 1024.0 / 1024.0,
|
||||
stream_bit_rate / 8.0 / 1024.0 / 1024.0);
|
||||
dcc->streams_max_bit_rate = stream_bit_rate;
|
||||
}
|
||||
}
|
||||
stream->refs++;
|
||||
red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &stream_agent->destroy_item);
|
||||
stream_agent_stats_print(stream_agent);
|
||||
}
|
||||
worker->streams_size_total -= stream->width * stream->height;
|
||||
ring_remove(&stream->link);
|
||||
red_release_stream(worker, stream);
|
||||
}
|
||||
|
||||
/* fixme: move to display channel */
|
||||
DrawablePipeItem *drawable_pipe_item_new(DisplayChannelClient *dcc,
|
||||
Drawable *drawable)
|
||||
@ -890,6 +1022,25 @@ static inline void red_destroy_surface_item(RedWorker *worker,
|
||||
red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &destroy->pipe_item);
|
||||
}
|
||||
|
||||
static void red_reset_stream_trace(RedWorker *worker)
|
||||
{
|
||||
Ring *ring = &worker->streams;
|
||||
RingItem *item = ring_get_head(ring);
|
||||
|
||||
while (item) {
|
||||
Stream *stream = SPICE_CONTAINEROF(item, Stream, link);
|
||||
item = ring_next(ring, item);
|
||||
if (!stream->current) {
|
||||
red_stop_stream(worker, stream);
|
||||
} else {
|
||||
spice_info("attached stream");
|
||||
}
|
||||
}
|
||||
|
||||
worker->next_item_trace = 0;
|
||||
memset(worker->items_trace, 0, sizeof(worker->items_trace));
|
||||
}
|
||||
|
||||
static void red_surface_unref(RedWorker *worker, uint32_t surface_id)
|
||||
{
|
||||
RedSurface *surface = &worker->surfaces[surface_id];
|
||||
@ -1514,21 +1665,6 @@ static int is_same_drawable(RedWorker *worker, Drawable *d1, Drawable *d2)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void red_free_stream(RedWorker *worker, Stream *stream)
|
||||
{
|
||||
stream->next = worker->free_streams;
|
||||
worker->free_streams = stream;
|
||||
}
|
||||
|
||||
static void red_release_stream(RedWorker *worker, Stream *stream)
|
||||
{
|
||||
if (!--stream->refs) {
|
||||
spice_assert(!ring_item_is_linked(&stream->link));
|
||||
red_free_stream(worker, stream);
|
||||
worker->stream_count--;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void red_detach_stream(RedWorker *worker, Stream *stream, int detach_sized)
|
||||
{
|
||||
spice_assert(stream->current && stream->current->stream);
|
||||
@ -1540,116 +1676,6 @@ static inline void red_detach_stream(RedWorker *worker, Stream *stream, int deta
|
||||
stream->current = NULL;
|
||||
}
|
||||
|
||||
static void dcc_push_stream_agent_clip(DisplayChannelClient* dcc, StreamAgent *agent)
|
||||
{
|
||||
StreamClipItem *item = stream_clip_item_new(dcc, agent);
|
||||
int n_rects;
|
||||
|
||||
if (!item) {
|
||||
spice_critical("alloc failed");
|
||||
}
|
||||
item->clip_type = SPICE_CLIP_TYPE_RECTS;
|
||||
|
||||
n_rects = pixman_region32_n_rects(&agent->clip);
|
||||
|
||||
item->rects = spice_malloc_n_m(n_rects, sizeof(SpiceRect), sizeof(SpiceClipRects));
|
||||
item->rects->num_rects = n_rects;
|
||||
region_ret_rects(&agent->clip, item->rects->rects, n_rects);
|
||||
red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), (PipeItem *)item);
|
||||
}
|
||||
|
||||
static void red_display_release_stream_clip(RedWorker *worker, StreamClipItem *item)
|
||||
{
|
||||
if (!--item->refs) {
|
||||
red_display_release_stream(worker, item->stream_agent);
|
||||
free(item->rects);
|
||||
free(item);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int get_stream_id(RedWorker *worker, Stream *stream)
|
||||
{
|
||||
return (int)(stream - worker->streams_buf);
|
||||
}
|
||||
|
||||
static void red_attach_stream(RedWorker *worker, Drawable *drawable, Stream *stream)
|
||||
{
|
||||
DisplayChannelClient *dcc;
|
||||
RingItem *item, *next;
|
||||
|
||||
spice_assert(!drawable->stream && !stream->current);
|
||||
spice_assert(drawable && stream);
|
||||
stream->current = drawable;
|
||||
drawable->stream = stream;
|
||||
stream->last_time = drawable->creation_time;
|
||||
|
||||
uint64_t duration = drawable->creation_time - stream->input_fps_start_time;
|
||||
if (duration >= RED_STREAM_INPUT_FPS_TIMEOUT) {
|
||||
/* Round to the nearest integer, for instance 24 for 23.976 */
|
||||
stream->input_fps = ((uint64_t)stream->num_input_frames * 1000 * 1000 * 1000 + duration / 2) / duration;
|
||||
spice_debug("input-fps=%u", stream->input_fps);
|
||||
stream->num_input_frames = 0;
|
||||
stream->input_fps_start_time = drawable->creation_time;
|
||||
} else {
|
||||
stream->num_input_frames++;
|
||||
}
|
||||
|
||||
FOREACH_DCC(worker->display_channel, item, next, dcc) {
|
||||
StreamAgent *agent;
|
||||
QRegion clip_in_draw_dest;
|
||||
|
||||
agent = &dcc->stream_agents[get_stream_id(worker, stream)];
|
||||
region_or(&agent->vis_region, &drawable->tree_item.base.rgn);
|
||||
|
||||
region_init(&clip_in_draw_dest);
|
||||
region_add(&clip_in_draw_dest, &drawable->red_drawable->bbox);
|
||||
region_and(&clip_in_draw_dest, &agent->clip);
|
||||
|
||||
if (!region_is_equal(&clip_in_draw_dest, &drawable->tree_item.base.rgn)) {
|
||||
region_remove(&agent->clip, &drawable->red_drawable->bbox);
|
||||
region_or(&agent->clip, &drawable->tree_item.base.rgn);
|
||||
dcc_push_stream_agent_clip(dcc, agent);
|
||||
}
|
||||
#ifdef STREAM_STATS
|
||||
agent->stats.num_input_frames++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void red_stop_stream(RedWorker *worker, Stream *stream)
|
||||
{
|
||||
DisplayChannelClient *dcc;
|
||||
RingItem *item, *next;
|
||||
|
||||
spice_assert(ring_item_is_linked(&stream->link));
|
||||
spice_assert(!stream->current);
|
||||
spice_debug("stream %d", get_stream_id(worker, stream));
|
||||
FOREACH_DCC(worker->display_channel, item, next, dcc) {
|
||||
StreamAgent *stream_agent;
|
||||
|
||||
stream_agent = &dcc->stream_agents[get_stream_id(worker, stream)];
|
||||
region_clear(&stream_agent->vis_region);
|
||||
region_clear(&stream_agent->clip);
|
||||
spice_assert(!pipe_item_is_linked(&stream_agent->destroy_item));
|
||||
if (stream_agent->mjpeg_encoder && dcc->use_mjpeg_encoder_rate_control) {
|
||||
uint64_t stream_bit_rate = mjpeg_encoder_get_bit_rate(stream_agent->mjpeg_encoder);
|
||||
|
||||
if (stream_bit_rate > dcc->streams_max_bit_rate) {
|
||||
spice_debug("old max-bit-rate=%.2f new=%.2f",
|
||||
dcc->streams_max_bit_rate / 8.0 / 1024.0 / 1024.0,
|
||||
stream_bit_rate / 8.0 / 1024.0 / 1024.0);
|
||||
dcc->streams_max_bit_rate = stream_bit_rate;
|
||||
}
|
||||
}
|
||||
stream->refs++;
|
||||
red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &stream_agent->destroy_item);
|
||||
stream_agent_stats_print(stream_agent);
|
||||
}
|
||||
worker->streams_size_total -= stream->width * stream->height;
|
||||
ring_remove(&stream->link);
|
||||
red_release_stream(worker, stream);
|
||||
}
|
||||
|
||||
static int red_display_drawable_is_in_pipe(DisplayChannelClient *dcc, Drawable *drawable)
|
||||
{
|
||||
DrawablePipeItem *dpi;
|
||||
@ -1870,12 +1896,6 @@ static inline void red_handle_streams_timout(RedWorker *worker)
|
||||
}
|
||||
}
|
||||
|
||||
static void red_display_release_stream(RedWorker *worker, StreamAgent *agent)
|
||||
{
|
||||
spice_assert(agent->stream);
|
||||
red_release_stream(worker, agent->stream);
|
||||
}
|
||||
|
||||
static inline Stream *red_alloc_stream(RedWorker *worker)
|
||||
{
|
||||
Stream *stream;
|
||||
@ -2146,19 +2166,6 @@ static void dcc_destroy_stream_agents(DisplayChannelClient *dcc)
|
||||
}
|
||||
}
|
||||
|
||||
static void red_init_streams(RedWorker *worker)
|
||||
{
|
||||
int i;
|
||||
|
||||
ring_init(&worker->streams);
|
||||
worker->free_streams = NULL;
|
||||
for (i = 0; i < NUM_STREAMS; i++) {
|
||||
Stream *stream = &worker->streams_buf[i];
|
||||
ring_item_init(&stream->link);
|
||||
red_free_stream(worker, stream);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int __red_is_next_stream_frame(RedWorker *worker,
|
||||
const Drawable *candidate,
|
||||
const int other_src_width,
|
||||
@ -2579,25 +2586,6 @@ static inline void red_use_stream_trace(RedWorker *worker, Drawable *drawable)
|
||||
}
|
||||
}
|
||||
|
||||
static void red_reset_stream_trace(RedWorker *worker)
|
||||
{
|
||||
Ring *ring = &worker->streams;
|
||||
RingItem *item = ring_get_head(ring);
|
||||
|
||||
while (item) {
|
||||
Stream *stream = SPICE_CONTAINEROF(item, Stream, link);
|
||||
item = ring_next(ring, item);
|
||||
if (!stream->current) {
|
||||
red_stop_stream(worker, stream);
|
||||
} else {
|
||||
spice_info("attached stream");
|
||||
}
|
||||
}
|
||||
|
||||
worker->next_item_trace = 0;
|
||||
memset(worker->items_trace, 0, sizeof(worker->items_trace));
|
||||
}
|
||||
|
||||
static inline int red_current_add(RedWorker *worker, Ring *ring, Drawable *drawable)
|
||||
{
|
||||
DrawItem *item = &drawable->tree_item;
|
||||
@ -8868,6 +8856,19 @@ static void display_channel_release_item(RedChannelClient *rcc, PipeItem *item,
|
||||
}
|
||||
}
|
||||
|
||||
static void red_init_streams(RedWorker *worker)
|
||||
{
|
||||
int i;
|
||||
|
||||
ring_init(&worker->streams);
|
||||
worker->free_streams = NULL;
|
||||
for (i = 0; i < NUM_STREAMS; i++) {
|
||||
Stream *stream = &worker->streams_buf[i];
|
||||
ring_item_init(&stream->link);
|
||||
red_free_stream(worker, stream);
|
||||
}
|
||||
}
|
||||
|
||||
static void display_channel_create(RedWorker *worker, int migrate)
|
||||
{
|
||||
DisplayChannel *display_channel;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user