转载时请注明出处和作者联系方式
文章出处:http://www.limodev.cn/blog
作者联系方式:李先静 <xianjimli@gmail.com>
FrameBuffer 在Android中并不像在其它GUI那样直观,抽象的层次比较多,加上GUI的更新是通过OpenGLES来做的。所以让人很难搞清GUI更新的整个流 程,最近要准备一个讲稿,所以花了一些去研究,这里做点笔记供大家参考,源代码是基于高通平台的,这些代码在网上都可以下载。
FrameBuffer相关的组件
1.SurfaceFlinger是一个服务,主要是负责合成各窗口的Surface,然后通过OpenGLES显示到FrameBuffer上。SurfaceFlinger本身比较重要而且比较复杂,以后专门写一篇吧。
2.DisplayHardware是对显示设备的抽象,包括FrameBuffer和Overlay。它加载FrameBuffer和Overlay插件,并初始化OpenGLES:
- mNativeWindow <span style="color: #339933;">=</span>
- new FramebufferNativeWindow<span style="color: #009900;">(</span>
- <span style="color: #009900;">)</span>
- <span style="color: #339933;">;</span>
- framebuffer_device_t <span style="color: #993333;">const</span>
- <span style="color: #339933;">*</span>
- fbDev <span style="color: #339933;">=</span>
- mNativeWindow<span style="color: #339933;">-></span>
- getDevice<span style="color: #009900;">(</span>
- <span style="color: #009900;">)</span>
- <span style="color: #339933;">;</span>
- <span style="color: #b1b100;">if</span>
- <span style="color: #009900;">(</span>
- hw_get_module<span style="color: #009900;">(</span>
- OVERLAY_HARDWARE_MODULE_ID<span style="color: #339933;">,</span>
- <span style="color: #339933;">&</span>
- module<span style="color: #009900;">)</span>
- <span style="color: #339933;">==</span>
- <span style="color: #0000dd;">0</span>
- <span style="color: #009900;">)</span>
- <span style="color: #009900;">{</span>
- overlay_control_open<span style="color: #009900;">(</span>
- module<span style="color: #339933;">,</span>
- <span style="color: #339933;">&</span>
- mOverlayEngine<span style="color: #009900;">)</span>
- <span style="color: #339933;">;</span>
- <span style="color: #009900;">}</span>
- surface <span style="color: #339933;">=</span>
- eglCreateWindowSurface<span style="color: #009900;">(</span>
- display<span style="color: #339933;">,</span>
- config<span style="color: #339933;">,</span>
- mNativeWindow.<span style="color: #202020;">get</span>
- <span style="color: #009900;">(</span>
- <span style="color: #009900;">)</span>
- <span style="color: #339933;">,</span>
- NULL<span style="color: #009900;">)</span>
- <span style="color: #339933;">;</span>
- eglMakeCurrent<span style="color: #009900;">(</span>
- display<span style="color: #339933;">,</span>
- surface<span style="color: #339933;">,</span>
- surface<span style="color: #339933;">,</span>
- context<span style="color: #009900;">)</span>
- <span style="color: #339933;">;</span>
3.FramebufferNativeWindow 是framebuffer 的抽象,它负责加载libgralloc,并打开framebuffer设备。FramebufferNativeWindow并不直接使用 framebuffer,而是自己创建了两个Buffer:
queueBuffer负责显示一个Buffer到屏幕上,它调用fb->post去显示。
dequeueBuffer获取一个空闲的Buffer,用来在后台绘制。
这两个函数由eglSwapBuffers调过来,调到
- egl_window_surface_v2_t<span style="color: #339933;">::</span>
- <span style="color: #202020;">swapBuffers</span>
- :
- nativeWindow<span style="color: #339933;">-></span>
- queueBuffer<span style="color: #009900;">(</span>
- nativeWindow<span style="color: #339933;">,</span>
- buffer<span style="color: #009900;">)</span>
- <span style="color: #339933;">;</span>
- nativeWindow<span style="color: #339933;">-></span>
- dequeueBuffer<span style="color: #009900;">(</span>
- nativeWindow<span style="color: #339933;">,</span>
- <span style="color: #339933;">&</span>
- buffer<span style="color: #009900;">)</span>
- <span style="color: #339933;">;</span>
4.msm7k/liboverlay是Overlay的实现,与其它平台不同的是,高通平台上的Overlay并不是提供一个framebuffer设备,而通过fb0的ioctl来实现的,ioctl分为两类操作:
OverlayControlChannel用于设置参数,比如设置Overlay的位置,宽度和高度:
- bool OverlayControlChannel<span style="color: #339933;">::</span>
- <span style="color: #202020;">setPosition</span>
- <span style="color: #009900;">(</span>
- <span style="color: #993333;">int</span>
- x<span style="color: #339933;">,</span>
- <span style="color: #993333;">int</span>
- y<span style="color: #339933;">,</span>
- uint32_t w<span style="color: #339933;">,</span>
- uint32_t h<span style="color: #009900;">)</span>
- <span style="color: #009900;">{</span>
- ov.<span style="color: #202020;">dst_rect</span>
- .<span style="color: #202020;">x</span>
- <span style="color: #339933;">=</span>
- x<span style="color: #339933;">;</span>
- ov.<span style="color: #202020;">dst_rect</span>
- .<span style="color: #202020;">y</span>
- <span style="color: #339933;">=</span>
- y<span style="color: #339933;">;</span>
- ov.<span style="color: #202020;">dst_rect</span>
- .<span style="color: #202020;">w</span>
- <span style="color: #339933;">=</span>
- w<span style="color: #339933;">;</span>
- ov.<span style="color: #202020;">dst_rect</span>
- .<span style="color: #202020;">h</span>
- <span style="color: #339933;">=</span>
- h<span style="color: #339933;">;</span>
- ioctl<span style="color: #009900;">(</span>
- mFD<span style="color: #339933;">,</span>
- MSMFB_OVERLAY_SET<span style="color: #339933;">,</span>
- <span style="color: #339933;">&</span>
- ov<span style="color: #009900;">)</span>
- <span style="color: #339933;">;</span>
- <span style="color: #009900;">}</span>
OverlayDataChannel用于显示Overlay,其中最重要的函数就是queueBuffer:
bool OverlayDataChannel::queueBuffer(uint32_t offset) {
- mOvData.<span style="color: #202020;">data</span>
- .<span style="color: #202020;">offset</span>
- <span style="color: #339933;">=</span>
- offset<span style="color: #339933;">;</span>
- ioctl<span style="color: #009900;">(</span>
- mFD<span style="color: #339933;">,</span>
- MSMFB_OVERLAY_PLAY<span style="color: #339933;">,</span>
- odPtr<span style="color: #009900;">)</span>
- <span style="color: #009900;">)</span>
- <span style="color: #009900;">}</span>
5.msm7k/libgralloc 是显示缓存的抽象,包括framebuffer和普通Surface的Buffer。framebuffer只是/dev/graphic/fb0的包 装,Surface的Buffer则是对/dev/pmem、ashmem和GPU内存(msm_hw3dm)的包装,它的目标主要是方便硬件加速,因为 DMA传输使用物理地址,要求内存在物理地址上连续。
6.msm7k/libcopybit这是2D加速库,主要负责Surface的拉伸、旋转和合成等操作。它有两种实现方式:
copybit.cpp: 基于fb0的ioctl(MSMFB_BLIT)的实现。
copybit_c2d.cpp: 基于kgsl的实现,只是对libC2D2.so的包装,libC2D2.so应该是不开源的。
7.pmem
misc/pmem.c: 对物理内存的管理,算法和用户空间的接口。
board-msm7x27.c定义了物理内存的缺省大小:
- <span style="color: #339933;">#define MSM_PMEM_MDP_SIZE 0x1B76000</span>
- <span style="color: #339933;">#define MSM_PMEM_ADSP_SIZE 0xB71000</span>
- <span style="color: #339933;">#define MSM_PMEM_AUDIO_SIZE 0x5B000</span>
- <span style="color: #339933;">#define MSM_FB_SIZE 0x177000</span>
- <span style="color: #339933;">#define MSM_GPU_PHYS_SIZE SZ_2M</span>
- <span style="color: #339933;">#define PMEM_KERNEL_EBI1_SIZE 0x1C000</span>
msm_msm7x2x_allocate_memory_regions分配几大块内存用于给pmem做二次分配。
8.KGSL
Kernel Graphics System Layer (KGSL),3D图形加速驱动程序,源代码drivers/gpu/msm目录下,它是对GPU的包装,给OpenGLES 2.0提供抽象的接口。
9.msm_hw3dm
这个我在内核中没有找到相关代码。
10.msm_fb
msm_fb.c: framebuffer, overlay和blit的用户接口。
mdp_dma.c: 对具体显示设备的包装,提供两种framebuffer更新的方式:
- mdp_refresh_screen: 定时更新。
- mdp_dma_pan_update: 通过pan display主动更新。
mdp_dma_lcdc.c:针对LCD实现的显示设备,mdp_lcdc_update用更新framebuffer。