一、创建Primary Surface
Primary Surface是当前可视的设备表面,它通过DDSAPS_PRIMARYSURFACE属性来标识。对于每一个DirectDraw对象,你只能拥有一个Primary Surface。
创建Primary Surface时要注意,尺寸和像素格式都隐性地匹配了当前的显示模式,所以,这里就不需要你去设置这些了;如果你一定要设置的话,程序将创建失败并返回DDERR_INVALIDPARAMS,即使你提供的信息与当前的显示模式相匹配。
下面这段代码展示了当创建primary surface时如何填充相应的 DDSURFACEDESC结构体成员的:
1 DDSURFACEDESC ddsd; 2 ddsd.dwSize = sizeof(ddsd); //便于后续此结构体的扩展 3 4 // Tell DirectDraw which members are valid. 5 ddsd.dwFlags = DDSD_CAPS; 6 7 // Request a primary surface. 8 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
当你创建primary surface后,你就可以通过method( IDirectDrawSurface::GetSurfaceDesc)来获取此主surface的尺寸和像素格式等信息。
这里有必要说一下这个结构体DDSUFACEDESC,它呢是用来描述一张surface属性信息的,为什么首先要填充此结构体的大小呢?因为后续可能此结构体会增加成员也说不定,便于成员的扩充;而配置下面的那个dwFlags成员用来表明现在起作用的是那些成员用的。
二、创建离屏表面(Off-Screen Surface)
它就常用来缓存那些稍后将要位传到primary surface或者back buffer上面的bitmap图片用的。创建这种表面就需要明确的声明它的尺寸,这里一定要记得先设置成员dwFlags包含到DDSD_WIDTH 和 DDSD_HEIGHT,然后再相应的设置成员dwWidth 和 dwHeight .
默认DirectDraw创建的表面都用的是显存,除非不合适,才会使用系统内存,但是我们也可指明,这就要设置成员dwCaps为DDSCAPS_SYSTEMMEMORY 和DDSCAPS_VIDEOMEMORY二者之一;
1 //创建前的准备工作 2 DDSURFACEDESC ddsd; 3 ddsd.dwSize = sizeof(ddsd); 4 5 // Tell DirectDraw which members are valid. 6 ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH; 7 8 // Request a simple off-screen surface, sized 9 // 100 by 100 pixels. 10 // 11 // (This assumes that the off-screen surface that is about 12 // to be created will match the pixel format of the 13 // primary surface.)它这里的假设分辨率是和primary surface的像素格式相匹配的 14 ddsd.dwHeight = 100; 15 ddsd.dwWidth = 100;
也可以不相匹配,但是有一个缺点:你使用系统内存时将被限制;
1 //这里就是在一个显示模式不是8bit每像素的设备上创建一个8-bit调色板 2 //表面所要做的准备工作 3 memset(&ddsd, 0, sizeof(ddsd)); 4 ddsd.dwSize = sizeof(ddsd); 5 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; 6 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY; 7 ddsd.dwHeight = 100; 8 ddsd.dwWidth = 100; 9 ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); 10 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8; 11 12 // Set the bit depth for an 8-bit surface, but DO NOT 13 // specify any RGB mask values. The masks must be zero 14 // for a palettized surface. 15 ddsd.ddpfPixelFormat.dwRGBBitCount = 8;
三、复合表面和翻转链(Complex Surfaces and Flipping Chains)
何为复合表面?通过单一调用CreateSurface创建的一系列表面就是复合表面。怎么说呢,举个例吧
1 int i = 0; 2 do { 3 ddsd.ddpfPixelFormat = ddpfOverlayFormats[i]; 4 hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSOverlay, NULL); 5 } while (hRet != DD_OK && (++i < PF_TABLE_SIZE));
上面呢就是基于不用像素格式创建了多个surface的实例,这样创建出来的就是complex surfaces;
而且使用CreateSurface时一旦指定DDSCAPS_FLIP,除了你明确指定,不然DirectDraw会隐式创建一到多个表面;
你可以把复合表面就当作一张表面来处理,所以处理起来也没什么特别之处;
那现在来说到翻转链,复合表面就是被用于翻转链的。通常一个primary surface和一到多个back buffers来组成一条翻转链。而且有DDSCAPS_FLIP标识创建出来的表面就表明了它也是翻转链的一组成部分;
1 //这里是创建一个主表面翻转链时先要配置的参数 2 DDSURFACEDESC ddsd; 3 ddsd.dwSize = sizeof(ddsd); 4 5 // Tell DirectDraw which members are valid. 6 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; 7 8 // Request a primary surface with a single 9 // back buffer 10 ddsd.ddsCaps.dwCaps = DDSCAPS_FLIP | 11 DDSCAPS_PRIMARYSURFACE; 12 ddsd.dwBackBufferCount = 1;
创建成功后就可以翻转了(primary surface和back buffer之间):
1 hRet = g_pDDSPrimary->Flip(NULL, 0);
如果上面的ddsd.dwBackBufferCount = 2;那么每调用一次上面的flip,就在这三个surface之间循环,这就是a triple-buffered flipping environment。下面要讲到。。。
四、Flipping Surfaces
这个就更有意思了。。。