fangyukuan

永无止境的追求...追求卓越!!!

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  94 随笔 :: 0 文章 :: 125 评论 :: 0 引用

使用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 


posted on 2011-06-09 00:04 fangyukuan 阅读(...) 评论(...) 编辑 收藏