HWComper介绍

HWComposer介绍

HWComposer类的作用:
1:打开了Gralloc模块FB设备,负责将图像缓冲区的内容渲染到FB显示缓冲区
Gralloc模块可以打开两种设备,一种负责分配图形缓冲区,另一种打开FB设备,负责渲染FB缓冲区。
2:负责管理硬件HWComposer设备
HWC(hwcomposer)是Android中进行窗口(Layer)合成和显示的HAL层模块,其实现是特定于设备的,而且通常由显示设备制造商 (OEM)完成,为SurfaceFlinger服务提供硬件支持。
SurfaceFlinger可以使用OpenGL ES合成Layer,这需要占用并消耗GPU资源。大多数GPU都没有针对图层合成进行优化,当SurfaceFlinger通过GPU合成图层时,应用程序无法使用GPU进行自己的渲染。而HWC通过硬件设备进行图层合成,可以减轻GPU的合成压力。
3:硬件HWComposer负责产生硬件VSync信号
HWC也提供了VSync事件,用于管理渲染和图层合成时机。

HWComposer初始化过程

在SurfaceFlinger的init方法中会初始化HWComposer对象

    // Initialize the H/W composer object.  There may or may not be an
    // actual hardware composer underneath.
    mHwc = new HWComposer(this,
            *static_cast(this));

init方法中直接创建了一个HWComposer对象,保存在SurfaceFlinger中。


HWComposer::HWComposer(
        const sp& flinger,
        EventHandler& handler)
    : mFlinger(flinger),
      mFbDev(0), mHwc(0), mNumDisplays(1),
      mCBContext(new cb_context),
      mEventHandler(handler),
      mDebugForceFakeVSync(false)
{
    ......

    bool needVSyncThread = true;

    // 加载Gralloc HAL模块,并打开FB设备,保存在mFbDev中
    int fberr = loadFbHalModule();、
    // 加载HWComposer HAL模块,并打开HWC设备,保存在mHWC中
    loadHwcModule();

    ......

    // 保留前三个设备ID
    for (size_t i=0 ; iregisterProcs) {
            mCBContext->hwc = this;
            //注册HWC硬件强制刷新的回调函数
            mCBContext->procs.invalidate = &hook_invalidate;
            //注册硬件Vsync回调函数
            mCBContext->procs.vsync = &hook_vsync;
            //注册热插拔回调函数
            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
                mCBContext->procs.hotplug = &hook_hotplug;
            else
                mCBContext->procs.hotplug = NULL;
            memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
            mHwc->registerProcs(mHwc, &mCBContext->procs);
        }

        // 是否需要软件模拟VSYNC信号
        needVSyncThread = false;
        // 硬件HWC VSYNC 开始的时候默认关闭
        eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);

        //根据HWC的版本好,决定支持显示设备的数量
        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
            // 1.3 adds support for virtual displays
            mNumDisplays = MAX_HWC_DISPLAYS;
        } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
            // 1.1 adds support for multiple displays
            mNumDisplays = NUM_BUILTIN_DISPLAYS;
        } else {
            mNumDisplays = 1;
        }
    }

    //如果FB设备打开成功,则获取FB显示设备的基本信息,保存在对应的DisplayData对象中.
    if (mFbDev) {
        DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);
        disp.connected = true;
        disp.format = mFbDev->format;
        DisplayConfig config = DisplayConfig();
        config.width = mFbDev->width;
        config.height = mFbDev->height;
        config.xdpi = mFbDev->xdpi;
        config.ydpi = mFbDev->ydpi;
        config.refresh = nsecs_t(1e9 / mFbDev->fps);
        disp.configs.push_back(config);
        disp.currentConfig = 0;
    } else if (mHwc) {
        // here we're guaranteed to have at least HWC 1.1
        for (size_t i =0 ; i

HWComposer的初始化函数做了那些内容?
1:加载Gralloc模块,打开FB设备,用于渲染显示缓冲区
2:加载HWC HAL模块,打开HWC设备,用于硬件合成Layer及产生Vsync信号
3:注册HWC Vsync, 热插拔,强制刷新的回调函数
4:获取FB显示驱动相关的参数,存放到DisplayData中

HWComposer 的DisplayData

  struct DisplayData {
        DisplayData();
        ~DisplayData();
        Vector configs; //设备配置信息
        size_t currentConfig;
        uint32_t format;    //FB Hal的数据格式
        bool connected; //设备时候连接
        bool hasFbComp; //是否需要GL合成
        bool hasOvComp; //是否需要HWC河涌
        size_t capacity; //列表的最大容量
        hwc_display_contents_1* list; //要合成的Layer的列表,用于传递个HWC HAL
        hwc_layer_1* framebufferTarget; //HWComposer将列表中的Layer合成后最终存放到这个Layer中
        buffer_handle_t fbTargetHandle; //最终合成Layer对应的图像缓冲区
        ......
        buffer_handle_t outbufHandle;
        sp outbufAcquireFence;

        // protected by mEventControlLock
        int32_t events;
    };

SurfaceFlinger中有DisplayDevice来描述一个显示设备, HWComposer中DisplayData来描述一个显示设备需要显示的数据信息。详细注释已经在代码中

HWComposer 硬件合成相关接口分析

SurfaceFlinger合成图像的时候会调用setHWComposer函数,来设置HWComposer硬件合成相关的参数

    //创建HWComposer任务列表,并初始化基本的属性信息
    HWComposer& hwc(getHwComposer());
    if (hwc.initCheck() == NO_ERROR) {
        // 创建HWC 合成的工作列表
        if (CC_UNLIKELY(mHwWorkListDirty)) {
            mHwWorkListDirty = false;
            //变量所有的显示设备列表,为每个显示设备都创建工作任务列表
            for (size_t dpy=0 ; dpy hw(mDisplays[dpy]);
                const int32_t id = hw->getHwcDisplayId();
                if (id >= 0) {
                    //获取当前显示设备需要显示的Layer列表,存放在VisibleLayersSortedByZ列表中
                    const Vector< sp >& currentLayers(
                        hw->getVisibleLayersSortedByZ());
                    const size_t count = currentLayers.size();
                    //调用HWComposer的createWorkList创建工作列表,指定显示设备ID和Layer数量
                    if (hwc.createWorkList(id, count) == NO_ERROR) {
                        HWComposer::LayerListIterator cur = hwc.begin(id);
                        const HWComposer::LayerListIterator end = hwc.end(id);
                        for (size_t i=0 ; cur!=end && i& layer(currentLayers[i]);
                            //遍历通过SurfaceFlinger的Layer设置HWC Layer的混合模式,裁剪区域等属性
                            layer->setGeometry(hw, *cur);
                            if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix) {
                                cur->setSkip(true);
                            }
                        }
                    }
                }
            }
        }

        // 为HWComposer的每个Layer设置图形数据

        // 遍历所有的显示设备,为每个设备的工作列表中的Layer设置数据
        for (size_t dpy=0 ; dpy hw(mDisplays[dpy]);
            const int32_t id = hw->getHwcDisplayId();
            if (id >= 0) {
                //获取当前显示设备中需要显示的Layer列表
                const Vector< sp >& currentLayers(
                    hw->getVisibleLayersSortedByZ());
                const size_t count = currentLayers.size();
                HWComposer::LayerListIterator cur = hwc.begin(id);
                const HWComposer::LayerListIterator end = hwc.end(id);
                for (size_t i=0 ; cur!=end && i& layer(currentLayers[i]);
                    layer->setPerFrameData(hw, *cur);
                }
            }
        }   

        //调用HWC的prepare,做硬件合成准备
        status_t err = hwc.prepare();
        ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));

SF设置HWComposer的顺序如下:
1:调用HWComposer的createWorkList创建合成任务列表
2:遍历所有的Layer为HWComposer的Layer设置图形数据
3:调用HWComposer的prepare做合成准备

HWComposer创建任务列表

HWComposer用于合成Layer图像数据,HWComposer硬件合成第一步是创建HWComposer任务列表

//参数id 表示当前为哪个显示设备创建任务列表, numLayers表示要创建多大的列表,也就是SurfaceFlinger中有多少个Layer要显示在这个屏幕上。
status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
        return BAD_INDEX;
    }

    if (mHwc) {
        //找到当前ID对应的显示设备的信息
        DisplayData& disp(mDisplayData[id]);
        //如果版本大于HWC_DEVICE_API_VERSION_1_1, 则需要多创建一个Layer, 这个Layer用来存放那些需要软件合成的Layer GL合成后的图像数据,这些Layer合成后的数据会放到任务列表中和其他的Layer一起参与硬件合成
        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
            numLayers++;
        }
        //如果对应显示设备的列表还没有分配内存,或者容量较小,则释放掉原来的列表,重新分配内存
        if (disp.capacity < numLayers || disp.list == NULL) {
            size_t size = sizeof(hwc_display_contents_1_t)
                    + numLayers * sizeof(hwc_layer_1_t);
            free(disp.list);
            disp.list = (hwc_display_contents_1_t*)malloc(size);
            disp.capacity = numLayers;
        }
        //如果版本大于HWC_DEVICE_API_VERSION_1_1
        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
            //将列表中最后一个Layer作为GL软件合成最后的存放Layer
            disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1];
            memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t));
            const DisplayConfig& currentConfig =
                    disp.configs[disp.currentConfig];
            const hwc_rect_t r = { 0, 0,
                    (int) currentConfig.width, (int) currentConfig.height };
            //设置最后一个Layer的合成方式为HWC_FRAMEBUFFER_TARGET
            disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
            disp.framebufferTarget->hints = 0;
            disp.framebufferTarget->flags = 0;
            disp.framebufferTarget->handle = disp.fbTargetHandle;
            disp.framebufferTarget->transform = 0;
            disp.framebufferTarget->blending = HWC_BLENDING_PREMULT;
            //设置最终GL合成的区域
            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
                disp.framebufferTarget->sourceCropf.left = 0;
                disp.framebufferTarget->sourceCropf.top = 0;
                disp.framebufferTarget->sourceCropf.right =
                        currentConfig.width;
                disp.framebufferTarget->sourceCropf.bottom =
                        currentConfig.height;
            } else {
                disp.framebufferTarget->sourceCrop = r;
            }
            disp.framebufferTarget->displayFrame = r;
            disp.framebufferTarget->visibleRegionScreen.numRects = 1;
            disp.framebufferTarget->visibleRegionScreen.rects =
                &disp.framebufferTarget->displayFrame;
            disp.framebufferTarget->acquireFenceFd = -1;
            disp.framebufferTarget->releaseFenceFd = -1;
            disp.framebufferTarget->planeAlpha = 0xFF;
        }
        disp.list->retireFenceFd = -1;
        disp.list->flags = HWC_GEOMETRY_CHANGED;
        //设置列表中Layer的数量为numHwLayers
        disp.list->numHwLayers = numLayers;
    }
    return NO_ERROR;
}

DisplayData描述了一个显示设备要合成的数据信息,其中有一个Layer列表,存放SufaceFlinger设置的该显示设备即将参加合成的Layer列表。
创建任务列表的时候首先需要判断列表的容量是否足以容纳当前设置的Layer数量,如果存放不了则需要重新分配列表的内存空间。
当我们把Layer列表交个硬件进行合成的时候,需要多指定一个Layer,该Layer用来存放,软件GL合成Layer的最终图像数据,这些Layer被软件合成的后放到任务列表最后一个Layer中,一起参与HWC硬件合成,最后一起显示到屏幕上,所以在申请列表空间的时候需要多申请一个Layer的空间。在列表中这个Layer的位置为列表最后一个,最终输出的这个Layer是需要openGL进行合成操作的,所以将最后的Layer的合成类型设置为HWC_FRAMEBUFFER_TARGET,表示这个Layer最终需要渲染到FB显示缓冲区。

HWComposer数据合成准备

status_t HWComposer::prepare() {
    Mutex::Autolock _l(mDisplayLock);
    ......

    //调用硬件HWC prepare 即将开始合成数据
    int err = mHwc->prepare(mHwc, mNumDisplays, mLists);
    ALOGE_IF(err, "HWComposer: prepare failed (%s)", strerror(-err));

    if (err == NO_ERROR) {
        //遍历每一个显示设备,确定该显示设备是否需要HWC和GL合成
        for (size_t i=0 ; inumHwLayers ; i++) {
                    hwc_layer_1_t& l = disp.list->hwLayers[i];
                    //如果该Layer的flag为HWC_SKIP_LAYER, 则需要GL方式合成
                    if (l.flags & HWC_SKIP_LAYER) {
                        l.compositionType = HWC_FRAMEBUFFER;
                    }
                    //如果Layer合成方式为HWC_FRAMEBUFFER,设置该设备hasFbComp为true
                    if (l.compositionType == HWC_FRAMEBUFFER) {
                        disp.hasFbComp = true;
                    }
                    //如果Layer合成方式为HWC_OVERLAY, 则设置该设备hasOvComp为true
                    if (l.compositionType == HWC_OVERLAY) {
                        disp.hasOvComp = true;
                    }
                    //如果Layer的合成凡是为HWC_CURSOR_OVERLAY, 也设置hasOvComp为ture
                    if (l.compositionType == HWC_CURSOR_OVERLAY) {
                        disp.hasOvComp = true;
                    }
                }
                //如果该Layer为HWC合成输出的Layer则设置hasFbComp为true
                if (disp.list->numHwLayers == (disp.framebufferTarget ? 1 : 0)) {
                    disp.hasFbComp = true;
                }
            } else {
                //如果list为空,则默认为GL方式合成
                disp.hasFbComp = true;
            }
        }
    }
    return (status_t)err;
}

HWComposer的prepare方法决定了该显示设备支持那种合成方式,合成方式主要分为两种
HWC硬件合成和GL方式的软件合成
有以下类型的Layer,该显示设备需要支持HWC硬件合成
1:Layer的合成类型为 HWC_OVERLAY
2:Layer的合成类型为 HWC_CURSOR_OVERLAY 光标类型的Layer
什么情况下显示设备需要支持软件合成呢?
1:如果HWComposer的任务列表为空,则默认该设备需要GL来进行软件合成
2:如果有Layer的flag为HWC_SKIP_LAYER,则需要支持GL合成
3:如果该Layer是HWC指定的输出Layer, 需要进行GL软件合成

你可能感兴趣的:(HWComper介绍)