Gralloc图形缓冲的分配过程

news2024/11/26 18:50:13

广告

首先帮我朋友打个广告 我们一起在运营一个视频号 感兴趣的可以帮忙点击右边这个小铃铛 铃铛

其实越往底下走在很多人嘴里就会变得很玄乎,变得不可思议,这里的gralloc就是一个native service,只是分装了一些调用接口,上层只是利用这些平台提供的接口组织业务场景而已,本质的来说完全可以把 ps -A | grep hardware 所有进程看成一个后台app即可,例如xxxcomposexxx等等,在我看来Android就是由一个一个app组织起来的

还是那句话,逆水行舟不进则退,我是发现00后的同事质素越来越高了

如有小伙伴需要 笔者可提供所有原材料供二次编辑 whsgzcy@foxmail.com

本文阐述的预期

1.只做对架构理解上的辅助case

一、从一个架构图开始

Gralloc 图形缓冲是一段保存图形数据的内存,这是一段共享的内存,Fence机制释放也是大多数都是通过memcpXXX等c++函数完成,也就是把指针重新指向一个地址,在Android系统中,Gralloc负责分配图形缓冲,也就是你要什么样的Buffer在此会给你申请一段Buffer,他是由一个结构体描述出来的,也就是我们通常看到的GraphicBuffer,并在业务层用数据组织起来,业务场景中再包裹一个结构体 并按照需要设置为FREE、DEQUEUED、QUEUED、ACQUIRED、FREE等等

Gralloc是一个独立的进程,native service,hal的接口是

/hardware/interfaces/graphics/allocator/2.0/IAllocator.hal
/**
...
28      * @param descriptor Properties of the buffers to allocate. This must be
29      *     obtained from IMapper::createDescriptor().
...
42     allocate(BufferDescriptor descriptor, uint32_t count)
43         generates (Error error,
44                    uint32_t stride,
45                    vec<handle> buffers);

第一个参数descriptor 包含了缓冲layer的宽、高等其他格式参数,第二个是申请的个数,申请成功后图形缓冲以handle的格式返回

IAllocator 创建 在 HIDL_FETCH_IAllocator

/hardware/interfaces/graphics/mapper/2.0/default/passthrough.cpp
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
17  #include <mapper-passthrough/2.0/GrallocLoader.h>
18  
19  using android::hardware::graphics::mapper::V2_0::IMapper;
20  using android::hardware::graphics::mapper::V2_0::passthrough::GrallocLoader;
21  
22  extern "C" IMapper* HIDL_FETCH_IMapper(const char* /*name*/) {
23      return GrallocLoader::load();
24  }

/hardware/interfaces/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h
39  class GrallocLoader {
40     public:
41      static IAllocator* load() {
42          const hw_module_t* module = loadModule();
43          if (!module) {
44              return nullptr;
45          }
46          auto hal = createHal(module);
47          if (!hal) {
48              return nullptr;
49          }
50          return createAllocator(std::move(hal));
51      }

      // load the gralloc module
54      static const hw_module_t* loadModule() {
55          const hw_module_t* module;
56          int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
57          if (error) {
58              ALOGE("failed to get gralloc module");
59              return nullptr;
60          }
61  
62          return module;
63      }

加载loadModule id为GRALLOC_HARDWARE_MODULE_ID对象,createHal适配层可获取设备抽象出的对象,收到缓冲请求后再交给设备对象处理,创建IAllocator在createAllocator中创建AllocatorImpl,该对象收到请求后交给适配层对象处理

启动Gralloc服务

/hardware/interfaces/graphics/allocator/2.0/default/service.cpp
 using android::hardware::defaultPassthroughServiceImplementation;
24  using android::hardware::graphics::allocator::V2_0::IAllocator;
25  
26  int main() {
27      return defaultPassthroughServiceImplementation<IAllocator>(4);
28  }
29  

上述代码不是很多,接下来分析分配图形缓冲流程

/frameworks/native/libs/ui/Gralloc2.cpp
  Gralloc2Allocator::Gralloc2Allocator(const Gralloc2Mapper& mapper) : mMapper(mapper) {
364      mAllocator = IAllocator::getService();
365      if (mAllocator == nullptr) {
366          ALOGW("allocator 2.x is not supported");
367          return;
368      }
369  }

5  status_t Gralloc2Allocator::allocate(std::string /*requestorName*/, uint32_t width, uint32_t height,
386                                       PixelFormat format, uint32_t layerCount, uint64_t usage,
387                                       uint32_t bufferCount, uint32_t* outStride,
388                                       buffer_handle_t* outBufferHandles, bool importBuffers) const {
389      IMapper::BufferDescriptorInfo descriptorInfo = {};
390      descriptorInfo.width = width;
391      descriptorInfo.height = height;
392      descriptorInfo.layerCount = layerCount;
393      descriptorInfo.format = static_cast<hardware::graphics::common::V1_1::PixelFormat>(format);
394      descriptorInfo.usage = usage;
395  
396      BufferDescriptor descriptor;
397      status_t error = mMapper.createDescriptor(static_cast<void*>(&descriptorInfo),
398                                                static_cast<void*>(&descriptor));
399      if (error != NO_ERROR) {
400          return error;
401      }
402  
403      auto ret = mAllocator->allocate(descriptor, bufferCount,
404                                      [&](const auto& tmpError, const auto& tmpStride,
405                                          const auto& tmpBuffers) {
406                                          error = static_cast<status_t>(tmpError);
407                                          if (tmpError != Error::NONE) {
408                                              return;
409                                          }
410  
411                                          if (importBuffers) {
412                                              for (uint32_t i = 0; i < bufferCount; i++) {
413                                                  error = mMapper.importBuffer(tmpBuffers[i],
414                                                                               &outBufferHandles[i]);
415                                                  if (error != NO_ERROR) {
416                                                      for (uint32_t j = 0; j < i; j++) {
417                                                          mMapper.freeBuffer(outBufferHandles[j]);
418                                                          outBufferHandles[j] = nullptr;
419                                                      }
420                                                      return;
421                                                  }
422                                              }
423                                          } else {
424                                              for (uint32_t i = 0; i < bufferCount; i++) {
425                                                  outBufferHandles[i] = native_handle_clone(
426                                                          tmpBuffers[i].getNativeHandle());
427                                                  if (!outBufferHandles[i]) {
428                                                      for (uint32_t j = 0; j < i; j++) {
429                                                          auto buffer = const_cast<native_handle_t*>(
430                                                                  outBufferHandles[j]);
431                                                          native_handle_close(buffer);
432                                                          native_handle_delete(buffer);
433                                                          outBufferHandles[j] = nullptr;
434                                                      }
435                                                  }
436                                              }
437                                          }
438                                          *outStride = tmpStride;
439                                      });
440  
441      // make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
442      hardware::IPCThreadState::self()->flushCommands();
443  
444      return (ret.isOk()) ? error : static_cast<status_t>(kTransactionError);

这里主要是allocate成功之后将句柄通过outBufferHandles返回调用者,AllocatorImpl收到请求后转到适配层 调用gralloc_alloc_buffer

/hardware/libhardware/modules/gralloc/gralloc.cpp
167  static int gralloc_alloc_buffer(alloc_device_t* dev,
168          size_t size, int /*usage*/, buffer_handle_t* pHandle)
169  {
170      int err = 0;
171      int fd = -1;
172  
173      size = roundUpToPageSize(size);
174  
175      fd = ashmem_create_region("gralloc-buffer", size);
176      if (fd < 0) {
177          ALOGE("couldn't create ashmem (%s)", strerror(-errno));
178          err = -errno;
179      }
180  
181      if (err == 0) {
182          private_handle_t* hnd = new private_handle_t(fd, size, 0);
183          gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>(
184                  dev->common.module);
185          err = mapBuffer(module, hnd);
186          if (err == 0) {
187              *pHandle = hnd;
188          }
189      }
190  
191      ALOGE_IF(err, "gralloc failed err=%s", strerror(-err));
192  
193      return err;
194  }

通过ashmem_create_region分配内存,得到文件描述符,客户进程拿到文件描述符通过mmap操作得到缓冲区地址

图形显示系统缓存图形数据是用GraphicBuffer表示

/frameworks/native/libs/nativebase/include/nativebase/nativebase.h
typedef struct ANativeWindowBuffer
67  {
68  #ifdef __cplusplus
69      ANativeWindowBuffer() {
70          common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
71          common.version = sizeof(ANativeWindowBuffer);
72          memset(common.reserved, 0, sizeof(common.reserved));
73      }
74  
75      // Implement the methods that sp<ANativeWindowBuffer> expects so that it
76      // can be used to automatically refcount ANativeWindowBuffer's.
77      void incStrong(const void* /*id*/) const {
78          common.incRef(const_cast<android_native_base_t*>(&common));
79      }
80      void decStrong(const void* /*id*/) const {
81          common.decRef(const_cast<android_native_base_t*>(&common));
82      }
83  #endif
84  
85      struct android_native_base_t common;
86  
87      int width;
88      int height;
89      int stride;
90      int format;
91      int usage_deprecated;
92      uintptr_t layerCount;
93  
94      void* reserved[1];
95  
96      const native_handle_t* handle;
97      uint64_t usage;
98  
99      // we needed extra space for storing the 64-bits usage flags
100      // the number of slots to use from reserved_proc depends on the
101      // architecture.
102      void* reserved_proc[8 - (sizeof(uint64_t) / sizeof(void*))];
103  } ANativeWindowBuffer_t;
104  
/frameworks/native/libs/ui/include/ui/GraphicBuffer.h
 
49  class GraphicBuffer
50      : public ANativeObjectBase<ANativeWindowBuffer, GraphicBuffer, RefBase>,
51        public Flattenable<GraphicBuffer>
52  {
53      friend class Flattenable<GraphicBuffer>;

GraphicBuffer继承于ANativeWindowBuffer,handle用户保存缓存对应文件描述符,创建GraphicBuffer代码如下

/frameworks/native/libs/ui/GraphicBuffer.cpp
4  GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
85                               uint32_t inLayerCount, uint64_t inUsage, std::string requestorName)
86        : GraphicBuffer() {
87      mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount, inUsage,
88                                std::move(requestorName));
89  }

申请成功后缓冲保存到handle中,使用者得到GraphicBuffer对象后需要取出地址才能保存图形数据

 status_t GraphicBuffer::unlock()
286  {
287      status_t res = getBufferMapper().unlock(handle);
288      return res;
289  }
290  
291  status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd,
292                                    int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
293      const Rect lockBounds(width, height);
294      status_t res =
295              lockAsync(inUsage, lockBounds, vaddr, fenceFd, outBytesPerPixel, outBytesPerStride);
296      return res;
297  }
298  
299  status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect, void** vaddr, int fenceFd,
300                                    int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
301      return lockAsync(inUsage, inUsage, rect, vaddr, fenceFd, outBytesPerPixel, outBytesPerStride);
302  }
303  
304  status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage, uint64_t inConsumerUsage,
305                                    const Rect& rect, void** vaddr, int fenceFd,
306                                    int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
307      if (rect.left < 0 || rect.right  > width ||
308          rect.top  < 0 || rect.bottom > height) {
309          ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
310                  rect.left, rect.top, rect.right, rect.bottom,
311                  width, height);
312          return BAD_VALUE;
313      }
314  
315      status_t res = getBufferMapper().lockAsync(handle, inProducerUsage, inConsumerUsage, rect,
316                                                 vaddr, fenceFd, outBytesPerPixel, outBytesPerStride);
317  
318      return res;
319  }

应用程序调用lockAsync可以获取缓冲区地址,此时应用程序就可以渲染、queuebuffer操作,后续分享会继续

其实这块分配的业务比较直接,一般问题都是在上层APP,例如闪屏、卡顿等,按照我现有的经验可以排查内存是否存在泄露等

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2190160.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用Scikit-image进行图像处理入门

简介 在数据科学的广阔领域中&#xff0c;图像处理占据了重要的一席之地&#xff0c;为分析和处理视觉数据提供了各种工具和技术。Python 拥有丰富的库生态系统&#xff0c;为图像处理提供了多种选择&#xff0c;其中&#xff0c;scikit-image 凭借其强大且易用的功能脱颖而出…

记录使用gym和stable_baseline3训练出成功通关的贪吃蛇ai

参考自b站up林亦LYi的开源项目 传送门 本次只训练了cnn版本的 第一次接触这种项目&#xff0c;建python虚拟环境时出了点难以说清楚的小问题&#xff0c;安装不上requirement.txt中的gym库那个版本&#xff0c;折腾了一会&#xff0c;自己都乱了头绪&#xff0c;最后导致训练…

TMGM:黄金价格持稳,而WTI原油价格和天然气价格飙升

黄金价格顽强地拒绝下跌&#xff0c;昨天和周三继续抵制下行的趋势。 价格继续保持在近期的历史高位附近&#xff0c;很可能会有进一步上涨的动力。美元走强阻止了价格的进一步上涨&#xff0c;但总体上升趋势仍在进行中。 目前还没有明显的向下催化剂迹象&#xff0c;不过如…

c++联合体

// // Created by 徐昌真 on 2024/10/5. // #include <iostream> using namespace std;//定义一个结构体 struct DataS{ //内存空间独立int a;double b;char c[10]; };//定义一个联合体 union DataU{ //内存空间在一起int a;double b;char c[10]; };int main() {//创建…

Pikachu-目录遍历

目录遍历&#xff0c;跟不安全文件上传下载有差不多&#xff1b; 访问 jarheads.php 、truman.php 都是通过 get 请求&#xff0c;往title 参数传参&#xff1b; 在后台&#xff0c;可以看到 jarheads.php 、truman.php所在目录&#xff1a; /var/www/html/vul/dir/soup 图片…

奥博思软件总经理刘玉军受邀为项目经理大会演讲嘉宾

全国项目经理专业人士年度盛会 北京奥博思软件技术有限公司联合创始人、总经理刘玉军先生受邀为PMO评论主办的全国项目经理专业人士年度盛会——2024第四届中国项目经理大会演讲嘉宾&#xff0c;演讲议题为“高效协作的秘密&#xff1a;项目管理平台助力跨部门协作”。大会将于…

信息学奥赛复赛复习12-CSP-J2021-01分糖果-模运算、余数、打擂台求最值、最大值、最小值

PDF文档回复:20241005 **1 P7909 [CSP-J 2021] 分糖果 ** [题目描述] 红太阳幼儿园有 n 个小朋友&#xff0c;你是其中之一。保证 n≥2 有一天你在幼儿园的后花园里发现无穷多颗糖果&#xff0c;你打算拿一些糖果回去分给幼儿园的小朋友们 由于你只是个平平无奇的幼儿园小朋…

【数学分析笔记】第4章第4节 复合函数求导法则及其应用(2)

4. 微分 4.4 复合函数求导法则及其应用 【例4.4.3】 y e 1 cos ⁡ x ye^{\sqrt{1\cos x}} ye1cosx ​&#xff0c;求 y ′ y y′ 【解】 y ′ e 1 cos ⁡ x ⋅ 1 2 1 cos ⁡ x ⋅ ( − sin ⁡ x ) − sin ⁡ x 2 1 cos ⁡ x e 1 cos ⁡ x ye^{\sqrt{1\cos x}}\cdot\f…

【LeetCode】每日一题 2024_10_5 完成旅途的最少时间(二分答案)

前言 每天和你一起刷 LeetCode 每日一题~ 大家国庆节快乐呀~ LeetCode 启动&#xff01; 突然发现&#xff0c;国庆的每日一题&#xff0c;不是坐公交就是坐火车&#xff0c;不是坐火车就是做飞机&#xff0c;这就是你的国庆旅游计划吗&#xff01;力扣&#xff01; 题目&a…

今日凌晨,ChatGPT重磅更新!—— 我心目中的终极AGI界面

今日凌晨&#xff0c;ChatGPT重磅更新&#xff01;—— 我心目中的终极AGI界面 我心目中的终极 AGI 界面是一张空白画布&#xff08;canvas&#xff09;。 今日凌晨&#xff0c;OpenAI 发布 canvas&#xff0c;一个与 ChatGPT 合作写作和编程的新界面&#xff01; canvas&…

Linux基于CentOS学习【进程状态】【进程优先级】【调度与切换】【进程挂起】【进程饥饿】

目录 进程状态 状态决定了什么 进程等待方式——队列 进程状态的表现 挂起状态 基于阻塞的挂起——阻塞挂起 swap分区 进程状态表示 Z僵尸状态 进程的优先级 什么是进程的优先级 为什么会有进程的优先级 进程饥饿 Linux的调度与切换 切换 调度 queue [ 140 ]&am…

模拟算法(3)_Z字形变换

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 模拟算法(3)_Z字形变换 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 1. 题目链…

VGG原理与实战

VGG网络结构 这也更好的块状结构,256个卷积核 卷积就是我们的一个特征图啊往往都会缩小 &#xff0c;然后的话但它通道不会变.卷积一般是使用我们的通道C变大,磁化但是它的通道就是我们那个H和W一般都会变小.下采样的意思就是使分辨率变小 vgg—block内的卷积层都是同结构的意…

【杂谈二之Relay继电器】介绍Relay继电器的概念、原理、分类以及实例应用

一、Relay是什么 Relay就是一个电控制的开关 二、Relay的工作原理 宏观上看主要由两部分电路组成&#xff0c;左侧的电路是低电流电路&#xff0c;右侧是高电流电路 左侧是由线圈绕制成&#xff0c;当有电流通过时就会产生磁场&#xff0c;会对于电枢产生吸引&#xff0c;由于…

【cpp/c++ summary 工具】 vcpkg 包管理器

由于之前的Hunter 包管理器在Boost的构建中速度太慢&#xff0c;准备尝试一下vcpkg。 vcpkg是由microsoft开发的、适用于 Windows、Linux 和 MacOS 的 C 库管理器。 1. 安装 vcpkg&#xff1a; 普通安装 C:\windows\system32>git clone https://github.com/microsoft/vcp…

华为 HCIP-Datacom H12-821 题库 (32)

&#x1f423;博客最下方微信公众号回复题库,领取题库和教学资源 &#x1f424;诚挚欢迎IT交流有兴趣的公众号回复交流群 &#x1f998;公众号会持续更新网络小知识&#x1f63c; 1.当一个运行 MSTP 协议的交换设备端口收到一个配置BPDU 时&#xff0c;会与设备保存的全局配…

20241005给荣品RD-RK3588-AHD开发板刷Rockchip原厂的Android12时使用iperf3测网速

20241005给荣品RD-RK3588-AHD开发板刷Rockchip原厂的Android12时使用iperf3测网速 2024/10/5 14:06 对于荣品RD-RK3588-AHD开发板&#xff0c;eth1位置上的PCIE转RJ458的以太网卡是默认好用的&#xff01; PCIE TO RJ45&#xff1a;RTL8111HS 被识别成为eth0了。inet addr:192.…

华为OD机试 - 最大连续文件之和(Python/JS/C/C++ 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

1.资源《Arduino UNO R3 proteus 仿真工程》说明。

资源链接&#xff1a; Arduino UNO R3 proteus 仿真工程 1.文件明细&#xff1a; 2.文件内容说明 包含&#xff1a;proteus工程、原理图、仿真程序。 3.内容展示 4.简述 该文件为proteus工程&#xff0c;用于Arduino uno r3仿真。 因为软件自动运行&#xff0c;所以最小…

深度学习每周学习总结J1(ResNet-50算法实战与解析 - 鸟类识别)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 目录 0. 总结1. 设置GPU2. 导入数据及处理部分3. 划分数据集4. 模型构建部分5. 设置超参数&#xff1a;定义损失函数&#xff0c;学习率&a…