egl/wayland: Fail EGL surface creation if opaque format is unsupported
When using the EGL_EXT_present_opaque extension we create wayland buffers with the opaque variant of the surface format, while the underlying image is created with the normal surface format. However, there is no guarantee that the compositor supports that opaque format, or that we can use that format with all the modifiers of the surface format. Since this is completely out of the control of the application, and the compositor will disconnect the client with an error if the format is not supported, this commit: 1. Fails EGL surface creation if it determines that the opaque format cannot be used, either because it's not present at all, or because it shares no modifier with the non-opaque format. 2. When creating the DRI image ensures that we use a modifier that's also supported by the opaque format. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28153>
This commit is contained in:
committed by
Marge Bot
parent
a271a34d59
commit
4cac8468d4
@@ -622,6 +622,29 @@ static const struct zwp_linux_dmabuf_feedback_v1_listener
|
||||
.done = surface_dmabuf_feedback_done,
|
||||
};
|
||||
|
||||
static bool
|
||||
dri2_wl_modifiers_have_common(struct u_vector *modifiers1,
|
||||
struct u_vector *modifiers2)
|
||||
{
|
||||
uint64_t *mod1, *mod2;
|
||||
|
||||
/* If both modifier vectors are empty, assume there is a compatible
|
||||
* implicit modifier. */
|
||||
if (u_vector_length(modifiers1) == 0 && u_vector_length(modifiers2) == 0)
|
||||
return true;
|
||||
|
||||
u_vector_foreach(mod1, modifiers1)
|
||||
{
|
||||
u_vector_foreach(mod2, modifiers2)
|
||||
{
|
||||
if (*mod1 == *mod2)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called via eglCreateWindowSurface(), drv->CreateWindowSurface().
|
||||
*/
|
||||
@@ -680,6 +703,20 @@ dri2_wl_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
|
||||
dri2_surf->format = dri2_wl_shm_format_from_visual_idx(visual_idx);
|
||||
}
|
||||
|
||||
if (dri2_surf->base.PresentOpaque) {
|
||||
uint32_t opaque_fourcc =
|
||||
dri2_wl_visuals[visual_idx].opaque_wl_drm_format;
|
||||
int opaque_visual_idx = dri2_wl_visual_idx_from_fourcc(opaque_fourcc);
|
||||
|
||||
if (!server_supports_format(&dri2_dpy->formats, opaque_visual_idx) ||
|
||||
!dri2_wl_modifiers_have_common(
|
||||
&dri2_dpy->formats.modifiers[visual_idx],
|
||||
&dri2_dpy->formats.modifiers[opaque_visual_idx])) {
|
||||
_eglError(EGL_BAD_MATCH, "Unsupported opaque format");
|
||||
goto cleanup_surf;
|
||||
}
|
||||
}
|
||||
|
||||
dri2_surf->wl_queue = wl_display_create_queue_with_name(dri2_dpy->wl_dpy,
|
||||
"mesa egl surface queue");
|
||||
if (!dri2_surf->wl_queue) {
|
||||
@@ -973,26 +1010,47 @@ create_dri_image(struct dri2_egl_surface *dri2_surf,
|
||||
dri2_egl_display(dri2_surf->base.Resource.Display);
|
||||
int visual_idx = dri2_wl_visual_idx_from_fourcc(dri2_surf->format);
|
||||
struct u_vector modifiers_subset;
|
||||
struct u_vector modifiers_subset_opaque;
|
||||
uint64_t *modifiers;
|
||||
unsigned int num_modifiers;
|
||||
struct u_vector *modifiers_set;
|
||||
struct u_vector *modifiers_present;
|
||||
|
||||
assert(visual_idx != -1);
|
||||
|
||||
if (!BITSET_TEST(formats->formats_bitmap, visual_idx))
|
||||
return;
|
||||
if (dri2_surf->base.PresentOpaque) {
|
||||
uint32_t opaque_fourcc =
|
||||
dri2_wl_visuals[visual_idx].opaque_wl_drm_format;
|
||||
int opaque_visual_idx = dri2_wl_visual_idx_from_fourcc(opaque_fourcc);
|
||||
struct u_vector *modifiers_dpy = &dri2_dpy->formats.modifiers[visual_idx];
|
||||
/* Surface creation would have failed if we didn't support the matching
|
||||
* opaque format. */
|
||||
assert(opaque_visual_idx != -1);
|
||||
|
||||
modifiers_set = &formats->modifiers[visual_idx];
|
||||
if (!BITSET_TEST(formats->formats_bitmap, opaque_visual_idx))
|
||||
return;
|
||||
|
||||
if (!intersect_modifiers(&modifiers_subset_opaque,
|
||||
&formats->modifiers[opaque_visual_idx],
|
||||
u_vector_tail(modifiers_dpy),
|
||||
u_vector_length(modifiers_dpy)))
|
||||
return;
|
||||
|
||||
modifiers_present = &modifiers_subset_opaque;
|
||||
} else {
|
||||
if (!BITSET_TEST(formats->formats_bitmap, visual_idx))
|
||||
return;
|
||||
modifiers_present = &formats->modifiers[visual_idx];
|
||||
}
|
||||
|
||||
if (surf_modifiers_count > 0) {
|
||||
if (!intersect_modifiers(&modifiers_subset, modifiers_set, surf_modifiers,
|
||||
surf_modifiers_count))
|
||||
return;
|
||||
if (!intersect_modifiers(&modifiers_subset, modifiers_present,
|
||||
surf_modifiers, surf_modifiers_count))
|
||||
goto cleanup_present;
|
||||
modifiers = u_vector_tail(&modifiers_subset);
|
||||
num_modifiers = u_vector_length(&modifiers_subset);
|
||||
} else {
|
||||
modifiers = u_vector_tail(modifiers_set);
|
||||
num_modifiers = u_vector_length(modifiers_set);
|
||||
modifiers = u_vector_tail(modifiers_present);
|
||||
num_modifiers = u_vector_length(modifiers_present);
|
||||
}
|
||||
|
||||
/* For the purposes of this function, an INVALID modifier on
|
||||
@@ -1013,6 +1071,10 @@ create_dri_image(struct dri2_egl_surface *dri2_surf,
|
||||
u_vector_finish(&modifiers_subset);
|
||||
update_surface(dri2_surf, dri2_surf->back->dri_image);
|
||||
}
|
||||
|
||||
cleanup_present:
|
||||
if (modifiers_present == &modifiers_subset_opaque)
|
||||
u_vector_finish(&modifiers_subset_opaque);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
Reference in New Issue
Block a user