混合内存分配

如果硬件支持,线性和矩形内存堆可以以任何方式混合和匹配。 例如,如果前缓冲区具有固定的间距,则支持 DirectDraw 的驱动程序可以在其右侧分配矩形堆。

如下图所示,如果主图面下方仍有足够的内存,则可以将此区域制成可用于后台缓冲区的线性堆。

说明混合内存分配与线性堆和矩形堆的关系图。

上图显示了堆 1) 主图面下方 (线性内存块,以及 DirectDraw 在堆 2) 的主图面 (右侧回收的矩形内存块。

以下伪代码演示了如何为混合线性内存和矩形内存设置 VIDEOMEMORY 结构:

/*
 * video memory pool usage
 */
static VIDEOMEMORY vidMem [] =
{
  { VIDMEM_ISRECTANGULAR, 0x00000000, 0x00000000,
            { 0 }, { 0 } },
  { VIDMEM_ISLINEAR, 0x00000000, 0x00000000,
            { 0 }, { 0 } },
};

在此实例中可以分配显示内存的两个区域。 主图面概念右侧的区域必然是矩形的,由VIDMEM_ISRECTANGULAR标志指示。 从概念上讲,主图面下方的区域可以是线性的,并由VIDMEM_ISLINEAR标志指示。

以下伪代码演示如何设置线性和矩形内存堆的混合:

/*
 * video memory pool information
 */

/* set up the pointer to the first available video memory after the primary surface */
    ddHALInfo.vmiData.pvmList       = vidMem;

/* how many heaps are there   
     ddHALInfo.vmiData.dwNumHeaps       = 2;

/* The linear piece:  */


/*
 * remainder of screen memory
 */

    VideoHeapBase = ddHALInfo.vmiData.fpPrimary + dwPrimarySurfaceSize
                    + dwCacheSize;
    VideoHeapEnd = VideoHeapBase + dwDDOffScreenSize - 1;
    vidMem[0].fpStart = VideoHeapBase;
    vidMem[0].fpEnd = VideoHeapEnd;

/* The rectangular piece:  */

/* set up the pointer to the next available video memory */
    ddHALInfo.vmiData.pvmList     = vidMem[1];

/*
 *  Compute the Pitch here ...
 */

    vidMem[1].fpStart  = ddHALInfo.vmiData.fpPrimary + 
                        dwPrimarySurfaceWidth;
    vidMem[1].dwWidth  = dwPitch - dwPrimarySurfaceWidth;
    vidMem[1].dwHeight = dwPrimarySurfaceHeight;
    vidMem[1].ddsCaps.dwCaps = 0;  // surface has no use restrictions

通过确定主图面下方暂存区域的起点和终点来设置线性 VIDEOMEMORY 结构的 fpStartfpEnd 成员 (vidMem[0]) 来设置线性内存堆。 矩形部分是使用起点设置的,该起点由矩形 VIDEOMEMORY 结构的 fpStart 成员指示 (vidMem[1]) 、宽度(由 dwWidth 成员指示)和主图面的 dwHeight 成员指示的高度。 必须先计算 dwPitch 成员) (间距,然后才能设置矩形部分。 这与上一个矩形示例中的相同,但在此示例中,音调是 VIDEOMEMORY 结构的第二个元素,而不是第一个元素。 每个新堆都需要新的 VIDEOMEMORY 结构。

在某些情况下,翻转寄存器只能处理 256 KB 边界。 在这些情况下,小堆可能会占用缓存底部与后台缓冲区开始之间的空间,从而允许后台缓冲区在 256 KB 边界上开始。 此示例未显示,但可以通过将另一个元素添加到 VIDEOMEMORY 结构,并将起始点设置在 256 KB 边界之前的缓存和终点之外来实现。 应使用DDSCAPS_BACKBUFFER标记此类堆,以便在堆管理器查找后台缓冲区时可以跳过它。 此后台缓冲区堆 (对齐) 还将标有DDSCAPS_OFFSCREENPLAIN,以阻止子画面和纹理使用此堆,直到其他堆中没有其他内存可用于屏幕外普通表面。