mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-19 08:00:36 +02:00
/s/ahw/ahb/ to match common vulkan Signed-off-by: Juston Li <justonli@google.com> Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38039>
182 lines
6.5 KiB
C
182 lines
6.5 KiB
C
/*
|
|
* Copyright © 2017, Google Inc.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including the next
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
* Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
* IN THE SOFTWARE.
|
|
*/
|
|
|
|
#include "anv_private.h"
|
|
|
|
/*
|
|
* Called from anv_AllocateMemory when import AHardwareBuffer.
|
|
*/
|
|
VkResult
|
|
anv_import_ahb_memory(VkDevice device_h,
|
|
struct anv_device_memory *mem)
|
|
{
|
|
#if ANDROID_API_LEVEL >= 26
|
|
ANV_FROM_HANDLE(anv_device, device, device_h);
|
|
|
|
/* Import from AHardwareBuffer to anv_device_memory. */
|
|
const native_handle_t *handle =
|
|
AHardwareBuffer_getNativeHandle(mem->vk.ahardware_buffer);
|
|
|
|
/* NOTE - We support buffers with only one handle but do not error on
|
|
* multiple handle case. Reason is that we want to support YUV formats
|
|
* where we have many logical planes but they all point to the same
|
|
* buffer, like is the case with VK_FORMAT_G8_B8R8_2PLANE_420_UNORM.
|
|
*/
|
|
int dma_buf = (handle && handle->numFds) ? handle->data[0] : -1;
|
|
if (dma_buf < 0)
|
|
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
|
|
|
VkResult result = anv_device_import_bo(device, dma_buf,
|
|
ANV_BO_ALLOC_EXTERNAL,
|
|
0 /* client_address */,
|
|
&mem->bo);
|
|
assert(result == VK_SUCCESS);
|
|
|
|
return VK_SUCCESS;
|
|
#else
|
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
|
#endif
|
|
}
|
|
|
|
VkResult
|
|
anv_android_get_tiling(struct anv_device *device,
|
|
struct u_gralloc_buffer_handle *gr_handle,
|
|
enum isl_tiling *tiling_out)
|
|
{
|
|
struct u_gralloc *gralloc = vk_android_get_ugralloc();
|
|
assert(gralloc);
|
|
|
|
struct u_gralloc_buffer_basic_info buf_info;
|
|
if (u_gralloc_get_buffer_basic_info(gralloc, gr_handle, &buf_info))
|
|
return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
|
|
"failed to get tiling from gralloc buffer info");
|
|
|
|
const struct isl_drm_modifier_info *mod_info =
|
|
isl_drm_modifier_get_info(buf_info.modifier);
|
|
if (!mod_info) {
|
|
return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
|
|
"invalid drm modifier from VkNativeBufferANDROID "
|
|
"gralloc buffer info 0x%"PRIx64"", buf_info.modifier);
|
|
}
|
|
|
|
*tiling_out = mod_info->tiling;
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VkResult
|
|
anv_image_init_from_gralloc(struct anv_device *device,
|
|
struct anv_image *image,
|
|
const VkImageCreateInfo *base_info,
|
|
const VkNativeBufferANDROID *gralloc_info)
|
|
{
|
|
struct anv_bo *bo = NULL;
|
|
VkResult result;
|
|
|
|
struct anv_image_create_info anv_info = {
|
|
.vk_info = base_info,
|
|
.isl_extra_usage_flags = ISL_SURF_USAGE_DISABLE_AUX_BIT,
|
|
};
|
|
|
|
/* Do not close the gralloc handle's dma_buf. The lifetime of the dma_buf
|
|
* must exceed that of the gralloc handle, and we do not own the gralloc
|
|
* handle.
|
|
*/
|
|
int dma_buf = gralloc_info->handle->data[0];
|
|
|
|
/* If this function fails and if the imported bo was resident in the cache,
|
|
* we should avoid updating the bo's flags. Therefore, we defer updating
|
|
* the flags until success is certain.
|
|
*
|
|
*/
|
|
result = anv_device_import_bo(device, dma_buf,
|
|
ANV_BO_ALLOC_EXTERNAL,
|
|
0 /* client_address */,
|
|
&bo);
|
|
if (result != VK_SUCCESS) {
|
|
return vk_errorf(device, result,
|
|
"failed to import dma-buf from VkNativeBufferANDROID");
|
|
}
|
|
|
|
enum isl_tiling tiling;
|
|
if (vk_android_get_ugralloc()) {
|
|
struct u_gralloc_buffer_handle gr_handle = {
|
|
.handle = gralloc_info->handle,
|
|
.hal_format = gralloc_info->format,
|
|
.pixel_stride = gralloc_info->stride,
|
|
};
|
|
result = anv_android_get_tiling(device, &gr_handle, &tiling);
|
|
if (result != VK_SUCCESS)
|
|
return result;
|
|
} else {
|
|
/* Fallback to get_tiling API. */
|
|
result = anv_device_get_bo_tiling(device, bo, &tiling);
|
|
if (result != VK_SUCCESS) {
|
|
return vk_errorf(device, result,
|
|
"failed to get tiling from VkNativeBufferANDROID");
|
|
}
|
|
}
|
|
anv_info.isl_tiling_flags = 1u << tiling;
|
|
|
|
anv_info.stride = gralloc_info->stride;
|
|
|
|
result = anv_image_init(device, image, &anv_info);
|
|
if (result != VK_SUCCESS)
|
|
goto fail_init;
|
|
|
|
VkMemoryRequirements2 mem_reqs = {
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
|
|
};
|
|
|
|
anv_image_get_memory_requirements(device, image, image->vk.aspects,
|
|
&mem_reqs);
|
|
|
|
VkDeviceSize aligned_image_size =
|
|
align64(mem_reqs.memoryRequirements.size,
|
|
mem_reqs.memoryRequirements.alignment);
|
|
|
|
if (bo->size < aligned_image_size) {
|
|
result = vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
|
|
"dma-buf from VkNativeBufferANDROID is too small for "
|
|
"VkImage: %"PRIu64"B < %"PRIu64"B",
|
|
bo->size, aligned_image_size);
|
|
goto fail_size;
|
|
}
|
|
|
|
assert(!image->disjoint);
|
|
assert(image->n_planes == 1);
|
|
assert(image->planes[0].primary_surface.memory_range.binding ==
|
|
ANV_IMAGE_MEMORY_BINDING_MAIN);
|
|
assert(image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN].address.bo == NULL);
|
|
assert(image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN].address.offset == 0);
|
|
image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN].address.bo = bo;
|
|
image->from_gralloc = true;
|
|
|
|
return VK_SUCCESS;
|
|
|
|
fail_size:
|
|
anv_image_finish(image);
|
|
fail_init:
|
|
anv_device_release_bo(device, bo);
|
|
|
|
return result;
|
|
}
|