renderer/native: Force EGL config pixel format

We just arbitrarily chose the first EGL config matching the passed
attributes, but we then assumed we always got GBM_FORMAT_XRGB8888. That
was not a correct assumption. Instead, make sure we always pick the
format we expect.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/2
This commit is contained in:
Jonas Ådahl 2018-02-23 22:14:07 +08:00
parent 7a41483ea0
commit 712ec30cd9
6 changed files with 196 additions and 14 deletions

View File

@ -90,6 +90,11 @@ typedef struct _CoglWinsysEGLVtable
(* add_config_attributes) (CoglDisplay *display, (* add_config_attributes) (CoglDisplay *display,
CoglFramebufferConfig *config, CoglFramebufferConfig *config,
EGLint *attributes); EGLint *attributes);
CoglBool
(* choose_config) (CoglDisplay *display,
EGLint *attributes,
EGLConfig *out_config,
CoglError **error);
} CoglWinsysEGLVtable; } CoglWinsysEGLVtable;
typedef enum _CoglEGLWinsysFeature typedef enum _CoglEGLWinsysFeature

View File

@ -336,6 +336,32 @@ _cogl_winsys_egl_add_config_attributes (CoglDisplay *display,
return i; return i;
} }
static CoglBool
_cogl_winsys_egl_choose_config (CoglDisplay *display,
EGLint *attributes,
EGLConfig *out_config,
CoglError **error)
{
CoglRenderer *renderer = display->renderer;
CoglRendererEGL *egl_renderer = renderer->winsys;
EGLint config_count = 0;
EGLBoolean status;
status = eglChooseConfig (egl_renderer->edpy,
attributes,
out_config, 1,
&config_count);
if (status != EGL_TRUE || config_count == 0)
{
_cogl_set_error (error, COGL_WINSYS_ERROR,
COGL_WINSYS_ERROR_CREATE_CONTEXT,
"No compatible EGL configs found");
return FALSE;
}
return TRUE;
}
static CoglBool static CoglBool
_cogl_winsys_egl_display_setup (CoglDisplay *display, _cogl_winsys_egl_display_setup (CoglDisplay *display,
CoglError **error) CoglError **error)
@ -841,6 +867,7 @@ static const CoglWinsysEGLVtable
_cogl_winsys_egl_vtable = _cogl_winsys_egl_vtable =
{ {
.add_config_attributes = _cogl_winsys_egl_add_config_attributes, .add_config_attributes = _cogl_winsys_egl_add_config_attributes,
.choose_config = _cogl_winsys_egl_choose_config,
.display_setup = _cogl_winsys_egl_display_setup, .display_setup = _cogl_winsys_egl_display_setup,
.display_destroy = _cogl_winsys_egl_display_destroy, .display_destroy = _cogl_winsys_egl_display_destroy,
.context_created = _cogl_winsys_egl_context_created, .context_created = _cogl_winsys_egl_context_created,

View File

@ -338,10 +338,9 @@ try_create_context (CoglDisplay *display,
CoglRendererEGL *egl_renderer = renderer->winsys; CoglRendererEGL *egl_renderer = renderer->winsys;
EGLDisplay edpy; EGLDisplay edpy;
EGLConfig config; EGLConfig config;
EGLint config_count = 0;
EGLBoolean status;
EGLint attribs[9]; EGLint attribs[9];
EGLint cfg_attribs[MAX_EGL_CONFIG_ATTRIBS]; EGLint cfg_attribs[MAX_EGL_CONFIG_ATTRIBS];
GError *config_error = NULL;
const char *error_message; const char *error_message;
_COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context == NULL, TRUE); _COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context == NULL, TRUE);
@ -356,14 +355,16 @@ try_create_context (CoglDisplay *display,
edpy = egl_renderer->edpy; edpy = egl_renderer->edpy;
status = eglChooseConfig (edpy, if (!egl_renderer->platform_vtable->choose_config (display,
cfg_attribs, cfg_attribs,
&config, 1, &config,
&config_count); &config_error))
if (status != EGL_TRUE || config_count == 0)
{ {
error_message = "Unable to find a usable EGL configuration"; _cogl_set_error (error, COGL_WINSYS_ERROR,
goto fail; COGL_WINSYS_ERROR_CREATE_CONTEXT,
"Couldn't choose config: %s", config_error->message);
g_error_free (config_error);
goto err;
} }
egl_display->egl_config = config; egl_display->egl_config = config;
@ -419,6 +420,7 @@ fail:
COGL_WINSYS_ERROR_CREATE_CONTEXT, COGL_WINSYS_ERROR_CREATE_CONTEXT,
"%s", error_message); "%s", error_message);
err:
cleanup_context (display); cleanup_context (display);
return FALSE; return FALSE;

View File

@ -265,6 +265,72 @@ meta_egl_get_proc_address (MetaEgl *egl,
return func; return func;
} }
gboolean
meta_egl_get_config_attrib (MetaEgl *egl,
EGLDisplay display,
EGLConfig config,
EGLint attribute,
EGLint *value,
GError **error)
{
if (!eglGetConfigAttrib (display,
config,
attribute,
value))
{
set_egl_error (error);
return FALSE;
}
return TRUE;
}
EGLConfig *
meta_egl_choose_all_configs (MetaEgl *egl,
EGLDisplay display,
const EGLint *attrib_list,
EGLint *out_num_configs,
GError **error)
{
EGLint num_configs;
EGLConfig *configs;
EGLint num_matches;
if (!eglGetConfigs (display, NULL, 0, &num_configs))
{
set_egl_error (error);
return FALSE;
}
if (num_configs < 1)
{
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_FAILED,
"No EGL configurations available");
return FALSE;
}
configs = g_new0 (EGLConfig, num_configs);
if (!eglChooseConfig (display, attrib_list, configs, num_configs, &num_matches))
{
g_free (configs);
set_egl_error (error);
return FALSE;
}
if (num_matches == 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"No matching EGL configs");
g_free (configs);
return NULL;
}
*out_num_configs = num_configs;
return configs;
}
gboolean gboolean
meta_egl_choose_first_config (MetaEgl *egl, meta_egl_choose_first_config (MetaEgl *egl,
EGLDisplay display, EGLDisplay display,

View File

@ -62,6 +62,19 @@ gboolean meta_egl_choose_first_config (MetaEgl *egl,
EGLConfig *chosen_config, EGLConfig *chosen_config,
GError **error); GError **error);
gboolean meta_egl_get_config_attrib (MetaEgl *egl,
EGLDisplay display,
EGLConfig config,
EGLint attribute,
EGLint *value,
GError **error);
EGLConfig * meta_egl_choose_all_configs (MetaEgl *egl,
EGLDisplay display,
const EGLint *attrib_list,
EGLint *out_num_configs,
GError **error);
EGLContext meta_egl_create_context (MetaEgl *egl, EGLContext meta_egl_create_context (MetaEgl *egl,
EGLDisplay display, EGLDisplay display,
EGLConfig config, EGLConfig config,

View File

@ -934,6 +934,73 @@ meta_renderer_native_add_egl_config_attributes (CoglDisplay *cogl_disp
return i; return i;
} }
static gboolean
choose_egl_config_from_gbm_format (MetaEgl *egl,
EGLDisplay egl_display,
const EGLint *attributes,
uint32_t gbm_format,
EGLConfig *out_config,
GError **error)
{
EGLConfig *egl_configs;
EGLint n_configs;
EGLint i;
egl_configs = meta_egl_choose_all_configs (egl, egl_display,
attributes,
&n_configs,
error);
if (!egl_configs)
return FALSE;
for (i = 0; i < n_configs; i++)
{
EGLint visual_id;
if (!meta_egl_get_config_attrib (egl, egl_display,
egl_configs[i],
EGL_NATIVE_VISUAL_ID,
&visual_id,
error))
{
g_free (egl_configs);
return FALSE;
}
if ((uint32_t) visual_id == gbm_format)
{
*out_config = egl_configs[i];
g_free (egl_configs);
return TRUE;
}
}
g_free (egl_configs);
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"No EGL config matching supported GBM format found");
return FALSE;
}
static gboolean
meta_renderer_native_choose_egl_config (CoglDisplay *cogl_display,
EGLint *attributes,
EGLConfig *out_config,
GError **error)
{
CoglRenderer *cogl_renderer = cogl_display->renderer;
CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
MetaBackend *backend = meta_get_backend ();
MetaEgl *egl = meta_backend_get_egl (backend);
EGLDisplay egl_display = cogl_renderer_egl->edpy;
return choose_egl_config_from_gbm_format (egl,
egl_display,
attributes,
GBM_FORMAT_XRGB8888,
out_config,
error);
}
static gboolean static gboolean
meta_renderer_native_setup_egl_display (CoglDisplay *cogl_display, meta_renderer_native_setup_egl_display (CoglDisplay *cogl_display,
GError **error) GError **error)
@ -2408,6 +2475,7 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
static const CoglWinsysEGLVtable static const CoglWinsysEGLVtable
_cogl_winsys_egl_vtable = { _cogl_winsys_egl_vtable = {
.add_config_attributes = meta_renderer_native_add_egl_config_attributes, .add_config_attributes = meta_renderer_native_add_egl_config_attributes,
.choose_config = meta_renderer_native_choose_egl_config,
.display_setup = meta_renderer_native_setup_egl_display, .display_setup = meta_renderer_native_setup_egl_display,
.display_destroy = meta_renderer_native_destroy_egl_display, .display_destroy = meta_renderer_native_destroy_egl_display,
.context_created = meta_renderer_native_egl_context_created, .context_created = meta_renderer_native_egl_context_created,
@ -2846,9 +2914,10 @@ create_secondary_egl_config (MetaEgl *egl,
EGL_NONE EGL_NONE
}; };
return meta_egl_choose_first_config (egl, return choose_egl_config_from_gbm_format (egl,
egl_display, egl_display,
attributes, attributes,
GBM_FORMAT_XRGB8888,
egl_config, egl_config,
error); error);
} }