iris: Hack around gbm_gralloc stride restrictions

gbm_bo_map returns a stride for the mapping, which may differ from the
stride of the underlying BO.  Drivers may implement mappings via staging
blits, returning a map of a temporary resource instead.  That temporary
may have fewer stride restrictions (i.e. it isn't used for display), and
thus be more tightly packed, saving memory.

However, gbm_gralloc has a design flaw where after calling gbm_bo_map,
it asserts that the stride exactly matches the original BO's stride:

   assert(stride == gbm_bo_get_stride(bo));

This is a bad assumption, as the GBM API returns a stride explicitly
precisely because it -can- differ.  But, this would require significant
changes to gbm_gralloc to fix.  So, to work around it, we add a driver
hack for Android-only that forces staging maps of any external BO to use
the original resource's stride.

This should fix issues with mapping cursor planes and SW media codec
uploads on Android-x86.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/7974
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22156>
This commit is contained in:
Kenneth Graunke 2023-03-27 13:43:38 -07:00 committed by Marge Bot
parent 1452b60f35
commit a4e13063ed

View file

@ -2077,14 +2077,37 @@ iris_map_copy_region(struct iris_transfer *map)
.format = res->internal_format,
};
if (xfer->resource->target == PIPE_BUFFER)
if (xfer->resource->target == PIPE_BUFFER) {
templ.target = PIPE_BUFFER;
else if (templ.array_size > 1)
templ.target = PIPE_TEXTURE_2D_ARRAY;
else
templ.target = PIPE_TEXTURE_2D;
map->staging = iris_resource_create_for_buffer(pscreen, &templ);
} else {
templ.target = templ.array_size > 1 ? PIPE_TEXTURE_2D_ARRAY
: PIPE_TEXTURE_2D;
map->staging = iris_resource_create(pscreen, &templ);
unsigned row_pitch_B = 0;
#ifdef ANDROID
/* Staging buffers for stall-avoidance blits don't always have the
* same restrictions on stride as the original buffer. For example,
* the original buffer may be used for scanout, while the staging
* buffer will not be. So we may compute a smaller stride for the
* staging buffer than the original.
*
* Normally, this is good, as it saves memory. Unfortunately, for
* Android, gbm_gralloc incorrectly asserts that the stride returned
* by gbm_bo_map() must equal the result of gbm_bo_get_stride(),
* which simply isn't always the case.
*
* Because gralloc is unlikely to be fixed, we hack around it in iris
* by forcing the staging buffer to have a matching stride.
*/
if (iris_bo_is_external(res->bo))
row_pitch_B = res->surf.row_pitch_B;
#endif
map->staging =
iris_resource_create_for_image(pscreen, &templ, NULL, 0, row_pitch_B);
}
/* If we fail to create a staging resource, the caller will fallback
* to mapping directly on the CPU.