mirror of
https://github.com/mpv-player/mpv.git
synced 2025-12-28 05:33:14 +00:00
vo: change draw_frame API to a boolean
x11 and wayland VOs + backends all have logic that skips drawing frames when the mpv isn't visible for efficiency reasons. This is implemented in each individual VO, but it is useful for the core to be aware of this as well. Currently, the display-sync modes on x11 do not try to be efficient and always render anyways because there is no blocking on the graphics API level if you skip rendering a frame (wayland works here by accident). This means mpv would otherwise blaze through frames which is not what anyone wants. We can instead improve this by implementing the blocking mechanism in the core and using that when appropriate. This commit does not implement that yet, but simply switches the draw_frame to a boolean. Receiving false means that the VO is not drawing frames and it should be treated as if the surface was hidden.
This commit is contained in:
@@ -407,8 +407,12 @@ struct vo_driver {
|
||||
* frame is freed by the caller if the callee did not assume ownership
|
||||
* of the frames, but in any case the callee can still modify the
|
||||
* contained data and references.
|
||||
*
|
||||
* Return false to signal to the core that rendering is being skipped for
|
||||
* this particular frame. vo.c will sleep for the expected duration of that
|
||||
* frame before advancing forward.
|
||||
*/
|
||||
void (*draw_frame)(struct vo *vo, struct vo_frame *frame);
|
||||
bool (*draw_frame)(struct vo *vo, struct vo_frame *frame);
|
||||
|
||||
/*
|
||||
* Blit/Flip buffer to the screen. Must be called after each frame!
|
||||
|
||||
@@ -111,15 +111,18 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
|
||||
return resize(vo);
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
struct priv *priv = vo->priv;
|
||||
struct mp_image *mpi = frame->current;
|
||||
if (!mpi)
|
||||
return;
|
||||
goto done;
|
||||
memcpy_pic(priv->dither_buffer, mpi->planes[0], priv->image_width * depth, priv->image_height,
|
||||
priv->image_width * depth, mpi->stride[0]);
|
||||
caca_dither_bitmap(priv->canvas, 0, 0, priv->screen_w, priv->screen_h, priv->dither, priv->dither_buffer);
|
||||
|
||||
done:
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static void flip_page(struct vo *vo)
|
||||
|
||||
@@ -1003,18 +1003,18 @@ static bool get_video_buffer(d3d_priv *priv, struct mp_image *out)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
d3d_priv *priv = vo->priv;
|
||||
if (!priv->d3d_device)
|
||||
return;
|
||||
goto done;
|
||||
|
||||
struct mp_image buffer;
|
||||
if (!get_video_buffer(priv, &buffer))
|
||||
return;
|
||||
goto done;
|
||||
|
||||
if (!frame->current)
|
||||
return;
|
||||
goto done;
|
||||
|
||||
mp_image_copy(&buffer, frame->current);
|
||||
|
||||
@@ -1024,6 +1024,9 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
priv->osd_pts = frame->current->pts;
|
||||
|
||||
d3d_draw_frame(priv);
|
||||
|
||||
done:
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static mp_image_t *get_window_screenshot(d3d_priv *priv)
|
||||
|
||||
@@ -592,7 +592,7 @@ done:
|
||||
return draw;
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
struct priv *p = vo->priv;
|
||||
struct vo_wayland_state *wl = vo->wl;
|
||||
@@ -603,7 +603,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
if (!vo_wayland_check_visible(vo)) {
|
||||
if (frame->current)
|
||||
talloc_free(frame);
|
||||
return;
|
||||
return VO_FALSE;
|
||||
}
|
||||
|
||||
if (p->destroy_buffers)
|
||||
@@ -641,6 +641,8 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
p->osd_surface_is_mapped = false;
|
||||
}
|
||||
}
|
||||
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static void flip_page(struct vo *vo)
|
||||
|
||||
@@ -300,13 +300,13 @@ static void swapchain_step(struct vo *vo)
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
struct vo_drm_state *drm = vo->drm;
|
||||
struct priv *p = vo->priv;
|
||||
|
||||
if (!drm->active)
|
||||
return;
|
||||
goto done;
|
||||
|
||||
drm->still = frame->still;
|
||||
|
||||
@@ -319,6 +319,9 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
}
|
||||
|
||||
enqueue_frame(vo, fb);
|
||||
|
||||
done:
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static void queue_flip(struct vo *vo, struct drm_frame *frame)
|
||||
|
||||
@@ -70,25 +70,27 @@ static void resize(struct vo *vo)
|
||||
vo->want_redraw = true;
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
struct gpu_priv *p = vo->priv;
|
||||
struct ra_swapchain *sw = p->ctx->swapchain;
|
||||
|
||||
struct ra_fbo fbo;
|
||||
if (!sw->fns->start_frame(sw, &fbo))
|
||||
return;
|
||||
return VO_FALSE;
|
||||
|
||||
gl_video_render_frame(p->renderer, frame, &fbo, RENDER_FRAME_DEF);
|
||||
if (!sw->fns->submit_frame(sw, frame)) {
|
||||
MP_ERR(vo, "Failed presenting frame!\n");
|
||||
return;
|
||||
return VO_FALSE;
|
||||
}
|
||||
|
||||
struct mp_image_params *params = gl_video_get_target_params_ptr(p->renderer);
|
||||
mp_mutex_lock(&vo->params_mutex);
|
||||
vo->target_params = params;
|
||||
mp_mutex_unlock(&vo->params_mutex);
|
||||
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static void flip_page(struct vo *vo)
|
||||
|
||||
@@ -904,7 +904,7 @@ static void update_tm_viz(struct pl_color_map_params *params,
|
||||
static void update_hook_opts_dynamic(struct priv *p, const struct pl_hook *hook,
|
||||
const struct mp_image *mpi);
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
struct priv *p = vo->priv;
|
||||
pl_options pars = p->pars;
|
||||
@@ -1029,7 +1029,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
#endif
|
||||
pl_queue_update(p->queue, NULL, &qparams);
|
||||
}
|
||||
return;
|
||||
return VO_FALSE;
|
||||
}
|
||||
|
||||
bool valid = false;
|
||||
@@ -1173,6 +1173,7 @@ done:
|
||||
|
||||
pl_gpu_flush(gpu);
|
||||
p->frame_pending = true;
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static void flip_page(struct vo *vo)
|
||||
|
||||
@@ -90,16 +90,19 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
struct priv *p = vo->priv;
|
||||
if (!frame->current)
|
||||
return;
|
||||
goto done;
|
||||
|
||||
p->current = frame->current;
|
||||
|
||||
struct mp_osd_res dim = osd_res_from_image_params(vo->params);
|
||||
osd_draw_on_image(vo->osd, dim, frame->current->pts, OSD_DRAW_SUB_ONLY, p->current);
|
||||
|
||||
done:
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static void flip_page(struct vo *vo)
|
||||
|
||||
@@ -239,7 +239,7 @@ static int create_shm(struct vo *vo)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
struct priv *p = vo->priv;
|
||||
mp_image_t *mpi = NULL;
|
||||
@@ -273,7 +273,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
|
||||
|
||||
if (p->opts.use_shm && !create_shm(vo))
|
||||
return;
|
||||
goto done;
|
||||
|
||||
memcpy_pic(p->buffer, p->frame->planes[0], p->width * BYTES_PER_PX,
|
||||
p->height, p->width * BYTES_PER_PX, p->frame->stride[0]);
|
||||
@@ -282,6 +282,9 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
av_base64_encode(p->output, p->output_size, p->buffer, p->buffer_size);
|
||||
|
||||
talloc_free(mpi);
|
||||
|
||||
done:
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static void flip_page(struct vo *vo)
|
||||
|
||||
@@ -182,7 +182,7 @@ static int query_format(struct vo *vo, int format)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *voframe)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *voframe)
|
||||
{
|
||||
struct priv *vc = vo->priv;
|
||||
struct encoder_context *enc = vc->enc;
|
||||
@@ -190,7 +190,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *voframe)
|
||||
AVCodecContext *avc = enc->encoder;
|
||||
|
||||
if (voframe->redraw || voframe->repeat || voframe->num_frames < 1)
|
||||
return;
|
||||
goto done;
|
||||
|
||||
struct mp_image *mpi = voframe->frames[0];
|
||||
|
||||
@@ -198,7 +198,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *voframe)
|
||||
osd_draw_on_image(vo->osd, dim, mpi->pts, OSD_DRAW_SUB_ONLY, mpi);
|
||||
|
||||
if (vc->shutdown)
|
||||
return;
|
||||
goto done;
|
||||
|
||||
// Lock for shared timestamp fields.
|
||||
mp_mutex_lock(&ectx->lock);
|
||||
@@ -241,6 +241,9 @@ static void draw_frame(struct vo *vo, struct vo_frame *voframe)
|
||||
frame->quality = avc->global_quality;
|
||||
encoder_encode(enc, frame);
|
||||
av_frame_free(&frame);
|
||||
|
||||
done:
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static void flip_page(struct vo *vo)
|
||||
|
||||
@@ -485,7 +485,7 @@ int mpv_render_context_get_info(mpv_render_context *ctx,
|
||||
return res;
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
struct vo_priv *p = vo->priv;
|
||||
struct mpv_render_context *ctx = p->ctx;
|
||||
@@ -498,6 +498,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
mp_mutex_unlock(&ctx->lock);
|
||||
|
||||
update(ctx);
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static void flip_page(struct vo *vo)
|
||||
|
||||
@@ -76,7 +76,7 @@ static void flip_page(struct vo *vo)
|
||||
mp_image_unrefp(&p->next_image);
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
struct priv *p = vo->priv;
|
||||
|
||||
@@ -86,6 +86,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
|
||||
talloc_free(p->next_image);
|
||||
p->next_image = mpi;
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static int query_format(struct vo *vo, int format)
|
||||
|
||||
@@ -32,8 +32,9 @@ struct priv {
|
||||
double cfg_fps;
|
||||
};
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static void flip_page(struct vo *vo)
|
||||
|
||||
@@ -879,7 +879,7 @@ static int query_format(struct vo *vo, int format)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
struct priv *vc = vo->priv;
|
||||
|
||||
@@ -894,7 +894,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
|
||||
mp_image_t texmpi;
|
||||
if (!lock_texture(vo, &texmpi))
|
||||
return;
|
||||
goto done;
|
||||
|
||||
mp_image_copy(&texmpi, frame->current);
|
||||
|
||||
@@ -914,6 +914,9 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
SDL_RenderCopy(vc->renderer, vc->tex, &src, &dst);
|
||||
|
||||
draw_osd(vo);
|
||||
|
||||
done:
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static struct mp_image *get_window_screenshot(struct vo *vo)
|
||||
|
||||
@@ -378,7 +378,7 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
struct priv *priv = vo->priv;
|
||||
SIXELSTATUS status;
|
||||
@@ -391,7 +391,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
bool resized = false;
|
||||
update_canvas_dimensions(vo);
|
||||
if (!priv->canvas_ok)
|
||||
return;
|
||||
goto done;
|
||||
|
||||
if (prev_rows != priv->num_rows || prev_cols != priv->num_cols ||
|
||||
prev_width != vo->dwidth || prev_height != vo->dheight)
|
||||
@@ -409,7 +409,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
if (frame->repeat && !frame->redraw && !resized) {
|
||||
// Frame is repeated, and no need to update OSD either
|
||||
priv->skip_frame_draw = true;
|
||||
return;
|
||||
goto done;
|
||||
} else {
|
||||
// Either frame is new, or OSD has to be redrawn
|
||||
priv->skip_frame_draw = false;
|
||||
@@ -457,6 +457,9 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
|
||||
if (mpi)
|
||||
talloc_free(mpi);
|
||||
|
||||
done:
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static void flip_page(struct vo *vo)
|
||||
|
||||
@@ -253,14 +253,17 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
struct priv *p = vo->priv;
|
||||
struct mp_image *src = frame->current;
|
||||
if (!src)
|
||||
return;
|
||||
goto done;
|
||||
// XXX: pan, crop etc.
|
||||
mp_sws_scale(p->sws, p->frame, src);
|
||||
|
||||
done:
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static void flip_page(struct vo *vo)
|
||||
|
||||
@@ -555,7 +555,7 @@ static void get_vsync(struct vo *vo, struct vo_vsync_info *info)
|
||||
present_sync_get_info(x11->present, info);
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
struct priv *p = vo->priv;
|
||||
struct mp_image *mpi = frame->current;
|
||||
@@ -564,7 +564,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
struct mp_image *dst = p->swdec_surfaces[p->output_surface];
|
||||
if (!dst || va_surface_upload(p, dst, mpi) < 0) {
|
||||
MP_WARN(vo, "Could not upload surface.\n");
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
mp_image_copy_attributes(dst, mpi);
|
||||
mpi = dst;
|
||||
@@ -573,6 +573,9 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
p->output_surfaces[p->output_surface] = mpi;
|
||||
|
||||
draw_osd(vo);
|
||||
|
||||
done:
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static void free_subpicture(struct priv *p, struct vaapi_osd_image *img)
|
||||
|
||||
@@ -870,7 +870,7 @@ drop:
|
||||
vo_increment_drop_count(vo, 1);
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
struct vdpctx *vc = vo->priv;
|
||||
|
||||
@@ -893,6 +893,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
video_to_output_surface(vo, vc->current_image);
|
||||
draw_osd(vo);
|
||||
}
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
// warning: the size and pixel format of surface must match that of the
|
||||
|
||||
@@ -239,7 +239,7 @@ static int control(struct vo *vo, uint32_t request, void *data)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
struct priv *p = vo->priv;
|
||||
struct vo_wayland_state *wl = vo->wl;
|
||||
@@ -248,7 +248,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
|
||||
bool render = vo_wayland_check_visible(vo);
|
||||
if (!render)
|
||||
return;
|
||||
return VO_FALSE;
|
||||
|
||||
buf = p->free_buffers;
|
||||
if (buf) {
|
||||
@@ -257,7 +257,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
buf = buffer_create(vo, vo->dwidth, vo->dheight);
|
||||
if (!buf) {
|
||||
wl_surface_attach(wl->surface, NULL, 0, 0);
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (src) {
|
||||
@@ -289,6 +289,9 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
osd_draw_on_image(vo->osd, p->osd, 0, 0, &buf->mpi);
|
||||
}
|
||||
wl_surface_attach(wl->surface, buf->buffer, 0, 0);
|
||||
|
||||
done:
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static void flip_page(struct vo *vo)
|
||||
|
||||
@@ -327,14 +327,14 @@ static void get_vsync(struct vo *vo, struct vo_vsync_info *info)
|
||||
present_sync_get_info(x11->present, info);
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
struct priv *p = vo->priv;
|
||||
|
||||
wait_for_completion(vo, 1);
|
||||
bool render = vo_x11_check_visible(vo);
|
||||
if (!render)
|
||||
return;
|
||||
return VO_FALSE;
|
||||
|
||||
struct mp_image *img = &p->mp_ximages[p->current_buf];
|
||||
|
||||
@@ -359,6 +359,8 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
|
||||
if (frame->current != p->original_image)
|
||||
p->original_image = frame->current;
|
||||
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static int query_format(struct vo *vo, int format)
|
||||
|
||||
@@ -708,14 +708,14 @@ static void get_vsync(struct vo *vo, struct vo_vsync_info *info)
|
||||
present_sync_get_info(x11->present, info);
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
static bool draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
struct xvctx *ctx = vo->priv;
|
||||
|
||||
wait_for_completion(vo, ctx->num_buffers - 1);
|
||||
bool render = vo_x11_check_visible(vo);
|
||||
if (!render)
|
||||
return;
|
||||
return VO_FALSE;
|
||||
|
||||
struct mp_image xv_buffer = get_xv_buffer(vo, ctx->current_buf);
|
||||
if (frame->current) {
|
||||
@@ -729,6 +729,8 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
|
||||
if (frame->current != ctx->original_image)
|
||||
ctx->original_image = frame->current;
|
||||
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static int query_format(struct vo *vo, int format)
|
||||
|
||||
Reference in New Issue
Block a user