導航欄網站模板特效搭建一個網站的流程
WayLand的架構和協議
1. Wayland簡介
1.1 Wayland
是啥?為啥它這么重要?
嘿,你知道嗎?有時候咱們用電腦的時候,是不是覺得圖形界面有點慢、有點卡?那是因為我們還在用一個叫X Window System (X11)
的老伙計。這個老伙計雖然功不可沒,但畢竟年紀大了,有些力不從心啦。這時候就輪到我們的新朋友——Wayland
登場了!
1.2 Wayland
背后的故事:它是怎么來的?
話說2008年的時候,有個叫Kristian H?gsberg的人,他想:“為什么不能有一個更好的方式來處理圖形呢?”于是他就開始了Wayland
項目。經過多年的努力,Wayland
逐漸成長起來,現在已經被很多主流桌面環(huán)境如GNOME
和KDE Plasma
所采用??梢哉f,Wayland
已經成為了Linux社區(qū)的新寵兒。
1.3 Wayland
的夢想:它想帶給我們什么?
簡單來說,Wayland
想讓你的電腦圖形體驗變得更棒!它通過簡化圖形渲染流程,直接與硬件對話,減少不必要的通信層,從而提高了性能和安全性。對于開發(fā)者而言,這意味著更少的代碼維護工作;對于用戶來說,則意味著更流暢的操作體驗。
2. Wayland架構
2.1 X和Wayland:兩者架構有何不同?
來聊聊X
是怎么處理輸入到顯示的
想象一下,當你在使用基于X
的應用時,每次你點擊鼠標或者敲擊鍵盤,都會觸發(fā)一系列復雜的步驟,直到最終的變化出現在屏幕上。這個過程有點像一個接力賽,每個環(huán)節(jié)都至關重要。
首先,內核會通過evdev
輸入驅動捕捉來自設備(如鼠標或鍵盤)的事件,并將這些事件發(fā)送給X Server
。這里,內核做了很多重活,它負責管理硬件并將各種特定于設備的事件協議轉換成統(tǒng)一的Linux evdev
標準格式。
接下來,X Server
要決定哪個窗口應該接收這個事件,并將其轉發(fā)給那些已經注冊了該類型事件監(jiān)聽的客戶端。但是,這里有個小問題——X Server
并不完全清楚窗口的實際位置和狀態(tài),因為這些是由合成器控制的,而合成器可能會對窗口進行各種變換(縮放、旋轉、特效等),這些變化是X Server
所不了解的。
然后,接收到事件的客戶端根據需要更新用戶界面。比如,你可能點擊了一個復選框,或者鼠標指針進入了某個按鈕區(qū)域,這時就需要高亮顯示。因此,客戶端會向X Server
發(fā)送渲染請求。
當X Server
收到渲染請求后,它會把任務交給顯卡驅動,讓其直接編程硬件完成渲染工作。同時,X Server
還會計算出渲染影響的屏幕區(qū)域,并向合成器發(fā)送一個損壞事件(damage event),告知合成器需要重新組合那一部分屏幕內容。
最后,合成器會通知X Server
,由它來決定是直接復制合成器的后臺緩沖區(qū)到前臺緩沖區(qū),還是執(zhí)行一次頁面翻轉(pageflip)。這一步驟對于處理窗口重疊等情況非常重要,但對于總是全屏顯示的合成器來說,就顯得多余了,因為它引入了不必要的上下文切換。
現在輪到Wayland
登場啦!
在Wayland
的世界里,整個流程變得更加簡潔高效。這里的關鍵點在于,合成器就是顯示服務器本身,這意味著我們可以直接從內核獲取事件并立即傳遞給合成器,而不需要經過額外的中間層。我們還把KMS
(模式設置)和evdev
的控制權交給了合成器,進一步簡化了架構。
這個過程大致如下:
-
內核依舊負責捕捉輸入事件并通過
evdev
接口發(fā)送給合成器。這部分與X
的情況相似,所以我們可以繼續(xù)利用內核中已有的輸入驅動。 -
合成器則會根據它的場景圖(scenegraph)來確定哪個窗口應該接收事件。由于合成器掌控著所有窗口的狀態(tài)及其可能應用的各種變換,它可以準確地選擇正確的窗口,并將屏幕坐標轉換為窗口本地坐標。只要合成器能夠計算出針對輸入事件的逆變換,那么理論上可以對窗口施加任何類型的變換。
-
客戶端接收到事件后,就像之前一樣更新用戶界面。不過,在
Wayland
下,渲染是在客戶端這邊完成的,之后只需告訴合成器哪些區(qū)域被更新了即可。 -
合成器收集來自各個客戶端的損壞請求,然后重新組合屏幕內容。這個時候,合成器可以直接調用
ioctl
命令通過KMS
安排頁面翻轉,無需再經過X Server
這一環(huán)。
這樣做的好處是減少了不必要的通信開銷,提高了系統(tǒng)的響應速度和效率。Wayland
的設計使得每個組件都能專注于自己最擅長的事情,從而構建出了一個更加流暢且安全的圖形環(huán)境。
2.2 Wayland
的圖像渲染
在Wayland
的世界里,所有的視覺內容都是通過緩沖區(qū)
來管理的。應用程序想要顯示任何東西時,它會在自己的內存空間中創(chuàng)建一個或多個圖像緩沖區(qū),并將這些緩沖區(qū)提交給合成器(compositor)
。合成器
扮演著藝術家的角色,負責將這些圖像組合成最終的畫面,展示給用戶。
Wayland
利用現代GPU
的強大功能,確保無論是播放視頻還是運行3D游戲,都能提供即時響應的速度。所有繪圖命令都通過DMA-BUF接口發(fā)送給GPU,這保證了即使在多任務環(huán)境中也能保持高效運作。
客戶端渲染機制
當X Server
被移除后,傳統(tǒng)的X
客戶端渲染機制也隨之消失。但Wayland
引入了直接渲染(direct rendering
)作為替代方案,這一機制已經在X
的DRI2
中有所體現。在直接渲染模式下,客戶端
和合成器
共享一塊視頻內存緩沖區(qū)。客戶端鏈接到如OpenGL
這樣的渲染庫,該庫知道如何編程硬件,并能夠直接將內容渲染到共享緩沖區(qū)
中。合成器
則可以將這塊緩沖區(qū)用作texture
,當它合成桌面時就能顯示出更新的內容。
硬件支持的重要性
為了使Wayland
能有效工作,良好的硬件支持至關重要。這包括但不限于模式設置/顯示管理和EGL/GLES2等功能。此外,Wayland
還需要一種機制來高效地在進程間共享緩沖區(qū),這部分涉及到客戶端和服務器端兩個方面的工作。
-
客戶端實現:定義了一個
Wayland EGL
平臺,它包含了一套原生類型(如EGLNativeDisplayType
、EGLNativeWindowType
和EGLNativePixmapType
),以及創(chuàng)建這些類型的接口。這是將EGL棧及其緩沖區(qū)共享機制綁定到通用Wayland API
的膠水代碼。開源實現中,mesa EGL棧中的wayland-egl.c
和platform_wayland.c
文件實現了這一功能。 -
服務器端實現:
Wayland
的服務器端即為合成器,它通常集成了任務切換器、應用啟動器、鎖屏界面等核心用戶體驗組件。服務器運行在一個模式設置API之上(如內核模式設置、OpenWF Display或其他類似技術),并通過EGL/GLES2合成器和硬件疊加層(如果有的話)來組合最終用戶界面。為了讓合成器能夠處理來自客戶端的Wayland共享緩沖區(qū),必須啟用EGL_WL_bind_wayland_display
擴展,這樣合成器就可以從任意Wayland共享緩沖區(qū)創(chuàng)建一個EGLImage對象。這個過程首先需要綁定EGL顯示到Wayland顯示,之后每當合成器接收到客戶端發(fā)來的緩沖區(qū)(通常是通過調用eglSwapBuffers
時),它可以將wl_buffer
指針傳遞給eglCreateImageKHR
函數,以EGLClientBuffer
參數的形式創(chuàng)建一個EGL圖像,用于后續(xù)作為紋理或通過模式設置代碼作為疊加平面使用。
3. Wayland協議
WayLand
協議, 是WayLand客戶端與WayLand合成器之間的通訊協議
官方提供的WayLand
協議的參考實現
https://gitlab.freedesktop.org/wayland/wayland
官方提供的WayLand合成器的參考實現
https://gitlab.freedesktop.org/wayland/weston
3.1 協議傳輸與消息格式
Wayland
協議通過UNIX
域流套接字進行傳輸,通常情況下,該套接字的端點名為wayland-0
(盡管可以通過環(huán)境變量WAYLAND_DISPLAY
來更改)。從Wayland
1.15版本開始,實現可以選配支持位于文件系統(tǒng)任意位置的服務器套接字端點,只需將WAYLAND_DISPLAY
設置為服務器端點監(jiān)聽的絕對路徑即可。
每條消息被構造成由多個32位字組成的序列;值以主機的字節(jié)序表示。消息頭部包含兩個32位字:
- 第一個字是發(fā)送者的對象ID(32位)。
- 第二個字分為兩部分:高16位是消息大小(以字節(jié)為單位),從頭部開始計算(即最小值為8字節(jié));低16位是請求或事件的操作碼。
有效載荷描述了請求或事件的參數。每個參數總是對齊到32位邊界;如果需要填充,填充字節(jié)的值未定義。沒有前綴描述類型,而是隱式地從XML規(guī)范推斷出來。
以下是參數類型的表示方式:
-
int
,uint
- 表示32位有符號或無符號整數值。
-
fixed
- 有符號的24.8定點數。它是一種提供符號位、23位整數精度和8位小數精度的有符號十進制類型。在C API中,它作為一個不透明的結構體,并提供了轉換為雙精度浮點數和整數的幫助函數。
-
string
- 以一個無符號的32位長度(包括空終止符)開頭,接著是字符串內容,包含終止的空字節(jié),然后是對齊到32位邊界的填充??罩涤瞄L度為0表示。
-
object
- 32位對象ID??罩涤肐D為0表示。
-
new_id
- 32位對象ID。一般情況下,新對象使用的接口可以從XML推斷出來,但在接口未指定的情況下,
new_id
之前會有一個指定接口名稱的字符串,以及一個指定版本的無符號整數。
- 32位對象ID。一般情況下,新對象使用的接口可以從XML推斷出來,但在接口未指定的情況下,
-
array
- 以32位數組大小(以字節(jié)為單位)開頭,接著是數組內容的直接拷貝,最后是對齊到32位邊界的填充。
-
fd
- 文件描述符并不存儲在消息緩沖區(qū)中,而是在UNIX域套接字消息的輔助數據(msg_control)中。
Wayland
協議并未明確規(guī)定輔助數據在流中的確切位置,只規(guī)定文件描述符的順序與消息及其內部的fd
參數在網絡上的順序相同。
這意味著流中的任何字節(jié),甚至是消息頭部,都可能攜帶帶有文件描述符的輔助數據。
客戶端和合成器(compositor
)應當排隊等待接收的數據,直到他們有完整的消息可供處理,因為文件描述符可能會早于或晚于對應的數據字節(jié)到達。
3.2 核心接口概述
Wayland
協議設計了一套核心接口,用于客戶端與服務器之間的交互。這些接口提供了請求、事件和錯誤(實際上也是特殊類型的事件)的功能,如前文所述。雖然具體的合成器(compositor
)實現可能會提供作為擴展的自有接口,但有一些接口是預期一定會存在的。
以下是Wayland
的核心接口:
-
wl_display
- 作為核心全局對象,它充當了客戶端與
Wayland
服務器之間通信的起點。通過這個接口,客戶端可以獲取其他全局對象,并發(fā)送或接收消息。
- 作為核心全局對象,它充當了客戶端與
-
wl_registry
- 全局注冊表對象,用來枚舉當前可用的全局對象。客戶端使用此接口來發(fā)現并綁定到它們需要的服務。
-
wl_callback
- 回調對象通常用于異步操作的完成通知,比如幀同步。
-
wl_compositor
- 合成器(
compositor
)單例,提供創(chuàng)建surface
和其他圖形資源的方法。
- 合成器(
-
wl_shm_pool
和wl_shm
- 這兩個接口共同支持共享內存池的創(chuàng)建和管理,使得圖像數據可以直接在客戶端和合成器(
compositor
)之間交換。
- 這兩個接口共同支持共享內存池的創(chuàng)建和管理,使得圖像數據可以直接在客戶端和合成器(
-
wl_buffer
- 表示一個
surface
的內容,可以由多種不同方式創(chuàng)建,包括但不限于共享內存。
- 表示一個
-
wl_data_offer
,wl_data_source
,wl_data_device
和wl_data_device_manager
- 這組接口支持數據傳輸功能,例如剪貼板和拖放操作。
-
wl_shell
和wl_shell_surface
- 提供了創(chuàng)建桌面風格
surface
的方法,并為這些surface
提供了額外的元數據接口。
- 提供了創(chuàng)建桌面風格
-
wl_surface
- 屏幕上的
surface
,是所有可視內容的基礎元素。
- 屏幕上的
-
wl_seat
- 輸入設備的集合,每個
seat
代表一組輸入設備,比如鍵盤、鼠標和觸控屏。
- 輸入設備的集合,每個
-
wl_pointer
,wl_keyboard
,wl_touch
- 分別對應指針、鍵盤和觸摸屏等輸入設備的具體接口。
-
wl_output
- 描述合成器(
compositor
)輸出區(qū)域的信息,比如顯示器的幾何屬性和模式。
- 描述合成器(
-
wl_region
- 定義了一個不規(guī)則形狀的區(qū)域,可以應用于
surface
以控制其可見性或其他特性。
- 定義了一個不規(guī)則形狀的區(qū)域,可以應用于
-
wl_subcompositor
和wl_subsurface
- 支持子
surface
組合,允許將一個surface
嵌入到另一個surface
中,形成復雜的用戶界面布局。
- 支持子
上述接口構成了Wayland
協議的基本構建塊,確保了客戶端應用程序能夠與合成器(compositor
)進行高效且安全的通信。
4. Wayland對X11應用的支持
為了讓那些還沒遷移到Wayland
上的老應用繼續(xù)工作,Wayland
引入了一個叫做XWayland
的小幫手。它實際上就是一個小型的X Server
,可以在Wayland
環(huán)境中運行,接受來自傳統(tǒng)X11
客戶端的連接請求,并將它們適配到新的顯示協議之上。這樣一來,用戶就可以在同一桌面上同時運行兩種類型的應用程序,無縫切換毫無壓力。
盡管Wayland
本身并不需要傳統(tǒng)的X窗口管理器
,但在某些情況下(例如通過XWayland
運行X11
應用時),它們仍然扮演著重要角色。此時,Wayland
合成器會充當“超級管理員”,負責協調不同類型的窗口行為,確保整個系統(tǒng)穩(wěn)定運行。
4.1 X11 應用程序的連接方式
X11
應用程序連接到Xwayland
的方式就如同它連接到任何其他X
服務器一樣。Xwayland
負責處理所有的X11
請求,并且在另一端,它作為一個Wayland
客戶端連接到了Wayland
合成器(compositor
)。
4.2 X Window Manager
(XWM) 和 Wayland Window Manager
(WWM)
XWM
是Wayland
合成器(compositor
)不可或缺的一部分。它使用標準的X11
窗口管理協議來管理所有通過Xwayland
運行的X11
窗口。重要的是,XWM
充當了Xwayland
窗口狀態(tài)和Wayland
合成器(compositor
)的WWM
之間的橋梁。這樣,WWM
就可以統(tǒng)一管理所有類型的窗口,無論是原生的Wayland
窗口還是X11
(即Xwayland
)窗口。這對于提供一致的用戶體驗至關重要。
4.3 Xwayland
的工作原理
由于Xwayland
依賴Wayland
進行輸入和輸出操作,所以它不需要像Xorg
那樣使用設備驅動程序。這意味著不會使用任何xf86-video-*
或xf86-input-*
模塊。此外,Xwayland
服務器沒有配置文件。對于可選的硬件加速渲染,Xwayland
采用了GLAMOR
庫。
4.4 單一實例的Xwayland
通常,一個Wayland
合成器(compositor
)只會產生一個Xwayland
實例。這是因為許多X11
應用程序假設它們可以通過X
服務器與其他X11
應用程序通信,而這需要共享同一個X
服務器實例。這也意味著,除非Wayland
合成器(compositor
)特別選擇通過為特定應用程序生成獨立的Xwayland
實例來打破這種通信,否則Xwayland
不會保護或隔離各個X11
客戶端。值得注意的是,X11
客戶端與Wayland
客戶端之間是天然隔離的。
4.5 Xwayland
的兼容性挑戰(zhàn)
盡管Xwayland
盡可能地兼容傳統(tǒng)的X
服務器,但要達到100%的兼容幾乎是不可能的。特別是桌面環(huán)境組件中的X11
窗口管理器基本上不受支持。一個X11
窗口管理器無法識別原生的Wayland
窗口,因此它只能管理X11
窗口。然而,必須有一個XWM
來保留獨占的窗口管理角色,以便Wayland
合成器(compositor
)可以適當地顯示X11
窗口。對于其他的桌面環(huán)境組件,如分頁器和面板,為了在WWM
中通過XWM
支持它們而添加必要的接口往往被認為是不值得的。
4.6 窗口標識與同步通信
在Xwayland
中,一個X11
窗口可能會對應于Wayland
中的一個wl_surface
對象。這個wl_surface
對象用于輸入和輸出:它被輸入事件引用,并用于向Wayland
合成器(compositor
)提供X11
窗口的內容。X11
窗口和wl_surface
存在于不同的協議流中,因此需要將它們匹配起來以使XWM
能夠正常工作。
當Xwayland
在Wayland
上創(chuàng)建一個wl_surface
時,它也會發(fā)送一個類型為原子"WL_SURFACE_ID
"的X11 ClientMessage
給對應的X11
窗口,該消息的第一個32位數據元素攜帶的是wl_surface
的Wayland
對象ID。這是XWM
關聯wl_surface
與X11
窗口的方法。需要注意的是,創(chuàng)建wl_surface
的請求和ID消息可能以任意順序到達Wayland
合成器(compositor
)。因此,在實現XWM
時,需要格外小心以避免(隨機)死鎖。強烈建議所有來自XWM
的X11
通信都應該是異步的,因為證明同步或阻塞的X11
調用不會導致死鎖通常是極其困難的。所有Wayland
通信已經天生就是異步設計的。
5. 總結
本文介紹了Wayland
作為新一代顯示服務器協議,旨在替代傳統(tǒng)的X Window System (X11)
,為Linux
及其他類Unix
系統(tǒng)提供更高效、安全的圖形界面體驗。
Wayland通過簡化圖形渲染流程,直接與硬件對話,減少了不必要的通信層,提高了性能。其架構中合成器即為顯示服務器,可直接從內核獲取事件并傳遞給合成器,避免了額外中間層,從而減少通信開銷。Wayland
利用現代GPU功能確保圖像內容即時響應,通過DMA-BUF接口發(fā)送繪圖命令保持高效運作。
在Wayland協議方面,它定義了一套核心接口,用于客戶端與服務器之間的交互,包括wl_display、wl_registry等,確保應用程序能與合成器進行高效安全通信。
此外,為了兼容傳統(tǒng)X11
應用,引入了XWayland
作為小型X Server,在Wayland環(huán)境中運行,使新舊應用無縫共存。然而,盡管XWayland盡力兼容,仍存在一定的兼容性挑戰(zhàn),特別是對于X11窗口管理器的支持有限。