现在的位置: 首页 > 综合 > 正文

使用blitter进行内存填充

2013年11月22日 ⁄ 综合 ⁄ 共 4619字 ⁄ 字号 评论关闭

前面的内存填充都是利用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 

抱歉!评论已关闭.