# include <Dxgi1_2.h>
#endif
-#if (DE_OS == DE_OS_ANDROID) && defined(__ANDROID_API_O__) && (DE_ANDROID_API >= __ANDROID_API_O__)
-# define USE_ANDROID_O_HARDWARE_BUFFER
-#endif
-
-#if (DE_OS == DE_OS_ANDROID) && defined(__ANDROID_API_P__) && (DE_ANDROID_API >= __ANDROID_API_P__)
-# define USE_ANDROID_P_HARDWARE_BUFFER
-#endif
-
-#if defined(USE_ANDROID_O_HARDWARE_BUFFER)
-# include <android/hardware_buffer.h>
-#endif
-
using tcu::TestLog;
using namespace vkt::ExternalMemoryUtil;
return fenceGroup;
}
-#if defined(USE_ANDROID_O_HARDWARE_BUFFER)
-deUint32 vkUsageToAhbUsage(deUint64 vkFlag) {
- switch(vkFlag) {
- case vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT:
- case vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT:
- // No AHB equivalent.
- return 0u;
- case vk::VK_IMAGE_USAGE_SAMPLED_BIT:
- return AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
- case vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT:
- return AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
- case vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT:
- return AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
- }
- return 0u;
-}
-
-deUint32 vkCreateToAhbUsage(deUint64 vkFlag) {
- switch(vkFlag) {
- case vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT:
- case vk::VK_IMAGE_CREATE_EXTENDED_USAGE_BIT:
- // No AHB equivalent.
- return 0u;
- case vk::VK_IMAGE_CREATE_PROTECTED_BIT:
- return AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
-#if defined(USE_ANDROID_P_HARDWARE_BUFFER)
- case vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT:
- return AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP;
-#endif
- }
- return 0u;
-}
-
-deUint32 vkFormatToAhbFormat(deUint64 vkFormat) {
- switch(vkFormat) {
- case vk::VK_FORMAT_R8G8B8A8_UNORM:
- return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
- case vk::VK_FORMAT_R8G8B8_UNORM:
- return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;
- case vk::VK_FORMAT_R5G6B5_UNORM_PACK16:
- return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
- case vk::VK_FORMAT_R16G16B16A16_SFLOAT:
- return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
- case vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32:
- return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
+bool ValidateAHardwareBuffer(vk::VkFormat format, deUint64 requiredAhbUsage, const vk::DeviceDriver& vkd, const vk::VkDevice& device)
+{
+ AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
+ if (!ahbApi)
+ {
+ TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
}
- return 0u;
-}
-bool ValidateAHardwareBuffer(vk::VkFormat format, deUint32 requiredAhbUsage, const vk::DeviceDriver& vkd, const vk::VkDevice& device) {
- AHardwareBuffer_Desc hbufferdesc =
- {
- 64u,
- 64u,
- 1u,
- vkFormatToAhbFormat(format),
- requiredAhbUsage,
- 0u,
- 0u,
- 0u
- };
- AHardwareBuffer* hbuffer = DE_NULL;
- AHardwareBuffer_allocate(&hbufferdesc, &hbuffer);
- if (!hbuffer)
+ vk::pt::AndroidHardwareBufferPtr ahb = ahbApi->allocate(64u, 64u, 1u, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
+ if (ahb.internal == DE_NULL)
return false;
- NativeHandle nativeHandle;
- nativeHandle = vk::pt::AndroidHardwareBufferPtr(hbuffer);
-
+ NativeHandle nativeHandle(ahb);
vk::VkAndroidHardwareBufferFormatPropertiesANDROID formatProperties =
{
vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
vk::VK_CHROMA_LOCATION_COSITED_EVEN,
vk::VK_CHROMA_LOCATION_COSITED_EVEN
};
- vk::VkAndroidHardwareBufferPropertiesANDROID bufferProperties = {
+ vk::VkAndroidHardwareBufferPropertiesANDROID bufferProperties =
+ {
vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
&formatProperties,
0u,
0u
};
- VK_CHECK(vkd.getAndroidHardwareBufferPropertiesANDROID(device, vk::pt::AndroidHardwareBufferPtr(hbuffer), &bufferProperties));
+ VK_CHECK(vkd.getAndroidHardwareBufferPropertiesANDROID(device, ahb, &bufferProperties));
TCU_CHECK(formatProperties.format != vk::VK_FORMAT_UNDEFINED);
TCU_CHECK(formatProperties.format == format);
TCU_CHECK(formatProperties.externalFormat != 0u);
TCU_CHECK((formatProperties.formatFeatures & (vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT | vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) != 0u);
return true;
}
-#endif
-tcu::TestStatus testAndroidHardwareBufferImageFormat(Context& context, vk::VkFormat format)
+tcu::TestStatus testAndroidHardwareBufferImageFormat (Context& context, vk::VkFormat format)
{
-#if defined(USE_ANDROID_O_HARDWARE_BUFFER)
+ AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
+ if (!ahbApi)
+ {
+ TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
+ }
+
const vk::VkExternalMemoryHandleTypeFlagBits externalMemoryType = vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
const vk::PlatformInterface& vkp (context.getPlatformInterface());
const vk::Unique<vk::VkInstance> instance (createInstance(vkp, context.getUsedApiVersion(), externalMemoryType, 0u, 0u));
const vk::InstanceDriver vki (vkp, *instance);
const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
- const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
const vk::Unique<vk::VkDevice> device (createDevice(context.getUsedApiVersion(), vki, physicalDevice, 0u, externalMemoryType, 0u, queueFamilyIndex, true));
const vk::DeviceDriver vkd (vki, *device);
+ TestLog& log = context.getTestContext().getLog();
const vk::VkImageUsageFlagBits usageFlags[] =
{
vk::VK_IMAGE_CREATE_PROTECTED_BIT,
vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
};
- deUint32 mustSupportAhbUsageFlags =
- AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
- AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
-#if defined(USE_ANDROID_P_HARDWARE_BUFFER)
- mustSupportAhbUsageFlags |=
- AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP |
- AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE;
-#endif
+ const vk::VkImageTiling tilings[] =
+ {
+ vk::VK_IMAGE_TILING_OPTIMAL,
+ vk::VK_IMAGE_TILING_LINEAR,
+ };
+ deUint64 mustSupportAhbUsageFlags = ahbApi->mustSupportAhbUsageFlags();
const size_t numOfUsageFlags = DE_LENGTH_OF_ARRAY(usageFlags);
const size_t numOfCreateFlags = DE_LENGTH_OF_ARRAY(createFlags);
const size_t numOfFlagCombos = 1u << (numOfUsageFlags + numOfCreateFlags);
+ const size_t numOfTilings = DE_LENGTH_OF_ARRAY(tilings);
for (size_t combo = 0; combo < numOfFlagCombos; combo++)
{
vk::VkImageUsageFlags usage = 0;
vk::VkImageCreateFlags createFlag = 0;
- deUint32 requiredAhbUsage = 0;
+ deUint64 requiredAhbUsage = 0;
for (size_t usageNdx = 0; usageNdx < numOfUsageFlags; usageNdx++)
{
if ((combo & (1u << usageNdx)) == 0)
continue;
usage |= usageFlags[usageNdx];
- requiredAhbUsage |= vkUsageToAhbUsage(usageFlags[usageNdx]);
+ requiredAhbUsage |= ahbApi->vkUsageToAhbUsage(usageFlags[usageNdx]);
}
for (size_t createFlagNdx = 0; createFlagNdx < numOfCreateFlags; createFlagNdx++)
{
if ((combo & (1u << bit)) == 0)
continue;
createFlag |= createFlags[createFlagNdx];
- requiredAhbUsage |= vkCreateToAhbUsage(createFlags[createFlagNdx]);
+ requiredAhbUsage |= ahbApi->vkCreateToAhbUsage(createFlags[createFlagNdx]);
}
// Only test a combination if the usage flags include at least one of the AHARDWAREBUFFER_USAGE_GPU_* flag.
if (!ValidateAHardwareBuffer(format, requiredAhbUsage, vkd, *device))
continue;
- const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
+ bool foundAnyUsableTiling = false;
+ for (size_t tilingIndex = 0; tilingIndex < numOfTilings; tilingIndex++)
{
- vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
- DE_NULL,
- vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
- };
- const vk::VkPhysicalDeviceImageFormatInfo2 info =
- {
- vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
- &externalInfo,
- format,
- vk::VK_IMAGE_TYPE_2D,
- vk::VK_IMAGE_TILING_OPTIMAL,
- usage,
- createFlag,
- };
+ const vk::VkImageTiling tiling = tilings[tilingIndex];
- vk::VkAndroidHardwareBufferUsageANDROID ahbUsageProperties =
- {
- vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID,
- DE_NULL,
- 0u
- };
- vk::VkExternalImageFormatProperties externalProperties =
- {
- vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
- &ahbUsageProperties,
- { 0u, 0u, 0u }
- };
- vk::VkImageFormatProperties2 properties =
- {
- vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
- &externalProperties,
+ const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
{
- { 0u, 0u, 0u },
- 0u,
- 0u,
- 0u,
+ vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
+ DE_NULL,
+ vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
+ };
+ const vk::VkPhysicalDeviceImageFormatInfo2 info =
+ {
+ vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
+ &externalInfo,
+ format,
+ vk::VK_IMAGE_TYPE_2D,
+ tiling,
+ usage,
+ createFlag,
+ };
+
+ vk::VkAndroidHardwareBufferUsageANDROID ahbUsageProperties =
+ {
+ vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID,
+ DE_NULL,
0u
- }
- };
+ };
+ vk::VkExternalImageFormatProperties externalProperties =
+ {
+ vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
+ &ahbUsageProperties,
+ { 0u, 0u, 0u }
+ };
+ vk::VkImageFormatProperties2 properties =
+ {
+ vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
+ &externalProperties,
+ {
+ { 0u, 0u, 0u },
+ 0u,
+ 0u,
+ 0u,
+ 0u
+ }
+ };
- vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties);
- TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0);
- TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) != 0);
- TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0);
- deUint32 maxWidth = properties.imageFormatProperties.maxExtent.width;
- deUint32 maxHeight = properties.imageFormatProperties.maxExtent.height;
- TCU_CHECK(maxWidth >= 4096);
- TCU_CHECK(maxHeight >= 4096);
- // Even if not requested, at least one of GPU_* usage flags must be present.
- TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & mustSupportAhbUsageFlags) != 0u);
- // The AHB usage flags corresponding to the create and usage flags used in info must be present.
- TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & requiredAhbUsage) == requiredAhbUsage);
-
- struct ImageSize {
- deUint32 width;
- deUint32 height;
- };
- ImageSize sizes[] = {
- {64u, 64u},
- {1024u, 2096u},
- };
- deUint32 exportedMemoryTypeIndex = ~0U;
- for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(sizes); i++) {
- const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, sizes[i].width, sizes[i].height, tiling, createFlag, usage));
- const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image));
- const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements, externalMemoryType, *image, exportedMemoryTypeIndex));
- NativeHandle handle;
-
- VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
- getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
-
- AHardwareBuffer_Desc desc;
- AHardwareBuffer_describe(static_cast<const AHardwareBuffer*>(handle.getAndroidHardwareBuffer().internal), &desc);
- TCU_CHECK(desc.format == vkFormatToAhbFormat(format));
- TCU_CHECK((desc.usage & requiredAhbUsage) == requiredAhbUsage);
- }
+ if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
+ {
+ log << TestLog::Message << "Tiling " << tiling << " is not supported." << TestLog::EndMessage;
+ continue;
+ }
- if (properties.imageFormatProperties.maxMipLevels > 1u) {
- const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage,
- properties.imageFormatProperties.maxMipLevels));
- const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image));
- const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements, externalMemoryType, *image, exportedMemoryTypeIndex));
- NativeHandle handle;
+ foundAnyUsableTiling = true;
- VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
- getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
+ TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0);
+ TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) != 0);
+ TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0);
+ deUint32 maxWidth = properties.imageFormatProperties.maxExtent.width;
+ deUint32 maxHeight = properties.imageFormatProperties.maxExtent.height;
+ TCU_CHECK(maxWidth >= 4096);
+ TCU_CHECK(maxHeight >= 4096);
+ // Even if not requested, at least one of GPU_* usage flags must be present.
+ TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & mustSupportAhbUsageFlags) != 0u);
+ // The AHB usage flags corresponding to the create and usage flags used in info must be present.
+ TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & requiredAhbUsage) == requiredAhbUsage);
- AHardwareBuffer_Desc desc;
- AHardwareBuffer_describe(static_cast<const AHardwareBuffer*>(handle.getAndroidHardwareBuffer().internal), &desc);
- TCU_CHECK(desc.format == vkFormatToAhbFormat(format));
- TCU_CHECK((desc.usage & requiredAhbUsage) == requiredAhbUsage);
- }
+ log << TestLog::Message << "Required flags: " << std::hex << requiredAhbUsage << " Actual flags: " << std::hex << ahbUsageProperties.androidHardwareBufferUsage
+ << TestLog::EndMessage;
- if (properties.imageFormatProperties.maxArrayLayers > 1u) {
- const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage,
- 1u, properties.imageFormatProperties.maxArrayLayers));
- const vk::VkMemoryRequirements requirements(getImageMemoryRequirements(vkd, *device, *image));
- const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements, externalMemoryType, *image, exportedMemoryTypeIndex));
- NativeHandle handle;
+ struct ImageSize
+ {
+ deUint32 width;
+ deUint32 height;
+ };
+ ImageSize sizes[] =
+ {
+ {64u, 64u},
+ {1024u, 2096u},
+ };
+ for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(sizes); i++)
+ {
+ deUint32 exportedMemoryTypeIndex = ~0U;
+ const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, sizes[i].width, sizes[i].height, tiling, createFlag, usage));
+ const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image));
+ const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements, externalMemoryType, *image, exportedMemoryTypeIndex));
+ NativeHandle handle;
+
+ VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
+ getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
+
+ deUint32 ahbFormat = 0;
+ deUint64 anhUsage = 0;
+ ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
+ TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
+ TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
+ }
- VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
- getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
+ if (properties.imageFormatProperties.maxMipLevels > 1u)
+ {
+ deUint32 exportedMemoryTypeIndex = ~0U;
+ const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, properties.imageFormatProperties.maxMipLevels));
+ const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image));
+ const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements, externalMemoryType, *image, exportedMemoryTypeIndex));
+ NativeHandle handle;
+
+ VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
+ getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
+
+ deUint32 ahbFormat = 0;
+ deUint64 anhUsage = 0;
+ ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
+ TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
+ TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
+ }
- AHardwareBuffer_Desc desc;
- AHardwareBuffer_describe(static_cast<const AHardwareBuffer*>(handle.getAndroidHardwareBuffer().internal), &desc);
- TCU_CHECK(desc.format == vkFormatToAhbFormat(format));
- TCU_CHECK((desc.usage & requiredAhbUsage) == requiredAhbUsage);
+ if (properties.imageFormatProperties.maxArrayLayers > 1u)
+ {
+ deUint32 exportedMemoryTypeIndex = ~0U;
+ const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 1u, properties.imageFormatProperties.maxArrayLayers));
+ const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image));
+ const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements, externalMemoryType, *image, exportedMemoryTypeIndex));
+ NativeHandle handle;
+
+ VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
+ getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
+
+ deUint32 ahbFormat = 0;
+ deUint64 anhUsage = 0;
+ ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
+ TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
+ TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
+ }
}
+
+ TCU_CHECK(foundAnyUsableTiling);
}
return tcu::TestStatus::pass("Pass");
-#else
- DE_UNREF(context);
- DE_UNREF(format);
- TCU_THROW(NotSupportedError, "Platform doesn't support AHardwareBuffers");
-#endif
}
de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx)
{
const vk::VkFormat format = ahbFormats[ahbFormatNdx];
const std::string testCaseName = getFormatCaseName(format);
+
addFunctionCase(formatGroup.get(), testCaseName, "", testAndroidHardwareBufferImageFormat, format);
}
# include <windows.h>
#endif
+#if (DE_OS == DE_OS_ANDROID)
+# include <sys/system_properties.h>
+#endif
+
#if (DE_OS == DE_OS_ANDROID) && defined(__ANDROID_API_O__) && (DE_ANDROID_API >= __ANDROID_API_O__)
# include <android/hardware_buffer.h>
-# define USE_ANDROID_O_HARDWARE_BUFFER 1
+# include "deDynamicLibrary.hpp"
+# define BUILT_WITH_ANDROID_HARDWARE_BUFFER 1
#endif
namespace vkt
DE_FATAL("Platform doesn't support win32 handles");
#endif
}
-#if defined(USE_ANDROID_O_HARDWARE_BUFFER)
else if (other.m_androidHardwareBuffer.internal)
{
DE_ASSERT(other.m_fd == -1);
DE_ASSERT(!other.m_win32Handle.internal);
m_androidHardwareBuffer = other.m_androidHardwareBuffer;
- AHardwareBuffer_acquire((AHardwareBuffer*)m_androidHardwareBuffer.internal);
+ AndroidHardwareBufferExternalApi::getInstance()->acquire(m_androidHardwareBuffer);
}
-#endif
else
DE_FATAL("Native handle can't be duplicated");
}
DE_FATAL("Platform doesn't support win32 handles");
#endif
}
-
-#if defined(USE_ANDROID_O_HARDWARE_BUFFER)
if (m_androidHardwareBuffer.internal)
{
DE_ASSERT(m_fd == -1);
DE_ASSERT(!m_win32Handle.internal);
- AHardwareBuffer_release((AHardwareBuffer*)m_androidHardwareBuffer.internal);
+ AndroidHardwareBufferExternalApi::getInstance()->release(m_androidHardwareBuffer);
}
-#endif
-
m_fd = -1;
m_win32Handle = vk::pt::Win32Handle(DE_NULL);
m_win32HandleType = WIN32HANDLETYPE_LAST;
}
else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
{
+ if (!AndroidHardwareBufferExternalApi::getInstance())
+ {
+ TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
+ }
const vk::VkMemoryGetAndroidHardwareBufferInfoANDROID info =
{
vk::VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID,
return memory;
}
-#if defined(USE_ANDROID_O_HARDWARE_BUFFER)
else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
{
- AHardwareBuffer_Desc desc;
- AHardwareBuffer_describe(static_cast<const AHardwareBuffer*>(handle.getAndroidHardwareBuffer().internal), &desc);
+ AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
+ if (!ahbApi)
+ {
+ TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
+ }
- DE_ASSERT(desc.format == AHARDWAREBUFFER_FORMAT_BLOB || image != 0);
+ deUint32 ahbFormat = 0;
+ ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, DE_NULL, DE_NULL);
+ DE_ASSERT(ahbApi->ahbFormatIsBlob(ahbFormat) || image != 0);
vk::VkImportAndroidHardwareBufferInfoANDROID importInfo =
{
return memory;
}
-#endif // (USE_ANDROID_O_HARDWARE_BUFFER)
else
{
DE_FATAL("Unknown external memory type");
vk::VkImageTiling tiling,
vk::VkImageCreateFlags createFlags,
vk::VkImageUsageFlags usageFlags,
- deUint32 mipLevels,
- deUint32 arrayLayers)
+ deUint32 mipLevels,
+ deUint32 arrayLayers)
{
const vk::VkExternalMemoryImageCreateInfo externalCreateInfo =
{
return vk::createImage(vkd, device, &createInfo);
}
+#if (DE_OS == DE_OS_ANDROID)
+# if defined(__ANDROID_API_P__) && (DE_ANDROID_API >= __ANDROID_API_P__)
+# define BUILT_WITH_ANDROID_P_HARDWARE_BUFFER 1
+# endif
+
+static deInt32 androidGetSdkVersion()
+{
+ static deInt32 sdkVersion = -1;
+ if (sdkVersion < 0)
+ {
+ char value[128] = {0};
+ __system_property_get("ro.build.version.sdk", value);
+ sdkVersion = static_cast<deInt32>(strtol(value, DE_NULL, 10));
+ printf("SDK Version is %d\n", sdkVersion);
+ }
+ return sdkVersion;
+}
+
+static deInt32 checkAnbApiBuild()
+{
+ deInt32 sdkVersion = androidGetSdkVersion();
+#if !defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
+ // When testing AHB on Android-O and newer the CTS must be compiled against API26 or newer.
+ DE_TEST_ASSERT(!(sdkVersion >= 26)); /* __ANDROID_API_O__ */
+#endif // !defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
+#if !defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)
+ // When testing AHB on Android-P and newer the CTS must be compiled against API28 or newer.
+ DE_TEST_ASSERT(!(sdkVersion >= 28)); /*__ANDROID_API_P__ */
+#endif // !defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)
+ return sdkVersion;
+}
+
+bool AndroidHardwareBufferExternalApi::supportsAhb()
+{
+ return (checkAnbApiBuild() >= __ANDROID_API_O__);
+}
+
+AndroidHardwareBufferExternalApi::AndroidHardwareBufferExternalApi()
+{
+ deInt32 sdkVersion = checkAnbApiBuild();
+ if(sdkVersion >= __ANDROID_API_O__)
+ {
+#if defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
+ if (!loadAhbDynamicApis(sdkVersion))
+ {
+ // Couldn't load Android AHB system APIs.
+ DE_TEST_ASSERT(false);
+ }
+#else
+ // Invalid Android AHB APIs configuration. Please check the instructions on how to build NDK for Android.
+ DE_TEST_ASSERT(false);
+#endif // defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
+ }
+}
+
+AndroidHardwareBufferExternalApi::~AndroidHardwareBufferExternalApi()
+{
+}
+
+#if defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
+typedef int (*pfn_system_property_get)(const char *, char *);
+typedef int (*pfnAHardwareBuffer_allocate)(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer);
+typedef void (*pfnAHardwareBuffer_describe)(const AHardwareBuffer* buffer, AHardwareBuffer_Desc* outDesc);
+typedef void (*pfnAHardwareBuffer_acquire)(AHardwareBuffer* buffer);
+typedef void (*pfnAHardwareBuffer_release)(AHardwareBuffer* buffer);
+
+struct AhbFunctions
+{
+ pfnAHardwareBuffer_allocate allocate;
+ pfnAHardwareBuffer_describe describe;
+ pfnAHardwareBuffer_acquire acquire;
+ pfnAHardwareBuffer_release release;
+};
+
+static AhbFunctions ahbFunctions;
+
+static bool ahbFunctionsLoaded(AhbFunctions* pAhbFunctions)
+{
+ static bool ahbApiLoaded = false;
+ if (ahbApiLoaded ||
+ ((pAhbFunctions->allocate != DE_NULL) &&
+ (pAhbFunctions->describe != DE_NULL) &&
+ (pAhbFunctions->acquire != DE_NULL) &&
+ (pAhbFunctions->release != DE_NULL)))
+ {
+ ahbApiLoaded = true;
+ return true;
+ }
+ return false;
+}
+
+bool AndroidHardwareBufferExternalApi::loadAhbDynamicApis(deInt32 sdkVersion)
+{
+ if(sdkVersion >= __ANDROID_API_O__)
+ {
+ if (!ahbFunctionsLoaded(&ahbFunctions))
+ {
+ de::DynamicLibrary libnativewindow("libnativewindow.so");
+ ahbFunctions.allocate = reinterpret_cast<pfnAHardwareBuffer_allocate>(libnativewindow.getFunction("AHardwareBuffer_allocate"));
+ ahbFunctions.describe = reinterpret_cast<pfnAHardwareBuffer_describe>(libnativewindow.getFunction("AHardwareBuffer_describe"));
+ ahbFunctions.acquire = reinterpret_cast<pfnAHardwareBuffer_acquire>(libnativewindow.getFunction("AHardwareBuffer_acquire"));
+ ahbFunctions.release = reinterpret_cast<pfnAHardwareBuffer_release>(libnativewindow.getFunction("AHardwareBuffer_release"));
+
+ return ahbFunctionsLoaded(&ahbFunctions);
+
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+class AndroidHardwareBufferExternalApi26 : public AndroidHardwareBufferExternalApi
+{
+public:
+
+ virtual vk::pt::AndroidHardwareBufferPtr allocate(deUint32 width, deUint32 height, deUint32 layers, deUint32 format, deUint64 usage);
+ virtual void acquire(vk::pt::AndroidHardwareBufferPtr buffer);
+ virtual void release(vk::pt::AndroidHardwareBufferPtr buffer);
+ virtual void describe(const vk::pt::AndroidHardwareBufferPtr buffer,
+ deUint32* width,
+ deUint32* height,
+ deUint32* layers,
+ deUint32* format,
+ deUint64* usage,
+ deUint32* stride);
+ virtual deUint64 vkUsageToAhbUsage(vk::VkImageUsageFlagBits vkFlag);
+ virtual deUint64 vkCreateToAhbUsage(vk::VkImageCreateFlagBits vkFlag);
+ virtual deUint32 vkFormatToAhbFormat(vk::VkFormat vkFormat);
+ virtual deUint64 mustSupportAhbUsageFlags();
+ virtual bool ahbFormatIsBlob(deUint32 ahbFormat) { return (ahbFormat == AHARDWAREBUFFER_FORMAT_BLOB); };
+
+ AndroidHardwareBufferExternalApi26() : AndroidHardwareBufferExternalApi() {};
+ virtual ~AndroidHardwareBufferExternalApi26() {};
+
+private:
+ // Stop the compiler generating methods of copy the object
+ AndroidHardwareBufferExternalApi26(AndroidHardwareBufferExternalApi26 const& copy); // Not Implemented
+ AndroidHardwareBufferExternalApi26& operator=(AndroidHardwareBufferExternalApi26 const& copy); // Not Implemented
+};
+
+vk::pt::AndroidHardwareBufferPtr AndroidHardwareBufferExternalApi26::allocate( deUint32 width,
+ deUint32 height,
+ deUint32 layers,
+ deUint32 format,
+ deUint64 usage)
+{
+ AHardwareBuffer_Desc hbufferdesc = {
+ width,
+ height,
+ layers, // number of images
+ format,
+ usage,
+ 0u, // Stride in pixels, ignored for AHardwareBuffer_allocate()
+ 0u, // Initialize to zero, reserved for future use
+ 0u // Initialize to zero, reserved for future use
+ };
+
+ AHardwareBuffer* hbuffer = DE_NULL;
+ ahbFunctions.allocate(&hbufferdesc, &hbuffer);
+
+ return vk::pt::AndroidHardwareBufferPtr(hbuffer);
+}
+
+void AndroidHardwareBufferExternalApi26::acquire(vk::pt::AndroidHardwareBufferPtr buffer)
+{
+ ahbFunctions.acquire(static_cast<AHardwareBuffer*>(buffer.internal));
+}
+
+void AndroidHardwareBufferExternalApi26::release(vk::pt::AndroidHardwareBufferPtr buffer)
+{
+ ahbFunctions.release(static_cast<AHardwareBuffer*>(buffer.internal));
+}
+
+void AndroidHardwareBufferExternalApi26::describe( const vk::pt::AndroidHardwareBufferPtr buffer,
+ deUint32* width,
+ deUint32* height,
+ deUint32* layers,
+ deUint32* format,
+ deUint64* usage,
+ deUint32* stride)
+{
+ AHardwareBuffer_Desc desc;
+ ahbFunctions.describe(static_cast<const AHardwareBuffer*>(buffer.internal), &desc);
+ if (width) *width = desc.width;
+ if (height) *height = desc.height;
+ if (layers) *layers = desc.layers;
+ if (format) *format = desc.format;
+ if (usage) *usage = desc.usage;
+ if (stride) *stride = desc.stride;
+}
+
+deUint64 AndroidHardwareBufferExternalApi26::vkUsageToAhbUsage(vk::VkImageUsageFlagBits vkFlags)
+{
+ switch(vkFlags)
+ {
+ case vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT:
+ case vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT:
+ // No AHB equivalent.
+ return 0u;
+ case vk::VK_IMAGE_USAGE_SAMPLED_BIT:
+ return AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
+ case vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT:
+ return AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
+ case vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT:
+ return AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
+ default:
+ return 0u;
+ }
+}
+
+deUint64 AndroidHardwareBufferExternalApi26::vkCreateToAhbUsage(vk::VkImageCreateFlagBits vkFlags)
+{
+ switch(vkFlags)
+ {
+ case vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT:
+ case vk::VK_IMAGE_CREATE_EXTENDED_USAGE_BIT:
+ // No AHB equivalent.
+ return 0u;
+ case vk::VK_IMAGE_CREATE_PROTECTED_BIT:
+ return AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
+ default:
+ return 0u;
+ }
+}
+
+deUint32 AndroidHardwareBufferExternalApi26::vkFormatToAhbFormat(vk::VkFormat vkFormat)
+{
+ switch(vkFormat)
+ {
+ case vk::VK_FORMAT_R8G8B8A8_UNORM:
+ return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
+ case vk::VK_FORMAT_R8G8B8_UNORM:
+ return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;
+ case vk::VK_FORMAT_R5G6B5_UNORM_PACK16:
+ return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
+ case vk::VK_FORMAT_R16G16B16A16_SFLOAT:
+ return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
+ case vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32:
+ return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
+ default:
+ return 0u;
+ }
+}
+
+deUint64 AndroidHardwareBufferExternalApi26::mustSupportAhbUsageFlags()
+{
+ return (AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT);
+}
+
+#if defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)
+class AndroidHardwareBufferExternalApi28 : public AndroidHardwareBufferExternalApi26
+{
+public:
+
+ virtual deUint64 vkCreateToAhbUsage(vk::VkImageCreateFlagBits vkFlag);
+ virtual deUint64 mustSupportAhbUsageFlags();
+
+ AndroidHardwareBufferExternalApi28() : AndroidHardwareBufferExternalApi26() {};
+ virtual ~AndroidHardwareBufferExternalApi28() {};
+
+private:
+ // Stop the compiler generating methods of copy the object
+ AndroidHardwareBufferExternalApi28(AndroidHardwareBufferExternalApi28 const& copy); // Not Implemented
+ AndroidHardwareBufferExternalApi28& operator=(AndroidHardwareBufferExternalApi28 const& copy); // Not Implemented
+};
+
+deUint64 AndroidHardwareBufferExternalApi28::vkCreateToAhbUsage(vk::VkImageCreateFlagBits vkFlags)
+{
+ switch(vkFlags)
+ {
+ case vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT:
+ return AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP;
+ default:
+ return AndroidHardwareBufferExternalApi26::vkCreateToAhbUsage(vkFlags);
+ }
+}
+
+deUint64 AndroidHardwareBufferExternalApi28::mustSupportAhbUsageFlags()
+{
+ return AndroidHardwareBufferExternalApi26::mustSupportAhbUsageFlags() | AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP | AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE;
+}
+
+#endif // defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)
+#endif // defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
+#endif // (DE_OS == DE_OS_ANDROID)
+
+AndroidHardwareBufferExternalApi* AndroidHardwareBufferExternalApi::getInstance()
+{
+#if (DE_OS == DE_OS_ANDROID)
+ deInt32 sdkVersion = checkAnbApiBuild();
+#if defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
+# if defined(__ANDROID_API_P__) && (DE_ANDROID_API >= __ANDROID_API_P__)
+ if (sdkVersion >= __ANDROID_API_P__ )
+ {
+ static AndroidHardwareBufferExternalApi28 api28Instance;
+ return &api28Instance;
+ }
+ else
+# elif defined(__ANDROID_API_O__) && (DE_ANDROID_API >= __ANDROID_API_O__)
+ if (sdkVersion >= __ANDROID_API_O__ )
+ {
+ static AndroidHardwareBufferExternalApi26 api26Instance;
+ return &api26Instance;
+ }
+# endif
+#endif // defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
+ DE_UNREF(sdkVersion);
+#endif // DE_OS == DE_OS_ANDROID
+ return DE_NULL;
+}
+
} // ExternalMemoryUtil
} // vkt