Commit f36b5274 authored by Bas Nieuwenhuizen's avatar Bas Nieuwenhuizen Committed by Bas Nieuwenhuizen
Browse files

radv/android: Add android hardware buffer queries.



Derived from the Intel code.

For the internal format we just use the internal Vulkan format,
as we have Vulkan formats for all android formats we care about.

For the ycbcr properties we just do something. I do not have a real
clue what would be recommended.
Reviewed-by: Samuel Pitoiset's avatarSamuel Pitoiset <samuel.pitoiset@gmail.com>
parent a34e4dd0
......@@ -139,6 +139,7 @@ if with_xlib_lease
endif
if with_platform_android
radv_deps += dep_android
radv_flags += [
'-DVK_USE_PLATFORM_ANDROID_KHR'
]
......
......@@ -24,11 +24,13 @@
#include <hardware/gralloc.h>
#include <hardware/hardware.h>
#include <hardware/hwvulkan.h>
#include <vndk/hardware_buffer.h>
#include <vulkan/vk_android_native_buffer.h>
#include <vulkan/vk_icd.h>
#include <libsync.h>
#include "radv_private.h"
#include "vk_util.h"
static int radv_hal_open(const struct hw_module_t* mod, const char* id, struct hw_device_t** dev);
static int radv_hal_close(struct hw_device_t *dev);
......@@ -372,3 +374,182 @@ radv_QueueSignalReleaseImageANDROID(
}
return VK_SUCCESS;
}
#if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER
enum {
/* Usage bit equal to GRALLOC_USAGE_HW_CAMERA_MASK */
AHARDWAREBUFFER_USAGE_CAMERA_MASK = 0x00060000U,
};
static inline VkFormat
vk_format_from_android(unsigned android_format, unsigned android_usage)
{
switch (android_format) {
case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
return VK_FORMAT_R8G8B8A8_UNORM;
case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
return VK_FORMAT_R8G8B8_UNORM;
case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
return VK_FORMAT_R5G6B5_UNORM_PACK16;
case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
return VK_FORMAT_R16G16B16A16_SFLOAT;
case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
case AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED:
if (android_usage & AHARDWAREBUFFER_USAGE_CAMERA_MASK)
return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
else
return VK_FORMAT_R8G8B8_UNORM;
case AHARDWAREBUFFER_FORMAT_BLOB:
default:
return VK_FORMAT_UNDEFINED;
}
}
static VkResult
get_ahb_buffer_format_properties(
VkDevice device_h,
const struct AHardwareBuffer *buffer,
VkAndroidHardwareBufferFormatPropertiesANDROID *pProperties)
{
RADV_FROM_HANDLE(radv_device, device, device_h);
/* Get a description of buffer contents . */
AHardwareBuffer_Desc desc;
AHardwareBuffer_describe(buffer, &desc);
/* Verify description. */
const uint64_t gpu_usage =
AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
/* "Buffer must be a valid Android hardware buffer object with at least
* one of the AHARDWAREBUFFER_USAGE_GPU_* usage flags."
*/
if (!(desc.usage & (gpu_usage)))
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
/* Fill properties fields based on description. */
VkAndroidHardwareBufferFormatPropertiesANDROID *p = pProperties;
p->format = vk_format_from_android(desc.format, desc.usage);
p->externalFormat = (uint64_t) (uintptr_t) p->format;
VkFormatProperties format_properties;
radv_GetPhysicalDeviceFormatProperties(
radv_physical_device_to_handle(device->physical_device),
p->format, &format_properties);
if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER)
p->formatFeatures = format_properties.linearTilingFeatures;
else
p->formatFeatures = format_properties.optimalTilingFeatures;
/* "Images can be created with an external format even if the Android hardware
* buffer has a format which has an equivalent Vulkan format to enable
* consistent handling of images from sources that might use either category
* of format. However, all images created with an external format are subject
* to the valid usage requirements associated with external formats, even if
* the Android hardware buffer’s format has a Vulkan equivalent."
*
* "The formatFeatures member *must* include
* VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT and at least one of
* VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or
* VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT"
*/
assert(p->formatFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
p->formatFeatures |= VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
/* "Implementations may not always be able to determine the color model,
* numerical range, or chroma offsets of the image contents, so the values
* in VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
* Applications should treat these values as sensible defaults to use in
* the absence of more reliable information obtained through some other
* means."
*/
p->samplerYcbcrConversionComponents.r = VK_COMPONENT_SWIZZLE_IDENTITY;
p->samplerYcbcrConversionComponents.g = VK_COMPONENT_SWIZZLE_IDENTITY;
p->samplerYcbcrConversionComponents.b = VK_COMPONENT_SWIZZLE_IDENTITY;
p->samplerYcbcrConversionComponents.a = VK_COMPONENT_SWIZZLE_IDENTITY;
p->suggestedYcbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601;
p->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
p->suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
p->suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
return VK_SUCCESS;
}
VkResult
radv_GetAndroidHardwareBufferPropertiesANDROID(
VkDevice device_h,
const struct AHardwareBuffer *buffer,
VkAndroidHardwareBufferPropertiesANDROID *pProperties)
{
RADV_FROM_HANDLE(radv_device, dev, device_h);
struct radv_physical_device *pdevice = dev->physical_device;
VkAndroidHardwareBufferFormatPropertiesANDROID *format_prop =
vk_find_struct(pProperties->pNext,
ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID);
/* Fill format properties of an Android hardware buffer. */
if (format_prop)
get_ahb_buffer_format_properties(device_h, buffer, format_prop);
/* 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.
*/
const native_handle_t *handle =
AHardwareBuffer_getNativeHandle(buffer);
int dma_buf = (handle && handle->numFds) ? handle->data[0] : -1;
if (dma_buf < 0)
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
/* All memory types. */
uint32_t memory_types = (1u << pdevice->memory_properties.memoryTypeCount) - 1;
pProperties->allocationSize = lseek(dma_buf, 0, SEEK_END);
pProperties->memoryTypeBits = memory_types;
return VK_SUCCESS;
}
VkResult
radv_GetMemoryAndroidHardwareBufferANDROID(
VkDevice device_h,
const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo,
struct AHardwareBuffer **pBuffer)
{
RADV_FROM_HANDLE(radv_device_memory, mem, pInfo->memory);
/* This should always be set due to the export handle types being set on
* allocation. */
assert(mem->android_hardware_buffer);
/* Some quotes from Vulkan spec:
*
* "If the device memory was created by importing an Android hardware
* buffer, vkGetMemoryAndroidHardwareBufferANDROID must return that same
* Android hardware buffer object."
*
* "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID must
* have been included in VkExportMemoryAllocateInfo::handleTypes when
* memory was created."
*/
*pBuffer = mem->android_hardware_buffer;
/* Increase refcount. */
AHardwareBuffer_acquire(mem->android_hardware_buffer);
return VK_SUCCESS;
}
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment