GraphicBuffer.cpp
#include <string>
#include <cstdlib>
#include <iostream>
#include <iostream>
#include <dlfcn.h>
const int GRAPHICBUFFER_SIZE = 1024;
using std::string;
DynamicLibrary::DynamicLibrary(const char *fileName)
{
libHandle = dlopen(fileName, RTLD_LAZY);
if (!libHandle) throw OpenLibFailedException();
}
DynamicLibrary::~DynamicLibrary()
{
if (libHandle) dlclose(libHandle);
}
void *DynamicLibrary::getFunctionPtr(const char *name) const
{
auto ret = (void *)dlsym(libHandle, name);
if (ret == nullptr) {
std::cerr << "Failed to get function " << name << std::endl;
}
return ret;
}
template<typename Func>
void setFuncPtr(Func *&funcPtr, const DynamicLibrary &lib, const string &symname) {
funcPtr = reinterpret_cast<Func *>(lib.getFunctionPtr(symname.c_str()));
}
#if defined(__aarch64__)
# define CPU_ARM_64
#elif defined(__arm__) || defined(__ARM__) || defined(__ARM_NEON__) || defined(ARM_BUILD)
# define CPU_ARM
#elif defined(_M_X64) || defined(__x86_64__) || defined(__amd64__)
# define CPU_X86_64
#elif defined(__i386__) || defined(_M_X86) || defined(_M_IX86) || defined(X86_BUILD)
# define CPU_X86
#else
# warning "target CPU does not support ABI"
#endif
template<typename RT, typename T1, typename T2, typename T3, typename T4>
RT *callConstructor4(void (*fptr)(), void *memory, T1 param1, T2 param2, T3 param3, T4 param4) {
#if defined(CPU_ARM)
typedef RT* (*ABIFptr)(void*, T1, T2, T3, T4);
(void)((ABIFptr)fptr)(memory, param1, param2, param3, param4);
return reinterpret_cast<RT*>(memory);
#elif defined(CPU_ARM_64)
typedef void (*ABIFptr)(void*, T1, T2, T3, T4);
((ABIFptr)fptr)(memory, param1, param2, param3, param4);
return reinterpret_cast<RT*>(memory);
#elif defined(CPU_X86) || defined(CPU_X86_64)
typedef void (*ABIFptr)(void *, T1, T2, T3, T4);
((ABIFptr) fptr)(memory, param1, param2, param3, param4);
return reinterpret_cast<RT *>(memory);
#else
return nullptr;
#endif
}
template<typename T>
void callDestructor(void (*fptr)(), T *obj) {
#if defined(CPU_ARM)
typedef void* (*ABIFptr)(T* obj);
(void)((ABIFptr)fptr)(obj);
#elif defined(CPU_ARM_64)
typedef void (*ABIFptr)(T* obj);
((ABIFptr)fptr)(obj);
#elif defined(CPU_X86) || defined(CPU_X86_64)
typedef void (*ABIFptr)(T *obj);
((ABIFptr) fptr)(obj);
#endif
}
template<typename T1, typename T2>
T1 *pointerToOffset(T2 *ptr, size_t bytes) {
return reinterpret_cast<T1 *>((uint8_t *) ptr + bytes);
}
static android::android_native_base_t *getAndroidNativeBase(android::GraphicBuffer *gb) {
return pointerToOffset<android::android_native_base_t>(gb, 2 * sizeof(void *));
}
GraphicBuffer::GraphicBuffer(uint32_t width, uint32_t height, PixelFormat format, uint32_t usage) :
library("libui.so") {
setFuncPtr(functions.constructor, library, "_ZN7android13GraphicBufferC1Ejjij");
setFuncPtr(functions.destructor, library, "_ZN7android13GraphicBufferD1Ev");
setFuncPtr(functions.getNativeBuffer, library,
"_ZNK7android13GraphicBuffer15getNativeBufferEv");
setFuncPtr(functions.lock, library, "_ZN7android13GraphicBuffer4lockEjPPv");
setFuncPtr(functions.unlock, library, "_ZN7android13GraphicBuffer6unlockEv");
setFuncPtr(functions.initCheck, library, "_ZNK7android13GraphicBuffer9initCheckEv");
void *const memory = malloc(GRAPHICBUFFER_SIZE);
if (memory == nullptr) {
std::cerr << "Could not alloc for GraphicBuffer" << std::endl;
return;
}
try {
android::GraphicBuffer *const gb =
callConstructor4<android::GraphicBuffer, uint32_t, uint32_t, PixelFormat, uint32_t>(
functions.constructor,
memory,
width,
height,
format,
usage
);
android::android_native_base_t *const base = getAndroidNativeBase(gb);
status_t ctorStatus = functions.initCheck(gb);
if (ctorStatus) {
callDestructor<android::GraphicBuffer>(functions.destructor, gb);
std::cerr << "GraphicBuffer ctor failed, initCheck returned " << ctorStatus <<
std::endl;
}
if (base->magic != 0x5f626672u)
std::cerr << "GraphicBuffer layout unexpected" << std::endl;
const uint32_t expectedVersion = sizeof(void *) == 4 ? 96 : 168;
if (base->version != expectedVersion)
std::cerr << "GraphicBuffer version unexpected" << std::endl;
base->incRef(base);
impl = gb;
} catch (...) {
free(memory);
throw;
}
}
GraphicBuffer::~GraphicBuffer() {
if (impl) {
android::android_native_base_t *const base = getAndroidNativeBase(impl);
base->decRef(base);
}
}
status_t GraphicBuffer::lock(uint32_t usage, void **vaddr) {
return functions.lock(impl, usage, vaddr);
}
status_t GraphicBuffer::unlock() {
return functions.unlock(impl);
}
ANativeWindowBuffer *GraphicBuffer::getNativeBuffer() const {
return functions.getNativeBuffer(impl);
}
uint32_t GraphicBuffer::getStride() const {
return ((android::android_native_buffer_t *) getNativeBuffer())->stride;
}
ANativeWindow_Buffer
结构体只在公共 API 中使用,用于封装需要在此返回的字段,并由调用方分配,因此结构体地址本身并不说明其背后的真实对象。关于它们如何相互关联的示例,请查看 https://android.googlesource.com/platform/frameworks/native/+/033f7e8e/libs/gui/Surface.cpp 中的Surface::lock
方法(特别是 876-880 行)。 - mstorsjo