backend-drm: Implement DRM_FORMAT_MOD_BROADCOM_SAND128 support

The BROADCOM_SAND128 modifier is usually used with an extra parameter
to pass in the stride via a side channel. Quoting from drm_fourcc.h:
> The pitch between the start of each column is set to optimally
> switch between SDRAM banks. This is passed as the number of lines
> of column width in the modifier (we can't use the stride value due
> to various core checks that look at it , so you should set the
> stride to width*cpp).

Fortunately this limitation only applies to the KMS layer - Mesa,
Wayland, Gstreamer etc. can use the modifier and stride as usual.

Implement the special modifier handling to enable KMS offloading.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
This commit is contained in:
Robert Mader 2024-11-08 20:42:05 +01:00
parent 4f4011d79e
commit e598e96468

View file

@ -220,13 +220,32 @@ drm_fb_addfb(struct drm_device *device, struct drm_fb *fb)
/* If we have a modifier set, we must only use the WithModifiers
* entrypoint; we cannot import it through legacy ioctls. */
if (device->fb_modifiers && fb->modifier != DRM_FORMAT_MOD_INVALID) {
uint32_t strides[4] = { };
uint64_t modifier;
modifier = fb->modifier;
for (i = 0; i < ARRAY_LENGTH(strides) && fb->handles[i]; i++)
strides[i] = fb->strides[i];
if (fourcc_mod_broadcom_mod(modifier) == DRM_FORMAT_MOD_BROADCOM_SAND128) {
uint32_t stride_multiplicator;
modifier =
DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT (strides[0]);
stride_multiplicator =
fb->format->format == DRM_FORMAT_NV12 ? 1 : 2;
for (i = 0; i < ARRAY_LENGTH(strides) && strides[i]; i++)
strides[i] = fb->width * stride_multiplicator;
}
/* KMS demands that if a modifier is set, it must be the same
* for all planes. */
for (i = 0; i < ARRAY_LENGTH(mods) && fb->handles[i]; i++)
mods[i] = fb->modifier;
mods[i] = modifier;
ret = drmModeAddFB2WithModifiers(fb->fd, fb->width, fb->height,
fb->format->format,
fb->handles, fb->strides,
fb->handles, strides,
fb->offsets, mods, &fb->fb_id,
DRM_MODE_FB_MODIFIERS);
return ret;