默认的Gralloc模块实现的代码路径如下:
hardware/libhardware/modules/gralloc/*
- $ ls hardware/libhardware/modules/gralloc/
- Android.mk framebuffer.cpp gralloc.cpp gralloc_priv.h gr.h mapper.cpp
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)) { //打开alloc_device_t设备
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; //alloc_device_t的alloc接口
dev->device.free = gralloc_free; //alloc_device_t的free接口
*device = &dev->device.common;
status = 0;
} else {
status = fb_device_open(module, name, device); //打开framebuffer_device_t设备
}
return status;
}
private_module_t 扩展了 gralloc_module_t 结构:
struct private_module_t HAL_MODULE_INFO_SYM= {
base:{ //base 就是gralloc_module_t
common:{
tag: HARDWARE_MODULE_TAG,
version_major: 1,
version_minor: 0,
id: GRALLOC_HARDWARE_MODULE_ID,
name:"Graphics Memory Allocator Module",
author:"The Android Open Source Project",
methods:&gralloc_module_methods
},
registerBuffer: gralloc_register_buffer, //都是gralloc_module_t的方法,这些方法都在mapper.cpp中实现。
unregisterBuffer: gralloc_unregister_buffer,
lock: gralloc_lock,
unlock: gralloc_unlock,
},
framebuffer: 0,
flags: 0,
numBuffers: 0,
bufferMask: 0,
lock: PTHREAD_MUTEX_INITIALIZER,
currentBuffer: 0,
};
private_module_t 原型定义在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;
};
2. framebuffer.cpp 用于实现 framebuffer_device_t 设备:
打开framebuffer_device_t设备函数 fb_device_open(),该函数初始化了一个framebuffer_device_t 设备。
int fb_device_open(hw_module_tconst* module, constchar* 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); //映射framebuffer设备
if (status >= 0){ //填充framebuffeer_device_t 设备的各项内容
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;
}
其主体实现函数是 mapFrameBuffer(m) :
staticint mapFrameBuffer(struct private_module_t*module)
{
pthread_mutex_lock(&module->lock);
int err = mapFrameBufferLocked(module);
pthread_mutex_unlock(&module->lock);
return err;
}
int mapFrameBufferLocked(struct private_module_t*module)
{
// already initialized...
if (module->framebuffer){
return 0;
}
char const* const device_template[]= { //定义framebuffer设备
"/dev/graphics/fb%u",
"/dev/fb%u",
0 };
int fd =-1;
int i=0;
char name[64];
while ((fd==-1)&& device_template[i]){
snprintf(name, 64, device_template[i], 0);
fd = open(name, O_RDWR, 0);
i++;
}
if (fd< 0)
return -errno;
struct fb_fix_screeninfo finfo;
if (ioctl(fd, FBIOGET_FSCREENINFO,&finfo) == -1) //固定屏幕信息
return -errno;
struct fb_var_screeninfo info;
if (ioctl(fd, FBIOGET_VSCREENINFO,&info) == -1) //变化屏幕信息
return -errno;
info.reserved[0]= 0;
info.reserved[1]= 0;
info.reserved[2]= 0;
info.xoffset = 0;
info.yoffset = 0;
info.activate = FB_ACTIVATE_NOW;
#if defined(NO_32BPP)
/*
* Explicitly request 5/6/5
*/
info.bits_per_pixel = 16; //RGB565的颜色空间
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;
#endif
/*
* Request NUM_BUFFERS screens (at lest 2 for page flipping)
*/
info.yres_virtual = info.yres * NUM_BUFFERS; //NUM_BUFFERS =2
uint32_t flags = PAGE_FLIP;
if (ioctl(fd, FBIOPUT_VSCREENINFO,&info) == -1){ //重新设置变化屏幕信息
info.yres_virtual = info.yres;
flags &=~PAGE_FLIP;
LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported");
}
if (info.yres_virtual< info.yres* 2) { //虚拟缓冲区尺寸小于实际缓冲区2倍的情况
// we need at least 2 for page-flipping
info.yres_virtual = info.yres;
flags &=~PAGE_FLIP;
LOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
info.yres_virtual, info.yres*2);
}
if (ioctl(fd, FBIOGET_VSCREENINFO,&info) == -1) //重新获取变化屏幕信息
return -errno;
uint64_t refreshQuotient =
(
uint64_t( info.upper_margin+ info.lower_margin+ info.yres)
* ( info.left_margin + info.right_margin + info.xres )
* info.pixclock
);
/* Beware, info.pixclock might be 0 under emulation, so avoid a
* division-by-0 here (SIGFPE on ARM) */
int refreshRate = refreshQuotient > 0 ? (int)(1000000000000000LLU/ refreshQuotient): 0;
if (refreshRate== 0){
// bleagh, bad info from the driver
refreshRate = 60*1000;// 60 Hz //刷新率为60Hz
}
if (int(info.width)<= 0 || int(info.height)<= 0){
// the driver doesn't return that information
// default to 160 dpi
info.width = ((info.xres* 25.4f)/160.0f+ 0.5f); //默认dpi为160,大屏可以设为250
info.height = ((info.yres* 25.4f)/160.0f+ 0.5f); //dpi ---单位面积的像素数目
}
float xdpi = (info.xres* 25.4f)/ info.width; //获得X,Y的dpi
float ydpi = (info.yres* 25.4f)/ info.height;
float fps = refreshRate / 1000.0f;
LOGI( "using (fd=%d)\n"
"id = %s\n"
"xres = %d px\n"
"yres = %d px\n"
"xres_virtual = %d px\n"
"yres_virtual = %d px\n"
"bpp = %d\n"
"r = %2u:%u\n"
"g = %2u:%u\n"
"b = %2u:%u\n",
fd,
finfo.id,
info.xres,
info.yres,
info.xres_virtual,
info.yres_virtual,
info.bits_per_pixel, //bpp---像素深度
info.red.offset, info.red.length,
info.green.offset, info.green.length,
info.blue.offset, info.blue.length
);
LOGI( "width = %d mm (%f dpi)\n"
"height = %d mm (%f dpi)\n"
"refresh rate = %.2f Hz\n",
info.width, xdpi,
info.height, ydpi,
fps
);
if (ioctl(fd, FBIOGET_FSCREENINFO,&finfo) == -1)
return -errno;
if (finfo.smem_len<= 0)
return -errno;
module->flags= flags; //设置模块内容
module->info= info;
module->finfo= finfo;
module->xdpi= xdpi;
module->ydpi= ydpi;
module->fps= fps;
/*
* map the framebuffer
*/
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; //数值一般为2
module->bufferMask= 0;
//进行从设备的内存映射
void* vaddr= mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (vaddr== MAP_FAILED){
LOGE("Error mapping the framebuffer (%s)", strerror(errno));
return -errno;
}
module->framebuffer->base= intptr_t(vaddr);
memset(vaddr, 0, fbSize);
return 0;
}
fb_device_open()基本上是对framebuffer驱动程序的标准操作。
使用RGB565的颜色空间,至少需要虚拟缓冲区是实际缓冲区的2倍(主要是指y方向2倍)。
刷新率和DPI(单位面积的像素数目)是android系统的一个可选参数。
3. fb_post()是framebuffer_device_t 设备实现的一个重点,表示将某个缓冲区Buffer显示在屏幕上。
static int fb_post(struct framebuffer_device_t* dev, buffer_handle_tbuffer)
{
if (private_handle_t::validate(buffer)< 0)
return -EINVAL;
fb_context_t* ctx = (fb_context_t*)dev;
private_handle_t const* hnd= reinterpret_cast<private_handle_tconst*>(buffer);
private_module_t* m = reinterpret_cast<private_module_t*>(
dev->common.module);
if (hnd->flags& private_handle_t::PRIV_FLAGS_FRAMEBUFFER){
const size_t offset = hnd->base- m->framebuffer->base;
m->info.activate= FB_ACTIVATE_VBL;
m->info.yoffset= offset / m->finfo.line_length; //设置变化屏幕信息
if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info)== -1) {
LOGE("FBIOPUT_VSCREENINFO failed");
m->base.unlock(&m->base,buffer); //解锁缓冲区
return -errno;
}
m->currentBuffer= buffer;
} else{
// If we can't do the page_flip, just copy the buffer to the front
// FIXME: use copybit HAL instead of memcpy
void* fb_vaddr;
void* buffer_vaddr;
//对内存区域进行操作,锁定-->复制-->解锁
m->base.lock(&m->base, m->framebuffer,
GRALLOC_USAGE_SW_WRITE_RARELY,
0, 0, m->info.xres, m->info.yres,
&fb_vaddr);
m->base.lock(&m->base,buffer,
GRALLOC_USAGE_SW_READ_RARELY,
0, 0, m->info.xres, m->info.yres,
&buffer_vaddr);
memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length* m->info.yres);
m->base.unlock(&m->base,buffer);
m->base.unlock(&m->base, m->framebuffer);
}
return 0;
}
屏幕上实际上需要显示系统通过硬件DMA读取的显示缓冲区数据,而在程序中需要写显示缓冲区的数据。
为了避免这两个步骤同时进行,Gralloc处理的方式就是,锁定一个,写内容,解锁它。在锁定期间显示缓冲区不能被硬件DMA获取。
4. alloc_device_t 部分:
gralloc.cpp 中实现 alloc_device_t 设备的几个部分:alloc, free, close 等函数指针。
static int gralloc_alloc(alloc_device_t* dev,
int w,int h, int format, int usage,
buffer_handle_t* pHandle,int* pStride)
{
if (!pHandle|| !pStride)
return -EINVAL;
size_t size, stride;
int align = 4;
int bpp = 0;
switch (format){ //颜色空间的处理,不同颜色空间决定每像素字节(bpp)。
case HAL_PIXEL_FORMAT_RGBA_8888: //每像素4字节
case HAL_PIXEL_FORMAT_RGBX_8888:
case HAL_PIXEL_FORMAT_BGRA_8888:
bpp = 4;
break;
case HAL_PIXEL_FORMAT_RGB_888: //每像素3字节
bpp = 3;
break;
case HAL_PIXEL_FORMAT_RGB_565:
case HAL_PIXEL_FORMAT_RGBA_5551:
case HAL_PIXEL_FORMAT_RGBA_4444:
bpp = 2; //每像素2字节
break;
default:
return -EINVAL;
}
size_t bpr = (w*bpp +(align-1))& ~(align-1); //根据行情况进行对齐处理
size = bpr* h;
stride = bpr / bpp; //没行的像素个数,即跨度stride
int err;
if (usage& GRALLOC_USAGE_HW_FB){
err = gralloc_alloc_framebuffer(dev,size, usage, pHandle); //调用了framebuffer.cpp中的mapFrameBuffer().
} else{
err = gralloc_alloc_buffer(dev,size, usage, pHandle); //调用了ashmem_create_region(),使用ashmem(匿名共享内存)分配了名称为"gralloc-buffer"的内存,这是一个纯软件的实现
}
if (err< 0) {
return err;
}
*pStride = stride;
return 0;
}