Android图形缓冲区映射过程源码分析
来源:互联网 发布:南大碎尸案推理 知乎 编辑:程序博客网 时间:2024/05/29 11:05
原文:http://blog.csdn.net/yangwen123/article/details/12234931?utm_source=tuicool
Android图形缓冲区分配过程源码分析中介绍了图形buffer的分配过程,图形buffer可以从系统帧缓冲区分配也可以从内存中分配,分配一个图形buffer后还需要将该图形缓冲区映射到分配该buffer的进程地址空间来,在Android系统中,图形buffer的管理由SurfaceFlinger服务来负责,在Android SurfaceFlinger服务启动过程源码分析中我们了解到SurfaceFlinger可以以服务进程的方式启动也可以以服务线程的方式在SystemServer进程中启动,如果是以服务进程的方式启动,那么创建的图形缓冲区就将映射到SurfaceFlinger进程地址空间;如果是以服务线程的方式在SystemServer中启动,那么创建的图形缓冲区将映射到SystemServer进程地址空间。在系统帧缓冲区中分配的图形缓冲区是在SurfaceFlinger服务中使用,而在内存中分配的图形缓冲区既可以在SurfaceFlinger服务中使用,也可以在其它的应用程序中使用。当其它的应用程序需要使用图形缓冲区的时候,它们就会请求SurfaceFlinger服务为它们分配并将SurfaceFlinger服务返回来的图形缓冲区映射到应用程序进程地址空间。图形缓冲区的分配过程在Android图形缓冲区分配过程源码分析中已经分析过了,在从内存中分配buffer时,已经将分配的buffer映射到了SurfaceFlinger服务进程地址空间,如果该buffer是应用程序请求SurfaceFlinger服务为它们分配的,那么还需要将SurfaceFlinger服务返回来的图形缓冲区映射到应用程序进程地址空间,本文介绍图形缓冲区映射到应用程序进程地址空间的过程。
Android提供了GraphicBufferMapper工具类,该类为上层访问Gralloc模块中的gralloc_module_t提供了接口,采用单例模式构造GraphicBufferMapper对象。
- GraphicBufferMapper::GraphicBufferMapper(): mAllocMod(0)
- {
- hw_module_t const* module;
- //根据模块ID得到模块描述符的首地址
- int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
- ALOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
- if (err == 0) {
- //将hw_module_t的指针转换为gralloc_module_t类型指针
- mAllocMod = (gralloc_module_t const *)module;
- }
- }
GraphicBufferMapper提供了访问Gralloc模块的gralloc_module_t接口,GraphicBuffer就是通过其成员变量mBufferMapper来注册buffer的。
GraphicBuffer::unflatten()
-->GraphicBufferMapper::registerBuffer()
-->mAllocMod->registerBuffer()
-->gralloc_register_buffer()
GraphicBuffer::free_handle()
-->GraphicBufferMapper::unregisterBuffer()
-->mAllocMod->unregisterBuffer()
-->gralloc_unregister_buffer()
GraphicBuffer::lock()
-->GraphicBufferMapper::lock()
-->mAllocMod->lock()
-->gralloc_lock()
GraphicBuffer::unlock()
-->GraphicBufferMapper::unlock()
-->mAllocMod->unlock()
-->gralloc_unlock()
registerBuffer和unregisterBuffer分别用来注册和注销一个指定的图形缓冲区,所谓注册图形缓冲区,实际上就是将一块图形缓冲区映射到一个进程的地址空间去,而注销图形缓冲区就是执行相反的操作。lock和unlock分别用来锁定和解锁一个指定的图形缓冲区,在访问一块图形缓冲区的时候,例如,向一块图形缓冲写入内容的时候,需要将该图形缓冲区锁定,用来避免访问冲突。在锁定一块图形缓冲区的时候,可以指定要锁定的图形绘冲区的位置以及大小,这是通过参数l、t、w和h来指定的,其中,参数l和t指定的是要访问的图形缓冲区的左上角位置,而参数w和h指定的是要访问的图形缓冲区的宽度和长度。锁定之后,就可以获得由参数参数l、t、w和h所圈定的一块缓冲区的起始地址,保存在输出参数vaddr中。另一方面,在访问完成一块图形缓冲区之后,需要解除这块图形缓冲区的锁定。
1. 图形缓冲区的注册过程
- status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
- {
- ATRACE_CALL();
- status_t err;
- err = mAllocMod->registerBuffer(mAllocMod, handle);
- return err;
- }
- int gralloc_register_buffer(gralloc_module_t const* module,buffer_handle_t handle)
- {
- //校验图形buffer
- if (private_handle_t::validate(handle) < 0)
- return -EINVAL;
- // if this handle was created in this process, then we keep it as is.
- int err = 0;
- private_handle_t* hnd = (private_handle_t*)handle;
- //判断当前进程是否为创建该图形buffer的进程,如果是创建该图形buffer的进程,则不需要在重复映射了,因为在创建过程中已经完成了地址空间的映射过程
- if (hnd->pid != getpid()) {
- void *vaddr;
- err = gralloc_map(module, handle, &vaddr);
- }
- return err;
- }
- static int gralloc_map(gralloc_module_t const* module,
- buffer_handle_t handle,
- void** vaddr)
- {
- private_handle_t* hnd = (private_handle_t*)handle;
- if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
- size_t size = hnd->size;
- void* mappedAddress = mmap(0, size,PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
- if (mappedAddress == MAP_FAILED) {
- ALOGE("Could not mmap %s", strerror(errno));
- return -errno;
- }
- hnd->base = intptr_t(mappedAddress) + hnd->offset;
- }
- *vaddr = (void*)hnd->base;
- return 0;
- }
2. 图形缓冲区的注销过程
图形缓冲区的注销过程和注册过程恰恰相反,函数调用过程类型,就是取消地址空间映射。- status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle)
- {
- ATRACE_CALL();
- status_t err;
- err = mAllocMod->unregisterBuffer(mAllocMod, handle);
- ALOGW_IF(err, "unregisterBuffer(%p) failed %d (%s)",handle, err, strerror(-err));
- return err;
- }
- int gralloc_unregister_buffer(gralloc_module_t const* module,buffer_handle_t handle)
- {
- if (private_handle_t::validate(handle) < 0)
- return -EINVAL;
- // never unmap buffers that were created in this process
- private_handle_t* hnd = (private_handle_t*)handle;
- if (hnd->pid != getpid()) {
- if (hnd->base) {
- gralloc_unmap(module, handle);
- }
- }
- return 0;
- }
- static int gralloc_unmap(gralloc_module_t const* module,buffer_handle_t handle)
- {
- private_handle_t* hnd = (private_handle_t*)handle;
- if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
- void* base = (void*)hnd->base;
- size_t size = hnd->size;
- if (munmap(base, size) < 0) {
- ALOGE("Could not unmap %s", strerror(errno));
- }
- }
- hnd->base = 0;
- return 0;
- }
3. 图形缓冲区的锁定过程
- status_t GraphicBufferMapper::lock(buffer_handle_t handle,
- int usage, const Rect& bounds, void** vaddr)
- {
- ATRACE_CALL();
- status_t err;
- err = mAllocMod->lock(mAllocMod, handle, usage,
- bounds.left, bounds.top, bounds.width(), bounds.height(),vaddr);
- ALOGW_IF(err, "lock(...) failed %d (%s)", err, strerror(-err));
- return err;
- }
- int gralloc_lock(gralloc_module_t const* module,
- buffer_handle_t handle, int usage,
- int l, int t, int w, int h,
- void** vaddr)
- {
- //根据硬件来具体实现
- return 0;
- }
4. 图形缓冲区的解锁过程
- status_t GraphicBufferMapper::unlock(buffer_handle_t handle)
- {
- ATRACE_CALL();
- status_t err;
- err = mAllocMod->unlock(mAllocMod, handle);
- ALOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err));
- return err;
- }
- int gralloc_unlock(gralloc_module_t const* module, buffer_handle_t handle)
- {
- if (private_handle_t::validate(handle) < 0)
- return -EINVAL;
- //根据硬件来具体实现
- ...
- return 0;
- }
- Android图形缓冲区映射过程源码分析
- Android图形缓冲区映射过程源码分析
- Android图形缓冲区映射过程源码分析
- Android图形缓冲区分配过程源码分析
- Android帧缓冲区状态监控过程源码分析
- 分析Android帧缓冲区状态监控过程
- Android 图形系统之图形缓冲区分配
- openSceneGraph源码分析——图形绘制过程
- [Android源码分析]蓝牙搜索过程分析
- Android 源码分析 -- (一) Android启动过程
- Android请求注册服务过程源码分析
- Android服务查询完整过程源码分析
- Android服务注册完整过程源码分析
- Android应用程序包扫描过程源码分析
- Android SurfaceFlinger服务启动过程源码分析
- Android OpenGL库加载过程源码分析
- Android应用程序创建Surface过程源码分析
- Android VSync信号产生过程源码分析
- Node.js 入门系列——寻找第三方模块
- 【C语言】猴子吃桃问题。
- JavaScript 基础 Part 2
- cocos2d-x添加android手机震动
- Canvas之太阳与地球
- Android图形缓冲区映射过程源码分析
- [部署篇6]VMWare搭建Openstack——控制节点的Neutron安装
- SDOUG--Oracle山东用户组成立了
- ListView 中使用onItemClick和onItemLongClick
- HDU 4749 Parade Show Kmp
- Redis data types
- NSArray,NSSet,NSDictionary 对比总结
- 特定条件下结构风险最小化等价于最大后验概率估计得证明
- 在thinkphp3.2基础上封装上传图片接口