天天看点

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,如需转载请自行联系原作者

继续阅读