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:
Jonathon Jongsma 2016-09-15 11:05:01 -05:00
parent 83ff645d54
commit fede3f38c5
5 changed files with 108 additions and 77 deletions

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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)
{

View File

@ -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);
}

View File

@ -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) {