SurfaceFlinger图像合成[2]

上一篇介绍了在Vsync到来时, SF首先会处理Layer属性变化, 显示设备变化等情况,然后将mCurrentState提交到了mDrawingState,等待合成处理,然后将遍历所有待处理的Layer,将新Buffer内容更新绑定到Layer纹理对象。经过这些处理流程,决定是否需SF要重新合成图像,如果需要则调用handleMessageRefresh方法合成并刷新。

void SurfaceFlinger::handleMessageRefresh() {
        ...... 
        //合成预处理工作
        preComposition();
        //计算和存储每个Layer的脏区域
        rebuildLayerStacks();
        //创建HWC硬件合成的任务列表
        setUpHWComposer();
        doDebugFlashRegions();
        //先进行GL合成,将合成后的图像放在HWC任务列表的最后为止
        //然后有HWC进行合成并输出到屏幕
        doComposition();
        //合成善后工作
        postComposition();
        ......
}

下面逐个方法的分析下SF合成主要工作内容和逻辑。

preComposition

void SurfaceFlinger::preComposition()
{
    bool needExtraInvalidate = false;
    //遍历mDrawingState中所有的Layer,调用Layer的onPreComposition方法,来决定是否需要预约下一次Vsync事件
    const LayerVector& layers(mDrawingState.layersSortedByZ);
    const size_t count = layers.size();
    for (size_t i=0 ; ionPreComposition()) {
            needExtraInvalidate = true;
        }
    }
    if (needExtraInvalidate) {
        signalLayerUpdate();
    }
}

bool Layer::onPreComposition() {
    mRefreshPending = false;
    return mQueuedFrames > 0 || mSidebandStreamChanged;
}

这个方法不是很复杂,就是遍历mDrawingState中所有的Layer,调用Layer的onPreComposition方法,根据onPreComposition,来决定是否需要预约下一次Vsync事件.
如果此时Layer中的mSidebandStreamChanged发生了变化, 或者Layer中仍然有新的待处理的Buffer,此时就需要下次Vsync信号到来的时候再次执行合成过程。

rebuildLayerStacks

在看rebuildLayerStacks方法前先看下computeVisibleRegions方法如何来计算各个显示设备上的脏区域?


void SurfaceFlinger::computeVisibleRegions(
        const LayerVector& currentLayers, uint32_t layerStack,
        Region& outDirtyRegion, Region& outOpaqueRegion)
{
    ATRACE_CALL();
    //处于该Layer上层的非透明区域
    Region aboveOpaqueLayers;
    //
    Region aboveCoveredLayers;
    //脏区域
    Region dirty;

    outDirtyRegion.clear();

    //layerSortByZ 从列表0位置到列表尾部, Layer存放依次为从底层到最上层
    //此处从列表尾部及最上层开始遍历来计算相关的显示区域.
    size_t i = currentLayers.size();
    while (i--) {
        const sp& layer = currentLayers[i];
        const Layer::State& s(layer->getDrawingState());

        //只计算当前显示设备的Layer
        if (s.layerStack != layerStack)
            continue;

        /*
         * opaqueRegion: Layer完全不透明的显示区域
         */
        Region opaqueRegion;

        /*
         * visibleRegion: 屏幕上可见且完全不透明的区域, 该层的不透明区域opaqueRegion - 上层所有不透明区域
         *                理论上,被透明区域覆盖的区域仍然属于 visibleRegion
         */
        Region visibleRegion;

        /*
         * coveredRegion: 被上方所有可见区域覆盖的区域, (包括透明区域覆盖的区域)
         */
        Region coveredRegion;

        /*
         * transparentRegion: 完全透明的区域,如果某一个Layer中没有可见切非透明的区域的话,就会被从合成列表中移除(完全透明的Layer没必要做任何合成操作).
         */
        Region transparentRegion;


        //仅处理所有的属性为可见的Layer,属性为Hidden的Layer没必要处理
        if (CC_LIKELY(layer->isVisible())) {
            //是否设置了Layer为透明
            const bool translucent = !layer->isOpaque(s);
            //计算Layer的边界
            Rect bounds(s.transform.transform(layer->computeBounds()));
            //默认visibleRegion为整个Layer的大小
            visibleRegion.set(bounds);
            if (!visibleRegion.isEmpty()) {
                // visibleRegion中需要移除透明区域
                if (translucent) {
                    const Transform tr(s.transform);
                    if (tr.transformed()) {
                        if (tr.preserveRects()) {
                            // transform the transparent region
                            transparentRegion = tr.transform(s.activeTransparentRegion);
                        } else {
                            // transformation too complex, can't do the
                            // transparent region optimization.
                            transparentRegion.clear();
                        }
                    } else {
                        transparentRegion = s.activeTransparentRegion;
                    }
                }

                // 计算非透明区域
                const int32_t layerOrientation = s.transform.getOrientation();
                if (s.alpha==255 && !translucent &&
                        ((layerOrientation & Transform::ROT_INVALID) == false)) {
                    // the opaque region is the layer's footprint
                    opaqueRegion = visibleRegion;
                }
            }
        }

        // aboveCoveredLayers(存放了上层所有层的visibleRegion)和visibleRegion的交集就是被覆盖区域
        coveredRegion = aboveCoveredLayers.intersect(visibleRegion);

        //将Layer自身的visibleRegion也添加到aboveCoveredLayers中, 方便下层Layer计算覆盖区域
        aboveCoveredLayers.orSelf(visibleRegion);

        // VisbleRegion需要减去上层所有的非透明区域
        visibleRegion.subtractSelf(aboveOpaqueLayers);

        // 如果Layer中的内容被修改了,需要显示将旧的VisibleRegion也进行刷新
        if (layer->contentDirty) {
            // we need to invalidate the whole region
            dirty = visibleRegion;
            // as well, as the old visible region
            dirty.orSelf(layer->visibleRegion);
            layer->contentDirty = false;
        } else {
            /* 计算暴露区域的变化:
             *   1) 原先被覆盖的区域变成可见了
             *   2) 现在暴露区域减去原先的暴露区域
             */
            const Region newExposed = visibleRegion - coveredRegion;
            const Region oldVisibleRegion = layer->visibleRegion;
            const Region oldCoveredRegion = layer->coveredRegion;
            const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
            dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed);
        }
        //脏区域需要减去被覆盖的部分
        dirty.subtractSelf(aboveOpaqueLayers);

        // 累加所有Layer的脏区域
        outDirtyRegion.orSelf(dirty);

        // 将当前Layer的不透明区域添加到 aboveOpaqueLayers
        aboveOpaqueLayers.orSelf(opaqueRegion);

        // 保存计算出的region到Layer中
        layer->setVisibleRegion(visibleRegion);
        layer->setCoveredRegion(coveredRegion);
        layer->setVisibleNonTransparentRegion(
                visibleRegion.subtract(transparentRegion));
    }

    outOpaqueRegion = aboveOpaqueLayers;
}

首先介绍下SF中一些区域相关的概念:

opaqueRegion Layer完全不透明的显示区域
visibleRegion: 屏幕上可见且完全不透明的区域, 该层的不透明区域opaqueRegion - 上层所有不透明区域,理论上,被透明区域覆盖的区域仍然属于 visibleRegion
coveredRegion: 被上方所有可见区域覆盖的区域, (包括透明区域覆盖的区域)
transparentRegion: 完全透明的区域,如果某一个Layer中没有可见切非透明的区域的话,就会被从合成列表中移除(完全透明的Layer没必要做任何合成操作).

aboveOpaqueLayers : 当前Layer上层所有Layer不透明区域的累加
aboveCoveredLayers : 当前Layer上层所有Layer可见区域的累加

computeVisibleRegions方法做了什么工作呢?
1: 从Layer Z轴最上层开始遍历该显示设备中所有的Layer
2: 计算该Layer的被覆盖区域 coveredRegion = aboveCoveredLayers(上层所有Layer的显示区域)当前Layer除去非透明区域部分 的交集
3: 将 当前Layer除去非透明区域部分 添加到aboveCoveredLayers中,为下一层Layer计算提供条件
4: 计算当前Layer的可见区域 VisibleRegion = 当前Layer除去非透明区域部分 - aboveOpaqueLayers(上层所有非透明区域)
5: 计算脏区域, 脏区域需要减去被遮盖的部分,并将当前Layer的脏区域累加到当前显示设备的脏区域outDirtyRegion
6: 保存计算的Region到Layer中

//重新构建每个显示设备的Layer Statck
void SurfaceFlinger::rebuildLayerStacks() {
    //mVisibleRegionsDirty表示Visible相关的显示区域是否发生变化,如果发生变化则需要重新构造LayerStack
    if (CC_UNLIKELY(mVisibleRegionsDirty)) {
        ATRACE_CALL();
        //处理后将mVisibleRegionsDirty设置为false
        mVisibleRegionsDirty = false;
        invalidateHwcGeometry();
        //遍历所有显示设备,根据显示设备来计算该显示设备中dirtyRegion(变化区域)和opaqueRegion(非透明区域)
        const LayerVector& layers(mDrawingState.layersSortedByZ);
        for (size_t dpy=0 ; dpy > layersSortedByZ;
            const sp& hw(mDisplays[dpy]);
            const Transform& tr(hw->getTransform());
            const Rect bounds(hw->getBounds());
            if (hw->isDisplayOn()) {
                //遍历该显示设备上所有的Layer并计算, 得出变化区域和非透明区域
                SurfaceFlinger::computeVisibleRegions(layers,
                        hw->getLayerStack(), dirtyRegion, opaqueRegion);

                const size_t count = layers.size();
                for (size_t i=0 ; i& layer(layers[i]);
                    const Layer::State& s(layer->getDrawingState());
                    if (s.layerStack == hw->getLayerStack()) {
                        //获取当前Layer的非透明的可见区域,和显示设备边界比较,时候和显示设备有交集,有的话则需要显示,将它放入layersSortedByZ列表中.
                        Region drawRegion(tr.transform(
                                layer->visibleNonTransparentRegion));
                        drawRegion.andSelf(bounds);

                        if (!drawRegion.isEmpty()) {
                            layersSortedByZ.add(layer);
                        }
                    }
                }
            }
            //将要绘制的Layer存放到一样display的VisibleLayersSortedByZ中等待合成处理。
            hw->setVisibleLayersSortedByZ(layersSortedByZ);
            hw->undefinedRegion.set(bounds);
            hw->undefinedRegion.subtractSelf(tr.transform(opaqueRegion));
            hw->dirtyRegion.orSelf(dirtyRegion);
        }
    }
}

rebuildLayerStacks在合成方法中主要作用是存储待显示的Layer及该显示设备的脏区域.
Android支持多个屏幕,每个屏幕的显示数据并不是完全一样的,每个Display是分开合成的;也就是说,layersSortedByZ中的layer需要根据显示屏的特性,分别进行合成,合成后的数据,送给各自的显示屏。
rebuildLayerStacks会遍历所有Layer计算Layer的脏区域, 然后和当前的显示设备进行比较,看Layer的脏区域是否在显示设备的显示区域内,如果在显示区域内的话说明该layer是需要绘制的,则更新到显示设备的VisibleLayersSortedByZ列表中,等待被合成.

setUpHWComposer

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做合成准备

doComposition

void SurfaceFlinger::doComposition() {
    ATRACE_CALL();
    const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
    for (size_t dpy=0 ; dpy& hw(mDisplays[dpy]);
        if (hw->isDisplayOn()) {
            //获取rebuildLayerStacks时计算的当前显示设备的脏区域DirtyRegion,。如果是强制重画,mRepaintEverything为true,那么脏区域就是整个屏幕的大小。
            const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));

            // 主要是对当前的显示设备上的所有不支持硬件合成Layer进行OpenGL合成处理
            doDisplayComposition(hw, dirtyRegion);

            hw->dirtyRegion.clear();
            //flip计数
            hw->flip(hw->swapRegion);
            hw->swapRegion.clear();
        }
        hw->compositionComplete();
    }
    //调用HWC硬件合成并显示
    postFramebuffer();
}

doComposition进行合成,获取rebuildLayerStacks时计算的当前显示设备的脏区域DirtyRegion,如果是强制重画,mRepaintEverything为true,那么脏区域就是整个屏幕的大小。然后调用doDisplayComposition对当前设备中需要OpenGL方式合成的Layer进行软件合成。
软件合成之后,统一交由HWC, 由HWC硬件合成并输出到显示屏。

先分析下软件GL合成Layer的过程。

void SurfaceFlinger::doDisplayComposition(const sp& hw,
        const Region& inDirtyRegion)
{
    // 只有在以下情况下才去真正合成这个Display的图像:
    // 1) 需要HWC硬件合成
    // 2) 脏区域不为空
    bool isHwcDisplay = hw->getHwcDisplayId() >= 0;
    if (!isHwcDisplay && inDirtyRegion.isEmpty()) {
        return;
    }

    Region dirtyRegion(inDirtyRegion);

    ......
        //调用doComposeSurfaces进行合成
        doComposeSurfaces(hw, dirtyRegion);
    }
    ......

    //调用SwapBuffer将软件合成的图像提交到该显示设备对应的FrameBufferSurface
    hw->swapBuffers(getHwComposer());
}

合成的操作主要在doComposeSurfaces函数中完成,合成方式,主要有两种,一种是使用软件方式的OpenGL合成;另外一种,用的是HWC硬件进行合成,合成策略也是能用HWC合成的尽量用HWC方式合成,不能用的硬件方式再用软件方式合成,毕竟硬件合成效率要高很多。doComposeSurfaces主要是主要是来处理无法用HWC合成的Layer。
GL方式合成完成以后调用SwapBuffers将合成后的Buffer提交给该显示设备的BufferQueue,最终有FrameBufferSurface进行处理。

bool SurfaceFlinger::doComposeSurfaces(const sp& hw, const Region& dirty)
{
    //获取SF的RenderEngine, 主要封装openGL一些操作,这个RenderEngine是SurfaceFlinger初始化的时候创建的
    RenderEngine& engine(getRenderEngine());
    const int32_t id = hw->getHwcDisplayId();
    HWComposer& hwc(getHwComposer());
    HWComposer::LayerListIterator cur = hwc.begin(id);
    const HWComposer::LayerListIterator end = hwc.end(id);

    bool hasGlesComposition = hwc.hasGlesComposition(id);
    if (hasGlesComposition) {
        //调用DisplayDevice的makeCurrent设置当前openGL的上下文为当前显示设备的上下
        //文,包括当前显示设备的ANativeWindow,后续该设备的Layer使用openGL软件合
        //成绘制最终都会绘制到当前显示设备的ANativeWindow中去, 调用swapBuffer的时候
        //提交给该显示设备的BufferQueue。
        if (!hw->makeCurrent(mEGLDisplay, mEGLContext)) {
            ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
                  hw->getDisplayName().string());
            eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
            if(!getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext)) {
              ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
            }
            return false;
        }

        // Never touch the framebuffer if we don't have any framebuffer layers
        const bool hasHwcComposition = hwc.hasHwcComposition(id);
        if (hasHwcComposition) {
            // when using overlays, we assume a fully transparent framebuffer
            // NOTE: we could reduce how much we need to clear, for instance
            // remove where there are opaque FB layers. however, on some
            // GPUs doing a "clean slate" clear might be more efficient.
            // We'll revisit later if needed.
            engine.clearWithColor(0, 0, 0, 0);
        } else {
            // we start with the whole screen area
            const Region bounds(hw->getBounds());

            // we remove the scissor part
            // we're left with the letterbox region
            // (common case is that letterbox ends-up being empty)
            const Region letterbox(bounds.subtract(hw->getScissor()));

            // compute the area to clear
            Region region(hw->undefinedRegion.merge(letterbox));

            // but limit it to the dirty region
            region.andSelf(dirty);

            // screen is already cleared here
            if (!region.isEmpty()) {
                // can happen with SurfaceView
                drawWormhole(hw, region);
            }
        }

        if (hw->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) {
            // just to be on the safe side, we don't set the
            // scissor on the main display. It should never be needed
            // anyways (though in theory it could since the API allows it).
            const Rect& bounds(hw->getBounds());
            const Rect& scissor(hw->getScissor());
            if (scissor != bounds) {
                // scissor doesn't match the screen's dimensions, so we
                // need to clear everything outside of it and enable
                // the GL scissor so we don't draw anything where we shouldn't

                // enable scissor for this frame
                const uint32_t height = hw->getHeight();
                engine.setScissor(scissor.left, height - scissor.bottom,
                        scissor.getWidth(), scissor.getHeight());
            }
        }
    }

第一步分,主要设置openGL相关的信息,以方便后续使用openGL进行合成,因为Layer是根据显示设备来进行合成的,不同的显示设备的Layer分别合成,所以在进行当前显示设备的Layer合成的时候首先会设置当前显示设备的上下文,每个显示设备DisplayDevice在初始化创建的时候都会创建一个自己显示设备的ANativeWindow,用来作为当前显示设备的画布,这个以前分析过,后续该设备所有使用OpenGL合成的Layer最终会合成并绘制到该Window上去,ANativeWindow的具体实现是在Surface中,也就是生产者,这一帧合成绘制完成后提交到BufferQueue,由该显示设备的消费这FrameBufferSurface接收处理,RenderEngine封装了SF openGL相关的信息和操作.对于非主屏还要设置其裁剪区.


    /*
     * and then, render the layers targeted at the framebuffer
     */

    const Vector< sp >& layers(hw->getVisibleLayersSortedByZ());
    const size_t count = layers.size();
    const Transform& tr = hw->getTransform();
    if (cur != end) {
        // 遍历所有的Layer,根据该Layer的类型,如果需要GL合成,则调用该Layer的draw方法
        for (size_t i=0 ; i& layer(layers[i]);
            const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
            if (!clip.isEmpty()) {
                switch (cur->getCompositionType()) {
                    case HWC_CURSOR_OVERLAY:
                    case HWC_OVERLAY: {
                        const Layer::State& state(layer->getDrawingState());
                        if ((cur->getHints() & HWC_HINT_CLEAR_FB)
                                && i
                                && layer->isOpaque(state) && (state.alpha == 0xFF)
                                && hasGlesComposition) {
                            // 如果该Layer使用硬件合成,需要做一些清理工作
                            layer->clearWithOpenGL(hw, clip);
                        }
                        break;
                    }
                    case HWC_FRAMEBUFFER: {
                        //使用软件合成的话,则需要调用Layer的draw方法进行OpenGL绘制
                        layer->draw(hw, clip);
                        break;
                    }
                    case HWC_FRAMEBUFFER_TARGET: {
                        //在分析HWComposer的时候知道,HWC中最后一个Layer是HWC硬件合成的输出 
                        //Layer,必须使用GL合成,所有这个Layer调用draw方法进行openGL绘制
                        //如果这个Layer是HWC_FRAMEBUFFER_TARGET类型,是openGL软件最终  
                        //输出的Layer, 则无需处理 
                        ALOGW("HWC_FRAMEBUFFER_TARGET found in hwc list (index=%zu)", i);
                        break;
                    }
                }
            }
            layer->setAcquireFence(hw, *cur);
        }
    } else {
        // 如果该显示设备上只有一个Layer, 直接用OpenGL合成就可以了,无需使用HWC硬件合成
        for (size_t i=0 ; i& layer(layers[i]);
            const Region clip(dirty.intersect(
                    tr.transform(layer->visibleRegion)));
            if (!clip.isEmpty()) {
                layer->draw(hw, clip);
            }
        }
    }
    return true;
}

第二部分:主要是作用是渲染那些需要使用OpenGL合成的Layer, 将会调用Layer的draw方法使用openGL绘制该Layer对应的Texture纹理,最终这些Layer的纹理将会合成输出到RenderEngine创建的ANativeWindow中。
有哪些Layer需要openGL方式来合成呢?
1:显示设备只有一个Layer的时候直接使用GL软件方式合成
2:合成类型是HWC_FRAMEBUFFER的Layer使用GL软件方式合成
如果HWC_FRAMEBUFFER_TARGET类型,则不需要处理, 在分析HWComposer的时候了解过, workList最后一个Layer是给openGL最终合成的图像来准备的,这些Layer在软件GL合成的最终会存放到HWC workList的最后一个Layer中。
那是什么时候放入的呢?接着看DisplayDevice的swapBuffers函数.

软件合成的图像最终输出
void DisplayDevice::swapBuffers(HWComposer& hwc) const {
    // 只有以下几种情况下才会调用eglSwapBuffers输出到FrameBufferSurface
    //  (1) 没有HWC硬件设备
    //  (2) 有部分Layer需要软件GLES方式合成
    //    (a) 需要输出的FrameBuffer Target
    //    (b) 这个是虚拟显示设备
    if (hwc.initCheck() != NO_ERROR ||
            (hwc.hasGlesComposition(mHwcDisplayId) &&
             (hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) {
        //调用EGL,提交到对应的BufferQueue队列
        EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
        ......
    }
 
}

swapBuffers直接将上一步中GLES合成到ANativeWindow中的图像提交到了BufferQueue队列,等待FrameBufferSurface消费者进行处理。

void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {
    sp buf;
    sp acquireFence;
    //从BufferQueue队列中获取新的Buffer, 不再详细分析
    status_t err = nextBuffer(buf, acquireFence);
    //调用HWC的fbPost来输出Buffer
    err = mHwc.fbPost(mDisplayType, acquireFence, buf);
}

DisplayDevice提交Buffer之后,FrameBufferSurface会接收到onFrameAvailable函数通知,然后调用nextBuffer从BufferQueue获取新的待处理的Buffer。使用fbPost来输出。

int HWComposer::fbPost(int32_t id,
        const sp& acquireFence, const sp& buffer) {
    //如果有HWC硬件设备,则调用setFramebufferTarget将GL合成的图像放到workList最后一个Layer中
    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
        return setFramebufferTarget(id, acquireFence, buffer);
    } else {
    //没有HWC硬件,则直接调用Gralloc模块的mFbDev的post函数,将图像设置到FrameBuffer显存,进行显示。
        acquireFence->waitForever("HWComposer::fbPost");
        return mFbDev->post(mFbDev, buffer->handle);
    }
}

我们设备目前是有HWC硬件设备的,此时只需要调用setFramebufferTarget将GL合成的图像放到workList最后一个Layer中。可以用硬件合成的Layer硬件放在了workList列表中,不能用硬件合成的Layer 现在也已经使用GL软件合成后放到了workList列表最后一个Layer中,所有待使用硬件合成的数据都已经准备好,放到了硬件合成工作列表workList中,只需最后一步硬件合成并显示了。

硬件合成并显示

硬件合成并显示是由postFramebuffer函数实现的.

void SurfaceFlinger::postFramebuffer()
{
    ......
    HWComposer& hwc(getHwComposer());
    if (hwc.initCheck() == NO_ERROR) {
        if (!hwc.supportsFramebufferTarget()) {
            // EGL spec says:
            //   "surface must be bound to the calling thread's current context,
            //    for the current rendering API."
            getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
        }
        //调用HWC的commit函数来提交合成任务
        hwc.commit();
    }
    ......
}

status_t HWComposer::commit() {
   
    ......
    err = mHwc->set(mHwc, mNumDisplays, mLists);

  
}

postFramebuffer最终调用了HWComposer的commit, 而commit则调用了HWC的set函数提交了硬件合成任务给HWC驱动. HWC会实现Layer的合成,并最终将合成后的图像显示到屏幕上。


void SurfaceFlinger::postComposition()
{
    //调用Layer的onPostComposition, 处理Layer中刚刚绘制的Buffer的Fence
    //此时才会真正释放掉一个Buffer
    const LayerVector& layers(mDrawingState.layersSortedByZ);
    const size_t count = layers.size();
    for (size_t i=0 ; ionPostComposition();
    }

    //平常我们用的Vsync都是mPrimaryDispSync分发出来的,并不是每一次都是从底层
    //硬件上报的,所以mPrimaryDispSync需要和底层的硬件Vsync保持同步
    //如果和硬件Vsync不同步的话则需要重新打开硬件Vsync,有DispSync重新采样计算模型
    const HWComposer& hwc = getHwComposer();
    sp presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);

    if (presentFence->isValid()) {
        if (mPrimaryDispSync.addPresentFence(presentFence)) {
            enableHardwareVsync();
        } else {
            disableHardwareVsync(false);
        }
    }

    const sp hw(getDefaultDisplayDevice());
    if (kIgnorePresentFences) {
        if (hw->isDisplayOn()) {
            enableHardwareVsync();
        }
    }

    //处理动画合成的逻辑
    if (mAnimCompositionPending) {
        mAnimCompositionPending = false;

        if (presentFence->isValid()) {
            mAnimFrameTracker.setActualPresentFence(presentFence);
        } else {
            // The HWC doesn't support present fences, so use the refresh
            // timestamp instead.
            nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
            mAnimFrameTracker.setActualPresentTime(presentTime);
        }
        mAnimFrameTracker.advanceFrame();
    }

}

postComposition主要做一些合成的善后处理工作. 有一个关键的部分就是Vsync的处理,每次合成后会对软件Vsync做一次校验,平常我们用的Vsync都是mPrimaryDispSync分发出来的,并不是每一次都是从底层硬件上报的,所以mPrimaryDispSync需要和底层的硬件Vsync保持同步,如果和硬件Vsync不同步的话则需要重新打开硬件Vsync,由DispSync重新采样计算软件 Vsync模型。
到此为止, SurfaceFlinger的图像合成就简单分析完了。

你可能感兴趣的:(SurfaceFlinger图像合成[2])