自学内容网 自学内容网

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.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,例如闪屏、卡顿等,按照我现有的经验可以排查内存是否存在泄露等


原文地址:https://blog.csdn.net/u010134178/article/details/142712724

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!