在工作的過程中逐漸有了總結一下當前Gfx技術棧的想法,方便自己對Linux Gfx的整體結構有更好的理解。
總的來說,這一些列文章大部分會翻譯自https://blogs.igalia.com/itoral/,這是在查資料的過程中發現的一個老哥的博客,其中對Linux Graphics的理解寫的很好。中間根據我的理解會插入一些知識點的補充。
本篇文章會對Linux Graphics技術棧做一個簡短的介紹,將着重於提供足夠的背景知識來理解Mesa和3D驅動程序在技術棧的作用,以便后續文章中深入了解Mesa和Intel DRI驅動程序的本質。
一點歷史
為了理解當前Graphics技術棧的一些特性,理解Graphics技術是如何變化以適應這些年不斷變化的需求和挑戰是非常重要的。
正如你所知,現在的Graphics技術比過去要復雜得多,在早期只有一種軟件可以直接訪問圖形硬件:X server。這種方法簡化了Graphics Stack,因為它不需要在多個客戶端之間同步對Graphics hardware的訪問。
在早期,Application將通過X server間接完成所有繪圖。通過使用Xlib,他們將通過X11協議發送渲染命令,X server將接收、處理並轉換為套接字另一側的實際硬件命令。請注意,此“轉換”是driver的工作:它將一組與硬件無關的渲染命令作為輸入,並按照目標GPU的預期將其轉換為硬件命令。
由於X server是設計中唯一可以與Graphics hardware通信的軟件,因此這些driver是專門為其編寫的,成為X server本身的模塊和其體系結構的一個組成部分。這些user space driver在X server argot中稱為DDX driver,它們在Graphics Stack中的作用是支持Xlib導出的2D操作以及X server實現所需的2D操作。
例如在我的ubuntu系統中,Intel GPU的DDX driver就來自xserver-xorg-video-intel package,對於其他GPU廠商來說也有類似的package.
3D Graphics
上述內容涵蓋了2D Graphics,因為這正是X server過去的全部內容。然而,3D Graphics hardware的到來極大地改變了場景,我們現在將看到這一點。
在Linux中,3D Gpraphics是通過OpenGL實現的,因此人們希望該標准的實現能夠充分利用3D Graphics hardware,即硬件加速(hardware accelerated)的libGL.so. 然而在一個只允許X server訪問Graphics hardware的系統中,我們不能使用libGL.so直接與3D硬件進行溝通。相反,解決方案是提供一個OpenGL實現,它通過X11協議的擴展將OpenGL命令發送到X server,並讓X server將這些命令轉換為實際的硬件命令,就像之前對2D命令所做的那樣。
我們把上述過程叫做間接渲染(Indirect Rendering),因為application沒有直接把渲染命令發給graphics hardware,而是通過X server間接渲染。
不幸的是,開發人員很快就會意識到,這種解決方案不足以滿足密集型3D application(如游戲)的需要,這些應用程序需要在保持高速率的同時渲染大量3D圖形。問題很明顯:在X11協議中包裝OpenGL調用不是有效的解決方案。
為了在3D application中獲得良好的性能,我們需要這些程序來直接訪問hardware,這需要重新考慮大塊的Graphics Stack。
Enter Direct Rendering Infrastructure (DRI)
Direct Rendering Infrastructure(DRI)是一種新的體系結構,它允許X client直接與Graphics hardware對話。實現DRI需要對Graphics stack的各個部分進行更改,包括X server、kernel 和各種client lib。
盡管術語DRI通常指的是完整的體系結構,但它通常也僅指中涉及application與X server交互的特定部分,因此在網上查閱相關資料時,尤其需要注意這一雙重含義。即下圖中的OpenGL DRI driver, 負責與OpenGL application直接交互,也可以與X server交互。
DRI的另一個重要部分是Direct Rendering Manager(DRM)。這是DRI體系結構中的kernel side。在這里,kernel處理諸如硬件鎖定、訪問同步、視頻內存等方面。DRM還為用戶空間提供了一個API,可用於以適合現代GPU的格式提交命令和數據,從而有效地允許user space與graphics hardware通信。
需要注意的時,許多操作都必須專門針對target hardware(目標硬件)進行,因此每個GPU都有不同的DRM驅動程序。在我的Ubuntu系統中,英特爾GPU的DRM模塊是通過libdrm-intel1:amd64包提供的。
DRI/DRM提供了使user space application能夠以高效和安全的方式直接訪問圖形硬件的構建塊(building blocks),但為了使用OpenGL,我們還需要另一個software,該軟件使用DRI/DRM提供的基礎設施,在滿足X服務器要求的同時實現OpenGL API。
Enter Mesa
Mesa是OpenGL規范的自由軟件實現,它提供了一個libGL.so,使得Linux中基於OpenGL的application可以用libGL.so來輸出3D圖形。Mesa可以在其OpenGL API的實現(Implementation)中,利用DRI架構獲取對底層Graphics hardware的直接訪問,從而提供3D硬件加速。
當我們的3D應用程序在X11環境中運行時,它會將其圖形輸出到X server分配的surface(window)。但是,請注意,對於DRI,這將在沒有X服務器干預的情況下發生,因此在這兩者之間自然要進行一些同步,因為X server仍然擁有Mesa正在渲染的窗口,並且是負責在屏幕上顯示其內容的窗口。OpenGL應用程序和X server之間的同步是DRI的一部分。Mesa對GLX的實現(針對X11平台的OpenGL規范的擴展)使用DRI與X server對話並完成此任務。
Mesa還必須在許多方面使用DRM。與Graphics hardware通信是通過發送命令(例如“繪制三角形”)和數據(例如三角形的頂點坐標、其顏色屬性、法線等)實現的。這個過程通常涉及在圖形硬件中分配一組buffer,在這些buffer中復制所有這些命令和數據,以便GPU可以訪問它們並執行其工作。這是由DRM驅動程序實現的,DRM驅動程序負責管理視頻內存,並向user space(本例中為Mesa)提供API,以便為特定的目標硬件執行此操作。當我們需要在Mesa中分配和管理視頻內存時,也需要DRM,因此創建紋理、將數據上載到紋理、分配顏色、深度或模具緩沖區等都需要為目標硬件使用DRM API。
What’s next?
本篇解釋了Mesa在Linux圖形堆棧中的作用,以及它如何與DRI協同工作,通過OpenGL實現高效的3D Graphics。在下一篇文章中,我們將更詳細地介紹Mesa,我們將看到它實際上是一個多個OpenGL驅動程序共存的框架,包括多種hardware和software,我們還將查看其目錄結構並確定其主要模塊,介紹Gallium框架等