DirectX5.0最新游戏编程指南 DirectDraw篇 三、DirectDraw的要素(三)(2) 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。