mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-01-08 04:11:52 +00:00
Improve encapsulation of DisplayChannel
Add a couple new functions to the header so that they can be called by other objects rather than poking into the internals of the struct.
This commit is contained in:
parent
83ff645d54
commit
fede3f38c5
@ -94,7 +94,7 @@ static int is_surface_area_lossy(DisplayChannelClient *dcc, uint32_t surface_id,
|
||||
QRegion lossy_region;
|
||||
DisplayChannel *display = DCC_TO_DC(dcc);
|
||||
|
||||
spice_return_val_if_fail(validate_surface(display, surface_id), FALSE);
|
||||
spice_return_val_if_fail(display_channel_validate_surface(display, surface_id), FALSE);
|
||||
|
||||
surface = &display->surfaces[surface_id];
|
||||
surface_lossy_region = &dcc->priv->surface_client_lossy_region[surface_id];
|
||||
@ -403,7 +403,7 @@ static FillBitsType fill_bits(DisplayChannelClient *dcc, SpiceMarshaller *m,
|
||||
RedSurface *surface;
|
||||
|
||||
surface_id = simage->u.surface.surface_id;
|
||||
if (!validate_surface(display, surface_id)) {
|
||||
if (!display_channel_validate_surface(display, surface_id)) {
|
||||
spice_warning("Invalid surface in SPICE_IMAGE_TYPE_SURFACE");
|
||||
pthread_mutex_unlock(&dcc->priv->pixmap_cache->lock);
|
||||
return FILL_BITS_TYPE_SURFACE;
|
||||
@ -1694,7 +1694,7 @@ static int red_marshall_stream_data(RedChannelClient *rcc,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
StreamAgent *agent = &dcc->priv->stream_agents[get_stream_id(display, stream)];
|
||||
StreamAgent *agent = &dcc->priv->stream_agents[display_channel_get_stream_id(display, stream)];
|
||||
uint64_t time_now = spice_get_monotonic_time_ns();
|
||||
|
||||
if (!dcc->priv->use_video_encoder_rate_control) {
|
||||
@ -1740,7 +1740,7 @@ static int red_marshall_stream_data(RedChannelClient *rcc,
|
||||
|
||||
red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_DATA, NULL);
|
||||
|
||||
stream_data.base.id = get_stream_id(display, stream);
|
||||
stream_data.base.id = display_channel_get_stream_id(display, stream);
|
||||
stream_data.base.multi_media_time = frame_mm_time;
|
||||
stream_data.data_size = outbuf->size;
|
||||
|
||||
@ -1750,7 +1750,7 @@ static int red_marshall_stream_data(RedChannelClient *rcc,
|
||||
|
||||
red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_DATA_SIZED, NULL);
|
||||
|
||||
stream_data.base.id = get_stream_id(display, stream);
|
||||
stream_data.base.id = display_channel_get_stream_id(display, stream);
|
||||
stream_data.base.multi_media_time = frame_mm_time;
|
||||
stream_data.data_size = outbuf->size;
|
||||
stream_data.width = copy->src_area.right - copy->src_area.left;
|
||||
@ -2159,7 +2159,7 @@ static void marshall_stream_start(RedChannelClient *rcc,
|
||||
SpiceClipRects clip_rects;
|
||||
|
||||
stream_create.surface_id = 0;
|
||||
stream_create.id = get_stream_id(DCC_TO_DC(dcc), stream);
|
||||
stream_create.id = display_channel_get_stream_id(DCC_TO_DC(dcc), stream);
|
||||
stream_create.flags = stream->top_down ? SPICE_STREAM_FLAGS_TOP_DOWN : 0;
|
||||
stream_create.codec_type = agent->video_encoder->codec_type;
|
||||
|
||||
@ -2195,7 +2195,7 @@ static void marshall_stream_clip(RedChannelClient *rcc,
|
||||
red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_CLIP, &item->base);
|
||||
SpiceMsgDisplayStreamClip stream_clip;
|
||||
|
||||
stream_clip.id = get_stream_id(DCC_TO_DC(dcc), agent->stream);
|
||||
stream_clip.id = display_channel_get_stream_id(DCC_TO_DC(dcc), agent->stream);
|
||||
stream_clip.clip.type = item->clip_type;
|
||||
stream_clip.clip.rects = item->rects;
|
||||
|
||||
@ -2209,7 +2209,7 @@ static void marshall_stream_end(RedChannelClient *rcc,
|
||||
SpiceMsgDisplayStreamDestroy destroy;
|
||||
|
||||
red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_DESTROY, NULL);
|
||||
destroy.id = get_stream_id(DCC_TO_DC(dcc), agent->stream);
|
||||
destroy.id = display_channel_get_stream_id(DCC_TO_DC(dcc), agent->stream);
|
||||
stream_agent_stop(agent);
|
||||
spice_marshall_msg_display_stream_destroy(base_marshaller, &destroy);
|
||||
}
|
||||
|
||||
@ -203,6 +203,13 @@ void display_channel_surface_unref(DisplayChannel *display, uint32_t surface_id)
|
||||
spice_warn_if_fail(ring_is_empty(&surface->depend_on_me));
|
||||
}
|
||||
|
||||
/* TODO: perhaps rename to "ready" or "realized" ? */
|
||||
gboolean display_channel_surface_has_canvas(DisplayChannel *display,
|
||||
uint32_t surface_id)
|
||||
{
|
||||
return display->surfaces[surface_id].context.canvas != NULL;
|
||||
}
|
||||
|
||||
static void streams_update_visible_region(DisplayChannel *display, Drawable *drawable)
|
||||
{
|
||||
Ring *ring;
|
||||
@ -232,7 +239,7 @@ static void streams_update_visible_region(DisplayChannel *display, Drawable *dra
|
||||
}
|
||||
|
||||
FOREACH_CLIENT(display, link, next, dcc) {
|
||||
agent = dcc_get_stream_agent(dcc, get_stream_id(display, stream));
|
||||
agent = dcc_get_stream_agent(dcc, display_channel_get_stream_id(display, stream));
|
||||
|
||||
if (region_intersects(&agent->vis_region, &drawable->tree_item.base.rgn)) {
|
||||
region_exclude(&agent->vis_region, &drawable->tree_item.base.rgn);
|
||||
@ -955,7 +962,7 @@ static int validate_drawable_bbox(DisplayChannel *display, RedDrawable *drawable
|
||||
/* surface_id must be validated before calling into
|
||||
* validate_drawable_bbox
|
||||
*/
|
||||
if (!validate_surface(display, drawable->surface_id)) {
|
||||
if (!display_channel_validate_surface(display, drawable->surface_id)) {
|
||||
return FALSE;
|
||||
}
|
||||
context = &display->surfaces[surface_id].context;
|
||||
@ -998,7 +1005,7 @@ static Drawable *display_channel_get_drawable(DisplayChannel *display, uint8_t e
|
||||
}
|
||||
for (x = 0; x < 3; ++x) {
|
||||
if (red_drawable->surface_deps[x] != -1
|
||||
&& !validate_surface(display, red_drawable->surface_deps[x])) {
|
||||
&& !display_channel_validate_surface(display, red_drawable->surface_deps[x])) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -1669,7 +1676,7 @@ void display_channel_update(DisplayChannel *display,
|
||||
SpiceRect rect;
|
||||
RedSurface *surface;
|
||||
|
||||
spice_return_if_fail(validate_surface(display, surface_id));
|
||||
spice_return_if_fail(display_channel_validate_surface(display, surface_id));
|
||||
|
||||
red_get_rect_ptr(&rect, area);
|
||||
display_channel_draw(display, &rect, surface_id);
|
||||
@ -1712,7 +1719,7 @@ static void display_channel_destroy_surface(DisplayChannel *display, uint32_t su
|
||||
|
||||
void display_channel_destroy_surface_wait(DisplayChannel *display, uint32_t surface_id)
|
||||
{
|
||||
if (!validate_surface(display, surface_id))
|
||||
if (!display_channel_validate_surface(display, surface_id))
|
||||
return;
|
||||
if (!display->surfaces[surface_id].context.canvas)
|
||||
return;
|
||||
@ -1882,7 +1889,7 @@ static SpiceCanvas *image_surfaces_get(SpiceImageSurfaces *surfaces, uint32_t su
|
||||
{
|
||||
DisplayChannel *display = SPICE_CONTAINEROF(surfaces, DisplayChannel, image_surfaces);
|
||||
|
||||
spice_return_val_if_fail(validate_surface(display, surface_id), NULL);
|
||||
spice_return_val_if_fail(display_channel_validate_surface(display, surface_id), NULL);
|
||||
|
||||
return display->surfaces[surface_id].context.canvas;
|
||||
}
|
||||
@ -2038,3 +2045,55 @@ void display_channel_gl_draw_done(DisplayChannel *display)
|
||||
{
|
||||
set_gl_draw_async_count(display, display->gl_draw_async_count - 1);
|
||||
}
|
||||
|
||||
int display_channel_get_stream_id(DisplayChannel *display, Stream *stream)
|
||||
{
|
||||
return (int)(stream - display->streams_buf);
|
||||
}
|
||||
|
||||
gboolean display_channel_validate_surface(DisplayChannel *display, uint32_t surface_id)
|
||||
{
|
||||
if SPICE_UNLIKELY(surface_id >= display->n_surfaces) {
|
||||
spice_warning("invalid surface_id %u", surface_id);
|
||||
return FALSE;
|
||||
}
|
||||
if (!display->surfaces[surface_id].context.canvas) {
|
||||
spice_warning("canvas address is %p for %d (and is NULL)\n",
|
||||
&(display->surfaces[surface_id].context.canvas), surface_id);
|
||||
spice_warning("failed on %d", surface_id);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void display_channel_update_monitors_config(DisplayChannel *display,
|
||||
QXLMonitorsConfig *config,
|
||||
uint16_t count, uint16_t max_allowed)
|
||||
{
|
||||
|
||||
if (display->monitors_config)
|
||||
monitors_config_unref(display->monitors_config);
|
||||
|
||||
display->monitors_config =
|
||||
monitors_config_new(config->heads, count, max_allowed);
|
||||
}
|
||||
|
||||
void set_monitors_config_to_primary(DisplayChannel *display)
|
||||
{
|
||||
DrawContext *context = &display->surfaces[0].context;
|
||||
QXLHead head = { 0, };
|
||||
|
||||
spice_return_if_fail(display->surfaces[0].context.canvas);
|
||||
|
||||
if (display->monitors_config)
|
||||
monitors_config_unref(display->monitors_config);
|
||||
|
||||
head.width = context->width;
|
||||
head.height = context->height;
|
||||
display->monitors_config = monitors_config_new(&head, 1, 1);
|
||||
}
|
||||
|
||||
void display_channel_reset_image_cache(DisplayChannel *self)
|
||||
{
|
||||
image_cache_reset(&self->image_cache);
|
||||
}
|
||||
|
||||
@ -208,10 +208,17 @@ struct DisplayChannel {
|
||||
ImageEncoderSharedData encoder_shared_data;
|
||||
};
|
||||
|
||||
static inline int get_stream_id(DisplayChannel *display, Stream *stream)
|
||||
{
|
||||
return (int)(stream - display->streams_buf);
|
||||
}
|
||||
|
||||
#define FOREACH_DCC(channel, _link, _next, _data) \
|
||||
for (_link = (channel ? RED_CHANNEL(channel)->clients : NULL), \
|
||||
_next = (_link ? _link->next : NULL), \
|
||||
_data = (_link ? _link->data : NULL); \
|
||||
_link; \
|
||||
_link = _next, \
|
||||
_next = (_link ? _link->next : NULL), \
|
||||
_data = (_link ? _link->data : NULL))
|
||||
|
||||
int display_channel_get_stream_id(DisplayChannel *display, Stream *stream);
|
||||
|
||||
typedef struct RedSurfaceDestroyItem {
|
||||
RedPipeItem pipe_item;
|
||||
@ -281,20 +288,13 @@ void display_channel_gl_draw (DisplayCha
|
||||
SpiceMsgDisplayGlDraw *draw);
|
||||
void display_channel_gl_draw_done (DisplayChannel *display);
|
||||
|
||||
static inline int validate_surface(DisplayChannel *display, uint32_t surface_id)
|
||||
{
|
||||
if SPICE_UNLIKELY(surface_id >= display->n_surfaces) {
|
||||
spice_warning("invalid surface_id %u", surface_id);
|
||||
return 0;
|
||||
}
|
||||
if (!display->surfaces[surface_id].context.canvas) {
|
||||
spice_warning("canvas address is %p for %d (and is NULL)\n",
|
||||
&(display->surfaces[surface_id].context.canvas), surface_id);
|
||||
spice_warning("failed on %d", surface_id);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
void display_channel_update_monitors_config(DisplayChannel *display, QXLMonitorsConfig *config,
|
||||
uint16_t count, uint16_t max_allowed);
|
||||
void set_monitors_config_to_primary(DisplayChannel *display);
|
||||
|
||||
gboolean display_channel_validate_surface(DisplayChannel *display, uint32_t surface_id);
|
||||
gboolean display_channel_surface_has_canvas(DisplayChannel *display, uint32_t surface_id);
|
||||
void display_channel_reset_image_cache(DisplayChannel *self);
|
||||
|
||||
static inline int is_equal_path(SpicePath *path1, SpicePath *path2)
|
||||
{
|
||||
|
||||
@ -247,7 +247,7 @@ static int red_process_display(RedWorker *worker, int *ring_is_empty)
|
||||
&update, ext_cmd.cmd.data)) {
|
||||
break;
|
||||
}
|
||||
if (!validate_surface(worker->display_channel, update.surface_id)) {
|
||||
if (!display_channel_validate_surface(worker->display_channel, update.surface_id)) {
|
||||
spice_warning("Invalid surface in QXL_CMD_UPDATE");
|
||||
} else {
|
||||
display_channel_draw(worker->display_channel, &update.area, update.surface_id);
|
||||
@ -587,18 +587,6 @@ static void handle_dev_destroy_surfaces(void *opaque, void *payload)
|
||||
cursor_channel_reset(worker->cursor_channel);
|
||||
}
|
||||
|
||||
static void display_update_monitors_config(DisplayChannel *display,
|
||||
QXLMonitorsConfig *config,
|
||||
uint16_t count, uint16_t max_allowed)
|
||||
{
|
||||
|
||||
if (display->monitors_config)
|
||||
monitors_config_unref(display->monitors_config);
|
||||
|
||||
display->monitors_config =
|
||||
monitors_config_new(config->heads, count, max_allowed);
|
||||
}
|
||||
|
||||
static void red_worker_push_monitors_config(RedWorker *worker)
|
||||
{
|
||||
DisplayChannelClient *dcc;
|
||||
@ -609,21 +597,6 @@ static void red_worker_push_monitors_config(RedWorker *worker)
|
||||
}
|
||||
}
|
||||
|
||||
static void set_monitors_config_to_primary(DisplayChannel *display)
|
||||
{
|
||||
DrawContext *context = &display->surfaces[0].context;
|
||||
QXLHead head = { 0, };
|
||||
|
||||
spice_return_if_fail(display->surfaces[0].context.canvas);
|
||||
|
||||
if (display->monitors_config)
|
||||
monitors_config_unref(display->monitors_config);
|
||||
|
||||
head.width = context->width;
|
||||
head.height = context->height;
|
||||
display->monitors_config = monitors_config_new(&head, 1, 1);
|
||||
}
|
||||
|
||||
static void dev_create_primary_surface(RedWorker *worker, uint32_t surface_id,
|
||||
QXLDevSurfaceCreate surface)
|
||||
{
|
||||
@ -689,12 +662,12 @@ static void destroy_primary_surface(RedWorker *worker, uint32_t surface_id)
|
||||
{
|
||||
DisplayChannel *display = worker->display_channel;
|
||||
|
||||
if (!validate_surface(display, surface_id))
|
||||
if (!display_channel_validate_surface(display, surface_id))
|
||||
return;
|
||||
spice_warn_if_fail(surface_id == 0);
|
||||
|
||||
spice_debug(NULL);
|
||||
if (!display->surfaces[surface_id].context.canvas) {
|
||||
if (!display_channel_surface_has_canvas(display, surface_id)) {
|
||||
spice_warning("double destroy of primary surface");
|
||||
return;
|
||||
}
|
||||
@ -704,7 +677,7 @@ static void destroy_primary_surface(RedWorker *worker, uint32_t surface_id)
|
||||
display_channel_surface_unref(display, 0);
|
||||
|
||||
spice_warn_if_fail(ring_is_empty(&display->streams));
|
||||
spice_warn_if_fail(!display->surfaces[surface_id].context.canvas);
|
||||
spice_warn_if_fail(!display_channel_surface_has_canvas(display, surface_id));
|
||||
|
||||
cursor_channel_reset(worker->cursor_channel);
|
||||
}
|
||||
@ -828,9 +801,8 @@ static void handle_dev_reset_cursor(void *opaque, void *payload)
|
||||
static void handle_dev_reset_image_cache(void *opaque, void *payload)
|
||||
{
|
||||
RedWorker *worker = opaque;
|
||||
DisplayChannel *display = worker->display_channel;
|
||||
|
||||
image_cache_reset(&display->image_cache);
|
||||
display_channel_reset_image_cache(worker->display_channel);
|
||||
}
|
||||
|
||||
static void handle_dev_destroy_surface_wait_async(void *opaque, void *payload)
|
||||
@ -950,9 +922,9 @@ static void handle_dev_monitors_config_async(void *opaque, void *payload)
|
||||
/* TODO: raise guest bug (requires added QXL interface) */
|
||||
return;
|
||||
}
|
||||
display_update_monitors_config(worker->display_channel, dev_monitors_config,
|
||||
MIN(count, msg->max_monitors),
|
||||
MIN(max_allowed, msg->max_monitors));
|
||||
display_channel_update_monitors_config(worker->display_channel, dev_monitors_config,
|
||||
MIN(count, msg->max_monitors),
|
||||
MIN(max_allowed, msg->max_monitors));
|
||||
red_worker_push_monitors_config(worker);
|
||||
}
|
||||
|
||||
|
||||
@ -101,11 +101,11 @@ void stream_stop(DisplayChannel *display, Stream *stream)
|
||||
spice_return_if_fail(ring_item_is_linked(&stream->link));
|
||||
spice_return_if_fail(!stream->current);
|
||||
|
||||
spice_debug("stream %d", get_stream_id(display, stream));
|
||||
spice_debug("stream %d", display_channel_get_stream_id(display, stream));
|
||||
FOREACH_CLIENT(display, link, next, dcc) {
|
||||
StreamAgent *stream_agent;
|
||||
|
||||
stream_agent = dcc_get_stream_agent(dcc, get_stream_id(display, stream));
|
||||
stream_agent = dcc_get_stream_agent(dcc, display_channel_get_stream_id(display, stream));
|
||||
region_clear(&stream_agent->vis_region);
|
||||
region_clear(&stream_agent->clip);
|
||||
if (stream_agent->video_encoder && dcc_use_video_encoder_rate_control(dcc)) {
|
||||
@ -302,7 +302,7 @@ static void attach_stream(DisplayChannel *display, Drawable *drawable, Stream *s
|
||||
StreamAgent *agent;
|
||||
QRegion clip_in_draw_dest;
|
||||
|
||||
agent = dcc_get_stream_agent(dcc, get_stream_id(display, stream));
|
||||
agent = dcc_get_stream_agent(dcc, display_channel_get_stream_id(display, stream));
|
||||
region_or(&agent->vis_region, &drawable->tree_item.base.rgn);
|
||||
|
||||
region_init(&clip_in_draw_dest);
|
||||
@ -349,7 +349,7 @@ static void before_reattach_stream(DisplayChannel *display,
|
||||
return;
|
||||
}
|
||||
|
||||
index = get_stream_id(display, stream);
|
||||
index = display_channel_get_stream_id(display, stream);
|
||||
DRAWABLE_FOREACH_DPI_SAFE(stream->current, ring_item, next, dpi) {
|
||||
dcc = dpi->dcc;
|
||||
agent = dcc_get_stream_agent(dcc, index);
|
||||
@ -759,7 +759,7 @@ static VideoEncoder* dcc_create_video_encoder(DisplayChannelClient *dcc,
|
||||
|
||||
void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream)
|
||||
{
|
||||
StreamAgent *agent = dcc_get_stream_agent(dcc, get_stream_id(DCC_TO_DC(dcc), stream));
|
||||
StreamAgent *agent = dcc_get_stream_agent(dcc, display_channel_get_stream_id(DCC_TO_DC(dcc), stream));
|
||||
|
||||
spice_return_if_fail(region_is_empty(&agent->vis_region));
|
||||
|
||||
@ -796,7 +796,7 @@ void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream)
|
||||
agent->report_id = rand();
|
||||
red_pipe_item_init(&report_pipe_item->pipe_item,
|
||||
RED_PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT);
|
||||
report_pipe_item->stream_id = get_stream_id(DCC_TO_DC(dcc), stream);
|
||||
report_pipe_item->stream_id = display_channel_get_stream_id(DCC_TO_DC(dcc), stream);
|
||||
red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &report_pipe_item->pipe_item);
|
||||
}
|
||||
#ifdef STREAM_STATS
|
||||
@ -839,7 +839,7 @@ static void dcc_detach_stream_gracefully(DisplayChannelClient *dcc,
|
||||
Drawable *update_area_limit)
|
||||
{
|
||||
DisplayChannel *display = DCC_TO_DC(dcc);
|
||||
int stream_id = get_stream_id(display, stream);
|
||||
int stream_id = display_channel_get_stream_id(display, stream);
|
||||
StreamAgent *agent = dcc_get_stream_agent(dcc, stream_id);
|
||||
|
||||
/* stopping the client from playing older frames at once*/
|
||||
@ -936,12 +936,12 @@ void stream_detach_behind(DisplayChannel *display, QRegion *region, Drawable *dr
|
||||
item = ring_next(ring, item);
|
||||
|
||||
FOREACH_CLIENT(display, link, next, dcc) {
|
||||
StreamAgent *agent = dcc_get_stream_agent(dcc, get_stream_id(display, stream));
|
||||
StreamAgent *agent = dcc_get_stream_agent(dcc, display_channel_get_stream_id(display, stream));
|
||||
|
||||
if (region_intersects(&agent->vis_region, region)) {
|
||||
dcc_detach_stream_gracefully(dcc, stream, drawable);
|
||||
detach = 1;
|
||||
spice_debug("stream %d", get_stream_id(display, stream));
|
||||
spice_debug("stream %d", display_channel_get_stream_id(display, stream));
|
||||
}
|
||||
}
|
||||
if (detach && stream->current) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user