summaryrefslogtreecommitdiffstats
path: root/video/out/opengl/video.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/opengl/video.c')
-rw-r--r--video/out/opengl/video.c58
1 files changed, 57 insertions, 1 deletions
diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c
index b69330d1a9..cd638ccd5e 100644
--- a/video/out/opengl/video.c
+++ b/video/out/opengl/video.c
@@ -39,6 +39,7 @@
#include "osd.h"
#include "stream/stream.h"
#include "superxbr.h"
+#include "nnedi3.h"
#include "video_shaders.h"
#include "video/out/filter_kernels.h"
#include "video/out/aspect.h"
@@ -156,6 +157,8 @@ struct gl_video {
GLuint dither_texture;
int dither_size;
+ GLuint nnedi3_weights_buffer;
+
struct mp_image_params real_image_params; // configured format
struct mp_image_params image_params; // texture format (mind hwdec case)
struct mp_imgfmt_desc image_desc;
@@ -444,12 +447,16 @@ const struct m_sub_options gl_video_conf = {
OPT_FLAG("deband", deband, 0),
OPT_SUBSTRUCT("deband", deband_opts, deband_conf, 0),
OPT_FLOAT("sharpen", unsharp, 0),
- OPT_CHOICE("prescale", prescale, 0, ({"none", 0}, {"superxbr", 1})),
+ OPT_CHOICE("prescale", prescale, 0,
+ ({"none", 0},
+ {"superxbr", 1},
+ {"nnedi3", 2})),
OPT_INTRANGE("prescale-passes",
prescale_passes, 0, 1, MAX_PRESCALE_PASSES),
OPT_FLOATRANGE("prescale-downscaling-threshold",
prescale_downscaling_threshold, 0, 0.0, 32.0),
OPT_SUBSTRUCT("superxbr", superxbr_opts, superxbr_conf, 0),
+ OPT_SUBSTRUCT("nnedi3", nnedi3_opts, nnedi3_conf, 0),
OPT_REMOVED("approx-gamma", "this is always enabled now"),
OPT_REMOVED("cscale-down", "chroma is never downscaled"),
@@ -597,6 +604,8 @@ static void uninit_rendering(struct gl_video *p)
gl->DeleteTextures(1, &p->dither_texture);
p->dither_texture = 0;
+ gl->DeleteBuffers(1, &p->nnedi3_weights_buffer);
+
fbotex_uninit(&p->chroma_merge_fbo);
fbotex_uninit(&p->chroma_deband_fbo);
fbotex_uninit(&p->indirect_fbo);
@@ -1202,6 +1211,10 @@ static void pass_prescale(struct gl_video *p, int src_tex_num, int dst_tex_num,
pass_superxbr(p->sc, planes, tex_num, step,
p->opts.superxbr_opts, &transform);
break;
+ case 2:
+ pass_nnedi3(p->sc, planes, tex_num, step,
+ p->opts.nnedi3_opts, &transform);
+ break;
default:
abort();
}
@@ -1230,6 +1243,27 @@ static bool pass_prescale_luma(struct gl_video *p, float tex_mul,
struct src_tex *prescaled_tex,
int *prescaled_planes)
{
+ if (p->opts.prescale == 2 &&
+ p->opts.nnedi3_opts->upload == NNEDI3_UPLOAD_UBO)
+ {
+ // nnedi3 are configured to use uniform buffer objects.
+ if (!p->nnedi3_weights_buffer) {
+ p->gl->GenBuffers(1, &p->nnedi3_weights_buffer);
+ p->gl->BindBufferBase(GL_UNIFORM_BUFFER, 0,
+ p->nnedi3_weights_buffer);
+ int weights_size;
+ const float *weights =
+ get_nnedi3_weights(p->opts.nnedi3_opts, &weights_size);
+
+ MP_VERBOSE(p, "Uploading NNEDI3 weights via uniform buffer (size=%d)\n",
+ weights_size);
+
+ // We don't know the endianness of GPU, just assume it's little
+ // endian.
+ p->gl->BufferData(GL_UNIFORM_BUFFER, weights_size, weights,
+ GL_STATIC_DRAW);
+ }
+ }
// number of passes to apply prescaler, can be zero.
int prescale_passes = get_prescale_passes(p);
@@ -2384,6 +2418,22 @@ static void check_gl_features(struct gl_video *p)
p->opts.deband = 0;
MP_WARN(p, "Disabling debanding (GLSL version too old).\n");
}
+
+ if (p->opts.prescale == 2) {
+ if (p->opts.nnedi3_opts->upload == NNEDI3_UPLOAD_UBO) {
+ // Check features for uniform buffer objects.
+ if (!p->gl->GetUniformBlockIndex || !p->gl->UniformBlockBinding) {
+ MP_WARN(p, "Disabling NNEDI3 (OpenGL 3.1 required).\n");
+ p->opts.prescale = 0;
+ }
+ } else if (p->opts.nnedi3_opts->upload == NNEDI3_UPLOAD_SHADER) {
+ // Check features for hard coding approach.
+ if (p->gl->glsl_version < 330) {
+ MP_WARN(p, "Disabling NNEDI3 (OpenGL 3.3 required).\n");
+ p->opts.prescale = 0;
+ }
+ }
+ }
}
static void init_gl(struct gl_video *p)
@@ -2708,6 +2758,7 @@ static void assign_options(struct gl_video_opts *dst, struct gl_video_opts *src)
talloc_free(dst->post_shaders);
talloc_free(dst->deband_opts);
talloc_free(dst->superxbr_opts);
+ talloc_free(dst->nnedi3_opts);
*dst = *src;
@@ -2719,6 +2770,11 @@ static void assign_options(struct gl_video_opts *dst, struct gl_video_opts *src)
src->superxbr_opts);
}
+ if (src->nnedi3_opts) {
+ dst->nnedi3_opts = m_sub_options_copy(NULL, &nnedi3_conf,
+ src->nnedi3_opts);
+ }
+
for (int n = 0; n < 4; n++) {
dst->scaler[n].kernel.name =
(char *)handle_scaler_opt(dst->scaler[n].kernel.name, n == 3);