HWComposer合成显示流程分析

在介绍HWComposer合成显示流程前,需要先了解下 AndroidO显示体统架构如下图:

1. AndroidO显示体统架构如

Linux Android display architecture

在这里插入图片描述

其中的SDM架构如下图:

在这里插入图片描述

2. setUpHWComposer介绍

在SurfaceFlinger进行合成显示的时候,首先需要初始化HWC,
代码为setUpHWComposer

void SurfaceFlinger::setUpHWComposer() {
    
    
    ...
    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
    
    
        ...
        //判断是否需要重新绘制
        bool mustRecompose = dirty && !(empty && wasEmpty);
        ...
        mDisplays[dpy]->beginFrame(mustRecompose);
        ...
    }
    ...
    // build the h/w work list
    if (CC_UNLIKELY(mGeometryInvalid)) {
    
    
        mGeometryInvalid = false;
        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
    
    
            sp<const DisplayDevice> displayDevice(mDisplays[dpy]);
            const auto hwcId = displayDevice->getHwcDisplayId();
            if (hwcId >= 0) {
    
    
                const Vector<sp<Layer>>& currentLayers(
                        displayDevice->getVisibleLayersSortedByZ());
                ...
                //为每个Layer创建一个与之对应的HwLayer
                //并设置Geometry
                for (size_t i = 0; i < currentLayers.size(); i++) {
    
    
                    const auto& layer = currentLayers[i];
                    if (!layer->hasHwcLayer(hwcId)) {
    
    
                        //为layer创建一个与之对应的HwcLayer
                        if (!layer->createHwcLayer(mHwc.get(), hwcId)) {
    
    
                            //如果创建失败,则强制修改合成方式为Client
                            layer->forceClientComposition(hwcId);
                            continue;
                        }
                    }
                    //设置几何尺寸
                    layer->setGeometry(displayDevice, i);
                     ...
                }
            }
        }
    }

    // Set the per-frame data
    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
    
    
        auto& displayDevice = mDisplays[displayId];
        const auto hwcId = displayDevice->getHwcDisplayId();
        ...
        //为每个Layer设置显示帧数据
        for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
    
    
            layer->setPerFrameData(displayDevice);
        }
        ...
    }
    ...
    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
    
    
        auto& displayDevice = mDisplays[displayId];
        if (!displayDevice->isDisplayOn()) {
    
    
            continue;
        }
        //尝试直接显示
        //如果成功则返回
        //如果显示不成功,则会执行刷新validate
        status_t result = displayDevice->prepareFrame(*mHwc);
        ...
    }
}

setUpHWComposer有几个重要的过程

  1. 判断是否需重新绘制
  2. 为每个Layer创建一个与之对应的HwcLayer并设置几何尺寸(Geometry)
  3. 为每个Layer及与之对应的HwLayer设置显示帧数据
  4. 尝试直接显示

2.1 HwLayer创建

我们首选分析下HwLayer的创建。其简要流程图如下:

在这里插入图片描述

2.2 setGeometry流程

下边分析下setGeometry函数:

//surfaceflinger\Layer.cpp
void Layer::setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z)
{
    
    

    const auto hwcId = displayDevice->getHwcDisplayId();
    auto& hwcInfo = mHwcLayers[hwcId];

    ...
    hwcInfo.forceClientComposition = false;
    ...
    auto& hwcLayer = hwcInfo.layer;
    ...
    // this gives us only the "orientation" component of the transform
    const State& s(getDrawingState());
    //设置hwcLayer的blendMode
    auto error = hwcLayer->setBlendMode(blendMode);

    // apply the layer's transform, followed by the display's global transform
    // here we're guaranteed that the layer's transform preserves rects
    Region activeTransparentRegion(s.activeTransparentRegion);
    Transform t = getTransform();
    ...
    const Transform& tr(displayDevice->getTransform());
    Rect transformedFrame = tr.transform(frame);
    error = hwcLayer->setDisplayFrame(transformedFrame);
    ...
    FloatRect sourceCrop = computeCrop(displayDevice);
    error = hwcLayer->setSourceCrop(sourceCrop);
    ...
    float alpha = getAlpha();
    error = hwcLayer->setPlaneAlpha(alpha);
    ...
    error = hwcLayer->setZOrder(z);
    ...
    error = hwcLayer->setInfo(type, appId);
    ...
    /*
     * Transformations are applied in this order:
     * 1) buffer orientation/flip/mirror
     * 2) state transformation (window manager)
     * 3) layer orientation (screen orientation)
     * (NOTE: the matrices are multiplied in reverse order)
     */

    const Transform bufferOrientation(mCurrentTransform);
    Transform transform(tr * t * bufferOrientation);

    if (getTransformToDisplayInverse()) {
    
    
        ...
        transform = Transform(invTransform) * tr * bufferOrientation;
    }

    // this gives us only the "orientation" component of the transform
    const uint32_t orientation = transform.getOrientation();

    if (orientation & Transform::ROT_INVALID) {
    
    
        // we can only handle simple transformation
        hwcInfo.forceClientComposition = true;
    } else {
    
    
        auto transform = static_cast<HWC2::Transform>(orientation);
        auto error = hwcLayer->setTransform(transform);
        ...
    }
    ...
}

setGeometry会给HWCLayer设置blendMode、DisplayFrame区域、SourceCrop区域、PlaneAlpha、ZOrder等属性。
基本流程图如下:
在这里插入图片描述

这些区域的含义请参考https://www.jianshu.com/p/824a9ddf68b9这篇大牛博客,我们直接附其一张神图1
在这里插入图片描述

2.3 setPerFrameData流程

下边分析下setPerFrameData

void Layer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) {
    
    
    // Apply this display's projection's viewport to the visible region
    // before giving it to the HWC HAL.
    const Transform& tr = displayDevice->getTransform();
    const auto& viewport = displayDevice->getViewport();
    Region visible = tr.transform(visibleRegion.intersect(viewport));
    auto hwcId = displayDevice->getHwcDisplayId();
    auto& hwcInfo = mHwcLayers[hwcId];
    auto& hwcLayer = hwcInfo.layer;
    auto error = hwcLayer->setVisibleRegion(visible);
    ...
    error = hwcLayer->setSurfaceDamage(surfaceDamageRegion);
    ...

    // Sideband layers
    if (mSidebandStream.get()) {
    
    
        setCompositionType(hwcId, HWC2::Composition::Sideband);
        error = hwcLayer->setSidebandStream(mSidebandStream->handle());
        ...
        return;
    }

    // Client layers
    if (hwcInfo.forceClientComposition ||
            (mActiveBuffer != nullptr && mActiveBuffer->handle == nullptr)) {
    
    
        setCompositionType(hwcId, HWC2::Composition::Client);
        return;
    }

    // SolidColor layers
    if (mActiveBuffer == nullptr) {
    
    
        setCompositionType(hwcId, HWC2::Composition::SolidColor);

        // For now, we only support black for DimLayer
        error = hwcLayer->setColor({
    
    0, 0, 0, 255});
        ...
        // Clear out the transform, because it doesn't make sense absent a
        // source buffer
        error = hwcLayer->setTransform(HWC2::Transform::None);
        ...
        return;
    }

    // Device or Cursor layers
    if (mPotentialCursor) {
    
    
        // 如果mPotentialCursor为true,设置合成方式为Cursor
        setCompositionType(hwcId, HWC2::Composition::Cursor);
    } else {
    
    
        //设置合成方式为Device,Layer的默认值合成方式
        setCompositionType(hwcId, HWC2::Composition::Device);
    }
    ...
    //设置dataspace
    error = hwcLayer->setDataspace(mCurrentState.dataSpace);
    ...
    uint32_t hwcSlot = 0;
    sp<GraphicBuffer> hwcBuffer;
    hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
            &hwcSlot, &hwcBuffer);
    auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence();
    //设置hwcLayer的hwcBuffer和acquireFence
    error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence);

}

setPerFrameData流程图如下:
在这里插入图片描述

至此,所有hwcLayer都设置完成合成方式和合成显示帧数据后,便可以调用displayDevice->prepareFrame(*mHwc)尝试直接显示,下边分析下该函数

2.3 prepareFrame分析

status_t DisplayDevice::prepareFrame(HWComposer& hwc) {
    
    
    //调用hwc.prepare尝试显示
    status_t error = hwc.prepare(*this);
    ...
    //mDisplaySurface 为FramebufferSurface.cpp
    //空实现
    return mDisplaySurface->prepareFrame(compositionType);
}

下边我们分析下HWComposer::prepare

status_t HWComposer::prepare(DisplayDevice& displayDevice) {
    
    
    ...
    auto displayId = displayDevice.getHwcDisplayId();
    ...
    auto& displayData = mDisplayData[displayId];
    auto& hwcDisplay = displayData.hwcDisplay;
    if (!hwcDisplay->isConnected()) {
    
    
        return NO_ERROR;
    }

    uint32_t numTypes = 0;
    uint32_t numRequests = 0;

    HWC2::Error error = HWC2::Error::None;

    // First try to skip validate altogether if the HWC supports it.
    displayData.validateWasSkipped = false;
    //如果HWC支持SkipValidate且没有合成方式为Client,即hasClientComposition为false
    //尝试直接显示,如果不能直接显示则执行Validate
    if (hasCapability(HWC2::Capability::SkipValidate) &&
            !displayData.hasClientComposition) {
    
    
        sp<android::Fence> outPresentFence;
        uint32_t state = UINT32_MAX;
        //首先会尝试直接显示,如果state == 1,表示显示成功
        //如果不能直接显示则尝试Validate,如果如果state == 0,表示validate成功
        error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state);
        ...
        //如果显示成功了,则直接返回了,不必执行其他操作
        if (state == 1) {
    
     //Present Succeeded.
            std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
            error = hwcDisplay->getReleaseFences(&releaseFences);
            displayData.releaseFences = std::move(releaseFences);
            displayData.lastPresentFence = outPresentFence;
            displayData.validateWasSkipped = true;
            displayData.presentError = error;
            return NO_ERROR;
        }
        // Present failed but Validate ran.
    } else {
    
    
        //尝试更新validate
        error = hwcDisplay->validate(&numTypes, &numRequests);
    }
    ...
    std::unordered_map<HWC2::Layer*, HWC2::Composition> changedTypes;
    changedTypes.reserve(numTypes);
    //执行完validate后,hwc会检查之前设置的合成方式是否支持
    //如果不支持,则会尝试修改,通过getChangedCompositionTypes
    //可以获取需要修改合成方式的HWcLayer和修改的合成方式
    error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
    ...
    displayData.displayRequests = static_cast<HWC2::DisplayRequest>(0);
    std::unordered_map<HWC2::Layer*, HWC2::LayerRequest> layerRequests;
    layerRequests.reserve(numRequests);
    error = hwcDisplay->getRequests(&displayData.displayRequests,
            &layerRequests);
    ...
    displayData.hasClientComposition = false;
    displayData.hasDeviceComposition = false;
    for (auto& layer : displayDevice.getVisibleLayersSortedByZ()) {
    
    
        auto hwcLayer = layer->getHwcLayer(displayId);
        //检查hwcLayer是否在changedTypes中,
        //如果在,则会修改其合成方式为changedTypes[hwcLayer]
        if (changedTypes.count(hwcLayer) != 0) {
    
    
            // We pass false so we only update our state and don't call back
            // into the HWC device
            //首先检查先新的合成方式changedTypes[hwcLayer]
            validateChange(layer->getCompositionType(displayId),
                    changedTypes[hwcLayer]);
            //修改合成方式为 changedTypes[hwcLayer]
            layer->setCompositionType(displayId, changedTypes[hwcLayer], false);
        }
        //如果存在Client合成,则将hasClientComposition置为true
        //如果存在Device合成,则将hasDeviceComposition置为true
        switch (layer->getCompositionType(displayId)) {
    
    
            case HWC2::Composition::Client:
                displayData.hasClientComposition = true;
                break;
            case HWC2::Composition::Device:
            case HWC2::Composition::SolidColor:
            case HWC2::Composition::Cursor:
            case HWC2::Composition::Sideband:
                displayData.hasDeviceComposition = true;
                break;
            default:
                break;
        }
        //如果hwcLayer在layerRequests且值为ClearClientTarget
        //则设置layer的ClearClientTarget标志位,
        //表示是否需要清理Client合成结果
        //否则置为false
        if (layerRequests.count(hwcLayer) != 0 &&
                layerRequests[hwcLayer] ==
                        HWC2::LayerRequest::ClearClientTarget) {
    
    
            layer->setClearClientTarget(displayId, true);
        } else {
    
    
            ...
            layer->setClearClientTarget(displayId, false);
        }
    }
    //通知Hwc做相应修改
    error = hwcDisplay->acceptChanges();
    ...
    return NO_ERROR;
}

我们分析下presentOrValidate流程,Validate流程在presentOrValidate失败时会执行,所以在分析presentOrValidate,其实也会分析Validate流程。

//ComposerHal.cpp
Error Composer::presentOrValidateDisplay(Display display, uint32_t* outNumTypes,
                               uint32_t* outNumRequests, int* outPresentFence, uint32_t* state) {
    
    
   mWriter.selectDisplay(display);
   mWriter.presentOrvalidateDisplay();
   //提交合成显示命令给IComposer服务
   Error error = execute();

   //读取结果
   mReader.takePresentOrValidateStage(display, state);
   //如果state == 1表示 Present succeeded
   if (*state == 1) {
    
     // Present succeeded
       mReader.takePresentFence(display, outPresentFence);
   }
   //如果state == 0表示 Validate succeeded
   if (*state == 0) {
    
     // Validate succeeded.
       mReader.hasChanges(display, outNumTypes, outNumRequests);
   }

   return Error::NONE;
}

我们来分析下Composer::execute是如何提交合成显示命令的

//ComposerHal.cpp
Error Composer::execute()
{
    
    
    // prepare input command queue
    bool queueChanged = false;
    uint32_t commandLength = 0;
    hidl_vec<hidl_handle> commandHandles;
    //将mWriter的合成显示命令提交给commandHandles
    if (!mWriter.writeQueue(&queueChanged, &commandLength, &commandHandles)) {
    
    
        mWriter.reset();
        return Error::NO_RESOURCES;
    }

    // set up new input command queue if necessary
    if (queueChanged) {
    
    
        auto ret = mClient->setInputCommandQueue(*mWriter.getMQDescriptor());
        auto error = unwrapRet(ret);
        ...
    }
    //mClient 为IComposerClient代理对象
    //通过该代理对象提交合成显示命令
    Error error = kDefaultError;
    auto ret = mClient->executeCommands(commandLength, commandHandles,
            [&](const auto& tmpError, const auto& tmpOutChanged,
                const auto& tmpOutLength, const auto& tmpOutHandles)
            {
    
    
                error = tmpError;

                // set up new output command queue if necessary
               ...
            });
    ...
    return error;
}

通过上边的分析发现,只有执行Composer::execute才会将合成显示命令提交给IComposer服务做进一步的合成显示。

3. Client合成Layer渲染至FBTarget

至此每个Layer的合成显示数据及合成方式都确定了,接着调用doComposition来实现最后的合成显示

  1. 如果在prepareFrame时,已经成功显示了,则doComposition只会清理下commandbuffer
  2. 如果prepareFrame时,显示不成功,则由doComposition来完成剩余的工作,如存在client合成则调用OpenGL进行合成。
void SurfaceFlinger::doComposition() {
    
    
    ...
    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
    
    
        const sp<DisplayDevice>& hw(mDisplays[dpy]);
        if (hw->isDisplayOn()) {
    
    
            // transform the dirty region into this screen's coordinate space
            const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));

            // repaint the framebuffer (if needed)
            //主要处理client合成
            doDisplayComposition(hw, dirtyRegion);
            ...
        }
    }
    //提交合成显示命令给HWC
    postFramebuffer();
}

3.1 doDisplayComposition介绍

void SurfaceFlinger::doDisplayComposition(
        const sp<const DisplayDevice>& displayDevice,
        const Region& inDirtyRegion)
{
    
    
    // We only need to actually compose the display if:
    // 1) It is being handled by hardware composer, which may need this to
    //    keep its virtual display state machine in sync, or
    // 2) There is work to be done (the dirty region isn't empty)
    ...
    //主要是执行client合成
    //将需要Client合成的Layer全部绘制到FBTarget上
    if (!doComposeSurfaces(displayDevice, dirtyRegion)) return;
    ...
    {
    
    
        // update the swap region and clear the dirty region
        displayDevice->swapRegion.orSelf(dirtyRegion);
        // swap buffers (presentation)
        //调用eglswapbuffer,交换前后buffer
        displayDevice->swapBuffers(getHwComposer());
    }
}
bool SurfaceFlinger::doComposeSurfaces(
        const sp<const DisplayDevice>& displayDevice, const Region& dirty)
{
    
    
    ...
    //检查是否存在client合成的Layer
    bool hasClientComposition = mHwc->hasClientComposition(hwcId);
    if (hasClientComposition) {
    
    
        ...
        //eglMakeCurrent
        //glViewport(0, 0, vpw, vph);
        //获取透视矩阵mProjectionMatrix
        if (!displayDevice->makeCurrent(mEGLDisplay, mEGLContext)) {
    
    
            ...
            return false;
        }
        ...
        //检查是否存在Device合成的Layer
        const bool hasDeviceComposition = mHwc->hasDeviceComposition(hwcId);
        if (hasDeviceComposition) {
    
    
            //清理FBTarget为(0, 0, 0, 0)透明
            mRenderEngine->clearWithColor(0, 0, 0, 0);
        } else {
    
    
            //如果Layer全部是Client合成
            //计算dirty region
            ...
            // screen is already cleared here
            if (!region.isEmpty()) {
    
    
                // can happen with SurfaceView
                //清理FBTarget的region对应的区域
                drawWormhole(displayDevice, region);
            }
        }
        ...
    }
    /*
     * and then, render the layers targeted at the framebuffer
     */
    //绘制需Client合成的Layer
    if (hwcId >= 0) {
    
    
        // we're using h/w composer
        bool firstLayer = true;
        for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
    
    
            const Region clip(dirty.intersect(
                    displayTransform.transform(layer->visibleRegion)));
            ...
            if (!clip.isEmpty()) {
    
    
                switch (layer->getCompositionType(hwcId)) {
    
    
                    case HWC2::Composition::Cursor:
                    case HWC2::Composition::Device:
                    case HWC2::Composition::Sideband:
                    case HWC2::Composition::SolidColor: {
    
    
                        const Layer::State& state(layer->getDrawingState());
                        //如果ClearClientTarget为true,且不是第一个Layer
                        //说明存在其他Layer为Client合成
                        if (layer->getClearClientTarget(hwcId) && !firstLayer &&
                                layer->isOpaque(state) && (layer->getAlpha() == 1.0f)
                                && hasClientComposition) {
    
    
                            // never clear the very first layer since we're
                            // guaranteed the FB is already cleared
                            //如果Layer是Device合成,则通过OpenGL清理layer在FBTarget上的对应区域
                            layer->clearWithOpenGL(displayDevice);
                        }
                        break;
                    }
                    case HWC2::Composition::Client: {
    
    
                        //如果是Client合成,则直接调用OpenGl绘制到FBTarget,区域为clip
                        //具体opengl实现,我们就不介绍了,这一部分需要有一些opengl的知识
                        layer->draw(displayDevice, clip);
                        break;
                    }
                    default:
                        break;
                }
            }
            firstLayer = false;
        }
    }
    ...
    return true;
}

至此FBTarget绘制完成,简单总结下:

  1. 首先如果display中的Layer存在client合成,则需要绑定glcontext,设置viewport
  2. 调用opengl做一些清理工作
  3. 对client合成Layer使用OpenGL渲染合成至FBTarget上

3.2 swapBuffers介绍

至此,需client合成的Layer已经使用OpenGL渲染合成至FBTarget上了,接着需要执行swapBuffers交换前后buffer,并将渲染结果提交给Hwccomposer

void DisplayDevice::swapBuffers(HWComposer& hwc) const {
    
    
    ...
    //如果存在Client合成
    if (hwc.hasClientComposition(mHwcDisplayId) 
    		|| hwc.hasFlipFBTRequest(mHwcDisplayId)) {
    
    
        ...
        //交换前后buffer
        EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
        ...
    }
    ...
    //获取渲染结果并提交给hwc
    status_t result = mDisplaySurface->advanceFrame();
    ...
}

获取FBTarget渲染结果并提交给hwc

status_t FramebufferSurface::advanceFrame() {
    
    
   ...
    uint32_t slot = 0;
    sp<GraphicBuffer> buf;
    sp<Fence> acquireFence(Fence::NO_FENCE);
    android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN;
    //通过acquireBuffer获取bufferqueue中一个queue状态的buffer
    //后边肯定会有一个releaBuffer
    status_t result = nextBuffer(slot, buf, acquireFence, dataspace);
    ...
    return result;
}
status_t FramebufferSurface::nextBuffer(uint32_t& outSlot,
        sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence,
        android_dataspace_t& outDataspace) {
    
    
    ...
    BufferItem item;
    //通过acquireBuffer获取bufferqueue中一个queue状态的buffer
    //后边肯定会有一个releaBuffer
    status_t err = acquireBufferLocked(&item, 0);
    ...
    //通过获取的item更新mCurrentBuffer 
    mCurrentBufferSlot = item.mSlot;
    mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
    mCurrentFence = item.mFence;
    outFence = item.mFence;
   //在mHwcBufferCache中查找mCurrentBuffer并返回查找结果outBuffer、outSlot
    mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
            &outSlot, &outBuffer);
    outDataspace = item.mDataSpace;
    //设置渲染结果提交给mHwc
    status_t result =
            mHwc.setClientTarget(mDisplayType, outSlot, outFence, outBuffer, outDataspace);
   ...
    return NO_ERROR;
}
Error Composer::setClientTarget(Display display, uint32_t slot,
        const sp<GraphicBuffer>& target,
        int acquireFence, Dataspace dataspace,
        const std::vector<IComposerClient::Rect>& damage)
{
    
    
    mWriter.selectDisplay(display);
    ...
    const native_handle_t* handle = nullptr;
    if (target.get()) {
    
    
        handle = target->getNativeBuffer()->handle;
    }
    //将渲染结果写入mWriter
    mWriter.setClientTarget(slot, handle, acquireFence, dataspace, damage);
    return Error::NONE;
}

3.3 postFramebuffer()分析

至此,将渲染结果写入了mWriter,需要执行postFramebuffer将FBtarget提交给IComposer服务进行渲染

void SurfaceFlinger::postFramebuffer()
{
    
    
    ...
    const nsecs_t now = systemTime();
    mDebugInSwapBuffers = now;

    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
    
    
        auto& displayDevice = mDisplays[displayId];
        if (!displayDevice->isDisplayOn()) {
    
    
            continue;
        }
        const auto hwcId = displayDevice->getHwcDisplayId();
        if (hwcId >= 0) {
    
    
            //提交合成显示命令给IComposer
            mHwc->presentAndGetReleaseFences(hwcId);
        }
        //执行releaseBufferLocked,将buffer归还给bufferqueue中
        displayDevice->onSwapBuffersCompleted();
        displayDevice->makeCurrent(mEGLDisplay, mEGLContext);
        //更新layer的release
        for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
    
    
            ...
            sp<Fence> releaseFence = Fence::NO_FENCE;
            if (hwcId >= 0) {
    
    
                auto hwcLayer = layer->getHwcLayer(hwcId);
                releaseFence = mHwc->getLayerReleaseFence(hwcId, hwcLayer);
            }
            if (layer->getCompositionType(hwcId) == HWC2::Composition::Client) {
    
    
                releaseFence = Fence::merge("LayerRelease", releaseFence,
                        displayDevice->getClientTargetAcquireFence());
            }
            layer->onLayerDisplayed(releaseFence);
        }
        ...
    }


}

下边分析下presentAndGetReleaseFences

status_t HWComposer::presentAndGetReleaseFences(int32_t displayId) {
    
    
    ...
    auto& displayData = mDisplayData[displayId];
    auto& hwcDisplay = displayData.hwcDisplay;
    //在DisplayDevice::prepareFrame尝试直接显示的时候
    //如果直接显示成功会将displayData.validateWasSkipped置为true
    if (displayData.validateWasSkipped) {
    
    
        bool discardCommands = true;
        ...
        if (discardCommands) {
    
    
            //清理调commandbuffer,并直接返回
            hwcDisplay->discardCommands();
        }
        auto error = displayData.presentError;
        ...
        return NO_ERROR;
    }
    //至此所有Layer及FBTarget都有合成显示buffer及其他相关信息了
    //调用hwcDisplay->present执行显示
    auto error = hwcDisplay->present(&displayData.lastPresentFence);
    ...
    std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
    //获取hwc返回的releasefence
    error = hwcDisplay->getReleaseFences(&releaseFences);
    ...
    //保存到displayData.releaseFences
    displayData.releaseFences = std::move(releaseFences);

    return NO_ERROR;
}

3.4 releaseBuffer流程分析

下边分析onSwapBuffersCompleted

void DisplayDevice::onSwapBuffersCompleted() const {
    
    
    mDisplaySurface->onFrameCommitted();
}
void FramebufferSurface::onFrameCommitted() {
    
    
   if (mHasPendingRelease) {
    
    
       sp<Fence> fence = mHwc.getPresentFence(mDisplayType);
       if (fence->isValid()) {
    
    
           //更新releasefence
           status_t result = addReleaseFence(mPreviousBufferSlot,
                   mPreviousBuffer, fence);
       }
       //归还buffer给bufferqueue
       status_t result = releaseBufferLocked(mPreviousBufferSlot,
               mPreviousBuffer, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
       ...
       mPreviousBuffer.clear();
       mHasPendingRelease = false;
   }
}

5 IComposer服务响应presentOrValidateDisplay流程

前边分析了SurfaceFlinger中的合成显示流程,SurfaceFlinger会将合成显示命令提交给IComposer在继续完成合成显示。下边我们分析下
IComposer服务响应presentOrValidateDisplay的流程:

//ap\hardware\interfaces\graphics\composer\2.1\default\ComposerClient.cpp
bool ComposerClient::CommandReader::parsePresentOrValidateDisplay(uint16_t length)
{
    
    
    ...
    // First try to Present as is.
    int presentFence = -1;
    std::vector<Layer> layers;
    std::vector<int> fences;
    //mHal为HwcHal对象
    //最终会调用HWCSession::PresentDisplay
    //HWCSession是一个hwc2_device_t设备对象
    auto err = mHal.presentDisplay(mDisplay, &presentFence, &layers, &fences);
    //显示成功
    if (err == Error::NONE) {
    
    
        //设置parsePresentOrValidateDisplay结果为1
        mWriter.setPresentOrValidateResult(1);
        mWriter.setPresentFence(presentFence);
        //设置ReleaseFence
        mWriter.setReleaseFences(layers, fences);
        return true;
    }
    // Present has failed. We need to fallback to validate
    //如果显示失败,则会执行validate
    std::vector<Layer> changedLayers;
    std::vector<IComposerClient::Composition> compositionTypes;
    uint32_t displayRequestMask = 0x0;
    std::vector<Layer> requestedLayers;
    std::vector<uint32_t> requestMasks;
    //mHal为HWCSession对象
    err = mHal.validateDisplay(mDisplay, &changedLayers,
                               &compositionTypes, &displayRequestMask,
                               &requestedLayers, &requestMasks);
    if (err == Error::NONE) {
    
    
        //设置parsePresentOrValidateDisplay结果为0
        mWriter.setPresentOrValidateResult(0);
        //修改合成方式
        mWriter.setChangedCompositionTypes(changedLayers,
                                           compositionTypes);
        //设置DisplayRequests
        mWriter.setDisplayRequests(displayRequestMask,
                                   requestedLayers, requestMasks);
    } else {
    
    
        mWriter.setError(getCommandLoc(), err);
    }

    return true;
}

接着分析下HWCSession::PresentDisplay

int32_t HWCSession::PresentDisplay(hwc2_device_t *device, hwc2_display_t display,
                                   int32_t *out_retire_fence) {
    
    
  HWCSession *hwc_session = static_cast<HWCSession *>(device);
    ...
    if (hwc_session->hwc_display_[display]) {
    
    
    //hwc_display_类型有几种,我们只介绍下HWCDisplayPrimary
      status = hwc_session->hwc_display_[display]->Present(out_retire_fence);
      ...
    }
    ...
  return INT32(status);
}

接着分析下present

//ap\hardware\qcom\display\sdm\libs\hwc2\hwc_display_builtin.cpp
HWC2::Error HWCDisplayPrimary::Present(int32_t *out_retire_fence) {
    
    
  auto status = HWC2::Error::None;
  if (display_paused_) {
    
    
    ...
  } else {
    
    
    status = HWCDisplay::CommitLayerStack();
    if (status == HWC2::Error::None) {
    
    
      HandleFrameOutput();
      SolidFillCommit();
      status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
    }
  }
  pending_commit_ = false;
  return status;
}

接着分下下CommitLayerStack

//hwc_display.cpp
HWC2::Error HWCDisplay::CommitLayerStack(void) {
    
    
  ...
  DumpInputBuffers();
  ...
  //display_intf_有三种类型
  //DisplayPrimary、DisplayHDMI、DisplayVirtual
  //我们只分析下DisplayPrimary
  error = display_intf_->Commit(&layer_stack_);
  ...
  skip_validate_ = true;
  return HWC2::Error::None;
}
//display_primary.cpp
DisplayError DisplayPrimary::Commit(LayerStack *layer_stack) {
    
    
  ...
  error = DisplayBase::Commit(layer_stack);
  ...
  return error;
}
DisplayError DisplayBase::Commit(LayerStack *layer_stack) {
    
    
  ...
  DisplayError error = kErrorNone;
  ...
  DLOGI_IF(kTagDisplay, "Entering commit for display type : %d", display_type_);
  CommitLayerParams(layer_stack);
  ...
  error = comp_manager_->Commit(display_comp_ctx_, &hw_layers_);
  ...
  //hw_intf_有几种类型
  //kPrimary:HWPeripheralDRM
  //kHDMI:HWTVDRM
  //kVirtual:HWVirtualDRM
  error = hw_intf_->Commit(&hw_layers_);
  ...
  PostCommitLayerParams(layer_stack);
  ...
  error = comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
  DLOGI_IF(kTagDisplay, "Exiting commit for display type : %d", display_type_);
  return kErrorNone;
}
DisplayError HWPeripheralDRM::Commit(HWLayers *hw_layers) {
    
    
  HWLayersInfo &hw_layer_info = hw_layers->info;
  SetDestScalarData(hw_layer_info);
  return HWDeviceDRM::Commit(hw_layers);
}

最终的提交在:

//hardware\qcom\display\sdm\libs\core\drm\hw_device_drm.cpp
DisplayError HWDeviceDRM::Commit(HWLayers *hw_layers) {
    
    
  ...
  DisplayError err = kErrorNone;
  registry_.RegisterCurrent(hw_layers);
  //目前default_mode_为false
  if (default_mode_) {
    
    
    err = DefaultCommit(hw_layers);
  } else {
    
    
    err = AtomicCommit(hw_layers);
  }
  registry_.UnregisterNext();
  return err;
}

DisplayError HWDeviceDRM::AtomicCommit(HWLayers *hw_layers) {
    
    
  ...
  SetupAtomic(hw_layers, false /* validate */);
  ...
  //drm_atomic_intf_是在ap\hardware\qcom\display\libdrmutils\drm_lib_loader.cpp中
  //通过dlopen(libsdedrm.so)获取的方法
  //libsdedrm.so源码高通并未开源
  int ret = drm_atomic_intf_->Commit(false /* synchronous */, false /* retain_planes*/);

  int release_fence = -1;
  int retire_fence = -1;

  drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, &release_fence);
  drm_atomic_intf_->Perform(DRMOps::CONNECTOR_GET_RETIRE_FENCE, token_.conn_id, &retire_fence);
  ...
  return kErrorNone;
}

在继续分析前需要先了解几个结构体

/*! @brief This structure defines a layer stack that contains layers which need to be composed and
  rendered onto the target.
*/
struct LayerStack {
    
    
  std::vector<Layer *> layers = {
    
    };    //!< Vector of layer pointers.
  ...
}
/*! @brief This structure defines display layer object which contains layer properties and a drawing
  buffer.

  @sa LayerArray
*/
struct Layer {
    
    
  LayerBuffer input_buffer = {
    
    };                   //!< Buffer to be composed.
                                                   //!< If this remains unchanged between two
                                                   //!< consecutive Prepare() calls and
                                                   //!< geometry_changed flag is not set for the
                                                   //!< second call, then the display device will
                                                   //!< assume that buffer content has not
                                                   //!< changed.

  LayerComposition composition = kCompositionGPU;  //!< Composition type which can be set by either
                                                   //!< the client or the display device. This value
                                                   //!< should be preserved between Prepare() and
                                                   //!< Commit() calls.

  LayerRect src_rect = {
    
    };                         //!< Rectangular area of the layer buffer to
                                                   //!< consider for composition.

  LayerRect dst_rect = {
    
    };                         //!< The target position where the frame will be
                                                   //!< displayed. Cropping rectangle is scaled to
                                                   //!< fit into this rectangle. The origin is the
                                                   //!< top-left corner of the screen.

  std::vector<LayerRect> visible_regions = {
    
    };     //!< Visible rectangular areas in screen space.
                                                   //!< The visible region includes areas overlapped
                                                   //!< by a translucent layer.

  std::vector<LayerRect> dirty_regions = {
    
    };       //!< Rectangular areas in the current frames
                                                   //!< that have changed in comparison to
                                                   //!< previous frame.

  std::vector<LayerRect> blit_regions = {
    
    };        //!< Rectangular areas of this layer which need
                                                   //!< to be composed to blit target. Display
                                                   //!< device will update blit rectangles if a
                                                   //!< layer composition is set as hybrid. Nth blit
                                                   //!< rectangle shall be composed onto Nth blit
                                                   //!< target.

  LayerBlending blending = kBlendingPremultiplied;  //!< Blending operation which need to be
                                                    //!< applied on the layer buffer during
                                                    //!< composition.

  LayerTransform transform = {
    
    };                   //!< Rotation/Flip operations which need to be
                                                   //!< applied to the layer buffer during
                                                   //!< composition.

  uint8_t plane_alpha = 0xff;                      //!< Alpha value applied to the whole layer.
                                                   //!< Value of each pixel is computed as:
                                                   //!<    if(kBlendingPremultiplied) {
    
    
                                                   //!<      pixel.RGB = pixel.RGB * planeAlpha/255
                                                   //!<    }
                                                   //!<    pixel.a = pixel.a * planeAlpha

  uint32_t frame_rate = 0;                         //!< Rate at which frames are being updated for
                                                   //!< this layer.

  uint32_t solid_fill_color = 0;                   //!< TODO: Remove this field when fb support
                                                   //!  is deprecated.
                                                   //!< Solid color used to fill the layer when
                                                   //!< no content is associated with the layer.

  LayerFlags flags;                                //!< Flags associated with this layer.

  LayerRequest request = {
    
    };                       //!< o/p - request on this Layer by SDM.

  Lut3d lut_3d = {
    
    };                               //!< o/p - Populated by SDM when tone mapping is
                                                   //!< needed on this layer.
  LayerSolidFill solid_fill_info = {
    
    };             //!< solid fill info along with depth.
}

  1. 图片来源于https://www.jianshu.com/p/824a9ddf68b9,如有侵权,请告知删除,谢谢。 ↩︎

猜你喜欢

转载自blog.csdn.net/u010116586/article/details/107840156