使用blitter进行内存填充
前面的内存填充都是利用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。
2011.06.08 方煜宽
转载请保留下面链接
http://www.cnblogs.com/fangyukuan/archive/2011/06/08/2075907.html