原文連結 : 2D Drawing APIs in Windows
背景知識 : Windows 圖形編程
在 Windows 7 作業系統中,微軟花費了很大的力氣構建了一套新的 2D 繪圖 API。我們稱之為 Direct2D ,隸屬於 DirectX 家族。這個 API 的開發填補了 Windows 圖形平台的一些缺陷。其中非常重要的一點就是普通的 2D 程式渲染不再缺乏硬體加速。而在 Windows Vista 中,我們知道 GDI 是無法進行硬體加速的。微軟寄望於開發的這個 API 具備很多現代特性。比如支援消除鋸齒和 Alpha Blend 的 2D 渲染,和其它現代圖形 API 互動,伺服器端渲染,諸如此類。
為了方便理解微軟為何開發 Direct2D ,我們先來回顧一下當初開發 Windows 時的曆史。最初的渲染系統叫做 GDI (圖形裝置介面),今天仍然存在。它最初為 16 位 Windows 寫就,隨後升級到 32 位 Windows (Windows 95 和 Windows NT)。因為 GDI 是為很久以前那些計算能力低下的電腦而開發的,所以它並沒有諸如消除鋸齒之類的特性,大多數 API 亦不支援 Alpha 通道。
在 Windows 95 期間,DirectX 發布了第一版。DirectDraw 是其中最早的組件之一。當初的本意是在硬體加速啟用的情況下,開發人員可以繞過 WinG 允許,直接存取硬體。這樣的一個協議堆棧既可以和 GDI 協作,但是又真正處在同一地位。
隨著圖形硬體(顯卡)演化,GDI 通過 DDI (裝置驅動介面) 獲得了硬體加速的能力。很多視訊卡實現了這些 DDI ,而通過購買一塊視訊卡來改善你的 Windows 效能亦成為平常之事。接下來,Direct3D 進駐到 DirectX 2 中,當然它也建立了自己的 DDI 集。隨之,視訊卡開始投入越來越多的精力來使得 3D 圖形越來越快,以便維持遊戲市場巨大的需求。最後導致誕生了兩個不同的領域 : 硬體加速和圖形編程。前者圍繞於 Direct3D 構建,後者則圍繞於 GDI 。
Direct3D 和 GDI 構建於不同目標,不同位置的事實意味著它們並不能像人們期望的那樣能夠良好的工作在一起。雖然實現了不少像 GetDC 這樣的協助橋接特性,但是在大量交叉渲染的情境下它們總是存在著或這或那的一些問題。儘管如此,微軟並沒有移除這些待解決的情境需求。
到了世紀之交,GDI 的限制越來越顯現。微軟針對這些功能缺陷做了一個 GDI 擴充,即 GDI+ 。這些擴充提供了諸如位元影像操作,畫筆,消除鋸齒和越來越複雜的 Primitive 渲染中不同像素深度格式,Alpha Blend 的支援。同時,GDI+ 亦包括了諸如開啟 Png 和 Jpg 格式檔案的映像操作支援。然而,GDI+ 新增的全部操作都沒有硬體加速支援。
GDI+ 在託管世界中非常流行,這主要得力於它是 System.Windows.Drawing 命名空間的主力。每一個客戶自訂渲染的非常漂亮的 Windows Form 程式都使用 GDI+ 來當此大任。但是,構建於 GDI 之上的 GDI+ 同樣繼承了與 Direct3D 互動的所有問題。事實上,因為它總是軟渲染,在某些情境下,它會變得更糟。
當時間走到計劃研發 Windows 7 時,很明顯,微軟需要解決很多互通性的不足,以及不平衡的硬體加速能力。保留現有的 API 且要達到上述目的是相當困難的事情。GDI 有很長的曆史,這需要應付海量的應用程式相容性問題。如果要把 Alpha Blend 支援(舉例) 弄進 GDI 核心 API 集合,而且還不得罪現有的客戶無異於天方夜譚。因為 GDI+ 構建於 GDI 之上,舊有的陋習同樣讓它獲得硬體加速能力變得難以實現。
解決方案就是建立新的 API 來囊括我們想要的功能和處理互通性問題。MIL 代碼(WPF 處理渲染的原生組件)是一個很方便的起點。它有著我們想要的渲染特性,而且同時提供了軟體渲染和硬體加速。
首先需要做的事情是使渲染代碼基於 D3D 10.1 ,而不是 D3D 9 。之所以這樣決定是因為有一些構建於這個運行時版本的其它技術把 D3D 10.1 作為基礎(10Level9,WARP,D3D Primitive Remoting)。而且我們還可以看到未來的硬體同樣構建於這個架構之上。這樣就能允許我們來設計 D3D 10.1 互通性。因此就能允許與其它技術互動,比如 Direct2D 。
另外一個互通性工作就是利用視窗管理器和 DXGI ,以確保 Direct2D 和 GDI 能夠共同工作。你可以使用 Direct2D 繪圖到 GDI 目標,同理,反之亦可。 但是,從效能的角度來看,這些特性並非免費。它只是讓那些構建在這兩種混合 API 上的應用程式能夠平滑過渡到新世界。
前面所作的工作中很重要的一塊就是盡量使得此 API 在效能方面富於表現力。對於開發人員來說,WPF 的好處在於它做了很重要的資源管理工作,但卻使得直接控制硬體變得困難起來。這聽起來貌似很簡單,但是這背後有著大量的設計決定以確保 GPU 記憶體沒有分配給不需要之人,且仍然能夠允許人們構造他們之所想。因此遵循了這樣一個原則的 Direct2D 設計和資源/執行緒模式就能夠允許伺服器端渲染進行合適的伸縮。GDI 卻不能。
此外,對於處理文本和映像可以分別採用 DirectWrite 和 WIC 。這表明了微軟 DirectX 家族正更加組件化。Direct2D 以一種互補的方式對 DirectWrite 文本和 WIC 位元影像操作提供硬體加速支援。
最後想說的是,我們構建了一個支援硬體加速的 2D 渲染 API (帶有軟渲染)。它有著現代渲染原語集合,能和以前的 API 進行互動。我們認為它完全可以取代作為大多數應用程式開發情境所使用的 GDI/GDI+ API ,而且也可以作為某些遊戲開發情境中 D3D 10.1 的補充。微軟構建的這麼一套組件化的技術集合完全允許開發人員混合搭配以構造以前難以構造的事物。比如把已定位的文本像素直接渲染到 Direct3D 紋理當中,而不需要任何字型的支援。