如何实现双缓冲
一、什么叫双缓冲
后备缓冲通过创建一个或多个主缓冲来实现平滑的动画显示,之后用户在不可见的后备缓冲里绘图(具备相同的尺寸和色彩深度的缓冲),只使用一个后备缓冲叫做双缓冲。
二、用双缓冲技术执行动画流程
三、创建后备缓冲
创建后备缓冲的目的是用DirectDraw的方式来实现对双缓冲功能的仿真。
为了创建一个关联有后备缓冲的主表面,必须创建DirectDraw所谓的复杂表面,步骤如下:
1、要将DDSD_BACKBUFFERCOUNT加到dwFlags标志字段,向DirectDraw表明DDSURFACEDESC2结构的dwBackBufferCount字段有效,其中含有后备缓冲的数目
2、将控制标志DDSCAPS_COMPLEX和DDSCAPS_FLIP加到DDSURFACEDESC2结构的特性描述字段ddsCaps.dwCaps上
3、创建主表面,从它调用IDIRECTDRAWSURFACE7::GetAttachedSurface()以得到后备缓冲
例:
DDSURFACEDESC2 ddsd; LPDIRECTDRAWSURFACE7 lpddsprimary=NULL; LPDIRECTDRAWSURFACE7 lpddsback=NULL; DDRAW_INIT_STRUCT(ddsd); ddsd.dwFlags=DDSD_CAPS|DDSD_BACKBUFFERCOUNT; ddsd.dwBackBufferCount=1; ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE|DDSCAPS_COMPLEX|DDSDCAPS_FLIP; if(FAILED(lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL))){return 0;} ddsd.ddsCaps.dwCaps=DDSCAPS_BUCKBUFFER; if(FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps,&lpddsback))){return 0;}
过程如下:
四、将后备缓冲中的画面复制到主缓冲中
假设你创建的画面是640*480,则需要先锁定后备缓冲,然后将缓存区的指针指向后备缓冲的显示表面,如:
DDRAW_INIT_STRUCT(ddsd);
lpddsback->Lock(NULL,&ddsd,DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT,NULL);
UCHAR *back_buffer=(UCHAR*)ddsd.lpSurface;
此时,你需要判断锁定内存的过程中存储了的内存步长mempitch,如果mempitch等于显示模式的宽度640,则将back_buffer拷贝到primary_buffer:
memcpy((void*)primary_buffer,(void*)back_buffer,640*480); //primary_buffer是指向主显示表面
否则,可以采取逐行拷贝的方式,如:
memcpy((void*)primary_buffer,(void*back_buffer,640));
primary_buffer+=mempitch;
back_buffer+=640;
五、实现页面切换
标准动画的循环步骤如下:
1、清除后备缓存
2、将场景渲染到后备缓冲
3、用后备缓冲表面切换掉主表面
4、锁定在某个帧数率(例如60fps)
5、重复第1步
流程图如下:
使用IDIRECTDRAWSURFACE7::Flip(),在交换链中用下一个关联的表面切换主表面
while(FAILED(lpddsprimary->Flip(NULL,DDFLIP_WAIT))); //DDFLIP_WAIT表示等待页面切换能够进行为止,第一个参数是DIRECTDRAWSURFACE7类型的指针,用来覆盖切换链,实现到另外一个表面,而不是切换到同主表面相关联的后备缓冲,设为NULL,就是表示切换到同主表面相关联的后备缓冲