Android 框架提供了各种用于 2D 和 3D 图形渲染的 API,可与制造商的图形驱动程序实现代码交互,因此,务必更好地了解这些 API 的工作原理。本页介绍了在其上构建这些驱动程序的图形硬件抽象层 (HAL)。
HAL Graphic
Android框架提供了三种绘制图形的方式/Canvas/OpenGL ES 和Vulkan/
图 1/ Surface 如何被渲染
主要组件如下所述:
图像流生产者(Image Stream Producers):图像流生产方可以是生成图形缓冲区以供消耗的任何内容。例如 OpenGL ES、Canvas 2D 和 mediaserver 视频***器。
图像流消费者(Image Stream Consumers):图像流的最常见消耗方是 SurfaceFlinger,该系统服务会消耗当前可见的 Surface,并使用窗口管理器中提供的信息将它们合成到屏幕。SurfaceFlinger 是可以修改所显示部分内容的唯一服务。SurfaceFlinger 使用 OpenGL 和 Hardware Composer 来合成一组 Surface。其他 OpenGL ES 应用也可以消耗图像流,例如相机应用会消耗相机预览图像流。非 GL 应用也可以是使用方,例如 ImageReader 类。
硬件混合渲染器(Hardware Composer):显示子系统的硬件抽象实现。SurfaceFlinger 可以将某些合成工作委托给硬件混合渲染器,以分担 OpenGL 和 GPU 上的工作量。SurfaceFlinger 只是充当另一个 OpenGL ES 客户端。因此,在 SurfaceFlinger 将一个或两个缓冲区合成到第三个缓冲区中的过程中,它会使用 OpenGL ES。这会让合成的功耗比通过 GPU 执行所有计算时更低。硬件混合器HAL则进行另一半的工作,是所有 Android 图形渲染的中心点。其中之一是 VSYNC(另一个是支持即插即用 HDMI 的热插拔)。
Gralloc:需要使用图形内存分配器 (Gralloc) 来分配图像生产者请求的内存。
有关 Android 图形管道的描述,请参见下图:
图 2/ 流经 Android 的图形数据流 /Figure 2/ Graphic data flow through Android
左侧的对象是生成图形缓冲区的渲染器,如主屏幕、状态栏和系统界面。SurfaceFlinger 是合成器,而硬件混合渲染器是制作器。
The objects on the left are renderers producing graphics buffers/ such as the home screen/ status bar/ and system UI/ SurfaceFlinger is the compositor and Hardware Composer is the composer/
BufferQueues 是 Android 图形组件之间的粘合剂。它们是一对队列,可以调解缓冲区从生产方到消耗方的固定周期。一旦生产方移交其缓冲区,SurfaceFlinger 便会负责将所有内容合成到显示部分。
图 3/ BufferQueue 通信过程
BufferQueue 包含将图像流生产方与图像流消耗方结合在一起的逻辑。BufferQueue 包含将图像流生产方与图像流消耗方结合在一起的逻辑。BufferQueue 是将缓冲区池与队列相结合的数据结构,它使用 Binder IPC 在进程之间传递缓冲区。生产方接口,或者您传递给想要生成图形缓冲区的某个人的内容,即是 IGraphicBufferProducer。BufferQueue 通常用于渲染到 Surface,并且与 GL 消耗方及其他任务一起消耗内容。
BufferQueue 可以在三种不同的模式下运行:
类同步模式(Synchronous-like mode): 默认情况下,BufferQueue 在类同步模式下运行,在该模式下,从生产方进入的每个缓冲区都在消耗方那退出。在此模式下不会舍弃任何缓冲区。如果生产方速度太快,创建缓冲区的速度比消耗缓冲区的速度更快,它将阻塞并等待可用的缓冲区。
非阻塞模式(Non-blocking mode):BufferQueue 还可以在非阻塞模式下运行,在此类情况下,它会生成错误,而不是等待缓冲区。在此模式下也不会舍弃缓冲区。这有助于避免可能不了解图形框架的复杂依赖项的应用软件出现潜在死锁现象。
舍弃模式(Discard mode):最后,BufferQueue 可以配置为丢弃旧缓冲区,而不是生成错误或进行等待。例如,如果对纹理视图执行 GL 渲染并尽快绘制,则必须丢弃缓冲区。
为了执行这项工作的大部分环节,SurfaceFlinger 就像另一个 OpenGL ES 客户端一样工作。例如,当 SurfaceFlinger 正在积极地将一个缓冲区或两个缓冲区合成到第三个缓冲区中时,它使用的是 OpenGL ES。
Hardware Composer HAL 执行另一半工作。该 HAL 充当所有 Android 图形渲染的中心点。
Canvas(画布)实现是由Skia图形库实现。如果您要绘制一个矩形,可以调用 Canvas API,它会在缓冲区中适当地设置字节。为了确保两个客户端不会同时更新某个缓冲区,或者在该缓冲区正在被显示时写入该缓冲区,请锁定该缓冲区以进行访问。您可以使用以下命令处理画布锁:
lockCanvas():可锁定缓冲区以在 CPU 上渲染,并返回用于绘图的画布。
unlocklockCanvasAndPost():可解锁缓冲区并将其发送到合成器。
lockHardwareCanvas():可锁定缓冲区以在 GPU 上渲染,并返回用于绘图的画布。
注意:
【1】:当应用通过lockCanvas()锁定 Surface 时,所获得的画布一概不会获得硬件加速。
【2】:如果您曾调用过lockCanvas(),则无法使用 GLES 在 Surface 上绘图或从视频***器向其发送帧。lockCanvas()会将 CPU 渲染程序连接到 BufferQueue 的生产方,直到 Surface 被销毁时才会断开连接。与大多数生产方(如 GLES 或 Vulkan)不同,基于画布的 CPU 渲染程序无法在断开连接后重新连接到 Surface。
生产方首次从 BufferQueue 请求某个缓冲区时,该缓冲区将被分配并初始化为零。必须进行初始化,以避免意外地在进程之间共享数据。但是,如果您重复使用缓冲区,以前的内容仍会存在。如果您反复调用 lockCanvas() 和 unlockCanvasAndPost() 而不绘制任何内容,则生产方会在先前渲染的帧之间循环。
Surface 锁定/解锁代***保留对先前渲染的缓冲区的引用。如果在锁定 Surface 时指定了脏区域,那么它将从以前的缓冲区复制非脏像素。SurfaceFlinger 或 HWC 通常会处理缓冲区;但是由于我们只需从缓冲区中读取内容,因此无需等待独占访问权。
Android 使用OpenGL ES(GLES) API渲染图形。 为了创建GLES 上下文并未GLES渲染提供窗口系统,Android使用EGL调用用于渲染到屏幕上。
在使用GLES进行绘制之前,你需要创建GL上下文。在EGL中,这意味着要创建的一个EGL Context和一个EGL Surface。GLES 操作适用于当前上下文,该上下文通过线程局部存储访问,而不是作为参数进行传递。渲染代码应该在当前GLES线程(而不是界面线程)上执行。
EGLSurface 可以是由 EGL 分配的离屏缓冲区(称为“pbuffer”),也可以是由操作系统分配的窗口。
调用eglCreateWindowSurface()函数可创建 EGL 窗口 Surface。eglCreateWindowSurface()将“窗口对象”作为参数,在 Android 上,该对象是 Surface。Surface 是 BufferQueue 的生产方端。消费方(SurfaceView、SurfaceTexture、TextureView 或 ImageReader)创建 Surface。当您调用eglCreateWindowSurface()时,EGL 将创建一个新的 EGLSurface 对象,并将其连接到窗口对象的 BufferQueue 的生产方接口。此后,渲染到该 EGLSurface 会导致一个缓冲区离开队列、进行渲染,然后排队等待消费方使用。
注意:虽然窗口通常会显示,但是在这种情况下,EGLSurface 窗口的输出可能不会出现在屏幕上。
EGL 不提供锁定/解锁调用。您需要发出绘制命令,然后调用eglSwapBuffers()来提交当前帧。方法名称来自传统的前后缓冲区交换,但实际实现可能有所不同。
一个 Surface 一次只能与一个 EGLSurface 关联(您只能将一个生产方连接到一个 BufferQueue),但是如果您销毁该 EGLSurface,它将与该 BufferQueue 断开连接,并允许其他内容连接到该 BufferQueue。
通过更改“当前”EGLSurface,指定线程可在多个 EGLSurface 之间进行切换。一个 EGLSurface 一次只能在一个线程上处于当前状态。
EGL 不是 Surface 的另一方面(如 SurfaceHolder)。EGLSurface 是一个相关但***的概念。您可以在没有 Surface 作为支持的 EGLSurface 上绘制,也可以在没有 EGL 的情况下使用 Surface。EGLSurface 只是为 GLES 提供一个绘制的地方。
如需了解 OpenGL ES 和 EGL 要求,请参阅 Android兼容性定义文档。
公开的 Surface 类以 Java 编程语言实现。C/C++ 中的同等项是 ANATIONWindow 类,由Android NDK半公开,可以使用ANativeWindow_fromSurface()调用从 Surface 获取 ANativeWindow。就像它的 Java 语言同等项一样,您可以对 ANativeWindow 进行锁定、以软件形式进行渲染,以及解锁并发布。基本的“原生窗口”类型是 BufferQueue 的生产方端。
如需从原生代码创建 EGL 窗口 Surface,可将 EGLNativeWindowType 的实例传递到eglCreateWindowSurface()。EGLNativeWindowType 是 ANativeWindow 的同义词,因此可以互换使用。
Android 支持Vulkan,这是一套适用于高性能 3D 图形的低开销、跨平台 API。与 OpenGL ES(GLES)一样,Vulkan也提供在应用中创建高品质实时图形的工具。
使用Vulkan的优势包括降低CPU开销以及支持SPIR-V二进制中间语言。
SOC厂商(例如GPU***供应商(IHV))可以编写适用于Android的Vulkan驱动程序。原始设备制造商(OEM)只需要为特定设备集成这些驱动程序即可。如需详细了解 Vulkan 驱动程序如何与系统进行交互、应如何安装特定于 GPU 的工具以及特定于 Android 的要求,请参阅实现 Vulkan。
应用开发者可以使用 Vulkan 来打造在 GPU 上执行命令的应用,大幅降低开销。与EGL和GLES相比,Vulkan 还可以更直接地映射到当前图形硬件中的功能,Vulkan 还可以更直接地映射到当前图形硬件中的功能。
如需了解 Vulkan 的常规信息,请参阅Vulkan 概览或查看资源列表。
对 Vulkan 的支持包含以下组件。
Vulkan 组件
Vulkan验证层 1. 文档收藏网仅提供《【Android】Graphics》全文中的部分公开内容,版权归原著者或相关公司所有。 2. 以上信息来源于互联网免费公开的渠道,若文章所含内容侵犯了您的版权或隐私,请通知我们立即删除。 3. 当前页面地址:https://doc.bogoing.com/doc/24e190ea11c8192c.html 复制内容请保留相关链接。 最近收录
热文排行
随机推荐
|