?? dx5.txt
字號:
像素格式指出了任何對表面內存中每個像素數據作出解釋。DirectDraw使用DDPIXELFORMAT結構描述各種像素信息。
DDPIXELFORMAT結構的成員描述了像素格式的下述特性:
.調色或非調色像素格式
.如果是非調色格式,像素格式是RGB還是YUV格式
.位深度
.像素格式組成部分的位屏蔽
你可以調用IDirectDrawSurface3::GetPixelFormat方法來獲取存在的表面的像素格式。
4.4、創建表面
DirectDrawSurface對象表征了駐留在顯示內存中的一個表面。如果顯示內存用完了或者是顯式地創建,該表面也可存在于系統內存中。
你可以使用IDirectDraw2::CreateSurface方法創建一個或多個表面。調用CreateSurface時,必須指定表面的大小、表面類型(是單一表面還
是復雜表面)、像素格式(如果表面不使用索引的調色板)。所有的這些特性都包含在DDSURFACEDESC結構中,在調用時需要將該結構的
地址傳送過去。如果硬件不支持請求的特性或者此前已經將那些資源分配給了另一個DirectDrawSurface對象,調用就會失敗。
創建單一的表面或多表面只需要幾行簡單的代碼。創建表面有四個主要的步驟。每一個步驟都需要比前一個步驟更多的準備工作,不過
并不太難,它們是:
(1). 創建主表面
(2). 創建一個屏外表面
(3). 創建復雜表面和翻轉鏈
(4). 創建寬表面
在缺省的情況下,DirectDraw在本地視頻內存創建一個表面,如果足夠的本地視頻內存保存該表面,DirectDraw就嘗試利用非本地視頻
內存(僅在一些AGP設備系統中)。你可以在調用CreateSurface時對DDSCAPS結構賦以適當的標志來顯式地指明在哪類內存中創建表面。
4.4.1、創建主表面
主表面是當前在顯示器上可見的并且由DDSCAPS_PRIMARYSURFACE標志指明的表面,每一個DirectDraw對象只能有一個主表面。
當你創建一個主表面時,其大小應該同當前的顯示模式匹配。因此,在這種情況下你不需要指明表面的大小。事實上,如果你指明了表面的
大小,即使同當前的顯示模式匹配,也會導致創建過程的失敗。
下面的例子顯示了如何設置DDSURFACEDESC結構的相關成員來創建主表面:
DDSURFACEDESC ddsd;
ddsd.dwSize = sizeof(ddsd);
// Tell DirectDraw which members are valid.
ddsd.dwFlags = DDSD_CAPS;
// Request a primary surface.
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4.4.2、創建屏外表面
屏外表面通常用于位圖的緩存,該位圖將被位塊傳輸到主表面或后臺緩沖區中。你必須設定包含DDSC_WIDTH和DDSD_HEIGHT標
志并設定dwWidth和dwHeight成員 為適當的值來說明屏外表面的大小。另外,還必須在DDSCAPS結構中包含DDSCAPS_OFFSCREENPLAIN
標志。
當沒有足夠的顯示內存使用時,DirectDraw就使用系統內存來創建表面。你可以在DDSCAPS結構中的dwCaps成員包含
DDSCAPS_SYSTEMMEMORY或 DDSCAPS_VIDEOMEMORY標志來顯式地指明是在顯示內存還是在系統內存中創建表面。下面的例子顯
示了創建一個屏外表面之前的準備工作:
DDSURFACEDESC ddsd;
ddsd.dwSize = sizeof(ddsd);
// Tell DirectDraw which members are valid.
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
// Request a simple off-screen surface, sized
// 100 by 100 pixels.
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
dwHeight = 100;
dwWidth = 100;
在DirectX以前的版本中,屏外表面的最大寬度不能超過主表面的寬度。在DirectX 5中,你可以創建任意寬度的屏外表面,只要顯示設
備指出就行。需要注意的是,當聲明了屏外表面的寬度時,如果顯示內存容不下請求的表面的寬度,該表面將換在系統內存中創建。如果顯
式地聲明使用視頻內存,而視頻內存又不夠時,創建表面的工作就會失敗。
4.4.3、創建復雜表面(Complex Surface)和翻轉鏈(Flipping Chain)
一個復雜表面就是用IDirectDraw2::CreateSurface方法創建的一組單一表面的組合。若在調用CreateSurface時設定了
DDSCAPS_COMPLEX標志,除了顯式指定的表面外,DirectDraw還將隱式地創建一個或多個表面。你可以象管理單一表面一樣管理復雜表
面。調用IDirectDraw::Release方法會釋放所有的表面,調用IDirectDrawSurface3::Restore則會將這些表面恢復。
最常用的復雜表面是翻轉鏈。通常,一個翻轉鏈由一個主表面和一個或多個后臺緩沖區組成。DDSCAPS_FLIP標志說明了某一表面是
一翻轉鏈一部分。用這種辦法創建一個翻轉鏈還需要包含DDSCAPS_COMPLEX標志。下面的例子創建一個主表面翻轉鏈所需要的準備工作:
DDSURFACEDESC ddsd;
ddsd.dwSize = sizeof(ddsd);
// Tell DirectDraw which members are valid.
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
// Request a primary surface with a single
// back buffer
ddsd.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP |
DDSCAPS_PRIMARYSURFACE;
ddsd.dwBackBufferCount = 1;
該例構建了一個雙緩沖翻轉環境。調用IDirectDrawSurface3::Flip方法將交換主表面和后臺緩沖區的表面內存。如果DDSURFACEDESC
結構中的成員dwBackBufferCount取值為2,就會創建兩個后臺緩沖區,每次調用Flip就會循環地翻轉表面,并提供三緩沖翻轉環境。
4.4.4、創建寬表面(Wide Surface)
DirectDraw允許創建比主表面寬的屏外表面,當然這需要顯示硬件支持才行。要確定顯示設備是否支持寬表面,需要調用
IDirectDraw2::GetCaps方法,查看第一個DDCAPS結構中的dwCaps2成員是否包含DDCAPS2_WIDESURFACES標志。如果該標志存在,
就表明可以在視頻內存中創建比主表面還要寬的屏外表面。如果該標志不存在,在視頻內存中創建寬表面將會失敗,并返回一個
DDERR_INVALIDPARAMS錯誤。
系統內存表面、視頻端口表面和執行緩沖區都支持寬表面。
4.4.5、翻轉表面(Flipping Surface)
DirectDraw中的任何表面都可以構建為一個翻轉表面。一個翻轉表面就是能夠在前臺緩沖區(front buffer)和后臺緩沖區(back buffer)
之間互相交換的任意一塊內存。通常,前臺緩沖區就是主表面,但這并不是必需的。
當使用IDirectDrawSurface3::Flip方法執行表面翻轉操作時指向主表面的表面內存的指針和后臺緩沖區的表面內存的指針互換。因此,表面的
翻轉是顯示設備用于指向內存的指針的交換,而不是對表面內存的拷貝。唯一的例外是,當DirectDraw用軟件仿真翻轉時只是簡單地拷貝表
面。如果一個后臺緩沖區不能裝入到顯示內存中或硬件不支持DirectDraw時,DirectDraw就用軟件仿真翻轉操作。當一個翻轉鏈包含了一個
主表面和多個后臺緩沖區時,指針的轉換就采用了循環的方式周而復始,如下圖所示:
DirectDraw對象的其它附加表面不是翻轉鏈的一部分,不受Flip方法的影響。切記,DirectDraw翻轉表面是通過交換DirectDrawSurface
對象表面內存的指針實現的,而不是交換這些對象。這就意味著,位塊傳輸到后臺緩沖區時,必須一直使用同一個DirectDrawSurface對象,
該緩沖區是你創建翻轉鏈的后臺緩沖區。而指向翻轉操作一直是通過調用前臺緩沖區的Flip方法完成的。
4.4.6、丟失表面(Losing Surface)
當表征表面內存的DirectDrawSurface對象不必要釋放時,同該表面關聯的表面內存卻被釋放了。這就是失去了表面。當DirectDrawSurface
對象事情了它的表面內存時,許多方法就不執行其它的操作并返回DDERR_SURFACELOST。
因為改變了顯示模式或另一個應用獲得了對顯示設備的獨占訪問而釋放了當前分配的所有表面內存,表面就可能會丟失。
IDirectDrawSurface3::Restore方法重新創建這些丟失的表面并同DirectDrawSurface對象重新聯結。恢復表面并不裝入表面丟失之前存在的位
圖。因此,如果丟失的表面,必須完全重新裝入此前曾裝入的圖形。
4.4.7、釋放表面(Releasing Surface)
象所有的COM接口一樣,不需要表面時,必須調用Release方法釋放表面。每一個單獨創建的表面都必須顯式地釋放。如果是一次調
用 IDirectDraw2::CreateSurface或IDirectDraw::CreateSurface方法顯式地創建的多個表面(如翻轉鏈等),你只需要釋放前臺緩沖區即可。在
這種情況下,指向后臺緩沖區表面的任何指針都會顯式地釋放,并且不可再用。
4.4.8、更新表面特征(Updating Surface Characteristics)
你可以使用IDirectDrawSurface3::SetSurfaceDesc方法來更新已有表面的特征。用該方法可以改變像素格式,也可以改變DirectDrawSurface
對象的表面內存在系統內存中的位置,該對象是應用程序顯式地分配的。它允許一個表面直接使用先前分配的緩沖區中的數據而不需要拷貝,
這一新的表面內存由客戶應用來分配,也由該客戶應用來釋放。
調用 IDirectDrawSurface3::SetSurfaceDesc方法時,lpddsd參數必須是描述新的表面內存的結構DDSURFACEDESC的地址,也就是指向
該內存地址的指針。在DDSURFACEDESC結構中,可以只設定dwFlags成員來反映表面內存的位置、大小和像素格式。因此dwFlags只能
包含DDSD_WIDTH、DDSD_HEIGHT、DDSD_PITCH、DDSD_LPSURFACE和DDSD_PIXELFORMAT等標志的組合,用這些組合來設定
有效的結構成員。
在設置結構的值前,必須分配內存來裝入表面。分配的內存的大小非常重要 。你不僅需要分配足夠的內存來容納表面的寬和高,還需
要為表面間距(pitch)留下足夠的內存空間,表面間距是一個QWORD(8個字節),間距是用高度而不是用像素度量的。
設置結構中表面的值時,lpSurface成員是你分配的內存的指針, dwHeight和dwWidth成員以像素單位描述了表面的大小。如果指定了
表面的大小,也需要填充Ipitch成員來反映表面間距。ddpfPixelFormat成員描述了表面的像素格式。除了lpSurface成員外,若你不為這些成
員設定值,IDirectDrawSurface3::SetSurfaceDesc方法就從當前的表面中使用缺省的值。
在調用IDirectDrawSurface3::SetSurfaceDesc方法時需要注意一些問題。例如,lpSurface必須是系統內存的一個有效指針(該方法目前不支持
視頻內存指針);dwWidth和dwHeight必須是非0的值;不能在主翻轉鏈中重新分配主表面或其它任意表面。
你可以為多個DirectDrawSurface對象分配同一內存,但必須注意當內存分配給任意表面對象后,就不能取消對該內存的分配。對
SetSurfaceDesc方法不正確的使用會導致不可預料的反應。因此,當不再需要表面內存時,你必須記住釋放它。不過,在調用該方法時,DirectDraw
將釋放創建表面時顯式分配的表面內存。
4.4.9、直接訪問幀緩沖區(Accessing the Frame-Buffer Directly)
你可以使用IDirectDrawSurface3::Lock方法直接訪問幀緩沖區或系統內存中的表面內存。當調用該方法時,lpDestRect參數是一個RECT
結構的指針。該結構描述了要直接訪問的表面上的矩形。若想鎖定整個表面,可將lpDestRect設為NULL。也可以指定一個只包含了表面的
一部分的RECT。如果沒有兩個矩形重疊,兩個進程可以同時鎖定一個表面中的多個矩形。
Lock方法用需要適當地訪問表面內存的所有信息填充DDSURFACEDESC結構。該結構包含了有關表面間距和像素格式的信息(在同主
表面的像素格式不同時)。在完成了對表面的訪問后,調用IDirectDrawSurface3::Unlock方法對其進行解鎖。
4.4.10、使用非本地視頻內存表面(Using Non-local Video Memory Surfaces)
DirectDraw支持高級圖形端口AGP(Advanced Graphics Port)特性,能夠在非本地視頻內存中創建表面。在AGP系統中,如果本地視
頻內存已用完或應用程序顯式地要求使用非本地內存,DirectDraw將會使用非本地視頻內存創建表面。
目前,有兩種AGP體系。一種是“執行模型”(Execute Model),一種是“DMA模型”(Direct Memory Access Model)。在執行模型中,
顯示設備支持非本地視頻內存和本地視頻內存同樣的特性。因此,當使用 IDirectDraw2::GetCaps方法獲取硬件的性能時,同位塊傳輸相關
的標志dwNLVBCaps、dwNLVBCaps2、dwNLVBCKeyCaps、dwNLVBFXCaps和dwNLVBRops將指明用于本地視頻內存。在執行模式下,
如果本地視頻內存被用完了,DirectDraw將自動使用非本地視頻內存。
在DMA模型中,對從非本地視頻內存中位塊傳輸的紋理貼圖的支持是有限的。當顯示設備使用了DMA模型時,欲獲得硬件的性能,
dwCaps成員將被設為DDCAPS2_NONLOCALVIDMEMCAPS標志。同位塊傳輸相關的標志包含在dwNLVBCaps、dwNLVBCaps2、
dwNLVBCKeyCaps、dwNLVBFXCaps和dwNLVBRops等成員中。除非顯式地指明,D
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -