前面的内存填充都是利用memset()或memcpy()进行的。主要是用cpu进行的,有点慢。特别是当表面非线性时,就得一行一行的填充,就更慢了。
利用blitter我们可以直接填充或移动大块VRAM和DDraw表面,速度比较快。有两个函数如下:
IDIRECTDRAWSURFACE7::Blt() IDIRECTDRAWSURFACE7::BltFast()
Blt
原型如下:
HRESULT Blt(LPRECT lpDestRect, // 目标区域,NULL为整个表面 LPDIRECTDRAWSURFACE7 lpDDSrcSurface, // 源表面 LPRECT lpSrcRect, // 源区域 DWORD dwFlags, // 控制标志,见下表 LPDDBLTFX lpDDBltFx); // DDBLTFX结构,见下面
Blt()函数dwFlags参数的控制标志 | |
值 | 描述 |
DDBLT_COLORFILL | 使用DDBLTFX结构中的dwFillColor成员作为用来填充在目标表面上目标矩形区域的RGB颜色 |
DDBLT_DDFX | 使用DDBLTFX结构中的dwDDFX成员指出使用该blit的效果 |
DDBLT_DDROPS | 使用DDBLTFX结构中的dwDDROP成员 指出非win32 api部分的光标操作(ROP) |
DDBLT_DEPTHFILL | 使用DDBLTFX结构中的dwFillDepth成员作为 填充到目标尝试缓冲(z-buffer)表面的目标矩形框的深度值 |
DDBLT_KEYDESTOVERRIDE | 使用DDBLTFX结构中的ddckDestColorkey成员作为目标表面的色彩键 |
DDBLT_KEYSRCOVERRIDE | 使用DDBLTFX结构中的ddckSrcColorkey 成员作为源表面的色彩键 |
DDBLT_ROP | 在本次blit的ROP(光栅操作)中使用DDBLTFX结构中的dwROP成员。这些ROP和Win32 API中定义相同 |
DDBLT_ROTATIONANGLE | 使用DDBLTFX结构中的dwRotationAngle 成员作为应该表面的旋转角(以1/100度为单位 )。这只被硬件支持,HEL(硬件仿真层)不能进行这样的旋转。 |
DDBLT_KEYDEST | 使用和目标表面相关联的色彩关键字 |
DDBLT_KEYSRC | 使用和源表面相关联的色彩关键字 |
DDBLT_ASYNC | 依接收次序通过FIFO(先进先出)异步地执行转换,或FIFO硬件中没有足够的空间,则该调用失败,它速度快,但有点冒险,应当编写出错处理逻辑以合理地使用该标志 |
DDBLT_WAIT | 等待直到blit能被执行,即使blitter正忙也不返回错误信息DDERR_WASSTILLDRAWING |
最后一个参数是一个结构如下:
typedef struct _DDBLTFX { DWORD dwSize; // size of structure DWORD dwDDFX; // FX operations DWORD dwROP; // Win32 raster operations DWORD dwDDROP; // Raster operations new for DirectDraw DWORD dwRotationAngle; // Rotation angle for blt DWORD dwZBufferOpCode; // ZBuffer compares DWORD dwZBufferLow; // Low limit of Z buffer DWORD dwZBufferHigh; // High limit of Z buffer DWORD dwZBufferBaseDest; // Destination base value DWORD dwZDestConstBitDepth; // Bit depth used to specify Z constant for destination union { DWORD dwZDestConst; // Constant to use as Z buffer for dest LPDIRECTDRAWSURFACE lpDDSZBufferDest; // Surface to use as Z buffer for dest } DUMMYUNIONNAMEN( 1 ); DWORD dwZSrcConstBitDepth; // Bit depth used to specify Z constant for source union { DWORD dwZSrcConst; // Constant to use as Z buffer for src LPDIRECTDRAWSURFACE lpDDSZBufferSrc; // Surface to use as Z buffer for src } DUMMYUNIONNAMEN( 2 ); DWORD dwAlphaEdgeBlendBitDepth; // Bit depth used to specify constant for alpha edge blend DWORD dwAlphaEdgeBlend; // Alpha for edge blending DWORD dwReserved; DWORD dwAlphaDestConstBitDepth; // Bit depth used to specify alpha constant for destination union { DWORD dwAlphaDestConst; // Constant to use as Alpha Channel LPDIRECTDRAWSURFACE lpDDSAlphaDest; // Surface to use as Alpha Channel } DUMMYUNIONNAMEN( 3 ); DWORD dwAlphaSrcConstBitDepth; // Bit depth used to specify alpha constant for source union { DWORD dwAlphaSrcConst; // Constant to use as Alpha Channel LPDIRECTDRAWSURFACE lpDDSAlphaSrc; // Surface to use as Alpha Channel } DUMMYUNIONNAMEN( 4 ); union { DWORD dwFillColor; // color in RGB or Palettized DWORD dwFillDepth; // depth value for z-buffer DWORD dwFillPixel; // pixel value for RGBA or RGBZ LPDIRECTDRAWSURFACE lpDDSPattern; // Surface to use as pattern } DUMMYUNIONNAMEN( 5 ); DDCOLORKEY ddckDestColorkey; // DestColorkey override DDCOLORKEY ddckSrcColorkey; // SrcColorkey override } DDBLTFX;
粗体为常用的字段。
代码如下:源代码下载
int MainGame() { if (window_closed) return 0 ; if (KEYDOWN(VK_ESCAPE)) { ::PostMessage(main_window_handle, WM_CLOSE, 0 , 0 ); window_closed = 1 ; } DDBLTFX ddbltfx; DDRAW_INIT_STRUCT(ddbltfx); ddbltfx.dwFillColor = _RGB16BIT565(rand() % 256 , rand() % 256 , rand() % 256 ); // 随便产生一个矩形区域 RECT dest_rect; dest_rect.left = rand() % SCREEN_WIDTH; dest_rect.top = rand() % SCREEN_HEIGHT; dest_rect.right = rand() % SCREEN_WIDTH; dest_rect.bottom = rand() % SCREEN_HEIGHT; // blitter if (FAILED(lpddsprimary -> Blt( & dest_rect, // 目标区域,NULL为整个表面 NULL, // 源表面 NULL, // 源区域 DDBLT_COLORFILL | DDBLT_WAIT, // 控制标志 & ddbltfx))) // DDBLTFX结构 { return 0 ; } Sleep( 500 ); return 1 ; }
运行效果
从一个表面向另一个表面复制位图:源代码下载
int MainGame() { if (window_closed) return 0 ; if (KEYDOWN(VK_ESCAPE)) { PostMessage(main_window_handle,WM_CLOSE, 0 , 0 ); window_closed = 1 ; } // 随机生成一个源区域 RECT rectSrc; rectSrc.left = rand() % SCREEN_WIDTH; rectSrc.top = rand() % SCREEN_HEIGHT; rectSrc.right = rand() % SCREEN_WIDTH; rectSrc.bottom = rand() % SCREEN_HEIGHT; // 随机生成一个目标区域 RECT rectDst; rectDst.left = rand() % SCREEN_WIDTH; rectDst.top = rand() % SCREEN_HEIGHT; rectDst.right = rand() % SCREEN_WIDTH; rectDst.bottom = rand() % SCREEN_HEIGHT; // blitter if (FAILED(lpddsprimary -> Blt( & rectDst, lpddsback, & rectSrc, DDBLT_WAIT, NULL))) { return 0 ; } Sleep( 500 ); return 1 ; }
BltFast
原型如下:
HRESULT BltFast( DWORD dwX, // 目标表面x坐标 DWORD dwY, // 目标表面y坐标 LPDIRECTDRAWSURFACE7 lpDDSrcSurface, // 源表面 LPRECT lpSrcRect, // 源区域 DWORD dwTrans); // blitter操作类型
BltFast()的blitter操作控制标志 | |
值 | 描述 |
DDBLTFAST_SRCCOLORKEY | 指定一次使用源色彩的透明blit |
DDBLTFAST_DESTCOLORKEY | 指定一次使用目标色彩的透明blit |
DDBLTFAST_NOCOLORKEY | 指定一次不使用透明的标准blit。在一些硬件上速度 要快一些。在HEL上速度更快。 |
DDBLTFAST_WAIT | 当图形变换器正忙时,强制blitter等待,并且 不返回DDERR_WASSTILLDRAWING。直到该blit能被执行,或者发生严重错误时,BltFast()才返回。 |
何时用Blt,何时用BltFast
BltFast比Blt快一些,但是Blt带有裁剪器,而BltFast没有。
所以需要裁剪时用Blt,不需要要裁剪时用BltFast。
转载请保留下面链接
http://www.cnblogs.com/fangyukuan/archive/2011/06/08/2075907.html