一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

GUI顯示系統(tǒng)之SurfaceFlinger

 老匹夫 2014-03-29

目錄(?)[+]

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中的重要成員變量

變量

描述

uint32_t  flags

標(biāo)志位,指示framebuffer的屬性配置

uint32_t  width;

uint32_t  height;

framebuffer的寬和高,以像素為單位

int       format

framebuffer的像素格式,比如:HAL_PIXEL_FORMAT_RGBA_8888 HAL_PIXEL_FORMAT_RGBX_8888

HAL_PIXEL_FORMAT_RGB_888

HAL_PIXEL_FORMAT_RGB_565等等

float     xdpi;

float     ydpi;

x和y軸的密度(pixel per inch)

float     fps

屏幕的每秒刷新頻率,假如無(wú)法正常從設(shè)備獲取的話,默認(rèn)設(shè)置為60Hz

int       minSwapInterval;

int       maxSwapInterval;

該framebuffer支持的最小和最大緩沖交換時(shí)間

到目前為止,我們還沒(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)圖

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多

    欧美性欧美一区二区三区| 欧美一区二区不卡专区| 有坂深雪中文字幕亚洲中文| 91在线国内在线中文字幕| 国产丝袜女优一区二区三区| 日韩一级免费中文字幕视频| 99精品国产一区二区青青 | 国产乱人伦精品一区二区三区四区 | 成人亚洲国产精品一区不卡| 激情国产白嫩美女在线观看| 国产一区二区精品丝袜| 在线免费观看一二区视频| 国产午夜福利一区二区| 蜜桃臀欧美日韩国产精品| 日韩三级黄色大片免费观看| 亚洲一区二区三在线播放| 欧美人妻少妇精品久久性色| 日韩国产亚洲一区二区三区| 国产免费一区二区不卡| 免费一级欧美大片免费看| 日本不卡在线一区二区三区| 美国女大兵激情豪放视频播放| 人妻中文一区二区三区| 视频一区二区黄色线观看| 国产精品一级香蕉一区| 欧美性高清一区二区三区视频 | 久久机热频这里只精品| 中文字幕中文字幕在线十八区| 又黄又硬又爽又色的视频| 国产一区二区三区色噜噜| 亚洲视频一级二级三级| 久久中文字幕中文字幕中文| 69老司机精品视频在线观看| 91欧美激情在线视频| 欧美亚洲综合另类色妞| 日韩欧美好看的剧情片免费| 夫妻性生活一级黄色录像| 精品欧美日韩一区二区三区| 国产亚洲成av人在线观看| 白丝美女被插入视频在线观看| 欧美日韩在线视频一区|