📄 gr32_blend.pas
字号:
db $0F,$67,$C8 /// PACKUSWB MM1,MM0
db $0F,$7E,$C8 /// MOVD EAX,MM1
end;
procedure M_CombineMem(F: TColor32; var B: TColor32; W: TColor32);
asm
// EAX - Color X
// [EDX] - Color Y
// ECX - Weight of X [0..255]
// Result := W * (X - Y) + Y
JCXZ @1
CMP ECX,$FF
JZ @2
db $0F,$6E,$C8 /// MOVD MM1,EAX
db $0F,$EF,$C0 /// PXOR MM0,MM0
SHL ECX,3
db $0F,$6E,$12 /// MOVD MM2,[EDX]
db $0F,$60,$C8 /// PUNPCKLBW MM1,MM0
db $0F,$60,$D0 /// PUNPCKLBW MM2,MM0
ADD ECX,alpha_ptr
db $0F,$F9,$CA /// PSUBW MM1,MM2
db $0F,$D5,$09 /// PMULLW MM1,[ECX]
db $0F,$71,$F2,$08 /// PSLLW MM2,8
MOV ECX,bias_ptr
db $0F,$FD,$11 /// PADDW MM2,[ECX]
db $0F,$FD,$CA /// PADDW MM1,MM2
db $0F,$71,$D1,$08 /// PSRLW MM1,8
db $0F,$67,$C8 /// PACKUSWB MM1,MM0
db $0F,$7E,$0A /// MOVD [EDX],MM1
@1: RET
@2: MOV [EDX],EAX
end;
function M_BlendReg(F, B: TColor32): TColor32;
asm
// blend foregrownd color (F) to a background color (B),
// using alpha channel value of F
// EAX <- F
// EDX <- B
// Result := Fa * (Frgb - Brgb) + Brgb
db $0F,$6E,$C0 /// MOVD MM0,EAX
db $0F,$EF,$DB /// PXOR MM3,MM3
db $0F,$6E,$D2 /// MOVD MM2,EDX
db $0F,$60,$C3 /// PUNPCKLBW MM0,MM3
MOV ECX,bias_ptr
db $0F,$60,$D3 /// PUNPCKLBW MM2,MM3
db $0F,$6F,$C8 /// MOVQ MM1,MM0
db $0F,$69,$C9 /// PUNPCKHWD MM1,MM1
db $0F,$F9,$C2 /// PSUBW MM0,MM2
db $0F,$6A,$C9 /// PUNPCKHDQ MM1,MM1
db $0F,$71,$F2,$08 /// PSLLW MM2,8
db $0F,$D5,$C1 /// PMULLW MM0,MM1
db $0F,$FD,$11 /// PADDW MM2,[ECX]
db $0F,$FD,$D0 /// PADDW MM2,MM0
db $0F,$71,$D2,$08 /// PSRLW MM2,8
db $0F,$67,$D3 /// PACKUSWB MM2,MM3
db $0F,$7E,$D0 /// MOVD EAX,MM2
end;
procedure M_BlendMem(F: TColor32; var B: TColor32);
asm
// EAX - Color X
// [EDX] - Color Y
// Result := W * (X - Y) + Y
TEST EAX,$FF000000
JZ @1
CMP EAX,$FF000000
JNC @2
db $0F,$EF,$DB /// PXOR MM3,MM3
db $0F,$6E,$C0 /// MOVD MM0,EAX
db $0F,$6E,$12 /// MOVD MM2,[EDX]
db $0F,$60,$C3 /// PUNPCKLBW MM0,MM3
MOV ECX,bias_ptr
db $0F,$60,$D3 /// PUNPCKLBW MM2,MM3
db $0F,$6F,$C8 /// MOVQ MM1,MM0
db $0F,$69,$C9 /// PUNPCKHWD MM1,MM1
db $0F,$F9,$C2 /// PSUBW MM0,MM2
db $0F,$6A,$C9 /// PUNPCKHDQ MM1,MM1
db $0F,$71,$F2,$08 /// PSLLW MM2,8
db $0F,$D5,$C1 /// PMULLW MM0,MM1
db $0F,$FD,$11 /// PADDW MM2,[ECX]
db $0F,$FD,$D0 /// PADDW MM2,MM0
db $0F,$71,$D2,$08 /// PSRLW MM2,8
db $0F,$67,$D3 /// PACKUSWB MM2,MM3
db $0F,$7E,$12 /// MOVD [EDX],MM2
@1: RET
@2: MOV [EDX],EAX
end;
function M_BlendRegEx(F, B, M: TColor32): TColor32;
asm
// blend foregrownd color (F) to a background color (B),
// using alpha channel value of F
// EAX <- F
// EDX <- B
// ECX <- M
// Result := M * Fa * (Frgb - Brgb) + Brgb
PUSH EBX
MOV EBX,EAX
SHR EBX,24
INC ECX // 255:256 range bias
IMUL ECX,EBX
SHR ECX,8
JZ @1
db $0F,$EF,$C0 /// PXOR MM0,MM0
db $0F,$6E,$C8 /// MOVD MM1,EAX
SHL ECX,3
db $0F,$6E,$D2 /// MOVD MM2,EDX
db $0F,$60,$C8 /// PUNPCKLBW MM1,MM0
db $0F,$60,$D0 /// PUNPCKLBW MM2,MM0
ADD ECX,alpha_ptr
db $0F,$F9,$CA /// PSUBW MM1,MM2
db $0F,$D5,$09 /// PMULLW MM1,[ECX]
db $0F,$71,$F2,$08 /// PSLLW MM2,8
MOV ECX,bias_ptr
db $0F,$FD,$11 /// PADDW MM2,[ECX]
db $0F,$FD,$CA /// PADDW MM1,MM2
db $0F,$71,$D1,$08 /// PSRLW MM1,8
db $0F,$67,$C8 /// PACKUSWB MM1,MM0
db $0F,$7E,$C8 /// MOVD EAX,MM1
POP EBX
RET
@1: MOV EAX,EDX
POP EBX
end;
procedure M_BlendMemEx(F: TColor32; var B:TColor32; M: TColor32);
asm
// blend foregrownd color (F) to a background color (B),
// using alpha channel value of F
// EAX <- F
// [EDX] <- B
// ECX <- M
// Result := M * Fa * (Frgb - Brgb) + Brgb
TEST EAX,$FF000000
JZ @2
PUSH EBX
MOV EBX,EAX
SHR EBX,24
INC ECX // 255:256 range bias
IMUL ECX,EBX
SHR ECX,8
JZ @1
db $0F,$EF,$C0 /// PXOR MM0,MM0
db $0F,$6E,$C8 /// MOVD MM1,EAX
SHL ECX,3
db $0F,$6E,$12 /// MOVD MM2,[EDX]
db $0F,$60,$C8 /// PUNPCKLBW MM1,MM0
db $0F,$60,$D0 /// PUNPCKLBW MM2,MM0
ADD ECX,alpha_ptr
db $0F,$F9,$CA /// PSUBW MM1,MM2
db $0F,$D5,$09 /// PMULLW MM1,[ECX]
db $0F,$71,$F2,$08 /// PSLLW MM2,8
MOV ECX,bias_ptr
db $0F,$FD,$11 /// PADDW MM2,[ECX]
db $0F,$FD,$CA /// PADDW MM1,MM2
db $0F,$71,$D1,$08 /// PSRLW MM1,8
db $0F,$67,$C8 /// PACKUSWB MM1,MM0
db $0F,$7E,$0A /// MOVD [EDX],MM1
@1: POP EBX
@2:
end;
procedure M_BlendLine(Src, Dst: PColor32; Count: Integer);
asm
// EAX <- Src
// EDX <- Dst
// ECX <- Count
// test the counter for zero or negativity
TEST ECX,ECX
JS @4
PUSH ESI
PUSH EDI
MOV ESI,EAX // ESI <- Src
MOV EDI,EDX // EDI <- Dst
// loop start
@1: MOV EAX,[ESI]
TEST EAX,$FF000000
JZ @3 // complete transparency, proceed to next point
CMP EAX,$FF000000
JNC @2 // opaque pixel, copy without blending
// blend
db $0F,$6E,$C0 /// MOVD MM0,EAX
db $0F,$EF,$DB /// PXOR MM3,MM3
db $0F,$6E,$17 /// MOVD MM2,[EDI]
db $0F,$60,$C3 /// PUNPCKLBW MM0,MM3
MOV EAX,bias_ptr
db $0F,$60,$D3 /// PUNPCKLBW MM2,MM3
db $0F,$6F,$C8 /// MOVQ MM1,MM0
db $0F,$69,$C9 /// PUNPCKHWD MM1,MM1
db $0F,$F9,$C2 /// PSUBW MM0,MM2
db $0F,$6A,$C9 /// PUNPCKHDQ MM1,MM1
db $0F,$71,$F2,$08 /// PSLLW MM2,8
db $0F,$D5,$C1 /// PMULLW MM0,MM1
db $0F,$FD,$10 /// PADDW MM2,[EAX]
db $0F,$FD,$D0 /// PADDW MM2,MM0
db $0F,$71,$D2,$08 /// PSRLW MM2,8
db $0F,$67,$D3 /// PACKUSWB MM2,MM3
db $0F,$7E,$D0 /// MOVD EAX,MM2
@2: MOV [EDI],EAX
@3: ADD ESI,4
ADD EDI,4
// loop end
DEC ECX
JNZ @1
POP EDI
POP ESI
@4: RET
end;
procedure M_BlendLineEx(Src, Dst: PColor32; Count: Integer; M: TColor32);
asm
// EAX <- Src
// EDX <- Dst
// ECX <- Count
// test the counter for zero or negativity
TEST ECX,ECX
JS @4
PUSH ESI
PUSH EDI
PUSH EBX
MOV ESI,EAX // ESI <- Src
MOV EDI,EDX // EDI <- Dst
MOV EDX,M // EDX <- Master Alpha
// loop start
@1: MOV EAX,[ESI]
TEST EAX,$FF000000
JZ @3 // complete transparency, proceed to next point
MOV EBX,EAX
SHR EBX,24
INC EBX // 255:256 range bias
IMUL EBX,EDX
SHR EBX,8
JZ @3 // complete transparency, proceed to next point
// blend
db $0F,$EF,$C0 /// PXOR MM0,MM0
db $0F,$6E,$C8 /// MOVD MM1,EAX
SHL EBX,3
db $0F,$6E,$17 /// MOVD MM2,[EDI]
db $0F,$60,$C8 /// PUNPCKLBW MM1,MM0
db $0F,$60,$D0 /// PUNPCKLBW MM2,MM0
ADD EBX,alpha_ptr
db $0F,$F9,$CA /// PSUBW MM1,MM2
db $0F,$D5,$0B /// PMULLW MM1,[EBX]
db $0F,$71,$F2,$08 /// PSLLW MM2,8
MOV EBX,bias_ptr
db $0F,$FD,$13 /// PADDW MM2,[EBX]
db $0F,$FD,$CA /// PADDW MM1,MM2
db $0F,$71,$D1,$08 /// PSRLW MM1,8
db $0F,$67,$C8 /// PACKUSWB MM1,MM0
db $0F,$7E,$C8 /// MOVD EAX,MM1
@2: MOV [EDI],EAX
@3: ADD ESI,4
ADD EDI,4
// loop end
DEC ECX
JNZ @1
POP EBX
POP EDI
POP ESI
@4:
end;
procedure M_CombineLine(Src, Dst: PColor32; Count: Integer; W: TColor32);
asm
// EAX <- Src
// EDX <- Dst
// ECX <- Count
// Result := W * (X - Y) + Y
TEST ECX,ECX
JS @3
PUSH EBX
MOV EBX,W
TEST EBX,EBX
JZ @2 // weight is zero
CMP EDX,$FF
JZ @4 // weight = 255 => copy src to dst
SHL EBX,3
ADD EBX,alpha_ptr
db $0F,$6F,$1B /// MOVQ MM3,[EBX]
MOV EBX,bias_ptr
db $0F,$6F,$23 /// MOVQ MM4,[EBX]
// loop start
@1: db $0F,$6E,$08 /// MOVD MM1,[EAX]
db $0F,$EF,$C0 /// PXOR MM0,MM0
db $0F,$6E,$12 /// MOVD MM2,[EDX]
db $0F,$60,$C8 /// PUNPCKLBW MM1,MM0
db $0F,$60,$D0 /// PUNPCKLBW MM2,MM0
db $0F,$F9,$CA /// PSUBW MM1,MM2
db $0F,$D5,$CB /// PMULLW MM1,MM3
db $0F,$71,$F2,$08 /// PSLLW MM2,8
db $0F,$FD,$D4 /// PADDW MM2,MM4
db $0F,$FD,$CA /// PADDW MM1,MM2
db $0F,$71,$D1,$08 /// PSRLW MM1,8
db $0F,$67,$C8 /// PACKUSWB MM1,MM0
db $0F,$7E,$0A /// MOVD [EDX],MM1
ADD EAX,4
ADD EDX,4
DEC ECX
JNZ @1
@2: POP EBX
POP EBP
@3: RET $0004
@4: CALL GR32_LowLevel.MoveLongword
POP EBX
end;
{ Non-MMX Color algebra versions }
function _ColorAdd(C1, C2: TColor32): TColor32;
var
r1, g1, b1, a1: Integer;
r2, g2, b2, a2: Integer;
begin
a1 := C1 shr 24;
r1 := C1 and $00FF0000;
g1 := C1 and $0000FF00;
b1 := C1 and $000000FF;
a2 := C2 shr 24;
r2 := C2 and $00FF0000;
g2 := C2 and $0000FF00;
b2 := C2 and $000000FF;
a1 := a1 + a2;
r1 := r1 + r2;
g1 := g1 + g2;
b1 := b1 + b2;
if a1 > $FF then a1 := $FF;
if r1 > $FF0000 then r1 := $FF0000;
if g1 > $FF00 then g1 := $FF00;
if b1 > $FF then b1 := $FF;
Result := a1 shl 24 + r1 + g1 + b1;
end;
function _ColorSub(C1, C2: TColor32): TColor32;
var
r1, g1, b1, a1: Integer;
r2, g2, b2, a2: Integer;
begin
a1 := C1 shr 24;
r1 := C1 and $00FF0000;
g1 := C1 and $0000FF00;
b1 := C1 and $000000FF;
r1 := r1 shr 16;
g1 := g1 shr 8;
a2 := C2 shr 24;
r2 := C2 and $00FF0000;
g2 := C2 and $0000FF00;
b2 := C2 and $000000FF;
r2 := r2 shr 16;
g2 := g2 shr 8;
a1 := a1 - a2;
r1 := r1 - r2;
g1 := g1 - g2;
b1 := b1 - b2;
if a1 < 0 then a1 := 0;
if r1 < 0 then r1 := 0;
if g1 < 0 then g1 := 0;
if b1 < 0 then b1 := 0;
Result := a1 shl 24 + r1 shl 16 + g1 shl 8 + b1;
end;
function _ColorDiv(C1, C2: TColor32): TColor32;
var
r1, g1, b1, a1: Integer;
r2, g2, b2, a2: Integer;
begin
a1 := C1 shr 24;
r1 := (C1 and $00FF0000) shr 16;
g1 := (C1 and $0000FF00) shr 8;
b1 := C1 and $000000FF;
a2 := C2 shr 24;
r2 := (C2 and $00FF0000) shr 16;
g2 := (C2 and $0000FF00) shr 8;
b2 := C2 and $000000FF;
if a1 = 0 then a1:=$FF
else a1 := (a2 shl 8) div a1;
if r1 = 0 then r1:=$FF
else r1 := (r2 shl 8) div r1;
if g1 = 0 then g1:=$FF
else g1 := (g2 shl 8) div g1;
if b1 = 0 then b1:=$FF
else b1 := (b2 shl 8) div b1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -