Android Gralloc模块分析

功能:Galloc模块是显示框架的硬件抽象层,主要是封装了/dev/graphics/fb%d设备文件的操作,

            为框架层提供接口。

实现:Gralloc是HAl中的模块,会被编译成动态链接库。框架层会将动态链接库加载到内存中,

            并利用导出符号得到封装的方法。

问题: Gralloc模块如何加载使用、Gralloc做了哪些事、Gralloc模块内部结构?

Gralloc模块如何加载、使用

答:框架层利用hw_get_module查找模块,并获取导出符号HMI对应的结构体。

hw_get_module(id, module) 提供给框架层调用

int hw_get_module(const char *id, const struct hw_module_t **module)
{
    return hw_get_module_by_class(id, NULL, module);
}

hw_get_module直接调用了hw_get_module_by_class

int hw_get_module_by_class(const char *class_id, const char *inst,
                           const struct hw_module_t **module)
{

    for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {
        if (i < HAL_VARIANT_KEYS_COUNT) {
            if (property_get(variant_keys[i], prop, NULL) == 0) {
                continue;
            }
            //1.在/system/lib/hw/和/vendor/lib/hw/目录下查找四个指定名称的gralloc.xx.so
            snprintf(path, sizeof(path), "%s/%s.%s.so",
                     HAL_LIBRARY_PATH2, name, prop);
            if (access(path, R_OK) == 0) break;

            snprintf(path, sizeof(path), "%s/%s.%s.so",
                     HAL_LIBRARY_PATH1, name, prop);
            if (access(path, R_OK) == 0) break;
        } else {

            //2.没有指定gralloc.xx.so时,使用 /system/lib/hw/gralloc.default.so
            snprintf(path, sizeof(path), "%s/%s.default.so",
                     HAL_LIBRARY_PATH1, name);
            if (access(path, R_OK) == 0) break;
        }
    }

    status = -ENOENT;
    if (i < HAL_VARIANT_KEYS_COUNT+1) {
        //3.加载gralloc.xx.so到内存
        status = load(class_id, path, module);
    }
    return status;
}

函数很简单,在几个路径下查询gralloc.xx.so模块选用一个,最后利用load函数将其加载到内存

static int load(const char *id,
        const char *path,
        const struct hw_module_t **pHmi)
{
    //1.使用dlopen打开动态链接库
    handle = dlopen(path, RTLD_NOW);


    //2.获取动态链接库符号HMI对应地址,得到结构体hw_module_t
    (HAL_MODULE_INFO_SYM_AS_STR是一个常量"HMI",也就是HAL中所有动态链接库导出的都是HMI符号)
    const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
    hmi = (struct hw_module_t *)dlsym(handle, sym);
    hmi->dso = handle;

    //3.返回给调用者hw_module_t
    *pHmi = hmi;

    return status;
}
                 

由此分析可知,load函数关键操作是获取.so中的HMI符号对应地址,得到hw_module_t,而hw_module_t是模块对所有设备操作的封装。


实际上HMI对应的是下面的结构:hardware/libhardware/modules/gralloc/gralloc.cpp

struct private_module_t HAL_MODULE_INFO_SYM = {  }

它与hw_module_t的关系为:


继承关系:private_module_t继承自gralloc_module_t继承自hw_module_t,因此private_module_t指针可以转化为hw_module_t指针。


Gralloc做了哪些事

答:封装了一个模块两个设备,提供了映射、分配、渲染的三个主要功能。

从APP层到驱动层,图像显示的过程:


        应用程序首选需要分配一个图像缓冲区并使用它,但是有由于app在java虚拟机运行中而图形缓冲区分配是在本地代码实现的,因此需要一个映射的过程将图像缓冲区映射到应用的地址空间中,这样应用程序就可以使用图形缓冲区了;而要让图形显示到LCD中,需要把数据写入设备文件里,这里还需要一个渲染的过程用于将图像缓冲区的数据送到帧缓冲区中。         

        由上面的分析可知,HAL层需要提供的抽象操作包括:分配、映射、渲染。而Gralloc模块中将这些操作封装到了下面的结构中。


1.加载Gralloc模块

    打开gralloc设备

    打开fb设备

2.分配图形缓冲区 (gralloc设备)

3.图形缓冲区映射 (Gralloc模块)

4.渲染图形缓冲区 (fb设备)


Gralloc模块内部结构

答:从功能角度来分析结构更容易。

忽略掉继承封装这些细节,下面画出了Gralloc模块的内部结构,这样再分析代码就很清晰了


galloc设备的方式实现在gralloc.cpp中, fb设备的方法实现在framebuffer.cpp中, 映射的方法实现在mapper.cpp中

Gralloc结构体分析

private_module_t定义在文件hardware/libhardware/modules/gralloc/gralloc_priv.h
 主要用来描述帧缓冲区信息。 其中private_handle_t继承自 native_handle, 用来描述一块图形缓冲区,它可能是在内存中分配的,也可能是在帧缓冲区中分配的,视具体情况而定。
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;      //正在被使用的缓冲区  native_handle* buffer_handle_t; 
    int pmem_master;
    void* pmem_master_base;

    struct fb_var_screeninfo info;
    struct fb_fix_screeninfo finfo;
    float xdpi;
    float ydpi;
    float fps;
};
gralloc_module_t定义在文件hardware/libhardware/include/hardware/gralloc.h
registerBuffer用来注册缓冲区,lock用来锁定。这里的注册实际上也就是映射地址空间的功能。

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,
            buffer_handle_t handle);


    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,
            buffer_handle_t handle);

    ......
}

alloc_device_t 也是定义在文件hardware/libhardware/include/hardware/gralloc.h

结构体用来描述一个Gralloc设备,主要负责分配和释放图形缓冲区。

typedef struct alloc_device_t {
    struct hw_device_t common;

    int (*alloc)(struct alloc_device_t* dev,
            int w, int h, int format, int usage,
            buffer_handle_t* handle, int* stride);

    int (*free)(struct alloc_device_t* dev,
            buffer_handle_t handle);

} alloc_device_t;

framebuffer_device_t 定义在文件hardware/libhardware/include/hardware/gralloc.h

结构体用来描述一个fb设备,即帧缓冲区的信息。setSwapInterval用来描述帧缓冲区与前后两个图形缓冲区交换的时间;setUpdateRect用来设置更新的区域;post用来将图形缓冲区渲染到帧缓冲区中区。

typedef struct framebuffer_device_t {
    struct hw_device_t common;

    /* flags describing some attributes of the framebuffer */
    const uint32_t  flags;

    /* dimensions of the framebuffer in pixels */
    const uint32_t  width;
    const uint32_t  height;

    /* frambuffer stride in pixels */
    const int       stride;

    /* framebuffer pixel format */
    const int       format;

    /* resolution of the framebuffer's display panel in pixel per inch*/
    const float     xdpi;
    const float     ydpi;

    /* framebuffer's display panel refresh rate in frames per second */
    const float     fps;

    /* min swap interval supported by this framebuffer */
    const int       minSwapInterval;

    /* max swap interval supported by this framebuffer */
    const int       maxSwapInterval;

    int reserved[8];

    int (*setSwapInterval)(struct framebuffer_device_t* window,
            int interval);

    int (*setUpdateRect)(struct framebuffer_device_t* window,
            int left, int top, int width, int height);

    int (*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer);

    int (*compositionComplete)(struct framebuffer_device_t* dev);

    void* reserved_proc[8];

} framebuffer_device_t;


Gralloc函数分析

gralloc_device_open定义在文件hardware/libhardware/modules/gralloc/gralloc.cpp

这里使用hw_module_t方法中的open操作打开并返回了alloc_device_t设备

struct gralloc_context_t {
    alloc_device_t  device;
    /* our private data here */
};

......

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;
        dev = (gralloc_context_t*)malloc(sizeof(*dev));

        /* initialize our state here */
        memset(dev, 0, sizeof(*dev));

        /* initialize the procs */
        dev->device.common.tag = HARDWARE_DEVICE_TAG;
        dev->device.common.version = 0;
        dev->device.common.module = const_cast<hw_module_t*>(module);
        dev->device.common.close = gralloc_close;

        dev->device.alloc   = gralloc_alloc;
        dev->device.free    = gralloc_free;

        *device = &dev->device.common;
        status = 0;
    } 
    ......

    return status;
}

fb_device_open定义在文件hardware/libhardware/modules/gralloc/framebuffer.cpp
函数打开并返回了setSwapInterval、post、setUpdateRect操作
struct fb_context_t {
    framebuffer_device_t  device;
};

......

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)) {
        alloc_device_t* gralloc_device;
        status = gralloc_open(module, &gralloc_device);
        if (status < 0)
            return status;

        /* initialize our state here */
        fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));
        memset(dev, 0, sizeof(*dev));

        /* initialize the procs */
        dev->device.common.tag = HARDWARE_DEVICE_TAG;
        dev->device.common.version = 0;
        dev->device.common.module = const_cast<hw_module_t*>(module);
        dev->device.common.close = fb_close;
        dev->device.setSwapInterval = fb_setSwapInterval;
        dev->device.post            = fb_post;
        dev->device.setUpdateRect = 0;

        private_module_t* m = (private_module_t*)module;
        status = mapFrameBuffer(m);
        if (status >= 0) {
            int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
            int format = (m->info.bits_per_pixel == 32)
                         ? HAL_PIXEL_FORMAT_RGBX_8888
                         : HAL_PIXEL_FORMAT_RGB_565;
#ifdef NO_32BPP
            format = HAL_PIXEL_FORMAT_RGB_565;
#endif
            const_cast<uint32_t&>(dev->device.flags) = 0;
            const_cast<uint32_t&>(dev->device.width) = m->info.xres;
            const_cast<uint32_t&>(dev->device.height) = m->info.yres;
            const_cast<int&>(dev->device.stride) = stride;
            const_cast<int&>(dev->device.format) = format;
            const_cast<float&>(dev->device.xdpi) = m->xdpi;
            const_cast<float&>(dev->device.ydpi) = m->ydpi;
            const_cast<float&>(dev->device.fps) = m->fps;
            const_cast<int&>(dev->device.minSwapInterval) = 1;
            const_cast<int&>(dev->device.maxSwapInterval) = 1;
            *device = &dev->device.common;
        }
    }
    return status;
}

Gralloc总结

        上面从功能的角度来学习Gralloc,发现它很简单,就是实现了图形缓冲区的分配与映射、帧缓冲区的渲染,总结起来就是分配、映射、渲染。而这些工作分别封装到了gralloc_module_t、alloc_device_t、framebuffer_device_t当中,经过封装继承的关系组织起来。其中gralloc_module_t在hw_get_module被调用时就返回给了框架层,而alloc_device_t和alloc_device_t在hw_module_t->method->open方法被调用时返回给了框架层。这里的结构已经很清楚了。
         一些函数和关键技术可以稍作分析,在需要使用时详细分析研究。至此,gralloc从框架上基本愉快的学习完成。





  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值