显示Gralloc模块分配内存(buffer_handle_t、private_handle_t数据结构的关系)

这篇文章我们主要分析下显示中gralloc模块分配内存以及一些数据结构的介绍。

在博客http://blog.csdn.net/kc58236582/article/details/52681363中,我们分析过了从BufferQueueProducer的dequeueBuffer函数开始分配内存的流程。我们直接从如下开始分析。

分配内存流程

我们是调用了GraphicBufferAllocator的alloc函数,并且最后内存地址是保存在buffer_handle_t类型的handle入参中。

status_t GraphicBufferAllocator::alloc(uint32_t width, uint32_t height,
        PixelFormat format, uint32_t usage, buffer_handle_t* handle,
        uint32_t* stride)
{
    if (!width || !height)
        width = height = 1;

    // we have a h/w allocator and h/w buffer is requested
    status_t err;

    // Filter out any usage bits that should not be passed to the gralloc module
    usage &= GRALLOC_USAGE_ALLOC_MASK;

    int outStride = 0;
    err = mAllocDev->alloc(mAllocDev, static_cast<int>(width),
            static_cast<int>(height), format, static_cast<int>(usage), handle,
            &outStride);
    ......
}

我们是调用了mAllocDev的alloc函数,而mAllocDev的赋值如下

GraphicBufferAllocator::GraphicBufferAllocator()
    : mAllocDev(0)
{
    hw_module_t const* module;
    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) {
        gralloc_open(module, &mAllocDev);
    }
}
这个函数的定义在hardware/libhardware/include/hardware/gralloc.h中
static inline int gralloc_open(const struct hw_module_t* module,
        struct alloc_device_t** device) {
    return module->methods->open(module,
            GRALLOC_HARDWARE_GPU0, (struct hw_device_t**)device);
}
再看如下定义,当然这块hal就是每个厂商自己的了(比如arm 高通),因此最后gralloc_open函数是调用了gralloc_device_open函数
static struct hw_module_methods_t gralloc_module_methods =
{
	open: gralloc_device_open
};

private_module_t::private_module_t()
{
#define INIT_ZERO(obj) (memset(&(obj),0,sizeof((obj))))

	base.common.tag = HARDWARE_MODULE_TAG;
	base.common.version_major = 1;
	base.common.version_minor = 0;
	base.common.id = GRALLOC_HARDWARE_MODULE_ID;
	base.common.name = "Graphics Memory Allocator Module";
	base.common.author = "Leadcore Ltd.";
	base.common.methods = &gralloc_module_methods;
因为传进来的name是GRALLOC_HARDWARE_GPU0,最后是调用了alloc_device_open函数
static int gralloc_device_open(const hw_module_t* module, const char* name, hw_device_t** device)
{
	int status = -EINVAL;

	if (!strncmp(name, GRALLOC_HARDWARE_GPU0, MALI_GRALLOC_HARDWARE_MAX_STR_LEN))
	{
		status = alloc_device_open(module, name, device);
	}
	else if (!strncmp(name, GRALLOC_HARDWARE_FB0, MALI_GRALLOC_HARDWARE_MAX_STR_LEN))
	{
		status = framebuffer_device_open(module, name, device);
	}

	return status;
}
在alloc_device_open中,我们就找到了我们需要的alloc函数就是alloc_device_alloc

int alloc_device_open(hw_module_t const* module, const char* name, hw_device_t** device)
{
	alloc_device_t *dev;

	dev = new alloc_device_t;
	if (NULL == dev)
	{
		return -1;
	}

#if USE_VIVANTE_2D == 1
	if (has2Ddev == -1)
	{
		struct stat buf;
		if (stat("/dev/graphics/galcore_smmu", &buf) == 0)
		{
			ALOGI("%s: galcore and smmu both exist!", __FUNCTION__);
			has2Ddev = 1;
			SMMUEnable = 1;
		}
		else if (stat("/dev/graphics/galcore", &buf) == 0)
		{
			ALOGI("%s: only galcore exist!", __FUNCTION__);
			has2Ddev = 1;
			SMMUEnable = 0;
		}
		else
		{
			ALOGI("%s: check galcore failed", __FUNCTION__);
			has2Ddev = 0;
			SMMUEnable = 0;
		}
	}
#endif

	/* initialize our state here */
	memset(dev, 0, sizeof(*dev));

	/* initialize the procs */
	dev->common.tag = HARDWARE_DEVICE_TAG;
	dev->common.version = 0;
	dev->common.module = const_cast<hw_module_t*>(module);
	dev->common.close = alloc_backend_close;
	dev->alloc = alloc_device_alloc;//alloc函数
	dev->free = alloc_device_free;

	if (0 != alloc_backend_open(dev)) {
		delete dev;
		return -1;
	}

	*device = &dev->common;

	return 0;
}

alloc_device_alloc又会调用alloc_backend_alloc函数,而我们的alloc_backend_alloc函数最终是在ion模块的,是在Alloc_ion.c中。这个函数先是调用了ion_share得到共享文件,然后再调用mmap函数得到映射地址。最后新建一个private_handle_t对象,并且把这个映射地址给了base变量。最后再把这一个private_handle_t给了buffer_handle_t对象也就是最后输出的handle对象。

int alloc_backend_alloc(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle, uint64_t fmt, int w, int h)
{
	private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module);
	ion_user_handle_t ion_hnd;
	unsigned char *cpu_ptr = NULL;
	int shared_fd;
	int ret;
	unsigned int heap_mask, priv_heap_flag = 0;
	int ion_flags = 0;
	static int support_protected = 1; /* initially, assume we support protected memory */
	int lock_state = 0;
	int min_pgsz = 0;

	heap_mask = pick_ion_heap(usage);
	set_ion_flags(heap_mask, usage, &priv_heap_flag, &ion_flags);

	ion_hnd = alloc_from_ion_heap(m->ion_client, size, heap_mask, ion_flags, &min_pgsz);
	if (ion_hnd <= ION_INVALID_HANDLE)
	{
		AERR("Failed to ion_alloc from ion_client:%d", m->ion_client);
		return -1;
	}

	ret = ion_share( m->ion_client, ion_hnd, &shared_fd );//获取到共享文件的fd
	if ( ret != 0 )
	{
		AERR( "ion_share( %d ) failed", m->ion_client );
		if ( 0 != ion_free( m->ion_client, ion_hnd ) ) AERR( "ion_free( %d ) failed", m->ion_client );
		return -1;
	}

	if (!(usage & GRALLOC_USAGE_PROTECTED))
	{
		cpu_ptr = (unsigned char*)mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shared_fd, 0 );//映射地址

		if ( MAP_FAILED == cpu_ptr )
		{
			AERR( "ion_map( %d ) failed", m->ion_client );
			if ( 0 != ion_free( m->ion_client, ion_hnd ) ) AERR( "ion_free( %d ) failed", m->ion_client );
			close( shared_fd );
			return -1;
		}
		lock_state = private_handle_t::LOCK_STATE_MAPPED;

#if GRALLOC_INIT_AFBC == 1
		if (fmt & (GRALLOC_ARM_INTFMT_AFBC | GRALLOC_ARM_INTFMT_AFBC_SPLITBLK | GRALLOC_ARM_INTFMT_AFBC_WIDEBLK))
		{
			init_afbc(cpu_ptr, fmt, w, h);
		}
#endif /* GRALLOC_INIT_AFBC == 1 */
	}

	private_handle_t *hnd = new private_handle_t( private_handle_t::PRIV_FLAGS_USES_ION | priv_heap_flag, usage, size, cpu_ptr,
	                                              lock_state );//新建一个private_handle_t把映射的地址给handle的base变量

	if ( NULL != hnd )
	{
		uint64_t phys_addr;
		hnd->share_fd = shared_fd;
		hnd->ion_hnd = ion_hnd;
		hnd->min_pgsz = min_pgsz;
		hnd->ion_hnd_debug = ion_hnd;

		if(ion_flags & (ION_HEAP_LC_VIDEO_MASK|ION_HEAP_LC_ISP_MASK))
		{
			ret = ion_phys(m->ion_client, shared_fd, &phys_addr);
			if(ret == 0)
			{
				hnd->phys_addr = phys_addr;
				*pHandle = hnd;
				return 0;
			}
		} else {
			*pHandle = hnd;//最后把这个private_handle_t给了buffer_handle_t就是最后要的handle对象
			return 0;
		}
	}
	else
	{
		AERR( "Gralloc out of mem for ion_client:%d", m->ion_client );
	}

	close( shared_fd );

	if(!(usage & GRALLOC_USAGE_PROTECTED))
	{
		ret = munmap( cpu_ptr, size );
		if ( 0 != ret ) AERR( "munmap failed for base:%p size: %zd", cpu_ptr, size );
	}

	ret = ion_free( m->ion_client, ion_hnd );
	if ( 0 != ret ) AERR( "ion_free( %d ) failed", m->ion_client );
	return -1;
}

最后我们把private_handle_t的指针给了buffer_handle_t对象,我们看看这两个结构体有什么关系。


buffer_handle_t和private_handle_t关系

首先在system/core/include/system/window.h中有如下定义

typedef const native_handle_t* buffer_handle_t;

在system/core/include/utils/NativeHandle.h有如下定义

typedef struct native_handle native_handle_t;

再来看看native_handle_t的定义

typedef struct native_handle
{
    int version;        /* sizeof(native_handle_t) */
    int numFds;         /* number of file-descriptors at &data[0] */
    int numInts;        /* number of ints at &data[numFds] */
    int data[0];        /* numFds + numInts ints */
} native_handle_t;

这样说native_handle就是buffer_handle_t的指针

我们再来看看private_handle_t 的定义,这里我们可以看到c++和c做了区别。c++的话直接继承native_handle这样native_handle的内存地址就在前面了,c的话直接把native_handle nativeHandle放在第一个,意思其实是一样的。而当我们把private_handle_t的指针强制转成buffer_handle_t的指针时。由于前面的内容都是native_handle的,这样也就没啥区别了,只是在用的时候再把buffer_handle_t的指针强制转成private_hanele_t类型的,就可以继续调用private_handle_t的变量了。

#ifdef __cplusplus
struct private_handle_t : public native_handle
{
#else
struct private_handle_t
{
	struct native_handle nativeHandle;
#endif

	enum
	{
		PRIV_FLAGS_FRAMEBUFFER = 0x00000001,
		PRIV_FLAGS_USES_UMP    = 0x00000002,
		PRIV_FLAGS_USES_ION    = 0x00000004,
		PRIV_FLAGS_USES_ION_DMA_HEAP = 0x00000008,
		PRIV_FLAGS_WIFI_DISPLAY    = 0x01000000,
	};

	enum
	{
		LOCK_STATE_WRITE     =   1<<31,
		LOCK_STATE_MAPPED    =   1<<30,
		LOCK_STATE_READ_MASK =   0x3FFFFFFF
	};

	/*
	 * Shared file descriptor for dma_buf sharing. This must be the first element in the
	 * structure so that binder knows where it is and can properly share it between
	 * processes.
	 * DO NOT MOVE THIS ELEMENT!
	 */
	int     share_fd;

#if MALI_AFBC_GRALLOC == 1
	int     share_attr_fd;
#endif

	ion_user_handle_t ion_hnd;
	ion_user_handle_t ion_hnd_debug;

	// ints
	int        magic;
	int        req_format;
	uint64_t   internal_format __attribute__((aligned(8)));
	int        byte_stride;
	int        flags;
	int        usage;
	int        size;
	int        width;
	int        height;
	int        format;
	int        internalWidth;
	int        internalHeight;
	int        stride;
	union {
		void*    base;//虚拟地址
		uint64_t padding __attribute__((aligned(8)));
	};
	int        lockState;
	int        writeOwner;
	int        pid;

#if MALI_AFBC_GRALLOC == 1
	// locally mapped shared attribute area
	union {
		void*    attr_base;
		uint64_t padding3 __attribute__((aligned(8)));
	};
#endif

	mali_gralloc_yuv_info yuv_info;
#if USE_VIVANTE_2D
	/* Vivante private ints. */
	int     viv_priv[24];
#endif
	uint64_t     phys_addr __attribute__((aligned(8)));//物理地址

	// Following members is for framebuffer only
	int   fd;
	union {
		off_t    offset;
		uint64_t padding4 __attribute__((aligned(8)));
	};






  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值