Gralloc图形缓冲的分配过程

广告

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

其实越往底下走在很多人嘴里就会变得很玄乎,变得不可思议,这里的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.cppusing 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.cppGralloc2Allocator::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.h49  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.xdnf.cn/news/1555102.html

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

相关文章

Pikachu-目录遍历

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

传感器模块编程实践(二)W5500 SPI转以太网模块简介及驱动源码

文章目录 一.概要二.W5500芯片介绍W5500通讯协议介绍 三.W5500模块介绍四.W5500模块原理图五.W5500以太网模通讯实验六.CubeMX工程源代码下载七.小结 一.概要 我们介绍过单片机的以太网系统一般是由&#xff1a;单片机MACPHYRJ45。有些单片机比如STM32F407VET6芯片内部自带MAC…

windows下载Redis

1.下载地址 Releases tporadowski/redis GitHub 下载后&#xff0c;将压缩包解压到你的文件夹即可。&#xff08;此时&#xff0c;redis已经完成安装&#xff09; 2.使用 2.1双击redis.server.exe即可启动&#xff08;启动redis服务端&#xff09;&#xff08;或者在当前目…

超声波清洗机什么牌子值得入手?推荐四款入手不亏的眼镜清洗机

在当今这个注重细节完美的时代&#xff0c;超声波清洗机凭借其卓越的清洁效率、深层渗透力及细腻的清洗效果&#xff0c;迅速赢得了家庭与专业场景的青睐。无论是精细的珠宝、眼镜框&#xff0c;还是金属装饰品、电子设备乃至医疗器具&#xff0c;超声波技术都能精准祛除隐秘处…

0110 Redis缓存的更新策略

在很多高并发的场景如秒杀系统&#xff0c;QPS会瞬时暴增&#xff0c;如果采用直接读写数据库&#xff08;如MySQL&#xff09;的方式&#xff0c;很可能会将数据库打垮。因此这种场景需要引入Redis做缓存&#xff0c;应对高并发的访问。但同时也会引入新的风险&#xff0c;最常…

数据结构——List接口

文章目录 一、什么是List&#xff1f;二、常见接口介绍三、List的使用总结 一、什么是List&#xff1f; 在集合框架中&#xff0c;List是一个接口&#xff0c;通过其源码&#xff0c;我们可以清楚看到其继承了Collection。 Collection 也是一个接口&#xff0c;该接口中规范了后…

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

&#x1f423;博客最下方微信公众号回复题库,领取题库和教学资源 &#x1f424;诚挚欢迎IT交流有兴趣的公众号回复交流群 &#x1f998;公众号会持续更新网络小知识&#x1f63c; 1. 默认情况下&#xff0c;IS-IS Level-1-2 路由器会将 Level-2 区域的明细路由信息发布到Lev…

Python入门--函数

目录 1. 函数介绍 2. 函数的定义 3. 函数的参数 4. 函数的返回值 5. 函数说明文档 6. 函数的嵌套调用 7. 函数的作用域 (1). 局部变量 (2). 全局变量 (3). global关键字 1. 函数介绍 函数&#xff1a;是组织好的&#xff0c;可重复使用的&#xff0c;用来实现特定功能…

YOLO-V7 二元分类器

在评估二元分类器性能时&#xff0c;TP、FP、TN和FN是四个核心指标&#xff0c;它们分别代表真阳性、假阳性、真阴性和假阴性。以下是这些指标的定义、计算方法以及在实际应用中的意义&#xff1a; 定义 TP&#xff08;真阳性&#xff09;&#xff1a;模型正确预测为正类且实…

Yocto - 使用Yocto开发嵌入式Linux系统_06 掌握Bitbake工具

Grasping the BitBake Tool 在上一章中&#xff0c;我们了解了元数据、元数据集合概念以及 conf/layer.conf 的重要性。在本章中&#xff0c;我们将更深入地研究元数据&#xff0c;了解配方如何相互依赖&#xff0c;并了解 BitBake 如何处理依赖关系。 In the previous chapter…

k8s 中微服务之 MetailLB 搭配 ingress-nginx 实现七层负载

目录 1 MetailLB 搭建 1.1 MetalLB 的作用和原理 1.2 MetalLB功能 1.3 部署 MetalLB 1.3.1 创建deployment控制器和创建一个服务 1.3.2 下载MealLB清单文件 1.3.3 使用 docker 对镜像进行拉取 1.3.4 将镜像上传至私人仓库 1.3.5 将官方仓库地址修改为本地私人地址 1.3.6 运行清…

【路径规划】多机器人路径规划

摘要 多机器人路径规划在现代自动化、仓储管理及智能交通系统中有着广泛的应用。本文提出了一种基于A*算法的多机器人路径规划方法&#xff0c;旨在解决多机器人在同一环境中的路径冲突问题。通过采用启发式搜索和路径优化策略&#xff0c;机器人能够在保持避障的前提下实现最…

Middleware---RocketMQ

RocketMQ是一个开源的分布式消息中间件。它是一种 低延迟、高可用、高可靠、高并发 的消息队列系统&#xff0c;用于在分布式系统中进行异步通信。 RocketMQ架构模型 Producer Group&#xff1a;消息生产者组&#xff0c;负责发送消息。 Broker&#xff1a;存储消息的服务节…

java:pdfbox 3.0 去除扫描版PDF中文本水印

官网下载 https://pdfbox.apache.org/download.html下载 pdfbox-app-3.0.3.jar cd D:\pdfbox 运行 java -jar pdfbox-app-3.0.3.jar java -jar pdfbox-app-3.0.3.jar Usage: pdfbox [COMMAND] [OPTIONS] Commands:debug Analyzes and inspects the internal structu…

Java第二阶段---10方法带参---第三节 面向对象和面向过程的区别

1.案例 2.代码实现 面向过程 import java.util.Scanner;/*** Procedure Oriented Programming 面向过程编程*/public class POP {public static void main(String[] args) {Scanner sc new Scanner(System.in);while(true){System.out.println("1.学生成绩管理");…

双十一不能错过的好物推荐!强推五款超好用的品牌好物

双十一快到了&#xff0c;这个时候的优惠力度都是最大的&#xff0c;还不知道买啥的小伙伴们赶紧来看这篇好物推荐&#xff01;以下五款产品是我花了几天时间精心挑选出来的&#xff0c;看完之后保证你想加入购物车&#xff01; 品牌好物推荐一、希亦CG超声波清洗机 如果你带眼…

中小型网络系统综合实验

一、实验要求 1.pc端自动获取ip地址&#xff0c;可以互通访问&#xff0c;可以访问域名解析服务器 2.设置vlan&#xff0c;三层交换机实现不同vlan之间的交流 3.设置静态路由&#xff0c;配置nat地址转换&#xff0c;实现全网可达 二、实验思路 1.首先给LSW2配置vlan 10 &a…

【无人机设计与技术】基于EKF的四旋翼无人机姿态估计matlab仿真

摘要&#xff1a; 本文设计了一种基于扩展卡尔曼滤波&#xff08;EKF&#xff09;的四旋翼无人机姿态估计方法。利用EKF算法处理四旋翼无人机姿态的动态模型&#xff0c;通过该滤波算法实现对姿态的实时估计和校正。该方法通过对无人机的运动学和动力学模型的分析&#xff0c;…

【Python游戏开发】贪吃蛇游戏demo拓展

拓展上一项目【Python游戏开发】贪吃蛇 实现穿墙效果 # 检测游戏是否结束 def check_gameover():global finished# 移除蛇头位置超过窗口判断for n in range(len(body) - 1):if(body[n].x snake_head.x and body[n].y snake_head.y):finished True # 状态检测 def ch…

涉案财务管理系统架构二—交警相关系统——未来之窗行业应用跨平台架构

一、涉案财务保管流程 二、涉案财务返回流程 三、阿雪技术观 拥抱开源与共享&#xff0c;见证科技进步奇迹&#xff0c;畅享人类幸福时光&#xff01; 让我们积极投身于技术共享的浪潮中&#xff0c;不仅仅是作为受益者&#xff0c;更要成为贡献者。无论是分享自己的代码、撰写…