Android9.0 CompositionType分析

1.adb shell dumpsys SurfaceFlinger

dump時(shí)會(huì)打印出是HWC合成還是GPU合成,androidO開始HWC換成了Device,GPU換成了Client。

2.問題場景

打開 Settings -> Accessibility -> Color inversion 后冷啟動(dòng)應(yīng)用會(huì)出現(xiàn)閃白屏。
在androidO上該問題是原生問題,但是在androidP上不再是原生問題。
通過dump SurfaceFlinger發(fā)現(xiàn)問題場景下為Client合成方式,而正常時(shí)為Device合成方式。
google原生解釋理由:
The reason is that the surface of the app has been created, but the app does not send the data that needs to be displayed to the surfaceflinger in time, and waits for a few frames before starting to update. In this case, the surfaceflinger has no valid data, and it shows black surface. If it is a reverse color(using Invert colours option), we will see a white surface twinkling.

3.分析CompositionType

1) 在prepare的時(shí)候會(huì)去設(shè)置frame data到hwc hal中,會(huì)傳入compositionType,根據(jù)下面的代碼可以看出默認(rèn)是有四種方式的:Sideband、Cursor、Device、SolidColor。

frameworks/native/services/surfaceflinger/BufferLayer.cpp
618void BufferLayer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) {
...
641    // Sideband layers
642    if (getBE().compositionInfo.hwc.sidebandStream.get()) {
643        setCompositionType(hwcId, HWC2::Composition::Sideband);
644        ALOGV("[%s] Requesting Sideband composition", mName.string());
645        error = hwcLayer->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle());
646        if (error != HWC2::Error::None) {
647            ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(),
648                  getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(),
649                  static_cast<int32_t>(error));
650        }
651        return;
652    }
653
654    // Device or Cursor layers
655    if (mPotentialCursor) {
656        ALOGV("[%s] Requesting Cursor composition", mName.string());
657        setCompositionType(hwcId, HWC2::Composition::Cursor);
658    } else {
659        ALOGV("[%s] Requesting Device composition", mName.string());
660        setCompositionType(hwcId, HWC2::Composition::Device);
661    }

frameworks/native/services/surfaceflinger/ColorLayer.cpp
64void ColorLayer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) {
...
78    setCompositionType(hwcId, HWC2::Composition::SolidColor);

還有一個(gè)地方會(huì)強(qiáng)制設(shè)置compositionType為Client。
hwc Hal層的layer創(chuàng)建失??;禁用HWC;打開debugRegion;layer的一些特殊屬性等會(huì)設(shè)置compositionType為Client到hwc hal中。

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
1959void SurfaceFlinger::setUpHWComposer() {
...
2003                    if (!layer->hasHwcLayer(hwcId)) {
2004                        if (!layer->createHwcLayer(getBE().mHwc.get(), hwcId)) {
2005                            layer->forceClientComposition(hwcId);
2006                            continue;
2007                        }
2008                    }
2009
2010                    layer->setGeometry(displayDevice, i);
2011                    if (mDebugDisableHWC || mDebugRegion) {
2012                        layer->forceClientComposition(hwcId);
2013                    }
...
2033        for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
2034            if (layer->isHdrY410()) {
2035                layer->forceClientComposition(hwcId);
2036            } else if ((layer->getDataSpace() == Dataspace::BT2020_PQ ||
2037                        layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) &&
2038                    !displayDevice->hasHDR10Support()) {
2039                layer->forceClientComposition(hwcId);
2040            } else if ((layer->getDataSpace() == Dataspace::BT2020_HLG ||
2041                        layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) &&
2042                    !displayDevice->hasHLGSupport()) {
2043                layer->forceClientComposition(hwcId);
2044            }
2045
2046            if (layer->getForceClientComposition(hwcId)) {
2047                ALOGV("[%s] Requesting Client composition", layer->getName().string());
2048                layer->setCompositionType(hwcId, HWC2::Composition::Client);
2049                continue;
2050            }

那么我們分析下Layer的setCompositionType,會(huì)根據(jù)callIntoHwc去決定是否將compositionType設(shè)置到hwc hal中,surfaceflinger第一次會(huì)向hwc hal中設(shè)置compositionType(callIntoHwc為true),hwc hal會(huì)返回給surfaceflinger側(cè)compositionType改變的值(androidO上新增mChangeType),如果有改變的話只需要改變surfaceflinger側(cè)即可,無需往hwc hal再設(shè)置compositionType(callIntoHwc為false),這個(gè)后面會(huì)分析。

frameworks/native/services/surfaceflinger/Layer.cpp
730void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc) {
731    if (getBE().mHwcLayers.count(hwcId) == 0) {
732        ALOGE("setCompositionType called without a valid HWC layer");
733        return;
734    }
735    auto& hwcInfo = getBE().mHwcLayers[hwcId];
736    auto& hwcLayer = hwcInfo.layer;
737    ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(), to_string(type).c_str(),
738          static_cast<int>(callIntoHwc));
739    if (hwcInfo.compositionType != type) {
740        ALOGV("    actually setting");
741        hwcInfo.compositionType = type;
742        if (callIntoHwc) {
743            auto error = hwcLayer->setCompositionType(type);
744            ALOGE_IF(error != HWC2::Error::None,
745                     "[%s] Failed to set "
746                     "composition type %s: %s (%d)",
747                     mName.string(), to_string(type).c_str(), to_string(error).c_str(),
748                     static_cast<int32_t>(error));
749        }
750    }
751}

最后,分析下hwc hal返回的結(jié)果。
在hwc hal層結(jié)束了prepare操作后,surfaceflinger側(cè)會(huì)調(diào)用getChangedCompositionTypes得到底層更改后的compositionType,hwc hal層會(huì)實(shí)現(xiàn)getChangedCompositionTypes方法,當(dāng)有改變的話changedTypes.count(hwcLayer)不為0,這樣的話會(huì)向layer中重新設(shè)置compositionType,但是此時(shí)的callIntoHwc為false,即不向hwc hal層中設(shè)置。
同時(shí),HWComposer中通過DisplayDate保存compositionType,注意只有兩種:hasClientComposition、hasDeviceComposition。

frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
406status_t HWComposer::prepare(DisplayDevice& displayDevice) {
...
456        error = hwcDisplay->validate(&numTypes, &numRequests);
463    std::unordered_map<HWC2::Layer*, HWC2::Composition> changedTypes;
464    changedTypes.reserve(numTypes);
465    error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
477    for (auto& layer : displayDevice.getVisibleLayersSortedByZ()) {
478        auto hwcLayer = layer->getHwcLayer(displayId);
479
480        if (changedTypes.count(hwcLayer) != 0) {
481            // We pass false so we only update our state and don't call back
482            // into the HWC device
483            validateChange(layer->getCompositionType(displayId),
484                    changedTypes[hwcLayer]);
485            layer->setCompositionType(displayId, changedTypes[hwcLayer], false);
486        }
488        switch (layer->getCompositionType(displayId)) {
489            case HWC2::Composition::Client:
490                displayData.hasClientComposition = true;
491                break;
492            case HWC2::Composition::Device:
493            case HWC2::Composition::SolidColor:
494            case HWC2::Composition::Cursor:
495            case HWC2::Composition::Sideband:
496                displayData.hasDeviceComposition = true;
497                break;
498            default:
499                break;
500        }

4.結(jié)論

有些平臺(tái)hwc可以很好的支持這種場景的合成,而有些平臺(tái)不支持的話就出現(xiàn)了問題。
至于底層如何實(shí)現(xiàn)的,這里就不方便貼出來了,自行研究~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容