gl-renderer: add function to query supported rendering formats

This goes through all formats available in the EGLConfig's that we
get from EGLDisplay and expose them in a struct weston_drm_format.

Currently backends choose a format for their outputs and hope that
GL-renderer is able to find a compatible EGLConfig. This should help
backends to avoid guessing.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
This commit is contained in:
Leandro Ribeiro 2024-09-30 18:34:21 -03:00
parent dd5e1f5047
commit c10857df5d
4 changed files with 104 additions and 0 deletions

View file

@ -280,6 +280,67 @@ out:
free(configs);
}
const struct pixel_format_info **
egl_set_supported_rendering_formats(EGLDisplay egldpy,
unsigned int *formats_count)
{
struct wl_array formats;
const struct pixel_format_info **f, *p;
EGLConfig *configs;
EGLint count = 0;
EGLint value;
EGLint i;
bool found;
wl_array_init(&formats);
if (!eglGetConfigs(egldpy, NULL, 0, &count) || count < 1)
return NULL;
configs = zalloc(count * sizeof(*configs));
if (!configs)
return NULL;
if (!eglGetConfigs(egldpy, configs, count, &count)) {
free(configs);
return NULL;
}
for (i = 0; i < count; i++) {
if (!eglGetConfigAttrib(egldpy, configs[i], EGL_SURFACE_TYPE, &value))
continue;
if (!(value & EGL_WINDOW_BIT))
continue;
if (!eglGetConfigAttrib(egldpy, configs[i], EGL_NATIVE_VISUAL_ID, &value))
continue;
if (value == 0)
continue;
p = pixel_format_get_info(value);
if (!p)
continue;
found = false;
wl_array_for_each(f, &formats) {
if (p == (*f)) {
found = true;
break;
}
}
if (found)
continue;
f = wl_array_add(&formats, sizeof(*f));
*f = p;
}
free(configs);
*formats_count = formats.size / sizeof(p);
return formats.data;
}
void
log_egl_config_info(struct gl_renderer *gr, EGLConfig eglconfig)
{

View file

@ -405,6 +405,9 @@ struct gl_renderer {
struct weston_drm_format_array supported_dmabuf_formats;
unsigned int supported_rendering_formats_count;
const struct pixel_format_info **supported_rendering_formats;
uint64_t egl_client_extensions;
uint64_t egl_device_extensions;
uint64_t egl_display_extensions;
@ -682,6 +685,10 @@ gl_renderer_log_extensions(struct gl_renderer *gr,
void
log_egl_config_info(struct gl_renderer *gr, EGLConfig eglconfig);
const struct pixel_format_info **
egl_set_supported_rendering_formats(EGLDisplay egldpy,
unsigned int *formats_count);
EGLConfig
gl_renderer_get_egl_config(struct gl_renderer *gr,
EGLint egl_surface_type,

View file

@ -4321,6 +4321,16 @@ gl_renderer_output_window_create(struct weston_output *output,
return ret;
}
static const struct pixel_format_info **
gl_renderer_get_supported_rendering_formats(struct weston_compositor *ec,
unsigned int *formats_count)
{
struct gl_renderer *gr = get_renderer(ec);
*formats_count = gr->supported_rendering_formats_count;
return gr->supported_rendering_formats;
}
static int
gl_renderer_output_fbo_create(struct weston_output *output,
const struct gl_renderer_fbo_options *options)
@ -4546,6 +4556,7 @@ gl_renderer_destroy(struct weston_compositor *ec)
dmabuf_format_destroy(format);
weston_drm_format_array_fini(&gr->supported_dmabuf_formats);
free(gr->supported_rendering_formats);
gl_renderer_allocator_destroy(gr->allocator);
@ -4688,6 +4699,14 @@ gl_renderer_display_create(struct weston_compositor *ec,
if (gr->allocator)
gr->base.dmabuf_alloc = gl_renderer_dmabuf_alloc;
if (gr->platform == EGL_PLATFORM_GBM_KHR) {
gr->supported_rendering_formats =
egl_set_supported_rendering_formats(gr->egl_display,
&gr->supported_rendering_formats_count);
if (!gr->supported_rendering_formats)
goto fail_terminate;
}
/* No need to check for GL_OES_EGL_image_external because this is gated
* by EGL_EXT_image_dma_buf_import_modifiers which depends on it. */
if (egl_display_has(gr, EXTENSION_EXT_IMAGE_DMA_BUF_IMPORT) &&
@ -4764,6 +4783,7 @@ fail_feedback:
ec->dmabuf_feedback_format_table = NULL;
}
fail_terminate:
free(gr->supported_rendering_formats);
weston_drm_format_array_fini(&gr->supported_dmabuf_formats);
eglTerminate(gr->egl_display);
fail:
@ -5078,6 +5098,7 @@ gl_renderer_setup(struct weston_compositor *ec)
WL_EXPORT struct gl_renderer_interface gl_renderer_interface = {
.display_create = gl_renderer_display_create,
.output_window_create = gl_renderer_output_window_create,
.get_supported_rendering_formats = gl_renderer_get_supported_rendering_formats,
.output_fbo_create = gl_renderer_output_fbo_create,
.output_destroy = gl_renderer_output_destroy,
.create_fence_fd = gl_renderer_create_fence_fd,

View file

@ -153,6 +153,21 @@ struct gl_renderer_interface {
int (*output_window_create)(struct weston_output *output,
const struct gl_renderer_output_options *options);
/**
* Query rendering formats supported by EGL on GBM platform
*
* \param ec The weston_compositor.
* \param formats_count The number of formats in the returned array.
* \return The array of formats supported, or NULL on failure.
*
* This function returns the formats that are present in the EGLConfig's
* that we query from the EGLDisplay. Such formats can be used for
* rendering.
*/
const struct pixel_format_info **
(*get_supported_rendering_formats)(struct weston_compositor *ec,
unsigned int *formats_count);
/**
* Attach GL-renderer to the output with a frame buffer object
*