camera内存之---gralloc_buffer(3)

因为camera要申请gralloc buf的缘故,打算仔细看看grallocbuf的原理,其实之前大概知道一些,这次梳理一下。因为部分接口封成了库,所以也没有去看相关代码,但是可以理解概念,知道gralloc是什么,怎么用就可以了。
Gralloc封装了用户层对帧缓冲区的操作接口,他可以申请图形缓冲区,然后将个缓冲区映射到应用程序上来,接下来就可以绘制界面。
主要是用于gpu和fb的操作,gpu用于分配图形缓冲,fb用于渲染帧缓冲。
但是rk从安卓7.1之后实现drm驱动,fb部分被删除了,应该是底层包含这部分功能。
先看看gralloc.h里面的结构

typedef struct gralloc_module_t {
struct hw_module_t common;//hal标准定义
//注册图形缓冲区,实际将一块图形缓冲区映射到一个进程的地址空间去
int (*registerBuffer)(struct gralloc_module_t const* module,
            buffer_handle_t handle);
int (*unregisterBuffer)(struct gralloc_module_t const* module,
buffer_handle_t handle);
//可以锁定,防止冲突,这里可以锁定缓冲区特定区域
int (*lock)(struct gralloc_module_t const* module,
            buffer_handle_t handle, int usage,
            int l, int t, int w, int h,
            void** vaddr);
    int (*unlock)(struct gralloc_module_t const* module,
            buffer_handle_t handle);
int (*lock_ycbcr)(struct gralloc_module_t const* module,
            buffer_handle_t handle, int usage,
            int l, int t, int w, int h,
            struct android_ycbcr *ycbcr);
    int (*lockAsync)(struct gralloc_module_t const* module,
            buffer_handle_t handle, int usage,
            int l, int t, int w, int h,
            void** vaddr, int fenceFd);
    int (*unlockAsync)(struct gralloc_module_t const* module,
            buffer_handle_t handle, int* fenceFd);
    int (*lockAsync_ycbcr)(struct gralloc_module_t const* module,
            buffer_handle_t handle, int usage,
            int l, int t, int w, int h,
            struct android_ycbcr *ycbcr, int fenceFd);
    void* reserved_proc[3];
} gralloc_module_t;

默认的代码在gralloc_module_t外面又封装了一层。保存了framebuffer的相关信息

struct private_module_t {
    gralloc_module_t base;
    private_handle_t* framebuffer;
    uint32_t flags;
    uint32_t numBuffers;
    uint32_t bufferMask;
    pthread_mutex_t lock;
    buffer_handle_t currentBuffer;
    int pmem_master;
    void* pmem_master_base;
    struct fb_var_screeninfo info;
    struct fb_fix_screeninfo finfo;
    float xdpi;
    float ydpi;
    float fps;
};

但是rk应该是实现了

struct drm_module_t {
	gralloc_module_t base;

	pthread_mutex_t mutex;

    /** gralloc_drm_device. */
	struct gralloc_drm_t *drm;
#ifdef __cplusplus
	/* default constructor */
	drm_module_t();
#endif

#if RK_DRM_GRALLOC
	volatile int32_t refcount;
#endif
}

这个gralloc实现就相对更简单了。

Hal部分rk的代码在\hardware\rockchip\libgralloc下面
在camera 部分调用加载模块的函数如下:
返回的alloc_device_是alloc_device_t结构,描述gralloc,里面有alloc和free函数。

加载模块的时候调用drm_module_t::drm_module_t()函数赋值gralloc_module_t里面的methods->open函数以及里面register和lock这些函数。

gralloc_open 执行的是模块的open函数

static inline int gralloc_open(const struct hw_module_t* module, 
        struct alloc_device_t** device) {
    return module->methods->open(module, 
            GRALLOC_HARDWARE_GPU0, TO_HW_DEVICE_T_OPEN(device));
}

Open函数调用drm_mod_open到drm_mod_open_gpu0函数。里面先执行
Drm_init()。这个初始化内容是创建gralloc_drm_t设备。打开系统属性vendor.ggralloc.drm.device里面记录的drm设备路径。
然后调用gralloc_drm_drv_create_for_rockchip

struct gralloc_drm_drv_t *gralloc_drm_drv_create_for_rockchip(int fd)
{
……
rk_drv = new rk_driver_of_gralloc_drm_device_t;
……
//这个函数实现在libdrm_rockchip.so,竟然不公开。。。
rk_drv->rk_drm_dev = rockchip_device_create(fd);
……
//初始化 'rk_drv' 中的 rk_drm_adapter.
rk_drm_adapter_init(rk_drv);
……
//赋值相关函数
	rk_drv->fd_of_drm_dev = fd;
	rk_drv->base.destroy = drm_gem_rockchip_destroy;
	rk_drv->base.alloc = drm_gem_rockchip_alloc;
	rk_drv->base.free = drm_gem_rockchip_free;
	rk_drv->base.map = drm_gem_rockchip_map;
	rk_drv->base.unmap = drm_gem_rockchip_unmap;
return &rk_drv->base;
}

然后赋值alloc和free函数,分别为
alloc->alloc = drm_mod_alloc_gpu0;
alloc->free = drm_mod_free_gpu0;
open整个过程如上面所说,初始化drm设备,和对应的操作函数。

初始化的时候要注册buffer
status_t CameraBuffer::init(const camera3_stream_buffer *aBuffer, int cameraId)
调用int ret = registerBuffer();//向gralloc 模块注册
mGbmBufferManager->Register(mHandle);
int CameraBufferManagerImpl::Register(buffer_handle_t buffer) {
执行gm_module_->registerBuffer(gm_module_, buffer);
注册buffer。
调用drm_mod_register_buffer—-> gralloc_drm_handle_register- validate_handle
主要调用drm_gem_rockchip_alloc 制作import工作

申请buffer的函数

int CameraBufferManagerImpl::AllocateGrallocBuffer(size_t width,
                                                   size_t height,
                                                   uint32_t format,
                                                   uint32_t usage,
                                                   buffer_handle_t* out_buffer,
                                                   uint32_t* out_stride) {
……
    int ret = alloc_device_->alloc(alloc_device_, width, height,
                                   format, usage, out_buffer,
                                   reinterpret_cast<int*>(out_stride));
}

这样会调用到gralloc的alloc函数

static int drm_mod_alloc_gpu0(alloc_device_t *dev,
		int w, int h, int format, int usage,
		buffer_handle_t *handle, int *stride)
{
……
bo = gralloc_drm_bo_create(dmod->drm, w, h, format, usage);
	*handle = gralloc_drm_bo_get_handle(bo, &byte_stride);

	gralloc_drm_handle_get_format(*handle, &actual_format);
	bpp = gralloc_drm_get_bpp(actual_format);
}
再看
struct gralloc_drm_bo_t *gralloc_drm_bo_create(struct gralloc_drm_t *drm,
		int width, int height, int format, int usage)
{
……
//先创建handle
handle = create_bo_handle(width, height, format, usage);
bo = drm->drv->alloc(drm->drv, handle);
……
return bo;

}

drm->drv->alloc 执行的是drm_gem_rockchip_alloc
这个函数特别长
大概是先判断格式获取stride,然后alloc一个rockchip_buffer结构体,这个是buffer的封装结构。接着判断如果prime_fd判断是否已经分配buffer,分配就就调用drmPrimeFDToHandle ,import到当前进程。如果buffer没有分配,则分配,调用rk_drm_adapter_create_rockchip_bo分配dma buffer.实际说通过rk_drm_adapter_get_gem_handle,返回创建到handle(gem_obj)。

实际上由于当前部分函数没有源码,说不详细,但是知道申请的大概是alloc函数是获取bpp,宽高,然后调用DRM_IOCTL_MODE_CREATE_DUMB这条ioctl。然后调用DRM_IOCTL_MODE_MAP_DUMB 来map这段内存。对于camera就只要知道申请,import就可以了,camera申请了gralloc buffer用做中间的处理buffer,上层是surface,会转换成gralloc buffer,然后在hal中import过来。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值