介绍了AndroidSurfaceFlinger层次以下的图形合成和显示系统,主要基于高通MSM8kMDP4x平台。
SurfaceFinger按英文翻译过来就是Surface投递者。SufaceFlinger的构成并不是太复杂,复杂的是他的客户端建构。SufaceFlinger主要功能是:
1)将Layers(Surfaces)内容的刷新到屏幕上
2)维持Layer的Zorder序列,并对Layer最终输出做出裁剪计算。
3)响应Client要求,创建Layer与客户端的Surface建立连接
4)接收Client要求,修改Layer属性(输出大小,Alpha等设定)
但是作为投递者的实际意义,我们首先需要知道的是如何投递,投掷物,投递路线,投递目的地。
1SurfaceFlinger的基本组成框架
SurfaceFlinger管理对象为:
mClientsMap:管理客户端与服务端的连接。
ISurface,IsurfaceComposer:AIDL调用接口实例
mLayerMap:服务端的Surface的管理对象。
mCurrentState.layersSortedByZ:以Surface的Z-order序列排列的Layer数组。
graphicPlane缓冲区输出管理
OpenGLES:图形计算,图像合成等图形库。
pmemDevice:提供共享内存,在这里只是在gralloc.xxx.so可见,在上层被gralloc.xxx.so抽象了。
2SurfaceFingerClient和服务端对象关系图
Client端与SurfaceFlinger连接图:
Client对象:一般的在客户端都是通过SurfaceComposerClient来跟SurfaceFlinger打交道。
3主要对象说明
3.1DisplayHardware&FrameBuffer
首先SurfaceFlinger需要操作到屏幕,需要建立一个屏幕硬件缓冲区管理框架。Android在设计支持时,考虑多个屏幕的情况,引入了graphicPlane的概念。在SurfaceFlinger上有一个graphicPlane数组,每一个graphicPlane对象都对应一个DisplayHardware.在当前的Android(2.1)版本的设计中,系统支持一个graphicPlane,所以也就支持一个DisplayHardware。
SurfaceFlinger,Hardware硬件缓冲区的数据结构关系图。
3.2Layer
method:setBuffer在SurfaceFlinger端建立显示缓冲区。这里的缓冲区是指的HW性质的,PMEM设备文件映射的内存。
1)layer的绘制
voidLayer::onDraw(constRegion&clip)const
{
intindex=mFrontBufferIndex;
GLuinttextureName=mTextures[index].name;
…
drawWithOpenGL(clip,mTextures[index]);
}
3.2mCurrentState.layersSortedByZ
以Surface的Z-order序列排列的LayerBase数组,该数组是层显示遮挡的依据。在每个层计算自己的可见区域时,从Z-order顶层开始计算,是考虑到遮挡区域的裁减,自己之前层的可见区域就是自己的不可见区域。而绘制Layer时,则从Z-order底层开始绘制,这个考虑到透明层的叠加。
4SurfaceFlinger的运行框架
我们从前面的章节
4.1SurfaceFlinger::readyToRun()
(1)建立GraphicPanle
(2)建立FrameBufferHardware(确定输出目标)
初始化:OpenGLES
建立兼容的mainSurface.利用eglCreateWindowSurface。
建立OpenGLES进程上下文。
建立主Surface(OpenGLES)。DisplayHardware的Init()@DisplayHardware.cpp函数对OpenGL做了初始化,并创建立主Surface。为什么叫主Surface,因为所有的Layer在绘制时,都需要先绘制在这个主Surface上,最后系统才将主Surface的内容”投掷”到真正的屏幕上。
(3)主Surface的绑定
1)在DisplayHandware初始完毕后,hw.makeCurrent()将主Surface,OpenGLES进程上下文绑定到SurfaceFlinger的上下文中,
2)之后所有的SurfaceFlinger进程中使用EGL的所有的操作目的地都是mSurface@DisplayHardware。
4.2ThreadLoop
(1)handleTransaction(…):主要计算每个Layer有无属性修改,如果有修改着内用需要重画。
(2)handlePageFlip()
computeVisibleRegions:根据Z-Order序列计算每个Layer的可见区域和被覆盖区域。裁剪输出范围计算-
在生成裁剪区域的时候,根据Z_order依次,每个Layer在计算自己在屏幕的可显示区域时,需要经历如下步骤:
1)以自己的W,H给出自己初始的可见区域
2)减去自己上面窗口所覆盖的区域
在绘制时,Layer将根据自己的可将区域做相应的区域数据Copy。
(3)handleRepaint()
composeSurfaces(需要刷新区域):
根据每个Layer的可见区域与需要刷新区域的交集区域从Z-Order序列从底部开始绘制到主Surface上。
(4)postFramebuffer()
(DisplayHardware)hw.flip(mInvalidRegion);
eglSwapBuffers(display,mSurface):将mSruface投递到屏幕。
5总结
现在SurfaceFlinger干的事情利用下面的示意图表示出来:
更详细地,参考
AndroidGUI之SurfaceFlinger系列
SurfaceFlinger使用的各组件,参考
*******************************************************************************
CopybitHALIntroduction
SurfaceFlingerlayer的compositionType有三种:
HWC_FRAMEBUFFER的使用OpenGLES来绘制;
HWC_OVERLAY的使用OverlayEngine来合成;
HWC_USE_COPYBIT的使用Copybit硬件加速绘制;
MSM8xxx平台Jellybean代码中没有发现使用HWC_USE_COPYBIT的layer,该平台下Copybit硬件加速主要有两种:
PPP:vpe模块的PPP,directcopy;
C2D:可能是2DGPUOpenVG之类的。
PPP驱动实现是做为Framebuffer设备的一个命令MSMFB_BLIT,C2D是使用c2dhal库;
MSM7627平台下hwcomposer还是使用copybit的。
可能早期系统没有HardwareComposer,又没有GPU的时候,layerdraw就要使用Copybit去一层一层一Rect一Rect的拷贝了。
Copybit的代码在display/libcopybit下,硬件合成器使用Copybit做的封装代码在display/libhwcomposer/copybit和copybit_c2d中,前者对应PPP,后者对应C2D。
主要介绍Gralloc/FramebufferHAL设备,可以籍此考察显示Buffer(Ashmem、Pmem)的拥有者和传递。
平台中内存有ashmen、PMEM等多种内存类型,为了Video、Graphics、GPU内存访问的需要,android引入Gralloc模块实现内存的管理。Gralloc把FrameBuffer的分配也纳入了其中,并且新引入ION做为Gralloc的非FrameBuffer内存的分配器。ION对于内核态内存在用户进程之间的访问和硬件平台模块之间数据流转提供了高效的解决方案。
Android中lcd是一个帧缓冲设备,驱动程序通过处理器的lcd控制器将物理内存的一段区域设置为显存,如果向这段内存区域写入数据就会马上在lcd上显示出来。Android在HAL中提供了gralloc模块,封装了用户层对帧缓冲设备的所有操作接口,并通过SurfaceFlinger服务向应用提供显示支持。在启动过程中系统会加载gralloc模块,然后打开帧缓冲设备,获取设备的各种参数并完成gralloc模块的初始化。当应用程序需要把内容显示到lcd上时,需要通过gralloc模块申请一块图形缓冲区,然后将这块图形缓冲区映射到自己的地址空间并写入内容即可。当应用程序不再需要这块图形缓冲区时需要通过gralloc模块释放掉,然后解除对缓冲区的映射。
1、基础数据结构
gralloc模块通过structprivate_module_t来描述,该结构定义如下:
1.structprivate_module_t{
2.gralloc_module_tbase;
3.
4.private_handle_t*framebuffer;/*指向图形缓冲区的句柄*/
5.uint32_tflags;/*用来标志系统帧缓冲区是否支持双缓冲*/
6.uint32_tnumBuffers;/*表示系统帧缓冲的个数*/
7.uint32_tbufferMask;/*记录系统帧缓冲的使用情况*/
8.pthread_mutex_tlock;/*保护结构体private_module_t的并行访问*/
9.buffer_handle_tcurrentBuffer;/*描述当前正在被渲染的图形缓冲区*/
10.intpmem_master;/*pmem设备节点的描述符*/
11.void*pmem_master_base;/*pmem的起始虚拟地址*/
12.
13.structfb_var_screeninfoinfo;/*lcd的可变参数*/
14.structfb_fix_screeninfofinfo;/*lcd的固定参数*/
15.floatxdpi;/*x方向上每英寸的像素数量*/
16.floatydpi;/*y方向上每英寸的像素数量*/
17.floatfps;/*lcd的刷新率*/
18.
19.intorientation;/*显示方向*/
20.
21.enum{
22.PRIV_USAGE_LOCKED_FOR_POST=0x80000000/*flagtoindicatewe'llpostthisbuffer*/
23.};
24.};
该结构的成员记录了gralloc模块的各种参数,主要为模块自己使用,应用程序操作的图形缓冲区的数据结构是structprivate_handle_t,定义如下:
1.>#ifdef__cplusplus
2.structprivate_handle_t:publicnative_handle{
3.#else
4.structprivate_handle_t{
5.structnative_handlenativeHandle;/*用来描述一个本地句柄值*/
6.#endif
7.
8.enum{
9.PRIV_FLAGS_FRAMEBUFFER=0x00000001,
10.PRIV_FLAGS_USES_PMEM=0x00000002,
11.PRIV_FLAGS_USES_MMEM=0x00000004,
12.PRIV_FLAGS_NEEDS_FLUSH=0x00000008,
13.};
14.
15.enum{
16.LOCK_STATE_WRITE=1<<31,
17.LOCK_STATE_MAPPED=1<<30,
18.LOCK_STATE_READ_MASK=0x3FFFFFFF
19.};
21./*指向一个文件描述符,这个文件描述符要么指向帧缓冲区设备,要么指向一块匿名共享内存
22.*取决于private_handle_t描述的图形缓冲区是在帧缓冲区分配的,还是在内存中分配的*/
23.intfd;
24./*指向一个魔数,它的值由静态成员变量sMagic来指定,用来标识一个private_handle_t结构体*/
25.intmagic;
26./*用来描述一个图形缓冲区的标志,它的值要么等于0,要么等于PRIV_FLAGS_FRAMEBUFFER
27.*当一个图形缓冲区的标志值等于PRIV_FLAGS_FRAMEBUFFER的时候,就表示它是在帧缓冲区中分配的*/
28.intflags;
29.intsize;/*描述一个图形缓冲区的大小*/
30.intoffset;/*描述一个图形缓冲区的偏移地址*/
31.
32.intphys;/*图形缓冲区或帧缓冲的起始物理地址*/
33.intbase;/*图形缓冲区或帧缓冲的起始虚拟地址*/
34.intlockState;
35.intwriteOwner;
36.intpid;/*描述一个图形缓冲区的创建者的PID*/
37.
38.#ifdef__cplusplus
39.staticconstintsNumInts=9;/*有9个整数变量*/
40.staticconstintsNumFds=1;/*有1个文件描述符*/
41.staticconstintsMagic=0x3141592;
42.
43.private_handle_t(intfd,intsize,intflags):
44.fd(fd),magic(sMagic),flags(flags),size(size),offset(0),
45.phys(0),base(0),lockState(0),writeOwner(0),pid(getpid())
46.{
47.version=sizeof(native_handle);
48.numInts=sNumInts;
49.numFds=sNumFds;
50.}
51.~private_handle_t(){
52.magic=0;
53.}
54.
55.boolusesPhysicallyContiguousMemory(){
56.return(flags&PRIV_FLAGS_USES_PMEM)!=0;
57.}
58.
59./*用来验证一个native_handle_t指针是否指向了一个private_handle_t结构体*/
60.staticintvalidate(constnative_handle*h){
61.constprivate_handle_t*hnd=(constprivate_handle_t*)h;
62.if(!h||h->version!=sizeof(native_handle)||
63.h->numInts!=sNumInts||h->numFds!=sNumFds||
64.hnd->magic!=sMagic)
65.{
66.LOGE("invalidgrallochandle(at%p)",h);
67.return-EINVAL;
68.}
69.return0;
70.}
71.
72.staticprivate_handle_t*dynamicCast(constnative_handle*in){
73.if(validate(in)==0){
74.return(private_handle_t*)in;
75.}
76.returnNULL;
77.}
78.#endif
79.};
图形缓冲区的操作接口由结构structgralloc_module_t定义:
80.typedefstructgralloc_module_t{
81.structhw_module_tcommon;
82.
83./*注册一个图形缓冲区,这个指定的图形缓冲区使用一个buffer_handle_t句柄来描述*/
84.int(*registerBuffer)(structgralloc_module_tconst*module,
85.buffer_handle_thandle);
86.
87./*注销一个图形缓冲区*/
88.int(*unregisterBuffer)(structgralloc_module_tconst*module,
89.buffer_handle_thandle);
90.
91./*用来锁定一个图形缓冲区并将缓冲区映射到用户进程
92.*在锁定一块图形缓冲区的时候,可以指定要锁定的图形绘冲区的位置以及大小
93.*这是通过参数l、t、w和h来指定的,其中,参数l和t指定的是要访问的图形缓冲区的左上角位置
94.*而参数w和h指定的是要访问的图形缓冲区的宽度和长度
95.*锁定之后,就可以获得由参数参数l、t、w和h所圈定的一块缓冲区的起始地址,保存在输出参数vaddr中
96.*另一方面,在访问完成一块图形缓冲区之后,需要解除这块图形缓冲区的锁定*/
97.int(*lock)(structgralloc_module_tconst*module,
98.buffer_handle_thandle,intusage,
99.intl,intt,intw,inth,
100.void**vaddr);
101.
102.int(*unlock)(structgralloc_module_tconst*module,
103.buffer_handle_thandle);
104.
105.int(*perform)(structgralloc_module_tconst*module,
106.intoperation,...);
107.
108./*reservedforfutureuse*/
109.void*reserved_proc[7];
110.}gralloc_module_t;
gralloc设备则用结构structalloc_device_t来描述,其定义如下:
111.typedefstructalloc_device_t{
112.structhw_device_tcommon;
113.
114./*申请图形缓冲区的内存空间*/
115.int(*alloc)(structalloc_device_t*dev,intw,inth,intformat,intusage,buffer_handle_t*handle,int*stride);
116.
117./*释放图形缓冲区的内存空间*/
118.int(*free)(structalloc_device_t*dev,buffer_handle_thandle);
119.}alloc_device_t;
帧缓冲设备则采用结构structframebuffer_device_t描述:
120.typedefstructframebuffer_device_t{
121.structhw_device_tcommon;
122.
123.constuint32_tflags;/*用来记录系统帧缓冲区的标志*/
124.
125.constuint32_twidth;/*lcd显示区域的像素点数*/
126.constuint32_theight;
127.
128.constintstride;/*描述设备显示屏的一行有多少个像素点*/
129.
130./*描述系统帧缓冲区的像素格式,主要有HAL_PIXEL_FORMAT_RGBX_8888和HAL_PIXEL_FORMAT_RGB_565两种*/
131.constintformat;
132.
133.constfloatxdpi;
134.constfloatydpi;
135.constfloatfps;/*lcd刷新率*/
138.
139.intreserved[8];
140.
141./*设置帧交换间隔*/
142.int(*setSwapInterval)(structframebuffer_device_t*window,intinterval);
143.
144./*设置帧缓冲区的更新区域*/
145.int(*setUpdateRect)(structframebuffer_device_t*window,intleft,inttop,intwidth,intheight);
146.
147./*用来将图形缓冲区buffer的内容渲染到帧缓冲区中去,即显示在设备的显示屏中去*/
148.int(*post)(structframebuffer_device_t*dev,buffer_handle_tbuffer);
149.
150./*用来通知fb设备device,图形缓冲区的组合工作已经完成*/
151.int(*compositionComplete)(structframebuffer_device_t*dev);
152.
153.void*reserved_proc[8];
154.}framebuffer_device_t;
其中成员函数post对应用程序来说是最重要的接口,它将完成数据写入显存的工作:
2、gralloc模块
HAL中通过hw_get_module接口加载指定id的模块,并获得一个hw_module_t结构来打开设备,流程如下:
1.>#defineHAL_LIBRARY_PATH1"/system/lib/hw"
2.#defineHAL_LIBRARY_PATH2"/vendor/lib/hw"
4.staticconstchar*variant_keys[]={
5."ro.hardware",/*Thisgoesfirstsothatitcanpickupadifferentfileontheemulator.*/
6."ro.product.board",
7."ro.board.platform",
8."ro.arch"
9.};
10.
11.staticconstintHAL_VARIANT_KEYS_COUNT=
12.(sizeof(variant_keys)/sizeof(variant_keys[0]));
13.
14.inthw_get_module(constchar*id,conststructhw_module_t**module)
15.{
16.intstatus;
17.inti;
18.conststructhw_module_t*hmi=NULL;
19.charprop[PATH_MAX];
20.charpath[PATH_MAX];
21.
22./*
23.*Herewerelyonthefactthatcallingdlopenmultipletimeson
24.*thesame.sowillsimplyincrementarefcount(andnotload
25.*anewcopyofthelibrary).
26.*Wealsoassumethatdlopen()isthread-safe.
27.*/
28.
29./*Loopthroughtheconfigurationvariantslookingforamodule*/
30.for(i=0;i 31.if(i 32.if(property_get(variant_keys[i],prop,NULL)==0){/*读取variant_keys数组指定的属性值*/ 33.continue; 34.} 35.snprintf(path,sizeof(path),"%s/%s.%s.so",/*格式化模块名和路径,如:/system/lib/hw/gralloc.xxx.so*/ 36.HAL_LIBRARY_PATH1,id,prop); 37.if(access(path,R_OK)==0)break; 38. 39.snprintf(path,sizeof(path),"%s/%s.%s.so", 40.HAL_LIBRARY_PATH2,id,prop); 41.if(access(path,R_OK)==0)break; 42.}else{ 43.snprintf(path,sizeof(path),"%s/%s.default.so", 44.HAL_LIBRARY_PATH1,id); 45.if(access(path,R_OK)==0)break; 46.} 47.} 48. 49.status=-ENOENT; 50.if(i 51./*loadthemodule,ifthisfails,we'redoomed,andweshouldnottrytoloadadifferentvariant.*/ 52.status=load(id,path,module);/*加载模块*/ 55.returnstatus; 56.} 可以看出,是使用id和系统平台的名字组合出so的文件名,去设定的目录动态加载该库文件然后解析特定符号,找到hw_module_tobject。函数会在/system/lib/hw或者/vendor/lib/hw目录中去寻找gralloc.xxx.so文件,如果找到了就调用load接口完成加载。最终会调用gralloc_device_open完成gralloc设备成员的初始化: 1.intgralloc_device_open(consthw_module_t*module,constchar*name, 2.hw_device_t**device) 3.{ 4.98intstatus=-EINVAL; 5.99if(!strcmp(name,GRALLOC_HARDWARE_GPU0)){ 6.100constprivate_module_t*m=reinterpret_cast 7.101module); 8.102gpu_context_t*dev; 9.103IAllocController*alloc_ctrl=IAllocController::getInstance(); 10.104dev=newgpu_context_t(m,alloc_ctrl); 11.105*device=&dev->common; 12.106status=0; 13.}else{ 14.status=fb_device_open(module,name,device); 15.} 16. 17.returnstatus; 18.} 可以认为Grallocmodule中有两个设备gpu_alloc_device和fb_device,前者用于分配GPU0使用的内存和FB内存,GPU0内存管理使用IONallocator;后者用于获取分配FramebufferInfo并操作fb。 在android系统中,所有的图形缓冲区都是由SurfaceFlinger服务分配的,在系统帧缓冲区中分配的图形缓冲区只在SurfaceFlinger服务中使用,而在内存中分配的图形缓冲区既可以在SurfaceFlinger服务中使用,也可以在其它的应用程序中使用,当应用程序请求SurfaceFlinger服务分配图形缓冲区时会发生两次映射:服务所在的进程首先会将申请到的缓冲区映射至服务的地址空间,然后应用程序使用这个图形缓冲时再将其映射至应用程序的地址空间。分配函数的实现如下: 1.staticintgralloc_alloc_framebuffer(alloc_device_t*dev,size_tsize,intusage,buffer_handle_t*pHandle) 2.{ 3.private_module_t*m=reinterpret_cast 4.dev->common.module); 5.pthread_mutex_lock(&m->lock); 6.interr=gralloc_alloc_framebuffer_locked(dev,size,usage,pHandle); 7.pthread_mutex_unlock(&m->lock); 8.returnerr; 9.} 11.staticintgralloc_alloc_buffer(alloc_device_t*dev,size_tsize,intusage,buffer_handle_t*pHandle) 12.{ 13.127interr=0; 14.128intflags=0; 15.129size=roundUpToPageSize(size); 16.130alloc_datadata; 17.131data.offset=0; 18.132data.fd=-1; 19.133data.base=0; 20.134data.size=size; 21.135if(format==HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) 22.136data.align=8192; 23.137else 24.138data.align=getpagesize(); 25.139data.pHandle=(unsignedint)pHandle; 26.140err=mAllocCtrl->allocate(data,usage); 27.141 28.142if(!err){ 29.143/*allocatememoryforenhancementdata*/ 30.144alloc_dataeData; 31.145eData.fd=-1; 32.146eData.base=0; 33.147eData.offset=0; 34.148eData.size=ROUND_UP_PAGESIZE(sizeof(MetaData_t)); 35.149eData.pHandle=data.pHandle; 36.150eData.align=getpagesize(); 37.151inteDataUsage=GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP; 38.152inteDataErr=mAllocCtrl->allocate(eData,eDataUsage); 39.153ALOGE_IF(eDataErr,"grallocfailedforeDataerr=%s",strerror(-err)); 40.154 41.155if(usage&GRALLOC_USAGE_PRIVATE_UNSYNCHRONIZED){ 42.156flags|=private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED; 43.157} 44.158 45.159if(usage&GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY){ 46.160flags|=private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY; 47.161//TheEXTERNAL_BLOCKflagisalwaysanadd-on 48.162if(usage&GRALLOC_USAGE_PRIVATE_EXTERNAL_BLOCK){ 49.163flags|=private_handle_t::PRIV_FLAGS_EXTERNAL_BLOCK; 50.164} 51.165if(usage&GRALLOC_USAGE_PRIVATE_EXTERNAL_CC){ 52.166flags|=private_handle_t::PRIV_FLAGS_EXTERNAL_CC; 53.167} 54.168} 55.169 56.170flags|=data.allocType; 57.171inteBaseAddr=int(eData.base)+eData.offset; 58.172private_handle_t*hnd=newprivate_handle_t(data.fd,size,flags, 59.173bufferType,format,width,height,eData.fd,eData.offset, 60.174eBaseAddr); 61.175 62.176hnd->offset=data.offset; 63.177hnd->base=int(data.base)+data.offset; 64.178*pHandle=hnd; 65.179} 66.180 67.181ALOGE_IF(err,"grallocfailederr=%s",strerror(-err)); 68.182 69.183returnerr; 70.184} 72./*****************************************************************************/ 73. 74.staticintgralloc_alloc(alloc_device_t*dev,intw,inth,intformat,intusage, 75.buffer_handle_t*pHandle,int*pStride) 76.{ 77.if(!pHandle||!pStride) 78.return-EINVAL; 79. 80.size_tsize,stride; 81. 82.intalign=4; 83.intbpp=0; 84.switch(format){/*一个像素点占用的字节数*/ 85.caseHAL_PIXEL_FORMAT_RGBA_8888: 86.caseHAL_PIXEL_FORMAT_RGBX_8888: 87.caseHAL_PIXEL_FORMAT_BGRA_8888: 88.bpp=4; 89.break; 90.caseHAL_PIXEL_FORMAT_RGB_888: 91.bpp=3; 92.break; 93.caseHAL_PIXEL_FORMAT_RGB_565: 94.caseHAL_PIXEL_FORMAT_RGBA_5551: 95.caseHAL_PIXEL_FORMAT_RGBA_4444: 96.bpp=2; 97.break; 98.default: 99.return-EINVAL; 100.} 101.size_tbpr=(w*bpp+(align-1))&~(align-1); 102.size=bpr*h; 103.stride=bpr/bpp; 105.interr; 106.if(usage&GRALLOC_USAGE_HW_FB){ 107.err=gralloc_alloc_framebuffer(dev,size,usage,pHandle);/*在系统帧缓冲中分配图形缓冲区*/ 108.}else{ 109.err=gralloc_alloc_buffer(dev,size,usage,pHandle);/*在内存中分配图形缓冲区*/ 110.} 111. 112.if(err<0){ 113.returnerr; 114.} 115. 116.*pStride=stride; 117.return0; 118.} 3、gpu_alloc模块 gpu0内存即非HW_FB内存使用ION分配器进行分配,此文不做详述。 4、fb模块 gralloc_device_open中会根据传递的参数分别初始化两个设备,定义如下: 1.>#defineGRALLOC_HARDWARE_FB0"fb0" 2.#defineGRALLOC_HARDWARE_GPU0"gpu0" 如果参数不是"gpu0",那么是"fb%u"的形式,则会调用fb_device_open初始化fb设备,主要流程和打开gralloc基本一致,在函数中会通过调用mapFrameBuffer->mapFrameBufferLocked获取帧缓存设备的参数并将其设备节点映射到用户空间,流程如下(大致如此,msm8960平台代码有所变化,msm平台上fb设备文件名是/dev/graphics/fb%u): 1.intmapFrameBufferLocked(structprivate_module_t*module) 3.if(module->framebuffer){ 4.return0; 5.} 6. 7.charconst*constdevice_template[]={ 8."/dev/graphics/fb%u", 9."/dev/fb%u", 10.0}; 11. 12.intfd=-1; 13.inti=0; 14.charname[64]; 15. 16.while((fd==-1)&&device_template[i]){ 17.snprintf(name,64,device_template[i],0); 18.fd=open(name,O_RDWR,0); 19.i++; 20.} 21.if(fd<0) 22.return-errno; 23. 24.structfb_fix_screeninfofinfo; 25.if(ioctl(fd,FBIOGET_FSCREENINFO,&finfo)==-1)/*获取帧缓冲的固定参数*/ 26.return-errno; 27. 28.structfb_var_screeninfoinfo; 29.if(ioctl(fd,FBIOGET_VSCREENINFO,&info)==-1)/*获取帧缓冲的可变参数*/ 30.return-errno; 32.info.reserved[0]=0; 33.info.reserved[1]=0; 34.info.reserved[2]=0; 35.info.xoffset=0; 36.info.yoffset=0; 37.info.activate=FB_ACTIVATE_NOW; 39.info.bits_per_pixel=32; 40.info.red.offset=16; 41.info.red.length=8; 42.info.green.offset=8; 43.info.green.length=8; 44.info.blue.offset=0; 45.info.blue.length=8; 46.info.transp.offset=24; 47.info.transp.length=8; 49./* 50.*RequestNUM_BUFFERSscreens(atlest2forpageflipping) 51.*/ 52.info.yres_virtual=info.yres*NUM_BUFFERS;/*帧缓冲总长度*/ 53. 55.uint32_tflags=PAGE_FLIP;/*支持缓冲交换*/ 56.if(ioctl(fd,FBIOPAN_DISPLAY,&info)==-1){ 57.info.yres_virtual=info.yres; 58.flags&=~PAGE_FLIP; 59.LOGW("FBIOPAN_DISPLAYfailed,pageflippingnotsupported"); 60.} 61. 62.if(info.yres_virtual 63./*weneedatleast2forpage-flipping*/ 64.info.yres_virtual=info.yres; 65.flags&=~PAGE_FLIP; 66.LOGW("pageflippingnotsupported(yres_virtual=%d,requested=%d)", 67.info.yres_virtual,info.yres*2); 69. 70.if(ioctl(fd,FBIOGET_VSCREENINFO,&info)==-1) 71.return-errno; 72. 73.intrefreshRate=1000000000000000LLU/ 74.( 75.uint64_t(info.upper_margin+info.lower_margin+info.yres) 76.*(info.left_margin+info.right_margin+info.xres) 77.*info.pixclock 78.);/*计算lcd刷新率*/ 80.if(refreshRate==0){ 81./*bleagh,badinfofromthedriver*/ 82.refreshRate=60*1000;//60Hz 83.} 84. 85.if(int(info.width)<=0||int(info.height)<=0){ 86./*thedriverdoesn'treturnthatinformation,defaultto160dpi*/ 87.info.width=((info.xres*25.4f)/160.0f+0.5f); 88.info.height=((info.yres*25.4f)/160.0f+0.5f); 89.} 91.floatxdpi=(info.xres*25.4f)/info.width; 92.floatydpi=(info.yres*25.4f)/info.height; 93.floatfps=refreshRate/1000.0f; 94. 95.LOGI("using(fd=%d)\n" 96."id=%s\n" 97."xres=%dpx\n" 98."yres=%dpx\n" 99."xres_virtual=%dpx\n" 100."yres_virtual=%dpx\n" 101."bpp=%d\n" 102."r=%2u:%u\n" 103."g=%2u:%u\n" 104."b=%2u:%u\n", 105.fd, 106.finfo.id, 107.info.xres, 108.info.yres, 109.info.xres_virtual, 110.info.yres_virtual, 111.info.bits_per_pixel, 112.info.red.offset,info.red.length, 113.info.green.offset,info.green.length, 114.info.blue.offset,info.blue.length 115.); 117.LOGI("width=%dmm(%fdpi)\n" 118."height=%dmm(%fdpi)\n" 119."refreshrate=%.2fHz\n", 120.info.width,xdpi, 121.info.height,ydpi, 122.fps 123.); 125.if(ioctl(fd,FBIOGET_FSCREENINFO,&finfo)==-1) 126.return-errno; 128.if(finfo.smem_len<=0) 129.return-errno; 130. 131.module->flags=flags; 132.module->info=info; 133.module->finfo=finfo; 134.module->xdpi=xdpi; 135.module->ydpi=ydpi; 136.module->fps=fps; 137. 138./* 139.*maptheframebuffer 140.*/ 141. 142.interr; 143.size_tfbSize=roundUpToPageSize(finfo.line_length*info.yres_virtual);/*帧缓冲大小*/ 144.module->framebuffer=newprivate_handle_t(dup(fd),fbSize, 145.private_handle_t::PRIV_FLAGS_USES_PMEM); 147.module->numBuffers=info.yres_virtual/info.yres;/*计算系统帧缓冲的个数*/ 148.module->bufferMask=0; 150.void*vaddr=mmap(0,fbSize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);/*将fb映射到用户空间*/ 151.if(vaddr==MAP_FAILED){ 152.LOGE("Errormappingtheframebuffer(%s)",strerror(errno)); 153.return-errno; 154.} 155.module->framebuffer->base=intptr_t(vaddr);/*帧缓冲的起始虚拟地址*/ 156.memset(vaddr,0,fbSize); 157.return0; 158.} 关于fb设备的打开和HW_FB内存的分配,是在FrameBufferNativeWindow的构造代码中,可以看到打开fb0设备获取FramebufferInfo,然后使用gralloc为该FrameBufferNativeWindow分配两个HW_FB内存即Framebuffer,即每个Window,doublebuffer。代码如下: 1.62/* 2.63*Thisimplementsthe(main)framebuffermanagement.Thisclassisused 3.64*mostlybySurfaceFlinger,butalsobycommandlineGLapplication. 4.65* 5.66*InfactthisisanimplementationofANativeWindowontopof 6.67*theframebuffer. 7.68* 8.69*Currentlyitisprettysimple,itmanagesonlytwobuffers(thefrontand 9.70*backbuffer). 10.71* 11.72*/ 12.73 13.74FramebufferNativeWindow::FramebufferNativeWindow() 14.75:BASE(),fbDev(0),grDev(0),mUpdateOnDemand(false) 15.76{ 16.77hw_module_tconst*module; 17.78if(hw_get_module(GRALLOC_HARDWARE_MODULE_ID,&module)==0){ 18.79intstride; 19.80interr; 20.81inti; 21.82err=framebuffer_open(module,&fbDev); 22.83ALOGE_IF(err,"couldn'topenframebufferHAL(%s)",strerror(-err)); 23.84 24.85err=gralloc_open(module,&grDev); 25.86ALOGE_IF(err,"couldn'topengrallocHAL(%s)",strerror(-err)); 26.87 27.88//bailoutifwecan'tinitializethemodules 28.89if(!fbDev||!grDev) 29.90return; 30.91 31.92mUpdateOnDemand=(fbDev->setUpdateRect!=0); 32.93 33.94//initializethebufferFIFO 34.95if(fbDev->numFramebuffers>=MIN_NUM_FRAME_BUFFERS&& 35.96fbDev->numFramebuffers<=MAX_NUM_FRAME_BUFFERS){ 36.97mNumBuffers=fbDev->numFramebuffers; 37.98}else{ 38.99mNumBuffers=MIN_NUM_FRAME_BUFFERS; 39.100} 40.101mNumFreeBuffers=mNumBuffers; 41.102mBufferHead=mNumBuffers-1; 42.103 43.104/* 44.105*Thisdoesnotactuallychangetheframebufferformat.Itmerely 45.106*fakesthisformattosurfaceflingersothatwhenitcreates 46.107*framebuffersurfacesitwillusethisformat.It'sreallyagiant 47.108*HACKtoallowinterworkingwithbuggygralloc+GPUdriver 48.109*implementations.Youshould*NEVER*needtosetthisforshipping 49.110*devices. 50.111*/ 51.112#ifdefFRAMEBUFFER_FORCE_FORMAT 52.113*((uint32_t*)&fbDev->format)=FRAMEBUFFER_FORCE_FORMAT; 53.114#endif 54.115 55.116for(i=0;i 56.117{ 57.118buffers[i]=newNativeBuffer( 58.119fbDev->width,fbDev->height,fbDev->format,GRALLOC_USAGE_HW_FB); 59.120} 60.121 61.122for(i=0;i 62.123{ 63.124err=grDev->alloc(grDev, 64.125fbDev->width,fbDev->height,fbDev->format, 65.126GRALLOC_USAGE_HW_FB,&buffers[i]->handle,&buffers[i]->stride); 66.127 67.128ALOGE_IF(err,"fbbuffer%dallocationfailedw=%d,h=%d,err=%s", 68.129i,fbDev->width,fbDev->height,strerror(-err)); 69.130 70.131if(err) 71.132{ 72.133mNumBuffers=i; 73.134mNumFreeBuffers=i; 74.135mBufferHead=mNumBuffers-1; 75.136break; 76.137} 77.138} 78.139 79.140const_cast 80.141const_cast 81.142const_cast 82.143const_cast 83.144fbDev->minSwapInterval; 84.145const_cast 85.146fbDev->maxSwapInterval; 86.147}else{ 87.148ALOGE("Couldn'tgetgrallocmodule"); 88.149} 89.150 90.151ANativeWindow::setSwapInterval=setSwapInterval; 91.152ANativeWindow::dequeueBuffer=dequeueBuffer; 92.153ANativeWindow::lockBuffer=lockBuffer; 93.154ANativeWindow::queueBuffer=queueBuffer; 94.155ANativeWindow::query=query; 95.156ANativeWindow::perform=perform; 96.157ANativeWindow::cancelBuffer=NULL; 97.158} 创建FrameBufferNativeWindow仅发生在DisplayHardware的构造后初始化中,代码片段如下: 1.150voidDisplayHardware::init(uint32_tdpy) 2.151{ 3.152mNativeWindow=newFramebufferNativeWindow();//****** 4.153framebuffer_device_tconst*fbDev=mNativeWindow->getDevice(); 5.154if(!fbDev){ 6.155ALOGE("Displaysubsystemfailedtoinitialize.checklogs.exiting..."); 7.156exit(0); 8.157} 9.158 10.159intformat; 11.160ANativeWindowconst*constwindow=mNativeWindow.get(); 12.161window->query(window,NATIVE_WINDOW_FORMAT,&format); 13.162mDpiX=mNativeWindow->xdpi; 14.163mDpiY=mNativeWindow->ydpi; 15.164mRefreshRate=fbDev->fps; 16..... 17.} 1.217status_tSurfaceFlinger::readyToRun() 2.218{ 3.219ALOGI("SurfaceFlinger'smainthreadreadytorun." 4.220"InitializinggraphicsH/W..."); 5.221 6.222//weonlysupportonedisplaycurrently 7.223intdpy=0; 8.224 9.225{ 10.226//initializethemaindisplay 11.227GraphicPlane&plane(graphicPlane(dpy)); 12.228DisplayHardware*consthw=newDisplayHardware(this,dpy);//******* 13.229plane.setDisplayHardware(hw); 14.230} 15.231 16.232//createthesharedcontrol-block 17.233mServerHeap=newMemoryHeapBase(4096, 18.234MemoryHeapBase::READ_ONLY,"SurfaceFlingerread-onlyheap"); 19.235ALOGE_IF(mServerHeap==0,"can'tcreatesharedmemorydealer"); 20.236 21.237mServerCblk=static_cast 22.238ALOGE_IF(mServerCblk==0,"can'tgettosharedcontrolblock'saddress"); 23.239 24.240new(mServerCblk)surface_flinger_cblk_t; 25.241 26.242//initializeprimaryscreen 27.243//(otherdisplayshouldbeinitializedinthesamemanner,but 28.244//asynchronously,astheycouldcomeandgo.Noneofthisissupported 29.245//yet). 30.246constGraphicPlane&plane(graphicPlane(dpy)); 31.247constDisplayHardware&hw=plane.displayHardware(); 32.248constuint32_tw=hw.getWidth(); 33.249constuint32_th=hw.getHeight(); 34.250constuint32_tf=hw.getFormat(); 35.251hw.makeCurrent(); 36...... 37.} fb模块最重要的工作就是将应用程序指定的内容写入显存中,是通过函数fb_post完成的,流程如下(msm8960代码大致如此,不过使用的是FBIOPUT_VSCREENINFOIOCTL_CODE): 1./*将图形缓冲区buffer的内容渲染到帧缓冲区中去*/ 2.staticintfb_post(structframebuffer_device_t*dev,buffer_handle_tbuffer) 4.unsignedintphys; 5.void*virt; 6.intpitch; 7.intformat; 8. 9./*首先验证参数handle指向的一块图形缓冲区的确是由Gralloc模块分配的*/ 10.if(private_handle_t::validate(buffer)<0) 11.return-EINVAL; 13.fb_context_t*ctx=(fb_context_t*)dev; 15.private_handle_tconst*hnd=reinterpret_cast 16.private_module_t*m=reinterpret_cast 17. 18.if(m->currentBuffer){/*当前正在渲染的图形缓冲区*/ 19.m->base.unlock(&m->base,m->currentBuffer); 20.m->currentBuffer=0; 21.} 22. 23.if(hnd->flags&private_handle_t::PRIV_FLAGS_FRAMEBUFFER){/*如果图形缓冲区是在系统帧缓冲中分配的*/ 24.m->base.lock(&m->base,buffer,/*锁定图像缓冲区*/ 25.private_module_t::PRIV_USAGE_LOCKED_FOR_POST, 26.0,0,m->info.xres,m->info.yres,NULL); 28.constsize_toffset=hnd->base-m->framebuffer->base;/*计算图形缓冲区与帧缓冲的偏移*/ 29./*将作为参数的fb_var_screeninfo结构体的成员变量activate的值设置FB_ACTIVATE_VBL 30.*表示要等到下一个垂直同步事件出现时,再将当前要渲染的图形缓冲区的内容绘制出来 31.*这样做的目的是避免出现屏幕闪烁,即避免前后两个图形缓冲区的内容各有一部分同时出现屏幕中*/ 32.m->info.activate=FB_ACTIVATE_VBL; 33.m->info.yoffset=offset/m->finfo.line_length;/*得到偏移的起始行*/ 34. 35.if(ioctl(m->framebuffer->fd,FBIOPAN_DISPLAY,&m->info)==-1){/*刷新显示内容*/ 36.LOGE("FBIOPAN_DISPLAYfailed"); 37.m->base.unlock(&m->base,buffer); 38.return-errno; 39.} 40. 41.if(UNLIKELY(mDebugFps)){ 42.debugShowFPS(); 43.} 44. 45.m->currentBuffer=buffer;/*设置当前图形缓冲区*/ 46.return0; 5、Grallocmap/unmap、register/unregister 当GPU内存filedescriptor从一个进程A传递到另一个进程B后,进程B做gralloc_register_buffer就是使用allocator此时是ION将该buffer在本进程映射一下,用于访问。这些功能做为gralloc的mapper功能。 关于内存filedescriptor、binder传递该内存fd的具体机制参见ION的功能。 SurfaceFlingerLayerClip&Draw /* *收到VSYNC后REFRESH显示 */ 413voidSurfaceFlinger::onMessageReceived(int32_twhat) 419//ifwe'reinaglobaltransaction,don'tdoanything. 420constuint32_tmask=eTransactionNeeded|eTraversalNeeded; 421uint32_ttransactionFlags=peekTransactionFlags(mask); 422if(CC_UNLIKELY(transactionFlags)){ 423handleTransaction(transactionFlags); 424} 425 426//postsurfaces(ifneeded) 427handlePageFlip(); 428 435handleRefresh(); 436 437constDisplayHardware&hw(graphicPlane(0).displayHardware()); 438 443if(CC_UNLIKELY(mHwWorkListDirty)){ 444//buildtheh/wworklist 445handleWorkList(); 446} 447 448if(CC_LIKELY(hw.canDraw())){ 449//repainttheframebuffer(ifneeded) 450handleRepaint(); 451//informtheh/wthatwe'redonecompositing 452hw.compositionComplete(); 453postFramebuffer(); 454}else{ 455//pretendwedidthepost 456hw.compositionComplete(); 457} 511voidSurfaceFlinger::handleTransactionLocked(uint32_ttransactionFlags) 512{ 513constLayerVector¤tLayers(mCurrentState.layersSortedByZ); 514constsize_tcount=currentLayers.size(); 515 516/* 517*Traversalofthechildren 518*(performthetransactionforeachofthemifneeded) 519*/ 520 *针对每个Layer,提交其所做的状态变化 521constboollayersNeedTransaction=transactionFlags&eTraversalNeeded; 522if(layersNeedTransaction){ 523for(size_ti=0;i 524constsp 525uint32_ttrFlags=layer->getTransactionFlags(eTransactionNeeded); 526if(!trFlags)continue; 527 528constuint32_tflags=layer->doTransaction(0); 529if(flags&Layer::eVisibleRegion) 530mVisibleRegionsDirty=true; 531} 532} 533 534/* 535*Performourowntransactionifneeded 536*/ 537/* *处理SurfaceFlinger全局状态变化 538if(transactionFlags&eTransactionNeeded){ *如果屏幕发生旋转,则设置mDirtyRegion为整个屏幕范围,更新mServerCblk *客户端可以访问到,通知HWC屏幕位向改变重新设置其参数。 539if(mCurrentState.orientation!=mDrawingState.orientation){ 540//theorientationhaschanged,recomputeallvisibleregions 541//andinvalidateeverything. 542 543constintdpy=0; 544constintorientation=mCurrentState.orientation; 545//Currentlyunused:constuint32_tflags=mCurrentState.orientationFlags; 546GraphicPlane&plane(graphicPlane(dpy)); 547plane.setOrientation(orientation); 548constTransform&planeTransform(plane.transform()); 549 550//updatethesharedcontrolblock 551constDisplayHardware&hw(plane.displayHardware()); 552volatiledisplay_cblk_t*dcblk=mServerCblk->displays+dpy; 553dcblk->orientation=orientation; 554dcblk->w=plane.getWidth(); 555dcblk->h=plane.getHeight(); 556 557mVisibleRegionsDirty=true; 558mDirtyRegion.set(hw.bounds()); 559 560//settheneworientationtoHWC 561HWComposer&hwc(graphicPlane(0).displayHardware().getHwComposer()); 562hwc.eventControl(DisplayHardware::EVENT_ORIENTATION, 563planeTransform.getOrientation()); 564 565} 566 *如果有Layer增加,设置赃区域标志,此时mDirtyRegion还为空, *每次Repaint后mDirtyRegion就清空了。 *此处的判断条件使用Layer个数比较,需要与下面mLayersRemoved结合看。 *如果Layer有减少,即使增加的个数小于减少的个数, *那么mVisibleRegionsDirty一定会被设置。 *如果没有减少,增加Layer后数目一定会增多。可读性不好。 567if(currentLayers.size()>mDrawingState.layersSortedByZ.size()){ 568//layershavebeenadded 569mVisibleRegionsDirty=true; 570} 571 *有减少的Layer,那么其下Layer可能会暴露出来,需要Invalidate该Layer *暴露出来的区域,所以需要记录这块区域。 *所有移除layer暴露出来的区域累积,记录在mDirtyRegionRemovedLayer中。 *Invalidate的效果是在lockPageFlip后,将mDirtyRegionRemovedLayer加到 *mDirtyRegion中。 *用户绘图后Post的赃区域在unlockPageFlip时做。 572//somelayersmighthavebeenremoved,so 573//weneedtoupdatetheregionsthey'reexposing. 574if(mLayersRemoved){ 575mLayersRemoved=false; 576mVisibleRegionsDirty=true; 577constLayerVector&previousLayers(mDrawingState.layersSortedByZ); 578constsize_tcount=previousLayers.size(); 579for(size_ti=0;i 580constsp 581if(currentLayers.indexOf(layer)<0){ 582//thislayerisnotvisibleanymore 583mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen); 584} 585} 586} 587} 588 *复制CurrentState到DrawingState中,即提交,下面代码处理Repaint时使用DrawingState 589commitTransaction(); 590} 735voidSurfaceFlinger::handlePageFlip() 736{ 737ATRACE_CALL(); 738constDisplayHardware&hw=graphicPlane(0).displayHardware(); 739constRegionscreenRegion(hw.bounds()); 740 *更新每个Layer的脏区域,获取每Layer这次重绘所需要的GraphicBuffer, *为每Layer生成纹理供GPUrender使用。 741constLayerVector¤tLayers(mDrawingState.layersSortedByZ); 742constboolvisibleRegions=lockPageFlip(currentLayers); 743 744if(visibleRegions||mVisibleRegionsDirty){ 745RegionopaqueRegion; *计算更新mDirtyRegion,得到所有OpaquedLayers的总的Region。 746computeVisibleRegions(currentLayers,mDirtyRegion,opaqueRegion); 747 748/* 749*rebuildthevisiblelayerlist;重建mVisibleLayersSortedByZ 750*/ 751constsize_tcount=currentLayers.size(); 752mVisibleLayersSortedByZ.clear(); 753mVisibleLayersSortedByZ.setCapacity(count); 754for(size_ti=0;i 755if(!currentLayers[i]->visibleRegionScreen.isEmpty()) 756mVisibleLayersSortedByZ.add(currentLayers[i]); 757} 758 *opaqueRegion区域外的区域绘制“虫洞”,记录该区域 759mWormholeRegion=screenRegion.subtract(opaqueRegion); *本轮处理中mVisibleRegionsDirty标志使用完毕,重置。 760mVisibleRegionsDirty=false; 761invalidateHwcGeometry(); 762} 763 *主要是将每个Layer用户Post的区域并到赃区域上 764unlockPageFlip(currentLayers); 765 766mDirtyRegion.orSelf(getAndClearInvalidateRegion()); 767mDirtyRegion.andSelf(screenRegion); 768} 775boolSurfaceFlinger::lockPageFlip(constLayerVector¤tLayers) 776{ 777boolrecomputeVisibleRegions=false; 778size_tcount=currentLayers.size(); 779sp 780for(size_ti=0;i 781constsp 782layer->lockPageFlip(recomputeVisibleRegions); 783} 784returnrecomputeVisibleRegions; 785} 527voidLayer::lockPageFlip(bool&recomputeVisibleRegions) 528{ 529ATRACE_CALL(); 530 *本Layer有新QueuedBuffer才需要更新纹理。 531if(mQueuedFrames>0){ 532 533//ifwe'vealreadycalledupdateTexImage()withoutgoingthrough 534//acompositionstep,wehavetoskipthislayeratthispoint 535//becausewecannotcallupdateTeximage()withoutacorresponding 536//compositionComplete()call. 537//we'lltriggeranupdateinonPreComposition(). *如果上次的重绘还没有显示,本轮又要显示了,直接返回。 538if(mRefreshPending){ 539mPostedDirtyRegion.clear(); 540return; 541} 543//Capturetheoldstateofthelayerforcomparisonslater 544constboololdOpacity=isOpaque(); 545sp 546 *因为有mRefreshPending时导致直接return,所有需要“引发”下个Frame的显示; *signalLayerUpdate()即是requestNextVsync(),因为setRefreshRate(0)时, *不接收VSYNC,所以需要显式要求下一个VSYNC发过来,“引发”下帧显示 547//signalanothereventifwehavemoreframespending 548if(android_atomic_dec(&mQueuedFrames)>1){ 549mFlinger->signalLayerUpdate(); 550} 551 *内部类用于检验Queued过来的Buffer是否符合该Layer的显示要求, *不符合则reject,不予显示。 *如Camera或Video图像buffer的大小,格式等要符合。 552structReject:publicSurfaceTexture::BufferRejecter{ 553Layer::State&front; 554Layer::State¤t; 555bool&recomputeVisibleRegions; 556Reject(Layer::State&front,Layer::State¤t, 557bool&recomputeVisibleRegions) 558:front(front),current(current), 559recomputeVisibleRegions(recomputeVisibleRegions){ 560} 561 562virtualboolreject(constsp 563constBufferQueue::BufferItem&item){ 564if(buf==NULL){ 565returnfalse; 566} 567 568uint32_tbufWidth=buf->getWidth(); 569uint32_tbufHeight=buf->getHeight(); 570 571//checkthatwereceivedabufferoftherightsize 572//(Takethebuffer'sorientationintoaccount) 573if(item.mTransform&Transform::ROT_90){ 574swap(bufWidth,bufHeight); 575} 576 577 578boolisFixedSize=item.mScalingMode!=NATIVE_WINDOW_SCALING_MODE_FREEZE; 579if(front.active!=front.requested){ 580 581if(isFixedSize|| 582(bufWidth==front.requested.w&& 583bufHeight==front.requested.h)) 584{ 585//Herewepretendthetransactionhappenedbyupdatingthe 586//currentanddrawingstates.Drawingstateisonlyaccessed 587//inthisthread,noneedtohaveitlocked 588front.active=front.requested; 589 590//Wealsoneedtoupdatethecurrentstatesothat 591//wedon'tend-upoverwritingthedrawingstatewith 592//thisstalecurrentstateduringthenexttransaction 593// 594//NOTE:Wedon'tneedtoholdthetransactionlockhere 595//becauseState::activeisonlyaccessedfromthisthread. 596current.active=front.active; 597 598//recomputevisibleregion 599recomputeVisibleRegions=true; 600} 601 622 623if(!isFixedSize){ 624if(front.active.w!=bufWidth|| 625front.active.h!=bufHeight){ 626//rejectthisbuffer 627returntrue; 628} 629} 630returnfalse; 631} 632}; 633 634 635Rejectr(mDrawingState,currentState(),recomputeVisibleRegions); 636 *使用该Layer的mActiveBuffer生成SurfaceTexture,用于OpenGL/3DGPUrender。 *图像格式不符合时,Reject::reject()被回调。 637if(mSurfaceTexture->updateTexImage(&r) 638//somethinghappened! 639recomputeVisibleRegions=true; 640return; 641} /************* *updateTexImage会释放上轮该Layer使用的GraphicBuffer; *也即本轮使用的GraphicBuffer持续到下次需要重绘时释放。 *记得其申请是在lockPageFlip中记录在mActiveBuffer。 642 *记录或更新当前使用的即mActiveBuffer字段 *注意该buffer直到该Layer下轮重绘Repaint时才Release, *期间SurfaceTexture对该Buffer是不可用的。 643//updatetheactivebuffer 644mActiveBuffer=mSurfaceTexture->getCurrentBuffer(); 645if(mActiveBuffer==NULL){ 646//thiscanonlyhappeniftheveryfirstbufferwasrejected. 647return; 648} 649 *设置mRefreshPending标志了,如果本轮还没有Paint而下次又来了,直接返回。 650mRefreshPending=true; 651mFrameLatencyNeeded=true; 652if(oldActiveBuffer==NULL){ 653//thefirsttimewereceiveabuffer,weneedtotriggera 654//geometryinvalidation. 655mFlinger->invalidateHwcGeometry(); 656} 657 *如果Crop&Transform&Scale改变,重设HWC参数 658Rectcrop(mSurfaceTexture->getCurrentCrop()); 659constuint32_ttransform(mSurfaceTexture->getCurrentTransform()); 660constuint32_tscalingMode(mSurfaceTexture->getCurrentScalingMode()); 661if((crop!=mCurrentCrop)|| 662(transform!=mCurrentTransform)|| 663(scalingMode!=mCurrentScalingMode)) 664{ 665mCurrentCrop=crop; 666mCurrentTransform=transform; 667mCurrentScalingMode=scalingMode; 668mFlinger->invalidateHwcGeometry(); 669} 670 *比较GraphicBuffer的维度是否有改变,用于更新HWC的维度参数, *从而使HWC知道该准备多大的buffer空间,和图像参数用于合成。 671if(oldActiveBuffer!=NULL){ 672uint32_tbufWidth=mActiveBuffer->getWidth(); 673uint32_tbufHeight=mActiveBuffer->getHeight(); 674if(bufWidth!=uint32_t(oldActiveBuffer->width)|| 675bufHeight!=uint32_t(oldActiveBuffer->height)){ 676mFlinger->invalidateHwcGeometry(); 677} 678} 679 680mCurrentOpacity=getOpacityForFormat(mActiveBuffer->format); 681if(oldOpacity!=isOpaque()){ 682recomputeVisibleRegions=true; 683} 684 *FIXME每个layer的dirty是在后面调用的computeVisibleRegions()中计算出来的, *可以在彼时设置给Layer,记录脏区域是个很好的优化。 *但是RegionmPostedDirtyRegion是classLayer而不是classLayerBase的成员, *慢慢FIX!此dirty非computeVisibleRegions中的dirty 685//FIXME:mPostedDirtyRegion=dirty&bounds 686constLayer::State&front(drawingState()); 687mPostedDirtyRegion.set(front.active.w,front.active.h); 688 689glTexParameterx(GL_TEXTURE_EXTERNAL_OES,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); 690glTexParameterx(GL_TEXTURE_EXTERNAL_OES,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); 691} 692} LayerClip精髓所在---- 592voidSurfaceFlinger::computeVisibleRegions( 593constLayerVector¤tLayers,Region&dirtyRegion,Region&opaqueRegion) 594{ 595ATRACE_CALL(); 596 597constGraphicPlane&plane(graphicPlane(0)); 598constTransform&planeTransform(plane.transform()); 599constDisplayHardware&hw(plane.displayHardware()); 600constRegionscreenRegion(hw.bounds()); 602RegionaboveOpaqueLayers; 603RegionaboveCoveredLayers; 604Regiondirty; 605 606boolsecureFrameBuffer=false; 607 608size_ti=currentLayers.size(); *Clip不就是计算遮挡吗?z-order从顶向底,合乎逻辑。 609while(i--){ 610constsp 611layer->validateVisibility(planeTransform); 612 613//startwiththewholesurfaceatitscurrentlocation 614constLayer::State&s(layer->drawingState()); 615 616/* 617*opaqueRegion:areaofasurfacethatisfullyopaque. 618*/ 619RegionopaqueRegion; 620 621/* 622*visibleRegion:areaofasurfacethatisvisibleonscreen 623*andnotfullytransparent.Thisisessentiallythelayer's 624*footprintminustheopaqueregionsaboveit. 625*Areascoveredbyatranslucentsurfaceareconsideredvisible. 626*/ 627RegionvisibleRegion; 628 629/* 630*coveredRegion:areaofasurfacethatiscoveredbyall 631*visibleregionsaboveit(whichincludesthetranslucentareas). 632*/ 633RegioncoveredRegion; 635 636//handlehiddensurfacesbysettingthevisibleregiontoempty 637if(CC_LIKELY(!(s.flags&ISurfaceComposer::eLayerHidden)&&s.alpha)){ //该Layer是否半透 638constbooltranslucent=!layer->isOpaque(); //该Layer可见范围 639constRectbounds(layer->visibleBounds()); 640visibleRegion.set(bounds); 641visibleRegion.andSelf(screenRegion); 642if(!visibleRegion.isEmpty()){ *如果本layer具有全透明区域(全透明子窗口),如Video或Camera, *本Layer该区域一定是不可见的,visibleRegion应该减去全透区域, *translucent的判断条件并不表示该Layer为半透,而是有全透区域时, *该Layer的Opaque属性应该设置为false,表并非FullOpaque。 *setTransparentRegion/setTransparentRegionWindow *=>setTransparentRegionHint设置透明的。 *那半透明子窗口如何呢?因为Layer的地位相当于该应用的Parentmostwindow, *所以半透子窗口下的区域也一定是本Layer的子窗口,而不可能是别的Layer, *从而该半透子窗口在本Layer范围内部就做Alpha混叠了,对于本Layer来说是 *Opaque的,所以不需要半透部分区域。半透属性是针对整个Layer的。 643//Removethetransparentareafromthevisibleregion 644if(translucent){ 645visibleRegion.subtractSelf(layer->transparentRegionScreen); 646} 647 648//computetheopaqueregion 649constint32_tlayerOrientation=layer->getOrientation(); *如果该Layer是Opaque的,那么其整个可见区域一定是遮挡下面的层的。 *记录,累积到aboveOpaqueLayers,供计算下面层的遮挡之用。 650if(s.alpha==255&&!translucent&& 651((layerOrientation&Transform::ROT_INVALID)==false)){ 652//theopaqueregionisthelayer'sfootprint 653opaqueRegion=visibleRegion; 654} 655} *coveredRegion本层被覆盖的区域,包括被上面层半透覆盖的区域,覆盖并非遮挡。 *本层可见区域总对下面层构成覆盖,累积到aboveCoveredLayers 658//Clipthecoveredregiontothevisibleregion 659coveredRegion=aboveCoveredLayers.intersect(visibleRegion); 660 661//UpdateaboveCoveredLayersfornext(lower)layer 662aboveCoveredLayers.orSelf(visibleRegion); 663 *减去本层被上面层遮挡的区域 664//subtracttheopaqueregioncoveredbythelayersaboveus 665visibleRegion.subtractSelf(aboveOpaqueLayers); 666 *计算本层的脏区域,分内容是否为脏(size是否变化)两种情形。 *如果是用内容脏,即size变化,那么认为整个区域都是脏的; *如果是移除上层的Layer暴露出本Layer区域,则计算可见的最小的脏区域; *此时赃区域是屏幕坐标系统? *这么有用的个dirty为什么不保存给各个Layer *此时的dirty还不包括用户Posted的真正意义上的脏区域! *为什么不直接地处理为visbleRegion.andSelf(mDirtyRegionRemovedLayer) *因为mDirtyRegionRemovedLayer仅是个区域,并没有记录层的透明属性。 667//computethislayer'sdirtyregion 668if(layer->contentDirty){ 669//weneedtoinvalidatethewholeregion 670dirty=visibleRegion; 671//aswell,astheoldvisibleregion 672dirty.orSelf(layer->visibleRegionScreen); 673layer->contentDirty=false; 674}else{ 675/*computetheexposedregion: 676*theexposedregionconsistsoftwocomponents: 677*1)what'sVISIBLEnowandwasCOVEREDbefore 678*2)what'sEXPOSEDnowlesswhatwasEXPOSEDbefore 679* 680*notethat(1)isconservative,westartwiththewhole 681*visibleregionbutonlykeepwhatusedtobecoveredby 682*something--whichmeanitmayhavebeenexposed. 683* 684*(2)handlesareasthatwerenotcoveredbyanythingbutgot 685*exposedbecauseofaresize. 686*/ 687constRegionnewExposed=visibleRegion-coveredRegion; 688constRegionoldVisibleRegion=layer->visibleRegionScreen; 689constRegionoldCoveredRegion=layer->coveredRegionScreen; 690constRegionoldExposed=oldVisibleRegion-oldCoveredRegion; 691dirty=(visibleRegion&oldCoveredRegion)|(newExposed-oldExposed); *被遮挡区域不需要重绘,从脏区域里除去 693dirty.subtractSelf(aboveOpaqueLayers); 694 *累积总的脏区域 695//accumulatetothescreendirtyregion 696dirtyRegion.orSelf(dirty); 697 *累积遮挡区域 698//UpdateaboveOpaqueLayersfornext(lower)layer 699aboveOpaqueLayers.orSelf(opaqueRegion); 700 *为每个Layer记录其mVisibleRegion和mCoveredRegion 701//Storethevisibleregionisscreenspace 702layer->setVisibleRegion(visibleRegion); 703layer->setCoveredRegion(coveredRegion); 704 705//Ifasecurelayerispartiallyvisible,lock-downthescreen! 706if(layer->isSecure()&&!visibleRegion.isEmpty()){ 707secureFrameBuffer=true; 708} 709} 710 *把mDirtyRegionRemovedLayer并到mDirtyRegion中去。 *有移除Layers暴露出来的区域需要其下的Layers重绘,其实这个在dirty计算时已处理 *关键的是移除的Layer是最底层Layer的时候则直接露出屏底色,所以要此处要或上。 711//invalidatetheareaswherealayerwasremoved 712dirtyRegion.orSelf(mDirtyRegionRemovedLayer); 713mDirtyRegionRemovedLayer.clear(); 714 715mSecureFrameBuffer=secureFrameBuffer; *传出遮挡区域,OpaqueRegion为所有OpaqueLayerArea之和 716opaqueRegion=aboveOpaqueLayers; 717} 787voidSurfaceFlinger::unlockPageFlip(constLayerVector¤tLayers) 788{ 789constGraphicPlane&plane(graphicPlane(0)); 790constTransform&planeTransform(plane.transform()); 791constsize_tcount=currentLayers.size(); 792sp 793for(size_ti=0;i 794constsp 795layer->unlockPageFlip(planeTransform,mDirtyRegion); 796} 797} 694voidLayer::unlockPageFlip( 695constTransform&planeTransform,Region&outDirtyRegion) 696{ 697ATRACE_CALL(); 698 699RegionpostedRegion(mPostedDirtyRegion); 700if(!postedRegion.isEmpty()){ 701mPostedDirtyRegion.clear(); 702if(!visibleRegionScreen.isEmpty()){ 703//Thedirtyregionisgiveninthelayer'scoordinatespace 704//transformthedirtyregionbythesurface'stransformation 705//andtheglobaltransformation. 706constLayer::State&s(drawingState()); 707constTransformtr(planeTransform*s.transform); 708postedRegion=tr.transform(postedRegion); 709 *computeVisibleRegions处理的赃区域是size变化和上层遮挡移除的情况,需要重绘; *而用户修改提交的区域也需要重绘,还未加到赃区域中,此时并进来。 710//Atthispoint,thedirtyregionisinscreenspace. 711//Makesureit'sconstrainedbythevisibleregion(which 712//isinscreenspaceaswell). 713postedRegion.andSelf(visibleRegionScreen); 714outDirtyRegion.orSelf(postedRegion); 715} 716} handleRefresh()没什么作用了。 handleWorkList()是为HWComposer分配缓冲工作集,用于硬件合成,暂不考察。 DisplayHardware.canDraw()用于判断当前是否处于draw过程中,屏是否已经关闭等,得出需要Repaint的判断。 835voidSurfaceFlinger::handleRepaint() 836{ 837ATRACE_CALL(); 838 839//computetheinvalidregion 840mSwapRegion.orSelf(mDirtyRegion); 841 842if(CC_UNLIKELY(mDebugRegion)){ 843debugFlashRegions(); 844} 845 846//settheframebuffer 847constDisplayHardware&hw(graphicPlane(0).displayHardware()); 848glMatrixMode(GL_MODELVIEW); 849glLoadIdentity(); 850 *针对DisplayHardware是支持RECT更新还是RECTS更新,做相应处理。 851uint32_tflags=hw.getFlags(); 852if(flags&DisplayHardware::SWAP_RECTANGLE){ 853//wecanredrawonlywhat'sdirty,butsinceSWAP_RECTANGLEonly 854//takesarectangle,wemustmakesuretoupdatethatwhole 855//rectangleinthatcase 856mDirtyRegion.set(mSwapRegion.bounds()); 857}else{ 858if(flags&DisplayHardware::PARTIAL_UPDATES){ 859//Weneedtoredrawtherectanglethatwillbeupdated 860//(pushedtotheframebuffer). 861//ThisisneededbecausePARTIAL_UPDATESonlytakesone 862//rectangleinsteadofaregion(seeDisplayHardware::flip()) 863mDirtyRegion.set(mSwapRegion.bounds()); 864}else{ 865//weneedtoredraweverything(thewholescreen) 866mDirtyRegion.set(hw.bounds()); 867mSwapRegion=mDirtyRegion; 868} 869} 870 *此处先不考虑HWC,HWC另见后续MIMOdisplay–Overlay&HWComposer *只考虑使用OpenGL/3DGPUrender的情况,即各layer->draw。 871setupHardwareComposer(); 872composeSurfaces(mDirtyRegion); 873 874//updatetheswapregionandclearthedirtyregion 875mSwapRegion.orSelf(mDirtyRegion); 876mDirtyRegion.clear(); 877} 912voidSurfaceFlinger::composeSurfaces(constRegion&dirty) 913{ 914constDisplayHardware&hw(graphicPlane(0).displayHardware()); 915HWComposer&hwc(hw.getHwComposer()); 916hwc_layer_t*constcur(hwc.getLayers()); 917 *不考虑HWC或者除HWC_OVERLAY有HWC_FB或者Layer数目超出HWC管道数时, *使用GPUrender。 918constsize_tfbLayerCount=hwc.getLayerCount(HWC_FRAMEBUFFER); 919if(!cur||fbLayerCount){ 920//Nevertouchtheframebufferifwedon'thaveanyframebufferlayers 921 *有HWC_FB有HWC_OVERLAY共存的情形,如Camera或Video *暂时认为0不表,详见后续MIMOdisplay–Overlay&HWComposer 922if(hwc.getLayerCount(HWC_OVERLAY)){ 923//whenusingoverlays,weassumeafullytransparentframebuffer 924//NOTE:wecouldreducehowmuchweneedtoclear,forinstance 925//removewherethereareopaqueFBlayers.however,onsome 926//GPUsdoinga"cleanslate"glClearmightbemoreefficient. 927//We'llrevisitlaterifneeded. 928constRegionregion(hw.bounds()); *为HWC先清原来的画面 929#ifdefQCOMHW 930if(0!=qdutils::CBUtils::qcomuiClearRegion(region, 931hw.getEGLDisplay())) 932#endif 933{ 934glClearColor(0,0,0,0); 935glClear(GL_COLOR_BUFFER_BIT); 936} 937}else{ *看来FB的时候不需要清屏;如果需要画虫洞,则为该区域清屏以显示虫洞 938//screenisalreadyclearedhere 939if(!mWormholeRegion.isEmpty()){ 940//canhappenwithSurfaceView 941#ifdefQCOMHW 942if(0!=qdutils::CBUtils::qcomuiClearRegion(mWormholeRegion, 943hw.getEGLDisplay())) 944#endif 945drawWormhole(); 946} 947} 948 *真正开画 949/* 950*andthen,renderthelayerstargetedattheframebuffer 951*/ 952 953constVector 954constsize_tcount=layers.size(); 955 *显然的,从底层向顶层画 956for(size_ti=0;i 957constsp *各Layer的赃区域 958constRegionclip(dirty.intersect(layer->visibleRegionScreen)); 959if(!clip.isEmpty()){ 960if(cur&&(cur[i].compositionType==HWC_OVERLAY)){ 961if(i&&(cur[i].hints&HWC_HINT_CLEAR_FB) 962&&layer->isOpaque()){ 963//nevercleartheveryfirstlayersincewe're 964//guaranteedtheFBisalreadycleared 965#ifdefQCOMHW 966if(0!=qdutils::CBUtils::qcomuiClearRegion(clip, 967hw.getEGLDisplay())) 968#endif 969layer->clearWithOpenGL(clip); 970} 971continue; 972} *如果是HWC_OVERLAY的,不需要Layer自己画 973#ifdefQCOMHW 974if(cur&&(cur[i].compositionType!=HWC_FRAMEBUFFER)) 975continue; 976#endif 977 *HWC_FBLayer,自己开画 978//renderthelayer 979layer->draw(clip); 980} 981} 982}elseif(cur&&!mWormholeRegion.isEmpty()){ 983constRegionregion(mWormholeRegion.intersect(mDirtyRegion)); 984if(!region.isEmpty()){ 985#ifdefQCOMHW 986if(0!=qdutils::CBUtils::qcomuiClearRegion(region, 987hw.getEGLDisplay())) 988#endif 989drawWormhole(); 990} 991} 992} 344voidLayerBase::draw(constRegion&clip)const 345{ 346//DontdrawExternal-onlylayers 347if(isLayerExternalOnly(getLayer())){ 348return; 349} 350onDraw(clip); 351} *BindTextureandDrawusingOpenGLforthislayerontheBACKFramebuffer. 321voidLayer::onDraw(constRegion&clip)const 322{ 323ATRACE_CALL(); 324 325if(CC_UNLIKELY(mActiveBuffer==0)){ 326//thetexturehasnotbeencreatedyet,thisLayerhas 327//infactneverbeendrawninto.Thishappensfrequentlywith 328//SurfaceViewbecausetheWindowManagercan'tknowwhentheclient 329//hasdrawnthefirsttime. 330 331//Ifthereisnothingunderus,wepaintthescreeninblack,otherwise 332//wejustskipthisupdate. 333 334//figureoutifthereissomethingbelowus 335Regionunder; 336constSurfaceFlinger::LayerVector&drawingLayers( 337mFlinger->mDrawingState.layersSortedByZ); 338constsize_tcount=drawingLayers.size(); 339for(size_ti=0;i 340constsp 341if(layer.get()==static_cast 342break; 343under.orSelf(layer->visibleRegionScreen); 344} 345//ifnoteverythingbelowusiscovered,weplugtheholes! 346Regionholes(clip.subtract(under)); 347if(!holes.isEmpty()){ 348clearWithOpenGL(holes,0,0,0,1); 350return; 352#ifdefQCOMHW 353if(!qdutils::isGPUSupportedFormat(mActiveBuffer->format)){ 354clearWithOpenGL(clip,0,0,0,1); 355return; 356} 357#endif 358if(!isProtected()){ 359//TODO:wecouldbemoresubtlewithisFixedSize() 360constbooluseFiltering=getFiltering()||needsFiltering()||isFixedSize(); 361 362//Querythetexturematrixgivenourcurrentfilteringmode. 363floattextureMatrix[16]; 364mSurfaceTexture->setFilteringEnabled(useFiltering); 365mSurfaceTexture->getTransformMatrix(textureMatrix); 366 367//Setthingsupfortexturing. 368glBindTexture(GL_TEXTURE_EXTERNAL_OES,mTextureName); 369GLenumfilter=GL_NEAREST; 370if(useFiltering){ 371filter=GL_LINEAR; 372} 373glTexParameterx(GL_TEXTURE_EXTERNAL_OES,GL_TEXTURE_MAG_FILTER,filter); 374glTexParameterx(GL_TEXTURE_EXTERNAL_OES,GL_TEXTURE_MIN_FILTER,filter); 375glMatrixMode(GL_TEXTURE); 376glLoadMatrixf(textureMatrix); 377glMatrixMode(GL_MODELVIEW); 378glDisable(GL_TEXTURE_2D); 379glEnable(GL_TEXTURE_EXTERNAL_OES); 380}else{ 381glBindTexture(GL_TEXTURE_2D,mFlinger->getProtectedTexName()); 382glMatrixMode(GL_TEXTURE); 383glLoadIdentity(); 384glMatrixMode(GL_MODELVIEW); 385glDisable(GL_TEXTURE_EXTERNAL_OES); 386glEnable(GL_TEXTURE_2D); 387} 388 389drawWithOpenGL(clip); 390 391glDisable(GL_TEXTURE_EXTERNAL_OES); 392glDisable(GL_TEXTURE_2D); 393} *提交FrameBuffer *对于使用GPU的情况,composeSurfaces已经将所有Surface都合成到BACKFramebuffer上了; *对于HWComposer的情况,此时还没有启动硬件合成,是在DisplayHardware::flip=> *HWComposer::commit中合成到BACKFramebuffer上并交换Framebuffer的。 *为了统一,应该把HWC合成的功能也放到composeSurfaces类似的composeLayers里面去, *不用Surface字样是因为Surface是GPU使用的,MDPHWComposer并不具有 *操作Surface/Texture的能力,而只能操作支持格式的GraphicBuffer。 463voidSurfaceFlinger::postFramebuffer() 464{ 465ATRACE_CALL(); 466//mSwapRegioncanbeemptyhereissomecases,forinstanceifahidden 467//orfullytransparentwindowisupdating. 468//inthatcase,weneedtoflipanywaystonotriskadeadlockwith 469//h/wcomposer. 470 471constDisplayHardware&hw(graphicPlane(0).displayHardware()); 472constnsecs_tnow=systemTime(); 473mDebugInSwapBuffers=now; 474hw.flip(mSwapRegion); 475 476size_tnumLayers=mVisibleLayersSortedByZ.size(); 477for(size_ti=0;i 478mVisibleLayersSortedByZ[i]->onLayerDisplayed(); 479} 480 481 482mLastSwapBufferTime=systemTime()-now; 483mDebugInSwapBuffers=0; 484mSwapRegion.clear(); 485} 435voidDisplayHardware::flip(constRegion&dirty)const 436{ 437checkGLErrors(); 439EGLDisplaydpy=mDisplay; 440EGLSurfacesurface=mSurface; 441 442#ifdefEGL_ANDROID_swap_rectangle 443if(mFlags&SWAP_RECTANGLE){ 444constRegionnewDirty(dirty.intersect(bounds())); 445constRectb(newDirty.getBounds()); 446eglSetSwapRectangleANDROID(dpy,surface, 447b.left,b.top,b.width(),b.height()); 448} 449#endif 450 451if(mFlags&PARTIAL_UPDATES){ 452mNativeWindow->setUpdateRectangle(dirty.getBounds()); 453} 454 455mPageFlipCount++; 456 *mHwc->commit中也会调用eglSwapBuffers,因为不管用什么方式, *EGL是FrameBufferNativeWindow的管理者,实现bufferswap,避免竞争。 457if(mHwc->initCheck()==NO_ERROR){ 458mHwc->commit(); 459}else{ 460eglSwapBuffers(dpy,surface); 461} 462checkEGLErrors("eglSwapBuffers"); 463 464//fordebugging 465//glClearColor(1,0,0,0); 466//glClear(GL_COLOR_BUFFER_BIT); 467} 没有GPU的eglSwapBuffers实现,就看看软的吧。 484EGLBooleanegl_window_surface_v2_t::swapBuffers() 485{ 486if(!buffer){ 487returnsetError(EGL_BAD_ACCESS,EGL_FALSE); 488} 489 490/* 491*HandleeglSetSwapRectangleANDROID() 492*Wecopybackfromthefrontbuffer 493*/ 494if(!dirtyRegion.isEmpty()){ 495dirtyRegion.andSelf(Rect(buffer->width,buffer->height)); 496if(previousBuffer){ 497//ThiswasconstRegioncopyBack,butthatcausesan 498//internalcompileerroronsimulatorbuilds *frontbuffer和backbuffer的赃区域的差值拷贝回backbuffer中; *因为frontbuffer的赃区域(即其重绘的区域)并未更新到backbuffer中, *所以需要考回来;但是backbuffer的赃区域已经重绘了,是不能覆盖掉的, *所以两个赃区域相减。 *这仅是doublebuffer的时候的实现,triplebuffer两个dirtyRegion就无法保证了。 499/*const*/RegioncopyBack(Region::subtract(oldDirtyRegion,dirtyRegion)); 500if(!copyBack.isEmpty()){ 501void*prevBits; 502if(lock(previousBuffer, 503GRALLOC_USAGE_SW_READ_OFTEN,&prevBits)==NO_ERROR){ 504//copyfrompreviousBuffertobuffer 505copyBlt(buffer,bits,previousBuffer,prevBits,copyBack); 506unlock(previousBuffer); 507} 508} 509} 510oldDirtyRegion=dirtyRegion; 511} 512/* *释放frontframebuffer 513if(previousBuffer){ 514previousBuffer->common.decRef(&previousBuffer->common); 515previousBuffer=0; 516} 517 *解锁backframebuffer,表用户用完,要queue了。queueBuffer() 518unlock(buffer); 519previousBuffer=buffer; 520nativeWindow->queueBuffer(nativeWindow,buffer); 521buffer=0; 522 *backframebuffer已经提交了,需要再dequeue下一个framebuffer来做backframebuffer *并且锁住,供使用; 523//dequeueanewbuffer 524if(nativeWindow->dequeueBuffer(nativeWindow,&buffer)==NO_ERROR){ 525 526//TODO:lockBuffershouldratherbeexecutedwhentheveryfirst 527//directrenderingoccurs. 528nativeWindow->lockBuffer(nativeWindow,buffer); 529 530//reallocatethedepth-bufferifneeded 531if((width!=buffer->width)||(height!=buffer->height)){ 532//TODO:weprobablyshouldresettheswaprecthere 533//ifthewindowsizehaschanged 534width=buffer->width; 535height=buffer->height; 536if(depth.data){ 537free(depth.data); 538depth.width=width; 539depth.height=height; 540depth.stride=buffer->stride; 541depth.data=(GGLubyte*)malloc(depth.stride*depth.height*2); 542if(depth.data==0){ 543setError(EGL_BAD_ALLOC,EGL_FALSE); 544returnEGL_FALSE; 545} 546} 547} 548 549//keepareferenceonthebuffer 550buffer->common.incRef(&buffer->common); *lock/unlock 552//finallypinthebufferdown 553if(lock(buffer,GRALLOC_USAGE_SW_READ_OFTEN| 554GRALLOC_USAGE_SW_WRITE_OFTEN,&bits)!=NO_ERROR){ 555ALOGE("eglSwapBuffers()failedtolockbuffer%p(%ux%u)", 556buffer,buffer->width,buffer->height); 557returnsetError(EGL_BAD_ACCESS,EGL_FALSE); 558//FIXME:weshouldmakesurewe'renotaccessingthebufferanymore 559} 560}else{ 561returnsetError(EGL_BAD_CURRENT_SURFACE,EGL_FALSE); 562} 563 564returnEGL_TRUE; ***************************************************************************** FileOrgnization 目录/hardware/qcom/display/liboverlay/ Android.mk mdpRotator.cppOverlayRotatorWrpper mdpWrapper.hMDPNormalandOverlayFrameBufferIOCTLWrapper mdssRotator.cppOverlayMDSSRotatorWrapper overlay.cppOverlayToplevelimplementationfile overlay.hOverlayTopleveldeclarationfile overlayCtrl.cppOverlayCtrlimplementationfile overlayCtrlData.hOverlayCtrlandOverlayDatadeclarationfileincludingOverlayDataimplementation overlayImpl.hOverlayimplementationwhichoperatesoverlaypipespair(LayerMixer) overlayMdp.cppOverlayimplementationonMDP,usedbyOverlayCtrlData overlayMdp.hOverlayonMDP overlayMem.hOverlayVGpipeinputkernelmemoryfiledescriptor,maybegraphicbufferorrotatoroutputbuffer overlayRotator.cppOverlayRotatortoplevelimplementation overlayRotator.hOverlayRotatortopleveldeclaration overlayState.hOverlaystatemachine overlayUtils.cppOverlayUtils overlayUtils.hOverlayUtils pipes/OverlayPipes,thatisOverlaychannel.ItisaVGandRGBpipepaironMDP. Platformarchitecture MDP中每个VG和RGBpipepair作为一个LayerMixer的输入,由LayerMixer完成Overlay功能,作为一个Overlaychannel。 注意,RGB和VG并不固定配对做为某个LayerMixer的输入。如MDP4.2的LayerMixer0可以合成一个Border或BaseLayer和4个layer,即可以多达5个pipe输入到LayerMixer0,从而用作HardwareComposer。 当使用Overlay功能时: RGBpipe的输入是普通的Framebuffer,是Surfaceflinger的合成输出; VG的输入是video或graphics或camera图像等,是内核空间内存buffer,其owner一般是Video、Graphics或V4L2等。当其前端是Rotator时,Rotator的输入是这些buffer,Rotator的输出Overlayrotatorframebuffer作为VG的输入。 每个OverlayChannel结构如下图所示 关于OverlayBuffer(FrameBufferRotatorBufferOverlayBuffer)这些名称并不特别明确,只要明白OverlayChannel数据流路上的各输入输出Buffer的位置和作用即可。 下面以Layermixer1(对应/dev/graphics/fb0)为参考详述各buffer: 只UI显示时, Framebuffer是fb0的framebuffer,是从启动时预留出的bootmem中的分配出来的。LayerMixer1处于BLT模式,Layermixer1和DMA_P(Primarydisplaydriver)分离,可以由软件完全控制。该Framebuffer做为DMA_P的输入,经MIPI_DSI输出到主屏上。 启用Overlay时, 上述Framebuffer做为RGB1pipe的输入,而视频或图像的内核buffer做为VGpipe的输入,二者经Layermixer1合成;此时LayerMixer1工作在非BLT模式,LayerMixer1和DMA_Pattach在一起,LayerMixer1输出控制参数直接提供给DMA_P使用。此时LayerMixer1仍有两种工作模式,FrameBuffer模式和DIRECT_OUT模式,前者时LayerMixer1和DMA_P之间使用一个overlaydoublebuffer做缓冲,输出给DMA_P;DIRECT_OUT模式下不使用该ovldoublebuffer,LayerMixer1直接输出给DMA_P。 一般VG和RGB的输入都可以是doublebuffer,ping-pang;LayerMixer的输出也是doublebuffer。DMA_P/S/E做为displaydriver传输前端buffer作为后端接口控制器的输入。 下面两图是QCMDPUImirror和Videomirror时的两结构图,并没有明确画出LayerMix1的Overlay流程路径,个别buffer的owner可能也有所差错,buffer也并不全,仅是大致描述Overlay及其部分buffer。 MDP和DSI和后端显示控制器和接口的连接结构如下图。 Layerarchitecture Overlay->OverlayImpl OverlayCtrlData OverlayMDPCtrlData MDPWrapper FrameBuffer KeyPoint Ctrl用来设置overlaychannel的参数,Data用来提交buffer到Overlaychannelqueue。其实使用overlay本质上就是设置好pin路由,设置好通道工作参数,然后不停的提交数据让OverlayEnginee工作。MDP的OverlayChannel并没有别的特殊的编程接口,都是使用控制、状态和数据寄存器来访问。其实MDP提供了远比AndroidOverlay实现强得多的Overlay功能。 Someflow Ctrl::commit()->MDPCtrl::set()->mdp_wrapper::setOverlay()->ioctl(fd,MSMFB_OVERLAY_SET,&ov) ->msm_fb->mdp4_overlay设置Overlay工作参数。 Data::queueBuffer->MDPData::play->mdp_wrapper::play()->ioctl(fd,MSMFB_OVERLAY_PLAY,&od) ->msm_fb->mdp4_overlay进行Overlay合成。注意queueBuffer第一参数fd是memFd,是内核空间的buffer,并不在用户空间和内核空间拷贝buffer数据。作用与framebuffer类似的是提交内核空间的该buffer到OverlayEngineeQueue。 Overlay&HWConMDP--MIMODisplay软硬整合 概述 Android显示系统SurfaceFlinger使用Overlay和HWC(Hardwarecomposer)完成SurfaceLayer的硬件合成。Overlay和HWC表现为两个HAL,为芯片方案制造商留了实现余地。 因为Overlay也时常被称为hardwarecomposition,为了避免混淆,本文中Overlay专指AndroidDisplayOverlayHAL,对应liboverlay.so;HWC专指SurfaceFlinger使用的硬件合成器HAL,对应hwcomposer.msm8xxxx.so。 QualcommMSM8k系列平台的MDP4.x(MobileDisplayPlatform)提供了硬件Overlay的功能,AndroidOverlayHAL与这个Overlay硬件相对应;当然,为了与上段照应,需要说明的是,MDP并不存在一个实现HWC的专门硬件,HWC也是在Overlay上实现的;体现在Android软件中,HWCHAL是建立在OverlayHAL基础上的,是使用OverlayHAL来实现的。 因此,再次,准确地说,提供硬件合成功能的是模块是Overlay,是MDPOverlay硬件的体现;而HWC则是SurfaceFlinger使用OverlayHAL的一个桥梁。 Overlay并非仅仅由SurfaceFlinger得到Surface后就不再经过SurfaceFlinger而使用硬件直接输出;从函数调用上看似乎是这样的,但是实际情形却非如此。硬件合成仅是合成的一种手段,合成的结果输出destination还是必须受控,因而也必须纳入SurfaceFlinger的输出管理范畴。 Overlay硬件平台 MSM8k上目前有MDP4.0,MDP4.1,MDP4.2三个硬件版本,主要是合成能力和管道数目的区别。通常,一个RGBpipe和一个VGpipe组成一个pipepair,前者是对应UIRGB图像数据,后者对应Camera或Video的RGB或YUV数据,两个pipe输入到一个LayerMixer0用于合成;额外的,LayerMixer可能还有BF(BorderFill)pipe,用于视频按比例显示时屏幕多余边框填充,这个多用于ExtTV或HDMI输出的时候。MDP4有7个pipe,3个LayerMixer,其中LayerMix0可以配置有多达两个RGBpipe,两个VGpipe,一个BFpipe输入,完成5Layer合成。 上述pipe是LayerMixer的输入元素,LayerMixer的输出对应到LCD,TV,HDMI等,当然不是直接对应,而是由DMAchannel和上述模块的控制器相连。三个LayerMixer对应的三个输出使用一般是约定的,当然,软件层面上MDPdriver中对每个管道的目标LayerMixer也做了固定的配置。三个输出一般标为Primary,Seconday,Extra,对应的DMA通道为DMA_P,DMA_S,DMA_E。 由于LayerMixer0提供了多达5个Layer的合成能力,所以当没有Camera或Video优先使用它的时候,它被充分利用来做Layer的Hardwarecomposition。提前且概要地,这儿必须清楚说明的是,LayerMixer0使用的两种情景: 当有Camera或Video的时候,SurfaceView对应的Layer为HWC_OVERLAY,这时该Layer对应一个VGpipe,而其余HWC_FRAMEBUFFERLayer经3DGPUrender到Framebuffer后,该Framebuffer输入一个pipe(RGB1--baselayer),和VGpipe经LayerMixer0合成输出。 当没有Camera或Video的时候,如果UILayer即HWC_FRAMEBUFFERLayer小于等于3个且都满足图像格式条件,那么这些Layer的CompositionType属性会被修改为HWC_OVERLAY,为每个Layer分配pipe,经LayerMixer0合成经DMA_P输出,这就是HWC。由于BFpipe能力条件的限制,不使用其做HWC,而RGB1做预留的baselayerFramebuffer使用,所以标榜的4-layermdpcompositionsupport实际只能接受SurfceFlinger的3个Layer做合成,也就是SurfaceFlinger的属性debug.mdpcomp.maxlayer=3。当超过3个Layer的时候,由于管道数量的限制,不能够再使用LayerMixer0,就使用GPUrender,也即每个Layer->draw。当然GPUrender也算是一个HardwareComposition,CompositionType方式的其中之一就是GPU。 OverlayHAL结构 MIMO输入输出代码结构设计,简单地讲,分为流路控制和数据流动两部分;Overlay及构建在其上的hwcomposer都是采用这种流路控制和数据流动的结构。 Overlay有多种应用场景,具体设计上描述为OverlayState。就是说如果允许管道任意灵活组合使用的话,可以有很多种花样的应用,但是这儿预先设计好这么些应用场景,应用场景一定,需要的管道类型和数目随之确定,管道连接的LayerMixer及其输出Video驱动控制器也确定。 OverlayState具体实现使用模板类OverlayImpl hwcomposer也设计了几个封装类与Overlay应用场景对应,屏蔽了场景功能的具体实现。hwcomposer中定义的应用场景比Overlay提供的场景还要少,仅是有限几个。大致结构图如下: 由于overlay场景太多,因此只示意了四个,OV_BYPASS_x_LAYER可以是1,2,3个,分别对应1个,2个或3个HWC_FRAMEBUFFERLayer和baselayerFramebuffer合成的情形。 hwc_prepare的设计逻辑过于固化和简单,成了一种基于if-else判断的优先配置方式,宽阔的城堡顶部建了个鸟笼似的小阁楼;应该设计成Policy或RouteState的形式更具备可扩展性。 mdp4_overlay_set() msmfb_overlay_set() ioctl(fb,MSMFB_OVERLAY_SET) overlay::mdp_wrapper::setOverlay() MdpCtrl::set() Ctrl::commit() pipe::commit()->GernericPipe OverlayImplBase::commit()->OverlayImpl<>::commit() Overlay::commit(overlay::utils::eDest) mdp4_overlay_play() msmfb_overlay_play() ioctl(fd,MSMFB_OVERLAY_PLAY,&od)msmfb_overlay_data.idismdp_overlay.idisthekernelpipeindexinkerneldbreturnedbyMdpCtrl.commit() overlay::mdp_wrapper::play() MdpData::play(intfd,uint32_toffset) Data::play() GenericPipe OverlayImplBase::queueBuffer()->OverlayImpl<>::(intfd,uint32_toffset,utils::eDestdest) Overlay::queueBuffer(intfd,uint32_toffset,utils::eDestdest) Camera或VideoOverlay CameraOverlay一般有两种实现模式,一种模式是V4L2不提供Overlay接口,在用户态把V4L2bufferhandle传递给Framebuffer,由FramebufferOverlayImplementation完成合成;另一种模式是V4L2提供Overlay接口,可以把Videobuffer在V4L2内核驱动中提交给FramebufferOverlay内核驱动完成合成。QCMSM8kOverlay是采用的第一种模式实现,但是V4L2和Framebuffer驱动也提供了第二种模式的实现;第二种模式可参见Freescale处理器上AndroidOverlay的实现。 Camera的取景器PreviewDisplayWindow是个SurfaceView,所在的Layer(HWC_OVERLAY)在UILayer底下,但是UIlayer会开个全透的区域露出这个HWC_OVERLAYLayer。 下面描述其合成过程。 3DGPU绘制:所有的HWC_FRAMEBUFFERlayers会首先经OpenGL3DGPU绘制到backFramebuffer上; OV_PIPE0配置:然后在setupHardwareComposer=>HWComposer::prepare=>hwc_prepare=>VideoOverlay::prepare中使用HWC_OVERLAYLayer参数设置OV_PIPE0分配的类型为Video/Graphic的MDPpipe; OV_PIPE0提交:DisplayHardware::flip=>HWComposer::commit=>hwc_set=>VideoOverlay::draw提交HWC_OVERLAYLayer的图像数据到OV_PIPE0的内核VGpipe的工作队列中(单容量队列即可); OV_PIPE3配置:DisplayHardware::flip=>HWComposer::commit=>hwc_set=>eglSwapBuffers=>queueBuffer=>fb_post=>update_framebuffer中使用baselayerbackframebuffer参数配置OV_PIPE3即RGB1pipe(注意baselayer的特殊地位); OV_PIPE3提交:当update_framebuffer真正提交图像数据到RGB1pipe时,对应stage0forbaselayer(内核驱动)会启动MDPLayerMixer0进行Layers合成; DMA传输:然后fb_post通过FBIOPUT_VSCREENINFO或PAN_DISPLAY启动DMA_P送合成好的图像经MIPI-DSI输出显示。 BufferFlip:queueBuffer后,该framebuffer即为frontframebuffer,然后eglSwapBuffers会dequeueBuffer下一个Framebuffer做为backframebuffer。 此时HardwareComposer使用的是VideoOverlay@hwcomposer.msm8960.so对应的逻辑。VGpipe设置和提交的栈示例如下: /system/lib/liboverlay.so(overlay::Overlay::commit(overlay::utils::eDest)+71) /system/lib/liboverlay.soconfigPrimVid(hwc_context_t*ctx,hwc_layer_t*layer) /system/lib/liboverlay.soVideoOverlay::configure(hwc_context_t*ctx,hwc_layer_t*,hwc_layer_t*) /system/lib/hw/hwcomposer.msm8960.so(qhwc::VideoOverlay::prepare(hwc_context_t*,hwc_layer_list_t*)+xxx) /system/lib/hw/hwcomposer.msm8960.so(qhwc::MDPComp::setup(hwc_context_t*,hwc_layer_list*)+163)foreachpipe. /system/lib/hw/hwcomposer.msm8960.so(qhwc::MDPComp::configure(hwc_composer_device*,hwc_layer_list*)+59) /system/lib/hw/hwcomposer.msm8960.sohwc_prepare(hwc_composer_device_t*dev,hwc_layer_list_t*list) /system/lib/libsurfaceflinger.so(android::HWComposer::prepare()const+9) /system/lib/libsurfaceflinger.so(android::SurfaceFlinger::setupHardwareComposer()+127) /system/lib/libsurfaceflinger.so(android::SurfaceFlinger::handleRepaint()+147) /system/lib/libsurfaceflinger.so(android::SurfaceFlinger::onMessageReceived(int)+91) /system/lib/liboverlay.soOverlay::queueBuffer(intfd,uint32_toffset,utils::eDestdest) /system/lib/hw/hwcomposer.msm8960.so(qhwc::VideoOverlay::draw(hwc_context_t*,hwc_layer_list*)+xx)foreachpipe. /system/lib/hw/hwcomposer.msm8960.sostaticinthwc_set(hwc_composer_device_t*dev,hwc_display_tdpy,hwc_surface_tsur,hwc_layer_list_t*list) /system/lib/libsurfaceflinger.so(android::HWComposer::commit()const+11) /system/lib/libsurfaceflinger.so(android::DisplayHardware::flip(android::Regionconst&)const+59) /system/lib/libsurfaceflinger.so(android::SurfaceFlinger::postFramebuffer()+61) /system/lib/libsurfaceflinger.so(android::SurfaceFlinger::onMessageReceived(int)+103) Baselayer对应的RGBpipe设置和提交的栈示例从略。Baselayer提交到RGB1时真正启动LayerMixer0的4-stagelayercomposition。 FBLayerHardwareComposition 在系统根目录文件/systembuild.prop中, debug.sf.hw=1 debug.egl.hw=1 debug.composition.type=mdp debug.enable.wl_log=1 debug.mdpcomp.maxlayer=3 debug.mdpcomp.logs=0 其中CompositionType有4种,debug.composition.type=dyn/c2d/mdp/cpu/gpu,dyn是根据c2d和mdp的硬件存在选择使用二者之一。 gpu/c2d/mdp可以释放cpu/gpu,减轻cpu/gpu的负担,但并不一定能使显示效果流畅。 782sMaxLayers=0; 783if(property_get("debug.mdpcomp.maxlayer",property,NULL)>0){ 784if(atoi(property)!=0) 785sMaxLayers=atoi(property); 786} 当没有Camera/Video/HDMI/WFD等Overlay应用情景时,所有Layer都是HWC_FRAMEBUFFER的,MDP的LayerMixer0是闲置的,这时可以优化利用其来做FramebufferLayer合成。由于管道数目限制的原因,只能合成小于等于sMaxLayers个Layers。多于3个的时候是否可以MDP合成其中的3个?可能需要考虑Layerbuffer维度、格式、缩放、Z序等因素。当多于3个的时候,是遍历layer::draw使用GPU来绘制纹理到backframebuffer上的。 下面着重看少于等于3个Layer,MDP合成的情况。 首先,所有的Layer的compositiontype都是HWC_FRAMEBUFFER的; 然后SurfaceFlinger在setHardwareComposer时发现hwc_prepare没有别的优先的Overlay情景,最后的一个if分支就是使用MDP来做Layer合成;SurfaceFlinger会检查Layer的属性看是否满足使用MDP的条件,然后设置满足条件的Layer的属性[compositionType,flags]=(HWC_OVERLAY,MDPCOMP);这样SurfaceFlinger::composeSurfaces时,就不再通过layer::draw使用GPU来绘制; PIPE配置:SurfaceFlinger为HWC创建工作集,为每个Layer分配并使用MDPComp::prepare配置每个pipe,如果有缩放需求,则会分配VGpipe,因为RGBpipe不支持缩放;有一个Layer则Overlay状态为BYPASS_1_LAYER,表示有1个LayerBypass,不需要OpenGL绘制,同理2个Layer为BYPASS_2_LAYER,3个为BYPASS_3_LAYER; PIPE提交:在DisplayHardware::flip中提交每个Layer的数据到管道,即MDPComp::draw()=>Overlay::queueBuffer()。注意Layer图像数据是在PMEM/ASHMEM内存中而不是Framebuffer内存中,但仍物理连续或IOMMU映射连续,LayerMixerdraw可访问。MDPComp::draw完即提交数据到对应管道的单容量队列后,清layer->flags&=~HWC_MDPCOMP标志; 在eglSwapBuffers时,真正做back&frontBuffer的切换(准确地说双缓冲是切换,三缓冲是轮用) OV_PIPE3配置:DisplayHardware::flip=>HWComposer::commit=>hwc_set=>eglSwapBuffers=>queueBuffer=>fb_post=>update_framebuffer中使用baselayerbackframebuffer参数配置OV_PIPE3即RGB1pipe; OV_PIPE3提交:当update_framebuffer真正提交图像数据到RGB1pipe时,对应stage0forbaselayer(内核驱动)会启动MDPLayerMixer0进行Layers合成;此时baselayer是个最顶层的全透明Layer,不妨碍底层Layer的显示; HWC功能时,是MDPComp@hwcomposer.msm8960.so对应的逻辑,一个Layer对应的pipe设置和提交的栈示例如下: #00pc0000b0d0/system/lib/liboverlay.so(overlay::Overlay::commit(overlay::utils::eDest)+71) #01pc00005d16/system/lib/hw/hwcomposer.msm8960.so(qhwc::MDPComp::prepare(hwc_context_t*,hwc_layer*,qhwc::MDPComp::mdp_pipe_info&)+577) #02pc00006190/system/lib/hw/hwcomposer.msm8960.so(qhwc::MDPComp::setup(hwc_context_t*,hwc_layer_list*)+163)foreachpipe. #03pc0000652c/system/lib/hw/hwcomposer.msm8960.so(qhwc::MDPComp::configure(hwc_composer_device*,hwc_layer_list*)+59) #04pc000037ea/system/lib/hw/hwcomposer.msm8960.sohwc_prepare(hwc_composer_device_t*dev,hwc_layer_list_t*list) #05pc0001ebba/system/lib/libsurfaceflinger.so(android::HWComposer::prepare()const+9) #06pc00020df4/system/lib/libsurfaceflinger.so(android::SurfaceFlinger::setupHardwareComposer()+127) #07pc000212f4/system/lib/libsurfaceflinger.so(android::SurfaceFlinger::handleRepaint()+147) #08pc000222e8/system/lib/libsurfaceflinger.so(android::SurfaceFlinger::onMessageReceived(int)+91) #00pc00006592/system/lib/hw/hwcomposer.msm8960.so(qhwc::MDPComp::draw(hwc_context_t*,hwc_layer_list*)+85)foreachpipe. #01pc00003ae4/system/lib/hw/hwcomposer.msm8960.sostaticinthwc_set(hwc_composer_device_t*dev,hwc_display_tdpy,hwc_surface_tsur,hwc_layer_list_t*list) #02pc0001ed56/system/lib/libsurfaceflinger.so(android::HWComposer::commit()const+11) #03pc0001e57c/system/lib/libsurfaceflinger.so(android::DisplayHardware::flip(android::Regionconst&)const+59) #04pc000209c6/system/lib/libsurfaceflinger.so(android::SurfaceFlinger::postFramebuffer()+61) #05pc00022474/system/lib/libsurfaceflinger.so(android::SurfaceFlinger::onMessageReceived(int)+103) Baselayer对应的RGBpipe设置和提交的栈示例从略。重复地,Baselayer提交到RGB1时真正启动LayerMixer0的4-stagelayercomposition。 HDMI/WFD 有机会待续。 LayerMixer0合成后图像经DMA_P输出时,在BLT模式和DIRECTOUT模式下LayerMixer0与DMA之间没有buffer;即使FB模式,也是一个Overlaybuffer而未必是做为Framebuffer内存,当然这个Overlaybuffer做为DMA_P输入传输给MIPI-DSI/LCDC。 FrameBufferdriverincludingMDPOverlay Framebuffer设备的sysfs 330staticintmsm_fb_create_sysfs(structplatform_device*pdev) 331{ 332intrc; 333structmsm_fb_data_type*mfd=platform_get_drvdata(pdev); 334 335rc=sysfs_create_group(&mfd->fbi->dev->kobj,&msm_fb_attr_group); 336if(rc) 337MSM_FB_ERR("%s:sysfsgroupcreationfailed,rc=%d\n",__func__, 338rc); 339returnrc; 340} root@android:/sys/class/graphics/fb0#ls-al -rw-r--r--rootroot40961970-06-2709:37bits_per_pixel -rw-r--r--rootroot40961970-06-2709:37blank -rw-r--r--rootroot40961970-06-2709:37console -rw-r--r--rootroot40961970-06-2709:37cursor -r--r--r--rootroot40961970-06-2709:37dev -rw-r--r--rootroot40961970-06-2709:37mode -rw-r--r--rootroot40961970-06-2709:37modes -r--r--r--rootroot40961970-06-2709:37msm_fb_type -r--r--r--rootroot40961970-06-2709:37name -rw-r--r--rootroot40961970-06-2709:37pan drwxr-xr-xrootroot1970-06-2708:28power -rw-r--r--rootroot40961970-06-2709:37rotate -rw-r--r--rootroot40961970-06-2709:37state -r--r--r--rootroot40961970-06-2709:37stride lrwxrwxrwxrootroot1970-06-2709:37subsystem->../../../../class/graphics -rw-r--r--rootroot40961970-06-2708:28uevent -rw-r--r--rootroot40961970-06-2709:37virtual_size -r--r--r--rootroot40961970-06-2708:28vsync_event root@android:/sys/class/graphics/fb0#catmsm_fb_type mipidsicmdpanel root@android:/sys/class/graphics/fb0#catbits_per_pixel 32 130|root@android:/sys/class/graphics/fb0#catdev 29:0 root@android:/sys/class/graphics/fb0#catmodes U:480x854p-0 root@android:/sys/class/graphics/fb0#catname msmfb42_90501 root@android:/sys/class/graphics/fb0#catstride 1920 root@android:/sys/class/graphics/fb0#catvirtual_size 480,2566 cont_splash_donefield Addsupportfor"ContinuousSplashScreen"feature. Theimagedisplayedonthescreenbytheandroidbootloaderdrivershouldcontinuetilltheandroidanimationshowsup. DelaythedisplayinitializationforMDP,displaydependentclocksandpanelpoweronfunctions. bootloader显示的image在linux内核启动过程中保持显示在屏幕上,知道开机动画显示,即linux内核启动过程中不要出现黑屏。 Earlysuspend&Earlyresume Earlysuspend是有wakelock还占有,系统还不能整体suspend,但是可以关闭屏幕、背光、输入等;在Earlysuspended状态时,重新打开屏幕、背光和输入,是为对应的earlyresume。 1551mfd->early_suspend.suspend=msmfb_early_suspend; 1552mfd->early_suspend.resume=msmfb_early_resume; 1553mfd->early_suspend.level=EARLY_SUSPEND_LEVEL_DISABLE_FB-2; 1554register_early_suspend(&mfd->early_suspend); 数据结构定义如下: 23/*Theearly_suspendstructuredefinessuspendandresumehookstobecalled 24*whentheuservisiblesleepstateofthesystemchanges,andalevelto 25*controltheorder.Theycanbeusedtoturnoffthescreenandinput 26*devicesthatarenotusedforwakeup. 27*Suspendhandlersarecalledinlowtohighlevelorder,resumehandlersare 28*calledintheoppositeorder.If,whencallingregister_early_suspend, 29*thesuspendhandlershavealreadybeencalledwithoutamatchingcalltothe 30*resumehandlers,thesuspendhandlerwillbecalleddirectlyfrom 31*register_early_suspend.Thisdirectcallcanviolatethenormallevelorder. 32*/ 33enum{ 34EARLY_SUSPEND_LEVEL_BLANK_SCREEN=50, 35EARLY_SUSPEND_LEVEL_STOP_DRAWING=100, 36EARLY_SUSPEND_LEVEL_DISABLE_FB=150, 37}; 38structearly_suspend{ 39#ifdefCONFIG_HAS_EARLYSUSPEND 40structlist_headlink; 41intlevel; 42void(*suspend)(structearly_suspend*h); 43void(*resume)(structearly_suspend*h); 44#endif 45}; backlight msm_fb_set_backlight以后是使用led_trigger调用真正led_classdev"wled"的brightnes_set去设置背光。 用户态ioctl通过msm_fb_set_backlight调用到msm_fb_panel_data::set_backlight, "lcd_backlight".brightness_set->msm_fb_panel_data::set_backlight->"bkl_trigger".led_trigger->"wled".brightness_set。然后找真正操作硬件IC部分。 驱动中设置背光则是绕过"lcd_backlight"设备直接通过backlight_worker工作执行到msm_fb_panel_data::set_backlight,然后->"bkl_trigger".led_trigger->"wled".brightness_set。 可以认为"lcd_backlight"是背光抽象设备,通过led_trigger的led组映射到不同的led_classdev设备 以三星DSICMD屏为例: Inmipi_samsung.c 294staticvoidmipi_samsung_set_backlight(structmsm_fb_data_type*mfd) 295{ 296if(!cci_fb_UpdateDone){ 297printk("Taylor:NoBLbeforeLCMon\n"); 298return; 299} 300 301pr_debug("Taylor:%s:SetBL:%d\n",__func__,mfd->bl_level); 302if((mipi_samsung_pdata->enable_wled_bl_ctrl) 303&&(wled_trigger_initialized)){ 304led_trigger_event(bkl_led_trigger,mfd->bl_level); 305return; 306} 307} kernel/drivers/leds/leds-pm8xxx.c #definePM8XXX_LEDS_DEV_NAME"pm8xxx-led" 2283staticstructplatform_driverpm8xxx_led_driver={ 2284.probe=pm8xxx_led_probe, 2285.remove=__devexit_p(pm8xxx_led_remove), 2286.driver={ 2287.name=PM8XXX_LEDS_DEV_NAME, 2288.owner=THIS_MODULE, 2289}, 2290}; pm8xxx_led_probe会对pm8038_led_info数组中的每个led使用设置led_classdev字段,并且初始化workitem,然后使用led_classdev_register向系统注册每个led设备。 2197INIT_WORK(&led_dat->work,pm8xxx_led_work); 2198INIT_WORK(&led_dat->modework,pm8xxx_mode_work); 2199INIT_WORK(&led_dat->testwork,pm8xxx_test_work); 每个led的brightness_set字段设置为pm8xxx_led_set。 1790staticvoidpm8xxx_led_set(structled_classdev*led_cdev, 1791enumled_brightnessvalue) 1792{ 1793structpm8xxx_led_data*led; 1794 1795led=container_of(led_cdev,structpm8xxx_led_data,cdev); 1796 1797if(value 1798dev_err(led->cdev.dev,"Invalidbrightnessvalueexceeds"); 1799return; 1800} 1801 1802led->cdev.brightness=value; 1803schedule_work(&led->work); 1804} 1730staticvoidpm8xxx_led_work(structwork_struct*work) 1731{ 1732intrc; 1733 1734structpm8xxx_led_data*led=container_of(work, 1735structpm8xxx_led_data,work); 1736 1737if(led->pwm_dev==NULL){ 1738__pm8xxx_led_work(led,led->cdev.brightness); 1739}else{ 1740rc=pm8xxx_led_pwm_work(led); 1741if(rc) 1742pr_err("couldnotconfigurePWMmodeforLED:%d\n", 1743led->id); 1744} 1745} 对PM8XXX_ID_WLED,是使用__pm8xxx_led_work 1692staticvoid__pm8xxx_led_work(structpm8xxx_led_data*led, 1693enumled_brightnesslevel) 1694{ 1695intrc; 1696 1697mutex_lock(&led->lock); 1698 1699switch(led->id){ 1700casePM8XXX_ID_LED_KB_LIGHT: 1701led_kp_set(led,level); 1702break; 1703casePM8XXX_ID_LED_0: 1704casePM8XXX_ID_LED_1: 1705casePM8XXX_ID_LED_2: 1706led_lc_set(led,level); 1707break; 1708casePM8XXX_ID_FLASH_LED_0: 1709casePM8XXX_ID_FLASH_LED_1: 1710led_flash_set(led,level); 1711break; 1712casePM8XXX_ID_WLED: 1713rc=led_wled_set(led,level); 1714if(rc<0) 1715pr_err("wledbrightnesssetfailed%d\n",rc); 1716break; 1717casePM8XXX_ID_RGB_LED_RED: 1718casePM8XXX_ID_RGB_LED_GREEN: 1719casePM8XXX_ID_RGB_LED_BLUE: 1720led_rgb_set(led,level); 1721break; 1722default: 1723dev_err(led->cdev.dev,"unknownledid%d",led->id); 1724break; 1725} 1726 1727mutex_unlock(&led->lock); 1728} led_wled_set写电源管理芯片pm8xxx的控制寄存器,控制wled。 Framebufferfb_info::node registered_fb它是一个数组,它的类型就是structfb_info,它用于保存我们调用register_framebuffer传进来的structfb_info。 num_registered_fb代表注册帧缓冲设备的个数。 1522for(i=0;i 相当于找到一个空的次设备号。 Framebuffer像素格式 主屏RGBA8888 Inmipi_dsi_probe() 481/* 482*get/setpanelspecificfbinfo 483*/ 484mfd->panel_info=pdata->panel_info; 485pinfo=&mfd->panel_info; 486 487if(mfd->panel_info.type==MIPI_VIDEO_PANEL) 488mfd->dest=DISPLAY_LCDC; 489else 490mfd->dest=DISPLAY_LCD; 491 492if(mdp_rev==MDP_REV_303&& 493mipi_dsi_pdata->get_lane_config){ 494if(mipi_dsi_pdata->get_lane_config()!=2){ 495pr_info("ChangingtoDSISingleModeConfiguration\n"); 496#ifdefCONFIG_FB_MSM_MDP303 497update_lane_config(pinfo); 498#endif 499} 500} 501 502if(mfd->index==0) 503mfd->fb_imgType=MSMFB_DEFAULT_TYPE;//configedasRGBA8888forfb0 504else 505mfd->fb_imgType=MDP_RGB_565; msmfb_update_notify/msmfb_no_update_notify 用于CABL功能时,统计直方图使用; sw_refresher 使用定时器去触发mdp_refresh_screen,添加work进行dma_fnc调用。 针对某些接口的VIDEO模式屏且控制器没有hw_refresh支持时,可以使用sw_refresher。 FB_ACTIVATE_VBL标志涵义 fb_var_screeninfo结构体的成员变量activate的值设置FB_ACTIVATE_VBL,表示要等到下一个垂直同步事件出现时,再将当前要渲染的图形缓冲区的内容绘制出来。这样做的目的是避免出现屏幕闪烁,即避免前后两个图形缓冲区的内容各有一部分同时出现屏幕中。 Framebuffer初始化 设备资源申请是在MACHINE_DESC中实现的。示例如下: 3463MACHINE_START(MSM8930_CDP,"QCTMSM8930CDP") 3464.map_io=msm8930_map_io, 3465.reserve=msm8930_reserve, 3466.init_irq=msm8930_init_irq, 3467.handle_irq=gic_handle_irq, 3468.timer=&msm_timer, 3469.init_machine=msm8930_cdp_init, 3470.init_early=msm8930_allocate_memory_regions, 3471.init_very_early=msm8930_early_memory, 3472.restart=msm_restart, 3473MACHINE_END 函数msm8930_cdp_init做Machine级别的设备的注册,部分代码如下: staticvoid__initmsm8930_cdp_init(void)@kernel/arch/arm/mach-msm/board-8930.c platform_add_devices(common_devices,ARRAY_SIZE(common_devices)); msm8930_init_gpu(); msm8930_init_mmc(); msm8930_init_cam(); msm8930_init_fb(); “msm_fb”msmframebuffer设备,注意不是linuxframebuffer设备,但是有对应关系; “wfd”wifi显示设备; “mipi_dsi_cmd_samsung_fwvga”mipi-dsi接口cmd模式LCD屏设备; “hdmi_msm”HDMI显示器设备; “mdp”mobiledisplaystation显示引擎设备; “mipi-dsi”MIPI-DSI显示器驱动设备(id例外用了1,可能有的平台上有两个MIPI-DSI,另一个id为0); 1168void__initmsm8930_init_fb(void)@kernel/arch/arm/mach-msm/board-8930-display.c 1169{ 1170platform_device_register(&msm_fb_device); 1171 1172#ifdefCONFIG_FB_MSM_WRITEBACK_MSM_PANEL 1173platform_device_register(&wfd_panel_device); 1174platform_device_register(&wfd_device); 1175#endif 1176 1178#ifdefCONFIG_FB_MSM_MIPI_NOVATEK_CMD_QHD_PT 1179platform_device_register(&mipi_dsi_novatek_panel_device); 1180#endif 1181 1184#ifdefCONFIG_FB_MSM_MIPI_SA77_CMD_FWVGA_PANEL 1185platform_device_register(&mipi_dsi_cmd_chimei_fwvga_panel_device); 1186platform_device_register(&mipi_dsi_cmd_samsung_fwvga_panel_device); 1187#endif 1189 1190#ifdefCONFIG_FB_MSM_HDMI_MSM_PANEL 1191platform_device_register(&hdmi_msm_device); 1192#endif 1193 1194platform_device_register(&mipi_dsi_toshiba_panel_device); 1195 1196msm_fb_register_device("mdp",&mdp_pdata); 1197msm_fb_register_device("mipi_dsi",&mipi_dsi_pdata); 1198#ifdefCONFIG_MSM_BUS_SCALING 1199#ifdefCONFIG_FB_MSM_DTV 1200msm_fb_register_device("dtv",&dtv_pdata); 1201#endif 1202#endif 1203} 因为注册这些设备的意图主要是资源申请和初步初始化设备,所以各设备注册顺序并无关紧要。其初始化顺序还与后来的驱动实际注册顺序有关。 首先注册paltform_devicemsm_fb_device,设备定义如下 71staticstructresourcemsm_fb_resources[]={ 72{ 73.flags=IORESOURCE_DMA, 74} 75}; 135staticstructmsm_fb_platform_datamsm_fb_pdata={ 136.detect_client=msm_fb_detect_panel, 137}; 138 139staticstructplatform_devicemsm_fb_device={ 140.name="msm_fb", 141.id=0, 142.num_resources=ARRAY_SIZE(msm_fb_resources), 143.resource=msm_fb_resources, 144.dev.platform_data=&msm_fb_pdata, 145}; 然后注册panel设备,设备定义如下 845staticstructmipi_dsi_panel_platform_datasamsung_pdata={ 846.enable_wled_bl_ctrl=0x1, 847}; 848 849staticstructplatform_devicemipi_dsi_cmd_samsung_fwvga_panel_device={ 850.name="dsi_cmd_samsung_fwvga", 851.id=0, 852.dev={ 853.platform_data=&samsung_pdata, 854} 855}; 然后关键的注册mdp和mipi-dsicontroller,设备定义如下 1749void__initmsm_fb_register_device(char*name,void*data) 1750{ 1751if(!strncmp(name,"mdp",3)) 1752msm_register_device(&msm_mdp_device,data); 1753elseif(!strncmp(name,"lcdc",4)) 1754msm_register_device(&msm_lcdc_device,data); 1755elseif(!strncmp(name,"mipi_dsi",8)) 1756msm_register_device(&msm_mipi_dsi_device,data); 1757#ifdefCONFIG_FB_MSM_TVOUT 1758elseif(!strncmp(name,"tvenc",5)) 1759msm_register_device(&msm_tvenc_device,data); 1760elseif(!strncmp(name,"tvout_device",12)) 1761msm_register_device(&msm_tvout_device,data); 1762#endif 1763#ifdefCONFIG_MSM_BUS_SCALING 1764elseif(!strncmp(name,"dtv",3)) 1765msm_register_device(&msm_dtv_device,data); 1766#endif 1767else 1768printk(KERN_ERR"%s:unknowndevice!%s\n",__func__,name); 1769} mdp和mipi-dsi设备及寄存器映射和中断需求如下 1484#defineMIPI_DSI_HW_BASE0x04700000 1485#defineROTATOR_HW_BASE0x04E00000 1486#defineTVENC_HW_BASE0x04F00000 1487#defineMDP_HW_BASE0x05100000 1488 1489staticstructresourcemsm_mipi_dsi_resources[]={ 1490{ 1491.name="mipi_dsi", 1492.start=MIPI_DSI_HW_BASE, 1493.end=MIPI_DSI_HW_BASE+0x000F0000-1, 1494.flags=IORESOURCE_MEM, 1495}, 1496{ 1497.start=DSI_IRQ, 1498.end=DSI_IRQ, 1499.flags=IORESOURCE_IRQ, 1500}, 1501}; 1502 1503staticstructplatform_devicemsm_mipi_dsi_device={ 1504.name="mipi_dsi", 1505.id=1, 1506.num_resources=ARRAY_SIZE(msm_mipi_dsi_resources), 1507.resource=msm_mipi_dsi_resources, 1508}; 1509 1510staticstructresourcemsm_mdp_resources[]={ 1511{ 1512.name="mdp", 1513.start=MDP_HW_BASE, 1514.end=MDP_HW_BASE+0x000F0000-1, 1515.flags=IORESOURCE_MEM, 1516}, 1517{ 1518.start=INT_MDP, 1519.end=INT_MDP, 1520.flags=IORESOURCE_IRQ, 1521}, 1522}; 1523 1524staticstructplatform_devicemsm_mdp_device={ 1525.name="mdp", 1526.id=0, 1527.num_resources=ARRAY_SIZE(msm_mdp_resources), 1528.resource=msm_mdp_resources, 1529}; 以上设备注册时,其驱动并未加载,因为machine_desc.init_machine设备注册的arch_initcall是在.initcall3.init中,而module_initdriver注册是在.initcall6.init中。等其驱动加载时,在对应的probe函数中,判断设备id,初步初始化设备,保存其资源分配。 此时,以下id为0的设备panel,dtv,hdmi,mdp,msm_fb,id为1的mipi-dsi设备已经注册进系统了。 dsi_cmd_chimei_fwvga.0 dsi_cmd_samsung_fwvga.0 dsi_cmd_samsung_fwvga.1281 dtv.0 dtv.458753 hdmi_msm.0 hdmi_msm.1 mdp.0 mdp.458753 mdp.591105 mdp.655361 mipi_dsi.1 mipi_dsi.591105 mipi_toshiba.0 msm_fb.0 msm_fb.458753 msm_fb.591105 msm_fb.655361 下面描述各驱动注册,各驱动都是module_init的。 msm_fb驱动注册如下 module_init(msm_fb_init); 3898int__initmsm_fb_init(void)@kernel/drivers/video/msm/msm_fb.c 3899{ 3900intrc=-ENODEV; 3901 3902if(msm_fb_register_driver()) 3903returnrc; …. 3705staticintmsm_fb_register_driver(void) 3706{ 3707returnplatform_driver_register(&msm_fb_driver); 3708} msm_fb_driver驱动定义如下 734staticstructplatform_drivermsm_fb_driver={ 735.probe=msm_fb_probe, 736.remove=msm_fb_remove, 737#ifndefCONFIG_HAS_EARLYSUSPEND 738.suspend=msm_fb_suspend, 739.resume=msm_fb_resume, 740#endif 741.shutdown=NULL, 742.driver={ 743/*Drivernamemustmatchthedevicenameaddedinplatform.c.*/ 744.name="msm_fb", 745.pm=&msm_fb_dev_pm_ops, 746}, 747}; platform_device“msm_fb”的resource[0]是一块DMA内存,是framebuffer内存,但是在资源定义中并没有设置size,而在msm_fb_probe中从其使用可以看到该DMA内存已经分配。其size是在machine的init_early中从bootmem中分配的,比machine级别设备注册要早! .init_early=msm8930_allocate_memory_regions, msm8930_allocate_memory_regions(void)@kernel/arch/arm/mach-msm/board-8930.c 1006staticvoid__initmsm8930_allocate_memory_regions(void) 1007{ 1008msm8930_allocate_fb_region(); 1009} msm8930_allocate_fb_region()@kernel/arch/arm/mach-msm/board-8930-display.c 1205void__initmsm8930_allocate_fb_region(void) 1206{ 1207void*addr; 1208unsignedlongsize; 1209 1210size=MSM_FB_SIZE; 1211addr=alloc_bootmem_align(size,0x1000); 1212msm_fb_resources[0].start=__pa(addr); 1213msm_fb_resources[0].end=msm_fb_resources[0].start+size-1; 1214pr_info("allocating%lubytesat%p(%lxphysical)forfb\n",size,addr,__pa(addr)); 1216} MSM_FB_SIZE宏定义如下,TRIPLE_BUFFER已是主流 32#ifdefCONFIG_FB_MSM_TRIPLE_BUFFER 33#defineMSM_FB_PRIM_BUF_SIZE\ 34(roundup((1920*1088*4),4096)*3)/*4bppx3pages*/ 35#else 36#defineMSM_FB_PRIM_BUF_SIZE\ 37(roundup((1920*1088*4),4096)*2)/*4bppx2pages*/ 38#endif 39/*Note:mustbemultipleof4096*/ 40#defineMSM_FB_SIZEroundup(MSM_FB_PRIM_BUF_SIZE,4096) 当”msm_fb”注册时,msm_fb_probe在设备和驱动match后被调用。对于msm_fb_deviceid=0,只做fbram保存和IONclient创建;这时probe到的设备对应/sys/bus/platform/devices/msm_fb.0。 msm_ion_client_create(-1,pdev->name); ”mipi-dsi”driver定义和注册如下(inkernel/drivers/video/msm/mipi_dsi.c) 55staticstructplatform_drivermipi_dsi_driver={ 56.probe=mipi_dsi_probe, 57.remove=mipi_dsi_remove, 58.shutdown=NULL, 59.driver={ 60.name="mipi_dsi", 61}, 62}; 603staticintmipi_dsi_register_driver(void) 604{ 605returnplatform_driver_register(&mipi_dsi_driver); 606} 608staticint__initmipi_dsi_driver_init(void) 609{ 610intret; 611 612mipi_dsi_init(); 613 614ret=mipi_dsi_register_driver(); 616device_initialize(&dsi_dev); 617 618if(ret){ 619pr_err("mipi_dsi_register_driver()failed!\n"); 620returnret; 621} 623returnret; 624} 625 626module_init(mipi_dsi_driver_init); “mdp”driver定义和注册如下(inkernel/drivers/video/msm/mdp.c) 2094staticstructplatform_drivermdp_driver={ 2095.probe=mdp_probe, 2096.remove=mdp_remove, 2097#ifndefCONFIG_HAS_EARLYSUSPEND 2098.suspend=mdp_suspend, 2099.resume=NULL, 2100#endif 2101.shutdown=NULL, 2102.driver={ 2103/* 2104*Drivernamemustmatchthedevicenameaddedin 2105*platform.c. 2106*/ 2107.name="mdp", 2108.pm=&mdp_dev_pm_ops, 2109}, 2110}; 3001staticintmdp_register_driver(void) 3002{ 3003#ifdefCONFIG_HAS_EARLYSUSPEND 3004early_suspend.level=EARLY_SUSPEND_LEVEL_DISABLE_FB-1; 3005early_suspend.suspend=mdp_early_suspend; 3006early_suspend.resume=mdp_early_resume; 3007register_early_suspend(&early_suspend); 3008#endif 3009 3010returnplatform_driver_register(&mdp_driver); 3011} 3012 3013staticint__initmdp_driver_init(void) 3014{ 3015intret; 3016 3017mdp_drv_init(); 3018 3019ret=mdp_register_driver(); 3020if(ret){ 3021printk(KERN_ERR"mdp_register_driver()failed!\n"); 3022returnret; 3023} 3024 3025#ifdefined(CONFIG_DEBUG_FS) 3026mdp_debugfs_init(); 3027#endif 3028 3029return0; 3030 3031} 3032 3033module_init(mdp_driver_init); 当真正从屏驱动中添加一块显示设备时,为了让上级设备(“mipi-dsi”“mdp”“msm_fb”“fb”)使用下级设备,高通实现为下级设备创建了每个上级设备的实例,通过从下到上的设备probe链一级一级向上注册。这时保证从下到上的设备注册顺序就是至关重要的了,probe链做注册来保证这一点。 下面描述由屏驱动添加屏到注册linuxframebuffer设备的流程。 在各自的屏设备注册文件中,会去探测屏,这种探测不是做真正扫描,仅仅是使用设备名字验证一下,以SAMSUNGMIPIDSICMD屏为例,驱动会使用相应规则ID注册一块屏。 staticint__initmipi_cmd_samsung_fwvga_pt_init(void)@kernel/drivers/video/msm/mipi_samsung_cmd_fwvga_pt.c 37intret; 38 39if(msm_fb_detect_client("mipi_cmd_samsung_fwvga")) 40return0; …… 88ret=mipi_samsung_device_register(&pinfo,MIPI_DSI_PRIM,MIPI_DSI_PANEL_QHD_PT); 90if(ret) 91pr_err("%s:failedtoregisterdevice!\n",__func__); 92 93returnret; 94} 95 96module_init(mipi_cmd_samsung_fwvga_pt_init); 探测函数intmsm_fb_detect_client(constchar*name)首先使用主屏和外屏名字匹配,匹配不成则使用msm_fd_device.dev.platform.detect_client=msm_fb_detect_panel去匹配。上面欲同时注册SAMSUNG和CHIMEI两块屏设备,当然不能同时detect_panel成功,使用GPIO管脚配置做了二次匹配。实际不同批次的手机可能用到两块屏中的一种。 然后mipi_samsung_device_register()(对CHIMEI则是mipi_chimei_device_register)注册屏驱动和屏设备。驱动定义和注册具体如下, 358staticstructplatform_driverthis_driver={ 359.probe=mipi_samsung_lcd_probe, 360.driver={ 361.name="dsi_cmd_samsung_fwvga", 362}, 363}; 364 365staticstructmsm_fb_panel_datasamsung_panel_data={ 366.on=mipi_samsung_lcd_on, 367.off=mipi_samsung_lcd_off, 368.set_backlight=mipi_samsung_set_backlight, 369}; 373intmipi_samsung_device_register(structmsm_panel_info*pinfo,u32channel,u32panel) 375{ 376structplatform_device*pdev=NULL; 377intret; 378 379if((channel>=3)||ch_used[channel]) 380return-ENODEV; 381 382ch_used[channel]=TRUE; 383 384ret=mipi_samsung_lcd_init(); 385if(ret){ 386pr_err("mipi_samsung_lcd_init()failedwithret%u\n",ret); 387returnret; 388} 389 390pdev=platform_device_alloc("dsi_cmd_samsung_fwvga",(panel<<8)|channel); 391if(!pdev) 392return-ENOMEM; 393 394samsung_panel_data.panel_info=*pinfo; 395 396ret=platform_device_add_data(pdev,&samsung_panel_data, 397sizeof(samsung_panel_data)); 398if(ret){ 399printk(KERN_ERR 400"%s:platform_device_add_datafailed!\n",__func__); 401gotoerr_device_put; 402} 403 404ret=platform_device_add(pdev); 405if(ret){ 406printk(KERN_ERR 407"%s:platform_device_registerfailed!\n",__func__); 408gotoerr_device_put; 409} 410 411return0; 412 413err_device_put: 414platform_device_put(pdev); 415returnret; 416} 417 418staticintmipi_samsung_lcd_init(void) 419{ 420 421led_trigger_register_simple("bkl_trigger",&bkl_led_trigger); 422pr_info("%s:SUCCESS(WLEDTRIGGER)\n",__func__); 423wled_trigger_initialized=1; 424 425mipi_dsi_buf_alloc(&samsung_tx_buf,DSI_BUF_SIZE); 426mipi_dsi_buf_alloc(&samsung_rx_buf,DSI_BUF_SIZE); 427 428returnplatform_driver_register(&this_driver); 429} 在mipi_samsung_lcd_init()中注册platform_driver屏驱动,然后分配注册platform_device屏设备;platform_data设置为msm_fb_panel_data向上传递参数并用于上级设备调用控制屏开关和背光。 屏设备注册后,platform_device和platform_drivermatch,驱动的probe函数被调用,把参数一级一级向上带,用于设置上级设备参数,向上一级一级注册设备(“mipi-dsi”,“mdp”,“msm_fb”,“framebuffer”)。 一个类似的调用栈如下 ------------[cuthere]------------ WARNING:at/home/CORPUSERS/xp010548/myworkdroid/7x25a/LINUX/kernel/drivers/video/msm/msm_fb.c:1221msm_fb_probe+0xf4/0xcbc() msm_fb_probe Moduleslinkedin: [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ ---[endtrace65f8ea860415c051]--- 下面考察设备probe链。 311staticint__devinitmipi_samsung_lcd_probe(structplatform_device*pdev) 312{ ….. 338current_pdev=msm_fb_add_device(pdev); 339 340if(current_pdev){ 341mfd=platform_get_drvdata(current_pdev); 342if(!mfd) 343return-ENODEV; 344if(mfd->key!=MFD_KEY) 345return-EINVAL; 346 347mipi=&mfd->panel_info.mipi; 348 349if(phy_settings!=NULL) 350mipi->dsi_phy_db=phy_settings; 351 352if(dlane_swap) 353mipi->dlane_swap=dlane_swap; 354} 355return0; msm_fb_add_device做如下事情: 调用structplatform_device*msm_fb_device_alloc(structmsm_fb_panel_data*pdata,u32type,u32id)函数分配platform_device“mipi-dsi.type_devid”并设置其platform_data为msm_fb_panel_data。 以额外msm_fb_data_type结构分配framebuffer。 注册”mipi-dsi”设备platform_device_add(this_dev)。 “mipi-dsi”设备和驱动进行attach,match后,“mipi-dsi”driver的probe被调用到。 staticintmipi_dsi_probe(structplatform_device*pdev)@kernel/drivers/video/msm/mipi_dsi.c做如下事情(这次的设备ID是真正实例的了,不是1了): 分配”mdp”设备实例并设置其数据,设置”mipi-dsi”设备操作函数,用于向下操作一级一级设备; 继续设置linuxframebuffer的参数; 根据屏分辨率设置mipi-dsi工作频率; 注册该”mdp”设备实例; “mdp”设备和驱动进行attach,match后,“mdp”driver的probe被调用到。 staticintmdp_probe(structplatform_device*pdev)@kernel/drivers/video/msm/mdp.c 分配”msm_fb”实例并设置其数据; 配置”mdp”工作模式; 注册”msm_fb”实例; “msm_fb”设备和驱动进行attach,match后,“msm_fb”driver的probe被调用到。 staticintmsm_fb_probe(structplatform_device*pdev)@kernel/drivers/video/msm/msm_fb.c 调用msm_fb_register设置linuxframebuffer并register_framebuffer。 dsi_cmd_samsung_fwvga.1281->mipi_dsi.591105->mdp.591105->msm_fb.591105->fbx dtv.458753->mdp.458753->msm_fb.458753->fbx hdmi_msm.1->mdp.655361->msm_fb.655361->fbx(hdmi) MDP图像合成和显示过程—Framebuffer驱动 Overlay设置和提交过程 msmfb_overlay_set(structfb_info*info,void__user*p) èmdp4_overlay_set(structfb_info*info,structmdp_overlay*req) 申请pipe,并设置pipe的clock和bandwidth。 intmsmfb_overlay_play(structfb_info*info,unsignedlong*argp) èintmdp4_overlay_play(structfb_info*info,structmsmfb_overlay_data*req) 计算pipe输入缓冲地址、参数配置等;将request暂存,如对DSICMD屏,是使用voidmdp4_dsi_cmd_pipe_queue(intcndx,structmdp4_overlay_pipe*pipe),而DSIVIDEO屏是使用voidmdp4_dsi_video_pipe_queue(intcndx,structmdp4_overlay_pipe*pipe)。 base_pipe设置和提交,LayerMix,DMA 当送FBIOPUT_VSCREENINFO或FBIOPAN_DISPLAY命令给FB设备时,最终会调用msm_fb_pan_display(structfb_var_screeninfo*var,structfb_info*info) msm_fb_pan_display èmdp_set_dma_pan_info(info,dirtyPtr,(var->activate==FB_ACTIVATE_VBL));//设置DMA区域 èmdp_dma_pan_update(info);//启动DMA,包括LayerMixer合成和DMA输出 voidmdp_dma_pan_update(structfb_info*info) èmfd->dma_fnc(mfd); 对MIPIDSICMD屏,该DMA函数是mdp4_dsi_cmd_overlay。 voidmdp4_dsi_cmd_overlay(structmsm_fb_data_type*mfd) pipe=vctrl->base_pipe; if(pipe->mixer_stage==MDP4_MIXER_STAGE_BASE){//itiscertainforbase_pipe //itissetupinmdp4_overlay_update_dsi_cmdwhendsicmdpanelison. mdp4_mipi_vsync_enable(mfd,pipe,0); mdp4_overlay_setup_pipe_addr(mfd,pipe); mdp4_dsi_cmd_pipe_queue(0,pipe);//armthebasepipewithframebuffer mdp4_overlay_mdp_perf_upd(mfd,1);//levelupthemdpperformance mutex_lock(&mfd->dma->ov_mutex); mdp4_dsi_cmd_pipe_commit(cndx,0);//firetheoverlaylayermixeranddma mdp4_overlay_mdp_perf_upd(mfd,0); mutex_unlock(&mfd->dma->ov_mutex); intmdp4_dsi_cmd_pipe_commit(intcndx,intwait) inti,undx; intmixer=0; structvsycn_ctrl*vctrl; structvsync_update*vp; structmdp4_overlay_pipe*pipe; structmdp4_overlay_pipe*real_pipe; unsignedlongflags; intneed_dmap_wait=0; intneed_ov_wait=0; intcnt=0; /** *staticstructvsycn_ctrl{…}vsync_ctrl_db[MAX_CONTROLLER] *在不同的显示器文件中有不同的定义,注意其是static的。 *不同显示应用时关联不同的LayerMixer,所以同一种应用中, *使用具有同一mixer_num的pipe,mixer_num由应用分配的主pipe即该应用对应的 *vsync_ctrl_db的base_pipe指定。所有pipe的LayerMixer0是驱动中固定指定好的。 vctrl=&vsync_ctrl_db[0]; mutex_lock(&vctrl->update_lock); undx=vctrl->update_ndx; vp=&vctrl->vlist[undx]; mixer=pipe->mixer_num;//theLayermixerused,LayerMixer0here. if(vp->update_cnt==0){ mutex_unlock(&vctrl->update_lock); returncnt; //vctrl->update_ndx++; //vctrl->update_ndx&=0x01; vp->update_cnt=0;/*reset*/ if(vctrl->blt_free){ vctrl->blt_free--; if(vctrl->blt_free==0) mdp4_free_writeback_buf(vctrl->mfd,mixer); /*freepreviouscommittediommubacktopool*/ mdp4_overlay_iommu_unmap_freelist(mixer); spin_lock_irqsave(&vctrl->spin_lock,flags); if(pipe->ov_blt_addr){ /*Blt*/ if(vctrl->blt_wait) need_dmap_wait=1; if(vctrl->ov_koff!=vctrl->ov_done){ INIT_COMPLETION(vctrl->ov_comp); need_ov_wait=1; }else{ /*directout*/ if(vctrl->dmap_koff!=vctrl->dmap_done){ INIT_COMPLETION(vctrl->dmap_comp); pr_debug("%s:wait,ok=%dod=%ddk=%ddd=%dcpu=%d\n", __func__,vctrl->ov_koff,vctrl->ov_done, vctrl->dmap_koff,vctrl->dmap_done,smp_processor_id()); spin_unlock_irqrestore(&vctrl->spin_lock,flags); /*setupcompletionfordmapwaitinDIRECTOUTmodeoroverlaywaitinBLTmode*/ if(need_dmap_wait){ pr_debug("%s:wait4dmap\n",__func__); mdp4_dsi_cmd_wait4dmap(0); if(need_ov_wait){ pr_debug("%s:wait4ov\n",__func__); mdp4_dsi_cmd_wait4ov(0); if(vctrl->blt_end){ vctrl->blt_end=0; pipe->ov_blt_addr=0; pipe->dma_blt_addr=0; pr_info("%s:resetov_blt_addranddma_blt_addr\n",__func__); /*ifblthassomechange,reconfigoverlayproccessoranddmap*/ if(vctrl->blt_change){ mdp4_overlayproc_cfg(pipe); mdp4_overlay_dmap_xy(pipe); vctrl->blt_change=0; pipe=vp->plist; *AllpipesusedhereistargetedtoLayerMixer0. *ThesepipesareallocatedwithMIXER0indeed, *andqueuedinvctrl->vlist[undx].>plist[pipe->pipe_ndx-1]again. *ObviouswithtargettoMIXER0. for(i=0;i if(pipe->pipe_used){ /*pipesinvp->plistmaybepointtosamephysicalpipe*/ cnt++; real_pipe=mdp4_overlay_ndx2pipe(pipe->pipe_ndx); if(real_pipe&&real_pipe->pipe_used){ /*pipenotunset*/ mdp4_overlay_vsync_commit(pipe); /*freepreviousiommutofreelist *whichwillbefreedatnext *pipe_commit mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx,0); pipe->pipe_used=0;/*clear*/ /*txdcscommandifhadany*/ mipi_dsi_cmdlist_commit(1); /*mixerisMIXER0here.Setupmixer’seachstagewithpipe*/ mdp4_mixer_stage_commit(mixer); mdp4_dsi_cmd_blt_ov_update(pipe); pipe->ov_cnt++; vctrl->ov_koff++; vsync_irq_enable(INTR_OVERLAY0_DONE,MDP_OVERLAY0_TERM); vsync_irq_enable(INTR_DMA_P_DONE,MDP_DMAP_TERM); vctrl->dmap_koff++; pr_debug("%s:kickoff,pid=%d\n",__func__,current->pid); /*kickoffoverlayengine*/ mdp4_stat.kickoff_ov0++; outpdw(MDP_BASE+0x0004,0); mb(); mdp4_stat.overlay_commit[pipe->mixer_num]++; /*waitforvsync*/ if(wait){ longlongtick; mdp4_dsi_cmd_wait4vsync(cndx,&tick); voidmdp4_overlay_vsync_commit(structmdp4_overlay_pipe*pipe) if(pipe->pipe_type==OVERLAY_TYPE_VIDEO) mdp4_overlay_vg_setup(pipe);/*video/graphicpipe*/ else mdp4_overlay_rgb_setup(pipe);/*rgbpipe*/ pr_debug("%s:pipe=%xndx=%dnum=%dused=%d\n",__func__, (int)pipe,pipe->pipe_ndx,pipe->pipe_num,pipe->pipe_used); /*figureouttheflushvaluetofillregister*/ mdp4_overlay_reg_flush(pipe,1); /*stagesetupbutnotcommit*/ mdp4_mixer_stage_up(pipe,0); voidmdp4_mixer_stage_commit(intmixer) inti,num; u32data,stage; intoff; data=0; for(i=MDP4_MIXER_STAGE_BASE;i pipe=ctrl->stage[mixer][i]; if(pipe==NULL) continue; pr_debug("%s:mixer=%dndx=%dstage=%d\n",__func__, mixer,pipe->pipe_ndx,i); stage=pipe->mixer_stage; if(mixer>=MDP4_MIXER1) stage+=8; stage<<=(4*pipe->pipe_num); data|=stage; *stage_commitmaybecalledfromoverlay_unset *forcommandpanel,mdpclocksmaybeoffatthistime. *somdpclockenabledisnecessary mdp_pipe_ctrl(MDP_CMD_BLOCK,MDP_BLOCK_POWER_ON,FALSE); mdp_clk_ctrl(1); mdp4_mixer_blend_setup(mixer); off=0; if(data!=ctrl->mixer_cfg[mixer]){ ctrl->mixer_cfg[mixer]=data; if(mixer>=MDP4_MIXER2){ /*MDP_LAYERMIXER2_IN_CFG*/ off=0x100f0; /*mixer0or1*/ num=mixer+1; num&=0x01; data|=ctrl->mixer_cfg[num]; off=0x10100; pr_debug("%s:mixer=%ddata=%xflush=%xpid=%d\n",__func__, mixer,data,ctrl->flush[mixer],current->pid); local_irq_save(flags); if(off) outpdw(MDP_BASE+off,data); if(ctrl->flush[mixer]){ outpdw(MDP_BASE+0x18000,ctrl->flush[mixer]); ctrl->flush[mixer]=0; local_irq_restore(flags); mdp_pipe_ctrl(MDP_CMD_BLOCK,MDP_BLOCK_POWER_OFF,FALSE);