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


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,,


原文地址:https://www.cnblogs.com/ztguang/p/12645189.html