Android P 显示流程分析---界面刷新

Posted Give.Me.Five

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android P 显示流程分析---界面刷新相关的知识,希望对你有一定的参考价值。

上篇分析到SurfaceFlinger.signalRefresh()里会调用到SurfaceFlinger里的handleMessageRefresh(), 现在这里面开始涉及到图层合成了,这里面涉及的流程。

handleMessageRefresh()

void SurfaceFlinger::handleMessageRefresh() 
    mRefreshPending = false;
    nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
	//合成图像前的准备工作,设置各种状态
    preComposition(refreshStartTime);
    //重建可见区域的所有图层
    rebuildLayerStacks();
    //启动硬件图像合成
    setUpHWComposer();
    //调试信息
    doDebugFlashRegions();
    doTracing("handleRefresh");
    logLayerStats();
    //合成处理
    doComposition();
    //更新状态与下次合成时间
    postComposition(refreshStartTime);

上面重点的就是两块,一个setupHWComposer() 启动硬件图像合成, 另一个是doComposition()合成处理。

setUpHWComposer()

void SurfaceFlinger::setUpHWComposer() 
...
    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());
                //遍历当前显示设备的所有图层
                for (size_t i = 0; i < currentLayers.size(); i++) 
                    const auto& layer = currentLayers[i];
                    if (!layer->hasHwcLayer(hwcId)) 
                    	//如果没有硬件图层,则创建一个硬件图层
                        if (!layer->createHwcLayer(getBE().mHwc.get(), hwcId)) 
                            layer->forceClientComposition(hwcId);
                            continue;
                        
                    
					//设置图层大小,坐标
                    layer->setGeometry(displayDevice, i);
                    if (mDebugDisableHWC || mDebugRegion) 
                        layer->forceClientComposition(hwcId);
                    
                
            
        
    // Set the per-frame data
    //遍历所有显示屏
    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) 
        auto& displayDevice = mDisplays[displayId];
        const auto hwcId = displayDevice->getHwcDisplayId();

        if (hwcId < 0) 
            continue;
        
        //更新颜色变化
        if (mDrawingState.colorMatrixChanged) 
            displayDevice->setColorTransform(mDrawingState.colorMatrix);
            status_t result = getBE().mHwc->setColorTransform(hwcId, mDrawingState.colorMatrix);
            ALOGE_IF(result != NO_ERROR, "Failed to set color transform on "
                    "display %zd: %d", displayId, result);
        
        //遍历当前显示屏的所有图层
        for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) 
        	//设置数据存储格式
            if (layer->isHdrY410()) 
                layer->forceClientComposition(hwcId);
             else if ((layer->getDataSpace() == Dataspace::BT2020_PQ ||
                        layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) &&
                    !displayDevice->hasHDR10Support()) 
                layer->forceClientComposition(hwcId);
             else if ((layer->getDataSpace() == Dataspace::BT2020_HLG ||
                        layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) &&
                    !displayDevice->hasHLGSupport()) 
                layer->forceClientComposition(hwcId);
            
			//设置图层合成类型
            if (layer->getForceClientComposition(hwcId)) 
                ALOGV("[%s] Requesting Client composition", layer->getName().string());
                layer->setCompositionType(hwcId, HWC2::Composition::Client);
                continue;
            
			//图层的数据设置到显示器
            layer->setPerFrameData(displayDevice);
        
		//设置颜色模式
        if (hasWideColorDisplay) 
            ColorMode colorMode;
            Dataspace dataSpace;
            RenderIntent renderIntent;
            pickColorMode(displayDevice, &colorMode, &dataSpace, &renderIntent);
            setActiveColorModeInternal(displayDevice, colorMode, dataSpace, renderIntent);
        
     
    mDrawingState.colorMatrixChanged = false;
	//遍历所有显示屏设备,做了prepareFrame
    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) 
        auto& displayDevice = mDisplays[displayId];
        if (!displayDevice->isDisplayOn()) 
            continue;
        

        status_t result = displayDevice->prepareFrame(*getBE().mHwc);
        ALOGE_IF(result != NO_ERROR, "prepareFrame for display %zd failed:"
                " %d (%s)", displayId, result, strerror(-result));
           
    

因为setUpHWComposer()里做的事情很多,我们一个一个来撸下:

  1. layer->createHwcLayer(getBE().mHwc.get(), hwcId)

    --> HWComposer->createLayer(hwcId)
    

按照我们《Android P 显示流程(一)—Display设备初始化过程分析》
后续最终会调用到HWC2On1Adapter里的createLayer的方法:

Error HWC2On1Adapter::Display::createLayer(hwc2_layer_t* outLayerId) 
    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
	//通过当前Display对象,创建一个新的layer对象,最后添加到mLayers 容器中
    auto layer = *mLayers.emplace(std::make_shared<Layer>(*this));
    mDevice.mLayers.emplace(std::make_pair(layer->getId(), layer));
    *outLayerId = layer->getId();
    ALOGV("[%" PRIu64 "] created layer %" PRIu64, mId, *outLayerId);
    markGeometryChanged();
    return Error::None;

  1. layer->setGeometry(displayDevice, i)
    设置图层大小和坐标位置,这个不是重点,我们就不往下分析了,后面更新颜色矩阵变化也直接跳过

  2. 后面有遍历显示屏的所有图层,设置数据存储格式也跳过不研究,来看看设置合成类型。

void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc) 
    auto& hwcInfo = getBE().mHwcLayers[hwcId];
    auto& hwcLayer = hwcInfo.layer;	
    //判读与目前此图层的合成类型是否一致,如果不一致,更改合成类型
    if (hwcInfo.compositionType != type) 
        ALOGV("    actually setting");
        hwcInfo.compositionType = type;
        if (callIntoHwc) 
            auto error = hwcLayer->setCompositionType(type);
        
    

Error Layer::setCompositionType(Composition type)

    auto intType = static_cast<Hwc2::IComposerClient::Composition>(type);
    auto intError = mComposer.setLayerCompositionType(
            mDisplayId, mId, intType);
    return static_cast<Error>(intError);

//同之前分析的流程,最后会调用到HWC2On1Adapter里面
Error HWC2On1Adapter::Layer::setCompositionType(Composition type)

    mCompositionType.setPending(type);
    return Error::None;
                

这个设置图层的类型,那图层到底有哪些类型呢?

  • Composition::Client
  • Composition::Device
  • Composition::SolidColor
  • Composition::Cursor
  • Composition::Sideband
    上面这几种Composition 类型到底有什么区别呢,看看applyCompositionType:
void HWC2On1Adapter::Layer::applyCompositionType(hwc_layer_1_t& hwc1Layer,
        bool applyAllState)

    // HWC1 never supports color transforms or dataspaces and only sometimes
    // supports plane alpha (depending on the version). These require us to drop
    // some or all layers to client composition.
    if (mHasUnsupportedDataspace || mHasUnsupportedPlaneAlpha ||
            mDisplay.hasColorTransform()) 
        hwc1Layer.compositionType = HWC_FRAMEBUFFER;
        hwc1Layer.flags = HWC_SKIP_LAYER;
        return;
    

    if (applyAllState || mCompositionType.isDirty()) 
        hwc1Layer.flags = 0;
        switch (mCompositionType.getPendingValue()) 
            case Composition::Client:
                hwc1Layer.compositionType = HWC_FRAMEBUFFER;
                hwc1Layer.flags |= HWC_SKIP_LAYER;
                break;
            case Composition::Device:
                hwc1Layer.compositionType = HWC_FRAMEBUFFER;
                break;
            case Composition::SolidColor:
                // In theory the following line should work, but since the HWC1
                // version of SurfaceFlinger never used HWC_BACKGROUND, HWC1
                // devices may not work correctly. To be on the safe side, we
                // fall back to client composition.
                //
                // hwc1Layer.compositionType = HWC_BACKGROUND;
                hwc1Layer.compositionType = HWC_FRAMEBUFFER;
                hwc1Layer.flags |= HWC_SKIP_LAYER;
                break;
            case Composition::Cursor:
                hwc1Layer.compositionType = HWC_FRAMEBUFFER;
                if (mDisplay.getDevice().getHwc1MinorVersion() >= 4) 
                    hwc1Layer.hints |= HWC_IS_CURSOR_LAYER;
                
                break;
            case Composition::Sideband:
                if (mDisplay.getDevice().getHwc1MinorVersion() < 4) 
                    hwc1Layer.compositionType = HWC_SIDEBAND;
                 else 
                    hwc1Layer.compositionType = HWC_FRAMEBUFFER;
                    hwc1Layer.flags |= HWC_SKIP_LAYER;
                
                break;
            default:
                hwc1Layer.compositionType = HWC_FRAMEBUFFER;
                hwc1Layer.flags |= HWC_SKIP_LAYER;
                break;
        
        ALOGV("Layer %" PRIu64 " %s set to %d", mId,
                to_string(mCompositionType.getPendingValue()).c_str(),
                hwc1Layer.compositionType);
        ALOGV_IF(hwc1Layer.flags & HWC_SKIP_LAYER, "    and skipping");
        mCompositionType.latch();
    

这几种虽然不一样,但对应的hwc1Layer.compositionType都是HWC_FRAMEBUFFER,实际上对应HAL层的实现没什么区别。

  1. 每个图层设置每帧的数据
    layer->setPerFrameData(displayDevice)
    但图层又分BufferLayer和ColorLayer,这两路图层有什么区别呢?
        const sp<Client>& client,
        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
        int32_t windowType, int32_t ownerUid, sp<IBinder>* handle,
        sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent)

 switch (flags & ISurfaceComposerClient::eFXSurfaceMask) 
        case ISurfaceComposerClient::eFXSurfaceNormal:
            result = createBufferLayer(client,
                    uniqueName, w, h, flags, format,
                    handle, gbp, &layer);

            break;
        case ISurfaceComposerClient::eFXSurfaceColor:
            result = createColorLayer(client,
                    uniqueName, w, h, flags,
                    handle, &layer);
            break;
        default:
            result = BAD_VALUE;
            ...

创建图层时,根据Flag 的不同来创建图层的,一种是纯色的,一种是普通数据显示的图层,这里我们一般指的是BufferLayer.
那继续看BufferLayer的setPerFrameData的函数:

void BufferLayer::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 = getBE().mHwcLayers[hwcId];
    auto& hwcLayer = hwcInfo.layer;
    //设置可见区域
    auto error = hwcLayer->setVisibleRegion(visible);
    if (error != HWC2::Error::None) 
        ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(),
              to_string(error).c_str(), static_cast<int32_t>(error));
        visible.dump(LOG_TAG);
    
	//设置损坏区域
    error = hwcLayer->setSurfaceDamage(surfaceDamageRegion);
    if (error != HWC2::Error::None) 
        ALOGE("[%s] Failed to set surface damage: %s (%d)", mName.string(),
              to_string(error).c_str(), static_cast<int32_t>(error));
        surfaceDamageRegion.dump(LOG_TAG);
    

    //如果是sideband 图层,直接设置sideband流,然后就返回了
    if (getBE().compositionInfo.hwc.sidebandStream.get()) 
        setCompositionType(hwcId, HWC2::Composition::Sideband);
        ALOGV("[%s] Requesting Sideband composition", mName.string());
        error = hwcLayer->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle());
        if (error != HWC2::Error::None) 
            ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(),
                  getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(),
                  static_cast<int32_t>(error));
        
        return;
    

	//如果是设备或光标图层,设置相对应的CompositionType
    // Device or Cursor layers
    if (mPotentialCursor) 
        ALOGV("[%s] Requesting Cursor composition", mName.string());
        setCompositionType(hwcId, HWC2::Composition::Cursor);
     else 
        ALOGV("[%s] Requesting Device composition", mName.string());
        setCompositionType(hwcId, HWC2::Composition::Device);
    
	//设置Dataspace
    ALOGV("setPerFrameData: dataspace = %d", mCurrentDataSpace);
    error = hwcLayer->setDataspace(mCurrentDataSpace);
    if (error != HWC2::Error::None) 
        ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace,
              to_string(error).c_str(), static_cast以上是关于Android P 显示流程分析---界面刷新的主要内容,如果未能解决你的问题,请参考以下文章

Android P 显示流程分析---EventThread MessageQueue 交互分析

Android P 显示流程---Display设备初始化过程分析

Android P 显示流程分析---获取显示屏配置

Android P 显示流程分析--- buffer的生产消费者模式

Android P 显示流程分析--- buffer的生产消费者模式

Android Q 基站刷新接口源码分析 & 适配双卡手机基站刷新逻辑