From d2082841df8bc39c585fc9d4be6498d1a296fed8 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Fri, 18 Aug 2023 15:36:59 +0200 Subject: [PATCH] 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) --- video/out/vo_gpu_next.c | 223 ++++++++++++++++++++++------------------ 1 file changed, 124 insertions(+), 99 deletions(-) diff --git a/video/out/vo_gpu_next.c b/video/out/vo_gpu_next.c index 4a799319b5..d6d13a40ef 100644 --- a/video/out/vo_gpu_next.c +++ b/video/out/vo_gpu_next.c @@ -53,6 +53,22 @@ #include "osdep/windows_utils.h" #endif +#if PL_API_VER >= 309 +#include +#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