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