简介
本次 IRC Conference 大致分兩個部分,前半部討論嶄新的 X Extensions,而
後半部則是簡單介紹一些非 FreeDesktop.org 直接相關,但是頗值得一書的項
目,當然也包含筆者近來進行的一些計畫與實驗。讲座时间是 2004 年 12 月
30 日。讲座人是 Jim Huang (黃敬群 / "jserv")。
X Extensions
關於嶄新的 X Extensions,筆者規劃了以下流程:
GL --> DRI/DRM --> X Render Extension --> Font (Xft / Fontconfig)
\
\__
\--- Cairo --> Glitz
XDamage + XFixes --> XComposite
Sun Looking Glass --> XEvIE
XInput Hotplug
DRI — Direct Rendering Infrastructure
DRI 是 XFree86 相當重要的嶄新設計,這在許多層面已經跳脫傳統 Client /
Server 的架構了。Client / Server 架構下使用相當緩慢的 transport 機制,
從 Client 端將 rendering 指令,送到 Server 端,這在普通的應用來說,已
經足夠了,但是對於 3D Graphics 顯然是很大的效能瓶頸 — 耗費太多時間在
round-trip (繪圖指令的往返) 通信上 [按1]。於是,能否提供更為直覺、簡單
的設計,讓 client 可以直接與 Graphics Hardward 對話呢?
[按1] X Window System 的 Transport 瓶頸可以從其架構得知,见下图:

在探討 DRI 之前,筆者要強調 DRI 對於 XFree86 / XOrg 的重要性。較早接觸 Linux 或 FreeBSD 的朋友都經歷過 XFree86 3.x 系列必須選用特定顯示卡 X server 的年代,當時的設計還是僅依循 DDX (Device-Dependent X) 與 DIX (Device-Independent X) 的劃分,其硬體加速能力也是有相當的限制。而在 March 8, 2000 的 XFree86 4.0 版釋出後,有了完全的改觀,一來是整合 MetroLink (一家相當著名的商業 X Server 製造商 [按2]) 貢獻的模組化程式碼,二來就是 DRI 架構的落實,給予更大的彈性與更好的表現。這段發展歷史變遷,筆者整理成以下的表格:
| 日期 |
重大事件 |
| 1998/8 |
展開 DRI High Level 設計 (評估階段) |
| 1998/12 |
展開 DRI Low Level 設計 |
| 1999/1 |
DRI 實作計畫展開,與 MESA (Free/Open Source Open GL 實作)計畫整合發展 |
| 1999/2/1 |
MESA 3.1 採 XFree86 / BSD / MIT 型態授權 |
| 1999/2/16 |
SGI 將其 GLX (GL Extension) 實作以 open source 授權釋出 |
| 1999/5/12 |
DRI Low Level 設計文件上線 |
| 1999/6 |
DRI 1.0 實作釋出 |
| 2000/3/8 |
XFree86 version 4.0 版釋出 |
| 2000/6 |
SGI 捐出 GLX 與字型處理技術給 XFree86 |
| 2000/10/27 |
X Render Extension 首度現身於 XFree86 4.0.1d |
[按2] 筆者已經找不到 MetroLink 公司的網頁了
直接與硬體溝通的 Graphics Toolkits / Window System 相繼被提出,也有不
錯的效能表現,但是在 X Window System 的設計原則,是希望透過層層的架構,
讓硬體能夠抽象化,是否意味著我們將無法處理 3D Graphics 呢?這是個相當
大的挑戰,一方面要能處理硬體,另一方面要依循 X Window System 的設計原
則,於是 XFree86 Developer 提出 DRI (Direct Rendering Infrastructure)
的機制。
不同於過去使用 Xlib 來傳遞 rendering request 給 X server 的方式,DRI
引入一個捷徑,重點在於事先部署好能夠直接與硬體溝通的 Kernel Driver,然
後 DRI 直接將 rendering commands/data 傳遞給該 driver,X Client 在此機
制下,仍是與其他 2D 或 3D X Client 共享 X Resources。那麼,究竟是哪個
環節特別了呢?
X Resources 的處理還是透過 X server 原有的機制,但是真實的 rendering,
或者明確來說,對螢幕/輸出裝置的顯示,是直接透過 Kernel-level driver 來
實現的。這意味著,透過 DRI,Graphics driver 的開發者可以將過去開發的
DDX driver 移轉到 DRI Kernel Driver、Client DRI Driver library,或者是
X server 中,這樣一來,除了效能的優勢,再來是安全性的考量。
有了以上的概念,咱們先理解以下關鍵字:
- RM —> Resource Management
- 2D —> 2D Commands and Data
- 3D —> 3D Commands and Data
- SAREA —> DRM Shared Memory
接著就要進入重頭戲 — XFree86 4.x DRI。
DRI 運作示意圖如下所示:

是的,DRI 的引入後,整個軟體架構變得相當複雜,讓我們抽絲剝繭,揭開這一切神秘的面紗。
「X Window System 的精髓在於 X Protocol」。由上往下看,在 Xlib 之下的
就是 Protocol Engine,為數眾多的 command/data 組合將透過網路 (廣義的說
法) 派送到 Server,而 X server 處理 X Protocol 則有對應的 Protocol
Decoder,這個部分並沒有涉入多少 Grapghics,就抽象來說,可以視為 Data
bus,於是我們稱為 X Transport,這是無法避免的成本,儘管已經有許多改良
的途徑相繼提出,比方說透過 POSIX Shared Memory。
圖-1 中央的流程便是我們熟知的模式,而一旦導入 X11/OpenGL 後,情勢就有很大的轉變。
再度補充,Transport 的實作幾乎都是商業 X server 的賣點。以 Sun 的 X
Window System 來說,其 X11 Transport 的設計就領先同業有相當大的距離,
這一方面是針對 Sparc 作了最佳化,另一方面是獲得 Solaris 作業系統的整合。
但無論如何,我們可以發現另一個瓶頸: 就是 Rendering 的處理。我們的重點
將置放於 X11/OpenGL 的展現。
Direct rendering program (3D):
Direct rendering (3D data) -> 3D data -> Graphics Hardware
Direct rendering program (2D):
X Protocol Encode -> Protocol Decode -> DIX -> XAA -> DDX Driver ->
Graphics Hardware
Indirect rendering program (2D):
X Protocol Encode -> Protocol Decode -> DIX -> XAA -> DDX Driver -> Graphics Hardware
Indirect rendering program (3D):
X Protocol Decode -> GLX -> Mesa (including SW rasterizer) -> DDX Driver -> Graphics Hardware
在過去 XFree86 3.x 系列的實作,DDX driver 有很多部分是處理底層 device routines。
我們都知道作業系統在做 content switching 是無法避免的成本消耗。
DDX driver 都帶有許多 magic 成分在。
除了 XFree86 4.x 的 DRI 之外,有個稱為 Utah GLX 的架構在觀念上是相當接
近的,但是實作的技術有很大的落差。
DRI 特別之處是需要 Kernel Level 的整合,現在的問題在於能否降低非必要的 latency。
再回到上圖。
使用 MMIO: (Memory-mapped I/O)
使用 SHM: (Shared Memory IPC)
使用 DMA:
這裡是非常難懂的一段落,必須有足夠的 H/W Graphics Devices 知識才能徹底
理解,我試著用很簡單的話帶過。
為何要分如此多層次?
我們都知道 C/S 架構下的衝擊非常的大,DRI 架構的提出,就是提供許多緩衝
的設計, 讓 SHM / MMIO / DMA 等基礎建立一系列 Hardware Acceleration 的
可能性。
XInput Hotplug
先跳過 DRI/DRM 複雜的設計,我們來探討 XInput Hotplug。
XInput Hotplug 是個相當複雜的議題,但是對 Desktop 需求又是相當重要。試
想,當我們將 USB 介面的手寫版插入時,X Window 可否自動偵測該 device,
並且驅動其功能?
Linux Kernel 可以提供 HAL 資訊,但是目前的 XFree86-based 實作在 XInput
Hotplug 的不完善導致相當多問題。
XOrg hacker 著手處理這議題,整理各方意見放在 wiki page 中:
http://xorg.freedesktop.org/wiki/XInputHotplug
就目前的設計來說,X server (XOrg) 並不支援 input devices 的 Hotplug,這表示說,你無法在不更動設定檔以及重新啟動 X server 的前提下,動態的新增或移除任何 input devices。然而,在 Linux Kernel 2.4 以來,Hotplug 的實作已經有相當卓越的設計,並且提出抽象化 (abstraction) 的途徑,可以很容易加入 input devices 的 hotplugging,包含鍵盤、滑鼠、搖桿,甚至是其他特殊的裝置。
XInputHotplug 的目標就是希望能夠銜接 Linux Kernel 或是底層 Kernel 提供
的 Hotplug 機制,做到真正不需要更改設定檔,而能動態處理任何 input
devices 的支援。
接著,我們來看 XRender extension。
就目前來說,Xft / Fontconfig / Xrender 這三者已經密切的整合在一起。但
是,Xrender 對 Graphics Design 確有其意義在。
引述我之前的筆記:OSD 在 X11 下的實現
[動機]
因為需要發展一套全功能的 Media Player,目前採用的 codebase 是 Xine,在 xine-ui 設計了一套 xitk,能夠處理 OSD (On-Screen Display),但是這不適合通用性處理,所以筆者試著參考 XOSD 這套實作,在追蹤後,發現很難在視覺效果與效能上有所突破,是此依循分析結果,紀錄 OSD 在 X11 下的實作心得,以及效能衝擊的瓶頸。
[現有的問題]
X Window System 是個 Client-Server 的架構,在此架構下的效能衝擊因素之
一就是大量的資料傳輸,當然,多數的情況下,只是少量資料的傳遞,比方說將
某個視窗 Window 移動到座標軸 [x,y] 之處一類的操作,然而,只要圖片或影
像涉入後,效能的衝擊就相當明顯。
有許多途徑相繼被提出,比方說透過 shared memory (亦即 SHM extension),
但是為了一般性,或者在不依賴 extension 的前提下,我們應該儘可能避免資
料傳遞。
X 有兩種互補的型態:Pixmap 與 Image。就 X client 的觀點,Pixmap 就是個
整數型態的 handle,而 Image 則是一個巨大的 struct,事實上,Pixmap 是存
在於 X server 端的圖形資料,而 Image 是存在於 X client 的資料。這兩者
可以轉換,但是效能成本就相當不小了,在半透明 (translucent) 視窗的實現
中,這是很嚴重的效能衝擊,而另外一個議題就是,我們無法在不對 Screen 作
polling 的前提下,得知 Window 下資料是否更動過,甚至就算當我們發現
Screen 已經被更動了,Window 本身卻對我們想取得的 Screen 資料一無所知。
是此,過去 X11 許多半透明實作來說,意味著效能上的衝擊,因為必須訴諸許
多 polling 與大量資料傳輸。
在未引入 XFree86 4.x 提出的 Xrender extension 之前,半透明效果是透過這
樣的方式實作的:先捕捉我們 Window 所在的 Screen 的 snapshot,然後在 X
client 端施加 Alpha composition,以達到我們想要的效果。這樣會有兩個效
能疑慮:
- snapshot 需要取得 X client 的圖形資料 (緩慢的資料傳輸)
- 在 Alpha composition 後,圖形資料必須被傳回 (再度緩慢的資料傳輸)
大家可以想見周旋在 Client<—>Server 之間的資料傳輸量是何等的大。
[改善的方式]
Xrender 一開始被提出的訴求是為了支援 anti-aliased 字型。在字體邊框的 pixel rendering 相當類似 composition,簡單來說,這類的狀況就是我們的繪圖呈現跟背景有關,所以 Xrender 還提供一些與 Glyphs 有關的資料型態,這是通用性的 composition 處理。而上述半透明效果實作遇到的問題,可以透過很明顯的解法處理,就是將 composition 轉交給 X server 處理,這基本上就是 Xrender extension 所作的項目,Xrender 提供另一個資料型態:Picture,類似 Pixmap 的整數型態 handle,但是具備 Alpha channel。
两个概念:
- glyph:字或字體,是指字的實體圖像
- character —> 字的抽象描述
Xrender 在 X server 端繪製 text,所以真正取得這些處理過的 pixel 需要透
過 socket 傳輸這些特化的資料。
shape functions (使用 bitmask) 處理 X server 端的 bitmap,如果我們讓
Xrender 在一個 bitmap 上作顯示,這樣的話,所需的過程就簡化為:
Screen --> Image (slow)
Image --> Pixmap (slow) --------+
| Xrender
(medium) Pixmap <------+
\
\ |
\|
shape function (fast)
於是乎,我們將 two-way roundtrip 降到可接受的 one-way roundtrip
[實作議題]
我們可以針對 1-bit transparency 使用 Shape extension,移去所有沒有涵蓋
於我們要顯示的文字以外的 Window,然後,複製桌面背景到剩餘的 Window,最
後透過 Xft 來描繪字形,這有無法避免的 round-trip,需要將這些 Window
「碎片」傳遞給 X client,除非有個直接使用 Pixmap 的 XGetImage() 與
XCopyArea() 函示。這樣一來,理論上已經可以在 X client 端完成所有的
composition。
相信很多朋友都看過 Sun Project Looking Glass 的成果, 一定對裡頭的設計
有相當的好奇,而 MacOS X 種種華麗的效果也不在話下。
Sun Project Looking Glass Demo:http://jserv.sayya.org/freedesktop/lg3d-demo.mov
而 X Window System 的設計下,有無可能達到類似的效果呢?
X 中的 Window Manager 是個很好的發揮題材,也有所謂的 3D Workspace 套件
現身,但是這並未能根本的、透明化的,以及高度的通透整合起來。所以,
keithp 開始思考這個議題。
Xfixes / XDamage / Composite Extension
Composite Extension 必須搭配另外兩個 extensions : Xfixes / XDamage /
Composite Extension。
Xfixes 的命名非常有意思。"fixes" 什麼呢?因為我們必須對現有的 Window
作重構的動作,比方說陰影、透明化,甚至扭轉的特校。
在 keithp 的想法中,XDamage extension 就是用以作碎片的切割,Programmer
可以依據特定的邏輯將該 Display / Screen 作處理。Xfixes 接著將這些「碎
片」再給予調整,比方說作外框、Alpha blending 等處理,最後,Composite
extension 作個最後的呈現。
需要注意的是,Composite extension 在 XFree86 4.3 以前就存在了,但是
Xorg X11R6.8 則是整合這三個 extensions。
同時,我們也可以發現當今 3D Desktop/Workspace 的趨勢已經不再是發展炫麗的特校。已經有太多基礎建設很完備了,問題在於「如何快速、無痛的移轉現有的操作環境?」
See Also
http://ircconf.debian.org.tw/log/2004-12-30.log
|