summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMisaki Kasumi <misakikasumi@outlook.com>2024-05-28 00:13:38 +0800
committersfan5 <sfan5@live.de>2024-06-08 10:23:32 +0200
commitc55ff4176c054edc7de1b08ef72dd88725e56f42 (patch)
treeca48fbb1601fe028d4c8a221d730046db0dffb09
parentcd74f8f7c5073448182c22e87f33a606396d0734 (diff)
downloadmpv-c55ff4176c054edc7de1b08ef72dd88725e56f42.tar.bz2
mpv-c55ff4176c054edc7de1b08ef72dd88725e56f42.tar.xz
opengl: add --egl-output-format
-rw-r--r--DOCS/interface-changes/egl-output-format.txt1
-rw-r--r--DOCS/man/options.rst21
-rw-r--r--options/options.c2
-rw-r--r--video/out/opengl/egl_helpers.c74
4 files changed, 87 insertions, 11 deletions
diff --git a/DOCS/interface-changes/egl-output-format.txt b/DOCS/interface-changes/egl-output-format.txt
index 9cc5bd0ce5..00bb7fd84f 100644
--- a/DOCS/interface-changes/egl-output-format.txt
+++ b/DOCS/interface-changes/egl-output-format.txt
@@ -1 +1,2 @@
add `--egl-config-id` option
+add `--egl-output-format` option
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 47910ae8b9..d7a74daac0 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -5722,6 +5722,27 @@ them.
Rendering surfaces and contexts will be created using this EGLConfig.
You can use ``--msg-level=vo=trace`` to obtain a list of available configs.
+``--egl-output-format=<auto|rgb8|rgba8|rgb10|rgb10_a2|rgb16|rgba16|rgb16f|rgba16f|rgb32f|rgba32f>``
+ (EGL only)
+ Select a specific EGL output format to utilize for OpenGL rendering.
+ This option is mutually exclusive with ``--egl-config-id``.
+ "auto" is the default, which will pick the first usable config
+ based on the order given by the driver.
+
+ All formats are not available.
+ A fatal error is caused if an unavailable format is selected.
+
+ .. note::
+
+ There is no reliable API to query desktop bit depth in EGL.
+ You can manually set this option
+ according to the bit depth of your display.
+ This option also affects the auto-detection of ``--dither-depth``.
+
+ .. note::
+
+ Unlike ``--d3d11-output-format``, this option also takes effect with ``--vo=gpu-next``.
+
``--vulkan-device=<device name|UUID>``
The name or UUID of the Vulkan device to use for rendering and presentation. Use
``--vulkan-device=help`` to see the list of available devices and their
diff --git a/options/options.c b/options/options.c
index 175b5e0916..a0d00dde38 100644
--- a/options/options.c
+++ b/options/options.c
@@ -905,7 +905,7 @@ static const m_option_t mp_opts[] = {
#endif
#if HAVE_EGL || HAVE_EGL_ANDROID || HAVE_EGL_ANGLE_WIN32
- {"", OPT_SUBSTRUCT(egl_opts, egl_conf)},
+ {"egl", OPT_SUBSTRUCT(egl_opts, egl_conf)},
#endif
#if HAVE_VULKAN
diff --git a/video/out/opengl/egl_helpers.c b/video/out/opengl/egl_helpers.c
index 6320d700bc..91a6480eb2 100644
--- a/video/out/opengl/egl_helpers.c
+++ b/video/out/opengl/egl_helpers.c
@@ -54,6 +54,12 @@ typedef intptr_t EGLAttrib;
#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0
#endif
+#ifndef EGL_COLOR_COMPONENT_TYPE_EXT
+#define EGL_COLOR_COMPONENT_TYPE_EXT EGL_NONE
+#define EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT EGL_NONE
+#define EGL_COLOR_COMPONENT_TYPE_FIXED_EXT EGL_NONE
+#endif
+
struct mp_egl_config_attr {
int attrib;
const char *name;
@@ -103,12 +109,35 @@ static void *mpegl_get_proc_address(void *ctx, const char *name)
struct egl_opts {
int config_id;
+ int output_format;
};
+#define RGBA_FORMAT(r, g, b, a) ((r) << 18 | (g) << 12 | (b) << 6 | (a))
+#define FLOAT_FORMAT (1 << 24)
+static void unpack_format(int format, EGLint *r_size, EGLint *g_size, EGLint *b_size, EGLint *a_size, bool *is_float) {
+ *is_float = format & FLOAT_FORMAT;
+ *r_size = format >> 18 & 0x3f;
+ *g_size = (format >> 12) & 0x3f;
+ *b_size = (format >> 6) & 0x3f;
+ *a_size = format & 0x3f;
+}
+
#define OPT_BASE_STRUCT struct egl_opts
const struct m_sub_options egl_conf = {
.opts = (const struct m_option[]) {
- {"egl-config-id", OPT_INT(config_id)},
+ {"config-id", OPT_INT(config_id)},
+ {"output-format", OPT_CHOICE(output_format,
+ {"auto", 0},
+ {"rgb8", RGBA_FORMAT(8, 8, 8, 0)},
+ {"rgba8", RGBA_FORMAT(8, 8, 8, 8)},
+ {"rgb10", RGBA_FORMAT(10, 10, 10, 0)},
+ {"rgb10_a2", RGBA_FORMAT(10, 10, 10, 2)},
+ {"rgb16", RGBA_FORMAT(16, 16, 16, 0)},
+ {"rgba16", RGBA_FORMAT(16, 16, 16, 16)},
+ {"rgb16f", RGBA_FORMAT(16, 16, 16, 0) | FLOAT_FORMAT},
+ {"rgba16f", RGBA_FORMAT(16, 16, 16, 16) | FLOAT_FORMAT},
+ {"rgb32f", RGBA_FORMAT(32, 32, 32, 0) | FLOAT_FORMAT},
+ {"rgba32f", RGBA_FORMAT(32, 32, 32, 32) | FLOAT_FORMAT})},
{0},
},
.size = sizeof(struct egl_opts),
@@ -134,6 +163,8 @@ static bool create_context(struct ra_ctx *ctx, EGLDisplay display,
name = "GLES 2.x +";
}
+ const char *egl_exts = eglQueryString(display, EGL_EXTENSIONS);
+
MP_VERBOSE(ctx, "Trying to create %s context.\n", name);
if (!eglBindAPI(api)) {
@@ -141,19 +172,31 @@ static bool create_context(struct ra_ctx *ctx, EGLDisplay display,
return false;
}
+ bool request_float_fmt;
+ EGLint r_size, g_size, b_size, a_size;
+ unpack_format(opts->output_format, &r_size, &g_size, &b_size, &a_size, &request_float_fmt);
+ bool has_float_format_ext = gl_check_extension(egl_exts, "EGL_EXT_pixel_format_float");
+ if (request_float_fmt && !has_float_format_ext) {
+ MP_MSG(ctx, msgl, "Could not request floating point pixel format for %s!\n", name);
+ return false;
+ }
+
EGLint attributes[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, ctx->opts.want_alpha ? 8 : 0,
EGL_RENDERABLE_TYPE, rend,
+ EGL_RED_SIZE, MPMAX(r_size, 8),
+ EGL_GREEN_SIZE, MPMAX(g_size, 8),
+ EGL_BLUE_SIZE, MPMAX(b_size, 8),
+ EGL_ALPHA_SIZE, opts->output_format ? a_size : (ctx->opts.want_alpha ? 8 : 0),
+ opts->output_format && has_float_format_ext ? EGL_COLOR_COMPONENT_TYPE_EXT : EGL_NONE,
+ request_float_fmt ? EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT : EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
EGL_NONE
};
if (opts->config_id) {
- attributes[0] = EGL_CONFIG_ID;
- attributes[1] = opts->config_id;
- attributes[2] = EGL_NONE;
+ // Keep EGL_SURFACE_TYPE & EGL_RENDERABLE_TYPE
+ attributes[4] = EGL_CONFIG_ID;
+ attributes[5] = opts->config_id;
+ attributes[6] = EGL_NONE;
}
EGLint num_configs;
@@ -174,9 +217,20 @@ static bool create_context(struct ra_ctx *ctx, EGLDisplay display,
dump_egl_config(ctx->log, MSGL_TRACE, display, configs[n]);
int chosen = 0;
- if (cb.refine_config)
+ if (opts->output_format) {
+ for (; chosen < num_configs; chosen++) {
+ EGLint real_r_size, real_g_size, real_b_size, real_a_size;
+ eglGetConfigAttrib(display, configs[chosen], EGL_RED_SIZE, &real_r_size);
+ eglGetConfigAttrib(display, configs[chosen], EGL_GREEN_SIZE, &real_g_size);
+ eglGetConfigAttrib(display, configs[chosen], EGL_BLUE_SIZE, &real_b_size);
+ eglGetConfigAttrib(display, configs[chosen], EGL_ALPHA_SIZE, &real_a_size);
+ if (r_size == real_r_size && g_size == real_g_size && b_size == real_b_size && a_size == real_a_size)
+ break;
+ }
+ } else if (cb.refine_config) {
chosen = cb.refine_config(cb.user_data, configs, num_configs);
- if (chosen < 0) {
+ }
+ if (chosen < 0 || chosen == num_configs) {
talloc_free(configs);
MP_MSG(ctx, msgl, "Could not refine EGLConfig for %s!\n", name);
return false;