From 8c3a92d6cb5293c0d058450cac0d1a1720411f47 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 1 May 2015 18:44:45 +0200 Subject: vo_opengl: refactor wayland frame skipping Currently, the wayland backend needs extra work to avoid drawing more often than the wayland frame callback allows. (This is not ideal, but will be fixed at a later time.) Unify this with the start_frame callback added for cocoa. Some details change for the better. For example, if a frame is dropped, and a redraw is done afterwards, the actually correct frame is redrawn, instead whatever was in the textures from before the dropped frame. (cherry picked from commit 0a7abbda6b555fb7746f737b52d0f00fb3e614db) --- video/out/gl_common.h | 8 ++------ video/out/gl_video.c | 23 +++++++++++++++-------- video/out/gl_video.h | 3 +-- video/out/gl_wayland.c | 4 ++-- video/out/vo_opengl.c | 24 ++++++++++++------------ video/out/vo_opengl_cb.c | 2 +- 6 files changed, 33 insertions(+), 31 deletions(-) diff --git a/video/out/gl_common.h b/video/out/gl_common.h index 1c908cfa2b..feeb3e59f4 100644 --- a/video/out/gl_common.h +++ b/video/out/gl_common.h @@ -114,13 +114,9 @@ typedef struct MPGLContext { void (*register_resize_callback)(struct vo *vo, void (*cb)(struct vo *vo, int w, int h)); - // Optional activity state of context. - // If false, OpenGL renderers should not draw anything. - bool (*is_active)(struct MPGLContext *); - // Optional callback on the beginning of a frame. The frame will be finished - // with swapGlBuffers(). Like is_active, this returns false if use of the - // OpenGL context should be avoided. + // with swapGlBuffers(). This returns false if use of the OpenGL context + // should be avoided. bool (*start_frame)(struct MPGLContext *); // For free use by the backend. diff --git a/video/out/gl_video.c b/video/out/gl_video.c index 9b4b46ad16..b1976d6521 100644 --- a/video/out/gl_video.c +++ b/video/out/gl_video.c @@ -107,6 +107,7 @@ struct texplane { struct video_image { struct texplane planes[4]; bool image_flipped; + bool needs_upload; struct mp_image *mpi; // original input image }; @@ -469,6 +470,7 @@ static void uninit_rendering(struct gl_video *p); static void uninit_scaler(struct gl_video *p, struct scaler *scaler); static void check_gl_features(struct gl_video *p); static bool init_format(int fmt, struct gl_video *init); +static void gl_video_upload_image(struct gl_video *p); #define GLSL(x) gl_sc_add(p->sc, #x "\n"); #define GLSLF(...) gl_sc_addf(p->sc, __VA_ARGS__) @@ -2048,6 +2050,8 @@ void gl_video_render_frame(struct gl_video *p, int fbo, struct frame_timing *t) } if (vimg->mpi) { + gl_video_upload_image(p); + gl_sc_set_vao(p->sc, &p->vao); if (p->opts.interpolation) { @@ -2124,27 +2128,30 @@ static bool get_image(struct gl_video *p, struct mp_image *mpi) return true; } -void gl_video_skip_image(struct gl_video *p, struct mp_image *mpi) +void gl_video_set_image(struct gl_video *p, struct mp_image *mpi) { + assert(mpi); + struct video_image *vimg = &p->image; talloc_free(vimg->mpi); vimg->mpi = mpi; + vimg->needs_upload = true; + + p->osd_pts = mpi->pts; } -void gl_video_upload_image(struct gl_video *p, struct mp_image *mpi) +static void gl_video_upload_image(struct gl_video *p) { GL *gl = p->gl; struct video_image *vimg = &p->image; + struct mp_image *mpi = vimg->mpi; - p->osd_pts = mpi->pts; - - talloc_free(vimg->mpi); - vimg->mpi = mpi; - - if (p->hwdec_active) + if (p->hwdec_active || !mpi || !vimg->needs_upload) return; + vimg->needs_upload = false; + assert(mpi->num_planes == p->plane_count); mp_image_t mpi2 = *mpi; diff --git a/video/out/gl_video.h b/video/out/gl_video.h index 30647153b5..77608760a3 100644 --- a/video/out/gl_video.h +++ b/video/out/gl_video.h @@ -83,8 +83,7 @@ bool gl_video_check_format(struct gl_video *p, int mp_format); void gl_video_config(struct gl_video *p, struct mp_image_params *params); void gl_video_set_output_depth(struct gl_video *p, int r, int g, int b); void gl_video_set_lut3d(struct gl_video *p, struct lut3d *lut3d); -void gl_video_skip_image(struct gl_video *p, struct mp_image *mpi); -void gl_video_upload_image(struct gl_video *p, struct mp_image *img); +void gl_video_set_image(struct gl_video *p, struct mp_image *img); void gl_video_render_frame(struct gl_video *p, int fbo, struct frame_timing *t); void gl_video_resize(struct gl_video *p, int vp_w, int vp_h, struct mp_rect *src, struct mp_rect *dst, diff --git a/video/out/gl_wayland.c b/video/out/gl_wayland.c index 0fcec82377..3307087a44 100644 --- a/video/out/gl_wayland.c +++ b/video/out/gl_wayland.c @@ -215,7 +215,7 @@ static int control(struct vo *vo, int *events, int request, void *data) return r; } -static bool is_active(struct MPGLContext *ctx) +static bool start_frame(struct MPGLContext *ctx) { struct vo_wayland_state *wl = ctx->vo->wayland; return wl->frame.pending; @@ -229,5 +229,5 @@ void mpgl_set_backend_wayland(MPGLContext *ctx) ctx->vo_control = control; ctx->vo_init = vo_wayland_init; ctx->vo_uninit = vo_wayland_uninit; - ctx->is_active = is_active; + ctx->start_frame = start_frame; } diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c index 43b2b9e04b..15b36e8238 100644 --- a/video/out/vo_opengl.c +++ b/video/out/vo_opengl.c @@ -78,6 +78,8 @@ struct gl_priv { int vo_flipped; + bool frame_started; + int frames_rendered; unsigned int prev_sgi_sync_count; @@ -124,8 +126,11 @@ static void flip_page(struct vo *vo) struct gl_priv *p = vo->priv; GL *gl = p->gl; - if (p->glctx->is_active && !p->glctx->is_active(p->glctx)) + if (!p->frame_started) { + vo_increment_drop_count(vo, 1); return; + } + p->frame_started = false; mpgl_lock(p->glctx); @@ -171,25 +176,20 @@ static void draw_image_timed(struct vo *vo, mp_image_t *mpi, struct gl_priv *p = vo->priv; GL *gl = p->gl; - if (p->glctx->is_active && !p->glctx->is_active(p->glctx)) { - if (mpi) - gl_video_skip_image(p->renderer, mpi); - return; - } - if (p->vo_flipped) mp_image_vflip(mpi); mpgl_lock(p->glctx); if (mpi) - gl_video_upload_image(p->renderer, mpi); + gl_video_set_image(p->renderer, mpi); if (p->glctx->start_frame && !p->glctx->start_frame(p->glctx)) { mpgl_unlock(p->glctx); return; } + p->frame_started = true; gl_video_render_frame(p->renderer, 0, t); // The playloop calls this last before waiting some time until it decides @@ -394,11 +394,11 @@ static int control(struct vo *vo, uint32_t request, void *data) request_hwdec_api(p, data); return true; case VOCTRL_REDRAW_FRAME: - if (p->glctx->is_active && !p->glctx->is_active(p->glctx)) - return true; - mpgl_lock(p->glctx); - gl_video_render_frame(p->renderer, 0, NULL); + if (!(p->glctx->start_frame && !p->glctx->start_frame(p->glctx))) { + p->frame_started = true; + gl_video_render_frame(p->renderer, 0, NULL); + } mpgl_unlock(p->glctx); return true; case VOCTRL_SET_COMMAND_LINE: { diff --git a/video/out/vo_opengl_cb.c b/video/out/vo_opengl_cb.c index 2f2ac63f21..1a2e1bf9a8 100644 --- a/video/out/vo_opengl_cb.c +++ b/video/out/vo_opengl_cb.c @@ -328,7 +328,7 @@ int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int vp_w, int vp_h) pthread_mutex_unlock(&ctx->lock); if (mpi) - gl_video_upload_image(ctx->renderer, mpi); + gl_video_set_image(ctx->renderer, mpi); gl_video_render_frame(ctx->renderer, fbo, NULL); -- cgit v1.2.3