Skip to content

Commit

Permalink
MNN:Refractor: Support low api for use hardwardbuffer
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaying committed Dec 20, 2024
1 parent 71168a9 commit 30c044b
Show file tree
Hide file tree
Showing 5 changed files with 284 additions and 16 deletions.
2 changes: 1 addition & 1 deletion project/android/build_32.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
2 changes: 1 addition & 1 deletion project/android/build_32_stl_shared.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion project/android/build_64.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
147 changes: 141 additions & 6 deletions test/sharedmem/AhardWareBufferTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

#ifdef __ANDROID__
#include <dlfcn.h>
#include <MNN/expr/ExprCreator.hpp>
#include "MNNTestSuite.h"
#include "MNN_generated.h"
Expand All @@ -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<void**>(&allocate_) =
dlsym(main_dl_handle, "AHardwareBuffer_allocate");
DCHECK(allocate_);
*reinterpret_cast<void**>(&acquire_) =
dlsym(main_dl_handle, "AHardwareBuffer_acquire");
DCHECK(acquire_);
*reinterpret_cast<void**>(&describe_) =
dlsym(main_dl_handle, "AHardwareBuffer_describe");
DCHECK(describe_);
*reinterpret_cast<void**>(&lock_) =
dlsym(main_dl_handle, "AHardwareBuffer_lock");
DCHECK(lock_);
*reinterpret_cast<void**>(&recv_handle_) =
dlsym(main_dl_handle, "AHardwareBuffer_recvHandleFromUnixSocket");
DCHECK(recv_handle_);
*reinterpret_cast<void**>(&release_) =
dlsym(main_dl_handle, "AHardwareBuffer_release");
DCHECK(release_);
*reinterpret_cast<void**>(&send_handle_) =
dlsym(main_dl_handle, "AHardwareBuffer_sendHandleToUnixSocket");
DCHECK(send_handle_);
*reinterpret_cast<void**>(&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<AndroidHardwareBufferCompat> gFunction;

static AHardwareBuffer* creatAHardwareBuffer(int width, int height, void *data){
// 创建和初始化硬件缓冲区
AHardwareBuffer_Desc bufferDesc = {};
Expand All @@ -29,45 +161,45 @@ 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);
}

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");
}
if (map) {
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){
int result = 0;
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");
}
if (map) {
memcpy(data, map, width * height * 4);
}

AHardwareBuffer_unlock(buffer, nullptr);
gFunction->Unlock(buffer, nullptr);
}
}

Expand Down Expand Up @@ -100,6 +232,9 @@ static std::shared_ptr<Module> _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;
Expand Down
Loading

0 comments on commit 30c044b

Please sign in to comment.