前言:在MSM处理器中,重新实现了Gralloc模块的架构,此Gralloc模块是基于FrameBuffer和Pmem驱动实现的。
一、文件gralloc.cpp
MSM平台中和Gralloc模块相关的文件目录:\hardware\qcom\display\libgralloc\
在文件gralloc.cpp中,使用Gralloc中的结构体private_module_t来扩展里面的结构体private_module_t。结构体private_module_t的实现文件是gtalloc_priv.h,在里面宝海了和上下文有关的信息。下面将简单分析文件gralloc.cpp的实现流程。
在文件gralloc.cpp中首先需要定义结构体HAL_MODULE_INFO_SYM,具体代码如下:
// HAL module initialize
struct private_module_t HAL_MODULE_INFO_SYM = {
base: {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: 1,
version_minor: 0,
id: GRALLOC_HARDWARE_MODULE_ID,
name: "Graphics Memory Allocator Module",
author: "The Android Open Source Project",
methods: &gralloc_module_methods,
dso: 0,
reserved: {0},
},
registerBuffer: gralloc_register_buffer,
unregisterBuffer: gralloc_unregister_buffer,
lock: gralloc_lock,
unlock: gralloc_unlock,
perform: gralloc_perform,
lock_ycbcr: gralloc_lock_ycbcr,
},
framebuffer: 0,
fbFormat: 0,
flags: 0,
numBuffers: 0,
bufferMask: 0,
lock: PTHREAD_MUTEX_INITIALIZER,
};
上述代码和Gralloc中的代码基本移植,只是增加了结构体private_module_t的perform()函数指针来实现gralloc_perform()。函数gralloc_perform()在文件mapper.cpp中定义,代码如下:
int gralloc_perform(struct gralloc_module_t const* module,
int operation, ... )
{
int res = -EINVAL;
va_list args;
if(!module)
return res;
va_start(args, operation);
switch (operation) {
case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER:
{
int fd = va_arg(args, int);
unsigned int size = va_arg(args, unsigned int);
unsigned int offset = va_arg(args, unsigned int);
void* base = va_arg(args, void*);
int width = va_arg(args, int);
int height = va_arg(args, int);
int format = va_arg(args, int);
native_handle_t** handle = va_arg(args, native_handle_t**);
private_handle_t* hnd = (private_handle_t*)native_handle_create(
private_handle_t::sNumFds, private_handle_t::sNumInts());
if (hnd) {
hnd->magic = private_handle_t::sMagic;
hnd->fd = fd;
hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION;
hnd->size = size;
hnd->offset = offset;
hnd->base = uint64_t(base) + offset;
hnd->gpuaddr = 0;
hnd->width = width;
hnd->height = height;
hnd->format = format;
*handle = (native_handle_t *)hnd;
res = 0;
}
break;
}
case GRALLOC_MODULE_PERFORM_GET_STRIDE:
{
int width = va_arg(args, int);
int format = va_arg(args, int);
int *stride = va_arg(args, int *);
int alignedw = 0, alignedh = 0;
AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
0, format, 0, alignedw, alignedh);
*stride = alignedw;
res = 0;
} break;
case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE:
{
const private_handle_t* hnd = va_arg(args, private_handle_t*);
int *stride = va_arg(args, int *);
if (private_handle_t::validate(hnd)) {
return res;
}
int alignedw = 0, alignedh = 0;
AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(hnd, alignedw, alignedh);
*stride = alignedw;
res = 0;
} break;
case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE:
{
const private_handle_t* hnd = va_arg(args, private_handle_t*);
int *stride = va_arg(args, int *);
int *height = va_arg(args, int *);
if (private_handle_t::validate(hnd)) {
return res;
}
int alignedw = 0, alignedh = 0;
AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(hnd, alignedw, alignedh);
*stride = alignedw;
*height = alignedh;
res = 0;
} break;
case GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES:
{
int width = va_arg(args, int);
int height = va_arg(args, int);
int format = va_arg(args, int);
int usage = va_arg(args, int);
int *alignedWidth = va_arg(args, int *);
int *alignedHeight = va_arg(args, int *);
int *tileEnabled = va_arg(args,int *);
*tileEnabled = isUBwcEnabled(format, usage) ||
isMacroTileEnabled(format, usage);
AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
height, format, usage, *alignedWidth, *alignedHeight);
res = 0;
} break;
case GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE:
{
private_handle_t* hnd = va_arg(args, private_handle_t*);
int *color_space = va_arg(args, int *);
if (private_handle_t::validate(hnd)) {
return res;
}
MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
if(metadata && metadata->operation & UPDATE_COLOR_SPACE) {
*color_space = metadata->colorSpace;
res = 0;
}
} break;
case GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO:
{
private_handle_t* hnd = va_arg(args, private_handle_t*);
android_ycbcr* ycbcr = va_arg(args, struct android_ycbcr *);
if (!private_handle_t::validate(hnd)) {
res = getYUVPlaneInfo(hnd, ycbcr);
}
} break;
case GRALLOC_MODULE_PERFORM_GET_MAP_SECURE_BUFFER_INFO:
{
private_handle_t* hnd = va_arg(args, private_handle_t*);
int *map_secure_buffer = va_arg(args, int *);
if (private_handle_t::validate(hnd)) {
return res;
}
MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
if(metadata && metadata->operation & MAP_SECURE_BUFFER) {
*map_secure_buffer = metadata->mapSecureBuffer;
res = 0;
} else {
*map_secure_buffer = 0;
}
} break;
case GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG:
{
private_handle_t* hnd = va_arg(args, private_handle_t*);
int *flag = va_arg(args, int *);
if (private_handle_t::validate(hnd)) {
return res;
}
*flag = hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
if (metadata && (metadata->operation & LINEAR_FORMAT)) {
*flag = 0;
}
res = 0;
} break;
case GRALLOC_MODULE_PERFORM_GET_RGB_DATA_ADDRESS:
{
private_handle_t* hnd = va_arg(args, private_handle_t*);
void** rgb_data = va_arg(args, void**);
if (!private_handle_t::validate(hnd)) {
res = getRgbDataAddress(hnd, rgb_data);
}
} break;
case GRALLOC_MODULE_PERFORM_GET_IGC:
{
private_handle_t* hnd = va_arg(args, private_handle_t*);
uint32_t *igc = va_arg(args, uint32_t *);
if (!private_handle_t::validate(hnd) && igc) {
MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
if (metadata && (metadata->operation & SET_IGC)) {
*igc = metadata->igc;
res = 0;
}
}
} break;
case GRALLOC_MODULE_PERFORM_SET_IGC:
{
private_handle_t* hnd = va_arg(args, private_handle_t*);
uint32_t igc = va_arg(args, uint32_t);
if (!private_handle_t::validate(hnd)) {
MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
if (metadata) {
metadata->igc = (IGC_t) igc;
metadata->operation |= SET_IGC;
res = 0;
}
}
} break;
case GRALLOC_MODULE_PERFORM_SET_SINGLE_BUFFER_MODE:
{
private_handle_t* hnd = va_arg(args, private_handle_t*);
uint32_t *enable = va_arg(args, uint32_t*);
if (private_handle_t::validate(hnd)) {
return res;
}
setMetaData(hnd, SET_SINGLE_BUFFER_MODE, enable);
} break;
default:
break;
}
va_end(args);
return res;
}
在上述代码中,通过case语句实现了一个命令GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER,此命令是在surfaceFlinger中被调用的内容,这是一个可选的功能,在此通过调用Pmem获取内存的大小。
二、文件framebuffer.cpp
在文件\hardware\qcom\display\libgralloc\framebuffer.cpp中实现了QSD8K的framebuffer_devices_t设备驱动,其实现源码和标准的程序类似,区别是增加了更多颜色格式的支持,并且用RGBA8888作为默认的颜色格式。
其中在post中的区别是不支持双缓冲需要的内存复制功能时,不会调用memcopy()来实现,而是滴啊用msm_copy_buffer()来实现。post实现函数的代码如下:
static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
{
private_module_t* m =
reinterpret_cast<private_module_t*>(dev->common.module);
private_handle_t *hnd = static_cast<private_handle_t*>
(const_cast<native_handle_t*>(buffer));
fb_context_t *ctx = reinterpret_cast<fb_context_t*>(dev);
const unsigned int offset = (unsigned int) (hnd->base -
m->framebuffer->base);
m->info.activate = FB_ACTIVATE_VBL;
m->info.yoffset = (int)(offset / m->finfo.line_length);
if (ioctl(ctx->fbFd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
ALOGE("%s: FBIOPUT_VSCREENINFO for primary failed, str: %s",
__FUNCTION__, strerror(errno));
return -errno;
}
return 0;
}
在文件gralloc.cpp中,实现了函数alloc()、free()、close()。这些函数是MSM的Galloc模块默认的实现函数,和标准函数一有一些区别的。函数gralloc_alloc()是MSM中gralloc_alloc_buffer来分配内存。由此课件这部分的实现和默认galloc模块中是不一样的。实现代码如下:
int gralloc_device_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
int status = -EINVAL;
if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
const private_module_t* m = reinterpret_cast<const private_module_t*>(
module);
gpu_context_t *dev;
IAllocController* alloc_ctrl = IAllocController::getInstance();
dev = new gpu_context_t(m, alloc_ctrl);
if(!dev)
return status;
*device = &dev->common;
status = 0;
} else {
status = fb_device_open(module, name, device);
}
return status;
}
由此可见,在qualcomm平台中提高了alloc_device_t设备性能,使用Pmem驱动程序作为内存映射工具,将原来通过ashmem分配和管理的内存部分转移到了Pmem上面。