Support Gralloc3 in SwiftShader

Also moves the -DHAVE_GRALLOC cflags away from the
host build as hosts do not have gralloc and mapper
3 does not have a header only library available.

Bug: b/157902551
Test: launch_cvd w/ Cuttlefish ashmem Gralloc0
Test: launch_cvd w/ Cuttlefish minigbm Gralloc3
Change-Id: I99da611a2b72f9d39df32ab9883dc52f2c081217
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/46408
Presubmit-Ready: Jason Macnak <natsu@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Jason Macnak <natsu@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Android.bp b/src/Android.bp
index 22c0c62..621b4d0 100644
--- a/src/Android.bp
+++ b/src/Android.bp
@@ -26,7 +26,6 @@
         "-D__STDC_LIMIT_MACROS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
-        "-DHAVE_GRALLOC1",
         "-DNO_SANITIZE_FUNCTION=",
         // FIXME: Use <android/api-level.h> instead?
         "-DANDROID_PLATFORM_SDK_VERSION=10000",
@@ -44,17 +43,24 @@
 
     target: {
         android: {
+            cflags: [
+                "-DHAVE_GRALLOC1",
+                "-DHAVE_GRALLOC3",
+            ],
             relative_install_path: "egl",
             header_libs: [
                 "swiftshader_platform_headers",
                 "libnativebase_headers",
             ],
             shared_libs: [
+                "android.hardware.graphics.mapper@3.0",
                 "libnativewindow",
                 "libhardware",
+                "libhidlbase",
                 "libcutils",
                 "libsync",
                 "liblog",
+                "libutils",
             ],
             static_libs: [
                 "libarect",
@@ -539,6 +545,7 @@
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
         "-DHAVE_GRALLOC1",
+        "-DHAVE_GRALLOC3",
         "-DNO_SANITIZE_FUNCTION=",
         // FIXME: Use <android/api-level.h> instead?
         "-DANDROID_PLATFORM_SDK_VERSION=10000",
@@ -576,11 +583,14 @@
                 "hwvulkan_headers",
             ],
             shared_libs: [
+                "android.hardware.graphics.mapper@3.0",
                 "libnativewindow",
                 "libhardware",
+                "libhidlbase",
                 "libcutils",
                 "libsync",
                 "liblog",
+                "libutils",
             ],
             static_libs: [
                 "libarect",
diff --git a/src/Common/GrallocAndroid.cpp b/src/Common/GrallocAndroid.cpp
index c877e9933..6a12b2b 100644
--- a/src/Common/GrallocAndroid.cpp
+++ b/src/Common/GrallocAndroid.cpp
@@ -16,7 +16,12 @@
 #include "Debug.hpp"
 
 #ifdef HAVE_GRALLOC1
-#include <sync/sync.h>
+#	include <sync/sync.h>
+#endif
+#ifdef HAVE_GRALLOC3
+using V3Error = android::hardware::graphics::mapper::V3_0::Error;
+using V3Mapper = android::hardware::graphics::mapper::V3_0::IMapper;
+using android::hardware::hidl_handle;
 #endif
 
 GrallocModule *GrallocModule::getInstance()
@@ -27,37 +32,109 @@
 
 GrallocModule::GrallocModule()
 {
+#ifdef HAVE_GRALLOC3
+	m_gralloc3_mapper = V3Mapper::getService();
+	if(m_gralloc3_mapper != nullptr)
+	{
+		return;
+	}
+#endif
+
 	const hw_module_t *module = nullptr;
 	hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
 
 	m_major_version = (module->module_api_version >> 8) & 0xff;
 	switch(m_major_version)
 	{
-	case 0:
-		m_module = reinterpret_cast<const gralloc_module_t*>(module);
-		break;
-	case 1:
+		case 0:
+			m_module = reinterpret_cast<const gralloc_module_t *>(module);
+			break;
+		case 1:
 #ifdef HAVE_GRALLOC1
-		gralloc1_open(module, &m_gralloc1_device);
-		m_gralloc1_lock = (GRALLOC1_PFN_LOCK) m_gralloc1_device->getFunction(m_gralloc1_device, GRALLOC1_FUNCTION_LOCK);
-		m_gralloc1_unlock = (GRALLOC1_PFN_UNLOCK)m_gralloc1_device->getFunction(m_gralloc1_device, GRALLOC1_FUNCTION_UNLOCK);
-		break;
+			gralloc1_open(module, &m_gralloc1_device);
+			m_gralloc1_lock = (GRALLOC1_PFN_LOCK)m_gralloc1_device->getFunction(m_gralloc1_device, GRALLOC1_FUNCTION_LOCK);
+			m_gralloc1_unlock = (GRALLOC1_PFN_UNLOCK)m_gralloc1_device->getFunction(m_gralloc1_device, GRALLOC1_FUNCTION_UNLOCK);
+			break;
 #endif
-	default:
-		TRACE("unknown gralloc major version (%d)", m_major_version);
-		break;
+		default:
+			TRACE("unknown gralloc major version (%d)", m_major_version);
+			break;
 	}
 }
 
+int GrallocModule::import(buffer_handle_t handle, buffer_handle_t *imported_handle)
+{
+#ifdef HAVE_GRALLOC3
+	if(m_gralloc3_mapper != nullptr)
+	{
+		V3Error error;
+		auto ret = m_gralloc3_mapper->importBuffer(handle,
+		                                           [&](const auto &tmp_err, const auto &tmp_buf) {
+			                                           error = tmp_err;
+			                                           if(error == V3Error::NONE)
+			                                           {
+				                                           *imported_handle = static_cast<buffer_handle_t>(tmp_buf);
+			                                           }
+		                                           });
+		return ret.isOk() && error == V3Error::NONE ? 0 : -1;
+	}
+#endif
+
+	*imported_handle = handle;
+	return 0;
+}
+
+int GrallocModule::release(buffer_handle_t handle)
+{
+#ifdef HAVE_GRALLOC3
+	if(m_gralloc3_mapper != nullptr)
+	{
+		native_handle_t *native_handle = const_cast<native_handle_t *>(handle);
+		return m_gralloc3_mapper->freeBuffer(native_handle).isOk() ? 0 : 1;
+	}
+#endif
+
+	return 0;
+}
+
 int GrallocModule::lock(buffer_handle_t handle, int usage, int left, int top, int width, int height, void **vaddr)
 {
+#ifdef HAVE_GRALLOC3
+	if(m_gralloc3_mapper != nullptr)
+	{
+		native_handle_t *native_handle = const_cast<native_handle_t *>(handle);
+
+		V3Mapper::Rect rect;
+		rect.left = left;
+		rect.top = top;
+		rect.width = width;
+		rect.height = height;
+
+		hidl_handle empty_fence_handle;
+
+		V3Error error;
+		auto ret = m_gralloc3_mapper->lock(native_handle, usage, rect, empty_fence_handle,
+		                                   [&](const auto &tmp_err,
+		                                       const auto &tmp_vaddr,
+		                                       const auto & /*bytes_per_pixel*/,
+		                                       const auto & /*bytes_per_stride*/) {
+			                                   error = tmp_err;
+			                                   if(tmp_err == V3Error::NONE)
+			                                   {
+				                                   *vaddr = tmp_vaddr;
+			                                   }
+		                                   });
+		return ret.isOk() && error == V3Error::NONE ? 0 : -1;
+	}
+#endif
+
 	switch(m_major_version)
 	{
-	case 0:
+		case 0:
 		{
 			return m_module->lock(m_module, handle, usage, left, top, width, height, vaddr);
 		}
-	case 1:
+		case 1:
 #ifdef HAVE_GRALLOC1
 		{
 			gralloc1_rect_t outRect{};
@@ -68,7 +145,7 @@
 			return m_gralloc1_lock(m_gralloc1_device, handle, usage, usage, &outRect, vaddr, -1);
 		}
 #endif
-	default:
+		default:
 		{
 			TRACE("no gralloc module to lock");
 			return -1;
@@ -78,18 +155,32 @@
 
 int GrallocModule::unlock(buffer_handle_t handle)
 {
+#ifdef HAVE_GRALLOC3
+	if(m_gralloc3_mapper != nullptr)
+	{
+		native_handle_t *native_handle = const_cast<native_handle_t *>(handle);
+
+		V3Error error;
+		auto ret = m_gralloc3_mapper->unlock(native_handle,
+		                                     [&](const auto &tmp_err, const auto &) {
+			                                     error = tmp_err;
+		                                     });
+		return ret.isOk() && error == V3Error::NONE ? 0 : -1;
+	}
+#endif
+
 	switch(m_major_version)
 	{
-	case 0:
+		case 0:
 		{
 			return m_module->unlock(m_module, handle);
 		}
-	case 1:
+		case 1:
 #ifdef HAVE_GRALLOC1
 		{
 			int32_t fenceFd = -1;
 			int error = m_gralloc1_unlock(m_gralloc1_device, handle, &fenceFd);
-			if (!error)
+			if(!error)
 			{
 				sync_wait(fenceFd, -1);
 				close(fenceFd);
@@ -97,7 +188,7 @@
 			return error;
 		}
 #endif
-	default:
+		default:
 		{
 			TRACE("no gralloc module to unlock");
 			return -1;
diff --git a/src/Common/GrallocAndroid.hpp b/src/Common/GrallocAndroid.hpp
index fe0b15a..265608c 100644
--- a/src/Common/GrallocAndroid.hpp
+++ b/src/Common/GrallocAndroid.hpp
@@ -16,17 +16,22 @@
 #define GRALLOC_ANDROID
 
 #include <hardware/gralloc.h>
-
-#ifdef HAVE_GRALLOC1
 #include <hardware/gralloc1.h>
+#ifdef HAVE_GRALLOC3
+#	include <android/hardware/graphics/mapper/3.0/IMapper.h>
+#	include <utils/StrongPointer.h>
 #endif
 
-#include <unistd.h> // for close()
+#include <unistd.h>  // for close()
 
 class GrallocModule
 {
 public:
 	static GrallocModule *getInstance();
+
+	int import(buffer_handle_t handle, buffer_handle_t *imported_handle);
+	int release(buffer_handle_t handle);
+
 	int lock(buffer_handle_t handle, int usage, int left, int top, int width, int height, void **vaddr);
 	int unlock(buffer_handle_t handle);
 
@@ -39,6 +44,9 @@
 	GRALLOC1_PFN_LOCK m_gralloc1_lock = nullptr;
 	GRALLOC1_PFN_UNLOCK m_gralloc1_unlock = nullptr;
 #endif
+#ifdef HAVE_GRALLOC3
+	android::sp<android::hardware::graphics::mapper::V3_0::IMapper> m_gralloc3_mapper;
+#endif
 };
 
 #endif  // GRALLOC_ANDROID
diff --git a/src/Main/FrameBufferAndroid.cpp b/src/Main/FrameBufferAndroid.cpp
index 38247bf..345a0b6 100644
--- a/src/Main/FrameBufferAndroid.cpp
+++ b/src/Main/FrameBufferAndroid.cpp
@@ -54,7 +54,7 @@
 
 	FrameBufferAndroid::FrameBufferAndroid(ANativeWindow* window, int width, int height)
 		: FrameBuffer(width, height, false, false),
-		  nativeWindow(window), buffer(nullptr)
+			nativeWindow(window), buffer(nullptr)
 	{
 #ifndef ANDROID_NDK_BUILD
 		nativeWindow->common.incRef(&nativeWindow->common);
@@ -101,7 +101,7 @@
 		if((surfaceBuffer.width < width) || (surfaceBuffer.height < height))
 		{
 			TRACE("lock failed: buffer of %dx%d too small for window of %dx%d",
-			      surfaceBuffer.width, surfaceBuffer.height, width, height);
+						surfaceBuffer.width, surfaceBuffer.height, width, height);
 			return nullptr;
 		}
 
@@ -126,9 +126,14 @@
 		{
 			return nullptr;
 		}
-		if(GrallocModule::getInstance()->lock(buffer->handle,
-		                 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
-		                 0, 0, buffer->width, buffer->height, &framebuffer) != 0)
+		if(GrallocModule::getInstance()->import(buffer->handle, &bufferImportedHandle) != 0) {
+			TRACE("%s failed to import buffer %p", __FUNCTION__, buffer);
+			return nullptr;
+		}
+
+		if(GrallocModule::getInstance()->lock(bufferImportedHandle,
+										 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+										 0, 0, buffer->width, buffer->height, &framebuffer) != 0)
 		{
 			TRACE("%s failed to lock buffer %p", __FUNCTION__, buffer);
 			return nullptr;
@@ -137,7 +142,7 @@
 		if((buffer->width < width) || (buffer->height < height))
 		{
 			TRACE("lock failed: buffer of %dx%d too small for window of %dx%d",
-			      buffer->width, buffer->height, width, height);
+						buffer->width, buffer->height, width, height);
 			return nullptr;
 		}
 
@@ -179,10 +184,13 @@
 #ifdef ANDROID_NDK_BUILD
 		ANativeWindow_unlockAndPost(nativeWindow);
 #else
-		if(GrallocModule::getInstance()->unlock(buffer->handle) != 0)
+		if(GrallocModule::getInstance()->unlock(bufferImportedHandle) != 0)
 		{
 			TRACE("%s: badness unlock failed", __FUNCTION__);
 		}
+		if(GrallocModule::getInstance()->release(bufferImportedHandle) != 0) {
+			TRACE("%s: badness release failed", __FUNCTION__);
+		}
 #endif
 	}
 }
diff --git a/src/Main/FrameBufferAndroid.hpp b/src/Main/FrameBufferAndroid.hpp
index 2e9924c..1b76d2d 100644
--- a/src/Main/FrameBufferAndroid.hpp
+++ b/src/Main/FrameBufferAndroid.hpp
@@ -15,6 +15,8 @@
 #ifndef sw_FrameBufferAndroid_hpp
 #define sw_FrameBufferAndroid_hpp
 
+#include <cutils/native_handle.h>
+
 #include "Main/FrameBuffer.hpp"
 #include "Common/Debug.hpp"
 
@@ -41,6 +43,7 @@
 	private:
 		ANativeWindow *nativeWindow;
 		ANativeWindowBuffer *buffer;
+		buffer_handle_t bufferImportedHandle;
 	};
 }
 
diff --git a/src/OpenGL/common/Image.hpp b/src/OpenGL/common/Image.hpp
index dec2ad0..7fb0817 100644
--- a/src/OpenGL/common/Image.hpp
+++ b/src/OpenGL/common/Image.hpp
@@ -273,15 +273,20 @@
 		  nativeBuffer(nativeBuffer)
 	{
 		nativeBuffer->common.incRef(&nativeBuffer->common);
+
+		GrallocModule::getInstance()->import(nativeBuffer->handle, &nativeBufferImportedHandle);
 	}
 
 private:
 	ANativeWindowBuffer *nativeBuffer;
+	buffer_handle_t nativeBufferImportedHandle;
 
 	~AndroidNativeImage() override
 	{
 		sync();   // Wait for any threads that use this image to finish.
 
+		GrallocModule::getInstance()->release(nativeBufferImportedHandle);
+
 		nativeBuffer->common.decRef(&nativeBuffer->common);
 	}
 
@@ -340,14 +345,14 @@
 	void *lockNativeBuffer(int usage)
 	{
 		void *buffer = nullptr;
-		GrallocModule::getInstance()->lock(nativeBuffer->handle, usage, 0, 0, nativeBuffer->width, nativeBuffer->height, &buffer);
+		GrallocModule::getInstance()->lock(nativeBufferImportedHandle, usage, 0, 0, nativeBuffer->width, nativeBuffer->height, &buffer);
 
 		return buffer;
 	}
 
 	void unlockNativeBuffer()
 	{
-		GrallocModule::getInstance()->unlock(nativeBuffer->handle);
+		GrallocModule::getInstance()->unlock(nativeBufferImportedHandle);
 	}
 
 	void release() override
diff --git a/src/System/GrallocAndroid.cpp b/src/System/GrallocAndroid.cpp
index 83a60a6..6a12b2b 100644
--- a/src/System/GrallocAndroid.cpp
+++ b/src/System/GrallocAndroid.cpp
@@ -18,6 +18,11 @@
 #ifdef HAVE_GRALLOC1
 #	include <sync/sync.h>
 #endif
+#ifdef HAVE_GRALLOC3
+using V3Error = android::hardware::graphics::mapper::V3_0::Error;
+using V3Mapper = android::hardware::graphics::mapper::V3_0::IMapper;
+using android::hardware::hidl_handle;
+#endif
 
 GrallocModule *GrallocModule::getInstance()
 {
@@ -27,6 +32,14 @@
 
 GrallocModule::GrallocModule()
 {
+#ifdef HAVE_GRALLOC3
+	m_gralloc3_mapper = V3Mapper::getService();
+	if(m_gralloc3_mapper != nullptr)
+	{
+		return;
+	}
+#endif
+
 	const hw_module_t *module = nullptr;
 	hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
 
@@ -49,8 +62,72 @@
 	}
 }
 
+int GrallocModule::import(buffer_handle_t handle, buffer_handle_t *imported_handle)
+{
+#ifdef HAVE_GRALLOC3
+	if(m_gralloc3_mapper != nullptr)
+	{
+		V3Error error;
+		auto ret = m_gralloc3_mapper->importBuffer(handle,
+		                                           [&](const auto &tmp_err, const auto &tmp_buf) {
+			                                           error = tmp_err;
+			                                           if(error == V3Error::NONE)
+			                                           {
+				                                           *imported_handle = static_cast<buffer_handle_t>(tmp_buf);
+			                                           }
+		                                           });
+		return ret.isOk() && error == V3Error::NONE ? 0 : -1;
+	}
+#endif
+
+	*imported_handle = handle;
+	return 0;
+}
+
+int GrallocModule::release(buffer_handle_t handle)
+{
+#ifdef HAVE_GRALLOC3
+	if(m_gralloc3_mapper != nullptr)
+	{
+		native_handle_t *native_handle = const_cast<native_handle_t *>(handle);
+		return m_gralloc3_mapper->freeBuffer(native_handle).isOk() ? 0 : 1;
+	}
+#endif
+
+	return 0;
+}
+
 int GrallocModule::lock(buffer_handle_t handle, int usage, int left, int top, int width, int height, void **vaddr)
 {
+#ifdef HAVE_GRALLOC3
+	if(m_gralloc3_mapper != nullptr)
+	{
+		native_handle_t *native_handle = const_cast<native_handle_t *>(handle);
+
+		V3Mapper::Rect rect;
+		rect.left = left;
+		rect.top = top;
+		rect.width = width;
+		rect.height = height;
+
+		hidl_handle empty_fence_handle;
+
+		V3Error error;
+		auto ret = m_gralloc3_mapper->lock(native_handle, usage, rect, empty_fence_handle,
+		                                   [&](const auto &tmp_err,
+		                                       const auto &tmp_vaddr,
+		                                       const auto & /*bytes_per_pixel*/,
+		                                       const auto & /*bytes_per_stride*/) {
+			                                   error = tmp_err;
+			                                   if(tmp_err == V3Error::NONE)
+			                                   {
+				                                   *vaddr = tmp_vaddr;
+			                                   }
+		                                   });
+		return ret.isOk() && error == V3Error::NONE ? 0 : -1;
+	}
+#endif
+
 	switch(m_major_version)
 	{
 		case 0:
@@ -78,6 +155,20 @@
 
 int GrallocModule::unlock(buffer_handle_t handle)
 {
+#ifdef HAVE_GRALLOC3
+	if(m_gralloc3_mapper != nullptr)
+	{
+		native_handle_t *native_handle = const_cast<native_handle_t *>(handle);
+
+		V3Error error;
+		auto ret = m_gralloc3_mapper->unlock(native_handle,
+		                                     [&](const auto &tmp_err, const auto &) {
+			                                     error = tmp_err;
+		                                     });
+		return ret.isOk() && error == V3Error::NONE ? 0 : -1;
+	}
+#endif
+
 	switch(m_major_version)
 	{
 		case 0:
diff --git a/src/System/GrallocAndroid.hpp b/src/System/GrallocAndroid.hpp
index 09a361d..265608c 100644
--- a/src/System/GrallocAndroid.hpp
+++ b/src/System/GrallocAndroid.hpp
@@ -16,9 +16,10 @@
 #define GRALLOC_ANDROID
 
 #include <hardware/gralloc.h>
-
-#ifdef HAVE_GRALLOC1
-#	include <hardware/gralloc1.h>
+#include <hardware/gralloc1.h>
+#ifdef HAVE_GRALLOC3
+#	include <android/hardware/graphics/mapper/3.0/IMapper.h>
+#	include <utils/StrongPointer.h>
 #endif
 
 #include <unistd.h>  // for close()
@@ -27,6 +28,10 @@
 {
 public:
 	static GrallocModule *getInstance();
+
+	int import(buffer_handle_t handle, buffer_handle_t *imported_handle);
+	int release(buffer_handle_t handle);
+
 	int lock(buffer_handle_t handle, int usage, int left, int top, int width, int height, void **vaddr);
 	int unlock(buffer_handle_t handle);
 
@@ -39,6 +44,9 @@
 	GRALLOC1_PFN_LOCK m_gralloc1_lock = nullptr;
 	GRALLOC1_PFN_UNLOCK m_gralloc1_unlock = nullptr;
 #endif
+#ifdef HAVE_GRALLOC3
+	android::sp<android::hardware::graphics::mapper::V3_0::IMapper> m_gralloc3_mapper;
+#endif
 };
 
 #endif  // GRALLOC_ANDROID
diff --git a/src/Vulkan/VkImage.cpp b/src/Vulkan/VkImage.cpp
index 555e7d1..f52ebcd 100644
--- a/src/Vulkan/VkImage.cpp
+++ b/src/Vulkan/VkImage.cpp
@@ -236,7 +236,17 @@
 	void *nativeBuffer = nullptr;
 	VkExtent3D extent = getMipLevelExtent(VK_IMAGE_ASPECT_COLOR_BIT, 0);
 
-	if(GrallocModule::getInstance()->lock(backingMemory.nativeHandle, GRALLOC_USAGE_SW_WRITE_OFTEN, 0, 0, extent.width, extent.height, &nativeBuffer) != 0)
+	buffer_handle_t importedBufferHandle = nullptr;
+	if(GrallocModule::getInstance()->import(backingMemory.nativeHandle, &importedBufferHandle) != 0)
+	{
+		return VK_ERROR_OUT_OF_DATE_KHR;
+	}
+	if(!importedBufferHandle)
+	{
+		return VK_ERROR_OUT_OF_DATE_KHR;
+	}
+
+	if(GrallocModule::getInstance()->lock(importedBufferHandle, GRALLOC_USAGE_SW_WRITE_OFTEN, 0, 0, extent.width, extent.height, &nativeBuffer) != 0)
 	{
 		return VK_ERROR_OUT_OF_DATE_KHR;
 	}
@@ -257,7 +267,12 @@
 		memcpy(dstBuffer + (i * bufferRowBytes), srcBuffer + (i * imageRowBytes), imageRowBytes);
 	}
 
-	if(GrallocModule::getInstance()->unlock(backingMemory.nativeHandle) != 0)
+	if(GrallocModule::getInstance()->unlock(importedBufferHandle) != 0)
+	{
+		return VK_ERROR_OUT_OF_DATE_KHR;
+	}
+
+	if(GrallocModule::getInstance()->release(importedBufferHandle) != 0)
 	{
 		return VK_ERROR_OUT_OF_DATE_KHR;
 	}
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index 4b4247d..7062103 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -64,6 +64,7 @@
 #	include "commit.h"
 #	include "System/GrallocAndroid.hpp"
 #	include <android/log.h>
+#	include <hardware/gralloc1.h>
 #	include <sync/sync.h>
 #endif