summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-10-29 23:14:46 +0100
committerwm4 <wm4@nowhere>2014-10-29 23:14:46 +0100
commitaa6b7fa07baa0066efb774deed8cb826e6193deb (patch)
tree418df4cd8e0000ae06efc9d68c3778c356fccca1 /video
parentfb4d26e769b847881ee6fb2577816d68b622e2c1 (diff)
downloadmpv-aa6b7fa07baa0066efb774deed8cb826e6193deb.tar.bz2
mpv-aa6b7fa07baa0066efb774deed8cb826e6193deb.tar.xz
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.
Diffstat (limited to 'video')
-rw-r--r--video/csputils.h5
-rw-r--r--video/out/gl_video.c56
-rw-r--r--video/out/gl_video_shaders.glsl3
3 files changed, 57 insertions, 7 deletions
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