Android Surface对应的Buffer怎么传递给HWC

2024-05-29 10:04

本文主要是介绍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流程




这篇关于Android Surface对应的Buffer怎么传递给HWC的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1013360

相关文章

AI绘图怎么变现?想做点副业的小白必看!

在科技飞速发展的今天,AI绘图作为一种新兴技术,不仅改变了艺术创作的方式,也为创作者提供了多种变现途径。本文将详细探讨几种常见的AI绘图变现方式,帮助创作者更好地利用这一技术实现经济收益。 更多实操教程和AI绘画工具,可以扫描下方,免费获取 定制服务:个性化的创意商机 个性化定制 AI绘图技术能够根据用户需求生成个性化的头像、壁纸、插画等作品。例如,姓氏头像在电商平台上非常受欢迎,

W外链微信推广短连接怎么做?

制作微信推广链接的难点分析 一、内容创作难度 制作微信推广链接时,首先需要创作有吸引力的内容。这不仅要求内容本身有趣、有价值,还要能够激起人们的分享欲望。对于许多企业和个人来说,尤其是那些缺乏创意和写作能力的人来说,这是制作微信推广链接的一大难点。 二、精准定位难度 微信用户群体庞大,不同用户的需求和兴趣各异。因此,制作推广链接时需要精准定位目标受众,以便更有效地吸引他们点击并分享链接

电脑桌面文件删除了怎么找回来?别急,快速恢复攻略在此

在日常使用电脑的过程中,我们经常会遇到这样的情况:一不小心,桌面上的某个重要文件被删除了。这时,大多数人可能会感到惊慌失措,不知所措。 其实,不必过于担心,因为有很多方法可以帮助我们找回被删除的桌面文件。下面,就让我们一起来了解一下这些恢复桌面文件的方法吧。 一、使用撤销操作 如果我们刚刚删除了桌面上的文件,并且还没有进行其他操作,那么可以尝试使用撤销操作来恢复文件。在键盘上同时按下“C

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

webm怎么转换成mp4?这几种方法超多人在用!

webm怎么转换成mp4?WebM作为一种新兴的视频编码格式,近年来逐渐进入大众视野,其背后承载着诸多优势,但同时也伴随着不容忽视的局限性,首要挑战在于其兼容性边界,尽管WebM已广泛适应于众多网站与软件平台,但在特定应用环境或老旧设备上,其兼容难题依旧凸显,为用户体验带来不便,再者,WebM格式的非普适性也体现在编辑流程上,由于它并非行业内的通用标准,编辑过程中可能会遭遇格式不兼容的障碍,导致操

怎么让1台电脑共享给7人同时流畅设计

在当今的创意设计与数字内容生产领域,图形工作站以其强大的计算能力、专业的图形处理能力和稳定的系统性能,成为了众多设计师、动画师、视频编辑师等创意工作者的必备工具。 设计团队面临资源有限,比如只有一台高性能电脑时,如何高效地让七人同时流畅地进行设计工作,便成为了一个亟待解决的问题。 一、硬件升级与配置 1.高性能处理器(CPU):选择多核、高线程的处理器,例如Intel的至强系列或AMD的Ry

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动