Linux Graphics
歷史發展
Console and Frame Buffer
當出 Linux 被寫出來的時候, 其 console 是直接使用 VGA 硬體的(text mode)。 剛開始時, 第一批有繪圖的應用程式都會自帶驅動程式, 後來第一批繪圖 Library 出現(例如 SVGALib)。 當時的應用程式必須維持繪圖硬體的狀態, 開始執行時儲存狀態, 結束執行後還原狀態, 而這樣的模式仍適用於現在的 X Server。
接著第一個 Kernel 內的繪圖 framework 『Framebuffer Devices』 出現了, 通常會被簡稱為『fbdev』,
+---------------------+
| Console Application |
+---------------------+
|
v
+-----------+
+------| /dev/tty1 |------+
| +-----------+ |
| Linux Console Subsystem |
+-------------------------+
|
v
+---------------+ +-----------------------+
| fbcon | | Graphical Application |
+---------------+ +-----------------------+
| |
v v
+-----------------+
+-| /dev/fb0 |-+
| +-----------------+ |
| Framebuffer Driver |
+---------------------+
|
v
+---------------------+
| Hardware |
+---------------------+
移植需求:很多平台不支援 text mode
- 針對不同硬體而做的驅動程式,卻有通用的 API
z.B. intelfb, atifb
vesafb:不依賴特定硬體,使用繪圖卡的 VESA BIOS
efifb:類似 vesafb,但適用於 UEFI
userspace 存取: /dev/fbX
簡單的 API
fbcon:text console 模擬,有 bitmapped fonts 和企鵝,在 kernel 內完成,而非 userspace
X Window System
X Window System
X Window System 是 Linux 上最通用的繪圖架構, 也在所有 Unix-like 的平台上流行, 常被簡稱為『X11』、『X』。 其為 client/server 架構, client 是應用程式, server 則負責輸入輸出。 這個 client/server 架構具有 Network Transparent 的特性, 不限定兩邊要跑在同一臺機器上, 中間可以利用 TCP/IP 傳輸, 或者在本地端使用 Unix Domain Sockets 溝通。
X11 是它的 protocol 名稱。
X Server 會管理整個視窗層級
root window:桌面背景
top-level window:應用程式的視窗
subwindows:控制(例如按鈕之類的)
+-------------+ +-------------+
| Application | | Application |
| (X Client) | | (X Client) |
+-------------+ +-------------+
^ | ^ |
| | X11 protocol | | X11 protocol
| v | v
+---------------------------------+
| X Server |
| |
| +--------+ +--------+ |
+--| Driver |-------| Driver |----+
+--------+ +--------+
^ |
| v
+---------------+ +-----------------+
| Input Devices | | Display Devices |
+---------------+ +-----------------+
X Clients and Servers
X Client 不直接實做 X11 protocol, 它們會使用 Libraries:
傳統的 Xlib
較新、較輕量的 XCB (X11 C Bindings)
其他工具包內部也是使用 Xlib 或 XCB,例如 Motif、GTK、Qt 。
+------+ +----+ +------+ +--------+ +-------+ +-----------+
| | | | | | | Athena | | Motif | | Open Look |
| | | | | | | (Xaw) | | (Xm) | | (Xview) |
| | | | | | +--------+ +-------+ +-----------+
| | | | | | | | |
| | | | | | v v v
| GTK+ | | Qt | | FLTK | +----------------------------+
| | | | | | | X-Toolkit (Xt) |
+------+ +----+ +------+ +----------------------------+
| | | |
v v v v
+-----------------------------------------------------+
| Client Libraries |
| (Xlib, XCB) |
+-----------------------------------------------------+
Display Server Window Manager
Window Manager 是特別的 X Client, 負責管理 top-level 視窗和畫出視窗的外框(frames)(decorations)。
X Server 要負責管理輸入(鍵盤、滑鼠等)和輸出(只有圖像):
通用的部份:DIX (Device Independent X)
- 針對特殊硬體的部份:DDX (Device Dependent X)
包含輸入、輸出裝置的驅動程式
大多數流行的 X Server 實做(XFree86 和現今的 X.Org):
DDX 部份是模組化的,驅動程式為獨立的模組
DDX 的界面會隨著 Server 版本更動
X Extensions
X protocol 可以利用 Extensions 擴充能力, 例如:
XSHM (X Shared Memory):針對 bitmap 的更快速本地端顯示
Xv (X Video):硬體加速的影像顯示
GLX:X 上的 OpenGL
Xinerama:多螢幕支援
XRandR (Resize and Rotate):不用重開 X Server 的繪圖模式設定
- XRendr:現代化的反鋸齒(平滑化)、透明度混合(alpha-blended)的 2D 圖像
現今用於幾乎每個 2D 的圖像程式
2D Acceleration in X
在 XFree86 或 X.Org 中, 要使用硬體加速的 2D 繪圖有好幾種方式:
XAA (XFree86 Acceleration Architecture,1996):簡單地加速線段繪製和填滿操作
EXA (2005):從 KAA (Kdrive Acceleration Architecture,2004)衍生而來,專門針對 XRendr 的加速
UXA (Unified Memory Acceleration Acceleration,2008):由 Intel 開發,設計要來取代 EXA,不被非 Intel 的驅動程式採用
SNA (Sandy Bridge New Acceleration,2011):完全針對 Intel 需求特製的,但也因此非常快
Glamor (2011):用 OpenGL 實做所有的 2D 加速功能,因此不依賴特定廠商的硬體
OpenGL
OpenGL
OpenGL (Open Graphics Language)是針對 3D 繪圖的工業標準, 由 Khronos Group 管理, 功能為硬體加速地繪製三角形結構。
OpenGL ES (OpenGL for Embedded Systems)大致上是 OpenGL 的子集合, 有大約 90% 的相容度。
OpenGL 2.0 後加入了可程式化的 Shader, 為一個 C-like 的語言稱為 GLSL (OpenGL Shading Language)。
OpenGL 具有擴充的機制, 類似 X11。
OpenGL 需要額外的一些 API 作為和視窗系統間的膠水:
GLX:針對 X 視窗系統
WGL:針對 Windows
AGL:針對 Mac OS X
- EGL:使用 OpenGL ES 的版本(Embedded Linux、Android、iOS 等)
在各系統皆可取得,最後會取代 GLX
Indirect v.s. Direct Rendering
OpenGL 在 Linux 上的 X.Org 會以以下方式運作,
X.Org 會把 GLX 作為 X protocol 的一部分,
Indirect Rendering 的狀況會把 OpenGL 指令透過 GLX protocol 傳輸。 在早期的一段時間,這樣的作法不能使用到硬體加速。
+-------------+
| Application |
+-------------+
| X11 + GLX
v
+-------------+
| X Server +--------+
+-----------| OpenGL |
+--------+
Direct Rendering 只能用於本地端, 不能透過網路傳輸, client 會連結到 libGL.so 並直接使用。 libGL.so 會包含 OpenGL 實做(可能是針對某個硬體的)。
+-------------+ direct function calls
| Application |-----------------------+
+-------------+ |
| X11 + GLX |
v v
+-------------+ +--------+
| X Server |<~~~~~~~~~~~~~~~~~>| OpenGL |
+-------------+ GLX +--------+
Mesa
Linux 上的 OpenGL 實做有兩種, 一種是私有的驅動程式(例如 NVIDIA 和 AMD), 另一種是開源的 Mesa。 Mesa 的實做也包含 GLX、EGL、OpenGL ES, 起初只有軟體渲染的功能, 而現今為各開源 3D 驅動程式的基礎。
Gallium3D
Gallium3D 是不依賴特定 OS 的 GPU 驅動程式 framework, 其中一部份依賴 Mesa, 包含的功能不只 3D 渲染, 還包括 GPU 運算、硬體影像解碼。
三個基本的部份:
- State Tracker :client API 的實做
OpenGL (利用 Mesa)
OpenCL (計算用)
VDPAU (影像)
OpenMAX (影像)
WinSys Driver :實做 GLX 或 EGL
- Pipe Driver :特定 GPU 的後端
llvmpipe :較快地軟體渲染
NVIDIA GPU : nv30, nv50, nvc0, nve0
AMD GPU : radeonsi
Gallium3D 使用 TGSI (Tungsten Graphics Shader Infrastructure)作為 shader 的表示方式, 某些後端內部會使用 LLVM。
OpenGL Driver Stacks
把不同實做搭配起來, OpenGL 可能會有四種驅動程式運作的架構:
私有的驅動程式:取代 libGL.so
典型的 Mesa :通用的 libGL.so,搭配 Mesa 內針對某些硬體的後端
Mesa + Gallium3D :使用 Mesa 作為 State Tracker,Gallium3D 作為後端(TGSI)
Mesa + Gallium3D + LLVM :使用 Mesa 作為 State Tracker,Gallium3D 作為後端(LLVM)
+-------------+ +-------------+ +-------------+ +-------------+
| Application | | Application | | Application | | Application |
+-------------+ +-------------+ +-------------+ +-------------+
| OpenGL | OpenGL | OpenGL | OpenGL
v v v v
+---------------+ +-------------------+ +---------------+ +---------------+
| proprietary | | Mesa | | Mesa | | Mesa |
| OpenGL driver | +-------------------+ +---------------+ +---------------+
+---------------+ | hardware-specific | | Gallium3D | | Gallium3D |
| | driver backend | | State Tracker | | State Tracker |
| +-------------------+ +---------------+ +---------------+
| | | Gallium3D | Gallium3D
| | | (TGSI) | (TGSI)
| | v |
| | +-------------+ +-----|---------------+
| | | Gallium3D | | v Pipe Driver |
| | | Pipe Driver | | +---------+ |
| | +-------------+ | | gallivm | |
| | | | +---------+ |
| | | | | LLVM IR |
| | | | v |
| | | | +---------+ |
| | | | | LLVM | |
| | | | +---------+ |
| | | | | Backend | |
| | | | +---------+ |
| | | +---------------------+
| | | |
v v v v
+-------------+ +-------------+ +-------------+ +-------------+
| GPU | | GPU | | GPU | | GPU |
+-------------+ +-------------+ +-------------+ +-------------+
OpenCL
現今的 GPU 因為有著快速的浮點數運算能力, 會被拿來用於非繪圖的運算, 被稱為 GPGPU (General Purpose GPU)。
GPGPU 的標準 API 為 OpenCL (Open Compute Language), 和 OpenGL 一樣由 Khronos Group 管理、制定。 Linux 上的支援方式類似 OpenGL, 私有的驅動程式自帶它們的實做, Gallium3D 則是 Clover State Tracker, Intel GPU 則有另外的專案叫 Beignet。
除了 OpenCL 之外, 另外還有流行的 NVIDIA API 叫 CUDA, 但是只能用於 NVIDIA 的顯示卡並且搭配私有的驅動程式。
Direct Rendering Infrastructure
DRI & DRM
OpenGL 的驅動程式會作為應用程式的一部分跑在 userspace, 對於顯示卡的存取由 kernel 內的驅動程式管理, 這管理包含多個程式同時存取。 私有的驅動程式會包含私有的 kernel 驅動程式 API, 開源的驅動程式則有通用的 framework 叫 DRI (Direct Rendering Infrastructure)。
多層架構:
不依賴特定硬體的 userspace library (libdrm.so)
依賴特定硬體和驅動程式的 userspace library (libdrm_intel.so)
kernel 模組: DRM (Direct Rendering Manager)
DRM 會把裝置顯示到 /dev/dri/cardX
libdrm_xxx.so 和 DRM 間的界面有一部份會依賴特定的驅動程式
DRI Versions
- DRI 1,1998
第一版,實做的能力有限,如果有多個應用程式想使用 3D 硬體的話效率不佳
- DRI 2,2007
解決了大部份第一版碰到的問題,為目前最廣範使用的版本
- DRI 3,2013
更多細部的改進
DRM Master and Render Node
DRM clients 並非都同等的, 其中會有 DRM Master,