mirror of https://github.com/mpv-player/mpv
vo_opengl: clean up ewa_lanczos code
This fixes compatibility with GLES 2.0 and makes the code a bit neater in general. It also properly forces indirect scaling for subsampled video regardless of the lscale setting.
This commit is contained in:
parent
571fe8f729
commit
f5e48f0235
|
@ -58,10 +58,9 @@ bool mp_init_filter(struct filter_kernel *filter, const int *sizes,
|
|||
{
|
||||
if (filter->radius < 0)
|
||||
filter->radius = 3.0;
|
||||
// polar filters can be of any radius, and nothing special is needed
|
||||
// polar filters are dependent only on the radius
|
||||
if (filter->polar) {
|
||||
filter->size = filter->radius;
|
||||
filter->num_coefficients = 1;
|
||||
filter->size = 1;
|
||||
return true;
|
||||
}
|
||||
// only downscaling requires widening the filter
|
||||
|
@ -76,14 +75,12 @@ bool mp_init_filter(struct filter_kernel *filter, const int *sizes,
|
|||
cursize++;
|
||||
if (*cursize) {
|
||||
filter->size = *cursize;
|
||||
filter->num_coefficients = filter->size;
|
||||
return true;
|
||||
} else {
|
||||
// The filter doesn't fit - instead of failing completely, use the
|
||||
// largest filter available. This is incorrect, but better than refusing
|
||||
// to do anything.
|
||||
filter->size = cursize[-1];
|
||||
filter->num_coefficients = filter->size;
|
||||
filter->inv_scale = filter->size / 2.0 / filter->radius;
|
||||
return false;
|
||||
}
|
||||
|
@ -110,16 +107,18 @@ void mp_compute_weights(struct filter_kernel *filter, double f, float *out_w)
|
|||
}
|
||||
|
||||
// Fill the given array with weights for the range [0.0, 1.0]. The array is
|
||||
// interpreted as rectangular array of count * filter->num_coefficients items.
|
||||
// interpreted as rectangular array of count * filter->size items.
|
||||
void mp_compute_lut(struct filter_kernel *filter, int count, float *out_array)
|
||||
{
|
||||
if (filter->polar) {
|
||||
// Compute a 1D array indexed by radius
|
||||
assert(filter->radius > 0);
|
||||
for (int x = 0; x < count; x++) {
|
||||
double r = x * filter->radius / (count - 1);
|
||||
out_array[x] = r <= filter->radius ? filter->weight(filter, r) : 0;
|
||||
}
|
||||
} else {
|
||||
// Compute a 2D array indexed by subpixel position
|
||||
for (int n = 0; n < count; n++) {
|
||||
mp_compute_weights(filter, n / (double)(count - 1),
|
||||
out_array + filter->size * n);
|
||||
|
|
|
@ -31,9 +31,8 @@ struct filter_kernel {
|
|||
// Whether or not the filter uses polar coordinates
|
||||
bool polar;
|
||||
// The following values are set by mp_init_filter() at runtime.
|
||||
int size;
|
||||
// Number of coefficients; equals the rounded up radius multiplied with 2.
|
||||
int num_coefficients;
|
||||
int size;
|
||||
double inv_scale;
|
||||
};
|
||||
|
||||
|
@ -44,6 +43,5 @@ bool mp_init_filter(struct filter_kernel *filter, const int *sizes,
|
|||
double scale);
|
||||
void mp_compute_weights(struct filter_kernel *filter, double f, float *out_w);
|
||||
void mp_compute_lut(struct filter_kernel *filter, int count, float *out_array);
|
||||
void mp_compute_lut_polar(struct filter_kernel *filter, int count, float *out_array);
|
||||
|
||||
#endif /* MPLAYER_FILTER_KERNELS_H */
|
||||
|
|
|
@ -96,6 +96,7 @@ static const struct feature features[] = {
|
|||
{MPGL_CAP_FLOAT_TEX, "Float textures"},
|
||||
{MPGL_CAP_TEX_RG, "RG textures"},
|
||||
{MPGL_CAP_1ST_CLASS_ARRAYS, "1st class shader arrays"},
|
||||
{MPGL_CAP_1D_TEX, "1D textures"},
|
||||
{MPGL_CAP_3D_TEX, "3D textures"},
|
||||
{MPGL_CAP_DEBUG, "debugging extensions"},
|
||||
{MPGL_CAP_SW, "suspected software renderer"},
|
||||
|
@ -207,7 +208,7 @@ static const struct gl_functions gl_functions[] = {
|
|||
// GL 2.1+ desktop only (and GLSL 120 shaders)
|
||||
{
|
||||
.ver_core = 210,
|
||||
.provides = MPGL_CAP_ROW_LENGTH | MPGL_CAP_3D_TEX |
|
||||
.provides = MPGL_CAP_ROW_LENGTH | MPGL_CAP_1D_TEX | MPGL_CAP_3D_TEX |
|
||||
MPGL_CAP_1ST_CLASS_ARRAYS,
|
||||
.functions = (const struct gl_function[]) {
|
||||
DEF_FN(DrawBuffer),
|
||||
|
|
|
@ -73,8 +73,9 @@ enum {
|
|||
MPGL_CAP_VDPAU = (1 << 11), // GL_NV_vdpau_interop
|
||||
MPGL_CAP_APPLE_RGB_422 = (1 << 12), // GL_APPLE_rgb_422
|
||||
MPGL_CAP_1ST_CLASS_ARRAYS = (1 << 13),
|
||||
MPGL_CAP_3D_TEX = (1 << 14),
|
||||
MPGL_CAP_DEBUG = (1 << 15),
|
||||
MPGL_CAP_1D_TEX = (1 << 14),
|
||||
MPGL_CAP_3D_TEX = (1 << 15),
|
||||
MPGL_CAP_DEBUG = (1 << 16),
|
||||
MPGL_CAP_SW = (1 << 30), // indirect or sw renderer
|
||||
};
|
||||
|
||||
|
|
|
@ -1006,16 +1006,18 @@ static void compile_shaders(struct gl_video *p)
|
|||
char *s_video = get_section(tmp, src, "frag_video");
|
||||
|
||||
bool rg = gl->mpgl_caps & MPGL_CAP_TEX_RG;
|
||||
bool tex1d = gl->mpgl_caps & MPGL_CAP_1D_TEX;
|
||||
bool tex3d = gl->mpgl_caps & MPGL_CAP_3D_TEX;
|
||||
bool arrays = gl->mpgl_caps & MPGL_CAP_1ST_CLASS_ARRAYS;
|
||||
char *header =
|
||||
talloc_asprintf(tmp, "#version %d%s\n"
|
||||
"#define HAVE_RG %d\n"
|
||||
"#define HAVE_1DTEX %d\n"
|
||||
"#define HAVE_3DTEX %d\n"
|
||||
"#define HAVE_ARRAYS %d\n"
|
||||
"%s%s",
|
||||
gl->glsl_version, gl->es >= 300 ? " es" : "",
|
||||
rg, tex3d, arrays, shader_prelude, PRELUDE_END);
|
||||
rg, tex1d, tex3d, arrays, shader_prelude, PRELUDE_END);
|
||||
|
||||
bool use_cms = p->opts.srgb || p->use_lut_3d;
|
||||
|
||||
|
@ -1185,7 +1187,7 @@ static void compile_shaders(struct gl_video *p)
|
|||
// has to fetch the coefficients for each texture separately, even though
|
||||
// they're the same (this is not an inherent restriction, but would require
|
||||
// to restructure the shader).
|
||||
if (header_sep && p->plane_count > 1)
|
||||
if (p->opts.scale_sep && p->plane_count > 1)
|
||||
use_indirect = true;
|
||||
|
||||
if (input_is_subsampled(p)) {
|
||||
|
@ -1302,7 +1304,7 @@ static void init_scaler(struct gl_video *p, struct scaler *scaler)
|
|||
|
||||
update_scale_factor(p, scaler);
|
||||
|
||||
int size = scaler->kernel->num_coefficients;
|
||||
int size = scaler->kernel->size;
|
||||
int elems_per_pixel = 4;
|
||||
if (size == 1) {
|
||||
elems_per_pixel = 1;
|
||||
|
@ -1314,25 +1316,41 @@ static void init_scaler(struct gl_video *p, struct scaler *scaler)
|
|||
int width = size / elems_per_pixel;
|
||||
assert(size == width * elems_per_pixel);
|
||||
const struct fmt_entry *fmt = &gl_float16_formats[elems_per_pixel - 1];
|
||||
scaler->lut_name = scaler->index == 0 ? "lut_l" : "lut_c";
|
||||
int target;
|
||||
|
||||
if (scaler->kernel->polar) {
|
||||
target = GL_TEXTURE_1D;
|
||||
scaler->lut_name = scaler->index == 0 ? "lut_1d_l" : "lut_1d_c";
|
||||
} else {
|
||||
target = GL_TEXTURE_2D;
|
||||
scaler->lut_name = scaler->index == 0 ? "lut_2d_l" : "lut_2d_c";
|
||||
}
|
||||
|
||||
gl->ActiveTexture(GL_TEXTURE0 + TEXUNIT_SCALERS + scaler->index);
|
||||
|
||||
if (!scaler->gl_lut)
|
||||
gl->GenTextures(1, &scaler->gl_lut);
|
||||
|
||||
gl->BindTexture(GL_TEXTURE_2D, scaler->gl_lut);
|
||||
gl->BindTexture(target, scaler->gl_lut);
|
||||
|
||||
float *weights = talloc_array(NULL, float, LOOKUP_TEXTURE_SIZE * size);
|
||||
mp_compute_lut(scaler->kernel, LOOKUP_TEXTURE_SIZE, weights);
|
||||
gl->TexImage2D(GL_TEXTURE_2D, 0, fmt->internal_format, width,
|
||||
LOOKUP_TEXTURE_SIZE, 0, fmt->format, GL_FLOAT, weights);
|
||||
|
||||
if (target == GL_TEXTURE_1D) {
|
||||
gl->TexImage1D(target, 0, fmt->internal_format, LOOKUP_TEXTURE_SIZE,
|
||||
0, fmt->format, GL_FLOAT, weights);
|
||||
} else {
|
||||
gl->TexImage2D(target, 0, fmt->internal_format, width, LOOKUP_TEXTURE_SIZE,
|
||||
0, fmt->format, GL_FLOAT, weights);
|
||||
}
|
||||
|
||||
talloc_free(weights);
|
||||
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
gl->TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
if (target != GL_TEXTURE_1D)
|
||||
gl->TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
gl->ActiveTexture(GL_TEXTURE0);
|
||||
|
||||
|
@ -2126,6 +2144,7 @@ static void check_gl_features(struct gl_video *p)
|
|||
bool have_fbo = gl->mpgl_caps & MPGL_CAP_FB;
|
||||
bool have_srgb = gl->mpgl_caps & MPGL_CAP_SRGB_TEX;
|
||||
bool have_arrays = gl->mpgl_caps & MPGL_CAP_1ST_CLASS_ARRAYS;
|
||||
bool have_1d_tex = gl->mpgl_caps & MPGL_CAP_1D_TEX;
|
||||
bool have_3d_tex = gl->mpgl_caps & MPGL_CAP_3D_TEX;
|
||||
bool have_mix = gl->glsl_version >= 130;
|
||||
|
||||
|
@ -2144,16 +2163,23 @@ static void check_gl_features(struct gl_video *p)
|
|||
// because they will be slow (not critically slow, but still slower).
|
||||
// Without FP textures, we must always disable them.
|
||||
// I don't know if luminance alpha float textures exist, so disregard them.
|
||||
if (!have_float_tex || !have_arrays || (!have_fbo && p->opts.scale_sep)) {
|
||||
if (!have_float_tex || !have_arrays || !have_fbo || !have_1d_tex) {
|
||||
for (int n = 0; n < 2; n++) {
|
||||
if (mp_find_filter_kernel(p->opts.scalers[n])) {
|
||||
p->opts.scalers[n] = "bilinear";
|
||||
char *reason = "scaler (FBO)";
|
||||
const struct filter_kernel *kernel = mp_find_filter_kernel(p->opts.scalers[n]);
|
||||
if (kernel) {
|
||||
char *reason = "";
|
||||
if (!have_fbo)
|
||||
reason = "scaler (FBO)";
|
||||
if (!have_float_tex)
|
||||
reason = "scaler (float tex.)";
|
||||
if (!have_arrays)
|
||||
reason = "scaler (no GLSL support)";
|
||||
disabled[n_disabled++] = reason;
|
||||
if (!have_1d_tex && kernel->polar)
|
||||
reason = "scaler (1D tex.)";
|
||||
if (*reason) {
|
||||
p->opts.scalers[n] = "bilinear";
|
||||
disabled[n_disabled++] = reason;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,8 +163,12 @@ uniform VIDEO_SAMPLER texture3;
|
|||
uniform vec2 textures_size[4];
|
||||
uniform vec2 chroma_center_offset;
|
||||
uniform vec2 chroma_div;
|
||||
uniform sampler2D lut_c;
|
||||
uniform sampler2D lut_l;
|
||||
uniform sampler2D lut_2d_c;
|
||||
uniform sampler2D lut_2d_l;
|
||||
#if HAVE_1DTEX
|
||||
uniform sampler1D lut_1d_c;
|
||||
uniform sampler1D lut_1d_l;
|
||||
#endif
|
||||
#if HAVE_3DTEX
|
||||
uniform sampler3D lut_3d;
|
||||
#endif
|
||||
|
@ -304,8 +308,7 @@ float[6] weights6(sampler2D lookup, float f) {
|
|||
float wsum = 0; \
|
||||
for (int y = 1-R; y <= R; y++) { \
|
||||
for (int x = 1-R; x <= R; x++) { \
|
||||
vec2 d = vec2(x,y) - fcoord; \
|
||||
float w = texture(LUT, vec2(0.5, length(d) / R)).r; \
|
||||
float w = texture1D(LUT, length(vec2(x,y) - fcoord)/R).r; \
|
||||
wsum += w; \
|
||||
res += w * texture(tex, base + pt * vec2(x, y)); \
|
||||
} \
|
||||
|
|
Loading…
Reference in New Issue