summaryrefslogtreecommitdiffstats
path: root/src/include/libplacebo/shaders/colorspace.h
blob: ead09587a050b2e7bb26df65943b0b62c4512eae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
/*
 * This file is part of libplacebo.
 *
 * libplacebo is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * libplacebo is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with libplacebo.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef LIBPLACEBO_SHADERS_COLORSPACE_H_
#define LIBPLACEBO_SHADERS_COLORSPACE_H_

// Color space transformation shaders. These all input and output a color
// value (PL_SHADER_SIG_COLOR).

#include <libplacebo/colorspace.h>
#include <libplacebo/gamut_mapping.h>
#include <libplacebo/tone_mapping.h>
#include <libplacebo/shaders.h>

// For backwards compatibility
#include <libplacebo/shaders/dithering.h>

PL_API_BEGIN

// Transform the input color, in its given representation, to ensure
// compatibility with the indicated alpha mode. Mutates `repr` to reflect the
// change. Note that this is a no-op if the input is PL_ALPHA_UNKNOWN.
PL_API void pl_shader_set_alpha(pl_shader sh, struct pl_color_repr *repr,
                                enum pl_alpha_mode mode);

// Colorspace reshaping for PL_COLOR_SYSTEM_DOLBYVISION. Note that this is done
// automatically by `pl_shader_decode_color` for PL_COLOR_SYSTEM_DOLBYVISION.
PL_API void pl_shader_dovi_reshape(pl_shader sh, const struct pl_dovi_metadata *data);

// Decode the color into normalized RGB, given a specified color_repr. This
// also takes care of additional pre- and post-conversions requires for the
// "special" color systems (XYZ, BT.2020-C, etc.). If `params` is left as NULL,
// it defaults to &pl_color_adjustment_neutral.
//
// Note: This function always returns PC-range RGB with independent alpha.
// It mutates the pl_color_repr to reflect the change.
//
// Note: For DCDM XYZ decoding output is linear
PL_API void pl_shader_decode_color(pl_shader sh, struct pl_color_repr *repr,
                                   const struct pl_color_adjustment *params);

// Encodes a color from normalized, PC-range, independent alpha RGB into a
// given representation. That is, this performs the inverse operation of
// `pl_shader_decode_color` (sans color adjustments).
//
// Note: For DCDM XYZ encoding input is expected to be linear
PL_API void pl_shader_encode_color(pl_shader sh, const struct pl_color_repr *repr);

// Linearize (expand) `vec4 color`, given a specified color space. In essence,
// this corresponds to the ITU-R EOTF.
//
// Note: Unlike the ITU-R EOTF, it never includes the OOTF - even for systems
// where the EOTF includes the OOTF (such as HLG).
PL_API void pl_shader_linearize(pl_shader sh, const struct pl_color_space *csp);

// Delinearize (compress), given a color space as output. This loosely
// corresponds to the inverse EOTF (not the OETF) in ITU-R terminology, again
// assuming a reference monitor.
PL_API void pl_shader_delinearize(pl_shader sh, const struct pl_color_space *csp);

struct pl_sigmoid_params {
    // The center (bias) of the sigmoid curve. Must be between 0.0 and 1.0.
    // If left as NULL, defaults to 0.75
    float center;

    // The slope (steepness) of the sigmoid curve. Must be between 1.0 and 20.0.
    // If left as NULL, defaults to 6.5.
    float slope;
};

#define PL_SIGMOID_DEFAULTS \
    .center = 0.75,         \
    .slope  = 6.50,

#define pl_sigmoid_params(...) (&(struct pl_sigmoid_params) { PL_SIGMOID_DEFAULTS __VA_ARGS__ })
PL_API extern const struct pl_sigmoid_params pl_sigmoid_default_params;

// Applies a sigmoidal color transform to all channels. This helps avoid
// ringing artifacts during upscaling by bringing the color information closer
// to neutral and away from the extremes. If `params` is NULL, it defaults to
// &pl_sigmoid_default_params.
//
// Warning: This function clamps the input to the interval [0,1]; and as such
// it should *NOT* be used on already-decoded high-dynamic range content.
PL_API void pl_shader_sigmoidize(pl_shader sh, const struct pl_sigmoid_params *params);

// This performs the inverse operation to `pl_shader_sigmoidize`.
PL_API void pl_shader_unsigmoidize(pl_shader sh, const struct pl_sigmoid_params *params);

struct pl_peak_detect_params {
    // Smoothing coefficient for the detected values. This controls the time
    // parameter (tau) of an IIR low pass filter. In other words, it represent
    // the cutoff period (= 1 / cutoff frequency) in frames. Frequencies below
    // this length will be suppressed. This helps block out annoying
    // "sparkling" or "flickering" due to small variations in frame-to-frame
    // brightness. If left as 0.0, this smoothing is completely disabled.
    float smoothing_period;

    // In order to avoid reacting sluggishly on scene changes as a result of
    // the low-pass filter, we disable it when the difference between the
    // current frame brightness and the average frame brightness exceeds a
    // given threshold difference. But rather than a single hard cutoff, which
    // would lead to weird discontinuities on fades, we gradually disable it
    // over a small window of brightness ranges. These parameters control the
    // lower and upper bounds of this window, in units of 1% PQ.
    //
    // Setting either one of these to 0.0 disables this logic.
    float scene_threshold_low;
    float scene_threshold_high;

    // Which percentile of the input image brightness histogram to consider as
    // the true peak of the scene. If this is set to 100 (or 0), the brightest
    // pixel is measured. Otherwise, the top of the frequency distribution is
    // progressively cut off. Setting this too low will cause clipping of very
    // bright details, but can improve the dynamic brightness range of scenes
    // with very bright isolated highlights.
    //
    // A recommended value is 99.995%, which is very conservative and should
    // cause no major issues in typical content.
    float percentile;

    // Allows the peak detection result to be delayed by up to a single frame,
    // which can sometimes improve thoughput, at the cost of introducing the
    // possibility of 1-frame flickers on transitions. Disabled by default.
    bool allow_delayed;

    // --- Deprecated / removed fields
    float overshoot_margin PL_DEPRECATED;
    float minimum_peak PL_DEPRECATED;
};

#define PL_PEAK_DETECT_DEFAULTS         \
    .smoothing_period       = 20.0f,    \
    .scene_threshold_low    = 1.0f,     \
    .scene_threshold_high   = 3.0f,     \
    .percentile             = 100.0f,

#define PL_PEAK_DETECT_HQ_DEFAULTS      \
    PL_PEAK_DETECT_DEFAULTS             \
    .percentile             = 99.995f,

#define pl_peak_detect_params(...) (&(struct pl_peak_detect_params) { PL_PEAK_DETECT_DEFAULTS __VA_ARGS__ })
PL_API extern const struct pl_peak_detect_params pl_peak_detect_default_params;
PL_API extern const struct pl_peak_detect_params pl_peak_detect_high_quality_params;

// This function can be used to measure the CLL and FALL of a video
// source automatically, using a compute shader. The measured values are
// smoothed automatically (depending on the parameters), so to keep track of
// the measured results over time, a tone mapping shader state object is used
// to hold the state. Returns false on failure initializing the tone mapping
// object, or if compute shaders are not supported.
//
// It's important that the same shader object is used for successive frames
// belonging to the same source. If the source changes (e.g. due to a file
// change or seek), the user should reset it with `pl_reset_detected_peak` (or
// destroy it and use a new state object).
//
// The parameter `csp` holds the representation of the color values that are
// the input to this function. (They must already be in decoded RGB form, i.e.
// alternate color representations are not supported)
PL_API bool pl_shader_detect_peak(pl_shader sh, struct pl_color_space csp,
                                  pl_shader_obj *state,
                                  const struct pl_peak_detect_params *params);

// After dispatching the above shader, this function can be used to retrieve
// the detected dynamic HDR10+ metadata parameters. The other fields of
// `metadata` are not written to. Returns whether or not any values were
// written. If not, the values are left untouched, so this can be used to
// safely update `pl_hdr_metadata` values in-place. This function may or may
// not block, depending on the previous setting of `allow_delayed`.
PL_API bool pl_get_detected_hdr_metadata(const pl_shader_obj state,
                                         struct pl_hdr_metadata *metadata);

// After dispatching the above shader, this function *may* be used to read out
// the detected CLL and FALL directly (in PL_HDR_NORM units). If the shader
// has never been dispatched yet, i.e. no information is available, this will
// return false.
//
// Deprecated in favor of `pl_get_detected_hdr_metadata`
PL_DEPRECATED PL_API bool pl_get_detected_peak(const pl_shader_obj state,
                                               float *out_cll, float *out_fall);

// Resets the peak detection state in a given tone mapping state object. This
// is not equal to `pl_shader_obj_destroy`, because it does not destroy any
// state used by `pl_shader_tone_map`.
PL_API void pl_reset_detected_peak(pl_shader_obj state);

// Feature map extraction (for pl_color_map_args.feature_map). The result
// of this shader should be downscaled / low-passed to the indicated kernel
// size before use. (This does not happen automatically)
PL_API void pl_shader_extract_features(pl_shader sh, struct pl_color_space csp);

// Deprecated and unused. Libplacebo now always performs a variant of the old
// hybrid tone-mapping, mixing together the intensity (I) and per-channel (LMS)
// results.
enum pl_tone_map_mode {
    PL_TONE_MAP_AUTO    PL_DEPRECATED_ENUMERATOR,
    PL_TONE_MAP_RGB     PL_DEPRECATED_ENUMERATOR,
    PL_TONE_MAP_MAX     PL_DEPRECATED_ENUMERATOR,
    PL_TONE_MAP_HYBRID  PL_DEPRECATED_ENUMERATOR,
    PL_TONE_MAP_LUMA    PL_DEPRECATED_ENUMERATOR,
    PL_TONE_MAP_MODE_COUNT,
};

// Deprecated by <libplacebo/gamut_mapping.h>
enum pl_gamut_mode {
    PL_GAMUT_CLIP       PL_DEPRECATED_ENUMERATOR, // pl_gamut_map_clip
    PL_GAMUT_WARN       PL_DEPRECATED_ENUMERATOR, // pl_gamut_map_highlight
    PL_GAMUT_DARKEN     PL_DEPRECATED_ENUMERATOR, // pl_gamut_map_darken
    PL_GAMUT_DESATURATE PL_DEPRECATED_ENUMERATOR, // pl_gamut_map_desaturate
    PL_GAMUT_MODE_COUNT,
};

struct pl_color_map_params {
    // --- Gamut mapping options

    // Gamut mapping function to use to handle out-of-gamut colors, including
    // colors which are out-of-gamut as a consequence of tone mapping.
    const struct pl_gamut_map_function *gamut_mapping;

    // Gamut mapping constants, for expert tuning. Leave as default otherwise.
    struct pl_gamut_map_constants gamut_constants;

    // Gamut mapping 3DLUT size, for channels ICh. Defaults to {48, 32, 256}
    int lut3d_size[3];

    // Use higher quality, but slower, tricubic interpolation for gamut mapping
    // 3DLUTs. May substantially improve the 3DLUT gamut mapping accuracy, in
    // particular at smaller 3DLUT sizes. Shouldn't have much effect at the
    // default size.
    bool lut3d_tricubic;

    // If true, allows the gamut mapping function to expand the gamut, in
    // cases where the target gamut exceeds that of the source. If false,
    // the source gamut will never be enlarged, even when using a gamut
    // mapping function capable of bidirectional mapping.
    bool gamut_expansion;

    // --- Tone mapping options

    // Tone mapping function to use to handle out-of-range colors.
    const struct pl_tone_map_function *tone_mapping_function;

    // Tone mapping constants, for expert tuning. Leave as default otherwise.
    struct pl_tone_map_constants tone_constants;

    // If true, and supported by the given tone mapping function, libplacebo
    // will perform inverse tone mapping to expand the dynamic range of a
    // signal. libplacebo is not liable for any HDR-induced eye damage.
    bool inverse_tone_mapping;

    // Data source to use when tone-mapping. Setting this to a specific
    // value allows overriding the default metadata preference logic.
    enum pl_hdr_metadata_type metadata;

    // Tone mapping LUT size. Defaults to 256.
    int lut_size;

    // HDR contrast recovery strength. If set to a value above 0.0, the source
    // image will be divided into high-frequency and low-frequency components,
    // and a portion of the high-frequency image is added back onto the
    // tone-mapped output. May cause excessive ringing artifacts for some HDR
    // sources, but can improve the subjective sharpness and detail left over
    // in the image after tone-mapping.
    float contrast_recovery;

    // Contrast recovery lowpass kernel size. Defaults to 3.5. Increasing
    // or decreasing this will affect the visual appearance substantially.
    float contrast_smoothness;

    // --- Debugging options

    // Force the use of a full tone-mapping LUT even for functions that have
    // faster pure GLSL replacements (e.g. clip, linear, saturation).
    bool force_tone_mapping_lut;

    // Visualize the tone-mapping LUT and gamut mapping 3DLUT, in IPT space.
    bool visualize_lut;

    // Controls where to draw the visualization, relative to the rendered
    // video (dimensions 0-1). Optional, defaults to the full picture.
    pl_rect2df visualize_rect;

    // Controls the rotation of the 3DLUT visualization.
    float visualize_hue;    // useful range [-pi, pi]
    float visualize_theta;  // useful range [0, pi/2]

    // Graphically highlight hard-clipped pixels during tone-mapping (i.e.
    // pixels that exceed the claimed source luminance range).
    bool show_clipping;

    // --- Deprecated fields
    enum pl_tone_map_mode tone_mapping_mode PL_DEPRECATED; // removed
    float tone_mapping_param PL_DEPRECATED;         // see `tone_constants`
    float tone_mapping_crosstalk PL_DEPRECATED;     // now hard-coded as 0.04
    enum pl_rendering_intent intent PL_DEPRECATED;  // see `gamut_mapping`
    enum pl_gamut_mode gamut_mode PL_DEPRECATED;    // see `gamut_mapping`
    float hybrid_mix PL_DEPRECATED;                 // removed
};

#define PL_COLOR_MAP_DEFAULTS                                   \
    .gamut_mapping          = &pl_gamut_map_perceptual,         \
    .tone_mapping_function  = &pl_tone_map_spline,              \
    .gamut_constants        = { PL_GAMUT_MAP_CONSTANTS },       \
    .tone_constants         = { PL_TONE_MAP_CONSTANTS },        \
    .metadata               = PL_HDR_METADATA_ANY,              \
    .lut3d_size             = {48, 32, 256},                    \
    .lut_size               = 256,                              \
    .visualize_rect         = {0, 0, 1, 1},                     \
    .contrast_smoothness    = 3.5f,

#define PL_COLOR_MAP_HQ_DEFAULTS                                \
    PL_COLOR_MAP_DEFAULTS                                       \
    .contrast_recovery      = 0.30f,

#define pl_color_map_params(...) (&(struct pl_color_map_params) { PL_COLOR_MAP_DEFAULTS __VA_ARGS__ })
PL_API extern const struct pl_color_map_params pl_color_map_default_params;
PL_API extern const struct pl_color_map_params pl_color_map_high_quality_params;

// Execution arguments for the `pl_shader_color_map_ex` call. Distinct from
// `pl_color_map_params` because it is filled by internally-provided execution
// metadata, instead of user-tunable aesthetic parameters.
struct pl_color_map_args {
    // Input/output color space for the mapping.
    struct pl_color_space src;
    struct pl_color_space dst;

    // If true, the logic will assume the input has already been linearized by
    // the caller (e.g. as part of a previous linear light scaling operation).
    bool prelinearized;

    // Object to be used to store generated LUTs. Note that this is the same
    // state object used by `pl_shader_detect_peak`, and if that function has
    // been called on `state` prior to `pl_shader_color_map`, the detected
    // values will be used to guide the tone mapping algorithm. If this is not
    // provided, tone/gamut mapping are disabled.
    pl_shader_obj *state;

    // Low-resolution intensity feature map, as generated by
    // `pl_shader_extract_features`. Optional. No effect if
    // `params->contrast_recovery` is disabled.
    pl_tex feature_map;
};

#define pl_color_map_args(...) (&(struct pl_color_map_args) { __VA_ARGS__ })

// Maps `vec4 color` from one color space to another color space according
// to the parameters (described in greater depth above). If `params` is left
// as NULL, it defaults to `&pl_color_map_default_params`
PL_API void pl_shader_color_map_ex(pl_shader sh,
                                   const struct pl_color_map_params *params,
                                   const struct pl_color_map_args *args);

// Backwards compatibility wrapper around `pl_shader_color_map_ex`
PL_API void pl_shader_color_map(pl_shader sh, const struct pl_color_map_params *params,
                                struct pl_color_space src, struct pl_color_space dst,
                                pl_shader_obj *state, bool prelinearized);

// Applies a set of cone distortion parameters to `vec4 color` in a given color
// space. This can be used to simulate color blindness. See `pl_cone_params`
// for more information.
PL_API void pl_shader_cone_distort(pl_shader sh, struct pl_color_space csp,
                                   const struct pl_cone_params *params);

PL_API_END

#endif // LIBPLACEBO_SHADERS_COLORSPACE_H_