mirror of https://github.com/mpv-player/mpv
vo_opengl: clean up rendering path
Shuffle the special cases around so that it looks cleaner. The result should be equivalent to the code before.
This commit is contained in:
parent
fd2f40762f
commit
cc00b3ff36
|
@ -1416,49 +1416,87 @@ static void change_dither_trafo(struct gl_video *p)
|
||||||
gl->UseProgram(0);
|
gl->UseProgram(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void render_to_fbo(struct gl_video *p, struct fbotex *fbo,
|
struct pass {
|
||||||
int x, int y, int w, int h, int tex_w, int tex_h)
|
// Not necessarily a FBO; we just abuse this struct because it's convenient.
|
||||||
{
|
// It specifies the source texture/sub-rectangle for the next pass.
|
||||||
GL *gl = p->gl;
|
struct fbotex f;
|
||||||
|
// If true, render source (f) to dst, instead of the full dest. fbo viewport
|
||||||
gl->Viewport(fbo->vp_x, fbo->vp_y, fbo->vp_w, fbo->vp_h);
|
bool use_dst;
|
||||||
gl->BindFramebuffer(GL_FRAMEBUFFER, fbo->fbo);
|
struct mp_rect dst;
|
||||||
|
bool flip;
|
||||||
struct vertex vb[VERTICES_PER_QUAD];
|
bool render_stereo;
|
||||||
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);
|
|
||||||
|
|
||||||
gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
gl->Viewport(p->vp_x, p->vp_y, p->vp_w, p->vp_h);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// *chain contains the source, and is overwritten with a copy of the result
|
// *chain contains the source, and is overwritten with a copy of the result
|
||||||
static void handle_pass(struct gl_video *p, struct fbotex *chain,
|
// 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 fbotex *fbo, GLuint program)
|
||||||
{
|
{
|
||||||
|
struct vertex vb[VERTICES_PER_QUAD];
|
||||||
GL *gl = p->gl;
|
GL *gl = p->gl;
|
||||||
|
|
||||||
if (!program)
|
if (!program)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gl->BindTexture(p->gl_target, chain->texture);
|
gl->BindTexture(p->gl_target, chain->f.texture);
|
||||||
gl->UseProgram(program);
|
gl->UseProgram(program);
|
||||||
render_to_fbo(p, fbo, chain->vp_x, chain->vp_y,
|
|
||||||
chain->vp_w, chain->vp_h,
|
gl->Viewport(fbo->vp_x, fbo->vp_y, fbo->vp_w, fbo->vp_h);
|
||||||
chain->tex_w, chain->tex_h);
|
gl->BindFramebuffer(GL_FRAMEBUFFER, fbo->fbo);
|
||||||
*chain = *fbo;
|
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
glEnable3DLeft(gl, p->opts.stereo_mode);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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)
|
void gl_video_render_frame(struct gl_video *p)
|
||||||
{
|
{
|
||||||
GL *gl = p->gl;
|
GL *gl = p->gl;
|
||||||
struct vertex vb[VERTICES_PER_QUAD];
|
|
||||||
struct video_image *vimg = &p->image;
|
struct video_image *vimg = &p->image;
|
||||||
bool is_flipped = vimg->image_flipped;
|
|
||||||
|
|
||||||
if (p->opts.temporal_dither)
|
if (p->opts.temporal_dither)
|
||||||
change_dither_trafo(p);
|
change_dither_trafo(p);
|
||||||
|
@ -1481,12 +1519,14 @@ void gl_video_render_frame(struct gl_video *p)
|
||||||
GLuint imgtex[4] = {0};
|
GLuint imgtex[4] = {0};
|
||||||
set_image_textures(p, vimg, imgtex);
|
set_image_textures(p, vimg, imgtex);
|
||||||
|
|
||||||
struct fbotex chain = {
|
struct pass chain = {
|
||||||
.vp_w = p->image_w,
|
.f = {
|
||||||
.vp_h = p->image_h,
|
.vp_w = p->image_w,
|
||||||
.tex_w = p->texture_w,
|
.vp_h = p->image_h,
|
||||||
.tex_h = p->texture_h,
|
.tex_w = p->texture_w,
|
||||||
.texture = imgtex[0],
|
.tex_h = p->texture_h,
|
||||||
|
.texture = imgtex[0],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
handle_pass(p, &chain, &p->indirect_fbo, p->indirect_program);
|
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
|
// Clip to visible height so that separate scaling scales the visible part
|
||||||
// only (and the target FBO texture can have a bounded size).
|
// 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.
|
// Don't clamp width; too hard to get correct final scaling on l/r borders.
|
||||||
chain.vp_y = p->src_rect.y0,
|
chain.f.vp_y = p->src_rect.y0;
|
||||||
chain.vp_h = p->src_rect.y1 - 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);
|
handle_pass(p, &chain, &p->scale_sep_fbo, p->scale_sep_program);
|
||||||
|
|
||||||
gl->BindTexture(p->gl_target, chain.texture);
|
struct fbotex screen = {
|
||||||
gl->UseProgram(p->final_program);
|
.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
|
||||||
|
};
|
||||||
|
|
||||||
struct mp_rect src = {p->src_rect.x0, chain.vp_y,
|
// For Y direction, use the whole source viewport; it has been fit to the
|
||||||
p->src_rect.x1, chain.vp_y + chain.vp_h};
|
// correct origin/height before.
|
||||||
int src_texw = chain.tex_w;
|
// For X direction, assume the texture wasn't scaled yet, so we can
|
||||||
int src_texh = chain.tex_h;
|
// 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;
|
||||||
|
|
||||||
if (p->opts.stereo_mode) {
|
chain.use_dst = true;
|
||||||
int w = src.x1 - src.x0;
|
chain.dst = p->dst_rect;
|
||||||
int imgw = p->image_w;
|
chain.flip = vimg->image_flipped;
|
||||||
|
chain.render_stereo = true;
|
||||||
|
|
||||||
glEnable3DLeft(gl, p->opts.stereo_mode);
|
handle_pass(p, &chain, &screen, p->final_program);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
glEnable3DRight(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 + 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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
gl->UseProgram(0);
|
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);
|
unset_image_textures(p);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue