Einzelnen Beitrag anzeigen

manfred42

Registriert seit: 23. Nov 2014
Ort: Leipzig
6 Beiträge
 
Delphi 7 Professional
 
#76

AW: Geht das noch schneller? - Bitmap-Verrechnung

  Alt 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]
nur mit einem Auge das hier verfolgt, aber ist folgender Blog nicht genau das Thema:

http://www.delphifeeds.com/go/f/1217...hiFeeds.com%29
Die haben hier ein VCL Beispiel und hinweise für die Firemonkey Umsetzung
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
  Mit Zitat antworten Zitat