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

無我

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

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 閱讀(6919) 評論(0)  編輯 收藏 引用 所屬分類: 游戲編程

<2011年3月>
272812345
6789101112
13141516171819
20212223242526
272829303112
3456789

導航

統計

公告

本博客原創文章,歡迎轉載和交流。不過請注明以下信息:
作者:TimWu
郵箱:timfly@yeah.net
來源:www.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>
            亚洲在线免费视频| 羞羞答答国产精品www一本| 久久久久一区二区三区| 性视频1819p久久| 国产日韩一区二区| 久久综合成人精品亚洲另类欧美| 欧美一区=区| 好看不卡的中文字幕| 美女国内精品自产拍在线播放| 欧美在线播放一区| 在线观看视频一区二区欧美日韩| 麻豆成人综合网| 欧美.日韩.国产.一区.二区| 99国产精品久久久久老师| 亚洲精品国产精品国自产观看| 欧美人与禽性xxxxx杂性| 亚洲视频在线一区观看| 亚洲欧美成人一区二区在线电影| 国产乱人伦精品一区二区| 久久免费视频在线观看| 欧美激情四色| 欧美一级淫片播放口| 久久一区二区三区四区五区| 妖精视频成人观看www| 午夜精品在线看| 亚洲黄色成人网| 一区二区三区不卡视频在线观看| 国产日韩欧美精品综合| 亚洲福利在线观看| 国产精品视频你懂的| 欧美丰满高潮xxxx喷水动漫| 国产精品videosex极品| 女主播福利一区| 国产精品久久久久毛片大屁完整版| 久久久久久久精| 欧美日韩精品免费观看视频| 久久久久久久久久久成人| 欧美日韩国产成人高清视频| 久久三级视频| 国产精品成人aaaaa网站| 免费h精品视频在线播放| 国产精品v欧美精品v日韩| 老司机免费视频一区二区三区| 欧美视频在线观看免费网址| 免费欧美高清视频| 国产亚洲欧美另类一区二区三区| 亚洲人线精品午夜| 在线观看欧美黄色| 午夜精品一区二区在线观看| 夜夜嗨av色综合久久久综合网| 久久久久久欧美| 久久激情综合| 国产精品卡一卡二卡三| 亚洲精品韩国| 亚洲人成在线观看| 久久蜜桃av一区精品变态类天堂| 欧美影院久久久| 欧美图区在线视频| 一区二区高清视频在线观看| 亚洲人成网在线播放| 麻豆av一区二区三区久久| 久久精选视频| 国产真实精品久久二三区| 亚洲欧美日韩成人高清在线一区| 中文日韩在线| 欧美日韩在线精品| 亚洲精选大片| 亚洲午夜久久久久久尤物| 欧美好吊妞视频| 亚洲激情二区| 一本色道久久加勒比88综合| 欧美国产一区在线| 亚洲国产你懂的| 亚洲毛片在线看| 欧美日韩美女一区二区| 99精品黄色片免费大全| 亚洲欧美高清| 国产欧美日韩中文字幕在线| 亚洲欧美日韩另类精品一区二区三区| 亚洲一级一区| 国产欧美日韩综合一区在线播放| 亚洲影院免费观看| 久久久一区二区| 影院欧美亚洲| 欧美黄网免费在线观看| 亚洲乱码国产乱码精品精可以看| 亚洲私人影吧| 国产亚洲人成网站在线观看| 久久亚洲欧美国产精品乐播| 亚洲高清在线视频| 亚洲午夜激情网站| 国产亚洲欧美在线| 欧美成熟视频| 一区二区三区国产在线观看| 久久精品国产77777蜜臀| 精品51国产黑色丝袜高跟鞋| 欧美精品 日韩| 亚洲婷婷综合色高清在线 | 久久久一区二区| 亚洲国产精品电影在线观看| 在线亚洲免费| 国产专区一区| 欧美日韩成人在线| 欧美亚洲一区三区| 亚洲激情视频在线观看| 午夜视黄欧洲亚洲| 亚洲国产精品视频| 国产精品一二一区| 蜜桃av综合| 亚洲欧美在线免费| 亚洲激情偷拍| 久久在线精品| 午夜精品久久久久久久99水蜜桃 | 国产精品一区在线播放| 久久久99爱| 一区二区三区高清视频在线观看| 巨胸喷奶水www久久久免费动漫| 一本色道久久综合亚洲精品高清| 国产性做久久久久久| 欧美日韩国产成人在线免费| 久久久成人精品| 亚洲午夜羞羞片| 亚洲日本va午夜在线电影| 久久久一二三| 欧美亚洲视频在线观看| 亚洲精品一品区二品区三品区| 国产一区二区三区在线观看免费视频 | 亚洲一区二区网站| 亚洲福利久久| 美国三级日本三级久久99| 亚洲欧美日韩精品一区二区 | 欧美午夜精品理论片a级按摩| 久久久精品日韩欧美| 亚洲午夜羞羞片| 亚洲免费av电影| 亚洲国产精品t66y| 欧美成人视屏| 美女久久网站| 久久夜精品va视频免费观看| 欧美一级播放| 午夜视频在线观看一区二区| 一区二区三区日韩| 99精品欧美一区二区三区综合在线| 在线观看视频一区二区| 韩国自拍一区| 激情欧美一区二区三区在线观看 | 免播放器亚洲一区| 久久久在线视频| 久久青草欧美一区二区三区| 久久精品国产第一区二区三区最新章节 | 91久久在线| 亚洲电影专区| 亚洲人成在线观看| 99国产精品国产精品久久| 亚洲精品视频在线观看免费| 亚洲精品欧美精品| 日韩午夜激情av| 国产精品99久久久久久白浆小说| 亚洲视频一区| 性欧美精品高清| 久久免费国产精品| 欧美大秀在线观看| 亚洲精品久久久久久下一站| 999亚洲国产精| 亚洲一区欧美二区| 久久国产主播| 欧美jizzhd精品欧美巨大免费| 欧美激情精品久久久久久久变态| 欧美人在线观看| 国产欧美一区二区精品忘忧草| 国产偷久久久精品专区| 在线免费观看视频一区| 99国产精品久久久久久久久久| 亚洲综合精品四区| 久久亚洲综合| 亚洲精品韩国| 欧美一级淫片播放口| 免费人成精品欧美精品| 欧美日一区二区在线观看| 国产在线欧美日韩| 亚洲精品一区久久久久久| 午夜精品一区二区三区电影天堂| 另类专区欧美制服同性| 亚洲精品久久久久久久久久久久久| 亚洲一区二区三区四区五区黄| 久久精视频免费在线久久完整在线看| 欧美成黄导航| 国产人成一区二区三区影院| 亚洲精品国产精品乱码不99按摩| 亚洲综合社区| 欧美刺激性大交免费视频| 亚洲影院高清在线| 欧美成人免费小视频| 国产日产精品一区二区三区四区的观看方式 | 欧美伊人久久| 亚洲精品在线免费观看视频| 久久久99精品免费观看不卡| 欧美日韩亚洲网| 在线观看日韩av| 香蕉成人久久|