managed DirectX9(第二章)

 

選擇正確的Device

翻譯:clayman

  
      The number of possible permutations when cretion a device is quite staggering. 如今,市場裏有大量不同類型的顯示卡,記住每種顯卡所支持的特性幾乎時不可能的。你應該詢問device,讓它告訴你它所支持的特性。我們接下來將討論:

                   枚舉系統裏所有的適配器(adapter

                   枚舉每一個device所支持的格式

                   確定所列舉的設備功能

 

 

枚舉系統裏的適配器

       如今的大多數系統都支持多顯示器。雖然這還不是主流配置,但多顯示器確實很有用,並且變的越來越流行。在過去,這是高端圖形卡專有的功能。但現在ATInVidia以及Matrox都支持讓多臺顯示器共享一塊顯卡的多頭顯示技術。

         Direct3Ddevice必須指定給每一個適配器。在這裏,你可以把“適配器”理解爲一塊鏈接了特定顯示器的顯卡。比如ATI Radeon 9700的顯卡只是一塊物理適配器,但它有兩個顯示器接口(DVIVGA),因此,在Direct3D裏,它有兩個適配器。也許你不知道選哪一個,甚至不確定有多少device在運行遊戲的系統裏,那麼怎樣來檢測它們並且選擇正確的一個呢?

         Direct3D裏,一個叫做Manager的靜態類可以簡單的完成以上任務:枚舉適配器和device的信息;獲得系統裏device所支持特性的信息。

         Manager類最重要的屬性就是適配器的列表。在許多地方都會用到這個屬性。它有一個“count”成員儲存了系統裏適配器的數量。因此,可以直接用索引訪問適配器(e.g. Manager.Adapters[0], 也可以枚舉出系統裏所有適配器。

         用一個簡單的程序測試一下這個功能,它將以樹狀結構顯示出系統裏的適配器,以及他們所支持的顯示模式:

1.   創建新的C# Windows Form工程;

2.   添加DirectX組件;

3.   創建一個TreeView控件,並且佔滿整個窗口:把Dock屬性設置爲fill

好了,現在該加入掃描每一個適配器,顯示所支持的每一種顯示模式的函數了:

Public void LoadGRaphics()

{

         foreach(AdapterInformation ai in Manager.Adapters)

         {

                   treeNode root = new TreeNOde(ai.Information.Description);

                   treeNode driverInfo = new TreeNode(string.Format(“Driver information:{0} – {1}”, ai.Information.DriverName, ai.Information.DriverVersion) );

                   root.Node.Add(driverInfo);

treeNode displayMode – new TreeNodeJ(string.Format(“Vurrent Display Mode:{0}×{1}×{2}”, ai.CurrentDisplayMode.Width, ai.CurrentDisplayMOde.Height, ai.CurrentDisplayuMode.Format) );

                   foreach(DisplayMode dm in ai.SupportedDisplayModes)

                   {

                            treeNode supportedNode = new TreeNode(string.Format(“Supported:{0}×{1}×{2}”, dm.Width, dm.Height, dm.Format) );

                            displayMode.Nodes.Add(supportedNode);

                   }

root.Nodes.Add(displayMode);

treeView1.Node.Add(root);

}

}

雖然代碼看起來有一點點多,但它所做的事情實際上是非常簡單的。你可以先分開來看看我們都作了些什麼。首先,我們枚舉系統裏的適配器。C#Foreach迭代器使這個過程異常的簡單。對每一個適配器來說,這個循環都只執行一次,並且用給定的適配器填充AdapterInformation結構。觀察一下AdapterInformation結構,有以下幾個成員

Public struct AdapterInformation

{

int adapter;

DisplayMode CurrentDisplayMode;

AdapterDetails Information;

AdapterDetails GetWhqlInformation();

DisplayModeEnumerator SupportedDisplayModes;

         }

這裏adapter成員指創建device時的適配器序數。序數是一個基於0的索引,並且序數的個數等於系統裏適配器的個數。兩個返回AdapterDetails結構的成員都使用同一個方法返回同樣的結果。對Information成員來說,Windows Hardware Quality LabsWHQL)並不返回細節,而GetWhqlInformation卻可以。獲得這些信息要花費一些代價及事件,所以我們把它分成了兩部分。

AdapterDetails結構保存了適配器的大量信息,包括對適配器自身的描述以及驅動信息。雖然這不是一定會用到的,但應用程序卻能依次作出對硬件類型的判斷。

剩下的兩個成員返回DisplayMode結構。這些結構包含了大量的顯示模式,包括顯示的高度和寬度,刷新率以及使用的格式。CurrentDisplayMode返回當前的顯示模式,SupportedDisplayModes返回適配器所支持的模式的列表。

So,我們用從Information屬性獲得的對device的描述作爲tree view的根節點。然後加入了一個表示驅動程序名字以及版本號的子節點。同樣也加入了一個顯示當前顯示模式的子節點,並且在這個子節點下列出了所有支持的顯示模式。

運行程序,可以看到包含了所有支持模式的列表。填充present parameter結構時,這些模式都能當作正確的後備緩衝格式。每一個枚舉出來的模式後面都有一個以固定模式顯示的字符串(e.g  X8R8G8B8,字母和數字交替出現。字母表示了數據的類型,數字表示這種類型的數據所佔的位數。下邊是常見的字母:

A――alpha        B――blue           X---unused          L----luminance    R----red     P----palette        G---green

(雖然有很多種格式,但只有幾種能正確的用於後備緩衝以及顯示模式。可用於後備緩衝的模式包括:A2R10G10B10, A1R5G5B5, A8R8G8B8, X1R5G5B5, X8R8G8B8, R5G5B5; Display formats can be the same as the back buffer formats, with the exception of those that contain an alpha component . The only format that can be used for a display weith alpha is A2R10G10B10and even then that’s only in full-screen mode.

每種類型所佔的位數加起來,就是這種格式的總大小。比如X8R8G8B8,就是32位的格式,紅、綠、藍各8位,還有8位沒有使用。

至今爲止,我們獲得了要創建的適配器序數,要支持的後備緩衝格式,那麼關於device構造函數的其他參數呢?很幸運,Manager類有我們所需的一切。

 

 

判斷哪一個設備是可用的

manager類有許多方法可以用來檢測你的適配器是否支持一個特定的功能。比如,你需要檢測適配器是否支持一種特殊的格式,但又不想枚舉所有可能的適配器以及格式,那你就可以用manager類來解決這個問題。使用如下的方法:

pubic static System.Boolean CheckDeviceType(int adapter, DeviceType checkType, Format DisplayFormat, Format backBufferFormat, bool windowed, int result)

這個方法可以快速的檢測出device是否支持你將要使用的格式。第一個參數是你要檢測的適配器序數;第二個是要檢測的device類型,但這個值大多數情況下都被設置爲DeviceType.Fardware。接着指定將使用的後備緩衝類型和顯示格式,以及是否需要全屏顯示。最後一個參數是可選的,如果使用的話他將返回關於這個方法的一個整數(即COM中的HRESULT)。如果這是一個有效的設備,則方法返回true,否則爲false。當你預先知道要使用的格式使,這個方法是很有用的。

(應該注意到,在窗口模式,後備緩衝的格式不一定要匹配於顯示格式,只要你的硬件支持適當的顏色轉換就可以了。不論你的硬件是否支持這種功能,CheckDeviceType方法都會返回適當的結果,應該使用manager類的CheckDeviceFormatConversion方法來判斷是否支持這種轉換。也可以在窗口模式下使用Format.Unknown。全屏模式下不需要這種轉換。)

 

 

檢測Device的功能(capabilities

我們把每一個device能完全用硬件實現的功能都叫做“capability”,或簡稱做“Cap”。Direct3D有一個Caps結構可以列出device所支持的每一種可能的capabilities。創建了device之後,就可以使用deviceCaps屬性來檢測他所支持的特性,但如果在創建設備之你就想知道device所支持的特性該怎麼辦呢?自然,Manager類也有一個方法能完成這個任務。

現在,先前的程序里加一點點代碼來獲得系統裏每一種適配器的capabilities。我們將不再使用tree view來顯示這些capabilities,應爲這可能包含了數百種capabilities。最好的方法是使用一個text box。回到windows form的設計模式,把tree viewDock屬性改爲“Left”,把寬度改爲現在的一半;入text box控件,把Dock屬性設置爲“Fill”,Multiline設置爲trueScrollbars設置爲“both”。

現在你可能想爲程序添加一個鉤子(hook),這樣在選擇了一個適配器之後,textbox裏的數據也會更新。使用tree viewAfterSelect事件,添加如下代碼:

private void treeView_1AfterSelect(object sender, System.Windows.Forms.TreeViewEcentArgs e)

{

         if (e.Node.Parent == null)

         {       

                   textBox1.Text = e.Node.Text + “Capabilities: /r/n/r/n” + Manager.GetDeviceCaps(e.Node.Indes, DeviceType.Hardware).ToString().Replace(“/n”, “/r/n”);

         }

}

如你所見,相當簡單。運行一下看看結果吧。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章