Android0显示系统三管理图像缓冲区_第1页
Android0显示系统三管理图像缓冲区_第2页
Android0显示系统三管理图像缓冲区_第3页
Android0显示系统三管理图像缓冲区_第4页
Android0显示系统三管理图像缓冲区_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Android6.0Android6.0显示系统(三)管理图像缓冲区、BufferQueueCoreBufferQueueProducerBufferQueueConsumer上篇博客在Layer的onFirstRef函数中,调用了下面函数,创建了3个对象BufferQueueCoreBufferQueueProducerBufferQueueConsumer。其中BufferCore是核心,把BufferQueueProducer和BufferQueueConsumer对象连接在一起。cppviewplaincopy在CODE上查看代码片派生到我的代码片voidBufferQueue:cre

2、ateBufferQueue(sp*outProducer,sp*outConsumer,constsp&allocator)spcore(newBufferQueueCore(allocator);spproducer(newBufferQueueProducer(core);spconsumer(newBufferQueueConsumer(core);*outProducer=producer;*outConsumer=consumer;1.1生产者和core的联系IGraphicBufferProducer的大致接口如下,BufferQueueProducer类是接口IGrap

3、hicBufferProducer的实现,使用BufferQueueProducer之前先要调用connect函数,使用结束后调用disconnect断开连接。cppviewplaincopy在CODE上查看代码片派生到我的代码片classIGraphicBufferProducer:publicIInterfacepublic:virtualstatus_trequestBuffer(intslot,sp*buf)=0;virtualstatus_tsetBufferCount(intbufferCount)=0;virtualstatus_tdequeueBuffer(int*slot,s

4、p*fence,boolasync,uint32_tw,uint32_th,PixelFormatformat,uint32_tusage)=0;virtualstatus_tdetachBuffer(intslot)=0;virtualstatus_tdetachNextBuffer(sp*outBuffer,sp*outFence)=0;virtualstatus_tattachBuffer(int*outSlot,constsp&buffer)=0;virtualstatus_tqueueBuffer(intslot,constQueueBufferInput&input

5、,QueueBufferOutput*output)=0;virtualvoidcancelBuffer(intslot,constsp&fence)=0;virtualintquery(intwhat,int*value)=0;virtualstatus_tconnect(constsp&listener,intapi,boolproducerControlledByApp,QueueBufferOutput*output)=0;virtualstatus_tdisconnect(intapi)=0;virtualstatus_tsetSidebandStream(const

6、sp&stream)=0;virtualvoidallocateBuffers(boolasync,uint32_twidth,uint32_theight,PixelFormatformat,uint32_tusage)=0;virtualstatus_tallowAllocation(boolallow)=0;virtualstatus_tsetGenerationNumber(uint32_tgenerationNumber)=0;virtualString8getConsumerName()const=0;在BufferQueueCore类中定义了一个64项的数据mSlots。

7、cppviewplaincopy在CODE上查看代码片派生到我的代码片BufferQueueDefs:SlotsTypemSlots;cppviewplaincopy在CODE上查看代码片派生到我的代码片typedefBufferSlotSlotsTypeNUM_BUFFER_SLOTS;每个缓冲区的类型是BufferSlot类型。它有两个重要的成员变量,mGraphicBuffer是指向图像缓冲区GraphicBuffer的指针,mBufferState表示图像缓冲区的状态。cppviewplaincopy在CODE上查看代码片派生到我的代码片spmGraphicBuffer;BufferS

8、tatemBufferState;BufferState的状态有下面几个cppviewplaincopy在CODE上查看代码片派生到我的代码片enumBufferStateFREE=0,空闲DEQUEUED=1,生产状态,被生产者拥有QUEUED=2,/保存数据状态,被BufferQueue拥有ACQUIRED=3/消费状态,被消费者拥有;BufferQueueProducer的dequeueBuffer函数用来向BufferQueueCore申请一个空闲的slot,这个slot可能已经有缓冲区,也可能没有,如果没有缓冲区,dequeueBuffer函数会分配一块新的缓冲区。得到空闲的slot

9、后,还需要调用requestBuffer函数来取得一块缓冲区。得到缓冲区,如果不需要了,可以使用cancelBuffer函数来释放这个slot。调用dequeueBuffer函数之后,缓冲区的拥有者是生产者,缓冲区处于DEQUEUED状态。一旦缓冲区复制数据完成,通过queueBuffer函数把缓冲区的控制权交还给BufferQueueCore,这时候缓冲区将处于QUEUED状态。1.2消费者和core的联系下面是IGraphicBufferComsumer接口的几个主要函数:cppviewplaincopy在CODE上查看代码片派生到我的代码片virtualstatus_tacquireBu

10、ffer(BufferItem*outBuffer,nsecs_texpectedPresent,uint64_tmaxFrameNumber=0)override;virtualstatus_treleaseBuffer(intslot,uint64_tframeNumber,constsp&releaseFence,EGLDisplaydisplay,EGLSyncKHRfence);virtualstatus_tconnect(constsp&consumerListener,boolcontrolledByApp);virtualstatus_tdisconnect()

11、;BufferQueueConsumer类是接口IGraphicBufferComsumer的实现,在使用它之前,先要调用connect函数建立联系,这里传递的参数是IConsumerListener对象,是一个回调接口,如果BufferQueue中有数据准备好了就会调用它的onFrameAvailable函数来通知消费者取走数据。取走数据的时候,需要调用acquireBuffer函数,将缓冲区状态变成ACQUIRED,使用完之后调用releaseBuffer函数可以吧缓冲区数据归还给BufferQueueCore,这样缓冲区就变成FREE。1.3三者联系对象BufferQueueProduc

12、er和BufferQueueConsumer好像没有直接联系,其实都是通过共同的BufferQueueCore对象连接在一起的,很多操作时直接使用BufferQueueCore对象的成员变量而不是函数来完成的。二、GraphicBuffer对象的创建对Surface而言,图像缓冲区是一个重要的数据结构,它是用户进程和图像显示器之间的纽带,下面我们来看看Surface的图像缓冲区是如何创建的。2.1内存缓冲区的创建前面介绍了过dequeueBuffer函数, 图像缓冲区GraphicBuffer就是在这个函数中创建的, 当从BufferQueueCore中获取到空间的slot时,如果这个slot

13、没有缓冲区就要新建一个。下面是dequeueBuffer函数的部分代码, 在从BufferQueueCore中获取到slot的时候, 如果需要重新分配图像缓冲区就会调用mCore-mAllocator-createGraphicBuffer函数来重新创建一个图像缓冲区。cppviewplaincopy在CODE上查看代码片派生到我的代码片*outSlot=found;/found复制到outslotATRACE_BUFFER_INDEX(found);attachedByConsumer=mSlotsfound.mAttachedByConsumer;mSlotsfound.mBufferSt

14、ate=BufferSlot:DEQUEUED;/slot的状态修改变成生产状态constsp&buffer(mSlotsfound.mGraphicBuffer);if(buffer=NULL)|/为空,或者需要重新分配buffer-needsReallocation(width,height,format,usage)mSlotsfound.mAcquireCalled=false;mSlotsfound.mGraphicBuffer=NULL;mSlotsfound.mRequestBufferCalled=false;mSlotsfound.mEglDisplay=EGL_NO

15、_DISPLAY;mSlotsfound.mEglFence=EGL_NO_SYNC_KHR;mSlotsfound.mFence=Fence:NO_FENCE;mCore-mBufferAge=0;returnFlags|=BUFFER_NEEDS_REALLOCATION;/需要重启分配缓冲区else/Weadd1becausethatwillbetheframenumberwhenthisbuffer/isqueuedmCore-mBufferAge=mCore-mFrameCounter+1-mSlotsfound.mFrameNumber;BQ_LOGV(dequeueBuffer:

16、settingbufferageto%PRIu64,mCore-mBufferAge);if(CC_UNLIKELY(mSlotsfound.mFence=NULL)BQ_LOGE(dequeueBuffer:abouttoreturnaNULLfence-slot=%dw=%dh=%dformat=%u,found,buffer-width,buffer-height,buffer-format);eglDisplay=mSlotsfound.mEglDisplay;eglFence=mSlotsfound.mEglFence;*outFence=mSlotsfound.mFence;mSl

17、otsfound.mEglFence=EGL_NO_SYNC_KHR;mSlotsfound.mFence=Fence:NO_FENCE;mCore-validateConsistencyLocked();/Autolockscopeif(returnFlags&BUFFER_NEEDS_REALLOCATION)/如果需要重启分配图像缓冲区status_terror;BQ_LOGV(dequeueBuffer:allocatinganewbufferforslot%d,*outSlot);spgraphicBuffer(mCore-mAllocator-createGraphicBu

18、ffer(/创建图像缓冲区width,height,format,usage,&error);if(graphicBuffer=NULL)BQ_LOGE(dequeueBuffer:createGraphicBufferfailed);returnerror;/AutolockscopeMutex:Autolocklock(mCore-mMutex);if(mCore-mIsAbandoned)BQ_LOGE(dequeueBuffer:BufferQueuehasbeenabandoned);returnNO_INIT;graphicBuffer-setGenerationNumbe

19、r(mCore-mGenerationNumber);mSlots*outSlot.mGraphicBuffer=graphicBuffer;/AutolockscopemAllocator的类型是IGraphicBufferA110c,也是一个Binder对象, 它是在BufferQueueCore的构造函数中得到的,这个时候allocator为空的,具体要从Layer的构造函数中调用BufferQueue:createBufferQueue函数是,那个时候allocator参数就为空。然后通过getComposerService来调用createGraphicBufferAlloc函数来创

20、建这个mAllocator对象。之前的博客分析过getComposerService返回的是和SurfaceFlinger进程的Binder对象,因此最后是到SurfaceFlinger的createGraphicBufferAlloc函数中去了(但是这里有点搞不明白明明是在一个进程中为什么要用Binder呢?)。cppviewplaincopy在CODE上查看代码片派生到我的代码片if(allocator=NULL)spcomposer(ComposerService:getComposerService();mAllocator=mposer-createGraphicBufferA110

21、c();if(mAllocator=NULL)BQ_LOGE(createGraphicBufferAllocfailed);下面我们来看SurfaceFlinger的createGraphicBufferAlloc函数。cppviewplaincopy在CODE上查看代码片派生到我的代码片spSurfaceFlinger:createGraphicBufferA110c()spgba(newGraphicBufferAlloc();returngba;)因此最后BufferQueueProducer中的dequeueBuffer函数中调用mCore-mAllocator的createGrap

22、hicBuffer函数就是调用了GraphicBufferAlloc的createGraphicBufferAlloc函数。cppviewplaincopy在CODE上查看代码片派生到我的代码片spGraphicBufferAlloc:createGraphicBuffer(uint32_twidth,uint32_theight,PixelFormatformat,uint32_tusage,status_t*error)spgraphicBuffer(newGraphicBuffer(width,height,format,usage);status_terr=graphicBuffer-

23、initCheck();*error=err;错误处理returngraphicBuffer;)我们来看下GraphicBuffer对象的构造函数中调用了initSize函数。cppviewplaincopy在CODE上查看代码片派生到我的代码片GraphicBuffer:GraphicBuffer(uint32_tinWidth,uint32_tinHeight,PixelFormatinFormat,uint32_tinUsage):BASE(),mOwner(ownData),mBufferMapper(GraphicBufferMapper:get(),mInitCheck(NO_ER

24、ROR),mId(getUniqueId()mInitCheck=initSize(inWidth,inHeight,inFormat,inUsage);)在initSize函数中调用GraphicBufferAllocator的alloc来分配内存。cppviewplaincopy在CODE上查看代码片派生到我的代码片status_tGraphicBuffer:initSize(uint32_tinWidth,uint32_tinHeight,PixelFormatinFormat,int32_tinUsage)GraphicBufferAllocator&allocator=Gra

25、phicBufferAllocator: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;)alloc又调

26、用了成员变量mAllocDev的alloc函数。cppviewplaincopy在CODE上查看代码片派生到我的代码片status_tGraphicBufferAllocator:alloc(uint32_twidth,uint32_theight,PixelFormatformat,uint32_tusage,buffer_handle_t*handle,uint32_t*stride)err=mAllocDev-alloc(mAllocDev,static_cast(width),static_cast(height),format,static_cast(usage),handle,&a

27、mp;outStride);在GraphicBufferAllocator的构造函数中装载了Gralloc模块,因此mAllocDev指向了Gralloc模块。这个会在后面的博客中分析cppviewplaincopy在CODE上查看代码片派生到我的代码片GraphicBufferAllocator:GraphicBufferAllocator():mAllocDev(0)hw_module_tconst*module;interr=hw_get_module(GRALLOC_HARDWARE_MODULE_ID,&module);ALOGE_IF(err,FATAL:cantfindt

28、he%smodule,GRALLOC_HARDWARE_MODULE_ID);if(err=0)gralloc_open(module,&mAllocDev);这里调用alloc分配了一块共享的内存缓冲区,alloc函数将返回共享区的fd和缓冲区的指针。既然GraphicBuffer中的缓冲区是共享内存,我们知道使用共享内存需要传递共享内存的句柄fd。下面我们看看是如何传到客户进程的。2.2内存缓冲区的fd传递到客户进程GraphicBuffer类从模板类Flattenable派生,这个派生类可以通过Parcel传递,通常派生类需要重载flatten和unflatten方法,用于对象的

29、序列化和反序列化。cppviewplaincopy在CODE上查看代码片派生到我的代码片classGraphicBuffer:publicANativeObjectBase,publicFlattenable我们先来看下flatten函数,fds参数用来传递文件句柄,函数把handle中的句柄复制到fds中,因此这些句柄就能通过binder传递到目标进程中去。cppviewplaincopy在CODE上查看代码片派生到我的代码片status_tGraphicBuffer:flatten(void*&buffer,size_t&size,int*&fds,size_t&a

30、mp;count)constsize_tsizeNeeded=GraphicBuffer:getFlattenedSize();if(sizesizeNeeded)returnNO_MEMORY;size_tfdCountNeeded=GraphicBuffer:getFdCount();if(countfdCountNeeded)returnNO_MEMORY;int32_t*buf=static_cast(buffer);buf0=GBFR;buf1=width;buf2=height;buf3=stride;buf4=format;buf5=usage;buf6=static_cast(

31、mId32);buf7=static_cast(mId&0 xFFFFFFFFull);buf8=static_cast(mGenerationNumber);buf9=0;buf10=0;if(handle)buf9=handle-numFds;buf10=handle-numInts;memcpy(fds,handle-data,把handle中的中复制到fds中static_cast(handle-numFds)*sizeof(int);memcpy(&buf11,handle-data+handle-numFds,static_cast(handle-numInts)*sizeof(int);)buffer=static_cast(static_cast(buffer)+sizeNeeded);size-=sizeNeeded;if(ndle)fds+=hand

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论