SurfaceFlinger启动过程分析(二)

转载时请注明出处和作者
文章出处:http://danielwood.cublog.cn
作者:Daniel Wood
------------------------------------------------------------
上节说到SurfaceFlinger的 readyToRun函数。先来看看它的代码:
Google Android 2.2
SurfaceFlinger.cpp

status_t SurfaceFlinger::readyToRun()
{
LOGI("SurfaceFlinger's main thread ready to run. "
"Initializing graphics H/W...");
// we only support one display currently
intdpy=0;
{
// initialize the main display
GraphicPlane&plane(graphicPlane(dpy));
DisplayHardware* const hw = new DisplayHardware(this, dpy);
plane.setDisplayHardware(hw);
}
// create the shared control-block
mServerHeap=newMemoryHeapBase(4096,
MemoryHeapBase::READ_ONLY,"SurfaceFlinger read-only heap");
LOGE_IF(mServerHeap==0,"can't create shared memory dealer");

mServerCblk=static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase());
LOGE_IF(mServerCblk==0,"can't get to shared control block's address");
new(mServerCblk)surface_flinger_cblk_t;
// initialize primary screen
// (other display should be initialized in the same manner, but
// asynchronously, as they could come and go. None of this is supported
// yet).
constGraphicPlane&plane(graphicPlane(dpy));
constDisplayHardware&hw=plane.displayHardware();
constuint32_tw=hw.getWidth();
constuint32_th=hw.getHeight();
constuint32_tf=hw.getFormat();
hw.makeCurrent();
// initialize the shared control block

mServerCblk->connected|=1<<dpy;
display_cblk_t*dcblk=mServerCblk->displays+dpy;
memset(dcblk,0,sizeof(display_cblk_t));
dcblk->w=plane.getWidth();
dcblk->h=plane.getHeight();
dcblk->format=f;
dcblk->orientation=ISurfaceComposer::eOrientationDefault;
dcblk->xdpi=hw.getDpiX();
dcblk->ydpi=hw.getDpiY();
dcblk->fps=hw.getRefreshRate();
dcblk->density=hw.getDensity();
asmvolatile("":::"memory");
// Initialize OpenGL|ES

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,0);
glTexParameterx(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameterx(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glTexParameterx(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameterx(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexEnvx(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
glPixelStorei(GL_UNPACK_ALIGNMENT,4);
glPixelStorei(GL_PACK_ALIGNMENT,4);
glEnableClientState(GL_VERTEX_ARRAY);
glEnable(GL_SCISSOR_TEST);
glShadeModel(GL_FLAT);
glDisable(GL_DITHER);
glDisable(GL_CULL_FACE);

constuint16_tg0=pack565(0x0F,0x1F,0x0F);
constuint16_tg1=pack565(0x17,0x2f,0x17);
constuint16_ttextureData[4]={g0,g1,g1,g0};
glGenTextures(1,&mWormholeTexName);
glBindTexture(GL_TEXTURE_2D,mWormholeTexName);
glTexParameterx(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameterx(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameterx(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameterx(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,2,2,0,
GL_RGB,GL_UNSIGNED_SHORT_5_6_5,textureData);
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(0,w,h,0,0,1);
LayerDim::initDimmer(this,w,h);
mReadyToRunBarrier.open();
/*
* We're now ready to accept clients...
*/

// start boot animation
property_set("ctl.start","bootanim");
returnNO_ERROR;
}

调用readyToRun函数用于初始化整个显示系统。

readyToRun()调用过程如下[这部分摘自网上资料]:

1)执行new DisplayHardware(this,dpy),通过DisplayHardware初始化FramebufferEGL并获取OpenGL ES信息。

2)创建共享的内存控制块。

3)将EGL与当前屏幕绑定。

4)初始化共享内存控制块。

5)初始化OpenGL ES

6)显示开机动画。

上面的六点作为阅读代码的提纲及参考,下面对照代码进行分析:

(1)创建一个DisplayHardware,通过它的init函数去初始化FramebufferEGL并获取OpenGL ES信息。

DisplayHardware.cpp[frameworks\base\libs\surfaceflinger\displayhardware]

DisplayHardware::DisplayHardware(
constsp<SurfaceFlinger>&flinger,
uint32_tdpy)
:DisplayHardwareBase(flinger,dpy)
{
init(dpy);
}


init函数的代码狠长,我们一块一块,一句一句地分析:

voidDisplayHardware::init(uint32_tdpy)
{
mNativeWindow=newFramebufferNativeWindow();

...


首先亮相的是第一句(如上),new一个FramebufferNativeWindow。
FramebufferNativeWindow构造函数的代码也不少,我们去掉一些次要的代码,挑重要的关键的说:

FramebufferNativeWindow::FramebufferNativeWindow()
:BASE(),fbDev(0),grDev(0),mUpdateOnDemand(false)
{
hw_module_tconst*module;
if(hw_get_module(GRALLOC_HARDWARE_MODULE_ID,&module)==0){
intstride;
interr;
err=framebuffer_open(module,&fbDev);
LOGE_IF(err,"couldn't open framebuffer HAL (%s)",strerror(-err));

err=gralloc_open(module,&grDev);
LOGE_IF(err,"couldn't open gralloc HAL (%s)",strerror(-err));
// bail out if we can't initialize the modules
if(!fbDev||!grDev)
return;
mUpdateOnDemand=(fbDev->setUpdateRect!=0);
// initialize the buffer FIFO
mNumBuffers=2;
mNumFreeBuffers=2;
mBufferHead=mNumBuffers-1;
buffers[0]=newNativeBuffer(
fbDev->width,fbDev->height,fbDev->format,GRALLOC_USAGE_HW_FB);
buffers[1]=newNativeBuffer(
fbDev->width,fbDev->height,fbDev->format,GRALLOC_USAGE_HW_FB);


err=grDev->alloc(grDev,
fbDev->width,fbDev->height,fbDev->format,
GRALLOC_USAGE_HW_FB,&buffers[0]->handle,&buffers[0]->stride);
LOGE_IF(err,"fb buffer 0 allocation failed w=%d, h=%d, err=%s",fbDev->width,fbDev->height,strerror(-err));

err=grDev->alloc(grDev,
fbDev->width,fbDev->height,fbDev->format,
GRALLOC_USAGE_HW_FB,&buffers[1]->handle,&buffers[1]->stride);

LOGE_IF(err,"fb buffer 1 allocation failed w=%d, h=%d, err=%s",fbDev->width,fbDev->height,strerror(-err));
...
}else{
LOGE("Couldn't get gralloc module");
}

...

}


关键的代码都被我高亮了,从最后一行的else的LOGE中可以看出这里主要是获得gralloc这个模块。模块ID定义在:gralloc.h[hardware\libhardware\include\hardware]

#defineGRALLOC_HARDWARE_MODULE_ID"gralloc"


ps:有时候代码中的log狠有用,可以帮助我们读懂代码,而且logcat也是我们调试代码的好东西。
首先打开framebuffer和gralloc这两个模块
framebuffer_opengralloc_open这两个接口在gralloc.h里面定义

staticinlineintframebuffer_open(conststructhw_module_t*module,
structframebuffer_device_t**device){
returnmodule->methods->open(module,
GRALLOC_HARDWARE_FB0,(structhw_device_t**)device);
}
staticinlineintgralloc_open(conststructhw_module_t*module,
structalloc_device_t**device){
returnmodule->methods->open(module,
GRALLOC_HARDWARE_GPU0,(structhw_device_t**)device);
}


两者指定的是gralloc.cpp中同一个函数gralloc_device_open,但是用的是不同的设备名,函数名和设备名分别在gralloc.cpp和gralloc.h中定义。

gralloc.h[hardware\libhardware\include\hardware]

#defineGRALLOC_HARDWARE_FB0"fb0"
#defineGRALLOC_HARDWARE_GPU0"gpu0"

gralloc.cpp[hardware\libhardware\modules\gralloc]
staticstructhw_module_methods_t gralloc_module_methods={
open:gralloc_device_open
};


gralloc.cpp [hardware\libhardware\modules\gralloc]

intgralloc_device_open(consthw_module_t*module,constchar*name,
hw_device_t**device)
{
intstatus=-EINVAL;
if(!strcmp(name,GRALLOC_HARDWARE_GPU0)){
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;
dev->device.free=gralloc_free;
*device=&dev->device.common;
status=0;
}else{
status=fb_device_open(module,name,device);
}
returnstatus;
}


gralloc_device_open函数通过设备名字来进行相关的初始化工作。打开framebuffer则调用fb_device_open函数。fb_device_open函数定义在framebuffer.cpp中。

intfb_device_open(hw_module_tconst*module,constchar*name,
hw_device_t**device)
{
intstatus=-EINVAL;
if(!strcmp(name,GRALLOC_HARDWARE_FB0)){
alloc_device_t*gralloc_device;
status=gralloc_open(module,&gralloc_device);
if(status<0)
returnstatus;
/* 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);
if(status>=0){
...
*device=&dev->device.common;
}
}
returnstatus;
}

fb_device_open函数是framebuffer.cpp里面的函数它会再次调用gralloc_open函数,调用gralloc_open并没有什么实际的用途,只是检测模块的正确性,感觉这句话没有必要,还是我哪里理解错了???因为gralloc_device这个变量在后面都没有用到啊。

哈哈,经过测试,把以下几句注释掉,然后make,烧到手机上,手机基本功能仍旧正常,看来这几句代码狠有可能是没有什么特别用处的。

alloc_device_t*gralloc_device;
status=gralloc_open(module,&gralloc_device);
if(status<0)
returnstatus;

然后调用mapFrameBuffer函数,就是将显示缓冲区映射到用户空间,这样在用户空间就可以直接对显示缓冲区进行读写操作。mapFrameBuffer函数的主体功能是在mapFrameBufferLocked函数里面完成的。

关于mapFrameBuffer函数,在下节讲解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值