Android Display模块基本概念

adtxl
2023-03-01 / 0 评论 / 1,394 阅读 / 正在检测是否收录...

学习一些简单的display基本概念,方便与display的同事对线

0. 概述

imagefbb6a61f5f141c65.png

  • View:所有控件的基类
  • SurfaceView:普通view公用一个Surface, SurfaceView独自拥有一个。SurfaceView能在子线程更新,普通View不能。
  • GLSurfaceView:继承SurfaceView,同时封装GL接口,便于调用GL接口绘制自身。
  • ViewRootImpl:所有View的根节点,WindowManager通过它向各个View分发事件。
  • WindowManagerService:负责View布局和次序管理。
  • SurfaceSession:Java层Surface和底层SurfaceFlinger通信的入口。
  • Skia:软件绘制库,默认不走。
  • RenderThread:控件的硬件绘制线程。
  • Surface & ANativeWindow:Native 层窗口概念,通过它传入要显示的Buffer。
  • BufferQueueproducer:Surface的成员,负责Buffer分配和传递至BufferQueueCore。
  • BufferQueueCore:Buffer管理和传递至SurfaceFlinger。
  • BufferQueueConsumer:SurfaceFlinger消耗完Buffer后,通过它告知BufferQueueCore。
  • Vsync:显示器的刷新信号。
  • SurfaceFlinger:接收所有的Surface传来的Buffer,在Vsync到来时合成和显示。
  • EventThreadConnection:接受Vsync信号,传递给SurfaceFlinger和Java层ViewRootImpl.
  • BufferQueueLayer:一个Surface在SurfaceFlinger对应的一个,用于保存Surface信息。
  • CompositionEngine:用于合成BufferQueueLayer中的数据。
  • Composer:基于HWC合成图层。
  • Fence:Buffer同步的一套方案,包括库和驱动
  • GLESRenderEngine:基于GPU合成图层
  • OpenGLES:基于GPU绘制的API库。Vulkan也是绘制的API库,Vulkan支持多线程,使用更加灵活,难度更大。
  • EGL:基于GPU绘制后显示的库,对接平台的显示系统,对于Android,对接SurfaceFlinger。
  • Allocator:Display的Buffer分配框架。
  • Gralloc: Display的Buffer分配器,厂商Gralloc库接入Allocator 。
  • Ion:Linux分析内存的一套框架,包括库和驱动。Gralloc通常基于Ion分配。
  • HWCHal:Composer的Hal框架,厂商Composer库接入次框架。
  • HWComposer :厂商Composer库。
  • FrameBuffer:一套简单的驱动框架,不支持多层合成、Vsync 、 DMA-BUF 、 fence等。
  • DRM:Direct Render Manager,一套功能强大的显示框架,克服FrameBuffer缺陷。
  • ADF:Atomic Display Framework,Google推出的一个Display驱动框架。
  • Overlay:图层合成器的驱动,不用厂商驱动不同,此处仅做代指。
  • 3D-KM:GPU驱动的代称。
  • MEMC:运动补偿模块。
  • HWC:图层合成模块。
  • PQ:图像质量模块,可以做 De-Interlace ,Noise Reduction,HDR & EDR & WDR,调节色温等。
  • DPU:显示处理模块,包含MEMC和PQ以及HWC等子模块。
  • GPU:图像处理模块。

1. 显示框架

为使得显示流程能兼容更多的场景,同时屏蔽不同厂商硬件的差异,操作系统通常都会集成一套显示框架。显示框架通常和图形库,内存分配,图层合成,显示,同步模块等相关联.

imagef8cdf9f58b1a9c33.png

早期很多设备底层使用的都是fb显示框架,整个Android显示系统框架如下图所示(比较老的设计了):

imagebc99ec3669b61497.png

  1. Linux内核提供了统一的framebuffer显示驱动,设备节点/dev/graphics/fb*或者/dev/fb*,以fb0表示第一个显示屏,当前实现中只用到了一个显示屏。
  2. Android的HAL层提供了Gralloc,分为fb和gralloc两个设备。设备fb负责打开内核中的framebuffer以及提供post、setSwapInterval等操作,设备gralloc则负责管理帧缓冲区的分配和释放。上层只能通过Gralloc访问帧缓冲区,这样一来就实现了有序的封装保护。
  3. 由于OpenGL ES是一个通用的函数库,在不同的平台系统上需要被“本地化”——即把它与具体平台上的窗口系统建立起关联,这样才能保证它正常工作。从FramebufferNativeWindow就是将OpenGL ES在Android平台上本地化窗口。
  4. OpenGL或者OpenGL ES 更多的只是一个接口协议,实现上既可以采用软件,也能依托于硬件。EGL通过读取egl.cfg配置文件,根据用户的设定来动态加载libagl(软件实现)或者libhgl(硬件实现)。然后上层才可以正常使用各种glXXX接口。
  5. SurfaceFlinger中持有一个GraphicPlane成员变量mGraphicPlanes来描述“显示屏”;GraphicPlane类中又包含了一个DisplayHardware对象实例(mHw)。DisplayHardware在初始化时还将调用eglInitialize、eglCreateWindowSurface等接口,并利用EGL完成对OpenGLES环境的搭建。

另一篇博客的介绍:

image.png

一些概念:

  1. GPU: (Graphic Process Unit)进行图像的混合渲染
  2. FB : (Frame Buffer)帧缓冲,LCD显示的内容就对应一个帧缓冲。不但显示使用FB,Camera视频输入也使用了FB。
  3. DC : (Display Controller)用于将FB中的数据搬移到LCD屏中
  4. OverLay: 每个硬件图层称为一个Overlay图层。
  5. HWC: (HardWare Composer)用于将OverlayLay图层混合后放到FB中。
  6. 不同的Soc上显示framebuffer的原理是一样的。
  7. 多任务系统的显示,必须有一个显示管理者,这个管理者就是SurfaceFlinger,它的作用:
    (1) 给App提供buffer:通过gralloc向ashmem(匿名内存)申请内存,得到一个fd,通过binder将fd传给某个App,App得到fd'后进行mmap(fd'),也可能是通过ion分配。
    (2) App1 App2 App3 把各自的界面发给SF,它根据Zorder,大小进行合成显示,显示。做两个事情:
    ① 根据各个界面的Zorder值(由WMS决定)决定前后顺序。
    ② 把这些排序后的buffer传给HardWare Controller.
    (3) 当HWC不能处理(没有HWC或支持的层数不够)时,使用GL(Graphic Library)处理。
  8. 上图中的EGL就是libEGL.so,它的作用是加载硬件GL库或软件GL库。
  9. Anroid上考虑所有硬件资源的情况:有的硬件上没有HWC,有些层数超过了HWC支持的层数,这时软件GL来实现。此时又区分是否有GPU,若有就通过GL来操作GPU,若连GPU也没有,那么只能使用纯软件来实现了。
  10. SurfaceFlinger可以使用EGL接口,App也可以使用EGL接口,App使用EGL接口来话一些图形将非常的高效。

1.2 DRM图形显示框架

以往我们在Linux上为显示设备开发驱动时,通常使用的是FrameBuffer的驱动框架, 在FrameBuffer驱动框架下,我们能够快速开发出可供简单使用的显示驱动。 但是随着芯片显示外设的性能逐渐增强及GPU的引入,FrameBuffer框架看起来似乎就有些落伍了, 最直接的体现,就是在传统的框架下,对于许多芯片显示外设的新特性如: 显示覆盖(菜单层级)、GPU加速、硬件光标等功能并不能得到很好得支持, 并且FrameBuffer框架将底层的显存通过用户空间/dev/fb接口,暴露给了用户空间, 这很容易导致不同的应用程序在操作显存时,产生访问冲突,而且这种方式看起来似乎不是那么安全。

在这背景下,就需要一个现代的图形显示框架来解决这些问题,那么DRM(Direct Rendering Manager,直接图形管理器)诞生。

DRM图形显示框架是Linux内核的一个子系统,负责与现代显卡的GPU进行交互。DRM提供了一个API,用户空间的程序可以使用它来向GPU发送命令和数据,并执行诸如配置显示模式设置等操作。DRM还支持内核模式设置(KMS),这是一种将显示模式设置从用户空间移动到内核空间的机制。DRM/KMS框架可以管理显示,图形和合成子系统,并利用相关硬件的特性,配置和加速。

1.2.1 框架简述

那么DRM图形显示框架是怎么解决FrameBuffer框架遇到的困境呢? DRM将现代显示领域中会涉及的一些操作进行分层并使这些模块独立, 如果上层应用想操作显存、显示效果亦或是GPU,都必须在一些框架的约束下进行,我们可以来了解一下。

我们可以从用户空间、内核空间的两个角度去了解DRM框架:

用户空间(libdrm driver):

  • Libdrm(DRM框架在用户空间的Lib)

内核空间(DRM driver):

  • KMS(Kernel Mode Setting,内核显示模式设置)
  • GEM(Graphic Execution Manager,图形执行管理器)

image.png

1.2.1.1 Libdrm

DRM框架在用户空间提供的Lib,用户或应用程序在用户空间调用libdrm提供的库函数, 即可访问到显示的资源,并对显示资源进行管理和使用。

这样通过libdrm对显示资源进行统一访问,libdrm将命令传递到内核最终由DRM驱动接管各应用的请求并处理,可以有效避免访问冲突。

1.2.1.2 KMS(Kernel Mode Setting)

KMS属于DRM框架下的一个大模块,主要负责两个功能:显示参数及显示控制。 这两个基本功能可以说是显示驱动必须具备的能力,在DRM框架下, 为了将这两部分适配得符合现代显示设备逻辑,又分出了几部分子模块配合框架。

Kernel Mode Setting,所谓Mode setting,其实说白了就两件事:更新画面和设置显示参数。
更新画面:显示buffer的切换,多图层的合成方式,以及每个图层的显示位置。
设置显示参数:包括分辨率、刷新率、电源状态(休眠唤醒)等。

  1. Planes

基本的显示控制单位,每个图像拥有一个Planes,Planes的属性控制着图像的显示区域、图像翻转、色彩混合方式等, 最终图像经过Planes并通过CRTC组件,得到多个图像的混合显示或单独显示的等等功能。

  1. CRTC

CRTC的工作,就是负责把要显示图像,转化为底层硬件层面上的具体时序要求,还负责着帧切换、电源控制、色彩调整等等。

  1. Encoder

Encoder的工作则是负责电源管理、视频输出格式封装(比如要将视频输出到HDMI接口、MIPI接口等)。

  1. Connector

Connector连接器负责硬件设备的接入、屏参获取等。

上述的这些组件,最终完成了一个完整的DRM显示控制过程,如下图所示:

image7768bd5f5c65349c.png

参考资料Kernel Mode Setting (KMS)")

image6eace738998de9e3.png

1.2.1.3 GEM(generic DRM memory-management)

Graphic Execution Manager,主要负责显示buffer的分配和释放,也是GPU唯一用到DRM的地方。顾名思义,GEM负责对DRM使用的内存(如显存)进行管理。

GEM框架提供的功能包括:

  • 内存分配和释放
  • 命令执行
  • 执行命令时的管理

参考资料 The Graphics Execution Manager (GEM)

基本元素总结大致如下:

image.png

1.3 驱动简述

我们通过简单讲解了DRM驱动的框架,简单地带领大家认识了DRM框架下对显示功能的实现方法。 实际的代码细节远比上述给大家介绍的内容复杂得多,给大家讲解框架组件功能只是起到一个抛砖引玉的作用, 如果对代码细节感兴趣的同学,可以在目录 drivers/gpu/drm 中,查看具体的驱动实现。

在实际的使用中,我这里将DRM的驱动实现分为了两个部分,主机驱动和设备驱动。主机驱动指的是片上的负责显示功能的外设驱动,如MP157上的LTDC外设、DSI外设的驱动, 这些一般由芯片厂商如ST、NXP等来负责实现,完成一个DRM-Host,主机驱动代码一般位于 drivers/gpu/drm/xxx/ 目录下,这里xxx代指芯片厂商如ST、NXP。

一般我们要做的,就是现实一个设备驱动,比如针对某款LCD显示屏, 将其参数(LCD Timing、Size…)、显示方式(DSI、HDMI…)等通过设备驱动,和主机驱动关联起来。

在内核的DRM驱动目录中,给出了许多设备驱动的示例,详见目录: drivers/gpu/drm/panel .

一个简单的DRM框架显示设备驱动例子可以参考 drivers/gpu/drm/panel/panel-simple.c .

参考:
1.Android显示系统(1)——显示框架——显示框架")
2.Android显示系统设计框架介绍
3.DRM图形显示框架

0

评论 (0)

取消