Add initial stub implementation of AHB

Bug: b/141698760
Change-Id: Icb293abc63a46c41a5165cdaa2061c23926b2568
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/39988
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Chris Forbes <chrisforbes@google.com>
diff --git a/src/Android.bp b/src/Android.bp
index 79bb946..3d957d6 100644
--- a/src/Android.bp
+++ b/src/Android.bp
@@ -47,7 +47,7 @@
             relative_install_path: "egl",
             header_libs: [
                 "swiftshader_platform_headers",
-		"libnativebase_headers",
+                "libnativebase_headers",
             ],
             shared_libs: [
                 "libnativewindow",
@@ -65,7 +65,7 @@
             header_libs: [
                 "swiftshader_host_headers",
                 "swiftshader_platform_headers",
-		"libnativebase_headers",
+                "libnativebase_headers",
             ],
 
             // Pretend to build for Android
@@ -549,7 +549,7 @@
             relative_install_path: "hw",
             header_libs: [
                 "swiftshader_platform_headers",
-				"vulkan_headers",
+                "vulkan_headers",
                 "hwvulkan_headers",
             ],
             shared_libs: [
@@ -559,6 +559,9 @@
                 "libsync",
                 "liblog",
             ],
+            static_libs: [
+                "libarect",
+            ],
         },
     },
 }
@@ -568,6 +571,7 @@
 
     cflags: [
         "-DLOG_TAG=\"swiftshader\"",
+        "-DSWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER",
     ],
 
     srcs: [
diff --git a/src/Vulkan/VkDeviceMemory.cpp b/src/Vulkan/VkDeviceMemory.cpp
index 0e84d74..c524570 100644
--- a/src/Vulkan/VkDeviceMemory.cpp
+++ b/src/Vulkan/VkDeviceMemory.cpp
@@ -13,6 +13,8 @@
 // limitations under the License.
 
 #include "VkDeviceMemory.hpp"
+#include "VkBuffer.hpp"
+#include "VkImage.hpp"
 
 #include "VkConfig.h"
 
@@ -42,6 +44,13 @@
 	}
 #endif
 
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+	virtual VkResult exportAhb(struct AHardwareBuffer **pAhb) const
+	{
+		return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+	}
+#endif
+
 protected:
 	ExternalBase() = default;
 };
@@ -129,6 +138,14 @@
 #	endif
 #endif
 
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+#	if defined(__ANDROID__)
+#		include "VkDeviceMemoryExternalAndroid.hpp"
+#	else
+#		error "Missing VK_ANDROID_external_memory_android_hardware_buffer implementation for this platform!"
+#	endif
+#endif
+
 namespace vk {
 
 static void findTraits(const VkMemoryAllocateInfo *pAllocateInfo,
@@ -140,6 +157,12 @@
 		return;
 	}
 #endif
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+	if(parseCreateInfo<AHardwareBufferExternalMemory>(pAllocateInfo, pTraits))
+	{
+		return;
+	}
+#endif
 	parseCreateInfo<DeviceMemoryHostExternalBase>(pAllocateInfo, pTraits);
 }
 
@@ -236,4 +259,16 @@
 }
 #endif
 
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+VkResult DeviceMemory::exportAhb(struct AHardwareBuffer **pAhb) const
+{
+	return external->exportAhb(pAhb);
+}
+
+VkResult DeviceMemory::getAhbProperties(const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties)
+{
+	return AHardwareBufferExternalMemory::getAhbProperties(buffer, pProperties);
+}
+#endif
+
 }  // namespace vk
diff --git a/src/Vulkan/VkDeviceMemory.hpp b/src/Vulkan/VkDeviceMemory.hpp
index 7ec0267..e99fa89 100644
--- a/src/Vulkan/VkDeviceMemory.hpp
+++ b/src/Vulkan/VkDeviceMemory.hpp
@@ -31,6 +31,11 @@
 	VkResult exportFd(int *pFd) const;
 #endif
 
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+	VkResult exportAhb(struct AHardwareBuffer **pAhb) const;
+	static VkResult getAhbProperties(const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties);
+#endif
+
 	void destroy(const VkAllocationCallbacks *pAllocator);
 	VkResult allocate();
 	VkResult map(VkDeviceSize offset, VkDeviceSize size, void **ppData);
diff --git a/src/Vulkan/VkDeviceMemoryExternalAndroid.hpp b/src/Vulkan/VkDeviceMemoryExternalAndroid.hpp
new file mode 100644
index 0000000..6cd2c93
--- /dev/null
+++ b/src/Vulkan/VkDeviceMemoryExternalAndroid.hpp
@@ -0,0 +1,156 @@
+// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "VkDebug.hpp"
+#include <android/hardware_buffer.h>
+
+#include <errno.h>
+#include <string.h>
+
+class AHardwareBufferExternalMemory : public vk::DeviceMemory::ExternalBase
+{
+public:
+	// Helper struct to parse the VkMemoryAllocateInfo.pNext chain and
+	// extract relevant information related to the handle type supported
+	// by this DeviceMemory::ExternalBase subclass.
+	struct AllocateInfo
+	{
+		bool importAhb = false;
+		bool exportAhb = false;
+		struct AHardwareBuffer *ahb = nullptr;
+		vk::Image *imageHandle = nullptr;
+		vk::Buffer *bufferHandle = nullptr;
+
+		AllocateInfo() = default;
+
+		// Parse the VkMemoryAllocateInfo.pNext chain to initialize an AllocateInfo.
+		AllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo)
+		{
+			const auto *createInfo = reinterpret_cast<const VkBaseInStructure *>(pAllocateInfo->pNext);
+			while(createInfo)
+			{
+				switch(createInfo->sType)
+				{
+					case VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID:
+					{
+						const auto *importInfo = reinterpret_cast<const VkImportAndroidHardwareBufferInfoANDROID *>(createInfo);
+						importAhb = true;
+						ahb = importInfo->buffer;
+					}
+					break;
+					case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO:
+					{
+						const auto *exportInfo = reinterpret_cast<const VkExportMemoryAllocateInfo *>(createInfo);
+
+						if(exportInfo->handleTypes != VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
+						{
+							UNIMPLEMENTED("exportInfo->handleTypes");
+						}
+						exportAhb = true;
+					}
+					break;
+					case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO:
+					{
+						// AHB requires dedicated allocation -- for images, the gralloc gets to decide the image layout,
+						// not us.
+						const auto *dedicatedAllocateInfo = reinterpret_cast<const VkMemoryDedicatedAllocateInfo *>(createInfo);
+						imageHandle = vk::Cast(dedicatedAllocateInfo->image);
+						bufferHandle = vk::Cast(dedicatedAllocateInfo->buffer);
+					}
+					break;
+
+					default:;
+				}
+				createInfo = createInfo->pNext;
+			}
+		}
+	};
+
+	static const VkExternalMemoryHandleTypeFlagBits typeFlagBit = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
+
+	static bool supportsAllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo)
+	{
+		AllocateInfo info(pAllocateInfo);
+		return (info.importAhb || info.exportAhb) && (info.bufferHandle || info.imageHandle);
+	}
+
+	explicit AHardwareBufferExternalMemory(const VkMemoryAllocateInfo *pAllocateInfo)
+	    : allocateInfo(pAllocateInfo)
+	{
+	}
+
+	~AHardwareBufferExternalMemory()
+	{
+		if(ahb)
+			AHardwareBuffer_release(ahb);
+	}
+
+	VkResult allocate(size_t size, void **pBuffer) override
+	{
+		if(allocateInfo.importAhb)
+		{
+			//ahb = allocateInfo.ahb;
+			//AHardwareBuffer_acquire(ahb);
+			// TODO: also allocate our internal shadow memory
+			return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+		}
+		else
+		{
+			ASSERT(allocateInfo.exportAhb);
+			// TODO: create and import the AHB
+			return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+		}
+
+		return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+		/*
+		void *addr = memfd.mapReadWrite(0, size);
+		if(!addr)
+		{
+			return VK_ERROR_MEMORY_MAP_FAILED;
+		}
+		*pBuffer = addr;
+		return VK_SUCCESS;
+		 */
+	}
+
+	void deallocate(void *buffer, size_t size) override
+	{
+		// FIXME
+	}
+
+	VkExternalMemoryHandleTypeFlagBits getFlagBit() const override
+	{
+		return typeFlagBit;
+	}
+
+	VkResult exportAhb(struct AHardwareBuffer **pAhb) const override
+	{
+		// Each call to vkGetMemoryAndroidHardwareBufferANDROID *must* return an Android hardware buffer with a new reference
+		// acquired in addition to the reference held by the VkDeviceMemory. To avoid leaking resources, the application *must*
+		// release the reference by calling AHardwareBuffer_release when it is no longer needed.
+		AHardwareBuffer_acquire(ahb);
+		*pAhb = ahb;
+		return VK_SUCCESS;
+	}
+
+	static VkResult getAhbProperties(const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties)
+	{
+		UNIMPLEMENTED("getAhbProperties");
+		return VK_SUCCESS;
+	}
+
+private:
+	struct AHardwareBuffer *ahb = nullptr;
+	AllocateInfo allocateInfo;
+};
diff --git a/src/Vulkan/VkGetProcAddress.cpp b/src/Vulkan/VkGetProcAddress.cpp
index fe7f282..796596b 100644
--- a/src/Vulkan/VkGetProcAddress.cpp
+++ b/src/Vulkan/VkGetProcAddress.cpp
@@ -371,6 +371,16 @@
 	        MAKE_VULKAN_DEVICE_ENTRY(vkGetMemoryFdPropertiesKHR),
 	    } },
 #endif
+
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+	// VK_ANDROID_external_memory_android_hardware_buffer
+	{
+	    VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME,
+	    {
+	        MAKE_VULKAN_DEVICE_ENTRY(vkGetAndroidHardwareBufferPropertiesANDROID),
+	        MAKE_VULKAN_DEVICE_ENTRY(vkGetMemoryAndroidHardwareBufferANDROID),
+	    } },
+#endif
 };
 
 #undef MAKE_VULKAN_DEVICE_ENTRY
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp
index a208fc8..10941ef 100644
--- a/src/Vulkan/VkPhysicalDevice.cpp
+++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -34,6 +34,15 @@
 		return;
 	}
 #endif
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+	if(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
+	{
+		properties->compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
+		properties->exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
+		properties->externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT;
+		return;
+	}
+#endif
 	properties->compatibleHandleTypes = 0;
 	properties->exportFromImportedHandleTypes = 0;
 	properties->externalMemoryFeatures = 0;
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index 6af8bd9..72d8e69 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -243,6 +243,9 @@
 	// (from KHR_swapchain v70) to vkBindImageMemory2.
 	{ VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME, 7 },
 #endif
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+	{ VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME, VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION },
+#endif
 #if SWIFTSHADER_EXTERNAL_SEMAPHORE_OPAQUE_FD
 	{ VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, VK_KHR_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION },
 #endif
@@ -815,17 +818,31 @@
 				}
 				break;
 			}
+#endif  // SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
 			case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO:
 			{
 				auto *exportInfo = reinterpret_cast<const VkExportMemoryAllocateInfo *>(allocationInfo);
-				if(exportInfo->handleTypes != VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT)
+				switch(exportInfo->handleTypes)
 				{
-					UNSUPPORTED("exportInfo->handleTypes %u", exportInfo->handleTypes);
-					return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+#if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
+					case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
+						break;
+#endif
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+					case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID:
+						break;
+#endif
+					default:
+						UNSUPPORTED("exportInfo->handleTypes %u", exportInfo->handleTypes);
+						return VK_ERROR_INVALID_EXTERNAL_HANDLE;
 				}
 				break;
 			}
-#endif  // SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+			case VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID:
+				// Ignore
+				break;
+#endif  // SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
 			default:
 				WARN("pAllocateInfo->pNext sType = %s", vk::Stringify(allocationInfo->sType).c_str());
 				break;
@@ -899,6 +916,24 @@
 }
 #endif  // SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
 
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryAndroidHardwareBufferANDROID(VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo, struct AHardwareBuffer **pBuffer)
+{
+	TRACE("(VkDevice device = %p, const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo = %p, struct AHardwareBuffer **pBuffer = %p)",
+	      device, pInfo, pBuffer);
+
+	return vk::Cast(pInfo->memory)->exportAhb(pBuffer);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetAndroidHardwareBufferPropertiesANDROID(VkDevice device, const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties)
+{
+	TRACE("(VkDevice device = %p, const struct AHardwareBuffer *buffer = %p, VkAndroidHardwareBufferPropertiesANDROID *pProperties = %p)",
+	      device, buffer, pProperties);
+
+	return vk::DeviceMemory::getAhbProperties(buffer, pProperties);
+}
+#endif  // SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+
 VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void **ppData)
 {
 	TRACE("(VkDevice device = %p, VkDeviceMemory memory = %p, VkDeviceSize offset = %d, VkDeviceSize size = %d, VkMemoryMapFlags flags = %d, void** ppData = %p)",