Android/Linux 子系统Graphics图形栈入门普法介绍

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

    Android/Linux 子系统Graphics图形栈入门普法介绍



写在最前面

  由于工作原因最近在公司做了一个关于Android/Linux 子系统Graphics图形栈入门相关知识的培训介绍个人感觉对于想要了解入门这块的朋友还是有一定帮助的。由于博客不能直接放入ppt这里我就将相关的ppt转换成可以博客展示的发表出来希望能帮助到对这一块感兴趣的朋友




前言

  由于Linux(外加Android)图形子系统过于复杂且个人由于能力有限这里我也仅能对Linux图形子系统做一些简单的概述进而罗列出Linux显示子系统涉及的相关的软件技术做到给大家一个了解的程度
本文很多图片都是从网上搜集而来的(很多是从维基百科)。虽然编写文档最好用自己的语言表述尽量自己画图但是Linux(外加Android)图形子系统太复杂了而我的个人理解能力有限而网上的图画的实在太好所以我觉得再怎么努力也画不出更好的了因此本着为站在巨人肩膀的角度出发就直接copy了。

在这里插入图片描述




一.什么是Linux图形子系统?

图形子系统是Linux操作系统中比较复杂的子系统之一:

  • 对下它要管理形态各异的、性能各异的显示相关的器件
  • 对上它要向应用程序提供易用的、友好的、功能强大的图形用户界面GUI。因此它是Linux中少有的、和用户空间程序甚至是用户息息相关的一个子系统

在这里插入图片描述




二.常用Android/Linux图形子系统图形栈总览

在这里插入图片描述

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

在这里插入图片描述




三.Linux图形子系统图形栈概念介绍

从前面的常用Linux图形子系统图形栈总览相信各位也看到了图形栈的确实比较复杂所以接下来我们将先理清局部概念再整体框架深入的来分别介绍Linux图形子系统图形栈的一些概念(所以一口气想吃成个胖子就不太可能了)

在这里插入图片描述


3.1 什么是GUI

古老物种DOS系统早已经作古现在发扬广大的就是我们这里要说的GUILinux(Linux,Android)图形子系统的本质就是是提供图形化的人机交互human-computer interaction界面也即常说的GUIGraphical User Interface。而人机交互的本质是人脑通过人的输出设备动作、声音等控制终端的输入设备终端经过一系列的处理后经由终端的输出设备将结果输出人脑再通过人的输入设备接收电脑的输出最终实现“人脑<–>终端”之间的人机交互。如下的图片对上述过程做了很好的总结

在这里插入图片描述

在这里插入图片描述

通过上图以一个非常前卫的应用场景----虚拟现实VRVirtual Reality游戏说明了以图形化为主的人机交互过程

  • 人脑通过动作、声音对人脑而言是output控制终端的输入设备包括键盘、鼠标、操作杆、麦克风、游戏手柄包含加速度计、陀螺仪等传感器。

  • 终端通过输入设备接收人脑的指令这些指令经过kernel Input subsystem、Middleware Gesture/Speech recognition等软件的处理转换成应用程序Game可以识别的、有意义的信息。

  • 应用程序Game根据输入信息做出相应的反馈主要包括图像和声音。对VR游戏而言可能需要2D/3D rendering这可以借助openGL及其相应的用户空间driver实现。

  • 应用程序的反馈经由kernel的Video subsystem如DRM/KMS、audio subsystem如ALSA输出到终端的输出设备上包括显示设备2D/3D、扬声器/耳机3D Positional Audio、游戏手柄力的反馈等。

  • 输出到显示设备上时可能会经过图形加速模块Graphics accelerator。


3.2 什么是Windowing system窗口系统?

窗口系统是GUI的一种也是当前计算机设备、智能设备广泛使用的一种以WIMP (windows、icons、menus、pointer)的形式提供人机交互接口。Linux系统中有很多窗口系统的实现如Linux上的X Window System、Wayland和Android SurfaceFlinger等虽然形态各异但思路大致相同包含如下要点

  • 一般都使用client-server架构server称作display server或者windows server、compositor等等管理所有输入设备以及用于输出的显示设备。

  • 应用程序作为display server的一个client在自己窗口window中运行并根据窗口类型的不同决定绘制是由client端进行还是请求服务端进行

  • Client的送显示请求都会提交给display serverdisplay server响应并处理这些请求以一定的规则混合、叠加最终在有限的输出资源上屏幕显示多个应用程序的GUI()

  • Display server和自己的client之间通过某种类型的通信协议交互该通信协议通常称作display server protocol。

  • Display server protocol可以是基于网络的甚至是网络透明的network transparent如X Window System所使用的。也可以是其它类型的如Android SurfaceFlinger所使用的binder。

如下是Linux下两个常用的窗口系统

在这里插入图片描述


3.3 什么是窗口管理器 ?

前面讲过多种窗口系统但是只提供了实现GUI环境的基本框架其它的UI设计所需的button、menu、window title-bar styles等基本元素则是由第三方的应用程序提供。这些应用程序主要包括窗口管理器window manager、GUI工具集GUI widget toolkit和桌面环境desktop environment。
窗口管理器(Window Manager)用一句话来概括的话那就是它是一个可以控制窗口环境中窗口属性的软件。通常它的作用如下

  • 窗口管理器核心功能是移动窗口改变窗口大小图标化最小化窗口和改变窗口层叠顺序通俗说就是对窗口进行管理。
  • 一般来说窗口管理器会对应用程序窗口加上标题栏用以进行窗口的拖拽操作其中还有最小化最大化关闭按钮方便用户快捷的操作窗口。
  • 窗口管理器还会对窗口边框进行处理设计边框颜色和阴影效果来区分激活与非激活窗口。
  • 同时大部分窗口管理器还提供了一些快捷键绑定来实现窗口切换工作区切换显示桌面等功能

3.4 窗口管理器分类和常用的

根据窗口管理器绘制和更新窗口的方式窗口管理器可以分为以下四类

  • 平铺式Tiling window manager

    在这里插入图片描述

  • 堆叠式窗口管理器Stacking window manager

    在这里插入图片描述

  • 动态窗口管理器Dynamic window manager

    在这里插入图片描述

  • 复合窗口管理器Compositing window manager
    在这里插入图片描述


3.5 什么是GUI工具集 ?

GUI(GUI toolkits)工具集是Windowing system之上的进一步的封装。还是以X为例它通过xlib提供给应用程序的API仅仅可以绘制基本的图形单元点、线、面等等这些基本的图形单元要组合成复杂的应用程序还有很多很多细碎、繁杂的任务要做。因此一些特定的操作系统会在X的基础上封装出一些更为便利的GUI接口方便应用程序使用如GTK+、QT等等。

GTK+和QT是GUI toolkits属于软件库类似c语言的stdio.hwin32java里import的各种外部包可以任开发者调用应该是C/C++使用的库去创建一些图形界面里面的控件例如button下拉菜单窗口等。我记得JAVA里面也有类似AWT和Swing库。用这一套库开发出的图形空间将会有一套统一的风格和标准这就是不同系统安装的不同软件有的时候会有相同的样式因为他们可能使用了GTK或者QT的库。KDE默认使用Qt库开发Gnome默认使用GTK+库开发而这两套库又是基于X window server的需要遵守x11协议在xwindow server上运行作为client应用实现的基础类库。接下来就要说说KDE和Gnome以及其他基于GTK和Qt开发的x软件。


3.6 什么是桌面环境,常用的有那些 ?

桌面环境Desktop Environments是最近发展起来的桌面图形环境它的主要目标是为Linux/Unix操作系统提供一个更加完善的界面以及大量各类整合工具和应用程序。桌面环境是应用程序级别的封装通过提供一系列界面一致、操作方式一致的应用程序使系统以更为友好的方式向用户提供服务。Linux系统比较主流的桌面环境包括GNOME、KDEUnity(各种),Xfce等等,下面我们简单介绍下:

  • KDE 桌面系统
    KDE 是 K Desktop Environment 的缩写中文译为“K桌面环境”。KDE 是基于大名鼎鼎的 Qt 的最初于 1996 年作为开源项目公布并在 1998 年发布了第一个版本现在 KDE 几乎是排名第一的桌面环境了。
    在这里插入图片描述

  • GNOME桌面环境
    GNOME 即GNU网络对象模型环境 (The GNU Network Object Model Environment)GNU计划的一部分开放源码运动的一个重要组成部分。 是一种让使用者容易操作和设定电脑环境的工具。目标是基于自由软件为Unix或者类Unix操作系统构造一个功能完善、操作简单以及界面友好的桌面环境他是GNU计划的正式桌面。
    在这里插入图片描述

  • Unity桌面环境
    Unity 是由 Ubuntu 的母公司 Canonical 开发的一款外壳。之所以说它是外壳是因为 Unity 运行在 GNOME 桌面环境之上使用了所有 GNOME 的核心应用程序。
    在这里插入图片描述

  • Xfce桌面环境
    Xfce是一个轻量级的类Unix的桌面系统Xfce这个词的发音为X-f-c-e(即四个字母一个一个的读,Xfce是使用率仅次于KDE与Gnome的Linux桌面系统。
    在这里插入图片描述


3.7 窗口/窗口管理器/桌面环境是什么关系 ?

套用一句比较流行的话来说就是人生无常,大肠包小肠(开玩笑可以认为它们是从属关系)可以用下面的示意图来表示
在这里插入图片描述


3.8 窗口/窗口管理器/桌面环境是什么关系 ?

  • OpenGLOpen Graphics Library是为了方便应用程序的开发而屏蔽各种硬件平台的一个稳定的、跨平台的API它定义了渲染有关的行为和动作它不提供具体的实现这个由各个GPU芯片厂自己实现(注意OpenGL并不是唯一能实现相关功能的API接口譬如vulkan也是可以的)。

  • OpenGL ES(OpenGL for Embedded Systems)是免授权费的跨平台的功能完善的2D和3D图形应用程序接口API它针对多种嵌入式系统专门设计。它由精心定义的桌面OpenGL子集组成创造了软件与图形加速间灵活强大的底层交互接口。说白了它就是OpenGL的子集、可以应用于ES嵌入式设备上。

  • EGL 是 OpenGL ES 渲染 API 和本地窗口系统(native platform window system)之间的一个中间接口层它主要由系统制造商实现。EGL提供如下机制

  • 与设备的原生窗口系统通信

  • 查询绘图表面的可用类型和配置

  • 创建绘图表面

  • 在OpenGL ES 和其他图形渲染API之间同步渲染

  • 管理纹理贴图等渲染资源


3.9 OpenGL接口的分类和实现有那些

通过前面的介绍我们了解到OpenGL只是一个API规范但由于3D绘图的复杂性它也是相当的复杂的。不过归根结底它的目的有两个

  • 对上屏蔽硬件细节为应用程序提供相对稳定的、平台无关的3D图像处理API当然也可以是2D。
  • 对下指引硬件相关的驱动软件实现3D图像处理相关的功能。

通常我们见到的各种libGLXXX.so就是OpenGL的实现从分类上可以是各种不同类型的OpenGL实现如OpenGLfor PC场景、OpenGLESfor嵌入式场景、OpenVGfor Flash、SVG矢量图。

libGL的实现既可以是基于软件的(譬如谷歌的swiftshaderswrast)也可以是基于硬件的(譬如鼎鼎大名的Arm的mail和高通的Adreno系列但是它们都是非开源的)。其中Mesa 3D是OpenGL的一个开源本的实现支持3D硬件加速(关于它在后面会介绍)。

OpenGL的一个重要特性是独立于操作系统和窗口系统而存在的(这个也正常因为它就是一个API的规范谁用谁遵守规范就好)但是它的实现通常不能独立于操作系统和窗口存在。


3.10 OpenGL OpenGLES EGL之间的关系

在这里插入图片描述

我们举个栗子我们来思考一下画家绘画的过程首先要有一名懂得各种绘画技艺的画家然后他需要一张画布一些笔一些颜料一些辅助工具尺、模板、橡皮、调色板等等然后他在画布上绘制第一幅画完成之后展示给人们看在人们观赏第一幅画的时候他可以在第二张画布上绘制第二幅画绘制完成后收回第一幅画将第二幅画展现给人们看接着使用工具擦除第一幅画在同一张画布上绘制第三幅画周而复始人们便看到了一幅接一幅的画。

对比 OpenGL ES/EGL各要素的对应关系大体如下

  • 画家编程人员
  • 笔、颜料、辅助工具OpenGL ES API
  • 画布EGL 创建的 Surface

3.11 什么是GLX它和EGL的关系是什么

在Linux的图形栈中也许我们会听到一个名词GLX这里也简单介绍下它GLX是OpenGL Extension to the X Window System的缩写。它作为x的扩展是x协议和X server的一部分已经包含在X server的代码中了。GLX提供了X window system使用的OpenGL接口允许通过x调用OpenGL库。OpenGL 在使用时需要与一个实际的窗口系统关联起来。在不同平台上有不同的机制以关联窗口系统在Windows上是WGL在Linux上是GLX在 Apple OS上是AGL等。

如果要问EGL和GLX有什么关系那么EGL则是OpenGL ES在嵌入式平台上WGL,GLX,AGL的等价物。EGL假设OS会提供窗口系统但EGL与平台无关并不局限于任何特定的窗口系统所有用到本地窗口系统的地方都用屏蔽指针来处理。我觉得这就是它易于移植的关键。

在这里插入图片描述




四.普法Meas

Mesa在Android/Linux graphics图形栈特别是Linux中是绕不开的一个技术这里我们从它是什么它的作用以及它的架构出发来简单介绍介绍


4.1 什么是Mesa

在前面介绍OpenGl的实现的时候简单介绍了下Mesa是OpenGL的一个开源实现。这里再隆重介绍下它Mesa也称为Mesa3D和Mesa 3D图形库是OpenGLVulkan和其他图形API规范的开源软件实现。它最重要的用户是两个图形驱动程序这些图形驱动程序主要由Intel和AMD为各自的硬件开发和资助。注意这里没有提到Nvidia因为它没有开放GPU的相关驱动所以有了下面的“英伟达是我们遇到的硬件厂商中最麻烦的一个”

在这里插入图片描述

在这里插入图片描述

在经过Linus Torvalds的一顿怒骂之后英伟达破天荒开源GPU内核驱动然后被戏称为”这是近十年来开源操作系统硬件支持方面发生的最大事件之一”。我们就当做看戏的观众吃吃瓜就OK了


4.2 Mesa的作用 ?

我们知道了Mesa是OpenGL的实现它提供了如下的两个基本作用:
- 对接各种GPU硬件将应用层对GL API的调用转换到对硬件GPU的调用上

  • 各种 GL API 的纯软实现当没有可用的硬件时它可以提供传软件的 GL API 的实现Mesa还包含称为swrast的软件渲染实现当不存在图形硬件加速器时该渲染器允许着色器在CPU上运行作为后备。 Gallium软件光栅化器称为软件管道(softpipe)或者在构建时支持LLVM llvmpipe后者在运行时生成CPU代码(我们的E2000就是使用此方案)。

我它可以用于LinuxWindowsMac等系统平台。在Windows上运行时它提供OpenGL API over DirectX的转换。它实现了 OpenGL,Vulkan以及其他的图形API。Mesa把这些API调用转换到相应驱动程序其实并不是真正的驱动程序是用户态的DRI驱动程序调用上。并且支持如下的API

  • OpenGL OpenGLES
  • EGL
  • OpenCL
  • Vulkan OpenVG

4.3 Mesa架构 ?

Gallium3D 是Mesa提出的用于简化GPU驱动开发的框架。下面是Mesa结构图展示了mesa如何通过libGL库跟内核打交道以及展示了新旧两种用户态设备驱动程序的实现方式。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

至于Mesa的源码框架这里就不分析了这也不是该PPT的重点该PPT的作用主要是为了普及一些Linux下graphic一些技术栈(其实主要是本人能力有限)




五.什么是渲染以及硬件渲染加速 ?

这里我们用通俗的语言来说就是:根据实际情况将2D的点线面和3D图形以一定手段绘制出来以一定的格式保存在buffer中。该过程就是常说的“Rendering”。UI 组件在绘制到屏幕之前都需要经过 Rasterization栅格化操作而栅格化又是一个非常耗时的操作。Rasterization 栅格化是绘制那些 Button、Shape、Path、String、Bitmap 等显示组件最基础的操作。栅格化将这些 UI 组件拆分到显示器的不同像素上进行显示。这是一个非常耗时的操作GPU 的引入就是为了加快栅格化。
通常情况下2D渲染一般是由CPU完成也可以由专门的硬件模块完成。3D渲染也可以由CPU完成但面临性能问题因此大多数平台都会使用单独硬件模块GPU或者显卡负责3D渲染。这种通过特定功能的硬件模块来处理那些CPU不擅长的事务的方法称作硬件加速Hardware acceleration相应的硬件模块就是硬件加速模块。而这种硬件加速模块的功能就是我们所说的硬件渲染加速了

在这里插入图片描述

在这里插入图片描述




六.为什么GPU能渲染加速而CPU不行 ?

在回答这个问题前我们非常有必要再来简单描述下CPU和GPU:

  • CPUCentral Processing Unit中央处理器是计算机设备核心器件用于执行程序代码软件开发者对此都很熟悉
  • GPUGraphics Processing Unit图形处理器主要用于处理图形运算通常所说“显卡”的核心部件就是GPU。
    下面是CPU和GPU的结构对比图(从出生就决定了不同的命运):

在这里插入图片描述

  • 从结构图可以看出CPU的控制器较为复杂而ALU数量较少。因此CPU擅长各种复杂的逻辑运算但不擅长数学尤其是浮点运算
  • CPU是串行结构。以计算100个数字为例对于CPU的一个核每次只能计算两个数的和结果逐步累加
  • 和CPU不同的是GPU就是为实现大量数学运算设计的。从结构图中可以看到GPU的控制器比较简单但包含了大量ALU。GPU中的ALU使用了并行设计且具有较多浮点运算单元
  • 硬件加速的主要原理就是通过底层软件代码将CPU不擅长的图形计算转换成GPU专用指令由GPU完成

假设我们有如下图像处理任务给每个像素值加1。GPU并行计算的方式简单粗暴在资源允许的情况下可以为每个像素开一个GPU线程由其进行加1操作。数学运算量越大这种并行方式性能优势越明显(就是这么简单粗暴多生孩子好干活)。

在这里插入图片描述




七.什么是图层合成 ?

图层合成指以一定形式组合各个图层的绘制内容然后送往显示设备显示的过程(注意是送往显示的过程而不是送显)。从原理上可分为在线合成(硬件合成)与离线合成(GPU或者CPU模拟合成)两种方式。

在这里插入图片描述

在这里插入图片描述

  • 离线合成(GPU合成或者CPU模拟)
    先将所有图层画到一个最终层(FrameBuffer)上再将FrameBuffer送到显示设备显示。由于合成FrameBuffer与送显示设备显示一般是异步的线下生成FrameBuffer需要时线上的显示设备去取因此叫离线合成(这种合成方式在Android中被叫做Client合成)。
    在这里插入图片描述
  • 在线合成(硬件合成)
    不使用FrameBuffer在显示设备需要显示某一行的像素时用显示控制器将所有图层与该行相关的数据取出合成一行像素送过去。通常这种技术又叫Overlay技术。由于省去合成FrameBuffer时读图层写FrameBuffer的步骤大幅降低了内存传输量减少了功耗但这个需要硬件支持(通常这种硬件被称为DPU显示处理单元)。
    在这里插入图片描述



八.普法DPU

DPU(Display Processor Unit)显示处理单元而不是当今大火的并不是机器学习的Deep-LeaningPU或者是被吹爆天的”数据处理器”。也许看到这个“生僻词”首先就一脸懵逼了不是CPU、GPU么什么时候还出来个DPU了(其实它是一直存在的只是它默默的躲在后面不被大众知道,通常被称为显卡三板斧之一。)

在这里插入图片描述


8.1 DPU的作用

当我们通常大谈显示高帧率、高动态范围显示这些其实都需要顶级的DPU来实现。相比于GPU,相比之下DPU显示处理单元对于用户体验的影响可能还要更大一些因为它就是直接控制图形处理器向屏幕输出显示信号的“最后一道关卡”。首先DPU的硬件性能高低直接决定了其所能支持的最大屏幕分辨率、最大频率刷新率、乃至最大色彩深度(色彩丰富程度的多少其次DPU运算精度的高低还会决定屏幕上线条、文字看起来的清晰度表现最后对于现代的DPU来说它们除了负责将GPU、VPU生成的视频信号“传递”给显示面板之外还可以对其进行效果强化方面的额外处理。比如说屏幕色彩校正、视频插帧、像素级的对比度增强和显示细节修复这些看起来很“高大上”的功能其实也都是由那些旗舰芯片里的DPU来进行处理。

所以通常的DPU必须有如下几部分功能:

  • 支持多个Source Layer overlays(通常包括鼠标以及其它各种图层我们的dc却只能支持两层overlays)
  • Display Interface支持多路同时的输出设备物理显示设备虚拟显示设备不需要实际的输出设备
  • Blender 支持多个Blender对应于多个Path除了LCD外对应于DP或HDMI投屏这里我个人是可以处理多路输入

在这里插入图片描述


8.2 DPU的发展史

VPU(视频处理单元这个交由后面视频栈进行普及)和DPU它们其实比“显卡”还要老资历妥妥的老人一枚

  • 如期说老资历我们不如说VPU和DPU的历史实际上比我们熟悉的“GPU”还要古老。这是因为个人电脑最初的显卡本来就是只有2D色彩和线条绘制能力的也就是说它们其实根本不是“GPU”而是全部都是“DPU”。直到后来1999年NVIDIA研发出了对CPU依赖程度更低的、拥有更强的3D处理能力的GeForce 256显示核心它才被认为是世界上的第一款“GPU”。至于VPU经历过486、初代奔腾时代的电脑用户都知道当时的计算机只靠CPU性能是无法流畅播放VCD视频的要想在电脑上“看片”首先你需要购买一块独立的“解码卡”而它本质上就是早期的VPU。

  • 当然这块从最早的Framebuffer机制也能看出DRM框架中最早版本中也是不存在GPU的代码。DPU最简单的功能便是将Frambuffer数据输出到显示设备上去而Framebuffer的来源也都是来自于CPU的软件绘制而非GPU绘制


8.3 DPU和GPU的关系

在实际中DPU和GPU没有相关联甚至完全可以是两个厂家的产品并且DPU与GPU在Linux代码中的耦合是历史产物完全可以独立出来。

在这里插入图片描述
通过上图我们可以得出如下的结论

  • 通过上图的Linux的DRI显示框架也能看出KMS的相对独立性对应于系统侧的composer而DRM则在于内容相关的应用侧。对于Android系统也是一样的GPU对应于DRM是用来绘制的属于应用端的进程而DPU对应于KMS运行于服务端可以认为在X/wayland Servicecomposer中开机就会初始化然后保持不变两者的分离更加彻底。

  • 所以DPU侧重于控制显示而GPU侧重于内容




九.什么是送显?

送显:把合并后的显存送到显示驱动显示到屏幕上的过程。从技术的发展史上来看它经过了FBDEV到DRM/KMS的转变过程

在这里插入图片描述




十.Application的UI展现给用过户需要经过几步 ?

总结起来分为如下几步:

  • 根据实际情况将Application的UI渲染绘制出来并且以一定的格式保存
  • 将渲染好的UI图层数据经过图层合成
  • 将合成好的UI图层数据最终显示在display device上.该过程一般称作送显

在这里插入图片描述




十一.什么是FBDEV显示方案 ?

The frame buffer device provides an abstraction for the graphics hardware. It represents the frame buffer of some video hardware and allows application software to access the graphics hardware through a well-defined interface, so the software doesn’t need to know anything about the low-level (hardware register) stuff. fbdev用于为显示图形硬件提供一层软件抽象.它代理了显示图形硬件的帧内存,并且提供了一些良好定义的接口让应用软件去访问图形硬件而不用去关心底层图形硬件的具体控制细节。用通俗的一句话来说就是它是这一种传统的显示框架简单但是它只能提供最基础的显示功能无法满足当前上层应用和底层硬件的显示需求(特别是移动操作系统的需求)。

在这里插入图片描述




十二.什么是DRI ?

DRI(Direct Render Infrastructure):直接渲染基础架构。DRI在当前或者说将来的linux图形子系统中有着举足轻重的地位甚至可以说是新的linux图形框架核心思想的体现。而现在的主流DRM/KMS框架都是围绕着它进行的。所以鉴于它的重要性我们非常有必要了解它

在这里插入图片描述




十三.DRI的发展史

没有无缘无故的爱也没有无缘无故的狠,而我们的DRI也不是无缘无故的凭空冒出来的它是Linux的技术发展过程中诞生的产物。我们这里对其捋一捋还记得我们在前面介绍窗口的的时候说过它们是经典的c/s架构吗在DRI诞生前应用不能直接访问硬件通常的软件框架是从上到下C<---->S<---->Driver<---->Hardware。这样考虑的原因主要有二安全性和共享硬件资源!对稍微有经验的软件开发人员特别是系统工程师和驱动工程师来说这种理念就像杀人偿命、欠债还钱一样天经地义。但直到X server+3D出现之后一切都不好了。因为X server大喊的着“让我来”给出了这样的框架

在这里插入图片描述

  • 基于OpenGL的3D program需要进行3D rendering的时候需要通过X server的一个扩展GLX前面已经介绍过了请求X server帮忙处理。X server再通过底层的driver位于用户空间通过kernel访问硬件如GPU。

  • 其它普通的2D rendering如2D绘图、字体等则直接请求X server帮忙完成。

但是任何事情都不可能满足所有人前面的渲染框架也是如此看着不错哦完全满足上面的理念。但计算机游戏、图形设备硬件等开发人员不乐意了请让我们直接访问硬件因为很多高性能的图形设备要求相应的应用程序直接访问硬件才能实现性能最优。好像每个人都是对的怎么办妥协的结果是为3D Rendering另起炉灶给出一个直接访问硬件的框架DRI就应运而生了如下

在这里插入图片描述

这里可以看到DRI好像基本都是Rendering有关的内容那送显呢还是由display server统一处理比较好因为显示设备是有限的多个应用程序的多个界面都要争取这有限的资源server会统一管理、叠加并显示到屏幕上。而这里叠加的过程通常称作合成Compositor这个在前面已经有涉及到了




十四.什么是DRM ?

DRM(Direct Rendering Manager):即直接渲染管理器。它是为了解决多个程序对GPU(或显卡graphics card)及相应的graphics memory资源的协同使用问题而产生的。它是一个内核级的设备驱动可以编译到内核中也可以作为标准模块进行加载并且对用户层提供了libdrm进行先关的接口调用(注意这里需要和Linux下面的DRM显示框架区分开来此处的DRM是DRM显示框架的子集它在DRM显示框架中主要被用来渲染)。它的功能有如下几点:

  • Initialize GPU card, load its firmware, etc.

  • Share the GPU command queue between multiple applications

  • Manage the memory (allocation, access)

  • 统一管理、调度多个应用程序向显卡发送的命令请求可以类比为管理CPU资源的进程管理process management模块。

  • 统一管理显示有关的memorymemory可以是GPU专用的也可以是system ram划给GPU的后一种方法在嵌入式系统比较常用该功能由GEMGraphics Execution Manager模块实现主要包括

注意这里的DRM只是DRM显示框架的一部分

在这里插入图片描述




十五.什么是KMS ?

KMS(Kernel Mode Setting):也称作Atomic KMS它是一个在linux 4.2版本的kernel上才最终定性的技术。从字面意义上理解它要实现的功能比较简单即显示模式display mode的设置包括屏幕分辨率resolution、颜色深的color depth、屏幕刷新率refresh rate等等(它在Linux graphic的显示框架中主要被用来送显)。它的出现是为了解决最开始的DRM显示框架的缺点那时候Mode-Setting (包括更新画面、配置 display pipeline、screen resolution、color depth、refresh rate等) 是在 Userspace 中实现的这样做的缺点是

  • Rendering 和 Mode-Setting 会发生竞争;

  • 不统一缺少抽象不同的硬件平台各自为营;
    后来就引入了 Kernel Mode-Setting (KMS)其实就是将 Mode-Setting 的活移回到内核DRM driver 即负责访问 GPU 也负责访问 Display Engine且将 KMS 作为 DRM API 的一部分如下图左边部分

在这里插入图片描述


15.1 KMS的组成

在这里插入图片描述

  • Framebuffer:帧缓冲区对象struct drm_framebuffer是帧内存对象的抽象它提供了像素源给到CRTC。帧缓冲区依赖于底层内存管理器分配内存。
  • Plane:一个平面对象struct drm_plane表示一个图像源从drm_framebuffer对象获取输入数据在输出过程中与CRTC的顶部混合或覆盖。
  • CRTC:一个CRTCstruct drm_crtc表示一整个显示管线。它从drm_plane平面接收像素数据并将它们混合在一起。
  • Encoder:Encoder对象struct drm_encoder是CRTC和连接器drm_connector之间的连接元素。编码器从CRTC获取像素数据并将其转换成适合任何连接的连接器的格式。
  • Connector:连接器struct drm_connector是显示接收器的抽象包括als固定面板或任何其他可以以某种形式显示像素的东西。
  • 最终应用通过 KMS api将上述对象连接成一条display pipeline最终将图像显示在屏幕上。
    在这里插入图片描述



十六.KMS和DRM的关系 ?

个人觉得抛开DRM/KMS显示系统不谈DRM和KMS是完全独立没有任何依附或者依赖的关系的。只所以谈到DRM会牵涉到KMS或者反之。它们二者完全是历史原因导致KMS的代码放到DRM中实现了。目前的kernel版本如4.2之后KMS和DRM基本上没有什么逻辑耦合除了代码位于相同目录以及通过相同的设备节点提供ioctl之外可以当做独立模块看待。并且是现有DRM后才有的KMS。并且DRM的核心点是渲染而KMS的重点在于送显

在这里插入图片描述




十七.DRM/KMS显示方案

在前面我们说道了FBDEV显示方案知道了它是一种简单的传统的不能符合现在操作系统特别是移动操作系统高刷新的显示方案。而DRM/KMS显示方案就是为了解决上述问题而来的一种新的Linux下的显示方案(当然Android最新的也引入了)。

DRM/KMS显示方案相较于FBDEV显示方案有如下的优点:

  • 适应当前日益更新的显示硬件发展
  • 软件上能支持更多高级的控制和特性譬如天生支持fence等特性
  • 适应移动操作系统高刷新等特性要求

此时的DRM和KMS在显示方案中才有了关联它们之间的相互协同作用最终构建了DRM/KMMS显示方案




十八.Linux下典型窗口类型+DRM/KMS显示方案总览

在这里插入图片描述

在这里插入图片描述




十九.Wayland + Mesa + DRM/KMS显示方案简介

在详细介绍前我们看下整体总览后面对每个模块简单概括:

在这里插入图片描述

前面的框图是基于Wayland的窗口系统为例描述了linux graphic系统在DRI框架下通过两条路径DRM和KMS分别实现Rendering和送显两个显示步骤。我们这里从上层到下层的角度出发来简单分析该显示流程(这也是当前Linux主流的graphics图形子系统)

  • Application如3D game根据用户动作需要重绘界面此时它会通过OpenGL|ES、EGL等接口将一系列的绘图请求提交给GPU(非3D渲染最后也是将一系列请求转换成GL命令提交给GPU)。

    • OpenGL|ES、EGL的实现可以有多种形式这里以Mesa 3D为例所有的3D rendering请求都会经过该软件库它会根据实际情况通过硬件或者软件的方式响应Application的rendering请求。
    • 当系统存在基于DRI的硬件rendering机制时Mesa 3D会通过libGL-meas-DRI调用DRI提供的rendering功能。
    • libGL-meas-DRI会调用libdrmlibdrm会通过ioctl调用kernel态的DRI驱动这里称作DRMDirect Rendering Module。
    • Kernel的DRM模块最终通过GPU完成rendering动作。
  • GPU绘制完成后将rendering的结果返回给Application。

    • rendering的结果是以image buffer的形式返回给应用程序(注意这里的返回并不是真的拷贝了一份而是通过共享方式达到共享的这种共享的方式通常是通过DMA-BUF来实现的)。
  • Application将这些绘制完成的图像buffer可能不知一个送给Wayland compositorWayland compositor会控制硬件将buffer显示到屏幕上。

    • Wayland compositor会搜集系统Applications送来的所有image buffers并处理buffer在屏幕上的坐标、叠加方式后直接通过ioctl交给kernel KMSkernel mode setting模块该模块会控制显示控制器将图像显示到具体的显示设备上

在这里插入图片描述




写在最后

到这里Linux子系统Graphics图形栈介绍就告一段落了!编写该PPT的过程我也是小心再小心谨慎再谨慎但是难免其中可能会有一些概念或者理论不对这个希望各位能多多指针
最后要感谢网络上的各路大神给我们提供了如此多的学习资料才让我对Linux子系统Graphics图形栈有了些皮毛的认识路漫漫吾将上下而求索总之青山不改绿水长流先到这里了

在这里插入图片描述

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: linuxandroid