Android: 顯示系統模組載入以及呼叫流程 HWComposer::loadFbHalModule() -> framebuffer_open()
阿新 • • 發佈:2019-02-19
開啟/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,,