summaryrefslogtreecommitdiffstats
path: root/src/include/libplacebo/shaders/sampling.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/libplacebo/shaders/sampling.h')
-rw-r--r--src/include/libplacebo/shaders/sampling.h257
1 files changed, 257 insertions, 0 deletions
diff --git a/src/include/libplacebo/shaders/sampling.h b/src/include/libplacebo/shaders/sampling.h
new file mode 100644
index 0000000..5221e44
--- /dev/null
+++ b/src/include/libplacebo/shaders/sampling.h
@@ -0,0 +1,257 @@
+/*
+ * 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_SAMPLING_H_
+#define LIBPLACEBO_SHADERS_SAMPLING_H_
+
+// Sampling operations. These shaders perform some form of sampling operation
+// from a given pl_tex. In order to use these, the pl_shader *must* have been
+// created using the same `gpu` as the originating `pl_tex`. Otherwise, this
+// is undefined behavior. They require nothing (PL_SHADER_SIG_NONE) and return
+// a color (PL_SHADER_SIG_COLOR).
+
+#include <libplacebo/colorspace.h>
+#include <libplacebo/filters.h>
+#include <libplacebo/shaders.h>
+
+PL_API_BEGIN
+
+// Common parameters for sampling operations
+struct pl_sample_src {
+ // There are two mutually exclusive ways of providing the source to sample
+ // from:
+ //
+ // 1. Provide the texture and sampled region directly. This generates
+ // a shader with input signature `PL_SHADER_SIG_NONE`, which binds the
+ // texture as a descriptor (and the coordinates as a vertex attribute)
+ pl_tex tex; // texture to sample
+ pl_rect2df rect; // sub-rect to sample from (optional)
+ enum pl_tex_address_mode address_mode; // preferred texture address mode
+
+ // 2. Have the shader take it as an argument. Doing this requires
+ // specifying the missing metadata of the texture backing the sampler, so
+ // that the shader generation can generate the correct code.
+ int tex_w, tex_h; // dimensions of the actual texture
+ enum pl_fmt_type format; // format of the sampler being accepted
+ enum pl_sampler_type sampler; // type of the sampler being accepted
+ enum pl_tex_sample_mode mode; // sample mode of the sampler being accepted
+ float sampled_w, sampled_h; // dimensions of the sampled region (optional)
+
+ // Common metadata for both sampler input types:
+ int components; // number of components to sample (optional)
+ uint8_t component_mask; // bitmask of components to sample (optional)
+ int new_w, new_h; // dimensions of the resulting output (optional)
+ float scale; // factor to multiply into sampled signal (optional)
+
+ // Note: `component_mask` and `components` are mutually exclusive, the
+ // former is preferred if both are specified.
+};
+
+#define pl_sample_src(...) (&(struct pl_sample_src) { __VA_ARGS__ })
+
+struct pl_deband_params {
+ // The number of debanding steps to perform per sample. Each step reduces a
+ // bit more banding, but takes time to compute. Note that the strength of
+ // each step falls off very quickly, so high numbers (>4) are practically
+ // useless. Defaults to 1.
+ int iterations;
+
+ // The debanding filter's cut-off threshold. Higher numbers increase the
+ // debanding strength dramatically, but progressively diminish image
+ // details. Defaults to 3.0.
+ float threshold;
+
+ // The debanding filter's initial radius. The radius increases linearly
+ // for each iteration. A higher radius will find more gradients, but a
+ // lower radius will smooth more aggressively. Defaults to 16.0.
+ float radius;
+
+ // Add some extra noise to the image. This significantly helps cover up
+ // remaining quantization artifacts. Higher numbers add more noise.
+ // Note: When debanding HDR sources, even a small amount of grain can
+ // result in a very big change to the brightness level. It's recommended to
+ // either scale this value down or disable it entirely for HDR.
+ //
+ // Defaults to 4.0, which is very mild.
+ float grain;
+
+ // 'Neutral' grain value for each channel being debanded (sorted in order
+ // from low to high index). Grain application will be modulated to avoid
+ // disturbing colors close to this value. Set this to a value corresponding
+ // to black in the relevant colorspace.
+ float grain_neutral[3];
+};
+
+#define PL_DEBAND_DEFAULTS \
+ .iterations = 1, \
+ .threshold = 3.0, \
+ .radius = 16.0, \
+ .grain = 4.0,
+
+#define pl_deband_params(...) (&(struct pl_deband_params) {PL_DEBAND_DEFAULTS __VA_ARGS__ })
+PL_API extern const struct pl_deband_params pl_deband_default_params;
+
+// Debands a given texture and returns the sampled color in `vec4 color`. If
+// `params` is left as NULL, it defaults to &pl_deband_default_params. Note
+// that `tex->params.format` must have PL_FMT_CAP_LINEAR. When the given
+// `pl_sample_src` implies scaling, this effectively performs bilinear
+// sampling on the input (but not the output).
+//
+// Note: This can also be used as a pure grain function, by setting the number
+// of iterations to 0.
+PL_API void pl_shader_deband(pl_shader sh, const struct pl_sample_src *src,
+ const struct pl_deband_params *params);
+
+// Performs direct / native texture sampling, using whatever texture filter is
+// available (linear for linearly sampleable sources, nearest otherwise).
+//
+// Note: This is generally very low quality and should be avoided if possible,
+// for both upscaling and downscaling.
+PL_API bool pl_shader_sample_direct(pl_shader sh, const struct pl_sample_src *src);
+
+// Performs hardware-accelerated nearest neighbour sampling. This is similar to
+// `pl_shader_sample_direct`, but forces nearest neighbour interpolation.
+PL_API bool pl_shader_sample_nearest(pl_shader sh, const struct pl_sample_src *src);
+
+// Performs hardware-accelerated bilinear sampling. This is similar to
+// `pl_shader_sample_direct`, but forces bilinear interpolation.
+PL_API bool pl_shader_sample_bilinear(pl_shader sh, const struct pl_sample_src *src);
+
+// Optimized versions of specific, strictly positive scaler kernels that take
+// adantage of linear texture sampling to reduce the number of fetches needed
+// by a factor of four. This family of functions performs radius-2 scaling
+// with only four texture fetches, which is far more efficient than using
+// the generalized 1D scaling method. Only works well for upscaling.
+PL_API bool pl_shader_sample_bicubic(pl_shader sh, const struct pl_sample_src *src);
+PL_API bool pl_shader_sample_hermite(pl_shader sh, const struct pl_sample_src *src);
+PL_API bool pl_shader_sample_gaussian(pl_shader sh, const struct pl_sample_src *src);
+
+// A sampler that is similar to nearest neighbour sampling, but tries to
+// preserve pixel aspect ratios. This is mathematically equivalent to taking an
+// idealized image with square pixels, sampling it at an infinite resolution,
+// and then downscaling that to the desired resolution. (Hence it being called
+// "oversample"). Good for pixel art.
+//
+// The threshold provides a cutoff threshold below which the contribution of
+// pixels should be ignored, trading some amount of aspect ratio distortion for
+// a slightly crisper image. A value of `threshold == 0.5` makes this filter
+// equivalent to regular nearest neighbour sampling.
+PL_API bool pl_shader_sample_oversample(pl_shader sh, const struct pl_sample_src *src,
+ float threshold);
+
+struct pl_sample_filter_params {
+ // The filter to use for sampling.
+ struct pl_filter_config filter;
+
+ // Antiringing strength. A value of 0.0 disables antiringing, and a value
+ // of 1.0 enables full-strength antiringing. Defaults to 0.0 if
+ // unspecified.
+ //
+ // Note: Ignored if `filter.antiring` is already set to something nonzero.
+ float antiring;
+
+ // Disable the use of compute shaders (e.g. if rendering to non-storable tex)
+ bool no_compute;
+ // Disable the use of filter widening / anti-aliasing (for downscaling)
+ bool no_widening;
+
+ // This shader object is used to store the LUT, and will be recreated
+ // if necessary. To avoid thrashing the resource, users should avoid trying
+ // to re-use the same LUT for different filter configurations or scaling
+ // ratios. Must be set to a valid pointer, and the target NULL-initialized.
+ pl_shader_obj *lut;
+
+ // Deprecated / removed fields
+ int lut_entries PL_DEPRECATED; // hard-coded as 256
+ float cutoff PL_DEPRECATED; // hard-coded as 1e-3
+};
+
+#define pl_sample_filter_params(...) (&(struct pl_sample_filter_params) { __VA_ARGS__ })
+
+// Performs polar sampling. This internally chooses between an optimized compute
+// shader, and various fragment shaders, depending on the supported GLSL version
+// and GPU features. Returns whether or not it was successful.
+//
+// Note: `params->filter.polar` must be true to use this function.
+PL_API bool pl_shader_sample_polar(pl_shader sh, const struct pl_sample_src *src,
+ const struct pl_sample_filter_params *params);
+
+// Performs orthogonal (1D) sampling. Using this twice in a row (once vertical
+// and once horizontal) effectively performs a 2D upscale. This is lower
+// quality than polar sampling, but significantly faster, and therefore the
+// recommended default. Returns whether or not it was successful.
+//
+// `src` must represent a scaling operation that only scales in one direction,
+// i.e. either only X or only Y. The other direction must be left unscaled.
+//
+// Note: Due to internal limitations, this may currently only be used on 2D
+// textures - even though the basic principle would work for 1D and 3D textures
+// as well.
+PL_API bool pl_shader_sample_ortho2(pl_shader sh, const struct pl_sample_src *src,
+ const struct pl_sample_filter_params *params);
+
+struct pl_distort_params {
+ // An arbitrary 2x2 affine transformation to apply to the input image.
+ // For simplicity, the input image is explicitly centered and scaled such
+ // that the longer dimension is in [-1,1], before applying this.
+ pl_transform2x2 transform;
+
+ // If true, the texture is placed inside the center of the canvas without
+ // scaling. If false, it is effectively stretched to the canvas size.
+ bool unscaled;
+
+ // If true, the transformation is automatically scaled down and shifted to
+ // ensure that the resulting image fits inside the output canvas.
+ bool constrain;
+
+ // If true, use bicubic interpolation rather than faster bilinear
+ // interpolation. Higher quality but slower.
+ bool bicubic;
+
+ // Specifies the texture address mode to use when sampling out of bounds.
+ enum pl_tex_address_mode address_mode;
+
+ // If set, all out-of-bounds accesses will instead be treated as
+ // transparent, according to the given alpha mode. (Which should match the
+ // alpha mode of the texture)
+ //
+ // Note: `address_mode` has no effect when this is specified.
+ enum pl_alpha_mode alpha_mode;
+};
+
+#define PL_DISTORT_DEFAULTS \
+ .transform.mat.m = {{ 1, 0 }, {0, 1}},
+
+#define pl_distort_params(...) (&(struct pl_distort_params) {PL_DISTORT_DEFAULTS __VA_ARGS__ })
+PL_API extern const struct pl_distort_params pl_distort_default_params;
+
+// Distorts the input image using a given set of transformation parameters.
+// `out_w` and `out_h` determine the size of the effective canvas inside which
+// the distorted result may be rendered. Areas outside of this canvas will
+// be implicitly cut off.
+PL_API void pl_shader_distort(pl_shader sh, pl_tex tex, int out_w, int out_h,
+ const struct pl_distort_params *params);
+
+enum PL_DEPRECATED { // for `int pass`
+ PL_SEP_VERT = 0,
+ PL_SEP_HORIZ,
+ PL_SEP_PASSES
+};
+
+PL_API_END
+
+#endif // LIBPLACEBO_SHADERS_SAMPLING_H_