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.c253
1 files changed, 158 insertions, 95 deletions
diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c
index a89ee4e73a..ff4c7a25aa 100644
--- a/video/out/opengl/video.c
+++ b/video/out/opengl/video.c
@@ -33,6 +33,8 @@
#include "misc/bstr.h"
#include "options/m_config.h"
+#include "common/global.h"
+#include "options/options.h"
#include "common.h"
#include "utils.h"
#include "hwdec.h"
@@ -47,9 +49,6 @@
#include "video/out/dither.h"
#include "video/out/vo.h"
-// Pixel width of 1D lookup textures.
-#define LOOKUP_TEXTURE_SIZE 256
-
// Maximal number of passes that prescaler can be applied.
#define MAX_PRESCALE_PASSES 5
@@ -164,12 +163,14 @@ struct gl_video {
struct mp_imgfmt_desc image_desc;
int plane_count;
- bool is_yuv, is_rgb, is_packed_yuv;
+ bool is_yuv, is_packed_yuv;
bool has_alpha;
char color_swizzle[5];
struct video_image image;
+ bool dumb_mode;
+
struct fbotex chroma_merge_fbo;
struct fbotex chroma_deband_fbo;
struct fbotex indirect_fbo;
@@ -223,6 +224,8 @@ struct gl_video {
struct gl_hwdec *hwdec;
bool hwdec_active;
+
+ bool dsi_warned;
};
struct fmt_entry {
@@ -332,15 +335,17 @@ const struct gl_video_opts gl_video_opts_def = {
.dither_depth = -1,
.dither_size = 6,
.temporal_dither_period = 1,
- .fbo_format = GL_RGBA16,
+ .fbo_format = 0,
.sigmoid_center = 0.75,
.sigmoid_slope = 6.5,
.scaler = {
{{"bilinear", .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // scale
{{NULL, .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // dscale
{{"bilinear", .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // cscale
- {{"oversample", .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // tscale
+ {{"mitchell", .params={NAN, NAN}}, {.params = {NAN, NAN}},
+ .clamp = 1, }, // tscale
},
+ .scaler_lut_size = 6,
.alpha_mode = 2,
.background = {0, 0, 0, 255},
.gamma = 1.0f,
@@ -352,7 +357,7 @@ const struct gl_video_opts gl_video_opts_hq_def = {
.dither_depth = 0,
.dither_size = 6,
.temporal_dither_period = 1,
- .fbo_format = GL_RGBA16,
+ .fbo_format = 0,
.correct_downscaling = 1,
.sigmoid_center = 0.75,
.sigmoid_slope = 6.5,
@@ -361,8 +366,10 @@ const struct gl_video_opts gl_video_opts_hq_def = {
{{"spline36", .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // scale
{{"mitchell", .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // dscale
{{"spline36", .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // cscale
- {{"oversample", .params={NAN, NAN}}, {.params = {NAN, NAN}}}, // tscale
+ {{"mitchell", .params={NAN, NAN}}, {.params = {NAN, NAN}},
+ .clamp = 1, }, // tscale
},
+ .scaler_lut_size = 6,
.alpha_mode = 2,
.background = {0, 0, 0, 255},
.gamma = 1.0f,
@@ -404,6 +411,7 @@ const struct m_sub_options gl_video_conf = {
SCALER_OPTS("dscale", 1),
SCALER_OPTS("cscale", 2),
SCALER_OPTS("tscale", 3),
+ OPT_INTRANGE("scaler-lut-size", scaler_lut_size, 0, 4, 10),
OPT_FLAG("scaler-resizes-only", scaler_resizes_only, 0),
OPT_FLAG("linear-scaling", linear_scaling, 0),
OPT_FLAG("correct-downscaling", correct_downscaling, 0),
@@ -414,6 +422,7 @@ const struct m_sub_options gl_video_conf = {
({"rgb", GL_RGB},
{"rgba", GL_RGBA},
{"rgb8", GL_RGB8},
+ {"rgba8", GL_RGBA8},
{"rgb10", GL_RGB10},
{"rgb10_a2", GL_RGB10_A2},
{"rgb16", GL_RGB16},
@@ -422,7 +431,8 @@ const struct m_sub_options gl_video_conf = {
{"rgba12", GL_RGBA12},
{"rgba16", GL_RGBA16},
{"rgba16f", GL_RGBA16F},
- {"rgba32f", GL_RGBA32F})),
+ {"rgba32f", GL_RGBA32F},
+ {"auto", 0})),
OPT_CHOICE_OR_INT("dither-depth", dither_depth, 0, -1, 16,
({"no", -1}, {"auto", 0})),
OPT_CHOICE("dither", dither_algo, 0,
@@ -449,8 +459,11 @@ const struct m_sub_options gl_video_conf = {
OPT_FLOAT("sharpen", unsharp, 0),
OPT_CHOICE("prescale", prescale, 0,
({"none", 0},
- {"superxbr", 1},
- {"nnedi3", 2})),
+ {"superxbr", 1}
+#if HAVE_NNEDI
+ , {"nnedi3", 2}
+#endif
+ )),
OPT_INTRANGE("prescale-passes",
prescale_passes, 0, 1, MAX_PRESCALE_PASSES),
OPT_FLOATRANGE("prescale-downscaling-threshold",
@@ -559,9 +572,8 @@ void gl_video_set_debug(struct gl_video *p, bool enable)
static void gl_video_reset_surfaces(struct gl_video *p)
{
- for (int i = 0; i < FBOSURFACES_MAX; i++) {
+ for (int i = 0; i < FBOSURFACES_MAX; i++)
p->surfaces[i].pts = MP_NOPTS_VALUE;
- }
p->surface_idx = 0;
p->surface_now = 0;
p->frames_drawn = 0;
@@ -642,8 +654,10 @@ void gl_video_set_lut3d(struct gl_video *p, struct lut3d *lut3d)
return;
}
- if (!(gl->mpgl_caps & MPGL_CAP_3D_TEX))
+ if (!(gl->mpgl_caps & MPGL_CAP_3D_TEX) || gl->es) {
+ MP_ERR(p, "16 bit fixed point 3D textures not available.\n");
return;
+ }
if (!p->lut_3d_texture)
gl->GenTextures(1, &p->lut_3d_texture);
@@ -1040,7 +1054,7 @@ static void reinit_scaler(struct gl_video *p, struct scaler *scaler,
scaler->insufficient = !mp_init_filter(scaler->kernel, sizes, scale_factor);
- if (scaler->kernel->polar) {
+ if (scaler->kernel->polar && (gl->mpgl_caps & MPGL_CAP_1D_TEX)) {
scaler->gl_target = GL_TEXTURE_1D;
} else {
scaler->gl_target = GL_TEXTURE_2D;
@@ -1067,14 +1081,16 @@ static void reinit_scaler(struct gl_video *p, struct scaler *scaler,
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);
+ scaler->lut_size = 1 << p->opts.scaler_lut_size;
+
+ float *weights = talloc_array(NULL, float, scaler->lut_size * size);
+ mp_compute_lut(scaler->kernel, scaler->lut_size, weights);
if (target == GL_TEXTURE_1D) {
- gl->TexImage1D(target, 0, fmt->internal_format, LOOKUP_TEXTURE_SIZE,
+ gl->TexImage1D(target, 0, fmt->internal_format, scaler->lut_size,
0, fmt->format, GL_FLOAT, weights);
} else {
- gl->TexImage2D(target, 0, fmt->internal_format, width, LOOKUP_TEXTURE_SIZE,
+ gl->TexImage2D(target, 0, fmt->internal_format, width, scaler->lut_size,
0, fmt->format, GL_FLOAT, weights);
}
@@ -1311,9 +1327,9 @@ static void pass_read_video(struct gl_video *p)
struct gl_transform chromafix;
pass_set_image_textures(p, &p->image, &chromafix);
- int in_bits = p->image_desc.component_bits,
- tx_bits = (in_bits + 7) & ~7;
- float tex_mul = ((1 << tx_bits) - 1.0) / ((1 << in_bits) - 1.0);
+ float tex_mul = 1 / mp_get_csp_mul(p->image_params.colorspace,
+ p->image_desc.component_bits,
+ p->image_desc.component_full_bits);
struct src_tex prescaled_tex;
struct gl_transform offset = {{{0}}};
@@ -1449,7 +1465,7 @@ static void pass_convert_yuv(struct gl_video *p)
struct mp_csp_params cparams = MP_CSP_PARAMS_DEFAULTS;
cparams.gray = p->is_yuv && !p->is_packed_yuv && p->plane_count == 1;
cparams.input_bits = p->image_desc.component_bits;
- cparams.texture_bits = (cparams.input_bits + 7) & ~7;
+ cparams.texture_bits = p->image_desc.component_full_bits;
mp_csp_set_image_params(&cparams, &p->image_params);
mp_csp_copy_equalizer_values(&cparams, &p->video_eq);
p->user_gamma = 1.0 / (cparams.gamma * p->opts.gamma);
@@ -1460,32 +1476,21 @@ static void pass_convert_yuv(struct gl_video *p)
GLSLF("color = color.%s;\n", p->color_swizzle);
// Pre-colormatrix input gamma correction
- if (p->image_desc.flags & MP_IMGFLAG_XYZ) {
- cparams.colorspace = MP_CSP_XYZ;
-
- // Pre-colormatrix input gamma correction. Note that this results in
- // linear light
- GLSL(color.rgb = pow(color.rgb, vec3(2.6));)
- }
+ if (cparams.colorspace == MP_CSP_XYZ)
+ GLSL(color.rgb = pow(color.rgb, vec3(2.6));) // linear light
- // Something already took care of expansion
+ // Something already took care of expansion - disable it.
if (p->use_normalized_range)
- cparams.input_bits = cparams.texture_bits;
-
- // Conversion from Y'CbCr or other linear spaces to RGB
- if (!p->is_rgb) {
- struct mp_cmat m = {{{0}}};
- if (p->image_desc.flags & MP_IMGFLAG_XYZ) {
- struct mp_csp_primaries csp = mp_get_csp_primaries(p->image_params.primaries);
- mp_get_xyz2rgb_coeffs(&cparams, csp, MP_INTENT_RELATIVE_COLORIMETRIC, &m);
- } else {
- mp_get_yuv2rgb_coeffs(&cparams, &m);
- }
- gl_sc_uniform_mat3(sc, "colormatrix", true, &m.m[0][0]);
- gl_sc_uniform_vec3(sc, "colormatrix_c", m.c);
+ cparams.input_bits = cparams.texture_bits = 0;
- GLSL(color.rgb = mat3(colormatrix) * color.rgb + colormatrix_c;)
- }
+ // Conversion to RGB. For RGB itself, this still applies e.g. brightness
+ // and contrast controls, or expansion of e.g. LSB-packed 10 bit data.
+ struct mp_cmat m = {{{0}}};
+ mp_get_csp_matrix(&cparams, &m);
+ gl_sc_uniform_mat3(sc, "colormatrix", true, &m.m[0][0]);
+ gl_sc_uniform_vec3(sc, "colormatrix_c", m.c);
+
+ GLSL(color.rgb = mat3(colormatrix) * color.rgb + colormatrix_c;)
if (p->image_params.colorspace == MP_CSP_BT_2020_C) {
// Conversion for C'rcY'cC'bc via the BT.2020 CL system:
@@ -1726,9 +1731,16 @@ static void pass_dither(struct gl_video *p)
p->last_dither_matrix_size = size;
}
+ const struct fmt_entry *fmt = find_tex_format(gl, 2, 1);
tex_size = size;
- tex_iformat = gl_float16_formats[0].internal_format;
- tex_format = gl_float16_formats[0].format;
+ // Prefer R16 texture since they provide higher precision.
+ if (fmt->internal_format) {
+ tex_iformat = fmt->internal_format;
+ tex_format = fmt->format;
+ } else {
+ tex_iformat = gl_float16_formats[0].internal_format;
+ tex_format = gl_float16_formats[0].format;
+ }
tex_type = GL_FLOAT;
tex_data = p->last_dither_matrix;
} else {
@@ -1771,7 +1783,7 @@ static void pass_dither(struct gl_video *p)
gl_sc_uniform_sampler(p->sc, "dither", GL_TEXTURE_2D, TEXUNIT_DITHER);
- GLSLF("vec2 dither_pos = gl_FragCoord.xy / %d;\n", p->dither_size);
+ GLSLF("vec2 dither_pos = gl_FragCoord.xy / %d.0;\n", p->dither_size);
if (p->opts.temporal_dither) {
int phase = (p->frames_rendered / p->opts.temporal_dither_period) % 8u;
@@ -1786,8 +1798,8 @@ static void pass_dither(struct gl_video *p)
}
GLSL(float dither_value = texture(dither, dither_pos).r;)
- GLSLF("color = floor(color * %d + dither_value + 0.5 / (%d * %d)) / %d;\n",
- dither_quantization, p->dither_size, p->dither_size,
+ GLSLF("color = floor(color * %d.0 + dither_value + 0.5 / %d.0) / %d.0;\n",
+ dither_quantization, p->dither_size * p->dither_size,
dither_quantization);
}
@@ -1878,7 +1890,7 @@ static void pass_render_frame(struct gl_video *p)
p->texture_h = p->image_params.h;
p->texture_offset = (struct gl_transform){{{1.0,0.0}, {0.0,1.0}}, {0.0,0.0}};
- if (p->opts.dumb_mode)
+ if (p->dumb_mode)
return;
p->use_linear = p->opts.linear_scaling || p->opts.sigmoid_upscaling;
@@ -1947,7 +1959,7 @@ static void pass_render_frame(struct gl_video *p)
static void pass_draw_to_screen(struct gl_video *p, int fbo)
{
- if (p->opts.dumb_mode)
+ if (p->dumb_mode)
pass_render_frame_dumb(p, fbo);
// Adjust the overall gamma before drawing to screen
@@ -2002,7 +2014,7 @@ static void gl_video_interpolate_frame(struct gl_video *p, struct vo_frame *t,
// Figure out the queue size. For illustration, a filter radius of 2 would
// look like this: _ A [B] C D _
- // A is surface_bse, B is surface_now, C is surface_nxt and D is
+ // A is surface_bse, B is surface_now, C is surface_now+1 and D is
// surface_end.
struct scaler *tscale = &p->scaler[3];
reinit_scaler(p, tscale, &p->opts.scaler[3], 1, tscale_sizes);
@@ -2019,7 +2031,6 @@ static void gl_video_interpolate_frame(struct gl_video *p, struct vo_frame *t,
int radius = size/2;
int surface_now = p->surface_now;
- int surface_nxt = fbosurface_wrap(surface_now + 1);
int surface_bse = fbosurface_wrap(surface_now - (radius-1));
int surface_end = fbosurface_wrap(surface_now + radius);
assert(fbosurface_wrap(surface_bse + size-1) == surface_end);
@@ -2040,7 +2051,6 @@ static void gl_video_interpolate_frame(struct gl_video *p, struct vo_frame *t,
continue;
if (f->pts > p->surfaces[p->surface_idx].pts) {
- MP_STATS(p, "new-pts");
gl_video_upload_image(p, f);
pass_render_frame(p);
finish_pass_fbo(p, &p->surfaces[surface_dst].fbotex,
@@ -2079,10 +2089,7 @@ static void gl_video_interpolate_frame(struct gl_video *p, struct vo_frame *t,
GLSL(vec4 color = texture(texture0, texcoord0);)
p->is_interpolated = false;
} else {
- double pts_now = p->surfaces[surface_now].pts,
- pts_nxt = p->surfaces[surface_nxt].pts;
-
- double mix = (t->vsync_offset / 1e6) / (pts_nxt - pts_now);
+ double mix = t->vsync_offset / t->ideal_frame_duration;
// The scaler code always wants the fcoord to be between 0 and 1,
// so we try to adjust by using the previous set of N frames instead
// (which requires some extra checking to make sure it's valid)
@@ -2101,7 +2108,7 @@ static void gl_video_interpolate_frame(struct gl_video *p, struct vo_frame *t,
// Blend the frames together
if (oversample) {
- double vsync_dist = t->vsync_interval / 1e6 / (pts_nxt - pts_now),
+ double vsync_dist = t->vsync_interval / t->ideal_frame_duration,
threshold = tscale->conf.kernel.params[0];
threshold = isnan(threshold) ? 0.0 : threshold;
mix = (1 - mix) / vsync_dist;
@@ -2123,9 +2130,8 @@ static void gl_video_interpolate_frame(struct gl_video *p, struct vo_frame *t,
vp_w, vp_h, i);
}
- MP_STATS(p, "frame-mix");
- MP_DBG(p, "inter frame pts: %lld, vsync: %lld, mix: %f\n",
- (long long)t->pts, (long long)t->vsync_interval, mix);
+ MP_DBG(p, "inter frame dur: %f vsync: %f, mix: %f\n",
+ t->ideal_frame_duration, t->vsync_interval, mix);
p->is_interpolated = true;
}
pass_draw_to_screen(p, fbo);
@@ -2154,37 +2160,47 @@ void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame, int fbo)
if (has_frame) {
gl_sc_set_vao(p->sc, &p->vao);
- if (p->opts.interpolation && (p->frames_drawn || !frame->still)) {
+ if (p->opts.interpolation && frame->display_synced &&
+ (p->frames_drawn || !frame->still))
+ {
gl_video_interpolate_frame(p, frame, fbo);
} else {
- // For the non-interplation case, we draw to a single "cache"
- // FBO to speed up subsequent re-draws (if any exist)
- int vp_w = p->dst_rect.x1 - p->dst_rect.x0,
- vp_h = p->dst_rect.y1 - p->dst_rect.y0;
-
bool is_new = !frame->redraw && !frame->repeat;
if (is_new || !p->output_fbo_valid) {
+ p->output_fbo_valid = false;
+
gl_video_upload_image(p, frame->current);
pass_render_frame(p);
- if (frame->num_vsyncs == 1 || !frame->display_synced ||
- p->opts.dumb_mode)
+ // For the non-interplation case, we draw to a single "cache"
+ // FBO to speed up subsequent re-draws (if any exist)
+ int dest_fbo = fbo;
+ if (frame->num_vsyncs > 1 && frame->display_synced &&
+ !p->dumb_mode && gl->BlitFramebuffer)
{
- // Disable output_fbo_valid to signal that this frame
- // does not require any redraws from the FBO.
- pass_draw_to_screen(p, fbo);
- p->output_fbo_valid = false;
- } else {
- finish_pass_fbo(p, &p->output_fbo, vp_w, vp_h, 0, FBOTEX_FUZZY);
+ fbotex_change(&p->output_fbo, p->gl, p->log,
+ p->vp_w, abs(p->vp_h),
+ p->opts.fbo_format, 0);
+ dest_fbo = p->output_fbo.fbo;
p->output_fbo_valid = true;
}
+ pass_draw_to_screen(p, dest_fbo);
}
// "output fbo valid" and "output fbo needed" are equivalent
if (p->output_fbo_valid) {
- pass_load_fbotex(p, &p->output_fbo, vp_w, vp_h, 0);
- GLSL(vec4 color = texture(texture0, texcoord0);)
- pass_draw_to_screen(p, fbo);
+ gl->BindFramebuffer(GL_READ_FRAMEBUFFER, p->output_fbo.fbo);
+ gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
+ struct mp_rect rc = p->dst_rect;
+ if (p->vp_h < 0) {
+ rc.y1 = -p->vp_h - p->dst_rect.y0;
+ rc.y0 = -p->vp_h - p->dst_rect.y1;
+ }
+ gl->BlitFramebuffer(rc.x0, rc.y0, rc.x1, rc.y1,
+ rc.x0, rc.y0, rc.x1, rc.y1,
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ gl->BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+ gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
}
}
@@ -2340,26 +2356,62 @@ static bool test_fbo(struct gl_video *p)
return success;
}
+// Return whether dumb-mode can be used without disabling any features.
+// Essentially, vo_opengl with mostly default settings will return true.
+static bool check_dumb_mode(struct gl_video *p)
+{
+ struct gl_video_opts *o = &p->opts;
+ if (o->dumb_mode)
+ return true;
+ if (o->target_prim || o->target_trc || o->linear_scaling ||
+ o->correct_downscaling || o->sigmoid_upscaling || o->interpolation ||
+ o->blend_subs || o->deband || o->unsharp || o->prescale)
+ return false;
+ // check scale, dscale, cscale (tscale is already implicitly excluded above)
+ for (int i = 0; i < 3; i++) {
+ const char *name = o->scaler[i].kernel.name;
+ if (name && strcmp(name, "bilinear") != 0)
+ return false;
+ }
+ if (o->pre_shaders && o->pre_shaders[0])
+ return false;
+ if (o->post_shaders && o->post_shaders[0])
+ return false;
+ if (p->use_lut_3d)
+ return false;
+ return true;
+}
+
// Disable features that are not supported with the current OpenGL version.
static void check_gl_features(struct gl_video *p)
{
GL *gl = p->gl;
bool have_float_tex = gl->mpgl_caps & MPGL_CAP_FLOAT_TEX;
bool have_fbo = gl->mpgl_caps & MPGL_CAP_FB;
- 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;
+ bool have_texrg = gl->mpgl_caps & MPGL_CAP_TEX_RG;
+
+ if (have_fbo) {
+ if (!p->opts.fbo_format)
+ p->opts.fbo_format = gl->es ? GL_RGB10_A2 : GL_RGBA16;
+ have_fbo = test_fbo(p);
+ }
if (gl->es && p->opts.pbo) {
p->opts.pbo = 0;
MP_WARN(p, "Disabling PBOs (GLES unsupported).\n");
}
- if (p->opts.dumb_mode || gl->es || !have_fbo || !test_fbo(p)) {
- if (!p->opts.dumb_mode) {
+ bool voluntarily_dumb = check_dumb_mode(p);
+ if (p->opts.dumb_mode || !have_fbo || !have_texrg || voluntarily_dumb) {
+ if (voluntarily_dumb) {
+ MP_VERBOSE(p, "No advanced processing required. Enabling dumb mode.\n");
+ } else if (!p->opts.dumb_mode) {
MP_WARN(p, "High bit depth FBOs unsupported. Enabling dumb mode.\n"
"Most extended features will be disabled.\n");
}
+ p->dumb_mode = true;
p->use_lut_3d = false;
// Most things don't work, so whitelist all options that still work.
struct gl_video_opts new_opts = {
@@ -2371,12 +2423,18 @@ static void check_gl_features(struct gl_video *p)
.use_rectangle = p->opts.use_rectangle,
.background = p->opts.background,
.dither_algo = -1,
- .dumb_mode = 1,
+ .scaler = {
+ gl_video_opts_def.scaler[0],
+ gl_video_opts_def.scaler[1],
+ gl_video_opts_def.scaler[2],
+ gl_video_opts_def.scaler[3],
+ },
};
assign_options(&p->opts, &new_opts);
p->opts.deband_opts = m_config_alloc_struct(NULL, &deband_conf);
return;
}
+ p->dumb_mode = false;
// Normally, we want to disable them by default if FBOs are unavailable,
// because they will be slow (not critically slow, but still slower).
@@ -2389,8 +2447,6 @@ static void check_gl_features(struct gl_video *p)
char *reason = NULL;
if (!have_float_tex)
reason = "(float tex. missing)";
- if (!have_1d_tex && kernel->polar)
- reason = "(1D tex. missing)";
if (reason) {
p->opts.scaler[n].kernel.name = "bilinear";
MP_WARN(p, "Disabling scaler #%d %s.\n", n, reason);
@@ -2428,14 +2484,18 @@ static void check_gl_features(struct gl_video *p)
if (p->opts.prescale == 2) {
if (p->opts.nnedi3_opts->upload == NNEDI3_UPLOAD_UBO) {
// Check features for uniform buffer objects.
- if (!p->gl->BindBufferBase || !p->gl->GetUniformBlockIndex) {
- MP_WARN(p, "Disabling NNEDI3 (OpenGL 3.1 required).\n");
+ if (!gl->BindBufferBase || !gl->GetUniformBlockIndex) {
+ MP_WARN(p, "Disabling NNEDI3 (%s required).\n",
+ gl->es ? "OpenGL ES 3.0" : "OpenGL 3.1");
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");
+ if ((!gl->es && gl->glsl_version < 330) ||
+ (gl->es && gl->glsl_version < 300))
+ {
+ MP_WARN(p, "Disabling NNEDI3 (%s required).\n",
+ gl->es ? "OpenGL ES 3.0" : "OpenGL 3.3");
p->opts.prescale = 0;
}
}
@@ -2583,8 +2643,6 @@ static bool init_format(int fmt, struct gl_video *init)
// YUV/half-packed
if (fmt == IMGFMT_NV12 || fmt == IMGFMT_NV21) {
- if (!(init->gl->mpgl_caps & MPGL_CAP_TEX_RG))
- return false;
plane_format[0] = find_tex_format(gl, 1, 1);
plane_format[1] = find_tex_format(gl, 1, 2);
if (fmt == IMGFMT_NV21)
@@ -2659,7 +2717,6 @@ supported:
}
init->is_yuv = desc.flags & MP_IMGFLAG_YUV;
- init->is_rgb = desc.flags & MP_IMGFLAG_RGB;
init->plane_count = desc.num_planes;
init->image_desc = desc;
@@ -2799,6 +2856,12 @@ void gl_video_set_options(struct gl_video *p, struct gl_video_opts *opts)
check_gl_features(p);
uninit_rendering(p);
+
+ if (p->opts.interpolation && !p->global->opts->video_sync && !p->dsi_warned) {
+ MP_WARN(p, "Interpolation now requires enabling display-sync mode.\n"
+ "E.g.: --video-sync=display-resample\n");
+ p->dsi_warned = true;
+ }
}
void gl_video_configure_queue(struct gl_video *p, struct vo *vo)
@@ -2820,7 +2883,7 @@ void gl_video_configure_queue(struct gl_video *p, struct vo *vo)
}
}
- vo_set_queue_params(vo, 0, p->opts.interpolation, queue_size);
+ vo_set_queue_params(vo, 0, queue_size);
}
struct mp_csp_equalizer *gl_video_eq_ptr(struct gl_video *p)