dri3: Don't compute intersection with drawable modifiers

In dri3_get_supported_modifiers we were previously intersecting
the drawable mods and the screen mods. This meant all screen mods
were returned, but the ones compatible with the drawable were
returned in the drawable mods list and the rest are returned in
the screen mods list.

This is a problem with linux_dmabuf v4 since the drawable mods may
contain different mods not found in the screen mods (such as scanout
entries). This change removes the intersection, and just returns
the drawable/screen mod lists directly.

Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
This commit is contained in:
Austin Shafer 2022-12-20 12:22:53 +01:00 committed by Michel Dänzer
parent f0415beb9f
commit 9865a2321f

View File

@ -211,18 +211,17 @@ cache_formats_and_modifiers(ScreenPtr screen)
int int
dri3_get_supported_modifiers(ScreenPtr screen, DrawablePtr drawable, dri3_get_supported_modifiers(ScreenPtr screen, DrawablePtr drawable,
CARD8 depth, CARD8 bpp, CARD8 depth, CARD8 bpp,
CARD32 *num_intersect_modifiers, CARD32 *num_drawable_modifiers,
CARD64 **intersect_modifiers, CARD64 **drawable_modifiers,
CARD32 *num_screen_modifiers, CARD32 *num_screen_modifiers,
CARD64 **screen_modifiers) CARD64 **screen_modifiers)
{ {
dri3_screen_priv_ptr ds = dri3_screen_priv(screen); dri3_screen_priv_ptr ds = dri3_screen_priv(screen);
const dri3_screen_info_rec *info = ds->info; const dri3_screen_info_rec *info = ds->info;
int i, j; int i;
int ret; int ret;
uint32_t num_drawable_mods; uint32_t num_drawable_mods;
uint64_t *drawable_mods; uint64_t *drawable_mods;
CARD64 *intersect_mods = NULL;
CARD64 *screen_mods = NULL; CARD64 *screen_mods = NULL;
CARD32 format; CARD32 format;
dri3_dmabuf_format_ptr screen_format = NULL; dri3_dmabuf_format_ptr screen_format = NULL;
@ -248,10 +247,15 @@ dri3_get_supported_modifiers(ScreenPtr screen, DrawablePtr drawable,
if (screen_format->num_modifiers == 0) { if (screen_format->num_modifiers == 0) {
*num_screen_modifiers = 0; *num_screen_modifiers = 0;
*num_intersect_modifiers = 0; *num_drawable_modifiers = 0;
return Success; return Success;
} }
/* copy the screen mods so we can return an owned allocation */
screen_mods = xnfalloc(screen_format->num_modifiers * sizeof(CARD64));
memcpy(screen_mods, screen_format->modifiers,
screen_format->num_modifiers * sizeof(CARD64));
if (!info->get_drawable_modifiers || if (!info->get_drawable_modifiers ||
!info->get_drawable_modifiers(drawable, format, !info->get_drawable_modifiers(drawable, format,
&num_drawable_mods, &num_drawable_mods,
@ -260,47 +264,11 @@ dri3_get_supported_modifiers(ScreenPtr screen, DrawablePtr drawable,
drawable_mods = NULL; drawable_mods = NULL;
} }
/* We're allocating slightly more memory than necessary but it reduces *num_drawable_modifiers = num_drawable_mods;
* the complexity of finding the intersection set. *drawable_modifiers = drawable_mods;
*/
screen_mods = malloc(screen_format->num_modifiers * sizeof(CARD64));
if (!screen_mods)
return BadAlloc;
if (num_drawable_mods > 0) {
intersect_mods = malloc(screen_format->num_modifiers * sizeof(CARD64));
if (!intersect_mods) {
free(screen_mods);
return BadAlloc;
}
}
*num_screen_modifiers = 0; *num_screen_modifiers = screen_format->num_modifiers;
*num_intersect_modifiers = 0;
for (i = 0; i < screen_format->num_modifiers; i++) {
CARD64 modifier = screen_format->modifiers[i];
Bool intersect = FALSE;
for (j = 0; j < num_drawable_mods; j++) {
if (drawable_mods[j] == modifier) {
intersect = TRUE;
break;
}
}
if (intersect) {
intersect_mods[*num_intersect_modifiers] = modifier;
*num_intersect_modifiers += 1;
} else {
screen_mods[*num_screen_modifiers] = modifier;
*num_screen_modifiers += 1;
}
}
assert(*num_intersect_modifiers + *num_screen_modifiers == screen_format->num_modifiers);
*intersect_modifiers = intersect_mods;
*screen_modifiers = screen_mods; *screen_modifiers = screen_mods;
free(drawable_mods);
return Success; return Success;
} }