mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2025-12-27 15:45:54 +00:00
Handle GL_SCANOUT messages
Go through dispatcher and marshall scanout message. Since the marshaller and the QXL state are manipulated from different threads, add a mutex to protect the current scanout. Signed-off-by: Marc-André Lureau <marcandre.lureau@gmail.com>
This commit is contained in:
parent
ebf461b8e6
commit
7a06efde1c
@ -2299,6 +2299,28 @@ static void marshall_stream_activate_report(RedChannelClient *rcc,
|
|||||||
spice_marshall_msg_display_stream_activate_report(base_marshaller, &msg);
|
spice_marshall_msg_display_stream_activate_report(base_marshaller, &msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void marshall_gl_scanout(RedChannelClient *rcc,
|
||||||
|
SpiceMarshaller *m,
|
||||||
|
PipeItem *item)
|
||||||
|
{
|
||||||
|
DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
|
||||||
|
DisplayChannel *display_channel = DCC_TO_DC(dcc);
|
||||||
|
RedWorker *worker = display_channel->common.worker;
|
||||||
|
QXLInstance* qxl = red_worker_get_qxl(worker);
|
||||||
|
SpiceMsgDisplayGlScanoutUnix *so = &qxl->st->scanout;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&qxl->st->scanout_mutex);
|
||||||
|
|
||||||
|
if (so->drm_dma_buf_fd == -1)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_GL_SCANOUT_UNIX, NULL);
|
||||||
|
spice_marshall_msg_display_gl_scanout_unix(m, so);
|
||||||
|
|
||||||
|
end:
|
||||||
|
pthread_mutex_unlock(&qxl->st->scanout_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
static void begin_send_message(RedChannelClient *rcc)
|
static void begin_send_message(RedChannelClient *rcc)
|
||||||
{
|
{
|
||||||
DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
|
DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
|
||||||
@ -2410,6 +2432,9 @@ void dcc_send_item(DisplayChannelClient *dcc, PipeItem *pipe_item)
|
|||||||
marshall_stream_activate_report(rcc, m, report_item->stream_id);
|
marshall_stream_activate_report(rcc, m, report_item->stream_id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PIPE_ITEM_TYPE_GL_SCANOUT:
|
||||||
|
marshall_gl_scanout(rcc, m, pipe_item);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
spice_warn_if_reached();
|
spice_warn_if_reached();
|
||||||
}
|
}
|
||||||
|
|||||||
21
server/dcc.c
21
server/dcc.c
@ -556,6 +556,25 @@ static SurfaceDestroyItem *surface_destroy_item_new(RedChannel *channel,
|
|||||||
return destroy;
|
return destroy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PipeItem *dcc_gl_scanout_item_new(RedChannelClient *rcc, void *data, int num)
|
||||||
|
{
|
||||||
|
GlScanoutUnixItem *item = spice_new(GlScanoutUnixItem, 1);
|
||||||
|
spice_return_val_if_fail(item != NULL, NULL);
|
||||||
|
|
||||||
|
/* FIXME: on !unix peer, start streaming with a video codec */
|
||||||
|
if (!reds_stream_is_plain_unix(rcc->stream) ||
|
||||||
|
!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;
|
||||||
|
}
|
||||||
|
|
||||||
|
red_channel_pipe_item_init(rcc->channel, &item->base,
|
||||||
|
PIPE_ITEM_TYPE_GL_SCANOUT);
|
||||||
|
|
||||||
|
return &item->base;
|
||||||
|
}
|
||||||
|
|
||||||
void dcc_destroy_surface(DisplayChannelClient *dcc, uint32_t surface_id)
|
void dcc_destroy_surface(DisplayChannelClient *dcc, uint32_t surface_id)
|
||||||
{
|
{
|
||||||
DisplayChannel *display;
|
DisplayChannel *display;
|
||||||
@ -1527,6 +1546,7 @@ static void release_item_after_push(DisplayChannelClient *dcc, PipeItem *item)
|
|||||||
case PIPE_ITEM_TYPE_IMAGE:
|
case PIPE_ITEM_TYPE_IMAGE:
|
||||||
image_item_unref((ImageItem *)item);
|
image_item_unref((ImageItem *)item);
|
||||||
break;
|
break;
|
||||||
|
case PIPE_ITEM_TYPE_GL_SCANOUT:
|
||||||
case PIPE_ITEM_TYPE_VERB:
|
case PIPE_ITEM_TYPE_VERB:
|
||||||
free(item);
|
free(item);
|
||||||
break;
|
break;
|
||||||
@ -1601,6 +1621,7 @@ static void release_item_before_push(DisplayChannelClient *dcc, PipeItem *item)
|
|||||||
case PIPE_ITEM_TYPE_PIXMAP_RESET:
|
case PIPE_ITEM_TYPE_PIXMAP_RESET:
|
||||||
case PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE:
|
case PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE:
|
||||||
case PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT:
|
case PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT:
|
||||||
|
case PIPE_ITEM_TYPE_GL_SCANOUT:
|
||||||
free(item);
|
free(item);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -124,6 +124,10 @@ typedef struct SurfaceCreateItem {
|
|||||||
PipeItem pipe_item;
|
PipeItem pipe_item;
|
||||||
} SurfaceCreateItem;
|
} SurfaceCreateItem;
|
||||||
|
|
||||||
|
typedef struct GlScanoutUnixItem {
|
||||||
|
PipeItem base;
|
||||||
|
} GlScanoutUnixItem;
|
||||||
|
|
||||||
typedef struct ImageItem {
|
typedef struct ImageItem {
|
||||||
PipeItem link;
|
PipeItem link;
|
||||||
int refs;
|
int refs;
|
||||||
@ -207,6 +211,8 @@ int dcc_clear_surface_drawables_from_pipe (DisplayCha
|
|||||||
int wait_if_used);
|
int wait_if_used);
|
||||||
int dcc_drawable_is_in_pipe (DisplayChannelClient *dcc,
|
int dcc_drawable_is_in_pipe (DisplayChannelClient *dcc,
|
||||||
Drawable *drawable);
|
Drawable *drawable);
|
||||||
|
PipeItem * dcc_gl_scanout_item_new (RedChannelClient *rcc,
|
||||||
|
void *data, int num);
|
||||||
|
|
||||||
typedef struct compress_send_data_t {
|
typedef struct compress_send_data_t {
|
||||||
void* comp_buf;
|
void* comp_buf;
|
||||||
|
|||||||
@ -2149,3 +2149,8 @@ void display_channel_update_compression(DisplayChannel *display, DisplayChannelC
|
|||||||
spice_info("jpeg %s", display->enable_jpeg ? "enabled" : "disabled");
|
spice_info("jpeg %s", display->enable_jpeg ? "enabled" : "disabled");
|
||||||
spice_info("zlib-over-glz %s", display->enable_zlib_glz_wrap ? "enabled" : "disabled");
|
spice_info("zlib-over-glz %s", display->enable_zlib_glz_wrap ? "enabled" : "disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void display_channel_gl_scanout(DisplayChannel *display)
|
||||||
|
{
|
||||||
|
red_channel_pipes_new_add_push(RED_CHANNEL(display), dcc_gl_scanout_item_new, NULL);
|
||||||
|
}
|
||||||
|
|||||||
@ -106,6 +106,7 @@ enum {
|
|||||||
PIPE_ITEM_TYPE_DESTROY_SURFACE,
|
PIPE_ITEM_TYPE_DESTROY_SURFACE,
|
||||||
PIPE_ITEM_TYPE_MONITORS_CONFIG,
|
PIPE_ITEM_TYPE_MONITORS_CONFIG,
|
||||||
PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT,
|
PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT,
|
||||||
|
PIPE_ITEM_TYPE_GL_SCANOUT,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct MonitorsConfig {
|
typedef struct MonitorsConfig {
|
||||||
@ -306,6 +307,7 @@ void display_channel_process_surface_cmd (DisplayCha
|
|||||||
int loadvm);
|
int loadvm);
|
||||||
void display_channel_update_compression (DisplayChannel *display,
|
void display_channel_update_compression (DisplayChannel *display,
|
||||||
DisplayChannelClient *dcc);
|
DisplayChannelClient *dcc);
|
||||||
|
void display_channel_gl_scanout (DisplayChannel *display);
|
||||||
|
|
||||||
static inline int validate_surface(DisplayChannel *display, uint32_t surface_id)
|
static inline int validate_surface(DisplayChannel *display, uint32_t surface_id)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -970,6 +970,8 @@ void spice_qxl_gl_scanout(QXLInstance *qxl,
|
|||||||
spice_return_if_fail(qxl != NULL);
|
spice_return_if_fail(qxl != NULL);
|
||||||
spice_return_if_fail(qxl->st->gl_draw_async == NULL);
|
spice_return_if_fail(qxl->st->gl_draw_async == NULL);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&qxl->st->scanout_mutex);
|
||||||
|
|
||||||
if (qxl->st->scanout.drm_dma_buf_fd != -1) {
|
if (qxl->st->scanout.drm_dma_buf_fd != -1) {
|
||||||
close(qxl->st->scanout.drm_dma_buf_fd);
|
close(qxl->st->scanout.drm_dma_buf_fd);
|
||||||
}
|
}
|
||||||
@ -982,6 +984,12 @@ void spice_qxl_gl_scanout(QXLInstance *qxl,
|
|||||||
.stride = stride,
|
.stride = stride,
|
||||||
.drm_fourcc_format = format
|
.drm_fourcc_format = format
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&qxl->st->scanout_mutex);
|
||||||
|
|
||||||
|
/* FIXME: find a way to coallesce all pending SCANOUTs */
|
||||||
|
dispatcher_send_message(&qxl->st->dispatcher->dispatcher,
|
||||||
|
RED_WORKER_MESSAGE_GL_SCANOUT, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
SPICE_GNUC_VISIBLE
|
SPICE_GNUC_VISIBLE
|
||||||
|
|||||||
@ -88,6 +88,7 @@ enum {
|
|||||||
|
|
||||||
RED_WORKER_MESSAGE_MONITORS_CONFIG_ASYNC,
|
RED_WORKER_MESSAGE_MONITORS_CONFIG_ASYNC,
|
||||||
RED_WORKER_MESSAGE_DRIVER_UNLOAD,
|
RED_WORKER_MESSAGE_DRIVER_UNLOAD,
|
||||||
|
RED_WORKER_MESSAGE_GL_SCANOUT,
|
||||||
|
|
||||||
RED_WORKER_MESSAGE_COUNT // LAST
|
RED_WORKER_MESSAGE_COUNT // LAST
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1159,6 +1159,14 @@ static void handle_dev_driver_unload(void *opaque, void *payload)
|
|||||||
worker->driver_cap_monitors_config = 0;
|
worker->driver_cap_monitors_config = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void handle_dev_gl_scanout(void *opaque, void *payload)
|
||||||
|
{
|
||||||
|
RedWorker *worker = opaque;
|
||||||
|
|
||||||
|
display_channel_gl_scanout(worker->display_channel);
|
||||||
|
}
|
||||||
|
|
||||||
static int loadvm_command(RedWorker *worker, QXLCommandExt *ext)
|
static int loadvm_command(RedWorker *worker, QXLCommandExt *ext)
|
||||||
{
|
{
|
||||||
RedCursorCmd *cursor_cmd;
|
RedCursorCmd *cursor_cmd;
|
||||||
@ -1396,6 +1404,11 @@ static void register_callbacks(Dispatcher *dispatcher)
|
|||||||
handle_dev_driver_unload,
|
handle_dev_driver_unload,
|
||||||
sizeof(RedWorkerMessageDriverUnload),
|
sizeof(RedWorkerMessageDriverUnload),
|
||||||
DISPATCHER_NONE);
|
DISPATCHER_NONE);
|
||||||
|
dispatcher_register_handler(dispatcher,
|
||||||
|
RED_WORKER_MESSAGE_GL_SCANOUT,
|
||||||
|
handle_dev_gl_scanout,
|
||||||
|
0,
|
||||||
|
DISPATCHER_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -3185,6 +3185,7 @@ SPICE_GNUC_VISIBLE int spice_server_add_interface(SpiceServer *s,
|
|||||||
|
|
||||||
qxl = SPICE_CONTAINEROF(sin, QXLInstance, base);
|
qxl = SPICE_CONTAINEROF(sin, QXLInstance, base);
|
||||||
qxl->st = spice_new0(QXLState, 1);
|
qxl->st = spice_new0(QXLState, 1);
|
||||||
|
pthread_mutex_init(&qxl->st->scanout_mutex, NULL);
|
||||||
qxl->st->scanout.drm_dma_buf_fd = -1;
|
qxl->st->scanout.drm_dma_buf_fd = -1;
|
||||||
qxl->st->qif = SPICE_CONTAINEROF(interface, QXLInterface, base);
|
qxl->st->qif = SPICE_CONTAINEROF(interface, QXLInterface, base);
|
||||||
red_dispatcher_init(qxl);
|
red_dispatcher_init(qxl);
|
||||||
|
|||||||
@ -36,6 +36,7 @@ extern RedsState *reds;
|
|||||||
struct QXLState {
|
struct QXLState {
|
||||||
QXLInterface *qif;
|
QXLInterface *qif;
|
||||||
struct RedDispatcher *dispatcher;
|
struct RedDispatcher *dispatcher;
|
||||||
|
pthread_mutex_t scanout_mutex;
|
||||||
SpiceMsgDisplayGlScanoutUnix scanout;
|
SpiceMsgDisplayGlScanoutUnix scanout;
|
||||||
struct AsyncCommand *gl_draw_async;
|
struct AsyncCommand *gl_draw_async;
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user