Android Surface對應的Buffer怎么傳遞給HWC

Android Surface對應的Buffer怎么傳遞給HWC



引言

因為要預研Android Video overlay,需要將SurfaceView對應的GraphicBuffer從drm_hwcomposer中剝離出來,這就需要們了解SurfaceView對應的GraphicBuffer的前世今生,以及它的數據流向以及在各個模塊之間的對應關系。這篇博客,我們分析下該GraphicBuffer是如何傳遞到HWC的。

參考源碼基于Android 13 AOSP!



Surface的Buffer是怎么傳遞給HWC呢

我們通過代碼流程來看看:

using LayerFESet = std::unordered_set<sp<LayerFE>, LayerFESpHash>;
SurfaceFlinger::composite(...)compositionengine::CompositionRefreshArgs refreshArgs;  mDrawingState.traverseInZOrder([&refreshArgs](Layer* layer) {if (auto layerFE = layer->getCompositionEngineLayerFE())refreshArgs.layers.push_back(layerFE);});        android::compositionengine::impl::CompositionEngine::presentLayerFESet latchedLayers;for (const auto& output : args.outputs) {output->prepare(args, latchedLayers);//impl::OutputrebuildLayerStacks(refreshArgs, geomSnapshots)compositionengine::Output::CoverageState coverage{layerFESet};collectVisibleLayers(refreshArgs, coverage);                    for (auto layer : reversed(refreshArgs.layers)) {ensureOutputLayerIfVisible(layer, coverage);if (!coverage.latchedLayers.count(layerFE)) {coverage.latchedLayers.insert(layerFE);layerFE->prepareCompositionState(compositionengine::LayerFE::StateSubset::BasicGeometry);}                                if (!coverage.latchedLayers.count(layerFE)) {coverage.latchedLayers.insert(layerFE);layerFE->prepareCompositionState(compositionengine::LayerFE::StateSubset::BasicGeometry);}const auto* layerFEState = layerFE->getCompositionState();ensureOutputLayer(prevOutputLayerIndex, layerFE)}               }           updateLayerStateFromFE(args)for (const auto& output : args.outputs) {output->present(args);//impl::Output frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cppupdateCompositionState(refreshArgs)writeCompositionState(refreshArgs)//impl::Outputlayer->writeStateToHWC(...)//impl::OutputLayerwriteOutputIndependentPerFrameStateToHWC(...)writeBufferStateToHWC(...)hwcLayer->setBuffer(...)//HWC2::impl::LayermComposer.setLayerBuffer(...)//Hwc2::impl::Composer}    

這里output實際上是Display,但是Display中沒有實現prepare,因為Display繼承自Output,使用的是父類Output的prepare方法。




ensureOutputLayerIfVisible

這里我們看下ensureOutputLayerIfVisible的作用,主要是構建出來看見的OutputLayer.

//frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
void Output::ensureOutputLayerIfVisible(sp<compositionengine::LayerFE>& layerFE,compositionengine::Output::CoverageState& coverage) layerFE->prepareCompositionState(compositionengine::LayerFE::StateSubset::BasicGeometry)const auto* layerFEState = layerFE->getCompositionState()//圖層可見。如果我們有輸出圖層,可以重復使用現有的輸出圖層。則重用現有的輸出層,否則創建一個新的輸出層auto result = ensureOutputLayer(prevOutputLayerIndex, layerFE)///frameworks/native/services/surfaceflinger/Layer.cpp   
Layer::prepareCompositionState(compositionengine::LayerFE::StateSubset subset) // 傳入的參數是BasicGeometryprepareBasicGeometryCompositionState()void Layer::prepareBasicGeometryCompositionState() {const auto& drawingState{getDrawingState()};const auto alpha = static_cast<float>(getAlpha());const bool opaque = isOpaque(drawingState);const bool usesRoundedCorners = hasRoundedCorners();auto blendMode = Hwc2::IComposerClient::BlendMode::NONE;if (!opaque || alpha != 1.0f) {blendMode = mPremultipliedAlpha ? Hwc2::IComposerClient::BlendMode::PREMULTIPLIED: Hwc2::IComposerClient::BlendMode::COVERAGE;}auto* compositionState = editCompositionState();//實現在BufferLayer中,獲取的是LayerFECompositionStatecompositionState->outputFilter = getOutputFilter();compositionState->isVisible = isVisible();compositionState->isOpaque = opaque && !usesRoundedCorners && alpha == 1.f;compositionState->shadowRadius = mEffectiveShadowRadius;compositionState->contentDirty = contentDirty;contentDirty = false;compositionState->geomLayerBounds = mBounds;compositionState->geomLayerTransform = getTransform();compositionState->geomInverseLayerTransform = compositionState->geomLayerTransform.inverse();compositionState->transparentRegionHint = getActiveTransparentRegion(drawingState);compositionState->blendMode = static_cast<Hwc2::IComposerClient::BlendMode>(blendMode);compositionState->alpha = alpha;compositionState->backgroundBlurRadius = drawingState.backgroundBlurRadius;compositionState->blurRegions = drawingState.blurRegions;compositionState->stretchEffect = getStretchEffect();
}

如果可見,需要生成一個outputLayer,放在mPendingOutputLayersOrderedByZ

這里我們對該函數單獨站看來分析下,ensureOutputLayer將創建Output layer,不是所有layer都會創建對應的hwc layer,創建出來的這些layer最后是要顯示到屏幕上的。

//frameworks/native/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.hOutputLayer* ensureOutputLayer(std::optional<size_t> prevIndex,const sp<LayerFE>& layerFE) {// 判斷當前的outputlayer 集合里面有沒有當前的layer,如果沒有則新創建一個auto outputLayer = (prevIndex && *prevIndex <= mCurrentOutputLayersOrderedByZ.size())? std::move(mCurrentOutputLayersOrderedByZ[*prevIndex]): BaseOutput::createOutputLayer(layerFE);auto result = outputLayer.get();mPendingOutputLayersOrderedByZ.emplace_back(std::move(outputLayer));return result;}//frameworks/native/services/surfaceflinger/CompositionEngine/src/Display.cppstd::unique_ptr<compositionengine::OutputLayer> Display::createOutputLayer(const sp<compositionengine::LayerFE>& layerFE) const {auto result = impl::createOutputLayer(*this, layerFE);if (result && mId) {auto& hwc = getCompositionEngine().getHwComposer();auto displayId = *mId;// 創建hwclayerauto hwcLayer = std::shared_ptr<HWC2::Layer>(hwc.createLayer(displayId),[&hwc, displayId](HWC2::Layer* layer) {hwc.destroyLayer(displayId, layer);});ALOGE_IF(!hwcLayer, "Failed to create a HWC layer for a HWC supported display %s",getName().c_str());// 更新state.hwcresult->setHwcLayer(std::move(hwcLayer));}return result;
}        

到這里就完成了OutputLayer和hwc layer的創建。




updateLayerStateFromFE

Update the composition state from each front-end layer更新各前端層的組成狀態,我們來看其實現:

//frameworks/native/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
void CompositionEngine::updateLayerStateFromFE(CompositionRefreshArgs& args) {// Update the composition state from each front-end layerfor (const auto& output : args.outputs) {output->updateLayerStateFromFE(args);}
}
void Output::updateLayerStateFromFE(const CompositionRefreshArgs& args) const {for (auto* layer : getOutputLayersOrderedByZ()) {//這個傳遞的參數是GeometryAndContentlayer->getLayerFE().prepareCompositionState(args.updatingGeometryThisFrame ? LayerFE::StateSubset::GeometryAndContent: LayerFE::StateSubset::Content);}//frameworks/native/services/surfaceflinger/Layer.cpp
Layer::prepareCompositionState(compositionengine::LayerFE::StateSubset subset)case StateSubset::GeometryAndContent:prepareBasicGeometryCompositionState();//將相關Layer信息,放到Layer對應的LAyerFEcompositionStateprepareGeometryCompositionState();preparePerFrameCompositionState();//重點看下這個,調用子類的break;    //frameworks/native/services/surfaceflinger/BufferLayer.cpp
void BufferLayer::preparePerFrameCompositionState() {Layer::preparePerFrameCompositionState();// Sideband layersauto* compositionState = editCompositionState();if (compositionState->sidebandStream.get() && !compositionState->sidebandStreamHasFrame) {compositionState->compositionType =aidl::android::hardware::graphics::composer3::Composition::SIDEBAND;return;} else if ((mDrawingState.flags & layer_state_t::eLayerIsDisplayDecoration) != 0) {compositionState->compositionType =aidl::android::hardware::graphics::composer3::Composition::DISPLAY_DECORATION;} else {// Normal buffer layerscompositionState->hdrMetadata = mBufferInfo.mHdrMetadata;compositionState->compositionType = mPotentialCursor? aidl::android::hardware::graphics::composer3::Composition::CURSOR: aidl::android::hardware::graphics::composer3::Composition::DEVICE;}compositionState->buffer = getBuffer();//將從App傳遞過來的渲染之后的GraphicBuffer保存在LayerFEcompositionState中compositionState->bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT)? 0: mBufferInfo.mBufferSlot;compositionState->acquireFence = mBufferInfo.mFence;compositionState->frameNumber = mBufferInfo.mFrameNumber;compositionState->sidebandStreamHasFrame = false;
}



updateCompositionState

這個函數的主要作用是什么呢,什么呢?我先分析下,再告訴你!

//frameworks/native/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
void Output::updateCompositionState(const compositionengine::CompositionRefreshArgs& refreshArgs) {...for (auto* layer : getOutputLayersOrderedByZ()) {layer->updateCompositionState(refreshArgs.updatingGeometryThisFrame,refreshArgs.devOptForceClientComposition ||forceClientComposition,refreshArgs.internalDisplayRotationFlags);}    ...
}void OutputLayer::updateCompositionState(bool includeGeometry, bool forceClientComposition,ui::Transform::RotationFlags internalDisplayRotationFlags) {const auto* layerFEState = getLayerFE().getCompositionState();if (!layerFEState) {return;}const auto& outputState = getOutput().getState();const auto& profile = *getOutput().getDisplayColorProfile();auto& state = editState();//這里指向的是OutputLayerCompositionStateif (includeGeometry) {state.forceClientComposition = false;state.displayFrame = calculateOutputDisplayFrame();state.sourceCrop = calculateOutputSourceCrop(internalDisplayRotationFlags);state.bufferTransform = static_cast<Hwc2::Transform>(calculateOutputRelativeBufferTransform(internalDisplayRotationFlags));if ((layerFEState->isSecure && !outputState.isSecure) ||(state.bufferTransform & ui::Transform::ROT_INVALID)) {state.forceClientComposition = true;}}state.dataspace = layerFEState->isColorspaceAgnostic &&outputState.targetDataspace != ui::Dataspace::UNKNOWN? outputState.targetDataspace: layerFEState->dataspace;if (outputState.treat170mAsSrgb && !layerFEState->isColorspaceAgnostic &&(state.dataspace & HAL_DATASPACE_TRANSFER_MASK) == HAL_DATASPACE_TRANSFER_SMPTE_170M) {state.dataspace = static_cast<ui::Dataspace>((state.dataspace & HAL_DATASPACE_STANDARD_MASK) |(state.dataspace & HAL_DATASPACE_RANGE_MASK) | HAL_DATASPACE_TRANSFER_SRGB);}if (isHdrDataspace(state.dataspace) ||getOutput().getState().displayBrightnessNits == getOutput().getState().sdrWhitePointNits ||getOutput().getState().displayBrightnessNits == 0.f || !layerFEState->dimmingEnabled) {state.dimmingRatio = 1.f;state.whitePointNits = getOutput().getState().displayBrightnessNits;} else {state.dimmingRatio = std::clamp(getOutput().getState().sdrWhitePointNits /getOutput().getState().displayBrightnessNits,0.f, 1.f);state.whitePointNits = getOutput().getState().sdrWhitePointNits;}if (layerFEState->forceClientComposition || !profile.isDataspaceSupported(state.dataspace) ||forceClientComposition) {state.forceClientComposition = true;}
}

這塊竟然沒有將LayerFErCompositionState對應的GraphicBuffer傳遞給OutputLayerCompositionState。并且為啥要搞這么多State的狀態呢,感覺有點多余!




writeCompositionState

該函數的核心功能就是設置outputlayer的dispFrame和sourceCrop等以及將outputlayer屬性設給hwc。

//frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
void Output::writeCompositionState(const compositionengine::CompositionRefreshArgs& refreshArgs) {for (auto* layer : getOutputLayersOrderedByZ()) {layer->writeStateToHWC(includeGeometry, skipLayer, z++, overrideZ, isPeekingThrough)}
}///frameworks/native/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
void OutputLayer::writeStateToHWC(bool includeGeometry, bool skipLayer, uint32_t z,bool zIsOverridden, bool isPeekingThrough) {const auto& state = getState();//這里獲取的是OutputLayerCompositionStateauto& hwcLayer = (*state.hwc).hwcLayerconst auto* outputIndependentState = getLayerFE().getCompositionState();//這里得到的是LayerFECompostionStatewriteOutputIndependentPerFrameStateToHWC(hwcLayer.get(), *outputIndependentState,requestedCompositionType, skipLayer)writeBufferStateToHWC(hwcLayer, outputIndependentState, skipLayer)sp<GraphicBuffer> buffer = outputIndependentState.buffer;sp<Fence> acquireFence = outputIndependentState.acquireFence;int slot = outputIndependentState.bufferSlot;if (getState().overrideInfo.buffer != nullptr && !skipLayer) {buffer = getState().overrideInfo.buffer->getBuffer();acquireFence = getState().overrideInfo.acquireFence;slot = HwcBufferCache::FLATTENER_CACHING_SLOT;}        sp<GraphicBuffer> hwcBuffer;editState().hwc->hwcBufferCache.getHwcBuffer(slot, buffer, &hwcSlot, &hwcBuffer); hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence)mComposer.setLayerBuffer(mDisplay->getId(), mId, slot, buffer, fenceFd)//HWC2.cppconst native_handle_t* handle = nullptr;//frameworks/native/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpphandle = buffer->getNativeBuffer()->handle;mWriter.setLayerBuffer(slot, handle, acquireFence)
}

最終將hwc_layer相關信息傳遞到HAL層的HWC實現!


SurfaceFinger layer創建過程
SurfaceControl之Transaction事物深入剖析
Surface的Buffer是怎么傳遞給HWC呢?
SurfaceFlinger layer之間的對應關系
Android Qcom Display學習
SurfaceFlinger處理事務
SurfaceFlinger Refresh流程




本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/18507.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/18507.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/18507.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

輕兔推薦 —— vfox

簡介 vfox 是一個跨平臺且可擴展的版本管理工具&#xff0c;終于有一個可以管理所有運行環境的工具了 - 支持一鍵安裝 Java、Node.js、Flutter、.Net、Golang、PHP、Python等多種環境 - 支持一鍵切換不同版本 特點 支持Windows(非WSL)、Linux、macOS! 支持不同項目不同版本、…

(四)事件系統

視頻鏈接:尚硅谷2024最新版微信小程序 文章目錄 事件綁定和事件對象事件分類以及阻止事件冒泡事件傳參-data-*自定義數據事件傳參-mark 自定義數據事件綁定和事件對象 小程序中綁定事件與在網頁開發中綁定事件幾乎一致,只不過在小程序不能通過 on 的方式綁定事件,也沒有 cli…

C# 9.0的init訪問器

不控制可變性 下面是我們最常見的屬性聲明方式&#xff0c;允許屬性在類的內部和外部都可以讀取和修改 public int Id { get; set; }namespace Demo {public class Company{public int Id { get; set; }public Company(){}public Company(int id){Id id; // 可以在構造函數中…

22.Volatile原理

文章目錄 Volatile原理1.Volatile語義中的內存屏障1.1.volatile寫操作的內存屏障1.1.1.StoreStore 屏障1.1.2.StoreLoad 屏障 1.2.volatile讀操作的內存屏障1.2.1.LoadStore屏障1.2.2.LoadLoad屏障 2.volatile不具備原子性2.1.原理 Volatile原理 1.Volatile語義中的內存屏障 在…

用于生成 Avatar 的文本引導式情感和運動控制-InstructAvatar

網址 https://wangyuchi369.github.io/InstructAvatar/ 用于生成 Avatar 的文本引導式情感和運動控制 官網翻譯 最近的會說話的頭像生成模型在實現與音頻的真實和準確的嘴唇同步方面取得了長足的進步&#xff0c;但在控制和傳達頭像的詳細表情和情感方面往往存在不足&#…

APM2.8如何做加速度校準

加速度的校準建議準備一個六面平整&#xff0c;邊角整齊的方形硬紙盒或者塑料盒&#xff0c;如下圖所示&#xff0c;我們將以它作為APM校準時的水平垂直姿態參考&#xff0c;另外當然還需要一塊水平的桌面或者地面 首先用雙面泡沫膠或者螺絲將APM主板正面向上固定于方形盒子上&…

JavaScrip原型對象

參考 JavaScrip原型對象 | LogDicthttps://www.logdict.com/archives/javascripyuan-xing-mo-shi

每天寫兩道(二)LRU緩存、

146.LRU 緩存 . - 力扣&#xff08;LeetCode&#xff09; 請你設計并實現一個滿足 LRU (最近最少使用) 緩存 約束的數據結構。 實現 LRUCache 類&#xff1a; LRUCache(int capacity) 以 正整數 作為容量 capacity 初始化 LRU 緩存int get(int key) 如果關鍵字 key 存在于緩存…

如何使用Python和大模型進行數據分析和文本生成

如何使用Python和大模型進行數據分析和文本生成 Python語言以其簡潔和強大的特性&#xff0c;成為了數據科學、機器學習和人工智能開發的首選語言之一。隨著大模型&#xff08;Large Language Models, LLMs&#xff09;如GPT-4的崛起&#xff0c;我們能夠利用這些模型實現諸多…

Revit——(2)模型的編輯、軸網和標高

目錄 一、關閉縮小的隱藏窗口 二、標高&#xff08;可創建平面&#xff0c;其他標高線復制即可&#xff09; 三、軸網 周圍的四個圈和三角表示四個里面&#xff0c;可以移動&#xff0c;不要刪除 一、關閉縮小的隱藏窗口 二、標高&#xff08;可創建平面&#xff0c;其他標…

計算機體系結構期末快速復習

文章目錄 前言CPI&#xff0c;MIPS&#xff08;大題1&#xff09;加速比&#xff08;大題2&#xff09;流水線&#xff08;大題3&#xff09;CRAY-1向量機&#xff08;大題4&#xff09;Tomasulo算法&#xff08;大題5&#xff09;概念簡答題計算機系統結構的經典定義什么是透明…

深入分析 Android Activity (二)

文章目錄 深入分析 Android Activity (二)1. Activity 的啟動模式&#xff08;Launch Modes&#xff09;1.1 標準模式&#xff08;standard&#xff09;1.2 單頂模式&#xff08;singleTop&#xff09;1.3 單任務模式&#xff08;singleTask&#xff09;1.4 單實例模式&#xf…

利用邊緣計算網關的工業設備數據采集方案探討-天拓四方

隨著工業4.0時代的到來&#xff0c;工業設備數據采集成為了實現智能制造、提升生產效率的關鍵環節。傳統的數據采集方案往往依賴于中心化的數據處理方式&#xff0c;但這種方式在面對海量數據、實時性要求高的工業場景時&#xff0c;往往顯得力不從心。因此&#xff0c;利用邊緣…

CSS實現一個雨滴滑落效果

使用純CSS來實現一個真實的雨滴滑落效果可能會有些挑戰&#xff0c;因為CSS主要關注于靜態樣式和簡單的動畫效果。然而&#xff0c;你可以使用CSS動畫和keyframes來模擬一個雨滴滑落的簡化效果。 以下是一個基本的示例&#xff0c;展示如何使用CSS來模擬雨滴從頂部滑落到底部的…

AI學習指南數學工具篇-MATLAB中的凸優化工具

AI學習指南數學工具篇-MATLAB中的凸優化工具 在人工智能領域&#xff0c;凸優化是一個非常重要的數學工具&#xff0c;它在機器學習、深度學習、數據分析等領域都有著廣泛的應用。而MATLAB作為一款強大的數學工具軟件&#xff0c;提供了豐富的凸優化工具和函數&#xff0c;為用…

二叉樹的鏈式結構(二叉樹)與順序結構(堆)---數據結構

一、樹的概念與結構 1、樹的概念 樹是一種非線性的數據結構&#xff0c;它是由n&#xff08;n>0&#xff09;個有限結點組成一個具有層次關系的集合。我們常把它叫做樹&#xff0c;是因為它看起來像一棵倒掛的樹&#xff0c;它的根是朝上的&#xff0c;而葉是朝下的。 下面…

給我一個用斷言結果執行下一步的例子

在使用 pytest 和 Selenium 進行自動化測試時&#xff0c;通常我們會根據斷言的結果來決定測試流程的走向。如果斷言失敗&#xff0c;測試通常會停止執行后續的步驟&#xff0c;因為失敗意味著被測系統沒有按照預期工作。然而&#xff0c;有時候我們可能需要在斷言失敗后執行特…

每日復盤-20240528

今日重點關注&#xff1a; 20240528 六日漲幅最大: ------1--------300956--------- 英力股份 五日漲幅最大: ------1--------301361--------- 眾智科技 四日漲幅最大: ------1--------301361--------- 眾智科技 三日漲幅最大: ------1--------301361--------- 眾智科技 二日漲…

前端編程語言——JS背景知識、JS基礎語法、算數運算符和關系運算符(1)

0、前言&#xff1a; JS全稱是JavaScript&#xff0c;是一種腳本語言&#xff0c;誕生于1995年&#xff0c;JS是由ECMAScript&#xff08;包含js語法&#xff09;、BOM&#xff08;Brower Oject Model&#xff0c;和瀏覽器相關操作&#xff09;、DOM&#xff08;Document Obje…

ubuntu設置中文輸入法教程

在 Ubuntu 上設置中文輸入法可以通過以下步驟來完成。我們將以安裝和配置 fcitx 輸入法框架及其中文輸入法插件 fcitx-sunpinyin 為例。 ### 步驟一&#xff1a;安裝 fcitx 和中文輸入法插件 1. **更新軟件包列表** 打開終端并運行以下命令來更新軟件包列表&#xff1a; …