GUI顯示系統(tǒng)之SurfaceFlinger其它部分完整章節(jié):http://blog.csdn.net/uiop78uiop78/article/details/8954508 第1章 GUI系統(tǒng)之SurfaceFlinger在進(jìn)入GUI系統(tǒng)的學(xué)習(xí)前,建議大家可以先閱讀本書(shū)應(yīng)用篇中的“OpenGLES”章節(jié),并參閱OpenGL ES官方指南。因?yàn)锳ndroid的GUI系統(tǒng)是基于OpenGL/EGL來(lái)實(shí)現(xiàn)的,如果沒(méi)有一定基礎(chǔ)的話,分析源碼時(shí)有可能會(huì)“事倍功半”。 1.1 Gralloc與Framebuffer相信做過(guò)Linux開(kāi)發(fā)的人對(duì)framebuffer不會(huì)太陌生,它是內(nèi)核系統(tǒng)提供的一個(gè)與硬件無(wú)關(guān)的顯示抽象層。之所以稱之為buffer,是由于它也是系統(tǒng)存儲(chǔ)空間的一部分,是一塊包含屏幕顯示信息的緩沖區(qū)。由此可見(jiàn),在“一切都是文件”的Linux系統(tǒng)中,F(xiàn)ramebuffer被看成了終端monitor的“化身”。它借助于文件系統(tǒng)向上層提供統(tǒng)一而方便的操作接口,從而讓用戶空間程序可以不用修改就能適應(yīng)多種屏幕——無(wú)論這些屏幕是哪家廠商、什么型號(hào),都由framebuffer內(nèi)部來(lái)兼容。 在Android系統(tǒng)中,framebuffer提供的設(shè)備文件節(jié)點(diǎn)是/dev/graphics/fb*。因?yàn)槔碚撋现С侄鄠€(gè)屏幕顯示,所以fb按數(shù)字序號(hào)進(jìn)行排列,即fb0、fb1等等。其中第一個(gè)fb0是主顯示屏幕,必須存在。如下是某設(shè)備的fb設(shè)備截圖: 圖 11?1 fb節(jié)點(diǎn) 根據(jù)前面章節(jié)學(xué)習(xí)過(guò)的知識(shí),Android中各子系統(tǒng)通常不會(huì)直接基于Linux驅(qū)動(dòng)來(lái)實(shí)現(xiàn),而是由HAL層間接引用底層架構(gòu),在顯示系統(tǒng)中也同樣如此——它借助于HAL層來(lái)操作幀緩沖區(qū),而完成這一中介任務(wù)的就是Gralloc,下面我們分幾個(gè)方面來(lái)介紹。 <1> Gralloc的加載 Gralloc對(duì)應(yīng)的模塊是由FramebufferNativeWindow(OpenGLES的本地窗口之一,后面小節(jié)有詳細(xì)介紹)在構(gòu)造時(shí)加載的,即: hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule); 這個(gè)hw_get_module函數(shù)我們?cè)谇懊嬉呀?jīng)見(jiàn)過(guò)很多次了,它是上層加載HAL庫(kù)的入口,這里傳入的模塊ID名為: #define GRALLOC_HARDWARE_MODULE_ID "gralloc" 按照hw_get_module的作法,它會(huì)在如下路徑中查找與ID值匹配的庫(kù): #define HAL_LIBRARY_PATH1 "/system/lib/hw" #define HAL_LIBRARY_PATH2 "/vendor/lib/hw" lib庫(kù)名有如下幾種形式: gralloc.[ro.hardware].so gralloc.[ro.product.board].so gralloc.[ro.board.platform].so gralloc.[ro.arch].so 或者當(dāng)上述的系統(tǒng)屬性組成的文件名都不存在時(shí),就使用默認(rèn)的: gralloc.default.so 最后這個(gè)庫(kù)是Android原生態(tài)的實(shí)現(xiàn),位置在hardware/libhardware/modules/gralloc/中,它由gralloc.cpp、framebuffer.cpp和mapper.cpp三個(gè)主要源文件編譯生成。 <2> Gralloc提供的接口 Gralloc對(duì)應(yīng)的庫(kù)被加載后,我們來(lái)看下它都提供了哪些接口方法。 由于Gralloc代表的是一個(gè)hw_module_t,這是HAL中統(tǒng)一定義的硬件模塊描述體,所以和其它module所能提供的接口是完全一致的: /*hardware/libhardware/include/hardware/Hardware.h*/ typedef struct hw_module_t {… structhw_module_methods_t* methods; … } hw_module_t; typedef struct hw_module_methods_t { int (*open)(const structhw_module_t* module, const char* id, structhw_device_t** device); } hw_module_methods_t; 這個(gè)open接口可以幫助上層打開(kāi)兩個(gè)設(shè)備,分別是: #defineGRALLOC_HARDWARE_FB0 "fb0" 以及 #define GRALLOC_HARDWARE_GPU0 "gpu0" “fb0”就是我們前面說(shuō)的主屏幕,gpu0負(fù)責(zé)圖形緩沖區(qū)的分配和釋放。這兩個(gè)設(shè)備將由FramebufferNativeWindow中的fbDev和grDev成員變量來(lái)管理。 /*frameworks/native/libs/ui/FramebufferNativeWindow.cpp*/ FramebufferNativeWindow::FramebufferNativeWindow() : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false) {… err =framebuffer_open(module, &fbDev); err =gralloc_open(module, &grDev); 這兩個(gè)open函數(shù)分別是由hardware/libhardware/include/hardware目錄下的Fb.h和Gralloc.h頭文件提供的打開(kāi)fb及gralloc設(shè)備的便捷實(shí)現(xiàn)。其中fb對(duì)應(yīng)的設(shè)備名為GRALLOC_HARDWARE_FB0,gralloc則是GRALLOC_HARDWARE_GPU0。各硬件生產(chǎn)商可以根據(jù)自己的平臺(tái)配置來(lái)實(shí)現(xiàn)fb和gralloc的打開(kāi)、關(guān)閉以及管理,比如hardware/msm7k/libgralloc就是一個(gè)很好的參考例子。 原生態(tài)的實(shí)現(xiàn)在hardware/libhardware/modules/gralloc中,對(duì)應(yīng)的是gralloc_device_open@Gralloc.cpp。在這個(gè)函數(shù)中,根據(jù)設(shè)備名來(lái)判斷是打開(kāi)fb或者gralloc。 /*hardware/libhardware/modules/gralloc/Gralloc.cpp*/ int gralloc_device_open(const hw_module_t*module, const char* name, hw_device_t** device) { intstatus = -EINVAL; if(!strcmp(name, GRALLOC_HARDWARE_GPU0)) {//打開(kāi)gralloc設(shè)備 … } else{ status = fb_device_open(module, name, device);//否則就是fb設(shè)備 } returnstatus; } 先來(lái)大概看下framebuffer設(shè)備的打開(kāi)過(guò)程: /*hardware/libhardware/modules/gralloc/Framebuffer.cpp*/ int fb_device_open(hw_module_t const* module, const char* name,hw_device_t** device) { int status = -EINVAL; if (!strcmp(name, GRALLOC_HARDWARE_FB0)){//設(shè)備名是否正確 fb_context_t *dev =(fb_context_t*)malloc(sizeof(*dev));//分配hw_device_t空間,這是一個(gè)“殼” memset(dev, 0,sizeof(*dev));//初始化,良好的編程習(xí)慣 … dev->device.common.close = fb_close;//這幾個(gè)接口是fb設(shè)備的核心 dev->device.setSwapInterval = fb_setSwapInterval; dev->device.post = fb_post; … private_module_t* m =(private_module_t*)module; status = mapFrameBuffer(m);//內(nèi)存映射,以及參數(shù)配置 if (status >= 0) { … *device =&dev->device.common;//“殼”和“核心”的關(guān)系 } } return status; } 其中fb_context_t是framebuffer內(nèi)部使用的一個(gè)類(lèi),它包含了眾多信息,而最終返回的device只是其內(nèi)部的device.common。這種“通用和差異”并存的編碼風(fēng)格在HAL層非常常見(jiàn),大家要做到習(xí)以為常。 Struct類(lèi)型fb_context_t里的唯一成員就是framebuffer_device_t,這是對(duì)frambuffer設(shè)備的統(tǒng)一描述。一個(gè)標(biāo)準(zhǔn)的fb設(shè)備通常要提供如下的函數(shù)實(shí)現(xiàn): l int(*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer); 將buffer數(shù)據(jù)post到顯示屏上。要求buffer必須與屏幕尺寸一致,并且沒(méi)有被locked。這樣的話buffer內(nèi)容將在下一次VSYNC中被顯示出來(lái) l int(*setSwapInterval)(struct framebuffer_device_t* window, int interval); 設(shè)置兩個(gè)緩沖區(qū)交換的時(shí)間間隔 l int(*setUpdateRect)(struct framebuffer_device_t* window, int left, int top, int width, int height); 設(shè)置刷新區(qū)域,需要framebuffer驅(qū)動(dòng)支持“update-on-demand”。也就是說(shuō)在這個(gè)區(qū)域外的數(shù)據(jù)很可能被認(rèn)為無(wú)效 我們?cè)賮?lái)解釋下framebuffer_device_t中一些重要的成員變量,如下表: 表格 11?1 framebuffer_device_t中的重要成員變量
到目前為止,我們還沒(méi)看到系統(tǒng)是如何打開(kāi)具體的fb設(shè)備、以及如何對(duì)fb進(jìn)行配置,這些工作都是在mapFrameBuffer()完成的。這個(gè)函數(shù)首先嘗試打開(kāi)(調(diào)用open,權(quán)限為O_RDWR)如下路徑中的fb設(shè)備: "/dev/graphics/fb%u"或者 "/dev/fb%u",其中%u當(dāng)前的實(shí)現(xiàn)中只用了“0”,也就是只會(huì)打開(kāi)一個(gè)fb,雖然Android從趨勢(shì)上看是要支持多屏幕的。成功打開(kāi)fb后,我們通過(guò): ioctl(fd, FBIOGET_FSCREENINFO, &finfo); ioctl(fd, FBIOGET_VSCREENINFO, &info) 來(lái)得到顯示屏的一系列參數(shù),同時(shí)通過(guò) ioctl(fd, FBIOPUT_VSCREENINFO, &info)來(lái)對(duì)底層fb進(jìn)行配置。 這個(gè)函數(shù)的另一重要任務(wù),就是對(duì)fb做內(nèi)存映射,主要語(yǔ)句如下: void* vaddr = mmap(0,fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); module->framebuffer->base = intptr_t(vaddr); memset(vaddr, 0, fbSize); 所以映射地址是module->framebuffer->base,這個(gè)module對(duì)應(yīng)的是前面hw_get_module(GRALLOC_HARDWARE_MODULE_ID,&module)得到的hw_module_t(被強(qiáng)制類(lèi)型轉(zhuǎn)化為private_module_t,大家可以自己看下這個(gè)struct)。 接下來(lái)再看下對(duì)gralloc設(shè)備的打開(kāi)操作,它相對(duì)fb簡(jiǎn)單些,如下所示: /*hardware/libhardware/modules/gralloc/Gralloc.cpp*/ int gralloc_device_open(const hw_module_t* module, const char* name,hw_device_t** device) { int status = -EINVAL; if (!strcmp(name,GRALLOC_HARDWARE_GPU0)) { gralloc_context_t*dev;//做法和fb類(lèi)似 dev =(gralloc_context_t*)malloc(sizeof(*dev));//分配空間 /* initialize ourstate here */ memset(dev, 0,sizeof(*dev)); … dev->device.alloc =gralloc_alloc; //從提供的接口來(lái)看,gralloc和分配/釋放有關(guān)系 dev->device.free =gralloc_free; … } 與fb相似的部分我們就不多做介紹了。因?yàn)間ralloc擔(dān)負(fù)著圖形緩沖區(qū)的分配與釋放,所以它提供了兩個(gè)最重要的實(shí)現(xiàn)即alloc和free。這里我們先不深入分析了,只要知道gralloc所提供的功能就可以了。 我們以下面簡(jiǎn)圖來(lái)小結(jié)對(duì)Gralloc的分析。 圖 11?2 Gralloc簡(jiǎn)圖 |
|
來(lái)自: 老匹夫 > 《Graphics》