当前位置: 首页 > news >正文

BLASTBufferQueue端的GraphicBuffer怎么和SurfaceFlinger端的BufferStateLayer关联上

BLASTBufferQueue端的GraphicBuffer怎么和SurfaceFlinger端的BufferStateLayer关联上



引言

在跟进hwc_layer是如何产生的,并如何被填充上GraphicBuffer的,怎么也找不到被填充的GraphicBuffer的来源,最终找到了,它的来源是客户端的BLASTBufferQueue传递过来的,我们这里跟进下这个流程。

这里使用的代码是Android 13 aosp



一. BLASTBufferQueue是如何传递GraphicBuffer到SurfaceFlinger端的BufferStateLayer的

当BufferQueueProducer完成绘制调用queueBuffer后,会调用BLASTBufferQueue::onFrameAvailable。

///rameworks/native/libs/gui/BLASTBufferQueue.cpp
void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {...acquireNextBufferLocked(mSyncTransaction)...
}void BLASTBufferQueue::acquireNextBufferLocked(const std::optional<SurfaceComposerClient::Transaction*> transaction) {...status_t status =mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false); auto buffer = bufferItem.mGraphicBuffer;t->setBuffer(mSurfaceControl, buffer, fence, bufferItem.mFrameNumber, releaseBufferCallback);t->setApplyToken(mApplyToken).apply(false, true);...
}

apply最终会通过Binder调用到SurfaceFlinger的>setTransactionState,我们接着往下看:

status_t SurfaceFlinger::setTransactionState(const FrameTimelineInfo& frameTimelineInfo, const Vector<ComposerState>& states,const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {...queueTransaction(state);//将相关的transaction状态存起来...}       

后续vsync会触发SurfaceFlinger执行如下逻辑:

MessageQueue::Handler::handleMessagecompositor.commitSurfaceFlinger::commitflushTransactionQueuesSurfaceFlinger::applyTransactionStateSurfaceFlinger::setClientStateLockedlayer->setBufferuint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTimelineInfo,ComposerState& composerState,int64_t desiredPresentTime, bool isAutoTimestamp,int64_t postTime, uint32_t permissions) {layer_state_t& s = composerState.state;sp<Layer> layer = nullptr;layer = fromHandle(s.surface).promote();//关键点,这个layer是怎么获取的if (what & layer_state_t::eBufferChanged) {std::shared_ptr<renderengine::ExternalTexture> buffer =getExternalTextureFromBufferData(*s.bufferData, layer->getDebugName());//这里并不是真的纹理,而是命名像而已if (layer->setBuffer(buffer, *s.bufferData, postTime, desiredPresentTime, isAutoTimestamp,dequeueBufferTimestamp, frameTimelineInfo)) {flags |= eTraversalNeeded;}}
}

这里我们看下fromHandle的实现:

//SurfaceFlinger.cpp
wp<Layer> SurfaceFlinger::fromHandle(const sp<IBinder>& handle) const {return Layer::fromHandle(handle);
}//Layer.cpp
wp<Layer> Layer::fromHandle(const sp<IBinder>& handleBinder) {if (handleBinder == nullptr) {return nullptr;}BBinder* b = handleBinder->localBinder();if (b == nullptr || b->getInterfaceDescriptor() != Handle::kDescriptor) {return nullptr;}// We can safely cast this binder since its local and we verified its interface descriptor.sp<Handle> handle = static_cast<Handle*>(handleBinder.get());return handle->owner;
}

那么这个Layer对应的Handle是什么时候被构建的呢,是什么时候呢。

status_t SurfaceFlinger::createLayer(LayerCreationArgs& args, sp<IBinder>* outHandle,const sp<IBinder>& parentHandle, int32_t* outLayerId,const sp<Layer>& parentLayer, uint32_t* outTransformHint) {...sp<Layer> layer;       createBufferStateLayer(args, outHandle, &layer)...
}    status_t SurfaceFlinger::createBufferStateLayer(LayerCreationArgs& args, sp<IBinder>* handle,sp<Layer>* outLayer) {args.textureName = getNewTexture();*outLayer = getFactory().createBufferStateLayer(args);*handle = (*outLayer)->getHandle();return NO_ERROR;
}//frameworks/native/services/surfaceflinger/Layer.cpp
sp<IBinder> Layer::getHandle() {Mutex::Autolock _l(mLock);if (mGetHandleCalled) {ALOGE("Get handle called twice" );return nullptr;}mGetHandleCalled = true;return new Handle(mFlinger, this);
}//frameworks/native/services/surfaceflinger/Layer.h
class Handle : public BBinder, public LayerCleaner {
public:Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer): LayerCleaner(flinger, layer, this), owner(layer) {}const String16& getInterfaceDescriptor() const override { return kDescriptor; }static const String16 kDescriptor;wp<Layer> owner;
};
...
}

这里我们要怎么理解这个Handle呢,它是对Layer的一个封装,不管是BufferStateLayer还是其它的,通过它可以让Layer在Binder中传递

我们接着继续往下看,layer->setBuffer会调用子类的setBuffer,子类是BufferStateLayer

//frameworks/native/services/surfaceflinger/BufferStateLayer.cpp
bool BufferStateLayer::setBuffer(std::shared_ptr<renderengine::ExternalTexture>& buffer,const BufferData& bufferData, nsecs_t postTime,nsecs_t desiredPresentTime, bool isAutoTimestamp,std::optional<nsecs_t> dequeueTime,const FrameTimelineInfo& info) {...mDrawingState.frameNumber = frameNumber;mDrawingState.releaseBufferListener = bufferData.releaseBufferListener;mDrawingState.buffer = std::move(buffer);mDrawingState.clientCacheId = bufferData.cachedBuffer;setTransactionFlags(eTransactionNeeded);...
}

这里只是把buffer赋值给mDrawingState.buffer了,肯定有地方把mDrawingState.buffer赋值mBufferInfo.mBuffer;

接着找,在updateActiveBuffer找到了mBufferInfo.mBuffer = s.buffer。updateActiveBuffer又是在哪里调用的呢?

status_t BufferStateLayer::updateActiveBuffer() {const State& s(getDrawingState());...mBufferInfo.mBuffer = s.buffer;mBufferInfo.mFence = s.acquireFence;mBufferInfo.mFrameNumber = s.frameNumber;...
}

在BufferStateLayer的父类BufferLayer::latchBuffer里调用:


bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,nsecs_t expectedPresentTime) {
... ...status_t err = updateTexImage(recomputeVisibleRegions, latchTime, expectedPresentTime);err = updateActiveBuffer();err = updateFrameNumber(latchTime);

接下来看下latchBuffer是在哪里调用的:

MessageQueue::Handler::handleMessagecompositor.commitSurfaceFlinger::commitlatchBuffers()for (const auto& layer : mLayersWithQueuedFrames) {if (layer->latchBuffer(visibleRegions, latchTime, expectedPresentTime)) {mLayersPendingRefresh.push_back(layer);newDataLatched = true;}layer->useSurfaceDamage();}            


二. BufferStateLayer的GraphicBuffer怎么传递到hwc_layer中去的

这个我们要知道的是BufferStateLayer的GraphicBuffer最终传递到hwc_layer中,是要经过OputputLayer的,通过前面我们知道此时的GraphicBuffer存储在BufferInfo中,如下:

class BufferLayer : public Layer {...struct BufferInfo {nsecs_t mDesiredPresentTime;std::shared_ptr<FenceTime> mFenceTime;sp<Fence> mFence;uint32_t mTransform{0};ui::Dataspace mDataspace{ui::Dataspace::UNKNOWN};Rect mCrop;uint32_t mScaleMode{NATIVE_WINDOW_SCALING_MODE_FREEZE};Region mSurfaceDamage;HdrMetadata mHdrMetadata;int mApi;PixelFormat mPixelFormat{PIXEL_FORMAT_NONE};bool mTransformToDisplayInverse{false};std::shared_ptr<renderengine::ExternalTexture> mBuffer;//存放GraphicBufferuint64_t mFrameNumber;int mBufferSlot{BufferQueue::INVALID_BUFFER_SLOT};bool mFrameLatencyNeeded{false};};    BufferInfo mBufferInfo;...}

我们先看怎么传递到OutputLayer的:

MessageQueue::Handler::handleMessage(...)compositor.composite(...)SurfaceFlinger::composite(...)mCompositionEngine->present(...)//CompositionEngine.cppupdateLayerStateFromFE(args)output->updateLayerStateFromFE(args)//Output.cppfor (auto* layer : getOutputLayersOrderedByZ()) {layer->getLayerFE().prepareCompositionState(args.updatingGeometryThisFrame ? LayerFE::StateSubset::GeometryAndContent: LayerFE::StateSubset::Content);}                    //frameworks/native/services/surfaceflinger/Layer.cppvoid Layer::prepareCompositionState(compositionengine::LayerFE::StateSubset subset) {using StateSubset = compositionengine::LayerFE::StateSubset;switch (subset) {case StateSubset::BasicGeometry:prepareBasicGeometryCompositionState();break;case StateSubset::GeometryAndContent:prepareBasicGeometryCompositionState();prepareGeometryCompositionState();preparePerFrameCompositionState();//调用子类BufferLayer的break;case StateSubset::Content:preparePerFrameCompositionState();break;case StateSubset::Cursor:prepareCursorCompositionState();break;}
}  //frameworks/native/services/surfaceflinger/BufferLayer.cpp
void BufferLayer::preparePerFrameCompositionState() {Layer::preparePerFrameCompositionState();...compositionState->buffer = getBuffer();compositionState->bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT)? 0: mBufferInfo.mBufferSlot;compositionState->acquireFence = mBufferInfo.mFence;compositionState->frameNumber = mBufferInfo.mFrameNumber;compositionState->sidebandStreamHasFrame = false;
}


分析layer是否参与合成

最简单的SurfaceFlinger应用程序

Android14 SurfaceFlinger-BLASTBufferQueue的创建

Android 14 SurfaceFlinger-Layer visibleRegion的计算过程

SurfaceFlinger的commit/handleTransaction分析

这里重点关注各种State!

相关文章:

BLASTBufferQueue端的GraphicBuffer怎么和SurfaceFlinger端的BufferStateLayer关联上

BLASTBufferQueue端的GraphicBuffer怎么和SurfaceFlinger端的BufferStateLayer关联上 引言 在跟进hwc_layer是如何产生的&#xff0c;并如何被填充上GraphicBuffer的&#xff0c;怎么也找不到被填充的GraphicBuffer的来源&#xff0c;最终找到了&#xff0c;它的来源是客户端的…...

48、spfa求最短路

spfa求最短路 题目描述 给定一个n个点m条边的有向图&#xff0c;图中可能存在重边和自环&#xff0c; 边权可能为负数。 请你求出1号点到n号点的最短距离&#xff0c;如果无法从1号点走到n号点&#xff0c;则输出impossible。 数据保证不存在负权回路。 输入格式 第一行包…...

安装PyTorch详细步骤

&#x1f4a5;注意事项&#xff1a; CPU版和GPU版选一个进行安装即可 如果有Nvidia显卡&#xff0c;则安装cuda版本的PyTorch&#xff0c;如没有nvidia显卡&#xff0c;则安装cpu版。 目前常见的深度学习框架有很多&#xff0c;最出名的是&#xff1a;PyTorch&#xff08;faceb…...

linux线程,线程控制与线程相关概念

线程概念 线程这个词或多或少大家都听过&#xff0c;今天我们正式的来谈一下线程&#xff1b; 在我一开始的概念中线程就是进程的一部分&#xff0c;一个进程中有很多个线程&#xff0c;这个想法基本是正确的&#xff0c;但细节部分呢我们需要细细讲解一下&#xff1b; 什么…...

第八大奇迹

目录 题目描述 输入描述 输出描述 输入输出样例 示例 输入 输出 运行限制 原题链接 代码思路 题目描述 在一条 R 河流域&#xff0c;繁衍着一个古老的名族 Z。他们世代沿河而居&#xff0c;也在河边发展出了璀璨的文明。 Z 族在 R 河沿岸修建了很多建筑&#xff0c…...

MySQL:CRUD初阶(有图有实操)

文章目录 &#x1f4d1;1. 数据库的操作&#x1f324;️1.1 显示当前的数据库&#x1f324;️1.2 创建数据库&#x1f324;️1.3 选中数据库&#x1f324;️1.4 删除数据库 &#x1f4d1;2. 表的操作&#x1f324;️2.1 查看表结构&#x1f324;️2.2 创建表&#x1f324;️2.3…...

『大模型笔记』使用 vLLM 和 PagedAttention 快速提供 LLM 服务!

使用 vLLM 和 PagedAttention 快速提供 LLM 服务! 文章目录 一. 使用 vLLM 和 PagedAttention 快速提供 LLM 服务!1.1. PagedAttention二. 参考文献小红书中文字幕视频:https://www.xiaohongshu.com/explore/66502b60000000000500433e官网文档(推荐,里面有动图解释):vLLM:…...

简述vue-loader是什么?使用它的用途有哪些

vue-loader是一个webpack的加载器(loader)&#xff0c;主要用于将Vue组件的单文件(.vue文件)转换为JavaScript模块。使用vue-loader的主要用途包括&#xff1a; 解析.vue文件&#xff1a;vue-loader能够解析.vue文件中的模板、样式和脚本&#xff0c;并将它们分离出来进行处理…...

如何远程访问Redis?

远程访问Redis是一种常见的需求&#xff0c;特别是在分布式系统或跨地域网络中。通过远程访问&#xff0c;我们可以轻松地对远程的Redis数据库进行操作和管理。 天联保障数据安全 对于远程访问Redis的安全性问题&#xff0c;我们可以借助天联来保障数据的安全。天联是一种基于…...

#12松桑前端后花园周刊-SolidStart、Vercel融资、Angular18、Nextjs15RC、p5.js、ChromeDevTools引入AI

⚡️行业动态 SolidStart 1.0 元框架发布 Solidjs 核心团队发布其元框架 SolidStart 1.0 正式版&#xff0c;其特点如下&#xff1a;基于文件系统的路由&#xff1b;支持SSR、流式SSR、CSR、SSG渲染模式&#xff1b;通过代码分割、树摇和无用代码删除构建优化&#xff1b;基于…...

vue3 vite title 页面标题设置

效果图&#xff1a; 1. 安装 vite-plugin-html 插件 npm install vite-plugin-html -D2. 修改 vite.config.js import {defineConfig, loadEnv} from vite import { createHtmlPlugin } from "vite-plugin-html" import {resolve} from path import vue from vitej…...

spring boot添加License(软件许可)

文章目录 前言1. 生成钥匙库2. 生成证书3. 生成公匙库4.业务代码1. 引入依赖2. 关键代码3. 配置文件 5、改成线上地址&#xff0c;这样不用每次打包&#xff0c;发送license.lic文件给客户&#xff0c;重启项目就行5.1、工具类5.2 修改部分&#xff1a; 总结 前言 工作需要给软…...

LangChain打造一个AI客服

最近在学习LangChain&#xff0c;langchain的第一个入门应用就是和ChatGPT结合形成的一个AI客服&#xff0c;本期文章就带大家一起认识下 LangChain LangChain是现在用得最多的AI框架&#xff0c;langchain在帮助如基于文档数据的回答、聊天机器人和代理这类的应用程序 langch…...

【前端三剑客之JS】详解JS

1. JS的引入方式 (1). 内部脚本方式引入 在页面上&#xff0c;通过一对script标签引入js代码.script代码放置位置有一定随意性&#xff0c;一般放在head标签中. (2).外部脚本方式引入. 内部脚本只能在当前页面中使用&#xff0c;代码复用度不高.可以将脚本放在单独的js文件…...

重庆耶非凡科技有限公司有选品师项目培训吗?

在当今科技飞速发展的时代&#xff0c;各种科技公司如雨后春笋般涌现&#xff0c;它们在不同领域发挥着重要作用。其中&#xff0c;重庆耶非凡科技有限公司以其独特的业务模式和专业服务&#xff0c;在业界赢得了良好的口碑。那么&#xff0c;重庆耶非凡科技有限公司究竟是做什…...

格式转化——Labelme标注好的json文件批量转为png(标签)文件(物体为红色,背景为黑色)和jpg原图

作用如题目&#xff0c;批量将标注好的json文件转成png标签&#xff0c;jpg原图&#xff0c;其中标签时红黑图。 代码如下&#xff1a; import argparse import base64 import json import os import os.path as osp import imgviz import PIL.Image import yaml from labelm…...

力扣刷题--2535. 数组元素和与数字和的绝对差【简单】

题目描述 给你一个正整数数组 nums 。 元素和 是 nums 中的所有元素相加求和。 数字和 是 nums 中每一个元素的每一数位&#xff08;重复数位需多次求和&#xff09;相加求和。 返回 元素和 与 数字和 的绝对差。 注意&#xff1a;两个整数 x 和 y 的绝对差定义为 |x - y| 。…...

2024年【危险化学品经营单位安全管理人员】考试报名及危险化学品经营单位安全管理人员找解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 危险化学品经营单位安全管理人员考试报名考前必练&#xff01;安全生产模拟考试一点通每个月更新危险化学品经营单位安全管理人员找解析题目及答案&#xff01;多做几遍&#xff0c;其实通过危险化学品经营单位安全管…...

IntelliJ IDEA集成Baidu Comate,商城系统支付交易功能开发实战

文章目录 Baidu Comate介绍安装配置体验安装插件配置体验注释生成代码技术问答 实战设计表生成代码导入数据 总结 Baidu Comate介绍 在科技互联网飞速发展的今天&#xff0c;百度凭借其深厚的技术积累和创新能力&#xff0c;推出了一款名为Baidu Comate智能代码助手的产品。该…...

20212313 2023-2024-2 《移动平台开发与实践》第5次作业

20212313 2023-2024-2 《移动平台开发与实践》第5次作业 1.实验内容 设计并开发一个地图应用系统。 该实验需提前申请百度API Key&#xff0c;调用接口实现百度地图的定位功能、地图添加覆盖物和显示文本信息。 2.实验过程 2.1 获取SHA1 &#xff08;1&#xff09;打开控制台…...

实战指南:基于快马平台快速开发并部署班级宠物园应用官方下载门户

最近学校想推广一个班级宠物园的教育应用&#xff0c;需要快速搭建一个官方下载页面。作为技术负责人&#xff0c;我尝试用InsCode(快马)平台来快速实现这个需求&#xff0c;整个过程比想象中顺利很多。 项目规划与结构设计 首先明确页面需要包含的几个核心模块&#xff1a;顶部…...

别再只用CEEMDAN了!信号分解后,这7种熵指标到底该怎么选?(能量熵/近似熵/模糊熵对比)

信号分解后熵指标选型指南&#xff1a;从能量熵到多尺度排列熵的深度解析 在信号处理领域&#xff0c;CEEMDAN等分解方法早已成为研究人员的标准工具包——它们像精密的滤波器&#xff0c;将复杂信号拆解为一系列物理意义明确的IMF分量。但当我们面对这些分解后的子信号时&…...

哔咔漫画下载器:多线程极速下载完整指南

哔咔漫画下载器&#xff1a;多线程极速下载完整指南 【免费下载链接】picacomic-downloader 哔咔漫画 picacomic pica漫画 bika漫画 PicACG 多线程下载器&#xff0c;带图形界面 带收藏夹&#xff0c;已打包exe 下载速度飞快 项目地址: https://gitcode.com/gh_mirrors/pi/pi…...

gInk:重新定义屏幕标注体验的轻量化协作工具

gInk&#xff1a;重新定义屏幕标注体验的轻量化协作工具 【免费下载链接】gInk An easy to use on-screen annotation software inspired by Epic Pen. 项目地址: https://gitcode.com/gh_mirrors/gi/gInk 远程会议中&#xff0c;当产品经理试图在共享屏幕上圈出设计稿的…...

Docker测试学习思路

Docker 核心概念学习与实战指南本文系统梳理 Docker 学习的核心思路与方法&#xff0c;用通俗类比帮助理解 Docker 的本质&#xff0c;涵盖镜像构建、容器运行、网络通信、数据持久化、资源限制五大核心能力&#xff0c;适合初学者建立清晰的 Docker 知识框架。一、Docker 到底…...

手机号查QQ号终极指南:3分钟快速找回遗忘的QQ号码

手机号查QQ号终极指南&#xff1a;3分钟快速找回遗忘的QQ号码 【免费下载链接】phone2qq 项目地址: https://gitcode.com/gh_mirrors/ph/phone2qq 你是否曾因忘记QQ号而无法登录&#xff1f;是否因为更换手机需要重新绑定QQ却找不到账号信息&#xff1f;手机号查QQ号工…...

OrangepiZERO3驱动USB摄像头的记录

关于orangepiZERO3的官方文档&#xff1a; http://www.orangepi.cn/orangepiwiki/index.php/Orange_Pi_Zero_3 按照里面有关的步骤进行操作&#xff0c;但是可能会有一点小问题&#xff0c;特此记录一下 第一步和第二步一致&#xff0c;不多说。 第三步&#xff1a; 我的命令…...

Unity性能优化实战:用Job System并行处理海量数据,告别主线程卡顿

Unity性能优化实战&#xff1a;用Job System并行处理海量数据&#xff0c;告别主线程卡顿 当你的游戏场景中出现成千上万的粒子在飞舞&#xff0c;或是数百个NPC同时进行复杂的AI决策时&#xff0c;是否经常遇到帧率骤降的困扰&#xff1f;作为Unity开发者&#xff0c;我们每天…...

NovelAI:从文本生成到内容创作的AIGC实践

1. NovelAI&#xff1a;你的AI创作助手 第一次接触NovelAI时&#xff0c;我正被一篇商业方案折磨得焦头烂额。凌晨三点的咖啡杯旁&#xff0c;这个基于GPT模型的AI工具在15分钟内就帮我完成了初稿框架&#xff0c;那一刻我就知道&#xff0c;内容创作的方式正在被重新定义。Nov…...

Mac环境OpenClaw深度优化:Qwen3-4B模型推理速度提升30%方案

Mac环境OpenClaw深度优化&#xff1a;Qwen3-4B模型推理速度提升30%方案 1. 为什么需要优化OpenClaw的模型推理速度 上周我在用OpenClaw处理一个简单的文件整理任务时&#xff0c;发现整个流程耗时比预期长了近一倍。通过日志排查才发现&#xff0c;大部分时间都消耗在等待Qwe…...