日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

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

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

變量

描述

uint32_t  flags

標志位,指示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

屏幕的每秒刷新頻率,假如無法正常從設備獲取的話,默認設置為60Hz

int       minSwapInterval;

int       maxSwapInterval;

該framebuffer支持的最小和最大緩沖交換時間

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

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

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多