summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-11-15 18:30:54 +0100
committerwm4 <wm4@nowhere>2015-11-15 18:30:54 +0100
commit883d3114138a8f9a03f778165de553b7cdb99bee (patch)
tree37baacb20b7d6a64f4209c6c6afa3818f0ebd8ce /video
parentc7d82dd25c4a059386de562bc26e58bffd71b3fd (diff)
downloadmpv-883d3114138a8f9a03f778165de553b7cdb99bee.tar.bz2
mpv-883d3114138a8f9a03f778165de553b7cdb99bee.tar.xz
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.)
Diffstat (limited to 'video')
-rw-r--r--video/out/opengl/common.c1
-rw-r--r--video/out/opengl/common.h2
-rw-r--r--video/out/opengl/video.c40
3 files changed, 27 insertions, 16 deletions
diff --git a/video/out/opengl/common.c b/video/out/opengl/common.c
index 54389e15cf..e0e3d498ca 100644
--- a/video/out/opengl/common.c
+++ b/video/out/opengl/common.c
@@ -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),
diff --git a/video/out/opengl/common.h b/video/out/opengl/common.h
index d87be595ba..acae464643 100644
--- a/video/out/opengl/common.h
+++ b/video/out/opengl/common.h
@@ -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);
diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c
index a89ee4e73a..c62cbeeafa 100644
--- a/video/out/opengl/video.c
+++ b/video/out/opengl/video.c
@@ -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);
}
}
}