From a4e13063edaf034a7866173bb95f7d06f362f2ed Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Mon, 27 Mar 2023 13:43:38 -0700 Subject: [PATCH] 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 Part-of: --- src/gallium/drivers/iris/iris_resource.c | 35 ++++++++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/gallium/drivers/iris/iris_resource.c b/src/gallium/drivers/iris/iris_resource.c index 48b9c6dad06..07678dbb184 100644 --- a/src/gallium/drivers/iris/iris_resource.c +++ b/src/gallium/drivers/iris/iris_resource.c @@ -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.