gralloc

2024-04-16 07:58
文章标签 gralloc

本文主要是介绍gralloc,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

系统中有好几个gralloc的模块,
分别是:
/hardware/libhardware/modules/gralloc/
/hardware/msm7k/libgralloc-qsd8k/
/hardware/msm7k/libgralloc/
但实际上调用的是第二个模块,通过logcat可以查到.
gralloc被编译成模块gralloc.$(TARGET_BOARD_PLATFORM).so
/hardware/libhardware/modules/gralloc/分析:
提供给上层的接口函数有:
open: gralloc_device_open
registerBuffer: gralloc_register_buffer,
unregisterBuffer: gralloc_unregister_buffer,
lock: gralloc_lock,
unlock: gralloc_unlock,
open函数
int gralloc_device_open(const hw_module_t* module, const char* name,
hw_device_t** device)
该函数首先判断传入的module的类型,类型有两个,分别为:
#define GRALLOC_HARDWARE_FB0 "fb0"
#define GRALLOC_HARDWARE_GPU0 "gpu0"
在gralloc.h文件中定义了,该文件页定义了调用gralloc_device_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, (struct hw_device_t**)device);
}
static inline int framebuffer_open(const struct hw_module_t* module, 
struct framebuffer_device_t** device) {
return module->methods->open(module, 
GRALLOC_HARDWARE_FB0, (struct hw_device_t**)device);
}
这两个函数其实就是调用了gralloc_device_open(),只不过参数不同而已;
如果参数是:GRALLOC_HARDWARE_GPU0
为定义的gralloc_context_t 指针分配内存,调用memset()初始化指针为空,并将该指针变量的函数指针指向
gralloc_context_t *dev;
dev = (gralloc_context_t*)malloc(sizeof(*dev));
memset(dev, 0, sizeof(*dev));
dev->device.common.tag = HARDWARE_DEVICE_TAG;
dev->device.common.version = 0;
dev->device.common.module = const_cast<hw_module_t*>(module);
dev->device.common.close = gralloc_close;
dev->device.alloc   = gralloc_alloc;
dev->device.free    = gralloc_free;
*device = &dev->device.common;
所以可以说Gralloc模块就是为分配显存的。位于framebuffer和surface两层之间。
如果参数是:GRALLOC_HARDWARE_FB0
执行:status = fb_device_open(module, name, device);
fb_device_open()函数调用gralloc_open()函数,这个framebuffer_open()函数的调用打开了gralloc_device_open()两次,第一次根据module的类型为:GRALLOC_HARDWARE_FB0,调用了fb_device_open()这个函数,而fb_device_open()这个函数中又调用了gralloc_open这个函数,这个函数中的module为GRALLOC_HARDWARE_GPU0。
继续分析fb_device_open()函数,
alloc_device_t* gralloc_device;
status = gralloc_open(module, &gralloc_device);
if (status < 0)
return status;
fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));
memset(dev, 0, sizeof(*dev));
dev->device.common.tag = HARDWARE_DEVICE_TAG;
dev->device.common.version = 0;
dev->device.common.module = const_cast<hw_module_t*>(module);
dev->device.common.close = fb_close;
dev->device.setSwapInterval = fb_setSwapInterval;
dev->device.post            = fb_post;
dev->device.setUpdateRect = 0;
该函数同理定义了fb_context_t的指针,并分配了内存,并初始化了几个函数指针。
然后调用mapFramebuffer() ---->mapFramebufferLocked()
在mapFramebufferLocked()函数中,打开了/dev/graphics/fb0的设备,调用ioctl函数的
FBIOGET_FSCREENINFO,FBIOGET_VSCREENINFO取得了fb_fix_screeninfo,fb_var_screeninfo结构体的数据,
并初始化了fb_var_screeninfo结构体变量info的数据:
info.reserved[0] = 0;
info.reserved[1] = 0;
info.reserved[2] = 0;
info.xoffset = 0;
info.yoffset = 0;
info.activate = FB_ACTIVATE_NOW;
info.bits_per_pixel = 16;
info.red.offset     = 11;
info.red.length     = 5;
info.green.offset   = 5;
info.green.length   = 6;
info.blue.offset    = 0;
info.blue.length    = 5;
info.transp.offset  = 0;
info.transp.length  = 0;
都是初始话像素的深度和红绿蓝分量在每个像素中的偏移。
随后调用ioctl的FBIOPUT_VSCREENINFO将info的数据写回到framebuffer中。
随后计算刷新的频率,
int refreshRate = 1000000000000000LLU /
(
uint64_t( info.upper_margin + info.lower_margin + info.yres )
* ( info.left_margin  + info.right_margin + info.xres )
* info.pixclock
);
if (refreshRate == 0) {
// bleagh, bad info from the driver
refreshRate = 60*1000;  // 60 Hz
}
float xdpi = (info.xres * 25.4f) / info.width;
float ydpi = (info.yres * 25.4f) / info.height;
float fps  = refreshRate / 1000.0f;
uint32_t flags = PAGE_FLIP;//从代码可以看出,支不支持PAGE_FLIP就看是不是:info.yres_virtual < info.yres * 2
最终把这些变量写入到module中:
module->flags = flags;
module->info = info;
module->finfo = finfo;
module->xdpi = xdpi;
module->ydpi = ydpi;
module->fps = fps;
int err;
size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual);
module->framebuffer = new private_handle_t(dup(fd), fbSize, 0);
module->numBuffers = info.yres_virtual / info.yres;
module->bufferMask = 0;
调用mmap将内核的fd映射到用户空间
并 module->framebuffer->base = intptr_t(vaddr);将vaddr的类型转化为int16_t的,之后memset将vaddr的数据初始化为空。
再来看fb_device_open()函数,
其实这一系列的过程就是初始化了两个结构体:
fb_context_t *dev ;
gralloc_context_t *dev;
为两个结构体分配了内存,并初始化.
gralloc_alloc()函数
该函数主要的作用就是分配内存的,如果支持PAGE_FLIP(双缓冲)模式,则调用gralloc_alloc_framebuffer(),否则,调用gralloc_alloc_buffer()
gralloc_alloc_framebuffer()函数:
调用gralloc_alloc_framebuffer_locked()函数,
在该函数中,调用mapFrameBufferLocked()函数得到fb的参数,并初始化private_module_t* m这个结构体,重新创建了一个private_handle_t* hnd,这个hndflags为private_handle_t::PRIV_FLAGS_FRAMEBUFFER.bufferMask应该等于11,numBuffers应该等于2,vaddr应该为第二块framebuffer的地址 (vaddr += bufferSize;),offset也相应改变.
gralloc_free()函数:
该函数正好和gralloc_alloc函数相反,是释放内存的,首先判断
hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER
之后,计算bufferSize大小,计算这个handle在framebuffer中的索引,根据索引来
const size_t bufferSize = m->finfo.line_length * m->info.yres;
int index = (hnd->base - m->framebuffer->base) / bufferSize;
m->bufferMask &= ~(1<<index); 
index应该等于1,则m->bufferMask计算之后等于1.
最开始调用fb_device_open创建的hnd的flags=0,走的是else后面的路,最终调用到mnumap()函数解除对内存的映射.
fb_post()分析:
首先也是判断
(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)
如果flags相等,则重新设置了一下该framebuffer_device_t的fb_var_screeninfo结构体的activate和yoffset信息,之后ioctl将fb_var_screeninfo写入到fb中,然后直接将当前的currentBuffer指向这个buffer_handle_t.
如果flags不相等,则调用gralloc_lock函数,得到两个buffer的地址,再调用memcpy()将buffer复制.
/
struct private_handle_t : public native_handle {}
typedef const native_handle* buffer_handle_t;
typedef struct gralloc_module_t {
struct hw_module_t common;
} gralloc_module_t;
typedef struct alloc_device_t {
struct hw_device_t common;
} alloc_device_t;
typedef struct framebuffer_device_t {
struct hw_device_t common;
} framebuffer_device_t;
typedef native_handle_t native_handle;
typedef struct
{
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;
typedef struct hw_module_t {
/** tag must be initialized to HARDWARE_MODULE_TAG */
uint32_t tag;
/** major version number for the module */
uint16_t version_major;
/** minor version number of the module */
uint16_t version_minor;
/** Identifier of module */
const char *id;
/** Name of this module */
const char *name;
/** Author/owner/implementor of the module */
const char *author;
/** Modules methods */
struct hw_module_methods_t* methods;
/** module's dso */
void* dso;
/** padding to 128 bytes, reserved for future use */
uint32_t reserved[32-7];
} hw_module_t;
typedef struct hw_module_methods_t {
/** Open a specific device */
int (*open)(const struct hw_module_t* module, const char* id,
struct hw_device_t** device);
} hw_module_methods_t;
typedef struct hw_device_t {
/** tag must be initialized to HARDWARE_DEVICE_TAG */
uint32_t tag;
/** version number for hw_device_t */
uint32_t version;
/** reference to the module this device belongs to */
struct hw_module_t* module;
/** padding reserved for future use */
uint32_t reserved[12];
/** Close this device */
int (*close)(struct hw_device_t* device);
} hw_device_t;
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;
};

这篇关于gralloc的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/908221

相关文章

Android图形系统之BufferQueue与Gralloc关系(三)

BufferQueue 类将可生成图形数据缓冲区的组件(生产方)连接到接受数据以便进行显示或进一步处理的组件(使用方)。几乎所有在系统中移动图形数据缓冲区的内容都依赖于 BufferQueue。 Gralloc 内存分配器会进行缓冲区分配,并通过两个特定于供应商的 HIDL 接口来进行实现(请参阅 hardware/interfaces/graphics/allocator/ 和 hardw

GUI系统之SurfaceFlinger(2)Gralloc与Framebuffer

文章都是通过阅读源码分析出来的,还在不断完善与改进中,其中难免有些地方理解得不对,欢迎大家批评指正 转载请注明:From LXS. http://blog.csdn.net/uiop78uiop78/ 1.1 Gralloc与Framebuffer 相信做过Linux开发的人对framebuffer不会太陌生,它是内核系统提供的一个与硬件无关的显示抽象层。之所以称之为buffer,是由

GUI显示系统之SurfaceFlinger--- Gralloc与Framebuffer

GUI显示系统之SurfaceFlinger其它部分完整章节: http://blog.csdn.net/uiop78uiop78/article/details/8954508 第1章  GUI系统之SurfaceFlinger 在进入GUI系统的学习前,建议大家可以先阅读本书应用篇中的“OpenGLES”章节,并参阅OpenGL ES官方指南。因为Android的GUI系统是基于

通过gralloc分析驱动module

Android Gralloc 是硬件抽象层,目的是把具体 framebuffer 相关的东西隔离,因为不同公司提供的framebuffer api 不同,这样就有一个统一的硬件抽象层 1.由3个模块组成 gralloc_module: 负责吧buffer 映射到进程空间 以及lock 操作 alloc_device_t :负责分配 buffer ( ashmem ) or fram