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