游戲編程之四 diectxdarw基礎(chǔ)篇(編程游戲

      網(wǎng)友投稿 689 2025-04-01

      視頻課:https://edu.csdn.net/course/play/7621

      第四章 diectxdarw基礎(chǔ)篇

      第一節(jié) DirectDraw簡(jiǎn)介

      Grubers的一個(gè)觀點(diǎn)是DirectDraw“只是一個(gè)bltting發(fā)動(dòng)機(jī)”。這是相當(dāng)準(zhǔn)確的,但卻太簡(jiǎn)化了。更準(zhǔn)確地講,DirectDraw是一個(gè)可以提供軟件仿真測(cè)試的獨(dú)立于硬件設(shè)備的bltting發(fā)動(dòng)機(jī)。DirectDraw的主要用途是盡可能快、盡可能可靠并且盡可能連續(xù)地將圖形考貝到視頻顯示設(shè)備上。

      另外一個(gè)定義DirectDraw的方式是把它作為一個(gè)視頻存儲(chǔ)器管理器,同常規(guī)的存儲(chǔ)器管理器一樣,DirectDraw發(fā)放存儲(chǔ)器信息包,跟蹤每一個(gè)信息包的狀態(tài)。信息包可以隨意地創(chuàng)建、復(fù)制、修改或破壞,同時(shí)這些操作的細(xì)節(jié)被程序員隱含起來(lái),這樣講是過(guò)于簡(jiǎn)單了。此外,DirectDraw是能夠使用系統(tǒng)RAM和視頻RAM的。存儲(chǔ)器管理器也經(jīng)常被設(shè)計(jì)成和主要目標(biāo)一樣強(qiáng)健,而不只是追求性能。對(duì)于DirectDraw,性能只是設(shè)計(jì)目標(biāo)之一。

      從技術(shù)角度講,DirectDraw是隨同設(shè)備驅(qū)動(dòng)器集合的便攜式API。DirectDraw設(shè)計(jì)成完全避開(kāi)傳統(tǒng)意義上的Windows圖形機(jī)構(gòu)(GDI,或稱(chēng)圖形設(shè)備接口)。GDI由于性能低而名聲不好,所以DirectDraw的設(shè)備獨(dú)立性在提供最佳性能方面是至關(guān)重要的。

      第二節(jié) DirectDraw基本概念

      1. 顯示模式

      顯示模式是由允許將要顯示的圖形輸出的顯示硬件支持的可視配置。最常用的顯示模式屬性是分辨率。Windows使用的顯示模式的默認(rèn)值是640×480的分辨率。這意味著,水平方向有640個(gè)像素,垂直方向有480個(gè)像素。其他一些常見(jiàn)的顯示模式分辨率有800×600,1024×768。一些顯示卡支持Mode X顯示模式。一個(gè)典型的Mode X顯示模式的分辨率為320×200。

      顯示模式也隨像素深度的變化而變化。像素深度決定著每一個(gè)像素所容納的多少不同的值,因而也就可以顯示多少種顏色。例如對(duì)于8位像素深度的顯示模式,每個(gè)像素能夠再現(xiàn)256種顏色的一種。像素深度為16位的顯示模式支持65536種顏色(即2的n次方),典型的像素深度為8、16、24和32位。

      顯示模式由安裝在機(jī)器中的顯示設(shè)備或視頻卡支持。顯示設(shè)備有自己的RAM,從計(jì)算機(jī)的RAM中分離出來(lái)。我們把位于顯示設(shè)備中的存儲(chǔ)器稱(chēng)為顯示RAM,而把常規(guī)存儲(chǔ)器稱(chēng)為系統(tǒng)RAM。

      支持一個(gè)給定的顯示模式的RAM的容量取決于顯示模式的分辨率和像素深度。例如,640×480×8(640×480像素,深度為8位)的顯示模式需要307200字節(jié)。1024×768×16的顯示模式需要1572864字節(jié)。支持顯示模式的存儲(chǔ)器必須是顯示RAM。一個(gè)給定顯示設(shè)備所支持的顯示模式因此也被可以利用的顯示RAM的容量所限制。例如,1024×768×16的顯示模式因?yàn)樾枰徽鬃止?jié)以上的內(nèi)存,所以就不能被只有一兆字節(jié)RAM的顯示設(shè)備所支持。

      DirectDraw的一個(gè)主要特征是顯示模式切換。這允許一個(gè)DirectDraw應(yīng)用程序檢測(cè)和激活所安裝的顯示設(shè)備所支持的任何顯示模式。我們將在第4章中討論顯示模式切換的細(xì)節(jié)。

      2. 硬件加速

      DirectDraw具有最優(yōu)性能的最重要的原因是,它盡可能地使用硬件加速來(lái)進(jìn)行設(shè)計(jì)。硬件加速發(fā)生在當(dāng)顯示設(shè)備能夠用建立在顯示設(shè)備之中的處理功能執(zhí)行操作時(shí)。硬件加速具有兩個(gè)優(yōu)點(diǎn),首先,當(dāng)硬件加速出現(xiàn)的時(shí)候,硬件按指定要求設(shè)計(jì)成支持圖形操作,這提供了執(zhí)行給定任務(wù)的最快的方法:其次,硬件加速使得計(jì)算主處理器從執(zhí)行操作中解放出來(lái),這使得主處理器可以執(zhí)行其他任務(wù)。

      3. 表面

      表面是存儲(chǔ)器的一個(gè)矩形部分的DirectDraw術(shù)語(yǔ),通常包括圖像數(shù)據(jù)。該存儲(chǔ)器通常用來(lái)表示一個(gè)存在于顯示RAM或系統(tǒng)RAM中的表面。駐留在顯示RAM中的表面享有超高性能,因?yàn)榻^大多數(shù)顯示硬件不能對(duì)系統(tǒng)RAM直接存取。

      表面分為向大類(lèi),最簡(jiǎn)單的類(lèi)型是脫離屏幕表面。脫離屏幕表面可以駐留在顯示RAM中或系統(tǒng)RAM中,但卻不能被顯示。這類(lèi)表面一般用于存儲(chǔ)子畫(huà)面和背景。

      另一方面,一個(gè)主表面是可在屏幕上看到的視頻RAM的一部分部分。所有的DirectDraw程序(可以提供視頻輸出)都擁有主表面。主表面必須駐留在顯示RAM中。

      主表面通常很復(fù)雜,或是可翻轉(zhuǎn)的。可翻轉(zhuǎn)表面允許頁(yè)面翻轉(zhuǎn),這是一項(xiàng)整個(gè)表面的內(nèi)容可以通過(guò)一個(gè)硬件操作而瞬時(shí)可見(jiàn)的技術(shù)。頁(yè)面翻轉(zhuǎn)用于許多基于DirectDraw或其他的圖形應(yīng)用程序中,因?yàn)樗梢援a(chǎn)生相當(dāng)平滑、不閃爍的動(dòng)畫(huà)。一個(gè)可翻轉(zhuǎn)的主表面實(shí)際上是兩個(gè)表面,一個(gè)可見(jiàn),另一個(gè)不可見(jiàn)。不可見(jiàn)的表面稱(chēng)為后備緩沖區(qū)。當(dāng)發(fā)生頁(yè)面翻轉(zhuǎn)時(shí),以前是后備緩沖區(qū)的表面就成為可見(jiàn)的,而以前可見(jiàn)的表面則成為后備緩沖區(qū)。

      離屏表面和主表面都有兩類(lèi):調(diào)色板的和無(wú)調(diào)色板的。在DirectDraw中,只有8位表面是調(diào)色板表面。調(diào)色板表面并不包含色彩數(shù)據(jù),但是卻引入一個(gè)色彩表。該表稱(chēng)為調(diào)色板。像素深度為16、24或32位的表面是無(wú)調(diào)色板表面。無(wú)調(diào)色板表面存儲(chǔ)實(shí)際色彩值,而不引入調(diào)色板。

      因?yàn)樵跓o(wú)調(diào)色板表面中的每一個(gè)像素都存儲(chǔ)色彩數(shù)據(jù),所以知道表面的像素格式是很重要的。像素格式描述了存儲(chǔ)于像素中的紅色、綠色和藍(lán)色(RGB)元件的方式。像素格式隨像素深度、顯示模式和硬件設(shè)計(jì)的不同而不同,在第5章中可以了解所有的像素格式。

      4. Bltting

      Bltting是用于復(fù)制的圖形語(yǔ)言。典型的blt操作是將離屏表面的內(nèi)容拷貝到一個(gè)后備緩沖區(qū)中。當(dāng)Bltting通過(guò)硬件完成的時(shí)候,執(zhí)行速度相當(dāng)快。如果無(wú)法得到硬件加速,DirectDraw將使用一個(gè)軟件操作來(lái)仿真blt。這種仿真操作雖然也能夠完成任務(wù),但卻比硬件慢得多.一般只有駐留在顯示RAM中的表面能夠通過(guò)使用顯示硬件來(lái)完成blt。

      blt操作調(diào)用一個(gè)源表面和一個(gè)目標(biāo)表面,源表面的內(nèi)容被拷貝到目標(biāo)表面中。源表面中的內(nèi)容在操作中不會(huì)改變,只有目標(biāo)表面受blt的影響。blt操作也并不需要使用全部的源表面或目標(biāo)表面。源表面中的任何矩形區(qū)域可以被放置于目標(biāo)表面中的任何位置。

      不規(guī)則形狀表面的bltting(例如典型的子畫(huà)面)是以透明方式完成的。透明性是通過(guò)指定表面中某個(gè)不被blt操作拷貝的像素而獲得的。像素值通過(guò)使用色彩鍵碼給以標(biāo)志。

      色彩鍵碼可以附加到源表面或目標(biāo)表面上。源色彩鍵碼是很普遍的。源色彩鍵碼允許透明性,因?yàn)樵幢砻嬷械南袼刂挡⑽幢豢钾悺V劣谀繕?biāo)色彩,只有目標(biāo)表面中通過(guò)色彩所指定的像素值能夠被源表面的內(nèi)容所覆蓋。

      DirectDraw也支持一些特定的操作,包括拉伸、壓縮、鏡像映射,以及混合等。這些功能的實(shí)現(xiàn)往往取決于顯示硬件。DirectDraw能夠仿真其中的某些操作,但是跟性能相比,價(jià)格往往是昂貴的。

      DirectDraw也有不能仿真的功能(例如目標(biāo)色彩鍵碼)。使用這些功能是冒險(xiǎn)的,除非該功能為所安裝的顯示硬件支持,否則使用該功能的操作將失敗。這給DirectDraw的開(kāi)發(fā)者帶來(lái)兩種基本選擇:要么放棄使用這些功能:要么往應(yīng)用程序中增加定制軟件。

      5. 調(diào)色板

      使用8位顯示模式的應(yīng)用程序需要提供調(diào)色板。調(diào)色板就是任何時(shí)候都可以使用的色彩表。如果8位顯示模式不需要調(diào)色板,應(yīng)用程序?qū)⒈黄仁褂?56種顏色的固定設(shè)置。調(diào)色板允許用戶(hù)定義將要使用的256種顏色之一。

      當(dāng)你使用調(diào)色板顯示模式時(shí),必須保證在應(yīng)用程序中的圖像也使用同一調(diào)色板。如果沒(méi)有做到這一點(diǎn),所顯示的一些或全部圖像中將出現(xiàn)錯(cuò)誤的顏色。調(diào)色板也會(huì)帶來(lái)麻煩,尤其是用一個(gè)調(diào)色板來(lái)顯示大量圖像的時(shí)候。調(diào)色板也有一些優(yōu)勢(shì)。正如前面提到的,調(diào)色板允許在一個(gè)有限色彩的場(chǎng)合使用最多的色彩。調(diào)色板也允許調(diào)色板動(dòng)畫(huà)。

      調(diào)色板動(dòng)畫(huà)是動(dòng)畫(huà)通過(guò)改變調(diào)色板項(xiàng)目,而不是改變像素值來(lái)執(zhí)行的技術(shù),這就使得一個(gè)屏幕上的很多像素可以瞬時(shí)改變顏色。對(duì)于一些有限的應(yīng)用程序,諸如分配的、重復(fù)的動(dòng)畫(huà),調(diào)色板動(dòng)畫(huà)很有用處。

      6. 剪裁

      理想狀態(tài)下,一個(gè)blt操作就是整個(gè)表面被blt成為另一個(gè)表面。通常源表面被blt成為目標(biāo)表面的邊,或者目標(biāo)表面被另一個(gè)表面或窗口遮蔽。像這樣的情況就需要進(jìn)行剪裁。剪裁只允許一部分或一個(gè)表面的一部分被blt。

      在編寫(xiě)窗口DirectDraw應(yīng)用程序時(shí)經(jīng)常用到剪裁,因?yàn)檫@些應(yīng)用程序必須遵守Windows桌面的規(guī)則。我們將在本章后面討論窗口應(yīng)用程序。

      DirectDraw提供全矩形剪裁支持。也有這種情況,就是付費(fèi)提供定制剪裁例程,我們將在第3章中研究定制剪裁解決方案。

      7. 其他表面

      離屏表面和主表面(具有任選的后備緩沖區(qū))是絕大多數(shù)DirectDraw應(yīng)用程序的主干。然而一些其他的表面就有不同,包括重疊表面、alpha通道表面、Z-緩沖區(qū)以及3D設(shè)備表面等。

      重疊表面是硬件單色畫(huà)面,因而也就在僅在支持重疊的顯示硬件上獲得。和軟件單色畫(huà)面不同,它可以被移動(dòng)而不需要背景圖像被恢復(fù)。

      alpha通道表面用來(lái)執(zhí)行alpha調(diào)配。Alpha調(diào)配是透明的高級(jí)形式。允許表面以透明度或半透明方式來(lái)拷貝。alpha通道表面可用來(lái)控制每一像素的透明度設(shè)置。alpha通道表面的深度有1、2、4、8位。1位深度alpha通道表面僅支持兩種透明設(shè)置,不透明(非透明)或不可見(jiàn)(全透明)。另一方面,8位alpha通道表面允許256種不同的透明度設(shè)置。Alpha調(diào)配是不被DirectDraw仿真的功能的一個(gè)例子。為了使用alpha調(diào)配,因而就需要有支持它的顯示硬件或建立在應(yīng)用程序之中的定制調(diào)配方案。

      Z-緩沖區(qū)和3D設(shè)備表面用于3D應(yīng)用程序中。這些類(lèi)型的表面已被特別地加入到DirectDraw之中,以支持Direct3D。Z-緩沖區(qū)用于景象繪制時(shí)期,以跟蹤景象中離瀏覽者最近的對(duì)象,從而該對(duì)象可以在其他對(duì)象的前面出現(xiàn)。3D設(shè)備表面可以用來(lái)作為Direct3D繪制目標(biāo)的表面。本書(shū)并不包括Z-緩沖區(qū)或3D設(shè)備。

      第三節(jié) 元件對(duì)象模型(COM)

      1.Microsoft的COM規(guī)格

      DirectDraw根據(jù)Microsoft的COM(Component Object Model)規(guī)格得以實(shí)現(xiàn)。COM設(shè)計(jì)成用來(lái)提供完全便攜的、安全的、可升級(jí)的軟件結(jié)構(gòu),COM是一個(gè)大的項(xiàng)目,但是它并不是本軟件討論的對(duì)象。我們討論COM只是為了方便使用DirectDraw進(jìn)行編程。

      COM使用一個(gè)面向?qū)ο蟮哪P停@要比像C++等語(yǔ)言所用的模型更嚴(yán)格。例如,COM對(duì)象經(jīng)常通過(guò)成員函數(shù)進(jìn)行存取,而且并不具備公共數(shù)據(jù)成員。COM對(duì)繼承性的支持與C++相比也是有限的。

      2. 對(duì)象和接口的比較

      COM在對(duì)象和接口之間具有很大的區(qū)別。COM對(duì)象提供實(shí)際函數(shù)性,而COM接口則提供存取函數(shù)性的方法。COM對(duì)象不能被直接存取,相反,所有的存取者通過(guò)接口來(lái)完成。這條規(guī)則是如此強(qiáng)有力的得到遵守,以致于我們不能給任何COM對(duì)象以名稱(chēng)。我們只能給用來(lái)存取對(duì)象的接口名稱(chēng)。因?yàn)槲覀儫o(wú)法存取COM對(duì)象,所以這里絕大多數(shù)時(shí)候是根據(jù)接口來(lái)講的。

      一個(gè)COM對(duì)象能夠支持多個(gè)接口。這聽(tīng)起來(lái)像個(gè)特例,但是它經(jīng)常出現(xiàn),因?yàn)楦鶕?jù)COM規(guī)格,一個(gè)COM接口一旦定義之后,就不能再被改變或增加。這樣做是為保證舊程序在一個(gè)COM對(duì)象升級(jí)的時(shí)候不會(huì)被停止使用。這個(gè)初始接口始終存在,一個(gè)新的、替換的接口在提供存取對(duì)象的新的函數(shù)性的時(shí)候才被提供。

      3. IUnknown接口

      所有的COM接口都是從IUnknown接口中衍生出來(lái)的。“I”標(biāo)志經(jīng)常用于命名COM接口(它代表Interface即界面)。DirectDraw接口總以“I”開(kāi)頭。但是在文獻(xiàn)中經(jīng)常看不到這個(gè)標(biāo)志。以后提到接口時(shí)也將省略“I”標(biāo)志。

      IUnknown接口將提供3個(gè)成員函數(shù),所有COM接口因而繼承這些函數(shù):

      ●AddRef()

      ●Release()

      ●QueryInterface()

      AddRef()和Release()成員函數(shù)為稱(chēng)為生命期封裝(lifetime encapsulation)的COM功能提供支持。生命期封裝是一個(gè)將每一個(gè)對(duì)象根據(jù)它自己的結(jié)構(gòu)放置的協(xié)議。

      生命期封裝通過(guò)引用值來(lái)實(shí)現(xiàn)。每一個(gè)對(duì)象擁有一個(gè)可以跟蹤對(duì)象的指針數(shù),或者引用的內(nèi)部值。當(dāng)對(duì)象創(chuàng)建之后,該值為1。如果附加的接口或接口的指針被創(chuàng)建,則該值遞增。與此類(lèi)似,如果接口的指針被破壞,則該值遞減。當(dāng)它的引用數(shù)到0的時(shí)候,該對(duì)象自行破壞。

      AddRef()函數(shù)用來(lái)使對(duì)象的內(nèi)部引用值遞增。絕大部分時(shí)間里,該函數(shù)通過(guò)DirectDraw API被用戶(hù)調(diào)用。例如,當(dāng)你使用DirectDrawaw API創(chuàng)建一個(gè)新的接口時(shí),創(chuàng)建函數(shù)就自動(dòng)調(diào)用AddRef()。

      Release()函數(shù)用來(lái)給對(duì)象的內(nèi)部引用值遞減。用戶(hù)應(yīng)該在接口的指針將要超出范圍時(shí)或者要通過(guò)使用接口指針來(lái)結(jié)束時(shí)使用這個(gè)函數(shù)。AddRef()和Release()函數(shù)都返回一個(gè)值,表示對(duì)象新的引用值。

      QueryInterface()函數(shù)允許COM對(duì)象就它們是否支持特定接口進(jìn)行查詢(xún)。例如,升級(jí)的COM對(duì)象提供附加的接口,而非現(xiàn)有接口的修改版。QueryInterface()函數(shù)可以用來(lái)確定舊的接口,以決定新的接口是否被支持。如果被查詢(xún)的對(duì)象不支持有問(wèn)題的接口,則更替接口的指針就返回。

      4. GUID

      為了查詢(xún)一個(gè)對(duì)象是否支持使用QueryInterface()函數(shù)的指定接口,就有秘要識(shí)別有問(wèn)題的接口。這通過(guò)接口的GUID(Globally Unique IDentifier)來(lái)實(shí)現(xiàn)。一個(gè)GUID是一個(gè)128位的值,也就是說(shuō),對(duì)于所有意圖和目的是唯一的。所有DirectDraw接口的GUIDs都包含在DirectX頭文件中。

      上述對(duì)于COM的簡(jiǎn)單介紹,就是為有效使用DirectDraw API所需要的全部?jī)?nèi)容。以后當(dāng)我們?cè)儆懻揇irectDraw API時(shí),你會(huì)發(fā)現(xiàn)這些內(nèi)容是有聯(lián)系的。

      第四節(jié) DirectDraw接口函數(shù)

      1.關(guān)于 DirectDraw API

      衡量API的一個(gè)方法就是看它的大小。一個(gè)龐大復(fù)雜的API可能就是計(jì)劃不周的結(jié)果。另一方面,一個(gè)龐大的API有時(shí)就意味著每一種情況都有可能出現(xiàn)。一個(gè)小的API就是一個(gè)新的、缺乏功能的軟件包的證據(jù)。它也意味著,一個(gè)API只能做它所需要做的,而不能多做一點(diǎn)。

      DirectDraw API是比較小的,因此本章中所討論的每一個(gè)函數(shù)不致于使本章看起來(lái)像一本參考手冊(cè)。DirectDraw提供很少的方便,也很少有限制。

      DirectDraw由個(gè)COM對(duì)象構(gòu)成,每個(gè)對(duì)象可以通過(guò)一個(gè)或多個(gè)接口存取。這些接口包括:

      ●DirectDraw

      ●DirectDraw2

      ●DirectDrawSurface

      ●DirectDrawSurface2

      ●DirectDrawSurface3

      ●DirectDrawPalette

      ●DirectDrawClipper

      我們將討論每一個(gè)接口,并隨后討論它們的成員函數(shù)。但我們并不討論每個(gè)函數(shù)的細(xì)節(jié),因?yàn)槲覀儾⒉皇窍蚰峁┮环輩⒖际謨?cè)。相反,我們將討論每個(gè)函數(shù)是干什么的,為什么這樣使用,以及你有可能如何去使用它。

      當(dāng)DirectX首次推出的時(shí)候(早先它被稱(chēng)作Games SDK),DirectDraw核心函數(shù)性以DirectDraw接口表示。當(dāng)DirectX2推出的時(shí)候,DirectDraw也已經(jīng)被升級(jí)了。DirectDraw遵守COM規(guī)格而未被改變。新的函數(shù)性可能通過(guò)DirectDraw2接口存取。

      特別要注意的是,DirectDraw2接口是DirectDraw接口的超級(jí)設(shè)置。DirectDraw2接口可提供DirectDraw接口的所有函數(shù),另外還增加了一些新的函數(shù)。如果你正在使用DirectX或更高版高,那么你可以隨意選用DirectDraw接口或DirectDraw2接口。但是,由于DirectDraw2接口較DirectDraw接口的功能更強(qiáng),所以沒(méi)有必要使用DirectDraw接口。同樣,Microsoft并不主張使用這些無(wú)組織的、網(wǎng)絡(luò)可變的接口。因此,在本書(shū)以后的程序中我們只使用DirectDraw2接口。

      DirectDraw和DirectDraw2接口提供的成員函數(shù)如下(按字母順序排列):

      ●Compact()

      ●CreateClipper()

      ●CreatePalette()

      ●CreateSurface()

      ●DuplicateSurface()

      ●EnumDisplayModes()

      ●EnumSurfaces()

      ●FlipToGDISurface()

      ●GetAvailableVidMem()

      ●GetCaps()

      ●GetDisplayMode()

      ●GetFourCCCodes()

      ●GetGDISurface()

      ●GetMonitorFrequency()

      ●GetScanline()

      ●GetVerticalBlankStatus()

      ●RestoreDisplayMode()

      ●SetCooperativeLevel()

      ●SetDisplayMode()

      ●WaitForVerticalBlank()

      接下來(lái)我們討論DirectDraw接口函數(shù)。注意,在本章以后的內(nèi)容中,DirectDraw接口既表示DirectDraw接口,也表示DirectDraw2接口。只有在區(qū)分DirectDraw接口和DirectDraw2接口的函數(shù)時(shí),才加以區(qū)別。

      1. 接口創(chuàng)建函數(shù)

      DirectDraw接口表示DirectDraw本身。該接口在被用于創(chuàng)建其他DirectDraw接口實(shí)例時(shí),是一個(gè)主接口。DirectDraw接口提供三個(gè)這樣的接口實(shí)例創(chuàng)建函數(shù):

      ●CreateClipper()

      ●CreatePalette()

      ●CreateSurface()

      CreateClipper()函數(shù)用于創(chuàng)建DirectDrawClipper接口實(shí)例。并非所有的DirectDraw應(yīng)用程序都用到剪裁器,所以該函數(shù)并不是在所有的程序中都出現(xiàn)。我們將很快討論DirectDrawClipper的細(xì)節(jié)。

      CreatePalette()函數(shù)用于創(chuàng)建DirectDrawPalette接口實(shí)例。同DirectDrawClipper一樣,并非所有的DirectDraw應(yīng)用程序都用到調(diào)色板。比如,應(yīng)用程序使用16位顯示模式時(shí),就不用調(diào)色板。但是,當(dāng)應(yīng)用程序使用8位顯示模式時(shí),就必須創(chuàng)建至少一個(gè)DirectDrawPalette實(shí)例。

      CreateSurface()函數(shù)用于創(chuàng)建DirectDrawSurface接口實(shí)例。任何一個(gè)DirectDraw應(yīng)用程序都要用表面來(lái)生成圖像數(shù)據(jù),因此經(jīng)常要用到這一函數(shù)。

      DirectDraw接口自己的實(shí)例是由DirectDrawCreate()函數(shù)創(chuàng)建的。DirectDrawCreate()是DirectDraw函數(shù)中少有的幾個(gè)常規(guī)函數(shù)之一,但并不是COM接口成員函數(shù)。

      2. GetCaps()函數(shù)

      DirectDraw接口允許準(zhǔn)確確定軟硬件都支持的特征。GetCaps()函數(shù)可以對(duì)兩個(gè)DDCAP結(jié)構(gòu)實(shí)例進(jìn)行初始化。一個(gè)結(jié)構(gòu)表明哪些特征由顯示硬件直接支持,另一個(gè)結(jié)構(gòu)表明哪些特征由軟件仿真支持。最好是用GetCaps()函數(shù)來(lái)決定你將用到的特征是否被支持。

      提示:DirectX瀏覽器

      DirectX SKD是與DXVIEW程序同時(shí)推出的。DXVIEW說(shuō)明了DirectX組件的功能,包括DirectDraw。大多數(shù)系統(tǒng)中,有兩個(gè)DirectDraw項(xiàng)目:主顯示驅(qū)動(dòng)器和硬件仿真層。第一項(xiàng)說(shuō)明了顯示硬件的功能。第二項(xiàng)說(shuō)明了在缺乏硬件支持的情況下,DirectDraw將要仿真的一些特征。在具有兩個(gè)以上的DirectDraw支持的顯示卡的計(jì)算機(jī)中,DXVIEW會(huì)顯示卡的功能。

      3. SetCooperativeLevel()函數(shù)

      SetCooperativeLevel()函數(shù)用于指定應(yīng)用程序所要求的對(duì)顯示硬件的控制程度。比如,一個(gè)正常合作度意味著應(yīng)用程序既改變不了當(dāng)前顯示模式,也不能指定整個(gè)系統(tǒng)調(diào)色板的內(nèi)容。而一個(gè)專(zhuān)有的合作度允許顯示模式切換,并能完全控制調(diào)色板。不管你決定使用哪種合作度,都必須調(diào)用SetCooperativeLevel()函數(shù)。

      4. 顯示模式函數(shù)

      DirectDraw接口提供4種顯示模式操作函數(shù)。它們是:

      ●EnumDisplayModes()

      ●GetDisplayMode()

      ●RestoreDisplayMode()

      ●SetDisplayMode()

      EnumDisplayModes()函數(shù)可用于查詢(xún)DirectDraw使用何種顯示模式。通過(guò)設(shè)置EnumDisplayModes()函數(shù)默認(rèn)值可以得到所有的顯示模式,而且可以通過(guò)顯示模式描述消除那些不感興趣的模式。進(jìn)行顯示模式切換的過(guò)程中最好使用EnumDisplayModes()函數(shù)。現(xiàn)在市場(chǎng)上有各種各樣的顯示設(shè)備,每種顯示設(shè)備都有自己的特征和局限。除了默認(rèn)的640×480×8窗口顯示模式,最好不要依靠任何給定的顯示模式的支持。

      GetDisplayMode()函數(shù)可以檢索到有關(guān)當(dāng)前顯示模式的信息,并在DDSURFACEDESC結(jié)構(gòu)實(shí)例中顯示當(dāng)前顯示模式的寬度、高度、像素深度以及像素格式等信息。還有別的途徑可以檢索到同樣的信息(比如檢索主表面描述),因此該函數(shù)并不出現(xiàn)在所有的程序中。

      SetDisplayMode()函數(shù)用于激活所支持的顯示模式。SetDisplayMode()函數(shù)的DirectDraw2版本還允許設(shè)定顯示模式的刷新率。而DirectDraw接口版本的SetDisplayMode()函數(shù)只能進(jìn)行顯示模式寬度、高度和像素深度的設(shè)置。任何一個(gè)要進(jìn)行顯示模式切換的程序都要用到SetDisplayMode()函數(shù)。

      RestoreDisplayMode()函數(shù)用于存儲(chǔ)調(diào)用SetDisplayMode()函數(shù)之前的顯示模式。SetDisplayMode()和RestoreDisplayMode()函數(shù)都要求優(yōu)先使用SetCooperativeLevel()函數(shù)得到的專(zhuān)有合作存取。

      5. 表面支持函數(shù)

      除了CreateSurface()函數(shù)之外,DirectDraw接口還提供了以下向個(gè)表面相關(guān)函數(shù):

      ●DuplicateSurface()

      ●EnumSurfaces()

      ●FlipToGDISurface()

      ●GetGDISurface()

      ●GetAvailableVidMem()

      ●Compact()

      DuplicateSurface()函數(shù)用于考貝當(dāng)前表面。該函數(shù)只復(fù)制表面接口,不復(fù)制內(nèi)存。被復(fù)制的表面與源表面共享內(nèi)存,因此改變內(nèi)存的內(nèi)容就同時(shí)改變了兩個(gè)表面的圖像。

      EnumSurfaces()函數(shù)可用于迭代所有滿足指定標(biāo)準(zhǔn)的表面。如果沒(méi)有指定標(biāo)準(zhǔn),那么所有當(dāng)前表面都被枚舉。

      FlipToGDISurface()函數(shù)的作用是在終止頁(yè)面翻轉(zhuǎn)應(yīng)用程序前確保主表面得以正確存儲(chǔ)。取消頁(yè)面翻轉(zhuǎn)時(shí),有兩個(gè)表面交替顯示。這就是說(shuō),在終止應(yīng)用程序之前有可能沒(méi)有保存最初的可見(jiàn)表面。這種情況下,Windows通過(guò)繪制一個(gè)不可見(jiàn)表面來(lái)恢復(fù)。利用FlipToGDISurface()函數(shù)就可以輕而易舉地避免發(fā)生這種情況。

      GetGDISurface()函數(shù)可以向只被GDI認(rèn)可的表面返回一個(gè)提針。GDI表面是Windows用于輸出的表面。在進(jìn)行屏幕捕捉時(shí),這個(gè)函數(shù)非常有用,DirectDraw可以捕捉到Windows桌面的任一部分。

      GetAvailableVidMem()函數(shù)用于檢索正在使用中的視頻存儲(chǔ)器(顯示RAM)的數(shù)量。這一函數(shù)由DirectDraw2接口提供,而不是由DirectDraw接口提供。該函數(shù)用于確定應(yīng)用程序利用顯示RAM可創(chuàng)建表面的數(shù)量。

      Compact()函數(shù)不是通過(guò)DirectX5實(shí)現(xiàn)的,但它可以為視頻存儲(chǔ)器提供碎片整理技巧。在基于顯示RAM的表面被不斷創(chuàng)建或受到破壞的時(shí)候,可以釋放大量?jī)?nèi)存。

      6. 監(jiān)視器刷新函數(shù)

      DirectDraw接口提供了4種適于計(jì)算機(jī)顯示設(shè)備或監(jiān)視器的函數(shù),但這些函數(shù)不適于顯示卡,它們是:

      ●GetMonitorFrequency()

      ●GetScanLine()

      ●GetVerticalBlankStatus()

      ●WaitForVerticalBlank()

      這些函數(shù)尤其與監(jiān)視器的刷新機(jī)制緊密機(jī)連。這在確保生成動(dòng)畫(huà)時(shí)盡可能不產(chǎn)生閃爍和圖像撕裂現(xiàn)象時(shí)是至關(guān)重要的。但必須注意,并非所有的顯示卡/監(jiān)視器組合都支持這些函數(shù)。

      GetMonitorFrequency()函數(shù)用于檢索監(jiān)視器當(dāng)前的刷新率。刷新率通常用赫茲表示,縮寫(xiě)為Hz。例如,60Hz的刷新率表示屏幕每秒更新60次。

      GetScanLine()函數(shù)用于向監(jiān)視器返回當(dāng)前正在被刷新的掃描行(水平像素行)。不是所有的顯示設(shè)備/監(jiān)視器組合都支持該函數(shù)。如果這一功能得不到支持,該函數(shù)將返回DDERR-UNSUPPORTED。

      對(duì)于高性能圖形應(yīng)用程序來(lái)說(shuō),通常要求利用垂直刷新同步地更新屏幕。尤其是,當(dāng)顯示器剛完成屏幕刷新時(shí),最好能夠更新主表面。否則,屏幕的一部分顯示新的圖像數(shù)據(jù),而另一部分仍顯示舊的圖像數(shù)據(jù),這種現(xiàn)象就是所謂的圖像撕裂。DirectDraw默認(rèn)利用垂直刷新同步更新屏幕。如果不是這樣還可以利用GetVerticalBlankStatus()和WaitForVerticalBlank()函數(shù)實(shí)現(xiàn)同步刷新。

      7. GetFourCCCodes()函數(shù)

      DirectDraw接口提供的最后一個(gè)函數(shù)是GetFourCCCodes()函數(shù)。該函數(shù)用于返回顯示卡所支持的FourCC代碼。FourCC代碼用于描述非RGB或YUV表面。我們不在此討論YOV表面,它們已超出本書(shū)的范圍。

      第五節(jié) DirectDrawSurface接口函數(shù)

      同DirectDraw接口一樣,DirectDrawSurface接口也遵守COM規(guī)格.最初,表面支持是由DirectDrawSurface接口提供的。DirectX2介紹了DirectDrawSurface2接口的新的函數(shù)性,DirectX5介紹了DirectDrawSurface3接口。

      盡管本軟件中討論的是DirectDraw2接口,而不是DirectDraw接口,但我們?nèi)灾矣谧畛醯腄irectDrawSurface接口,因?yàn)镈irectDrawSurface2和DirectDrawSurface3接口新增的函數(shù)并不十分重要。在以后的內(nèi)容里,我們將用DirectDrawSurface接口表示這3種接口,除非特別注明。

      DirectDrawSurface是最大的DirectDraw接口,它允許表面內(nèi)容的拷貝、清除以及被調(diào)用程序直接存取。DirectDrawSurawSurface接口總共提供36個(gè)成員函數(shù),按字母順序排列如下:

      ●AddAttachedSurface()

      ●AddOverlayDirtyRect()

      ●Blt()

      ●BltBatch()

      ●BltFast()

      ●DeleteAttachedSurface()

      ●EnumAttachedSurfaces()

      ●EnumOverlayZOrders()

      ●Flip()

      ●GetAttachedSurface()

      ●GetBltstatus()

      ●GetCaps()

      ●GetClipper()

      ●GetColorKey()

      ●GetDC()

      ●GetDDInterface()

      ●GetFlipStatus()

      ●GetOverlayPosition()

      ●GetPalette()

      ●GetPixelFormat()

      ●GetSurfaceDesc()

      ●IsLost()

      ●Lock()

      ●PageLock()

      ●PageUnlock()

      ●ReleaseDC()

      ●Restore()

      ●SetClipper()

      ●SetColorKey()

      ●SetOverlayPosition()

      ●SetPalette()

      ●SetSurfaceDesc()

      ●Unlock()

      ●UpdateOverlay()

      ●UpdateOverlayDisplay()

      ●UpdateOverlayZOrder()

      1. 表面描述函數(shù)

      我們首先討論的個(gè)可用于檢索表面自身信息的函數(shù),它們是:

      ●GetCaps()

      ●GetPixelFormat()

      ●GetSurfaceDesc()

      ●SetSurfaceDesc()

      同DirectDraw接口提供的GetCaps()函數(shù)一樣,DirectDrawSurface接口提供的GetCaps()函數(shù)用于輸出表征哪些特征可被表面支持的數(shù)據(jù)。該信息包括:表面是主表面還是離屏表面;表面使用的存儲(chǔ)器定位于顯示RAM還是系統(tǒng)RAM。

      GetPixelFormat()函數(shù)在用于高彩和真彩表面時(shí)是非常重要的,這是由于像素格式因顯示卡的不同而不同。該函數(shù)返回表征碼,這些表征碼表明每一種顏色部件是如何存儲(chǔ)的。

      GetSurfaceDesc()函數(shù)返回一個(gè)表面描述。該信息包括表面的寬度、高度和深度。表面像素格式(同樣被GetPixelFormat()函數(shù)檢索)也包含在其中。

      SetSurfaceDesc()函數(shù)(對(duì)于DirectX5)來(lái)講是新增的,只由DirectDrawSurface3接口提供)允許設(shè)定某些表面屬性。該函數(shù)可用于指定表面使用的內(nèi)存。這一點(diǎn)在設(shè)計(jì)定制表面存儲(chǔ)器管理器策略時(shí)非常有用。

      2。 表面Blt函數(shù)

      DirectDrawSurface接口提供3個(gè)支持blt操作的函數(shù):

      ●Blt()

      ●BltBatch()

      ●BltFast()

      Blt()函數(shù)是一個(gè)主要函數(shù)。Blt()函數(shù)能夠進(jìn)行常規(guī)的blting(無(wú)特殊影響的簡(jiǎn)單的表面到表面的blt),同時(shí)支持延伸、旋轉(zhuǎn)、鏡像和顏色填充的操作。當(dāng)用于同剪裁器關(guān)聯(lián)的表面時(shí),Blt()可進(jìn)行剪裁blt操作。

      BltBatch()函數(shù)不是在DirectX3下實(shí)現(xiàn)的(你可以調(diào)用該函數(shù),但什么也不會(huì)發(fā)生)。執(zhí)行BltBatch()函數(shù)時(shí),如果可能,它可同時(shí)進(jìn)行多blt操作。

      BltFast()函數(shù)是Blt()函數(shù)的優(yōu)化版本。BltFast()函數(shù)的效率提高了,但性能卻下降了。BltFast()函數(shù)不能進(jìn)行一些特殊的blt操作,而B(niǎo)lt()函數(shù)可以。而且,BltFast()函數(shù)不能用于剪裁。但是BltFast()函數(shù)支持源和目標(biāo)色彩鍵碼blt的操作。在遵循定制剪裁例程的情況下,BltFast()函數(shù)可進(jìn)行DirectDraw能夠提供的最快捷、靈活的blt操作。在下章中我們將執(zhí)行一個(gè)定制剪裁例程。

      以上3個(gè)blt函數(shù)均將源表面和目標(biāo)表面作為變量。其他的數(shù)據(jù),例如blt在目標(biāo)表面上的理想定位,是通過(guò)指定理想blt操作的確切屬性來(lái)提供的。一旦可能,這3個(gè)函數(shù)將進(jìn)行硬件加速blt。

      3. Flip()函數(shù)

      Flip()函數(shù)用于頁(yè)面翻轉(zhuǎn)操作。調(diào)用Flip()函數(shù)可隱藏屏幕上先前可見(jiàn)的表面,并使一個(gè)后備緩沖區(qū)顯現(xiàn)。只有被明確地創(chuàng)建為翻轉(zhuǎn)表面的表面,才響應(yīng)該函數(shù)的調(diào)用。

      必須牢記,真正的翻轉(zhuǎn)操作不可能總是成功。頁(yè)面翻轉(zhuǎn)要求有足夠的顯示RAM容納兩整屏有效數(shù)據(jù)。如果滿足不了這一要求,系統(tǒng)RAM中將創(chuàng)建一個(gè)后備緩沖區(qū)。這時(shí)調(diào)用Flip()函數(shù)進(jìn)行的是blt操作而不是頁(yè)面翻轉(zhuǎn)。基于系統(tǒng)RAM的后備緩沖區(qū)中的內(nèi)容被拷貝到主表面上。這樣會(huì)嚴(yán)重影響性能,但是,在真正的頁(yè)面翻轉(zhuǎn)中如果沒(méi)有足夠的顯示RAM,又不退出程序,也只能如此了。如果你的應(yīng)用程序要求最佳性能,就得設(shè)法避免激活不能進(jìn)行真正頁(yè)面翻轉(zhuǎn)的顯示模式。

      4. 表面狀態(tài)函數(shù)

      下面討論兩個(gè)能檢索有關(guān)操作和翻轉(zhuǎn)操作信息的函數(shù),它們是:

      ●GetBltStatus()

      ●GetFlipStatus()

      GetBltStatus()函數(shù)用于確定當(dāng)前是否進(jìn)行blt操作。這一點(diǎn)很重要,因?yàn)檎籦lt的表面不能進(jìn)行其他操作。該函數(shù)表明,給定的表面是否正是一個(gè)進(jìn)行blt操作的源表面或目標(biāo)表面。

      同樣地,GetBltStatus()函數(shù)表明是否正在進(jìn)行翻轉(zhuǎn)操作。即使DirectDraw通過(guò)blt操作仿真頁(yè)面翻轉(zhuǎn),該函數(shù)而不GetBltStatus()也必須用于由Flip()函數(shù)初始化的監(jiān)視器頁(yè)面翻轉(zhuǎn)。

      5. 色彩鍵碼函數(shù)

      DirectDrawSurface接口提供了以下兩個(gè)函數(shù),來(lái)設(shè)置和檢查表面色彩鍵碼或色彩鍵碼的范圍,它們是:

      ●GetColorKey()

      ●SetColoKey()

      默認(rèn)狀態(tài)下,表面沒(méi)有色彩鍵碼。一個(gè)色彩鍵碼只對(duì)應(yīng)一種顏色,但某些硬件支持色彩鍵碼范圍。色彩鍵碼和色彩鍵碼范圍是DDCOLORKEY結(jié)構(gòu)定義的。GetColorKey()和SetColoKey()函數(shù)都將該結(jié)構(gòu)的指針作為變量。在要求表面的一部分透明時(shí)或需要進(jìn)行目標(biāo)色彩鍵碼操作時(shí),可以使用這兩個(gè)函數(shù)。

      6. Lock和Unlock()函數(shù)

      DirectDraw的一個(gè)主要特點(diǎn),就是能夠提供對(duì)圖像數(shù)據(jù)的直接存取。直接存取可以提供最佳性能和更好的靈活性,因?yàn)闆](méi)有中間API影響運(yùn)行速度,并且開(kāi)發(fā)人員呆任意使用圖像數(shù)據(jù)。對(duì)表面存儲(chǔ)器的中間存取通過(guò)以下出眾個(gè)函數(shù)實(shí)現(xiàn):

      ●Unlock()

      ●Lock()

      Lock()函數(shù)向組成表面的存儲(chǔ)器返回一個(gè)指針,不管表面存儲(chǔ)器位于顯示RAM還是系統(tǒng)RAM。存儲(chǔ)器一般按線性風(fēng)格排列,以便能簡(jiǎn)單地進(jìn)行圖像 數(shù)據(jù)存取。Unolock()函數(shù)在完成表面存儲(chǔ)器的存取之后指定給DirectDraw。

      對(duì)圖像數(shù)據(jù)的直接存取必須付出代價(jià)。為了支持這種存取方式,DirectDraw在表面鎖定的時(shí)候必須關(guān)閉基本的Windows機(jī)構(gòu)。在Windows95狀態(tài)下,如果忘記解鎖表面,必定會(huì)損壞機(jī)器。

      因此,表面鎖定的時(shí)間應(yīng)盡量縮短。測(cè)試前應(yīng)仔細(xì)檢查L(zhǎng)ock()和Unlock()函數(shù)之間的程序調(diào)用。因?yàn)檫@一程序無(wú)法用傳統(tǒng)的調(diào)試程序進(jìn)行調(diào)試。

      鎖定表面不能被blt和翻轉(zhuǎn),因此試圖保持表面處于鎖定狀態(tài)沒(méi)有任何有益之處。而且,一旦表面解鎖,由Lock()函數(shù)檢索的指針就失效了。

      表面鎖定后不能再次被鎖定。在表面鎖定時(shí)也就無(wú)法調(diào)用Lock()函數(shù)。

      7. GetDC()ReleaseDC()函數(shù)

      對(duì)表面的直接存取占用很大內(nèi)存,有時(shí)候把表面作為一個(gè)常規(guī)的Windows設(shè)備會(huì)更好。在此,DirectDrawSurface接口提供以下兩個(gè)函數(shù):

      ●GetDC()

      ●ReleaseDC()

      GetDC()函數(shù)提供了一個(gè)DC(設(shè)備環(huán)境),可以用常規(guī)的Win32函數(shù)寫(xiě)到表面上。例如,DC可以用Win32的TextOut()函數(shù)在表面上繪制文本。用完DC后必須馬上調(diào)用ReleaseDC()函數(shù)。

      同Lock()和Unlock()函數(shù)使用一樣,在調(diào)用完GetDC()函數(shù)后必須馬上調(diào)用ReleaseDC()函數(shù)。這是因?yàn)镚etDC()函數(shù)內(nèi)部調(diào)用Lock函數(shù),而ReleaseDC()函數(shù)內(nèi)部調(diào)用Unlock()函數(shù)。

      8. PageLock()和PageUnlock()函數(shù)

      接下來(lái),我們討論另外兩個(gè)與Lock()函數(shù)和Unlock()函數(shù)看上去非常相像的函數(shù):

      ●PageLock()

      ●PageUnlock()

      盡管這兩個(gè)函數(shù)看上去很像Lock()和Unlock()函數(shù),但它們卻有完全不同的作用。PageLock()和PageUnlock()函數(shù)用于控制Windows對(duì)基于系統(tǒng)RAM的表面的處理方式。這兩個(gè)函數(shù)由DirectDrawSurface2接口提供,而不是由DirectDrawSurface接口提供。

      當(dāng)Windows認(rèn)為當(dāng)前正在運(yùn)行的其他應(yīng)用程序或進(jìn)程更適于使用內(nèi)存時(shí),Windows會(huì)向硬盤(pán)釋放部分內(nèi)存。這種緩沖對(duì)于整個(gè)系統(tǒng)內(nèi)存都起作用,因此駐留在系統(tǒng)內(nèi)存中的DirectDraw表面有可能被存到硬盤(pán)上。如果要用到這樣的表面,Windows需要花費(fèi)一定的時(shí)間從硬盤(pán)上讀取表面數(shù)據(jù)。

      PageLock()函數(shù)提示W(wǎng)indows哪些給定的表面不應(yīng)該釋放到硬盤(pán)上。這樣,在使用表面時(shí)就不用耗費(fèi)時(shí)間進(jìn)行硬盤(pán)存取了。相反地,PageUnlock()函數(shù)用于告知Windows哪些表面內(nèi)存可被釋放。

      過(guò)程調(diào)用PageLock()函數(shù)會(huì)減少緩沖內(nèi)存的總量,從而導(dǎo)致Windows的速度大大降低。至于這種情況何時(shí)發(fā)生,取決于頁(yè)面鎖定系統(tǒng)內(nèi)存量及機(jī)器提供的系統(tǒng)內(nèi)存量。

      PageLock()和PageUnlock()函數(shù)主要是由DirectDraw提供而非DirectDraw應(yīng)用程序。舉個(gè)例子來(lái)說(shuō),DirectDraw自動(dòng)使用PageLock()函數(shù),以確保運(yùn)行blt操作時(shí),基于系統(tǒng)RAM的表面不被釋放到硬盤(pán)。

      PageLock()函數(shù)可以被同一個(gè)表面多次調(diào)用。DirectDraw用參考計(jì)數(shù)法記錄PageLock()函數(shù)被調(diào)用的次數(shù),因此多次調(diào)用PageUnlock()函數(shù)就必須避免多次調(diào)用PageLock()函數(shù)。

      PageLock()和PageUnlock()函數(shù)對(duì)于駐留在顯示RAM中的表面不起作用。

      9. IsLost()的Restore()函數(shù)

      現(xiàn)在討論兩個(gè)與使用駐留在顯示RAM中的表面有關(guān)的函數(shù):

      ●IsLost()

      ●Restore()

      游戲編程之四 diectxdarw基礎(chǔ)篇(編程游戲)

      讓我們來(lái)看一看下面這種情況。應(yīng)用程序正在運(yùn)行時(shí),盡量把表面分配到顯示RAM中,剩下的創(chuàng)建到系統(tǒng)RAM中。應(yīng)用程序在運(yùn)行一段時(shí)間之后,用戶(hù)執(zhí)行或切換到另一個(gè)應(yīng)用程序。該應(yīng)用程序是任意的,可以是一個(gè)常規(guī)的Windows程序,如Windows開(kāi)發(fā)程序或記事本。它也可以是另外的DirectDraw應(yīng)用程序,該程序也試圖將盡可能多地分配顯示RAM。如果DirectDraw不接受顯示RAM,那么新的應(yīng)用程序就很可能根本運(yùn)行不了。相反的情況就意味著,應(yīng)用程序不允許分配到任何顯示RAM中。

      因此,DirectDraw可以隨意將任何一個(gè)或者所有的基于顯示RAM的表面從非激活應(yīng)用程序中移走。這種情況就是所謂的表面丟失。從技術(shù)上講,程序仍具有表面,但它們不再同任何內(nèi)存相關(guān)。要使用丟失的表面會(huì)導(dǎo)致DDERR-SURFACELOST錯(cuò)誤。IsLost()函數(shù)可用于確定一個(gè)表面是否丟失了內(nèi)存。

      表面內(nèi)存丟失后可通過(guò)Restore()函數(shù)恢復(fù),但只能在應(yīng)用程序被重新激活之后才可恢復(fù)。這會(huì)導(dǎo)致應(yīng)用程序無(wú)法將處于最小化狀態(tài)的所有表面復(fù)原。

      Restore()函數(shù)可恢復(fù)附屬于表面的任一內(nèi)存,但并不恢復(fù)內(nèi)存的內(nèi)容。表面被復(fù)原后,應(yīng)用程序就可以恢復(fù)表面內(nèi)容了。

      注意,這種用法不適合利用系統(tǒng)RAM創(chuàng)建的表面。如果需要用到基于系統(tǒng)RAM的表面所占內(nèi)存,那么Windows會(huì)立即將這些表面釋放到硬盤(pán)上。Windows自動(dòng)地處理存儲(chǔ)和恢復(fù),包括恢復(fù)表面的內(nèi)容。

      10. GetDDInterface()函數(shù)

      GetDDInterface()函數(shù)可檢索用于創(chuàng)建給定表面的DirectDraw接口的指針。由于程序中大多數(shù)情況下只有一個(gè)DirectDraw接口實(shí)例,所以GetDDInterface()函數(shù)并不常用。但是一個(gè)應(yīng)用程序中有可能使用多個(gè)DirectDraw接口,在這種情況下,GetDDInterface()函數(shù)會(huì)起到重要作用。

      11. 表面連接函數(shù)

      DirectDrawSurface接口提供以下4個(gè)函數(shù),用來(lái)維持表面間的連接:

      ●AddAttachedSurface()

      ●DeleteAttachedSurface()

      ●EnumAttachedSurfaces()

      ●GetAttachedSurface()

      DirectDraw支持大量的用于表面間的連接情況。最常見(jiàn)的情況就是頁(yè)面翻轉(zhuǎn)。進(jìn)行頁(yè)面翻轉(zhuǎn)時(shí),兩個(gè)或兩個(gè)以上的表面連接成環(huán)狀,每次調(diào)用Flip()函數(shù)時(shí),都會(huì)使連成環(huán)狀的表面中的下一個(gè)表面顯現(xiàn)。

      表面連接函數(shù)用于創(chuàng)建、檢查或消除表面間的連接,但這些函數(shù)并非必不可少的。DirectDraw往往是自動(dòng)創(chuàng)建連接表面。比如,當(dāng)創(chuàng)建一個(gè)主翻轉(zhuǎn)表面時(shí),可以指定用于連接表面的后備緩沖區(qū)的數(shù)量。DirectDraw就會(huì)創(chuàng)建這些表面,并將它們連接起來(lái)。

      12. 重疊函數(shù)

      DirectDrawSurface接口用于支持重疊的函數(shù)如下:

      ●AddOverlayDirtyRect()

      ●EnumOverlayZOrders()

      ●GetOverlayPosition()

      ●SetOverlayPosition()

      ●UpdateOverlay()

      ●UpdateOverlayDisplay()

      ●UpdateOverlayZOrder()

      GetOverlayPosition()和SetOverlayPosition()函數(shù)用于控制重疊的位置。UpdateOverlay()函數(shù)用于更新大量的重疊設(shè)置,包括重疊是否可見(jiàn),以及重疊是以色彩鍵碼還是用alpha混合到背景表面上。

      UpdateOverlayDisplay()函數(shù)用于更新顯示設(shè)置。該函數(shù)用于更新整個(gè)重疊顯示,或者只更新由AddOverlayDirtyRect()函數(shù)指定的矩形重疊部分。EnumOverlayZOrders()函數(shù)可根據(jù)重疊的Z值(Z值控制哪一個(gè)重疊位于最上面)重復(fù)重疊。重疊可按從前到后或從后到前的順序枚舉。

      13. 剪裁器函數(shù)

      DirectDraw支持的剪裁是將DirectDrawClipper接口(該接口我們尚未討論)的一個(gè)實(shí)例連接到表面。一旦連接完畢,剪裁器對(duì)象就會(huì)有規(guī)律地blt到表面。剪裁器/表面的連接由以下兩個(gè)DirectDrawSurface函數(shù)控制:

      ●GetClipper()

      ●SetClipper()

      SetClipper()函數(shù)用來(lái)將剪裁器對(duì)象連接到表面。GetClipper()函數(shù)用于向前一個(gè)連接的剪裁器對(duì)象返回一個(gè)指針。SetClipper()函數(shù)還可用于解除表面同剪裁器的連接,具體的做法是通過(guò)指定NULL來(lái)替代DirctDrawClipper接口指針。

      14。 調(diào)色板函數(shù)

      像剪裁器一樣,調(diào)色板也可連接到表面。DirctDrawSurface接口為此提供以下兩個(gè)函數(shù):

      ●GetPalette()

      ●SetPalette()

      SetPalette()函數(shù)用來(lái)將DirctDrawPalette接口(該接口我們接下來(lái)就要討論)的一個(gè)實(shí)例連接到表面。GetPalette()函數(shù)用于檢索前一個(gè)連接調(diào)色板的指針。

      調(diào)色板可被連接到任何表面,但只有連接到主表面時(shí),調(diào)色板才起作用。當(dāng)與主表面連接時(shí),調(diào)色板決定顯示硬件調(diào)色板的設(shè)置。

      第六節(jié) DirectDrawPlette接口函數(shù)

      DirctDraw提供DirctDrawPalette接口用于調(diào)色板顯示模式和表面。盡管Windows支持幾種低于8位像素深度的顯示模式,但DirctDraw所支持的唯一的調(diào)色板顯示模式是8位模式。

      DirctDrawPalette接口實(shí)例由DirctDraw CreatePalette()函數(shù)創(chuàng)建。CreatePalette()函數(shù)用大量的標(biāo)志來(lái)定義調(diào)色板屬性。

      DirctDrawPalette接口只提供以下3個(gè)函數(shù):

      ●GetCaps()

      ●GetEntries()

      ●SetEntries()

      GetCaps()函數(shù)用于檢索有關(guān)調(diào)色板的信息,包括調(diào)色板項(xiàng)目數(shù)量,調(diào)色板是否支持同步垂直刷新,以及在8位調(diào)色板狀態(tài)下是否所有的256個(gè)調(diào)色板項(xiàng)目都能被設(shè)定。

      SetEntries()函數(shù)允許在程序中設(shè)置調(diào)色板的色彩值。該數(shù)據(jù)從文件中讀取。而這些項(xiàng)目在運(yùn)行過(guò)程中可被計(jì)算和設(shè)定。GetEntries()函數(shù)用于檢索先前設(shè)定的調(diào)色板項(xiàng)目。

      DirctDrawPalette()接口實(shí)例可利用DirctDrawSurface SetPalette()函數(shù)連接到表面。將不同調(diào)色板連接到主表面或利用SetEntries()函數(shù)改變調(diào)色板項(xiàng)目都可激活調(diào)色板。

      第七節(jié) DirectDrawClipper接口函數(shù)

      DirctDrawClipper接口支持剪裁。將剪裁器對(duì)象連接到表面并在blt操作中將其當(dāng)作目標(biāo)表面就可以進(jìn)行剪裁。

      directDrawClipper實(shí)例由DirectDraw CreateClipper()函數(shù)創(chuàng)建。DirectDrawClipper接口支持以下5個(gè)函數(shù):

      ●SetHWnd()

      ●GetHWnd()

      ●IsClipListChanged()

      ●SetClipList()

      ●GetClipList()

      剪裁器對(duì)象一般用于出現(xiàn)在窗口中的DirctDraw應(yīng)用程序必需的剪裁。要求剪裁器必須確保在blt操作過(guò)程中考慮到桌面上其他的窗口。比如,當(dāng)應(yīng)用程序的全部或一部分被另一個(gè)窗口遮蔽,剪裁就必須確保被遮蔽的窗口不被DirctDraw應(yīng)用程序破壞。

      桌面剪裁由SetWnd()函數(shù)完成。SetHWnd()函數(shù)將剪裁器對(duì)象連接到一個(gè)窗口句柄。這樣就初始化了Windows和剪裁器對(duì)象之間的通訊。當(dāng)桌面上的任何一個(gè)窗口發(fā)生變化時(shí),剪裁器對(duì)象就會(huì)得到通知,并作出反應(yīng)。GetHWnd()函數(shù)用于決定剪裁器同哪一個(gè)窗口句柄連接。IsClipListChanged()函數(shù)用于決定內(nèi)部剪裁清單是否因桌面的改變而被更新。

      SetClipList()和GetClipList()函數(shù)為DirectDrawClipper接口提供便利的定制使用。SetClipList()函數(shù)用于定義一些矩形區(qū)域,這些矩形區(qū)域用來(lái)定義blt操作的合法區(qū)域。GetClipList()函數(shù)用于檢索剪裁器的內(nèi)部剪裁數(shù)據(jù)。

      一旦被連接到表面,Blt(),BltBatch()以及UpdateOverlay()函數(shù)所進(jìn)行的blt操作將根據(jù)DirctDrawCliper接口中包含的數(shù)據(jù)被自動(dòng)地剪裁。注意,Blt Fast()函數(shù)在此被忽略。BltFast()函數(shù)不支持剪裁。

      第八節(jié) 附加DirectDraw接口

      DirctDraw還提供了另外個(gè)我們沒(méi)有討論的接口,它們是:

      ●DDVideoPortContainer

      ●DirectDrawColorControl

      ●DirectDrawVideoport

      這些接口由DirectX5介紹,它們提供低水平視頻端口控制。這些接口還向DirctDraw表面提供流活動(dòng)視頻的方法。盡管利用這些接口可以為DirctDraw應(yīng)用程序增加視頻支持,但除非高水平視頻APIs不能滿足需要,否則最好不用這一方法。

      第九節(jié) DirectDraw結(jié)構(gòu)

      我們已討論過(guò)DirctDraw接口及其成員函數(shù)了,接下來(lái)再看看DirctDraw定義的結(jié)構(gòu)。DirctDraw總共定義了8全結(jié)構(gòu):

      ●DDBLTFX

      ●DDCAPS

      ●DDOVERLAYFX

      ●DDPIXELFORMAT

      ●DDSURFACEDESC

      ●DDSCAPS

      ●DDBLTBATCH

      ●DDCOLORKEY

      我們已經(jīng)見(jiàn)過(guò)其中的一些結(jié)構(gòu)了,比如在討論DirctDrawSurface SetColorKey()函數(shù)時(shí)我們就接觸過(guò)DDCOLORKEY結(jié)構(gòu)。在此,我們不詳細(xì)討論每一個(gè)結(jié)構(gòu)的細(xì)節(jié),但必須指出,DirctDraw quirk被忘記時(shí)會(huì)導(dǎo)致失敗。

      以上所列結(jié)構(gòu)中的前5個(gè)有一個(gè)稱(chēng)作dwSize的字段。該字段用于存儲(chǔ)結(jié)構(gòu)的大小,設(shè)定該字段的工作由你來(lái)做。另外,該字段如果沒(méi)有被正確設(shè)定的話,那么任何一個(gè)將這5個(gè)結(jié)構(gòu)作為變量的DirctDraw函數(shù)都會(huì)失效。

      以DDSURFACEDESC結(jié)構(gòu)為例,使用結(jié)構(gòu)的代碼如下:

      DDSURFACEDESC surfdesc;

      surfdesc.dwSize=sizeof(surfdesc);

      surf->GetSurfaceDesc(&surfdesc);

      首先聲明結(jié)構(gòu),然后用sizeof()關(guān)鍵字設(shè)定dwSize字段。最后結(jié)構(gòu)傳遞給DirctDrawSurface GetSurfaceDesc()函數(shù)。忘記設(shè)定dwSize字段將導(dǎo)致這段代碼失效。

      到底為什么DirctDraw堅(jiān)持要求給出它所定義的結(jié)構(gòu)的大小?原因在于這5個(gè)包含dwSize字段的結(jié)構(gòu)將來(lái)有可能會(huì)改變。DirctDraw會(huì)檢查結(jié)構(gòu)的大小,以便確定正在使用的版本。DirctDraw堅(jiān)持要求給出一個(gè)有效的大小值,是為了讓開(kāi)發(fā)者提供有效的結(jié)構(gòu)大小。這樣做是有好處的,因?yàn)镈irctDraw的新版本可以正確運(yùn)用舊版本的DirctDraw程序。

      在使用結(jié)構(gòu)之前,最好將結(jié)構(gòu)初始化為零。這樣,前面的代碼就變成:

      DDSURFACEDESC surfdesc;

      ZeroMemory (&surfdesc,sizeof(surfdesc));

      surfdesc.dwSize=sizeof(surfdesc);

      surf->GetSurfaceDesc(&surfdesc);

      ZeroMemory()函數(shù)是一個(gè)Win32函數(shù),它將作為第一個(gè)參數(shù)的存儲(chǔ)器設(shè)定為零.ZeroMemory()函數(shù)的第二個(gè)參數(shù)表明有多少存儲(chǔ)器應(yīng)被初始化。這一做法的好處是,通過(guò)GetSurfaceDesc()函數(shù)調(diào)用可以知道結(jié)構(gòu)的哪些字段被更新了。如果沒(méi)有對(duì)結(jié)構(gòu)進(jìn)行初始化,就有可能將結(jié)構(gòu)字段中不可預(yù)測(cè)的值當(dāng)作DirectDraw的設(shè)定值。

      第十節(jié) 窗口應(yīng)用程序

      DirctDraw應(yīng)用程序主要有兩種型式:窗口的和全屏的。窗口DirctDraw應(yīng)用程序看起來(lái)就像一個(gè)常規(guī)的Windows程序。我們很快將討論到全屏應(yīng)用程序。

      窗口應(yīng)用程序包括窗口邊界、標(biāo)題框以及菜單,這些都是傳統(tǒng)的Windows應(yīng)用程序中常見(jiàn)的部分。由于窗口應(yīng)用程序同其他窗口一起出現(xiàn)在桌面上,因此它們被迫使用Windows當(dāng)前所使用的分辨率和比特深度。

      窗口程序有一個(gè)主表面,但只在進(jìn)行真實(shí)頁(yè)面翻轉(zhuǎn)時(shí)才顯現(xiàn)。而且,主表面并不代表窗口的客戶(hù)區(qū)域(該區(qū)域在窗口邊界內(nèi))。主表面還代表整個(gè)桌面。這就是說(shuō),你的程序必須追蹤窗口的位置和大小,以便在窗口內(nèi)正確顯示可見(jiàn)的輸出。換言之,利用窗口化的應(yīng)用程序中可以在整個(gè)桌面上進(jìn)行繪圖。

      如果不允許頁(yè)面翻轉(zhuǎn),那么圖像就必須從離屏緩沖區(qū)blt到主表面上。這就增加了圖像撕裂的可能性,因?yàn)閎lt比頁(yè)面翻轉(zhuǎn)速度慢。為了避免圖像撕裂,blt操作可以與監(jiān)視的刷新率保持同步。

      如果與窗口客戶(hù)區(qū)域同樣大小的離屏緩沖區(qū)被創(chuàng)建到顯示RAM中,窗口應(yīng)用程序就可以很好地運(yùn)行。這樣,窗口的內(nèi)容可利用離屏表面合成。然后離屏表面可以通過(guò)硬件加速很快地到主表面上。

      由于顯示存儲(chǔ)器的缺乏而不得不將離屏緩沖區(qū)創(chuàng)建到系統(tǒng)RAM中時(shí),會(huì)嚴(yán)重影響性能。不幸的是,這種情況常常發(fā)生,尤其是在只有2MB顯示卡的時(shí)候,這是因?yàn)槿藗兛傁M麨樽约篧indows的桌面設(shè)置高分辨的顯示模式。例如,采用1024×768×16顯示模式的主表面自己就要占用2MB的RAM。在一個(gè)2MB顯示卡上,幾乎沒(méi)有顯示RAM留給離屏表面。

      窗口應(yīng)用程序的另一個(gè)問(wèn)題是剪裁。一個(gè)性能良好的應(yīng)用程序必須有一個(gè)連接到主表面的剪裁對(duì)象。這是有損性能的,原因在于為了檢查剪裁器的剪裁清單內(nèi)容,blt操作只能在一個(gè)小的矩形部分內(nèi)進(jìn)行。而且,不能使用優(yōu)化的BltFast()函數(shù)。Bltting必須用較慢的,(而且更笨重的)Blt()函數(shù)。

      最后要講的是,窗口應(yīng)用程序不允許全調(diào)色板控制。由于Windows保留了20個(gè)調(diào)色板項(xiàng),所以在256種顏色只有236種顏色可被設(shè)定。被Windows保留的顏色只用系統(tǒng)調(diào)色板的前10個(gè)項(xiàng)和后10個(gè)項(xiàng)。因此在給圖像上色時(shí),只能使用中間236個(gè)調(diào)色板項(xiàng)。

      第十一節(jié)全屏應(yīng)用程序

      包含對(duì)顯示設(shè)備進(jìn)行專(zhuān)有存取的DirctDraw應(yīng)用程序就是全屏應(yīng)用程序。這種應(yīng)用程序可以任意選取顯示卡所支持的顯示模式,并享有全調(diào)色板控制。另外,全屏應(yīng)用程序還可進(jìn)行頁(yè)面翻轉(zhuǎn)。因此同窗口應(yīng)用程序相比,全屏應(yīng)用程序速度更快,靈活性更好。

      典型的全屏應(yīng)用程序首先檢查所支持的顯示模式,并激活其中一個(gè)。然后創(chuàng)建具有一個(gè)或更多后備緩沖區(qū)的可翻轉(zhuǎn)主表面,剩下的顯示RAM用于創(chuàng)建離屏表面。當(dāng)顯示RAM耗盡時(shí),就啟用系統(tǒng)RAM。屏幕被在后備緩沖區(qū)中合成的第一個(gè)場(chǎng)景更新,然后進(jìn)行頁(yè)面翻轉(zhuǎn)。即使主表面占用了所有的可用的顯示RAM,全屏應(yīng)用程序還可輸出執(zhí)行其窗口化的副本,這是因?yàn)槿翍?yīng)用程序可進(jìn)行真實(shí)頁(yè)面翻轉(zhuǎn)。

      由于全屏應(yīng)用程序不一定非得使用Windows的當(dāng)前顯示模式,所以顯示RAM的可用與否不存在多少問(wèn)題。如果只檢測(cè)到2MB的顯示RAM,就可使用低分辨率顯示模式來(lái)保留內(nèi)存。如果檢測(cè)到4MB的顯示RAM,應(yīng)用程序就可使用要求的顯示模式并仍有保持良好性能。

      全調(diào)色板控制也是個(gè)有利因素。這樣可以使用所有256個(gè)調(diào)色板項(xiàng)而無(wú)需根據(jù)Windows保留的20中顏色重新分配位圖。

      第十二節(jié)混合應(yīng)用程序

      混合應(yīng)用程序既可以在全屏方式下運(yùn)行也可在窗口方式下運(yùn)行。混合應(yīng)用程序內(nèi)部非常復(fù)雜,但卻可以提供良好的性能。用戶(hù)可在窗口方式下運(yùn)行,如果太慢,則可切換到全屏方式下運(yùn)行。

      編寫(xiě)混合應(yīng)用程序最好的方法是編寫(xiě)一個(gè)定制庫(kù),該庫(kù)包括那些與應(yīng)用程序使用全屏方式還是窗口方式無(wú)關(guān)的函數(shù)。象編程

      Windows實(shí)現(xiàn)了一種仿OOP(面向?qū)ο缶幊?環(huán)境。Windows下的消息系統(tǒng)負(fù)責(zé)在多任務(wù)環(huán)境中分解信息。從應(yīng)用程序的角度來(lái)看,消息是關(guān)于發(fā)生的事件的通知。用戶(hù)可以通過(guò)按下或移動(dòng)鼠標(biāo)來(lái)產(chǎn)生這些事件。

      5G游戲 視頻

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶(hù)投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶(hù)投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:2003excel表格如何篩選重復(fù)數(shù)據(jù)(excel2003怎樣篩選出重復(fù)的數(shù)據(jù))
      下一篇:Python程序員面試常用基礎(chǔ)問(wèn)題解析
      相關(guān)文章
      亚洲午夜久久久影院伊人| 妇女自拍偷自拍亚洲精品| 亚洲丰满熟女一区二区哦| 亚洲色图视频在线观看| 亚洲中文字幕第一页在线| 亚洲精品乱码久久久久久不卡| 日韩亚洲人成网站| 亚洲成a人无码亚洲成av无码| 亚洲人成色777777精品| 亚洲日韩av无码中文| 亚洲国产成人久久77| 亚洲最新视频在线观看| 亚洲黄色高清视频| 亚洲精品高清无码视频| 在线观看亚洲免费| 亚洲精品宾馆在线精品酒店| 亚洲精品无码专区在线播放| 亚洲色偷偷色噜噜狠狠99| 亚洲AV永久无码精品放毛片| 亚洲人成网站在线在线观看| 亚洲综合色一区二区三区小说| 亚洲毛片在线免费观看| 99久久精品国产亚洲| 亚洲精品在线播放| 亚洲大片在线观看| 久久久无码精品亚洲日韩蜜臀浪潮| 亚洲欧洲日产国产综合网| 亚洲精品在线免费看| 亚洲伊人色一综合网| 亚洲午夜无码毛片av久久京东热| 亚洲欧洲无卡二区视頻| 国产尤物在线视精品在亚洲| 亚洲一区二区三区乱码A| 国产亚洲老熟女视频| 久久精品国产亚洲av成人| 亚洲成人免费在线观看| 亚洲乱妇熟女爽到高潮的片 | 全亚洲最新黄色特级网站 | 亚洲高清无在码在线电影不卡| 亚洲春色另类小说| 亚洲日韩AV无码一区二区三区人|