vo_dmabuf_wayland: support osd rendering when there's no video

The osd support was originally written with the requirement that we have
actual frames getting delivered to the VO. This isn't always the case
though. If you force a window on a blank audio file for example, then
there will be no frame thus draw_frame did nothing. Since the previous
commit allows us to reliably detect this, we can rearrange the code
around a little bit to make this possible. A key change is to make the
osd_subsurface have wl->surface as the parent. This is seemingly
required otherwise the osd_surface buffers are never visible above the
empty video_surface when we have a black window. Also nuke the desync
call since it's completely pointless. Fixes #12429.
This commit is contained in:
Dudemanguy 2023-09-20 13:29:42 -05:00
parent 69b7af3106
commit e125da2096
2 changed files with 29 additions and 25 deletions

View File

@ -102,6 +102,7 @@ struct priv {
struct mp_osd_res screen_osd_res;
bool destroy_buffers;
bool force_window;
enum hwdec_type hwdec_type;
uint32_t drm_format;
uint64_t drm_modifier;
@ -586,32 +587,35 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
struct osd_buffer *osd_buf;
double pts;
if (!vo_wayland_check_visible(vo) || !frame->current)
if (!vo_wayland_check_visible(vo) && !p->force_window)
return;
if (p->destroy_buffers)
destroy_buffers(vo);
pts = frame->current->pts;
struct mp_image *src = mp_image_new_ref(frame->current);
buf = buffer_get(vo, src);
pts = frame->current ? frame->current->pts : 0;
if (frame->current) {
struct mp_image *src = mp_image_new_ref(frame->current);
buf = buffer_get(vo, src);
if (buf && buf->image) {
wl_surface_attach(wl->video_surface, buf->buffer, 0, 0);
wl_surface_damage_buffer(wl->video_surface, 0, 0, buf->image->w,
buf->image->h);
}
}
osd_buf = osd_buffer_get(vo);
if (buf && buf->image) {
wl_surface_attach(wl->video_surface, buf->buffer, 0, 0);
wl_surface_damage_buffer(wl->video_surface, 0, 0, buf->image->w,
buf->image->h);
if (osd_buf && osd_buf->buffer) {
if (draw_osd(vo, &osd_buf->image, pts) && p->osd_surface_has_contents) {
wl_surface_attach(wl->osd_surface, osd_buf->buffer, 0, 0);
wl_surface_damage_buffer(wl->osd_surface, 0, 0, osd_buf->image.w,
osd_buf->image.h);
p->osd_surface_is_mapped = true;
} else if (!p->osd_surface_has_contents && p->osd_surface_is_mapped) {
wl_surface_attach(wl->osd_surface, NULL, 0, 0);
p->osd_surface_is_mapped = false;
}
if (osd_buf && osd_buf->buffer) {
if (draw_osd(vo, &osd_buf->image, pts) && p->osd_surface_has_contents) {
wl_surface_attach(wl->osd_surface, osd_buf->buffer, 0, 0);
wl_surface_damage_buffer(wl->osd_surface, 0, 0, osd_buf->image.w,
osd_buf->image.h);
p->osd_surface_is_mapped = true;
} else if (!p->osd_surface_has_contents && p->osd_surface_is_mapped) {
wl_surface_attach(wl->osd_surface, NULL, 0, 0);
p->osd_surface_is_mapped = false;
}
}
}
@ -652,10 +656,10 @@ static int reconfig(struct vo *vo, struct mp_image *img)
{
struct priv *p = vo->priv;
// If we have a supported format but no hw_subfmt, this
// is probably handle_force_window. Consider it valid.
if (is_supported_fmt(img->params.imgfmt) && img->params.hw_subfmt == IMGFMT_NONE)
if (img->params.force_window) {
p->force_window = true;
goto done;
}
if (!drm_format_check(vo, img)) {
MP_ERR(vo, "Unable to get drm format from hardware decoding!\n");
@ -668,6 +672,7 @@ static int reconfig(struct vo *vo, struct mp_image *img)
return VO_ERROR;
}
p->force_window = false;
done:
if (!vo_wayland_reconfig(vo))
return VO_ERROR;

View File

@ -2239,9 +2239,8 @@ bool vo_wayland_init(struct vo *vo)
goto err;
if (wl->subcompositor) {
wl->osd_subsurface = wl_subcompositor_get_subsurface(wl->subcompositor, wl->osd_surface, wl->video_surface);
wl->video_subsurface = wl_subcompositor_get_subsurface(wl->subcompositor, wl->video_surface, wl->surface);
wl_subsurface_set_desync(wl->video_subsurface);
wl->osd_subsurface = wl_subcompositor_get_subsurface(wl->subcompositor, wl->osd_surface, wl->surface);
}
#if HAVE_WAYLAND_PROTOCOLS_1_27