summaryrefslogtreecommitdiffstats
path: root/video/out/gl_video.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-05-01 23:59:00 +0200
committerwm4 <wm4@nowhere>2013-05-04 01:32:50 +0200
commit872aefaa1521a8cf70c6e14f3356e9d00ed7efa3 (patch)
tree4f04a63b9c31d71a326a112004e8d8e213e739e4 /video/out/gl_video.c
parent16d40828aecf4028acadeeecaf0294756298f970 (diff)
downloadmpv-872aefaa1521a8cf70c6e14f3356e9d00ed7efa3.tar.bz2
mpv-872aefaa1521a8cf70c6e14f3356e9d00ed7efa3.tar.xz
vo_opengl: XYZ input support
Useful for the j2k decoder. Matrix taken from http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html (XYZ to sRGB, whitepoint D65) Gamma conversion follows what libswscale does (2.6 in, 2.2 out). If linear RGB is used internally for scaling, the gamma conversion will be undone by setting the exponent to 1. Unfortunately, the two gamma values don't compensate each others exactly (2.2 vs. 1/0.45=2.22...), so output is a little bit incorrect in sRGB or color-managed mode. But for now try hard to match libswscale output, which may or may not be correct.
Diffstat (limited to 'video/out/gl_video.c')
-rw-r--r--video/out/gl_video.c47
1 files changed, 40 insertions, 7 deletions
diff --git a/video/out/gl_video.c b/video/out/gl_video.c
index 43dbb843f1..a000624f9c 100644
--- a/video/out/gl_video.c
+++ b/video/out/gl_video.c
@@ -168,6 +168,8 @@ struct gl_video {
bool is_yuv, is_rgb;
bool is_linear_rgb;
+ float input_gamma, conv_gamma;
+
// per pixel (full pixel when packed, each component when planar)
int plane_bits;
int plane_count;
@@ -452,6 +454,11 @@ static void update_uniforms(struct gl_video *p, GLuint program)
.texture_bits = (p->plane_bits + 7) & ~7,
};
mp_csp_copy_equalizer_values(&cparams, &p->video_eq);
+ if (p->image_desc.flags & MP_IMGFLAG_XYZ) {
+ cparams.colorspace.format = MP_CSP_XYZ;
+ cparams.input_bits = 8;
+ cparams.texture_bits = 8;
+ }
loc = gl->GetUniformLocation(program, "transform");
if (loc >= 0) {
@@ -463,11 +470,16 @@ static void update_uniforms(struct gl_video *p, GLuint program)
loc = gl->GetUniformLocation(program, "colormatrix");
if (loc >= 0) {
float yuv2rgb[3][4] = {{0}};
- if (p->is_yuv)
- mp_get_yuv2rgb_coeffs(&cparams, yuv2rgb);
+ mp_get_yuv2rgb_coeffs(&cparams, yuv2rgb);
gl->UniformMatrix4x3fv(loc, 1, GL_TRUE, &yuv2rgb[0][0]);
}
+ gl->Uniform1f(gl->GetUniformLocation(program, "input_gamma"),
+ p->input_gamma);
+
+ gl->Uniform1f(gl->GetUniformLocation(program, "conv_gamma"),
+ p->conv_gamma);
+
gl->Uniform3f(gl->GetUniformLocation(program, "inv_gamma"),
1.0 / cparams.rgamma,
1.0 / cparams.ggamma,
@@ -704,8 +716,22 @@ static void compile_shaders(struct gl_video *p)
char *header_final = talloc_strdup(tmp, "");
char *header_sep = NULL;
- bool convert_input_to_linear = !p->is_linear_rgb &&
- (p->opts.srgb || p->use_lut_3d);
+ float input_gamma = 1.0;
+ float conv_gamma = 1.0;
+
+ if (p->image_desc.flags & MP_IMGFLAG_XYZ) {
+ input_gamma *= 2.6;
+ conv_gamma *= 1.0 / 2.2;
+ }
+
+ if (!p->is_linear_rgb && (p->opts.srgb || p->use_lut_3d))
+ conv_gamma *= 1.0 / 0.45;
+
+ p->input_gamma = input_gamma;
+ p->conv_gamma = conv_gamma;
+
+ bool convert_input_gamma = p->input_gamma != 1.0;
+ bool convert_input_to_linear = p->conv_gamma != 1.0;
if (p->image_format == IMGFMT_NV12 || p->image_format == IMGFMT_NV21) {
shader_def(&header_conv, "USE_CONV", "CONV_NV12");
@@ -716,8 +742,9 @@ static void compile_shaders(struct gl_video *p)
shader_def_opt(&header_conv, "USE_GBRP", p->image_format == IMGFMT_GBRP);
shader_def_opt(&header_conv, "USE_SWAP_UV", p->image_format == IMGFMT_NV21);
shader_def_opt(&header_conv, "USE_YGRAY", p->is_yuv && p->plane_count == 1);
- shader_def_opt(&header_conv, "USE_COLORMATRIX", p->is_yuv);
- shader_def_opt(&header_conv, "USE_LINEAR_CONV", convert_input_to_linear);
+ shader_def_opt(&header_conv, "USE_INPUT_GAMMA", convert_input_gamma);
+ shader_def_opt(&header_conv, "USE_COLORMATRIX", !p->is_rgb);
+ shader_def_opt(&header_conv, "USE_CONV_GAMMA", convert_input_to_linear);
if (p->opts.enable_alpha && p->plane_count == 4)
shader_def(&header_conv, "USE_ALPHA_PLANE", "3");
@@ -745,7 +772,7 @@ static void compile_shaders(struct gl_video *p)
// Don't sample from input video textures before converting the input to
// linear light. (Unneeded when sRGB textures are used.)
- if (convert_input_to_linear)
+ if (convert_input_gamma || convert_input_to_linear)
use_indirect = true;
// It doesn't make sense to scale the chroma with cscale in the 1. scale
@@ -1634,6 +1661,12 @@ static bool init_format(int fmt, struct gl_video *init)
plane_format[0] = byte_formats[1];
}
+ // XYZ (same roganization as RGB packed, but requires conversion matrix)
+ if (!supported && fmt == IMGFMT_XYZ12) {
+ supported = true;
+ plane_format[0] = IMGFMT_RGB48;
+ }
+
// All formats in mp_to_gl_formats[] are supported
// If it's not in the table, it will be rejected below.
// Includes packed RGB and YUV formats