Ignore:
Timestamp:
Apr 17, 2019, 10:42:18 AM (5 years ago)
Author:
chronos
Message:
  • Modified: Updated Graphics32 library.
Location:
GraphicTest/Packages/Graphics32
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • GraphicTest/Packages/Graphics32

    • Property svn:ignore set to
      lib
  • GraphicTest/Packages/Graphics32/GR32_Blend.pas

    r450 r522  
    4141 *      - 2004/08/25 - ColorDiv
    4242 *
     43 *  Christian-W. Budde
     44 *      - 2019/04/01 - Refactoring
     45 *
    4346 * ***** END LICENSE BLOCK ***** *)
    4447
     
    4851
    4952uses
    50   GR32, GR32_System, GR32_Bindings, SysUtils;
     53  GR32, GR32_Bindings, SysUtils;
    5154
    5255var
     
    5760  TBlendReg    = function(F, B: TColor32): TColor32;
    5861  TBlendMem    = procedure(F: TColor32; var B: TColor32);
     62  TBlendMems   = procedure(F: TColor32; B: PColor32; Count: Integer);
    5963  TBlendRegEx  = function(F, B, M: TColor32): TColor32;
    6064  TBlendMemEx  = procedure(F: TColor32; var B: TColor32; M: TColor32);
     65  TBlendRegRGB = function(F, B, W: TColor32): TColor32;
     66  TBlendMemRGB = procedure(F: TColor32; var B: TColor32; W: TColor32);
     67{$IFDEF TEST_BLENDMEMRGB128SSE4}
     68  TBlendMemRGB128 = procedure(F: TColor32; var B: TColor32; W: UInt64);
     69{$ENDIF}
    6170  TBlendLine   = procedure(Src, Dst: PColor32; Count: Integer);
    6271  TBlendLineEx = procedure(Src, Dst: PColor32; Count: Integer; M: TColor32);
     72  TBlendLine1  = procedure(Src: TColor32; Dst: PColor32; Count: Integer);
    6373  TCombineReg  = function(X, Y, W: TColor32): TColor32;
    6474  TCombineMem  = procedure(X: TColor32; var Y: TColor32; W: TColor32);
     
    7484  BlendReg: TBlendReg;
    7585  BlendMem: TBlendMem;
     86  BlendMems: TBlendMems;
    7687
    7788  BlendRegEx: TBlendRegEx;
    7889  BlendMemEx: TBlendMemEx;
    7990
     91  BlendRegRGB: TBlendRegRGB;
     92  BlendMemRGB: TBlendMemRGB;
     93{$IFDEF TEST_BLENDMEMRGB128SSE4}
     94  BlendMemRGB128: TBlendMemRGB128;
     95{$ENDIF}
     96
    8097  BlendLine: TBlendLine;
    8198  BlendLineEx: TBlendLineEx;
     99  BlendLine1: TBlendLine1;
    82100
    83101  CombineReg: TCombineReg;
     
    93111  MergeLine: TBlendLine;
    94112  MergeLineEx: TBlendLineEx;
     113  MergeLine1: TBlendLine1;
    95114
    96115{ Color algebra functions }
     
    105124  ColorExclusion: TBlendReg;
    106125  ColorScale: TBlendReg;
     126  ColorScreen: TBlendReg;
     127  ColorDodge: TBlendReg;
     128  ColorBurn: TBlendReg;
     129
     130{ Blended color algebra functions }
     131  BlendColorAdd: TBlendReg;
     132  BlendColorModulate: TBlendReg;
    107133
    108134{ Special LUT pointers }
     
    119145{ Access to alpha composite functions corresponding to a combine mode }
    120146
     147type
     148  PBlendReg = ^TBlendReg;
     149  PBlendMem = ^TBlendMem;
     150  PBlendRegEx = ^TBlendRegEx;
     151  PBlendMemEx = ^TBlendMemEx;
     152  PBlendLine = ^TBlendLine;
     153  PBlendLineEx = ^TBlendLineEx;
     154
     155  TBlendRegCombineModeArray = array[TCombineMode] of PBlendReg;
     156  TBlendMemCombineModeArray = array[TCombineMode] of PBlendMem;
     157  TBlendRegExCombineModeArray = array[TCombineMode] of PBlendRegEx;
     158  TBlendMemExCombineModeArray = array[TCombineMode] of PBlendMemEx;
     159  TBlendLineCombineModeArray = array[TCombineMode] of PBlendLine;
     160  TBlendLineExCombineModeArray = array[TCombineMode] of PBlendLineEx;
     161
    121162const
    122   BLEND_REG: array[TCombineMode] of ^TBlendReg = ((@@BlendReg),(@@MergeReg));
    123   BLEND_MEM: array[TCombineMode] of ^TBlendMem = ((@@BlendMem),(@@MergeMem));
    124   BLEND_REG_EX: array[TCombineMode] of ^TBlendRegEx = ((@@BlendRegEx),(@@MergeRegEx));
    125   BLEND_MEM_EX: array[TCombineMode] of ^TBlendMemEx = ((@@BlendMemEx),(@@MergeMemEx));
    126   BLEND_LINE: array[TCombineMode] of ^TBlendLine = ((@@BlendLine),(@@MergeLine));
    127   BLEND_LINE_EX: array[TCombineMode] of ^TBlendLineEx = ((@@BlendLineEx),(@@MergeLineEx));
     163  BLEND_REG: TBlendRegCombineModeArray = ((@@BlendReg),(@@MergeReg));
     164  BLEND_MEM: TBlendMemCombineModeArray = ((@@BlendMem),(@@MergeMem));
     165  BLEND_REG_EX: TBlendRegExCombineModeArray = ((@@BlendRegEx),(@@MergeRegEx));
     166  BLEND_MEM_EX: TBlendMemExCombineModeArray = ((@@BlendMemEx),(@@MergeMemEx));
     167  BLEND_LINE: TBlendLineCombineModeArray = ((@@BlendLine),(@@MergeLine));
     168  BLEND_LINE_EX: TBlendLineExCombineModeArray = ((@@BlendLineEx),(@@MergeLineEx));
    128169
    129170var
     
    134175{$ENDIF}
    135176
    136 implementation
    137 
    138 {$IFDEF TARGET_x86}
    139 uses GR32_LowLevel;
    140 {$ENDIF}
    141 
    142177var
    143178  RcTable: array [Byte, Byte] of Byte;
    144179  DivTable: array [Byte, Byte] of Byte;
     180
     181implementation
     182
     183uses
     184  GR32_LowLevel,
     185{$IFNDEF PUREPASCAL}
     186  GR32_BlendASM,
     187{$IFNDEF OMIT_MMX}
     188  GR32_BlendMMX,
     189{$ENDIF}
     190{$IFNDEF OMIT_SSE2}
     191  GR32_BlendSSE2,
     192{$ENDIF}
     193{$ENDIF}
     194  GR32_System;
    145195
    146196{$IFDEF OMIT_MMX}
     
    173223  end;
    174224
     225  Af := @DivTable[FA];
     226  Ab := @DivTable[not FA];
    175227  with BX do
    176228  begin
    177     Af := @DivTable[FA];
    178     Ab := @DivTable[not FA];
    179229    R := Af[FX.R] + Ab[R];
    180230    G := Af[FX.G] + Ab[G];
    181231    B := Af[FX.B] + Ab[B];
     232    A := $FF;
    182233  end;
    183234  Result := B;
     
    201252  end;
    202253
     254  Af := @DivTable[FA];
     255  Ab := @DivTable[not FA];
    203256  with BX do
    204257  begin
    205     Af := @DivTable[FA];
    206     Ab := @DivTable[not FA];
    207258    R := Af[FX.R] + Ab[R];
    208259    G := Af[FX.G] + Ab[G];
    209260    B := Af[FX.B] + Ab[B];
     261    A := $FF;
     262  end;
     263end;
     264
     265procedure BlendMems_Pas(F: TColor32; B: PColor32; Count: Integer);
     266begin
     267  while Count > 0 do
     268  begin
     269    BlendMem(F, B^);
     270    Inc(B);
     271    Dec(Count);
    210272  end;
    211273end;
     
    233295  end;
    234296
     297  Ab := @DivTable[255 - M];
    235298  with BX do
    236299  begin
    237     Af := @DivTable[M];
    238     Ab := @DivTable[255 - M];
    239300    R := Af[FX.R] + Ab[R];
    240301    G := Af[FX.G] + Ab[G];
    241302    B := Af[FX.B] + Ab[B];
     303    A := $FF;
    242304  end;
    243305  Result := B;
     
    265327  end;
    266328
     329  Ab := @DivTable[255 - M];
    267330  with BX do
    268331  begin
    269     Af := @DivTable[M];
    270     Ab := @DivTable[255 - M];
    271332    R := Af[FX.R] + Ab[R];
    272333    G := Af[FX.G] + Ab[G];
    273334    B := Af[FX.B] + Ab[B];
     335    A := $FF;
     336  end;
     337end;
     338
     339function BlendRegRGB_Pas(F, B, W: TColor32): TColor32;
     340var
     341  FX: TColor32Entry absolute F;
     342  BX: TColor32Entry absolute B;
     343  WX: TColor32Entry absolute W;
     344  RX: TColor32Entry absolute Result;
     345begin
     346  RX.R := (FX.R - BX.R) * WX.B div 255 + BX.R;
     347  RX.G := (FX.G - BX.G) * WX.G div 255 + BX.G;
     348  RX.B := (FX.B - BX.B) * WX.R div 255 + BX.B;
     349end;
     350
     351procedure BlendMemRGB_Pas(F: TColor32; var B: TColor32; W: TColor32);
     352var
     353  FX: TColor32Entry absolute F;
     354  BX: TColor32Entry absolute B;
     355  WX: TColor32Entry absolute W;
     356begin
     357  BX.R := (FX.R - BX.R) * WX.B div 255 + BX.R;
     358  BX.G := (FX.G - BX.G) * WX.G div 255 + BX.G;
     359  BX.B := (FX.B - BX.B) * WX.R div 255 + BX.B;
     360end;
     361
     362procedure BlendLine1_Pas(Src: TColor32; Dst: PColor32; Count: Integer);
     363begin
     364  while Count > 0 do
     365  begin
     366    BlendMem(Src, Dst^);
     367    Inc(Dst);
     368    Dec(Count);
    274369  end;
    275370end;
     
    315410  end;
    316411
     412  Af := @DivTable[W];
     413  Ab := @DivTable[255 - W];
    317414  with Xe do
    318415  begin
    319     Af := @DivTable[W];
    320     Ab := @DivTable[255 - W];
    321416    R := Ab[Ye.R] + Af[R];
    322417    G := Ab[Ye.G] + Af[G];
    323418    B := Ab[Ye.B] + Af[B];
     419    A := Ab[Ye.A] + Af[A];
    324420  end;
    325421  Result := X;
     
    343439  end;
    344440
     441  Af := @DivTable[W];
     442  Ab := @DivTable[255 - W];
    345443  with Xe do
    346444  begin
    347     Af := @DivTable[W];
    348     Ab := @DivTable[255 - W];
    349445    R := Ab[Ye.R] + Af[R];
    350446    G := Ab[Ye.G] + Af[G];
    351447    B := Ab[Ye.B] + Af[B];
     448    A := Ab[Ye.A] + Af[A];
    352449  end;
    353450  Y := X;
     
    367464function MergeReg_Pas(F, B: TColor32): TColor32;
    368465var
    369  Fa, Ba, Wa: TColor32;
    370  Fw, Bw: PByteArray;
    371  Fx: TColor32Entry absolute F;
    372  Bx: TColor32Entry absolute B;
    373  Rx: TColor32Entry absolute Result;
    374 begin
    375  Fa := F shr 24;
    376  Ba := B shr 24;
    377  if Fa = $FF then
    378    Result := F
    379  else if Fa = $0 then
    380    Result := B
    381  else if Ba = $0 then
    382    Result := F
    383  else
    384  begin
    385    Rx.A := DivTable[Fa xor 255, Ba xor 255] xor 255;
    386    Wa := RcTable[Rx.A, Fa];
    387    Fw := @DivTable[Wa];
    388    Bw := @DivTable[Wa xor $ff];
    389    Rx.R := Fw[Fx.R] + Bw[Bx.R];
    390    Rx.G := Fw[Fx.G] + Bw[Bx.G];
    391    Rx.B := Fw[Fx.B] + Bw[Bx.B];
    392  end;
     466  Fa, Ba, Wa: TColor32;
     467  Fw, Bw: PByteArray;
     468  Fx: TColor32Entry absolute F;
     469  Bx: TColor32Entry absolute B;
     470  Rx: TColor32Entry absolute Result;
     471begin
     472  Fa := F shr 24;
     473  Ba := B shr 24;
     474  if Fa = $FF then
     475    Result := F
     476  else if Fa = $0 then
     477    Result := B
     478  else if Ba = $0 then
     479    Result := F
     480  else
     481  begin
     482    Rx.A := DivTable[Fa xor 255, Ba xor 255] xor 255;
     483    Wa := RcTable[Rx.A, Fa];
     484    Fw := @DivTable[Wa];
     485    Bw := @DivTable[Wa xor $FF];
     486    Rx.R := Fw[Fx.R] + Bw[Bx.R];
     487    Rx.G := Fw[Fx.G] + Bw[Bx.G];
     488    Rx.B := Fw[Fx.B] + Bw[Bx.B];
     489  end;
    393490end;
    394491
     
    406503begin
    407504  B := MergeReg(DivTable[M, F shr 24] shl 24 or F and $00FFFFFF, B);
     505end;
     506
     507procedure MergeLine1_Pas(Src: TColor32; Dst: PColor32; Count: Integer);
     508begin
     509  while Count > 0 do
     510  begin
     511    Dst^ := MergeReg(Src, Dst^);
     512    Inc(Dst);
     513    Dec(Count);
     514  end;
    408515end;
    409516
     
    435542procedure EMMS_Pas;
    436543begin
    437 //Dummy
     544  // Dummy
    438545end;
    439546
    440547function LightenReg_Pas(C: TColor32; Amount: Integer): TColor32;
    441548var
    442   r, g, b, a: Integer;
     549  r, g, b: Integer;
    443550  CX: TColor32Entry absolute C;
    444551  RX: TColor32Entry absolute Result;
    445552begin
    446   a := CX.A;
    447553  r := CX.R;
    448554  g := CX.G;
     
    457563  if b > 255 then b := 255 else if b < 0 then b := 0;
    458564
    459   RX.A := a;
     565  // preserve alpha
     566  RX.A := CX.A;
    460567  RX.R := r;
    461568  RX.G := g;
     
    467574function ColorAdd_Pas(C1, C2: TColor32): TColor32;
    468575var
    469   r1, g1, b1, a1: Integer;
    470   r2, g2, b2, a2: Integer;
    471 begin
    472   a1 := C1 shr 24;
    473   r1 := C1 and $00FF0000;
    474   g1 := C1 and $0000FF00;
    475   b1 := C1 and $000000FF;
    476 
    477   a2 := C2 shr 24;
    478   r2 := C2 and $00FF0000;
    479   g2 := C2 and $0000FF00;
    480   b2 := C2 and $000000FF;
    481 
    482   a1 := a1 + a2;
    483   r1 := r1 + r2;
    484   g1 := g1 + g2;
    485   b1 := b1 + b2;
    486 
    487   if a1 > $FF then a1 := $FF;
    488   if r1 > $FF0000 then r1 := $FF0000;
    489   if g1 > $FF00 then g1 := $FF00;
    490   if b1 > $FF then b1 := $FF;
    491 
    492   Result := a1 shl 24 + r1 + g1 + b1;
     576  Xe: TColor32Entry absolute C1;
     577  Ye: TColor32Entry absolute C2;
     578  R: TColor32Entry absolute Result;
     579begin
     580  R.A := Clamp(Xe.A + Ye.A, 255);
     581  R.R := Clamp(Xe.R + Ye.R, 255);
     582  R.G := Clamp(Xe.G + Ye.G, 255);
     583  R.B := Clamp(Xe.B + Ye.B, 255);
    493584end;
    494585
    495586function ColorSub_Pas(C1, C2: TColor32): TColor32;
    496587var
    497   r1, g1, b1, a1: Integer;
    498   r2, g2, b2, a2: Integer;
    499 begin
    500   a1 := C1 shr 24;
    501   r1 := C1 and $00FF0000;
    502   g1 := C1 and $0000FF00;
    503   b1 := C1 and $000000FF;
    504 
    505   r1 := r1 shr 16;
    506   g1 := g1 shr 8;
    507 
    508   a2 := C2 shr 24;
    509   r2 := C2 and $00FF0000;
    510   g2 := C2 and $0000FF00;
    511   b2 := C2 and $000000FF;
    512 
    513   r2 := r2 shr 16;
    514   g2 := g2 shr 8;
    515 
    516   a1 := a1 - a2;
    517   r1 := r1 - r2;
    518   g1 := g1 - g2;
    519   b1 := b1 - b2;
    520 
    521   if a1 < 0 then a1 := 0;
    522   if r1 < 0 then r1 := 0;
    523   if g1 < 0 then g1 := 0;
    524   if b1 < 0 then b1 := 0;
    525 
    526   Result := a1 shl 24 + r1 shl 16 + g1 shl 8 + b1;
     588  Xe: TColor32Entry absolute C1;
     589  Ye: TColor32Entry absolute C2;
     590  R: TColor32Entry absolute Result;
     591  Temp: SmallInt;
     592begin
     593  Temp := Xe.A - Ye.A;
     594  if Temp < 0 then
     595    R.A := 0
     596  else
     597    R.A := Temp;
     598  Temp := Xe.R - Ye.R;
     599  if Temp < 0 then
     600    R.R := 0
     601  else
     602    R.R := Temp;
     603  Temp := Xe.G - Ye.G;
     604  if Temp < 0 then
     605    R.G := 0
     606  else
     607    R.G := Temp;
     608  Temp := Xe.B - Ye.B;
     609  if Temp < 0 then
     610    R.B := 0
     611  else
     612    R.B := Temp;
    527613end;
    528614
    529615function ColorDiv_Pas(C1, C2: TColor32): TColor32;
    530616var
    531   r1, g1, b1, a1: Integer;
    532   r2, g2, b2, a2: Integer;
    533 begin
    534   a1 := C1 shr 24;
    535   r1 := (C1 and $00FF0000) shr 16;
    536   g1 := (C1 and $0000FF00) shr 8;
    537   b1 := C1 and $000000FF;
    538 
    539   a2 := C2 shr 24;
    540   r2 := (C2 and $00FF0000) shr 16;
    541   g2 := (C2 and $0000FF00) shr 8;
    542   b2 := C2 and $000000FF;
    543 
    544   if a1 = 0 then a1:=$FF
    545   else a1 := (a2 shl 8) div a1;
    546   if r1 = 0 then r1:=$FF
    547   else r1 := (r2 shl 8) div r1;
    548   if g1 = 0 then g1:=$FF
    549   else g1 := (g2 shl 8) div g1;
    550   if b1 = 0 then b1:=$FF
    551   else b1 := (b2 shl 8) div b1;
    552 
    553   if a1 > $FF then a1 := $FF;
    554   if r1 > $FF then r1 := $FF;
    555   if g1 > $FF then g1 := $FF;
    556   if b1 > $FF then b1 := $FF;
    557 
    558   Result := a1 shl 24 + r1 shl 16 + g1 shl 8 + b1;
     617  C1e: TColor32Entry absolute C1;
     618  C2e: TColor32Entry absolute C2;
     619  Re: TColor32Entry absolute Result;
     620  Temp: Word;
     621begin
     622  if C1e.A = 0 then
     623    Re.A := $FF
     624  else
     625  begin
     626    Temp := (C2e.A shl 8) div C1e.A;
     627    if Temp > $FF then
     628      Re.A := $FF
     629    else
     630      Re.A := Temp;
     631  end;
     632
     633  if C1e.R = 0 then
     634    Re.R := $FF
     635  else
     636  begin
     637    Temp := (C2e.R shl 8) div C1e.R;
     638    if Temp > $FF then
     639      Re.R := $FF
     640    else
     641      Re.R := Temp;
     642  end;
     643
     644  if C1e.G = 0 then
     645    Re.G := $FF
     646  else
     647  begin
     648    Temp := (C2e.G shl 8) div C1e.G;
     649    if Temp > $FF then
     650      Re.G := $FF
     651    else
     652      Re.G := Temp;
     653  end;
     654
     655  if C1e.B = 0 then
     656    Re.B := $FF
     657  else
     658  begin
     659    Temp := (C2e.B shl 8) div C1e.B;
     660    if Temp > $FF then
     661      Re.B := $FF
     662    else
     663      Re.B := Temp;
     664  end;
    559665end;
    560666
    561667function ColorModulate_Pas(C1, C2: TColor32): TColor32;
    562668var
    563   REnt: TColor32Entry absolute Result;
    564   C2Ent: TColor32Entry absolute C2;
    565 begin
    566   Result := C1;
    567   REnt.A := (C2Ent.A * REnt.A) shr 8;
    568   REnt.R := (C2Ent.R * REnt.R) shr 8;
    569   REnt.G := (C2Ent.G * REnt.G) shr 8;
    570   REnt.B := (C2Ent.B * REnt.B) shr 8;
     669  C1e: TColor32Entry absolute C2;
     670  C2e: TColor32Entry absolute C2;
     671  Re: TColor32Entry absolute Result;
     672begin
     673  Re.A := (C2e.A * C1e.A + $80) shr 8;
     674  Re.R := (C2e.R * C1e.R + $80) shr 8;
     675  Re.G := (C2e.G * C1e.G + $80) shr 8;
     676  Re.B := (C2e.B * C1e.B + $80) shr 8;
    571677end;
    572678
     
    603709function ColorDifference_Pas(C1, C2: TColor32): TColor32;
    604710var
    605   r1, g1, b1, a1: TColor32;
    606   r2, g2, b2, a2: TColor32;
    607 begin
    608   a1 := C1 shr 24;
    609   r1 := C1 and $00FF0000;
    610   g1 := C1 and $0000FF00;
    611   b1 := C1 and $000000FF;
    612 
    613   r1 := r1 shr 16;
    614   g1 := g1 shr 8;
    615 
    616   a2 := C2 shr 24;
    617   r2 := C2 and $00FF0000;
    618   g2 := C2 and $0000FF00;
    619   b2 := C2 and $000000FF;
    620 
    621   r2 := r2 shr 16;
    622   g2 := g2 shr 8;
    623 
    624   a1 := abs(a2 - a1);
    625   r1 := abs(r2 - r1);
    626   g1 := abs(g2 - g1);
    627   b1 := abs(b2 - b1);
    628 
    629   Result := a1 shl 24 + r1 shl 16 + g1 shl 8 + b1;
     711  Xe: TColor32Entry absolute C1;
     712  Ye: TColor32Entry absolute C2;
     713  R: TColor32Entry absolute Result;
     714begin
     715  R.A := Abs(Xe.A - Ye.A);
     716  R.R := Abs(Xe.R - Ye.R);
     717  R.G := Abs(Xe.G - Ye.G);
     718  R.B := Abs(Xe.B - Ye.B);
    630719end;
    631720
    632721function ColorExclusion_Pas(C1, C2: TColor32): TColor32;
    633722var
    634   r1, g1, b1, a1: TColor32;
    635   r2, g2, b2, a2: TColor32;
    636 begin
    637   a1 := C1 shr 24;
    638   r1 := C1 and $00FF0000;
    639   g1 := C1 and $0000FF00;
    640   b1 := C1 and $000000FF;
    641 
    642   r1 := r1 shr 16;
    643   g1 := g1 shr 8;
    644 
    645   a2 := C2 shr 24;
    646   r2 := C2 and $00FF0000;
    647   g2 := C2 and $0000FF00;
    648   b2 := C2 and $000000FF;
    649 
    650   r2 := r2 shr 16;
    651   g2 := g2 shr 8;
    652 
    653   a1 := a1 + a2 - (a1 * a2 shr 7);
    654   r1 := r1 + r2 - (r1 * r2 shr 7);
    655   g1 := g1 + g2 - (g1 * g2 shr 7);
    656   b1 := b1 + b2 - (b1 * b2 shr 7);
    657 
    658   Result := a1 shl 24 + r1 shl 16 + g1 shl 8 + b1;
     723  Xe: TColor32Entry absolute C1;
     724  Ye: TColor32Entry absolute C2;
     725  R: TColor32Entry absolute Result;
     726begin
     727  R.A := Xe.A + Ye.A - ((Xe.A * Ye.A) shl 7);
     728  R.R := Xe.R + Ye.R - ((Xe.R * Ye.R) shr 7);
     729  R.G := Xe.G + Ye.G - ((Xe.G * Ye.G) shr 7);
     730  R.B := Xe.B + Ye.B - ((Xe.B * Ye.B) shr 7);
    659731end;
    660732
     
    674746function ColorScale_Pas(C, W: TColor32): TColor32;
    675747var
     748  Ce: TColor32Entry absolute C;
     749var
    676750  r1, g1, b1, a1: Cardinal;
    677751begin
    678   a1 := C shr 24;
    679   r1 := C and $00FF0000;
    680   g1 := C and $0000FF00;
    681   b1 := C and $000000FF;
    682 
    683   r1 := r1 shr 16;
    684   g1 := g1 shr 8;
    685 
    686   a1 := a1 * W shr 8;
    687   r1 := r1 * W shr 8;
    688   g1 := g1 * W shr 8;
    689   b1 := b1 * W shr 8;
     752  a1 := Ce.A * W shr 8;
     753  r1 := Ce.R * W shr 8;
     754  g1 := Ce.G * W shr 8;
     755  b1 := Ce.B * W shr 8;
    690756
    691757  if a1 > 255 then a1 := 255;
     
    697763end;
    698764
     765function ColorScreen_Pas(B, S: TColor32): TColor32;
     766var
     767  Be: TColor32Entry absolute B;
     768  Se: TColor32Entry absolute S;
     769  R: TColor32Entry absolute Result;
     770begin
     771  R.A := Be.A + Se.A - (Be.A * Se.A) div 255;
     772  R.R := Be.R + Se.R - (Be.R * Se.R) div 255;
     773  R.G := Be.G + Se.G - (Be.G * Se.G) div 255;
     774  R.B := Be.B + Se.B - (Be.B * Se.B) div 255;
     775end;
     776
     777function ColorDodge_Pas(B, S: TColor32): TColor32;
     778
     779  function Dodge(B, S: Byte): Byte;
     780  begin
     781    if B = 0 then
     782      Result := 0
     783    else
     784    if S = 255 then
     785      Result := 255
     786    else
     787      Result := Clamp((255 * B) div (255 - S), 255);
     788  end;
     789
     790var
     791  Be: TColor32Entry absolute B;
     792  Se: TColor32Entry absolute S;
     793  R: TColor32Entry absolute Result;
     794begin
     795  R.A := Dodge(Be.A, Se.A);
     796  R.R := Dodge(Be.R, Se.R);
     797  R.G := Dodge(Be.G, Se.G);
     798  R.B := Dodge(Be.B, Se.B);
     799end;
     800
     801function ColorBurn_Pas(B, S: TColor32): TColor32;
     802
     803  function Burn(B, S: Byte): Byte;
     804  begin
     805    if B = 255 then
     806      Result := 255
     807    else
     808    if S = 0 then
     809      Result := 0
     810    else
     811      Result := 255 - Clamp(255 * (255 - B) div S, 255);
     812  end;
     813
     814var
     815  Be: TColor32Entry absolute B;
     816  Se: TColor32Entry absolute S;
     817  R: TColor32Entry absolute Result;
     818begin
     819  R.A := Burn(Be.A, Se.A);
     820  R.R := Burn(Be.R, Se.R);
     821  R.G := Burn(Be.G, Se.G);
     822  R.B := Burn(Be.B, Se.B);
     823end;
     824
     825
     826{ Blended color algebra }
     827
     828function BlendColorAdd_Pas(C1, C2: TColor32): TColor32;
     829var
     830  Xe: TColor32Entry absolute C1;
     831  Ye: TColor32Entry absolute C2;
     832  R: TColor32Entry absolute Result;
     833  Af, Ab: PByteArray;
     834begin
     835  Af := @DivTable[Xe.A];
     836  Ab := @DivTable[not Xe.A];
     837  R.A := Af[Clamp(Xe.A + Ye.A, 255)] + Ab[Ye.A];
     838  R.R := Af[Clamp(Xe.R + Ye.R, 255)] + Ab[Ye.R];
     839  R.G := Af[Clamp(Xe.G + Ye.G, 255)] + Ab[Ye.G];
     840  R.B := Af[Clamp(Xe.B + Ye.B, 255)] + Ab[Ye.B];
     841end;
     842
     843function BlendColorModulate_Pas(C1, C2: TColor32): TColor32;
     844var
     845  C1e: TColor32Entry absolute C1;
     846  C2e: TColor32Entry absolute C2;
     847  R: TColor32Entry absolute Result;
     848  Af, Ab: PByteArray;
     849begin
     850  Af := @DivTable[C1e.A];
     851  Ab := @DivTable[not C1e.A];
     852  R.A := Af[(C2e.A * C1e.A + $80) shr 8] + Ab[C2e.A];
     853  R.R := Af[(C2e.R * C1e.R + $80) shr 8] + Ab[C2e.R];
     854  R.G := Af[(C2e.G * C1e.G + $80) shr 8] + Ab[C2e.G];
     855  R.B := Af[(C2e.B * C1e.B + $80) shr 8] + Ab[C2e.B];
     856end;
     857
    699858{$IFNDEF PUREPASCAL}
    700 
    701 { Assembler versions }
    702 
    703 const
    704   bias = $00800080;
    705 
    706 
    707 function BlendReg_ASM(F, B: TColor32): TColor32;
    708 asm
    709   // blend foreground color (F) to a background color (B),
    710   // using alpha channel value of F
    711   // Result Z = Fa * Frgb + (1 - Fa) * Brgb
    712 
    713 {$IFDEF TARGET_x86}
    714   // EAX <- F
    715   // EDX <- B
    716 
    717 // Test Fa = 255 ?
    718         CMP     EAX,$FF000000   // Fa = 255 ? => Result = EAX
    719         JNC     @2
    720 
    721   // Test Fa = 0 ?
    722         TEST    EAX,$FF000000   // Fa = 0 ?   => Result = EDX
    723         JZ      @1
    724 
    725   // Get weight W = Fa * M
    726         MOV     ECX,EAX         // ECX  <-  Fa Fr Fg Fb
    727         SHR     ECX,24          // ECX  <-  00 00 00 Fa
    728 
    729         PUSH    EBX
    730 
    731   // P = W * F
    732         MOV     EBX,EAX         // EBX  <-  Fa Fr Fg Fb
    733         AND     EAX,$00FF00FF   // EAX  <-  00 Fr 00 Fb
    734         AND     EBX,$FF00FF00   // EBX  <-  Fa 00 Fg 00
    735         IMUL    EAX,ECX         // EAX  <-  Pr ** Pb **
    736         SHR     EBX,8           // EBX  <-  00 Fa 00 Fg
    737         IMUL    EBX,ECX         // EBX  <-  Pa ** Pg **
    738         ADD     EAX,bias
    739         AND     EAX,$FF00FF00   // EAX  <-  Pr 00 Pb 00
    740         SHR     EAX,8           // EAX  <-  00 Pr ** Pb
    741         ADD     EBX,bias
    742         AND     EBX,$FF00FF00   // EBX  <-  Pa 00 Pg 00
    743         OR      EAX,EBX         // EAX  <-  Pa Pr Pg Pb
    744 
    745   // W = 1 - W; Q = W * B
    746         XOR     ECX,$000000FF   // ECX  <-  1 - ECX
    747         MOV     EBX,EDX         // EBX  <-  Ba Br Bg Bb
    748         AND     EDX,$00FF00FF   // EDX  <-  00 Br 00 Bb
    749         AND     EBX,$FF00FF00   // EBX  <-  Ba 00 Bg 00
    750         IMUL    EDX,ECX         // EDX  <-  Qr ** Qb **
    751         SHR     EBX,8           // EBX  <-  00 Ba 00 Bg
    752         IMUL    EBX,ECX         // EBX  <-  Qa ** Qg **
    753         ADD     EDX,bias
    754         AND     EDX,$FF00FF00   // EDX  <-  Qr 00 Qb 00
    755         SHR     EDX,8           // EDX  <-  00 Qr ** Qb
    756         ADD     EBX,bias
    757         AND     EBX,$FF00FF00   // EBX  <-  Qa 00 Qg 00
    758         OR      EBX,EDX         // EBX  <-  Qa Qr Qg Qb
    759 
    760   // Z = P + Q (assuming no overflow at each byte)
    761         ADD     EAX,EBX         // EAX  <-  Za Zr Zg Zb
    762 
    763         POP     EBX
    764 {$IFDEF FPC}
    765         JMP @2
    766 {$ELSE}
    767         RET
    768 {$ENDIF}
    769 
    770 @1:     MOV     EAX,EDX
    771 @2:
    772 {$ENDIF}
    773 
    774   // EAX <- F
    775   // EDX <- B
    776 {$IFDEF TARGET_x64}
    777         MOV     RAX, RCX
    778 
    779   // Test Fa = 255 ?
    780         CMP     EAX,$FF000000   // Fa = 255 ? => Result = EAX
    781         JNC     @2
    782 
    783   // Test Fa = 0 ?
    784         TEST    EAX,$FF000000   // Fa = 0 ?   => Result = EDX
    785         JZ      @1
    786 
    787   // Get weight W = Fa * M
    788         MOV     ECX,EAX         // ECX  <-  Fa Fr Fg Fb
    789         SHR     ECX,24          // ECX  <-  00 00 00 Fa
    790 
    791   // P = W * F
    792         MOV     R9D,EAX         // R9D  <-  Fa Fr Fg Fb
    793         AND     EAX,$00FF00FF   // EAX  <-  00 Fr 00 Fb
    794         AND     R9D,$FF00FF00   // R9D  <-  Fa 00 Fg 00
    795         IMUL    EAX,ECX         // EAX  <-  Pr ** Pb **
    796         SHR     R9D,8           // R9D  <-  00 Fa 00 Fg
    797         IMUL    R9D,ECX         // R9D  <-  Pa ** Pg **
    798         ADD     EAX,bias
    799         AND     EAX,$FF00FF00   // EAX  <-  Pr 00 Pb 00
    800         SHR     EAX,8           // EAX  <-  00 Pr ** Pb
    801         ADD     R9D,bias
    802         AND     R9D,$FF00FF00   // R9D  <-  Pa 00 Pg 00
    803         OR      EAX,R9D         // EAX  <-  Pa Pr Pg Pb
    804 
    805   // W = 1 - W; Q = W * B
    806         XOR     ECX,$000000FF   // ECX  <-  1 - ECX
    807         MOV     R9D,EDX         // R9D  <-  Ba Br Bg Bb
    808         AND     EDX,$00FF00FF   // EDX  <-  00 Br 00 Bb
    809         AND     R9D,$FF00FF00   // R9D  <-  Ba 00 Bg 00
    810         IMUL    EDX,ECX         // EDX  <-  Qr ** Qb **
    811         SHR     R9D,8           // R9D  <-  00 Ba 00 Bg
    812         IMUL    R9D,ECX         // R9D  <-  Qa ** Qg **
    813         ADD     EDX,bias
    814         AND     EDX,$FF00FF00   // EDX  <-  Qr 00 Qb 00
    815         SHR     EDX,8           // EDX  <-  00 Qr ** Qb
    816         ADD     R9D,bias
    817         AND     R9D,$FF00FF00   // R9D  <-  Qa 00 Qg 00
    818         OR      R9D,EDX         // R9D  <-  Qa Qr Qg Qb
    819 
    820   // Z = P + Q (assuming no overflow at each byte)
    821         ADD     EAX,R9D         // EAX  <-  Za Zr Zg Zb
    822 {$IFDEF FPC}
    823         JMP @2
    824 {$ELSE}
    825         RET
    826 {$ENDIF}
    827 
    828 @1:     MOV     EAX,EDX
    829 @2:
    830 {$ENDIF}
    831 end;
    832 
    833 procedure BlendMem_ASM(F: TColor32; var B: TColor32);
    834 asm
    835 {$IFDEF TARGET_x86}
    836   // EAX <- F
    837   // [EDX] <- B
    838 
    839   // Test Fa = 0 ?
    840         TEST    EAX,$FF000000   // Fa = 0 ?   => do not write
    841         JZ      @2
    842 
    843   // Get weight W = Fa * M
    844         MOV     ECX,EAX         // ECX  <-  Fa Fr Fg Fb
    845         SHR     ECX,24          // ECX  <-  00 00 00 Fa
    846 
    847   // Test Fa = 255 ?
    848         CMP     ECX,$FF
    849         JZ      @1
    850 
    851         PUSH    EBX
    852         PUSH    ESI
    853 
    854   // P = W * F
    855         MOV     EBX,EAX         // EBX  <-  Fa Fr Fg Fb
    856         AND     EAX,$00FF00FF   // EAX  <-  00 Fr 00 Fb
    857         AND     EBX,$FF00FF00   // EBX  <-  Fa 00 Fg 00
    858         IMUL    EAX,ECX         // EAX  <-  Pr ** Pb **
    859         SHR     EBX,8           // EBX  <-  00 Fa 00 Fg
    860         IMUL    EBX,ECX         // EBX  <-  Pa ** Pg **
    861         ADD     EAX,bias
    862         AND     EAX,$FF00FF00   // EAX  <-  Pr 00 Pb 00
    863         SHR     EAX,8           // EAX  <-  00 Pr ** Pb
    864         ADD     EBX,bias
    865         AND     EBX,$FF00FF00   // EBX  <-  Pa 00 Pg 00
    866         OR      EAX,EBX         // EAX  <-  Pa Pr Pg Pb
    867 
    868         MOV     ESI,[EDX]
    869 
    870 // W = 1 - W; Q = W * B
    871         XOR     ECX,$000000FF   // ECX  <-  1 - ECX
    872         MOV     EBX,ESI         // EBX  <-  Ba Br Bg Bb
    873         AND     ESI,$00FF00FF   // ESI  <-  00 Br 00 Bb
    874         AND     EBX,$FF00FF00   // EBX  <-  Ba 00 Bg 00
    875         IMUL    ESI,ECX         // ESI  <-  Qr ** Qb **
    876         SHR     EBX,8           // EBX  <-  00 Ba 00 Bg
    877         IMUL    EBX,ECX         // EBX  <-  Qa ** Qg **
    878         ADD     ESI,bias
    879         AND     ESI,$FF00FF00   // ESI  <-  Qr 00 Qb 00
    880         SHR     ESI,8           // ESI  <-  00 Qr ** Qb
    881         ADD     EBX,bias
    882         AND     EBX,$FF00FF00   // EBX  <-  Qa 00 Qg 00
    883         OR      EBX,ESI         // EBX  <-  Qa Qr Qg Qb
    884 
    885   // Z = P + Q (assuming no overflow at each byte)
    886         ADD     EAX,EBX         // EAX  <-  Za Zr Zg Zb
    887 
    888         MOV     [EDX],EAX
    889         POP     ESI
    890         POP     EBX
    891 {$IFDEF FPC}
    892         JMP @2
    893 {$ELSE}
    894         RET
    895 {$ENDIF}
    896 
    897 @1:     MOV     [EDX],EAX
    898 @2:
    899 {$ENDIF}
    900 
    901 {$IFDEF TARGET_x64}
    902   // ECX <- F
    903   // [RDX] <- B
    904 
    905   // Test Fa = 0 ?
    906         TEST    ECX,$FF000000   // Fa = 0 ?   => do not write
    907         JZ      @2
    908 
    909         MOV     EAX, ECX        // EAX  <-  Fa Fr Fg Fb
    910 
    911         // Get weight W = Fa * M
    912         SHR     ECX,24          // ECX  <-  00 00 00 Fa
    913 
    914         // Test Fa = 255 ?
    915         CMP     ECX,$FF
    916         JZ      @1
    917 
    918   // P = W * F
    919         MOV     R8D,EAX         // R8D  <-  Fa Fr Fg Fb
    920         AND     EAX,$00FF00FF   // EAX  <-  00 Fr 00 Fb
    921         AND     R8D,$FF00FF00   // R8D  <-  Fa 00 Fg 00
    922         IMUL    EAX,ECX         // EAX  <-  Pr ** Pb **
    923         SHR     R8D,8           // R8D  <-  00 Fa 00 Fg
    924         IMUL    R8D,ECX         // R8D  <-  Pa ** Pg **
    925         ADD     EAX,bias
    926         AND     EAX,$FF00FF00   // EAX  <-  Pr 00 Pb 00
    927         SHR     EAX,8           // EAX  <-  00 Pr ** Pb
    928         ADD     R8D,bias
    929         AND     R8D,$FF00FF00   // R8D  <-  Pa 00 Pg 00
    930         OR      EAX,R8D         // EAX  <-  Pa Pr Pg Pb
    931 
    932         MOV     R9D,[RDX]
    933 
    934   // W = 1 - W; Q = W * B
    935         XOR     ECX,$000000FF   // ECX  <-  1 - ECX
    936         MOV     R8D,R9D         // R8D  <-  Ba Br Bg Bb
    937         AND     R9D,$00FF00FF   // R9D  <-  00 Br 00 Bb
    938         AND     R8D,$FF00FF00   // R8D  <-  Ba 00 Bg 00
    939         IMUL    R9D,ECX         // R9D  <-  Qr ** Qb **
    940         SHR     R8D,8           // R8D  <-  00 Ba 00 Bg
    941         IMUL    R8D,ECX         // R8D  <-  Qa ** Qg **
    942         ADD     R9D,bias
    943         AND     R9D,$FF00FF00   // R9D  <-  Qr 00 Qb 00
    944         SHR     R9D,8           // R9D  <-  00 Qr ** Qb
    945         ADD     R8D,bias
    946         AND     R8D,$FF00FF00   // R8D  <-  Qa 00 Qg 00
    947         OR      R8D,R9D         // R8D  <-  Qa Qr Qg Qb
    948 
    949   // Z = P + Q (assuming no overflow at each byte)
    950         ADD     EAX,R8D         // EAX  <-  Za Zr Zg Zb
    951 
    952         MOV     [RDX],EAX
    953 {$IFDEF FPC}
    954         JMP @2
    955 {$ELSE}
    956         RET
    957 {$ENDIF}
    958 
    959 @1:     MOV     [RDX],EAX
    960 @2:
    961 {$ENDIF}
    962 end;
    963 
    964 function BlendRegEx_ASM(F, B, M: TColor32): TColor32;
    965 asm
    966   // blend foreground color (F) to a background color (B),
    967   // using alpha channel value of F multiplied by master alpha (M)
    968   // no checking for M = $FF, in this case Graphics32 uses BlendReg
    969   // Result Z = Fa * M * Frgb + (1 - Fa * M) * Brgb
    970   // EAX <- F
    971   // EDX <- B
    972   // ECX <- M
    973 
    974 {$IFDEF TARGET_x86}
    975 
    976 // Check Fa > 0 ?
    977         TEST    EAX,$FF000000   // Fa = 0? => Result := EDX
    978         JZ      @2
    979 
    980         PUSH    EBX
    981 
    982   // Get weight W = Fa * M
    983         MOV     EBX,EAX         // EBX  <-  Fa Fr Fg Fb
    984         INC     ECX             // 255:256 range bias
    985         SHR     EBX,24          // EBX  <-  00 00 00 Fa
    986         IMUL    ECX,EBX         // ECX  <-  00 00  W **
    987         SHR     ECX,8           // ECX  <-  00 00 00  W
    988         JZ      @1              // W = 0 ?  => Result := EDX
    989 
    990   // P = W * F
    991         MOV     EBX,EAX         // EBX  <-  ** Fr Fg Fb
    992         AND     EAX,$00FF00FF   // EAX  <-  00 Fr 00 Fb
    993         AND     EBX,$0000FF00   // EBX  <-  00 00 Fg 00
    994         IMUL    EAX,ECX         // EAX  <-  Pr ** Pb **
    995         SHR     EBX,8           // EBX  <-  00 00 00 Fg
    996         IMUL    EBX,ECX         // EBX  <-  00 00 Pg **
    997         ADD     EAX,bias
    998         AND     EAX,$FF00FF00   // EAX  <-  Pr 00 Pb 00
    999         SHR     EAX,8           // EAX  <-  00 Pr ** Pb
    1000         ADD     EBX,bias
    1001         AND     EBX,$0000FF00   // EBX  <-  00 00 Pg 00
    1002         OR      EAX,EBX         // EAX  <-  00 Pr Pg Pb
    1003 
    1004   // W = 1 - W; Q = W * B
    1005         XOR     ECX,$000000FF   // ECX  <-  1 - ECX
    1006         MOV     EBX,EDX         // EBX  <-  00 Br Bg Bb
    1007         AND     EDX,$00FF00FF   // EDX  <-  00 Br 00 Bb
    1008         AND     EBX,$0000FF00   // EBX  <-  00 00 Bg 00
    1009         IMUL    EDX,ECX         // EDX  <-  Qr ** Qb **
    1010         SHR     EBX,8           // EBX  <-  00 00 00 Bg
    1011         IMUL    EBX,ECX         // EBX  <-  00 00 Qg **
    1012         ADD     EDX,bias
    1013         AND     EDX,$FF00FF00   // EDX  <-  Qr 00 Qb 00
    1014         SHR     EDX,8           // EDX  <-  00 Qr ** Qb
    1015         ADD     EBX,bias
    1016         AND     EBX,$0000FF00   // EBX  <-  00 00 Qg 00
    1017         OR      EBX,EDX         // EBX  <-  00 Qr Qg Qb
    1018 
    1019   // Z = P + Q (assuming no overflow at each byte)
    1020         ADD     EAX,EBX         // EAX  <-  00 Zr Zg Zb
    1021 
    1022         POP     EBX
    1023 {$IFDEF FPC}
    1024         JMP @3
    1025 {$ELSE}
    1026         RET
    1027 {$ENDIF}
    1028 
    1029 @1:
    1030         POP     EBX
    1031 
    1032 @2:     MOV     EAX,EDX
    1033 @3:
    1034 {$ENDIF}
    1035 
    1036 {$IFDEF TARGET_x64}
    1037         MOV     EAX,ECX         // EAX  <-  Fa Fr Fg Fb
    1038         TEST    EAX,$FF000000   // Fa = 0? => Result := EDX
    1039         JZ      @1
    1040 
    1041   // Get weight W = Fa * M
    1042         INC     R8D             // 255:256 range bias
    1043         SHR     ECX,24          // ECX  <-  00 00 00 Fa
    1044         IMUL    R8D,ECX         // R8D  <-  00 00  W **
    1045         SHR     R8D,8           // R8D  <-  00 00 00  W
    1046         JZ      @1              // W = 0 ?  => Result := EDX
    1047 
    1048   // P = W * F
    1049         MOV     ECX,EAX         // ECX  <-  ** Fr Fg Fb
    1050         AND     EAX,$00FF00FF   // EAX  <-  00 Fr 00 Fb
    1051         AND     ECX,$0000FF00   // ECX  <-  00 00 Fg 00
    1052         IMUL    EAX,R8D         // EAX  <-  Pr ** Pb **
    1053         SHR     ECX,8           // ECX  <-  00 00 00 Fg
    1054         IMUL    ECX,R8D         // ECX  <-  00 00 Pg **
    1055         ADD     EAX,bias
    1056         AND     EAX,$FF00FF00   // EAX  <-  Pr 00 Pb 00
    1057         SHR     EAX,8           // EAX  <-  00 Pr ** Pb
    1058         ADD     ECX,bias
    1059         AND     ECX,$0000FF00   // ECX  <-  00 00 Pg 00
    1060         OR      EAX,ECX         // EAX  <-  00 Pr Pg Pb
    1061 
    1062   // W = 1 - W; Q = W * B
    1063         XOR     R8D,$000000FF   // R8D  <-  1 - R8D
    1064         MOV     ECX,EDX         // ECX  <-  00 Br Bg Bb
    1065         AND     EDX,$00FF00FF   // EDX  <-  00 Br 00 Bb
    1066         AND     ECX,$0000FF00   // ECX  <-  00 00 Bg 00
    1067         IMUL    EDX,R8D         // EDX  <-  Qr ** Qb **
    1068         SHR     ECX,8           // ECX  <-  00 00 00 Bg
    1069         IMUL    ECX,R8D         // ECX  <-  00 00 Qg **
    1070         ADD     EDX,bias
    1071         AND     EDX,$FF00FF00   // EDX  <-  Qr 00 Qb 00
    1072         SHR     EDX,8           // EDX  <-  00 Qr ** Qb
    1073         ADD     ECX,bias
    1074         AND     ECX,$0000FF00   // ECX  <-  00 00 Qg 00
    1075         OR      ECX,EDX         // ECX  <-  00 Qr Qg Qb
    1076 
    1077   // Z = P + Q (assuming no overflow at each byte)
    1078         ADD     EAX,ECX         // EAX  <-  00 Zr Zg Zb
    1079 
    1080 {$IFDEF FPC}
    1081         JMP @2
    1082 {$ELSE}
    1083         RET
    1084 {$ENDIF}
    1085 
    1086 @1:     MOV     EAX,EDX
    1087 @2:
    1088 {$ENDIF}
    1089 end;
    1090 
    1091 procedure BlendMemEx_ASM(F: TColor32; var B: TColor32; M: TColor32);
    1092 asm
    1093 {$IFDEF TARGET_x86}
    1094   // EAX <- F
    1095   // [EDX] <- B
    1096   // ECX <- M
    1097 
    1098   // Check Fa > 0 ?
    1099         TEST    EAX,$FF000000   // Fa = 0? => write nothing
    1100         JZ      @2
    1101 
    1102         PUSH    EBX
    1103 
    1104   // Get weight W = Fa * M
    1105         MOV     EBX,EAX         // EBX  <-  Fa Fr Fg Fb
    1106         INC     ECX             // 255:256 range bias
    1107         SHR     EBX,24          // EBX  <-  00 00 00 Fa
    1108         IMUL    ECX,EBX         // ECX  <-  00 00  W **
    1109         SHR     ECX,8           // ECX  <-  00 00 00  W
    1110         JZ      @1              // W = 0 ?  => write nothing
    1111 
    1112         PUSH    ESI
    1113 
    1114   // P = W * F
    1115         MOV     EBX,EAX         // EBX  <-  ** Fr Fg Fb
    1116         AND     EAX,$00FF00FF   // EAX  <-  00 Fr 00 Fb
    1117         AND     EBX,$0000FF00   // EBX  <-  00 00 Fg 00
    1118         IMUL    EAX,ECX         // EAX  <-  Pr ** Pb **
    1119         SHR     EBX,8           // EBX  <-  00 00 00 Fg
    1120         IMUL    EBX,ECX         // EBX  <-  00 00 Pg **
    1121         ADD     EAX,bias
    1122         AND     EAX,$FF00FF00   // EAX  <-  Pr 00 Pb 00
    1123         SHR     EAX,8           // EAX  <-  00 Pr ** Pb
    1124         ADD     EBX,bias
    1125         AND     EBX,$0000FF00   // EBX  <-  00 00 Pg 00
    1126         OR      EAX,EBX         // EAX  <-  00 Pr Pg Pb
    1127 
    1128   // W = 1 - W; Q = W * B
    1129         MOV     ESI,[EDX]
    1130         XOR     ECX,$000000FF   // ECX  <-  1 - ECX
    1131         MOV     EBX,ESI         // EBX  <-  00 Br Bg Bb
    1132         AND     ESI,$00FF00FF   // ESI  <-  00 Br 00 Bb
    1133         AND     EBX,$0000FF00   // EBX  <-  00 00 Bg 00
    1134         IMUL    ESI,ECX         // ESI  <-  Qr ** Qb **
    1135         SHR     EBX,8           // EBX  <-  00 00 00 Bg
    1136         IMUL    EBX,ECX         // EBX  <-  00 00 Qg **
    1137         ADD     ESI,bias
    1138         AND     ESI,$FF00FF00   // ESI  <-  Qr 00 Qb 00
    1139         SHR     ESI,8           // ESI  <-  00 Qr ** Qb
    1140         ADD     EBX,bias
    1141         AND     EBX,$0000FF00   // EBX  <-  00 00 Qg 00
    1142         OR      EBX,ESI         // EBX  <-  00 Qr Qg Qb
    1143 
    1144   // Z = P + Q (assuming no overflow at each byte)
    1145         ADD     EAX,EBX         // EAX  <-  00 Zr Zg Zb
    1146 
    1147         MOV     [EDX],EAX
    1148         POP     ESI
    1149 
    1150 @1:     POP     EBX
    1151 @2:
    1152 {$ENDIF}
    1153 
    1154 {$IFDEF TARGET_x64}
    1155   // ECX <- F
    1156   // [RDX] <- B
    1157   // R8 <- M
    1158 
    1159   // ECX <- F
    1160   // [EDX] <- B
    1161   // R8 <- M
    1162 
    1163   // Check Fa > 0 ?
    1164         TEST    ECX,$FF000000   // Fa = 0? => write nothing
    1165         JZ      @1
    1166 
    1167   // Get weight W = Fa * M
    1168         MOV     EAX,ECX         // EAX  <-  Fa Fr Fg Fb
    1169         INC     R8D             // 255:256 range bias
    1170         SHR     EAX,24          // EAX  <-  00 00 00 Fa
    1171         IMUL    R8D,EAX         // R8D <-  00 00  W **
    1172         SHR     R8D,8           // R8D <-  00 00 00  W
    1173         JZ      @1              // W = 0 ?  => write nothing
    1174 
    1175   // P = W * F
    1176         MOV     EAX,ECX         // EAX  <-  ** Fr Fg Fb
    1177         AND     ECX,$00FF00FF   // ECX  <-  00 Fr 00 Fb
    1178         AND     EAX,$0000FF00   // EAX  <-  00 00 Fg 00
    1179         IMUL    ECX,R8D         // ECX  <-  Pr ** Pb **
    1180         SHR     EAX,8           // EAX  <-  00 00 00 Fg
    1181         IMUL    EAX,R8D         // EAX  <-  00 00 Pg **
    1182         ADD     ECX,bias
    1183         AND     ECX,$FF00FF00   // ECX  <-  Pr 00 Pb 00
    1184         SHR     ECX,8           // ECX  <-  00 Pr ** Pb
    1185         ADD     EAX,bias
    1186         AND     EAX,$0000FF00   // EAX  <-  00 00 Pg 00
    1187         OR      ECX,EAX         // ECX  <-  00 Pr Pg Pb
    1188 
    1189   // W = 1 - W; Q = W * B
    1190         MOV     R9D,[RDX]
    1191         XOR     R8D,$000000FF   // R8D  <-  1 - R8
    1192         MOV     EAX,R9D         // EAX  <-  00 Br Bg Bb
    1193         AND     R9D,$00FF00FF   // R9D  <-  00 Br 00 Bb
    1194         AND     EAX,$0000FF00   // EAX  <-  00 00 Bg 00
    1195         IMUL    R9D,R8D         // R9D  <-  Qr ** Qb **
    1196         SHR     EAX,8           // EAX  <-  00 00 00 Bg
    1197         IMUL    EAX,R8D         // EAX  <-  00 00 Qg **
    1198         ADD     R9D,bias
    1199         AND     R9D,$FF00FF00   // R9D  <-  Qr 00 Qb 00
    1200         SHR     R9D,8           // R9D  <-  00 Qr ** Qb
    1201         ADD     EAX,bias
    1202         AND     EAX,$0000FF00   // EAX  <-  00 00 Qg 00
    1203         OR      EAX,R9D         // EAX  <-  00 Qr Qg Qb
    1204 
    1205   // Z = P + Q (assuming no overflow at each byte)
    1206         ADD     ECX,EAX         // ECX  <-  00 Zr Zg Zb
    1207 
    1208         MOV     [RDX],ECX
    1209 
    1210 @1:
    1211 {$ENDIF}
    1212 end;
    1213 
    1214 procedure BlendLine_ASM(Src, Dst: PColor32; Count: Integer);
    1215 asm
    1216 {$IFDEF TARGET_x86}
    1217   // EAX <- Src
    1218   // EDX <- Dst
    1219   // ECX <- Count
    1220 
    1221   // test the counter for zero or negativity
    1222         TEST    ECX,ECX
    1223         JS      @4
    1224 
    1225         PUSH    EBX
    1226         PUSH    ESI
    1227         PUSH    EDI
    1228 
    1229         MOV     ESI,EAX         // ESI <- Src
    1230         MOV     EDI,EDX         // EDI <- Dst
    1231 
    1232   // loop start
    1233 @1:     MOV     EAX,[ESI]
    1234         TEST    EAX,$FF000000
    1235         JZ      @3              // complete transparency, proceed to next point
    1236 
    1237         PUSH    ECX             // store counter
    1238 
    1239   // Get weight W = Fa * M
    1240         MOV     ECX,EAX         // ECX  <-  Fa Fr Fg Fb
    1241         SHR     ECX,24          // ECX  <-  00 00 00 Fa
    1242 
    1243   // Test Fa = 255 ?
    1244         CMP     ECX,$FF
    1245         JZ      @2
    1246 
    1247   // P = W * F
    1248         MOV     EBX,EAX         // EBX  <-  Fa Fr Fg Fb
    1249         AND     EAX,$00FF00FF   // EAX  <-  00 Fr 00 Fb
    1250         AND     EBX,$FF00FF00   // EBX  <-  Fa 00 Fg 00
    1251         IMUL    EAX,ECX         // EAX  <-  Pr ** Pb **
    1252         SHR     EBX,8           // EBX  <-  00 Fa 00 Fg
    1253         IMUL    EBX,ECX         // EBX  <-  Pa ** Pg **
    1254         ADD     EAX,bias
    1255         AND     EAX,$FF00FF00   // EAX  <-  Pr 00 Pb 00
    1256         SHR     EAX,8           // EAX  <-  00 Pr ** Pb
    1257         ADD     EBX,bias
    1258         AND     EBX,$FF00FF00   // EBX  <-  Pa 00 Pg 00
    1259         OR      EAX,EBX         // EAX  <-  Pa Pr Pg Pb
    1260 
    1261   // W = 1 - W; Q = W * B
    1262         MOV     EDX,[EDI]
    1263         XOR     ECX,$000000FF   // ECX  <-  1 - ECX
    1264         MOV     EBX,EDX         // EBX  <-  Ba Br Bg Bb
    1265         AND     EDX,$00FF00FF   // ESI  <-  00 Br 00 Bb
    1266         AND     EBX,$FF00FF00   // EBX  <-  Ba 00 Bg 00
    1267         IMUL    EDX,ECX         // ESI  <-  Qr ** Qb **
    1268         SHR     EBX,8           // EBX  <-  00 Ba 00 Bg
    1269         IMUL    EBX,ECX         // EBX  <-  Qa ** Qg **
    1270         ADD     EDX,bias
    1271         AND     EDX,$FF00FF00   // ESI  <-  Qr 00 Qb 00
    1272         SHR     EDX,8           // ESI  <-  00 Qr ** Qb
    1273         ADD     EBX,bias
    1274         AND     EBX,$FF00FF00   // EBX  <-  Qa 00 Qg 00
    1275         OR      EBX,EDX         // EBX  <-  Qa Qr Qg Qb
    1276 
    1277   // Z = P + Q (assuming no overflow at each byte)
    1278         ADD     EAX,EBX         // EAX  <-  Za Zr Zg Zb
    1279 @2:
    1280         MOV     [EDI],EAX
    1281 
    1282         POP     ECX             // restore counter
    1283 
    1284 @3:
    1285         ADD     ESI,4
    1286         ADD     EDI,4
    1287 
    1288   // loop end
    1289         DEC     ECX
    1290         JNZ     @1
    1291 
    1292         POP     EDI
    1293         POP     ESI
    1294         POP     EBX
    1295 
    1296 @4:
    1297 {$ENDIF}
    1298 
    1299 {$IFDEF TARGET_x64}
    1300   // RCX <- Src
    1301   // RDX <- Dst
    1302   // R8 <- Count
    1303 
    1304   // test the counter for zero or negativity
    1305         TEST    R8D,R8D
    1306         JS      @4
    1307 
    1308         MOV     R10,RCX         // R10 <- Src
    1309         MOV     R11,RDX         // R11 <- Dst
    1310         MOV     ECX,R8D         // RCX <- Count
    1311 
    1312   // loop start
    1313 @1:
    1314         MOV     EAX,[R10]
    1315         TEST    EAX,$FF000000
    1316         JZ      @3              // complete transparency, proceed to next point
    1317 
    1318   // Get weight W = Fa * M
    1319         MOV     R9D,EAX        // R9D  <-  Fa Fr Fg Fb
    1320         SHR     R9D,24         // R9D  <-  00 00 00 Fa
    1321 
    1322   // Test Fa = 255 ?
    1323         CMP     R9D,$FF
    1324         JZ      @2
    1325 
    1326   // P = W * F
    1327         MOV     R8D,EAX         // R8D  <-  Fa Fr Fg Fb
    1328         AND     EAX,$00FF00FF   // EAX  <-  00 Fr 00 Fb
    1329         AND     R8D,$FF00FF00   // R8D  <-  Fa 00 Fg 00
    1330         IMUL    EAX,R9D         // EAX  <-  Pr ** Pb **
    1331         SHR     R8D,8           // R8D  <-  00 Fa 00 Fg
    1332         IMUL    R8D,R9D         // R8D  <-  Pa ** Pg **
    1333         ADD     EAX,bias
    1334         AND     EAX,$FF00FF00   // EAX  <-  Pr 00 Pb 00
    1335         SHR     EAX,8           // EAX  <-  00 Pr ** Pb
    1336         ADD     R8D,bias
    1337         AND     R8D,$FF00FF00   // R8D  <-  Pa 00 Pg 00
    1338         OR      EAX,R8D         // EAX  <-  Pa Pr Pg Pb
    1339 
    1340   // W = 1 - W; Q = W * B
    1341         MOV     EDX,[R11]
    1342         XOR     R9D,$000000FF   // R9D  <-  1 - R9D
    1343         MOV     R8D,EDX         // R8D  <-  Ba Br Bg Bb
    1344         AND     EDX,$00FF00FF   // ESI  <-  00 Br 00 Bb
    1345         AND     R8D,$FF00FF00   // R8D  <-  Ba 00 Bg 00
    1346         IMUL    EDX,R9D         // ESI  <-  Qr ** Qb **
    1347         SHR     R8D,8           // R8D  <-  00 Ba 00 Bg
    1348         IMUL    R8D,R9D         // R8D  <-  Qa ** Qg **
    1349         ADD     EDX,bias
    1350         AND     EDX,$FF00FF00   // ESI  <-  Qr 00 Qb 00
    1351         SHR     EDX,8           // ESI  <-  00 Qr ** Qb
    1352         ADD     R8D,bias
    1353         AND     R8D,$FF00FF00   // R8D  <-  Qa 00 Qg 00
    1354         OR      R8D,EDX         // R8D  <-  Qa Qr Qg Qb
    1355 
    1356   // Z = P + Q (assuming no overflow at each byte)
    1357         ADD     EAX,R8D         // EAX  <-  Za Zr Zg Zb
    1358 @2:
    1359         MOV     [R11],EAX
    1360 
    1361 @3:
    1362         ADD     R10,4
    1363         ADD     R11,4
    1364 
    1365   // loop end
    1366         DEC     ECX
    1367         JNZ     @1
    1368 
    1369 @4:
    1370 {$ENDIF}
    1371 end;
    1372 
    1373 {$IFDEF TARGET_x86}
    1374 
    1375 function MergeReg_ASM(F, B: TColor32): TColor32;
    1376 asm
    1377         // EAX <- F
    1378         // EDX <- B
    1379 
    1380         // if F.A = 0 then
    1381         TEST    EAX,$FF000000
    1382         JZ      @exit0
    1383 
    1384         // else if B.A = 255 then
    1385         CMP     EDX,$FF000000
    1386         JNC     @blend
    1387 
    1388         // else if F.A = 255 then
    1389         CMP     EAX,$FF000000
    1390         JNC     @Exit
    1391 
    1392         // else if B.A = 0 then
    1393         TEST    EDX,$FF000000
    1394         JZ      @Exit
    1395 
    1396 @4:
    1397         PUSH    EBX
    1398         PUSH    ESI
    1399         PUSH    EDI
    1400         ADD     ESP,-$0C
    1401         MOV     [ESP+$04],EDX
    1402         MOV     [ESP],EAX
    1403 
    1404         // AH <- F.A
    1405         // DL, CL <- B.A
    1406         SHR     EAX,16
    1407         AND     EAX,$0000FF00
    1408         SHR     EDX,24
    1409         MOV     CL,DL
    1410         NOP
    1411         NOP
    1412         NOP
    1413 
    1414         // EDI <- PF
    1415         // EDX <- PB
    1416         // ESI <- PR
    1417 
    1418         // PF := @DivTable[F.A];
    1419         LEA     EDI,[EAX+DivTable]
    1420         // PB := @DivTable[B.A];
    1421         SHL     EDX,$08
    1422         LEA     EDX,[EDX+DivTable]
    1423         // Result.A := B.A + F.A - PB[F.A];
    1424         SHR     EAX,8
    1425         //ADD CL,al
    1426         ADD     ECX,EAX
    1427         //SUB CL,[EDX+EAX]
    1428         SUB     ECX,[EDX+EAX]
    1429         MOV     [ESP+$0B],CL
    1430         // PR := @RcTable[Result.A];
    1431         SHL     ECX,$08
    1432         AND     ECX,$0000FFFF
    1433         LEA     ESI,[ECX+RcTable]
    1434 
    1435   { Red component }
    1436 
    1437         // Result.R := PB[B.R];
    1438         XOR     EAX,EAX
    1439         MOV     AL,[ESP+$06]
    1440         MOV     CL,[EDX+EAX]
    1441         MOV     [ESP+$0a],CL
    1442         // X := F.R - Result.R;
    1443         MOV     AL,[ESP+$02]
    1444         XOR     EBX,EBX
    1445         MOV     BL,CL
    1446         SUB     EAX,EBX
    1447         // if X >= 0 then
    1448         JL      @5
    1449         // Result.R := PR[PF[X] + Result.R]
    1450         MOVZX   EAX,BYTE PTR[EDI+EAX]
    1451         AND     ECX,$000000FF
    1452         ADD     EAX,ECX
    1453         MOV     AL,[ESI+EAX]
    1454         MOV     [ESP+$0a],al
    1455         JMP     @6
    1456 @5:
    1457         // Result.R := PR[Result.R - PF[-X]];
    1458         NEG     EAX
    1459         MOVZX   EAX,BYTE PTR[EDI+EAX]
    1460         XOR     ECX,ECX
    1461         MOV     CL,[ESP+$0A]
    1462         SUB     ECX,EAX
    1463         MOV     AL,[ESI+ECX]
    1464         MOV     [ESP+$0A],al
    1465 
    1466 
    1467   { Green component }
    1468 
    1469 @6:
    1470   // Result.G := PB[B.G];
    1471         XOR     EAX,EAX
    1472         MOV     AL,[ESP+$05]
    1473         MOV     CL,[EDX+EAX]
    1474         MOV     [ESP+$09],CL
    1475   // X := F.G - Result.G;
    1476         MOV     AL,[ESP+$01]
    1477         XOR     EBX,EBX
    1478         MOV     BL,CL
    1479         SUB     EAX,EBX
    1480   // if X >= 0 then
    1481         JL      @7
    1482   // Result.G := PR[PF[X] + Result.G]
    1483         MOVZX   EAX,BYTE PTR[EDI+EAX]
    1484         AND     ECX,$000000FF
    1485         ADD     EAX,ECX
    1486         MOV     AL,[ESI+EAX]
    1487         MOV     [ESP+$09],AL
    1488         JMP     @8
    1489 @7:
    1490   // Result.G := PR[Result.G - PF[-X]];
    1491         NEG     EAX
    1492         MOVZX   EAX,BYTE PTR[EDI+EAX]
    1493         XOR     ECX,ECX
    1494         MOV     CL,[ESP+$09]
    1495         SUB     ECX,EAX
    1496         MOV     AL,[ESI+ECX]
    1497         MOV     [ESP+$09],AL
    1498 
    1499 
    1500   { Blue component }
    1501 @8:
    1502   // Result.B := PB[B.B];
    1503         XOR     EAX,EAX
    1504         MOV     AL,[ESP+$04]
    1505         MOV     CL,[EDX+EAX]
    1506         MOV     [ESP+$08],CL
    1507   // X := F.B - Result.B;
    1508         MOV     AL,[ESP]
    1509         XOR     EDX,EDX
    1510         MOV     DL,CL
    1511         SUB     EAX,EDX
    1512   // if X >= 0 then
    1513         JL      @9
    1514   // Result.B := PR[PF[X] + Result.B]
    1515         MOVZX   EAX,BYTE PTR[EDI+EAX]
    1516         XOR     EDX,EDX
    1517         MOV     DL,CL
    1518         ADD     EAX,EDX
    1519         MOV     AL,[ESI+EAX]
    1520         MOV     [ESP+$08],al
    1521         JMP     @10
    1522 @9:
    1523   // Result.B := PR[Result.B - PF[-X]];
    1524         NEG     EAX
    1525         MOVZX   EAX,BYTE PTR[EDI+EAX]
    1526         XOR     EDX,EDX
    1527         MOV     DL,CL
    1528         SUB     EDX,EAX
    1529         MOV     AL,[ESI+EDX]
    1530         MOV     [ESP+$08],AL
    1531 
    1532 @10:
    1533   // EAX <- Result
    1534         MOV     EAX,[ESP+$08]
    1535 
    1536   // end;
    1537         ADD     ESP,$0C
    1538         POP     EDI
    1539         POP     ESI
    1540         POP     EBX
    1541 {$IFDEF FPC}
    1542         JMP @Exit
    1543 {$ELSE}
    1544         RET
    1545 {$ENDIF}
    1546 @blend:
    1547         CALL    DWORD PTR [BlendReg]
    1548         OR      EAX,$FF000000
    1549 {$IFDEF FPC}
    1550         JMP @Exit
    1551 {$ELSE}
    1552         RET
    1553 {$ENDIF}
    1554 @exit0:
    1555         MOV     EAX,EDX
    1556 @Exit:
    1557 end;
    1558 
    1559 {$ENDIF}
    1560 
    1561 function CombineReg_ASM(X, Y, W: TColor32): TColor32;
    1562 asm
    1563   // combine RGBA channels of colors X and Y with the weight of X given in W
    1564   // Result Z = W * X + (1 - W) * Y (all channels are combined, including alpha)
    1565 {$IFDEF TARGET_x86}
    1566   // EAX <- X
    1567   // EDX <- Y
    1568   // ECX <- W
    1569 
    1570   // W = 0 or $FF?
    1571         JCXZ    @1              // CX = 0 ?  => Result := EDX
    1572         CMP     ECX,$FF         // CX = $FF ?  => Result := EDX
    1573         JE      @2
    1574 
    1575         PUSH    EBX
    1576 
    1577   // P = W * X
    1578         MOV     EBX,EAX         // EBX  <-  Xa Xr Xg Xb
    1579         AND     EAX,$00FF00FF   // EAX  <-  00 Xr 00 Xb
    1580         AND     EBX,$FF00FF00   // EBX  <-  Xa 00 Xg 00
    1581         IMUL    EAX,ECX         // EAX  <-  Pr ** Pb **
    1582         SHR     EBX,8           // EBX  <-  00 Xa 00 Xg
    1583         IMUL    EBX,ECX         // EBX  <-  Pa ** Pg **
    1584         ADD     EAX,bias
    1585         AND     EAX,$FF00FF00   // EAX  <-  Pa 00 Pg 00
    1586         SHR     EAX,8           // EAX  <-  00 Pr 00 Pb
    1587         ADD     EBX,bias
    1588         AND     EBX,$FF00FF00   // EBX  <-  Pa 00 Pg 00
    1589         OR      EAX,EBX         // EAX  <-  Pa Pr Pg Pb
    1590 
    1591   // W = 1 - W; Q = W * Y
    1592         XOR     ECX,$000000FF   // ECX  <-  1 - ECX
    1593         MOV     EBX,EDX         // EBX  <-  Ya Yr Yg Yb
    1594         AND     EDX,$00FF00FF   // EDX  <-  00 Yr 00 Yb
    1595         AND     EBX,$FF00FF00   // EBX  <-  Ya 00 Yg 00
    1596         IMUL    EDX,ECX         // EDX  <-  Qr ** Qb **
    1597         SHR     EBX,8           // EBX  <-  00 Ya 00 Yg
    1598         IMUL    EBX,ECX         // EBX  <-  Qa ** Qg **
    1599         ADD     EDX,bias
    1600         AND     EDX,$FF00FF00   // EDX  <-  Qr 00 Qb 00
    1601         SHR     EDX,8           // EDX  <-  00 Qr ** Qb
    1602         ADD     EBX,bias
    1603         AND     EBX,$FF00FF00   // EBX  <-  Qa 00 Qg 00
    1604         OR      EBX,EDX         // EBX  <-  Qa Qr Qg Qb
    1605 
    1606   // Z = P + Q (assuming no overflow at each byte)
    1607         ADD     EAX,EBX         // EAX  <-  Za Zr Zg Zb
    1608 
    1609         POP     EBX
    1610 {$IFDEF FPC}
    1611         JMP @2
    1612 {$ELSE}
    1613         RET
    1614 {$ENDIF}
    1615 
    1616 @1:     MOV     EAX,EDX
    1617 @2:
    1618 {$ENDIF}
    1619 
    1620 {$IFDEF TARGET_x64}
    1621   // ECX <- X
    1622   // EDX <- Y
    1623   // R8D <- W
    1624 
    1625   // W = 0 or $FF?
    1626         TEST    R8D,R8D
    1627         JZ      @1              // W = 0 ?  => Result := EDX
    1628         MOV     EAX,ECX         // EAX  <-  Xa Xr Xg Xb
    1629         CMP     R8B,$FF         // W = $FF ?  => Result := EDX
    1630         JE      @2
    1631 
    1632   // P = W * X
    1633         AND     EAX,$00FF00FF   // EAX  <-  00 Xr 00 Xb
    1634         AND     ECX,$FF00FF00   // ECX  <-  Xa 00 Xg 00
    1635         IMUL    EAX,R8D         // EAX  <-  Pr ** Pb **
    1636         SHR     ECX,8           // ECX  <-  00 Xa 00 Xg
    1637         IMUL    ECX,R8D         // ECX  <-  Pa ** Pg **
    1638         ADD     EAX,bias
    1639         AND     EAX,$FF00FF00   // EAX  <-  Pa 00 Pg 00
    1640         SHR     EAX,8           // EAX  <-  00 Pr 00 Pb
    1641         ADD     ECX,bias
    1642         AND     ECX,$FF00FF00   // ECX  <-  Pa 00 Pg 00
    1643         OR      EAX,ECX         // EAX  <-  Pa Pr Pg Pb
    1644 
    1645   // W = 1 - W; Q = W * Y
    1646         XOR     R8D,$000000FF   // R8D  <-  1 - R8D
    1647         MOV     ECX,EDX         // ECX  <-  Ya Yr Yg Yb
    1648         AND     EDX,$00FF00FF   // EDX  <-  00 Yr 00 Yb
    1649         AND     ECX,$FF00FF00   // ECX  <-  Ya 00 Yg 00
    1650         IMUL    EDX,R8D         // EDX  <-  Qr ** Qb **
    1651         SHR     ECX,8           // ECX  <-  00 Ya 00 Yg
    1652         IMUL    ECX,R8D         // ECX  <-  Qa ** Qg **
    1653         ADD     EDX,bias
    1654         AND     EDX,$FF00FF00   // EDX  <-  Qr 00 Qb 00
    1655         SHR     EDX,8           // EDX  <-  00 Qr ** Qb
    1656         ADD     ECX,bias
    1657         AND     ECX,$FF00FF00   // ECX  <-  Qa 00 Qg 00
    1658         OR      ECX,EDX         // ECX  <-  Qa Qr Qg Qb
    1659 
    1660   // Z = P + Q (assuming no overflow at each byte)
    1661         ADD     EAX,ECX         // EAX  <-  Za Zr Zg Zb
    1662 
    1663 {$IFDEF FPC}
    1664         JMP @2
    1665 {$ELSE}
    1666         RET
    1667 {$ENDIF}
    1668 
    1669 @1:     MOV     EAX,EDX
    1670 @2:
    1671 {$ENDIF}
    1672 end;
    1673 
    1674 procedure CombineMem_ASM(X: TColor32; var Y: TColor32; W: TColor32);
    1675 asm
    1676 {$IFDEF TARGET_x86}
    1677   // EAX <- F
    1678   // [EDX] <- B
    1679   // ECX <- W
    1680 
    1681   // Check W
    1682         JCXZ    @1              // W = 0 ?  => write nothing
    1683         CMP     ECX,$FF         // W = 255? => write F
    1684 {$IFDEF FPC}
    1685         DB      $74,$76         //Prob with FPC 2.2.2 and below
    1686 {$ELSE}
    1687         JZ      @2
    1688 {$ENDIF}
    1689 
    1690 
    1691         PUSH    EBX
    1692         PUSH    ESI
    1693 
    1694   // P = W * F
    1695         MOV     EBX,EAX         // EBX  <-  ** Fr Fg Fb
    1696         AND     EAX,$00FF00FF   // EAX  <-  00 Fr 00 Fb
    1697         AND     EBX,$FF00FF00   // EBX  <-  Fa 00 Fg 00
    1698         IMUL    EAX,ECX         // EAX  <-  Pr ** Pb **
    1699         SHR     EBX,8           // EBX  <-  00 Fa 00 Fg
    1700         IMUL    EBX,ECX         // EBX  <-  00 00 Pg **
    1701         ADD     EAX,bias
    1702         AND     EAX,$FF00FF00   // EAX  <-  Pr 00 Pb 00
    1703         SHR     EAX,8           // EAX  <-  00 Pr 00 Pb
    1704         ADD     EBX,bias
    1705         AND     EBX,$FF00FF00   // EBX  <-  Pa 00 Pg 00
    1706         OR      EAX,EBX         // EAX  <-  00 Pr Pg Pb
    1707 
    1708   // W = 1 - W; Q = W * B
    1709         MOV     ESI,[EDX]
    1710         XOR     ECX,$000000FF   // ECX  <-  1 - ECX
    1711         MOV     EBX,ESI         // EBX  <-  Ba Br Bg Bb
    1712         AND     ESI,$00FF00FF   // ESI  <-  00 Br 00 Bb
    1713         AND     EBX,$FF00FF00   // EBX  <-  Ba 00 Bg 00
    1714         IMUL    ESI,ECX         // ESI  <-  Qr ** Qb **
    1715         SHR     EBX,8           // EBX  <-  00 Ba 00 Bg
    1716         IMUL    EBX,ECX         // EBX  <-  Qa 00 Qg **
    1717         ADD     ESI,bias
    1718         AND     ESI,$FF00FF00   // ESI  <-  Qr 00 Qb 00
    1719         SHR     ESI,8           // ESI  <-  00 Qr ** Qb
    1720         ADD     EBX,bias
    1721         AND     EBX,$FF00FF00   // EBX  <-  Qa 00 Qg 00
    1722         OR      EBX,ESI         // EBX  <-  00 Qr Qg Qb
    1723 
    1724   // Z = P + Q (assuming no overflow at each byte)
    1725         ADD     EAX,EBX         // EAX  <-  00 Zr Zg Zb
    1726 
    1727         MOV     [EDX],EAX
    1728 
    1729         POP     ESI
    1730         POP     EBX
    1731 {$IFDEF FPC}
    1732 @1:     JMP @3
    1733 {$ELSE}
    1734 @1:     RET
    1735 {$ENDIF}
    1736 
    1737 @2:     MOV     [EDX],EAX
    1738 @3:
    1739 {$ENDIF}
    1740 
    1741 {$IFDEF TARGET_x64}
    1742   // ECX <- F
    1743   // [RDX] <- B
    1744   // R8 <- W
    1745 
    1746   // Check W
    1747         TEST    R8D,R8D         // Set flags for R8
    1748         JZ      @2              // W = 0 ?  => Result := EDX
    1749         MOV     EAX,ECX         // EAX  <-  ** Fr Fg Fb
    1750         CMP     R8B,$FF         // W = 255? => write F
    1751         JZ      @1
    1752 
    1753   // P = W * F
    1754         AND     EAX,$00FF00FF   // EAX  <-  00 Fr 00 Fb
    1755         AND     ECX,$FF00FF00   // ECX  <-  Fa 00 Fg 00
    1756         IMUL    EAX,R8D         // EAX  <-  Pr ** Pb **
    1757         SHR     ECX,8           // ECX  <-  00 Fa 00 Fg
    1758         IMUL    ECX,R8D         // ECX  <-  00 00 Pg **
    1759         ADD     EAX,bias
    1760         AND     EAX,$FF00FF00   // EAX  <-  Pr 00 Pb 00
    1761         SHR     EAX,8           // EAX  <-  00 Pr 00 Pb
    1762         ADD     ECX,bias
    1763         AND     ECX,$FF00FF00   // ECX  <-  Pa 00 Pg 00
    1764         OR      EAX,ECX         // EAX  <-  00 Pr Pg Pb
    1765 
    1766   // W = 1 - W; Q = W * B
    1767         MOV     R9D,[RDX]
    1768         XOR     R8D,$000000FF   // R8D  <-  1 - R8D
    1769         MOV     ECX,R9D         // ECX  <-  Ba Br Bg Bb
    1770         AND     R9D,$00FF00FF   // R9D  <-  00 Br 00 Bb
    1771         AND     ECX,$FF00FF00   // ECX  <-  Ba 00 Bg 00
    1772         IMUL    R9D,R8D         // R9D  <-  Qr ** Qb **
    1773         SHR     ECX,8           // ECX  <-  00 Ba 00 Bg
    1774         IMUL    ECX,R8D         // ECX  <-  Qa 00 Qg **
    1775         ADD     R9D,bias
    1776         AND     R9D,$FF00FF00   // R9D  <-  Qr 00 Qb 00
    1777         SHR     R9D,8           // R9D  <-  00 Qr ** Qb
    1778         ADD     ECX,bias
    1779         AND     ECX,$FF00FF00   // ECX  <-  Qa 00 Qg 00
    1780         OR      ECX,R9D         // ECX  <-  00 Qr Qg Qb
    1781 
    1782   // Z = P + Q (assuming no overflow at each byte)
    1783         ADD     EAX,ECX         // EAX  <-  00 Zr Zg Zb
    1784 
    1785 @1:     MOV     [RDX],EAX
    1786 @2:
    1787 
    1788 {$ENDIF}
    1789 end;
    1790 
    1791 procedure EMMS_ASM;
    1792 asm
    1793 end;
    1794859
    1795860procedure GenAlphaTable;
     
    1830895  FreeMem(AlphaTable);
    1831896end;
    1832 
    1833 {$IFNDEF OMIT_MMX}
    1834 
    1835 { MMX versions }
    1836 
    1837 function BlendReg_MMX(F, B: TColor32): TColor32;
    1838 asm
    1839   // blend foreground color (F) to a background color (B),
    1840   // using alpha channel value of F
    1841 {$IFDEF TARGET_x86}
    1842   // EAX <- F
    1843   // EDX <- B
    1844   // Result := Fa * (Frgb - Brgb) + Brgb
    1845         MOVD      MM0,EAX
    1846         PXOR      MM3,MM3
    1847         MOVD      MM2,EDX
    1848         PUNPCKLBW MM0,MM3
    1849         MOV       ECX,bias_ptr
    1850         PUNPCKLBW MM2,MM3
    1851         MOVQ      MM1,MM0
    1852         PUNPCKHWD MM1,MM1
    1853         PSUBW     MM0,MM2
    1854         PUNPCKHDQ MM1,MM1
    1855         PSLLW     MM2,8
    1856         PMULLW    MM0,MM1
    1857         PADDW     MM2,[ECX]
    1858         PADDW     MM2,MM0
    1859         PSRLW     MM2,8
    1860         PACKUSWB  MM2,MM3
    1861         MOVD      EAX,MM2
    1862 {$ENDIF}
    1863 
    1864 {$IFDEF TARGET_x64}
    1865   // ECX <- F
    1866   // EDX <- B
    1867   // Result := Fa * (Frgb - Brgb) + Brgb
    1868         MOVD      MM0,ECX
    1869         PXOR      MM3,MM3
    1870         MOVD      MM2,EDX
    1871         PUNPCKLBW MM0,MM3
    1872         MOV       RAX,bias_ptr
    1873         PUNPCKLBW MM2,MM3
    1874         MOVQ      MM1,MM0
    1875         PUNPCKHWD MM1,MM1
    1876         PSUBW     MM0,MM2
    1877         PUNPCKHDQ MM1,MM1
    1878         PSLLW     MM2,8
    1879         PMULLW    MM0,MM1
    1880         PADDW     MM2,[RAX]
    1881         PADDW     MM2,MM0
    1882         PSRLW     MM2,8
    1883         PACKUSWB  MM2,MM3
    1884         MOVD      EAX,MM2
    1885 {$ENDIF}
    1886 end;
    1887 
    1888 {$IFDEF TARGET_x86}
    1889 
    1890 procedure BlendMem_MMX(F: TColor32; var B: TColor32);
    1891 asm
    1892   // EAX - Color X
    1893   // [EDX] - Color Y
    1894   // Result := W * (X - Y) + Y
    1895 
    1896         TEST      EAX,$FF000000
    1897         JZ        @1
    1898         CMP       EAX,$FF000000
    1899         JNC       @2
    1900 
    1901         PXOR      MM3,MM3
    1902         MOVD      MM0,EAX
    1903         MOVD      MM2,[EDX]
    1904         PUNPCKLBW MM0,MM3
    1905         MOV       ECX,bias_ptr
    1906         PUNPCKLBW MM2,MM3
    1907         MOVQ      MM1,MM0
    1908         PUNPCKHWD MM1,MM1
    1909         PSUBW     MM0,MM2
    1910         PUNPCKHDQ MM1,MM1
    1911         PSLLW     MM2,8
    1912         PMULLW    MM0,MM1
    1913         PADDW     MM2,[ECX]
    1914         PADDW     MM2,MM0
    1915         PSRLW     MM2,8
    1916         PACKUSWB  MM2,MM3
    1917         MOVD      [EDX],MM2
    1918 
    1919 {$IFDEF FPC}
    1920 @1:     JMP @3
    1921 {$ELSE}
    1922 @1:     RET
    1923 {$ENDIF}
    1924 
    1925 @2:     MOV       [EDX],EAX
    1926 @3:
    1927 end;
    1928 
    1929 function BlendRegEx_MMX(F, B, M: TColor32): TColor32;
    1930 asm
    1931   // blend foreground color (F) to a background color (B),
    1932   // using alpha channel value of F
    1933   // EAX <- F
    1934   // EDX <- B
    1935   // ECX <- M
    1936   // Result := M * Fa * (Frgb - Brgb) + Brgb
    1937         PUSH      EBX
    1938         MOV       EBX,EAX
    1939         SHR       EBX,24
    1940         INC       ECX             // 255:256 range bias
    1941         IMUL      ECX,EBX
    1942         SHR       ECX,8
    1943         JZ        @1
    1944 
    1945         PXOR      MM0,MM0
    1946         MOVD      MM1,EAX
    1947         SHL       ECX,4
    1948         MOVD      MM2,EDX
    1949         PUNPCKLBW MM1,MM0
    1950         PUNPCKLBW MM2,MM0
    1951         ADD       ECX,alpha_ptr
    1952         PSUBW     MM1,MM2
    1953         PMULLW    MM1,[ECX]
    1954         PSLLW     MM2,8
    1955         MOV       ECX,bias_ptr
    1956         PADDW     MM2,[ECX]
    1957         PADDW     MM1,MM2
    1958         PSRLW     MM1,8
    1959         PACKUSWB  MM1,MM0
    1960         MOVD      EAX,MM1
    1961 
    1962         POP       EBX
    1963 {$IFDEF FPC}
    1964         JMP @2
    1965 {$ELSE}
    1966         RET
    1967 {$ENDIF}
    1968 
    1969 @1:     MOV       EAX,EDX
    1970         POP       EBX
    1971 @2:
    1972 end;
    1973 
    1974 {$ENDIF}
    1975 
    1976 procedure BlendMemEx_MMX(F: TColor32; var B:TColor32; M: TColor32);
    1977 asm
    1978 {$IFDEF TARGET_x86}
    1979   // blend foreground color (F) to a background color (B),
    1980   // using alpha channel value of F
    1981   // EAX <- F
    1982   // [EDX] <- B
    1983   // ECX <- M
    1984   // Result := M * Fa * (Frgb - Brgb) + Brgb
    1985         TEST      EAX,$FF000000
    1986         JZ        @2
    1987 
    1988         PUSH      EBX
    1989         MOV       EBX,EAX
    1990         SHR       EBX,24
    1991         INC       ECX             // 255:256 range bias
    1992         IMUL      ECX,EBX
    1993         SHR       ECX,8
    1994         JZ        @1
    1995 
    1996         PXOR      MM0,MM0
    1997         MOVD      MM1,EAX
    1998         SHL       ECX,4
    1999         MOVD      MM2,[EDX]
    2000         PUNPCKLBW MM1,MM0
    2001         PUNPCKLBW MM2,MM0
    2002         ADD       ECX,alpha_ptr
    2003         PSUBW     MM1,MM2
    2004         PMULLW    MM1,[ECX]
    2005         PSLLW     MM2,8
    2006         MOV       ECX,bias_ptr
    2007         PADDW     MM2,[ECX]
    2008         PADDW     MM1,MM2
    2009         PSRLW     MM1,8
    2010         PACKUSWB  MM1,MM0
    2011         MOVD      [EDX],MM1
    2012 
    2013 @1:     POP       EBX
    2014 
    2015 @2:
    2016 {$ENDIF}
    2017 
    2018 {$IFDEF TARGET_x64}
    2019   // blend foreground color (F) to a background color (B),
    2020   // using alpha channel value of F
    2021   // ECX <- F
    2022   // [EDX] <- B
    2023   // R8 <- M
    2024   // Result := M * Fa * (Frgb - Brgb) + Brgb
    2025         TEST      ECX,$FF000000
    2026         JZ        @1
    2027 
    2028         MOV       EAX,ECX
    2029         SHR       EAX,24
    2030         INC       R8D             // 255:256 range bias
    2031         IMUL      R8D,EAX
    2032         SHR       R8D,8
    2033         JZ        @1
    2034 
    2035         PXOR      MM0,MM0
    2036         MOVD      MM1,ECX
    2037         SHL       R8D,4
    2038         MOVD      MM2,[RDX]
    2039         PUNPCKLBW MM1,MM0
    2040         PUNPCKLBW MM2,MM0
    2041         ADD       R8,alpha_ptr
    2042         PSUBW     MM1,MM2
    2043         PMULLW    MM1,[R8]
    2044         PSLLW     MM2,8
    2045         MOV       RAX,bias_ptr
    2046         PADDW     MM2,[RAX]
    2047         PADDW     MM1,MM2
    2048         PSRLW     MM1,8
    2049         PACKUSWB  MM1,MM0
    2050         MOVD      [RDX],MM1
    2051 
    2052 @1:
    2053 {$ENDIF}
    2054 end;
    2055 
    2056 {$IFDEF TARGET_x86}
    2057 procedure BlendLine_MMX(Src, Dst: PColor32; Count: Integer);
    2058 asm
    2059   // EAX <- Src
    2060   // EDX <- Dst
    2061   // ECX <- Count
    2062 
    2063   // test the counter for zero or negativity
    2064         TEST      ECX,ECX
    2065         JS        @4
    2066 
    2067         PUSH      ESI
    2068         PUSH      EDI
    2069 
    2070         MOV       ESI,EAX         // ESI <- Src
    2071         MOV       EDI,EDX         // EDI <- Dst
    2072 
    2073   // loop start
    2074 @1:     MOV       EAX,[ESI]
    2075         TEST      EAX,$FF000000
    2076         JZ        @3              // complete transparency, proceed to next point
    2077         CMP       EAX,$FF000000
    2078         JNC       @2              // opaque pixel, copy without blending
    2079 
    2080   // blend
    2081         MOVD      MM0,EAX         // MM0  <-  00 00 00 00 Fa Fr Fg Fb
    2082         PXOR      MM3,MM3         // MM3  <-  00 00 00 00 00 00 00 00
    2083         MOVD      MM2,[EDI]       // MM2  <-  00 00 00 00 Ba Br Bg Bb
    2084         PUNPCKLBW MM0,MM3         // MM0  <-  00 Fa 00 Fr 00 Fg 00 Fb
    2085         MOV       EAX,bias_ptr
    2086         PUNPCKLBW MM2,MM3         // MM2  <-  00 Ba 00 Br 00 Bg 00 Bb
    2087         MOVQ      MM1,MM0         // MM1  <-  00 Fa 00 Fr 00 Fg 00 Fb
    2088         PUNPCKHWD MM1,MM1         // MM1  <-  00 Fa 00 Fa 00 ** 00 **
    2089         PSUBW     MM0,MM2         // MM0  <-  00 Da 00 Dr 00 Dg 00 Db
    2090         PUNPCKHDQ MM1,MM1         // MM1  <-  00 Fa 00 Fa 00 Fa 00 Fa
    2091         PSLLW     MM2,8           // MM2  <-  Ba 00 Br 00 Bg 00 Bb 00
    2092         PMULLW    MM0,MM1         // MM2  <-  Pa ** Pr ** Pg ** Pb **
    2093         PADDW     MM2,[EAX]       // add bias
    2094         PADDW     MM2,MM0         // MM2  <-  Qa ** Qr ** Qg ** Qb **
    2095         PSRLW     MM2,8           // MM2  <-  00 Qa 00 Qr 00 Qg 00 Qb
    2096         PACKUSWB  MM2,MM3         // MM2  <-  00 00 00 00 Qa Qr Qg Qb
    2097         MOVD      EAX,MM2
    2098 
    2099 @2:     MOV       [EDI],EAX
    2100 
    2101 @3:     ADD       ESI,4
    2102         ADD       EDI,4
    2103 
    2104   // loop end
    2105         DEC       ECX
    2106         JNZ       @1
    2107 
    2108         POP       EDI
    2109         POP       ESI
    2110 
    2111 @4:
    2112 end;
    2113 
    2114 procedure BlendLineEx_MMX(Src, Dst: PColor32; Count: Integer; M: TColor32);
    2115 asm
    2116   // EAX <- Src
    2117   // EDX <- Dst
    2118   // ECX <- Count
    2119 
    2120   // test the counter for zero or negativity
    2121         TEST      ECX,ECX
    2122         JS        @4
    2123 
    2124         PUSH      ESI
    2125         PUSH      EDI
    2126         PUSH      EBX
    2127 
    2128         MOV       ESI,EAX         // ESI <- Src
    2129         MOV       EDI,EDX         // EDI <- Dst
    2130         MOV       EDX,M           // EDX <- Master Alpha
    2131 
    2132   // loop start
    2133 @1:     MOV       EAX,[ESI]
    2134         TEST      EAX,$FF000000
    2135         JZ        @3             // complete transparency, proceed to next point
    2136         MOV       EBX,EAX
    2137         SHR       EBX,24
    2138         INC       EBX            // 255:256 range bias
    2139         IMUL      EBX,EDX
    2140         SHR       EBX,8
    2141         JZ        @3              // complete transparency, proceed to next point
    2142 
    2143   // blend
    2144         PXOR      MM0,MM0
    2145         MOVD      MM1,EAX
    2146         SHL       EBX,4
    2147         MOVD      MM2,[EDI]
    2148         PUNPCKLBW MM1,MM0
    2149         PUNPCKLBW MM2,MM0
    2150         ADD       EBX,alpha_ptr
    2151         PSUBW     MM1,MM2
    2152         PMULLW    MM1,[EBX]
    2153         PSLLW     MM2,8
    2154         MOV       EBX,bias_ptr
    2155         PADDW     MM2,[EBX]
    2156         PADDW     MM1,MM2
    2157         PSRLW     MM1,8
    2158         PACKUSWB  MM1,MM0
    2159         MOVD      EAX,MM1
    2160 
    2161 @2:     MOV       [EDI],EAX
    2162 
    2163 @3:     ADD       ESI,4
    2164         ADD       EDI,4
    2165 
    2166   // loop end
    2167         DEC       ECX
    2168         JNZ       @1
    2169 
    2170         POP       EBX
    2171         POP       EDI
    2172         POP       ESI
    2173 @4:
    2174 end;
    2175 
    2176 {$ENDIF}
    2177 
    2178 function CombineReg_MMX(X, Y, W: TColor32): TColor32;
    2179 asm
    2180 {$IFDEF TARGET_X86}
    2181   // EAX - Color X
    2182   // EDX - Color Y
    2183   // ECX - Weight of X [0..255]
    2184   // Result := W * (X - Y) + Y
    2185 
    2186         MOVD      MM1,EAX
    2187         PXOR      MM0,MM0
    2188         SHL       ECX,4
    2189 
    2190         MOVD      MM2,EDX
    2191         PUNPCKLBW MM1,MM0
    2192         PUNPCKLBW MM2,MM0
    2193 
    2194         ADD       ECX,alpha_ptr
    2195 
    2196         PSUBW     MM1,MM2
    2197         PMULLW    MM1,[ECX]
    2198         PSLLW     MM2,8
    2199 
    2200         MOV       ECX,bias_ptr
    2201 
    2202         PADDW     MM2,[ECX]
    2203         PADDW     MM1,MM2
    2204         PSRLW     MM1,8
    2205         PACKUSWB  MM1,MM0
    2206         MOVD      EAX,MM1
    2207 {$ENDIF}
    2208 
    2209 {$IFDEF TARGET_X64}
    2210   // ECX - Color X
    2211   // EDX - Color Y
    2212   // R8 - Weight of X [0..255]
    2213   // Result := W * (X - Y) + Y
    2214 
    2215         MOVD      MM1,ECX
    2216         PXOR      MM0,MM0
    2217         SHL       R8D,4
    2218 
    2219         MOVD      MM2,EDX
    2220         PUNPCKLBW MM1,MM0
    2221         PUNPCKLBW MM2,MM0
    2222 
    2223         ADD       R8,alpha_ptr
    2224 
    2225         PSUBW     MM1,MM2
    2226         PMULLW    MM1,[R8]
    2227         PSLLW     MM2,8
    2228 
    2229         MOV       RAX,bias_ptr
    2230 
    2231         PADDW     MM2,[RAX]
    2232         PADDW     MM1,MM2
    2233         PSRLW     MM1,8
    2234         PACKUSWB  MM1,MM0
    2235         MOVD      EAX,MM1
    2236 {$ENDIF}
    2237 end;
    2238 
    2239 procedure CombineMem_MMX(F: TColor32; var B: TColor32; W: TColor32);
    2240 asm
    2241 {$IFDEF TARGET_X86}
    2242   // EAX - Color X
    2243   // [EDX] - Color Y
    2244   // ECX - Weight of X [0..255]
    2245   // Result := W * (X - Y) + Y
    2246 
    2247         JCXZ      @1
    2248         CMP       ECX,$FF
    2249         JZ        @2
    2250 
    2251         MOVD      MM1,EAX
    2252         PXOR      MM0,MM0
    2253 
    2254         SHL       ECX,4
    2255 
    2256         MOVD      MM2,[EDX]
    2257         PUNPCKLBW MM1,MM0
    2258         PUNPCKLBW MM2,MM0
    2259 
    2260         ADD       ECX,alpha_ptr
    2261 
    2262         PSUBW     MM1,MM2
    2263         PMULLW    MM1,[ECX]
    2264         PSLLW     MM2,8
    2265 
    2266         MOV       ECX,bias_ptr
    2267 
    2268         PADDW     MM2,[ECX]
    2269         PADDW     MM1,MM2
    2270         PSRLW     MM1,8
    2271         PACKUSWB  MM1,MM0
    2272         MOVD      [EDX],MM1
    2273 
    2274 {$IFDEF FPC}
    2275 @1:     JMP @3
    2276 {$ELSE}
    2277 @1:     RET
    2278 {$ENDIF}
    2279 
    2280 @2:     MOV       [EDX],EAX
    2281 @3:
    2282 {$ENDIF}
    2283 
    2284 {$IFDEF TARGET_x64}
    2285   // ECX - Color X
    2286   // [RDX] - Color Y
    2287   // R8 - Weight of X [0..255]
    2288   // Result := W * (X - Y) + Y
    2289 
    2290         TEST      R8D,R8D            // Set flags for R8
    2291         JZ        @1                 // W = 0 ?  => Result := EDX
    2292         CMP       R8D,$FF
    2293         JZ        @2
    2294 
    2295         MOVD      MM1,ECX
    2296         PXOR      MM0,MM0
    2297 
    2298         SHL       R8D,4
    2299 
    2300         MOVD      MM2,[RDX]
    2301         PUNPCKLBW MM1,MM0
    2302         PUNPCKLBW MM2,MM0
    2303 
    2304         ADD       R8,alpha_ptr
    2305 
    2306         PSUBW     MM1,MM2
    2307         PMULLW    MM1,[R8]
    2308         PSLLW     MM2,8
    2309 
    2310         MOV       RAX,bias_ptr
    2311 
    2312         PADDW     MM2,[RAX]
    2313         PADDW     MM1,MM2
    2314         PSRLW     MM1,8
    2315         PACKUSWB  MM1,MM0
    2316         MOVD      [RDX],MM1
    2317 
    2318 {$IFDEF FPC}
    2319 @1:     JMP @3
    2320 {$ELSE}
    2321 @1:     RET
    2322 {$ENDIF}
    2323 
    2324 @2:     MOV       [RDX],RCX
    2325 @3:
    2326 {$ENDIF}
    2327 end;
    2328 
    2329 {$IFDEF TARGET_x86}
    2330 
    2331 procedure CombineLine_MMX(Src, Dst: PColor32; Count: Integer; W: TColor32);
    2332 asm
    2333   // EAX <- Src
    2334   // EDX <- Dst
    2335   // ECX <- Count
    2336 
    2337   // Result := W * (X - Y) + Y
    2338 
    2339         TEST      ECX,ECX
    2340         JS        @3
    2341 
    2342         PUSH      EBX
    2343         MOV       EBX,W
    2344 
    2345         TEST      EBX,EBX
    2346         JZ        @2              // weight is zero
    2347 
    2348         CMP       EBX,$FF
    2349         JZ        @4              // weight = 255  =>  copy src to dst
    2350 
    2351         SHL       EBX,4
    2352         ADD       EBX,alpha_ptr
    2353         MOVQ      MM3,[EBX]
    2354         MOV       EBX,bias_ptr
    2355         MOVQ      MM4,[EBX]
    2356 
    2357    // loop start
    2358 @1:     MOVD      MM1,[EAX]
    2359         PXOR      MM0,MM0
    2360         MOVD      MM2,[EDX]
    2361         PUNPCKLBW MM1,MM0
    2362         PUNPCKLBW MM2,MM0
    2363 
    2364         PSUBW     MM1,MM2
    2365         PMULLW    MM1,MM3
    2366         PSLLW     MM2,8
    2367 
    2368         PADDW     MM2,MM4
    2369         PADDW     MM1,MM2
    2370         PSRLW     MM1,8
    2371         PACKUSWB  MM1,MM0
    2372         MOVD      [EDX],MM1
    2373 
    2374         ADD       EAX,4
    2375         ADD       EDX,4
    2376 
    2377         DEC       ECX
    2378         JNZ       @1
    2379 @2:     POP       EBX
    2380         POP       EBP
    2381 @3:     RET       $0004
    2382 
    2383 @4:     CALL      GR32_LowLevel.MoveLongword
    2384         POP       EBX
    2385 end;
    2386 
    2387 {$ENDIF}
    2388 
    2389 procedure EMMS_MMX;
    2390 asm
    2391   EMMS
    2392 end;
    2393 
    2394 function LightenReg_MMX(C: TColor32; Amount: Integer): TColor32;
    2395 asm
    2396 {$IFDEF TARGET_X86}
    2397         MOVD    MM0,EAX
    2398         TEST    EDX,EDX
    2399         JL      @1
    2400         IMUL    EDX,$010101
    2401         MOVD    MM1,EDX
    2402         PADDUSB MM0,MM1
    2403         MOVD    EAX,MM0
    2404         RET
    2405 @1:     NEG     EDX
    2406         IMUL    EDX,$010101
    2407         MOVD    MM1,EDX
    2408         PSUBUSB MM0,MM1
    2409         MOVD    EAX,MM0
    2410 {$ENDIF}
    2411 
    2412 {$IFDEF TARGET_X64}
    2413         MOVD    MM0,ECX
    2414         TEST    EDX,EDX
    2415         JL      @1
    2416         IMUL    EDX,$010101
    2417         MOVD    MM1,EDX
    2418         PADDUSB MM0,MM1
    2419         MOVD    EAX,MM0
    2420         RET
    2421 @1:     NEG     EDX
    2422         IMUL    EDX,$010101
    2423         MOVD    MM1,EDX
    2424         PSUBUSB MM0,MM1
    2425         MOVD    EAX,MM0
    2426 {$ENDIF}
    2427 end;
    2428 
    2429 { MMX Color algebra versions }
    2430 
    2431 function ColorAdd_MMX(C1, C2: TColor32): TColor32;
    2432 asm
    2433 {$IFDEF TARGET_X86}
    2434         MOVD      MM0,EAX
    2435         MOVD      MM1,EDX
    2436         PADDUSB   MM0,MM1
    2437         MOVD      EAX,MM0
    2438 {$ENDIF}
    2439 
    2440 {$IFDEF TARGET_X64}
    2441         MOVD      MM0,ECX
    2442         MOVD      MM1,EDX
    2443         PADDUSB   MM0,MM1
    2444         MOVD      EAX,MM0
    2445 {$ENDIF}
    2446 end;
    2447 
    2448 function ColorSub_MMX(C1, C2: TColor32): TColor32;
    2449 asm
    2450 {$IFDEF TARGET_X86}
    2451         MOVD      MM0,EAX
    2452         MOVD      MM1,EDX
    2453         PSUBUSB   MM0,MM1
    2454         MOVD      EAX,MM0
    2455 {$ENDIF}
    2456 
    2457 {$IFDEF TARGET_X64}
    2458         MOVD      MM0,ECX
    2459         MOVD      MM1,EDX
    2460         PSUBUSB   MM0,MM1
    2461         MOVD      EAX,MM0
    2462 {$ENDIF}
    2463 end;
    2464 
    2465 function ColorModulate_MMX(C1, C2: TColor32): TColor32;
    2466 asm
    2467 {$IFDEF TARGET_X86}
    2468         PXOR      MM2,MM2
    2469         MOVD      MM0,EAX
    2470         PUNPCKLBW MM0,MM2
    2471         MOVD      MM1,EDX
    2472         PUNPCKLBW MM1,MM2
    2473         PMULLW    MM0,MM1
    2474         PSRLW     MM0,8
    2475         PACKUSWB  MM0,MM2
    2476         MOVD      EAX,MM0
    2477 {$ENDIF}
    2478 
    2479 {$IFDEF TARGET_X64}
    2480         PXOR      MM2,MM2
    2481         MOVD      MM0,ECX
    2482         PUNPCKLBW MM0,MM2
    2483         MOVD      MM1,EDX
    2484         PUNPCKLBW MM1,MM2
    2485         PMULLW    MM0,MM1
    2486         PSRLW     MM0,8
    2487         PACKUSWB  MM0,MM2
    2488         MOVD      EAX,MM0
    2489 {$ENDIF}
    2490 end;
    2491 
    2492 function ColorMax_EMMX(C1, C2: TColor32): TColor32;
    2493 asm
    2494 {$IFDEF TARGET_X86}
    2495         MOVD      MM0,EAX
    2496         MOVD      MM1,EDX
    2497         PMAXUB    MM0,MM1
    2498         MOVD      EAX,MM0
    2499 {$ENDIF}
    2500 
    2501 {$IFDEF TARGET_X64}
    2502         MOVD      MM0,ECX
    2503         MOVD      MM1,EDX
    2504         PMAXUB    MM0,MM1
    2505         MOVD      EAX,MM0
    2506 {$ENDIF}
    2507 end;
    2508 
    2509 function ColorMin_EMMX(C1, C2: TColor32): TColor32;
    2510 asm
    2511 {$IFDEF TARGET_X86}
    2512         MOVD      MM0,EAX
    2513         MOVD      MM1,EDX
    2514         PMINUB    MM0,MM1
    2515         MOVD      EAX,MM0
    2516 {$ENDIF}
    2517 
    2518 {$IFDEF TARGET_X64}
    2519         MOVD      MM0,ECX
    2520         MOVD      MM1,EDX
    2521         PMINUB    MM0,MM1
    2522         MOVD      EAX,MM0
    2523 {$ENDIF}
    2524 end;
    2525 
    2526 function ColorDifference_MMX(C1, C2: TColor32): TColor32;
    2527 asm
    2528 {$IFDEF TARGET_X86}
    2529         MOVD      MM0,EAX
    2530         MOVD      MM1,EDX
    2531         MOVQ      MM2,MM0
    2532         PSUBUSB   MM0,MM1
    2533         PSUBUSB   MM1,MM2
    2534         POR       MM0,MM1
    2535         MOVD      EAX,MM0
    2536 {$ENDIF}
    2537 
    2538 {$IFDEF TARGET_X64}
    2539         MOVD      MM0,ECX
    2540         MOVD      MM1,EDX
    2541         MOVQ      MM2,MM0
    2542         PSUBUSB   MM0,MM1
    2543         PSUBUSB   MM1,MM2
    2544         POR       MM0,MM1
    2545         MOVD      EAX,MM0
    2546 {$ENDIF}
    2547 end;
    2548 
    2549 function ColorExclusion_MMX(C1, C2: TColor32): TColor32;
    2550 asm
    2551 {$IFDEF TARGET_X86}
    2552         PXOR      MM2,MM2
    2553         MOVD      MM0,EAX
    2554         PUNPCKLBW MM0,MM2
    2555         MOVD      MM1,EDX
    2556         PUNPCKLBW MM1,MM2
    2557         MOVQ      MM3,MM0
    2558         PADDW     MM0,MM1
    2559         PMULLW    MM1,MM3
    2560         PSRLW     MM1,7
    2561         PSUBUSW   MM0,MM1
    2562         PACKUSWB  MM0,MM2
    2563         MOVD      EAX,MM0
    2564 {$ENDIF}
    2565 
    2566 {$IFDEF TARGET_X64}
    2567         PXOR      MM2,MM2
    2568         MOVD      MM0,ECX
    2569         PUNPCKLBW MM0,MM2
    2570         MOVD      MM1,EDX
    2571         PUNPCKLBW MM1,MM2
    2572         MOVQ      MM3,MM0
    2573         PADDW     MM0,MM1
    2574         PMULLW    MM1,MM3
    2575         PSRLW     MM1,7
    2576         PSUBUSW   MM0,MM1
    2577         PACKUSWB  MM0,MM2
    2578         MOVD      EAX,MM0
    2579 {$ENDIF}
    2580 end;
    2581 
    2582 function ColorScale_MMX(C, W: TColor32): TColor32;
    2583 asm
    2584 {$IFDEF TARGET_X86}
    2585         PXOR      MM2,MM2
    2586         SHL       EDX,4
    2587         MOVD      MM0,EAX
    2588         PUNPCKLBW MM0,MM2
    2589         ADD       EDX,alpha_ptr
    2590         PMULLW    MM0,[EDX]
    2591         PSRLW     MM0,8
    2592         PACKUSWB  MM0,MM2
    2593         MOVD      EAX,MM0
    2594 {$ENDIF}
    2595 
    2596 {$IFDEF TARGET_X64}
    2597         PXOR      MM2,MM2
    2598         SHL       RDX,4
    2599         MOVD      MM0,ECX
    2600         PUNPCKLBW MM0,MM2
    2601         ADD       RDX,alpha_ptr
    2602         PMULLW    MM0,[RDX]
    2603         PSRLW     MM0,8
    2604         PACKUSWB  MM0,MM2
    2605         MOVD      EAX,MM0
    2606 {$ENDIF}
    2607 end;
    2608 {$ENDIF}
    2609 
    2610 
    2611 { SSE2 versions }
    2612 
    2613 {$IFNDEF OMIT_SSE2}
    2614 
    2615 function BlendReg_SSE2(F, B: TColor32): TColor32;
    2616 asm
    2617   // blend foreground color (F) to a background color (B),
    2618   // using alpha channel value of F
    2619   // EAX <- F
    2620   // EDX <- B
    2621   // Result := Fa * (Frgb - Brgb) + Brgb
    2622 
    2623 {$IFDEF TARGET_x86}
    2624         MOVD      XMM0,EAX
    2625         PXOR      XMM3,XMM3
    2626         MOVD      XMM2,EDX
    2627         PUNPCKLBW XMM0,XMM3
    2628         MOV       ECX,bias_ptr
    2629         PUNPCKLBW XMM2,XMM3
    2630         MOVQ      XMM1,XMM0
    2631         PSHUFLW   XMM1,XMM1, $FF
    2632         PSUBW     XMM0,XMM2
    2633         PSLLW     XMM2,8
    2634         PMULLW    XMM0,XMM1
    2635         PADDW     XMM2,[ECX]
    2636         PADDW     XMM2,XMM0
    2637         PSRLW     XMM2,8
    2638         PACKUSWB  XMM2,XMM3
    2639         MOVD      EAX,XMM2
    2640 {$ENDIF}
    2641 
    2642 {$IFDEF TARGET_x64}
    2643         MOVD      XMM0,ECX
    2644         PXOR      XMM3,XMM3
    2645         MOVD      XMM2,EDX
    2646         PUNPCKLBW XMM0,XMM3
    2647         MOV       RAX,bias_ptr
    2648         PUNPCKLBW XMM2,XMM3
    2649         MOVQ      XMM1,XMM0
    2650         PSHUFLW   XMM1,XMM1, $FF
    2651         PSUBW     XMM0,XMM2
    2652         PSLLW     XMM2,8
    2653         PMULLW    XMM0,XMM1
    2654         PADDW     XMM2,[RAX]
    2655         PADDW     XMM2,XMM0
    2656         PSRLW     XMM2,8
    2657         PACKUSWB  XMM2,XMM3
    2658         MOVD      EAX,XMM2
    2659 {$ENDIF}
    2660 end;
    2661 
    2662 procedure BlendMem_SSE2(F: TColor32; var B: TColor32);
    2663 asm
    2664 {$IFDEF TARGET_x86}
    2665   // EAX - Color X
    2666   // [EDX] - Color Y
    2667   // Result := W * (X - Y) + Y
    2668 
    2669         TEST      EAX,$FF000000
    2670         JZ        @1
    2671         CMP       EAX,$FF000000
    2672         JNC       @2
    2673 
    2674         PXOR      XMM3,XMM3
    2675         MOVD      XMM0,EAX
    2676         MOVD      XMM2,[EDX]
    2677         PUNPCKLBW XMM0,XMM3
    2678         MOV       ECX,bias_ptr
    2679         PUNPCKLBW XMM2,XMM3
    2680         MOVQ      XMM1,XMM0
    2681         PSHUFLW   XMM1,XMM1, $FF
    2682         PSUBW     XMM0,XMM2
    2683         PSLLW     XMM2,8
    2684         PMULLW    XMM0,XMM1
    2685         PADDW     XMM2,[ECX]
    2686         PADDW     XMM2,XMM0
    2687         PSRLW     XMM2,8
    2688         PACKUSWB  XMM2,XMM3
    2689         MOVD      [EDX],XMM2
    2690 
    2691 {$IFDEF FPC}
    2692 @1:     JMP @3
    2693 {$ELSE}
    2694 @1:     RET
    2695 {$ENDIF}
    2696 
    2697 @2:     MOV       [EDX], EAX
    2698 @3:
    2699 {$ENDIF}
    2700 
    2701 {$IFDEF TARGET_x64}
    2702   // ECX - Color X
    2703   // [EDX] - Color Y
    2704   // Result := W * (X - Y) + Y
    2705 
    2706         TEST      ECX,$FF000000
    2707         JZ        @1
    2708         CMP       ECX,$FF000000
    2709         JNC       @2
    2710 
    2711         PXOR      XMM3,XMM3
    2712         MOVD      XMM0,ECX
    2713         MOVD      XMM2,[RDX]
    2714         PUNPCKLBW XMM0,XMM3
    2715         MOV       RAX,bias_ptr
    2716         PUNPCKLBW XMM2,XMM3
    2717         MOVQ      XMM1,XMM0
    2718         PSHUFLW   XMM1,XMM1, $FF
    2719         PSUBW     XMM0,XMM2
    2720         PSLLW     XMM2,8
    2721         PMULLW    XMM0,XMM1
    2722         PADDW     XMM2,[RAX]
    2723         PADDW     XMM2,XMM0
    2724         PSRLW     XMM2,8
    2725         PACKUSWB  XMM2,XMM3
    2726         MOVD      [RDX],XMM2
    2727 
    2728 {$IFDEF FPC}
    2729 @1:     JMP @3
    2730 {$ELSE}
    2731 @1:     RET
    2732 {$ENDIF}
    2733 
    2734 @2:     MOV       [RDX], ECX
    2735 @3:
    2736 {$ENDIF}
    2737 end;
    2738 
    2739 function BlendRegEx_SSE2(F, B, M: TColor32): TColor32;
    2740 asm
    2741   // blend foreground color (F) to a background color (B),
    2742   // using alpha channel value of F
    2743   // Result := M * Fa * (Frgb - Brgb) + Brgb
    2744 
    2745 {$IFDEF TARGET_x86}
    2746   // EAX <- F
    2747   // EDX <- B
    2748   // ECX <- M
    2749         PUSH      EBX
    2750         MOV       EBX,EAX
    2751         SHR       EBX,24
    2752         INC       ECX             // 255:256 range bias
    2753         IMUL      ECX,EBX
    2754         SHR       ECX,8
    2755         JZ        @1
    2756 
    2757         PXOR      XMM0,XMM0
    2758         MOVD      XMM1,EAX
    2759         SHL       ECX,4
    2760         MOVD      XMM2,EDX
    2761         PUNPCKLBW XMM1,XMM0
    2762         PUNPCKLBW XMM2,XMM0
    2763         ADD       ECX,alpha_ptr
    2764         PSUBW     XMM1,XMM2
    2765         PMULLW    XMM1,[ECX]
    2766         PSLLW     XMM2,8
    2767         MOV       ECX,bias_ptr
    2768         PADDW     XMM2,[ECX]
    2769         PADDW     XMM1,XMM2
    2770         PSRLW     XMM1,8
    2771         PACKUSWB  XMM1,XMM0
    2772         MOVD      EAX,XMM1
    2773 
    2774         POP       EBX
    2775 {$IFDEF FPC}
    2776         JMP @2
    2777 {$ELSE}
    2778         RET
    2779 {$ENDIF}
    2780 
    2781 @1:     MOV       EAX,EDX
    2782         POP       EBX
    2783 @2:
    2784 {$ENDIF}
    2785 
    2786 {$IFDEF TARGET_x64}
    2787   // ECX <- F
    2788   // EDX <- B
    2789   // R8D <- M
    2790 
    2791         MOV       EAX,ECX
    2792         SHR       EAX,24
    2793         INC       R8D             // 255:256 range bias
    2794         IMUL      R8D,EAX
    2795         SHR       R8D,8
    2796         JZ        @1
    2797 
    2798         PXOR      XMM0,XMM0
    2799         MOVD      XMM1,ECX
    2800         SHL       R8D,4
    2801         MOVD      XMM2,EDX
    2802         PUNPCKLBW XMM1,XMM0
    2803         PUNPCKLBW XMM2,XMM0
    2804         ADD       R8,alpha_ptr
    2805         PSUBW     XMM1,XMM2
    2806         PMULLW    XMM1,[R8]
    2807         PSLLW     XMM2,8
    2808         MOV       R8,bias_ptr
    2809         PADDW     XMM2,[R8]
    2810         PADDW     XMM1,XMM2
    2811         PSRLW     XMM1,8
    2812         PACKUSWB  XMM1,XMM0
    2813         MOVD      EAX,XMM1
    2814 {$IFDEF FPC}
    2815         JMP @2
    2816 {$ELSE}
    2817         RET
    2818 {$ENDIF}
    2819 
    2820 @1:     MOV       EAX,EDX
    2821 @2:
    2822 {$ENDIF}
    2823 end;
    2824 
    2825 procedure BlendMemEx_SSE2(F: TColor32; var B:TColor32; M: TColor32);
    2826 asm
    2827 {$IFDEF TARGET_x86}
    2828   // blend foreground color (F) to a background color (B),
    2829   // using alpha channel value of F
    2830   // EAX <- F
    2831   // [EDX] <- B
    2832   // ECX <- M
    2833   // Result := M * Fa * (Frgb - Brgb) + Brgb
    2834         TEST      EAX,$FF000000
    2835         JZ        @2
    2836 
    2837         PUSH      EBX
    2838         MOV       EBX,EAX
    2839         SHR       EBX,24
    2840         INC       ECX             // 255:256 range bias
    2841         IMUL      ECX,EBX
    2842         SHR       ECX,8
    2843         JZ        @1
    2844 
    2845         PXOR      XMM0,XMM0
    2846         MOVD      XMM1,EAX
    2847         SHL       ECX,4
    2848         MOVD      XMM2,[EDX]
    2849         PUNPCKLBW XMM1,XMM0
    2850         PUNPCKLBW XMM2,XMM0
    2851         ADD       ECX,alpha_ptr
    2852         PSUBW     XMM1,XMM2
    2853         PMULLW    XMM1,[ECX]
    2854         PSLLW     XMM2,8
    2855         MOV       ECX,bias_ptr
    2856         PADDW     XMM2,[ECX]
    2857         PADDW     XMM1,XMM2
    2858         PSRLW     XMM1,8
    2859         PACKUSWB  XMM1,XMM0
    2860         MOVD      [EDX],XMM1
    2861 
    2862 @1:
    2863         POP       EBX
    2864 
    2865 @2:
    2866 {$ENDIF}
    2867 
    2868 {$IFDEF TARGET_x64}
    2869   // blend foreground color (F) to a background color (B),
    2870   // using alpha channel value of F
    2871   // RCX <- F
    2872   // [RDX] <- B
    2873   // R8 <- M
    2874   // Result := M * Fa * (Frgb - Brgb) + Brgb
    2875 
    2876         TEST      ECX, $FF000000
    2877         JZ        @1
    2878 
    2879         MOV       R9D,ECX
    2880         SHR       R9D,24
    2881         INC       R8D            // 255:256 range bias
    2882         IMUL      R8D,R9D
    2883         SHR       R8D,8
    2884         JZ        @1
    2885 
    2886         PXOR      XMM0,XMM0
    2887         MOVD      XMM1,ECX
    2888         SHL       R8D,4
    2889         MOVD      XMM2,[RDX]
    2890         PUNPCKLBW XMM1,XMM0
    2891         PUNPCKLBW XMM2,XMM0
    2892         ADD       R8,alpha_ptr
    2893         PSUBW     XMM1,XMM2
    2894         PMULLW    XMM1,[R8]
    2895         PSLLW     XMM2,8
    2896         MOV       R8,bias_ptr
    2897         PADDW     XMM2,[R8]
    2898         PADDW     XMM1,XMM2
    2899         PSRLW     XMM1,8
    2900         PACKUSWB  XMM1,XMM0
    2901         MOVD      DWORD PTR [RDX],XMM1
    2902 @1:
    2903 {$ENDIF}
    2904 end;
    2905 
    2906 procedure BlendLine_SSE2(Src, Dst: PColor32; Count: Integer);
    2907 asm
    2908 {$IFDEF TARGET_X86}
    2909   // EAX <- Src
    2910   // EDX <- Dst
    2911   // ECX <- Count
    2912 
    2913         TEST      ECX,ECX
    2914         JZ        @4
    2915 
    2916         PUSH      EBX
    2917 
    2918         MOV       EBX,EAX
    2919 
    2920 @1:     MOV       EAX,[EBX]
    2921         TEST      EAX,$FF000000
    2922         JZ        @3
    2923         CMP       EAX,$FF000000
    2924         JNC       @2
    2925 
    2926         MOVD      XMM0,EAX
    2927         PXOR      XMM3,XMM3
    2928         MOVD      XMM2,[EDX]
    2929         PUNPCKLBW XMM0,XMM3
    2930         MOV       EAX,bias_ptr
    2931         PUNPCKLBW XMM2,XMM3
    2932         MOVQ      XMM1,XMM0
    2933         PUNPCKLBW XMM1,XMM3
    2934         PUNPCKHWD XMM1,XMM1
    2935         PSUBW     XMM0,XMM2
    2936         PUNPCKHDQ XMM1,XMM1
    2937         PSLLW     XMM2,8
    2938         PMULLW    XMM0,XMM1
    2939         PADDW     XMM2,[EAX]
    2940         PADDW     XMM2,XMM0
    2941         PSRLW     XMM2,8
    2942         PACKUSWB  XMM2,XMM3
    2943         MOVD      EAX, XMM2
    2944 
    2945 @2:     MOV       [EDX],EAX
    2946 
    2947 @3:     ADD       EBX,4
    2948         ADD       EDX,4
    2949 
    2950         DEC       ECX
    2951         JNZ       @1
    2952 
    2953         POP       EBX
    2954 
    2955 @4:
    2956 {$ENDIF}
    2957 
    2958 {$IFDEF TARGET_X64}
    2959   // ECX <- Src
    2960   // EDX <- Dst
    2961   // R8D <- Count
    2962 
    2963         TEST      R8D,R8D
    2964         JZ        @4
    2965 
    2966 @1:     MOV       EAX,[RCX]
    2967         TEST      EAX,$FF000000
    2968         JZ        @3
    2969         CMP       EAX,$FF000000
    2970         JNC       @2
    2971 
    2972         MOVD      XMM0,EAX
    2973         PXOR      XMM3,XMM3
    2974         MOVD      XMM2,[RDX]
    2975         PUNPCKLBW XMM0,XMM3
    2976         MOV       RAX,bias_ptr
    2977         PUNPCKLBW XMM2,XMM3
    2978         MOVQ      XMM1,XMM0
    2979         PUNPCKLBW XMM1,XMM3
    2980         PUNPCKHWD XMM1,XMM1
    2981         PSUBW     XMM0,XMM2
    2982         PUNPCKHDQ XMM1,XMM1
    2983         PSLLW     XMM2,8
    2984         PMULLW    XMM0,XMM1
    2985         PADDW     XMM2,[RAX]
    2986         PADDW     XMM2,XMM0
    2987         PSRLW     XMM2,8
    2988         PACKUSWB  XMM2,XMM3
    2989         MOVD      EAX, XMM2
    2990 
    2991 @2:     MOV       [RDX],EAX
    2992 
    2993 @3:     ADD       RCX,4
    2994         ADD       RDX,4
    2995 
    2996         DEC       R8D
    2997         JNZ       @1
    2998 
    2999 @4:
    3000 {$ENDIF}
    3001 end;
    3002 
    3003 
    3004 procedure BlendLineEx_SSE2(Src, Dst: PColor32; Count: Integer; M: TColor32);
    3005 asm
    3006 {$IFDEF TARGET_X86}
    3007   // EAX <- Src
    3008   // EDX <- Dst
    3009   // ECX <- Count
    3010 
    3011   // test the counter for zero or negativity
    3012         TEST      ECX,ECX
    3013         JS        @4
    3014 
    3015         PUSH      ESI
    3016         PUSH      EDI
    3017         PUSH      EBX
    3018 
    3019         MOV       ESI,EAX         // ESI <- Src
    3020         MOV       EDI,EDX         // EDI <- Dst
    3021         MOV       EDX,M           // EDX <- Master Alpha
    3022 
    3023   // loop start
    3024 @1:     MOV       EAX,[ESI]
    3025         TEST      EAX,$FF000000
    3026         JZ        @3             // complete transparency, proceed to next point
    3027         MOV       EBX,EAX
    3028         SHR       EBX,24
    3029         INC       EBX            // 255:256 range bias
    3030         IMUL      EBX,EDX
    3031         SHR       EBX,8
    3032         JZ        @3             // complete transparency, proceed to next point
    3033 
    3034   // blend
    3035         PXOR      XMM0,XMM0
    3036         MOVD      XMM1,EAX
    3037         SHL       EBX,4
    3038         MOVD      XMM2,[EDI]
    3039         PUNPCKLBW XMM1,XMM0
    3040         PUNPCKLBW XMM2,XMM0
    3041         ADD       EBX,alpha_ptr
    3042         PSUBW     XMM1,XMM2
    3043         PMULLW    XMM1,[EBX]
    3044         PSLLW     XMM2,8
    3045         MOV       EBX,bias_ptr
    3046         PADDW     XMM2,[EBX]
    3047         PADDW     XMM1,XMM2
    3048         PSRLW     XMM1,8
    3049         PACKUSWB  XMM1,XMM0
    3050         MOVD      EAX,XMM1
    3051 
    3052 @2:     MOV       [EDI],EAX
    3053 
    3054 @3:     ADD       ESI,4
    3055         ADD       EDI,4
    3056 
    3057   // loop end
    3058         DEC       ECX
    3059         JNZ       @1
    3060 
    3061         POP       EBX
    3062         POP       EDI
    3063         POP       ESI
    3064 @4:
    3065 {$ENDIF}
    3066 
    3067 {$IFDEF TARGET_X64}
    3068   // ECX <- Src
    3069   // EDX <- Dst
    3070   // R8D <- Count
    3071   // R9D <- M
    3072 
    3073   // test the counter for zero or negativity
    3074         TEST      R8D,R8D
    3075         JS        @4
    3076         TEST      R9D,R9D
    3077         JZ        @4
    3078 
    3079         MOV       R10,RCX         // ESI <- Src
    3080 
    3081   // loop start
    3082 @1:     MOV       ECX,[R10]
    3083         TEST      ECX,$FF000000
    3084         JZ        @3              // complete transparency, proceed to next point
    3085         MOV       EAX,ECX
    3086         SHR       EAX,24
    3087         INC       EAX             // 255:256 range bias
    3088         IMUL      EAX,R9D
    3089         SHR       EAX,8
    3090         JZ        @3              // complete transparency, proceed to next point
    3091 
    3092   // blend
    3093         PXOR      XMM0,XMM0
    3094         MOVD      XMM1,ECX
    3095         SHL       EAX,4
    3096         MOVD      XMM2,[RDX]
    3097         PUNPCKLBW XMM1,XMM0
    3098         PUNPCKLBW XMM2,XMM0
    3099         ADD       RAX,alpha_ptr
    3100         PSUBW     XMM1,XMM2
    3101         PMULLW    XMM1,[RAX]
    3102         PSLLW     XMM2,8
    3103         MOV       RAX,bias_ptr
    3104         PADDW     XMM2,[RAX]
    3105         PADDW     XMM1,XMM2
    3106         PSRLW     XMM1,8
    3107         PACKUSWB  XMM1,XMM0
    3108         MOVD      ECX,XMM1
    3109 
    3110 @2:     MOV       [RDX],ECX
    3111 
    3112 @3:     ADD       R10,4
    3113         ADD       RDX,4
    3114 
    3115   // loop end
    3116         DEC       R8D
    3117         JNZ       @1
    3118 @4:
    3119 {$ENDIF}
    3120 end;
    3121 
    3122 function CombineReg_SSE2(X, Y, W: TColor32): TColor32;
    3123 asm
    3124 {$IFDEF TARGET_X86}
    3125   // EAX - Color X
    3126   // EDX - Color Y
    3127   // ECX - Weight of X [0..255]
    3128   // Result := W * (X - Y) + Y
    3129 
    3130         MOVD      XMM1,EAX
    3131         PXOR      XMM0,XMM0
    3132         SHL       ECX,4
    3133 
    3134         MOVD      XMM2,EDX
    3135         PUNPCKLBW XMM1,XMM0
    3136         PUNPCKLBW XMM2,XMM0
    3137 
    3138         ADD       ECX,alpha_ptr
    3139 
    3140         PSUBW     XMM1,XMM2
    3141         PMULLW    XMM1,[ECX]
    3142         PSLLW     XMM2,8
    3143 
    3144         MOV       ECX,bias_ptr
    3145 
    3146         PADDW     XMM2,[ECX]
    3147         PADDW     XMM1,XMM2
    3148         PSRLW     XMM1,8
    3149         PACKUSWB  XMM1,XMM0
    3150         MOVD      EAX,XMM1
    3151 {$ENDIF}
    3152 
    3153 {$IFDEF TARGET_X64}
    3154   // ECX - Color X
    3155   // EDX - Color Y
    3156   // R8D - Weight of X [0..255]
    3157   // Result := W * (X - Y) + Y
    3158 
    3159         MOVD      XMM1,ECX
    3160         PXOR      XMM0,XMM0
    3161         SHL       R8D,4
    3162 
    3163         MOVD      XMM2,EDX
    3164         PUNPCKLBW XMM1,XMM0
    3165         PUNPCKLBW XMM2,XMM0
    3166 
    3167         ADD       R8,alpha_ptr
    3168 
    3169         PSUBW     XMM1,XMM2
    3170         PMULLW    XMM1,[R8]
    3171         PSLLW     XMM2,8
    3172 
    3173         MOV       R8,bias_ptr
    3174 
    3175         PADDW     XMM2,[R8]
    3176         PADDW     XMM1,XMM2
    3177         PSRLW     XMM1,8
    3178         PACKUSWB  XMM1,XMM0
    3179         MOVD      EAX,XMM1
    3180 {$ENDIF}
    3181 end;
    3182 
    3183 procedure CombineMem_SSE2(F: TColor32; var B: TColor32; W: TColor32);
    3184 asm
    3185 {$IFDEF TARGET_X86}
    3186   // EAX - Color X
    3187   // [EDX] - Color Y
    3188   // ECX - Weight of X [0..255]
    3189   // Result := W * (X - Y) + Y
    3190 
    3191         JCXZ    @1
    3192 
    3193         CMP       ECX,$FF
    3194         JZ        @2
    3195 
    3196         MOVD      XMM1,EAX
    3197         PXOR      XMM0,XMM0
    3198 
    3199         SHL       ECX,4
    3200 
    3201         MOVD      XMM2,[EDX]
    3202         PUNPCKLBW XMM1,XMM0
    3203         PUNPCKLBW XMM2,XMM0
    3204 
    3205         ADD       ECX,alpha_ptr
    3206 
    3207         PSUBW     XMM1,XMM2
    3208         PMULLW    XMM1,[ECX]
    3209         PSLLW     XMM2,8
    3210 
    3211         MOV       ECX,bias_ptr
    3212 
    3213         PADDW     XMM2,[ECX]
    3214         PADDW     XMM1,XMM2
    3215         PSRLW     XMM1,8
    3216         PACKUSWB  XMM1,XMM0
    3217         MOVD      [EDX],XMM1
    3218 
    3219 {$IFDEF FPC}
    3220 @1:     JMP @3
    3221 {$ELSE}
    3222 @1:     RET
    3223 {$ENDIF}
    3224 
    3225 @2:     MOV       [EDX],EAX
    3226 @3:
    3227 {$ENDIF}
    3228 
    3229 {$IFDEF TARGET_X64}
    3230   // ECX - Color X
    3231   // [RDX] - Color Y
    3232   // R8D - Weight of X [0..255]
    3233   // Result := W * (X - Y) + Y
    3234 
    3235         TEST      R8D,R8D            // Set flags for R8
    3236         JZ        @1                 // W = 0 ?  => Result := EDX
    3237         CMP       R8D,$FF
    3238         JZ        @2
    3239 
    3240         MOVD      XMM1,ECX
    3241         PXOR      XMM0,XMM0
    3242 
    3243         SHL       R8D,4
    3244 
    3245         MOVD      XMM2,[RDX]
    3246         PUNPCKLBW XMM1,XMM0
    3247         PUNPCKLBW XMM2,XMM0
    3248 
    3249         ADD       R8,alpha_ptr
    3250 
    3251         PSUBW     XMM1,XMM2
    3252         PMULLW    XMM1,[R8]
    3253         PSLLW     XMM2,8
    3254 
    3255         MOV       RAX,bias_ptr
    3256 
    3257         PADDW     XMM2,[RAX]
    3258         PADDW     XMM1,XMM2
    3259         PSRLW     XMM1,8
    3260         PACKUSWB  XMM1,XMM0
    3261         MOVD      [RDX],XMM1
    3262 
    3263 {$IFDEF FPC}
    3264 @1:     JMP @3
    3265 {$ELSE}
    3266 @1:     RET
    3267 {$ENDIF}
    3268 
    3269 @2:     MOV       [RDX],ECX
    3270 @3:
    3271 {$ENDIF}
    3272 end;
    3273 
    3274 
    3275 procedure CombineLine_SSE2(Src, Dst: PColor32; Count: Integer; W: TColor32);
    3276 asm
    3277 {$IFDEF TARGET_X86}
    3278   // EAX <- Src
    3279   // EDX <- Dst
    3280   // ECX <- Count
    3281 
    3282   // Result := W * (X - Y) + Y
    3283 
    3284         TEST      ECX,ECX
    3285         JZ        @3
    3286 
    3287         PUSH      EBX
    3288         MOV       EBX,W
    3289 
    3290         TEST      EBX,EBX
    3291         JZ        @2
    3292 
    3293         CMP       EBX,$FF
    3294         JZ        @4
    3295 
    3296         SHL       EBX,4
    3297         ADD       EBX,alpha_ptr
    3298         MOVQ      XMM3,[EBX]
    3299         MOV       EBX,bias_ptr
    3300         MOVQ      XMM4,[EBX]
    3301 
    3302 @1:     MOVD      XMM1,[EAX]
    3303         PXOR      XMM0,XMM0
    3304         MOVD      XMM2,[EDX]
    3305         PUNPCKLBW XMM1,XMM0
    3306         PUNPCKLBW XMM2,XMM0
    3307 
    3308         PSUBW     XMM1,XMM2
    3309         PMULLW    XMM1,XMM3
    3310         PSLLW     XMM2,8
    3311 
    3312         PADDW     XMM2,XMM4
    3313         PADDW     XMM1,XMM2
    3314         PSRLW     XMM1,8
    3315         PACKUSWB  XMM1,XMM0
    3316         MOVD      [EDX],XMM1
    3317 
    3318         ADD       EAX,4
    3319         ADD       EDX,4
    3320 
    3321         DEC       ECX
    3322         JNZ       @1
    3323 
    3324 @2:     POP       EBX
    3325         POP       EBP
    3326 
    3327 @3:     RET       $0004
    3328 
    3329 @4:     SHL       ECX,2
    3330         CALL      Move
    3331         POP       EBX
    3332 {$ENDIF}
    3333 
    3334 {$IFDEF TARGET_X64}
    3335   // ECX <- Src
    3336   // EDX <- Dst
    3337   // R8D <- Count
    3338 
    3339   // Result := W * (X - Y) + Y
    3340 
    3341         TEST      R8D,R8D
    3342         JZ        @2
    3343 
    3344         TEST      R9D,R9D
    3345         JZ        @2
    3346 
    3347         CMP       R9D,$FF
    3348         JZ        @3
    3349 
    3350         SHL       R9D,4
    3351         ADD       R9,alpha_ptr
    3352         MOVQ      XMM3,[R9]
    3353         MOV       R9,bias_ptr
    3354         MOVQ      XMM4,[R9]
    3355 
    3356 @1:     MOVD      XMM1,[RCX]
    3357         PXOR      XMM0,XMM0
    3358         MOVD      XMM2,[RDX]
    3359         PUNPCKLBW XMM1,XMM0
    3360         PUNPCKLBW XMM2,XMM0
    3361 
    3362         PSUBW     XMM1,XMM2
    3363         PMULLW    XMM1,XMM3
    3364         PSLLW     XMM2,8
    3365 
    3366         PADDW     XMM2,XMM4
    3367         PADDW     XMM1,XMM2
    3368         PSRLW     XMM1,8
    3369         PACKUSWB  XMM1,XMM0
    3370         MOVD      [RDX],XMM1
    3371 
    3372         ADD       RCX,4
    3373         ADD       RDX,4
    3374 
    3375         DEC       R8D
    3376         JNZ       @1
    3377 
    3378 {$IFDEF FPC}
    3379 @2:     JMP @4
    3380 {$ELSE}
    3381 @2:     RET
    3382 {$ENDIF}
    3383 
    3384 @3:     SHL       R8D,2
    3385         CALL      Move
    3386 @4:
    3387 {$ENDIF}
    3388 end;
    3389 
    3390 function MergeReg_SSE2(F, B: TColor32): TColor32;
    3391 asm
    3392   { This is an implementation of the merge formula, as described
    3393     in a paper by Bruce Wallace in 1981. Merging is associative,
    3394     that is, A over (B over C) = (A over B) over C. The formula is,
    3395 
    3396       Ra = Fa + Ba - Fa * Ba
    3397       Rc = (Fa (Fc - Bc * Ba) + Bc * Ba) / Ra
    3398 
    3399     where
    3400 
    3401       Rc is the resultant color,
    3402       Ra is the resultant alpha,
    3403       Fc is the foreground color,
    3404       Fa is the foreground alpha,
    3405       Bc is the background color,
    3406       Ba is the background alpha.
    3407 
    3408     Implementation:
    3409 
    3410       Ra := 1 - (1 - Fa) * (1 - Ba);
    3411       Wa := Fa / Ra;
    3412       Rc := Bc + Wa * (Fc - Bc);
    3413       // Rc := Bc + Wa * (Fc - Bc)
    3414 
    3415       (1 - Fa) * (1 - Ba) = 1 - Fa - Ba + Fa * Ba = (1 - Ra)
    3416   }
    3417 
    3418 {$IFDEF TARGET_X86}
    3419         TEST      EAX,$FF000000  // foreground completely transparent =>
    3420         JZ        @1             // result = background
    3421         CMP       EAX,$FF000000  // foreground completely opaque =>
    3422         JNC       @2             // result = foreground
    3423         TEST      EDX,$FF000000  // background completely transparent =>
    3424         JZ        @2             // result = foreground
    3425 
    3426         PXOR      XMM7,XMM7       // XMM7  <-  00
    3427         MOVD      XMM0,EAX        // XMM0  <-  Fa Fr Fg Fb
    3428         SHR       EAX,24          //  EAX  <-  Fa
    3429         ROR       EDX,24
    3430         MOVZX     ECX,DL          //  ECX  <-  Ba
    3431         PUNPCKLBW XMM0,XMM7       // XMM0  <-  00 Fa 00 Fr 00 Fg 00 Fb
    3432         SUB       EAX,$FF         //  EAX  <-  (Fa - 1)
    3433         XOR       ECX,$FF         //  ECX  <-  (1 - Ba)
    3434         IMUL      ECX,EAX         //  ECX  <-  (Fa - 1) * (1 - Ba)  =  Ra - 1
    3435         IMUL      ECX,$8081       //  ECX  <-  Xa 00 00 00
    3436         ADD       ECX,$8081*$FF*$FF
    3437         SHR       ECX,15          //  ECX  <-  Ra
    3438         MOV       DL,CH           //  EDX  <-  Br Bg Bb Ra
    3439         ROR       EDX,8           //  EDX  <-  Ra Br Bg Bb
    3440         MOVD      XMM1,EDX        // XMM1  <-  Ra Br Bg Bb
    3441         PUNPCKLBW XMM1,XMM7       // XMM1  <-  00 Ra 00 Br 00 Bg 00 Bb
    3442         SHL       EAX,20          //  EAX  <-  Fa 00 00
    3443         PSUBW     XMM0,XMM1       // XMM0  <-  ** Da ** Dr ** Dg ** Db
    3444         ADD       EAX,$0FF01000
    3445         PSLLW     XMM0,4
    3446         XOR       EDX,EDX         //  EDX  <-  00
    3447         DIV       ECX             //  EAX  <-  Fa / Ra  =  Wa
    3448         MOVD      XMM4,EAX        // XMM3  <-  Wa
    3449         PSHUFLW   XMM4,XMM4,$C0   // XMM3  <-  00 00 ** Wa ** Wa ** Wa
    3450         PMULHW    XMM0,XMM4       // XMM0  <-  00 00 ** Pr ** Pg ** Pb
    3451         PADDW     XMM0,XMM1       // XMM0  <-  00 Ra 00 Rr 00 Rg 00 Rb
    3452         PACKUSWB  XMM0,XMM7       // XMM0  <-  Ra Rr Rg Rb
    3453         MOVD      EAX,XMM0
    3454 
    3455 {$IFDEF FPC}
    3456         JMP @2
    3457 {$ELSE}
    3458         RET
    3459 {$ENDIF}
    3460 @1:     MOV       EAX,EDX
    3461 @2:
    3462 {$ENDIF}
    3463 
    3464 {$IFDEF TARGET_X64}
    3465         TEST      ECX,$FF000000   // foreground completely transparent =>
    3466         JZ        @1              // result = background
    3467         MOV       EAX,ECX         //  EAX  <-  Fa
    3468         CMP       EAX,$FF000000   // foreground completely opaque =>
    3469         JNC       @2              // result = foreground
    3470         TEST      EDX,$FF000000   // background completely transparent =>
    3471         JZ        @2              // result = foreground
    3472 
    3473         PXOR      XMM7,XMM7       // XMM7  <-  00
    3474         MOVD      XMM0,EAX        // XMM0  <-  Fa Fr Fg Fb
    3475         SHR       EAX,24          //  EAX  <-  Fa
    3476         ROR       EDX,24
    3477         MOVZX     ECX,DL          //  ECX  <-  Ba
    3478         PUNPCKLBW XMM0,XMM7       // XMM0  <-  00 Fa 00 Fr 00 Fg 00 Fb
    3479         SUB       EAX,$FF         //  EAX  <-  (Fa - 1)
    3480         XOR       ECX,$FF         //  ECX  <-  (1 - Ba)
    3481         IMUL      ECX,EAX         //  ECX  <-  (Fa - 1) * (1 - Ba)  =  Ra - 1
    3482         IMUL      ECX,$8081       //  ECX  <-  Xa 00 00 00
    3483         ADD       ECX,$8081*$FF*$FF
    3484         SHR       ECX,15          //  ECX  <-  Ra
    3485         MOV       DL,CH           //  EDX  <-  Br Bg Bb Ra
    3486         ROR       EDX,8           //  EDX  <-  Ra Br Bg Bb
    3487         MOVD      XMM1,EDX        // XMM1  <-  Ra Br Bg Bb
    3488         PUNPCKLBW XMM1,XMM7       // XMM1  <-  00 Ra 00 Br 00 Bg 00 Bb
    3489         SHL       EAX,20          //  EAX  <-  Fa 00 00
    3490         PSUBW     XMM0,XMM1       // XMM0  <-  ** Da ** Dr ** Dg ** Db
    3491         ADD       EAX,$0FF01000
    3492         PSLLW     XMM0,4
    3493         XOR       EDX,EDX         //  EDX  <-  00
    3494         DIV       ECX             //  EAX  <-  Fa / Ra  =  Wa
    3495         MOVD      XMM4,EAX        // XMM3  <-  Wa
    3496         PSHUFLW   XMM4,XMM4,$C0   // XMM3  <-  00 00 ** Wa ** Wa ** Wa
    3497         PMULHW    XMM0,XMM4       // XMM0  <-  00 00 ** Pr ** Pg ** Pb
    3498         PADDW     XMM0,XMM1       // XMM0  <-  00 Ra 00 Rr 00 Rg 00 Rb
    3499         PACKUSWB  XMM0,XMM7       // XMM0  <-  Ra Rr Rg Rb
    3500         MOVD      EAX,XMM0
    3501 
    3502 {$IFDEF FPC}
    3503         JMP @2
    3504 {$ELSE}
    3505         RET
    3506 {$ENDIF}
    3507 @1:     MOV       EAX,EDX
    3508 @2:
    3509 {$ENDIF}
    3510 end;
    3511 
    3512 procedure EMMS_SSE2;
    3513 asm
    3514 end;
    3515 
    3516 
    3517 function LightenReg_SSE2(C: TColor32; Amount: Integer): TColor32;
    3518 asm
    3519 {$IFDEF TARGET_X86}
    3520         MOVD    XMM0,EAX
    3521         TEST    EDX,EDX
    3522         JL      @1
    3523         IMUL    EDX,$010101
    3524         MOVD    XMM1,EDX
    3525         PADDUSB XMM0,XMM1
    3526         MOVD    EAX,XMM0
    3527         RET
    3528 @1:     NEG     EDX
    3529         IMUL    EDX,$010101
    3530         MOVD    XMM1,EDX
    3531         PSUBUSB XMM0,XMM1
    3532         MOVD    EAX,XMM0
    3533 {$ENDIF}
    3534 
    3535 {$IFDEF TARGET_X64}
    3536         MOVD    XMM0,ECX
    3537         TEST    EDX,EDX
    3538         JL      @1
    3539         IMUL    EDX,$010101
    3540         MOVD    XMM1,EDX
    3541         PADDUSB XMM0,XMM1
    3542         MOVD    EAX,XMM0
    3543         RET
    3544 @1:     NEG     EDX
    3545         IMUL    EDX,$010101
    3546         MOVD    XMM1,EDX
    3547         PSUBUSB XMM0,XMM1
    3548         MOVD    EAX,XMM0
    3549 {$ENDIF}
    3550 end;
    3551 
    3552 
    3553 { SSE2 Color algebra}
    3554 
    3555 function ColorAdd_SSE2(C1, C2: TColor32): TColor32;
    3556 asm
    3557 {$IFDEF TARGET_X86}
    3558         MOVD      XMM0,EAX
    3559         MOVD      XMM1,EDX
    3560         PADDUSB   XMM0,XMM1
    3561         MOVD      EAX,XMM0
    3562 {$ENDIF}
    3563 
    3564 {$IFDEF TARGET_X64}
    3565         MOVD      XMM0,ECX
    3566         MOVD      XMM1,EDX
    3567         PADDUSB   XMM0,XMM1
    3568         MOVD      EAX,XMM0
    3569 {$ENDIF}
    3570 end;
    3571 
    3572 function ColorSub_SSE2(C1, C2: TColor32): TColor32;
    3573 asm
    3574 {$IFDEF TARGET_X86}
    3575         MOVD      XMM0,EAX
    3576         MOVD      XMM1,EDX
    3577         PSUBUSB   XMM0,XMM1
    3578         MOVD      EAX,XMM0
    3579 {$ENDIF}
    3580 
    3581 {$IFDEF TARGET_X64}
    3582         MOVD      XMM0,ECX
    3583         MOVD      XMM1,EDX
    3584         PSUBUSB   XMM0,XMM1
    3585         MOVD      EAX,XMM0
    3586 {$ENDIF}
    3587 end;
    3588 
    3589 function ColorModulate_SSE2(C1, C2: TColor32): TColor32;
    3590 asm
    3591 {$IFDEF TARGET_X86}
    3592         PXOR      XMM2,XMM2
    3593         MOVD      XMM0,EAX
    3594         PUNPCKLBW XMM0,XMM2
    3595         MOVD      XMM1,EDX
    3596         PUNPCKLBW XMM1,XMM2
    3597         PMULLW    XMM0,XMM1
    3598         PSRLW     XMM0,8
    3599         PACKUSWB  XMM0,XMM2
    3600         MOVD      EAX,XMM0
    3601 {$ENDIF}
    3602 
    3603 {$IFDEF TARGET_X64}
    3604         PXOR      XMM2,XMM2
    3605         MOVD      XMM0,ECX
    3606         PUNPCKLBW XMM0,XMM2
    3607         MOVD      XMM1,EDX
    3608         PUNPCKLBW XMM1,XMM2
    3609         PMULLW    XMM0,XMM1
    3610         PSRLW     XMM0,8
    3611         PACKUSWB  XMM0,XMM2
    3612         MOVD      EAX,XMM0
    3613 {$ENDIF}
    3614 end;
    3615 
    3616 function ColorMax_SSE2(C1, C2: TColor32): TColor32;
    3617 asm
    3618 {$IFDEF TARGET_X86}
    3619         MOVD      XMM0,EAX
    3620         MOVD      XMM1,EDX
    3621         PMAXUB    XMM0,XMM1
    3622         MOVD      EAX,XMM0
    3623 {$ENDIF}
    3624 
    3625 {$IFDEF TARGET_X64}
    3626         MOVD      XMM0,ECX
    3627         MOVD      XMM1,EDX
    3628         PMAXUB    XMM0,XMM1
    3629         MOVD      EAX,XMM0
    3630 {$ENDIF}
    3631 end;
    3632 
    3633 function ColorMin_SSE2(C1, C2: TColor32): TColor32;
    3634 asm
    3635 {$IFDEF TARGET_X86}
    3636         MOVD      XMM0,EAX
    3637         MOVD      XMM1,EDX
    3638         PMINUB    XMM0,XMM1
    3639         MOVD      EAX,XMM0
    3640 {$ENDIF}
    3641 
    3642 {$IFDEF TARGET_X64}
    3643         MOVD      XMM0,ECX
    3644         MOVD      XMM1,EDX
    3645         PMINUB    XMM0,XMM1
    3646         MOVD      EAX,XMM0
    3647 {$ENDIF}
    3648 end;
    3649 
    3650 function ColorDifference_SSE2(C1, C2: TColor32): TColor32;
    3651 asm
    3652 {$IFDEF TARGET_X86}
    3653         MOVD      XMM0,EAX
    3654         MOVD      XMM1,EDX
    3655         MOVQ      XMM2,XMM0
    3656         PSUBUSB   XMM0,XMM1
    3657         PSUBUSB   XMM1,XMM2
    3658         POR       XMM0,XMM1
    3659         MOVD      EAX,XMM0
    3660 {$ENDIF}
    3661 
    3662 {$IFDEF TARGET_X64}
    3663         MOVD      XMM0,ECX
    3664         MOVD      XMM1,EDX
    3665         MOVQ      XMM2,XMM0
    3666         PSUBUSB   XMM0,XMM1
    3667         PSUBUSB   XMM1,XMM2
    3668         POR       XMM0,XMM1
    3669         MOVD      EAX,XMM0
    3670 {$ENDIF}
    3671 end;
    3672 
    3673 function ColorExclusion_SSE2(C1, C2: TColor32): TColor32;
    3674 asm
    3675 {$IFDEF TARGET_X86}
    3676         PXOR      XMM2,XMM2
    3677         MOVD      XMM0,EAX
    3678         PUNPCKLBW XMM0,XMM2
    3679         MOVD      XMM1,EDX
    3680         PUNPCKLBW XMM1,XMM2
    3681         MOVQ      XMM3,XMM0
    3682         PADDW     XMM0,XMM1
    3683         PMULLW    XMM1,XMM3
    3684         PSRLW     XMM1,7
    3685         PSUBUSW   XMM0,XMM1
    3686         PACKUSWB  XMM0,XMM2
    3687         MOVD      EAX,XMM0
    3688 {$ENDIF}
    3689 
    3690 {$IFDEF TARGET_X64}
    3691         PXOR      XMM2,XMM2
    3692         MOVD      XMM0,ECX
    3693         PUNPCKLBW XMM0,XMM2
    3694         MOVD      XMM1,EDX
    3695         PUNPCKLBW XMM1,XMM2
    3696         MOVQ      XMM3,XMM0
    3697         PADDW     XMM0,XMM1
    3698         PMULLW    XMM1,XMM3
    3699         PSRLW     XMM1,7
    3700         PSUBUSW   XMM0,XMM1
    3701         PACKUSWB  XMM0,XMM2
    3702         MOVD      EAX,XMM0
    3703 {$ENDIF}
    3704 end;
    3705 
    3706 function ColorScale_SSE2(C, W: TColor32): TColor32;
    3707 asm
    3708 {$IFDEF TARGET_X86}
    3709         PXOR      XMM2,XMM2
    3710         SHL       EDX,4
    3711         MOVD      XMM0,EAX
    3712         PUNPCKLBW XMM0,XMM2
    3713         ADD       EDX,alpha_ptr
    3714         PMULLW    XMM0,[EDX]
    3715         PSRLW     XMM0,8
    3716         PACKUSWB  XMM0,XMM2
    3717         MOVD      EAX,XMM0
    3718 {$ENDIF}
    3719 
    3720 {$IFDEF TARGET_X64}
    3721         PXOR      XMM2,XMM2
    3722         SHL       RDX,4
    3723         MOVD      XMM0,ECX
    3724         PUNPCKLBW XMM0,XMM2
    3725         ADD       RDX,alpha_ptr
    3726         PMULLW    XMM0,[RDX]
    3727         PSRLW     XMM0,8
    3728         PACKUSWB  XMM0,XMM2
    3729         MOVD      EAX,XMM0
    3730 {$ENDIF}
    3731 end;
    3732 
    3733 {$ENDIF}
    3734897{$ENDIF}
    3735898
     
    3744907var
    3745908  I, J: Integer;
    3746 const
    3747   OneByteth : Double = 1 / 255;
    3748909begin
    3749910  for J := 0 to 255 do
    3750     for I := 0 to 255 do
     911  begin
     912    DivTable[0, J] := 0;
     913    RcTable[0, J] := 0;
     914  end;
     915  for J := 0 to 255 do
     916    for I := 1 to 255 do
    3751917    begin
    3752       DivTable[I, J] := Round(I * J * OneByteth);
    3753       if I > 0 then
    3754         RcTable[I, J] := Round(J * 255 / I)
    3755       else
    3756         RcTable[I, J] := 0;
     918      DivTable[I, J] := Round(I * J * COne255th);
     919      RcTable[I, J] := Round(J * 255 / I)
    3757920    end;
    3758921end;
     
    3763926  FID_MERGEMEM = 2;
    3764927  FID_MERGELINE = 3;
    3765   FID_MERGEREGEX = 4;
    3766   FID_MERGEMEMEX = 5;
    3767   FID_MERGELINEEX = 6;
    3768   FID_COMBINEREG = 7;
    3769   FID_COMBINEMEM = 8;
    3770   FID_COMBINELINE = 9;
    3771 
    3772   FID_BLENDREG = 10;
    3773   FID_BLENDMEM = 11;
    3774   FID_BLENDLINE = 12;
    3775   FID_BLENDREGEX = 13;
    3776   FID_BLENDMEMEX = 14;
    3777   FID_BLENDLINEEX = 15;
    3778 
    3779   FID_COLORMAX = 16;
    3780   FID_COLORMIN = 17;
    3781   FID_COLORAVERAGE = 18;
    3782   FID_COLORADD = 19;
    3783   FID_COLORSUB = 20;
    3784   FID_COLORDIV = 21;
    3785   FID_COLORMODULATE = 22;
    3786   FID_COLORDIFFERENCE = 23;
    3787   FID_COLOREXCLUSION = 24;
    3788   FID_COLORSCALE = 25;
    3789   FID_Lighten = 26;
     928  FID_MERGELINE1 = 4;
     929  FID_MERGEREGEX = 5;
     930  FID_MERGEMEMEX = 6;
     931  FID_MERGELINEEX = 7;
     932  FID_COMBINEREG = 8;
     933  FID_COMBINEMEM = 9;
     934  FID_COMBINELINE = 10;
     935
     936  FID_BLENDREG = 11;
     937  FID_BLENDMEM = 12;
     938  FID_BLENDMEMS = 13;
     939  FID_BLENDLINE = 14;
     940  FID_BLENDREGEX = 15;
     941  FID_BLENDMEMEX = 16;
     942  FID_BLENDLINEEX = 17;
     943  FID_BLENDLINE1 = 18;
     944
     945  FID_COLORMAX = 19;
     946  FID_COLORMIN = 20;
     947  FID_COLORAVERAGE = 21;
     948  FID_COLORADD = 22;
     949  FID_COLORSUB = 23;
     950  FID_COLORDIV = 24;
     951  FID_COLORMODULATE = 25;
     952  FID_COLORDIFFERENCE = 26;
     953  FID_COLOREXCLUSION = 27;
     954  FID_COLORSCALE = 28;
     955  FID_COLORSCREEN = 29;
     956  FID_COLORDODGE = 30;
     957  FID_COLORBURN = 31;
     958  FID_BLENDCOLORADD = 32;
     959  FID_BLENDCOLORMODULATE = 33;
     960  FID_LIGHTEN = 34;
     961
     962  FID_BLENDREGRGB = 35;
     963  FID_BLENDMEMRGB = 36;
     964{$IFDEF TEST_BLENDMEMRGB128SSE4}
     965  FID_BLENDMEMRGB128 = 37;
     966{$ENDIF}
     967
     968const
     969  BlendBindingFlagPascal = $0001;
     970
    3790971
    3791972procedure RegisterBindings;
     
    3807988  BlendRegistry.RegisterBinding(FID_BLENDREG, @@BlendReg);
    3808989  BlendRegistry.RegisterBinding(FID_BLENDMEM, @@BlendMem);
     990  BlendRegistry.RegisterBinding(FID_BLENDMEMS, @@BlendMems);
    3809991  BlendRegistry.RegisterBinding(FID_BLENDLINE, @@BlendLine);
    3810992  BlendRegistry.RegisterBinding(FID_BLENDREGEX, @@BlendRegEx);
    3811993  BlendRegistry.RegisterBinding(FID_BLENDMEMEX, @@BlendMemEx);
    3812994  BlendRegistry.RegisterBinding(FID_BLENDLINEEX, @@BlendLineEx);
     995  BlendRegistry.RegisterBinding(FID_BLENDLINE1, @@BlendLine1);
    3813996
    3814997  BlendRegistry.RegisterBinding(FID_COLORMAX, @@ColorMax);
     
    38221005  BlendRegistry.RegisterBinding(FID_COLOREXCLUSION, @@ColorExclusion);
    38231006  BlendRegistry.RegisterBinding(FID_COLORSCALE, @@ColorScale);
     1007  BlendRegistry.RegisterBinding(FID_COLORSCREEN, @@ColorScreen);
     1008  BlendRegistry.RegisterBinding(FID_COLORDODGE, @@ColorDodge);
     1009  BlendRegistry.RegisterBinding(FID_COLORBURN, @@ColorBurn);
     1010
     1011  BlendRegistry.RegisterBinding(FID_BLENDCOLORADD, @@BlendColorAdd);
     1012  BlendRegistry.RegisterBinding(FID_BLENDCOLORMODULATE, @@BlendColorModulate);
    38241013
    38251014  BlendRegistry.RegisterBinding(FID_LIGHTEN, @@LightenReg);
     1015  BlendRegistry.RegisterBinding(FID_BLENDREGRGB, @@BlendRegRGB);
     1016  BlendRegistry.RegisterBinding(FID_BLENDMEMRGB, @@BlendMemRGB);
     1017{$IFDEF TEST_BLENDMEMRGB128SSE4}
     1018  BlendRegistry.RegisterBinding(FID_BLENDMEMRGB128, @@BlendMemRGB128);
     1019{$ENDIF}
    38261020
    38271021  // pure pascal
    3828   BlendRegistry.Add(FID_EMMS, @EMMS_Pas);
    3829   BlendRegistry.Add(FID_MERGEREG, @MergeReg_Pas);
    3830   BlendRegistry.Add(FID_MERGEMEM, @MergeMem_Pas);
    3831   BlendRegistry.Add(FID_MERGEMEMEX, @MergeMemEx_Pas);
    3832   BlendRegistry.Add(FID_MERGEREGEX, @MergeRegEx_Pas);
    3833   BlendRegistry.Add(FID_MERGELINE, @MergeLine_Pas);
    3834   BlendRegistry.Add(FID_MERGELINEEX, @MergeLineEx_Pas);
    3835   BlendRegistry.Add(FID_COLORDIV, @ColorDiv_Pas);
    3836   BlendRegistry.Add(FID_COLORAVERAGE, @ColorAverage_Pas);
    3837   BlendRegistry.Add(FID_COMBINEREG, @CombineReg_Pas);
    3838   BlendRegistry.Add(FID_COMBINEMEM, @CombineMem_Pas);
    3839   BlendRegistry.Add(FID_COMBINELINE, @CombineLine_Pas);
    3840   BlendRegistry.Add(FID_BLENDREG, @BlendReg_Pas);
    3841   BlendRegistry.Add(FID_BLENDMEM, @BlendMem_Pas);
    3842   BlendRegistry.Add(FID_BLENDLINE, @BlendLine_Pas);
    3843   BlendRegistry.Add(FID_BLENDREGEX, @BlendRegEx_Pas);
    3844   BlendRegistry.Add(FID_BLENDMEMEX, @BlendMemEx_Pas);
    3845   BlendRegistry.Add(FID_BLENDLINEEX, @BlendLineEx_Pas);
    3846   BlendRegistry.Add(FID_COLORMAX, @ColorMax_Pas);
    3847   BlendRegistry.Add(FID_COLORMIN, @ColorMin_Pas);
    3848   BlendRegistry.Add(FID_COLORADD, @ColorAdd_Pas);
    3849   BlendRegistry.Add(FID_COLORSUB, @ColorSub_Pas);
    3850   BlendRegistry.Add(FID_COLORMODULATE, @ColorModulate_Pas);
    3851   BlendRegistry.Add(FID_COLORDIFFERENCE, @ColorDifference_Pas);
    3852   BlendRegistry.Add(FID_COLOREXCLUSION, @ColorExclusion_Pas);
    3853   BlendRegistry.Add(FID_COLORSCALE, @ColorScale_Pas);
    3854   BlendRegistry.Add(FID_LIGHTEN, @LightenReg_Pas);
     1022  BlendRegistry.Add(FID_EMMS, @EMMS_Pas, [], BlendBindingFlagPascal);
     1023  BlendRegistry.Add(FID_MERGEREG, @MergeReg_Pas, [], BlendBindingFlagPascal);
     1024  BlendRegistry.Add(FID_MERGEMEM, @MergeMem_Pas, [], BlendBindingFlagPascal);
     1025  BlendRegistry.Add(FID_MERGEMEMEX, @MergeMemEx_Pas, [], BlendBindingFlagPascal);
     1026  BlendRegistry.Add(FID_MERGEREGEX, @MergeRegEx_Pas, [], BlendBindingFlagPascal);
     1027  BlendRegistry.Add(FID_MERGELINE, @MergeLine_Pas, [], BlendBindingFlagPascal);
     1028  BlendRegistry.Add(FID_MERGELINEEX, @MergeLineEx_Pas, [], BlendBindingFlagPascal);
     1029  BlendRegistry.Add(FID_MERGELINE1, @MergeLine1_Pas, [], BlendBindingFlagPascal);
     1030  BlendRegistry.Add(FID_COLORDIV, @ColorDiv_Pas, [], BlendBindingFlagPascal);
     1031  BlendRegistry.Add(FID_COLORAVERAGE, @ColorAverage_Pas, [], BlendBindingFlagPascal);
     1032  BlendRegistry.Add(FID_COMBINEREG, @CombineReg_Pas, [], BlendBindingFlagPascal);
     1033  BlendRegistry.Add(FID_COMBINEMEM, @CombineMem_Pas, [], BlendBindingFlagPascal);
     1034  BlendRegistry.Add(FID_COMBINELINE, @CombineLine_Pas, [], BlendBindingFlagPascal);
     1035  BlendRegistry.Add(FID_BLENDREG, @BlendReg_Pas, [], BlendBindingFlagPascal);
     1036  BlendRegistry.Add(FID_BLENDMEM, @BlendMem_Pas, [], BlendBindingFlagPascal);
     1037  BlendRegistry.Add(FID_BLENDMEMS, @BlendMems_Pas, [], BlendBindingFlagPascal);
     1038  BlendRegistry.Add(FID_BLENDLINE, @BlendLine_Pas, [], BlendBindingFlagPascal);
     1039  BlendRegistry.Add(FID_BLENDREGEX, @BlendRegEx_Pas, [], BlendBindingFlagPascal);
     1040  BlendRegistry.Add(FID_BLENDMEMEX, @BlendMemEx_Pas, [], BlendBindingFlagPascal);
     1041  BlendRegistry.Add(FID_BLENDLINEEX, @BlendLineEx_Pas, [], BlendBindingFlagPascal);
     1042  BlendRegistry.Add(FID_BLENDLINE1, @BlendLine1_Pas, [], BlendBindingFlagPascal);
     1043  BlendRegistry.Add(FID_COLORMAX, @ColorMax_Pas, [], BlendBindingFlagPascal);
     1044  BlendRegistry.Add(FID_COLORMIN, @ColorMin_Pas, [], BlendBindingFlagPascal);
     1045  BlendRegistry.Add(FID_COLORADD, @ColorAdd_Pas, [], BlendBindingFlagPascal);
     1046  BlendRegistry.Add(FID_COLORSUB, @ColorSub_Pas, [], BlendBindingFlagPascal);
     1047  BlendRegistry.Add(FID_COLORMODULATE, @ColorModulate_Pas, [], BlendBindingFlagPascal);
     1048  BlendRegistry.Add(FID_COLORDIFFERENCE, @ColorDifference_Pas, [], BlendBindingFlagPascal);
     1049  BlendRegistry.Add(FID_COLOREXCLUSION, @ColorExclusion_Pas, [], BlendBindingFlagPascal);
     1050  BlendRegistry.Add(FID_COLORSCALE, @ColorScale_Pas, [], BlendBindingFlagPascal);
     1051  BlendRegistry.Add(FID_COLORSCREEN, @ColorScreen_Pas, [], BlendBindingFlagPascal);
     1052  BlendRegistry.Add(FID_COLORDODGE, @ColorDodge_Pas, [], BlendBindingFlagPascal);
     1053  BlendRegistry.Add(FID_COLORBURN, @ColorBurn_Pas, [], BlendBindingFlagPascal);
     1054  BlendRegistry.Add(FID_BLENDCOLORADD, @BlendColorAdd_Pas, [], BlendBindingFlagPascal);
     1055  BlendRegistry.Add(FID_BLENDCOLORMODULATE, @BlendColorModulate_Pas, [], BlendBindingFlagPascal);
     1056  BlendRegistry.Add(FID_LIGHTEN, @LightenReg_Pas, [], BlendBindingFlagPascal);
     1057  BlendRegistry.Add(FID_BLENDREGRGB, @BlendRegRGB_Pas, [], BlendBindingFlagPascal);
     1058  BlendRegistry.Add(FID_BLENDMEMRGB, @BlendMemRGB_Pas, [], BlendBindingFlagPascal);
    38551059
    38561060{$IFNDEF PUREPASCAL}
     
    38601064  BlendRegistry.Add(FID_BLENDREG, @BlendReg_ASM, []);
    38611065  BlendRegistry.Add(FID_BLENDMEM, @BlendMem_ASM, []);
     1066  BlendRegistry.Add(FID_BLENDMEMS, @BlendMems_ASM, []);
    38621067  BlendRegistry.Add(FID_BLENDREGEX, @BlendRegEx_ASM, []);
    38631068  BlendRegistry.Add(FID_BLENDMEMEX, @BlendMemEx_ASM, []);
    38641069  BlendRegistry.Add(FID_BLENDLINE, @BlendLine_ASM, []);
    3865   BlendRegistry.Add(FID_LIGHTEN, @LightenReg_Pas, []);   // no ASM version available
     1070  BlendRegistry.Add(FID_BLENDLINE1, @BlendLine1_ASM, []);
     1071{$IFNDEF TARGET_x64}
     1072  BlendRegistry.Add(FID_MERGEREG, @MergeReg_ASM, []);
     1073{$ENDIF}
    38661074{$IFNDEF OMIT_MMX}
    38671075  BlendRegistry.Add(FID_EMMS, @EMMS_MMX, [ciMMX]);
     
    38841092  BlendRegistry.Add(FID_COLORSCALE, @ColorScale_MMX, [ciMMX]);
    38851093  BlendRegistry.Add(FID_LIGHTEN, @LightenReg_MMX, [ciMMX]);
     1094  BlendRegistry.Add(FID_BLENDREGRGB, @BlendRegRGB_MMX, [ciMMX]);
     1095  BlendRegistry.Add(FID_BLENDMEMRGB, @BlendMemRGB_MMX, [ciMMX]);
    38861096{$ENDIF}
    38871097{$IFNDEF OMIT_SSE2}
     
    38931103  BlendRegistry.Add(FID_BLENDREG, @BlendReg_SSE2, [ciSSE2]);
    38941104  BlendRegistry.Add(FID_BLENDMEM, @BlendMem_SSE2, [ciSSE2]);
     1105  BlendRegistry.Add(FID_BLENDMEMS, @BlendMems_SSE2, [ciSSE2]);
    38951106  BlendRegistry.Add(FID_BLENDMEMEX, @BlendMemEx_SSE2, [ciSSE2]);
    38961107  BlendRegistry.Add(FID_BLENDLINE, @BlendLine_SSE2, [ciSSE2]);
     
    39061117  BlendRegistry.Add(FID_COLORSCALE, @ColorScale_SSE2, [ciSSE2]);
    39071118  BlendRegistry.Add(FID_LIGHTEN, @LightenReg_SSE2, [ciSSE]);
    3908 {$ENDIF}
    3909 {$IFNDEF TARGET_x64}
    3910   BlendRegistry.Add(FID_MERGEREG, @MergeReg_ASM, []);
     1119  BlendRegistry.Add(FID_BLENDREGRGB, @BlendRegRGB_SSE2, [ciSSE2]);
     1120  BlendRegistry.Add(FID_BLENDMEMRGB, @BlendMemRGB_SSE2, [ciSSE2]);
     1121{$IFDEF TEST_BLENDMEMRGB128SSE4}
     1122  BlendRegistry.Add(FID_BLENDMEMRGB128, @BlendMemRGB128_SSE4, [ciSSE2]);
     1123{$ENDIF}
    39111124{$ENDIF}
    39121125{$ENDIF}
     
    39161129
    39171130initialization
     1131  BlendColorAdd := BlendColorAdd_Pas;
     1132
    39181133  RegisterBindings;
    39191134  MakeMergeTables;
     
    39291144finalization
    39301145{$IFNDEF PUREPASCAL}
    3931 {$IFNDEF OMIT_MMX}
    3932   if (ciMMX in CPUFeatures) then FreeAlphaTable;
    3933 {$ENDIF}
     1146  if [ciMMX, ciSSE2] * CPUFeatures <> [] then
     1147    FreeAlphaTable;
    39341148{$ENDIF}
    39351149
Note: See TracChangeset for help on using the changeset viewer.