一、OpenGL ES与EGL
SurfaceFlinger与OpenGL等模块的关系Android的GUI系统是基于OpenGL/EGL来实现的。
- 由于OpenGL是通用函数库,在不同平台系统上需要被“本土化”——把它与具体平台的窗口系统建立起关联,FramebufferNativeWindow是负责OpenGL ES在Android平台上本地化的中介之一。为OpenGL ES配置本地窗口的是EGL,EGL介于本地窗口系统和Rendering API(即OPenGL ES)之间的一层接口。
- 与OpenGL相关的模块可分为:
(1)配置类。 帮助OpenGL ES完成配置的,包括EGL、DisplayHardware都归为此类。
(2)依赖类。 OpenGL ES正常运行所依赖的“本地化”的东西,如FramebufferNativeWindow。
(3)使用类。 使用者也可能是配置者,如DisplayDevice既扮演了构建OpenGL ES环境的角色,同时也是它的用户。 - OpenGL相关知识可查看Android中的OpenGL ES使用基础
二、 硬件接口 - HAL
HAL是很多子系统(显示/音频系统等)与Linux Kernel驱动之间通信的统一接口。各子系统通常不会直接使用内核驱动。
HAL解决的问题:
(1)硬件接口抽象。从众多硬件设备中提取出共同属性并付诸软件实现。
(2)接口稳定性。 HAL层的接口不允许频繁更动。
(3)灵活的使用方法。供硬件开发商及上层使用者定制他们的需求。
三、终端显示设备 - Gralloc与Framebuffer
Linux内核提供了统一的framebuffer显示驱动。Framebuffer是内核系统提供的图形硬件的抽象描述,称为buffer是因为它也占用了系统存储空间的一部分,是一块包含屏幕显示信息的缓冲区。
Framebuffer借助于Linux文件系统向上层应用提供了统一而高效的操作接口,让用户空间运行的程序比较容易地适配多种显示设备。
Android系统中,framebuffer提供的设备节点为/dev/graphics/fb或者/dev/fb,其中fb0表示第一个主显示屏幕,必须存在,当前系统实现中只用到了一个显示屏。
显示系统使用HAL层间接引用底层架构,从而操作帧缓冲区。而完成这一中介任务的就是Gralloc.
下图为Gralloc的模块简图,描述了gpu0和fb0的主要API.
Gralloc对应的模块是由FramebufferNativeWindow在构造函数加载的,Gralloc包括fb和gralloc两个设备,前者负责打开内核中的Framebuffer、初始化配置,并提供了post、setSwapInterval等操作接口。后者则管理帧缓冲区的分配和释放。
Gralloc API架构
四、本地窗口(Native Window)
Native Window为OpenGL与本地窗口系统之间搭建了桥梁。整个GGUI系统至少需要两种本地窗口:
(1)面向管理者(SurfaceFlinger)
SurfaceFlinger是系统中所有UI界面的管理者,需要直接或间接的持有“本地窗口”,此本地窗口是FramebufferNativeWindow。
(2)面向应用程序
这类本地窗口是Surface。
正常情况按照SDK向导生成APK应用程序,是采用Skia等第三方图形库,而对于希望使用OpenGL ES来完成复杂界面渲染的应用开发者来说,Android也提供封装的GLSurfaceView(或其他方式)来实现图形显示。
- FramebufferNativeWindow
EGL需要通过本地窗口来为OpenGL/OpenGL ES创建环境。由于OpenGL/ES对多平台支持,考虑到兼容性和移植性。不同平台的本地窗口EGLNativeWindowType数据类型不同。
Android平台的数据类型是ANativeWindow,像是一份“协议”,规定了一个本地窗口的形态和功能。ANativeWindow是FramebufferNativeWindow的父类。
Android中,由于多缓冲技术,EGLNativeWindowType所管理的缓冲区最少2个,最大3个。
FramebufferNativeWindow初始化需要Golloc支持,步骤如下:
- 加载GRALLOC_HARDWARE_MODULE_ID模块,参见上节。
- 分别打开fb和gralloc设备,打开后的设备由全局变量fbDev和grDev管理。
- 根据设备的属性来给FramebufferNativeWindow赋初值。
- 根据FramebufferNativeWindow的实现来填充ANativeWindow中的“协议”
- 其他一些必要的初始化
- 应用程序的本地窗口 - Surface
Surface也继承了ANativeWindow
class Surface : public ANativeObjectBase<ANativeWindow, Surface, RefBase>
Surface是面向Android系统中所有UI应用程序的,即它承担着应用进程中的UI显示需求。
需要面向上层实现(主要是Java层)提供绘制图像的画板。SurfaceFlinger需要收集系统中所有应用程序绘制的图像数据,然后集中显示到物理屏幕上。Surface需要扮演相应角色,本质上还是由SURfaceFlinger服务统一管理的,涉及到很多跨进程的通信细节。
- Surface的创建
Surface将通过mGraphicBufferProducer来获取buffer,这些缓冲区会被记录在mSlots中数据中。mGraphicBufferProducer这一核心成员的初始化流程如下:
ViewRootImpl持有一个Java层的Surface对象(mSurface)。
ViewRootImpl向WindowManagerService发起relayout请求,此时mSurface被赋予真正的有效值,将辗转生成的SurfaceControl通过Surface.copyFrom()函数复制到mSurface中。
由此,Surface由SurfaceControl管理,SurfaceControl由SurfaceComposerClient创建。SurfaceComposerClient获得的匿名Binder是ISurfaceComposer,其服务端实现是SurfaceFlinger。而Surface依赖的IGraphicBufferProducer对象在Service端的实现是BufferQueue。
class SurfaceFlinger :
public BinderService<SurfaceFlinger>, //在ServiceManager中注册为SurfaceFlinger
public BnSurfaceComposer,//实现的接口却叫ISurfaceComposer
- SurfaceFlinger服务框架
Buffer,Consumer,Producer是“生产者-消费者”模型中的3个参与对象,如何协调好它们的工作是应用程序能否正常显示UI的关键。
Buffer是BufferQueue,Producer是应用程序,Consumer是SurfaceFlinger。
五、BufferQueue详解
为应用程序服务的本地窗口Surface,其依赖的IGraphicBufferProducer对象在Server端的实现是BufferQueue.
一块Buffer在处理过程中经历的生命周期依次是FREE-> DEQUEUED->QUEUED->ACQUIRED->FREE.
BufferQueue中的mSlots数组用于管理期内的缓冲区,最大容器是32.数据缓冲区的空间是动态分配的.
应用程序与SurfaceFlinger都是使用OpenGL ES来完成UI显示的.
Layer类在SurfaceFlinger中表示“层”,通俗地讲就是代表了一个“画面”,最终物理屏幕上的显示结果就是通过对系统中同时存在的所有“画面”进行处理而得到的.
注:主要内容摘录自书籍 深入理解Android内核设计思想,林学森 著
网友评论