diff --git a/video/csputils.h b/video/csputils.h index a99fe5b280..a494a06b28 100644 --- a/video/csputils.h +++ b/video/csputils.h @@ -82,7 +82,12 @@ enum mp_render_intent { // The numeric values (except -1) match the Matroska StereoMode element value. enum mp_stereo3d_mode { MP_STEREO3D_INVALID = -1, + /* only modes explicitly referenced in the code are listed */ MP_STEREO3D_MONO = 0, + MP_STEREO3D_SBS2L = 1, + MP_STEREO3D_AB2R = 2, + MP_STEREO3D_AB2L = 3, + MP_STEREO3D_SBS2R = 11, /* no explicit enum entries for most valid values */ MP_STEREO3D_COUNT = 13, // 12 is last valid mode }; diff --git a/video/out/gl_video.c b/video/out/gl_video.c index 7e416a61c2..97463b8adf 100644 --- a/video/out/gl_video.c +++ b/video/out/gl_video.c @@ -156,6 +156,8 @@ struct gl_video { struct osd_state *osd_state; struct mpgl_osd *osd; double osd_pts; + float osd_offset[2]; + bool osd_offset_set; GLuint lut_3d_texture; bool use_lut_3d; @@ -307,7 +309,7 @@ const struct gl_video_opts gl_video_opts_hq_def = { static int validate_scaler_opt(struct mp_log *log, const m_option_t *opt, struct bstr name, struct bstr param); -static void draw_osd_cb(void *ctx, struct sub_bitmaps *imgs); +static void draw_osd(struct gl_video *p); #define OPT_BASE_STRUCT struct gl_video_opts const struct m_sub_options gl_video_conf = { @@ -686,6 +688,8 @@ static void update_uniforms(struct gl_video *p, GLuint program) gl->Uniform1f(gl->GetUniformLocation(program, "filter_param1_c"), isnan(sparam1_c) ? 0.5f : sparam1_c); + gl->Uniform3f(gl->GetUniformLocation(program, "translation"), 0, 0, 0); + gl->UseProgram(0); debug_check_gl(p, "update_uniforms()"); @@ -1679,10 +1683,7 @@ void gl_video_render_frame(struct gl_video *p) debug_check_gl(p, "after video rendering"); draw_osd: - assert(p->osd); - - osd_draw(p->osd_state, p->osd_rect, p->osd_pts, 0, p->osd->formats, - draw_osd_cb, p); + draw_osd(p); } static void update_window_sized_objects(struct gl_video *p) @@ -1924,15 +1925,58 @@ static void draw_osd_cb(void *ctx, struct sub_bitmaps *imgs) debug_check_gl(p, "before drawing osd"); - gl->UseProgram(p->osd_programs[osd->format]); + int osd_program = p->osd_programs[osd->format]; + gl->UseProgram(osd_program); + + bool set_offset = p->osd_offset[0] != 0 || p->osd_offset[1] != 0; + if (p->osd_offset_set || set_offset) { + gl->Uniform3f(gl->GetUniformLocation(osd_program, "translation"), + p->osd_offset[0], p->osd_offset[1], 0); + p->osd_offset_set = set_offset; + } + mpgl_osd_set_gl_state(p->osd, osd); draw_triangles(p, osd->vertices, osd->num_vertices); mpgl_osd_unset_gl_state(p->osd, osd); + gl->UseProgram(0); debug_check_gl(p, "after drawing osd"); } +// number of screen divisions per axis (x=0, y=1) for the current 3D mode +static void get_3d_side_by_side(struct gl_video *p, int div[2]) +{ + int mode = p->image_params.stereo_out; + div[0] = div[1] = 1; + switch (mode) { + case MP_STEREO3D_SBS2L: + case MP_STEREO3D_SBS2R: div[0] = 2; break; + case MP_STEREO3D_AB2R: + case MP_STEREO3D_AB2L: div[1] = 2; break; + } +} + +static void draw_osd(struct gl_video *p) +{ + assert(p->osd); + + int div[2]; + get_3d_side_by_side(p, div); + + for (int x = 0; x < div[0]; x++) { + for (int y = 0; y < div[1]; y++) { + struct mp_osd_res res = p->osd_rect; + res.w = res.w / div[0]; + res.h = res.h / div[1]; + p->osd_offset[0] = res.w * x; + p->osd_offset[1] = res.h * y; + osd_draw(p->osd_state, res, p->osd_pts, 0, p->osd->formats, + draw_osd_cb, p); + } + } +} + static bool test_fbo(struct gl_video *p, GLenum format) { static const float vals[] = { diff --git a/video/out/gl_video_shaders.glsl b/video/out/gl_video_shaders.glsl index 7b6a1f07fa..11d2e94a61 100644 --- a/video/out/gl_video_shaders.glsl +++ b/video/out/gl_video_shaders.glsl @@ -71,6 +71,7 @@ vec3 bt2020_compand(vec3 v) #endif uniform mat3 transform; +uniform vec3 translation; uniform sampler3D lut_3d; uniform mat3 cms_matrix; // transformation from file's gamut to bt.2020 @@ -81,7 +82,7 @@ in vec2 vertex_texcoord; out vec2 texcoord; void main() { - vec3 position = vec3(vertex_position, 1); + vec3 position = vec3(vertex_position, 1) + translation; #ifndef FIXED_SCALE position = transform * position; #endif