GUI:Gralloc和FrameBuffer

1.FrameBuffer概述

FrameBuffer是linux内核系统提供的图形硬件的抽象描述,之所以称为buffer,是因为它也占用了系统存储空间的一部分,是一块包含屏幕显示信息的缓冲区;另外FrameBuffer借助于linux文件系统向上层应用提供了统一而高效的操作接口,从而让用户空间中运行的程序可以在不做太多修改的情况下去适配多种显示设备(无论它们属于什么厂家,什么型号,都有FrameBuffer内部来兼容)。
在android系统中,FrameBuffer提供的文件节点是/dev/graphics/fb*,因为理论上支持多屏幕显示,所以fb按数字序号排列,其中fb0是主屏幕。

android的各个子系统通常不会直接使用内核驱动,而是通过HAL层来间接引用底层框架,显示系统也一样,它借助HAL层来操作帧缓冲区,而完成这一中介任务的就是Gralloc

2.Gralloc

2.1 Gralloc模块的加载

Gralloc对应的模块是由FrameBufferNativeWindow在构造函数中加载的。

hw_get_module(GRALLOC_HADRWARE_MODULE_ID,&module);
  • hw_get_module是上层使用者加载HAL库的入口,不论哪个厂商提供的HAL库都由这个函数来加载
  • GRALLOC_HADRWARE_MODULE_ID的值是"gralloc"
  • hw_get_module会在指定的目录中寻找目标库,android原生的默认库是gralloc.default.so

2.2 Gralloc提供的接口

通过hw_get_module成功加载Gralloc对应的HAL库之后,就可以使用它所提供的接口了

typedef struct hw_module_t{
  struct hw_module_methods_t * methods;//一个HAL库必须提供的方法

} hw_module_t;

typedef struct hw_module_methods_t{
  int (*open)(const struct hw_module_t *module,const char *id,strcut hw_device_t **device);
}hw_module_methods_t;

Gralloc是hw_module_t的子类,有此看出,任何硬件设备的HAL库都必须实现hw_module_methods_t,当上层调用hw_get_module时,系统首先在指定目录查找并加载正确的HAL库,然后通过open来打开指定的设备,在Gralloc中,open可以帮助上层打开两个设备,分别是"fb0"和"gpu0";"fb0"就是主屏幕,"gpu0"负责图形缓冲区的分配和释放,这两个设备分别由FrameBufferNativeWindow的fbDev和grDev成员变量来管理。

    if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { 
        err = framebuffer_open(module, &fbDev);
        err = gralloc_open(module, &grDev);

2.3 gralloc_device_open


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)); 
        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(module);
        dev->device.common.close = gralloc_close;

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

        *device = &dev->device.common;
        status = 0;
    } else {
        //打开framebuffer
        status = fb_device_open(module, name, device);
    }
    return status;
}

2.3.1 fb_device_open打开framebuffer

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空间并初始化 */
        fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));
        memset(dev, 0, sizeof(*dev));

        /*这几个接口是frambuffer的核心 */
        dev->device.common.tag = HARDWARE_DEVICE_TAG;
        dev->device.common.version = 0;
        dev->device.common.module = const_cast(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) { 
             //......壳子与核心的关系
            *device = &dev->device.common;
        }
    }
    return status;
}

static int fb_setSwapInterval(struct framebuffer_device_t* dev,
int interval);
设置两个缓冲区交换的时间间隔
static int fb_setUpdateRect(struct framebuffer_device_t* dev,
int l, int t, int w, int h);
设置刷新区域
static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer);
将buffer数据post到显示屏上,要求buffer与显示屏尺寸一致,并且没有被locked,这样buffer的内容在下一次vsync中被显示出来

int mapFrameBufferLocked(struct private_module_t* module)
{
    //打开设备
    while ((fd==-1) && device_template[i]) {
        snprintf(name, 64, device_template[i], 0);
        fd = open(name, O_RDWR, 0);
        i++;
    }
    //获取显示屏的一些参数 
    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
        return -errno;
 
    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
        return -errno;
 
//根据获取的参数对fb进行设置
     if (ioctl(fd, FBIOPAN_DISPLAY, &info) == -1)  
    if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) 
 

    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
  
    //屏幕属性
    float xdpi = (info.xres * 25.4f) / info.width;
    float ydpi = (info.yres * 25.4f) / info.height;
    float fps  = refreshRate / 1000.0f;
    //对fb做内存映射
    void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if (vaddr == MAP_FAILED) {
         
    }
    module->framebuffer->base = intptr_t(vaddr);
    memset(vaddr, 0, fbSize);
    return 0;
}

2.3.2 打开gralloc

        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(module);
        dev->device.common.close = gralloc_close;
        //gralloc的两个主要操作,alloc和free
        dev->device.alloc   = gralloc_alloc;
        dev->device.free    = gralloc_free;

        *device = &dev->device.common;
        status = 0;
GUI:Gralloc和FrameBuffer_第1张图片
Gralloc.png

你可能感兴趣的:(GUI:Gralloc和FrameBuffer)