mirror of https://github.com/mpv-player/mpv
vo_opengl: remove requirement for RG textures
Features not supported are disabled (although with a misleading error message).
This commit is contained in:
parent
446e759f64
commit
0e8fbdbdb1
|
@ -61,6 +61,9 @@ struct mpgl_osd *mpgl_osd_init(GL *gl, struct mp_log *log, struct osd_state *osd
|
|||
.scratch = talloc_zero_size(ctx, 1),
|
||||
};
|
||||
|
||||
if (!(gl->mpgl_caps & MPGL_CAP_TEX_RG))
|
||||
ctx->fmt_table = osd_to_gl_legacy_formats;
|
||||
|
||||
for (int n = 0; n < MAX_OSD_PARTS; n++) {
|
||||
struct mpgl_osd_part *p = talloc_ptrtype(ctx, p);
|
||||
*p = (struct mpgl_osd_part) {
|
||||
|
|
|
@ -231,6 +231,21 @@ static const struct fmt_entry gl_byte_formats[] = {
|
|||
{0, GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT}, // 4 x 16
|
||||
};
|
||||
|
||||
static const struct fmt_entry gl_byte_formats_legacy[] = {
|
||||
{0, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE}, // 1 x 8
|
||||
{0, GL_LUMINANCE_ALPHA,
|
||||
GL_LUMINANCE_ALPHA,
|
||||
GL_UNSIGNED_BYTE}, // 2 x 8
|
||||
{0, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE}, // 3 x 8
|
||||
{0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE}, // 4 x 8
|
||||
{0, GL_ALPHA16, GL_ALPHA, GL_UNSIGNED_SHORT}, // 1 x 16
|
||||
{0, GL_LUMINANCE16_ALPHA16,
|
||||
GL_LUMINANCE_ALPHA,
|
||||
GL_UNSIGNED_SHORT}, // 2 x 16
|
||||
{0, GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT}, // 3 x 16
|
||||
{0, GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT}, // 4 x 16
|
||||
};
|
||||
|
||||
static const struct fmt_entry gl_float16_formats[] = {
|
||||
{0, GL_R16F, GL_RED, GL_FLOAT}, // 1 x f
|
||||
{0, GL_RG16F, GL_RG, GL_FLOAT}, // 2 x f
|
||||
|
@ -369,6 +384,15 @@ static void delete_shaders(struct gl_video *p);
|
|||
static void check_gl_features(struct gl_video *p);
|
||||
static bool init_format(int fmt, struct gl_video *init);
|
||||
|
||||
static const struct fmt_entry *find_tex_format(GL *gl, int bytes_per_comp,
|
||||
int n_channels)
|
||||
{
|
||||
assert(bytes_per_comp == 1 || bytes_per_comp == 2);
|
||||
assert(n_channels >= 1 && n_channels <= 4);
|
||||
const struct fmt_entry *fmts = (gl->mpgl_caps & MPGL_CAP_TEX_RG)
|
||||
? gl_byte_formats : gl_byte_formats_legacy;
|
||||
return &fmts[n_channels - 1 + (bytes_per_comp - 1) * 4];
|
||||
}
|
||||
|
||||
static void default_tex_params(struct GL *gl, GLenum target, GLint filter)
|
||||
{
|
||||
|
@ -887,8 +911,12 @@ static void compile_shaders(struct gl_video *p)
|
|||
char *shader_prelude = get_section(tmp, src, "prelude");
|
||||
char *s_video = get_section(tmp, src, "frag_video");
|
||||
|
||||
char *header = talloc_asprintf(tmp, "#version %d\n%s%s", gl->glsl_version,
|
||||
shader_prelude, PRELUDE_END);
|
||||
int rg = !!(gl->mpgl_caps & MPGL_CAP_TEX_RG);
|
||||
char *header =
|
||||
talloc_asprintf(tmp, "#version %d\n"
|
||||
"#define HAVE_RG %d\n"
|
||||
"%s%s",
|
||||
gl->glsl_version, rg, shader_prelude, PRELUDE_END);
|
||||
|
||||
bool use_cms = p->opts.srgb || p->use_lut_3d;
|
||||
|
||||
|
@ -1233,6 +1261,7 @@ static void init_dither(struct gl_video *p)
|
|||
GLint tex_iformat;
|
||||
GLenum tex_type;
|
||||
unsigned char temp[256];
|
||||
GLint tex_format = find_tex_format(gl, 1, 1)->format;
|
||||
|
||||
if (p->opts.dither_algo == 0) {
|
||||
int sizeb = p->opts.dither_size;
|
||||
|
@ -1246,7 +1275,7 @@ static void init_dither(struct gl_video *p)
|
|||
}
|
||||
|
||||
tex_size = size;
|
||||
tex_iformat = GL_R16;
|
||||
tex_iformat = find_tex_format(gl, 2, 1)->internal_format;
|
||||
tex_type = GL_FLOAT;
|
||||
tex_data = p->last_dither_matrix;
|
||||
} else {
|
||||
|
@ -1254,7 +1283,7 @@ static void init_dither(struct gl_video *p)
|
|||
mp_make_ordered_dither_matrix(temp, 8);
|
||||
|
||||
tex_size = 8;
|
||||
tex_iformat = GL_RED;
|
||||
tex_iformat = tex_format;
|
||||
tex_type = GL_UNSIGNED_BYTE;
|
||||
tex_data = temp;
|
||||
}
|
||||
|
@ -1272,8 +1301,8 @@ static void init_dither(struct gl_video *p)
|
|||
gl->BindTexture(GL_TEXTURE_2D, p->dither_texture);
|
||||
gl->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
gl->PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
gl->TexImage2D(GL_TEXTURE_2D, 0, tex_iformat, tex_size, tex_size, 0, GL_RED,
|
||||
tex_type, tex_data);
|
||||
gl->TexImage2D(GL_TEXTURE_2D, 0, tex_iformat, tex_size, tex_size, 0,
|
||||
tex_format, tex_type, tex_data);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
|
@ -2022,9 +2051,10 @@ static bool test_fbo(struct gl_video *p, GLenum format)
|
|||
for (int i = 0; i < 4; i++) {
|
||||
float pixel = -1;
|
||||
float val = vals[i];
|
||||
gl->ClearColor(val, 0.0f, 0.0f, 1.0f);
|
||||
gl->ClearColor(val, val, val, val);
|
||||
gl->Clear(GL_COLOR_BUFFER_BIT);
|
||||
gl->ReadPixels(0, 0, 1, 1, GL_RED, GL_FLOAT, &pixel);
|
||||
GLint one_byte = find_tex_format(gl, 1, 1)->format;
|
||||
gl->ReadPixels(0, 0, 1, 1, one_byte, GL_FLOAT, &pixel);
|
||||
MP_VERBOSE(p, " %s: %a\n", val_names[i], val - pixel);
|
||||
}
|
||||
gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
@ -2044,6 +2074,7 @@ static void check_gl_features(struct gl_video *p)
|
|||
bool have_float_tex = gl->mpgl_caps & MPGL_CAP_FLOAT_TEX;
|
||||
bool have_fbo = gl->mpgl_caps & MPGL_CAP_FB;
|
||||
bool have_srgb = gl->mpgl_caps & MPGL_CAP_SRGB_TEX;
|
||||
bool have_rg = gl->mpgl_caps & MPGL_CAP_TEX_RG;
|
||||
bool have_mix = gl->glsl_version >= 130;
|
||||
|
||||
char *disabled[10];
|
||||
|
@ -2068,7 +2099,8 @@ static void check_gl_features(struct gl_video *p)
|
|||
// Normally, we want to disable them by default if FBOs are unavailable,
|
||||
// because they will be slow (not critically slow, but still slower).
|
||||
// Without FP textures, we must always disable them.
|
||||
if (!have_float_tex || (!have_fbo && p->opts.scale_sep)) {
|
||||
// I don't know if luminance alpha float textures exist, so disregard them.
|
||||
if (!have_float_tex || !have_rg || (!have_fbo && p->opts.scale_sep)) {
|
||||
for (int n = 0; n < 2; n++) {
|
||||
if (mp_find_filter_kernel(p->opts.scalers[n])) {
|
||||
p->opts.scalers[n] = "bilinear";
|
||||
|
@ -2110,8 +2142,7 @@ static void check_gl_features(struct gl_video *p)
|
|||
}
|
||||
|
||||
if (n_disabled) {
|
||||
MP_ERR(p, "Some OpenGL extensions not detected, "
|
||||
"disabling: ");
|
||||
MP_ERR(p, "Some OpenGL extensions not detected, disabling: ");
|
||||
for (int n = 0; n < n_disabled; n++) {
|
||||
if (n)
|
||||
MP_ERR(p, ", ");
|
||||
|
@ -2208,22 +2239,26 @@ void gl_video_unset_gl_state(struct gl_video *p)
|
|||
}
|
||||
|
||||
// dest = src.<w> (always using 4 components)
|
||||
static void packed_fmt_swizzle(char w[5], const struct packed_fmt_entry *fmt)
|
||||
static void packed_fmt_swizzle(char w[5], const struct fmt_entry *texfmt,
|
||||
const struct packed_fmt_entry *fmt)
|
||||
{
|
||||
for (int c = 0; c < 4; c++)
|
||||
w[c] = "rgba"[MPMAX(fmt->components[c] - 1, 0)];
|
||||
w[4] = '\0';
|
||||
}
|
||||
const char *comp = "rgba";
|
||||
|
||||
static const struct fmt_entry *find_tex_format(int bytes_per_comp, int n_channels)
|
||||
{
|
||||
assert(bytes_per_comp == 1 || bytes_per_comp == 2);
|
||||
assert(n_channels >= 1 && n_channels <= 4);
|
||||
return &gl_byte_formats[n_channels - 1 + (bytes_per_comp - 1) * 4];
|
||||
// Normally, we work with GL_RED and GL_RG
|
||||
if (texfmt && texfmt->internal_format == GL_LUMINANCE_ALPHA)
|
||||
comp = "ragb";
|
||||
if (texfmt && texfmt->internal_format == GL_ALPHA)
|
||||
comp = "argb";
|
||||
|
||||
for (int c = 0; c < 4; c++)
|
||||
w[c] = comp[MPMAX(fmt->components[c] - 1, 0)];
|
||||
w[4] = '\0';
|
||||
}
|
||||
|
||||
static bool init_format(int fmt, struct gl_video *init)
|
||||
{
|
||||
struct GL *gl = init->gl;
|
||||
|
||||
init->hwdec_active = false;
|
||||
if (init->hwdec && init->hwdec->driver->imgfmt == fmt) {
|
||||
fmt = init->hwdec->converted_imgfmt;
|
||||
|
@ -2250,17 +2285,21 @@ static bool init_format(int fmt, struct gl_video *init)
|
|||
if ((desc.flags & MP_IMGFLAG_NE) && bits >= 8 && bits <= 16) {
|
||||
init->plane_bits = bits;
|
||||
init->has_alpha = desc.num_planes > 3;
|
||||
plane_format[0] = find_tex_format((bits + 7) / 8, 1);
|
||||
plane_format[0] = find_tex_format(gl, (bits + 7) / 8, 1);
|
||||
for (int p = 1; p < desc.num_planes; p++)
|
||||
plane_format[p] = plane_format[0];
|
||||
if (!(init->gl->mpgl_caps & MPGL_CAP_TEX_RG) && desc.num_planes < 2)
|
||||
snprintf(init->color_swizzle, sizeof(init->color_swizzle), "argb");
|
||||
goto supported;
|
||||
}
|
||||
}
|
||||
|
||||
// YUV/half-packed
|
||||
if (fmt == IMGFMT_NV12 || fmt == IMGFMT_NV21) {
|
||||
plane_format[0] = find_tex_format(1, 1);
|
||||
plane_format[1] = find_tex_format(1, 2);
|
||||
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)
|
||||
snprintf(init->color_swizzle, sizeof(init->color_swizzle), "rbga");
|
||||
goto supported;
|
||||
|
@ -2269,7 +2308,7 @@ static bool init_format(int fmt, struct gl_video *init)
|
|||
// RGB/planar
|
||||
if (fmt == IMGFMT_GBRP) {
|
||||
snprintf(init->color_swizzle, sizeof(init->color_swizzle), "brga");
|
||||
plane_format[0] = find_tex_format(1, 1);
|
||||
plane_format[0] = find_tex_format(gl, 1, 1);
|
||||
for (int p = 1; p < desc.num_planes; p++)
|
||||
plane_format[p] = plane_format[0];
|
||||
goto supported;
|
||||
|
@ -2277,7 +2316,7 @@ static bool init_format(int fmt, struct gl_video *init)
|
|||
|
||||
// XYZ (same organization as RGB packed, but requires conversion matrix)
|
||||
if (fmt == IMGFMT_XYZ12) {
|
||||
plane_format[0] = find_tex_format(2, 3);
|
||||
plane_format[0] = find_tex_format(gl, 2, 3);
|
||||
goto supported;
|
||||
}
|
||||
|
||||
|
@ -2293,8 +2332,8 @@ static bool init_format(int fmt, struct gl_video *init)
|
|||
for (const struct packed_fmt_entry *e = mp_packed_formats; e->fmt; e++) {
|
||||
if (e->fmt == fmt) {
|
||||
int n_comp = desc.bytes[0] / e->component_size;
|
||||
plane_format[0] = find_tex_format(e->component_size, n_comp);
|
||||
packed_fmt_swizzle(init->color_swizzle, e);
|
||||
plane_format[0] = find_tex_format(gl, e->component_size, n_comp);
|
||||
packed_fmt_swizzle(init->color_swizzle, plane_format[0], e);
|
||||
init->has_alpha = e->components[3] != 0;
|
||||
goto supported;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,14 @@
|
|||
# define in varying
|
||||
#endif
|
||||
|
||||
#if HAVE_RG
|
||||
#define R r
|
||||
#define RG rg
|
||||
#else
|
||||
#define R a
|
||||
#define RG ra
|
||||
#endif
|
||||
|
||||
// Earlier GLSL doesn't support mix() with bvec
|
||||
#if __VERSION__ >= 130
|
||||
vec3 srgb_expand(vec3 v)
|
||||
|
@ -133,7 +141,7 @@ in vec4 color;
|
|||
DECLARE_FRAGPARMS
|
||||
|
||||
void main() {
|
||||
out_color = vec4(color.rgb, color.a * texture(texture0, texcoord).r);
|
||||
out_color = vec4(color.rgb, color.a * texture(texture0, texcoord).R);
|
||||
}
|
||||
|
||||
#!section frag_osd_rgba
|
||||
|
@ -205,8 +213,8 @@ vec4 sample_bicubic_fast(VIDEO_SAMPLER tex, vec2 texsize, vec2 texcoord, float p
|
|||
vec4 parmx = calcweights(fcoord.x);
|
||||
vec4 parmy = calcweights(fcoord.y);
|
||||
vec4 cdelta;
|
||||
cdelta.xz = parmx.rg * vec2(-pt.x, pt.x);
|
||||
cdelta.yw = parmy.rg * vec2(-pt.y, pt.y);
|
||||
cdelta.xz = parmx.RG * vec2(-pt.x, pt.x);
|
||||
cdelta.yw = parmy.RG * vec2(-pt.y, pt.y);
|
||||
// first y-interpolation
|
||||
vec4 ar = texture(tex, texcoord + cdelta.xy);
|
||||
vec4 ag = texture(tex, texcoord + cdelta.xw);
|
||||
|
@ -220,7 +228,7 @@ vec4 sample_bicubic_fast(VIDEO_SAMPLER tex, vec2 texsize, vec2 texcoord, float p
|
|||
}
|
||||
|
||||
float[2] weights2(sampler2D lookup, float f) {
|
||||
vec4 c = texture(lookup, vec2(0.5, f));
|
||||
vec2 c = texture(lookup, vec2(0.5, f)).RG;
|
||||
return float[2](c.r, c.g);
|
||||
}
|
||||
|
||||
|
@ -326,22 +334,22 @@ void main() {
|
|||
#define USE_CONV 0
|
||||
#endif
|
||||
#if USE_CONV == CONV_PLANAR
|
||||
vec4 acolor = vec4(SAMPLE_L(texture0, textures_size[0], texcoord).r,
|
||||
SAMPLE_C(texture1, textures_size[1], chr_texcoord).r,
|
||||
SAMPLE_C(texture2, textures_size[2], chr_texcoord).r,
|
||||
vec4 acolor = vec4(SAMPLE_L(texture0, textures_size[0], texcoord).R,
|
||||
SAMPLE_C(texture1, textures_size[1], chr_texcoord).R,
|
||||
SAMPLE_C(texture2, textures_size[2], chr_texcoord).R,
|
||||
1.0);
|
||||
#elif USE_CONV == CONV_NV12
|
||||
vec4 acolor = vec4(SAMPLE_L(texture0, textures_size[0], texcoord).r,
|
||||
SAMPLE_C(texture1, textures_size[1], chr_texcoord).rg,
|
||||
vec4 acolor = vec4(SAMPLE_L(texture0, textures_size[0], texcoord).R,
|
||||
SAMPLE_C(texture1, textures_size[1], chr_texcoord).RG,
|
||||
1.0);
|
||||
#else
|
||||
vec4 acolor = SAMPLE_L(texture0, textures_size[0], texcoord);
|
||||
#endif
|
||||
#ifdef USE_ALPHA_PLANE
|
||||
acolor.a = SAMPLE_L(texture3, textures_size[3], texcoord).r;
|
||||
#endif
|
||||
#ifdef USE_COLOR_SWIZZLE
|
||||
acolor = acolor. USE_COLOR_SWIZZLE ;
|
||||
#endif
|
||||
#ifdef USE_ALPHA_PLANE
|
||||
acolor.a = SAMPLE_L(texture3, textures_size[3], texcoord).R;
|
||||
#endif
|
||||
vec3 color = acolor.rgb;
|
||||
float alpha = acolor.a;
|
||||
|
@ -452,7 +460,7 @@ void main() {
|
|||
#ifdef USE_TEMPORAL_DITHER
|
||||
dither_pos = dither_trafo * dither_pos;
|
||||
#endif
|
||||
float dither_value = texture(dither, dither_pos).r;
|
||||
float dither_value = texture(dither, dither_pos).R;
|
||||
color = floor(color * dither_quantization + dither_value + dither_center) /
|
||||
dither_quantization;
|
||||
#endif
|
||||
|
|
|
@ -410,7 +410,7 @@ static int preinit(struct vo *vo)
|
|||
if (p->use_gl_debug)
|
||||
vo_flags |= VOFLAG_GL_DEBUG;
|
||||
|
||||
int mpgl_caps = MPGL_CAP_GL21 | MPGL_CAP_TEX_RG;
|
||||
int mpgl_caps = MPGL_CAP_GL21;
|
||||
if (!p->allow_sw)
|
||||
mpgl_caps |= MPGL_CAP_NO_SW;
|
||||
|
||||
|
|
|
@ -135,7 +135,7 @@ int mpv_opengl_cb_init_gl(struct mpv_opengl_cb_context *ctx, const char *exts,
|
|||
|
||||
mpgl_load_functions2(ctx->gl, get_proc_address, get_proc_address_ctx,
|
||||
exts, ctx->log);
|
||||
int caps = MPGL_CAP_GL21 | MPGL_CAP_TEX_RG;
|
||||
int caps = MPGL_CAP_GL21;
|
||||
if ((ctx->gl->mpgl_caps & caps) != caps) {
|
||||
MP_FATAL(ctx, "Missing OpenGL features.\n");
|
||||
return MPV_ERROR_UNSUPPORTED;
|
||||
|
|
Loading…
Reference in New Issue