关键字:创建后备缓冲 页面切换
1.后备缓冲
在双缓冲技术中,分配了一块缓冲区作为一个double_buffer,绘制的时候,先在doublue_buffer中完全绘制完成,然后再将内存块拷贝到主表面的内存区。
后备缓冲(back buffer)是指创建一个和主表面有着相同尺寸和色深的表面(direct draw surface),来实现双缓冲。
如果显存足够,后备缓冲区也将分配到VRAM,这样和主表面进行内存拷贝的速度会快得多。
2.创建后备缓冲
在DX中,后备缓冲是和主表面相关联的。
创建后备缓冲的步骤是:
1.ddsd.dwFlags追加DDSD_BACKBUFFERCOUNT(表示设置后备缓冲数量backCount字段有效)
2.ddsd.ddsCaps.dwCaps字段追加 DDSCAPS_COMPLEX | DDSCAPS_FLIP (表示要创建复杂表面,并且会切换表面)
3.创建完成主表面后,调用 lpddsprimary->GetAttachedSurface获取到和主表面关联的后备缓冲表面。
HRESULT GetAttachedSurface()函数原型:
1
2HRESULT GetAttachedSurface(LPDDSCAPS lpDDSCaps, // DDSCAPS2表达显示面属性的结构,需要设置为DDSCAPS_BACKBUFFER
LPDIRECTDRAWSURFACE FAR *lplpDDAttackedSurface); // 接收后备缓冲显示表面的指针
4.要对后备缓冲进行修改,需要对后备缓冲显示表面进行加锁和解锁
创建后备缓冲界面的示例代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 LPDIRECTDRAWSURFACE7 lpddsprimary = NULL;
LPDIRECTDRAWSURFACE7 lpddsback = NULL;
DDSURFACEDESC2 ddsd;
DDRAW_INIT_STRUCT(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.dwBackBufferCount = 1;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
if(FAILED(lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL)))
{
return 0;
}
// 方法一:使用ddsd的ddsCaps字段
// ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
// if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback)))
// {
// return 0;
// }
// 方法二:使用一个新的DDSCAPS结构
DDSCAPS2 ddsCaps;
ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
if (FAILED(lpddsprimary->GetAttachedSurface(&ddsCaps, &lpddsback)))
{
return 0;
}
return 1;
3.切换链
和主表面相关联可以有多个备用表面,它们一起组成一个切换链。
1.页面切换
当创建了拥有后备缓冲表面的复杂表面之后,可以进行页面的切换,以实现双缓冲技术。
调用IDIRECTDRAWSURFACE7::FLIP()方法进行显示表面的切换。
标准的双缓冲页面切换的步骤是:
- 清除后备缓冲
- 将场景渲染到后备缓冲
- 用后备缓冲表面切换掉主表面
- 锁定在某个帧率
- 重复步骤 1
IDIRECTDRAWSURFACE7::FLIP()如果调用成功,将返回DD_OK,否则返回错误代码。
函数原型:1
2HRESULT Flip(LPDIRECTDRAWSURFACE7 lpDDSurfaceTargetOverride, // 高级参数。用来覆盖切换链,实现切换到另外一个表面,而不是切换到同主表面相关联的后备缓冲。设置为NULL
DWORD dwFlags); // 控制标记
垂直逆程值(默认为1) | 描述(默认1次垂直逆程后切换) |
---|---|
DDFLIP_INTERVAL2 | 2次垂直逆程(Vertical Retrace)后切换 |
DDFLIP_INTERVAL3 | 3次垂直逆程(Vertical Retrace)后切换 |
DDFLIP_INTERVAL4 | 4次垂直逆程(Vertical Retrace)后切换 |
仅仅当DDCAPS结构中设置了DDCAPS2_FLIPINTERVAL设置了才起作用
值 | 描述 |
---|---|
DDFLIP_NOVSYNC | DirectDraw执行物理切换时,尽量靠近下一条扫描线 |
DDFLIP_WAIT | 强迫硬件不出现问题时立即返回,而是等待知道页面切换能够进行位置 |
一般使用DDFLIP_WAIT
注意1:最后都是调用主显示表面的Flip()方法。因为主表面是 parent ,后备缓冲表面都是child,是挂在parent下的。
注意2:绘制后备表面的时候,也需要对表面进行加锁,使用完成之后解锁释放
2.示例代码
初始化代码
1 | // 全局变量 |
释放资源代码
- 释放资源:依次释放调色板、后备缓冲、主缓冲、directDraw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
int Game_Exit(void *params , int num_parms )
{
if(lpddpal)
{
lpddpal->Release();
lpddpal = NULL;
}
if(lpddsback)
{
lpddsback->Release();
lpddsback = NULL;
}
if (lpddsprimary)
{
lpddsprimary->Release();
lpddsprimary = NULL;
}
if(lpdd)
{
lpdd->Release();
lpdd = NULL;
}
return 1;
}
每帧调用代码
1 | // 每帧调用 |
page 221 待续…
4.其他
1.xxxcaps字段1
DDSCAPS ddsCaps; // DDSCAPS structure has all the general capabilities
这里的Caps是capabilities的简写。表示拥有哪些功能。
2.DDSCAPS_COMPLEX1
2
3
4
5
6
7
8
9/*
* Indicates a complex surface structure is being described. A
* complex surface structure results in the creation of more than
* one surface. The additional surfaces are attached to the root
* surface. The complex structure can only be destroyed by
* destroying the root.
*/
`
复杂表面将创建多个surface。附加的表面会附在根表面上。只有根表面销毁的时候,附加表面才会被销毁。
3.DDSCAPS_FLIP1
2
3
4
5
6
7
8
9
10/*
* Indicates that this surface is a part of a surface flipping structure.
* When it is passed to CreateSurface the DDSCAPS_FRONTBUFFER and
* DDSCAP_BACKBUFFER bits are not set. They are set by CreateSurface
* on the resulting creations. The dwBackBufferCount field in the
* DDSURFACEDESC structure must be set to at least 1 in order for
* the CreateSurface call to succeed. The DDSCAPS_COMPLEX capability
* must always be set with creating multiple surfaces through CreateSurface.
*/
和表面切换有关系。
创建多个表面的时候,必须设置这个标识。
并且,dwBackBufferCount字段必需被设置为大于等于1的数。
(有多个表面才能切换)