目录
SurfaceFlinger 和 WindowManager
从架构层面大致了解Android图形的概览,接下来先对一些组件进行更具体深入的理解
BufferQueue 和 Gralloc
Surface 和 SurfaceHolder
SurfaceView 和 GLSurfaceView
SurfaceFlinger 和 WindowManager
Bufferqueue :连接 图像流的生产者和消费者,几乎所有的图形数据缓冲区的内容都依赖于BufferQueue
Gralloc 内存分配器会进行缓冲区分配,并通过两个特定于供应商的 HIDL 接口来进行实现。
hardware/interfaces/graphics/allocator/
hardware/interfaces/graphics/mapper/
allocate() 函数采用预期的参数(宽度、高度、像素格式)以及一组用法标志。
主要是在生产者和消费者模型中,对BufferQueue的操作,伴随者缓冲区的流转。包括生产者对缓冲区的出列入列操作,消费者对缓冲区的获取和释放操作。
1)消费者创建并拥有BufferQueue的数据结构,并且可以存在与其他生产者不同的进程中
2)dequeueBuffer():生产者从 BufferQueue 请求一个可用的缓冲区,并指定缓冲区的宽度、高度、像素格式和用法标志
3)queueBuffer():生产者填充好缓冲区后,调用该函数将缓冲区返回到队列。
4)acquireBuffer():消费者获取缓冲区并使用缓冲区的内容
5)releaseBuffer():消费者用完缓冲区后,调用改函数将缓冲区返回到队列。
注意:同步框架可控制缓冲区在 Android 图形pipeline中移动的方式。
1)如果生产者请求具有不同大小的缓冲区,系统会释放旧的缓冲区,并根据需要分配新的缓冲区。
2)缓冲区始终通过句柄进行传递而不是通过复制的方式来进行传递。
1)如需了解图形缓冲区如何移动,请使用 Systrace。系统级的图形代码插入了埋点信息都经过充分检测的。
2)启用gfx、view 和 sched 标记。如:$ python systrace.py -o mynewtrace.html sched freq idle am wm gfx view binder_driver hal dalvik camera input res memory
Gralloc 分配器 HAL
头文件路径:hardware/libhardware/include/hardware/gralloc.h
通过用法标志执行缓冲区分配。
用法标志包括以下属性:
1)从软件 (CPU) 访问内存的频率
2)从硬件 (GPU) 访问内存的频率
3)是否将内存用作 OpenGL ES (GLES) 纹理
4)视频编码器是否会使用内存
Gralloc 用法标志 GRALLOC_USAGE_PROTECTED 允许仅通过受硬件保护的路径显示图形缓冲区。这些叠加平面是显示 DRM (Digital Rights Management数字版权管理)内容的唯一途径(SurfaceFlinger 或 OpenGL ES 驱动程序无法访问受 DRM 保护的缓冲区)。受 DRM 保护的视频只能在叠加平面上呈现。支持受保护内容的视频播放器必须使用 SurfaceView实现。在不受保护的硬件上运行的软件无法读取或写入缓冲区;受硬件保护的路径必须显示在硬件混合渲染器叠加层上(也就是说,如果硬件混合渲染器切换到 OpenGL ES 合成,受保护的视频将从屏幕中消失)。
概念
应用的图像要显示到屏幕上,需要先在Surface对象上进行渲染
SurfaceHolder接口就可以编辑和控制Surface的大小,格式等。
Java的类继承:
- public class Surface
- extends Object implements Parcelable
-
- java.lang.Object
- android.view.Surface
- public interface SurfaceHolder
-
- android.view.SurfaceHolder
大多数客户端使用 OpenGL ES 或 Vulkan 渲染到 Surface 上。但是,有些客户端使用 Canvas 渲染到 Surface 上
Canvas由Skia图形库提供。
带锁的Canvas:
1)lockCanvas() 可锁定缓冲区以在 CPU 上渲染,并返回用于绘图的画布。
2)unlockCanvasAndPost() 可解锁缓冲区并将其发送到合成器。
3)lockHardwareCanvas() 可锁定缓冲区以在 GPU 上渲染,并返回用于绘图的画布。
注意:当应用通过 lockCanvas() 锁定 Surface 时,所获得的画布一概不会获得硬件加速。
注意:如果您曾调用过 lockCanvas(),则无法使用 GLES 在 Surface 上绘图或从视频解码器向其发送帧。lockCanvas() 会将 CPU 渲染程序连接到 BufferQueue 的生产方,直到 Surface 被销毁时才会断开连接。与大多数生产方(如 GLES 或 Vulkan)不同,基于画布的 CPU 渲染程序无法在断开连接后重新连接到 Surface。
SurfaceHolder 是系统用于与应用共享 Surface 所有权的接口。
与 Surface 配合使用的一些客户端需要 SurfaceHolder,因为用于获取和设置 Surface 参数的 API 是通过 SurfaceHolder 实现的。
一个 SurfaceView 包含一个 SurfaceHolder。
与 View 交互的大多数组件都涉及到 SurfaceHolder。
一些其他 API(如 MediaCodec)将在 Surface 本身上运行。
- public class View
- extends Object implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource
-
- java.lang.Object
- ↳ android.view.View
- public class SurfaceView
- extends View
-
- java.lang.Object
- ↳ android.view.View
- ↳ android.view.SurfaceView
如需在创建或销毁 Surface 时收到回调,请使用 SurfaceHolder 接口。
默认情况下,新创建的 Surface 放置在应用界面 Surface 的后面。您可以替换默认的 Z 轴顺序,将新的 Surface 放在前面。
在需要渲染到单独的 Surface(例如,使用 Camera API 或 OpenGL ES 上下文进行渲染)时,使用 SurfaceView 进行渲染很有帮助。
使用 SurfaceView 进行渲染时,SurfaceFlinger 会直接将缓冲区合成到屏幕上。
使用 SurfaceView 进行渲染后,请使用界面线程与 activity 生命周期相协调,并根据需要调整 View 的大小或位置。然后,HWC会将应用界面与其他层混合在一起。
- public class TextureView
- extends View
-
- java.lang.Object
- ↳ android.view.View
- ↳ android.view.TextureView
SurfaceView 采用与其他 View 相同的参数,但 SurfaceView 内容在呈现时是透明的。
TextureView使用OpenGLES渲染
TextureView 具有更出色的 Alpha 版和旋转处理能力,但在视频上以分层方式合成界面元素时,SurfaceView 具有性能方面的优势。
当客户端使用 SurfaceView 呈现内容时,SurfaceView 会为客户端提供单独的合成层。如果设备支持,SurfaceFlinger 会将单独的层合成为硬件叠加层。
当客户端使用 TextureView 呈现内容时,界面工具包会使用 GPU 将 TextureView 的内容合成到视图层次结构中。
对内容进行的更新可能会导致其他 View 元素重绘,例如,在其他 View 被置于 TextureView 顶部时。View 呈现完成后,SurfaceFlinger 会合成应用界面层和所有其他层,以便每个可见像素合成两次。
注意:受 DRM 保护的视频只能在叠加平面上呈现。支持受保护内容的视频播放器必须使用 SurfaceView 实现。
Surfaceflinger接受缓冲区,对他们进行合成,然后发送到屏幕。
WindowManager为Surfaceflinger提供缓冲区和窗口Metadata,Surfaceflinger可以使用这些信息将Surface合成到屏幕
在收集可见层的所有缓冲区后,便会询问HWC如何进行合成。如果HWC将层合成类型标记为Client合成,则Surfaceflinger将合成这些层,然后Surfaceflinger会将输出缓冲区传递给HWC
WindowManager会控制window对象,他们是用于容纳view的对象容器。window对象始终由Surface对象提供支持。
WindowManager会监督生命周期,输入和聚焦事件,屏幕方向,转换,动画,位置,Z轴顺序以及窗口的许多方面。
WindowManager会将所有窗口的Metadata发送到Surfaceflinger
- public abstract class Window
- extends Object
-
- java.lang.Object
- ↳ android.view.Window