summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-12-17 21:48:23 +0100
committerwm4 <wm4@nowhere>2014-12-17 21:48:23 +0100
commit10befa26d952ac2c403da1adcb3d36c300af0567 (patch)
tree4560871956886679f1a0292cde3a50571f433280 /video
parent07975877be410ed07d3110dc2a5350246360acd0 (diff)
downloadmpv-10befa26d952ac2c403da1adcb3d36c300af0567.tar.bz2
mpv-10befa26d952ac2c403da1adcb3d36c300af0567.tar.xz
vo_opengl: GLES 3 support
Tested with MESA on software emulation. Seems to work well, although the default FBO format in opengl-hq disables most interesting features. I have no idea how well it will work on real hardware (or if it does at all). Unfortunately, some features, including playback of 10 bit video, are not supported. Not sure what to do about this. GLES 2 or 1 do not work.
Diffstat (limited to 'video')
-rw-r--r--video/out/gl_common.c43
-rw-r--r--video/out/gl_common.h2
-rw-r--r--video/out/gl_osd.c10
-rw-r--r--video/out/gl_video.c39
-rw-r--r--video/out/gl_video_shaders.glsl4
-rw-r--r--video/out/gl_x11egl.c37
6 files changed, 111 insertions, 24 deletions
diff --git a/video/out/gl_common.c b/video/out/gl_common.c
index d9df1aa7ee..2af96cab5a 100644
--- a/video/out/gl_common.c
+++ b/video/out/gl_common.c
@@ -495,9 +495,20 @@ void mpgl_load_functions2(GL *gl, void *(*get_fn)(void *ctx, const char *n),
int major = 0, minor = 0;
const char *version = gl->GetString(GL_VERSION);
+ if (strncmp(version, "OpenGL ES ", 10) == 0) {
+ version += 10;
+ gl->es = true;
+ }
sscanf(version, "%d.%d", &major, &minor);
gl->version = MPGL_VER(major, minor);
- mp_verbose(log, "Detected OpenGL %d.%d.\n", major, minor);
+ mp_verbose(log, "Detected OpenGL %d.%d (%s).\n", major, minor,
+ gl->es ? "GLES" : "desktop");
+
+ if (gl->es && gl->version < MPGL_VER(3, 0)) {
+ mp_warn(log, "At least GLESv3 required.\n");
+ gl->version = 0;
+ return;
+ }
mp_verbose(log, "GL_VENDOR='%s'\n", gl->GetString(GL_VENDOR));
mp_verbose(log, "GL_RENDERER='%s'\n", gl->GetString(GL_RENDERER));
@@ -607,16 +618,21 @@ void mpgl_load_functions2(GL *gl, void *(*get_fn)(void *ctx, const char *n),
}
gl->glsl_version = 0;
- if (gl->version >= MPGL_VER(2, 0))
- gl->glsl_version = 110;
- if (gl->version >= MPGL_VER(2, 1))
- gl->glsl_version = 120;
- if (gl->version >= MPGL_VER(3, 0))
- gl->glsl_version = 130;
- // Specifically needed for OSX (normally we request 3.0 contexts only, but
- // OSX always creates 3.2 contexts when requesting a core context).
- if (gl->version >= MPGL_VER(3, 2))
- gl->glsl_version = 150;
+ if (gl->es) {
+ if (gl->version >= MPGL_VER(3, 0))
+ gl->glsl_version = 300;
+ } else {
+ if (gl->version >= MPGL_VER(2, 0))
+ gl->glsl_version = 110;
+ if (gl->version >= MPGL_VER(2, 1))
+ gl->glsl_version = 120;
+ if (gl->version >= MPGL_VER(3, 0))
+ gl->glsl_version = 130;
+ // Specifically needed for OSX (normally we request 3.0 contexts only, but
+ // OSX always creates 3.2 contexts when requesting a core context).
+ if (gl->version >= MPGL_VER(3, 2))
+ gl->glsl_version = 150;
+ }
if (!is_software_gl(gl))
gl->mpgl_caps |= MPGL_CAP_NO_SW;
@@ -678,14 +694,18 @@ int glFmt2bpp(GLenum format, GLenum type)
return 2;
case GL_RGB:
case GL_BGR:
+ case GL_RGB_INTEGER:
return 3 * component_size;
case GL_RGBA:
case GL_BGRA:
+ case GL_RGBA_INTEGER:
return 4 * component_size;
case GL_RED:
+ case GL_RED_INTEGER:
return component_size;
case GL_RG:
case GL_LUMINANCE_ALPHA:
+ case GL_RG_INTEGER:
return 2 * component_size;
}
abort(); // unknown
@@ -817,6 +837,7 @@ static const struct backend backends[] = {
#endif
#if HAVE_EGL_X11
{"x11egl", mpgl_set_backend_x11egl},
+ {"x11egles", mpgl_set_backend_x11egles},
#endif
{0}
};
diff --git a/video/out/gl_common.h b/video/out/gl_common.h
index 3f86d74036..7ec06fc248 100644
--- a/video/out/gl_common.h
+++ b/video/out/gl_common.h
@@ -156,6 +156,7 @@ void mpgl_set_backend_cocoa(MPGLContext *ctx);
void mpgl_set_backend_w32(MPGLContext *ctx);
void mpgl_set_backend_x11(MPGLContext *ctx);
void mpgl_set_backend_x11egl(MPGLContext *ctx);
+void mpgl_set_backend_x11egles(MPGLContext *ctx);
void mpgl_set_backend_wayland(MPGLContext *ctx);
void mpgl_load_functions(GL *gl, void *(*getProcAddress)(const GLubyte *),
@@ -169,6 +170,7 @@ void mp_log_source(struct mp_log *log, int lev, const char *src);
//function pointers loaded from the OpenGL library
struct GL {
+ bool es; // false: desktop GL, true: GLES
int version; // MPGL_VER() mangled
int glsl_version; // e.g. 130 for GLSL 1.30
char *extensions; // Equivalent to GL_EXTENSIONS
diff --git a/video/out/gl_osd.c b/video/out/gl_osd.c
index 6b97ef77cf..2276dc9f71 100644
--- a/video/out/gl_osd.c
+++ b/video/out/gl_osd.c
@@ -42,6 +42,11 @@ static const struct osd_fmt_entry osd_to_gl3_formats[SUBBITMAP_COUNT] = {
[SUBBITMAP_RGBA] = {GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE},
};
+static const struct osd_fmt_entry osd_to_gles3_formats[SUBBITMAP_COUNT] = {
+ [SUBBITMAP_LIBASS] = {GL_R8, GL_RED, GL_UNSIGNED_BYTE},
+ [SUBBITMAP_RGBA] = {GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE},
+};
+
static const struct osd_fmt_entry osd_to_gl_legacy_formats[SUBBITMAP_COUNT] = {
[SUBBITMAP_LIBASS] = {GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE},
[SUBBITMAP_RGBA] = {GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE},
@@ -61,8 +66,11 @@ 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))
+ if (gl->es) {
+ ctx->fmt_table = osd_to_gles3_formats;
+ } else 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);
diff --git a/video/out/gl_video.c b/video/out/gl_video.c
index b139fed07c..e7c2c46450 100644
--- a/video/out/gl_video.c
+++ b/video/out/gl_video.c
@@ -231,6 +231,19 @@ 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_gles3[] = {
+ {0, GL_R8, GL_RED, GL_UNSIGNED_BYTE}, // 1 x 8
+ {0, GL_RG8, GL_RG, GL_UNSIGNED_BYTE}, // 2 x 8
+ {0, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE}, // 3 x 8
+ {0, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE}, // 4 x 8
+ // There are no filterable texture formats that can be uploaded as
+ // GL_UNSIGNED_SHORT, so apparently we're out of luck.
+ {0, 0, 0, 0}, // 1 x 16
+ {0, 0, 0, 0}, // 2 x 16
+ {0, 0, 0, 0}, // 3 x 16
+ {0, 0, 0, 0}, // 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,
@@ -389,8 +402,12 @@ static const struct fmt_entry *find_tex_format(GL *gl, int bytes_per_comp,
{
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;
+ const struct fmt_entry *fmts = gl_byte_formats;
+ if (gl->es) {
+ fmts = gl_byte_formats_gles3;
+ } else if (!(gl->mpgl_caps & MPGL_CAP_TEX_RG)) {
+ fmts = gl_byte_formats_legacy;
+ }
return &fmts[n_channels - 1 + (bytes_per_comp - 1) * 4];
}
@@ -905,6 +922,8 @@ static void compile_shaders(struct gl_video *p)
{
GL *gl = p->gl;
+ debug_check_gl(p, "before shaders");
+
delete_shaders(p);
void *tmp = talloc_new(NULL);
@@ -916,10 +935,11 @@ static void compile_shaders(struct gl_video *p)
int rg = !!(gl->mpgl_caps & MPGL_CAP_TEX_RG);
char *header =
- talloc_asprintf(tmp, "#version %d\n"
+ talloc_asprintf(tmp, "#version %d%s\n"
"#define HAVE_RG %d\n"
"%s%s",
- gl->glsl_version, rg, shader_prelude, PRELUDE_END);
+ gl->glsl_version, gl->es ? " es" : "",
+ rg, shader_prelude, PRELUDE_END);
bool use_cms = p->opts.srgb || p->use_lut_3d;
@@ -2086,6 +2106,12 @@ static void check_gl_features(struct gl_video *p)
}
}
+ // GLES doesn't provide filtered 16 bit integer textures
+ if (p->use_lut_3d && gl->es) {
+ p->use_lut_3d = false;
+ disabled[n_disabled++] = "color management (GLES unsupported)";
+ }
+
int use_cms = p->opts.srgb || p->use_lut_3d;
// srgb_compand() not available
@@ -2338,6 +2364,11 @@ supported:
return false;
for (int p = 0; p < desc.num_planes; p++) {
+ if (!plane_format[p]->format)
+ return false;
+ }
+
+ for (int p = 0; p < desc.num_planes; p++) {
struct texplane *plane = &init->image.planes[p];
const struct fmt_entry *format = plane_format[p];
assert(format);
diff --git a/video/out/gl_video_shaders.glsl b/video/out/gl_video_shaders.glsl
index 6c588073ac..7f77be0421 100644
--- a/video/out/gl_video_shaders.glsl
+++ b/video/out/gl_video_shaders.glsl
@@ -27,6 +27,10 @@
// inserted at the beginning of all shaders
#!section prelude
+#ifdef GL_ES
+precision mediump float;
+#endif
+
// GLSL 1.20 compatibility layer
// texture() should be assumed to always map to texture2D()
#if __VERSION__ >= 130
diff --git a/video/out/gl_x11egl.c b/video/out/gl_x11egl.c
index 9732774994..8f2a5e4ffa 100644
--- a/video/out/gl_x11egl.c
+++ b/video/out/gl_x11egl.c
@@ -34,7 +34,7 @@ struct priv {
EGLSurface egl_surface;
};
-static EGLConfig select_fb_config_egl(struct MPGLContext *ctx)
+static EGLConfig select_fb_config_egl(struct MPGLContext *ctx, bool es)
{
struct priv *p = ctx->priv;
@@ -44,7 +44,7 @@ static EGLConfig select_fb_config_egl(struct MPGLContext *ctx)
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_DEPTH_SIZE, 0,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
+ EGL_RENDERABLE_TYPE, es ? EGL_OPENGL_ES_BIT : EGL_OPENGL_BIT,
EGL_NONE
};
@@ -62,13 +62,13 @@ static EGLConfig select_fb_config_egl(struct MPGLContext *ctx)
}
static bool create_context_egl(MPGLContext *ctx, EGLConfig config,
- EGLNativeWindowType window)
+ EGLNativeWindowType window, bool es)
{
struct priv *p = ctx->priv;
EGLint context_attributes[] = {
EGL_CONTEXT_MAJOR_VERSION_KHR,
- MPGL_VER_GET_MAJOR(ctx->requested_gl_version),
+ es ? 3 : MPGL_VER_GET_MAJOR(ctx->requested_gl_version),
EGL_NONE
};
@@ -93,7 +93,7 @@ static bool create_context_egl(MPGLContext *ctx, EGLConfig config,
return true;
}
-static bool config_window_x11_egl(struct MPGLContext *ctx, int flags)
+static bool config_window_x11_egl_(struct MPGLContext *ctx, int flags, bool es)
{
struct priv *p = ctx->priv;
struct vo *vo = ctx->vo;
@@ -103,12 +103,12 @@ static bool config_window_x11_egl(struct MPGLContext *ctx, int flags)
return true;
}
- eglBindAPI(EGL_OPENGL_API);
+ eglBindAPI(es ? EGL_OPENGL_ES_API : EGL_OPENGL_API);
p->egl_display = eglGetDisplay(vo->x11->display);
eglInitialize(p->egl_display, NULL, NULL);
- EGLConfig config = select_fb_config_egl(ctx);
+ EGLConfig config = select_fb_config_egl(ctx, es);
if (!config)
return false;
@@ -126,7 +126,7 @@ static bool config_window_x11_egl(struct MPGLContext *ctx, int flags)
XFree(vi);
- if (!create_context_egl(ctx, config, (EGLNativeWindowType)vo->x11->window))
+ if (!create_context_egl(ctx, config, (EGLNativeWindowType)vo->x11->window, es))
{
vo_x11_uninit(ctx->vo);
return false;
@@ -138,6 +138,16 @@ static bool config_window_x11_egl(struct MPGLContext *ctx, int flags)
return true;
}
+static bool config_window_x11_egl(struct MPGLContext *ctx, int flags)
+{
+ return config_window_x11_egl_(ctx, flags, false);
+}
+
+static bool config_window_x11_egles(struct MPGLContext *ctx, int flags)
+{
+ return config_window_x11_egl_(ctx, flags, true);
+}
+
static void releaseGlContext_egl(MPGLContext *ctx)
{
struct priv *p = ctx->priv;
@@ -165,3 +175,14 @@ void mpgl_set_backend_x11egl(MPGLContext *ctx)
ctx->vo_uninit = vo_x11_uninit;
ctx->vo_control = vo_x11_control;
}
+
+void mpgl_set_backend_x11egles(MPGLContext *ctx)
+{
+ ctx->priv = talloc_zero(ctx, struct priv);
+ ctx->config_window = config_window_x11_egles;
+ ctx->releaseGlContext = releaseGlContext_egl;
+ ctx->swapGlBuffers = swapGlBuffers_egl;
+ ctx->vo_init = vo_x11_init;
+ ctx->vo_uninit = vo_x11_uninit;
+ ctx->vo_control = vo_x11_control;
+}