📄 asl_asm.cpp
字号:
//-----------------------------------------------------------------------------
//
// ____ Azure Star Game Engine 蓝星游戏引擎 ____
//
// Copyright (c) 2006, 蓝星工作室
// All rights reserved.
//
// 文件名称: asl_asm.cpp
// 摘 要: MMX加速的图像处理函数实现(被ASLBitmap, ASLFont类使用)
//
// 当前版本: 1.0
// 作 者: 汤 祺
// 创建日期: 2006-8-7
//
//-----------------------------------------------------------------------------
#include "asl_asm.h"
namespace ASL
{
//-----------------------------------------------------------------------------// 宏名: ALPHABLEND()// 功能: 执行4字Alpha混合, 本宏使用所有8个mmx寄存器// 输入: mm3 - 目的颜色// mm0 - 源颜色// mm7 - 33级alpha值(0~32)// 输出: mm0 - 结果颜色// 算法: alpha混合公式为: src * alpha + dst * (1 - alpha)// 变形为: (src - dst) * alpha + dst 其中alpha范围0~1// 对于33级alpha值, 计算前留出5位空白防止溢出, 计算完成后右移5位// 逐行注释:// movq mm4, mm3 ; g1 mm4 = dst3 dst3 dst1 dst0// movq mm5, mm3 ; b1 mm5 = dst3 dst3 dst1 dst0// movq mm6, mm3 ; r1 mm6 = dst3 dst3 dst1 dst0// psrlw mm3, 5 ; r2 mm3 = dst?: 00000rrrrrgggggg// pand mm4, mask_g ; g2 mm4 = dst?: 00000gggggg00000// pand mm5, mask_b ; b2 mm5 = dst?: 00000000000bbbbb// movq mm1, mm0 ; g3 mm1 = src3 src2 src1 src0// movq mm2, mm0 ; b3 mm2 = src3 src2 src1 src0// psrlw mm0, 5 ; r3 mm0 = src?: 00000rrrrrgggggg// pand mm1, mask_g ; g4 mm1 = src?: 00000gggggg00000// pand mm2, mask_b ; b4 mm2 = src?: 00000000000bbbbb// psubw mm0, mm3 ; r4 mm0 = src? - dst?// psubw mm1, mm4 ; g5 mm1 = src? - dst?// pmullw mm0, mm7 ; r5 mm0 = (src? - dst?) * alpha?// psubw mm2, mm5 ; b5 mm2 = src? - dst?// pmullw mm1, mm7 ; g6 mm1 = (src? - dst?) * alpha?// paddw mm0, mm6 ; r6 mm0 = (src? - dst?) * alpha? + dst?// pmullw mm2, mm7 ; b6 mm2 = (src? - dst?) * alpha?// psrlw mm1, 5 ; g7 mm1右移5位,使alpha值范围变为0~1// psrlw mm2, 5 ; b7 mm2右移5位,使alpha值范围变为0~1// paddw mm1, mm4 ; g8 mm1 = (src? - dst?) * alpha? + dst?// paddw mm2, mm5 ; b8 mm2 = (src? - dst?) * alpha? + dst?// pand mm0, mask_r ; r7 mm0 = result?: rrrrr00000000000// pand mm1, mask_g ; g9 mm1 = result?: 00000gggggg00000// pand mm2, mask_b ; b9 mm2 = result?: 00000ggggggbbbbb// por mm0, mm1 ; mm0 = result?: rrrrrgggggg00000// por mm0, mm2 ; mm0 = result?: rrrrrggggggbbbbb//-----------------------------------------------------------------------------
#define ALPHABLEND() \
__asm movq mm4, mm3 \ __asm movq mm5, mm3 \ __asm movq mm6, mm3 \ __asm psrlw mm3, 5 \ __asm pand mm4, mask_g \ __asm pand mm5, mask_b \ __asm movq mm1, mm0 \ __asm movq mm2, mm0 \ __asm psrlw mm0, 5 \ __asm pand mm1, mask_g \ __asm pand mm2, mask_b \ __asm psubw mm0, mm3 \ __asm psubw mm1, mm4 \ __asm pmullw mm0, mm7 \ __asm psubw mm2, mm5 \ __asm pmullw mm1, mm7 \ __asm paddw mm0, mm6 \ __asm pmullw mm2, mm7 \ __asm psrlw mm1, 5 \ __asm psrlw mm2, 5 \ __asm paddw mm1, mm4 \ __asm paddw mm2, mm5 \ __asm pand mm0, mask_r \ __asm pand mm1, mask_g \ __asm pand mm2, mask_b \ __asm por mm0, mm1 \ __asm por mm0, mm2
//-----------------------------------------------------------------------------
// 宏名: ADDITIVE()// 功能: 执行4字色饱和处理, 本宏使用寄存器: mm0, mm1, mm2, mm3, mm6, mm7// 输入: mm0 - 源颜色// mm2 - 目的颜色// mm6 - 绿掩码// mm7 - 红蓝掩码// 输出: mm0 - 结果颜色// 算法: // 逐行注释:
//-----------------------------------------------------------------------------
#define ADDITIVE() \
__asm movq mm1, mm0 \
__asm movq mm3, mm2 \
__asm pand mm0, mm7 \
__asm por mm2, mm6 \
__asm pand mm1, mm6 \
__asm por mm3, mm7 \
__asm paddusb mm0, mm2 \
__asm paddusw mm1, mm3 \
__asm pand mm0, mm1
// 全局常量定义
const __int64 mask_r = 0xF800F800F800F800; // 红色掩码
const __int64 mask_g = 0x07E007E007E007E0; // 绿色掩码
const __int64 mask_b = 0x001F001F001F001F; // 蓝色掩码
//-----------------------------------------------------------------------------
// 函数名: asmDrawPlain()
// 功 能: 普通位图绘制
// 参 数: [*pSrc] - 源位图数据
// [*pDst] - 目的位图数据
// [nWidth] - 待处理宽度
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
void asmDrawPlain(BYTE *pSrc, BYTE *pDst, int nWidth)
{
__asm
{
mov edi, pDst // edi = 目的指针
mov esi, pSrc // esi = 源指针
mov ecx, nWidth // ecx = 宽度
cld
align 4
_nextqword:
sub ecx, 4
jl _residual
movq mm0, [esi] // 从源地址取4象素数据
add esi, 8
movq [edi], mm0 // 直接写入目的地址
add edi, 8
jmp _nextqword
_residual:
add ecx, 4
jz _done
rep movsw
_done:
emms
}
}
//-----------------------------------------------------------------------------
// 函数名: asmDrawColorkey()
// 功 能: 普通位图绘制(带Colorkey处理)
// 参 数: [*pSrc] - 源位图数据
// [*pDst] - 目的位图数据
// [nWidth] - 待处理宽度
// [ck64] - 64位颜色键
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
void asmDrawColorkey(BYTE *pSrc, BYTE *pDst, int nWidth, __int64 ck64)
{
__asm
{
movq mm7, ck64 // 64位颜色键
mov edi, pDst // edi = 目的指针
mov esi, pSrc // esi = 源指针
mov ecx, nWidth // ecx = 宽度
movd edx, mm7 // 取32位颜色键, 用于剩余处理
cld
align 4
_nextqword:
sub ecx, 4
jl _residual
movq mm0, [esi] // 从源地址取4象素数据
add esi, 8
movq mm1, mm0 // 源数据给mm1
pcmpeqw mm0, mm7 // mm0为透明掩码
psubusw mm1, mm0 // 源数据透明点置0
pand mm0, [edi] // 目的数据非透明点置0
por mm0, mm1 // 相与得结果数据
movq [edi], mm0 // 结果送目的地址
add edi, 8
jmp _nextqword
_residual: // 剩余处理
add ecx, 4
jz _done
_draw16:
lodsw // 从源地址取1象素数据
cmp ax, dx // 将其与透明色比较
jz _nextone // 相等则跳过
mov [edi], ax // 不等则写入目的地址
_nextone:
add edi, 2
dec ecx
jnz _draw16
_done:
emms
}
}
//-----------------------------------------------------------------------------
// 函数名: asmAlphaPlain()
// 功 能: 半透明位图绘制(实际33级透明度)
// 参 数: [*pSrc] - 源位图数据
// [*pDst] - 目的位图数据
// [nWidth] - 待处理宽度
// [alpha] - 透明度 0-256
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
void asmAlphaPlain(BYTE *pSrc, BYTE *pDst, int nWidth, __int64 alpha)
{
__asm
{
mov edi, pDst // edi = 目的指针
mov esi, pSrc // esi = 源指针
mov ecx, nWidth // ecx = 宽度
movq mm7, alpha // 透明度
align 4
_nextqword:
sub ecx, 4
jl _residual
movq mm3, [edi] movq mm0, [esi] } // 调用Alpha混合宏 ALPHABLEND() __asm { add esi, 8 movq [edi], mm0 add edi, 8
jmp _nextqword
_residual:
add ecx, 4
jz _done // ecx=0, 已完成
test ecx, 2
jz _onein // ecx=1, 转单象素处理
movd mm3, [edi] // ecx!=1, 先拷贝2象素
movd mm0, [esi]
test ecx, 1
jz _startres // ecx=2, 开始剩余处理
mov dx, [edi+4] // ecx=3, 再拷贝一个象素
movd mm6, edx
mov dx, [esi+4]
psllq mm6, 32
por mm3, mm6
movd mm6, edx
psllq mm6, 32
por mm0, mm6
jmp _startres
_onein: // 单象素处理
mov dx, [edi]
movd mm3, edx
mov dx, [esi]
movd mm0, edx
_startres:
}
// 调用Alpha混合宏 ALPHABLEND()
__asm
{
test ecx, 2 jz _onepixel movd [edi], mm0 sub ecx, 2 jz _done psrlq mm0, 32 add edi, 4_onepixel: movd edx, mm0 mov [edi], dx
_done:
emms
}
}
//-----------------------------------------------------------------------------
// 函数名: asmAlphaColorkey()
// 功 能: 半透明位图绘制(带Colorkey处理)
// 参 数: [*pSrc] - 源位图数据
// [*pDst] - 目的位图数据
// [nWidth] - 待处理宽度
// [alpha] - 透明度 0-256
// [ck64] - 64位颜色键
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
void asmAlphaColorkey(BYTE *pSrc, BYTE *pDst, int nWidth, __int64 alpha,
__int64 ck64)
{
__asm
{
mov edi, pDst // edi = 目的指针
mov esi, pSrc // esi = 源指针
mov ecx, nWidth // ecx = 宽度
cld
align 4
_nextqword:
sub ecx, 4
jl _residual
movq mm1, ck64
movd eax, mm1
cmp [esi], eax
jnz _notequal
cmp [esi+4], eax
jnz _notequal
jmp _finishone
_notequal:
movq mm3, [edi] movq mm0, [esi] movq mm7, alpha pcmpeqw mm1, mm0 psubusw mm7, mm1 } // 调用Alpha混合宏 ALPHABLEND() __asm { movq [edi], mm0_finishone: add esi,8
add edi,8
jmp _nextqword
_residual:
add ecx, 4
jz _done // ecx=0, 已完成
test ecx, 2
jz _onein // ecx=1, 转单象素处理
movd mm3, [edi] // ecx!=1, 先拷贝2象素
movd mm0, [esi]
test ecx, 1
jz _startres // ecx=2, 开始剩余处理
mov dx, [edi+4] // ecx=3, 再拷贝一个象素
movd mm6, edx
mov dx, [esi+4]
psllq mm6, 32
por mm3, mm6
movd mm6, edx
psllq mm6, 32
por mm0, mm6
jmp _startres
_onein: // 单象素处理
mov dx, [edi]
movd mm3, edx
mov dx, [esi]
movd mm0, edx
_startres: movq mm1, ck64 movq mm7, alpha pcmpeqw mm1, mm0 psubusw mm7, mm1 } // 调用Alpha混合宏 ALPHABLEND() __asm { test ecx, 2
jz _oneout // ecx为1,则写入1个象素数据 movd [edi], mm0 // ecx为2或3,先写入2个象素 sub ecx, 2 jz _done // ecx为2,则结束 psrlq mm0, 32 // ecx为3,再写入1个象素 add edi, 4_oneout: movd edx, mm0 mov [edi], dx // 写入一个象素_done:
emms
}
}
//-----------------------------------------------------------------------------
// 函数名: asmFastPlain()
// 功 能: 快速半透明位图绘制(50%-50%)
// 参 数: [*pSrc] - 源位图数据
// [*pDst] - 目的位图数据
// [nWidth] - 待处理宽度
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
void asmFastPlain(BYTE *pSrc, BYTE *pDst, int nWidth)
{
static const __int64 mask = 0x7BEF7BEF7BEF7BEF;
// 算法: 将颜色值全部右移一位, 再与掩码做且运算, 则三色分量均除以2
// 源数据和目的数据均做上述操作, 再相加即实现半透明
__asm
{
mov edi, pDst // edi = 目的指针
mov esi, pSrc // esi = 源指针
movq mm7, mask // 64位掩码
mov ecx, nWidth // ecx = 宽度
movd edx, mm7 // 将32位掩码给edx, 用于剩余处理
cld
align 4
_nextqword:
sub ecx, 4
jl _residual
movq mm0, [esi] // 取源数据到mm0
movq mm1, [edi] // 取目的数据到mm1
psrlq mm0, 1 // src? = 0rrrrrggggggbbbb
psrlq mm1, 1 // dst? = 0rrrrrggggggbbbb
pand mm0, mm7 // src? = 0rrrr0ggggg0bbbb
pand mm1, mm7 // dst? = 0rrrr0ggggg0bbbb
paddw mm0, mm1 // result? = rrrrrggggggbbbbb
add esi, 8
movq [edi], mm0 // 写回目的地址
add edi, 8
jmp _nextqword
_residual: // 剩余处理
add ecx, 4
jz _done
_alpha16:
lodsw
mov bx, [edi];
shr bx, 1;
shr ax, 1;
and bx, dx;
and ax, dx;
add ax, bx;
stosw
dec ecx
jnz _alpha16
_done:
emms
}
}
//-----------------------------------------------------------------------------
// 函数名: asmFastColorkey()
// 功 能: 快速半透明位图绘制(带Colorkey处理)
// 参 数: [*pSrc] - 源位图数据
// [*pDst] - 目的位图数据
// [nWidth] - 待处理宽度
// [ck64] - 64位颜色键
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
void asmFastColorkey(BYTE *pSrc, BYTE *pDst, int nWidth, __int64 ck64)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -