From c33cf706f22de15b77096beb1d01df842c4f1db5 Mon Sep 17 00:00:00 2001 From: Sean Callanan Date: Fri, 23 Apr 2021 15:57:18 -0700 Subject: gralloc4: align buffers for the GPU to 64 bytes The camera requires 64-byte stride alignment for a variety of formats. Set this alignment if GPU usage is detected. Test: Boot, use viewfinder Bug: 185836979 Bug: 185065640 Bug: 184793812 Change-Id: I96a5abf5465fb583d5f3393dece431d3b60a2cdb --- gralloc4/src/core/format_info.cpp | 6 -- gralloc4/src/core/format_info.h | 4 ++ .../src/core/mali_gralloc_bufferallocation.cpp | 68 ++++++++++++++++++++-- 3 files changed, 68 insertions(+), 10 deletions(-) (limited to 'gralloc4/src') diff --git a/gralloc4/src/core/format_info.cpp b/gralloc4/src/core/format_info.cpp index fedb9ff..1a8c92e 100644 --- a/gralloc4/src/core/format_info.cpp +++ b/gralloc4/src/core/format_info.cpp @@ -438,12 +438,6 @@ void get_format_dataspace(uint32_t base_format, } -bool is_power2(uint8_t n) -{ - return ((n & (n-1)) == 0); -} - - bool sanitize_formats(void) { bool fail = false; diff --git a/gralloc4/src/core/format_info.h b/gralloc4/src/core/format_info.h index 9882187..ad2db6d 100644 --- a/gralloc4/src/core/format_info.h +++ b/gralloc4/src/core/format_info.h @@ -39,6 +39,10 @@ typedef struct uint16_t height; } rect_t; +constexpr bool is_power2(uint8_t n) +{ + return ((n & (n-1)) == 0); +} /* * Pixel format information. diff --git a/gralloc4/src/core/mali_gralloc_bufferallocation.cpp b/gralloc4/src/core/mali_gralloc_bufferallocation.cpp index d0f2410..7defdde 100644 --- a/gralloc4/src/core/mali_gralloc_bufferallocation.cpp +++ b/gralloc4/src/core/mali_gralloc_bufferallocation.cpp @@ -41,6 +41,9 @@ #define YUV_BYTE_ALIGN_DEFAULT 16 #define RGB_BYTE_ALIGN_DEFAULT 64 +/* IP-specific align values */ +#define GPU_BYTE_ALIGN_DEFAULT 64 + /* Always CPU align for Exynos */ #define CAN_SKIP_CPU_ALIGN 0 @@ -486,6 +489,11 @@ static uint64_t update_usage_for_BO(uint64_t usage) { return usage; } +static void align_plane_stride(plane_info_t *plane_info, int plane, const format_info_t format, uint32_t stride_align) +{ + plane_info[plane].byte_stride = GRALLOC_ALIGN(plane_info[plane].byte_stride * format.tile_size, stride_align) / format.tile_size; + plane_info[plane].alloc_width = plane_info[plane].byte_stride * 8 / format.bpp[plane]; +} /* * Calculate allocation size. @@ -509,6 +517,7 @@ static void calc_allocation_size(const int width, const format_info_t format, const bool has_cpu_usage, const bool has_hw_usage, + const bool has_gpu_usage, int * const pixel_stride, uint64_t * const size, plane_info_t plane_info[MAX_PLANES]) @@ -557,11 +566,27 @@ static void calc_allocation_size(const int width, uint16_t hw_align = 0; if (has_hw_usage) { + static_assert(is_power2(YUV_BYTE_ALIGN_DEFAULT), + "YUV_BYTE_ALIGN_DEFAULT is not a power of 2"); + static_assert(is_power2(RGB_BYTE_ALIGN_DEFAULT), + "RGB_BYTE_ALIGN_DEFAULT is not a power of 2"); + hw_align = format.is_yuv ? YUV_BYTE_ALIGN_DEFAULT : (format.is_rgb ? RGB_BYTE_ALIGN_DEFAULT : 0); } + if (has_gpu_usage) + { + static_assert(is_power2(GPU_BYTE_ALIGN_DEFAULT), + "RGB_BYTE_ALIGN_DEFAULT is not a power of 2"); + + /* + * The GPU requires stricter alignment on YUV and raw formats. + */ + hw_align = std::max(hw_align, static_cast(GPU_BYTE_ALIGN_DEFAULT)); + } + uint32_t cpu_align = 0; #if CAN_SKIP_CPU_ALIGN == 1 @@ -579,8 +604,7 @@ static void calc_allocation_size(const int width, uint32_t stride_align = lcm(hw_align, cpu_align); if (stride_align) { - plane_info[plane].byte_stride = GRALLOC_ALIGN(plane_info[plane].byte_stride * format.tile_size, stride_align) / format.tile_size; - plane_info[plane].alloc_width = plane_info[plane].byte_stride * 8 / format.bpp[plane]; + align_plane_stride(plane_info, plane, format, stride_align); } #if REALIGN_YV12 == 1 @@ -719,7 +743,8 @@ static bool validate_format(const format_info_t * const format, } static int prepare_descriptor_exynos_formats( - buffer_descriptor_t *bufDescriptor) + buffer_descriptor_t *bufDescriptor, + format_info_t format_info) { int fd_count = 1; int w = bufDescriptor->width; @@ -865,6 +890,40 @@ static int prepare_descriptor_exynos_formats( plane_info_t *plane = bufDescriptor->plane_info; + if (usage & (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_GPU_DATA_BUFFER)) + { + if (is_sbwc_format(format)) + { + MALI_GRALLOC_LOGE("using SBWC format (%s %" PRIx64 ") with GPU is invalid", + format_name(bufDescriptor->alloc_format), + bufDescriptor->alloc_format); + return -1; + } + else + { + /* + * The GPU requires stricter alignment on YUV formats. + */ + for (int pidx = 0; pidx < plane_count; ++pidx) + { + if (plane[pidx].size == plane[pidx].byte_stride * plane[pidx].alloc_height) + { + align_plane_stride(plane, pidx, format_info, GPU_BYTE_ALIGN_DEFAULT); + plane[pidx].size = plane[pidx].byte_stride * plane[pidx].alloc_height; + } + else + { + MALI_GRALLOC_LOGE("buffer with format (%s %" PRIx64 + ") has size %" PRIu64 + " != byte_stride %" PRIu32 " * alloc_height %" PRIu32, + format_name(bufDescriptor->alloc_format), + bufDescriptor->alloc_format, + plane[pidx].size, plane[pidx].byte_stride, plane[pidx].alloc_height); + } + } + } + } + for (int fidx = 0; fidx < fd_count; fidx++) { uint64_t size = 0; @@ -945,7 +1004,7 @@ int mali_gralloc_derive_format_and_size(buffer_descriptor_t * const bufDescripto if (is_exynos_format(bufDescriptor->alloc_format)) { - prepare_descriptor_exynos_formats(bufDescriptor); + prepare_descriptor_exynos_formats(bufDescriptor, formats[format_idx]); } else { @@ -967,6 +1026,7 @@ int mali_gralloc_derive_format_and_size(buffer_descriptor_t * const bufDescripto formats[format_idx], usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK), usage & ~(GRALLOC_USAGE_PRIVATE_MASK | GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK), + usage & (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_GPU_DATA_BUFFER), &bufDescriptor->pixel_stride, &bufDescriptor->alloc_sizes[0], bufDescriptor->plane_info); -- cgit v1.2.3