vo_opengl: add support for linear scaling without CMS

This introduces a new option linear-scaling, which is now implied by
srgb, icc-profile and sigmoid-upscaling.

Notably, this means (sigmoidized) linear upscaling is now enabled by
default in opengl-hq mode. The impact should be negligible, and there
has been no observation of negative side effects of sigmoidized scaling,
so it feels safe to do so.
This commit is contained in:
Niklas Haas 2015-02-06 03:37:21 +01:00
parent 4872443fc0
commit 4fed18e81e
No known key found for this signature in database
GPG Key ID: 3BA77D4BFDB10BCE
4 changed files with 41 additions and 23 deletions

View File

@ -359,7 +359,7 @@ Available video output drivers are:
``srgb``
Convert and color correct the output to sRGB before displaying it on
the screen. This option enables linear light scaling.
the screen. This option enables ``linear-scaling``.
This option is equivalent to using ``icc-profile`` with an sRGB ICC
profile, but it is implemented without a 3DLUT and does not require
@ -438,6 +438,11 @@ Available video output drivers are:
See ``scale-param1``, ``scale-param2``, ``scale-radius`` and
``scale-antiring``.
``linear-scaling``
Scale in linear light. This is automatically enabled if ``srgb``,
``icc-profile`` or ``sigmoid-upscaling`` is set. It should only
be used with a ``fbo-format`` that has at least 16 bit precision.
``fancy-downscaling``
When using convolution based filters, extend the filter size
when downscaling. Trades quality for reduced downscaling performance.
@ -447,8 +452,8 @@ Available video output drivers are:
different directions.
``sigmoid-upscaling``
When upscaling in linear light, use a sigmoidal color transform
to avoid emphasizing ringing artifacts.
When upscaling, use a sigmoidal color transform to avoid emphasizing
ringing artifacts. This also enables ``linear-scaling``.
``sigmoid-center``
The center of the sigmoid curve used for ``sigmoid-upscaling``, must
@ -521,8 +526,8 @@ Available video output drivers are:
``icc-profile=<file>``
Load an ICC profile and use it to transform linear RGB to screen output.
Needs LittleCMS 2 support compiled in. This option overrides the ``srgb``
property, as using both is somewhat redundant. It also enables linear
light scaling.
property, as using both is somewhat redundant. It also enables
``linear-scaling``.
``icc-profile-auto``

View File

@ -370,6 +370,7 @@ const struct m_sub_options gl_video_conf = {
OPT_FLOATRANGE("scale-antiring", scaler_antiring[0], 0, 0.0, 1.0),
OPT_FLOATRANGE("cscale-antiring", scaler_antiring[1], 0, 0.0, 1.0),
OPT_FLAG("scaler-resizes-only", scaler_resizes_only, 0),
OPT_FLAG("linear-scaling", linear_scaling, 0),
OPT_FLAG("fancy-downscaling", fancy_downscaling, 0),
OPT_FLAG("sigmoid-upscaling", sigmoid_upscaling, 0),
OPT_FLOATRANGE("sigmoid-center", sigmoid_center, 0, 0.0, 1.0),
@ -904,6 +905,8 @@ static void compile_shaders(struct gl_video *p)
rg, tex1d, tex3d, arrays, shader_prelude, PRELUDE_END);
bool use_cms = p->opts.srgb || p->use_lut_3d;
// 3DLUT overrides sRGB
bool use_srgb = p->opts.srgb && !p->use_lut_3d;
float input_gamma = 1.0;
float conv_gamma = 1.0;
@ -911,12 +914,8 @@ static void compile_shaders(struct gl_video *p)
bool is_xyz = p->image_desc.flags & MP_IMGFLAG_XYZ;
if (is_xyz) {
input_gamma *= 2.6;
// If we're using cms, we can treat it as proper linear input,
// otherwise we just scale back to 2.40 to match typical displays,
// as a reasonable approximation.
if (!use_cms)
conv_gamma *= 1.0 / 2.40;
// Note that this results in linear light, so we make sure to enable
// use_linear_light for XYZ inputs as well.
}
p->input_gamma = input_gamma;
@ -928,10 +927,13 @@ static void compile_shaders(struct gl_video *p)
enum mp_csp_trc gamma_fun = MP_CSP_TRC_NONE;
// Linear light scaling is only enabled when either color correction
// option (3dlut or srgb) is enabled, otherwise scaling is done in the
// source space.
if (use_cms) {
// If either color correction option (3dlut or srgb) is enabled, or if
// sigmoidal upscaling is requested, or if the source is linear XYZ, we
// always scale in linear light
bool use_linear_light = p->opts.linear_scaling || p->opts.sigmoid_upscaling
|| use_cms || is_xyz;
if (use_linear_light) {
// We use the color level range to distinguish between PC
// content like images, which are most likely sRGB, and TV content
// like movies, which are most likely BT.1886. XYZ input is always
@ -945,11 +947,19 @@ static void compile_shaders(struct gl_video *p)
}
}
bool use_linear_light = gamma_fun != MP_CSP_TRC_NONE;
// The inverse of the above transformation is normally handled by
// the CMS cases, but if CMS is disabled we need to go back manually
bool use_inv_bt1886 = false;
if (use_linear_light && !use_cms) {
if (gamma_fun == MP_CSP_TRC_SRGB) {
use_srgb = true;
} else {
use_inv_bt1886 = true;
}
}
// Optionally transform to sigmoidal color space if requested, but only
// when upscaling in linear light
p->sigmoid_enabled = p->opts.sigmoid_upscaling && use_linear_light;
// Optionally transform to sigmoidal color space if requested.
p->sigmoid_enabled = p->opts.sigmoid_upscaling;
bool use_sigmoid = p->sigmoid_enabled && p->upscaling;
// Figure out the right color spaces we need to convert, if any
@ -994,8 +1004,7 @@ static void compile_shaders(struct gl_video *p)
use_cms && gamma_fun == MP_CSP_TRC_SRGB);
shader_def_opt(&header_osd, "USE_OSD_CMS_MATRIX", use_cms_matrix);
shader_def_opt(&header_osd, "USE_OSD_3DLUT", p->use_lut_3d);
// 3DLUT overrides SRGB
shader_def_opt(&header_osd, "USE_OSD_SRGB", !p->use_lut_3d && p->opts.srgb);
shader_def_opt(&header_osd, "USE_OSD_SRGB", use_cms && use_srgb);
for (int n = 0; n < SUBBITMAP_COUNT; n++) {
const char *name = osd_shaders[n];
@ -1042,8 +1051,8 @@ static void compile_shaders(struct gl_video *p)
shader_def_opt(&header_final, "USE_INV_GAMMA", p->user_gamma_enabled);
shader_def_opt(&header_final, "USE_CMS_MATRIX", use_cms_matrix);
shader_def_opt(&header_final, "USE_3DLUT", p->use_lut_3d);
// 3DLUT overrides SRGB
shader_def_opt(&header_final, "USE_SRGB", p->opts.srgb && !p->use_lut_3d);
shader_def_opt(&header_final, "USE_SRGB", use_srgb);
shader_def_opt(&header_final, "USE_INV_BT1886", use_inv_bt1886);
shader_def_opt(&header_final, "USE_DITHER", p->dither_texture != 0);
shader_def_opt(&header_final, "USE_TEMPORAL_DITHER", p->opts.temporal_dither);

View File

@ -36,6 +36,7 @@ struct gl_video_opts {
float scaler_antiring[2];
float gamma;
int srgb;
int linear_scaling;
int fancy_downscaling;
int sigmoid_upscaling;
float sigmoid_center;

View File

@ -508,6 +508,9 @@ void main() {
// Adapt and compand from the linear BT2020 source to the sRGB output
color = srgb_compand(color);
#endif
#ifdef USE_INV_BT1886
color = pow(color, vec3(1.0/1.961));
#endif
#ifdef USE_DITHER
vec2 dither_pos = gl_FragCoord.xy / dither_size;
#ifdef USE_TEMPORAL_DITHER