mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-08-07 14:50:22 +00:00
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:
parent
5881b40ebd
commit
381dc93ec0
@ -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();
|
||||
}
|
||||
|
||||
23
server/dcc.c
23
server/dcc.c
@ -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:
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
};
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user