1. 程式人生 > >Android: 顯示系統模組載入以及呼叫流程 HWComposer::loadFbHalModule() -> framebuffer_open()

Android: 顯示系統模組載入以及呼叫流程 HWComposer::loadFbHalModule() -> framebuffer_open()

開啟/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,,