Handle GL_DRAW messages

Create an async, and marshall the GL_DRAW message. Count number of
clients, and wait until gl_draw_async_count is 0 to complete the async.
The count is going to be updated in the following patch when the client
is done with the draw.

Signed-off-by: Marc-André Lureau <marcandre.lureau@gmail.com>
[removed unused sent field; move gl_draw_async_count to DisplayChannel
 - Frediano Ziglio]
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
This commit is contained in:
Marc-André Lureau 2016-02-09 14:35:05 +01:00 committed by Frediano Ziglio
parent 5881b40ebd
commit 381dc93ec0
8 changed files with 103 additions and 0 deletions

View File

@ -2321,6 +2321,17 @@ end:
pthread_mutex_unlock(&qxl->st->scanout_mutex);
}
static void marshall_gl_draw(RedChannelClient *rcc,
SpiceMarshaller *m,
PipeItem *item)
{
GlDrawItem *p = SPICE_CONTAINEROF(item, GlDrawItem, base);
red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_GL_DRAW, NULL);
spice_marshall_msg_display_gl_draw(m, &p->draw);
}
static void begin_send_message(RedChannelClient *rcc)
{
DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
@ -2435,6 +2446,9 @@ void dcc_send_item(DisplayChannelClient *dcc, PipeItem *pipe_item)
case PIPE_ITEM_TYPE_GL_SCANOUT:
marshall_gl_scanout(rcc, m, pipe_item);
break;
case PIPE_ITEM_TYPE_GL_DRAW:
marshall_gl_draw(rcc, m, pipe_item);
break;
default:
spice_warn_if_reached();
}

View File

@ -586,6 +586,27 @@ PipeItem *dcc_gl_scanout_item_new(RedChannelClient *rcc, void *data, int num)
return &item->base;
}
PipeItem *dcc_gl_draw_item_new(RedChannelClient *rcc, void *data, int num)
{
DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
const SpiceMsgDisplayGlDraw *draw = data;
GlDrawItem *item = spice_new(GlDrawItem, 1);
spice_return_val_if_fail(item != NULL, NULL);
if (!red_channel_client_test_remote_cap(rcc, SPICE_DISPLAY_CAP_GL_SCANOUT)) {
spice_printerr("FIXME: client does not support GL scanout");
red_channel_client_disconnect(rcc);
return NULL;
}
dcc->gl_draw_ongoing = TRUE;
item->draw = *draw;
red_channel_pipe_item_init(rcc->channel, &item->base,
PIPE_ITEM_TYPE_GL_DRAW);
return &item->base;
}
void dcc_destroy_surface(DisplayChannelClient *dcc, uint32_t surface_id)
{
DisplayChannel *display;
@ -1558,6 +1579,7 @@ static void release_item_after_push(DisplayChannelClient *dcc, PipeItem *item)
image_item_unref((ImageItem *)item);
break;
case PIPE_ITEM_TYPE_GL_SCANOUT:
case PIPE_ITEM_TYPE_GL_DRAW:
case PIPE_ITEM_TYPE_VERB:
free(item);
break;
@ -1633,6 +1655,7 @@ static void release_item_before_push(DisplayChannelClient *dcc, PipeItem *item)
case PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE:
case PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT:
case PIPE_ITEM_TYPE_GL_SCANOUT:
case PIPE_ITEM_TYPE_GL_DRAW:
free(item);
break;
default:

View File

@ -111,6 +111,7 @@ struct DisplayChannelClient {
int use_mjpeg_encoder_rate_control;
uint32_t streams_max_latency;
uint64_t streams_max_bit_rate;
bool gl_draw_ongoing;
};
#define DCC_TO_WORKER(dcc) \
@ -128,6 +129,11 @@ typedef struct GlScanoutUnixItem {
PipeItem base;
} GlScanoutUnixItem;
typedef struct GlDrawItem {
PipeItem base;
SpiceMsgDisplayGlDraw draw;
} GlDrawItem;
typedef struct ImageItem {
PipeItem link;
int refs;
@ -213,6 +219,8 @@ int dcc_drawable_is_in_pipe (DisplayCha
Drawable *drawable);
PipeItem * dcc_gl_scanout_item_new (RedChannelClient *rcc,
void *data, int num);
PipeItem * dcc_gl_draw_item_new (RedChannelClient *rcc,
void *data, int num);
typedef struct compress_send_data_t {
void* comp_buf;

View File

@ -2154,3 +2154,27 @@ void display_channel_gl_scanout(DisplayChannel *display)
{
red_channel_pipes_new_add_push(RED_CHANNEL(display), dcc_gl_scanout_item_new, NULL);
}
static void set_gl_draw_async_count(DisplayChannel *display, int num)
{
RedWorker *worker = COMMON_CHANNEL(display)->worker;
QXLInstance *qxl = red_worker_get_qxl(worker);
display->gl_draw_async_count = num;
if (num == 0) {
struct AsyncCommand *async = qxl->st->gl_draw_async;
qxl->st->gl_draw_async = NULL;
red_dispatcher_async_complete(qxl->st->dispatcher, async);
}
}
void display_channel_gl_draw(DisplayChannel *display, SpiceMsgDisplayGlDraw *draw)
{
int num;
spice_return_if_fail(display->gl_draw_async_count == 0);
num = red_channel_pipes_new_add_push(RED_CHANNEL(display), dcc_gl_draw_item_new, draw);
set_gl_draw_async_count(display, num);
}

View File

@ -107,6 +107,7 @@ enum {
PIPE_ITEM_TYPE_MONITORS_CONFIG,
PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT,
PIPE_ITEM_TYPE_GL_SCANOUT,
PIPE_ITEM_TYPE_GL_DRAW,
};
typedef struct MonitorsConfig {
@ -201,6 +202,8 @@ struct DisplayChannel {
ImageCache image_cache;
RedCompressBuf *free_compress_bufs;
int gl_draw_async_count;
/* TODO: some day unify this, make it more runtime.. */
stat_info_t add_stat;
stat_info_t exclude_stat;
@ -308,6 +311,8 @@ void display_channel_process_surface_cmd (DisplayCha
void display_channel_update_compression (DisplayChannel *display,
DisplayChannelClient *dcc);
void display_channel_gl_scanout (DisplayChannel *display);
void display_channel_gl_draw (DisplayChannel *display,
SpiceMsgDisplayGlDraw *draw);
static inline int validate_surface(DisplayChannel *display, uint32_t surface_id)
{

View File

@ -998,9 +998,22 @@ void spice_qxl_gl_draw_async(QXLInstance *qxl,
uint32_t w, uint32_t h,
uint64_t cookie)
{
RedDispatcher *dispatcher;
RedWorkerMessage message = RED_WORKER_MESSAGE_GL_DRAW_ASYNC;
SpiceMsgDisplayGlDraw draw = {
.x = x,
.y = y,
.w = w,
.h = h
};
spice_return_if_fail(qxl != NULL);
spice_return_if_fail(qxl->st->scanout.drm_dma_buf_fd != -1);
spice_return_if_fail(qxl->st->gl_draw_async == NULL);
dispatcher = qxl->st->dispatcher;
qxl->st->gl_draw_async = async_command_alloc(dispatcher, message, cookie);
dispatcher_send_message(&dispatcher->dispatcher, message, &draw);
}
void red_dispatcher_async_complete(struct RedDispatcher *dispatcher,
@ -1020,6 +1033,7 @@ void red_dispatcher_async_complete(struct RedDispatcher *dispatcher,
case RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC:
case RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC:
case RED_WORKER_MESSAGE_MONITORS_CONFIG_ASYNC:
case RED_WORKER_MESSAGE_GL_DRAW_ASYNC:
break;
case RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC:
red_dispatcher_create_primary_surface_complete(dispatcher);

View File

@ -89,6 +89,7 @@ enum {
RED_WORKER_MESSAGE_MONITORS_CONFIG_ASYNC,
RED_WORKER_MESSAGE_DRIVER_UNLOAD,
RED_WORKER_MESSAGE_GL_SCANOUT,
RED_WORKER_MESSAGE_GL_DRAW_ASYNC,
RED_WORKER_MESSAGE_COUNT // LAST
};

View File

@ -1167,6 +1167,15 @@ void handle_dev_gl_scanout(void *opaque, void *payload)
display_channel_gl_scanout(worker->display_channel);
}
static
void handle_dev_gl_draw_async(void *opaque, void *payload)
{
RedWorker *worker = opaque;
SpiceMsgDisplayGlDraw *draw = payload;
display_channel_gl_draw(worker->display_channel, draw);
}
static int loadvm_command(RedWorker *worker, QXLCommandExt *ext)
{
RedCursorCmd *cursor_cmd;
@ -1409,6 +1418,11 @@ static void register_callbacks(Dispatcher *dispatcher)
handle_dev_gl_scanout,
0,
DISPATCHER_NONE);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_GL_DRAW_ASYNC,
handle_dev_gl_draw_async,
sizeof(SpiceMsgDisplayGlDraw),
DISPATCHER_NONE);
}