天天看點

Android幀緩沖區(Frame Buffer)硬體抽象層(HAL)子產品Gralloc的實作原理分析(3)

   結構體gralloc_module_t定義在檔案hardware/libhardware/include/hardware/gralloc.h中,它主要是定義了四個用來操作圖形緩沖區的成員函數,如下所示:

typedef struct gralloc_module_t {  

    ......  

    int (*registerBuffer)(struct gralloc_module_t const* module,  

            buffer_handle_t handle);  

    int (*unregisterBuffer)(struct gralloc_module_t const* module,  

    int (*lock)(struct gralloc_module_t const* module,  

            buffer_handle_t handle, int usage,  

            int l, int t, int w, int h,  

            void** vaddr);  

    int (*unlock)(struct gralloc_module_t const* module,  

}  

        成員函數registerBuffer和unregisterBuffer分别用來注冊和登出一個指定的圖形緩沖區,這個指定的圖形緩沖區使用一個buffer_handle_t句柄來描述。所謂注冊圖形緩沖區,實際上就是将一塊圖形緩沖區映射到一個程序的位址空間去,而登出圖形緩沖區就是執行相反的操作。

        成員函數lock和unlock分别用來鎖定和解鎖一個指定的圖形緩沖區,這個指定的圖形緩沖區同樣是使用一個buffer_handle_t句柄來描述。在通路一塊圖形緩沖區的時候,例如,向一塊圖形緩沖寫入内容的時候,需要将該圖形緩沖區鎖定,用來避免通路沖突。在鎖定一塊圖形緩沖區的時候,可以指定要鎖定的圖形繪沖區的位置以及大小,這是通過參數l、t、w和h來指定的,其中,參數l和t指定的是要通路的圖形緩沖區的左上角位置,而參數w和h指定的是要通路的圖形緩沖區的寬度和長度。鎖定之後,就可以獲得由參數參數l、t、w和h所圈定的一塊緩沖區的起始位址,儲存在輸出參數vaddr中。另一方面,在通路完成一塊圖形緩沖區之後,需要解除這塊圖形緩沖區的鎖定。

        在Gralloc子產品中,符号HAL_MODULE_INFO_SYM指向的gralloc結構體的成員函數registerBuffer、unregisterBuffer、lock和unlock分别被指定為函數gralloc_register_buffer、gralloc_unregister_buffer、gralloc_lock和gralloc_unlock,後面我們再詳細分析它們的實作。

        結構體private_module_t定義在檔案hardware/libhardware/modules/gralloc/gralloc_priv.h中,它主要是用來描述幀緩沖區的屬性,如下所示:

struct private_module_t {  

    gralloc_module_t base;  

    private_handle_t* framebuffer;  

    uint32_t flags;  

    uint32_t numBuffers;  

    uint32_t bufferMask;  

    pthread_mutex_t lock;  

    buffer_handle_t currentBuffer;  

    int pmem_master;  

    void* pmem_master_base;  

    struct fb_var_screeninfo info;  

    struct fb_fix_screeninfo finfo;  

    float xdpi;  

    float ydpi;  

    float fps;  

};  

       成員變量framebuffer的類型為private_handle_t,它是一個指向系統幀緩沖區的句柄,後面我們再分析結構體private_handle_t的定義。

       成員變量flags用來标志系統幀緩沖區是否支援雙緩沖。如果支援的話,那麼它的PAGE_FLIP位就等于1,否則的話,就等于0。

       成員變量numBuffers表示系統幀緩沖區包含有多少個圖形緩沖區。一個幀緩沖區包含有多少個圖形緩沖區是與它的可視分辨率以及虛拟分辨率的大小有關的。例如,如果一個幀緩沖區的可視分辨率為800 x 600,而虛拟分辨率為1600 x 600,那麼這個幀緩沖區就可以包含有兩個圖形緩沖區。

       成員變量bufferMask用來記錄系統幀緩沖區中的圖形緩沖區的使用情況。例如,假設系統幀緩沖區有兩個圖形緩沖區,這時候成員變量bufferMask就有四種取值,分别是二進制的00、01、10和11,其中,00分别表示兩個圖緩沖區都是空閑的,01表示第1個圖形緩沖區已經配置設定出去,而第2個圖形緩沖區是空閑的,10表示第1個圖形緩沖區是空閑的,而第2個圖形緩沖區已經配置設定出去,11表示兩個圖緩沖區都已經配置設定出去。

       成員變量lock是一個互斥鎖,用來保護結構體private_module_t的并行通路。

       成員變量currentBuffer的類型為buffer_handle_t,用來描述目前正在被渲染的圖形緩沖區,後面我們再分析它的定義。

       成員變量pmem_master和pmem_master_base目前沒有使用。

       成員變量info和finfo的類型分别為fb_var_screeninfo和fb_fix_screeninfo,它們用來儲存裝置顯示屏的屬性資訊,其中,成員變量info儲存的屬性資訊是可以動态設定的,而成員變量finfo儲存的屬性資訊是隻讀的。這兩個成員變量的值可以通過IO控制指令FBIOGET_VSCREENINFO和FBIOGET_FSCREENINFO來從幀緩沖區驅動子產品中獲得。

       成員變量xdpi和ydpi分别用來描述裝置顯示屏在寬度和高度上的密度,即每英寸有多少個像素點。

       成員變量fps用來描述顯示屏的重新整理頻率,它的機關的fps,即每秒幀數。

       接下來, 我們再分析結構體buffer_handle_t和private_handle_t的定義。

       結構體buffer_handle_t定義在檔案hardware/libhardware/include/hardware/gralloc.h檔案中,如下所示:

typedef const native_handle* buffer_handle_t;  

       它是一個類型為native_handle_t的指針,而結構體native_handle_t用來描述一個本地句柄值,它定義在系統運作時層的檔案system/core/include/cutils/native_handle.h檔案中,如下所示:

typedef struct  

{  

    int version;        /* sizeof(native_handle_t) */  

    int numFds;         /* number of file-descriptors at &data[0] */  

    int numInts;        /* number of ints at &data[numFds] */  

    int data[0];        /* numFds + numInts ints */  

} native_handle_t;  

       成員變量version的大小被設定為結構體native_handle_t的大小,用來辨別結構體native_handle_t的版本。

       成員變量numFds和numInts表示結構體native_handle_t所包含的檔案描述符以及整數值的個數,這些檔案描述符和整數儲存在成員變量data所指向的一塊緩沖區中。

       我們一般不直接使用native_handle_t結構體來描述一個本地句柄值,而是通過它的子類來描述一個具體的本地句柄值。接下來我們就通過結構體private_handle_t的定義來說明native_handle_t結構體的用法。

       結構體private_handle_t用來描述一塊圖形緩沖區,這塊圖形緩沖區可能是在幀緩沖區中配置設定的,也可能是在記憶體中配置設定的,視具體情況而定,它定義在檔案hardware/libhardware/modules/gralloc/gralloc_priv.h檔案中,如下所示:

#ifdef __cplusplus  

struct private_handle_t : public native_handle {  

#else  

struct private_handle_t {  

    struct native_handle nativeHandle;  

#endif  

    enum {  

        PRIV_FLAGS_FRAMEBUFFER = 0x00000001  

    };  

    // file-descriptors  

    int     fd;  

    // ints  

    int     magic;  

    int     flags;  

    int     size;  

    int     offset;  

    // FIXME: the attributes below should be out-of-line  

    int     base;  

    int     pid;  

    static const int sNumInts = 6;  

    static const int sNumFds = 1;  

    static const int sMagic = 0x3141592;  

    private_handle_t(int fd, int size, int flags) :  

        fd(fd), magic(sMagic), flags(flags), size(size), offset(0),  

        base(0), pid(getpid())  

    {  

        version = sizeof(native_handle);  

        numInts = sNumInts;  

        numFds = sNumFds;  

    }  

    ~private_handle_t() {  

        magic = 0;  

    static int validate(const native_handle* h) {  

        const private_handle_t* hnd = (const private_handle_t*)h;  

        if (!h || h->version != sizeof(native_handle) ||  

                h->numInts != sNumInts || h->numFds != sNumFds ||  

                hnd->magic != sMagic)  

        {  

            LOGE("invalid gralloc handle (at %p)", h);  

            return -EINVAL;  

        }  

        return 0;  

        為了友善描述,我們假設我們是在C++環境中編譯檔案gralloc_priv.h,即編譯環境定義有宏__cplusplus。這樣,結構體private_handle_t就是從結構體native_handle_t繼承下來的,它包含有1個檔案描述符以及6個整數,以及三個靜态成員變量。

本文轉自 Luoshengyang 51CTO部落格,原文連結:http://blog.51cto.com/shyluo/967065,如需轉載請自行聯系原作者

繼續閱讀