SurfaceFlinger启动过程分析(三)

转载时请注明出处和作者
文章出处:http://danielwood.cublog.cn
作者:Daniel Wood
------------------------------------------------------------
内存映射对于framebuffer来说非常重要,因为通常用户是不能直接操作物理地址空间的(也就是物理内存?),然而通过mmap映射之后,将framebuffer的物理地址空间映射到用户空间的一段虚拟地址中,用户就可以通过操作这段虚拟内存而间接操作framebuffer了,你在那段虚拟内存中画了图,相应的图就会显示到屏幕上。
——这段是自己的理解,有错必究!
下面是framebuffer.cpp中的 mapFrameBufferLocked函数。

intmapFrameBufferLocked(structprivate_module_t*module)
{
// already initialized...
if(module->framebuffer){
return0;
}
charconst*constdevice_template[]={
"/dev/graphics/fb%u",
"/dev/fb%u",
0};

intfd=-1;
inti=0;
charname[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;

structfb_fix_screeninfo finfo;
if(ioctl(fd,FBIOGET_FSCREENINFO,&finfo)==-1)
return-errno;
structfb_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;
/*
* Explicitly request 5/6/5
*/

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;

/*
* Request NUM_BUFFERS screens (at lest 2 for page flipping)
*/

info.yres_virtual=info.yres*NUM_BUFFERS;
uint32_tflags=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){
// 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;
intrefreshRate=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
}
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);
info.height=((info.yres*25.4f)/160.0f+0.5f);
}
floatxdpi=(info.xres*25.4f)/info.width;
floatydpi=(info.yres*25.4f)/info.height;
floatfps=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,
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
*/

interr;
size_tfbSize=
roundUpToPageSize(finfo.line_length*info.yres_virtual);//对齐页
module->framebuffer=newprivate_handle_t(dup(fd),fbSize,0);

module->numBuffers=info.yres_virtual/info.yres;
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);
return0;
}

这个函数就是和驱动相关的调用,其实结合驱动去看代码是很有意思的,把一路都打通了。
该函数首先通过open函数打开设备结点。
"/dev/graphics/fb%u"和"/dev/fb%u",如果前一个顺利打开的话,那么就不打开第二个。我的Log显示打开的是第一个设备结点 /dev/graphics/fb%u。
然后通过ioctl读取设备的固定参数( FBIOGET_FSCREENINFO )和可变参数(FBIOGET_VSCREENINFO)。
【kernel部分的代码在drivers\video\fbmem.c中。】
然后对可变参数进行修改,通过ioctl设置(FBIOPUT_VSCREENINFO)显示屏的可变参数。
设置好以后再ioctl- FBIOGET_VSCREENINFO获得可变参数,然后在log上打出显示屏的各个参数设置,也就是我们开机看到的一长串log。

I/gralloc(1620):using(fd=8)
I/gralloc(1620):id=truly-ILI9327
I/gralloc(1620):xres=240 px
I/gralloc(1620):yres=400 px
I/gralloc(1620):xres_virtual=240 px
I/gralloc(1620):yres_virtual=800 px
I/gralloc(1620):bpp=16
I/gralloc(1620):r=11:5
I/gralloc(1620):g=5:6
I/gralloc(1620):b=0:5
I/gralloc(1620):width=38 mm(160.421051 dpi)
I/gralloc(1620):height=64 mm(158.750000 dpi)
I/gralloc(1620):refresh rate=60.00 Hz

然后通过mmap完成对显示缓存区的映射。这样 mapFrameBufferLocked函数的任务算是完成了。
好了,以上所讲的只是(1)中的第一句话而已
Displayhardware.cpp中的init函数。

mNativeWindow=newFramebufferNativeWindow();

下面贴张图,直观一点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值