From 0e8fbdbdb1ea212128ae6a193d198ed90f5ca4ac Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 16 Dec 2014 18:55:02 +0100 Subject: vo_opengl: remove requirement for RG textures Features not supported are disabled (although with a misleading error message). --- video/out/gl_osd.c | 3 ++ video/out/gl_video.c | 93 +++++++++++++++++++++++++++++------------ video/out/gl_video_shaders.glsl | 34 +++++++++------ video/out/vo_opengl.c | 2 +- video/out/vo_opengl_cb.c | 2 +- 5 files changed, 92 insertions(+), 42 deletions(-) diff --git a/video/out/gl_osd.c b/video/out/gl_osd.c index 67944186a1..6b97ef77cf 100644 --- a/video/out/gl_osd.c +++ b/video/out/gl_osd.c @@ -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) { diff --git a/video/out/gl_video.c b/video/out/gl_video.c index c74e387f01..f37c715356 100644 --- a/video/out/gl_video.c +++ b/video/out/gl_video.c @@ -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. (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) { + const char *comp = "rgba"; + + // 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] = "rgba"[MPMAX(fmt->components[c] - 1, 0)]; + w[c] = comp[MPMAX(fmt->components[c] - 1, 0)]; w[4] = '\0'; } -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]; -} - 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; } diff --git a/video/out/gl_video_shaders.glsl b/video/out/gl_video_shaders.glsl index 4c32f77c3a..eb24d6ab75 100644 --- a/video/out/gl_video_shaders.glsl +++ b/video/out/gl_video_shaders.glsl @@ -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 diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c index 0728223415..65f5d4c434 100644 --- a/video/out/vo_opengl.c +++ b/video/out/vo_opengl.c @@ -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; diff --git a/video/out/vo_opengl_cb.c b/video/out/vo_opengl_cb.c index 97c50ba489..a6731c6a51 100644 --- a/video/out/vo_opengl_cb.c +++ b/video/out/vo_opengl_cb.c @@ -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; -- cgit v1.2.3