Linux graphic subsytem(1)_概述

作者:wowo 发布于:2015-12-17 22:21 分类:图形子系统

1. 前言

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

本文是图形子系统分析文章的第一篇,也是提纲挈领的一篇,将会从整体上,对linux显示子系统做一个简单的概述,进而罗列出显示子系统的软件构成,后续的文章将会围绕这些软件一一展开分析。

注1:本文所有的描述将以原生linux系统为例(如Ubuntu、Debian等),对其它基于linux的系统(如Android),部分内容会不适用。

注2:本文很多图片都是从网上搜集而来的(很多是从维基百科)。虽然蜗窝的宗旨是用自己的语言表述,尽量自己画图,但是linux图形子系统太复杂了,蜗蜗的理解有限,而老外的图画的实在太好,蜗蜗觉得,再怎么努力,也画不出更好的了,因此本着为读者负责的态度,就直接copy了。

2. 概念介绍

2.1 GUI(Graphical User Interface,图形用户界面)

linux图形子系统的本质,是提供图形化的人机交互(human-computer interaction)界面,也即常说的GUI(Graphical User Interface)。而人机交互的本质,是人脑通过人的输出设备(动作、声音等),控制电脑的输入设备,电脑经过一系列的处理后,经由电脑的输出设备将结果输出,人脑再通过人的输入设备接收电脑的输出,最终实现“人脑<-->电脑”之间的人机交互。下面一幅摘自维基百科的图片(可从“这里”查看比较清晰的SVG格式的原始图片),对上述过程做了很好的总结:

Linux_kernel_INPUT_OUPUT_evdev_gem_USB_framebuffer.svg

该图以一个非常前卫的应用场景----虚拟现实(VR,Virtual Reality)游戏,说明了以图形化为主的人机交互过程:

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

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

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

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

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

注3:图中提到了VR场景的典型帧率(1280×800@95fps for VR),这是一个非常庞大的信息输出,要求图形子系统能10.5ms的时间内,生成并输出一帧,以RGBA的数据格式为例,每秒需要处理的数据量是1280x800x95x4x8=3.11296Gb,压力和挑战是相当大的(更不用提1080P了)。

有关GUI更为详细的解释,请参考:https://en.wikipedia.org/wiki/Graphical_user_interface

2.2 Windowing system(窗口系统)

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

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

2)应用程序作为display server的一个client,在自己窗口(window)中运行,并绘制自己的GUI。

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

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

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

有关Windowing system的详细解释,请参考:https://en.wikipedia.org/wiki/Windowing_system

2.3 X Window System

似乎终于要进入正题了。

X Window System是Windowing System一种实现,广泛使用于UNIX-like的操作系统上(当然也包括Linux系统),由MIT(Massachusetts Institute of Technology,麻省理工学院)在1984年发布。下图(可从“这里”查看比较清晰的SVG格式的原始图片)是它的典型架构:

X_client_server_example

1)X Window System简称X,或者X11,或者X-Windows。之所以称作X,是因为在字母表中X位于W之后,而W是MIT在X之前所使用的GUI系统。之所以称作X11,是因为在1987年的时候,X Window System已经进化到第11个版本了,后续所有的X,都是基于X11版本发展而来的(变动不是很大)。为了方便,后续我们都以X代指X Window System。

2)X最初是由X.org(XOrg Foundation)维护,后来基于X11R6发展出来了最初专门给Intel X86架构PC使用的X,称作XFree86(提供X服务,它是自由的,它是基于Intel的PC平台)。而后XFree86发展成为几乎适用于所有类UNIX操作系统的X Window系统,因此在相当长的一段时间里,XFree86也是X的代名词。再后来,从2004年的时候,XFree86不再遵从GPL许可证发行,导致许多发行套件不再使用XFree86,转而使用Xorg,再加上Xorg在X维护工作上又趋于活跃,现在Xorg由成为X的代名词(具体可参考“http://www.x.org/”)。

3)X设计之初,制定了很多原则,其中一条----"It is as important to decide what a system is not as to decide what it is”,决定了X的“性格”,即:X只提供实现GUI环境的基本框架,如定义protocol、在显示设备上绘制基本的图形单元(点、线、面等等)、和鼠标键盘等输入设备交互、等等。它并没有实现UI设计所需的button、menu、window title-bar styles等元素,而是由第三方的应用程序提供。这就是Unix的哲学:只做我应该做、必须做的事情。这就是这么多年来,X能保持稳定的原因。也是Linux OS界面百花齐放(不统一)的原因,各有利弊吧,后续文章会展开讨论。

4)X包括X server和X client,它们之间通过X protocol通信。

5)X server接收X clients的显示请求,并输出到显示设备上,同时,会把输入设备的输入事件,转递给相应的X client。X server一般以daemon进程的形式存在。

6)X protocol是网络透明(network-transparently)的,也就是说,server和client可以位于同一台机器上的同一个操作系统中,也可以位于不同机器上的不同操作系统中(因此X是跨平台的)。这为远端GUI登录提供了便利,如上面图片所示的运行于remote computer 的terminal emulator,但它却可以被user computer的鼠标键盘控制,以及可以输出到user computer的显示器上。
注4:这种情况下,user computer充当server的角色,remote computer是client,有点别扭,需要仔细品味一下(管理输入设备和显示设备的是server)。

7)X将protocol封装为命令原语(X command primitives),以库的形式(xlib或者xcb)向client提供接口。X client(即应用程序)利用这些API,可以向X server发起2D(或3D,通过GLX等扩展,后面会介绍)的绘图请求。

有关X更为详细的介绍,请参考:https://en.wikipedia.org/wiki/X_Window_System,后续蜗蜗可能会在单独的文章中分析它。

2.4 窗口管理器、GUI工具集、桌面环境及其它

前面讲过,X作为Windowing system中的一种,只提供了实现GUI环境的基本框架,其它的UI设计所需的button、menu、window title-bar styles等基本元素,则是由第三方的应用程序提供。这些应用程序主要包括:窗口管理器(window manager)、GUI工具集(GUI widget toolkit)和桌面环境(desktop environment)。

窗口管理器负责控制应用程序窗口(application windows)的布局和外观,使每个应用程序窗口尽量以统一、一致的方式呈现给用户,如针对X的最简单的窗口管理程序--twm(Tab Window Manager)。

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

桌面环境是应用程序级别的封装,通过提供一系列界面一致、操作方式一致的应用程序,使系统以更为友好的方式向用户提供服务。Linux系统比较主流的桌面环境包括GNOME、KDE等等。

2.5 3D渲染、硬件加速、OpenGL及其它

渲染(Render)在电脑绘图中,是指:用软件从模型生成图像的过程。模型是用严格定义的语言或者数据结构对于三维物体的描述,它包括几何、视点、纹理以及照明信息。图像是数字图像或者位图图像。

上面的定义摘录自“百度百科”,它是着重提及“三维物体”,也就是我们常说的3D渲染。其实我们在GUI编程中习以为常的点、线、矩形等等的绘制,也是渲染的过程中,只不过是2D渲染。2D渲染面临的计算复杂度和性能问题没有3D厉害,因此渲染一般都是指3D渲染。

在计算机中,2D渲染一般是由CPU完成(也可以由专门的硬件模块完成)。3D渲染也可以由CPU完成,但面临性能问题,因此大多数平台都会使用单独硬件模块(GPU或者显卡)负责3D渲染。这种通过特定功能的硬件模块,来处理那些CPU不擅长的事务的方法,称作硬件加速(Hardware acceleration),相应的硬件模块,就是硬件加速模块。

众所周知,硬件设备是多种多样的,为了方便应用程序的开发,需要一个稳定的、最好是跨平台的API,定义渲染有关的行为和动作。OpenGL(Open Graphics Library)就是这类API的一种,也是最为广泛接纳的一种。

虽然OpenGL只是一个API,但由于3D绘图的复杂性,它也是相当的复杂的。不过,归根结底,它的目的有两个:

1)对上,屏蔽硬件细节,为应用程序提供相对稳定的、平台无关的3D图像处理API(当然,也可以是2D)。

2)对下,指引硬件相关的驱动软件,实现3D图像处理相关的功能。

另外,openGL的一个重要特性,是独立于操作系统和窗口系统而存在的,具体可以参考后面软件框架相关的章节。

3. 软件框架

通过第2章的介绍,linux系统中图形有关的软件层次已经呼之欲出,具体如下:

display_software_layer

该层次图中大部分的内容,已经在第2章解释过了,这里再补充说明一下:

1)该图片没有体现3D渲染、硬件加速等有关的内容,而这些内容却是当下移动互联、智能化等产品比较关注的地方,也是linux平台相对薄弱的环节。后续会在软件框架有关的内容中再着重说明。

2)从层次结构的角度看,linux图形子系统是比较清晰的,但牵涉到每个层次上的实现的时候,就比较复杂了,因为有太多的选择了,这可归因于“提供机制,而非策略”的Unix软件准则。该准则为类Unix平台软件的多样性、针对性做出了很大的贡献,但在今天这种各类平台趋于整合的大趋势下,过多的实现会导致用户体验的不一致、开发者开发精力分散等弊端,值得我们思考。

3)虽然图形子系统的层次比较多,但不同的人可能关注的内容不太一样。例如对Linux系统工程师(驱动&中间件)而言,比较关注hardware、kernel和display server这三个层次。而对Application工程师来说,可能更比较关心GUI Toolkits。本文以及后续display subsystem的文章,主要以Linux系统工程师的视角,focus在hardware、kernel和display server(可能包括windows manager)上面。

以X window为例,将hardware、kernel和display server展开如下(可从“这里”查看比较清晰的SVG格式的原始图片):Linux_Graphics_Stack_2013.svg

From: https://upload.wikimedia.org/wikipedia/commons/c/c2/Linux_Graphics_Stack_2013.svg

对于软件架构而言,这张来自维基百科的图片并不是特别合适,因为它包含了太多的细节,从而显得有些杂乱。不过瑕不掩瑜,对本文的描述,也足够了。从向到下,图中包括如下的软件的软件模块:

1)3D-game engine、Applications和Toolkits,应用软件,其中3D-game engine是3D application的一个特例。

2)Display Server

图片给出了两个display server:Wayland compositor和X-Server(X.Org)。X-Server是linux系统在PC时代使用比较广泛的display server,而Wayland compositor则是新设计的,计划在移动时代取代X-Server的一个新的display server。

3)libX/libXCB和libwayland-client

display server提供给Application(或者GUI Toolkits)的、访问server所提供功能的API。libX/libXCB对应X-server,libwayland-client对已Wayland compositor。

4)libGL

libGL是openGL接口的实现,3D application(如这里的3D-game engine)可以直接调用libGL进行3D渲染。

libGL可以是各种不同类型的openGL实现,如openGL(for PC场景)、openGL|ES(for嵌入式场景)、openVG(for Flash、SVG矢量图)。

libGL的实现,既可以是基于软件的,也可以是基于硬件的。其中Mesa 3D是OpenGL的一个开源本的实现,支持3D硬件加速。

5)libDRM和kernel DRM

DRI(Direct Render Infrastructure)的kernel实现,及其library。X-server或者Mesa 3D,可以通过DRI的接口,直接访问底层的图形设备(如GPU等)。

6)KMS(Kernel Mode Set)

一个用于控制显示设备属性的内核driver,如显示分辨率等。直接由X-server控制。

4. 后续工作

本文有点像一个大杂烩,丢进去太多的东西,每个东西又不能细说。觉得说了很多,又觉得什么都没有说。后续蜗蜗将有针对性的,focus在某些点上面,更进一步的分析,思路如下:

1)将会把显示框架限定到某个确定的实现上,初步计划是:Wayland client+Wayland compositor+Mesa+DRM+KMS,因为它们之中,除了Mesa之外,其它的都是linux系统中显示有关的比较前沿的技术。当然,最重要的,是比较适合移动端的技术。

2)通过单独的一篇文章,更详细的分析Wayland+Mesa+DRM+KMS的软件框架,着重分析图像送显、3D渲染、Direct render的过程,以此总结出DRM的功能和工作流程。

3)之后,把重心拉回kernel部分,主要包括DRM和KMS,当然,也会顺带介绍framebuffer。

4)kernel部分分析完毕后,回到Wayland,主要关心它的功能、使用方式等等。

5)其它的,边学、边写、边看吧。

原创文章,转发请注明出处。蜗窝科技,www.wowotech.net

标签: Linux display subsystem GUI Wayland SurfaceFlinger DRI

评论:

semilog
2018-01-09 13:54
直接有X-server控制。 写的很好,有个错别字
wowo
2018-01-16 09:28
@semilog:多谢提醒,已修改~~
wzyy2
2017-12-08 09:14
图形这块的文章太少了, 支持客户好痛苦
:p 想要研究这块的可以买个rockchip的开发板来玩,我觉得我们是DRM/KMS这块做的最好的arm linux了(不过不知道terga是什么情况。。)
http://blog.iotwrt.com/media/2017/11/27/graphic/
wowo
2017-12-08 09:42
@wzyy2:是啊,我一直想把这块的文章整理一下,只是苦于没有时间:-(
miroor
2017-12-28 10:15
@wowo:博主有没有V4l2实现及适配相关的文章?
wowo
2017-12-29 09:15
@miroor:暂时没有写这一块的内容。
miroor
2017-12-29 10:42
@wowo:感觉这一块内容也很多,很多网上的很多都没说清楚,希望出一个系列!
demon
2017-01-24 16:39
wowo,
如果我想在android系统中实现数据的转换,比如将RGB数据变为RGBW之类的。
有什么好的建议么?
wowo
2017-01-25 09:15
@demon:openGL中有大把的颜色转换的实现,不过RGBW这种新东西,不知道有没有。
whl
2017-06-14 11:45
@demon:希望大神能多写些关于GPU的知识
wowo
2017-06-14 21:30
@whl:苦于没时间……
motou
2016-11-29 23:10
不错,2)后面就再没有新的了吗?
wowo
2016-11-30 08:44
@motou:多谢关注。由于太忙,要写的东西又比较杂,所以这一块一直没有机会更新。
我准备在x project做到显示的时候,再接着写这一系列的文章。
lifupan@gmail.com
2016-07-04 11:49
期待后续....
buhui
2016-03-11 10:47
希望把VR显示在Linux下面实现也给猜想推测一下,让我们星际穿越一下。
wowo
2016-03-11 16:52
@buhui:VR的重点在应用和GPU,有机会可以介绍一下。
seven
2016-02-18 14:59
赞一下, 期待
尼玛
2015-12-30 15:18
你将“图形子系统”放到“linux内核分析”分类下,你这样划分是不严格的。内核里压根就没有图形相关的东西,不过是一些设备的驱动而已。linux的图形服务就是在后台运行的linux应用程序。
wowo
2015-12-30 16:13
@尼玛:您的表述从一定程度上是对的,不过也是值得思考的。其实我这样划分是有原因的,主要有二:
1. 最近几年linux图形框架有很大程度的进化,主要体现在:将旧的、包罗万象的display server(如x server)边缘化。
这里的“边缘化”并非贬义词,之所以这么做,是从复杂度、可维护性、移动化等多个角度考虑的。而边缘化的手段之一,就是将display server中诸多的机制移出,一部分交由kernel实现,如memory管理、mode setting等,一部分交给第三方软件实现(如字库等)。
而边缘化的结果就是,display server变成薄薄的一层,而和真正的graphic相关的东西,分布在两个地方:
        1)GUI Toolkits以及3D有关的工具集中,如GTK+、QT等非常复杂的图形库,Mesa3D等OpenGL实现;
        2)kernel中,负责管理复杂的显示设备。
2. 我对graphic subsystem的分析,重点不是GUI Toolkits,它们太庞大、太专业了。因此在进行一些铺垫之后,我会把关注点放在kernel中,这也是graphic subsystem放到linux内核分析这个分类的原因。
另外,也正是因为“内核里压根就没有图形相关的东西,不过是一些设备的驱动而已”这样的理念(它没有错,错的是linux系统忽视了移动终端显示有关需求的多样性),才导致这么长时间一来,linux kernel显示驱动的简单、粗暴(只有简单Framebufffer驱动)。不过随着DRM/KMS的完成,情况已经有改善了。
cainiao367
2015-12-23 13:17
特意注册,赞一下。期待后续^_^
wowo
2015-12-23 13:25
@cainiao367:多谢关注~~

发表评论:

Copyright @ 2013-2015 蜗窝科技 All rights reserved. Powered by emlog