From 30c044ba3df6a5a273ad1198279f5ac4367e03a2 Mon Sep 17 00:00:00 2001 From: xiaying Date: Thu, 19 Dec 2024 20:58:57 +0800 Subject: [PATCH] MNN:Refractor: Support low api for use hardwardbuffer --- project/android/build_32.sh | 2 +- project/android/build_32_stl_shared.sh | 2 +- project/android/build_64.sh | 2 +- test/sharedmem/AhardWareBufferTest.cpp | 147 ++++++++++++++++++++++++- tools/cpp/GpuInterTest.cpp | 147 +++++++++++++++++++++++-- 5 files changed, 284 insertions(+), 16 deletions(-) diff --git a/project/android/build_32.sh b/project/android/build_32.sh index c9f9f7b24..24f0eb8cc 100755 --- a/project/android/build_32.sh +++ b/project/android/build_32.sh @@ -4,7 +4,7 @@ cmake ../../../ \ -DCMAKE_BUILD_TYPE=Release \ -DANDROID_ABI="armeabi-v7a" \ -DANDROID_STL=c++_static \ --DANDROID_NATIVE_API_LEVEL=android-26 \ +-DANDROID_NATIVE_API_LEVEL=android-14 \ -DANDROID_TOOLCHAIN=clang \ -DMNN_USE_LOGCAT=false \ -DMNN_USE_SSE=OFF \ diff --git a/project/android/build_32_stl_shared.sh b/project/android/build_32_stl_shared.sh index cafa6bf97..1fb38d5d8 100755 --- a/project/android/build_32_stl_shared.sh +++ b/project/android/build_32_stl_shared.sh @@ -5,7 +5,7 @@ cmake ../../../ \ -DANDROID_ABI="armeabi-v7a" \ -DANDROID_STL=c++_shared \ -DCMAKE_BUILD_TYPE=Release \ --DANDROID_NATIVE_API_LEVEL=android-26 \ +-DANDROID_NATIVE_API_LEVEL=android-14 \ -DANDROID_TOOLCHAIN=clang \ -DMNN_BUILD_FOR_ANDROID_COMMAND=true \ -DNATIVE_LIBRARY_OUTPUT=. -DNATIVE_INCLUDE_OUTPUT=. $1 $2 $3 diff --git a/project/android/build_64.sh b/project/android/build_64.sh index 328d8ea74..34b18057e 100755 --- a/project/android/build_64.sh +++ b/project/android/build_64.sh @@ -8,7 +8,7 @@ cmake ../../../ \ -DMNN_BUILD_BENCHMARK=ON \ -DMNN_USE_SSE=OFF \ -DMNN_BUILD_TEST=ON \ --DANDROID_NATIVE_API_LEVEL=android-26 \ +-DANDROID_NATIVE_API_LEVEL=android-21 \ -DMNN_BUILD_FOR_ANDROID_COMMAND=true \ -DNATIVE_LIBRARY_OUTPUT=. -DNATIVE_INCLUDE_OUTPUT=. $1 $2 $3 $4 $5 $6 $7 diff --git a/test/sharedmem/AhardWareBufferTest.cpp b/test/sharedmem/AhardWareBufferTest.cpp index f8ea492ef..002a8caa4 100644 --- a/test/sharedmem/AhardWareBufferTest.cpp +++ b/test/sharedmem/AhardWareBufferTest.cpp @@ -7,6 +7,7 @@ // #ifdef __ANDROID__ +#include #include #include "MNNTestSuite.h" #include "MNN_generated.h" @@ -19,6 +20,137 @@ using namespace MNN; using namespace MNN::Express; +/* +Ref from +https://android.googlesource.com/platform/external/libchrome/+/refs/tags/aml_res_331314010/base/android/android_hardware_buffer_compat.h +*/ +using PFAHardwareBuffer_allocate = int (*)(const AHardwareBuffer_Desc* desc, + AHardwareBuffer** outBuffer); +using PFAHardwareBuffer_acquire = void (*)(AHardwareBuffer* buffer); +using PFAHardwareBuffer_describe = void (*)(const AHardwareBuffer* buffer, + AHardwareBuffer_Desc* outDesc); +using PFAHardwareBuffer_lock = int (*)(AHardwareBuffer* buffer, + uint64_t usage, + int32_t fence, + const ARect* rect, + void** outVirtualAddress); +using PFAHardwareBuffer_recvHandleFromUnixSocket = + int (*)(int socketFd, AHardwareBuffer** outBuffer); +using PFAHardwareBuffer_release = void (*)(AHardwareBuffer* buffer); +using PFAHardwareBuffer_sendHandleToUnixSocket = + int (*)(const AHardwareBuffer* buffer, int socketFd); +using PFAHardwareBuffer_unlock = int (*)(AHardwareBuffer* buffer, + int32_t* fence); + +class AndroidHardwareBufferCompat { + public: + bool IsSupportAvailable() const { + return true; + } + AndroidHardwareBufferCompat(); + int Allocate(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer); + void Acquire(AHardwareBuffer* buffer); + void Describe(const AHardwareBuffer* buffer, AHardwareBuffer_Desc* outDesc); + int Lock(AHardwareBuffer* buffer, + uint64_t usage, + int32_t fence, + const ARect* rect, + void** out_virtual_address); + int RecvHandleFromUnixSocket(int socketFd, AHardwareBuffer** outBuffer); + void Release(AHardwareBuffer* buffer); + int SendHandleToUnixSocket(const AHardwareBuffer* buffer, int socketFd); + int Unlock(AHardwareBuffer* buffer, int32_t* fence); + private: + PFAHardwareBuffer_allocate allocate_; + PFAHardwareBuffer_acquire acquire_; + PFAHardwareBuffer_describe describe_; + PFAHardwareBuffer_lock lock_; + PFAHardwareBuffer_recvHandleFromUnixSocket recv_handle_; + PFAHardwareBuffer_release release_; + PFAHardwareBuffer_sendHandleToUnixSocket send_handle_; + PFAHardwareBuffer_unlock unlock_; +}; +#define DCHECK(x) MNN_ASSERT(x) +AndroidHardwareBufferCompat::AndroidHardwareBufferCompat() { + // TODO(klausw): If the Chromium build requires __ANDROID_API__ >= 26 at some + // point in the future, we could directly use the global functions instead of + // dynamic loading. However, since this would be incompatible with pre-Oreo + // devices, this is unlikely to happen in the foreseeable future, so just + // unconditionally use dynamic loading. + // cf. base/android/linker/modern_linker_jni.cc + void* main_dl_handle = dlopen(nullptr, RTLD_NOW); + *reinterpret_cast(&allocate_) = + dlsym(main_dl_handle, "AHardwareBuffer_allocate"); + DCHECK(allocate_); + *reinterpret_cast(&acquire_) = + dlsym(main_dl_handle, "AHardwareBuffer_acquire"); + DCHECK(acquire_); + *reinterpret_cast(&describe_) = + dlsym(main_dl_handle, "AHardwareBuffer_describe"); + DCHECK(describe_); + *reinterpret_cast(&lock_) = + dlsym(main_dl_handle, "AHardwareBuffer_lock"); + DCHECK(lock_); + *reinterpret_cast(&recv_handle_) = + dlsym(main_dl_handle, "AHardwareBuffer_recvHandleFromUnixSocket"); + DCHECK(recv_handle_); + *reinterpret_cast(&release_) = + dlsym(main_dl_handle, "AHardwareBuffer_release"); + DCHECK(release_); + *reinterpret_cast(&send_handle_) = + dlsym(main_dl_handle, "AHardwareBuffer_sendHandleToUnixSocket"); + DCHECK(send_handle_); + *reinterpret_cast(&unlock_) = + dlsym(main_dl_handle, "AHardwareBuffer_unlock"); + DCHECK(unlock_); +} + +int AndroidHardwareBufferCompat::Allocate(const AHardwareBuffer_Desc* desc, + AHardwareBuffer** out_buffer) { + DCHECK(IsSupportAvailable()); + return allocate_(desc, out_buffer); +} +void AndroidHardwareBufferCompat::Acquire(AHardwareBuffer* buffer) { + DCHECK(IsSupportAvailable()); + acquire_(buffer); +} +void AndroidHardwareBufferCompat::Describe(const AHardwareBuffer* buffer, + AHardwareBuffer_Desc* out_desc) { + DCHECK(IsSupportAvailable()); + describe_(buffer, out_desc); +} +int AndroidHardwareBufferCompat::Lock(AHardwareBuffer* buffer, + uint64_t usage, + int32_t fence, + const ARect* rect, + void** out_virtual_address) { + DCHECK(IsSupportAvailable()); + return lock_(buffer, usage, fence, rect, out_virtual_address); +} +int AndroidHardwareBufferCompat::RecvHandleFromUnixSocket( + int socket_fd, + AHardwareBuffer** out_buffer) { + DCHECK(IsSupportAvailable()); + return recv_handle_(socket_fd, out_buffer); +} +void AndroidHardwareBufferCompat::Release(AHardwareBuffer* buffer) { + DCHECK(IsSupportAvailable()); + release_(buffer); +} +int AndroidHardwareBufferCompat::SendHandleToUnixSocket( + const AHardwareBuffer* buffer, + int socket_fd) { + DCHECK(IsSupportAvailable()); + return send_handle_(buffer, socket_fd); +} +int AndroidHardwareBufferCompat::Unlock(AHardwareBuffer* buffer, + int32_t* fence) { + DCHECK(IsSupportAvailable()); + return unlock_(buffer, fence); +} + +static std::shared_ptr gFunction; + static AHardwareBuffer* creatAHardwareBuffer(int width, int height, void *data){ // 创建和初始化硬件缓冲区 AHardwareBuffer_Desc bufferDesc = {}; @@ -29,7 +161,7 @@ static AHardwareBuffer* creatAHardwareBuffer(int width, int height, void *data){ bufferDesc.usage = AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; AHardwareBuffer* buffer = nullptr; - int result = AHardwareBuffer_allocate(&bufferDesc, &buffer); + int result = gFunction->Allocate(&bufferDesc, &buffer); if(result != 0) { MNN_ERROR("alloc AHardwareBuffer failed %d\n", result); } @@ -37,7 +169,7 @@ static AHardwareBuffer* creatAHardwareBuffer(int width, int height, void *data){ if(nullptr != data){ void* map = nullptr; ARect rect = { 0, 0, width, height }; // Define the region to lock - result = AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, &rect, &map); + result = gFunction->Lock(buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, &rect, &map); if (result != 0) { MNN_ERROR("Handle lock failed\n"); } @@ -45,13 +177,13 @@ static AHardwareBuffer* creatAHardwareBuffer(int width, int height, void *data){ memcpy(map, data, width * height * 4); } - AHardwareBuffer_unlock(buffer, nullptr); + gFunction->Unlock(buffer, nullptr); } return buffer; } static void ReleaseAHardWareBuffer(AHardwareBuffer* buffer){ - AHardwareBuffer_release(buffer); + gFunction->Release(buffer); } static void copyDataFromAHardWareBuffer(AHardwareBuffer* buffer, int width, int height, void *data){ @@ -59,7 +191,7 @@ static void copyDataFromAHardWareBuffer(AHardwareBuffer* buffer, int width, int if(nullptr != data){ void* map = nullptr; ARect rect = { 0, 0, width, height }; // Define the region to lock - result = AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, -1, &rect, &map); + result = gFunction->Lock(buffer, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, -1, &rect, &map); if (result != 0) { MNN_ERROR("Handle lock failed\n"); } @@ -67,7 +199,7 @@ static void copyDataFromAHardWareBuffer(AHardwareBuffer* buffer, int width, int memcpy(data, map, width * height * 4); } - AHardwareBuffer_unlock(buffer, nullptr); + gFunction->Unlock(buffer, nullptr); } } @@ -100,6 +232,9 @@ static std::shared_ptr _createModel() { class AhardWareBufferTest : public MNNTestCase { public: virtual bool run(int precision) { + if (nullptr == gFunction) { + gFunction.reset(new AndroidHardwareBufferCompat); + } if (MNN_FORWARD_OPENCL != getCurrentType()) { MNN_ERROR("Currently forwardtype[%d] run sharedmem/AhardWareBuffer has error, skip it\n", getCurrentType()); return true; diff --git a/tools/cpp/GpuInterTest.cpp b/tools/cpp/GpuInterTest.cpp index 93e7435ed..991ba8c3f 100644 --- a/tools/cpp/GpuInterTest.cpp +++ b/tools/cpp/GpuInterTest.cpp @@ -23,8 +23,140 @@ using namespace MNN::Express; using namespace MNN; #ifdef __ANDROID__ +#include #include - + +/* +Ref from +https://android.googlesource.com/platform/external/libchrome/+/refs/tags/aml_res_331314010/base/android/android_hardware_buffer_compat.h +*/ +using PFAHardwareBuffer_allocate = int (*)(const AHardwareBuffer_Desc* desc, + AHardwareBuffer** outBuffer); +using PFAHardwareBuffer_acquire = void (*)(AHardwareBuffer* buffer); +using PFAHardwareBuffer_describe = void (*)(const AHardwareBuffer* buffer, + AHardwareBuffer_Desc* outDesc); +using PFAHardwareBuffer_lock = int (*)(AHardwareBuffer* buffer, + uint64_t usage, + int32_t fence, + const ARect* rect, + void** outVirtualAddress); +using PFAHardwareBuffer_recvHandleFromUnixSocket = + int (*)(int socketFd, AHardwareBuffer** outBuffer); +using PFAHardwareBuffer_release = void (*)(AHardwareBuffer* buffer); +using PFAHardwareBuffer_sendHandleToUnixSocket = + int (*)(const AHardwareBuffer* buffer, int socketFd); +using PFAHardwareBuffer_unlock = int (*)(AHardwareBuffer* buffer, + int32_t* fence); + +class AndroidHardwareBufferCompat { + public: + bool IsSupportAvailable() const { + return true; + } + AndroidHardwareBufferCompat(); + int Allocate(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer); + void Acquire(AHardwareBuffer* buffer); + void Describe(const AHardwareBuffer* buffer, AHardwareBuffer_Desc* outDesc); + int Lock(AHardwareBuffer* buffer, + uint64_t usage, + int32_t fence, + const ARect* rect, + void** out_virtual_address); + int RecvHandleFromUnixSocket(int socketFd, AHardwareBuffer** outBuffer); + void Release(AHardwareBuffer* buffer); + int SendHandleToUnixSocket(const AHardwareBuffer* buffer, int socketFd); + int Unlock(AHardwareBuffer* buffer, int32_t* fence); + private: + PFAHardwareBuffer_allocate allocate_; + PFAHardwareBuffer_acquire acquire_; + PFAHardwareBuffer_describe describe_; + PFAHardwareBuffer_lock lock_; + PFAHardwareBuffer_recvHandleFromUnixSocket recv_handle_; + PFAHardwareBuffer_release release_; + PFAHardwareBuffer_sendHandleToUnixSocket send_handle_; + PFAHardwareBuffer_unlock unlock_; +}; +#define DCHECK(x) MNN_ASSERT(x) +AndroidHardwareBufferCompat::AndroidHardwareBufferCompat() { + // TODO(klausw): If the Chromium build requires __ANDROID_API__ >= 26 at some + // point in the future, we could directly use the global functions instead of + // dynamic loading. However, since this would be incompatible with pre-Oreo + // devices, this is unlikely to happen in the foreseeable future, so just + // unconditionally use dynamic loading. + // cf. base/android/linker/modern_linker_jni.cc + void* main_dl_handle = dlopen(nullptr, RTLD_NOW); + *reinterpret_cast(&allocate_) = + dlsym(main_dl_handle, "AHardwareBuffer_allocate"); + DCHECK(allocate_); + *reinterpret_cast(&acquire_) = + dlsym(main_dl_handle, "AHardwareBuffer_acquire"); + DCHECK(acquire_); + *reinterpret_cast(&describe_) = + dlsym(main_dl_handle, "AHardwareBuffer_describe"); + DCHECK(describe_); + *reinterpret_cast(&lock_) = + dlsym(main_dl_handle, "AHardwareBuffer_lock"); + DCHECK(lock_); + *reinterpret_cast(&recv_handle_) = + dlsym(main_dl_handle, "AHardwareBuffer_recvHandleFromUnixSocket"); + DCHECK(recv_handle_); + *reinterpret_cast(&release_) = + dlsym(main_dl_handle, "AHardwareBuffer_release"); + DCHECK(release_); + *reinterpret_cast(&send_handle_) = + dlsym(main_dl_handle, "AHardwareBuffer_sendHandleToUnixSocket"); + DCHECK(send_handle_); + *reinterpret_cast(&unlock_) = + dlsym(main_dl_handle, "AHardwareBuffer_unlock"); + DCHECK(unlock_); +} + +int AndroidHardwareBufferCompat::Allocate(const AHardwareBuffer_Desc* desc, + AHardwareBuffer** out_buffer) { + DCHECK(IsSupportAvailable()); + return allocate_(desc, out_buffer); +} +void AndroidHardwareBufferCompat::Acquire(AHardwareBuffer* buffer) { + DCHECK(IsSupportAvailable()); + acquire_(buffer); +} +void AndroidHardwareBufferCompat::Describe(const AHardwareBuffer* buffer, + AHardwareBuffer_Desc* out_desc) { + DCHECK(IsSupportAvailable()); + describe_(buffer, out_desc); +} +int AndroidHardwareBufferCompat::Lock(AHardwareBuffer* buffer, + uint64_t usage, + int32_t fence, + const ARect* rect, + void** out_virtual_address) { + DCHECK(IsSupportAvailable()); + return lock_(buffer, usage, fence, rect, out_virtual_address); +} +int AndroidHardwareBufferCompat::RecvHandleFromUnixSocket( + int socket_fd, + AHardwareBuffer** out_buffer) { + DCHECK(IsSupportAvailable()); + return recv_handle_(socket_fd, out_buffer); +} +void AndroidHardwareBufferCompat::Release(AHardwareBuffer* buffer) { + DCHECK(IsSupportAvailable()); + release_(buffer); +} +int AndroidHardwareBufferCompat::SendHandleToUnixSocket( + const AHardwareBuffer* buffer, + int socket_fd) { + DCHECK(IsSupportAvailable()); + return send_handle_(buffer, socket_fd); +} +int AndroidHardwareBufferCompat::Unlock(AHardwareBuffer* buffer, + int32_t* fence) { + DCHECK(IsSupportAvailable()); + return unlock_(buffer, fence); +} + +static std::shared_ptr gFunction; + static AHardwareBuffer* creatAHardwareBuffer(int width, int height, void *data){ // 创建和初始化硬件缓冲区 AHardwareBuffer_Desc bufferDesc = {}; @@ -35,7 +167,7 @@ static AHardwareBuffer* creatAHardwareBuffer(int width, int height, void *data){ bufferDesc.usage = AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; AHardwareBuffer* buffer = nullptr; - int result = AHardwareBuffer_allocate(&bufferDesc, &buffer); + int result = gFunction->Allocate(&bufferDesc, &buffer); if(result != 0) { // Handle allocation error MNN_PRINT("alloc AHardwareBuffer failed %d\n", result); @@ -44,7 +176,7 @@ static AHardwareBuffer* creatAHardwareBuffer(int width, int height, void *data){ if(nullptr != data){ void* map = nullptr; ARect rect = { 0, 0, width, height }; // Define the region to lock - result = AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, &rect, &map); + result = gFunction->Lock(buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, &rect, &map); if (result != 0) { // Handle lock failure MNN_PRINT("Handle lock failed\n"); @@ -55,7 +187,7 @@ static AHardwareBuffer* creatAHardwareBuffer(int width, int height, void *data){ memcpy(map, data, width * height * 4); // Assuming RGBA8888 format } - AHardwareBuffer_unlock(buffer, nullptr); + gFunction->Unlock(buffer, nullptr); } return buffer; } @@ -64,7 +196,7 @@ static void copyDataFromAHardWareBuffer(AHardwareBuffer* buffer, int width, int if(nullptr != data){ void* map = nullptr; ARect rect = { 0, 0, width, height }; // Define the region to lock - result = AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, -1, &rect, &map); + result = gFunction->Lock(buffer, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, -1, &rect, &map); if (result != 0) { MNN_PRINT("Handle lock failed\n"); } @@ -72,12 +204,12 @@ static void copyDataFromAHardWareBuffer(AHardwareBuffer* buffer, int width, int memcpy(data, map, width * height * 4); } - AHardwareBuffer_unlock(buffer, nullptr); + gFunction->Unlock(buffer, nullptr); } } static void ReleaseAHardWareBuffer(AHardwareBuffer* buffer){ if(buffer != nullptr){ - AHardwareBuffer_release(buffer); + gFunction->Release(buffer); } } #endif @@ -192,6 +324,7 @@ int main(int argc, char *argv[]) { MNN::Express::Module::Config mConfig; mConfig.shapeMutable = shapeMutable; #ifdef __ANDROID__ + gFunction.reset(new AndroidHardwareBufferCompat); std::vector AHardwarePtrInputVec; std::vector AHardwarePtrOutputVec; #endif