Backport post-P AHardwareBuffer changes from Khronos CTS
authorChris Forbes <chrisforbes@google.com>
Thu, 19 Jul 2018 23:47:11 +0000 (16:47 -0700)
committerChris Forbes <chrisforbes@google.com>
Tue, 24 Jul 2018 22:27:27 +0000 (22:27 +0000)
This includes all the changes approved by Khronos to these tests between
the time we initially landed them for P CTS, and the upstream changes
being accepted.

Bug: b/75981905, b/109927547
Change-Id: I23550489a55af36089451384f75f62ae54f99c27

external/vulkancts/modules/vulkan/api/vktApiExternalMemoryTests.cpp
external/vulkancts/modules/vulkan/vktExternalMemoryUtil.cpp
external/vulkancts/modules/vulkan/vktExternalMemoryUtil.hpp

index 9724e19..6186423 100644 (file)
 #      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;
 
@@ -3806,75 +3794,19 @@ de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx, vk:
        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,
@@ -3887,14 +3819,15 @@ bool ValidateAHardwareBuffer(vk::VkFormat format, deUint32 requiredAhbUsage, con
                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);
@@ -3902,20 +3835,24 @@ bool ValidateAHardwareBuffer(vk::VkFormat format, deUint32 requiredAhbUsage, con
        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[]            =
        {
@@ -3932,29 +3869,28 @@ tcu::TestStatus testAndroidHardwareBufferImageFormat(Context& context, vk::VkFor
                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++)
                {
@@ -3962,7 +3898,7 @@ tcu::TestStatus testAndroidHardwareBufferImageFormat(Context& context, vk::VkFor
                        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.
@@ -3973,123 +3909,144 @@ tcu::TestStatus testAndroidHardwareBufferImageFormat(Context& context, vk::VkFor
                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)
@@ -4259,6 +4216,7 @@ de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx, vk
                {
                        const vk::VkFormat      format                  = ahbFormats[ahbFormatNdx];
                        const std::string       testCaseName    = getFormatCaseName(format);
+
                        addFunctionCase(formatGroup.get(), testCaseName, "", testAndroidHardwareBufferImageFormat, format);
                }
 
index b7e2095..1e8f82f 100644 (file)
 #      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
@@ -119,15 +124,13 @@ NativeHandle::NativeHandle (const NativeHandle& other)
                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");
 }
@@ -195,16 +198,12 @@ void NativeHandle::reset (void)
                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;
@@ -503,6 +502,10 @@ void getMemoryNative (const vk::DeviceInterface&                                   vkd,
        }
        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,
@@ -1014,13 +1017,17 @@ static vk::Move<vk::VkDeviceMemory> importMemory (const vk::DeviceInterface&
 
                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 =
                {
@@ -1046,7 +1053,6 @@ static vk::Move<vk::VkDeviceMemory> importMemory (const vk::DeviceInterface&
 
                return memory;
        }
-#endif // (USE_ANDROID_O_HARDWARE_BUFFER)
        else
        {
                DE_FATAL("Unknown external memory type");
@@ -1125,8 +1131,8 @@ vk::Move<vk::VkImage> createExternalImage (const vk::DeviceInterface&                                     vkd,
                                                                                   vk::VkImageTiling                                                    tiling,
                                                                                   vk::VkImageCreateFlags                                               createFlags,
                                                                                   vk::VkImageUsageFlags                                                usageFlags,
-                                                                                  deUint32 mipLevels,
-                                                                                  deUint32 arrayLayers)
+                                                                                  deUint32                                                                             mipLevels,
+                                                                                  deUint32                                                                             arrayLayers)
 {
        const vk::VkExternalMemoryImageCreateInfo               externalCreateInfo      =
        {
@@ -1156,5 +1162,320 @@ vk::Move<vk::VkImage> createExternalImage (const vk::DeviceInterface&                                   vkd,
        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
index ae573a8..f448326 100644 (file)
@@ -70,6 +70,83 @@ private:
        NativeHandle&                                           operator=                                       (const NativeHandle&);
 };
 
+class AndroidHardwareBufferExternalApi
+{
+public:
+
+       /**
+        * getInstance obtains the object, that provides an interface to AHB system APIs .
+        * If the AHB system API is not supported or if it is not built as supported with the CTS,
+        * then this function would return a null object.
+        */
+       static AndroidHardwareBufferExternalApi* getInstance();
+
+       /* Is AndroidHardwareBuffer supported? */
+       static bool supportsAhb();
+
+       /**
+        * Allocates a buffer that backs an AHardwareBuffer using the passed parameter as follows:
+        * width;      - width in pixels
+        * height;     - height in pixels
+        * layers;     - number of images
+        * format;     - One of AHARDWAREBUFFER_FORMAT_*
+        * usage;      - Combination of AHARDWAREBUFFER_USAGE_*
+        *
+        * Returns a valid AndroidHardwareBufferPtr object on success, or an null AndroidHardwareBufferPtr if
+        * the allocation fails for any reason.
+        */
+       virtual vk::pt::AndroidHardwareBufferPtr allocate(deUint32 width, deUint32  height, deUint32 layers, deUint32  format, deUint64 usage) = 0;
+
+       /**
+        * Acquire a reference on the given AHardwareBuffer object.  This prevents the
+        * object from being deleted until the last reference is removed.
+        */
+       virtual void acquire(vk::pt::AndroidHardwareBufferPtr buffer) = 0;
+
+       /**
+        * Remove a reference that was previously acquired with
+        * AHardwareBuffer_acquire().
+        */
+       virtual void release(vk::pt::AndroidHardwareBufferPtr buffer) = 0;
+
+       /**
+        * Return a description of the AHardwareBuffer in the passed in the following fields, if not NULL:
+        * width;      - width in pixels
+        * height;     - height in pixels
+        * layers;     - number of images
+        * format;     - One of AHARDWAREBUFFER_FORMAT_*
+        * usage;      - Combination of AHARDWAREBUFFER_USAGE_*
+        *
+        */
+       virtual void describe(const vk::pt::AndroidHardwareBufferPtr buffer,
+                                 deUint32* width,
+                                 deUint32* height,
+                                 deUint32* layers,
+                                 deUint32* format,
+                                 deUint64* usage,
+                                 deUint32* stride) = 0;
+
+
+       virtual deUint64 vkUsageToAhbUsage(vk::VkImageUsageFlagBits vkFlag) = 0;
+       virtual deUint64 vkCreateToAhbUsage(vk::VkImageCreateFlagBits vkFlag) = 0;
+       virtual deUint32 vkFormatToAhbFormat(vk::VkFormat vkFormat) = 0;
+       virtual deUint64 mustSupportAhbUsageFlags() = 0;
+       virtual bool     ahbFormatIsBlob(deUint32 format) = 0;
+
+       virtual ~AndroidHardwareBufferExternalApi();
+
+protected:
+       // Protected Constructor
+       AndroidHardwareBufferExternalApi();
+
+private:
+       // Stop the compiler generating methods of copy the object
+       AndroidHardwareBufferExternalApi(AndroidHardwareBufferExternalApi const& copy);            // Not Implemented
+       AndroidHardwareBufferExternalApi& operator=(AndroidHardwareBufferExternalApi const& copy); // Not Implemented
+
+       static bool loadAhbDynamicApis(deInt32 sdkVersion);
+};
+
 const char*                                            externalSemaphoreTypeToName     (vk::VkExternalSemaphoreHandleTypeFlagBits      type);
 const char*                                            externalFenceTypeToName         (vk::VkExternalFenceHandleTypeFlagBits          type);
 const char*                                            externalMemoryTypeToName        (vk::VkExternalMemoryHandleTypeFlagBits         type);
@@ -236,8 +313,8 @@ vk::Move<vk::VkImage>                       createExternalImage                                     (const vk::DeviceInterface&
                                                                                                                                         vk::VkImageTiling                                                      tiling,
                                                                                                                                         vk::VkImageCreateFlags                                         createFlags,
                                                                                                                                         vk::VkImageUsageFlags                                          usageFlags,
-                                                                                                                                        deUint32 mipLevels = 1u,
-                                                                                                                                        deUint32 arrayLayers = 1u);
+                                                                                                                                        deUint32                                                                       mipLevels = 1u,
+                                                                                                                                        deUint32                                                                       arrayLayers = 1u);
 
 } // ExternalMemoryUtil
 } // vkt