Android60 显示系统GraphicBuffer分配内存.docx
《Android60 显示系统GraphicBuffer分配内存.docx》由会员分享,可在线阅读,更多相关《Android60 显示系统GraphicBuffer分配内存.docx(22页珍藏版)》请在冰豆网上搜索。
Android60显示系统GraphicBuffer分配内存
Android6.0显示系统GraphicBuffer分配内存
之前分析了显示系统的大致流程,其中有几个地方不是很清楚,这里我专门写几篇专题。
这篇先来看GraphicBuffer分配内存,我们在之前的博客中分析到用户进程创建一个Surface,最后返回的参数gbp是sp类型的,过程之前都分析过了,我们就不分析了,这个gbp是在Layer的onFirstRef中创建的。
在BufferQueue的createBufferQueue中创建了producer和consumer,然后创建了MonitoredProducer对象,并且用producer来作为参数。
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidLayer:
:
onFirstRef(){
//CreatesacustomBufferQueueforSurfaceFlingerConsumertouse
spproducer;
spconsumer;
BufferQueue:
:
createBufferQueue(&producer,&consumer);
mProducer=newMonitoredProducer(producer,mFlinger);
......
用户进程和SurfaceFlinger通信的Binder类
MonitoredProducer是继承IGraphicBufferProducer类。
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
classMonitoredProducer:
publicIGraphicBufferProducer{
我们再来看看IGraphicBufferProducer类的实现,典型的Binder用法,在这个类中有Bp端和Bn端的实现。
这个就是用户进程和SurfaceFlinger进程的关于内存的Binder通信。
我们requestBuffer函数,用户进程通过binder和SurfaceFlinger通信,获取数据,然后新建一个GraphicBuffer对象,将数据放入这个对象。
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
classBpGraphicBufferProducer:
publicBpInterface
{
public:
BpGraphicBufferProducer(constsp&impl)
:
BpInterface(impl)
{
}
virtual~BpGraphicBufferProducer();
virtualstatus_trequestBuffer(intbufferIdx,sp*buf){
Parceldata,reply;
data.writeInterfaceToken(IGraphicBufferProducer:
:
getInterfaceDescriptor());
data.writeInt32(bufferIdx);
status_tresult=remote()->transact(REQUEST_BUFFER,data,&reply);//通过Binder获取SurfaceFlinger的数据
if(result!
=NO_ERROR){
returnresult;
}
boolnonNull=reply.readInt32();
if(nonNull){
*buf=newGraphicBuffer();//新建一个GraphicBuffer
result=reply.read(**buf);//将从SurfaceFlinger获取的数据放入这个新建的对象
if(result!
=NO_ERROR){
(*buf).clear();
returnresult;
}
}
result=reply.readInt32();
returnresult;
}
我们再来看看SurfaceFlinger的Bn侧是如何实现的,这里主要是调用子类获取到buffer,然后通过Binder传出。
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
status_tBnGraphicBufferProducer:
:
onTransact(
uint32_tcode,constParcel&data,Parcel*reply,uint32_tflags)
{
switch(code){
caseREQUEST_BUFFER:
{
CHECK_INTERFACE(IGraphicBufferProducer,data,reply);
intbufferIdx=data.readInt32();
spbuffer;
intresult=requestBuffer(bufferIdx,&buffer);//调用子类的requestBuffer函数,获取到buffer
reply->writeInt32(buffer!
=0);
if(buffer!
=0){
reply->write(*buffer);//将buffer传出
}
reply->writeInt32(result);
returnNO_ERROR;
而其子类也就是MonitoredProducer类,主要是调用了mProducer的方法,这个在MonitoredProducer对象创建的时候传入的,是BufferQueueProducer类。
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
status_tMonitoredProducer:
:
requestBuffer(intslot,sp*buf){
returnmProducer->requestBuffer(slot,buf);
}
新建一个GraphicBuffer
BufferQueueProducer类的requestBuffer类从mSlots中获取buffer传出,这个之前我们也分析过,mSlots中的buffer是在dequeueBuffer函数中申请的。
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
status_tBufferQueueProducer:
:
requestBuffer(intslot,sp*buf){
ATRACE_CALL();
BQ_LOGV("requestBuffer:
slot%d",slot);
Mutex:
:
Autolocklock(mCore->mMutex);
if(mCore->mIsAbandoned){
BQ_LOGE("requestBuffer:
BufferQueuehasbeenabandoned");
returnNO_INIT;
}
if(slot<0||slot>=BufferQueueDefs:
:
NUM_BUFFER_SLOTS){
BQ_LOGE("requestBuffer:
slotindex%doutofrange[0,%d)",
slot,BufferQueueDefs:
:
NUM_BUFFER_SLOTS);
returnBAD_VALUE;
}elseif(mSlots[slot].mBufferState!
=BufferSlot:
:
DEQUEUED){
BQ_LOGE("requestBuffer:
slot%disnotownedbytheproducer"
"(state=%d)",slot,mSlots[slot].mBufferState);
returnBAD_VALUE;
}
mSlots[slot].mRequestBufferCalled=true;
*buf=mSlots[slot].mGraphicBuffer;//从mSlots获取buffer
returnNO_ERROR;
}
这里之前分析过了,我们就简单分析下,在dequeueBuffer函数中,如果flags是BUFFER_NEEDS_REALLOCATION就需要重新分配GraphicBuffer,是通过mCore->mAllocator->createGraphicBuffer来分配的。
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
......
if(returnFlags&BUFFER_NEEDS_REALLOCATION){
status_terror;
BQ_LOGV("dequeueBuffer:
allocatinganewbufferforslot%d",*outSlot);
spgraphicBuffer(mCore->mAllocator->createGraphicBuffer(
width,height,format,usage,&error));
......
GraphicBufferAlloc:
:
createGraphicBuffer函数如下。
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
spGraphicBufferAlloc:
:
createGraphicBuffer(uint32_twidth,
uint32_theight,PixelFormatformat,uint32_tusage,status_t*error){
spgraphicBuffer(
newGraphicBuffer(width,height,format,usage));
status_terr=graphicBuffer->initCheck();
*error=err;
if(err!
=0||graphicBuffer->handle==0){
if(err==NO_MEMORY){
GraphicBuffer:
:
dumpAllocationsToSystemLog();
}
ALOGE("GraphicBufferAlloc:
:
createGraphicBuffer(w=%d,h=%d)"
"failed(%s),handle=%p",
width,height,strerror(-err),graphicBuffer->handle);
return0;
}
returngraphicBuffer;
}
然后我们再来看看GraphicBuffer的构造函数,主要是初始化了各个变量,然后调用了GraphicBuffer的initSize函数。
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
GraphicBuffer:
:
GraphicBuffer(uint32_tinWidth,uint32_tinHeight,
PixelFormatinFormat,uint32_tinUsage)
:
BASE(),mOwner(ownData),mBufferMapper(GraphicBufferMapper:
:
get()),
mInitCheck(NO_ERROR),mId(getUniqueId())
{
width=
height=
stride=
format=
usage=0;
handle=NULL;
mInitCheck=initSize(inWidth,inHeight,inFormat,inUsage);
}
我们来看看这个函数主要是通过GraphicBufferAllocator的alloc来分配buffer
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
status_tGraphicBuffer:
:
initSize(uint32_tinWidth,uint32_tinHeight,
PixelFormatinFormat,uint32_tinUsage)
{
GraphicBufferAllocator&allocator=GraphicBufferAllocator:
:
get();
uint32_toutStride=0;
status_terr=allocator.alloc(inWidth,inHeight,inFormat,inUsage,
&handle,&outStride);
if(err==NO_ERROR){
width=static_cast(inWidth);
height=static_cast(inHeight);
format=inFormat;
usage=static_cast(inUsage);
stride=static_cast(outStride);
}
returnerr;
}
HAL层alloc函数分配buffer
GraphicBufferAllocator的构造函数中获取hal层模块。
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
GraphicBufferAllocator:
:
GraphicBufferAllocator()
:
mAllocDev(0)
{
hw_module_tconst*module;
interr=hw_get_module(GRALLOC_HARDWARE_MODULE_ID,&module);
if(err==0){
gralloc_open(module,&mAllocDev);
}
}
然后在alloc中分配内存。
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
status_tGraphicBufferAllocator:
:
alloc(uint32_twidth,uint32_theight,
PixelFormatformat,uint32_tusage,buffer_handle_t*handle,
uint32_t*stride)
{
ATRACE_CALL();
//makesuretonotallocateaNx0or0xNbuffer,sincethisis
//allowedfromanAPIstand-pointallocatea1x1bufferinstead.
if(!
width||!
height)
width=height=1;
//wehaveah/wallocatorandh/wbufferisrequested
status_terr;
//Filteroutanyusagebitsthatshouldnotbepassedtothegrallocmodule
usage&=GRALLOC_USAGE_ALLOC_MASK;
intoutStride=0;
err=mAllocDev->alloc(mAllocDev,static_cast(width),
static_cast(height),format,static_cast(usage),handle,
&outStride);
*stride=static_cast(outStride);
if(err==NO_ERROR){
Mutex:
:
Autolock_l(sLock);
KeyedVector&list(sAllocList);
uint32_tbpp=bytesPerPixel(format);
alloc_rec_trec;
rec.width=width;
rec.height=height;
rec.stride=*stride;
rec.format=format;
rec.usage=usage;
rec.size=static_cast(height*(*stride)*bpp);
list.add(*handle,rec);
}
returnerr;
}
分配的HAL层我们之前分析过了,是在alloc_device.cpp中调用alloc_device_alloc函数,这里buffer_handle_t类型就是native_handle_t类型。
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
staticintalloc_device_alloc(alloc_device_t*dev,intw,inth,intformat,intusage,buffer_handle_t*pHandle,int*pStride)
我们来看下native_handle_t类型,numFds就是data[0]这个数组中有几个是代表fd,numInts是代表data[0]有几个是代表int字段的。
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
typedefstructnative_handle
{
intversion;/*sizeof(native_handle_t)*/
intnumFds;/*numberoffile-descriptorsat&data[0]*/
intnumInts;/*numberofintsat&data[numFds]*/
intdata[0];/*numFds+numIntsints*/
}native_handle_t;
而我们在alloc_devcei_alloc,实际分配的时候是新建的private_handle_t,也就是说最后我们分配的全在这个变量中,因为native_handle是其第一个参数,所有通过指针这两个对象都是可以强制转的。
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
#ifdef__cplusplus
structprivate_handle_t:
publicnative_handle{
#else
structprivate_handle_t{
structnative_handlenativeHandle;
#endif
enum{
PRIV_FLAGS_FRAMEBUFFER=0x00000001
};
//file-descriptors
intfd;
//ints
intmagic;
intflags;
intsize;
intoffset;
//FIXME:
theattributesbelowshouldbeout-of-line
uint64_tbase__attribute__((aligned(8)));
intpid;
#ifdef__cplusplus
staticinlineintsNumInts(){
return(((sizeof(private_handle_t)-sizeof(native_handle_t))/sizeof(int))-sNumFds);
}
staticconstintsNumFds=1;
staticconstintsMagic=0x3141592;
private_handle_t(intfd,intsize,intflags):
fd(fd),magic(sMagic),flags(flags),size(size),offset(0),
base(0),pid(getpid())
{
version=sizeof(native_handle);
numInts=sNumInts();
numFds=sNumFds;
}
~private_handle_t(){
magic=0;
}
staticintvalidate(constnative_handle*h){
constprivate_handle_t*hnd=(constprivate_handle_t*)h;
if(!
h||h->version!
=sizeof(native_handle)||
h->numInts!
=sNumInts()||h->numFds!
=sNumFds||
hnd->magic!
=sMagic)
{
ALOGE("invalidgrallochandle(at%p)",h);
return-EINVAL;
}
return0;
}
#endif
};
GraphicBuffer序列化传给用户进程
分配好了GraphicBuffer之后,就是通过Binder传给用户进程。
[