Android
图形 Graphic
和显示 Display
是两个独立的部分,这里放在一起简述;介绍了图像和显示相关的基本概念,比如 BufferQueue
生产者消费者模型, Surface/SurfaceFlinger
图形合成等等。
概念 应用开发者可通过两种方式将图像绘制到屏幕上:使用 Canvas
或 OpenGL
:
android.graphics.Canvas
是一个 2D
图形 API
, Canvas API
通过一个名为 OpenGLRenderer
的绘制库实现硬件加速,该绘制库将 Canvas
运算转换为 OpenGL
运算,以便它们可以在 GPU
上执行。从 Android 4.0
开始,硬件加速的 Canvas
默认情况下处于启用状态
除了 Canvas
,开发者渲染图形的另一个主要方式是使用 OpenGL ES
直接渲染到 Surface
。 Android
在 Android.opengl
软件包中提供了 OpenGL ES
接口
EGL
先熟悉 Android
平台图形处理 API
的标准:
OpenGL
是由 SGI
公司开发的一套 3D
图形软件接口标准,由于具有体系结构简单合理、使用方便、与操作平台无关等优点, OpenGL
迅速成为 3D
图形接口的工业标准,并陆续在各种平台上得以实现。
OpenGL ES
是由 khronos
组织根据手持及移动平台的特点,对 OpenGL 3D
图形 API
标准进行裁剪定制而形成的。
Vulkan
是由 khronos
组织在 2016 年正式发布的,是 OpenGL ES
的继任者。 API
是轻量级、更贴近底层硬件 close-to-the-metal
的接口,可使 GPU
驱动软件运用多核与多线程 CPU
性能。
OpenGL ES
定义了一个渲染图形的 API
,但没有定义窗口系统。为了让它能够适合各种平台,它将与知道如何通过操作系统创建和访问窗口的库结合使用。而在 Android
中,这个库被称为 EGL
;也就是说 EGL
主要是适配系统和关联窗口属性。如果要绘制纹理多边形,应使用 OpenGL ES
调用;如果要在屏幕上进行渲染,应使用 EGL
调用。OpenGL ES
是 Android
绘图 API
,但 OpenGL ES
是平台通用的,在特定设备上使用需要一个中间层做适配, Android
中这个中间层就是 EGL
。
Surface
和 SurfaceFlinger
无论开发者使用什么渲染 API
,一切内容都会渲染到 Surface
。 Surface
表示缓冲队列中的生产者,而缓冲队列通常会被 SurfaceFlinger
消耗。在 Android
平台上创建的每个窗口都由 Surface
提供支持。所有被渲染的可见 Surface
都被 SurfaceFlinger
合成到显示部分。它们遵循生产者/消费者模型:
图像流生产者 图像流生产者可以是生成图形缓冲区以供消耗的任何内容。例如 OpenGL ES, Canvas 2D, mediaserver
视频解码器。
图像流消费者 图像流的最常见消费者是 SurfaceFlinger
,该系统服务会消耗当前可见的 Surface
,并使用窗口管理器中提供的信息将它们合成到显示部分。 SurfaceFlinger
是可以修改所显示部分内容的唯一服务。 SurfaceFlinger
使用 OpenGL
和 Hardware Composer
来合成一组 Surface
。 其他 OpenGL ES
应用也可以消耗图像流,例如相机应用会消耗相机预览图像流。非 GL
应用也可以是消费者,例如 ImageReader
类。
WMS: WindowManagerServices
窗口管理器,控制窗口的 Android
系统服务,它是视图容器。窗口总是由 Surface
提供支持。该服务会监督生命周期、输入和聚焦事件、屏幕方向、转换、动画、位置、变形、 Z-Order
以及窗口的其他许多方面。窗口管理器会将所有窗口元数据发送到 SurfaceFlinger
,以便 SurfaceFlinger
可以使用该数据在显示部分合成 Surface
。
FrameBuffer
FrameBuffer
帧缓冲驱动,它是 Linux
的一种驱动程序接口。 Linux
是工作在保护模式下,所以用户态进程是无法象 DOS
那样使用显卡 BIOS
里提供的中断调用来实现直接写屏, Linux
抽象出 FrameBuffer
这个设备来供用户态进程实现直接写屏。 FrameBuffer
机制模仿显卡的功能,将显卡硬件结构抽象掉,可以通过 FrameBuffer
的读写直接对显存进行操作。用户可以将 FrameBuffer
看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。这种操作是抽象的统一的。用户不必关心物理显存的位置、换页机制等等具体细节,这些都是由 FrameBuffer
设备驱动来完成的。但 FrameBuffer
本身不具备任何运算数据的能力,就只好比是一个暂时存放水的水池。 CPU
将运算后的结果放到这个水池,水池再将结果流到显示器,中间不会对数据做处理。应用程序也可以直接读写这个水池的内容在这种机制下,尽管 FrameBuffer
需要真正的显卡驱动的支持,但所有显示任务都有 CPU
完成,因此 CPU
负担很重。
在开发者看来, FrameBuffer
本质上是一块显示缓存,往显示缓存中写入特定格式的数据就意味着向屏幕输出内容。所以说 FrameBuffer
就是一块白板。例如对于初始化为 16 位色的 FrameBuffer
来说, FrameBuffer
中的两个字节代表屏幕上一个点,从上到下,从左至右,屏幕位置与内存地址是顺序的线性关系。 帧缓存可以在系统存储器(内存)的任意位置,视频控制器通过访问帧缓存来刷新屏幕。帧缓存也叫刷新缓存 FrameBuffer
或 RefreshBuffer
,这里的帧 Frame
是指整个屏幕范围。帧缓存有个地址,是在内存里。我们通过不停的向 FrameBuffer
中写入数据,显示控制器就自动的从 FrameBuffer
中取数据并显示出来。全部的图形都共享内存中同一个帧缓存。
FrameBuffer
帧缓冲实际上包括两个不同的方面:
Frame
:帧,就是指一幅图像,在屏幕上看到的那幅图像就是一帧
Buffer
:缓冲,就是一段存储区域,可这个区域存储的是帧
FrameBuffer
就是一个存储图形/图像帧数据的缓冲。Linux
内核提供了统一的 Framebuffer
显示驱动,设备节点 /dev/graphics/fb*
或者 /dev/fb*
,以 fb0
表示第一个 Monitor
,当前实现中只用到了一个显示屏。这个虚拟设备将不同硬件厂商实现的真实设备统一在一个框架下,这样应用层就可以通过标准的接口进行图形/图像的输入和输出了:
从上图中可以看出,应用层通过标准的 ioctl, mmap
等系统调用,就可以操作显示设备,用起来非常方便。这里 mmap
把设备中的显存映射到用户空间的,在这块缓冲上写数据,就相当于在屏幕上绘画。
Gralloc
Gralloc
的含义为是 Graphics Alloc
图形分配 。 Android
系统在硬件抽象层中提供了一个 Gralloc
模块,封装了对 Framebuffer
的所有访问操作。Gralloc
模块符合 Android
标准的 HAL
架构设计;它分为 fb
和 gralloc
两个设备:前者负责打开内核中的 Framebuffer
、初始化配置,以及提供 post, setSwapInterval
等操作;后者则管理帧缓冲区的分配和释放。上层只能通过 Gralloc
访问帧缓冲区,这样一来就实现了有序的封装保护。
Gralloc
图形内存分配器,分配图像生产者请求的内存。它不仅仅是在原生堆上分配内存的另一种方法;在某些情况下,分配的内存可能并非缓存一致,或者可能完全无法从用户空间访问。分配的性质由用法标记确定,这些标记包括以下属性:
从软件 CPU
访问内存的频率
从硬件 GPU
访问内存的频率
是否将内存用作 OpenGL ES: GLES
纹理
视频编码器是否会使用内存
例如如果格式指定为 RGBA 8888
像素,并且指明将从软件访问缓冲区(这意味着应用将直接触摸像素),则分配器必须按照 R-G-B-A
的顺序为每个像素创建 4 个字节的缓冲区。相反如果指明仅从硬件访问缓冲区且缓冲区作为 GLES
纹理,则分配器可以执行 GLES
驱动程序所需的任何操作 - BGRA
排序、非线性搅和布局、替代颜色格式等。允许硬件使用其首选格式可以提高性能。某些值在特定平台上无法组合,例如视频编码器标记可能需要 YUV
像素,因此将无法添加软件访问权并指定 RGBA 8888
。
Gralloc
分配器返回的句柄可以通过 Binder
在进程之间传递。
HWC
HWC: Hardware Composer
硬件混合渲染器,显示子系统的硬件抽象实现。 SurfaceFlinger
可以将某些合成工作委托给 Hardware Composer
,以分担 OpenGL
和 GPU
上的工作量。 SurfaceFlinger
只是充当另一个 OpenGL ES
客户端。因此在 SurfaceFlinger
将一个或两个缓冲区合成到第三个缓冲区中的过程中,它会使用 OpenGL ES
。这样使合成的功耗比通过 GPU
执行所有计算更低。Hardware Composer HAL
则进行另一半的工作,并且是所有 Android
图形渲染的核心。 Hardware Composer
必须支持事件,其中之一是 VSYNC
(另一个是支持即插即用 HDMI
的热插拔 hotplug
) 。
VSYNC 垂直刷新 先介绍几个概念:
帧 视频,动画中的每一张画面,而视频和动画特效就是由无数张画面组合而成,每一张画面都是一帧。
帧率Frame Rate
,也指帧速率,单位 fps:frames per second
,描述视频、电子绘图或游戏每秒播放多少帧;FPS
是测量用于保存、显示动态视频的信息数量;我们本篇讲的帧率/帧速率指的是系统显卡处理的速率,即每秒能处理多少帧 。 每秒钟帧数愈多,所显示的动作就会愈流畅。通常要避免动作不流畅的最低是 30 ,所以常见的有 30fps, 60fps
等。 wiki
百科中提到几个帧率数字:
12 fps
:由于人类眼睛的特殊生理结构,如果所看画面之帧率高于每秒约 10-12 帧的时候,就会认为是连贯的,是动画的
24 fps
:有声电影的拍摄及播放帧率均为每秒 24 帧,对一般人而言已算可接受
30 fps
:早期的高动态电子游戏,帧率少于每秒 30 帧的话就会显得不连贯,这是因为没有动态模糊使流畅度降低
60 fps
:在实际体验中,60 帧相对于 30 帧有着更好的体验
85 fps
:一般而言,大脑处理视频的极限
屏幕刷新频率Refresh Rate
或者是 Scanning Frequency
,单位赫兹 Hz
(即周期/秒),是指设备刷新屏幕的频率,通常为 60hz
。屏幕的刷新过程是每一行从左到右(行刷新 ,水平刷新,Horizontal Scanning
),从上到下(屏幕刷新,垂直刷新, Vertical Scanning
)。
Tearing
撕裂 显示出来的图像出现上半部分和下半部分不属于同一帧,我们称之为 tearing
。假设系统显卡处理能力为 FPS 100
,显示器的刷新频率是 75Hz
,显卡将比显示器快 1/3
;这意味着,在一个刷新周期之内,显卡将写入 4/3
的帧数据,也就是说下一帧的 1/3 覆盖在前一帧之上;当然随着系统运行, 1/3 这个比例会发生变化,1/3,2/3,1,1/3,循环;这种帧与帧之间的不完全覆盖重合现象就是 Tearing
撕裂现象。
显卡处理图像的帧速率和屏幕刷新频率是相互独立的,当两者不一致时会出现 tearing
问题,为了解决不一致的问题,引入了 Vsync
信号:当整个屏幕刷新完毕,即一个垂直刷新周期完成,会有短暂的空白期,等待定期同步信号 VSync
信号,收到后才开始下一次屏幕刷新;所以 VSync
中的 V
指的是垂直刷新中的垂直 Vertical
。Vsync
技术意味着,显卡显示性能极限被限制在屏幕刷新率以内了:在系统显卡处理的 FPS
高于屏幕刷新率时,显卡会将一部分时间浪费在等待上;因为没有可用的内存用于绘制,显卡需要等待 Vsync
信号才能绘制下一帧。
60Hz 和 16 ms 从上面解释帧速率时提到,虽然人眼感知生理的极限 85fps
,但达到 60fps
时动画就已经有很好的体验,不会出现卡顿和迟滞现象;而最为关键的是 60Hz
是美国交流电的频率,如果屏幕刷新频率能够匹配交流电的频率就可以有效的预防屏幕中出现滚动条;所以:
60Hz
的屏幕刷新率或者 60fps
的帧率,是人眼能够感知到比较流畅的数值
1000ms/60=16ms
, 16ms
是指 GPU/CPU
在绘制图形时,必须在这个刷新频率内绘制完成,否则会出现丢帧现象
BufferQueue
实现了整个生产者消费者模型。 BufferQueues
是 Android
图形组件之间的粘合剂。它们是一对队列,可以调解缓冲区从生产者到消费者的固定周期。一旦生产者移交其缓冲区, SurfaceFlinger
便会负责将所有内容合成到显示部分。BufferQueue
永远不会复制缓冲区内容(移动如此多的数据是非常低效的操作);相反缓冲区始终通过句柄进行传递。
BufferQueue
包含将图像流生产者与图像流消费者结合在一起的逻辑。图像生产者的一些示例包括由相机 HAL
或 OpenGL ES
游戏生成的相机预览。图像消费者的一些示例包括 SurfaceFlinger
或显示 OpenGL ES
流的另一个应用,如显示相机取景器的相机应用。BufferQueue
是将缓冲区池与队列相结合的数据结构,它使用 Binder IPC
在进程之间传递缓冲区。生产者接口,或者您传递给想要生成图形缓冲区的某个人的内容,即是 IGraphicBufferProducer
( SurfaceTexture
的一部分)。 BufferQueue
通常用于渲染到 Surface
,并且与 GL
消费者及其他任务一起消耗内容。 BufferQueue
可以在三种不同的模式下运行:
类同步模式 默认情况下, BufferQueue
在类同步模式下运行,在该模式下,从生产者进入的每个缓冲区都在消费者那退出。在此模式下不会舍弃任何缓冲区。如果生产者速度太快,创建缓冲区的速度比消耗缓冲区的速度更快,它将阻塞并等待可用的缓冲区。
非阻塞模式BufferQueue
还可以在非阻塞模式下运行,在此类情况下,它会生成错误,而不是等待缓冲区。在此模式下也不会舍弃缓冲区。这有助于避免可能不了解图形框架的复杂依赖项的应用软件出现潜在死锁现象。
舍弃模式BufferQueue
可以配置为丢弃旧缓冲区,而不是生成错误或进行等待。例如,如果对纹理视图执行 GL
渲染并尽快绘制,则必须丢弃缓冲区。
为了执行这项工作的大部分环节, SurfaceFlinger
就像另一个 OpenGL ES
客户端一样工作。例如当 SurfaceFlinger
正在积极地将一个缓冲区或两个缓冲区合成到第三个缓冲区中时,它使用的是 OpenGL ES
。
数据流 Android
图形管道数据流如下图所示:
左侧的对象是生成图形缓冲区的渲染器,如主屏幕、状态栏和系统界面。 SurfaceFlinger
是合成器,而硬件混合渲染器是制作器。
组件小结
低级别组件
BufferQueue
和 gralloc
。 BufferQueue
将可生成图形数据缓冲区的组件(生产者)连接到接受数据以便进行显示或进一步处理的组件(消费者)。通过供应商专用 HAL
接口实现的 gralloc
内存分配器将用于执行缓冲区分配任务。
SurfaceFlinger, Hardware Composer
和虚拟显示屏。 SurfaceFlinger
接受来自多个源的数据缓冲区,然后将它们进行合成并发送到显示屏。 Hardware Composer HAL (HWC)
确定使用可用硬件合成缓冲区的最有效的方法,虚拟显示屏使合成输出可在系统内使用(录制屏幕或通过网络发送屏幕)。
Surface, Canvas, SurfaceHolder
。 Surface
可生成一个通常由 SurfaceFlinger
使用的缓冲区队列。当渲染到 Surface
上时,结果最终将出现在传送给消费者的缓冲区中。 Canvas API
提供一种软件实现方法(支持硬件加速),用于直接在 Surface
上绘图( OpenGL ES
的低级别替代方案)。与视图有关的任何内容均涉及到 SurfaceHolder
,其 API
可用于获取和设置 Surface
参数(如大小和格式)。
EGLSurface, OpenGL ES
。 OpenGL ES (GLES)
定义了用于与 EGL
结合使用的图形渲染 API
。 EGI
是一个规定如何通过操作系统创建和访问窗口的库(要绘制纹理多边形,请使用 GLES
调用;要将渲染放到屏幕上,请使用 EGL
调用)。 ANativeWindow
,它是 Java Surface
类的 C/C++
等价类,用于通过原生代码创建 EGL
窗口 Surface
。
Vulkan
。 Vulkan
是一种用于高性能 3D
图形的低开销、跨平台 API
。与 OpenGL ES
一样, Vulkan
提供用于在应用中创建高质量实时图形的工具。 Vulkan
的优势包括降低 CPU
开销以及支持 SPIR-V
二进制中间语言。
高级别组件
SurfaceView
和 GLSurfaceView
。 SurfaceView
结合了 Surface
和 View
。 SurfaceView
的 View
组件由 SurfaceFlinger
(而不是应用)合成,从而可以通过单独的线程/进程渲染,并与应用界面渲染隔离。 GLSurfaceView
提供帮助程序类来管理 EGL
上下文、线程间通信以及与 Activity
生命周期的交互(但使用 GLES
时并不需要 GLSurfaceView
)。
SurfaceTexture
。 SurfaceTexture
将 Surface
和 GLES
纹理相结合来创建 BufferQueue
,而应用是 BufferQueue
的消费者。当生产者将新的缓冲区排入队列时,它会通知应用。应用会依次释放先前占有的缓冲区,从队列中获取新缓冲区并执行 EGL
调用,从而使 GLES
可将此缓冲区作为外部纹理使用。 Android 7.0
增加了对安全纹理视频播放的支持,以便用户能够对受保护的视频内容进行 GPU
后处理。
TextureView
。 TextureView
结合了 View
和 SurfaceTexture
。 TextureView
对 SurfaceTexture
进行包装,并负责响应回调以及获取新的缓冲区。在绘图时, TextureView
使用最近收到的缓冲区的内容作为其数据源,根据 View
状态指示,在它应该渲染的任何位置和以它应该采用的任何渲染方式进行渲染。 View
合成始终通过 GLES
来执行,这意味着内容更新可能会导致其他 View
元素重绘。
高级别组件可以直接在 APP
中使用。
Buffer/Window
体系代码速查表 1 2 3 4 5 6 7 system/core/libcutils/include/cutils/native_handle.h hardware/qcom/display/libgralloc/gralloc_priv.h frameworks/native/libs/nativebase/include/nativebase/nativebase.h frameworks/native/libs/nativewindow/include/system/window.h frameworks/native/libs/ui/include/ui/ANativeObjectBase.h frameworks/native/libs/ui/include/ui/GraphicBuffer.h frameworks/native/libs/gui/include/gui/Surface.h
native_handle/buffer_handle_t
先看 native_handle
这个结构体的定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 typedef struct native_handle { int version; int numFds; int numInts; #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wzero-length-array" #endif int data[0 ]; #if defined(__clang__) #pragma clang diagnostic pop #endif } native_handle_t ; typedef const native_handle_t * buffer_handle_t ;
native_handle
这个结构体,描述了一个数据结构,其中最关键的是 data[0]
,它是一个长度为 0 的数组,即 native_handle
是一个柔性数组。在标准的 C/C++
中,长度为 0 的数组是不被允许的,编译时会产生错误!长度为 0 的数组是 C/C++
的扩展,需要当前编译器支持这个扩展。从头文件注释中也可以看出,当使用的是 clang
编译器时,才会定义 data[0]
并且忽略数组为 0 的警告。
从 C/C++
中柔性数组的用途来看, native_handle
表示的是一个不定长数据结构,实际意义指向连续分配的内存空间(除了 native_handle
之外)代表的数据结构(通常是 private_handle_t
)。这里这么做,是因为显示系统和每家实现平台相关度很高, native_handle
定义一个通用的数据结构,至于显示系统如何显示,每家自己去实现对应的 private_handle_t
。
native_handle
结构体中的注释写的很清楚, numFds
表示被指向数据结构包含几个文件描述符; numInts
表示被指向数据结构长度是多少个整型;有了这两个信息后,内存分配就很容易了,参考 native_handle_create
的源码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 native_handle_t * native_handle_create (int numFds, int numInts) { if (numFds < 0 || numInts < 0 || numFds > kMaxNativeFds || numInts > kMaxNativeInts) { errno = EINVAL; return NULL ; } size_t mallocSize = sizeof (native_handle_t ) + (sizeof (int ) * (numFds + numInts)); native_handle_t * h = malloc (mallocSize); if (h) { h->version = sizeof (native_handle_t ); h->numFds = numFds; h->numInts = numInts; } return h; }
小结: native_handle, native_handle_t
表示一个不定长数据结构,而 buffer_handle_t
表示指向 native_handle
的指针。
private_handle_t
private_handle_t
描述的是一块缓存,因为和实现平台高度相关,我这里选取高通平台,先看头文件定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 #ifdef __cplusplus struct private_handle_t : public native_handle {#else struct private_handle_t { native_handle_t nativeHandle; #endif enum { PRIV_FLAGS_FRAMEBUFFER = 0x00000001 , ... }; int fd; int fd_metadata; int magic; int flags; unsigned int size; unsigned int offset; int bufferType; uint64_t base __attribute__((aligned(8 ))); unsigned int offset_metadata; uint64_t gpuaddr __attribute__((aligned(8 ))); int format; int width; int height; uint64_t base_metadata __attribute__((aligned(8 ))); int unaligned_width; int unaligned_height; #ifdef __cplusplus static const int sNumFds = 2 ; static inline int sNumInts () { return ((sizeof (private_handle_t ) - sizeof (native_handle_t )) / sizeof (int )) - sNumFds; } static const int sMagic = 'gmsm'; ... }
private_handle_t
描述了缓存区使用的文件描述符 fd, fd_metadata
、大小、偏移量、基地址、长宽、格式、没有对齐的长宽等等,而 sNumFds
对应 nativeHandle.numFds
; sNumInts
对应 nativeHandle.numInts
,即除了文件描述符之外,该数据结构的长度。 小结: private_handle_t
在各个模块之间传递的时候很不方便,而如果用 native_handle
的来传递,就可以消除平台的差异性。一个简单示意图描述两者的关系:
至此,我们可以简单的理解为 native_handle, native_handle_t, private_handle_t, buffer_handle_t
表示的是同一块内存。
ANativeWindowBuffer
先了解 android_native_base_t
数据结构的定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 typedef struct android_native_base_t { int magic; int version; void * reserved[4 ]; void (*incRef)(struct android_native_base_t * base); void (*decRef)(struct android_native_base_t * base); } android_native_base_t ;
android_native_base_t
中 incRef/decRef
主要功能是:为了把派生类和 Android
所有 class
的老祖宗 RefBase
联系起来所预留的函数指针。
再看 ANativeWindowBuffer
数据结构的定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 typedef struct ANativeWindowBuffer { #ifdef __cplusplus ANativeWindowBuffer() { common.magic = ANDROID_NATIVE_BUFFER_MAGIC; common.version = sizeof (ANativeWindowBuffer); memset (common.reserved, 0 , sizeof (common.reserved)); } void incStrong (const void * ) const { common.incRef(const_cast <android_native_base_t *>(&common)); } void decStrong (const void * ) const { common.decRef(const_cast <android_native_base_t *>(&common)); } #endif struct android_native_base_t common ; int width; int height; int stride; int format; int usage_deprecated; uintptr_t layerCount; void * reserved[1 ]; const native_handle_t * handle; uint64_t usage; void * reserved_proc[8 - (sizeof (uint64_t ) / sizeof (void *))]; } ANativeWindowBuffer_t; typedef struct ANativeWindowBuffer ANativeWindowBuffer ;typedef ANativeWindowBuffer_t android_native_buffer_t ;
ANativeWindowBuffer
中使用了 native_handle_t
指针,同时该结构体中也有长宽、格式、步进等基本描述信息;也就是 ANativeWindowBuffer
描述的是一块 Window
相关的缓存区。
ANativeWindow
ANativeWindow
数据结构的定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 struct ANativeWindow { #ifdef __cplusplus ANativeWindow() : flags(0 ), minSwapInterval(0 ), maxSwapInterval(0 ), xdpi(0 ), ydpi(0 ) { common.magic = ANDROID_NATIVE_WINDOW_MAGIC; common.version = sizeof (ANativeWindow); memset (common.reserved, 0 , sizeof (common.reserved)); } void incStrong (const void * ) const { common.incRef(const_cast <android_native_base_t *>(&common)); } void decStrong (const void * ) const { common.decRef(const_cast <android_native_base_t *>(&common)); } #endif struct android_native_base_t common ; const uint32_t flags; const int minSwapInterval; const int maxSwapInterval; const float xdpi; const float ydpi; intptr_t oem[4 ]; int (*setSwapInterval)(struct ANativeWindow* window, int interval); int (*dequeueBuffer_DEPRECATED)(struct ANativeWindow* window, struct ANativeWindowBuffer** buffer); int (*lockBuffer_DEPRECATED)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer); int (*queueBuffer_DEPRECATED)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer); int (*query)(const struct ANativeWindow* window, int what, int * value); int (*perform)(struct ANativeWindow* window, int operation, ... ); int (*cancelBuffer_DEPRECATED)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer); int (*dequeueBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer** buffer, int * fenceFd); int (*queueBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer, int fenceFd); int (*cancelBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer, int fenceFd); }; typedef struct ANativeWindow android_native_window_t __deprecated ;
从数据结构定义中可以看出, ANativeWindow
和窗口属性相关,它表示的是一个底层实现的窗口,定义的各种函数指针都是对 ANativeWindowBuffer
内存的操作;而 fenceFd
可以看成这个 buffer
的锁。
小结:不管是 ANativeWindow, ANativeWindowBuffer
它们都包含 android_native_base_t
结构体,但是都没有对 incRef, decRef
赋值;可以认为 ANativeWindow, ANativeWindowBuffer
为抽象数据结构。
ANativeObjectBase
模板ANativeObjectBase
是一个模板类,定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 template <typename NATIVE_TYPE, typename TYPE, typename REF, typename NATIVE_BASE = android_native_base_t > class ANativeObjectBase : public NATIVE_TYPE, public REF { public : void incStrong(const void * id) const { REF::incStrong(id); } void decStrong (const void * id) const { REF::decStrong(id); } protected : typedef ANativeObjectBase<NATIVE_TYPE, TYPE, REF, NATIVE_BASE> BASE; ANativeObjectBase() : NATIVE_TYPE(), REF() { NATIVE_TYPE::common.incRef = incRef; NATIVE_TYPE::common.decRef = decRef; } static inline TYPE* getSelf (NATIVE_TYPE* self) { return static_cast <TYPE*>(self); } static inline TYPE const * getSelf (NATIVE_TYPE const * self) { return static_cast <TYPE const *>(self); } static inline TYPE* getSelf (NATIVE_BASE* base) { return getSelf(reinterpret_cast <NATIVE_TYPE*>(base)); } static inline TYPE const * getSelf (NATIVE_BASE const * base) { return getSelf(reinterpret_cast <NATIVE_TYPE const *>(base)); } static void incRef (NATIVE_BASE* base) { ANativeObjectBase* self = getSelf(base); self->incStrong(self); } static void decRef (NATIVE_BASE* base) { ANativeObjectBase* self = getSelf(base); self->decStrong(self); } }; } #endif
ANativeObjectBase
模板类的主要作用就是实现 incRef, decRef
引用计数,以及父类子类的类型转换。
GraphicBuffer
先看 GraphicBuffer
的头文件定义:
1 2 3 4 5 class GraphicBuffer : public ANativeObjectBase<ANativeWindowBuffer, GraphicBuffer, RefBase>, public Flattenable<GraphicBuffer> {...}
GraphicBuffer
使用 ANativeObjectBase
模板,即 GraphicBuffer
就是 ANativeWindowBuffer
的一种具体实现;而 ANativeWindowBuffer.common
成员的两个函数指针 incRef, decRef
指向了 GraphicBuffer
的另一个基类 RefBase
的 incStrong, decStrong
;而 ANativeWindowBuffer
可以看做是把 buffer_handle_t
包了一层,所以 GraphicBuffer
也是指向的一块缓存区。
Surface
Surface
的头文件定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Surface : public ANativeObjectBase<ANativeWindow, Surface, RefBase>{ ... protected : ... struct BufferSlot { sp<GraphicBuffer> buffer; Region dirtyRegion; }; BufferSlot mSlots[NUM_BUFFER_SLOTS]; ... }
Surface
也使用了 ANativeObjectBase
模板,即 Surface
就是 ANativeWindow
的一种具体实现,同样也继承了 RefBase
实现引用计数。另外成员数据结构 BufferSlot
是对 GraphicBuffer
的包装,而 mSlots
数组表示每个 Surface
中包含 NUM_BUFFER_SLOTS
个 GraphicBuffer
缓存。 而 Surface
的构造函数中,也将 ANativeWindow
的函数指针进行了赋值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp) : mGraphicBufferProducer(bufferProducer), mCrop(Rect::EMPTY_RECT), mBufferAge(0 ), mGenerationNumber(0 ), mSharedBufferMode(false ), mAutoRefresh(false ), mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT), mSharedBufferHasBeenQueued(false ), mQueriedSupportedTimestamps(false ), mFrameTimestampsSupportsPresent(false ), mEnableFrameTimestamps(false ), mFrameEventHistory(std ::make_unique<ProducerFrameEventHistory>()){ ANativeWindow::setSwapInterval = hook_setSwapInterval; ANativeWindow::dequeueBuffer = hook_dequeueBuffer; ANativeWindow::cancelBuffer = hook_cancelBuffer; ANativeWindow::queueBuffer = hook_queueBuffer; ANativeWindow::query = hook_query; ANativeWindow::perform = hook_perform; ... }
小结
native_handle/native_handle_t
是 private_handle_t
的抽象表示方法,消除平台相关性;方便 private_handle_t
所表示的缓存区可以在 Android
各个层次之间传递;而 buffer_handle_t
是指向他们的指针
ANativeWindowBuffer
将 buffer_handle_t
进行了包装;ANativeWindow, ANativeWindowBuffer
都继承于 android_native_base_t
,它定义了引用计数两个函数指针;可以认为 ANativeWindow, ANativeWindowBuffer
为抽象数据结构,表示窗口和其对应缓存
GraphicBuffer, Surface
都使用了模版类 ANativeObjectBase
,都继承了 RefBase
实现 incRef, decRef
引用计数;它们是具体的实现类,即实现具体的窗口缓存和窗口
Surface
的成员 BufferSlot mSlots[NUM_BUFFER_SLOTS];
可以看作是 sp<GraphicBuffer>
类型的数组;也就是说每个 Surface
中都包含有 NUM_BUFFER_SLOTS
个 GraphicBuffer
Surface, GraphicBuffer
是图形显示系统的高层类,后续主要围绕这两个类来介绍;一个代表窗口,一个代表窗口对应的缓存
Buffer/Window 体系缓存,查看大图
BufferQueue
中的 Buffer
对象,我们用的都是 GraphicBuffer
。 Surface
是 Andorid
窗口的描述,是 ANativeWindow
的实现;同样 GraphicBuffer
是 Android
中图形 Buffer
的描述,是 ANativeWindowBuffer
的实现。而一个窗口可以有多个 Buffer
。
libui
库libui.so
库主要是 GraphicBuffer
缓存相关的代码,包含缓存分配,映射当当前进程等等,而 IAllocator, IMapper
具体是在 HAL
中实现的。
代码目录结构 frameworks/native/libs/ui
目录结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 ui ├── Android.bp ├── ColorSpace.cpp ├── DebugUtils.cpp ├── Fence.cpp ├── FenceTime.cpp ├── FrameStats.cpp ├── Gralloc2.cpp ├── GraphicBufferAllocator.cpp ├── GraphicBuffer.cpp ├── GraphicBufferMapper.cpp ├── HdrCapabilities.cpp ├── include │ └── ui │ ├── ANativeObjectBase.h │ ├── BufferQueueDefs.h │ ├── ColorSpace.h │ ├── DebugUtils.h │ ├── DisplayInfo.h │ ├── DisplayStatInfo.h │ ├── Fence.h │ ├── FenceTime.h │ ├── FloatRect.h │ ├── FrameStats.h │ ├── Gralloc2.h │ ├── GraphicBufferAllocator.h │ ├── GraphicBuffer.h │ ├── GraphicBufferMapper.h │ ├── HdrCapabilities.h │ ├── PixelFormat.h │ ├── Point.h │ ├── Rect.h │ ├── Region.h │ └── UiConfig.h ├── MODULE_LICENSE_APACHE2 ├── NOTICE ├── PixelFormat.cpp ├── Rect.cpp ├── Region.cpp ├── tests │ ├── Android.bp │ ├── colorspace_test.cpp │ └── Region_test.cpp ├── tools │ ├── Android.bp │ └── lutgen.cpp └── UiConfig.cpp 4 directories, 42 files
GraphicBufferAllocator/GraphicBufferMapper
它们两个都是包装类,包装了 IAllocator, IMapper
,而这两个类都是在 HAL Gralloc2
中实现的。
GraphicBufferAllocator
缓存分配,包装了 IAllocator
类。
GraphicBufferMapper
缓存映射到当前进程,包装了 IMapper
类。
GraphicBuffer
GraphicBuffer
继承 ANativeWindowBuffer
,并持有 GraphicBufferMapper
映射对应的缓存区。
1 2 3 4 5 6 7 8 9 10 11 12 13 class GraphicBuffer : public ANativeObjectBase<ANativeWindowBuffer, GraphicBuffer,RefBase>, public Flattenable<GraphicBuffer> { public : static sp<GraphicBuffer> from (ANativeWindowBuffer *) ; ... private : GraphicBufferMapper& mBufferMapper; ssize_t mInitCheck; uint64_t mId; uint32_t mGenerationNumber; };
Fence
机制Fence
是一种同步机制,主要用于 GraphicBuffer
的同步。它主要被用来处理跨硬件的情况,尤其是 CPU, GPU, HWC
之间的同步,另外它还可以用于多个时间点之间的同步。 GPU
编程和纯 CPU
编程一个很大的不同是它是异步的,也就是说当我们调用 GL command
返回时这条命令并不一定完成了,只是把这个命令放在本地的 command buffer
里,而 Fence
机制就是解决这些同步问题的。Fence
顾名思义就是把先到的拦住,等后来的,两者步调一致了再往前走。抽象地说,Fence
包含了同一或不同时间轴上的多个时间点,只有当这些点同时到达时 Fence
才会被触发。 Fence
可以由硬件实现 Graphic driver
,也可以由软件实现 Android kernel
中的 sw_sync
。
Fence
的主要实现代码路径:
1 2 3 4 frameworks/native/libs/ui/Fence.cpp system/core/libsync/sync.c kernel/drivers/base/sync.c frameworks/native/libs/gui/SyncFeatures.cpp
总得来说, kernel driver
部分是同步的主要实现,libsync
是对 driver
接口的封装, Fence
是对 libsync
的进一步的 C++
封装。 Fence
会被作为 GraphicBuffer
的附属随着 GraphicBuffer
在生产者和消费间传输; SyncFeatures
用以查询系统支持的同步机制。
DisplayInfo
显示信息1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 struct DisplayInfo { uint32_t w{0 }; uint32_t h{0 }; float xdpi{0 }; float ydpi{0 }; float fps{0 }; float density{0 }; uint8_t orientation{0 }; bool secure{false }; nsecs_t appVsyncOffset{0 }; nsecs_t presentationDeadline{0 }; }; enum { DISPLAY_ORIENTATION_0 = 0 , DISPLAY_ORIENTATION_90 = 1 , DISPLAY_ORIENTATION_180 = 2 , DISPLAY_ORIENTATION_270 = 3 }; };
DisplayInfo
结构体包含了显示屏幕的基本信息:
屏幕分辨率 Resolution
屏幕的宽高是用分辨率 Resolution
来描述的,也就是有多少个像素点。屏幕宽度,即屏幕横向可以显示多少个像素点;屏幕高度,即屏幕纵向可以显示多少给像素点。平常所说的 720P: 1080x720
屏幕,即横向可以显示 1080 个像素点,纵向可以显示 720 个像素点。如下为常见屏幕分辨率:
屏幕 DPI
DPI: Dots Per Inch
每英寸点数,是一个度量单位,表示屏幕每英寸上有多少个物理点。常见屏幕物理大小,是用英寸来描述屏幕对角线的长度,比如 IPhone X
的大小 5.8 寸,即屏幕对角线长度为 5.8 英寸。**标准 DPI
为 160dpi
**,人类视网膜级通常为 300dpi
。PPI: Pixel Per Inch
每英寸像素,也是度量单位,表示每英寸显示多少个像素。通常情况下 DPI, PPI
设为相同,表示每个物理点显示一个像素;但是好一点的显示器,可能 DPI
比 PPI
大,即一个像素由多个物理点来显示。
密度 Density
DIP: Density Independent Pixels
设备无关像素,通常简写为 DP=DIP
,请注意 DPI
做好区分。 DP
表示这个像素的数值是和设备无关的,那实际转换时怎么转换呢?Density
密度,实际是一个缩放因子,它表示当前设备实际 DPI
和标准 DPI
的比例值;比如设备实际 DPI
为 320dpi
,那么 density=320/160=2
,即 density
为 2 。有了 density
之后, dp, px
可以使用公式来转换 px=density*dp
。 所以我们在 APP
布局设计中,所有显示设置的距离,通常使用 dp
来计算,来规避不同屏幕特性。
屏幕刷新率 FPS
这里屏幕刷新率使用 FPS
来表示,不是 Hz
,表示屏幕每秒能显示多少帧数据;通常为 60 fps ,即 16 ms 刷新一次。
屏幕旋转方向 orientations
手机默认竖屏,0 表示竖屏, 180 表示横屏。
屏幕安全性 secure
这主要是用于 DRM
数字版权保护时,确保显示的设备是安全的,以防止 DRM
的内容被在显示的过程中被截取,只有安全的设备才能显示 DRM
的内容。 Android
默认所有的非虚拟显示都是安全的。
appVsyncOffset, presentationDeadline
这两个都和 Vsync
有关; appVsyncOffset
是一个偏移量,在系统或硬件 Vsync
的基础上做一些偏移; presentationDeadline
表示,一帧数据必现在这个时间内显示出来。
libgui
库代码目录结构 frameworks/native/libs/gui
目录结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 gui/ ├── Android.bp ├── BitTube.cpp ├── BufferItemConsumer.cpp ├── BufferItem.cpp ├── bufferqueue │ └── 1.0 │ ├── B2HProducerListener.cpp │ └── H2BGraphicBufferProducer.cpp ├── BufferQueueConsumer.cpp ├── BufferQueueCore.cpp ├── BufferQueue.cpp ├── BufferQueueProducer.cpp ├── BufferSlot.cpp ├── CleanSpec.mk ├── ConsumerBase.cpp ├── CpuConsumer.cpp ├── DisplayEventReceiver.cpp ├── FrameTimestamps.cpp ├── GLConsumer.cpp ├── GuiConfig.cpp ├── IConsumerListener.cpp ├── IDisplayEventConnection.cpp ├── IGraphicBufferConsumer.cpp ├── IGraphicBufferProducer.cpp ├── include │ ├── gui │ │ ├── BufferItemConsumer.h │ │ ├── BufferItem.h │ │ ├── bufferqueue │ │ │ └── 1.0 │ │ │ ├── B2HProducerListener.h │ │ │ └── H2BGraphicBufferProducer.h │ │ ├── BufferQueueConsumer.h │ │ ├── BufferQueueCore.h │ │ ├── BufferQueueDefs.h │ │ ├── BufferQueue.h │ │ ├── BufferQueueProducer.h │ │ ├── BufferSlot.h │ │ ├── ConsumerBase.h │ │ ├── CpuConsumer.h │ │ ├── DisplayEventReceiver.h │ │ ├── FrameTimestamps.h │ │ ├── GLConsumer.h │ │ ├── GuiConfig.h │ │ ├── IConsumerListener.h │ │ ├── IDisplayEventConnection.h │ │ ├── IGraphicBufferConsumer.h │ │ ├── IGraphicBufferProducer.h │ │ ├── IProducerListener.h │ │ ├── ISurfaceComposerClient.h │ │ ├── ISurfaceComposer.h │ │ ├── OccupancyTracker.h │ │ ├── StreamSplitter.h │ │ ├── SurfaceComposerClient.h │ │ ├── SurfaceControl.h │ │ ├── Surface.h │ │ └── view │ │ └── Surface.h │ └── private │ └── gui │ ├── BitTube.h │ ├── ComposerService.h │ ├── LayerState.h │ └── SyncFeatures.h ├── IProducerListener.cpp ├── ISurfaceComposerClient.cpp ├── ISurfaceComposer.cpp ├── LayerState.cpp ├── OccupancyTracker.cpp ├── StreamSplitter.cpp ├── SurfaceComposerClient.cpp ├── SurfaceControl.cpp ├── Surface.cpp ├── SyncFeatures.cpp ├── tests │ ├── ... └── view └── Surface.cpp 11 directories, 96 files
其中 H2B, B2H
表示 Framework Buffer
和 HAL
层数据结构的相互转换;实际上代表的是同一样东西,方便各层内部使用。
IGraphicBufferProducer/IProducerListener
生产者IGraphicBufferProducer
是生产者接口,实现了 IInterface
可以用于跨进程通信。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class IGraphicBufferProducer : public IInterface{ public : DECLARE_HYBRID_META_INTERFACE(GraphicBufferProducer, HGraphicBufferProducer) ... virtual status_t dequeueBuffer (int * slot, sp<Fence>* fence, uint32_t w, uint32_t h, PixelFormat format, uint64_t usage, uint64_t * outBufferAge, FrameEventHistoryDelta* outTimestamps) = 0 ; virtual status_t requestBuffer (int slot, sp<GraphicBuffer>* buf) = 0 ; virtual status_t queueBuffer (int slot, const QueueBufferInput& input, QueueBufferOutput* output) = 0 ; virtual status_t detachBuffer (int slot) = 0 ; virtual status_t detachNextBuffer (sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) = 0 ; virtual status_t attachBuffer (int * outSlot, const sp<GraphicBuffer>& buffer) = 0 ; virtual status_t cancelBuffer (int slot, const sp<Fence>& fence) = 0 ; ... virtual status_t connect (const sp<IProducerListener>& listener, int api, bool producerControlledByApp, QueueBufferOutput* output) = 0 ; virtual status_t disconnect (int api, DisconnectMode mode = DisconnectMode::Api) = 0 ; virtual String8 getConsumerName () const = 0 ; ... };
IProducerListener
是 IGraphicBufferProducer
对应的回调接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class ProducerListener : public virtual RefBase{ public : ProducerListener() {} virtual ~ProducerListener(); virtual void onBufferReleased () = 0 ; virtual bool needsReleaseNotify () = 0 ; }; class IProducerListener : public ProducerListener, public IInterface{ public : DECLARE_META_INTERFACE(ProducerListener) }; class BnProducerListener : public BnInterface<IProducerListener>{ public : virtual status_t onTransact (uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0 ) ; virtual bool needsReleaseNotify () ; }; class DummyProducerListener : public BnProducerListener{ public : virtual ~DummyProducerListener(); virtual void onBufferReleased () {} virtual bool needsReleaseNotify () { return false ; } };
IGraphicBufferConsumer/IConsumerListener
消费者IGraphicBufferConsumer
是消费者接口,实现了 IInterface
可以用于跨进程通信。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class IGraphicBufferConsumer : public IInterface {public : DECLARE_META_INTERFACE(GraphicBufferConsumer) ... virtual status_t acquireBuffer (BufferItem* buffer, nsecs_t presentWhen, uint64_t maxFrameNumber = 0 ) = 0 ; virtual status_t detachBuffer (int slot) = 0 ; virtual status_t attachBuffer (int * outSlot, const sp<GraphicBuffer>& buffer) = 0 ; virtual status_t releaseBuffer (int buf, uint64_t frameNumber, EGLDisplay display, EGLSyncKHR fence, const sp<Fence>& releaseFence) = 0 ; ... virtual status_t consumerConnect (const sp<IConsumerListener>& consumer, bool controlledByApp) = 0 ; virtual status_t consumerDisconnect () = 0 ; ... };
IConsumerListener
是 IGraphicBufferConsumer
对应的回调接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class ConsumerListener : public virtual RefBase {public : ConsumerListener() {} virtual ~ConsumerListener(); virtual void onDisconnect () {} virtual void onFrameAvailable (const BufferItem& item) = 0 ; virtual void onFrameReplaced (const BufferItem& ) {} virtual void onBuffersReleased () = 0 ; virtual void onSidebandStreamChanged () = 0 ; virtual void addAndGetFrameTimestamps (const NewFrameEventsEntry* , FrameEventHistoryDelta* ) {}}; class IConsumerListener : public ConsumerListener, public IInterface {public : DECLARE_META_INTERFACE(ConsumerListener) };
BufferItem
BufferItem
描述了一块缓存 GraphicBuffer
,以及位置 mSlot
,同步 mFence
等等信息。
1 2 3 4 5 6 7 8 9 10 11 12 class BufferItem : public Flattenable<BufferItem> { ... sp<GraphicBuffer> mGraphicBuffer; sp<Fence> mFence; Rect mCrop; ... android_dataspace mDataSpace; uint64_t mFrameNumber; int mSlot; ... }
BufferSlot
BufferSlot
记录了当前 slot
位置的缓存 GraphicBuffer
,以及对应状态, EGL
相关信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 struct BufferSlot { BufferSlot() : mGraphicBuffer(nullptr ), mEglDisplay(EGL_NO_DISPLAY), mBufferState(), mRequestBufferCalled(false ), mFrameNumber(0 ), mEglFence(EGL_NO_SYNC_KHR), mFence(Fence::NO_FENCE), mAcquireCalled(false ), mNeedsReallocation(false ) { } sp<GraphicBuffer> mGraphicBuffer; EGLDisplay mEglDisplay; BufferState mBufferState; bool mRequestBufferCalled; uint64_t mFrameNumber; EGLSyncKHR mEglFence; sp<Fence> mFence; bool mAcquireCalled; bool mNeedsReallocation; };
BufferQueueDefs
中定义了一个 BufferSlot
的数组结构类型 SlotsType
。
1 2 3 4 5 6 7 8 namespace android { class BufferQueueCore ; namespace BufferQueueDefs { typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS]; } }
BufferQueueCore
BufferQueueCore
是生产者消费模型的核心,如下是几个重要的成员变量:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class BufferQueueCore : public virtual RefBase {public : ... typedef Vector<BufferItem> Fifo; private : ... String8 mConsumerName; sp<IConsumerListener> mConsumerListener; sp<IProducerListener> mConnectedProducerListener; BufferQueueDefs::SlotsType mSlots; Fifo mQueue; ... }
mQueue
是一个新建先出队列,存储了一队 BufferItem
数据,即一组缓存区。
mSlots
一个数组,保存了 BufferSlot
数据,每个 slot
位置对应一个缓存。
mConsumerListener
当前生产消费模型中的,消费者回调接口。
mConnectedProducerListener
当前生产消费模型中的,生产者回调接口。
BufferQueueProducer/BufferQueueConsumer
生产者/消费者实现类BufferQueueProducer
是 IGraphicBufferConsumer
的实现类,实现了生产者对应的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class BufferQueueProducer : public BnGraphicBufferProducer, private IBinder::DeathRecipient { ... private : ... sp<BufferQueueCore> mCore; BufferQueueDefs::SlotsType& mSlots; String8 mConsumerName; ... sp<Fence> mLastQueueBufferFence; Rect mLastQueuedCrop; uint32_t mLastQueuedTransform; }
BufferQueueProducer
中持有 BufferQueueCore
对象; mSlots
指向 mCore->mSlots
;同时保持了生产消费模型中,对应消费者的名称。
BufferQueueConsumer
是 IGraphicBufferConsumer
的实现类,实现了消费者对应的功能。
1 2 3 4 5 6 7 8 9 class BufferQueueConsumer : public BnGraphicBufferConsumer { ... private : sp<BufferQueueCore> mCore; BufferQueueDefs::SlotsType& mSlots; String8 mConsumerName; }
BufferQueueConsumer
中持有 BufferQueueCore
对象; mSlots
指向 mCore->mSlots
。
BufferQueue
模型BufferQueue
类是 Android
中所有图形处理操作的核心。它的作用很简单:将生成图形数据缓冲区的一方(生产者)连接到接受数据以进行显示或进一步处理的一方(消费者)。几乎所有在系统中移动图形数据缓冲区的内容都依赖于 BufferQueue
。 基本用法很简单:生产者请求一个可用的缓冲区 dequeueBuffer
,并指定一组特性,包括宽度、高度、像素格式和用法标记;生产者填充缓冲区并将其返回到队列 queueBuffer
。随后消费者获取该缓冲区 acquireBuffer
,并使用该缓冲区的内容。当消费者操作完毕后,将该缓冲区返回到队列 releaseBuffer
。 最新的 Android 设备支持“同步框架”,这使得系统能够在与可以异步处理图形数据的硬件组件结合使用时提高工作效率。例如,生产者可以提交一系列 OpenGL ES
绘制命令,然后在渲染完成之前将输出缓冲区加入队列。该缓冲区伴有一个栅栏,当内容准备就绪时,栅栏会发出信号。当该缓冲区返回到空闲列表时,会伴有第二个栅栏,因此消费者可以在内容仍在使用期间释放该缓冲区。该方法缩短了缓冲区通过系统时的延迟时间,并提高了吞吐量。 队列的一些特性(例如可以容纳的最大缓冲区数)由生产者和消费者联合决定。但是 BufferQueue
负责根据需要分配缓冲区。除非特性发生变化,否则将会保留缓冲区;例如,如果生产者请求具有不同大小的缓冲区,则系统会释放旧的缓冲区,并根据需要分配新的缓冲区。 生产者和消费者可以存在于不同的进程中; BufferQueue
永远不会复制缓冲区内容(移动如此多的数据是非常低效的操作),缓冲区始终通过句柄进行传递。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class BufferQueue {public : ... typedef ::android::ConsumerListener ConsumerListener; class ProxyConsumerListener : public BnConsumerListener { public : explicit ProxyConsumerListener (const wp<ConsumerListener>& consumerListener) ; ~ProxyConsumerListener() override ; void onDisconnect () override ; void onFrameAvailable (const BufferItem& item) override ; void onFrameReplaced (const BufferItem& item) override ; void onBuffersReleased () override ; void onSidebandStreamChanged () override ; void addAndGetFrameTimestamps ( const NewFrameEventsEntry* newTimestamps, FrameEventHistoryDelta* outDelta) override ; private : wp<ConsumerListener> mConsumerListener; }; static void createBufferQueue ( sp<IGraphicBufferProducer>* outProducer, sp<IGraphicBufferConsumer>* outConsumer, bool consumerIsSurfaceFlinger = false ) ; BufferQueue() = delete ; };
BufferQueue
的头文件定义很简单:
定义了一个 ConsumerListener
的弱引用
整个类只有一个函数 createBufferQueue
,它将参数中的 IGraphicBufferProducer, IGraphicBufferConsumer
消费者关联起来
没有构造函数,只能通过 createBufferQueue
来创建对象
BufferQueue
中并不包含队列数据结构来存储缓存,仅仅连接了生产者、消费者两者的关系
来看 createBufferQueue
的具体实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void BufferQueue::createBufferQueue ( sp<IGraphicBufferProducer>* outProducer, sp<IGraphicBufferConsumer>* outConsumer, bool consumerIsSurfaceFlinger) { ... sp<BufferQueueCore> core (new BufferQueueCore()) ; sp<IGraphicBufferProducer> producer ( new BufferQueueProducer(core, consumerIsSurfaceFlinger)) ; ... sp<IGraphicBufferConsumer> consumer (new BufferQueueConsumer(core)) ; ... *outProducer = producer; *outConsumer = consumer; }
上面代码删掉了 LOG
打印及空判断,整个代码流程非常简单:
新建 BufferQueueCore core
由 core
新建生产者 IGraphicBufferProducer
由 core
新建消费者 IGraphicBufferConsumer
也就是说 BufferQueueCore
是最终的纽带,保存了生产者消费者对应的缓存区,连接了两者的关系。
Surface
Surface
代表着窗口,它包含一个生产者 IGraphicBufferProducer
用来填充缓存,也就是窗口中用来显示在屏幕上的内容,mSlot
数组表示可以有多个缓存区。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Surface : public ANativeObjectBase<ANativeWindow, Surface, RefBase>{ public : ... sp<IGraphicBufferProducer> getIGraphicBufferProducer () const ; String8 getConsumerName () const ; ... protected : ... struct BufferSlot { sp<GraphicBuffer> buffer; Region dirtyRegion; }; sp<IGraphicBufferProducer> mGraphicBufferProducer; BufferSlot mSlots[NUM_BUFFER_SLOTS]; uint32_t mReqWidth; uint32_t mReqHeight; PixelFormat mReqFormat; ... sp<GraphicBuffer> mLockedBuffer; sp<GraphicBuffer> mPostedBuffer; ... private : ... }
ISurfaceComposer/ISurfaceComposerClient
ISurfaceComposerClient/ISurfaceComposer
都继承了 IInterface
,它们俩分别代表 Surface
合成的客户端和服务端,具体在 SurfaceFlinger
服务进程中实现, libgui
中只对合成能力(函数)做了定义。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class ISurfaceComposerClient : public IInterface {public : DECLARE_META_INTERFACE(SurfaceComposerClient) ... virtual status_t createSurface (const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, const sp<IBinder>& parent, uint32_t windowType, uint32_t ownerUid, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) = 0 ; virtual status_t destroySurface (const sp<IBinder>& handle) = 0 ; virtual status_t clearLayerFrameStats (const sp<IBinder>& handle) const = 0 ; virtual status_t getLayerFrameStats (const sp<IBinder>& handle, FrameStats* outStats) const = 0 ;}; class ISurfaceComposer : public IInterface {public : DECLARE_META_INTERFACE(SurfaceComposer) ... virtual sp<ISurfaceComposerClient> createConnection () = 0 ; virtual sp<ISurfaceComposerClient> createScopedConnection ( const sp<IGraphicBufferProducer>& parent) = 0 ; virtual sp<IDisplayEventConnection> createDisplayEventConnection ( VsyncSource vsyncSource = eVsyncSourceApp) = 0 ; virtual sp<IBinder> createDisplay (const String8& displayName, bool secure) = 0 ; virtual void destroyDisplay (const sp<IBinder>& display) = 0 ; ... virtual status_t captureScreen (const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, Rotation rotation = eRotateNone) = 0 ;}
如下是 ISurfaceComposerClient
相关的类图结构:
先看 ComposerService
,它代表着 SurfaceFlinger
服务端,头文件定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class ComposerService : public Singleton<ComposerService>{ sp<ISurfaceComposer> mComposerService; sp<IBinder::DeathRecipient> mDeathObserver; Mutex mLock; ComposerService(); void connectLocked () ; void composerServiceDied () ; friend class Singleton < ComposerService>; public : static sp<ISurfaceComposer> getComposerService () ; };
查看 connectLocked, getComposerService
两个函数的实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 void ComposerService::connectLocked () { const String16 name ("SurfaceFlinger" ) ; while (getService(name, &mComposerService) != NO_ERROR) { usleep(250000 ); } assert(mComposerService != NULL ); ... } sp<ISurfaceComposer> ComposerService::getComposerService () { ComposerService& instance = ComposerService::getInstance(); Mutex::Autolock _l(instance.mLock); if (instance.mComposerService == NULL ) { ComposerService::getInstance().connectLocked(); assert(instance.mComposerService != NULL ); ALOGD("ComposerService reconnected" ); } return instance.mComposerService; }
connectLocked
连接过程就是等待 SurfaceFlinger
服务启动后并获取它; getComposerService
直接返回已经连接成功的实例 mComposerService
。
再看 SurfaceComposerClient
,可以将它理解为应用端,是 SurfaceFlinger
服务的客户端,它将建立和 SurfaceFlinger
服务的通信,头文件定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class SurfaceComposerClient : public RefBase{ public : sp<IBinder> connection () const ; ... sp<SurfaceControl> createSurface ( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags = 0 , SurfaceControl* parent = nullptr , uint32_t windowType = 0 , uint32_t ownerUid = 0 ) ; status_t destroySurface (const sp<IBinder>& id) ; static sp<IBinder> createDisplay (const String8& displayName, bool secure) ; static void destroyDisplay (const sp<IBinder>& display) ; ... private : virtual void onFirstRef () ; Composer& getComposer () ; ... sp<ISurfaceComposerClient> mClient; Composer& mComposer; wp<IGraphicBufferProducer> mParent; };
mClient
实际对应的是 SurfaceFlinger
进程中的 Client.cpp
,查看 SurfaceComposerClient::onFirstRef
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 void SurfaceComposerClient::onFirstRef () { sp<ISurfaceComposer> sm (ComposerService::getComposerService()) ; if (sm != 0 ) { auto rootProducer = mParent.promote(); sp<ISurfaceComposerClient> conn; conn = (rootProducer != nullptr ) ? sm->createScopedConnection(rootProducer) : sm->createConnection(); if (conn != 0 ) { mClient = conn; mStatus = NO_ERROR; } } } sp<ISurfaceComposerClient> SurfaceFlinger::createScopedConnection ( const sp<IGraphicBufferProducer>& gbp) { if (authenticateSurfaceTexture(gbp) == false ) { return nullptr ; } const auto & layer = (static_cast <MonitoredProducer*>( gbp.get()))->getLayer(); if (layer == nullptr ) { return nullptr ; } return initClient(new Client(this , layer)); }
SurfaceComposerClient
中有一个重要功能就是创建 Surface
,对应源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 sp<SurfaceControl> SurfaceComposerClient::createSurface ( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, SurfaceControl* parent, uint32_t windowType, uint32_t ownerUid) { sp<SurfaceControl> sur; if (mStatus == NO_ERROR) { sp<IBinder> handle; sp<IBinder> parentHandle; sp<IGraphicBufferProducer> gbp; if (parent != nullptr ) { parentHandle = parent->getHandle(); } status_t err = mClient->createSurface(name, w, h, format, flags, parentHandle, windowType, ownerUid, &handle, &gbp); ALOGE_IF(err, "SurfaceComposerClient::createSurface error.." ); if (err == NO_ERROR) { sur = new SurfaceControl(this , handle, gbp); } } return sur; }
最终会调用 SurfaceFlinger
中的 mClient
来创建 Layer, IGraphicBufferProducer
;而具体的 Surface
则由 SurfaceControl
来创建。
SurfaceControl
SurfaceControl
持有创建的 Surface
的强引用,头文件定义:
1 2 3 4 5 6 7 8 9 10 11 12 class SurfaceControl : public RefBase{ ... private : ... sp<SurfaceComposerClient> mClient; sp<IBinder> mHandle; sp<IGraphicBufferProducer> mGraphicBufferProducer; mutable sp<Surface> mSurfaceData; }; }
mHandle
指向 SurfaceFlinger
创建的 Layer
。而 SurfaceControl::createSurface
直接 new
了一个 Surface
对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 sp<Surface> SurfaceControl::generateSurfaceLocked () const { mSurfaceData = new Surface(mGraphicBufferProducer, false ); return mSurfaceData; } sp<Surface> SurfaceControl::createSurface () const { Mutex::Autolock _l(mLock); return generateSurfaceLocked(); }
IDisplayEventConnection
显示连接IDisplayEventConnection
继承了 IInterface
,客户端 APP
通过它向服务端 SurfaceFlinger
发送刷新请求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class IDisplayEventConnection : public IInterface {public : DECLARE_META_INTERFACE(DisplayEventConnection) virtual status_t stealReceiveChannel (gui::BitTube* outChannel) = 0 ; virtual status_t setVsyncRate (uint32_t count) = 0 ; virtual void requestNextVsync () = 0 ; };
IDisplayEventConnection
的类图结构
IDisplayEventConnection
的具体实现是在 SurfaceFlinger
进程中的 EventThread::Connection
;DisplayEventReceiver
持有该实例。
小结
libgui
中一共提供了 4 组 IInterface
接口: IGraphicBufferProducer/IProducerListener, IGraphicBufferConsumer/IConsumerListener, ISurfaceComposerClient/ISurfaceComposer, IDisplayEventConnection
IGraphicBufferProducer/IProducerListener
生产者模型
IGraphicBufferConsumer/IConsumerListener
消费者模型
ISurfaceComposerClient/ISurfaceComposer
提供创建 Surface
的功能,及相关管理
IDisplayEventConnection
提供了 APP
客户端请求服务端 SurfaceFlinger
刷新的接口
SurfaceFlinger
代码速查表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 surfaceflinger/ ├── Android.bp ├── Android.mk ├── Barrier.h ├── Client.cpp ├── Client.h ├── clz.h ├── Colorizer.h ├── DdmConnection.cpp ├── DdmConnection.h ├── DisplayDevice.cpp ├── DisplayDevice.h ├── DisplayHardware │ ├── ComposerHal.cpp │ ├── ComposerHal.h │ ├── DisplaySurface.h │ ├── FramebufferSurface.cpp │ ├── FramebufferSurface.h │ ├── HWC2.cpp │ ├── HWC2.h │ ├── HWComposerBufferCache.cpp │ ├── HWComposerBufferCache.h │ ├── HWComposer.cpp │ ├── HWComposer.h │ ├── HWComposer_hwc1.cpp │ ├── HWComposer_hwc1.h │ ├── PowerHAL.cpp │ ├── PowerHAL.h │ ├── VirtualDisplaySurface.cpp │ └── VirtualDisplaySurface.h ├── DisplayUtils.cpp ├── DisplayUtils.h ├── DispSync.cpp ├── DispSync.h ├── Effects │ ├── Daltonizer.cpp │ └── Daltonizer.h ├── EventControlThread.cpp ├── EventControlThread.h ├── EventLog │ ├── EventLog.cpp │ ├── EventLog.h │ └── EventLogTags.logtags ├── EventThread.cpp ├── EventThread.h ├── ExSurfaceFlinger │ ├── ExLayer.cpp │ ├── ExLayer.h │ ├── ExSurfaceFlinger.cpp │ ├── ExSurfaceFlinger.h │ ├── ExVirtualDisplaySurface.cpp │ └── ExVirtualDisplaySurface.h ├── FrameTracker.cpp ├── FrameTracker.h ├── GpuService.cpp ├── GpuService.h ├── Layer.cpp ├── LayerDim.cpp ├── LayerDim.h ├── Layer.h ├── LayerRejecter.cpp ├── LayerRejecter.h ├── LayerVector.cpp ├── LayerVector.h ├── main_surfaceflinger.cpp ├── MessageQueue.cpp ├── MessageQueue.h ├── MODULE_LICENSE_APACHE2 ├── MonitoredProducer.cpp ├── MonitoredProducer.h ├── RenderEngine │ ├── Description.cpp │ ├── Description.h │ ├── GLES20RenderEngine.cpp │ ├── GLES20RenderEngine.h │ ├── GLExtensions.cpp │ ├── GLExtensions.h │ ├── Mesh.cpp │ ├── Mesh.h │ ├── ProgramCache.cpp │ ├── ProgramCache.h │ ├── Program.cpp │ ├── Program.h │ ├── RenderEngine.cpp │ ├── RenderEngine.h │ ├── Texture.cpp │ └── Texture.h ├── StartPropertySetThread.cpp ├── StartPropertySetThread.h ├── SurfaceFlingerConsumer.cpp ├── SurfaceFlingerConsumer.h ├── SurfaceFlinger.cpp ├── SurfaceFlinger.h ├── SurfaceFlinger_hwc1.cpp ├── surfaceflinger.rc ├── SurfaceInterceptor.cpp ├── SurfaceInterceptor.h ├── Transform.cpp └── Transform.h 9 directories, 117 files
surfaceflinger
进程SurfaceFlinger
是以独立进程运行的,进程名为 surfaceflinger
,对应的 rc
文件如下:
1 2 3 4 5 6 7 8 9 10 // surfaceflinger.rc service surfaceflinger /system/bin/surfaceflinger class core animation user system group graphics drmrpc readproc onrestart restart zygote writepid /dev/stune/foreground/tasks socket pdx/system/vr/display/client stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0 socket pdx/system/vr/display/manager stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0 socket pdx/system/vr/display/vsync stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0
surfaceflinger
服务属于核心类 core
,当 surfaceflinger
重启时会触发 zygote
的重启。接下来看进程 main
方法对应文件为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 // main_surfaceflinger.cpp int main(int, char**) { // 启动 IAllocator, DisplayService 两个服务 startHidlServices(); signal(SIGPIPE, SIG_IGN); ProcessState::self()->setThreadPoolMaxThreadCount(4); sp<ProcessState> ps(ProcessState::self()); ps->startThreadPool(); // 1. new SurfaceFlinger 实例 sp<SurfaceFlinger> flinger = DisplayUtils::getInstance()->getSFInstance(); setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY); set_sched_policy(0, SP_FOREGROUND); if (cpusets_enabled()) set_cpuset_policy(0, SP_SYSTEM); // 2. SurfaceFlinger 初始化 flinger->init(); // 3. 发布 SurfaceFlinger, GpuService 两个服务 // publish surface flinger sp<IServiceManager> sm(defaultServiceManager()); sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false); // publish GpuService sp<GpuService> gpuservice = new GpuService(); sm->addService(String16(GpuService::SERVICE_NAME),gpuservice,false); struct sched_param param = {0}; param.sched_priority = 2; if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) { ALOGE("Couldn't set SCHED_FIFO"); } // run surface flinger in this thread // 4. SurfaceFlinger 无限循环等待事件 flinger->run(); return 0; }
surfaceflinger
进程的 main
函数中主要做了 4 件事:
通过 DisplayUtils
创建 SurfaceFlinger
对象
SurfaceFlinger
对象调用 init
方法,实现初始化
SurfaceFlinger
向系统注册 Binder
服务
SurfaceFlinger
对象调用 run
方法,该方法是一个 do-while
无限循环
初始化流程 SurfaceFlinger 初始化流程,查看大图
DisplayDevice
显示设备1 2 3 4 5 6 7 8 9 10 11 12 13 14 class DisplayDevice : public LightRefBase<DisplayDevice>{ public : ... enum DisplayType { DISPLAY_ID_INVALID = -1 , DISPLAY_PRIMARY = HWC_DISPLAY_PRIMARY, DISPLAY_EXTERNAL = HWC_DISPLAY_EXTERNAL, DISPLAY_VIRTUAL = HWC_DISPLAY_VIRTUAL, NUM_BUILTIN_DISPLAY_TYPES = HWC_NUM_PHYSICAL_DISPLAY_TYPES, }; ... }
显示设备有三种类型:主显、外显、虚显;每添加一个显示屏,都会创建一个 DisplayDevice
。
Layer
层Layer
是 SurfaceFlinger
进行合成的基本操作单元。Layer
在应用请求创建 Surface
的时候在 SurfaceFlinger
内部创建,因此一个 Surface
对应一个 Layer
。每个 Layer
包含常见属性:
Z order
Alpha value from 0 to 255
visibleRegion
crop region
transformation: rotate 0, 90, 180, 270: flip H, V: scale
当多个 Layer
进行合成的时候,并不是整个 Layer
的空间都会被完全显示,根据这个 Layer
最终的显示效果,一个 Layer
可以被划分成很多的 Region
, 在 SurfaceFlinger
中定义了以下几种类型:
TransparantRegion
:完全透明的区域,在它之下的区域将被显示出来
OpaqueRegion
:完全不透明的区域,是否显示取决于它上面是否有遮挡或是否透明
VisibleRegion
:可见区域,包括完全不透明无遮挡区域或半透明区域;即 visibleRegion = Region - above OpaqueRegion.
CoveredRegion
:被遮挡区域,在它之上,有不透明或半透明区域
DirtyRegion
:可见部分改变区域,包括新的被遮挡区域,和新的露出区域
头文件定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class Layer : public SurfaceFlingerConsumer::ContentsChangedListener {public : ... Region visibleRegion; Region coveredRegion; Region visibleNonTransparentRegion; Region surfaceDamageRegion; int32_t sequence; ... private : ... sp<SurfaceFlingerConsumer> mSurfaceFlingerConsumer; sp<IGraphicBufferProducer> mProducer; uint32_t mTextureName; bool mPremultipliedAlpha; String8 mName; String8 mTransactionName; PixelFormat mFormat; ... FenceTimeline mAcquireTimeline; FenceTimeline mReleaseTimeline; ... mutable Mesh mMesh; mutable Texture mTexture; Vector<BufferItem> mQueueItems; LayerVector mCurrentChildren; LayerVector mDrawingChildren; wp<Layer> mCurrentParent; wp<Layer> mDrawingParent; }
SurfaceFlinger
接收所有 Surface
作为输入,根据 Z-Order
, 透明度,大小,位置等参数,计算出每个 Surface
在最终合成图像中的位置,然后交由 HWComposer, OpenGL
生成最终的显示 Buffer
, 然后显示到特定的显示设备上。Layer
的合成分为两种,离线合成和在线合成:
离线合成 先将所有图层画到一个最终层 FrameBuffer
上,再将 FrameBuffer
送到 LCD
显示。由于合成 FrameBuffer
与送 LCD
显示一般是异步的(线下生成 FrameBuffer
,需要时线上的 LCD
去取),因此叫离线合成。
在线合成 不使用 FrameBuffer
,在 LCD
需要显示某一行的像素时,用显示控制器将所有图层与该行相关的数据取出,合成一行像素送过去。只有一个图层时,又叫 Overlay
技术。 由于省去合成 FrameBuffer
时读图层,写 FrameBuffer
的步骤,大幅降低了内存传输量,减少了功耗,但这个需要硬件支持。
Surface
创建流程图由客户端 SurfaceComposerClient
发起创建流程,然后由服务端 SurfaceFlinger
创建对应的 Layer
,而 Layer
在被引用时会创建生产者消费者模型的 BufferQueue
,然后再由客户端将拿到的结果传入 SurfaceControl
,最后直接实例化一个 Surface
。
创建生产者消费者模型 BufferQueue
的关键代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 void Layer::onFirstRef () { sp<IGraphicBufferProducer> producer; sp<IGraphicBufferConsumer> consumer; BufferQueue::createBufferQueue(&producer, &consumer, true ); mProducer = new MonitoredProducer(producer, mFlinger, this ); mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName, this ); mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0 )); mSurfaceFlingerConsumer->setContentsChangedListener(this ); mSurfaceFlingerConsumer->setName(mName); if (mFlinger->isLayerTripleBufferingDisabled()) { mProducer->setMaxDequeuedBufferCount(2 ); } const sp<const DisplayDevice> hw (mFlinger->getDefaultDisplayDevice()) ; updateTransformHint(hw); }
创建 Surface 流程,查看大图
VSYNC
垂直刷新Android
中有 2 种 VSync
信号:屏幕产生的硬件 VSync
和由 SurfaceFlinger
将其转成的软件 Vsync
信号;软件 Vsync
后者经由 Binder
传递给 Choreographer
。Vsync
信号可将某些事件同步到显示设备的刷新周期。应用总是在 VSYNC
边界上开始绘制,而 SurfaceFlinger
总是在 VSYNC
边界上进行合成。这样可以消除卡顿,并提升图形的视觉表现。 HWComposer
对象创建过程,会注册一些回调方法;当硬件产生 VSYNC
信号时,则会回调 HWC2::ComposerCallbackBridge::onVsync
方法,然后逐级回调,下图是整个回调流程图:
硬件 Vsync
信号发送过来,一路执行到 DispSyncThread.updateModel
方法中调用 mCond.signal
,唤醒 DispSyncThread
线程
DispSyncThread
线程中执行 EventThread::onVSyncEvent
中调用 mCondition.broadcast
唤醒 EventThread
线程
EventThread
线程中执行 DisplayEventReceiver::sendEvents
方法,会调用 BitTube::sendObjects
;在 MessageQueue::setEventThread
中,我们设置了 BitTube
事件的回调,当收到数据会触发 MQ.cb_eventReceiver
;根据 Handler
消息机制,进入 SurfaceFlinger
主线程
SurfaceFlinger
主线程进入到 MesageQueue的handleMessage
,最终调用 SurfaceFlinger::handleMessageRefresh
客户端通知 SurfaceFlinger
刷新 BufferQueueProducer::queueBuffer
函数中会调用 listener->onFrameAvailable
,而这最终会触发服务端的 Layer::onFrameAvailable
,从而通知 SurfaceFlinger
合成图像。我们先看 onFrameAvailable
接口的继承关系:
从 Surface
创建流程中贴出的 Layer::onFirstRef
代码中可以看到,在 Layer
中设置了 mSurfaceFlingerConsumer->setContentsChangedListener
监听事件,所以 BufferQueueProducer::queueBuffer
会触发 Layer::onFrameAvailable
事件,下面是完整的请求流程。 客户端在 BufferQueue
中生产完图像数据后,通知 SurfaceFlinger
刷新界面的流程图:
客户端通知 SurfaceFlinger 刷新,查看大图
后续
WMS
Layer
合成流程
结合 Camera
熟悉图形显示中 Buffer
相关流程
Choreographer
及掉帧分析
详述 SurfaceTexture, SurfaceView, GLSurfaceView
等区别
工具 dumpsys SurfaceFlinger
输出的 LOG
分析
screencap
命令及源码分析
Systrace
性能工具分析
参考文档