系列文章请扫关注公众号!
本文主要包括部分:
- 显示虚拟化场景
- DRM架构
2.1 DRM简介(Direct Rendering Manager)
2.2 高通SDM驱动
- Multiple-drm-cards方案
3.1 介绍
3.2 Qcom驱动框架解析
3.3 高通及MTK平台支持情况
3.4 方案的实现
- 显示虚拟化场景
对于Linux和Android来说,只要是多屏(>=2)显示的场景都可以显示虚拟化。只是大部分场景对显示稳定性没有要求,系统异常了就都不显示了。但对于容器相关方案,或要求显示隔离的场景,是需要进行显示虚拟化的。
比如目前比较火的新能源智能座舱系统,使用轻量级容器方案时,仪表和中控是共用一个kernel内核的。IVI中控系统一般是高度定制化的Android,Cluster仪表系统一般是Linux库环境或 Android Native环境。此时就要求IVI系统和Cluster系统的显示部分不能互相影响,需要对显示部分进行虚拟化。
一般的Android系统或Linux系统自带的SDK包是不支持虚拟化的,需要跟芯片厂商共同调试,实现kernel层的/dev/dri/card的虚拟化。
对于使用高通8155等重量级虚拟化Hypervisor的方案,底层也是对同一个显卡硬件进行了虚拟化,只是芯片厂做好了。
- DRM框架
2.1 DRM简介(Direct Rendering Manager)
传统linux显示设备驱动开发时,通常使用FB驱动架构,随着显卡性能升级:显示覆盖(菜单层级)、GPU加速、硬件光标,传统FB架构无法很好支持,此外,对于多应用的访问冲突也无法很好控制。在这样的背景下,DRM应用而生。
DRM(Direct Rendering Manager)即直接渲染管理器,是linux内核中负责与显卡交互的管理架构,用户空间很方便的利用DRM提供的API,实现3D渲染、视频解码和GPU计算等工作。
DRM为了解决多个程序对 显卡资源的协同使用问题而产生的。
图2.1 DRM图形显示框架总览
libdrm
对底层接口进行封装,向上层提供通用的API接口,主要是对各种IOCTL接口进行封装。
KMS
Kernel Mode Setting,所谓Mode setting,其实说白了就两件事:更新画面和设置显示参数。
更新画面:显示buffer的切换,多图层的合成方式,以及每个图层的显示位置。
设置显示参数:包括分辨率、刷新率、电源状态(休眠唤醒)等。
GEM
Graphic Execution Manager,主要负责显示buffer的分配和释放,也是GPU唯一用到DRM的地方。
基本元素
DRM框架涉及到的元素很多,大致如下:
KMS:CRTC,ENCODER,CONNECTOR,PLANE,FB,VBLANK,property
GEM:DUMB、PRIME、fence
元素 | 说明 |
CRTC | 对显示buffer进行扫描,并产生时序信号的硬件模块,通常指Display Controller |
ENCODER | 负责将CRTC输出的timing时序转换成外部设备所需要的信号的模块,如HDMI转换器或DSI Controller |
CONNECTOR | 连接物理显示设备的连接器,如HDMI、DisplayPort、DSI总线,通常和Encoder驱动绑定在一起 |
PLANE | 硬件图层,有的Display硬件支持多层合成显示,但所有的Display Controller至少要有1个plane |
FB | Framebuffer,单个图层的显示内容,唯一一个和硬件无关的基本元素 |
VBLANK | 软件和硬件的同步机制,RGB时序中的垂直消影区,软件通常使用硬件VSYNC来实现 |
property | 任何你想设置的参数,都可以做成property,是DRM驱动中最灵活、最方便的Mode setting机制 |
DUMB | 只支持连续物理内存,基于kernel中通用CMA API实现,多用于小分辨率简单场景 |
PRIME | 连续、非连续物理内存都支持,基于DMA-BUF机制,可以实现buffer共享,多用于大内存复杂场景 |
fence | buffer同步机制,基于内核dma_fence机制实现,用于防止显示内容出现异步问题 |
2.2 高通SDM驱动
高通的调用关系是通过SurfaceFlinger调用HardwareComposer,通过SDM Interfaces调用opensource code及Proprietary code。又进一步通过libdrm库跟/dev/dri/card节点交互。
详细关系调用图如下:
遵循Linux下一切皆文件的思想。从文件系统角度,drm对应/dev/dri/card0文件。HAL层可以通过打开该文件,从而进行一系列操作。
- Multiple-drm-cards方案
3.1 介绍
汽车产品有需要multiple displays的用例。但实际芯片的屏接口数量有限。SOC支持share display 的目的是通过单个接口连接多个虚拟显示器。例如,dsi接口可以虚拟化成dsi0和dsi1两个虚拟屏。Share display feature也可用于dynamic splash。
下图显示了virtual的一个虚拟化示例配置:
上图的显示器和接口连接如下:
n DSI3、DSI4 virtual displays 在接口DSI0.
n DSI5、DSI6 virtual displays 在接口 DSI1.
n DP1、DP2 virtual displays 在接口 DisplayPort.
上面的每个虚拟屏,配置成功后,其实使用的还是同一个/dev/dri/card0. 默认情况下Android系统会镜像primary屏的显示。
如果想让DP屏使用一个/dev/dri/card1,dsi1使用/dev/dri/card2,减少相互影响及耦合。需要从kernel层 drm框架出发实现出card的虚拟化。
Multiple-drm-cards虚拟化的前提是各显示屏已可以正常显示了,虽然他们显示的内容是一样的。
3.2 Qcom驱动框架解析
未虚拟化前qcom平台使用的是QC SDE Display Driver,
Card虚拟化就需要纯软件实现对Card的lease租赁功能,框架如下:
上述方案的优点:
- 降低上层开发难度,上层应用可以无感知,无须调整。
- 每个Display对应一个Card,操作各自的文件,解耦相互之间的关系。
3.3 高通及MTK平台支持情况
目前只有高通SA8*55和SA6*55支持,像消费级芯片 6125,6350,6490,8475等都不支持显示虚拟化。MTK平台目前了解到也是不支持的。
分析SA8155的kernel代码,Card的lease 方案是纯软件实现的,需要修改dtsi文件配置各Display的plane。其难点在于:每个平台的drm_connector和 plane都不一样,这一块是软件也无法代替的,需要跟芯片厂共同debug验证后确定,这里调试耗时非常长。
3.4 方案的实现
Card lease方案的实现,其实也就是梳理已支持平台的msm_lease_drv的probe流程,配置各card所需的资源。Card lease方案实现后可以在/dev/dri/目录下看到多个card。
由于每个芯片平台的drm connector和plane 都不同,且芯片厂也不提供这两个的对应关系,调试耗时巨长......
调试成功后的结果如下:
以8*55平台为例,说明下connector和plane的对应情况*********
=========================================================================
=================方案实现详情及修改patch见公众号或下方链接=====================
=========================================================================