DirectDrawSurface对象表现一个平面通常是驻留在显存中,但也可在系统内存中创建, 除非如果显存不够或特别指出。
使用IDirectDraw4::CreateSurface宏来创建一个平面或多重平面(复杂平面)。 当调用CreateSurface,你需要指定平面尺寸,及是单一平面还是多重平面, 及像素格式(如果平面不使用一个索引调色板)。所有这些特性都包含在一个DDSURFACEDESC2的结构中, 也就是在调用时要传递的。如果硬件无法支持所需能力或资源已被以前的另一个DirectDrawSurface 对象所占用,调用便会失败。
创建一个单一平面或一个多重平面简单得只需几行代码即可。在创建平面时有许多相同情况 (及一些部分相同),包括以下情况:
默认时,除了内存平面(Client Memory Surfaces),DirectDraw会尝试在本地显存中创建平面。 如果没有足够显存来装入平面,DirectDraw会试着用非本地显存 (如一些加速图形端口系统 Accelerated Graphics Port-equipped System 译者按:也就是平时所称的AGP系统), 最后会在其他内存都不行时使用系统内存。你可以指定平面创建时所使用的内存类型, 可以在调用IDirectDraw4::CreateSurface时改变在DDSCAPS2结构中包含的标志符。
主平面是在显示器上可见平面并可通过DDSCAPS_PRIMARYSURFACE标志来鉴定。 每个DirectDraw对象只能有一个主平面。
当你创建一个主平面时,记住尺寸及像素格式应匹配当前显示模式。 因此,此时你无须申明平面的尺寸或像素格式。如果你具体说明它们, 调用就会失败并返回DDERR_INVALIDPARAMS即使你使用的信息与当前显示模式匹配也是如此。
以下例程指出如何准备DDSURFACEDESC2结构成员用来创建主平面:
DDSURFACEDESC2 ddsd; ddsd.dwSize = sizeof(ddsd); // Tell DirectDraw which members are valid. 告诉DirectDraw什么成员是有效的 ddsd.dwFlags = DDSD_CAPS; // Request a primary surface. 需要一个主平面 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
在创建主平面后,你能通过调用IDirectDrawSurface4::GetSurfaceDesc宏来获得其尺寸及像素格式。 参见,显示模式(Display Modes)
一个屏下平面是通常用于缓冲存放位图,可被用于Blit (译者按:Blit 无法找到可用译法,其意义是指将位图一部分或全部进行块移动) 到主平面或屏后缓冲。你必须申明其尺寸,通过包含的DDSD_WIDTH及DDSD_HEIGHT标志及dwWidth及 dwHeight成员一致的值。另外,你必须在DDSCAPS2结构中包含DDSCAPS_OFFSCREENPLAIN标志。
默认时,DirectDraw会在显存中创建一个平面除非无法装入,此时就会在系统内存中创建平面。 你可以在DDSCAPS2结构中的dwCaps的DDSCAPS_SYSTEMMEMORY或DDSCAPS_VIDEOMEMORY 标志来明确选择是系统内存或显存。如果无法在指定位置创建平面,则宏调用失败,返回错误。
以下例子显示如何准备创建一个简单的屏下平面(Off-Screen):
DDSURFACEDESC2 ddsd; ddsd.dwSize = sizeof(ddsd); // Tell DirectDraw which members are valid. 告诉DirectDraw什么成员有效 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; // Request a simple off-screen surface, sized // 100 by 100 pixels. // 需要一个简单屏下平面,尺寸为100X100点像素 // // (This assumes that the off-screen surface we are about // to create will match the pixel format of the // primary surface.) // (这是假设在我们创建的屏下平面的像素格式与主平面的像素格式相匹配) // ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; ddsd.dwHeight = 100; ddsd.dwWidth = 100;
另外,你也可以创建与主平面像素格式不同的平面。不管怎样,在这种情况下有一个不利点, 你只能限于使用系统内存。以下代码段显示如何准备DDSURFACEDESC2结构来创建一个8-Bit 基于调色板的平面(假设当前显示模式是非8-Bit像素点)。
ZeroMemory(&ddsd, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; ddsd.dwHeight = 100; ddsd.dwWidth = 100; ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8; // Set the bit depth for an 8-bit surface, but DO NOT // specify any RGB mask values. The masks must be zero // for a palettized surface. // 设置平面位深为8-Bit,但不要指定任何RGB屏蔽值。在基于调色板的8-Bit平面中屏蔽 // 值必须为零。 // ddsd.ddpfPixelFormat.dwRGBBitCount = 8;
在以前版本的DirectX中,屏下平面的最大宽度是限制于主平面的宽度。从DirectX 5.0起, 你可以创建任意宽度的平面,只要显示硬件支持。要注意当定义宽屏下缓冲时, 如果显存无法装入这个宽度的平面,平面就会在系统内存中创建。如果你明确选择显存, 但硬件无法支持,就会返回错误。请参阅创建宽平面。
你也可以创建多重平面。一个多重平面通过一次调用IDirectDraw4::CreateSurface 宏在创建设置平面。当你在调用CreateSurface时设置了DDSCAPS_COMPLEX标志,DirectDraw 就会根据需要暗中创建一个或多个平面。你可以象管理单一平面时管理多重平面, 一次调用IDirectDraw::Release宏释放所有平面,一次调用IDirectDrawSurface4::Restore 宏来恢复所有平面。不管怎样,暗中创建的平面是无法被分开的。参阅 IDirectDrawSurface4::DeleteAttachSurface。
创建多重平面的一个最重要的用处是你可以创建切换链。通常, 一个切换链是由一个主平面及一个或多个屏后缓冲组成。这样创建切换链就需要包含DDSCAPS_COMPLEX标志。
以下例程显示了如何准备创建一个主平面切换链。
DDSURFACEDESC2 ddsd2; ddsd2.dwSize = sizeof(ddsd2); // Tell DirectDraw which members are valid. // 告诉DirectDraw什么成员是有效的。 ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; // Request a primary surface with a single // back buffer // 需要创建一个只需一个屏后缓冲的主平面 ddsd2.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE; ddsd2.dwBackBufferCount = 1;
上面的例程生成一个双缓冲(Double-Buffer)切换环境,一次调用IDirectDrawSurface4::Flip 宏来对换主平面及屏后缓冲的平面内存。如果你指定DDSURFACEDESC2结构中的dwBackBufferCount 成员值为2,就会创建两个缓冲,每次调用Flip就会使平面循环改变,产生一个三缓冲(Triple-Buffer) 切换环境。参见:切换平面。
注意:
要创建的切换链中包含的平面如果要用于三维演示目标, 请注意在描述平面时要包含DDSCAPS_3DDEVICE能力标志符,就象DDSCAPS_COMPLEX及DDSCAPS_FLIP标志符。 不象IDirectDraw3或更早的界面中的CreateSurface宏,你不能用IDirectDraw4::CreateSurface 来暗中通过一个附加的深度缓冲(Depth-Buffer)创建一个演示目标平面的切换链。 IDirectDraw4::CreateSurface宏支持的DDSURFACEDESC2结构并不包括指定深度缓冲位深的部分。 所以,程序必须明确创建一个深度缓冲的平面,然后将其附加到屏后缓冲来演示目标平面。 参见:深度缓冲。
Lucker 1999.3.25
E-Mail: fred_cai@kali.com.cn