swap chain- IDirect3DSwapChain9




  交换链,对应的接口是IDirect3DSwapChain9,是整个Directx 3D中最核心的接口。D3d程序至少包含一个swap chain,在调用CreateDevice时自动创建,

其中的
D3DPRESENT_PARAMETERS * pPresentationParameters参数设置将要创建的IDirect3DSwapChain9的属性。首先我们看看这个接口提供的函数,我们
可以找到Present函数,
其实不难猜到IDirect3DDevice9::Present函数内部就是调用了默认IDirect3DSwapChain9Present函数。
  进一步讲,IDirect3DDevice9GetBackBufferGetFrontBufferData等函数都调用了IDirect3DSwapChain9的接口所以一般有一个UINT  iSwapChain参数来指示调用哪个
swap chain
,0代表默认
CreateDevice时创建的
IDirect3DSwapChain9

IDirect3DSwapChain9::GetBackBuffer

Retrieves a back buffer from the swap chain of the device.

IDirect3DSwapChain9::GetDevice
Retrieves the device associated with the swap chain.
IDirect3DSwapChain9::GetDisplayMode
Retrieves the display mode's spatial resolution, color resolution, and refresh frequency.
IDirect3DSwapChain9::GetFrontBufferData
Generates a copy of the swapchain's front buffer and places that copy in a system memory buffer provided by the application.
IDirect3DSwapChain9::GetPresentParameters
Retrieves the presentation parameters associated with a swap chain.
IDirect3DSwapChain9::GetRasterStatus
Returns information describing the raster of the monitor on which the swap chain is presented.
IDirect3DSwapChain9::Present
Presents the contents of the next buffer in the sequence of back buffers owned by the swap chain.

Front buffer

  A graphics adapter holds a pointer to a surface that represents the image being displayed on the monitor, called a front buffer.其中的内容会直接发送给显示器显示,

其大小等于screen size,可以通过下面代码来获取。首先我们必须创建一个Cpu的IDirect3DSurface9,然后通过GetFrontBufferData填充其内容。如果直接绘制到Front buffer上,会使画面不连续
,撕裂(tearing)等等。当显示器(monitor)刷新时,显卡把front buffer的内容发送给显示器。一般的显示器刷新频率在60Hz到100Hz之间,这跟计算机其他部件的工作频率相差甚远。如果程序在显示器
刷新的过程中更新了front buffer,那么显示出来的上半部分画面是旧的,下半部分画面是新的,这就是撕裂(tearing).
1 D3DDISPLAYMODE dm;
2 g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT,&dm );
3 IDirect3DSurface9* pSurface;
4 g_pd3dDevice->CreateOffscreenPlainSurface( dm.Width, Height,
5 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL);
6 g_pd3dDevice->GetFrontBufferData(0, pSurface);  
7 D3DXSaveSurfaceToFile( 
8 _T("Desktop.bmp"),D3DXIFF_BMP,pSurface, NULL, NULL );
9 pSurface->Release();

解决这个问题有两种方案:

1,只在垂直回扫(vertical retrace)时允许更新front buffer,在每一次刷新,显示器从上到下,从左到右的移动光头(light pin),一直到右下角为止。然后光头又移动回
显示器的
左上角(vertical retrace),为下一次刷新做准备。这样可以避免撕裂,但是垂直回扫(vertical retrace)时间往往不足以绘制复杂场景。

2, 后台缓存(back buffering)
Back buffering is the process of drawing a scene to an off-screen surface, called a back buffer. Note that any surface
other than the front buffer is called an off-screen surface because it is never directly viewed by the monitor. By using a back buffer, an application
has the freedom to render a scene whenever the system is idle (that is, no windows messages are waiting) without having to consider the monitor's refresh
rate. Back buffering brings in an additional complication of how and when to move the back buffer to the front buffer.
解决方法是在
垂直回扫(vertical retrace) 时把数据从back buffer移动到front buffer,两种移动方式,直接copy或者Flipping Surfaces,这可以通过D3DPRESENT_PARAMETERSSwapEffect参数来指定。


原文地址:https://www.cnblogs.com/lc-cnblong/p/3365066.html