summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--video/out/gl_video.c170
1 files changed, 94 insertions, 76 deletions
diff --git a/video/out/gl_video.c b/video/out/gl_video.c
index 49f83a0971..be6e6af662 100644
--- a/video/out/gl_video.c
+++ b/video/out/gl_video.c
@@ -1416,49 +1416,87 @@ static void change_dither_trafo(struct gl_video *p)
gl->UseProgram(0);
}
-static void render_to_fbo(struct gl_video *p, struct fbotex *fbo,
- int x, int y, int w, int h, int tex_w, int tex_h)
+struct pass {
+ // Not necessarily a FBO; we just abuse this struct because it's convenient.
+ // It specifies the source texture/sub-rectangle for the next pass.
+ struct fbotex f;
+ // If true, render source (f) to dst, instead of the full dest. fbo viewport
+ bool use_dst;
+ struct mp_rect dst;
+ bool flip;
+ bool render_stereo;
+};
+
+// *chain contains the source, and is overwritten with a copy of the result
+// fbo is used as destination texture/render target.
+static void handle_pass(struct gl_video *p, struct pass *chain,
+ struct fbotex *fbo, GLuint program)
{
+ struct vertex vb[VERTICES_PER_QUAD];
GL *gl = p->gl;
+ if (!program)
+ return;
+
+ gl->BindTexture(p->gl_target, chain->f.texture);
+ gl->UseProgram(program);
+
gl->Viewport(fbo->vp_x, fbo->vp_y, fbo->vp_w, fbo->vp_h);
gl->BindFramebuffer(GL_FRAMEBUFFER, fbo->fbo);
- struct vertex vb[VERTICES_PER_QUAD];
- write_quad(vb, -1, -1, 1, 1,
- x, y, x + w, y + h,
- tex_w, tex_h,
- NULL, p->gl_target, false);
- draw_triangles(p, vb, VERTICES_PER_QUAD);
+ int tex_w = chain->f.tex_w;
+ int tex_h = chain->f.tex_h;
+ struct mp_rect src = {
+ .x0 = chain->f.vp_x,
+ .y0 = chain->f.vp_y,
+ .x1 = chain->f.vp_x + chain->f.vp_w,
+ .y1 = chain->f.vp_y + chain->f.vp_h,
+ };
- gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
- gl->Viewport(p->vp_x, p->vp_y, p->vp_w, p->vp_h);
+ struct mp_rect dst = {-1, -1, 1, 1};
+ if (chain->use_dst)
+ dst = chain->dst;
-}
+ if (chain->render_stereo && p->opts.stereo_mode) {
+ int w = src.x1 - src.x0;
+ int imgw = p->image_w;
-// *chain contains the source, and is overwritten with a copy of the result
-static void handle_pass(struct gl_video *p, struct fbotex *chain,
- struct fbotex *fbo, GLuint program)
-{
- GL *gl = p->gl;
+ glEnable3DLeft(gl, p->opts.stereo_mode);
- if (!program)
- return;
+ write_quad(vb,
+ dst.x0, dst.y0, dst.x1, dst.y1,
+ src.x0 / 2, src.y0,
+ src.x0 / 2 + w / 2, src.y1,
+ tex_w, tex_h, NULL, p->gl_target, chain->flip);
+ draw_triangles(p, vb, VERTICES_PER_QUAD);
- gl->BindTexture(p->gl_target, chain->texture);
- gl->UseProgram(program);
- render_to_fbo(p, fbo, chain->vp_x, chain->vp_y,
- chain->vp_w, chain->vp_h,
- chain->tex_w, chain->tex_h);
- *chain = *fbo;
+ glEnable3DRight(gl, p->opts.stereo_mode);
+
+ write_quad(vb,
+ dst.x0, dst.y0, dst.x1, dst.y1,
+ src.x0 / 2 + imgw / 2, src.y0,
+ src.x0 / 2 + imgw / 2 + w / 2, src.y1,
+ tex_w, tex_h, NULL, p->gl_target, chain->flip);
+ draw_triangles(p, vb, VERTICES_PER_QUAD);
+
+ glDisable3D(gl, p->opts.stereo_mode);
+ } else {
+ write_quad(vb,
+ dst.x0, dst.y0, dst.x1, dst.y1,
+ src.x0, src.y0, src.x1, src.y1,
+ tex_w, tex_h, NULL, p->gl_target, chain->flip);
+ draw_triangles(p, vb, VERTICES_PER_QUAD);
+ }
+
+ *chain = (struct pass){
+ .f = *fbo,
+ };
}
void gl_video_render_frame(struct gl_video *p)
{
GL *gl = p->gl;
- struct vertex vb[VERTICES_PER_QUAD];
struct video_image *vimg = &p->image;
- bool is_flipped = vimg->image_flipped;
if (p->opts.temporal_dither)
change_dither_trafo(p);
@@ -1481,12 +1519,14 @@ void gl_video_render_frame(struct gl_video *p)
GLuint imgtex[4] = {0};
set_image_textures(p, vimg, imgtex);
- struct fbotex chain = {
- .vp_w = p->image_w,
- .vp_h = p->image_h,
- .tex_w = p->texture_w,
- .tex_h = p->texture_h,
- .texture = imgtex[0],
+ struct pass chain = {
+ .f = {
+ .vp_w = p->image_w,
+ .vp_h = p->image_h,
+ .tex_w = p->texture_w,
+ .tex_h = p->texture_h,
+ .texture = imgtex[0],
+ },
};
handle_pass(p, &chain, &p->indirect_fbo, p->indirect_program);
@@ -1494,58 +1534,36 @@ void gl_video_render_frame(struct gl_video *p)
// Clip to visible height so that separate scaling scales the visible part
// only (and the target FBO texture can have a bounded size).
// Don't clamp width; too hard to get correct final scaling on l/r borders.
- chain.vp_y = p->src_rect.y0,
- chain.vp_h = p->src_rect.y1 - p->src_rect.y0,
+ chain.f.vp_y = p->src_rect.y0;
+ chain.f.vp_h = p->src_rect.y1 - p->src_rect.y0;
handle_pass(p, &chain, &p->scale_sep_fbo, p->scale_sep_program);
- gl->BindTexture(p->gl_target, chain.texture);
- gl->UseProgram(p->final_program);
-
- struct mp_rect src = {p->src_rect.x0, chain.vp_y,
- p->src_rect.x1, chain.vp_y + chain.vp_h};
- int src_texw = chain.tex_w;
- int src_texh = chain.tex_h;
-
- if (p->opts.stereo_mode) {
- int w = src.x1 - src.x0;
- int imgw = p->image_w;
-
- glEnable3DLeft(gl, p->opts.stereo_mode);
-
- write_quad(vb,
- p->dst_rect.x0, p->dst_rect.y0,
- p->dst_rect.x1, p->dst_rect.y1,
- src.x0 / 2, src.y0,
- src.x0 / 2 + w / 2, src.y1,
- src_texw, src_texh,
- NULL, p->gl_target, is_flipped);
- draw_triangles(p, vb, VERTICES_PER_QUAD);
+ struct fbotex screen = {
+ .vp_x = p->vp_x,
+ .vp_y = p->vp_y,
+ .vp_w = p->vp_w,
+ .vp_h = p->vp_h,
+ .texture = 0, //makes BindFramebuffer select the screen backbuffer
+ };
- glEnable3DRight(gl, p->opts.stereo_mode);
+ // For Y direction, use the whole source viewport; it has been fit to the
+ // correct origin/height before.
+ // For X direction, assume the texture wasn't scaled yet, so we can
+ // select the correct portion, which will be scaled to screen.
+ chain.f.vp_x = p->src_rect.x0;
+ chain.f.vp_w = p->src_rect.x1 - p->src_rect.x0;
- write_quad(vb,
- p->dst_rect.x0, p->dst_rect.y0,
- p->dst_rect.x1, p->dst_rect.y1,
- src.x0 / 2 + imgw / 2, src.y0,
- src.x0 / 2 + imgw / 2 + w / 2, src.y1,
- src_texw, src_texh,
- NULL, p->gl_target, is_flipped);
- draw_triangles(p, vb, VERTICES_PER_QUAD);
+ chain.use_dst = true;
+ chain.dst = p->dst_rect;
+ chain.flip = vimg->image_flipped;
+ chain.render_stereo = true;
- glDisable3D(gl, p->opts.stereo_mode);
- } else {
- write_quad(vb,
- p->dst_rect.x0, p->dst_rect.y0,
- p->dst_rect.x1, p->dst_rect.y1,
- src.x0, src.y0,
- src.x1, src.y1,
- src_texw, src_texh,
- NULL, p->gl_target, is_flipped);
- draw_triangles(p, vb, VERTICES_PER_QUAD);
- }
+ handle_pass(p, &chain, &screen, p->final_program);
gl->UseProgram(0);
+ gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
+ gl->Viewport(p->vp_x, p->vp_y, p->vp_w, p->vp_h);
unset_image_textures(p);