mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-08-06 18:52:33 +00:00
Send initial draw on client connect for DMA-BUF encoder
Ensure an initial draw is sent immediately upon client connection if the DMA-BUF video encoder is in use. Without this, a frame would only be pushed when the screen content changes and the GPU renders a new frame—which could take a while, causing delays for the client. GStreamer now receives a duplicated file descriptor (fd) and takes responsibility for closing it. This guarantees the buffer remains available long enough. The previous fd mechanism is still retained to ensure a valid scanout buffer is always available for a new client.
This commit is contained in:
parent
a904cd8643
commit
26e650d612
@ -66,6 +66,7 @@ struct DisplayChannelClientPrivate
|
||||
std::array<VideoStreamAgent, NUM_STREAMS> stream_agents;
|
||||
uint64_t streams_max_bit_rate;
|
||||
bool gl_draw_ongoing;
|
||||
bool gl_initial_draw_ongoing = FALSE;
|
||||
};
|
||||
|
||||
#include "pop-visibility.h"
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#include <common/marshaller.h>
|
||||
#include <common/generated_server_marshallers.h>
|
||||
|
||||
#include "dcc.h"
|
||||
#include "dcc-private.h"
|
||||
#include "display-channel-private.h"
|
||||
#include "red-qxl.h"
|
||||
@ -1761,10 +1762,7 @@ static void red_free_cb(VideoEncoderDmabufData *video_dmabuf_data)
|
||||
{
|
||||
auto dmabuf_data = static_cast<DmabufData*>(video_dmabuf_data);
|
||||
auto dcc = dmabuf_data->dcc;
|
||||
DisplayChannel *display = DCC_TO_DC(dcc);
|
||||
|
||||
dcc->priv->gl_draw_ongoing = false;
|
||||
display_channel_gl_draw_done(display);
|
||||
dcc_handle_gl_draw_done(dcc);
|
||||
delete dmabuf_data;
|
||||
}
|
||||
|
||||
@ -1803,7 +1801,7 @@ static void red_marshall_gl_draw_stream(DisplayChannelClient *dcc,
|
||||
return;
|
||||
}
|
||||
|
||||
dmabuf_data->drm_dma_buf_fd = scanout->fd[0];
|
||||
dmabuf_data->drm_dma_buf_fd = dup(scanout->fd[0]);
|
||||
dmabuf_data->drm_fourcc_format = scanout->fourcc;
|
||||
dmabuf_data->width = stream->width;
|
||||
dmabuf_data->height = stream->height;
|
||||
@ -1828,9 +1826,7 @@ static void red_marshall_gl_draw_stream(DisplayChannelClient *dcc,
|
||||
spice_warning("bad ret value (%d) from VideoEncoder::encode_dmabuf",
|
||||
ret);
|
||||
}
|
||||
|
||||
dcc->priv->gl_draw_ongoing = false;
|
||||
display_channel_gl_draw_done(display);
|
||||
dcc_handle_gl_draw_done(dcc);
|
||||
delete dmabuf_data;
|
||||
return;
|
||||
}
|
||||
@ -2432,9 +2428,7 @@ static void marshall_gl_draw(DisplayChannelClient *dcc,
|
||||
} else if (DCC_TO_DC(dcc)->priv->gl_draw_stream) {
|
||||
red_marshall_gl_draw_stream(dcc, m);
|
||||
} else if (dcc->priv->gl_draw_ongoing) {
|
||||
auto display = DCC_TO_DC(dcc);
|
||||
dcc->priv->gl_draw_ongoing = false;
|
||||
display_channel_gl_draw_done(display);
|
||||
dcc_handle_gl_draw_done(dcc);
|
||||
} else {
|
||||
spice_warning("nothing to send to the client");
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#include "red-client.h"
|
||||
#include "main-channel-client.h"
|
||||
#include <spice-server-enums.h>
|
||||
#include "red-qxl.h"
|
||||
|
||||
#define DISPLAY_CLIENT_SHORT_TIMEOUT 15000000000ULL //nano
|
||||
#define DISPLAY_FREE_LIST_DEFAULT_SIZE 128
|
||||
@ -421,6 +422,22 @@ void dcc_start(DisplayChannelClient *dcc)
|
||||
dcc->pipe_add(dcc_gl_scanout_item_new(dcc, nullptr, 0));
|
||||
dcc_push_monitors_config(dcc);
|
||||
}
|
||||
|
||||
if (!dcc->is_gl_client()) {
|
||||
QXLInstance* qxl = display->priv->qxl;
|
||||
RedGLScanout *scanout = red_qxl_get_gl_scanout(qxl);
|
||||
if (scanout) {
|
||||
SpiceMsgDisplayGlDraw draw = {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.w = scanout->width,
|
||||
.h = scanout->height
|
||||
};
|
||||
red_qxl_put_gl_scanout(qxl, scanout);
|
||||
dcc->pipe_add(dcc_gl_draw_item_new(dcc, &draw, -1));
|
||||
dcc_push_monitors_config(dcc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void dcc_destroy_stream_agents(DisplayChannelClient *dcc)
|
||||
@ -531,7 +548,11 @@ RedPipeItemPtr dcc_gl_draw_item_new(RedChannelClient *rcc, void *data, int num)
|
||||
}
|
||||
}
|
||||
|
||||
dcc->priv->gl_draw_ongoing = TRUE;
|
||||
if (num >= 0) {
|
||||
dcc->priv->gl_draw_ongoing = TRUE;
|
||||
} else {
|
||||
dcc->priv->gl_initial_draw_ongoing = TRUE;
|
||||
}
|
||||
auto item = red::make_shared<RedGlDrawItem>();
|
||||
item->draw = *draw;
|
||||
|
||||
@ -983,19 +1004,20 @@ GArray *dcc_get_preferred_video_codecs_for_encoding(DisplayChannelClient *dcc)
|
||||
return display_channel_get_video_codecs(DCC_TO_DC(dcc));
|
||||
}
|
||||
|
||||
static bool dcc_handle_gl_draw_done(DisplayChannelClient *dcc)
|
||||
bool dcc_handle_gl_draw_done(DisplayChannelClient *dcc)
|
||||
{
|
||||
DisplayChannel *display = DCC_TO_DC(dcc);
|
||||
|
||||
if (G_UNLIKELY(!dcc->priv->gl_draw_ongoing)) {
|
||||
if (G_UNLIKELY(!dcc->priv->gl_initial_draw_ongoing && !dcc->priv->gl_draw_ongoing)) {
|
||||
g_warning("unexpected DRAW_DONE received\n");
|
||||
/* close client connection */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dcc->priv->gl_draw_ongoing = FALSE;
|
||||
display_channel_gl_draw_done(display);
|
||||
|
||||
if (!dcc->priv->gl_initial_draw_ongoing) {
|
||||
dcc->priv->gl_draw_ongoing = FALSE;
|
||||
display_channel_gl_draw_done(display);
|
||||
}
|
||||
dcc->priv->gl_initial_draw_ongoing = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@ -144,6 +144,7 @@ int dcc_compress_image (DisplayCha
|
||||
SpiceImage *dest, SpiceBitmap *src, Drawable *drawable,
|
||||
int can_lossy,
|
||||
compress_send_data_t* o_comp_data);
|
||||
bool dcc_handle_gl_draw_done (DisplayChannelClient *dcc);
|
||||
|
||||
void dcc_create_surface(DisplayChannelClient *dcc, struct RedSurface *surface);
|
||||
void dcc_push_surface_image(DisplayChannelClient *dcc, struct RedSurface *surface);
|
||||
|
||||
@ -1793,10 +1793,9 @@ spice_gst_encoder_encode_dmabuf(VideoEncoder *video_encoder,
|
||||
*outbuf = NULL;
|
||||
rc = VIDEO_ENCODER_FRAME_UNSUPPORTED;
|
||||
|
||||
mem = gst_dmabuf_allocator_alloc_with_flags(encoder->allocator,
|
||||
dmabuf_data->drm_dma_buf_fd,
|
||||
size,
|
||||
GST_FD_MEMORY_FLAG_DONT_CLOSE);
|
||||
mem = gst_dmabuf_allocator_alloc(encoder->allocator,
|
||||
dmabuf_data->drm_dma_buf_fd,
|
||||
size);
|
||||
if (!mem) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user