android graphic(7)—gralloc分配图形缓冲区


android中,HAL层的gralloc库负责了申请图形缓冲区的所有工作,HAL层之上的Surface、BufferQueue最终都是调用gralloc库去申请图形缓冲区,然后返回给上层一个buffer_handle_t的handle,这个handle的结构大致如下所示,

typedef struct native_handle
{
    int version;        /* sizeof(native_handle_t) */
    //data[0]中的文件描述符个数
    int numFds;         /* number of file-descriptors at &data[0] */
    //&data[numFds]中int的个数
    int numInts;        /* number of ints at &data[numFds] */
    int data[0];        /* numFds + numInts ints */
} native_handle_t;

typedef const native_handle_t* buffer_handle_t;

返回的这个handle中的实际有用数据都在data[0]中,里面有fd和一些int值,都是些什么?先分析下gralloc如何分配图形缓冲区,在分配缓冲区时mmap函数是关键。

mmap

mmap可以将某个设备或者文件映射到应用程序进程的内存空间中,mmap函数返回值为用户空间映射的这段内存,这样访问这段内存就相当于对设备/文件进行读写,而不用再通过read(),write()了,减少了数据拷贝的次数。

void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset);

一个使用的例子为,通过mmap将fd所对应的文件或者设备映射到用户进程,返回的用户进程内存起始地址为vaddr,大小为fbSize,

void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

上面data[0]中里面的fd和一些int值最主要的就是mmap中的fd、fbSize、以及返回的起始地址vaddr,而gralloc分配图形缓冲区,又分为framebuffer图形缓冲区和普通图形缓冲区两种。

gralloc分配framebuffer图形缓冲区

gralloc调用gralloc_alloc_framebuffer()分配framebuffer的内存,其核心是对fb设备/dev/graphics/fb*或者/dev/fb*执行mmap(),映射到用户空间,然后去操作。

static int gralloc_alloc_framebuffer(alloc_device_t* dev,
        size_t size, int usage, buffer_handle_t* pHandle)
{
    private_module_t* m = reinterpret_cast<private_module_t*>(
            dev->common.module);
    pthread_mutex_lock(&m->lock);
    int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle);
    pthread_mutex_unlock(&m->lock);
    return err;
}
static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev,
        size_t size, int usage, buffer_handle_t* pHandle)
{
    private_module_t* m = reinterpret_cast<private_module_t*>(
            dev->common.module);

    // allocate the framebuffer
    if (m->framebuffer == NULL) {
        // initialize the framebuffer, the framebuffer is mapped once
        // and forever.
        //framebuffer的分配主要就是对fb设备的映射
        int err = mapFrameBufferLocked(m);
        if (err < 0) {
            return err;
        }
    }
    .........
}
int mapFrameBufferLocked(struct private_module_t* module)
{
    // already initialized...
    if (module->framebuffer) {
        return 0;
    }

    char const * const device_template[] = {
            "/dev/graphics/fb%u",
            "/dev/fb%u",
            0 };

    int fd = -1;
    int i=0;
    char name[64];
    //打开设备文件,返回fd
    while ((fd==-1) && device_template[i]) {
        snprintf(name, 64, device_template[i], 0);
        fd = open(name, O_RDWR, 0);
        i++;
    }
    ............
    //对fd进行mmap,大小为fbSize
    void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if (vaddr == MAP_FAILED) {
        ALOGE("Error mapping the framebuffer (%s)", strerror(errno));
        return -errno;
    }
    //这个返回的vaddr,就是申请的图形缓冲区,需要保存起来,返回给上层
    module->framebuffer->base = intptr_t(vaddr);
    memset(vaddr, 0, fbSize);
 }

gralloc分配普通图形缓冲区

而普通图形缓冲区的分配是调用gralloc_alloc_buffer(),其核心是先在内核中创建一块匿名共享内存,关于匿名共享内存网上有很多资料(匿名共享内存通过tmpfs临时文件、binder传递fd可以将内核中的同一块内存映射到不同进程中,这样也是一种进程间通信的方式,普通图形缓冲区就是通过这种方式在不同进程中进行共享的,例如在BufferQueue所在进程中创建buffer,然后在Surface所在进程中通过映射使用这个buffer),调用ashmem_create_region()返回对应的fd,然后再对这个fd,size进行映射,给上层进程返回缓冲区的起始地址。

static int gralloc_alloc_buffer(alloc_device_t* dev,
        size_t size, int usage, buffer_handle_t* pHandle)
{
    int err = 0;
    int fd = -1;

    size = roundUpToPageSize(size);
    //① 创建匿名共享内存
    fd = ashmem_create_region("gralloc-buffer", size);
    if (fd < 0) {
        ALOGE("couldn't create ashmem (%s)", strerror(-errno));
        err = -errno;
    }

    if (err == 0) {
        private_handle_t* hnd = new private_handle_t(fd, size, 0);
        gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>(
                dev->common.module);
         //② 执行mmap对内存进行mmap
        err = mapBuffer(module, hnd);
        if (err == 0) {
            *pHandle = hnd;
        }
    }

    ALOGE_IF(err, "gralloc failed err=%s", strerror(-err));

    return err;
}
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值