diff options
author | Niklas Haas <git@haasn.dev> | 2023-09-16 13:31:25 +0200 |
---|---|---|
committer | Niklas Haas <github-daiK1o@haasn.dev> | 2023-09-16 14:33:45 +0200 |
commit | 06e65778beac1e6f110466b34b5ceb6a8d1ddb42 (patch) | |
tree | 81f4a55398f3eea285374412e0b14f145e51476e | |
parent | 87162f0722dfcf6f71276e1ccadb81d7b58f721b (diff) | |
download | mpv-06e65778beac1e6f110466b34b5ceb6a8d1ddb42.tar.bz2 mpv-06e65778beac1e6f110466b34b5ceb6a8d1ddb42.tar.xz |
filter_kernels: properly sharpen/blur filter radius
We currently always scaled the window to the size of the configured
radius. However, this is wrong - we should instead be scaling it to the
size of the sharpened/blurred kernel. Since the window is always
stretched to the configured size of the filter, we can accomplish this
easily by just multiplying the blur value into the filter radius
directly, and then using that adjusted radius in place of `f.radius`
everywhere.
On a side note, this gives a very minor performance boost to
ewa_lanczossharp for no downside.
-rw-r--r-- | video/out/filter_kernels.c | 13 | ||||
-rw-r--r-- | video/out/filter_kernels.h | 3 | ||||
-rw-r--r-- | video/out/gpu/video_shaders.c | 2 |
3 files changed, 11 insertions, 7 deletions
diff --git a/video/out/filter_kernels.c b/video/out/filter_kernels.c index cf681cc5db..a007f1e71f 100644 --- a/video/out/filter_kernels.c +++ b/video/out/filter_kernels.c @@ -60,16 +60,19 @@ bool mp_init_filter(struct filter_kernel *filter, const int *sizes, double inv_scale) { assert(filter->f.radius > 0); + double blur = filter->f.blur > 0.0 ? filter->f.blur : 1.0; + filter->radius = blur * filter->f.radius; + // Only downscaling requires widening the filter filter->filter_scale = MPMAX(1.0, inv_scale); - double src_radius = filter->f.radius * filter->filter_scale; + double src_radius = filter->radius * filter->filter_scale; // Polar filters are dependent solely on the radius if (filter->polar) { filter->size = 1; // Not meaningful for EWA/polar scalers. // Safety precaution to avoid generating a gigantic shader if (src_radius > 16.0) { src_radius = 16.0; - filter->filter_scale = src_radius / filter->f.radius; + filter->filter_scale = src_radius / filter->radius; return false; } return true; @@ -89,7 +92,7 @@ bool mp_init_filter(struct filter_kernel *filter, const int *sizes, // largest filter available. This is incorrect, but better than refusing // to do anything. filter->size = cursize[-1]; - filter->filter_scale = (filter->size/2.0) / filter->f.radius; + filter->filter_scale = (filter->size/2.0) / filter->radius; return false; } } @@ -116,7 +119,7 @@ static double sample_window(struct filter_window *kernel, double x) static double sample_filter(struct filter_kernel *filter, double x) { // The window is always stretched to the entire kernel - double w = sample_window(&filter->w, x / filter->f.radius * filter->w.radius); + double w = sample_window(&filter->w, x / filter->radius * filter->w.radius); double k = w * sample_window(&filter->f, x); return k < 0 ? (1 - filter->clamp) * k : k; } @@ -158,7 +161,7 @@ void mp_compute_lut(struct filter_kernel *filter, int count, int stride, filter->radius_cutoff = 0.0; // Compute a 1D array indexed by radius for (int x = 0; x < count; x++) { - double r = x * filter->f.radius / (count - 1); + double r = x * filter->radius / (count - 1); out_array[x] = sample_filter(filter, r); if (fabs(out_array[x]) > filter->value_cutoff) diff --git a/video/out/filter_kernels.h b/video/out/filter_kernels.h index dd9672a256..1da5f18a35 100644 --- a/video/out/filter_kernels.h +++ b/video/out/filter_kernels.h @@ -35,11 +35,12 @@ struct filter_kernel { bool polar; // whether or not the filter uses polar coordinates // The following values are set by mp_init_filter() at runtime. int size; // number of coefficients (may depend on radius) + double radius; // true filter radius, derived from f.radius and f.blur double filter_scale; // Factor to convert the mathematical filter // function radius to the possibly wider // (in the case of downsampling) filter sample // radius. - double radius_cutoff; // the true radius at which we can cut off the filter + double radius_cutoff; // the radius at which we can cut off the filter }; extern const struct filter_window mp_filter_windows[]; diff --git a/video/out/gpu/video_shaders.c b/video/out/gpu/video_shaders.c index 4b4c13bd84..1957797692 100644 --- a/video/out/gpu/video_shaders.c +++ b/video/out/gpu/video_shaders.c @@ -103,7 +103,7 @@ void pass_sample_separated_gen(struct gl_shader_cache *sc, struct scaler *scaler static void polar_sample(struct gl_shader_cache *sc, struct scaler *scaler, int x, int y, int components, bool planar) { - double radius = scaler->kernel->f.radius * scaler->kernel->filter_scale; + double radius = scaler->kernel->radius * scaler->kernel->filter_scale; double radius_cutoff = scaler->kernel->radius_cutoff; // Since we can't know the subpixel position in advance, assume a |