mirror of https://github.com/mpv-player/mpv
vo_opengl: use glBlitFramebuffer to draw repeated frames
In the display-sync, non-interpolation case, and if the display refresh rate is higher than the video framerate, we duplicate display frames by rendering exactly the same screen again. The redrawing is cached with a FBO to speed up the repeat. Use glBlitFramebuffer() instead of another shader pass. It should be faster. For some reason, post-process was run again on each display refresh. Stop doing this, which should also be slightly faster. The only disadvantage is that temporal dithering will be run only once per video frame, but I can live with this. One aspect is messy: clearing the background is done at the start on the target framebuffer, so to avoid clearing twice and duplicating the code, only copy the part of the framebuffer that contains the rendered video. (Which also gets slightly messy - needs to compensate for coordinate system flipping.)
This commit is contained in:
parent
c7d82dd25c
commit
883d311413
|
@ -172,6 +172,7 @@ static const struct gl_functions gl_functions[] = {
|
|||
.ver_es_core = 300,
|
||||
.functions = (const struct gl_function[]) {
|
||||
DEF_FN(BindBufferBase),
|
||||
DEF_FN(BlitFramebuffer),
|
||||
DEF_FN(GetStringi),
|
||||
// for ES 3.0
|
||||
DEF_FN(GetTexLevelParameteriv),
|
||||
|
|
|
@ -234,6 +234,8 @@ struct GL {
|
|||
GLenum (GLAPIENTRY *CheckFramebufferStatus)(GLenum);
|
||||
void (GLAPIENTRY *FramebufferTexture2D)(GLenum, GLenum, GLenum, GLuint,
|
||||
GLint);
|
||||
void (GLAPIENTRY *BlitFramebuffer)(GLint, GLint, GLint, GLint, GLint, GLint,
|
||||
GLint, GLint, GLbitfield, GLenum);
|
||||
|
||||
void (GLAPIENTRY *Uniform1f)(GLint, GLfloat);
|
||||
void (GLAPIENTRY *Uniform2f)(GLint, GLfloat, GLfloat);
|
||||
|
|
|
@ -2157,34 +2157,42 @@ void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame, int fbo)
|
|||
if (p->opts.interpolation && (p->frames_drawn || !frame->still)) {
|
||||
gl_video_interpolate_frame(p, frame, fbo);
|
||||
} else {
|
||||
// For the non-interplation case, we draw to a single "cache"
|
||||
// FBO to speed up subsequent re-draws (if any exist)
|
||||
int vp_w = p->dst_rect.x1 - p->dst_rect.x0,
|
||||
vp_h = p->dst_rect.y1 - p->dst_rect.y0;
|
||||
|
||||
bool is_new = !frame->redraw && !frame->repeat;
|
||||
if (is_new || !p->output_fbo_valid) {
|
||||
p->output_fbo_valid = false;
|
||||
|
||||
gl_video_upload_image(p, frame->current);
|
||||
pass_render_frame(p);
|
||||
|
||||
if (frame->num_vsyncs == 1 || !frame->display_synced ||
|
||||
p->opts.dumb_mode)
|
||||
// For the non-interplation case, we draw to a single "cache"
|
||||
// FBO to speed up subsequent re-draws (if any exist)
|
||||
int dest_fbo = fbo;
|
||||
if (frame->num_vsyncs > 1 && frame->display_synced &&
|
||||
!p->opts.dumb_mode && gl->BlitFramebuffer)
|
||||
{
|
||||
// Disable output_fbo_valid to signal that this frame
|
||||
// does not require any redraws from the FBO.
|
||||
pass_draw_to_screen(p, fbo);
|
||||
p->output_fbo_valid = false;
|
||||
} else {
|
||||
finish_pass_fbo(p, &p->output_fbo, vp_w, vp_h, 0, FBOTEX_FUZZY);
|
||||
fbotex_change(&p->output_fbo, p->gl, p->log,
|
||||
p->vp_w, abs(p->vp_h),
|
||||
p->opts.fbo_format, 0);
|
||||
dest_fbo = p->output_fbo.fbo;
|
||||
p->output_fbo_valid = true;
|
||||
}
|
||||
pass_draw_to_screen(p, dest_fbo);
|
||||
}
|
||||
|
||||
// "output fbo valid" and "output fbo needed" are equivalent
|
||||
if (p->output_fbo_valid) {
|
||||
pass_load_fbotex(p, &p->output_fbo, vp_w, vp_h, 0);
|
||||
GLSL(vec4 color = texture(texture0, texcoord0);)
|
||||
pass_draw_to_screen(p, fbo);
|
||||
gl->BindFramebuffer(GL_READ_FRAMEBUFFER, p->output_fbo.fbo);
|
||||
gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
|
||||
struct mp_rect rc = p->dst_rect;
|
||||
if (p->vp_h < 0) {
|
||||
rc.y1 = -p->vp_h - p->dst_rect.y0;
|
||||
rc.y0 = -p->vp_h - p->dst_rect.y1;
|
||||
}
|
||||
gl->BlitFramebuffer(rc.x0, rc.y0, rc.x1, rc.y1,
|
||||
rc.x0, rc.y0, rc.x1, rc.y1,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
gl->BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue