Registriert seit: 23. Nov 2014
Ort: Leipzig
6 Beiträge
Delphi 7 Professional
|
AW: Geht das noch schneller? - Bitmap-Verrechnung
1. Jan 2015, 22:22
Hier mein letztes Angebot
Delphi-Quellcode:
unit UAlphaSSE;
{
SSE-Version von Harry Stahls
procedure Draw32BitToBitmap(const BitOben: TBitmap; BitUnten: TBitmap);
}
interface
uses
Winapi.Windows, Vcl.Graphics;
procedure Draw32BitToBitmapSSE( const BitOben: TBitmap; BitUnten: TBitmap);
implementation
procedure Draw32BitToBitmapSSE( const BitOben: TBitmap; BitUnten: TBitmap);
const
// bbggrr
RGBFF: array[0..1] of UInt64 = ($FF000000, 0);
// src bytes ......01......00 ......03......02
UMsk: array[0..1] of UInt64 = ($8080800180808000, $8080800380808002);
// res bytes .......... 8 4 0 ................
PMsk: array[0..1] of UInt64 = ($8080808080080400, $8080808080808080);
C255: array[0..3] of Single = (1/255, 1/255, 1/255, 0);
var
BmpO, BmpU: PRGBQuad;
N: Integer;
begin
N := BitOben.Height;
BmpO := BitOben.ScanLine[N - 1];
BmpU := BitUnten.ScanLine[N - 1];
N := N * BitOben.Width - 1; // size of bitmap - 1
asm
PUSH EBX
MOV EAX, BmpO
MOV EDX, BmpU
MOV ECX, N
// XMM7 free
LDDQU XMM6, UMsk
LDDQU XMM5, PMsk
LDDQU XMM4, C255
LDDQU XMM3, RGBFF
{$IFOPT O+}
DB $66,$90 // 2-Byte-NOP
{$ELSE}
DB $66,$0F,$1F,$44,0,0 // 6-Byte-NOP
{$ENDIF}
@Loop:
MOVD XMM0, [EAX+4*ECX] // XMM0 = | 0 |α|B|G|R
PEXTRW EBX, XMM0, 1 // EBX = α | B
SHR EBX, 8 // EBX = 0 | α
JZ @LoopEnd // test α ≡ RGBA_O.rgbReserved = 0 ?
PSHUFB XMM0, XMM6 // unpack to Int32
CVTDQ2PS XMM0, XMM0 // convert RGB_O to single FP
// SHUFPS XMM1, XMM0, $FF // !!! useless result
MOVAPD XMM1, XMM0 // copy RGB_O (necessary !)
SHUFPS XMM1, XMM1, $FF // XMM1 = α | α | α | α
MULPS XMM1, XMM4 // XMM1 = 0 | α/255 | α/255 | α/255
MOVD XMM2,[EDX+4*ECX] // XMM2 = | 0 |α|B|G|R
PSHUFB XMM2, XMM6 // unpack to Int32
CVTDQ2PS XMM2, XMM2 // convert RGB_U to single FP
SUBPS XMM0, XMM2 // RGB_O - RGB_U
MULPS XMM0, XMM1 // α * (RGB_O - RGB_U) / 255
ADDPS XMM0, XMM2 // α * (RGB_O - RGB_U) / 255 + RGB_U
CVTPS2DQ XMM0, XMM0 // convert FP to Int32 with rounding
PSHUFB XMM0, XMM5 // pack into TRGBQuad
POR XMM0, XMM3 // RGB_U.rgbReserved = $FF
MOVD [EDX+4*ECX],XMM0 // restore RGB_U
@LoopEnd:
SUB ECX, 1
JNS @Loop
POP EBX
end;
end;
end.
QUOTE=Harry Stahl;1281742] Nun ja, TParallel hatten wir hier ja auch schon. Der Link zeigt zwar die Parallel-For-Verwendung aber mit canvas.pixel, das ist ja so ziemlich das Langsamste, was man machen kann.[/QUOTE]
Mit anonymen Threads habe ich hier nichts machen können. Sie laufen schön langsam
nacheinander auf dem selben Prozessorkern. Könnte vor Wut das CPU-Gatget pulversisieren
Manfred
Manfred Zimmer
Geändert von mkinzler ( 1. Jan 2015 um 22:34 Uhr)
Grund: Delphi-Tag gefixt
|