内存堆分配

为了分配图面,DirectDraw 会按照驱动程序指定的顺序扫描显示内存堆。 堆在 VIDEOMEMORY 结构的数组中指定。 DirectDraw 按数组中 VIDEOMEMORY 结构的顺序访问堆。 VIDEOMEMORY 结构设置堆的某些指标,例如起始和结束内存地址、描述堆访问的标志,以及此堆中放置的图面限制使用类型。 DirectDraw 通过子分配和解除分配内存来管理堆,即在每个堆的管辖范围内创建和销毁图面。 物理限制决定了如何设置这些属性。

DirectDraw 的堆管理器在尝试分配内存以响应图面创建或还原时,会通过 VIDEOMEMORY 结构进行两次传递。 VIDEOMEMORY 结构的 ddsCaps 成员在第一次传递时通知 DirectDraw 堆中的内存不能用于什么。 例如,如果堆大到足以用于后台缓冲区,则可以通过设置 DDSCAPS_OFFSCREENPLAIN 标志,在第一次传递时排除子画面的分配。 这样一来,其他堆会填满屏幕外普通表面,同时保留后台缓冲区以便翻转页面。

可以将 VIDEOMEMORY 结构的 ddsCapsAlt 成员设置为允许第二次传递的子画面。 这样,有问题的堆可以允许子画面,但前提是无法在任何其他堆中创建子画面。 请勿在 ddsCapsAlt 中指定DDSCAPS_OFFSCREENPLAIN标志。 这允许以最佳方式使用堆,而不排除替代用途。

显示内存堆可以是线性或矩形,具体取决于 blitter 或现有显示驱动程序的需求。 VIDEOMEMORY 结构的 dwFlags 成员用于指定内存分配类型。 线性堆描述每个图面的间距可能不同的内存区域。 矩形堆描述每个图面的间距固定的内存区域。 如有必要,可以在同一显示卡中混合和匹配这些堆。 有关详细信息,请参阅 内存配置

图面的内存 间距(也称为步幅或偏移量)是添加到显示内存列中的字节数,以便在以下扫描行上达到同一列显示内存。 由于间距以字节而不是像素为单位,因此 640x480x8 图面的间距值与宽度和高度尺寸相同但像素格式不同的图面 (深度(以位) 为单位)。 此外,间距值有时反映运行时保留为缓存的额外字节,以及由于对齐要求而保留的额外字节。 因此,不能假设间距只是图面的宽度乘以每个像素的字节数。 相反,可视化宽度和间距之间的差异,如下图所示。

图示显示了图面内存中宽度和间距之间的差异。

如前所述,在确定音调值时,还必须考虑对齐要求。 例如,假设每个像素 (bpp) 图面的一个字节宽度为 97 像素。 此外,假设硬件或显示驱动程序需要 DWORD (4 个字节) 对齐。 如果运行时没有保留缓存字节,则音调为 100,这是高于 97 的下一个更高的数字,可均匀地被 4 整除。 以下计算确定此音调值:

pitch = bpp * width + ( 4 - ( bpp * width) % 4 )
// that is, pitch = 97 + (4 - 1) = 100