Framebuffer.cpp就是以前的EGLdisplaysurface.cpp改进版
1、int fb_device_open(hw_module_t const* module, const char* name,
hw_device_t** device)
1)gralloc_open(module, &gralloc_device);
2)初始化fb_context_t(该结构继承framebuffer_device_t)
主要填充parent hw_device_t内容和两个重要函数
dev->device.setSwapInterval = fb_setSwapInterval;
dev->device.post = fb_post;
3)mapFrameBuffer(m);-->mapFrameBufferLocked(module);
4)填充parent framebuffer_device_t结构体
2、int mapFrameBufferLocked(struct private_module_t* module)
1)打开framebuffer设备
2)get fb_fix_screeninfo and fb_var_screeninfo
3)refill fb_var_screeninfo
4)判断是否支持PAGE_FLIP
5)计算刷新率
6)打印gralloc信息
7)填充private_module_t
8)mmap the framebuffer
3、static int fb_setSwapInterval(struct framebuffer_device_t* dev,
int interval)
这个函数完全没用嘛,因为minSwapInterval=maxSwapInterval=1
4、static int fb_setUpdateRect(struct framebuffer_device_t* dev,
int l, int t, int w, int h)
局部刷新,默认不启用,MSM7K貌似启用了
5、static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
最关键的函数
1)检查buffer是否合法
2)进行相应的类型转换
3)如果currentbuffer非空,unlokc
4-1)如果支持PAGE_FLIP
lock
ioctl
unlock
currentbuffer=buffer
重点看lock函数
m->base.lock(&m->base, buffer,
private_module_t::PRIV_USAGE_LOCKED_FOR_POST,
0, 0, m->info.xres, m->info.yres, NULL);
看参数,是没有vaddr的,lock时也不需要mmap操作。
4-2)如果不支持PAGE_FLIP
lock for read
lock for wrtie
memcpy
unlock
unlock
继续看其中一个lock
m->base.lock(&m->base, m->framebuffer,
GRALLOC_USAGE_SW_WRITE_RARELY,
0, 0, m->info.xres, m->info.yres,
&fb_vaddr);
看,usage被置位,有vaddr,需要进行mmap操作。
6、最后一个环节继续是喜闻乐见的高通干了啥节目
1)open中启用了局部刷新,不过也需要上层支持的
if (m->finfo.reserved[0] == 0x5444 &&
m->finfo.reserved[1] == 0x5055) {
dev->device.setUpdateRect = fb_setUpdateRect;
LOGD("UPDATE_ON_DEMAND supported");
}
2)貌似高通的MSM7K不支持PAGE_FLIP,但他绝不会傻到用memcpy来做,所以给个这个函数
/* Copy a pmem buffer to the framebuffer */
static void
msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height,
int x, int y, int w, int h)
{
struct {
unsigned int count;
mdp_blit_req req;
} blit;
private_handle_t *priv = (private_handle_t*) handle;
memset(&blit, 0, sizeof(blit));
blit.count = 1;
blit.req.flags = 0;
blit.req.alpha = 0xff;
blit.req.transp_mask = 0xffffffff;
blit.req.src.width = width;
blit.req.src.height = height;
blit.req.src.offset = 0;
blit.req.src.memory_id = priv->fd;
blit.req.dst.width = width;
blit.req.dst.height = height;
blit.req.dst.offset = 0;
blit.req.dst.memory_id = fd;
blit.req.dst.format = MDP_RGB_565;
blit.req.src_rect.x = blit.req.dst_rect.x = x;
blit.req.src_rect.y = blit.req.dst_rect.y = y;
blit.req.src_rect.w = blit.req.dst_rect.w = w;
blit.req.src_rect.h = blit.req.dst_rect.h = h;
if (ioctl(fd, MSMFB_BLIT, &blit))
LOGE("MSMFB_BLIT failed = %d", -errno);
}
调用方法
//memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres);
msm_copy_buffer(m->framebuffer, m->framebuffer->fd,
m->info.xres, m->info.yres,
m->info.xoffset, m->info.yoffset,
m->info.width, m->info.height);
说明:
1)看注释是用了PMEM,还么看到在哪申请的PMEM
2)看传参完全没有使用mmap获取的vaddr,而是将fd传入驱动,具体如何获取物理addr要仔细看msm的驱动(useful,高通真好)