Android60 显示系统GraphicBuffer分配内存.docx

上传人:b****8 文档编号:23608172 上传时间:2023-05-19 格式:DOCX 页数:22 大小:21.25KB
下载 相关 举报
Android60 显示系统GraphicBuffer分配内存.docx_第1页
第1页 / 共22页
Android60 显示系统GraphicBuffer分配内存.docx_第2页
第2页 / 共22页
Android60 显示系统GraphicBuffer分配内存.docx_第3页
第3页 / 共22页
Android60 显示系统GraphicBuffer分配内存.docx_第4页
第4页 / 共22页
Android60 显示系统GraphicBuffer分配内存.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

Android60 显示系统GraphicBuffer分配内存.docx

《Android60 显示系统GraphicBuffer分配内存.docx》由会员分享,可在线阅读,更多相关《Android60 显示系统GraphicBuffer分配内存.docx(22页珍藏版)》请在冰豆网上搜索。

Android60 显示系统GraphicBuffer分配内存.docx

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传给用户进程。

[

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 其它模板

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1