閱讀466 返回首頁    go 阿裏雲 go 技術社區[雲棲]


DirectDraw用到的DDSURFACEDESC2

DDSURFACEDESC2 結構定義一個需求的平麵.下麵的例子演示了結構的定義和標誌位的設定:
// Create the primary surface with one back buffer. 
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
                     DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1;

在這個例子中,dwSize成員是DDSURFACEDESC2結構的大小.這是防止你用到的DirectDraw方法返回無效成員的錯誤.(dwSize是準備給將來的DDSURFACEDESC2結構的擴展用的)
dwFlags成員決定的DDSURFACEDESC2結構中那些成員將被填充有效的信息.例如在DDEx1中,dwFlags被設為你想要用DDSCAPS結構(DDSD_CAPS)和你想創建一個後台緩衝(back buffer)(DDSD_BACKBUFFERCOUNT)
dwCaps成員在例子中標示一個將要在DDSCAPS結構中使用的標誌位.在這種情況下,他指定一個主平麵(primary surface DDSCAPS_PRIMARYSURFACE),一個交換頁(flipping surface DDSCAPS_FLIP),一個合成表麵(complex surface DDSCAPS_COMPLEX).
最後,例子指定了一個後台緩衝.後台緩衝就是實際的繪圖操作先在那裏完成,然後,再快速的翻動(flip)到主平麵(primary surface)上.在DDEx1中,後台緩衝的數目是1.其實,你要你的顯存允許,你想建幾個就建幾個.你想知道更多的關於創建大於1塊緩衝的信息,可以去看  "triple buffering".
創建的"平麵"占用的存儲空間,可以是係統內存也可以是顯存.如果應用程序使用的空間超出了顯存,DirectDraw就會使用係統內存.(例如你指定多塊緩存在一個僅有1MB顯存的是配器上).你也可以這樣設置DDSCAPS結構的dwCaps成員,設成DDSCAPS_VIDEOMEMEORY或DDCAPS_SYSTEMMEMORY以達到隻用顯存或隻用內存.(如指定用顯存,而顯存不夠,IDirectDraw7::CreateSurface返回一個DDERR_OUTOFVIDEOMEMORY錯誤) 
補充:

DDSURFACEDESC2 ddsd;
ddsd.dwSize = sizeof(DDSURFACEDESC2);

dwFlags:這個域用來告訴DirectDraw,你給的數據是用來填充DDSURFACEDESC2的哪個域的。或者,如果你在一個查詢操作中用這個結構,告訴DirectDraw你要獲得DDSURFACEDESC2的哪個域的信息。看看表6.5,其列出了這個標誌字可取的值。比如,你如果你要在 dwWidth 和 dwHeight 兩個域中填入有效數據則應該像下麵這樣設置dwFlags域:

ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;

這樣,DirectDraw便知道去查找 dwWidth 和 dwHeight 域,然後放入有效值。就把單位dwFlags看成是引導數據的指示器吧。

表 6.5. DDSURFACEDESC2的dwFlags域的各種可能的標誌
        值                          描述 
DDSD_ALPHABITDEPTH    表明 dwAlphaBitDepth 有效 
DDSD_BACKBUFFERCOUNT   表明 dwBackBufferCount 有效 
DDSD_CAPS     表明 ddsCaps 有效
DDSD_CKDESTBLT    表明 ddckCKDestBlt 有效 
DDSD_CKDESTOVERLAY    表明 ddckCKDestOverlay 有效 
DDSD_CKSRCBLT    表明 ddckCKSrcBlt 有效 
DDSD_CKSRCOVERLAY    表明 ddckCKSrcOverlay 有效 
DDSD_HEIGHT     表明 dwHeight 有效
DDSD_LINEARSIZE    表明 dwLinearSize 有效 
DDSD_LPSURFACE    表明 lpSurface 有效 
DDSD_MIPMAPCOUNT    表明 dwMipMapCount 有效 
DDSD_PITCH     表明 lPitch 有效 
DDSD_PIXELFORMAT    表明 ddpfPixelFormat 有效 
DDSD_REFRESHRATE    表明 dwRefreshRate 有效 
DDSD_TEXTURESTAGE    表明 dwTextureStage 有效
DDSD_WIDTH     表明 dwWidth 有效 

dwWidth:表明表麵的像素寬度。當你創建一個表麵是,這裏便是你設定寬度的地方。320,640等等。此外,如果你要查詢表麵的屬性,這個域將返回表麵的寬度(如果你這麼要求的話)。

dwHeight:表麵表麵的像素高度。與dwWidth類似,這裏是你在創建表麵時設定其高度的地方。300,240,480等等。

lPitch:這是個有趣的域。基本上它是你所選擇模式的水平內存間距。看圖6.8。lPitch,也被稱為步幅或內存寬度,是在給定視頻模式下每行的的字節數。基於如下原因,這是個非常重要的數據域:當你要求一個640×480×8的顯示模式,你知道每行有640個像素,每個像素占8位內存(即1個字節)。所以,每行有640個字節,於是lPitch似乎便該設為640。對嗎?不一定哦。
                        圖 6.8. 訪問一個表麵

技巧:lPitch將根據VRAM的不同設計而不同。故而,當你在DirectDraw表麵上從一行訪問另一行的內存時,你必需使用lPitch來移動到下一行,而不是用寬度乘上每像素的字節數。這一點非常之重要。

大多數新顯卡支持我們所謂的“線性內存模式”而且有硬件尋址功能,這些屬性已經是現實了,但並不保證每塊顯卡都實現之。所以,你不能假設一個640×480×8視頻模式在內存中每行占640個字節。而這便是lPitch域存在的理由。你必需在你計算內存地址時應用它以保證計算正確,這樣你便可以從一行移動到另一行了。比如,要訪問640×480×8(256色)視頻模式下的任何一個像素,你可以使用下麵的代碼。假設你已經從DirectDraw得到lPitch值,並且lpSurface已經指向表麵內存(我會在下麵解釋這個參數的)

ddsd.lpSurface[x + y*ddsd.lPitch] = color;

是不是很簡單啊?大多數情況下,ddsd.lPitch 設為640以代表640x480x8模式。而對於640×480×16模式,ddsd.lPitch 將設為1280(兩字節每像素=640×2)。但是,對於某些顯卡,出於顯存的布局原因,比如內在緩存的設立或其他什麼東西,就使得事情不像上述這樣了。所以最正規的方式是:在計算內存時總是使用lPitch,你便總是安全的。

技巧:盡管lPitch值並不總是等於你設置的視頻模式的水平值,但使用其來測試水平值可以使你能夠調用到其他優化函數。比如,在你完成初始化部分功能的代碼中,你可以去獲得lPitch值並與你選擇的視頻模式水平值比較。如果它們相等,則你可以切換到你為優化程序而硬編碼每行字節數的函數上。

lpSurface:這個域獲得指向你隨創建表麵的真實內存地址的指針。這些內存可能是VRAM也可能是係統內存,但是你無需為次擔心。一旦你獲得了指向該內存的指針,你便可以像操作其他內存一樣操作它了,比如向它寫數據或讀數據,等等,這完全取決於你想如何填充像素。嗬嗬,讓這個指針有效多容易啊!但是我們還是要在這裏多停留一會。一般,你必需“鎖定”表麵內存,並且告訴DirectX你要在該內存上麵工作了而其他的進程不許試圖在該內存上讀或寫。進一步的,當你獲得了這個指針時,根據不同的色深(8,16,24,32)你要經常對其進行類型轉換並將其複值給一個工作指針。

dwBackBufferCount:這個域被用來設置和讀取後備緩存(或與主表麵關聯的副離屏翻頁緩存)的數目。如果你能回憶起來,通過創建一個或更多的虛主表麵(與表麵擁有同樣的圖樣和色深的緩存),後備緩存可用來實現動畫的平滑化,這也便是離屏緩存。然後你在後備緩存上繪圖,這個後備緩存對於用戶而言是不可見的。接著快速的翻頁或拷貝後備緩存到主表麵以供顯示。如果你隻有一個後備緩存,這個技術便成為“雙緩存技術”。使用兩個緩存便叫“三緩存技術”,當然後者比前者擁有更好的效果但也占用更多的內存。為了是事情簡單點,大多數情況下,你將創建一個包括一個主表麵和一個後備緩存的翻頁鏈。

ddckCKDestBlt:這個域被用來控製目標顏色鍵。當進行塊傳輸操作時,這個域控製寫入顏色的方式。更多信息將在後麵第七章“高級DirectDraw和位圖圖形”上介紹。

ddckCKSrcBlt:這個域表明源顏色鍵。即當你進行bitmapping操作時{?後麵好像有這個術語,一時想不起來了,但翻到後麵再該過來吧。yew98}你不想被塊傳遞的顏色。這是一個你如何設置你位圖透明色的的方法。詳見第七章。

ddpfPixelFormat:這個域用來獲得表明像素的格式。當你去查詢表明的屬性是這就非常重要了。下麵的是其結構。你可能要去查詢DirectX SDK以獲得更多的細節信息。因為這些信息實在太多了,而且和現在的討論關心也不大。
typedef struct _DDPIXELFORMAT
        {
        DWORD dwSize;
       DWORD dwFlags;
        DWORD dwFourCC;
        union
        {
        DWORD dwRGBBitCount;
        DWORD dwYUVBitCount;
        DWORD dwZBufferBitDepth;
        DWORD dwAlphaBitDepth;
        DWORD dwLuminanceBitCount; // new for DirectX 6.0
        DWORD dwBumpBitCount;      // new for DirectX 6.0
        } DUMMYUNIONNAMEN(1);
        union
        {
        DWORD dwRBitMask;
        DWORD dwYBitMask;
        DWORD dwStencilBitDepth;   // new for DirectX 6.0
        DWORD dwLuminanceBitMask;  // new for DirectX 6.0
        DWORD dwBumpDuBitMask;     // new for DirectX 6.0
        } DUMMYUNIONNAMEN(2);
        union
        {
        DWORD dwGBitMask;
        DWORD dwUBitMask;
        DWORD dwZBitMask;          // new for DirectX 6.0
        DWORD dwBumpDvBitMask;     // new for DirectX 6.0
        } DUMMYUNIONNAMEN(3);
        union
        {
        DWORD dwBBitMask;
        DWORD dwVBitMask;
        DWORD dwStencilBitMask;    // new for DirectX 6.0
        DWORD dwBumpLuminanceBitMask;  // new for DirectX 6.0
        } DUMMYUNIONNAMEN(4);
        union
        {
        DWORD dwRGBAlphaBitMask;
        DWORD dwYUVAlphaBitMask;
        DWORD dwLuminanceAlphaBitMask; // new for DirectX 6.0
        DWORD dwRGBZBitMask;
        DWORD dwYUVZBitMask;
        } DUMMYUNIONNAMEN(5);
        } DDPIXELFORMAT, FAR* LPDDPIXELFORMAT;
注意:我加粗的域是常用域

ddsCaps:這個域用來使那些被要求的但尚未在表麵屬性中定義的項有效。事實上,這個域又是另一個數據結構。下麵顯示了DDSCAPS2:
typedef struct _DDSCAPS2
        {
        DWORD    dwCaps;   // Surface capabilities
        DWORD    dwCaps2;  // More surface capabilities
        DWORD    dwCaps3;  // future expansion
        DWORD    dwCaps4;  // future expansion
        } DDSCAPS2, FAR* LPDDSCAPS2;
在99.9%的情況下,你隻需設置該結構的第一個域。dwCaps.dwCaps2 是為3D準備的,而其他域dwCaps3 和 dwCaps4是為未來擴展之用,尚未使用。總之,表6.6列出了dwCaps可能設置的標誌值。要看完整的列表,到DirectX SDK裏去。

比如當要創建一個主表麵是,你可以像下麵這樣設置ddsd.ddsCaps

ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

我知道上麵這種表達方式很複雜,在某種程度上確實如此。雙重嵌套的控製標誌確實有點痛苦。但是,忍受吧……

   表 6.6. DirectDraw表麵的屬性控製設置
        值                                         描述
DDSCAPS_BACKBUFFER     表明這個表麵是表麵翻頁結構中的後備緩存。 
DDSCAPS_COMPLEX     表明是一個複習表麵。一個複雜表麵是一個與一或多個串成翻頁鏈的後備緩存關聯的主表麵。 
DDSCAPS_FLIP     表明這個表麵是一個表麵翻頁結構中的一部分。但這個屬性被傳遞給 CreateSurface() 方法時, 一個前端緩存和一個或多個後備     緩存將被創建。 
DDSCAPS_LOCALVIDMEM    表明這個表麵優先存在於顯存中。如果這個標誌選中則 DDSCAPS_VIDEOMEMORY 也必需選中。 
DDSCAPS_MODEX     表明這個表麵是一個320x200 或 320x240 的Mode X 表麵。 
DDSCAPS_NONLOCALVIDMEM    表明這個表麵優先存在於非本地顯存中。如果這個標誌選中則 DDSCAPS_VIDEOMEMORY 也必需選中。
DDSCAPS_OFFSCREENPLAIN    表明這個表麵是個離屏表麵。這樣該表麵便不能是某種特殊表麵了,比如不是一個覆蓋層,素材,z序,前端緩存,後備緩存,或者     alpha 表麵。(Usually used for sprites。) 
DDSCAPS_OWNDC     表明這個表麵將長期與一個設備上下文關聯。 
DDSCAPS_PRIMARYSURFACE    表明這個表麵是主表麵。其描述了此刻為用戶所見的東西。
DDSCAPS_STANDARDVGAMODE    表明該表麵是一個標準的VGA模式的表麵,而非 Mode X 模式。這個標誌不能與 DDSCAPS_MODEX 標誌同時使用。 
DDSCAPS_SYSTEMMEMORY    表明這個表麵創建在係統內存中。 
DDSCAPS_VIDEOMEMORY    表明這個表麵創建在顯存中。

最後更新:2017-04-03 14:54:15

  上一篇:go 【轉載】win7+ubuntu 下ubuntu卸載方法
  下一篇:go Maven中pom.xml的scope