图形 Allocator 介绍
Allocator 整体 Allocator是干什么的 Gralloc 是申请和释放内存的模块,由硬件驱动提供实现,为BufferQueue机制提供了基础,且分配的图形Buffer是进程间共享的。Gralloc分为两部分:内存申请allocator(AllocMem) 和 其它内存接口mapper(FreeMem、Mamp、UnMap等)。其中内存申请接口(AllocMem)设计为跨进程调用,实现
Allocator
整体
Allocator是干什么的
Gralloc 是申请和释放内存的模块,由硬件驱动提供实现,为BufferQueue
机制提供了基础,且分配的图形Buffer是进程间共享的。Gralloc分为两部分:内存申请allocator(AllocMem) 和 其它内存接口mapper(FreeMem、Mamp、UnMap等)。其中内存申请接口(AllocMem)设计为跨进程调用,实现进程隔离,满足安全要求;而其余内存映射等接口则为Passthrough方式,因为Map、free等接口涉及访问的内核节点安全权限要求低,甚至不涉及内核节点,而且Map接口返回的是虚拟地址,无法跨进程调用,所以此类接口设计为Passthrough模式。
上层是怎么与 Allocator 对接的
流程图
说明
Stub 跟 Proxy 是一对,俗称“代理-桩”,一般用在远程方法调用。
Proxy 相当于是拿在手里的遥控器,而 Stub 相当于长在电视机里的遥控接收器,它们有着一一对应的接口方法,但操作的方向刚好相反。
Proxy 的接口供客户端程序调用,然后它内部会把信息包装好,以某种方式(比如 RMI)传递给 Stub,而后者通过对应的接口作用于服务端系统,从而完成了“远程调用”。
一般不同进程间通信的时候都会用到这种模式。
Stub(存根)
定义:Stub是服务端的接口实现,继承自IBinder接口。它代表了服务端暴露给客户端调用的接口。
功能:Stub负责接收来自客户端的请求,通过onTransact方法处理客户端的调用请求。在这个方法中,Stub会根据不同的请求码(code)执行对应的服务逻辑,并通过Parcel对象传递参数和返回值。
生成:通常,使用IDL(Interface Definition Language)文件定义接口时,编译器会自动为服务端生成Stub类的实现。
Proxy(代理)
定义:Proxy是客户端侧的Stub的本地代理,同样继承自IBinder接口。它是Stub的一个远程代理对象,使得客户端可以像调用本地对象一样调用远程服务的方法。
功能:当客户端调用Proxy上的方法时,Proxy会将调用序列化(通过Parcel对象),然后通过Binder驱动发送到服务端。同时,Proxy还会监听来自服务端的返回结果,并将其反序列化后返回给客户端。
生成:同样,使用IDL定义接口时,编译器也会为客户端自动生成一个Proxy类
接口流程梳理
Allocator (AllocMem)
内存申请接口只在requestbuffer时用到了,下面通过requestbuffer流程来看下它是如何使用的
1.应用创建RT进程,Render中调用 ProcessRootRenderNode,申请buffer(rsSurface->RequestFrame)
void RSRenderThreadVisitor::ProcessRootRenderNode(RSRootRenderNode& node)
{
...
#ifdef ROSEN_OHOS
auto surfaceFrame = rsSurface->RequestFrame(bufferWidth, bufferHeight, uiTimestamp_);
#else
auto surfaceFrame = rsSurface->RequestFrame(std::round(bufferWidth), std::round(bufferHeight), uiTimestamp_);
#endif
...
}
2. 上层跳转到 bufferquene 的 RequestBuffer 接口
GSError BufferQueueProducer::RequestBuffer(const BufferRequestConfig &config, sptr<BufferExtraData> &bedata,
RequestBufferReturnValue &retval)
{
...
return bufferQueue_->RequestBuffer(config, bedata, retval);
}
3. bufferquene 调用到 SurfaceBufferImpl 中
GSError BufferQueue::AllocBuffer(sptr<SurfaceBuffer> &buffer,
const BufferRequestConfig &config)
{
ScopedBytrace func(__func__);
sptr<SurfaceBuffer> bufferImpl = new SurfaceBufferImpl();
uint32_t sequence = bufferImpl->GetSeqNum();
BufferRequestConfig updateConfig = config;
updateConfig.usage |= defaultUsage;
GSError ret = bufferImpl->Alloc(updateConfig);
if (ret != GSERROR_OK) {
BLOGN_FAILURE_ID_API(sequence, Alloc, ret);
return ret;
}
...
}
4. SurfaceBufferImpl 初始化 GetDisPlayBuffer
GSError SurfaceBufferImpl::Alloc(const BufferRequestConfig &config)
{
...
BufferHandle *handle = nullptr;
OHOS::HDI::Display::Buffer::V1_0::AllocInfo info = {config.width, config.height, config.usage, config.format};
auto dret = g_displayBuffer->AllocMem(info, handle);
...
}
5.g_displayBuffer通过 IDisplayBuffer *Get()初始化
IDisplayBufferSptr GetDisplayBufferLocked()
{
...
g_displayBuffer.reset(OHOS::HDI::Display::Buffer::V1_2::IDisplayBuffer::Get());
...
}
// drivers/interface/display/buffer/v1_1/hdi_impl/display_buffer_hdi_impl.cpp
namespace OHOS {
namespace HDI {
namespace Display {
namespace Buffer {
namespace V1_1 {
using namespace OHOS::HDI::Display::Buffer::V1_1;
IDisplayBuffer *IDisplayBuffer::Get()
{
IDisplayBuffer *instance = new V1_1::HdiDisplayBufferImpl();
if (instance == nullptr) {
return nullptr;
}
return instance;
}
} // namespace V1_1
} // namespace Buffer
} // namespace Display
} // namespace HDI
} // namespace OHOS
6.IDisplayBuffer *Get() 初始化了一个HdiDisplayBufferImpl类实例
namespace OHOS {
namespace HDI {
namespace Display {
namespace Buffer {
namespace V1_1 {
template<typename Interface>
class DisplayBufferHdiImpl : public V1_0::DisplayBufferHdiImpl<Interface> {
public:
...
private:
using BaseType1_0 = V1_0::DisplayBufferHdiImpl<Interface>;
using BaseType1_0::WAIT_TIME_INTERVAL;
protected:
sptr<IMetadata> metadata_;
};
using HdiDisplayBufferImpl = DisplayBufferHdiImpl<V1_1::IDisplayBuffer>;
} // namespace V1_1
} // namespace Buffer
} // namespace Display
} // namespace HDI
} // namespace OHOS
#endif // OHOS_HDI_DISPLAY_V1_1_DISPLAY_BUFFER_HDI_IMPL_H
7. DisplayBufferHdiImpl 中的alloca接口,其中allocator_的IAllocator类通过IDL文件编译生成的
class DisplayBufferHdiImpl : public Interface {
public:
explicit DisplayBufferHdiImpl(bool isAllocLocal = false) : allocator_(nullptr),
mapper_(nullptr), recipient_(nullptr)
{
while ((allocator_ = IAllocator::Get(isAllocLocal)) == nullptr) {
// Waiting for allocator service ready
usleep(WAIT_TIME_INTERVAL);
}
while ((mapper_ = IMapper::Get(true)) == nullptr) {
// Waiting for mapper IF ready
usleep(WAIT_TIME_INTERVAL);
}
}
int32_t AllocMem(const AllocInfo& info, BufferHandle*& handle) const override
{
CHECK_NULLPOINTER_RETURN_VALUE(allocator_, HDF_FAILURE);
sptr<NativeBuffer> hdiBuffer;
int32_t ret = allocator_->AllocMem(info, hdiBuffer);
if ((ret == HDF_SUCCESS) && (hdiBuffer != nullptr)) {
handle = hdiBuffer->Move();
} else {
handle = nullptr;
if (ret == HDF_SUCCESS) {
ret = HDF_FAILURE;
}
HDF_LOGE("%{public}s: AllocMem error", __func__);
}
return ret;
}
8. IAllocator 类的构成
class IAllocator : public HdiBase {
public:
DECLARE_HDI_DESCRIPTOR(u"ohos.hdi.display.buffer.v1_0.IAllocator");
virtual ~IAllocator() = default;
static sptr<OHOS::HDI::Display::Buffer::V1_0::IAllocator> Get(bool isStub = false);
static sptr<OHOS::HDI::Display::Buffer::V1_0::IAllocator> Get(const std::string &serviceName, bool isStub = false);
virtual int32_t AllocMem(const OHOS::HDI::Display::Buffer::V1_0::AllocInfo& info, sptr<NativeBuffer>& handle) = 0;
virtual int32_t GetVersion(uint32_t& majorVer, uint32_t& minorVer)
{
majorVer = 1;
minorVer = 0;
return HDF_SUCCESS;
}
virtual bool IsProxy()
{
return false;
}
virtual const std::u16string GetDesc()
{
return metaDescriptor_;
}
};
9. IAllocator::Get 为了满足安全要求,isStub = false,IAllocator走的是 Proxy——Stub 模式,核心代码如下
sptr<OHOS::HDI::Display::Buffer::V1_0::IAllocator> OHOS::HDI::Display::Buffer::V1_0::IAllocator::Get(bool isStub)
{
return IAllocator::Get("allocator_service", isStub);
}
sptr<OHOS::HDI::Display::Buffer::V1_0::IAllocator> OHOS::HDI::Display::Buffer::V1_0::IAllocator::Get(const std::string& serviceName, bool isStub)
{
if (isStub) {
std::string desc = Str16ToStr8(OHOS::HDI::Display::Buffer::V1_0::IAllocator::GetDescriptor());
void *impl = LoadHdiImpl(desc.c_str(), serviceName == "allocator_service" ? "service" : serviceName.c_str());
if (impl == nullptr) {
HDF_LOGE("failed to load hdi impl %{public}s", desc.data());
return nullptr;
}
return reinterpret_cast<OHOS::HDI::Display::Buffer::V1_0::IAllocator *>(impl);
}
using namespace OHOS::HDI::ServiceManager::V1_0;
auto servMgr = IServiceManager::Get();
if (servMgr == nullptr) {
HDF_LOGE("%{public}s:get IServiceManager failed!", __func__);
return nullptr;
}
sptr<IRemoteObject> remote = servMgr->GetService(serviceName.c_str());
if (remote == nullptr) {
HDF_LOGE("%{public}s:get remote object failed!", __func__);
return nullptr;
}
sptr<OHOS::HDI::Display::Buffer::V1_0::AllocatorProxy> proxy = new OHOS::HDI::Display::Buffer::V1_0::AllocatorProxy(remote);
if (proxy == nullptr) {
HDF_LOGE("%{public}s:iface_cast failed!", __func__);
return nullptr;
}
proxy->servMgr_ = OHOS::HDI::hdi_objcast<IServiceManager>(servMgr);
proxy->deathRecipient_ = new OHOS::HDI::Display::Buffer::V1_0::AllocatorProxy::IServiceManagerDeathRecipient(proxy);
proxy->servMgr_->AddDeathRecipient(proxy->deathRecipient_);
proxy->isReconnected_ = false;
proxy->serviceName_ = serviceName;
uint32_t serMajorVer = 0;
uint32_t serMinorVer = 0;
int32_t allocatorRet = proxy->GetVersion(serMajorVer, serMinorVer);
if (allocatorRet != HDF_SUCCESS) {
HDF_LOGE("%{public}s:get version failed!", __func__);
return nullptr;
}
if (serMajorVer != 1) {
HDF_LOGE("%{public}s:check version failed! version of service:%u.%u, version of client:1.0", __func__, serMajorVer, serMinorVer);
return nullptr;
}
return proxy;
}
Mmap (Free、flush、map...)
内存映射等接口以Flush举例,完整流程如下
1.应用创建RT进程,Render中调用 ProcessRootRenderNode,flushbuffer(rsSurface->FlushFrame)
void RSRenderThreadVisitor::ProcessRootRenderNode(RSRootRenderNode& node)
{
...
#ifdef NEW_RENDER_CONTEXT
rsSurface->FlushFrame(uiTimestamp_);
#else
rsSurface->FlushFrame(surfaceFrame, uiTimestamp_);
#endif
...
}
2.上层跳转到 bufferquene 的 FlushBuffers 接口
GSError BufferQueueProducer::FlushBuffer(uint32_t sequence, sptr<BufferExtraData> bedata,
sptr<SyncFence> fence, BufferFlushConfigWithDamages &config)
{
if (bufferQueue_ == nullptr) {
return SURFACE_ERROR_UNKOWN;
}
return bufferQueue_->FlushBuffer(sequence, bedata, fence, config);
}
3.与上面rquest流程一致,bufferquene 调用到 SurfaceBufferImpl 中
4.SurfaceBufferImpl 初始化 GetDisPlayBuffer
GSError SurfaceBufferImpl::FlushCache()
{
std::lock_guard<std::mutex> bufferLock(g_displayBufferMutex);
if (GetDisplayBufferLocked() == nullptr) {
return SURFACE_ERROR_UNKOWN;
}
std::lock_guard<std::mutex> lock(mutex_);
if (handle_ == nullptr) {
return GSERROR_INVALID_OPERATING;
}
auto dret = g_displayBuffer->FlushCache(*handle_);
if (dret == GRAPHIC_DISPLAY_SUCCESS) {
return GSERROR_OK;
}
BLOGW("Failed with %{public}d", dret);
return GenerateError(GSERROR_API_FAILED, dret);
}
5.6流程与上面一致, 初始化了一个HdiDisplayBufferImpl类实例
7. DisplayBufferHdiImpl 中的flush接口,其中mapper_的IMapper类通过IDL文件编译生成的
class DisplayBufferHdiImpl : public Interface {
public:
explicit DisplayBufferHdiImpl(bool isAllocLocal = false) : allocator_(nullptr),
mapper_(nullptr), recipient_(nullptr)
{
while ((allocator_ = IAllocator::Get(isAllocLocal)) == nullptr) {
// Waiting for allocator service ready
usleep(WAIT_TIME_INTERVAL);
}
while ((mapper_ = IMapper::Get(true)) == nullptr) {
// Waiting for mapper IF ready
usleep(WAIT_TIME_INTERVAL);
}
}
int32_t FlushCache(const BufferHandle& handle) const override
{
CHECK_NULLPOINTER_RETURN_VALUE(mapper_, HDF_FAILURE);
sptr<NativeBuffer> hdiBuffer = new NativeBuffer();
CHECK_NULLPOINTER_RETURN_VALUE(hdiBuffer, HDF_FAILURE);
hdiBuffer->SetBufferHandle(const_cast<BufferHandle*>(&handle));
int32_t ret = mapper_->FlushCache(hdiBuffer);
return ret;
}
8. IMapper 类的构成
class IMapper : public HdiBase {
public:
DECLARE_HDI_DESCRIPTOR(u"ohos.hdi.display.buffer.v1_0.IMapper");
virtual ~IMapper() = default;
static sptr<OHOS::HDI::Display::Buffer::V1_0::IMapper> Get(bool isStub = false);
static sptr<OHOS::HDI::Display::Buffer::V1_0::IMapper> Get(const std::string &serviceName, bool isStub = false);
virtual int32_t FreeMem(const sptr<NativeBuffer>& handle) = 0;
virtual int32_t Mmap(const sptr<NativeBuffer>& handle) = 0;
virtual int32_t Unmap(const sptr<NativeBuffer>& handle) = 0;
virtual int32_t FlushCache(const sptr<NativeBuffer>& handle) = 0;
virtual int32_t InvalidateCache(const sptr<NativeBuffer>& handle) = 0;
virtual int32_t GetVersion(uint32_t& majorVer, uint32_t& minorVer)
{
majorVer = 1;
minorVer = 0;
return HDF_SUCCESS;
}
virtual bool IsProxy()
{
return false;
}
virtual const std::u16string GetDesc()
{
return metaDescriptor_;
}
};
9. IMapper::Get 不涉及到安全内核节点 isStub = true,IMapper走的是直通模式,直接加载到so,核心代码如下
sptr<OHOS::HDI::Display::Buffer::V1_0::IMapper> OHOS::HDI::Display::Buffer::V1_0::IMapper::Get(bool isStub)
{
return IMapper::Get("mapper_service", isStub);
}
sptr<OHOS::HDI::Display::Buffer::V1_0::IMapper> OHOS::HDI::Display::Buffer::V1_0::IMapper::Get(const std::string& serviceName, bool isStub)
{
if (isStub) {
std::string desc = Str16ToStr8(OHOS::HDI::Display::Buffer::V1_0::IMapper::GetDescriptor());
void *impl = LoadHdiImpl(desc.c_str(), serviceName == "mapper_service" ? "service" : serviceName.c_str());
if (impl == nullptr) {
HDF_LOGE("failed to load hdi impl %{public}s", desc.data());
return nullptr;
}
return reinterpret_cast<OHOS::HDI::Display::Buffer::V1_0::IMapper *>(impl);
}
...
}
服务启动流程
1. allocator_driver 和 mapper_driver
代码路径 drivers/peripheral/display/buffer/hdi_service/src
// allocator_driver
static int HdfAllocatorDriverBind(struct HdfDeviceObject* deviceObject)
{
...
auto serviceImpl = IAllocator::Get(true);
if (serviceImpl == nullptr) {
HDF_LOGE("%{public}s: failed to get the implement of service", __func__);
delete hdfAllocatorHost;
return HDF_FAILURE;
}
hdfAllocatorHost->stub =
OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, IAllocator::GetDescriptor());
if (hdfAllocatorHost->stub == nullptr) {
HDF_LOGE("%{public}s: failed to get stub object", __func__);
delete hdfAllocatorHost;
return HDF_FAILURE;
}
deviceObject->service = &hdfAllocatorHost->ioService;
return HDF_SUCCESS;
}
// mapper_driver
static int HdfMapperDriverBind(struct HdfDeviceObject* deviceObject)
{
...
auto serviceImpl = Display::Buffer::V1_2::IMapper::Get(true);
if (serviceImpl == nullptr) {
HDF_LOGE("%{public}s: failed to get the implement of service", __func__);
delete hdfMapperHost;
return HDF_FAILURE;
}
hdfMapperHost->stub =
OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl,
Display::Buffer::V1_2::IMapper::GetDescriptor());
if (hdfMapperHost->stub == nullptr) {
HDF_LOGE("%{public}s: failed to get stub object", __func__);
delete hdfMapperHost;
return HDF_FAILURE;
}
deviceObject->service = &hdfMapperHost->ioService;
return HDF_SUCCESS;
}
2.初始化 Stub 并加载对应的 HdiIpml
代码路径 out/oriole/gen/drivers/interface/display/buffer/v1_0
//allocator_stub 初始化
sptr<OHOS::HDI::Display::Buffer::V1_0::IAllocator> OHOS::HDI::Display::Buffer::V1_0::IAllocator::Get(bool isStub)
{
return OHOS::HDI::Display::Buffer::V1_0::IAllocator::Get("allocator_service", isStub);
}
sptr<OHOS::HDI::Display::Buffer::V1_0::IAllocator> OHOS::HDI::Display::Buffer::V1_0::IAllocator::Get(const std::string& serviceName, bool isStub)
{
if (!isStub) {
return nullptr;
}
std::string desc = Str16ToStr8(OHOS::HDI::Display::Buffer::V1_0::IAllocator::GetDescriptor());
void *impl = LoadHdiImpl(desc.c_str(), serviceName == "allocator_service" ? "service" : serviceName.c_str());
if (impl == nullptr) {
HDF_LOGE("failed to load hdi impl %{public}s", desc.c_str());
return nullptr;
}
return reinterpret_cast<OHOS::HDI::Display::Buffer::V1_0::IAllocator *>(impl);
}
//mapper_stub 初始化
sptr<OHOS::HDI::Display::Buffer::V1_0::IMapper> OHOS::HDI::Display::Buffer::V1_0::IMapper::Get(bool isStub)
{
return OHOS::HDI::Display::Buffer::V1_0::IMapper::Get("mapper_service", isStub);
}
sptr<OHOS::HDI::Display::Buffer::V1_0::IMapper> OHOS::HDI::Display::Buffer::V1_0::IMapper::Get(const std::string& serviceName, bool isStub)
{
if (!isStub) {
return nullptr;
}
std::string desc = Str16ToStr8(OHOS::HDI::Display::Buffer::V1_0::IMapper::GetDescriptor());
void *impl = LoadHdiImpl(desc.c_str(), serviceName == "mapper_service" ? "service" : serviceName.c_str());
if (impl == nullptr) {
HDF_LOGE("failed to load hdi impl %{public}s", desc.c_str());
return nullptr;
}
return reinterpret_cast<OHOS::HDI::Display::Buffer::V1_0::IMapper *>(impl);
}
3. 拼接得到对应的 serviceImplGetInstance
void *LoadHdiImpl(const char *desc, const char *serviceName)
{
...
std::string symName = interfaceName + "ImplGetInstance";
hdiImpl.constructor = reinterpret_cast<HdiImplInstanceFunc>(dlsym(hdiImpl.handler, symName.data()));
...
return implInstance;
}
4. service加载vdi,对接到vdiIpml
代码路径 drivers/peripheral/display/buffer/hdi_service/src/
//allocactor_service
extern "C" IAllocator* AllocatorImplGetInstance(void)
{
return new (std::nothrow) AllocatorService();
}
AllocatorService::AllocatorService()
: libHandle_(nullptr),
vdiImpl_(nullptr),
createVdi_(nullptr),
destroyVdi_(nullptr)
{
int32_t ret = LoadVdi();
if (ret == HDF_SUCCESS) {
vdiImpl_ = createVdi_();
CHECK_NULLPOINTER_RETURN(vdiImpl_);
} else {
HDF_LOGE("%{public}s: Load buffer VDI failed", __func__);
}
}
int32_t AllocatorService::LoadVdi()
{
...
createVdi_ = reinterpret_cast<CreateDisplayBufferVdiFunc>(dlsym(libHandle_, "CreateDisplayBufferVdi"));
...
return HDF_SUCCESS;
}
extern "C" Buffer::V1_2::IMapper* MapperImplGetInstance(void)
{
return new (std::nothrow) MapperService();
}
//mapper_service
MapperService::MapperService()
: libHandle_(nullptr),
vdiImpl_(nullptr),
createVdi_(nullptr),
destroyVdi_(nullptr)
{
int32_t ret = LoadVdi();
if (ret == HDF_SUCCESS) {
vdiImpl_ = createVdi_();
CHECK_NULLPOINTER_RETURN(vdiImpl_);
} else {
HDF_LOGE("%{public}s: Load buffer VDI failed", __func__);
}
}
int32_t MapperService::LoadVdi()
{
...
createVdi_ = reinterpret_cast<CreateDisplayBufferVdiFunc>(dlsym(libHandle_, "CreateDisplayBufferVdi"));
...
return HDF_SUCCESS;
}
5. 通过vdiImpl_调用device接口
int32_t AllocatorService::AllocMem(const AllocInfo& info, sptr<NativeBuffer>& handle)
{
BufferHandle* buffer = nullptr;
CHECK_NULLPOINTER_RETURN_VALUE(vdiImpl_, HDF_FAILURE);
int32_t ec = vdiImpl_->AllocMem(info, buffer);
if (ec != HDF_SUCCESS) {
HDF_LOGE("%{public}s: AllocMem failed, ec = %{public}d", __func__, ec);
return ec;
}
CHECK_NULLPOINTER_RETURN_VALUE(buffer, HDF_DEV_ERR_NO_MEMORY);
handle = new NativeBuffer();
if (handle == nullptr) {
HDF_LOGE("%{public}s: new NativeBuffer failed", __func__);
delete handle;
vdiImpl_->FreeMem(*buffer);
return HDF_FAILURE;
}
handle->SetBufferHandle(buffer, true, [this](BufferHandle* freeBuffer) {
vdiImpl_->FreeMem(*freeBuffer);
});
return HDF_SUCCESS;
}
int32_t MapperService::FlushCache(const sptr<NativeBuffer>& handle)
{
DISPLAY_TRACE;
CHECK_NULLPOINTER_RETURN_VALUE(handle, HDF_FAILURE);
CHECK_NULLPOINTER_RETURN_VALUE(vdiImpl_, HDF_FAILURE);
BufferHandle* buffer = handle->GetBufferHandle();
CHECK_NULLPOINTER_RETURN_VALUE(buffer, HDF_FAILURE);
int32_t ret = vdiImpl_->FlushCache(*buffer);
DISPLAY_CHK_RETURN(ret != HDF_SUCCESS, HDF_FAILURE, DISPLAY_LOGE(" fail"));
return ret;
}
Device对外提供了哪些接口
1. AllocMem 申请内存
int32_t Allocator::AllocMem(const AllocInfo &info, BufferHandle **handle)
{
int ret;
DISPLAY_LOGD();
BufferInfo bufferInfo;
ret = ConvertToBufferInfo(bufferInfo, info);
DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_NOT_SUPPORT, DISPLAY_LOGE("failed to convert to bufferInfo"));
BufferHandle *priBuffer = nullptr;
ret = Allocate(bufferInfo, &priBuffer);
if (ret != DISPLAY_SUCCESS) {
DISPLAY_LOGE("AllocMem failed");
return ret;
}
*handle = priBuffer;
DumpBufferHandle(*priBuffer);
return DISPLAY_SUCCESS;
}
2. FreeMem 释放内存
int32_t Allocator::FreeMem(BufferHandle *handle)
{
DISPLAY_LOGD();
DISPLAY_CHK_RETURN((handle == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("buffer is null"));
if (handle->fd >= 0) {
DISPLAY_LOGD("release the fd is %{public}d", handle->fd);
close(handle->fd);
handle->fd = -1;
}
const uint32_t reserveFds = handle->reserveFds;
for (uint32_t i = 0; i < reserveFds; i++) {
if (handle->reserve[i] >= 0) {
DISPLAY_LOGD("release the fd is %{public}d", handle->reserve[i]);
close(handle->reserve[i]);
handle->reserve[i] = -1;
}
}
free(handle);
return DISPLAY_SUCCESS;
}
3. Mmap 内存映射
void *Allocator::Mmap(BufferHandle *handle)
{
DISPLAY_LOGD();
void *virAddr = nullptr;
if (handle->virAddr != nullptr) {
DISPLAY_LOGW("the buffer has virtual addr");
return handle->virAddr;
}
DISPLAY_LOGI("buffer handle size %{public}d, width %{public}d, height %{public}d, stride %{public}d, fd %{public}d, format: %d, "
"phy 0x%{public}" PRIx64 ", usage 0x%{public}" PRIx64 ", viraddr 0x%{public}p",
handle->size, handle->width, handle->height, handle->stride, handle->fd, handle->format, handle->phyAddr,
handle->usage, handle->virAddr);
virAddr = mmap(nullptr, handle->size, PROT_READ | PROT_WRITE, MAP_SHARED, handle->fd, 0);
if (virAddr == MAP_FAILED) {
DISPLAY_LOGE("mmap failed errno %{public}d:%{public}s, fd : %{public}d", errno, strerror(errno), handle->fd);
handle->virAddr = nullptr;
return nullptr;
}
handle->virAddr = virAddr;
return virAddr;
}
4. Unmap 解除内存映射
int32_t Allocator::Unmap(BufferHandle *handle)
{
if (handle->virAddr == nullptr) {
DISPLAY_LOGE("virAddr is nullptr , has not map the buffer");
return DISPLAY_PARAM_ERR;
}
int ret = munmap(handle->virAddr, handle->size);
if (ret != 0) {
DISPLAY_LOGE("munmap failed err: %{public}d", errno);
return DISPLAY_FAILURE;
}
handle->virAddr = nullptr;
return DISPLAY_SUCCESS;
}
5. FlushCache 刷新缓存 将cache数据写进memory后使缓存失效
int32_t Allocator::FlushCache(BufferHandle *handle)
{
DISPLAY_LOGD();
return DmaBufferSync(*handle, DMA_BUF_SYNC_START);
}
6. InvalidateCache 使缓存失效 将cache数据设置为无效(即discard cache中的数据),不会将cache数据写入memory
int32_t Allocator::InvalidateCache(BufferHandle *handle)
{
DISPLAY_LOGD();
return DmaBufferSync(*handle, DMA_BUF_SYNC_END);
}
Device层 serviceManger 调用各自实现
int32_t AllocatorManager::Init()
{
DISPLAY_LOGD("AllocatorManager::Init");
if (init_) {
DISPLAY_LOGW("allocator has initialized");
return DISPLAY_SUCCESS;
}
// first use sprd allocator
std::shared_ptr<Allocator> sprdAllocator = std::make_shared<SprdAllocator>();
int ret = sprdAllocator->Init();
if (ret == DISPLAY_SUCCESS) {
frameBufferAllocator_ = sprdAllocator;
allocator_ = sprdAllocator;
} else {
std::shared_ptr<Allocator> drmAllocator = std::make_shared<DrmAllocator>();
int ret = drmAllocator->Init();
if (ret == DISPLAY_SUCCESS) {
frameBufferAllocator_ = drmAllocator;
allocator_ = drmAllocator;
} else {
std::shared_ptr<Allocator> fbAllocator = std::make_shared<FramebufferAllocator>();
ret = fbAllocator->Init();
DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE,
DISPLAY_LOGE("Failed init framebuffer allocator"));
std::shared_ptr<Allocator> dmaBufferallocator = std::make_shared<DmaBufferHeapAllocator>();
ret = dmaBufferallocator->Init();
DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE,
DISPLAY_LOGE("Failed init Dmabuffer allocator"));
frameBufferAllocator_ = fbAllocator;
allocator_ = dmaBufferallocator;
}
}
init_ = true;
DISPLAY_LOGD("init success");
return DISPLAY_SUCCESS;
}
更多推荐
所有评论(0)