DirectX5.0最新遊戲程式設計指南 DirectDraw篇 三、DirectDraw的要素(一) (轉)

worldblog發表於2007-12-04
DirectX5.0最新遊戲程式設計指南 DirectDraw篇 三、DirectDraw的要素(一) (轉)[@more@]

 

三、DirectDraw的要素
  DirectDraw中最基本的要素有協作等級、顯示、DirectDraw、表面、調色盤、剪下板等,下面對各個要素逐一進行介紹。
1、協作等級(Cerative Level)
  協作等級描述了DirectDraw如何同顯示互動及對那些可能影響顯示的事件的反應。你可以使用IDirectDraw2::SetCooperativeLevel方法來設定協作等級。在大多數的情況下,你可以使用協作等級來確定應用是否執行在獨佔全屏模式或視窗模式。DirectDraw協作等級還具有以下作用:
 .使DirectDraw能夠使用X模式(Mode X)解析度。
 .如果按了ctrl + alt + del,禁止DirectDraw釋放對顯示的獨佔控制和重新啟動(僅在獨佔模式下)。
 .使DirectDraw能夠最大化和最小化以響應啟用的事件。
  標準的協作等級指明瞭DirectDraw程式是一個視窗應用程式。在這種情況下,你不能改變主表面的調色盤和頁翻轉。另外,你還不
能那些對顯示或影片影響程度大的方法,如 IDirectDraw2::Compact等。
在全屏獨佔協作等級下,你可以使用的所有,設定慣用調色盤和動態調色盤,改變顯示解析度,緊湊記憶體和實現頁翻轉等。全屏獨佔模式不禁止其它的應用分配表面,也不禁止它們使用DirectDraw和GDI,但禁止其它發應用改變顯示解析度和調色盤。
  因為應用程式可以在多視窗使用DirectDraw,所以當應用要求工作在DDSCL_NORMAL模式時,IDirectDraw2:: SetCooperativeLevel方法並不需要一個指定的視窗控制程式碼。將NULL傳遞給視窗控制程式碼,所有的視窗都能同時工作在標準視窗模式下。

2、顯示模式(Display Modes)
  顯示模式是對顯示硬體從主表面傳送給顯示器的圖象的大小和位深度(bit-depth)的描述。顯示模式可以刻畫為:寬、高和位深度。例如,大多數的顯示介面卡都能顯示寬640個畫素,高480個畫素,每個畫素的顏色值為8位的資料圖象,該顯示模式就幾為640x480x256。
要想得到更大的解析度或位深度,就需要更多的顯示記憶體。
  顯示模式有兩種型別:調色模式和非調色模式。對於調色顯示模式,每一個畫素都是一個指向相關調色盤的值。顯示模式的位深度決定了調色盤中能夠具有的顏色的數目。例如,對於8位調色顯示模式,每一個畫素都是一個從0到255的值。在這種顯示模式下,調色盤可以包含256中顏色。非調色顯示模式則不使用調色盤,該模式下的位深度指明瞭用於描述一個畫素的總的位數。
  主表面和主翻轉鏈中的任何表面都應該和顯示模式的大小、位深度和畫素格式匹配。
2.1、檢測所支援的顯示模式
  因為顯示硬體的不同,並不是所有的裝置都支援所有的顯示模式。要檢測所支援的顯示模式,需要呼叫IDirectDraw2::EnumDisplayModes方法。透過設定適當的值和標誌, IDirectDraw2::EnumDisplayModes方法可以列出所有支援的顯示模式,也能判斷是否支援某一指定的顯示模式。
  該方法的第一個引數dwFlags控制方法其它的選項,通常可以將dwFlags設為0來忽略其它的選項;第二個引數lpDDSurfaceDesc是用以描述所給顯示模式的結構 DDSURFACEDESC的地址,一般將其設為NULL可以列出所有的模式。第三個引數lpContext是一個指標,DirectDraw需要將該指標傳遞給回撥,如果不需要在回撥函式中有額外的資料,可將其設為NULL。最後一個引數是lpEnumModesCallback,它是DirectDraw對於每一種支援的顯示模式呼叫的回撥函式的地址。
  在呼叫IDirectDraw2::EnumDisplayModes方法時提供的回撥函式必須同EnumModesCallback函式的原型相匹配。對於硬體所支援的每一種顯示模式,DirectDraw呼叫你的回撥函式來傳遞兩個引數,第一個是DDSURFACEDESC結構的地址,該結構描述了一種支援的顯示模式;
第二個引數是呼叫IDirectDraw2::EnumDisplayModes時指定的應用定義的資料的地址。
  透過檢查DDSURFACEDESC結構的值來得到它所描述的顯示模式,其中關鍵的成員是dwWidth、dwHeight、和ddpfPixelFormat。dwWidth和dwHeight描述了顯示模式的大小;ddpfPixelFormat是一個DDPIXELFORMAT結構,它包含了有關位深度的資訊。
  DDPIXELFORMAT結構包含了描述顯示模式位深度的資訊,並且說明該顯示模式是否使用調色盤。如果dwFlags成員包含了 DDPF_PALETTEINDEXED1、DDPF_PALETTEINDEXED2、DDPF_PALETTEINDEXED4或DDPF_PALETTEINDEXED8標誌,該顯示模式的位深度就是1、2、4或8位,並且每個畫素都是一個相公調色盤的索引。如果dwFlags包含了DDPF_RGB標誌,該顯示模式就是非調色顯示模式,並且其位深度由DDPIXELFORMAT結構中的dwRGBBitCount成員提供。
2.2、設定顯示模式
  你可以呼叫IDirectDraw2::SetDisplayMode方法來設定顯示模式。該方法接受四個引數來設定顯示模式的解析度的大小、位深度和重新整理率。它使用第五個引數來指定給定模式的特殊選項,目前僅用於13模式和X模式320x200x8中。
  你可以指定期望得到的顯示模式的位深度,但不能指定顯示硬體用於該位深度的畫素格式。要檢測顯示硬體用於當前位深度的RGB位遮蔽,可以在設定顯示模式後呼叫 IDirectDraw2::GetDisplayMode方法。如果當前顯示模式是非調色模式,你可以透過檢查dwRBitMask、dwGBitMask和dwBBitMask中的值來獲得教正的紅、綠、藍顏色位。
  你還可以透過多個應用來改變顯示模式,只要它們都共享同一個顯示卡。也可以改變位深度,只要應用程式能獨佔式地訪問DirectDraw物件,所有的DirectDrawSurface物件在顯示模式改變後都會釋放表面記憶體,所以在更改了顯示模式之後,必須使用 IDirectDrawSurface3::Restore方法重新為物件分配表面記憶體。
2.3、恢復顯示模式
  如果顯示模式是透過呼叫IDirectDraw2::SetDisplayMode方法(而不是 IDirectDraw::SetDisplayMode方法)完成的,你可以呼叫IDirectDraw2::RestoreDisplayMode方法來恢復到原來的顯示模式。如果應用程式是獨佔式的協作等級,當你將應用程式的協作等級設回標準時,顯示模式就會自動恢復為原來的模式。如果使用了DirectDraw介面,你必須顯式地恢復顯示模式。
2.4、X模式和13模式
  DirectDraw支援X模式和13模式兩類顯示模式。13模式是320x200,每個畫素是8位的調色模式,其16進位制模式號為13。模式X是從標準的VGA 13模式衍生出來的混合模式,該模式允許使用256KB的顯示記憶體(13模式僅允許實用64KB的顯示記憶體)。
  在95下,DirectDraw對所有的顯示卡提供兩種X模式(320x200x8和320x240x8)。一些顯示卡也支援線性低解析度模式,線上性低解析度默默上下,主表面能夠被鎖定也能直接訪問,這在X模式下是不允許的。
  只要應用程式呼叫IDirectDraw2::SetCooperativeLevel方法時使用了 DDSCL_ALLOWMODEX,、DDSCL_FULLSCREEN和DDSCL_EXCLUSIVE標誌,X模式就可用。如果沒有指定 DDSCL_ALLOWMODEX標誌, IDirectDraw2::EnumDisplayModes方法就不能列出X模式,當請求X模式時,對IDirectDraw2::SetDisplayMode方法的呼叫就會失敗。
  當應用程式在X模式時不能使用IDirectDrawSurface3::Lock或IDirectDrawSurface3::Blt方法鎖定主表面或向主表面塊寫資料,也不能在主表面或螢幕DC的GDI使用 IDirectDrawSurface3::GetDC方法。X模式由DDSCAPS肩胛骨中的DDSCAPS_MODEX標誌來指定,DDSCAPS結構是呼叫IDirectDrawSurface3::GetCaps和IDirectDraw2::EnumDisplayModes方法返回的DDSURFACEDESC結構中的一部分。
2.5、高解析度和真彩色
  DirectDraw支援由顯示裝置程式支援的所有的螢幕解析度和位深度。DirectDraw允許應用程式改變顯示模式到任一種顯示驅動程式支援的顯示模式,包括24位和32位(真彩色)模式。
  DirectDraw也支援真彩色表面的HEL位塊傳輸。如果顯示裝置驅動程式在這些解析度下支援位塊傳輸,顯示記憶體──顯示記憶體的位塊傳輸將使用硬體塊寫方式,否則將使用HEL來提高位塊傳輸的效能。
  Windows95和NT允許你指定正在使用的顯示器的型別。DirectDraw檢查已知顯示模式的列表,如果DirectDraw檢測到要求的模式同該顯示器不相容,對 IDirectDraw2::SetDisplayMode方法的呼叫將會失敗。當你呼叫方法IDirectDraw2::EnumDisplayModes時,只有顯示器支援的模式才會被列出來。

3、DirectDraw物件
  DirectDraw物件是所有DirectDraw應用程式的核心,也是Direct3D應用程式的一個有機組成部分。DirectDraw物件是你建立的第一個物件,透過該物件再建立其它相關物件。一般透過呼叫DirectDrawCreate函式來建立一個DirectDraw物件,該函式返回一個IDirectDraw介面。
  DirectDraw物件表徵了顯示裝置。如果該顯示裝置支援硬體加速功能,DirectDraw物件還能利用硬體的加速功能。每一個DirectDraw物件都能處理顯示裝置和建立依賴於該DirectDraw物件的表面物件、調色盤物件和剪下板物件。例如,建立一個表面需要呼叫IDirectDraw2::CreateSurface方法,若要將一個調色盤物件附在表面上,需要呼叫 IDirectDraw2::CreatePalette方法。另外, IDirectDraw2介面還包含了類似的建立剪下板物件的方法。
  你可以同時建立一個DirectDraw物件的多個例項。最簡單的例子是在Windows95系統中使用雙顯示器。儘管Windows95目前不支援多顯示器,但為每一個顯示裝置寫DirectDraw硬體抽象層是可能的。Windows95和GDI能夠識別的顯示裝置在建立預設的DirectDraw物件的例項時將會被用到。Windows95和GDI不能識別的顯示裝置能被另一個獨立的DirectDraw物件所表徵,該物件必須用第二個顯示裝置的全域性統一識別符號GUID(Globally Unique ntifier)來建立,此GUID可以透過函式DirectDrawEnumerate獲得。
  DirectDraw物件管理它所建立的其它所有物件。它控制預設調色盤、Color Key和硬體顯示模式,它還對已經分配的資源和保留的資源做上標記。
  新版本的DirectDraw在以前的版本中增加了新的內容。IDirectDraw2介面透過增加了IDirectDraw2::GetAvailableVidMem方法而對IDirectDraw介面進行了擴充套件。該方法使你能夠查詢顯示裝置總的可用影片記憶體及其中有多少記憶體供一個指定的表面使用。
IDirectDraw2::SetCooperativeLevel方法同IDirectDraw2::SetDisplayMode之間的互動作用同IDirectDraw介面中的這些方法有所不同。如果應用程式使用IDirectDraw介面設定全屏獨佔方式的協作等級並且改變顯示模式,當返回標準協作等級時,顯示模式不會自動恢復,你必須呼叫
IDirectDraw::RestoreDisplayMode方法來顯式地恢復。如果使用了IDirectDraw2介面,對RestoreDisplayMode的呼叫就不是必須的。然而IDirectDraw2::RestoreDisplayMode方法不支援顯式地恢復原先的顯示模式。
作為的基礎的COM指明瞭一個物件可以透過增加新的介面來提供新的功能而不影響其向後相容性。因此IDirectDraw2介面就可以代替IDirectDraw介面。新的介面可以透過IDirectDraw::QueryInterface方法獲得,如下面的C++程式碼所示:
// Create an IDirectDraw2 interface.
LPDIRECTDRAW  lpDD;
LPDIRECTDRAW2 lpDD2;
 
ddrval = DirectDrawCreate(NULL, &lpDD, NULL);
if(ddrval != DD_OK)
  return;
 
ddrval = lpDD->SetCooperativeLevel(hwnd,
  DDSCL_NORMAL);
if(ddrval != DD_OK)
  return;
 
ddrval = lpDD->QueryInterface(IID_IDirectDraw2,
  (LPVOID *)&lpDD2);
if(ddrval != DD_OK)
  return;
例中建立了一個DirectDraw物件,然後呼叫IDirectDraw介面的 IUnknown::QueryInterface方法建立一個IDirectDraw2介面。
  獲取了一個IDirectDraw2介面後,就可以呼叫它的方法以利用其新特性的優點。因為一些方法可能會在新版本的介面中有所變化,因此混合使用不同版本的介面(例如IDirectDraw和IDirectDraw2)可能會導致不可預測的錯誤。
3.1、每一程式中的多個DirectDraw物件
  DirectDraw允許在一個程式中多次呼叫DirectDrawCreate函式。每次呼叫之後對每個唯一獨立DirectDraw物件都返回一個唯一的獨立的介面。每個DirectDraw物件都可以用於所需,物件之間沒有依賴關係。每個物件就象是單獨在程式中建立的一樣。
  每一個DirectDraw物件建立的DirectDrawSurface物件、DirectDrawClipper 物件和DirectDrawPalette物件都不能被其它的DirectDraw物件使用,因為這些物件在其父物件DirectDraw物件撤消時都會自動撤消。
  使用DirectDrawCreateClipper函式建立的DirectDrawClipper物件是一例外,這種情況下的DirectDrawClipper物件獨立於其它任意的DirectDraw物件並能用於一個或多個DirectDraw物件。
3.2、用CoCreateInstance建立DirectDraw物件
  你也可以不使用DirectDrawCreate函式而使用CoCreateInstance函式和 IDirectDraw2::Initialize方法來建立DirectDraw物件。下面是用CoCreateInstance函式建立DirectDraw物件的步驟:
i. 在應用程式開始時呼叫CoInitialize初始化COM:
if (FAILED(CoInitialize(NULL)))
  return FALSE;
ii.  使用CoCreateInstance函式和IDirectDraw2::Initialize方法建立DirectDraw物件:
ddrval = CoCreateInstance(&CLSID_DirectDraw,
  NULL, CLSCTX_ALL, &IID_IDirectDraw2, &lpdd);
if(!FAILED(ddrval))
  ddrval = IDirectDraw2_Initialize(lpdd, NULL);
  在對CoCreateInstance的呼叫中,第一個引數CLSID_DirectDraw是DirectDraw驅動物件類的類標誌符, IID_IDirectDraw2引數指明瞭要建立的DirectDraw介面,lpdd引數指向獲取的DirectDraw物件。如果呼叫成功,函式將返回一貫未初始化的DirectDraw物件。
  在使用DirectDraw物件之前,還必須呼叫IDirectDraw2::Initialize方法,該方法不使用GUID引數(DirectDrawCreate函式則需要只要)。
DirectDraw物件初始化後就可以使用也可以釋放該物件,就好象是該物件是由DirectDrawCreate函式建立的一樣。若在呼叫IDirectDraw2::Initialize方法之前使用同DirectDraw物件相關的方法將會導致一個DDERR_NOTINITIALIZED錯誤。
  在關閉應用程式前,應該使用CoUninitialize函式關閉COM,形式如下:
CoUnitialize();


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-987874/,如需轉載,請註明出處,否則將追究法律責任。

相關文章