您的位置:首页 > 移动开发 > Android开发

Android: 显示系统模块加载以及调用流程 HWComposer::loadFbHalModule() -> framebuffer_open()

2016-11-28 21:47 1511 查看
http://blog.csdn.net/hongzg1982/article/details/49681705

打开/dev/graphics/fb0节点的过程:

打开/dev/graphics/fb0这个设备的调用过程如下:

1.在HWComposer中,加载module

HWComposer::HWComposer(
const sp<SurfaceFlinger>& flinger,
EventHandler& handler)
{
...
// Note: some devices may insist that the FB HAL be opened before HWC.
int fberr = loadFbHalModule();
loadHwcModule();
...
}

1)loadFbHalModule()直接从下面的路径打开fb,初始化并保存framebuffer_device_t类型成员变量mFbDev。

gralloc_device_open()->fb_device_open()->mapFrameBuffer() -> mapFrameBufferLocked()

加载module和调用open函数过程如下

这里gralloc_device_open定义在HAL层定义的:

//gralloc.cpp文件中
static struct hw_module_methods_t gralloc_module_methods = {
.open = gralloc_device_open
};
struct private_module_t HAL_MODULE_INFO_SYM = {
.base = {
.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,
.unregisterBuffer = gralloc_unregister_buffer,
.lock = gralloc_lock,
.unlock = gralloc_unlock,
},
.framebuffer = 0,
.flags = 0,
.numBuffers = 0,
.bufferMask = 0,
.lock = PTHREAD_MUTEX_INITIALIZER,
.currentBuffer = 0,
};

这个Module会在HWComposer::loadFbHalModule()中被加载,调用对应的open函数。

看以下代码注释

int HWComposer::loadFbHalModule()
{
hw_module_t const* module;
//根据GRALLOC_HARDWARE_MODULE_ID这个值,加载对应的module代码,也就是上面说的内容
int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
if (err != 0) {
ALOGE("%s module not found", GRALLOC_HARDWARE_MODULE_ID);
return err;
}
return framebuffer_open(module, &mFbDev);
}

//这里methods->open当然就是调用上面module的open函数,也就是gralloc_device_open()
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_HARDWARE_FB0,所以会跑到fb_device_open中
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)) {
const private_module_t* m = reinterpret_cast<const private_module_t*>(
module);
gpu_context_t *dev;
IAllocController* alloc_ctrl = IAllocController::getInstance();
dev = new gpu_context_t(m, alloc_ctrl);
if(!dev)
return status;

*device = &dev->common;
status = 0;
} else {
status = fb_device_open(module, name, device);
}
return status;
}

//由于name是GRALLOC_HARDWARE_FB0,会跑到if语句里进行初始化工作,包括打开/dev/graphics/fb0等
int fb_device_open(hw_module_t const* module, const char* 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));
if(dev == NULL) {
gralloc_close(gralloc_device);
return status;
}
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;
dev->device.compositionComplete = fb_compositionComplete;

status = mapFrameBuffer((framebuffer_device_t*)dev);
private_module_t* m = (private_module_t*)dev->device.common.module;
if (status >= 0) {
int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
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) = m->fbFormat;
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) =
PRIV_MIN_SWAP_INTERVAL;
const_cast<int&>(dev->device.maxSwapInterval) =
PRIV_MAX_SWAP_INTERVAL;
const_cast<int&>(dev->device.numFramebuffers) = m->numBuffers;
dev->device.setUpdateRect = 0;

*device = &dev->device.common;
}

// Close the gralloc module
gralloc_close(gralloc_device);
}
return status;
}

2)loadHwcModule()函数通过以下路径打开fb,初始化并保存hwc_composer_device_1_t类型的成员变量mHwc。

HWComposer::loadHwcModule()->hw_get_module(HWC_HARDWARE_MODULE_ID, &module)
然后在调用hwc_open_1(module, &mHwc)->hwc_device_open()->initContext()->
CopyBit::CopyBit()[hwc_copybit.cpp]->hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module)
->open_copybit()->open("/dev/graphics/fb0", O_RDWR, 0);

这里的module加载以及调用open函数的过程基本和上面的一样,不多说了。

到此可以知道framework层是怎么打开的/dev/graphics/fb0节点,以待后续进行处理的!!

操作/dev/graphics/fb0节点的过程:

在SurfaceFlinger中最后进行数据刷新的函数,我们知道是postFrameBuffer()函数。定义如下:

void SurfaceFlinger::postFramebuffer()
{
ATRACE_CALL();

#ifdef PRODUCT_DEV
if (CC_UNLIKELY(mDebugFps)) {
debugShowFPS();
}
/*
if(CC_UNLIKELY(ATRACE_ENABLED())){
debugShowGPUInfoToSysTrace();
}*/
#endif

const nsecs_t now = systemTime();
mDebugInSwapBuffers = now;

HWComposer& hwc(getHwComposer());
if (hwc.initCheck() == NO_ERROR) {
if (!hwc.supportsFramebufferTarget()) {
getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
}
//这个函数当然就是调用HWComposer::commit()函数,,不言而喻~
hwc.commit();
}
...
}

status_t HWComposer::commit() {
int err = NO_ERROR;
if (mHwc) {
...
for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) {
DisplayData& disp(mDisplayData[i]);
if (disp.outbufHandle) {
mLists[i]->outbuf = disp.outbufHandle;
mLists[i]->outbufAcquireFenceFd =
disp.outbufAcquireFence->dup();
}
}
//这里的mHwc是加载了/hardware/qcom/display/libhwcomposer/Hwc.cpp的内容的
//理由吗,,和上面说的一样,根据id来选择module加载~
//所以set函数就是需要在Hwc.cpp文件中寻找了~
//这里mLists是hwc_display_contents_1_t类型,包含要画的buffer[]
//而mLists是HWComposer::prepare()函数中,从
//DisplayData& disp(mDisplayData[i]);
//mLists[i] = disp.list
//这样取出来的!!
//SurfaceFlinger怎么把内容赋给mDisplayData的,需要后面分析
err = mHwc->set(mHwc, mNumDisplays, mLists);
....
}
return (status_t)err;
}

//hwc_display_contents_1_t这个结构体包含要画的buffer内容,以及fense等成员的
//需要后面仔细看看每个成员表示什么
static int hwc_set(hwc_composer_device_1 *dev,
size_t numDisplays,
hwc_display_contents_1_t** displays)
{
int ret = 0;
hwc_context_t* ctx = (hwc_context_t*)(dev);
for (int dpy = 0; dpy < (int)numDisplays; dpy++) {
hwc_display_contents_1_t* list = displays[dpy];
switch(dpy) {
case HWC_DISPLAY_PRIMARY:
//这个就是主屏!!!看hwc_set_primary()函数
ret = hwc_set_primary(ctx, list);
break;
case HWC_DISPLAY_EXTERNAL:
ret = hwc_set_external(ctx, list);
break;
case HWC_DISPLAY_VIRTUAL:
if(ctx->mHWCVirtual)
ret = ctx->mHWCVirtual->set(ctx, list);
break;
default:
ret = -EINVAL;
}
}

return ret;
}

static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
ATRACE_CALL();
int ret = 0;
const int dpy = HWC_DISPLAY_PRIMARY;
if (LIKELY(list) && ctx->dpyAttr[dpy].isActive
&& !ctx->dpyAttr[dpy].isPause) {
...
//利用copybit或者mdp,每个layer都有几个flags来标记用哪个去画
//以做过的一个平台为例,有以下两种方式
//// LayerProp::flag values
/* enum {
HWC_MDPCOMP = 0x00000001,
HWC_COPYBIT = 0x00000002,
};
*/
if (ctx->mCopyBit[dpy]) {
if (ctx->mMDP.version < qdutils::MDP_V4_0)
copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
else
fd = ctx->mMDPComp[dpy]->drawOverlap(ctx, list);
}
...
if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
ALOGE("%s: MDPComp draw failed", __FUNCTION__);
ret = -1;
}
...
if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd, lRoi, rRoi)) {
ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
ret = -1;
}
...
}
}



在加载完fb相关的module之后,SurfaceFlinger就可以通过HWC把Layer画上去。流程如下:

SurfaceFlinger creates a list of layers and sends them to the HWC in the

prepare phase (hwc_prepare).
HWC sets the compositionType for those layers to be composed by

SurfaceFlinger as HWC_FRAMEBUFFER.
All layers marked as HWC_FRAMEBUFFER and layers whose flag is set

as HWC_SKIP are drawn by SurfaceFlinger.
SurfaceFlinger sends the layer list back to HWC after composing in

Framebuffer.
HWC draws the layers marked for copybit (HWC_COPYBIT) using the

copybit HAL respectively. This is the path taken if MDP composition is set.
The MDP composition mode in the MSM8x25 makes use of the copybit

HAL, which in turn uses the MDP IOCTLs to fill the framebuffer.
HWC invokes eglSwapBuffers.
到这里就可以知道怎么加载的模块,也看了SurfaceFlinger通过HWComposer和HWC.cpp模块的内容进行显示数据的刷写的过程。接下来看一下SurfaceFlinger,,
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐