1. libui简介
libui是Android图形库的本地框架,负责提供图形界面(Surface)的框架。libui不仅仅负责图形界面框架,
还提供处理事件输入、摄像头输出、Overlay显示等框架,是整个图形用户交互(GUI)系统的中枢。
头文件位置 /frameworks/base/include/ui
源文件文章 /frameworks/base/libs/ui
编译生成动态链接库libui.so
2. libui库包含内容
1)Camera相关框架及底层接口
2)Event / Key event事件处理
3)Overlay相关框架和底层接口
4)定义一些图形显示相关数据结构(Rect、Region和PixelFormat)
5)Framebuffer管理和显存分配
6)Surface图形界面框架
主要分析一下显示控制机制及图形界面框架。
3. Framebuffer管理和显存分配
3.1设备初始化
libui定义了FramebufferNativeWindow类,在构造函数中加载Gralloc硬件模块,并通过该模块提供的接口打
开Linux的Framebuffer设备,同时将打开Gralloc模块。设备打开后,将初始化FramebufferNativeWindow的
参数,将显示缓冲区设置为2,同时向系统申请两块NativeBuffer结构用于存储显示设备的双缓冲,再调用
Gralloc模块的alloc接口分配显存空间。以下为部分初始化代码:
if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
err = framebuffer_open(module, &fbDev);
err = gralloc_open(module, &grDev);
// initialize the buffer FIFO
mNumBuffers = 2;
mNumFreeBuffers = 2;
mBufferHead = mNumBuffers-1;
buffers[0] = new NativeBuffer(
fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
buffers[1] = new NativeBuffer(
fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
err = grDev->alloc(grDev, fbDev->width, fbDev->height, fbDev->format,
GRALLOC_USAGE_HW_FB, &buffers[0]->handle, &buffers[0]->stride);
err = grDev->alloc(grDev, fbDev->width, fbDev->height, fbDev->format,
GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride);
… …
3.2 共享式分配显存
相对于Gralloc模块采用独立内存空间作为显示缓冲区,libui提供了一套通过ashmem机制,和系统主存共享分
配显存的方案。这种方案适用于物理内存较少且对显示要求低的设备。该策略通过宏定义
GRALLOC_USAGE_HW_MASK进行判断,如果标志位没有被置位,则初始化sw_gralloc_handle_t结构体。
sw_gralloc_handle_t::alloc负责申请共享内存,根据图形格式计算需要申请的图形尺寸,计算公式为
size = bpp * w * h,另外需要保证size为PAGE_SIZE对齐。调用ashmem_create_region函数申请空间,调
用ashmem_set_prot_region设置参数,最后用mmap获取申请空间的内存地址。
int fd = ashmem_create_region("sw-gralloc-buffer", size);
int prot = PROT_READ;
if (usage & GRALLOC_USAGE_SW_WRITE_MASK)
prot |= PROT_WRITE;
ashmem_set_prot_region(fd, prot) ;
void* base = mmap(0, size, prot, MAP_SHARED, fd, 0);
sw_gralloc_handle_t::registerBuffer会判断当前进程是否与sw_gralloc_handle_t相同,若不相同需要
重新mmap,获取新的内存地址。
if (hnd->pid != getpid()) {
void* base = mmap(0, hnd->size, hnd->prot, MAP_SHARED, hnd->fd, 0);
hnd->base = intptr_t(base);
}
4. libui中的Surface图形界面框架
libui库提供了Surface图形界面框架,包括上层应用的调用接口和于SurfaceFlinger库的通信接口,图形界面
的具体实现由SurfaceFlinger库完成。Android上层应用的调用接口主要包含SurfaceComposerClient、
SurfaceControl和Surface三个主要数据结构。
4.1 创建SurfaceComposerClient客户端
上层启动一个新的图形会话,首先要建立一个SurfaceComposerClient对象,用来创建图形会话客户端。
SurfaceComposerClient在其构造函数中调用getComposerService(),返回ISurfaceComposer接口,在调用
ISurfaceComposer:createConnection(),通过binder和SurfaceFlinger库通讯,最终SurfaceFlinger库返
4.2 创建一个Surface
创建SurfaceComposerClient对象后,可以调用createSurface()创建一个新的Surface,实际上是调用
ISurfaceFlingerClient接口的createSurface(),通过binder进入SurfaceFlinger创建真正的显示Layer。
创建成功后将返回一个SurfaceControl类型的对象。
4.3 获取Surface和ISurface
SurfaceControl对象可使用getSurface()获取Surface对象。这两个数据结构分工不同,SurfaceControl主
要负责设置图形界面的参数,Surface则提供了控制图形界面的接口。Surface可以通过getISurface()获取服
务器端ISurface的接口,利用ISurface的接口,通过binder进程间通讯机制和服务器端传输Surface数据。
4.4 客户端和服务端模型
图中Server下层即SurfaceFlinger实现,这里没有列出。解释一下我理解的客户和服务端模型,上层图形应用
程序利用SurfaceComposerClient、SurfaceControl及Surface对象向服务端申请Surface,获取控制Surface
的接口ISurfaceXXX,利用该接口提供的Binder进程通讯机制和服务端进行通讯和数据交换。服务端指libui提
供的Surface框架和libsurfaceflinger库,系统启动时将SurfaceFlinger注册为系统服务,负责处理所有客
户端拥有的Surface,决定当前显示内容及数据更新情况。