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


  • 相关阅读:
    C++ 获取图片文件信息
    java中redis的分布式锁工具类
    java中的redis工具类
    mysql中的sql查询优化
    利用Linux中的crontab实现分布式项目定时任务
    MYSQL的REPLACE和ON DUPLICATE KEY UPDATE使用
    redis学习三,Redis主从复制和哨兵模式
    redis学习五,redis集群搭建及添加主从节点
    String 转化成java.sql.Date和java.sql.Time
    SpringMVC配置双数据源,一个java项目同时连接两个数据库
  • 原文地址:https://www.cnblogs.com/ztguang/p/12645189.html
Copyright © 2020-2023  润新知