opengl: add --egl-output-format

This commit is contained in:
Misaki Kasumi 2024-05-28 00:13:38 +08:00 committed by sfan5
parent cd74f8f7c5
commit c55ff4176c
4 changed files with 87 additions and 11 deletions

View File

@ -1 +1,2 @@
add `--egl-config-id` option add `--egl-config-id` option
add `--egl-output-format` option

View File

@ -5722,6 +5722,27 @@ them.
Rendering surfaces and contexts will be created using this EGLConfig. Rendering surfaces and contexts will be created using this EGLConfig.
You can use ``--msg-level=vo=trace`` to obtain a list of available configs. 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>`` ``--vulkan-device=<device name|UUID>``
The name or UUID of the Vulkan device to use for rendering and presentation. Use 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 ``--vulkan-device=help`` to see the list of available devices and their

View File

@ -905,7 +905,7 @@ static const m_option_t mp_opts[] = {
#endif #endif
#if HAVE_EGL || HAVE_EGL_ANDROID || HAVE_EGL_ANGLE_WIN32 #if HAVE_EGL || HAVE_EGL_ANDROID || HAVE_EGL_ANGLE_WIN32
{"", OPT_SUBSTRUCT(egl_opts, egl_conf)}, {"egl", OPT_SUBSTRUCT(egl_opts, egl_conf)},
#endif #endif
#if HAVE_VULKAN #if HAVE_VULKAN

View File

@ -54,6 +54,12 @@ typedef intptr_t EGLAttrib;
#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0 #define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0
#endif #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 { struct mp_egl_config_attr {
int attrib; int attrib;
const char *name; const char *name;
@ -103,12 +109,35 @@ static void *mpegl_get_proc_address(void *ctx, const char *name)
struct egl_opts { struct egl_opts {
int config_id; 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 #define OPT_BASE_STRUCT struct egl_opts
const struct m_sub_options egl_conf = { const struct m_sub_options egl_conf = {
.opts = (const struct m_option[]) { .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}, {0},
}, },
.size = sizeof(struct egl_opts), .size = sizeof(struct egl_opts),
@ -134,6 +163,8 @@ static bool create_context(struct ra_ctx *ctx, EGLDisplay display,
name = "GLES 2.x +"; name = "GLES 2.x +";
} }
const char *egl_exts = eglQueryString(display, EGL_EXTENSIONS);
MP_VERBOSE(ctx, "Trying to create %s context.\n", name); MP_VERBOSE(ctx, "Trying to create %s context.\n", name);
if (!eglBindAPI(api)) { if (!eglBindAPI(api)) {
@ -141,19 +172,31 @@ static bool create_context(struct ra_ctx *ctx, EGLDisplay display,
return false; 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[] = { EGLint attributes[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 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_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 EGL_NONE
}; };
if (opts->config_id) { if (opts->config_id) {
attributes[0] = EGL_CONFIG_ID; // Keep EGL_SURFACE_TYPE & EGL_RENDERABLE_TYPE
attributes[1] = opts->config_id; attributes[4] = EGL_CONFIG_ID;
attributes[2] = EGL_NONE; attributes[5] = opts->config_id;
attributes[6] = EGL_NONE;
} }
EGLint num_configs; 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]); dump_egl_config(ctx->log, MSGL_TRACE, display, configs[n]);
int chosen = 0; 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); chosen = cb.refine_config(cb.user_data, configs, num_configs);
if (chosen < 0) { }
if (chosen < 0 || chosen == num_configs) {
talloc_free(configs); talloc_free(configs);
MP_MSG(ctx, msgl, "Could not refine EGLConfig for %s!\n", name); MP_MSG(ctx, msgl, "Could not refine EGLConfig for %s!\n", name);
return false; return false;