vo_opengl: draw OSD twice in 3D mode case

Apparently this is needed for correct 3D mode subtitles. In general,
it seems you need to duplicate the whole "GUI", so it's done for all
OSD elements.

This doesn't handle the "duplication" of the mouse pointer. Instead,
the mouse can be used for the top/left field only. Also, it's possible
that we should "compress" the OSD in the direction it's duplicated, but
I don't know about that.

Fixes #1124, at least partially.
This commit is contained in:
wm4 2014-10-29 23:14:46 +01:00
parent fb4d26e769
commit aa6b7fa07b
3 changed files with 57 additions and 7 deletions

View File

@ -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
};

View File

@ -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[] = {

View File

@ -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