青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

無我

讓內心永遠燃燒著偉大的光明的精神之火!
靈活的思考,嚴謹的實現
豪邁的氣魄、頑強的意志和周全的思考

DirectDraw編程方法與技巧


 
 DirectDraw編程方法與技巧
添加時間:2006-10-18   出處:www.3DGameDev.org  作者:songtao
 
 
1 概 述

  DirectX是Microsoft為軟件開發人員提供的一套精心設計的接口,用于開發高性能、實時的應用程序。它以COM(component object modal)為基本結構[1],位于硬件和軟件之間,像gdi(graphics device interface)一樣提供了硬件無關的API(application programming interface)接口;它和GDI有一重要不同點:DirectX是一套底層的API接口,它提供了直接訪問硬件的能力,使得DirectX應用程序能充分發揮硬件的威力。
  DirectDraw是DirectX中提供直接操縱顯存、執行硬件映射、硬件覆蓋及切換顯示頁等功能的組件。它不但兼容已有的Windows應用程序和驅動程序,而且還兼容許多顯示卡:從簡單的SVGA到支持圖像剪裁、拉伸和非RGB格式圖像的高檔顯示卡。DirectDrawHAL(hardware-abstraction layer)抽象了顯示卡的硬件功能,以設備無關的方式提供了一些以前是設備相關的功能,如多顯示頁技術、訪問并控制顯示卡映射寄存器、支持3DZ-Buffer、支持Z-order硬件覆蓋、訪問圖像拉伸硬件,以及同時訪問標準顯存和控制顯存。正因為DirectDraw有這些優點,現在許多基于Windows95/98/NT的游戲程序都使用了DirectDraw;而它的設備無關性使開發者擺脫了繁重的顯示卡接口工作,集中精力實現程序的主要功能。DirectX中的DDraw.dll實現了DirectDraw所需要的函數、對象及其接口。下面先介紹DirectDraw中主要的函數、對象和接口,然后再說明DirectDraw的使用方法。

2 DirectDraw中的函數、對象和接口簡介

  DirectDraw包括一個代表顯示卡的主對象DirectDraw,由函數DirectDrawCreate創建,實現接口IDirectDraw和IDirectDraw2。如果機器上裝有多個顯示卡,可以為每個顯示卡創建一個DirectDraw對象。也可以創建多個DirectDraw對象,它們各自獨立并代表同一物理對象。IDirectDraw是為了和以前版本DirectX兼容而保留的接口,基于DirectX3以上版本的程序應該使用IDirectDraw2。IDirectDraw2和IDirectDraw接口所包含的方法定義基本相同,但具體實現不同。DirectDraw對象主要用于創建其它3個對象:DirectDrawSurface、DirectDrawPalette、DirectDrawClipper。
  DirectDrawSurface對象由函數IDirectDraw2::CreateSurface創建,代表顯存中一塊線性區域,實現接口IDirectDrawSurface和IDirectDrawSurface2。IDirectDrawSurface是為了和以前版本DirectX兼容而保留的接口,基于DirectX3以上版本的程序應該使用IDirectDrawSurface2。二者的接口定義也基本相同。可以為一個DirectDraw對象創建多個IDirectDrawSurface對象,代表物理屏幕或邏輯屏幕,通過IDirectDrawSurface2::Flip、IDirectDrawSurface2::BltFast等方法切換顯示頁或映射部分屏幕內容。
  DirectDrawPalette對象由函數IDirectDraw2::CreatePalette創建,實現接口IDirectDrawPalette。它代表顯示卡的物理調色板,可以是16色或256色。每個DirectDrawPalette必須附著(attach)在一個DirectDrawSurface上,不同的DirectDrawSurface對象可以有不同的DirectDrawPalette。
  DirectDrawClipper對象由函數IDirectDraw2::CreateClipper或DirectDrawCreateClipp
er創建,實現接口IDirectDrawClipper。DirectDraw用它來處理屏幕的剪貼。它常用于在Window模式(與全屏模式相對應)下運行的DirectDraw程序,在使用前也必須被附著在一個DirectDrawSurface上。

3 DirectDraw程序一般工作過程

  和一般的Windows程序[2]一樣,DirectDraw程序要先創建一個主窗口,然后進行DirectDraw的初始化:創建所需要的對象,設置程序的工作模式,建立必要的數據結構。在初始化工作完成后,就可以在主窗口的消息循環中根據用戶的輸入調用相應對象的方法。

3.1 初始化DirectDraw
3.1.1 創建DirectDraw對象
  首先調用DirectDrawCreate創建代表某個顯示卡的DirectDraw對象:
  ddres=DirectDrawCreate(NULL,&lpDD,NULL);
  DirectDrawCreate的第一項參數是代表顯示卡驅動程序的GUID(globally unique identifier),若為NULL則表示采用系統默認的驅動程序。第二項參數是IDirectDraw接口類型指針的地址,用于接收指向由DirectDrawCreate所創建對象的指針。這個指針不需應用程序預先分配內存。DirectDrawCreate成功時會調用AddRef將對象的引用計數加1。如果要知道系統中所有驅動程序的GUID,可以調用DirectDrawEnumerate,它接收兩個參數:回調函數的地址和傳給回調函數的自定義數據的地址,其工作方式和Win32 API Enum Windows類似。
3.1.2 設置DirectDraw的工作模式
  創建DirectDraw對象后應該馬上設置DirectDraw對象的工作模式:
  ddres=lpDD→SetCooperativeLevel(hWnd,DDSCL_EXCLUSIVE|DDSCLFUL_LSCREEN);
  SetCooperativeLevel的第一個參數是和DirectDraw對象關聯的窗口句柄,一般是程序主窗口的句柄;第二個參數指明了DirectDraw對象的工作模式。DirectDraw對象有兩種工作模式:普通模式(Windowedmode,參數DDSCL_NORMAL)和獨占模式(Full_Screen mode,參數DDSCL_EXCLUSIVE)。普通模式下DirectDraw和普通Windows程序的區別不大,主要是DirectDraw程序可以隨心所欲地讀取整個屏幕的內容或在屏幕的任意位置輸出,而其它的Windows程序毫無察覺。獨占模式就是游戲“紅色警報”和“赤壁”所采用的方式,并必須和全屏模式(參數DDSCL_FULLSCREEN)聯用,此時程序的主窗口被擴展為整個屏幕。其它應用程序都成為后臺程序,使用Alt+Tab鍵可以在程序間切換。
3.1.3 得到IDirectDraw2類型的接口
  接下來利用COM的重要方法QueryInterface,通過IDirectDraw接口得到一個IDirectDraw2類型的接口。QueryInterface成功時會將對象的引用計數加1,而我們也不再需要IDirectDraw接口,因此這里調用IDirectDraw::Release將對象的引用計數減1,也即釋放先前得到的IDirectDraw接口。
3.1.4 根據需要切換屏幕顯示模式
  如果DirectDraw的工作模式設定為全屏獨占模式,則可以根據需要切換屏幕顯示模式:
  ddres=lpDD2→SetDisplayMode(800,600,16);
  SetDisplayMode的前兩個參數是屏幕的橫、縱分辨率,最后一個是每個像素點的顏色位數。上例將屏幕設為800×600,16位色。
3.1.5 創建DirectDrawSurface對象并得到IDirectDrawSurface2接口
  創建DirectDraw對象后,下一步調用IDirectDraw2::CreateSurface創建代表物理屏幕或邏輯屏幕的DirectDrawSurface對象。IDirectDraw2::CreateSurface的第一個參數是DDSURFACEDESC結構的地址,第二個參數是一個IDirectDrawSurface接口類型的指針地址,第三個參數必須是NULL。數據結構DDSURFACEDESC包含了創建DirectDrawSurface所需信息。在得到一個IDirectDrawSurface類型接口后,仍使用QueryInterface得到一個IDirectDrawSurface2類型的接口,并釋放先前得到的IDirectDrawSurface接口:
  //Get the IDirectDrawSurface2interface.
  LPDIRECTDRAWSURFACE2lpDDSPrimary=NULL;
  ddres=lpDDSPrimaryTemp>QueryInterface(IID_IDirectDrawSurface2,(LPVOID)&lpDDSPrimary;
  lpDDSPrimaryTemp→Release();
  上面得到的lpDDSPrimary指向代表物理屏幕的對象。還需調用IDirectDrawSurface2::GetAttachedSurface得到指向創建時附帶的代表相關邏輯屏幕的對象指針。至此,DirectDraw初始化工作完成。

3.2 使用DirectDraw
3.2.1 使用GDI函數向物理屏幕或邏輯屏幕輸出
  調用IDirectDrawSurface2::GetDC可得代表某個屏幕的設備描述表的句柄,使用GDI函數輸出,最后調用IDirectDrawSurface2::ReleaseDC釋放句柄。為防止在對屏幕作圖期間其它應用程序爭奪顯存,IDirectDrawSurface2::GetDC調用IDirectDrawSurface2::Lock得到Winl6 Lock。這意味著其它程序在該程序釋放Win16Lock前都不能訪問GDI和USER資源。IDirectDrawSurface2::ReleaseDC調用IDirectDrawSurface2::Unlock釋放Win16 Lock。于是,在調用IDirectDrawSurface2::GetDC和IDirectDrawSurface2::ReleaseDC期間,Windows將被掛起。因此,應用程序應盡量縮短這一對函數調用之間的間隔時間,而且調試程序也無法跟蹤這段時間內執行的操作。
3.2.2 交替切換物理屏幕和邏輯屏幕或執行屏幕內容的映射
  準備好內存中的邏輯屏幕后,可以調用IDirectDrawSurface2::Flip方法切換物理屏幕和邏輯屏幕,也可調用IDirectDrawSurface2::BltFast、IDirectDrawSurface2::Blt等方法執行部分屏幕內容的映射。一般情況下程序采用異步方式,在顯示卡硬件執行切換動作的同時準備下一頁屏幕,使CPU和顯示卡硬件并行,提高整體執行速度。
  使用Flip切換物理屏幕和邏輯屏幕后,原指向物理屏幕的指針仍然指向物理屏幕,原指向邏輯屏幕的指針仍然指向邏輯屏幕,即指針所指內容也被交換了,便于程序操縱各個屏幕而不至于混淆。
3.2.3 釋放DirectDraw對象
  程序結束之前要釋放所創建的DirectDraw對象。這只要在相應接口上調用Release方法即可。

4 使用DirectDraw的技巧和注意事項

4.1 檢查方法的返回值
  正確執行DirectDraw方法時都返回DDOK。且其值是零。返回其它值表明發生了某種錯誤。一般地,程序應檢查這些返回值以決定是否出錯。

4.2 檢查Flip和Blt的狀態
  如果在Flip或Blt操作的返回值是DDERR_WASSTILLDRAWING情況,為提高效率,DirectDraw提供了IDirectDrawSurface2::GetFlipStatus和IDirectDrawSurface2::GetBltStatus方法。它們能立即返回當前的Flip和Blt狀態,于是應用程序可以在上一操作完成之前執行某些其他的任務。

4.3 在位圖映射中使用ColorKey
  ColorKey是一種或幾種顏色的集合,用于在位圖映射操作中區分前景色和背景色。ColorKey包括兩種:Source color key和Destination color key。前者是指源位圖中代表透明色的顏色,在執行映射操作時將不被映射到目標位圖上;后者是指目標位圖中將被源位圖中相應位置顏色取代的顏色,如果目標位圖指定了Destination color key,則只有這些指定的顏色被替換。可以在創建DirectDrawSurface對象時指定Color Key;也可使用方法IDirectDrawSurface2::GetColorKey和IDirectDrawSurface2::SetColorKey以獲取和設置已有的DirectDrawSurface對象的ColorKey。

4.4 GDI重定向
  由于GDI在Windows系統啟動時先于DirectDraw被裝入,而DirectDraw工作時又繞過了GDI,因此GDI不知道DirectDraw對物理屏幕所進行的操作。即使DirectDraw調用了Flip方法將先前的物理屏幕切換為邏輯屏幕,如不采取措施,GDI將仍然向切換后的邏輯屏幕上輸出。如果DirectDraw程序擁有菜單、滾動條等由GDI負責繪制的元素,那么在Flip完成后這些元素就會成為不可見,而在對應的邏輯屏幕被切換成物理屏幕時又會顯示出來。為避免屏幕閃爍,DirectDraw提供了IDirectDraw2::GetGDISurface,用于確定當前被GDI認為是物理屏幕的DirectDrawSurface對象;以及IDirectDraw2::FlipToGDISurface,用于將GDI的輸出重新定向到當前的物理屏幕上。如果需要,可以在每次Flip操作后調用它,以保證屏幕正常。

4.5 在顯存中存放位圖
  由于從顯存到顯存的映射比從系統內存到顯存的映射快,所以經常將需要映射的位圖存放在顯存中以提高速度。大多數顯示卡在存放了物理屏幕和相關邏輯屏幕之外還有足夠的內存可以用來存放位圖。可以調用IDirectDraw2::GetCaps檢查顯存;在創建DirectDrawSurface對象時可以通過結構DDSURFACEDESC中的DDSCAPS域指定該對象存在于顯存或系統內存中。如果指定在顯存中創建對象,而顯存又沒有地方容納該對象,IDirectDraw2::CreateSurface會返回錯誤信息DDERR_OUTOFVIDEOMEMORY。如果沒有指定創建的位置,DirectDraw總是盡量利用空閑的顯存。

4.6 檢查硬件的性能
  雖然DirectDraw通過HAL和HEL屏蔽了硬件的具體特性,但應用程序也需根據硬件的不同性能來改變自身的執行方式。利用IDirectDraw2::GetCaps方法可以得到有關硬件性能的詳細信息。

4.7 保持主窗口的消息循環暢通
  在調用SetCooperativeLevel設置DirectDraw的工作模式時,應用程序為DirectDraw指定了主窗口。由于DirectDraw直接操縱硬件可能導致死機,因此DirectDraw在后臺監視主窗口的消息循環,當消息循環長時間沒有反應時,DirectDraw就釋放所有的資源,結束應用程序的執行。所以DirectDraw程s序應該注意避免長時間封鎖消息循環。

 

posted on 2007-07-22 15:27 Tim 閱讀(6918) 評論(0)  編輯 收藏 引用 所屬分類: 游戲編程

<2012年5月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

導航

統計

公告

本博客原創文章,歡迎轉載和交流。不過請注明以下信息:
作者:TimWu
郵箱:timfly@yeah.net
來源:m.shnenglu.com/Tim
感謝您對我的支持!

留言簿(9)

隨筆分類(173)

IT

Life

搜索

積分與排名

最新隨筆

最新評論

閱讀排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美精品18videos性欧美| 国产一区二区三区在线观看视频| 中日韩在线视频| 国产精品白丝av嫩草影院| 亚洲视频1区| 久久天堂av综合合色| 亚洲精品一区二区三区樱花| 国产精品视频自拍| 欧美成人精品一区| 欧美一区三区三区高中清蜜桃| 久久尤物视频| 欧美成人亚洲成人| 亚洲激情黄色| 亚洲日本中文| 一本色道久久综合狠狠躁篇的优点 | 性欧美精品高清| 久久精品亚洲一区二区| 浪潮色综合久久天堂| 欧美91精品| 日韩视频在线观看| 亚洲欧美自拍偷拍| 欧美成人精品三级在线观看| 欧美视频网站| 国内外成人在线| 国产精品www994| 欧美乱大交xxxxx| 欧美成人精品在线| 久久一区二区三区四区| 欧美国产视频一区二区| 久久久亚洲欧洲日产国码αv | 国产精品色婷婷| 欧美天天在线| 久久久久一区二区三区四区| 午夜精品视频在线| 国产精品ⅴa在线观看h| 亚洲大胆在线| 免费成人美女女| 蜜臀久久久99精品久久久久久| 久久一二三区| 91久久精品美女| 亚洲成色精品| 久久夜色精品国产| 久久夜色精品国产亚洲aⅴ| 国产一区二区三区在线播放免费观看| 久久亚洲春色中文字幕| 欧美日韩综合视频网址| 在线免费不卡视频| 久久久欧美精品sm网站| 亚洲调教视频在线观看| 欧美 日韩 国产一区二区在线视频 | 免费成人av在线| 亚洲欧美福利一区二区| 欧美日韩在线一区| 最近看过的日韩成人| 久久免费黄色| 久久aⅴ国产欧美74aaa| 国产亚洲美州欧州综合国| 亚洲一区二区三区视频| 日韩亚洲欧美一区| 欧美岛国在线观看| 亚洲人成7777| 亚洲国产一区二区三区a毛片| 欧美在线综合| 国产视频亚洲精品| 久久国产精品亚洲va麻豆| 亚洲在线网站| 国产伦精品免费视频| 午夜精品久久久久久久白皮肤| 亚洲日本一区二区三区| 欧美激情小视频| 亚洲精品免费一区二区三区| 女女同性精品视频| 久久一区二区三区超碰国产精品| 亚洲第一黄色| 亚洲国产精品电影在线观看| 美女主播视频一区| 亚洲精品影院| 亚洲视频在线一区观看| 国产人久久人人人人爽| 久久激情五月丁香伊人| 欧美在线观看视频一区二区| 在线精品视频免费观看| 亚洲国产成人av在线| 欧美激情日韩| 亚洲综合成人婷婷小说| 欧美一级专区免费大片| 亚洲高清资源| 日韩一区二区福利| 国产欧美精品va在线观看| 亚洲欧美日本国产有色| 狂野欧美性猛交xxxx巴西| 亚洲人成啪啪网站| 日韩一级大片| 国产精品免费网站| 麻豆成人在线播放| 欧美人成网站| 久久精品久久99精品久久| 麻豆乱码国产一区二区三区| 亚洲一区二区三区中文字幕在线 | 亚洲电影自拍| 国产精品久久久久91| 久久天天躁狠狠躁夜夜av| 欧美夫妇交换俱乐部在线观看| 亚洲欧美国产精品va在线观看 | 久久九九国产精品| 欧美精品啪啪| 久久精品国亚洲| 欧美特黄a级高清免费大片a级| 欧美中文在线视频| 欧美激情性爽国产精品17p| 久久亚洲精品一区二区| 欧美日韩国产影片| 欧美成人久久| 黑人巨大精品欧美黑白配亚洲| avtt综合网| 日韩午夜激情电影| 美腿丝袜亚洲色图| 狂野欧美一区| 韩日欧美一区二区| 欧美一区二区免费观在线| 亚洲一区精品电影| 欧美伦理在线观看| 亚洲国产你懂的| 亚洲电影免费在线| 久久精视频免费在线久久完整在线看| 亚洲欧美日韩视频一区| 免费不卡中文字幕视频| 久久久久久久综合日本| 国产日韩精品一区二区| 国产精品99久久久久久久久| 99精品欧美一区二区三区 | 亚洲美女啪啪| 日韩一区二区精品在线观看| 久久久777| 久久综合九色九九| 国产精品一区二区男女羞羞无遮挡| 亚洲欧洲精品一区二区三区不卡| 在线精品一区| 亚洲欧美伊人| 亚洲性夜色噜噜噜7777| 欧美亚洲成人精品| 日韩午夜视频在线观看| 99在线观看免费视频精品观看| 免费欧美电影| 欧美激情二区三区| 在线观看欧美日本| 久久久久国产精品一区| 久久影视精品| 欧美xart系列高清| 女生裸体视频一区二区三区| 亚洲天堂免费观看| 亚洲日本中文字幕| 亚洲第一网站| 老**午夜毛片一区二区三区| 亚洲欧洲一区二区三区久久| 老司机精品视频网站| 亚洲天堂黄色| 久久九九国产精品| 欧美韩日一区二区| 欧美亚州韩日在线看免费版国语版| 亚洲国产二区| 国产精品一区二区在线观看| 欧美一级免费视频| 99视频有精品| 国产欧美日韩免费看aⅴ视频| 亚洲欧美电影院| 亚洲天堂成人在线观看| 国产亚洲成av人片在线观看桃| 欧美18av| 亚洲一区视频在线| 欧美成人精品在线播放| 亚洲综合视频在线| 国产精品99久久久久久宅男 | 亚洲欧美日韩另类| 亚洲日本激情| 久久夜色精品| 久久这里有精品视频| 国产精品视频yy9299一区| 香蕉精品999视频一区二区 | 欧美在线播放视频| 亚洲黄色小视频| 欧美伊人久久久久久午夜久久久久| 亚洲成色777777在线观看影院| 国产精品99久久久久久久vr | 日韩亚洲欧美成人| 久久综合中文色婷婷| 国产精品一区免费观看| 欧美黄色免费| 久久九九热免费视频| 久久亚洲欧美| 久久精品卡一| 国产亚洲精品综合一区91| 欧美性一区二区| 亚洲一区二区三区四区五区黄| 亚洲国产精品尤物yw在线观看| 欧美在线视频一区| 国产午夜精品一区二区三区欧美 | 亚洲视频在线观看网站| 欧美久久婷婷综合色| 蜜臀91精品一区二区三区|