1
0
mirror of https://github.com/mpv-player/mpv synced 2025-01-30 03:32:50 +00:00

vo_gpu_next: switch to new pl_options system

With a backwards compatibility shim for older versions of libplacebo in
which we simply define the relevant subset of this struct ourselves and
initialize it to known-good values, to be able to continue using our
options assigning code.

It's worth pointing out that our use of scalers deviates from how
pl_options was intended to be used, as a consequence of backwards
compatibility with pre-308 versions of libplacebo. But this should work
fine in practice, since we don't care about serializing these custom
scalers correctly. Users can still override them using the built-in
pl_options scalers when loading custom scalers via --libplacebo-options.
(To be added in the next commit)
This commit is contained in:
Niklas Haas 2023-08-18 15:36:59 +02:00 committed by Niklas Haas
parent 4eedb8710c
commit d2082841df

View File

@ -53,6 +53,22 @@
#include "osdep/windows_utils.h"
#endif
#if PL_API_VER >= 309
#include <libplacebo/options.h>
#else
typedef struct pl_options_t {
// Backwards compatibility shim of this struct
struct pl_render_params params;
struct pl_deband_params deband_params;
struct pl_sigmoid_params sigmoid_params;
struct pl_color_adjustment color_adjustment;
struct pl_peak_detect_params peak_detect_params;
struct pl_color_map_params color_map_params;
struct pl_dither_params dither_params;
struct pl_icc_params icc_params;
} *pl_options;
#endif
struct osd_entry {
pl_tex tex;
struct pl_overlay_part *parts;
@ -122,21 +138,14 @@ struct priv {
bool want_reset;
bool frame_pending;
pl_options pars;
struct m_config_cache *opts_cache;
struct mp_csp_equalizer_state *video_eq;
struct pl_render_params params;
struct pl_deband_params deband;
struct pl_sigmoid_params sigmoid;
struct pl_color_adjustment color_adjustment;
struct pl_peak_detect_params peak_detect;
struct pl_color_map_params color_map;
struct pl_dither_params dither;
struct scaler_params scalers[SCALER_COUNT];
const struct pl_hook **hooks; // storage for `params.hooks`
const struct pl_filter_config *frame_mixer;
enum mp_csp_levels output_levels;
struct pl_icc_params icc;
struct pl_icc_profile icc_profile;
char *icc_path;
@ -768,22 +777,22 @@ static void info_callback(void *priv, const struct pl_render_info *info)
static void update_options(struct vo *vo)
{
struct priv *p = vo->priv;
pl_options pars = p->pars;
if (m_config_cache_update(p->opts_cache))
update_render_options(vo);
update_lut(p, &p->lut);
p->params.lut = p->lut.lut;
p->params.lut_type = p->lut.type;
pars->params.lut = p->lut.lut;
pars->params.lut_type = p->lut.type;
// Update equalizer state
struct mp_csp_params cparams = MP_CSP_PARAMS_DEFAULTS;
mp_csp_equalizer_state_get(p->video_eq, &cparams);
p->color_adjustment = pl_color_adjustment_neutral;
p->color_adjustment.brightness = cparams.brightness;
p->color_adjustment.contrast = cparams.contrast;
p->color_adjustment.hue = cparams.hue;
p->color_adjustment.saturation = cparams.saturation;
p->color_adjustment.gamma = cparams.gamma;
pars->color_adjustment.brightness = cparams.brightness;
pars->color_adjustment.contrast = cparams.contrast;
pars->color_adjustment.hue = cparams.hue;
pars->color_adjustment.saturation = cparams.saturation;
pars->color_adjustment.gamma = cparams.gamma;
p->output_levels = cparams.levels_out;
}
@ -815,6 +824,7 @@ static void apply_target_contrast(struct priv *p, struct pl_color_space *color)
static void apply_target_options(struct priv *p, struct pl_frame *target)
{
pl_options pars = p->pars;
update_lut(p, &p->target_lut);
target->lut = p->target_lut.lut;
@ -843,12 +853,12 @@ static void apply_target_options(struct priv *p, struct pl_frame *target)
if (opts->icc_opts->icc_use_luma) {
// Use detected luminance
p->icc.max_luma = 0;
pars->icc_params.max_luma = 0;
} else {
// Use HDR levels if available, fall back to default luminance
p->icc.max_luma = target->color.hdr.max_luma;
if (!p->icc.max_luma)
p->icc.max_luma = pl_icc_default_params.max_luma;
pars->icc_params.max_luma = target->color.hdr.max_luma;
if (!pars->icc_params.max_luma)
pars->icc_params.max_luma = pl_icc_default_params.max_luma;
}
}
@ -878,10 +888,11 @@ static void apply_crop(struct pl_frame *frame, struct mp_rect crop,
static void draw_frame(struct vo *vo, struct vo_frame *frame)
{
struct priv *p = vo->priv;
pl_options pars = p->pars;
pl_gpu gpu = p->gpu;
update_options(vo);
p->params.info_callback = info_callback;
p->params.info_priv = vo;
pars->params.info_callback = info_callback;
pars->params.info_priv = vo;
// Push all incoming frames into the frame queue
for (int n = 0; n < frame->num_frames; n++) {
@ -937,7 +948,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
// Advance the queue state to the current PTS to discard unused frames
pl_queue_update(p->queue, NULL, pl_queue_params(
.pts = frame->current->pts + vsync_offset,
.radius = pl_frame_mix_radius(&p->params),
.radius = pl_frame_mix_radius(&pars->params),
));
}
return;
@ -960,7 +971,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
// Update queue state
struct pl_queue_params qparams = {
.pts = frame->current->pts + vsync_offset,
.radius = pl_frame_mix_radius(&p->params),
.radius = pl_frame_mix_radius(&pars->params),
.vsync_duration = frame->vsync_interval,
.interpolation_threshold = opts->interpolation_threshold,
};
@ -1033,13 +1044,13 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
bool will_redraw = frame->display_synced && frame->num_vsyncs > 1;
bool cache_frame = will_redraw || frame->still;
p->params.skip_caching_single_frame = !cache_frame;
p->params.preserve_mixing_cache = p->inter_preserve && !frame->still;
p->params.frame_mixer = frame->still ? NULL : p->frame_mixer;
p->peak_detect.allow_delayed = p->delayed_peak;
pars->params.skip_caching_single_frame = !cache_frame;
pars->params.preserve_mixing_cache = p->inter_preserve && !frame->still;
pars->params.frame_mixer = frame->still ? NULL : p->frame_mixer;
pars->peak_detect_params.allow_delayed = p->delayed_peak;
// Render frame
if (!pl_render_image_mix(p->rr, &mix, &target, &p->params)) {
if (!pl_render_image_mix(p->rr, &mix, &target, &pars->params)) {
MP_ERR(vo, "Failed rendering frame!\n");
goto done;
}
@ -1160,16 +1171,17 @@ static bool update_auto_profile(struct priv *p, int *events)
static void video_screenshot(struct vo *vo, struct voctrl_screenshot *args)
{
struct priv *p = vo->priv;
pl_options pars = pars;
pl_gpu gpu = p->gpu;
pl_tex fbo = NULL;
args->res = NULL;
update_options(vo);
p->params.info_callback = NULL;
p->params.skip_caching_single_frame = true;
p->params.preserve_mixing_cache = false;
p->params.frame_mixer = NULL;
p->peak_detect.allow_delayed = false;
pars->params.info_callback = NULL;
pars->params.skip_caching_single_frame = true;
pars->params.preserve_mixing_cache = false;
pars->params.frame_mixer = NULL;
pars->peak_detect_params.allow_delayed = false;
// Retrieve the current frame from the frame queue
struct pl_frame_mix mix;
@ -1270,7 +1282,7 @@ static void video_screenshot(struct vo *vo, struct voctrl_screenshot *args)
&p->osd_state, &target);
image.num_overlays = 0; // Disable on-screen overlays
if (!pl_render_image(p->rr, &image, &target, &p->params)) {
if (!pl_render_image(p->rr, &image, &target, &pars->params)) {
MP_ERR(vo, "Failed rendering frame!\n");
goto done;
}
@ -1481,6 +1493,10 @@ static void uninit(struct vo *vo)
pl_shader_info_deref(&p->perf_redraw.info[i].shader);
}
#if PL_API_VER >= 309
pl_options_free(&p->pars);
#endif
p->ra_ctx = NULL;
p->pllog = NULL;
p->gpu = NULL;
@ -1537,6 +1553,23 @@ static int preinit(struct vo *vo)
talloc_free(cache_file);
}
#if PL_API_VER >= 309
p->pars = pl_options_alloc(p->pllog);
#else
p->pars = talloc_ptrtype(p, p->pars);
p->pars->params = pl_render_default_params;
p->pars->deband_params = pl_deband_default_params;
p->pars->sigmoid_params = pl_sigmoid_default_params;
p->pars->color_adjustment = pl_color_adjustment_neutral;
p->pars->peak_detect_params = pl_peak_detect_default_params;
p->pars->color_map_params = pl_color_map_default_params;
p->pars->dither_params = pl_dither_default_params;
p->pars->icc_params = pl_icc_default_params;
// Redirect always-enabled params structs to shim
p->pars->params.color_adjustment = &p->pars->color_adjustment;
p->pars->params.color_map_params = &p->pars->color_map_params;
p->pars->params.icc_params = &p->pars->icc_params;
#endif
update_render_options(vo);
return 0;
@ -1744,6 +1777,7 @@ static bool icc_load(void *priv, uint64_t sig, uint8_t *cache, size_t size)
static void update_icc_opts(struct priv *p, const struct mp_icc_opts *opts)
{
pl_options pars = p->pars;
if (!opts)
return;
@ -1755,15 +1789,13 @@ static void update_icc_opts(struct priv *p, const struct mp_icc_opts *opts)
int s_r = 0, s_g = 0, s_b = 0;
gl_parse_3dlut_size(opts->size_str, &s_r, &s_g, &s_b);
p->params.icc_params = &p->icc;
p->icc = pl_icc_default_params;
p->icc.intent = opts->intent;
p->icc.size_r = s_r;
p->icc.size_g = s_g;
p->icc.size_b = s_b;
p->icc.cache_priv = p;
p->icc.cache_save = icc_save;
p->icc.cache_load = icc_load;
pars->icc_params.intent = opts->intent;
pars->icc_params.size_r = s_r;
pars->icc_params.size_g = s_g;
pars->icc_params.size_b = s_b;
pars->icc_params.cache_priv = p;
pars->icc_params.cache_save = icc_save;
pars->icc_params.cache_load = icc_load;
if (!opts->profile || !opts->profile[0]) {
// No profile enabled, un-load any existing profiles
@ -1886,30 +1918,25 @@ static void update_hook_opts(struct priv *p, char **opts, const char *shaderpath
static void update_render_options(struct vo *vo)
{
struct priv *p = vo->priv;
pl_options pars = p->pars;
const struct gl_video_opts *opts = p->opts_cache->opts;
p->params = pl_render_default_params;
p->params.lut_entries = 1 << opts->scaler_lut_size;
p->params.antiringing_strength = opts->scaler[0].antiring;
p->params.polar_cutoff = opts->scaler[0].cutoff;
p->params.deband_params = opts->deband ? &p->deband : NULL;
p->params.sigmoid_params = opts->sigmoid_upscaling ? &p->sigmoid : NULL;
p->params.color_adjustment = &p->color_adjustment;
p->params.peak_detect_params = opts->tone_map.compute_peak >= 0 ? &p->peak_detect : NULL;
p->params.color_map_params = &p->color_map;
p->params.background_color[0] = opts->background.r / 255.0;
p->params.background_color[1] = opts->background.g / 255.0;
p->params.background_color[2] = opts->background.b / 255.0;
p->params.background_transparency = 1.0 - opts->background.a / 255.0;
p->params.skip_anti_aliasing = !opts->correct_downscaling;
p->params.disable_linear_scaling = !opts->linear_downscaling && !opts->linear_upscaling;
p->params.disable_fbos = opts->dumb_mode == 1;
p->params.blend_against_tiles = opts->alpha_mode == ALPHA_BLEND_TILES;
p->params.corner_rounding = p->corner_rounding;
pars->params.lut_entries = 1 << opts->scaler_lut_size;
pars->params.antiringing_strength = opts->scaler[0].antiring;
pars->params.polar_cutoff = opts->scaler[0].cutoff;
pars->params.background_color[0] = opts->background.r / 255.0;
pars->params.background_color[1] = opts->background.g / 255.0;
pars->params.background_color[2] = opts->background.b / 255.0;
pars->params.background_transparency = 1.0 - opts->background.a / 255.0;
pars->params.skip_anti_aliasing = !opts->correct_downscaling;
pars->params.disable_linear_scaling = !opts->linear_downscaling && !opts->linear_upscaling;
pars->params.disable_fbos = opts->dumb_mode == 1;
pars->params.blend_against_tiles = opts->alpha_mode == ALPHA_BLEND_TILES;
pars->params.corner_rounding = p->corner_rounding;
// Map scaler options as best we can
p->params.upscaler = map_scaler(p, SCALER_SCALE);
p->params.downscaler = map_scaler(p, SCALER_DSCALE);
p->params.plane_upscaler = map_scaler(p, SCALER_CSCALE);
pars->params.upscaler = map_scaler(p, SCALER_SCALE);
pars->params.downscaler = map_scaler(p, SCALER_DSCALE);
pars->params.plane_upscaler = map_scaler(p, SCALER_CSCALE);
p->frame_mixer = opts->interpolation ? map_scaler(p, SCALER_TSCALE) : NULL;
// Request as many frames as required from the decoder
@ -1919,21 +1946,21 @@ static void update_render_options(struct vo *vo)
vo_set_queue_params(vo, 0, 2);
}
p->deband = pl_deband_default_params;
p->deband.iterations = opts->deband_opts->iterations;
p->deband.radius = opts->deband_opts->range;
p->deband.threshold = opts->deband_opts->threshold / 16.384;
p->deband.grain = opts->deband_opts->grain / 8.192;
pars->params.deband_params = opts->deband ? &pars->deband_params : NULL;
pars->deband_params.iterations = opts->deband_opts->iterations;
pars->deband_params.radius = opts->deband_opts->range;
pars->deband_params.threshold = opts->deband_opts->threshold / 16.384;
pars->deband_params.grain = opts->deband_opts->grain / 8.192;
p->sigmoid = pl_sigmoid_default_params;
p->sigmoid.center = opts->sigmoid_center;
p->sigmoid.slope = opts->sigmoid_slope;
pars->params.sigmoid_params = opts->sigmoid_upscaling ? &pars->sigmoid_params : NULL;
pars->sigmoid_params.center = opts->sigmoid_center;
pars->sigmoid_params.slope = opts->sigmoid_slope;
p->peak_detect = pl_peak_detect_default_params;
p->peak_detect.smoothing_period = opts->tone_map.decay_rate;
p->peak_detect.scene_threshold_low = opts->tone_map.scene_threshold_low;
p->peak_detect.scene_threshold_high = opts->tone_map.scene_threshold_high;
p->peak_detect.percentile = opts->tone_map.peak_percentile;
pars->params.peak_detect_params = opts->tone_map.compute_peak >= 0 ? &pars->peak_detect_params : NULL;
pars->peak_detect_params.smoothing_period = opts->tone_map.decay_rate;
pars->peak_detect_params.scene_threshold_low = opts->tone_map.scene_threshold_low;
pars->peak_detect_params.scene_threshold_high = opts->tone_map.scene_threshold_high;
pars->peak_detect_params.percentile = opts->tone_map.peak_percentile;
const struct pl_tone_map_function * const tone_map_funs[] = {
[TONE_MAPPING_AUTO] = &pl_tone_map_auto,
@ -1962,55 +1989,53 @@ static void update_render_options(struct vo *vo)
[GAMUT_LINEAR] = &pl_gamut_map_linear,
};
p->color_map = pl_color_map_default_params;
p->color_map.tone_mapping_function = tone_map_funs[opts->tone_map.curve];
p->color_map.tone_mapping_param = opts->tone_map.curve_param;
p->color_map.inverse_tone_mapping = opts->tone_map.inverse;
if (isnan(p->color_map.tone_mapping_param)) // vo_gpu compatibility
p->color_map.tone_mapping_param = 0.0;
p->color_map.visualize_lut = opts->tone_map.visualize;
p->color_map.contrast_recovery = opts->tone_map.contrast_recovery;
p->color_map.contrast_smoothness = opts->tone_map.contrast_smoothness;
pars->color_map_params.tone_mapping_function = tone_map_funs[opts->tone_map.curve];
pars->color_map_params.tone_mapping_param = opts->tone_map.curve_param;
pars->color_map_params.inverse_tone_mapping = opts->tone_map.inverse;
if (isnan(pars->color_map_params.tone_mapping_param)) // vo_gpu compatibility
pars->color_map_params.tone_mapping_param = 0.0;
pars->color_map_params.contrast_recovery = opts->tone_map.contrast_recovery;
pars->color_map_params.visualize_lut = opts->tone_map.visualize;
pars->color_map_params.contrast_smoothness = opts->tone_map.contrast_smoothness;
if (opts->tone_map.gamut_mode != GAMUT_AUTO)
p->color_map.gamut_mapping = gamut_modes[opts->tone_map.gamut_mode];
pars->color_map_params.gamut_mapping = gamut_modes[opts->tone_map.gamut_mode];
switch (opts->dither_algo) {
case DITHER_NONE:
p->params.dither_params = NULL;
pars->params.dither_params = NULL;
break;
case DITHER_ERROR_DIFFUSION:
p->params.error_diffusion = pl_find_error_diffusion_kernel(opts->error_diffusion);
if (!p->params.error_diffusion) {
pars->params.error_diffusion = pl_find_error_diffusion_kernel(opts->error_diffusion);
if (!pars->params.error_diffusion) {
MP_WARN(p, "Could not find error diffusion kernel '%s', falling "
"back to fruit.\n", opts->error_diffusion);
}
MP_FALLTHROUGH;
case DITHER_ORDERED:
case DITHER_FRUIT:
p->params.dither_params = &p->dither;
p->dither = pl_dither_default_params;
p->dither.method = opts->dither_algo == DITHER_ORDERED
pars->params.dither_params = &pars->dither_params;
pars->dither_params.method = opts->dither_algo == DITHER_ORDERED
? PL_DITHER_ORDERED_FIXED
: PL_DITHER_BLUE_NOISE;
p->dither.lut_size = opts->dither_size;
p->dither.temporal = opts->temporal_dither;
pars->dither_params.lut_size = opts->dither_size;
pars->dither_params.temporal = opts->temporal_dither;
break;
}
if (opts->dither_depth < 0)
p->params.dither_params = NULL;
pars->params.dither_params = NULL;
update_icc_opts(p, opts->icc_opts);
const struct pl_hook *hook;
for (int i = 0; opts->user_shaders && opts->user_shaders[i]; i++) {
if ((hook = load_hook(p, opts->user_shaders[i]))) {
MP_TARRAY_APPEND(p, p->hooks, p->params.num_hooks, hook);
MP_TARRAY_APPEND(p, p->hooks, pars->params.num_hooks, hook);
update_hook_opts(p, opts->user_shader_opts, opts->user_shaders[i], hook);
}
}
p->params.hooks = p->hooks;
pars->params.hooks = p->hooks;
}
#define OPT_BASE_STRUCT struct priv