home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 November / CDVD1105.ISO / Software / Freeware / programare / graphics32 / GR32_Blend.pas < prev    next >
Pascal/Delphi Source File  |  2005-02-24  |  50KB  |  1,634 lines

  1. unit GR32_Blend;
  2.  
  3. (* ***** BEGIN LICENSE BLOCK *****
  4.  * Version: MPL 1.1
  5.  *
  6.  * The contents of this file are subject to the Mozilla Public License Version
  7.  * 1.1 (the "License"); you may not use this file except in compliance with
  8.  * the License. You may obtain a copy of the License at
  9.  * http://www.mozilla.org/MPL/
  10.  *
  11.  * Software distributed under the License is distributed on an "AS IS" basis,
  12.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13.  * for the specific language governing rights and limitations under the
  14.  * License.
  15.  *
  16.  * The Original Code is Graphics32
  17.  *
  18.  * The Initial Developer of the Original Code is
  19.  * Alex A. Denisov
  20.  *
  21.  * Portions created by the Initial Developer are Copyright (C) 2000-2004
  22.  * the Initial Developer. All Rights Reserved.
  23.  *
  24.  * Contributor(s):
  25.  *  Mattias Andersson
  26.  *      - 2004/07/07 - MMX Blendmodes
  27.  *      - 2004/12/10 - _MergeReg, M_MergeReg
  28.  *
  29.  *  Michael Hansen <dyster_tid@hotmail.com>
  30.  *      - 2004/07/07 - Pascal Blendmodes, function setup
  31.  *
  32.  *  Bob Voigt
  33.  *      - 2004/08/25 - ColorDiv
  34.  *
  35.  * ***** END LICENSE BLOCK ***** *)
  36.  
  37. interface
  38.  
  39. {$I GR32.inc}
  40.  
  41. uses
  42.   GR32;
  43.  
  44. var
  45.   MMX_ACTIVE: Boolean;
  46.  
  47. procedure EMMS;
  48.  
  49. type
  50. { Function Prototypes }
  51.   TCombineReg  = function(X, Y, W: TColor32): TColor32;
  52.   TCombineMem  = procedure(F: TColor32; var B: TColor32; W: TColor32);
  53.   TBlendReg    = function(F, B: TColor32): TColor32;
  54.   TBlendMem    = procedure(F: TColor32; var B: TColor32);
  55.   TBlendRegEx  = function(F, B, M: TColor32): TColor32;
  56.   TBlendMemEx  = procedure(F: TColor32; var B: TColor32; M: TColor32);
  57.   TBlendLine   = procedure(Src, Dst: PColor32; Count: Integer);
  58.   TBlendLineEx = procedure(Src, Dst: PColor32; Count: Integer; M: TColor32);
  59.  
  60. var
  61. { Function Variables }
  62.   CombineReg: TCombineReg;
  63.   CombineMem: TCombineMem;
  64.  
  65.   BlendReg: TBlendReg;
  66.   BlendMem: TBlendMem;
  67.  
  68.   BlendRegEx: TBlendRegEx;
  69.   BlendMemEx: TBlendMemEx;
  70.  
  71.   BlendLine: TBlendLine;
  72.   BlendLineEx: TBlendLineEx;
  73.  
  74.   CombMergeReg: TCombineReg;
  75.   CombMergeMem: TCombineMem;
  76.  
  77.   MergeReg: TBlendReg;
  78.   MergeMem: TBlendMem;
  79.  
  80.   MergeRegEx: TBlendRegEx;
  81.   MergeMemEx: TBlendMemEx;
  82.  
  83.   MergeLine: TBlendLine;
  84.   MergeLineEx: TBlendLineEx;
  85.  
  86. { Access to alpha composite functions corresponding to a combine mode }
  87.   BLEND_REG: array[TCombineMode] of TBlendReg;
  88.   BLEND_MEM: array[TCombineMode] of TBlendMem;
  89.   COMBINE_REG: array[TCombineMode] of TCombineReg;
  90.   COMBINE_MEM: array[TCombineMode] of TCombineMem;
  91.   BLEND_REG_EX: array[TCombineMode] of TBlendRegEx;
  92.   BLEND_MEM_EX: array[TCombineMode] of TBlendMemEx;
  93.   BLEND_LINE: array[TCombineMode] of TBlendLine;
  94.   BLEND_LINE_EX: array[TCombineMode] of TBlendLineEx;
  95.  
  96. { Color algebra functions }
  97.   ColorAdd: TBlendReg;
  98.   ColorSub: TBlendReg;
  99.   ColorDiv: TBlendReg;
  100.   ColorModulate: TBlendReg;
  101.   ColorMax: TBlendReg;
  102.   ColorMin: TBlendReg;
  103.   ColorDifference: TBlendReg;
  104.   ColorExclusion: TBlendReg;
  105.  
  106. { Special LUT pointers }
  107.   AlphaTable: Pointer;
  108.   bias_ptr: Pointer;
  109.   alpha_ptr: Pointer;
  110.  
  111.  
  112. { Misc stuff }
  113. function Lighten(C: TColor32; Amount: Integer): TColor32;
  114.  
  115. implementation
  116.  
  117. uses Math, GR32_System;
  118.  
  119. { Non-MMX versions }
  120.  
  121. const bias = $00800080;
  122.  
  123. function _CombineReg(X, Y, W: TColor32): TColor32;
  124. asm
  125.   // combine RGBA channels of colors X and Y with the weight of X given in W
  126.   // Result Z = W * X + (1 - W) * Y (all channels are combined, including alpha)
  127.   // EAX <- X
  128.   // EDX <- Y
  129.   // ECX <- W
  130.  
  131.   // W = 0 or $FF?
  132.         JCXZ    @1              // CX = 0 ?  => Result := EDX
  133.         CMP     ECX,$FF         // CX = $FF ?  => Result := EDX
  134.         JE      @2
  135.  
  136.         PUSH    EBX
  137.  
  138.   // P = W * X
  139.         MOV     EBX,EAX         // EBX  <-  Xa Xr Xg Xb
  140.         AND     EAX,$00FF00FF   // EAX  <-  00 Xr 00 Xb
  141.         AND     EBX,$FF00FF00   // EBX  <-  Xa 00 Xg 00
  142.         IMUL    EAX,ECX         // EAX  <-  Pr ** Pb **
  143.         SHR     EBX,8           // EBX  <-  00 Xa 00 Xg
  144.         IMUL    EBX,ECX         // EBX  <-  Pa ** Pg **
  145.         ADD     EAX,bias
  146.         AND     EAX,$FF00FF00   // EAX  <-  Pa 00 Pg 00
  147.         SHR     EAX,8           // EAX  <-  00 Pr 00 Pb
  148.         ADD     EBX,bias
  149.         AND     EBX,$FF00FF00   // EBX  <-  Pa 00 Pg 00
  150.         OR      EAX,EBX         // EAX  <-  Pa Pr Pg Pb
  151.  
  152.   // W = 1 - W; Q = W * Y
  153.         XOR     ECX,$000000FF   // ECX  <-  1 - ECX
  154.         MOV     EBX,EDX         // EBX  <-  Ya Yr Yg Yb
  155.         AND     EDX,$00FF00FF   // EDX  <-  00 Yr 00 Yb
  156.         AND     EBX,$FF00FF00   // EBX  <-  Ya 00 Yg 00
  157.         IMUL    EDX,ECX         // EDX  <-  Qr ** Qb **
  158.         SHR     EBX,8           // EBX  <-  00 Ya 00 Yg
  159.         IMUL    EBX,ECX         // EBX  <-  Qa ** Qg **
  160.         ADD     EDX,bias
  161.         AND     EDX,$FF00FF00   // EDX  <-  Qr 00 Qb 00
  162.         SHR     EDX,8           // EDX  <-  00 Qr ** Qb
  163.         ADD     EBX,bias
  164.         AND     EBX,$FF00FF00   // EBX  <-  Qa 00 Qg 00
  165.         OR      EBX,EDX         // EBX  <-  Qa Qr Qg Qb
  166.  
  167.   // Z = P + Q (assuming no overflow at each byte)
  168.         ADD     EAX,EBX         // EAX  <-  Za Zr Zg Zb
  169.  
  170.         POP     EBX
  171.         RET
  172.  
  173. @1:     MOV     EAX,EDX
  174. @2:     RET
  175. end;
  176.  
  177. procedure _CombineMem(F: TColor32; var B: TColor32; W: TColor32);
  178. asm
  179.   // EAX <- F
  180.   // [EDX] <- B
  181.   // ECX <- W
  182.  
  183.   // Check W
  184.         JCXZ    @1              // W = 0 ?  => write nothing
  185.         CMP     ECX,$FF         // W = 255? => write F
  186.         JZ      @2
  187.  
  188.         PUSH    EBX
  189.         PUSH    ESI
  190.  
  191.   // P = W * F
  192.         MOV     EBX,EAX         // EBX  <-  ** Fr Fg Fb
  193.         AND     EAX,$00FF00FF   // EAX  <-  00 Fr 00 Fb
  194.         AND     EBX,$0000FF00   // EBX  <-  00 00 Fg 00
  195.         IMUL    EAX,ECX         // EAX  <-  Pr ** Pb **
  196.         SHR     EBX,8           // EBX  <-  00 00 00 Fg
  197.         IMUL    EBX,ECX         // EBX  <-  00 00 Pg **
  198.         ADD     EAX,bias
  199.         AND     EAX,$FF00FF00   // EAX  <-  Pr 00 Pb 00
  200.         SHR     EAX,8           // EAX  <-  00 Pr 00 Pb
  201.         ADD     EBX,bias
  202.         AND     EBX,$0000FF00   // EBX  <-  00 00 Pg 00
  203.         OR      EAX,EBX         // EAX  <-  00 Pr Pg Pb
  204.  
  205.   // W = 1 - W; Q = W * B
  206.         MOV     ESI,[EDX]
  207.         XOR     ECX,$000000FF   // ECX  <-  1 - ECX
  208.         MOV     EBX,ESI         // EBX  <-  00 Br Bg Bb
  209.         AND     ESI,$00FF00FF   // ESI  <-  00 Br 00 Bb
  210.         AND     EBX,$0000FF00   // EBX  <-  00 00 Bg 00
  211.         IMUL    ESI,ECX         // ESI  <-  Qr ** Qb **
  212.         SHR     EBX,8           // EBX  <-  00 00 00 Bg
  213.         IMUL    EBX,ECX         // EBX  <-  00 00 Qg **
  214.         ADD     ESI,bias
  215.         AND     ESI,$FF00FF00   // ESI  <-  Qr 00 Qb 00
  216.         SHR     ESI,8           // ESI  <-  00 Qr ** Qb
  217.         ADD     EBX,bias
  218.         AND     EBX,$0000FF00   // EBX  <-  00 00 Qg 00
  219.         OR      EBX,ESI         // EBX  <-  00 Qr Qg Qb
  220.  
  221.   // Z = P + Q (assuming no overflow at each byte)
  222.         ADD     EAX,EBX         // EAX  <-  00 Zr Zg Zb
  223.  
  224.         MOV     [EDX],EAX
  225.  
  226.         POP     ESI
  227.         POP     EBX
  228. @1:     RET
  229.  
  230. @2:     MOV     [EDX],EAX
  231.         RET
  232. end;
  233.  
  234. function _BlendReg(F, B: TColor32): TColor32;
  235. asm
  236.   // blend foregrownd color (F) to a background color (B),
  237.   // using alpha channel value of F
  238.   // Result Z = Fa * Frgb + (1 - Fa) * Brgb
  239.   // EAX <- F
  240.   // EDX <- B
  241.  
  242.   // Test Fa = 255 ?
  243.         CMP     EAX,$FF000000   // Fa = 255 ? => Result = EAX
  244.         JNC     @2
  245.  
  246.   // Test Fa = 0 ?
  247.         TEST    EAX,$FF000000   // Fa = 0 ?   => Result = EDX
  248.         JZ      @1
  249.  
  250.   // Get weight W = Fa * M
  251.         MOV     ECX,EAX         // ECX  <-  Fa Fr Fg Fb
  252.         SHR     ECX,24          // ECX  <-  00 00 00 Fa
  253.  
  254.         PUSH    EBX
  255.  
  256.   // P = W * F
  257.         MOV     EBX,EAX         // EBX  <-  Fa Fr Fg Fb
  258.         AND     EAX,$00FF00FF   // EAX  <-  00 Fr 00 Fb
  259.         AND     EBX,$FF00FF00   // EBX  <-  Fa 00 Fg 00
  260.         IMUL    EAX,ECX         // EAX  <-  Pr ** Pb **
  261.         SHR     EBX,8           // EBX  <-  00 Fa 00 Fg
  262.         IMUL    EBX,ECX         // EBX  <-  Pa ** Pg **
  263.         ADD     EAX,bias
  264.         AND     EAX,$FF00FF00   // EAX  <-  Pr 00 Pb 00
  265.         SHR     EAX,8           // EAX  <-  00 Pr ** Pb
  266.         ADD     EBX,bias
  267.         AND     EBX,$FF00FF00   // EBX  <-  Pa 00 Pg 00
  268.         OR      EAX,EBX         // EAX  <-  Pa Pr Pg Pb
  269.  
  270.   // W = 1 - W; Q = W * B
  271.         XOR     ECX,$000000FF   // ECX  <-  1 - ECX
  272.         MOV     EBX,EDX         // EBX  <-  Ba Br Bg Bb
  273.         AND     EDX,$00FF00FF   // EDX  <-  00 Br 00 Bb
  274.         AND     EBX,$FF00FF00   // EBX  <-  Ba 00 Bg 00
  275.         IMUL    EDX,ECX         // EDX  <-  Qr ** Qb **
  276.         SHR     EBX,8           // EBX  <-  00 Ba 00 Bg
  277.         IMUL    EBX,ECX         // EBX  <-  Qa ** Qg **
  278.         ADD     EDX,bias
  279.         AND     EDX,$FF00FF00   // EDX  <-  Qr 00 Qb 00
  280.         SHR     EDX,8           // EDX  <-  00 Qr ** Qb
  281.         ADD     EBX,bias
  282.         AND     EBX,$FF00FF00   // EBX  <-  Qa 00 Qg 00
  283.         OR      EBX,EDX         // EBX  <-  Qa Qr Qg Qb
  284.  
  285.   // Z = P + Q (assuming no overflow at each byte)
  286.         ADD     EAX,EBX         // EAX  <-  Za Zr Zg Zb
  287.  
  288.         POP     EBX
  289.         RET
  290.  
  291. @1:     MOV     EAX,EDX
  292. @2:     RET
  293. end;
  294.  
  295. procedure _BlendMem(F: TColor32; var B: TColor32);
  296. asm
  297.   // EAX <- F
  298.   // [EDX] <- B
  299.  
  300.  
  301.   // Test Fa = 0 ?
  302.         TEST    EAX,$FF000000   // Fa = 0 ?   => do not write
  303.         JZ      @2
  304.  
  305.   // Get weight W = Fa * M
  306.         MOV     ECX,EAX         // ECX  <-  Fa Fr Fg Fb
  307.         SHR     ECX,24          // ECX  <-  00 00 00 Fa
  308.  
  309.   // Test Fa = 255 ?
  310.         CMP     ECX,$FF
  311.         JZ      @1
  312.  
  313.         PUSH EBX
  314.         PUSH ESI
  315.  
  316.   // P = W * F
  317.         MOV     EBX,EAX         // EBX  <-  Fa Fr Fg Fb
  318.         AND     EAX,$00FF00FF   // EAX  <-  00 Fr 00 Fb
  319.         AND     EBX,$FF00FF00   // EBX  <-  Fa 00 Fg 00
  320.         IMUL    EAX,ECX         // EAX  <-  Pr ** Pb **
  321.         SHR     EBX,8           // EBX  <-  00 Fa 00 Fg
  322.         IMUL    EBX,ECX         // EBX  <-  Pa ** Pg **
  323.         ADD     EAX,bias
  324.         AND     EAX,$FF00FF00   // EAX  <-  Pr 00 Pb 00
  325.         SHR     EAX,8           // EAX  <-  00 Pr ** Pb
  326.         ADD     EBX,bias
  327.         AND     EBX,$FF00FF00   // EBX  <-  Pa 00 Pg 00
  328.         OR      EAX,EBX         // EAX  <-  Pa Pr Pg Pb
  329.  
  330.   // W = 1 - W; Q = W * B
  331.         MOV     ESI,[EDX]
  332.         XOR     ECX,$000000FF   // ECX  <-  1 - ECX
  333.         MOV     EBX,ESI         // EBX  <-  Ba Br Bg Bb
  334.         AND     ESI,$00FF00FF   // ESI  <-  00 Br 00 Bb
  335.         AND     EBX,$FF00FF00   // EBX  <-  Ba 00 Bg 00
  336.         IMUL    ESI,ECX         // ESI  <-  Qr ** Qb **
  337.         SHR     EBX,8           // EBX  <-  00 Ba 00 Bg
  338.         IMUL    EBX,ECX         // EBX  <-  Qa ** Qg **
  339.         ADD     ESI,bias
  340.         AND     ESI,$FF00FF00   // ESI  <-  Qr 00 Qb 00
  341.         SHR     ESI,8           // ESI  <-  00 Qr ** Qb
  342.         ADD     EBX,bias
  343.         AND     EBX,$FF00FF00   // EBX  <-  Qa 00 Qg 00
  344.         OR      EBX,ESI         // EBX  <-  Qa Qr Qg Qb
  345.  
  346.   // Z = P + Q (assuming no overflow at each byte)
  347.         ADD     EAX,EBX         // EAX  <-  Za Zr Zg Zb
  348.         MOV     [EDX],EAX
  349.  
  350.         POP     ESI
  351.         POP     EBX
  352.         RET
  353.  
  354. @1:     MOV     [EDX],EAX
  355. @2:     RET
  356. end;
  357.  
  358. function _BlendRegEx(F, B, M: TColor32): TColor32;
  359. asm
  360.   // blend foregrownd color (F) to a background color (B),
  361.   // using alpha channel value of F multiplied by master alpha (M)
  362.   // no checking for M = $FF, if this is the case when Graphics32 uses BlendReg
  363.   // Result Z = Fa * M * Frgb + (1 - Fa * M) * Brgb
  364.   // EAX <- F
  365.   // EDX <- B
  366.   // ECX <- M
  367.  
  368.   // Check Fa > 0 ?
  369.         TEST    EAX,$FF000000   // Fa = 0? => Result := EDX
  370.         JZ      @2
  371.  
  372.         PUSH    EBX
  373.  
  374.   // Get weight W = Fa * M
  375.         MOV     EBX,EAX         // EBX  <-  Fa Fr Fg Fb
  376.         INC     ECX             // 255:256 range bias
  377.         SHR     EBX,24          // EBX  <-  00 00 00 Fa
  378.         IMUL    ECX,EBX         // ECX  <-  00 00  W **
  379.         SHR     ECX,8           // ECX  <-  00 00 00  W
  380.         JZ      @1              // W = 0 ?  => Result := EDX
  381.  
  382.   // P = W * F
  383.         MOV     EBX,EAX         // EBX  <-  ** Fr Fg Fb
  384.         AND     EAX,$00FF00FF   // EAX  <-  00 Fr 00 Fb
  385.         AND     EBX,$0000FF00   // EBX  <-  00 00 Fg 00
  386.         IMUL    EAX,ECX         // EAX  <-  Pr ** Pb **
  387.         SHR     EBX,8           // EBX  <-  00 00 00 Fg
  388.         IMUL    EBX,ECX         // EBX  <-  00 00 Pg **
  389.         ADD     EAX,bias
  390.         AND     EAX,$FF00FF00   // EAX  <-  Pr 00 Pb 00
  391.         SHR     EAX,8           // EAX  <-  00 Pr ** Pb
  392.         ADD     EBX,bias
  393.         AND     EBX,$0000FF00   // EBX  <-  00 00 Pg 00
  394.         OR      EAX,EBX         // EAX  <-  00 Pr Pg Pb
  395.  
  396.   // W = 1 - W; Q = W * B
  397.         XOR     ECX,$000000FF   // ECX  <-  1 - ECX
  398.         MOV     EBX,EDX         // EBX  <-  00 Br Bg Bb
  399.         AND     EDX,$00FF00FF   // EDX  <-  00 Br 00 Bb
  400.         AND     EBX,$0000FF00   // EBX  <-  00 00 Bg 00
  401.         IMUL    EDX,ECX         // EDX  <-  Qr ** Qb **
  402.         SHR     EBX,8           // EBX  <-  00 00 00 Bg
  403.         IMUL    EBX,ECX         // EBX  <-  00 00 Qg **
  404.         ADD     EDX,bias
  405.         AND     EDX,$FF00FF00   // EDX  <-  Qr 00 Qb 00
  406.         SHR     EDX,8           // EDX  <-  00 Qr ** Qb
  407.         ADD     EBX,bias
  408.         AND     EBX,$0000FF00   // EBX  <-  00 00 Qg 00
  409.         OR      EBX,EDX         // EBX  <-  00 Qr Qg Qb
  410.  
  411.   // Z = P + Q (assuming no overflow at each byte)
  412.         ADD     EAX,EBX         // EAX  <-  00 Zr Zg Zb
  413.  
  414.         POP     EBX
  415.         RET
  416.         
  417. @1:     POP     EBX
  418. @2:     MOV     EAX,EDX
  419.         RET
  420. end;
  421.  
  422. procedure _BlendMemEx(F: TColor32; var B: TColor32; M: TColor32);
  423. asm
  424.   // EAX <- F
  425.   // [EDX] <- B
  426.   // ECX <- M
  427.  
  428.   // Check Fa > 0 ?
  429.         TEST    EAX,$FF000000   // Fa = 0? => write nothing
  430.         JZ      @2
  431.  
  432.         PUSH    EBX
  433.  
  434.   // Get weight W = Fa * M
  435.         MOV     EBX,EAX         // EBX  <-  Fa Fr Fg Fb
  436.         INC     ECX             // 255:256 range bias
  437.         SHR     EBX,24          // EBX  <-  00 00 00 Fa
  438.         IMUL    ECX,EBX         // ECX  <-  00 00  W **
  439.         SHR     ECX,8           // ECX  <-  00 00 00  W
  440.         JZ      @1              // W = 0 ?  => write nothing
  441.  
  442.         PUSH    ESI
  443.  
  444.   // P = W * F
  445.         MOV     EBX,EAX         // EBX  <-  ** Fr Fg Fb
  446.         AND     EAX,$00FF00FF   // EAX  <-  00 Fr 00 Fb
  447.         AND     EBX,$0000FF00   // EBX  <-  00 00 Fg 00
  448.         IMUL    EAX,ECX         // EAX  <-  Pr ** Pb **
  449.         SHR     EBX,8           // EBX  <-  00 00 00 Fg
  450.         IMUL    EBX,ECX         // EBX  <-  00 00 Pg **
  451.         ADD     EAX,bias
  452.         AND     EAX,$FF00FF00   // EAX  <-  Pr 00 Pb 00
  453.         SHR     EAX,8           // EAX  <-  00 Pr ** Pb
  454.         ADD     EBX,bias
  455.         AND     EBX,$0000FF00   // EBX  <-  00 00 Pg 00
  456.         OR      EAX,EBX         // EAX  <-  00 Pr Pg Pb
  457.  
  458.   // W = 1 - W; Q = W * B
  459.         MOV     ESI,[EDX]
  460.         XOR     ECX,$000000FF   // ECX  <-  1 - ECX
  461.         MOV     EBX,ESI         // EBX  <-  00 Br Bg Bb
  462.         AND     ESI,$00FF00FF   // ESI  <-  00 Br 00 Bb
  463.         AND     EBX,$0000FF00   // EBX  <-  00 00 Bg 00
  464.         IMUL    ESI,ECX         // ESI  <-  Qr ** Qb **
  465.         SHR     EBX,8           // EBX  <-  00 00 00 Bg
  466.         IMUL    EBX,ECX         // EBX  <-  00 00 Qg **
  467.         ADD     ESI,bias
  468.         AND     ESI,$FF00FF00   // ESI  <-  Qr 00 Qb 00
  469.         SHR     ESI,8           // ESI  <-  00 Qr ** Qb
  470.         ADD     EBX,bias
  471.         AND     EBX,$0000FF00   // EBX  <-  00 00 Qg 00
  472.         OR      EBX,ESI         // EBX  <-  00 Qr Qg Qb
  473.  
  474.   // Z = P + Q (assuming no overflow at each byte)
  475.         ADD     EAX,EBX         // EAX  <-  00 Zr Zg Zb
  476.  
  477.         MOV     [EDX],EAX
  478.         POP     ESI
  479.  
  480. @1:     POP     EBX
  481. @2:     RET
  482. end;
  483.  
  484. procedure _BlendLine(Src, Dst: PColor32; Count: Integer);
  485. asm
  486.   // EAX <- Src
  487.   // EDX <- Dst
  488.   // ECX <- Count
  489.  
  490.   // test the counter for zero or negativity
  491.         TEST    ECX,ECX
  492.         JS      @4
  493.  
  494.         PUSH    EBX
  495.         PUSH    ESI
  496.         PUSH    EDI
  497.  
  498.         MOV     ESI,EAX         // ESI <- Src
  499.         MOV     EDI,EDX         // EDI <- Dst
  500.  
  501.   // loop start
  502. @1:     MOV     EAX,[ESI]
  503.         TEST    EAX,$FF000000
  504.         JZ      @3              // complete transparency, proceed to next point
  505.  
  506.         PUSH    ECX             // store counter
  507.  
  508.   // Get weight W = Fa * M
  509.         MOV     ECX,EAX         // ECX  <-  Fa Fr Fg Fb
  510.         SHR     ECX,24          // ECX  <-  00 00 00 Fa
  511.  
  512.   // Test Fa = 255 ?
  513.         CMP     ECX,$FF
  514.         JZ      @2
  515.  
  516.   // P = W * F
  517.         MOV     EBX,EAX         // EBX  <-  Fa Fr Fg Fb
  518.         AND     EAX,$00FF00FF   // EAX  <-  00 Fr 00 Fb
  519.         AND     EBX,$FF00FF00   // EBX  <-  Fa 00 Fg 00
  520.         IMUL    EAX,ECX         // EAX  <-  Pr ** Pb **
  521.         SHR     EBX,8           // EBX  <-  00 Fa 00 Fg
  522.         IMUL    EBX,ECX         // EBX  <-  Pa ** Pg **
  523.         ADD     EAX,bias
  524.         AND     EAX,$FF00FF00   // EAX  <-  Pr 00 Pb 00
  525.         SHR     EAX,8           // EAX  <-  00 Pr ** Pb
  526.         ADD     EBX,bias
  527.         AND     EBX,$FF00FF00   // EBX  <-  Pa 00 Pg 00
  528.         OR      EAX,EBX         // EAX  <-  Pa Pr Pg Pb
  529.  
  530.   // W = 1 - W; Q = W * B
  531.         MOV     EDX,[EDI]
  532.         XOR     ECX,$000000FF   // ECX  <-  1 - ECX
  533.         MOV     EBX,EDX         // EBX  <-  Ba Br Bg Bb
  534.         AND     EDX,$00FF00FF   // ESI  <-  00 Br 00 Bb
  535.         AND     EBX,$FF00FF00   // EBX  <-  Ba 00 Bg 00
  536.         IMUL    EDX,ECX         // ESI  <-  Qr ** Qb **
  537.         SHR     EBX,8           // EBX  <-  00 Ba 00 Bg
  538.         IMUL    EBX,ECX         // EBX  <-  Qa ** Qg **
  539.         ADD     EDX,bias
  540.         AND     EDX,$FF00FF00   // ESI  <-  Qr 00 Qb 00
  541.         SHR     EDX,8           // ESI  <-  00 Qr ** Qb
  542.         ADD     EBX,bias
  543.         AND     EBX,$FF00FF00   // EBX  <-  Qa 00 Qg 00
  544.         OR      EBX,EDX         // EBX  <-  Qa Qr Qg Qb
  545.  
  546.   // Z = P + Q (assuming no overflow at each byte)
  547.         ADD     EAX,EBX         // EAX  <-  Za Zr Zg Zb
  548. @2:     MOV     [EDI],EAX
  549.  
  550.         POP     ECX             // restore counter
  551.  
  552. @3:     ADD     ESI,4
  553.         ADD     EDI,4
  554.  
  555.   // loop end
  556.         DEC     ECX
  557.         JNZ     @1
  558.  
  559.         POP     EDI
  560.         POP     ESI
  561.         POP     EBX
  562.  
  563. @4:     RET
  564. end;
  565.  
  566. procedure _BlendLineEx(Src, Dst: PColor32; Count: Integer; M: TColor32);
  567. begin
  568.   while Count > 0 do
  569.   begin
  570.     _BlendMemEx(Src^, Dst^, M);
  571.     Inc(Src);
  572.     Inc(Dst);
  573.     Dec(Count);
  574.   end;
  575. end;
  576.  
  577. { MMX versions }
  578.  
  579.  
  580. procedure GenAlphaTable;
  581. var
  582.   I: Integer;
  583.   L: Longword;
  584.   P: ^Longword;
  585. begin
  586.   GetMem(AlphaTable, 257 * 8);
  587.   alpha_ptr := Pointer(Integer(AlphaTable) and $FFFFFFF8);
  588.   if Integer(alpha_ptr) < Integer(AlphaTable) then
  589.     alpha_ptr := Pointer(Integer(alpha_ptr) + 8);
  590.   P := alpha_ptr;
  591.   for I := 0 to 255 do
  592.   begin
  593.     L := I + I shl 16;
  594.     P^ := L;
  595.     Inc(P);
  596.     P^ := L;
  597.     Inc(P);
  598.   end;
  599.   bias_ptr := Pointer(Integer(alpha_ptr) + $80 * 8);
  600. end;
  601.  
  602. procedure FreeAlphaTable;
  603. begin
  604.   FreeMem(AlphaTable);
  605. end;
  606.  
  607. procedure EMMS;
  608. begin
  609.   if MMX_ACTIVE then
  610.   asm
  611.     db $0F,$77               /// EMMS
  612.   end;
  613. end;
  614.  
  615. function M_CombineReg(X, Y, W: TColor32): TColor32;
  616. asm
  617.   // EAX - Color X
  618.   // EDX - Color Y
  619.   // ECX - Weight of X [0..255]
  620.   // Result := W * (X - Y) + Y
  621.  
  622.         db $0F,$6E,$C8           /// MOVD      MM1,EAX
  623.         db $0F,$EF,$C0           /// PXOR      MM0,MM0
  624.         SHL       ECX,3
  625.         db $0F,$6E,$D2           /// MOVD      MM2,EDX
  626.         db $0F,$60,$C8           /// PUNPCKLBW MM1,MM0
  627.         db $0F,$60,$D0           /// PUNPCKLBW MM2,MM0
  628.         ADD       ECX,alpha_ptr
  629.         db $0F,$F9,$CA           /// PSUBW     MM1,MM2
  630.         db $0F,$D5,$09           /// PMULLW    MM1,[ECX]
  631.         db $0F,$71,$F2,$08       /// PSLLW     MM2,8
  632.         MOV       ECX,bias_ptr
  633.         db $0F,$FD,$11           /// PADDW     MM2,[ECX]
  634.         db $0F,$FD,$CA           /// PADDW     MM1,MM2
  635.         db $0F,$71,$D1,$08       /// PSRLW     MM1,8
  636.         db $0F,$67,$C8           /// PACKUSWB  MM1,MM0
  637.         db $0F,$7E,$C8           /// MOVD      EAX,MM1
  638. end;
  639.  
  640. procedure M_CombineMem(F: TColor32; var B: TColor32; W: TColor32);
  641. asm
  642.   // EAX - Color X
  643.   // [EDX] - Color Y
  644.   // ECX - Weight of X [0..255]
  645.   // Result := W * (X - Y) + Y
  646.  
  647.         JCXZ      @1
  648.         CMP       ECX,$FF
  649.         JZ        @2
  650.  
  651.         db $0F,$6E,$C8           /// MOVD      MM1,EAX
  652.         db $0F,$EF,$C0           /// PXOR      MM0,MM0
  653.         SHL       ECX,3
  654.         db $0F,$6E,$12           /// MOVD      MM2,[EDX]
  655.         db $0F,$60,$C8           /// PUNPCKLBW MM1,MM0
  656.         db $0F,$60,$D0           /// PUNPCKLBW MM2,MM0
  657.         ADD       ECX,alpha_ptr
  658.         db $0F,$F9,$CA           /// PSUBW     MM1,MM2
  659.         db $0F,$D5,$09           /// PMULLW    MM1,[ECX]
  660.         db $0F,$71,$F2,$08       /// PSLLW     MM2,8
  661.         MOV       ECX,bias_ptr
  662.         db $0F,$FD,$11           /// PADDW     MM2,[ECX]
  663.         db $0F,$FD,$CA           /// PADDW     MM1,MM2
  664.         db $0F,$71,$D1,$08       /// PSRLW     MM1,8
  665.         db $0F,$67,$C8           /// PACKUSWB  MM1,MM0
  666.         db $0F,$7E,$0A           /// MOVD      [EDX],MM1
  667. @1:     RET
  668.  
  669. @2:     MOV       [EDX],EAX
  670. end;
  671.  
  672. function M_BlendReg(F, B: TColor32): TColor32;
  673. asm
  674.   // blend foregrownd color (F) to a background color (B),
  675.   // using alpha channel value of F
  676.   // EAX <- F
  677.   // EDX <- B
  678.   // Result := Fa * (Frgb - Brgb) + Brgb
  679.         db $0F,$6E,$C0           /// MOVD      MM0,EAX
  680.         db $0F,$EF,$DB           /// PXOR      MM3,MM3
  681.         db $0F,$6E,$D2           /// MOVD      MM2,EDX
  682.         db $0F,$60,$C3           /// PUNPCKLBW MM0,MM3
  683.         MOV     ECX,bias_ptr
  684.         db $0F,$60,$D3           /// PUNPCKLBW MM2,MM3
  685.         db $0F,$6F,$C8           /// MOVQ      MM1,MM0
  686.         db $0F,$69,$C9           /// PUNPCKHWD MM1,MM1
  687.         db $0F,$F9,$C2           /// PSUBW     MM0,MM2
  688.         db $0F,$6A,$C9           /// PUNPCKHDQ MM1,MM1
  689.         db $0F,$71,$F2,$08       /// PSLLW     MM2,8
  690.         db $0F,$D5,$C1           /// PMULLW    MM0,MM1
  691.         db $0F,$FD,$11           /// PADDW     MM2,[ECX]
  692.         db $0F,$FD,$D0           /// PADDW     MM2,MM0
  693.         db $0F,$71,$D2,$08       /// PSRLW     MM2,8
  694.         db $0F,$67,$D3           /// PACKUSWB  MM2,MM3
  695.         db $0F,$7E,$D0           /// MOVD      EAX,MM2
  696. end;
  697.  
  698. procedure M_BlendMem(F: TColor32; var B: TColor32);
  699. asm
  700.   // EAX - Color X
  701.   // [EDX] - Color Y
  702.   // Result := W * (X - Y) + Y
  703.  
  704.         TEST      EAX,$FF000000
  705.         JZ        @1
  706.         CMP       EAX,$FF000000
  707.         JNC       @2
  708.  
  709.         db $0F,$EF,$DB           /// PXOR      MM3,MM3
  710.         db $0F,$6E,$C0           /// MOVD      MM0,EAX
  711.         db $0F,$6E,$12           /// MOVD      MM2,[EDX]
  712.         db $0F,$60,$C3           /// PUNPCKLBW MM0,MM3
  713.         MOV       ECX,bias_ptr
  714.         db $0F,$60,$D3           /// PUNPCKLBW MM2,MM3
  715.         db $0F,$6F,$C8           /// MOVQ      MM1,MM0
  716.         db $0F,$69,$C9           /// PUNPCKHWD MM1,MM1
  717.         db $0F,$F9,$C2           /// PSUBW     MM0,MM2
  718.         db $0F,$6A,$C9           /// PUNPCKHDQ MM1,MM1
  719.         db $0F,$71,$F2,$08       /// PSLLW     MM2,8
  720.         db $0F,$D5,$C1           /// PMULLW    MM0,MM1
  721.         db $0F,$FD,$11           /// PADDW     MM2,[ECX]
  722.         db $0F,$FD,$D0           /// PADDW     MM2,MM0
  723.         db $0F,$71,$D2,$08       /// PSRLW     MM2,8
  724.         db $0F,$67,$D3           /// PACKUSWB  MM2,MM3
  725.         db $0F,$7E,$12           /// MOVD      [EDX],MM2
  726. @1:     RET
  727.  
  728. @2:     MOV       [EDX],EAX
  729. end;
  730.  
  731. function M_BlendRegEx(F, B, M: TColor32): TColor32;
  732. asm
  733.   // blend foregrownd color (F) to a background color (B),
  734.   // using alpha channel value of F
  735.   // EAX <- F
  736.   // EDX <- B
  737.   // ECX <- M
  738.   // Result := M * Fa * (Frgb - Brgb) + Brgb
  739.         PUSH      EBX
  740.         MOV       EBX,EAX
  741.         SHR       EBX,24
  742.         INC       ECX             // 255:256 range bias
  743.         IMUL      ECX,EBX
  744.         SHR       ECX,8
  745.         JZ        @1
  746.  
  747.         db $0F,$EF,$C0           /// PXOR      MM0,MM0
  748.         db $0F,$6E,$C8           /// MOVD      MM1,EAX
  749.         SHL       ECX,3
  750.         db $0F,$6E,$D2           /// MOVD      MM2,EDX
  751.         db $0F,$60,$C8           /// PUNPCKLBW MM1,MM0
  752.         db $0F,$60,$D0           /// PUNPCKLBW MM2,MM0
  753.         ADD       ECX,alpha_ptr
  754.         db $0F,$F9,$CA           /// PSUBW     MM1,MM2
  755.         db $0F,$D5,$09           /// PMULLW    MM1,[ECX]
  756.         db $0F,$71,$F2,$08       /// PSLLW     MM2,8
  757.         MOV       ECX,bias_ptr
  758.         db $0F,$FD,$11           /// PADDW     MM2,[ECX]
  759.         db $0F,$FD,$CA           /// PADDW     MM1,MM2
  760.         db $0F,$71,$D1,$08       /// PSRLW     MM1,8
  761.         db $0F,$67,$C8           /// PACKUSWB  MM1,MM0
  762.         db $0F,$7E,$C8           /// MOVD      EAX,MM1
  763.  
  764.         POP       EBX
  765.         RET
  766.  
  767. @1:     MOV       EAX,EDX
  768.         POP       EBX
  769. end;
  770.  
  771. procedure M_BlendMemEx(F: TColor32; var B:TColor32; M: TColor32);
  772. asm
  773.   // blend foregrownd color (F) to a background color (B),
  774.   // using alpha channel value of F
  775.   // EAX <- F
  776.   // [EDX] <- B
  777.   // ECX <- M
  778.   // Result := M * Fa * (Frgb - Brgb) + Brgb
  779.         TEST      EAX,$FF000000
  780.         JZ        @2
  781.  
  782.         PUSH      EBX
  783.         MOV       EBX,EAX
  784.         SHR       EBX,24
  785.         INC       ECX             // 255:256 range bias
  786.         IMUL      ECX,EBX
  787.         SHR       ECX,8
  788.         JZ        @1
  789.  
  790.         db $0F,$EF,$C0           /// PXOR      MM0,MM0
  791.         db $0F,$6E,$C8           /// MOVD      MM1,EAX
  792.         SHL       ECX,3
  793.         db $0F,$6E,$12           /// MOVD      MM2,[EDX]
  794.         db $0F,$60,$C8           /// PUNPCKLBW MM1,MM0
  795.         db $0F,$60,$D0           /// PUNPCKLBW MM2,MM0
  796.         ADD       ECX,alpha_ptr
  797.         db $0F,$F9,$CA           /// PSUBW     MM1,MM2
  798.         db $0F,$D5,$09           /// PMULLW    MM1,[ECX]
  799.         db $0F,$71,$F2,$08       /// PSLLW     MM2,8
  800.         MOV       ECX,bias_ptr
  801.         db $0F,$FD,$11           /// PADDW     MM2,[ECX]
  802.         db $0F,$FD,$CA           /// PADDW     MM1,MM2
  803.         db $0F,$71,$D1,$08       /// PSRLW     MM1,8
  804.         db $0F,$67,$C8           /// PACKUSWB  MM1,MM0
  805.         db $0F,$7E,$0A           /// MOVD      [EDX],MM1
  806. @1:     POP       EBX
  807. @2:
  808. end;
  809.  
  810. procedure M_BlendLine(Src, Dst: PColor32; Count: Integer);
  811. asm
  812.   // EAX <- Src
  813.   // EDX <- Dst
  814.   // ECX <- Count
  815.  
  816.   // test the counter for zero or negativity
  817.         TEST      ECX,ECX
  818.         JS        @4
  819.  
  820.         PUSH      ESI
  821.         PUSH      EDI
  822.  
  823.         MOV       ESI,EAX         // ESI <- Src
  824.         MOV       EDI,EDX         // EDI <- Dst
  825.  
  826.   // loop start
  827. @1:     MOV       EAX,[ESI]
  828.         TEST      EAX,$FF000000
  829.         JZ        @3              // complete transparency, proceed to next point
  830.         CMP       EAX,$FF000000
  831.         JNC       @2              // opaque pixel, copy without blending
  832.  
  833.   // blend
  834.         db $0F,$6E,$C0           /// MOVD      MM0,EAX
  835.         db $0F,$EF,$DB           /// PXOR      MM3,MM3
  836.         db $0F,$6E,$17           /// MOVD      MM2,[EDI]
  837.         db $0F,$60,$C3           /// PUNPCKLBW MM0,MM3
  838.         MOV       EAX,bias_ptr
  839.         db $0F,$60,$D3           /// PUNPCKLBW MM2,MM3
  840.         db $0F,$6F,$C8           /// MOVQ      MM1,MM0
  841.         db $0F,$69,$C9           /// PUNPCKHWD MM1,MM1
  842.         db $0F,$F9,$C2           /// PSUBW     MM0,MM2
  843.         db $0F,$6A,$C9           /// PUNPCKHDQ MM1,MM1
  844.         db $0F,$71,$F2,$08       /// PSLLW     MM2,8
  845.         db $0F,$D5,$C1           /// PMULLW    MM0,MM1
  846.         db $0F,$FD,$10           /// PADDW     MM2,[EAX]
  847.         db $0F,$FD,$D0           /// PADDW     MM2,MM0
  848.         db $0F,$71,$D2,$08       /// PSRLW     MM2,8
  849.         db $0F,$67,$D3           /// PACKUSWB  MM2,MM3
  850.         db $0F,$7E,$D0           /// MOVD      EAX,MM2
  851.  
  852. @2:     MOV       [EDI],EAX
  853.  
  854. @3:     ADD       ESI,4
  855.         ADD       EDI,4
  856.  
  857.   // loop end
  858.         DEC       ECX
  859.         JNZ       @1
  860.  
  861.         POP       EDI
  862.         POP       ESI
  863.  
  864. @4:     RET
  865. end;
  866.  
  867. procedure M_BlendLineEx(Src, Dst: PColor32; Count: Integer; M: TColor32);
  868. asm
  869.   // EAX <- Src
  870.   // EDX <- Dst
  871.   // ECX <- Count
  872.  
  873.   // test the counter for zero or negativity
  874.         TEST      ECX,ECX
  875.         JS        @4
  876.  
  877.         PUSH      ESI
  878.         PUSH      EDI
  879.         PUSH      EBX
  880.  
  881.         MOV       ESI,EAX         // ESI <- Src
  882.         MOV       EDI,EDX         // EDI <- Dst
  883.         MOV       EDX,M           // EDX <- Master Alpha
  884.  
  885.   // loop start
  886. @1:     MOV       EAX,[ESI]
  887.         TEST      EAX,$FF000000
  888.         JZ        @3             // complete transparency, proceed to next point
  889.         MOV       EBX,EAX
  890.         SHR       EBX,24
  891.         INC       EBX            // 255:256 range bias
  892.         IMUL      EBX,EDX
  893.         SHR       EBX,8
  894.         JZ        @3              // complete transparency, proceed to next point
  895.  
  896.   // blend
  897.         db $0F,$EF,$C0           /// PXOR      MM0,MM0
  898.         db $0F,$6E,$C8           /// MOVD      MM1,EAX
  899.         SHL       EBX,3
  900.         db $0F,$6E,$17           /// MOVD      MM2,[EDI]
  901.         db $0F,$60,$C8           /// PUNPCKLBW MM1,MM0
  902.         db $0F,$60,$D0           /// PUNPCKLBW MM2,MM0
  903.         ADD       EBX,alpha_ptr
  904.         db $0F,$F9,$CA           /// PSUBW     MM1,MM2
  905.         db $0F,$D5,$0B           /// PMULLW    MM1,[EBX]
  906.         db $0F,$71,$F2,$08       /// PSLLW     MM2,8
  907.         MOV       EBX,bias_ptr
  908.         db $0F,$FD,$13           /// PADDW     MM2,[EBX]
  909.         db $0F,$FD,$CA           /// PADDW     MM1,MM2
  910.         db $0F,$71,$D1,$08       /// PSRLW     MM1,8
  911.         db $0F,$67,$C8           /// PACKUSWB  MM1,MM0
  912.         db $0F,$7E,$C8           /// MOVD      EAX,MM1
  913.  
  914. @2:     MOV       [EDI],EAX
  915.  
  916. @3:     ADD       ESI,4
  917.         ADD       EDI,4
  918.  
  919.   // loop end
  920.         DEC       ECX
  921.         JNZ       @1
  922.  
  923.         POP       EBX
  924.         POP       EDI
  925.         POP       ESI
  926. @4:
  927. end;
  928.  
  929. { Merge }
  930.  
  931. function _MergeReg(F, B: TColor32): TColor32;
  932. var
  933.   Fa, Fr, Fg, Fb: Byte;
  934.   Ba, Br, Bg, Bb: Byte;
  935.   Ra, Rr, Rg, Rb: Byte;
  936.   InvRa: Integer;
  937. begin
  938.   Fa := F shr 24;
  939.   if Fa = $FF then
  940.   begin
  941.     Result := F;
  942.     exit;
  943.   end
  944.   else if Fa = 0 then
  945.   begin
  946.     Result := B;
  947.     Exit;
  948.   end;
  949.  
  950.   Ba := B shr 24;
  951.   if Ba = 0 then
  952.   begin
  953.     Result := F;
  954.     exit;
  955.   end;
  956.  
  957.   // Blended pixels
  958.   Fr := F shr 16;  Fg := F shr 8;  Fb := F;
  959.   Br := B shr 16;  Bg := B shr 8;  Bb := B;
  960.   Ra := Fa + Ba - (Fa * Ba) div 255;
  961.   InvRa := (256 * 256) div Ra;
  962.   Br := Br * Ba shr 8;
  963.   Rr := (Fa * (Fr - Br) shr 8 + Br) * InvRa shr 8;
  964.   Bg := Bg * Ba shr 8;
  965.   Rg := (Fa * (Fg - Bg) shr 8 + Bg) * InvRa shr 8;
  966.   Bb := Bb * Ba shr 8;
  967.   Rb := (Fa * (Fb - Bb) shr 8 + Bb) * InvRa shr 8;
  968.   Result := Ra shl 24 + Rr shl 16 + Rg shl 8 + Rb;
  969. end;
  970.  
  971. procedure _MergeMem(F: TColor32; var B:TColor32);
  972. begin
  973.   B := _MergeReg(F, B);
  974. end;
  975.  
  976. function _MergeRegEx(F, B, M: TColor32): TColor32;
  977. var
  978.   Fa, Fr, Fg, Fb: Byte;
  979.   Ba, Br, Bg, Bb: Byte;
  980.   Ra, Rr, Rg, Rb: Byte;
  981.   InvRa: Integer;
  982. begin
  983.   Fa := F shr 24;
  984.   if Fa = 255 then
  985.   begin
  986.     if M = 255 then
  987.     begin
  988.       Result := F;
  989.       Exit;
  990.     end
  991.     else if M = 0 then
  992.     begin
  993.       Result := B;
  994.       Exit;
  995.     end;
  996.   end
  997.   else if Fa = 0 then
  998.   begin
  999.     Result := B;
  1000.     Exit;
  1001.   end;
  1002.  
  1003.   Fa := (Fa * M) div 255;
  1004.   // Create F, but now with correct Alpha
  1005.   F := F and $00FFFFFF or Fa shl 24;
  1006.   if Fa = $FF then
  1007.   begin
  1008.     Result := F;
  1009.     Exit;
  1010.   end;
  1011.   Ba := B shr 24;
  1012.   if Ba = 0 then
  1013.   begin
  1014.     Result := F;
  1015.     Exit;
  1016.   end;
  1017.  
  1018.   // Blended pixels
  1019.   Fr := F shr 16;  Fg := F shr 8;  Fb := F;
  1020.   Br := B shr 16;  Bg := B shr 8;  Bb := B;
  1021.   Ra := Fa + Ba - (Fa * Ba) div 255;
  1022.   InvRa := (256 * 256) div Ra;
  1023.   Br := Br * Ba shr 8;
  1024.   Rr := (Fa * (Fr - Br) shr 8 + Br) * InvRa shr 8;
  1025.   Bg := Bg * Ba shr 8;
  1026.   Rg := (Fa * (Fg - Bg) shr 8 + Bg) * InvRa shr 8;
  1027.   Bb := Bb * Ba shr 8;
  1028.   Rb := (Fa * (Fb - Bb) shr 8 + Bb) * InvRa shr 8;
  1029.   Result := Ra shl 24 + Rr shl 16 + Rg shl 8 + Rb;
  1030. end;
  1031.  
  1032. procedure _MergeMemEx(F: TColor32; var B:TColor32; M: TColor32);
  1033. begin
  1034.   B := _MergeRegEx(F, B, M);
  1035. end;
  1036.  
  1037. procedure _MergeLine(Src, Dst: PColor32; Count: Integer);
  1038. begin
  1039.   while Count > 0 do
  1040.   begin
  1041.     Dst^ := _MergeReg(Src^, Dst^);
  1042.     Inc(Src);
  1043.     Inc(Dst);
  1044.     Dec(Count);
  1045.   end;
  1046. end;
  1047.  
  1048. procedure _MergeLineEx(Src, Dst: PColor32; Count: Integer; M: TColor32);
  1049. begin
  1050.   while Count > 0 do
  1051.   begin
  1052.     Dst^ := _MergeRegEx(Src^, Dst^, M);
  1053.     Inc(Src);
  1054.     Inc(Dst);
  1055.     Dec(Count);
  1056.   end;
  1057. end;
  1058.  
  1059. function _CombMergeReg(X, Y, W: TColor32): TColor32;
  1060. begin
  1061.   Result := _MergeReg(X and $00FFFFFF or W shl 24, Y);
  1062. end;
  1063.  
  1064. procedure _CombMergeMem(X: TColor32; var Y: TColor32; W: TColor32);
  1065. begin
  1066.   Y := _MergeReg(X and $00FFFFFF or W shl 24, Y);
  1067. end;
  1068.  
  1069. { MMX Merge }
  1070.  
  1071. function M_MergeReg(F, B: TColor32): TColor32;
  1072. asm
  1073.   { This is an implementation of the merge formula, as described
  1074.     in a paper by Bruce Wallace in 1981. Merging is associative,
  1075.     that is, A over (B over C) = (A over B) over C. The formula is,
  1076.  
  1077.       Ra = Fa + Ba - Fa * Ba
  1078.       Rc = (Fa (Fc - Bc * Ba) + Bc * Ba) / Ra
  1079.  
  1080.     where
  1081.  
  1082.       Rc is the resultant color,  Ra is the resultant alpha,
  1083.       Fc is the foreground color, Fa is the foreground alpha,
  1084.       Bc is the background color, Ba is the background alpha.
  1085.   }
  1086.  
  1087.         TEST      EAX,$FF000000  // foreground completely transparent =>
  1088.         JZ        @1             // result = background
  1089.         TEST      EDX,$FF000000  // background completely transparent =>
  1090.         JZ        @2             // result = foreground
  1091.         CMP       EAX,$FF000000  // foreground completely opaque =>
  1092.         JNC       @2             // result = foreground
  1093.  
  1094.         db $0F,$EF,$DB           /// PXOR      MM3,MM3
  1095.         PUSH      ESI
  1096.         db $0F,$6E,$C0           /// MOVD      MM0,EAX        // MM0  <-  Fa Fr Fg Fb
  1097.         db $0F,$60,$C3           /// PUNPCKLBW MM0,MM3        // MM0  <-  00 Fa 00 Fr 00 Fg 00 Fb
  1098.         db $0F,$6E,$CA           /// MOVD      MM1,EDX        // MM1  <-  Ba Br Bg Bb
  1099.         db $0F,$60,$CB           /// PUNPCKLBW MM1,MM3        // MM1  <-  00 Ba 00 Br 00 Bg 00 Bb
  1100.         SHR       EAX,24         // EAX  <-  00 00 00 Fa
  1101.         db $0F,$6F,$E0           /// MOVQ      MM4,MM0        // MM4  <-  00 Fa 00 Fr 00 Fg 00 Fb
  1102.         SHR       EDX,24         // EDX  <-  00 00 00 Ba
  1103.         db $0F,$6F,$E9           /// MOVQ      MM5,MM1        // MM5  <-  00 Ba 00 Br 00 Bg 00 Bb
  1104.         MOV       ECX,EAX        // ECX  <-  00 00 00 Fa
  1105.         db $0F,$69,$E4           /// PUNPCKHWD MM4,MM4        // MM4  <-  00 Fa 00 Fa 00 Fg 00 Fg
  1106.         ADD       ECX,EDX        // ECX  <-  00 00 Sa Sa
  1107.         db $0F,$6A,$E4           /// PUNPCKHDQ MM4,MM4        // MM4  <-  00 Fa 00 Fa 00 Fa 00 Fa
  1108.         MUL       EDX            // EAX  <-  00 00 Pa **
  1109.         db $0F,$69,$ED           /// PUNPCKHWD MM5,MM5        // MM5  <-  00 Ba 00 Ba 00 Bg 00 Bg
  1110.         MOV       ESI,$FF        // ESI  <-  00 00 00 00 FF
  1111.         db $0F,$6A,$ED           /// PUNPCKHDQ MM5,MM5        // MM5  <-  00 Ba 00 Ba 00 Ba 00 Ba
  1112.         DIV       ESI
  1113.         SUB       ECX,EAX        // ECX  <-  00 00 00 Ra
  1114.         MOV       EAX,$ffff
  1115.         CDQ
  1116.         db $0F,$D5,$CD           /// PMULLW    MM1,MM5        // MM1  <-  B * Ba
  1117.         db $0F,$71,$D1,$08       /// PSRLW     MM1,8
  1118.         DIV       ECX
  1119.         db $0F,$D5,$C4           /// PMULLW    MM0,MM4        // MM0  <-  F * Fa
  1120.         db $0F,$71,$D0,$08       /// PSRLW     MM0,8
  1121.         db $0F,$D5,$E1           /// PMULLW    MM4,MM1        // MM4  <-  B * Ba * Fa
  1122.         db $0F,$71,$D4,$08       /// PSRLW     MM4,8
  1123.         SHL       ECX,24
  1124.         db $0F,$DD,$C8           /// PADDUSW   MM1,MM0        // MM1  <-  B * Ba + F * Fa
  1125.         db $0F,$D9,$CC           /// PSUBUSW   MM1,MM4        // MM1  <-  B * Ba + F * Fa - B * Ba * Fa
  1126.         db $0F,$6E,$D0           /// MOVD      MM2,EAX        // MM2  <-  Qa = 1 / Ra
  1127.         db $0F,$61,$D2           /// PUNPCKLWD MM2,MM2        // MM2  <-  00 00 00 00 00 Qa 00 Qa
  1128.         db $0F,$61,$D2           /// PUNPCKLWD MM2,MM2        // MM2  <-  00 Qa 00 Qa 00 Qa 00 Qa
  1129.         db $0F,$D5,$CA           /// PMULLW    MM1,MM2
  1130.         db $0F,$71,$D1,$08       /// PSRLW     MM1,8
  1131.         db $0F,$67,$CB           /// PACKUSWB  MM1,MM3        // MM1  <-  00 00 00 00 xx Rr Rg Rb
  1132.         db $0F,$7E,$C8           /// MOVD      EAX,MM1        // EAX  <-  xx Rr Rg Rb
  1133.         AND       EAX,$00FFFFFF  // EAX  <-  00 Rr Rg Rb
  1134.         OR        EAX,ECX        // EAX  <-  Ra Rr Rg Rb
  1135.         POP ESI
  1136.         RET
  1137. @1:     MOV       EAX,EDX
  1138. @2:
  1139. end;
  1140.  
  1141. procedure M_MergeMem(F: TColor32; var B:TColor32);
  1142. begin
  1143.   B := M_MergeReg(F, B);
  1144. end;
  1145.  
  1146. function M_MergeRegEx(F, B, M: TColor32): TColor32;
  1147. begin
  1148.   Result := M_MergeReg(F and $00FFFFFF or ((F shr 24) * M) div 255 shl 24, B);
  1149. end;
  1150.  
  1151. procedure M_MergeMemEx(F: TColor32; var B:TColor32; M: TColor32);
  1152. begin
  1153.   B := M_MergeReg(F and $00FFFFFF or ((F shr 24) * M) div 255 shl 24, B);
  1154. end;
  1155.  
  1156. procedure M_MergeLine(Src, Dst: PColor32; Count: Integer);
  1157. begin
  1158.   while Count > 0 do
  1159.   begin
  1160.     Dst^ := M_MergeReg(Src^, Dst^);
  1161.     Inc(Src);
  1162.     Inc(Dst);
  1163.     Dec(Count);
  1164.   end;
  1165. end;
  1166.  
  1167. procedure M_MergeLineEx(Src, Dst: PColor32; Count: Integer; M: TColor32);
  1168. begin
  1169.   while Count > 0 do
  1170.   begin
  1171.     Dst^ := M_MergeReg(Src^ and $00FFFFFF or ((Src^ shr 24) * M) div 255 shl 24, Dst^);
  1172.     Inc(Src);
  1173.     Inc(Dst);
  1174.     Dec(Count);
  1175.   end;
  1176. end;
  1177.  
  1178. function M_CombMergeReg(X, Y, W: TColor32): TColor32;
  1179. begin
  1180.   Result := M_MergeReg(X and $00FFFFFF or W shl 24, Y);
  1181. end;
  1182.  
  1183. procedure M_CombMergeMem(X: TColor32; var Y: TColor32; W: TColor32);
  1184. begin
  1185.   Y := M_MergeReg(X and $00FFFFFF or W shl 24, Y);
  1186. end;
  1187.  
  1188. { Non-MMX Color algebra versions }
  1189.  
  1190. function _ColorAdd(C1, C2: TColor32): TColor32;
  1191. var
  1192.   r1, g1, b1, a1: Integer;
  1193.   r2, g2, b2, a2: Integer;
  1194. begin
  1195.   a1 := C1 shr 24;
  1196.   r1 := C1 and $00FF0000;
  1197.   g1 := C1 and $0000FF00;
  1198.   b1 := C1 and $000000FF;
  1199.  
  1200.   a2 := C2 shr 24;
  1201.   r2 := C2 and $00FF0000;
  1202.   g2 := C2 and $0000FF00;
  1203.   b2 := C2 and $000000FF;
  1204.  
  1205.   a1 := a1 + a2;
  1206.   r1 := r1 + r2;
  1207.   g1 := g1 + g2;
  1208.   b1 := b1 + b2;
  1209.  
  1210.   if a1 > $FF then a1 := $FF;
  1211.   if r1 > $FF0000 then r1 := $FF0000;
  1212.   if g1 > $FF00 then g1 := $FF00;
  1213.   if b1 > $FF then b1 := $FF;
  1214.  
  1215.   Result := a1 shl 24 + r1 + g1 + b1;
  1216. end;
  1217.  
  1218. function _ColorSub(C1, C2: TColor32): TColor32;
  1219. var
  1220.   r1, g1, b1, a1: Integer;
  1221.   r2, g2, b2, a2: Integer;
  1222. begin
  1223.   a1 := C1 shr 24;
  1224.   r1 := C1 and $00FF0000;
  1225.   g1 := C1 and $0000FF00;
  1226.   b1 := C1 and $000000FF;
  1227.  
  1228.   r1 := r1 shr 16;
  1229.   g1 := g1 shr 8;
  1230.  
  1231.   a2 := C2 shr 24;
  1232.   r2 := C2 and $00FF0000;
  1233.   g2 := C2 and $0000FF00;
  1234.   b2 := C2 and $000000FF;
  1235.  
  1236.   r2 := r2 shr 16;
  1237.   g2 := g2 shr 8;
  1238.  
  1239.   a1 := a1 - a2;
  1240.   r1 := r1 - r2;
  1241.   g1 := g1 - g2;
  1242.   b1 := b1 - b2;
  1243.  
  1244.   if a1 < 0 then a1 := 0;
  1245.   if r1 < 0 then r1 := 0;
  1246.   if g1 < 0 then g1 := 0;
  1247.   if b1 < 0 then b1 := 0;
  1248.  
  1249.   Result := a1 shl 24 + r1 shl 16 + g1 shl 8 + b1;
  1250. end;
  1251.  
  1252. function _ColorDiv(C1, C2: TColor32): TColor32;
  1253. var
  1254.   r1, g1, b1, a1: Integer;
  1255.   r2, g2, b2, a2: Integer;
  1256. begin
  1257.   a1 := C1 shr 24;
  1258.   r1 := (C1 and $00FF0000) shr 16;
  1259.   g1 := (C1 and $0000FF00) shr 8;
  1260.   b1 := C1 and $000000FF;
  1261.  
  1262.   a2 := C2 shr 24;
  1263.   r2 := (C2 and $00FF0000) shr 16;
  1264.   g2 := (C2 and $0000FF00) shr 8;
  1265.   b2 := C2 and $000000FF;
  1266.  
  1267.   if a1 = 0 then a1:=$FF
  1268.   else a1 := (a2 shl 8) div a1;
  1269.   if r1 = 0 then r1:=$FF
  1270.   else r1 := (r2 shl 8) div r1;
  1271.   if g1 = 0 then g1:=$FF
  1272.   else g1 := (g2 shl 8) div g1;
  1273.   if b1 = 0 then b1:=$FF
  1274.   else b1 := (b2 shl 8) div b1;
  1275.  
  1276.   if a1 > $FF then a1 := $FF;
  1277.   if r1 > $FF then r1 := $FF;
  1278.   if g1 > $FF then g1 := $FF;
  1279.   if b1 > $FF then b1 := $FF;
  1280.  
  1281.   Result := a1 shl 24 + r1 shl 16 + g1 shl 8 + b1;
  1282. end;
  1283.  
  1284. function _ColorModulate(C1, C2: TColor32): TColor32;
  1285. var
  1286.   r1, g1, b1, a1: Integer;
  1287.   r2, g2, b2, a2: Integer;
  1288. begin
  1289.   a1 := C1 shr 24;
  1290.   r1 := C1 and $00FF0000;
  1291.   g1 := C1 and $0000FF00;
  1292.   b1 := C1 and $000000FF;
  1293.  
  1294.   r1 := r1 shr 16;
  1295.   g1 := g1 shr 8;
  1296.  
  1297.   a2 := C2 shr 24;
  1298.   r2 := C2 and $00FF0000;
  1299.   g2 := C2 and $0000FF00;
  1300.   b2 := C2 and $000000FF;
  1301.  
  1302.   r2 := r2 shr 16;
  1303.   g2 := g2 shr 8;
  1304.  
  1305.   a1 := a1 * a2 shr 8;
  1306.   r1 := r1 * r2 shr 8;
  1307.   g1 := g1 * g2 shr 8;
  1308.   b1 := b1 * b2 shr 8;
  1309.  
  1310.   if a1 > 255 then a1 := 255;
  1311.   if r1 > 255 then r1 := 255;
  1312.   if g1 > 255 then g1 := 255;
  1313.   if b1 > 255 then b1 := 255;
  1314.  
  1315.   Result := a1 shl 24 + r1 shl 16 + g1 shl 8 + b1;
  1316. end;
  1317.  
  1318. function _ColorMax(C1, C2: TColor32): TColor32;
  1319. var
  1320.   r1, g1, b1, a1: TColor32;
  1321.   r2, g2, b2, a2: TColor32;
  1322. begin
  1323.   a1 := C1 shr 24;
  1324.   r1 := C1 and $00FF0000;
  1325.   g1 := C1 and $0000FF00;
  1326.   b1 := C1 and $000000FF;
  1327.  
  1328.   a2 := C2 shr 24;
  1329.   r2 := C2 and $00FF0000;
  1330.   g2 := C2 and $0000FF00;
  1331.   b2 := C2 and $000000FF;
  1332.  
  1333.   if a2 > a1 then a1 := a2;
  1334.   if r2 > r1 then r1 := r2;
  1335.   if g2 > g1 then g1 := g2;
  1336.   if b2 > b1 then b1 := b2;
  1337.  
  1338.   Result := a1 shl 24 + r1 + g1 + b1;
  1339. end;
  1340.  
  1341. function _ColorMin(C1, C2: TColor32): TColor32;
  1342. var
  1343.   r1, g1, b1, a1: TColor32;
  1344.   r2, g2, b2, a2: TColor32;
  1345. begin
  1346.   a1 := C1 shr 24;
  1347.   r1 := C1 and $00FF0000;
  1348.   g1 := C1 and $0000FF00;
  1349.   b1 := C1 and $000000FF;
  1350.  
  1351.   a2 := C2 shr 24;
  1352.   r2 := C2 and $00FF0000;
  1353.   g2 := C2 and $0000FF00;
  1354.   b2 := C2 and $000000FF;
  1355.  
  1356.   if a2 < a1 then a1 := a2;
  1357.   if r2 < r1 then r1 := r2;
  1358.   if g2 < g1 then g1 := g2;
  1359.   if b2 < b1 then b1 := b2;
  1360.  
  1361.   Result := a1 shl 24 + r1 + g1 + b1;
  1362. end;
  1363.  
  1364. function _ColorDifference(C1, C2: TColor32): TColor32;
  1365. var
  1366.   r1, g1, b1, a1: TColor32;
  1367.   r2, g2, b2, a2: TColor32;
  1368. begin
  1369.   a1 := C1 shr 24;
  1370.   r1 := C1 and $00FF0000;
  1371.   g1 := C1 and $0000FF00;
  1372.   b1 := C1 and $000000FF;
  1373.  
  1374.   r1 := r1 shr 16;
  1375.   g1 := g1 shr 8;
  1376.  
  1377.   a2 := C2 shr 24;
  1378.   r2 := C2 and $00FF0000;
  1379.   g2 := C2 and $0000FF00;
  1380.   b2 := C2 and $000000FF;
  1381.  
  1382.   r2 := r2 shr 16;
  1383.   g2 := g2 shr 8;
  1384.  
  1385.   a1 := abs(a2 - a1);
  1386.   r1 := abs(r2 - r1);
  1387.   g1 := abs(g2 - g1);
  1388.   b1 := abs(b2 - b1);
  1389.  
  1390.   Result := a1 shl 24 + r1 shl 16 + g1 shl 8 + b1;
  1391. end;
  1392.  
  1393. function _ColorExclusion(C1, C2: TColor32): TColor32;
  1394. var
  1395.   r1, g1, b1, a1: TColor32;
  1396.   r2, g2, b2, a2: TColor32;
  1397. begin
  1398.   a1 := C1 shr 24;
  1399.   r1 := C1 and $00FF0000;
  1400.   g1 := C1 and $0000FF00;
  1401.   b1 := C1 and $000000FF;
  1402.  
  1403.   r1 := r1 shr 16;
  1404.   g1 := g1 shr 8;
  1405.  
  1406.   a2 := C2 shr 24;
  1407.   r2 := C2 and $00FF0000;
  1408.   g2 := C2 and $0000FF00;
  1409.   b2 := C2 and $000000FF;
  1410.  
  1411.   r2 := r2 shr 16;
  1412.   g2 := g2 shr 8;
  1413.  
  1414.   a1 := a1 + a2 - (a1 * a2 shr 7);
  1415.   r1 := r1 + r2 - (r1 * r2 shr 7);
  1416.   g1 := g1 + g2 - (g1 * g2 shr 7);
  1417.   b1 := b1 + b2 - (b1 * b2 shr 7);
  1418.  
  1419.   Result := a1 shl 24 + r1 shl 16 + g1 shl 8 + b1;
  1420. end;
  1421.  
  1422. { MMX Color algebra versions }
  1423.  
  1424. function M_ColorAdd(C1, C2: TColor32): TColor32;
  1425. asm
  1426.         db $0F,$6E,$C0           /// MOVD      MM0,EAX
  1427.         db $0F,$6E,$CA           /// MOVD      MM1,EDX
  1428.         db $0F,$DC,$C1           /// PADDUSB   MM0,MM1
  1429.         db $0F,$7E,$C0           /// MOVD      EAX,MM0
  1430. end;
  1431.  
  1432. function M_ColorSub(C1, C2: TColor32): TColor32;
  1433. asm
  1434.         db $0F,$6E,$C0           /// MOVD      MM0,EAX
  1435.         db $0F,$6E,$CA           /// MOVD      MM1,EDX
  1436.         db $0F,$D8,$C1           /// PSUBUSB   MM0,MM1
  1437.         db $0F,$7E,$C0           /// MOVD      EAX,MM0
  1438. end;
  1439.  
  1440. function M_ColorModulate(C1, C2: TColor32): TColor32;
  1441. asm
  1442.         db $0F,$EF,$D2           /// PXOR      MM2,MM2
  1443.         db $0F,$6E,$C0           /// MOVD      MM0,EAX
  1444.         db $0F,$60,$C2           /// PUNPCKLBW MM0,MM2
  1445.         db $0F,$6E,$CA           /// MOVD      MM1,EDX
  1446.         db $0F,$60,$CA           /// PUNPCKLBW MM1,MM2
  1447.         db $0F,$D5,$C1           /// PMULLW    MM0,MM1
  1448.         db $0F,$71,$D0,$08       /// PSRLW     MM0,8
  1449.         db $0F,$67,$C2           /// PACKUSWB  MM0,MM2
  1450.         db $0F,$7E,$C0           /// MOVD      EAX,MM0
  1451. end;
  1452.  
  1453. function M_ColorMax(C1, C2: TColor32): TColor32;
  1454. asm
  1455.         db $0F,$6E,$C0           /// MOVD      MM0,EAX
  1456.         db $0F,$6E,$CA           /// MOVD      MM1,EDX
  1457.         db $0F,$DE,$C1           /// PMAXUB    MM0,MM1
  1458.         db $0F,$7E,$C0           /// MOVD      EAX,MM0
  1459. end;
  1460.  
  1461. function M_ColorMin(C1, C2: TColor32): TColor32;
  1462. asm
  1463.         db $0F,$6E,$C0           /// MOVD      MM0,EAX
  1464.         db $0F,$6E,$CA           /// MOVD      MM1,EDX
  1465.         db $0F,$DA,$C1           /// PMINUB    MM0,MM1
  1466.         db $0F,$7E,$C0           /// MOVD      EAX,MM0
  1467. end;
  1468.  
  1469.  
  1470. function M_ColorDifference(C1, C2: TColor32): TColor32;
  1471. asm
  1472.         db $0F,$6E,$C0           /// MOVD      MM0,EAX
  1473.         db $0F,$6E,$CA           /// MOVD      MM1,EDX
  1474.         db $0F,$6F,$D0           /// MOVQ      MM2,MM0
  1475.         db $0F,$D8,$C1           /// PSUBUSB   MM0,MM1
  1476.         db $0F,$D8,$CA           /// PSUBUSB   MM1,MM2
  1477.         db $0F,$EB,$C1           /// POR       MM0,MM1
  1478.         db $0F,$7E,$C0           /// MOVD      EAX,MM0
  1479. end;
  1480.  
  1481. function M_ColorExclusion(C1, C2: TColor32): TColor32;
  1482. asm
  1483.         db $0F,$EF,$D2           /// PXOR      MM2,MM2
  1484.         db $0F,$6E,$C0           /// MOVD      MM0,EAX
  1485.         db $0F,$60,$C2           /// PUNPCKLBW MM0,MM2
  1486.         db $0F,$6E,$CA           /// MOVD      MM1,EDX
  1487.         db $0F,$60,$CA           /// PUNPCKLBW MM1,MM2
  1488.         db $0F,$6F,$D8           /// MOVQ      MM3,MM0
  1489.         db $0F,$FD,$C1           /// PADDW     MM0,MM1
  1490.         db $0F,$D5,$CB           /// PMULLW    MM1,MM3
  1491.         db $0F,$71,$D1,$07       /// PSRLW     MM1,7
  1492.         db $0F,$D9,$C1           /// PSUBUSW   MM0,MM1
  1493.         db $0F,$67,$C2           /// PACKUSWB  MM0,MM2
  1494.         db $0F,$7E,$C0           /// MOVD      EAX,MM0
  1495. end;
  1496.  
  1497. { Misc stuff }
  1498.  
  1499. function Lighten(C: TColor32; Amount: Integer): TColor32;
  1500. var
  1501.   r, g, b, a: Integer;
  1502. begin
  1503.   a := C shr 24;
  1504.   r := C and $00FF0000;
  1505.   g := C and $0000FF00;
  1506.   b := C and $000000FF;
  1507.  
  1508.   r := r shr 16;
  1509.   g := g shr 8;
  1510.  
  1511.   Inc(r, Amount);
  1512.   Inc(g, Amount);
  1513.   Inc(b, Amount);
  1514.  
  1515.   if r > 255 then r := 255 else if r < 0 then r := 0;
  1516.   if g > 255 then g := 255 else if g < 0 then g := 0;
  1517.   if b > 255 then b := 255 else if b < 0 then b := 0;
  1518.  
  1519.   Result := a shl 24 + r shl 16 + g shl 8 + b;
  1520. end;
  1521.  
  1522. { MMX Detection and linking }
  1523.  
  1524. procedure SetupFunctions;
  1525. begin
  1526.   MMX_ACTIVE := HasMMX;
  1527.   if MMX_ACTIVE then
  1528.   begin
  1529.     // link MMX functions
  1530.     CombineReg := M_CombineReg;
  1531.     CombineMem := M_CombineMem;
  1532.     BlendReg := M_BlendReg;
  1533.     BlendMem := M_BlendMem;
  1534.     BlendRegEx := M_BlendRegEx;
  1535.     BlendMemEx := M_BlendMemEx;
  1536.     BlendLine := M_BlendLine;
  1537.     BlendLineEx := M_BlendLineEx;
  1538.  
  1539.     CombMergeReg := M_CombMergeReg;
  1540.     CombMergeMem := M_CombMergeMem;
  1541.     MergeReg := M_MergeReg;
  1542.     MergeMem := M_MergeMem;
  1543.     MergeRegEx := M_MergeRegEx;
  1544.     MergeMemEx := M_MergeMemEx;
  1545.     MergeLine := M_MergeLine;
  1546.     MergeLineEx := M_MergeLineEx;
  1547.  
  1548.     BLEND_MEM[cmBlend] := M_BlendMem;
  1549.     BLEND_MEM[cmMerge] := M_MergeMem;
  1550.     BLEND_REG[cmBlend] := M_BlendReg;
  1551.     BLEND_REG[cmMerge] := M_MergeReg;
  1552.     COMBINE_MEM[cmBlend] := M_CombineMem;
  1553.     COMBINE_MEM[cmMerge] := M_CombMergeMem;
  1554.     COMBINE_REG[cmBlend] := M_CombineReg;
  1555.     COMBINE_REG[cmMerge] := M_CombMergeReg;
  1556.     BLEND_MEM_EX[cmBlend] := M_BlendMemEx;
  1557.     BLEND_MEM_EX[cmMerge] := M_MergeMemEx;
  1558.     BLEND_REG_EX[cmBlend] := M_BlendRegEx;
  1559.     BLEND_REG_EX[cmMerge] := M_MergeRegEx;
  1560.     BLEND_LINE[cmBlend] := M_BlendLine;
  1561.     BLEND_LINE[cmMerge] := M_MergeLine;
  1562.     BLEND_LINE_EX[cmBlend] := M_BlendLineEx;
  1563.     BLEND_LINE_EX[cmMerge] := M_MergeLineEx;
  1564.  
  1565.     ColorAdd := M_ColorAdd;
  1566.     ColorSub := M_ColorSub;
  1567.     ColorDiv := _ColorDiv;
  1568.     ColorModulate := M_ColorModulate;
  1569.     ColorMax := M_ColorMax;
  1570.     ColorMin := M_ColorMin;
  1571.     ColorDifference := M_ColorDifference;
  1572.     ColorExclusion := M_ColorExclusion;
  1573.   end
  1574.   else
  1575.   begin
  1576.     // link non-MMX functions
  1577.     CombineReg := _CombineReg;
  1578.     CombineMem := _CombineMem;
  1579.     BlendReg := _BlendReg;
  1580.     BlendMem := _BlendMem;
  1581.     BlendRegEx := _BlendRegEx;
  1582.     BlendMemEx := _BlendMemEx;
  1583.     BlendLine := _BlendLine;
  1584.     BlendLineEx := _BlendLineEx;
  1585.  
  1586.     CombMergeReg := _CombMergeReg;
  1587.     CombMergeMem := _CombMergeMem;
  1588.     MergeReg := _MergeReg;
  1589.     MergeMem := _MergeMem;
  1590.     MergeRegEx := _MergeRegEx;
  1591.     MergeMemEx := _MergeMemEx;
  1592.     MergeLine := _MergeLine;
  1593.     MergeLineEx := _MergeLineEx;
  1594.  
  1595.     BLEND_MEM[cmBlend] := _BlendMem;
  1596.     BLEND_MEM[cmMerge] := _MergeMem;
  1597.     BLEND_REG[cmBlend] := _BlendReg;
  1598.     BLEND_REG[cmMerge] := _MergeReg;
  1599.     COMBINE_MEM[cmBlend] := _CombineMem;
  1600.     COMBINE_MEM[cmMerge] := _CombMergeMem;
  1601.     COMBINE_REG[cmBlend] := _CombineReg;
  1602.     COMBINE_REG[cmMerge] := _CombMergeReg;
  1603.     BLEND_MEM_EX[cmBlend] := _BlendMemEx;
  1604.     BLEND_MEM_EX[cmMerge] := _MergeMemEx;
  1605.     BLEND_REG_EX[cmBlend] := _BlendRegEx;
  1606.     BLEND_REG_EX[cmMerge] := _MergeRegEx;
  1607.     BLEND_LINE[cmBlend] := _BlendLine;
  1608.     BLEND_LINE[cmMerge] := _MergeLine;
  1609.     BLEND_LINE_EX[cmBlend] := _BlendLineEx;
  1610.     BLEND_LINE_EX[cmMerge] := _MergeLineEx;
  1611.  
  1612.     ColorAdd := _ColorAdd;
  1613.     ColorSub := _ColorSub;
  1614.     ColorDiv := _ColorDiv;
  1615.     ColorModulate := _ColorModulate;
  1616.     ColorMax := _ColorMax;
  1617.     ColorMin := _ColorMin;
  1618.     ColorDifference := _ColorDifference;
  1619.     ColorExclusion := _ColorExclusion;
  1620.   end;
  1621. end;
  1622.  
  1623. initialization
  1624.   SetupFunctions;
  1625.   if MMX_ACTIVE then GenAlphaTable;
  1626.  
  1627. finalization
  1628.   if MMX_ACTIVE then FreeAlphaTable;
  1629.  
  1630. end.
  1631.  
  1632.  
  1633.  
  1634.