diff options
author | Misaki Kasumi <misakikasumi@outlook.com> | 2024-05-28 00:13:38 +0800 |
---|---|---|
committer | sfan5 <sfan5@live.de> | 2024-06-08 10:23:32 +0200 |
commit | c55ff4176c054edc7de1b08ef72dd88725e56f42 (patch) | |
tree | ca48fbb1601fe028d4c8a221d730046db0dffb09 | |
parent | cd74f8f7c5073448182c22e87f33a606396d0734 (diff) | |
download | mpv-c55ff4176c054edc7de1b08ef72dd88725e56f42.tar.bz2 mpv-c55ff4176c054edc7de1b08ef72dd88725e56f42.tar.xz |
opengl: add --egl-output-format
-rw-r--r-- | DOCS/interface-changes/egl-output-format.txt | 1 | ||||
-rw-r--r-- | DOCS/man/options.rst | 21 | ||||
-rw-r--r-- | options/options.c | 2 | ||||
-rw-r--r-- | video/out/opengl/egl_helpers.c | 74 |
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; |