gralloc

来源:互联网 发布:游戏优化差会怎样 编辑:程序博客网 时间:2024/05/17 05:59
系统中有好几个gralloc的模块,
分别是:
/hardware/libhardware/modules/gralloc/
/hardware/msm7k/libgralloc-qsd8k/
/hardware/msm7k/libgralloc/
但实际上调用的是第二个模块,通过logcat可以查到.
gralloc被编译成模块gralloc.$(TARGET_BOARD_PLATFORM).so
/hardware/libhardware/modules/gralloc/分析:
提供给上层的接口函数有:
 open: gralloc_device_open
 registerBuffer: gralloc_register_buffer,
 unregisterBuffer: gralloc_unregister_buffer,
 lock: gralloc_lock,
 unlock: gralloc_unlock,
open函数
int gralloc_device_open(const hw_module_t* module, const char* name,
        hw_device_t** device)
该函数首先判断传入的module的类型,类型有两个,分别为:
#define GRALLOC_HARDWARE_FB0 "fb0"
#define GRALLOC_HARDWARE_GPU0 "gpu0"
在gralloc.h文件中定义了,该文件页定义了调用gralloc_device_open()函数的接口,如下:
static inline int gralloc_open(const struct hw_module_t* module, 
        struct alloc_device_t** device) {
    return module->methods->open(module, 
            GRALLOC_HARDWARE_GPU0, (struct hw_device_t**)device);
}
static inline int framebuffer_open(const struct hw_module_t* module, 
        struct framebuffer_device_t** device) {
    return module->methods->open(module, 
            GRALLOC_HARDWARE_FB0, (struct hw_device_t**)device);
}
这两个函数其实就是调用了gralloc_device_open(),只不过参数不同而已;
如果参数是:GRALLOC_HARDWARE_GPU0
为定义的gralloc_context_t 指针分配内存,调用memset()初始化指针为空,并将该指针变量的函数指针指向
        gralloc_context_t *dev;
        dev = (gralloc_context_t*)malloc(sizeof(*dev));
        memset(dev, 0, sizeof(*dev));
        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;
所以可以说Gralloc模块就是为分配显存的。位于framebuffer和surface两层之间。
如果参数是:GRALLOC_HARDWARE_FB0
执行:status = fb_device_open(module, name, device);
fb_device_open()函数调用gralloc_open()函数,这个framebuffer_open()函数的调用打开了gralloc_device_open()两次,第一次根据module的类型为:GRALLOC_HARDWARE_FB0,调用了fb_device_open()这个函数,而fb_device_open()这个函数中又调用了gralloc_open这个函数,这个函数中的module为GRALLOC_HARDWARE_GPU0。
继续分析fb_device_open()函数,
        alloc_device_t* gralloc_device;
        status = gralloc_open(module, &gralloc_device);
        if (status < 0)
            return status;
        fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));
        memset(dev, 0, sizeof(*dev));
        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;
该函数同理定义了fb_context_t的指针,并分配了内存,并初始化了几个函数指针。
然后调用mapFramebuffer() ---->mapFramebufferLocked()
在mapFramebufferLocked()函数中,打开了/dev/graphics/fb0的设备,调用ioctl函数的
FBIOGET_FSCREENINFO,FBIOGET_VSCREENINFO取得了fb_fix_screeninfo,fb_var_screeninfo结构体的数据,
并初始化了fb_var_screeninfo结构体变量info的数据:
    info.reserved[0] = 0;
    info.reserved[1] = 0;
    info.reserved[2] = 0;
    info.xoffset = 0;
    info.yoffset = 0;
    info.activate = FB_ACTIVATE_NOW;
    info.bits_per_pixel = 16;
    info.red.offset     = 11;
    info.red.length     = 5;
    info.green.offset   = 5;
    info.green.length   = 6;
    info.blue.offset    = 0;
    info.blue.length    = 5;
    info.transp.offset  = 0;
    info.transp.length  = 0;
都是初始话像素的深度和红绿蓝分量在每个像素中的偏移。
随后调用ioctl的FBIOPUT_VSCREENINFO将info的数据写回到framebuffer中。
随后计算刷新的频率,
    int refreshRate = 1000000000000000LLU /
    (
            uint64_t( info.upper_margin + info.lower_margin + info.yres )
            * ( info.left_margin  + info.right_margin + info.xres )
            * info.pixclock
    );
    if (refreshRate == 0) {
        // bleagh, bad info from the driver
        refreshRate = 60*1000;  // 60 Hz
    }
    float xdpi = (info.xres * 25.4f) / info.width;
    float ydpi = (info.yres * 25.4f) / info.height;
    float fps  = refreshRate / 1000.0f;
  uint32_t flags = PAGE_FLIP;//从代码可以看出,支不支持PAGE_FLIP就看是不是:info.yres_virtual < info.yres * 2
最终把这些变量写入到module中:
    module->flags = flags;
    module->info = info;
    module->finfo = finfo;
    module->xdpi = xdpi;
    module->ydpi = ydpi;
    module->fps = fps;
    int err;
    size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual);
    module->framebuffer = new private_handle_t(dup(fd), fbSize, 0);
    module->numBuffers = info.yres_virtual / info.yres;
    module->bufferMask = 0;
调用mmap将内核的fd映射到用户空间
并 module->framebuffer->base = intptr_t(vaddr);将vaddr的类型转化为int16_t的,之后memset将vaddr的数据初始化为空。
再来看fb_device_open()函数,
其实这一系列的过程就是初始化了两个结构体:
  fb_context_t *dev ;
gralloc_context_t *dev;
为两个结构体分配了内存,并初始化.
gralloc_alloc()函数
该函数主要的作用就是分配内存的,如果支持PAGE_FLIP(双缓冲)模式,则调用gralloc_alloc_framebuffer(),否则,调用gralloc_alloc_buffer()
gralloc_alloc_framebuffer()函数:
调用gralloc_alloc_framebuffer_locked()函数,
在该函数中,调用mapFrameBufferLocked()函数得到fb的参数,并初始化private_module_t* m这个结构体,重新创建了一个private_handle_t* hnd,这个hndflags为private_handle_t::PRIV_FLAGS_FRAMEBUFFER.bufferMask应该等于11,numBuffers应该等于2,vaddr应该为第二块framebuffer的地址 (vaddr += bufferSize;),offset也相应改变.
gralloc_free()函数:
该函数正好和gralloc_alloc函数相反,是释放内存的,首先判断
hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER
之后,计算bufferSize大小,计算这个handle在framebuffer中的索引,根据索引来
        const size_t bufferSize = m->finfo.line_length * m->info.yres;
        int index = (hnd->base - m->framebuffer->base) / bufferSize;
        m->bufferMask &= ~(1<<index); 
index应该等于1,则m->bufferMask计算之后等于1.
最开始调用fb_device_open创建的hnd的flags=0,走的是else后面的路,最终调用到mnumap()函数解除对内存的映射.
fb_post()分析:
首先也是判断
(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)
如果flags相等,则重新设置了一下该framebuffer_device_t的fb_var_screeninfo结构体的activate和yoffset信息,之后ioctl将fb_var_screeninfo写入到fb中,然后直接将当前的currentBuffer指向这个buffer_handle_t.
如果flags不相等,则调用gralloc_lock函数,得到两个buffer的地址,再调用memcpy()将buffer复制.
/////////////////////////////////////////////////////////
struct private_handle_t : public native_handle {}
typedef const native_handle* buffer_handle_t;
typedef struct gralloc_module_t {
    struct hw_module_t common;
} gralloc_module_t;
typedef struct alloc_device_t {
    struct hw_device_t common;
} alloc_device_t;
typedef struct framebuffer_device_t {
    struct hw_device_t common;
} framebuffer_device_t;
typedef native_handle_t native_handle;
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;
typedef struct hw_module_t {
    /** tag must be initialized to HARDWARE_MODULE_TAG */
    uint32_t tag;
    /** major version number for the module */
    uint16_t version_major;
    /** minor version number of the module */
    uint16_t version_minor;
    /** Identifier of module */
    const char *id;
    /** Name of this module */
    const char *name;
    /** Author/owner/implementor of the module */
    const char *author;
    /** Modules methods */
    struct hw_module_methods_t* methods;
    /** module's dso */
    void* dso;
    /** padding to 128 bytes, reserved for future use */
    uint32_t reserved[32-7];
} hw_module_t;
typedef struct hw_module_methods_t {
    /** Open a specific device */
    int (*open)(const struct hw_module_t* module, const char* id,
            struct hw_device_t** device);
} hw_module_methods_t;
typedef struct hw_device_t {
    /** tag must be initialized to HARDWARE_DEVICE_TAG */
    uint32_t tag;
    /** version number for hw_device_t */
    uint32_t version;
    /** reference to the module this device belongs to */
    struct hw_module_t* module;
    /** padding reserved for future use */
    uint32_t reserved[12];
    /** Close this device */
    int (*close)(struct hw_device_t* device);
} hw_device_t;
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;
};