gralloc

    技术2022-05-20  26

    2011.03.01 系统中有好几个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; };

    最新回复(0)