summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNiklas Haas <git@haasn.dev>2023-09-16 13:31:25 +0200
committerNiklas Haas <github-daiK1o@haasn.dev>2023-09-16 14:33:45 +0200
commit06e65778beac1e6f110466b34b5ceb6a8d1ddb42 (patch)
tree81f4a55398f3eea285374412e0b14f145e51476e
parent87162f0722dfcf6f71276e1ccadb81d7b58f721b (diff)
downloadmpv-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.c13
-rw-r--r--video/out/filter_kernels.h3
-rw-r--r--video/out/gpu/video_shaders.c2
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