1. 程式人生 > >XRender 擴充套件的設計和實現(Design and Implementation of the X Rendering Extension)

XRender 擴充套件的設計和實現(Design and Implementation of the X Rendering Extension)

原文地址:https://keithp.com/~keithp/talks/usenix2001/xrender/,本文僅做翻譯。

     X Rendering Extension(或者說render,XRender)是X11核心協議的擴充套件,用於在X Server中實現影象合成。

一、摘要

    在2000年的Usenix技術大會,介紹了X渲染環境以及將X呈現出來所需的能力。 在過去的一年中,新的擴充套件,作為標準XFree86發行版的一部分,已經被設計和實現。
    X渲染擴充套件解決了核心X渲染架構中的許多問題,並且沒有顯著地增加協議解釋或是增加伺服器負擔。通過借用Plan 9視窗系統的基本影象合成概念並提供複雜和可擴充套件的字型渲染,XFree86可以更好地支援現有應用程式,同時鼓勵使用者介面的新發展。在精確的多邊形光柵化和影象變換領域仍然有很多工作有待我們去完成。

二、簡介

    在2000年的Usenix會議上,學者提交了一篇論文,討論了核心X渲染架構中存在的問題以及可能的解決方案。根本問題是:渲染系統的編碼實踐,事後很快就會被廢棄。急於釋出原始的X11標準,沒有時間留給技術問題的解決。最重要的問題是那個時代的硬體不能支援複雜的互動式視窗系統。

    去年的一些論文 - alpha合成,抗鋸齒,亞畫素定位和梯形 - 都包含在這個新的擴充套件中。擴充套件的其他部分,如客戶端字型管理是在擴充套件設計期間開發的。

    擴充套件版本的開發以開放的方式進行,並且從視窗系統社群的各處獲得輸入。參與XFree86,KDE,Qt,Gdk,Gnome和OpenGL的人都為最終架構的形成作出了貢獻。

    但是規範的某些方面仍然不夠完善。工具包和應用程式開發從XRender中收益,因此它已經成為XFree86發行版的重要部分。它還傳達出了一個強烈的訊號:XFree86已準備就緒並能夠將X Window系統的開發推向未來。

三、渲染模型

    XRender 與核心X 渲染系統不同,用RGB模型替換基於畫素值的模型。雖然客戶端仍然可以看到畫素值,但每個畫素值(即使儲存在畫素圖中的畫素值)都有一個與之關聯的顏色值。這樣就可以提供基於顏色的自然成像,同時仍允許應用程式在必要時檢視畫素值。

    這種改變帶來的一個問題是偽彩色視覺效果。最好的方法是動態分配顏色以最接近地匹配顯示的顏色。但是,偽彩色桌面的數量正在減少,取代它的是靜態顏色模型。這樣可以大幅減少執行時的負擔,同時仍然允許應用程式在偽彩色硬體上執行。 (事實上​​,目前的XFree86實現甚至沒有這種簡化的支援,但迄今為止還沒有提交錯誤報告。)

    除了將影象資料呈現為顏色值之外,Render還使用由Porter和Duff兩人在1984年正式提出的影象合成操作取代核心協議中的光柵化操作。這些操作指令通過引入透明度和允許當影象一層一層的疊加時顏色資料混合的方式來獲得顏色資料。

    Porter-Duff混合模型統一了半透明的概念:畫素完全被非不透明值(non-opaque value)覆蓋,具有區域性覆蓋的概念,其中一部分畫素被覆蓋而剩餘部分未被覆蓋。渲染使用部分覆蓋來近似抗鋸齒;沿著幾何物件邊緣的部分覆蓋的畫素被渲染為好像它們是半透明的。

    Render中的所有操作都是根據原始運算操作合成的,產生一致的模型同時支援最簡單的實現。渲染模型的設計宗旨是:通過儘可能簡單的方式提供必要的服務操作,使其與現代工具包和應用程式配合良好。

3.1影象合成

    從物理學上來說,半透明物體會吸收一些照射在它身上的光但不是全部。物體的顏色會影響哪些波長吸收最多。在視覺上,半透明物體似乎會影響其他物體的顏色和亮度。

    部分遮擋視野的和半透明物體的效果是相似的;在足夠精細的解析度下,在物件邊緣附近的點處取樣的顏色將顯示為上層和下層顏色的混合。Porter和Duff使用此屬性將部分覆蓋轉換為半透明。

    光對半透明物件的影響可以通過將半透明物件的顏色與旁邊物件的顏色混合來模擬。當處理計算機影象時,半透明度可以描述為對影象集合顏色資料的數學運算。Porter和Duff利用顏色資料和稱為“alpha”的每畫素不透明度值組成的公式建立模型。利用這些公式,可以執行許多直觀的影象處理。

3.1.1影象合成運算

    由Porter和Duff定義的運算獨立地在每個畫素的每個顏色通道上操作。為了顯示每個畫素點的每個通道上的操作方程式被縮寫。

    常見的合成操作是將一個影象放在另一個影象上。上層影象的透明區域中可以顯示底層影象,不透明區域隱藏底層影象,而半透明區域將兩個影象混合在一起。將畫素的“alpha”定義為0到1之間的數來衡量不透明度,那麼可以用一個簡單的等式將兩個畫素顏色組合在一起:

                                                         

 

    Porter和Duff稱之為“over”運算。

    另一個常見的操作是用另一個影象掩蓋本影象;透明區域從影象中移除,而不透明區域使得影象可見。

                                                            

    這是“in”運算。 他們提出了完整的合成代數和其他操作,但是此擴充套件中只需要這兩個。

    這個模型的一個重要方面是它建立了一個新的影象描述——為每個畫素附加了一個值“alpha”。該值測量畫素的“不透明度”,並且可以通過渲染函式和顏色分量進行操作。

3.1.2目標Alpha

     有時,建立本身半透明的合成影象很有用,換句話說,包含alpha值。這種效果可以通過增加操作來實現,該操作可以產生複合α值和顏色值。 對於“over”運算操作,複合alpha值定義為:

                                                

“in”運算子複合alpha值是:

                                                           

生成的影象現在可用於其他渲染操作。

3.1.3預乘Alpha

      上面用於計算“over”運算的等式中,可以看到alpha和顏色分量的計算方式存在不對稱性:

                                               

                                        

      將影象資料重新指定為“由alpha預乘”。影象中的每個顏色分量由該分量乘以相應的alpha值代替。Blinn 指出:預乘影象在執行長序列操作時可以輕易獲得正確的結果,而非預乘影象則涉及笨拙的計算。因此所有四個元素在一個方程式中表示為:

                                               

3.2渲染合成基礎

      由Russ Cox和Rob Pike設計的Plan 9 Window系統提供了基於Porter-Duff合成的統一渲染操作:

                                          

      所有畫素操作都是通過此操作完成的,該操作在整個渲染系統中提供了一個簡單且一致的模型。渲染採用此操作但稍做擴充套件。Plan 9僅提供OVER運算,Render允許使用Porter和Duff定義的所有運算子和專為從OpenGL中來的抗鋸齒圖形的繪製而設計的特殊運算。渲染操作如圖1所示。

 

     使用此基本渲染操作,擴充套件通過指定隱式掩碼的構造來定義幾何操作,然後在一般操作中使用該隱式掩碼。通過沿邊緣生成具有部分不透明度的隱式掩碼來模擬消除鋸齒圖形

四、基本渲染物件

      與大多數X擴充套件一樣,Render添加了許多X伺服器端資料型別來封裝上面表達的概念:

4.1PictFormat

     PictFormats儲存將畫素值轉換為紅色、綠色、藍色和Alpha通道所需的資訊。伺服器具有與螢幕上的各種視覺效果對應的圖片格式列表,表示pixmaps儲存的各種格式的資料的附加格式。有兩種格式:索引和直接。索引的PictFormats包含畫素值和RGBA值的列表,而直接PictFormats為R,G,B和A中的每一個保持位掩碼。

    直接PictFormats可能包含所有R,G,B和A,或者它們可能只包含R,G和B或僅包含A。後兩者為單獨的alpha掩碼和沒有目標alpha通道的伺服器視覺效果提供必要的格式。

    每個索引PictFormat都有一個關聯的色彩對映表,從中可以分配相關的顏色值。這允許多個不同的索引格式共存,允許應用程式選擇最佳匹配格式,併為以該格式呈現的視窗選擇關聯的色彩對映。

4.2Picture

     Picture將X Drawable(視窗或Pixmap)與合適的PictFormat連線起來。它們還可以作為放置與圖片相關的渲染狀態的便利位置。當PictFormat不提供Alpha通道時,Picture可能會引用外部Alpha通道,該通道表示為另一個Picture,其中僅使用alpha通道。如果沒有此外部Alpha通道,則每個畫素的圖片隱含alpha值為1。

     Picture是Render中的通用畫素資料表示。沒有為任何操作提供明確的畫素值。純色或重複圖案時,圖片具有“重複”屬性,設定後,通過沿兩個軸將圖片內容平鋪展開,圖片將被視為無限資料來源。

     這允許純色填充,平鋪和點畫是物件到物件資料複製的特殊情況。

     一個附加屬性允許在具有已知子畫素幾何形狀的顯示器上優化影象顯示。在這樣的環境中,應用程式需要控制每個顏色元件的合成。通常合成運算操作使用相同的alpha值混合所有四個元件。當合成原始碼中的mask圖片運算元設定為“ComponentAlpha”屬性時,R,G,B和A值被解釋為孤立地在每個通道上操作的alpha值。

4.3複合請求

     Render擴充套件的核心是單個請求:所有其他渲染都是通過基本複合渲染操作的Composite定義的。 此運算子在Render規範中定義如下:

                                                    

     此請求通過使用op合成運算將特定的src矩形和dst矩形的掩碼結合。座標是相對於它們各自的繪圖原點的。渲染被剪裁為dst drawable的幾何體,然後剪下到dst剪輯列表,src剪輯列表和掩碼剪輯列表。

     如果指定的矩形超出src,那麼如果src設定了repeat屬性,則src圖片將被平鋪以填充指定的矩形。否則渲染會剪下到src幾何體。

    如果指定的矩形超出了掩碼,那麼如果掩碼設定了重複屬性,則將平鋪掩碼圖片以填充指定的矩形,否則渲染將剪下到掩碼指定的幾何體。

    如果src,mask和dst的格式不同,並且其中一種格式可以保持全部而不會丟失精度,則它們將轉換為該格式。或者,伺服器將每個運算元轉換為保留格式。

    如果mask為None,則將alpha設定為常量值1。

    當dst具有剪輯通知集合時,如果渲染操作未被src或掩碼剪下,則傳送NoExpose事件,否則傳送一系列 GraphicsExpose事件,覆蓋dst中由src或mask剪下渲染的區域。

    關於這個定義的一些重要說明:

  •   運算元格式不需要匹配;渲染會自動將轉換為最精確的格式或內部保留格式,以防所提供的格式無法在不丟失的情況下儲存資料。
  •  通過設定源圖片的“重複”屬性可以控制實心填充、圖案和影象複製。
  •  通過使用適當的影象填充“mask”來繪製幾何物件,然後可以使用這些物件來模板化任何圖案。

4.4客戶提供的即時資料

     由於Pictures是Render中畫素資料的唯一表示,因此應用程式生成的影象必須使用現有核心中的X PutImage請求來將該資訊傳輸到伺服器。未來的擴充套件可以提供新的影象傳輸功能:消除中間緩衝和提供標準影象壓縮演算法,以減少網路環境中的大量影象資料所消耗的頻寬。

五、文字渲染

     字型管理和文字渲染一直是讓架構設計者和應用程式開發人員感到頭疼的部分。 X試圖將字型抽象為簡單的點陣圖影象和描述為簡單字串或整數值的相關資料。影象的光柵化留給了X伺服器,應用程式無法通過標準的X介面訪問高階字型資訊,例如字距調整表和連字。

     許多應用程式在面對X文字模型時,放棄並完全在應用程式中實現所有文字顯示——將生成的顯示影象直接傳送到X伺服器。 X文字渲染程式碼被降級為按鈕和對話方塊訊息的繪圖標籤。這樣不能有效地利用圖形系統的巨大加速潛能。

     在為Render擴充套件構建類似系統的過程中,有幾個因素共同將開發導向一個全新的方向。第一個是認識到應用程式需要直接訪問完整的字型資訊,最好是原始字型檔案本身。只有通過這種直接訪問才能確保應用程式能夠獲得有關字型的所有資訊。

    最初的渲染協議通過擴充套件現有的X字型服務協議來提供此訪問。應用程式和X伺服器通過X字型伺服器和應用程式請求高階字型屬性。通過現有的字型檔案格式或者使用某個格式,來顯示所有的資訊,這是一項艱鉅的任務,因此在開發擴充套件影象的組成部分時推遲了這項任務。

    改變文本系統方向的第二個因素是:關於PDF檔案和嵌入字型資料的討論。與其他應用程式一樣,PDF檔案要求顯示僅應用程式可用的字型。在現有字型框架中使用應用程式提供的字型的唯一可移植機制是:讓應用程式通過在應用程式中建立自定義字型伺服器來使用X字型服務協議。這為所有X應用程式增加了另一個可能的故障點,因為現在無論何時訪問字型都會依賴於此字型伺服器;在操作字型名稱時,新增大量此類應用程式將顯著降低應用程式的效能。

    Render的一個目標是以更直接的方式解決這個問題。讓應用程式根據它提供的資料構建字型是一個顯然的解決方法,通過X協議流傳送字形影象,而不是通過X字型服務協議的後門。

    最後一個因素是關於Unicode編碼字型的。在繪製單個字形之前,X客戶端接收字型中每個字形的幾何資訊,以及整個字型的最小值和最大值。使用輪廓字型時,獲取此資訊的唯一方法是必須首先光柵化每個字形。對於具有256個字形的字型,這不是一個巨大的負擔。但是漢字形編碼可能包含數千個字形,從而引起一些效能問題。Unicode字型可能包含數百萬個字形。此時,光柵化所有字形並將所有這些資訊傳遞給應用程式變得不切實際,特別是當只有一小部分字型可能被顯示時。

    因此需要設計一個新的允許字形的增量光柵化的文本系統。在X伺服器中增量光柵化字形的問題就是在於應用程式需要增量的請求有關字形的資訊,這將需要在協議層增加資料往返傳輸過程。往返是網路環境中的一個嚴重的效能問題,並且在應用程式啟動時會感受效能損失(這已經是某些X應用程式的痛處了)。

    綜上所述——提供複雜的字型資訊,客戶端生成字型,在不增加往返次數的情況下增量的光柵化字型——引匯出一個非常簡單的解決方案。X渲染擴充套件沒有字型支援。相反,它為應用程式提供了一種機制,用於快取伺服器中的字形影象並光柵化它們的序列。應用程式負責定位字型,光柵化字形並生成幾何資訊。

    這種方法解決了所有三個問題,同時降低了擴充套件的複雜性。應用程式可以直接訪問字型檔案,從而可以訪問其中包含的所有資訊。由於所有字型都是由客戶端提供的,因此PDF文件中的嵌入字型與任何其他字型一樣能得到有效地處理。最後,沒有字型處理的往返,這可以減少應用程式啟動時間。它還減少了網路流量,因為只有應用程式實際使用的字形才會在網路上傳輸。由於缺少從未在螢幕上繪製的字形的資訊,因此字形影象消耗的額外流量大於補償。

    在網路流量分析一節中將會顯示,在應用程式啟動時間和網路利用率方面均有顯著下降,即使對字形中的每個畫素使用8位也是如此。

5.1字形管理

    在Render中消除伺服器端字型帶來了一些新的挑戰。應用程式仍然需要一種簡潔有效的方法來沿固定基線渲染一系列字形。Render提供了多個字形的儲存,稱為“GlyphSets”。每個字形本質上都是一個帶有附加幾何資訊的圖片,用於描述相對於基線繪製字形的位置以及下一個字形的偏移量

    通過任意32位數字在GlyphSets中命名字形:沒有假定的編碼。這些名稱以8,16或32位編碼傳輸:沒有提供可變長度編碼。

    在當前的XFree86實現架構中,相同的字形共享相同的儲存。這適用於GlyphSet,以及來自一個或多個客戶端的多個GlyphSet。客戶端提供字形的消除了伺服器端儲存開銷。

    通過使多個應用程式在特定字型的字形光柵化過程中協作,可以改善字形的重複渲染和傳輸。作者設想了一種協作的共享記憶體機制:其中同一地址空間中的應用程式可以一起工作構建所需的字形。因為用於引用X伺服器內的GlyphSets名稱的生命週期不大於建立名稱的X連線,所以Render協議允許每個客戶端為每個GlyphSet都有自己的名稱。只要還有名稱存在,GlyphSet就會存在。

需要為這種共享設計重要的基礎架構。由於這些更改不會影響Render協議本身,因此可以在需要時進行此設計。

5.2字形繪製

     一旦將所需的字形傳遞給X伺服器,客戶端就會使用CompositeGlyphs請求之一顯示其序列(有三個,對應於三個字形的名稱編碼)。這些請求顯示了許多字形列表,每個字形列表都沿著兩個軸的位置增量的從前一個位元組偏移。對所選字形集的更改可以寫入字形列表中。這非常類似於核心X文字顯示請求附件垂直位置調整。位置調整也從8位擴充套件到16位。簡單文字顯示的一個例子如圖2所示。字形位置沿著基線用插入符號標記,每個字形影象的範圍用虛線框標出。每個字形包含從字形影象的左上角到渲染原點的距離、字形影象的尺寸以及從渲染原點到下一個要繪製字形位置的距離

 

     當近似抗鋸齒時,多個操作覆蓋相同區域時,使用OVER運算一系列單獨操作會生成不準確的值,而alpha值既不透明也不非透明。問題是兩個目標的子畫素幾何在轉換為覆蓋值時會丟失。

     OVER運算通過假定每個目標覆蓋所有畫素中的相同比例,來獲得兩個目標子畫素覆蓋的最優近似。在繪製文字時,更好的近似是假設字形實際上不重疊;此時,畫素的整個覆蓋區域是每個畫素覆蓋的區域的總和。

     發出字形繪製請求時可以建立中間Picture物件;請求中的所有字形都使用ADD運算子呈現給此中間圖片。然後,使用請求中指定的運算將生成的影象渲染到目標。當渲染結果不受其使用影響時,伺服器可以自由地消除中間Picture物件,例如當每個畫素僅用一個位表示字形或者沒有任何字形重疊時。

5.3網路流量分析

     字形在客戶端內光柵化並傳輸到X伺服器,顯然我們會擔心這些字形給網路帶來額外負擔。雖然字形影象確實會增加從客戶端傳送到伺服器的流量,但是從伺服器到客戶端字形的流量將被消除。

     事實證明,對於典型的應用程式執行場景來說,消除的從伺服器傳送到客戶端的字形矩陣和字型名稱的流量,遠遠高於由字形影象產生的額外流量。表1顯示了使用少於256個字形的拉丁字型的兩個常見應用程式的網路利用率。

 

      有趣的是,僅僅選擇適當的字型就需要大量的位元組;通過ListFonts請求和回覆表示。由於核心X架構僅提供基於字串的字型匹配,因此必須在客戶端內實現更復雜的方案,從而需要從伺服器傳輸有關可用字型的資訊。

  從小型Latin-1編碼字型到較大的漢字或Unicode字型,會顯著增加傳輸矩陣的資料量,但是不會顯著增加字形資料量:漢字或Unicode字符集中的大部分不會被用到。

  值得注意的是,核心X架構需要往返列表或開啟字型。由於應用程式通常在啟動時開啟許多字型,因此這些額外的往返可以大大增加初始化應用程式所需的時間。

六、Xft

  消除X伺服器內的字型處理會將字型檔案管理的負擔轉移到客戶端。在不同客戶端之間進行字型管理的不同機制導致需要標準字型檔案訪問庫。Xft庫的設計基FreeType庫,提供常見的字型命名,字型檔案管理和字型自定義。Xft不是Render擴充套件的一部分,但它是提供應用程式字型訪問的整體架構的重要組成部分。

  Xft還通過提供統一的API來允許與舊X伺服器的某種程度的相容性。應用程式可以檢測何時發生這種情況以便進行補償。幸運的是,隨著XFree86變得越來越普遍,傳統X伺服器的數量應該繼續減少,這使得這種相容性在很大程度上是不必要的。

  設計Xft的一個重要前提是:庫不應該向應用程式隱藏底層光柵化引擎和字型檔案。任何想抽象化此類訪問的嘗試,都只會阻止應用程式充分利用字型檔案和光柵化引擎中的功能。

  這裡存在明顯的衝突——一方面,Xft提供了足夠的抽象功能來掩蓋核心X字型和基於渲染的字形之間的差異,另一方面,它提供了對基礎字型檔案(如果存在)的完全訪問。應用程式需要為任何可能性和行為一致性做好準備。Xft由工具包庫使用。

6.1字型名稱

  選擇字型的過程可以分為兩個階段:首先定位適當的面,然後根據額外的應用屬性修改面以建立正確的字形影象。完成此操作後,有關字型的屬性將傳遞迴應用程式。

  Xft將這些步驟統一到一個機制中。 XftFontName是一個型別化的屬性列表;每個元素都有一個名稱和一個值。每個可用的面由XftFontName表示,該XftFontName包含由底層字型機制提供的面部屬性。

  應用程式構造XftFontNames並將它們呈現給API。庫將此名稱與可用面匹配以選擇最佳面,然後用其他額外的屬性設定情況來調整最終字形顯示的光柵化。生成的字型匹配一個名稱,其中包含有關字型的其他資訊,例如載入面的原始檔。

  雖然名稱的內部表示是屬性列表,但現有應用程式可以方便地將字串表示轉化為內部表示。 Xft字型名字的一般格式是:

 

  典型的規範可能是“times-12”,它指定了來自時間族的12點字型。使用加粗和斜體的預設值會產生中等加粗的羅馬變體。Family和size域是可選的;Xft將根據剩餘的屬性選擇合適的famliy和預設大小。在最小的情況下,字型名稱將始終匹配。

七、渲染仍在完善中

  上面描述的這些Render部分不是很有爭議;他們已經在實踐應用中表現出很好的工作效能,也已經使用了一段時間,為它們存在的價值提供了一定程度的保證。擴充套件的另外兩個元件,目前尚未在XFree86中實現。接下來將討論這些元件,多邊形渲染和影象變換,以及當前思路中的已解決和未解決的問題

八、多邊形渲染

  從OpenGL中獲取提示,Render將伺服器渲染的幾何物件減少到最小集合。複雜物件在客戶端內進行細分,並作為一組基本物件傳送到伺服器。這最大限度地減少了伺服器內的實現工作量以及測試實現的一致性所需的工作量,同時不會給應用程式帶來太多麻煩。

  Render提供兩個獨立的原始物件:三角形和梯形。兩者都是根據32位定點數定義的,它使用24位作為值的整數部分,8位作為小數部分。允許更精確地定位多邊形的頂點,並消除當物件被捕捉到整數網格時引起的視覺噪聲。

  通過使用座標定位三個頂點來指定三角形。梯形更復雜,因為它們設計的目的是準確地表示細分。梯形由兩條劃分梯形頂部和底部的水平線和兩條由任意點指定的附加線表示,如圖3所示。四條線之間的任何區域都是梯形(或者,在簡併的情況下,是一個三角形)。允許梯形頂部或底部的點不重合,使得多個梯形的邊緣精確對齊;不管這些物體的水平範圍如何,相同的線都可以用於所有梯形。

                                               

  多邊形的光柵化似乎是一個沒有爭議的問題,用線條連線一系列頂點並填充覆蓋區域。但確實會出現一個問題:適當的渲染精度如何定義。

8.1精確與不精確

  首要問題是:是否應該為多邊形的精確畫素化制定標準。為了簡化執行的情況的驗證,核心X協議要求所有物件必須精確畫素化,但這樣也基本上消除了物件的效用。最初的核心X協議很難進行有效的軟體實現,只有最近的一些硬體,可以在靈活的硬體中實現協議中的大部分。應用很少使用超過零寬度線的X幾何物件。

  對於不精確的光柵化,畫素化的不確定性使得原始碼很難使用;應用程式必須接受顯示出來的影象可能存在很大差異。現在的問題是如何限制畫素化的過程。OpenGL具有相對較弱的不變性需求,因為其追求軟體和硬體實現高效能混合。現有的應用程式對畫素化的一致性有很高的需求,那麼這就需要制定額外的約束了。

  精確的畫素化需要規範:指定的畫素化必須合理地執行。一個不好的規範會使得每次執行都是無用的。應用程式也需要精確的規範來需要混合伺服器端和客戶端渲染,同時規範必須是直接執行的。

  渲染同時提供上述兩種模式。不精確的方式用來對映到現有的GL-優化的硬體,精確的方式提供給應用程式實現對螢幕上顯示出的渲染效果的嚴格控制。

8.2不精確多邊形

不精確的多邊形必須滿足以下要求:

  • 鄰接邊緣的精確匹配。當指定沿公共邊緣鄰接的兩個多邊形時,如果每個多邊型的邊緣由相同的座標表示,那麼兩個多邊形的並集內的所有畫素值的和必須是1。
  •  平移不變性。在多邊形或者繪製目標沿著任何方向上的任何整數畫素平移以後,多邊形的畫素化結果必須仍然相同。
  • 鋒利的邊緣。當使用鋒利的(非鋸齒)邊緣對多邊形進行光柵化時,每個畫素的alpha掩碼將僅包含1或0。
  • 順序獨立性。使用不同的頂點順序定義的兩個相同的多邊形必須生成相同的結果。

這些約束旨在通過多邊形細分和平移,最小化視覺假象。現有的硬體可以滿足這些要求。

8.3精確多邊形

  精確多邊形是一項巨大的挑戰。對於尖銳的多邊形,規範很簡單:繪製中心點落在多邊形內的畫素,而外部的畫素則不繪製。根據X模型的要求,如果多邊形內部偏右,中心恰好位於邊緣的畫素點會被繪製,如果多邊形內部偏下,落在垂直邊緣的中心點會被繪製。 

  給定32位座標空間,當表示僅用於剪下的不大於64位的值時可以精確的使用。

  對於平滑(抗鋸齒)多邊形,解決方案還不太確定。如果要計算每個畫素被多邊形覆蓋的比例,這個計算成本是非常高的;需要至少192b來精確計算梯形兩側相交的畫素所覆蓋的區域。

  雖然這可能會比遵照核心協議渲染一個寬橢圓時的計算量小一些,但是沒有證據表明實現這個特定的規範會比計算量小一些的規範更好。畫素覆蓋的區域僅是將多邊形形狀過濾為畫素集合需要的正確值的粗略近似,只要它提供相同的值,簡單的規範也是“正確”的。

  一種思路是將相關畫素分成三種:完全被多邊形覆蓋、完全沒有被覆蓋以及部分覆蓋。覆蓋和未覆蓋情況下的畫素結果是顯而易見的。

  對於被梯形部分覆蓋的畫素,通過將梯形剪下到畫素邊界來計算覆蓋率。在梯形邊緣與畫素的邊界相交的情況下,沿畫素邊緣的座標表示為16位小數值。在此精度下,當僅要求32位的算數計算時會產生小於分之一的畫素覆蓋誤差。

  另一個建議是從擴充套件中刪除多邊形,只留下不精確的多邊形。關於需要在現有列表中新增什麼不變數,是否影響不精確多邊形情況下的硬體加速,這些問題仍然存在。

  哪個選擇最有意義取決於是否能設計實現如上定義的精確多邊形或者其他精度規範。由於缺乏有效的實現,應用程式傾向於使用不精確多邊形,而精確多邊形給X伺服器帶來了承重的負擔。

8.4多邊形請求

  假設有一個渲染一系列梯形的請求和三個渲染三角形的請求。一個梯形由左、右、上、下四條邊界線確定。從圖3中可以看出,在梯形中指定左右邊緣的座標並不需要與水平對齊。

  對三角形的請求僅在三角形頂點的編碼方面存在不同,請求格式取自OpenGL API。第一種形式提供一個簡單的三角形列表,每個三角形中每個頂點有一個點。另一種形式的頂點列表是:將三角形的最後兩個頂點與下一個頂點結合形成另一個三角形。在列表資源用盡之前優先使用後者。最終的三角形的表示將一個三角形的第一個、第三個頂點與下一個頂點組合在一起,形成後續的三角形。

  這些請求均作為基本複合運算中的隱式掩碼元素執行。源圖片提供RGBA元素。如果有為每個頂點提供RGBA值的附加請求,那麼源影象會被替換為通過在多邊形中插入指定的RGBA頂點顏色而生成的新影象。這樣只需要幾個請求就可以實現各種顏色效果。

九、影象變換

  新增到Render中的最終操作涉及在X伺服器中進行影象資料變換。任意仿射變換提供了大量可行的操作,可以通過用於3D紋理對映的硬體進行加速。

  變換請求從源影象中獲取一個四邊形區域並將其對映到目標範圍內的四邊形區域中。頂點被順序對映,這允許從源到目的影象資料的任意仿射變換。

  目標四邊形形成一個隱式的alpha掩碼,其可用於平滑變換過來的影象的邊緣。通過在轉換期間過濾source Picture來建立源影象。暫時還不需要提供過濾精度設定情況;通用硬體濾波器和一些使用數字訊號處理技術的高質量濾波器都是必要的。

  我們的最終目的是在實現架構中可以根據需求提供額外的濾波器,並在協議內建立一種機制來傳遞他們的一些特徵。

  關於過濾器執行中的邊緣效應還有其他問題;可能需要額外的濾波器引數來生成超出源影象邊界的畫素值。

  還有一項建議是將目標限制為梯形而不是一般的四邊形。這樣可以簡化基本實現,同時不會過度限制未來的優化。

十、歷史和現狀

  自從X伺服器從單色變為彩色,對Render擴充套件的需求一直存在。原始渲染架構不適合處理顏色資料。然而,最近基於X的應用程式開發的興起和隨之而來的X技術的重振,為研發注入了活力。

  歷史上,太過於關注與現有X應用程式和X伺服器的相容性。現有的X渲染系統限制了新的開源使用者介面環境Gnome和KDE。KDE接受了環境的限制並充分利用了它們。Gnome用客戶端的渲染取代了伺服器端的渲染,將X協議轉變為簡單的影象傳輸系統。缺乏硬體加速和遠端應用程式效能的下降表明,研究應該轉向考慮提供一些伺服器端的支援。

  截至Usenix 2000,尚未制定所有擴充套件的正式協議,但此問題引起了廣泛的關注,一系列構想被提出。其中一位與會者Rob Pike描述了他和Russ Cox為Plan 9視窗系統開發的渲染系統的架構。該環境中的簡單統一架構只需要稍微擴充套件一下即可實現。

  Render擴充套件協議在XFree86社群中討論了幾個月。一旦它穩定下來,就開始實施,目標是在2000年8月之前製作一個可行的抗鋸齒文字演示。

  此時,該實現僅提供對基本合成原語以及文字原語的支援。上面討論的與抗鋸齒多邊形光柵化有關的問題,排除了多邊形或影象變換操作的實現。一旦該問題得到解決,就可以完成實施。

  從去年10月開始,XFree86服務端中正在開發一種加速Render擴充套件架構。由於協議的設計目的是在現代硬體上進行實現,因此原語本身的實現相對簡單。正如所料,硬體加速提供了巨大的效能優勢。本人和Mark Vojkovich對簡單影象合成的初步度量表明,硬體的執行速度比合理優化的C程式碼快40倍。

  2000年末,對Xft的支援已整合到了Qt工具包中,該工具包構成了K桌面環境的基礎。該工具包為所有渲染操作提供了完整的抽象,因此修改工具包即可在所有KDE應用程式中提供抗鋸齒文字。在Qt 3.0中,還提供了一個新的渲染功能,允許應用程式在螢幕上合成影象。

  還有一些嘗試在Gnome社群中使用Render。但是,在從Gtk + 1.2過渡到Gtk + 2.0之前,為實現完全轉化需要將太多的底層X字型模型傳遞給應用程式。 Gtk + 2.0應該在明年準備就緒,為社群提供另一個完全獨立的X字型工具包。

十一、結論

  X渲染擴充套件提供了一個可在X視窗系統中使用的全新渲染模型。它的小尺寸和低階原語允許在提供完整功能的同時以合適的大小實現。這些原語旨在緊密匹配應用程式要求和硬體功能。

  X桌面已經開始轉型,在幾個工具包和應用程式套件中引入了抗鋸齒文字。工具包曾經努力想要提供現代使用者介面技術,Render介入並允許應用程式使用自己的語言。新的應用程式已經將X轉變為簡單的影象傳輸協議;事實證明,核心渲染系統在現代世界中基本上是行不通的。渲染將繪圖帶回伺服器,充分利用硬體的功能,同時允許應用程式再次在網路上高效執行。Render允許X視窗系統再次支援高階開源桌面環境。