summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--video/csputils.c26
-rw-r--r--video/csputils.h1
-rw-r--r--video/out/gl_video.c47
-rw-r--r--video/out/gl_video_shaders.glsl8
4 files changed, 70 insertions, 12 deletions
diff --git a/video/csputils.c b/video/csputils.c
index 23eb099f69..e7ea5a388b 100644
--- a/video/csputils.c
+++ b/video/csputils.c
@@ -40,6 +40,7 @@ char * const mp_csp_names[MP_CSP_COUNT] = {
"BT.709 (HD)",
"SMPTE-240M",
"RGB",
+ "XYZ",
};
char * const mp_csp_equalizer_names[MP_CSP_EQ_COUNT] = {
@@ -165,10 +166,30 @@ void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float m[3][4])
int format = params->colorspace.format;
if (format <= MP_CSP_AUTO || format >= MP_CSP_COUNT)
format = MP_CSP_BT_601;
+ int levels_in = params->colorspace.levels_in;
+ if (levels_in <= MP_CSP_LEVELS_AUTO || levels_in >= MP_CSP_LEVELS_COUNT)
+ levels_in = MP_CSP_LEVELS_TV;
+
switch (format) {
case MP_CSP_BT_601: luma_coeffs(m, 0.299, 0.587, 0.114 ); break;
case MP_CSP_BT_709: luma_coeffs(m, 0.2126, 0.7152, 0.0722); break;
case MP_CSP_SMPTE_240M: luma_coeffs(m, 0.2122, 0.7013, 0.0865); break;
+ case MP_CSP_RGB: {
+ static const float ident[3][4] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
+ memcpy(m, ident, sizeof(ident));
+ levels_in = -1;
+ break;
+ }
+ case MP_CSP_XYZ: {
+ static const float xyz_to_rgb[3][4] = {
+ {3.2404542, -1.5371385, -0.4985314},
+ {-0.9692660, 1.8760108, 0.0415560},
+ {0.0556434, -0.2040259, 1.0572252},
+ };
+ memcpy(m, xyz_to_rgb, sizeof(xyz_to_rgb));
+ levels_in = -1;
+ break;
+ }
default:
abort();
};
@@ -183,9 +204,6 @@ void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float m[3][4])
m[i][COL_V] = huesin * u + huecos * m[i][COL_V];
}
- int levels_in = params->colorspace.levels_in;
- if (levels_in <= MP_CSP_LEVELS_AUTO || levels_in >= MP_CSP_LEVELS_COUNT)
- levels_in = MP_CSP_LEVELS_TV;
assert(params->input_bits >= 8);
assert(params->texture_bits >= params->input_bits);
double s = (1 << params->input_bits-8) / ((1<<params->texture_bits)-1.);
@@ -193,10 +211,12 @@ void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float m[3][4])
struct yuvlevels { double ymin, ymax, cmin, cmid; }
yuvlim = { 16*s, 235*s, 16*s, 128*s },
yuvfull = { 0*s, 255*s, 1*s, 128*s }, // '1' for symmetry around 128
+ anyfull = { 0*s, 255*s, -255*s/2, 0 },
yuvlev;
switch (levels_in) {
case MP_CSP_LEVELS_TV: yuvlev = yuvlim; break;
case MP_CSP_LEVELS_PC: yuvlev = yuvfull; break;
+ case -1: yuvlev = anyfull; break;
default:
abort();
}
diff --git a/video/csputils.h b/video/csputils.h
index d66bb86fa3..184e1ee76a 100644
--- a/video/csputils.h
+++ b/video/csputils.h
@@ -40,6 +40,7 @@ enum mp_csp {
MP_CSP_BT_709,
MP_CSP_SMPTE_240M,
MP_CSP_RGB,
+ MP_CSP_XYZ,
MP_CSP_COUNT
};
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
diff --git a/video/out/gl_video_shaders.glsl b/video/out/gl_video_shaders.glsl
index 2f10e5fdf6..b968cb2c87 100644
--- a/video/out/gl_video_shaders.glsl
+++ b/video/out/gl_video_shaders.glsl
@@ -122,6 +122,7 @@ uniform sampler3D lut_3d;
uniform sampler2D dither;
uniform mat4x3 colormatrix;
uniform vec3 inv_gamma;
+uniform float input_gamma;
uniform float conv_gamma;
uniform float dither_quantization;
uniform float dither_multiply;
@@ -351,11 +352,14 @@ void main() {
// wrong for 9/10 bit input
color.gb = vec2(128.0/255.0);
#endif
+#ifdef USE_INPUT_GAMMA
+ color = pow(color, vec3(input_gamma));
+#endif
#ifdef USE_COLORMATRIX
color = mat3(colormatrix) * color + colormatrix[3];
#endif
-#ifdef USE_LINEAR_CONV
- color = pow(color, vec3(1.0/0.45));
+#ifdef USE_CONV_GAMMA
+ color = pow(color, vec3(conv_gamma));
#endif
#ifdef USE_LINEAR_CONV_INV
// Convert from linear RGB to gamma RGB before putting it through the 3D-LUT