yuvammx.asm
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:70k
源码类别:

Symbian

开发平台:

Visual C++

  1. ;
  2. ; ***** BEGIN LICENSE BLOCK *****
  3. ; Source last modified: $Id: yuvammx.asm,v 1.1.1.1.50.1 2004/07/09 02:00:19 hubbe Exp $
  4. ; Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5. ; The contents of this file, and the files included with this file,
  6. ; are subject to the current version of the RealNetworks Public
  7. ; Source License (the "RPSL") available at
  8. ; http://www.helixcommunity.org/content/rpsl unless you have licensed
  9. ; the file under the current version of the RealNetworks Community
  10. ; Source License (the "RCSL") available at
  11. ; http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  12. ; will apply. You may also obtain the license terms directly from
  13. ; RealNetworks.  You may not use this file except in compliance with
  14. ; the RPSL or, if you have a valid RCSL with RealNetworks applicable
  15. ; to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  16. ; the rights, obligations and limitations governing use of the
  17. ; contents of the file.
  18. ; Alternatively, the contents of this file may be used under the
  19. ; terms of the GNU General Public License Version 2 or later (the
  20. ; "GPL") in which case the provisions of the GPL are applicable
  21. ; instead of those above. If you wish to allow use of your version of
  22. ; this file only under the terms of the GPL, and not to allow others
  23. ; to use your version of this file under the terms of either the RPSL
  24. ; or RCSL, indicate your decision by deleting the provisions above
  25. ; and replace them with the notice and other provisions required by
  26. ; the GPL. If you do not delete the provisions above, a recipient may
  27. ; use your version of this file under the terms of any one of the
  28. ; RPSL, the RCSL or the GPL.
  29. ; This file is part of the Helix DNA Technology. RealNetworks is the
  30. ; developer of the Original Code and owns the copyrights in the
  31. ; portions it created.
  32. ; This file, and the files included with this file, is distributed
  33. ; and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  34. ; KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  35. ; ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  36. ; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  37. ; ENJOYMENT OR NON-INFRINGEMENT.
  38. ; Technology Compatibility Kit Test Suite(s) Location:
  39. ;    http://www.helixcommunity.org/content/tck
  40. ; Contributor(s):
  41. ; ***** END LICENSE BLOCK *****
  42. ;
  43. ;;--------------------------------------------
  44. ;; yuvammx.asm   
  45. ;;
  46. ;;  mmx alpha blender routines
  47. ;;
  48. ;;  NASM 0.98
  49. ;;  target machine = Pentium II
  50. ;----------------------------------------------------------
  51. ; Note:  Output buffer can be the same as one of the input
  52. ;        buffers for I420 and YV12 output only.  Common 
  53. ;        input/output buffer must have same pitch, lines,
  54. ;        width and height.
  55. ;=========================================================
  56. ;; data segment should be qword aligned for best performance
  57. %define ALIGNMENT
  58. %ifdef   COFF
  59.     %define _I420andYUVAtoI420_MMX        _I420andYUVAtoI420_MMX        
  60.     %define _I420andYUVAtoYV12_MMX        _I420andYUVAtoYV12_MMX        
  61.     %define _I420andYUVAtoYUY2_MMX        _I420andYUVAtoYUY2_MMX        
  62.     %define _I420andYUVAtoUYVY_MMX        _I420andYUVAtoUYVY_MMX        
  63.     %define _I420andI420toI420_MMX_sub        _I420andI420toI420_MMX_sub        
  64.     %error data segment possibly not qword aligned
  65. %elifdef WIN32
  66.     %define _I420andYUVAtoI420_MMX        _I420andYUVAtoI420_MMX        
  67.     %define _I420andYUVAtoYV12_MMX        _I420andYUVAtoYV12_MMX        
  68.     %define _I420andYUVAtoYUY2_MMX        _I420andYUVAtoYUY2_MMX        
  69.     %define _I420andYUVAtoUYVY_MMX        _I420andYUVAtoUYVY_MMX        
  70.     %define _I420andI420toI420_MMX_sub        _I420andI420toI420_MMX_sub        
  71.     %define ALIGNMENT align=8
  72. %elifdef ELF
  73.     %define _I420andYUVAtoI420_MMX        I420andYUVAtoI420_MMX        
  74.     %define _I420andYUVAtoYV12_MMX        I420andYUVAtoYV12_MMX        
  75.     %define _I420andYUVAtoYUY2_MMX        I420andYUVAtoYUY2_MMX        
  76.     %define _I420andYUVAtoUYVY_MMX        I420andYUVAtoUYVY_MMX        
  77.     %define _I420andI420toI420_MMX_sub        I420andI420toI420_MMX_sub        
  78.     %error data segment possibly not qword aligned
  79. %elifdef AOUTB
  80.     %define _I420andYUVAtoI420_MMX        I420andYUVAtoI420_MMX        
  81.     %define _I420andYUVAtoYV12_MMX        I420andYUVAtoYV12_MMX        
  82.     %define _I420andYUVAtoYUY2_MMX        I420andYUVAtoYUY2_MMX        
  83.     %define _I420andYUVAtoUYVY_MMX        I420andYUVAtoUYVY_MMX        
  84.     %define _I420andI420toI420_MMX_sub        I420andI420toI420_MMX_sub        
  85.     %error data segment possibly not qword aligned
  86. %else
  87.         %error linking format currently not supported 
  88. %endif
  89. global _I420andYUVAtoI420_MMX
  90. global _I420andYUVAtoYV12_MMX
  91. global _I420andYUVAtoYUY2_MMX 
  92. global _I420andYUVAtoUYVY_MMX 
  93. global _I420andI420toI420_MMX_sub 
  94. %assign CID_I420   0   ;;/* planar YCrCb 4:2:0 format (CCIR)     */
  95. %assign CID_YV12   1   ;;/* planar YVU 4:2:0 (ATI)               */
  96. %assign CID_YUY2   3   ;;/* packed YVU 4:2:2 (ATI,MATROX,etc.)   */
  97. %assign CID_UYVY   4   ;;/* yet another packed 4:2:2 (ATI)       */
  98. %macro  make_labels 1
  99. %define exit       exit%1
  100. %define fail_exit  fail_exit%1
  101. %define a100       a100%1
  102. %define a200       a200%1
  103. %define a300       a300%1
  104. %define a400       a400%1
  105. %define y100       y100%1
  106. %define two_pels   two_pels%1
  107. %define line_done  line_done%1
  108. %define y_by_fours y_by_fours%1
  109. %define y_one_two_three y_one_two_three%1
  110. %endmacro
  111. ;=========================================================
  112. segment .data data ALIGNMENT
  113. align 8
  114. mask3 
  115.     db  -1, 0, -1, 0, -1, 0, -1, 0
  116. mask3b 
  117.     db  0, -1, 0, -1, 0, -1, 0, -1
  118. con1  
  119.     dw 1, 1, 1, 1
  120. ;;_DATA ENDS
  121. ;=========================================================
  122. ;=========================================================
  123. segment .text code 
  124. ;;==========================================================
  125. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  126. ;;
  127. ;; I420andYUVAtoYV12
  128. ;;
  129. ;; This function alpha-blends two I420 buffers into a third
  130. ;; YV12 buffer using the alpha info tacked to the 
  131. ;; end of the second I420 buffer
  132. ;;
  133. ;;  yuva = top
  134. ;;  inverted alpha
  135. ;;  uv size computed as: uvpitch*uvlines = (pitch/2)*(lines/2)
  136. ;;
  137. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  138. _I420andYUVAtoYV12_MMX:
  139. ;;
  140. ;; int I420andYUVAtoYV12_MMX(
  141. ;;          unsigned char* src, int src_pels, int src_lines, int src_pitch
  142. ;;          int src_startx, int src_starty;
  143. ;;          unsigned char* yuva, int yuva_pels, int yuva yuva_lines, int yuva_pitch
  144. ;;          int yuva_startx, int yuva_starty;
  145. ;;          unsigned char* dst, int dst_pels, int dst_lines, int dst_pitch,
  146. ;;          int dst_startx, int dst_starty,
  147. ;;          int width,  int height);
  148. ;;
  149. ;; arguments
  150. %define src            dword [esp+4*(1+npush)]
  151. %define src_pels       dword [esp+4*(2+npush)]
  152. %define src_lines      dword [esp+4*(3+npush)]
  153. %define src_pitch      dword [esp+4*(4+npush)]
  154. %define src_startx     dword [esp+4*(5+npush)]
  155. %define src_starty     dword [esp+4*(6+npush)]
  156. %define yuva           dword [esp+4*(7+npush)]
  157. %define yuva_pels      dword [esp+4*(8+npush)]
  158. %define yuva_lines     dword [esp+4*(9+npush)]
  159. %define yuva_pitch     dword [esp+4*(10+npush)]
  160. %define yuva_startx    dword [esp+4*(11+npush)]
  161. %define yuva_starty    dword [esp+4*(12+npush)]
  162. %define dst            dword [esp+4*(13+npush)]
  163. %define dst_pels       dword [esp+4*(14+npush)]
  164. %define dst_lines      dword [esp+4*(15+npush)]
  165. %define dst_pitch      dword [esp+4*(16+npush)]
  166. %define dst_startx     dword [esp+4*(17+npush)]
  167. %define dst_starty     dword [esp+4*(18+npush)]
  168. %define width          dword [esp+4*(19+npush)]
  169. %define height         dword [esp+4*(20+npush)]
  170.     push    ebp
  171.     push    esi
  172.     push    edi
  173.     push    ecx
  174.     push    ebx
  175. ;; tmp on stack
  176. %assign ntmps 16
  177. %assign npush (5+ntmps)
  178.     sub esp, ntmps*4 
  179. %define yuvay        dword [esp + 0*4]
  180. %define yuvau        dword [esp + 1*4]
  181. %define yuvaoffsetv  dword [esp + 2*4]
  182. %define yuvaa        dword [esp + 3*4]
  183. %define yuvaauv      dword [esp + 4*4]
  184. %define yuvauvpitch  dword [esp + 5*4]
  185. %define sy           dword [esp + 6*4]
  186. %define su           dword [esp + 7*4]
  187. %define soffsetv     dword [esp + 8*4]
  188. %define suvpitch     dword [esp + 9*4]
  189. %define dy           dword [esp + 10*4]
  190. %define du           dword [esp + 11*4]
  191. %define doffsetv     dword [esp + 12*4]
  192. %define duvpitch     dword [esp + 13*4]
  193. %define dtmp0        dword [esp + 14*4]
  194. %define dtmp1        dword [esp + 15*4]
  195. ;; YV12
  196. ;;    [ Y Y ]
  197. ;;      [V]
  198. ;;      [U]
  199.         
  200. ;; YV12 u v reversed from I420
  201. ;; compute reversed order pointers 
  202. ;; then comtinue with I420 routine
  203. ;;-----
  204.     mov eax, dst_lines
  205.     mov ecx, dst_pitch
  206.     mov edx, eax
  207.     imul    eax, ecx        ;; pitch*lines
  208.     shr ecx, 1              ;; pitch/2
  209.     mov duvpitch, ecx
  210.     mov esi, dst
  211.     mov dy, esi
  212.     add esi, eax
  213.     shr edx, 1              ;;  lines/2
  214.     imul    edx, ecx        ;; (pitch/2)*(lines/2)
  215.     add esi, edx
  216.     mov du, esi
  217.     neg edx         ;; negative offset from u
  218.     mov doffsetv, edx
  219. ;;-----
  220.     jmp I420andYUVAtoI420_MMX_entry
  221. ;_I420andYUVAtoYV12_MMX endp
  222. ;=============================================================
  223. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  224. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  225. ;;
  226. ;; I420andYUVAtoI420
  227. ;;
  228. ;; This function alpha-blends two I420 buffers into a third
  229. ;; I420 buffer using the alpha info tacked to the 
  230. ;; end of the second I420 buffer
  231. ;;
  232. ;;  yuva = top
  233. ;;  inverted alpha
  234. ;;  uv size computed as: uvpitch*uvlines = (pitch/2)*(lines/2)
  235. ;;
  236. ;;
  237. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  238. _I420andYUVAtoI420_MMX:
  239. ;;
  240. ;; int I420andYUVAtoI420_MMX(
  241. ;;          unsigned char* src, int src_pels, int src_lines, int src_pitch
  242. ;;          int src_startx, int src_starty;
  243. ;;          unsigned char* yuva, int yuva_pels, int yuva yuva_lines, int yuva_pitch
  244. ;;          int yuva_startx, int yuva_starty;
  245. ;;          unsigned char* dst, int dst_pels, int dst_lines, int dst_pitch,
  246. ;;          int dst_startx, int dst_starty,
  247. ;;          int width,  int height);
  248. ;;
  249. ;%define exit      _I420andYUVAtoI420_MMX_exit
  250. ;%define fail_exit _I420andYUVAtoI420_MMX_fail_exit
  251. ;%define a100      _I420andYUVAtoI420_MMX_a100
  252. ;%define a200      _I420andYUVAtoI420_MMX_a200
  253. ;%define a300      _I420andYUVAtoI420_MMX_a300
  254. ;%define a400      _I420andYUVAtoI420_MMX_a400
  255. make_labels _I420andYUVAtoI420_MMX
  256. ;; arguments
  257. %define src            dword [esp+4*(1+npush)]
  258. %define src_pels       dword [esp+4*(2+npush)]
  259. %define src_lines      dword [esp+4*(3+npush)]
  260. %define src_pitch      dword [esp+4*(4+npush)]
  261. %define src_startx     dword [esp+4*(5+npush)]
  262. %define src_starty     dword [esp+4*(6+npush)]
  263. %define yuva           dword [esp+4*(7+npush)]
  264. %define yuva_pels      dword [esp+4*(8+npush)]
  265. %define yuva_lines     dword [esp+4*(9+npush)]
  266. %define yuva_pitch     dword [esp+4*(10+npush)]
  267. %define yuva_startx    dword [esp+4*(11+npush)]
  268. %define yuva_starty    dword [esp+4*(12+npush)]
  269. %define dst            dword [esp+4*(13+npush)]
  270. %define dst_pels       dword [esp+4*(14+npush)]
  271. %define dst_lines      dword [esp+4*(15+npush)]
  272. %define dst_pitch      dword [esp+4*(16+npush)]
  273. %define dst_startx     dword [esp+4*(17+npush)]
  274. %define dst_starty     dword [esp+4*(18+npush)]
  275. %define width          dword [esp+4*(19+npush)]
  276. %define height         dword [esp+4*(20+npush)]
  277.     push    ebp
  278.     push    esi
  279.     push    edi
  280.     push    ecx
  281.     push    ebx
  282. ;; tmp on stack
  283. %assign ntmps 16
  284. %assign npush (5+ntmps)
  285.     sub esp, ntmps*4 
  286. %define yuvay        dword [esp + 0*4]
  287. %define yuvau        dword [esp + 1*4]
  288. %define yuvaoffsetv  dword [esp + 2*4]
  289. %define yuvaa        dword [esp + 3*4]
  290. %define yuvaauv      dword [esp + 4*4]
  291. %define yuvauvpitch  dword [esp + 5*4]
  292. %define sy           dword [esp + 6*4]
  293. %define su           dword [esp + 7*4]
  294. %define soffsetv     dword [esp + 8*4]
  295. %define suvpitch     dword [esp + 9*4]
  296. %define dy           dword [esp + 10*4]
  297. %define du           dword [esp + 11*4]
  298. %define doffsetv     dword [esp + 12*4]
  299. %define duvpitch     dword [esp + 13*4]
  300. %define dtmp0        dword [esp + 14*4]
  301. %define dtmp1        dword [esp + 15*4]
  302. %define btmp0(x)     byte [esp + 14*4 + x]
  303. %define btmp1(x)     byte [esp + 15*4 + x]
  304. ;;-----
  305.     mov eax, dst_lines
  306.     mov ecx, dst_pitch
  307.     mov edx, eax
  308.     imul    eax, ecx        ;; pitch*lines
  309.     shr ecx, 1              ;; pitch/2
  310.     mov duvpitch, ecx
  311.     mov esi, dst
  312.     mov dy, esi
  313.     add esi, eax
  314.     mov du, esi
  315.     shr edx, 1              ;; lines/2
  316.     imul    edx, ecx        ;; (pitch/2)*(lines/2)
  317.     mov doffsetv, edx
  318. ;;-----
  319. ;;  entry point for I420andYUVAtoYV12_MMX_entry
  320. ;;
  321. I420andYUVAtoI420_MMX_entry:
  322. ;;
  323.     mov eax, src_lines
  324.     mov ecx, src_pitch
  325.     mov edx, eax
  326.     imul    eax, ecx        ;; pitch*lines
  327.     shr ecx, 1              ;; pitch/2
  328.     mov suvpitch, ecx
  329.     mov esi, src
  330.     mov sy, esi
  331.     add esi, eax
  332.     mov su, esi
  333.     shr edx, 1              ;; lines/2
  334.     imul    edx, ecx        ;; (pitch/2)*(lines/2)
  335.     mov soffsetv, edx
  336. ;;-----
  337.     mov eax, yuva_lines
  338.     mov ecx, yuva_pitch
  339.     mov edx, eax
  340.     imul    eax, ecx        ;; pitch*lines
  341.     shr ecx, 1              ;; pitch/2
  342.     mov yuvauvpitch, ecx
  343.     mov esi, yuva
  344.     mov yuvay, esi
  345.     add esi, eax
  346.     mov yuvau, esi
  347.     
  348.     shr edx, 1              ;; lines/2
  349.     imul   edx, ecx         ;; (pitch/2)*(lines/2)
  350.     mov yuvaoffsetv, edx
  351.     lea esi, [esi+edx*2]
  352.     mov yuvaa, esi
  353.     mov yuvaauv, esi        ;; duplicate yuvaa for uv use
  354. ;;------------------
  355. ;;------------------
  356. ;; pointer adjustment to (x,y)
  357.     mov ecx, src_pitch
  358.     mov eax, src_starty
  359.     mov edx, eax
  360.     mov ebx, src_startx
  361.     imul    eax, ecx        ;; y*pitch
  362.     mov esi, sy             ;;
  363.     add esi, eax            ;;  sy + y*pitch
  364.     add esi, ebx            ;;  sy + y*pitch + x
  365.     mov sy, esi
  366.     shr ecx, 1          ;; pitch/2
  367.     shr edx, 1          ;; y/2
  368.     imul    edx, ecx    ;; (y/2)*(pitch/2)
  369.     shr ebx, 1          ;; x/2
  370.     mov esi, su             ;;
  371.     add esi, edx            ;;  su + (y/2)*(pitch/2)
  372.     add esi, ebx            ;;  su + (y/2)*(pitch/2) + x/2
  373.     mov su, esi
  374. ;;
  375. ;; pointer adjustment to (x,y)
  376.     mov ecx, dst_pitch
  377.     mov eax, dst_starty
  378.     mov edx, eax
  379.     mov ebx, dst_startx
  380.     imul    eax, ecx        ;; y*pitch
  381.     mov esi, dy             ;;
  382.     add esi, eax            ;;  dy + y*pitch
  383.     add esi, ebx            ;;  dy + y*pitch + x
  384.     mov dy, esi
  385.     shr ecx, 1          ;; pitch/2
  386.     shr edx, 1          ;; y/2
  387.     imul    edx, ecx    ;; (y/2)*(pitch/2)
  388.     shr ebx, 1          ;; x/2
  389.     mov esi, du             ;;
  390.     add esi, edx            ;;  du + (y/2)*(pitch/2)
  391.     add esi, ebx            ;;  du + (y/2)*(pitch/2) + x/2
  392.     mov du, esi
  393. ;;    
  394. ;; pointer adjustment to (x,y)
  395.     mov ecx, yuva_pitch
  396.     mov eax, yuva_starty
  397.     mov edx, eax
  398.     mov ebx, yuva_startx
  399.     imul    eax, ecx        ;; y*pitch
  400.     add eax, ebx            ;; y*pitch + x
  401.     
  402.     mov esi, yuvay          ;;
  403.     add esi, eax            ;;  yuvay + y*pitch + x
  404.     mov yuvay, esi
  405.     
  406.     mov edi, yuvaa          ;;
  407.     add edi, eax            ;;  yuvaa + y*pitch + x
  408.     mov yuvaa, edi
  409.     mov yuvaauv, edi        ;; dup for uv use
  410.     shr ecx, 1          ;; pitch/2
  411.     shr edx, 1          ;; y/2
  412.     imul    edx, ecx    ;; (y/2)*(pitch/2)
  413.     shr ebx, 1          ;; x/2
  414.     mov esi, yuvau             ;;
  415.     add esi, edx            ;;  yuvau + (y/2)*(pitch/2)
  416.     add esi, ebx            ;;  yuvau + (y/2)*(pitch/2) + x/2
  417.     mov yuvau, esi
  418.     
  419. ;;-----
  420. ;; yuva   P = top
  421. ;; [Y01Y02][Y03Y04]
  422. ;; [Y11Y12][Y13Y04]
  423. ;;   [U1]    [U3]
  424. ;;   [V1]    [V3]
  425. ;; [A01A02][A03A04]
  426. ;; [A11A12][A13A04]
  427. ;; I420 src  Q = bot
  428. ;; [Y01Y02][Y03Y04]
  429. ;; [Y11Y12][Y13Y04]
  430. ;;   [U1]    [U3]
  431. ;;   [V1]    [V3]
  432. ;; I420 dst
  433. ;; [Y01Y02][Y03Y04]
  434. ;; [Y11Y12][Y13Y04]
  435. ;;   [U1]    [U3]
  436. ;;   [V1]    [V3]
  437. ;;-------
  438.     mov esi, yuvay
  439.     mov ecx, yuvaa
  440.     mov edi, sy
  441.     mov ebx, dy
  442.     mov ebp, height      ;; y lines loop counter
  443.     or  ebp, ebp
  444.     jle near exit
  445. y100:
  446.     mov eax, width
  447.     sub eax, 7
  448.     jle  y_by_fours
  449.     movq    mm7, [mask3]
  450.     movq    mm6, [mask3b]
  451. a100:
  452.     ;; yuva 8 y's
  453.     movq    mm0, [esi]          ;; p8 p7 p6 p5 p4 p3 p2 p1
  454.     movq    mm1, mm0            ;; p8 p7 p6 p5 p4 p3 p2 p1
  455.     psrlw   mm0, 8              ;; word p8 p6 p4 p2 
  456.     ;; src I420 8 y's
  457.     movq    mm2, [edi]          ;; q8 q7 q6 q5 q4 q3 q2 q1
  458.     movq    mm3, mm2            ;; q8 q7 q6 q5 q4 q3 q2 q1
  459.     psrlw   mm2, 8              ;; word q8 q6 q4 q2 
  460.     psubw   mm2, mm0            ;; q-p
  461.     ;; yuva 8 a's
  462.     movq    mm4, [ecx]          ;; a8 a7 a6 a5 a4 a3 a2 a1
  463.     movq    mm5, mm4            ;; a8 a7 a6 a5 a4 a3 a2 a1
  464.     psrlw   mm4, 8              ;; word a8 a6 a4 a2
  465.     pmullw  mm2, mm4            ;; word alpha*(q-p)  for y8 y6 y4 y2
  466.     pand    mm2, mm6            ;; word hi-byte alpha*(q-p) for y8 y6 y4 y2
  467.     ;;
  468.     ;;
  469.     movq    mm0, mm1            ;; p8 p7 p6 p5 p4 p3 p2 p1
  470.     pand    mm1, mm7            ;; word p7 p5 p3 p1
  471.     pand    mm3, mm7            ;; word q7 q5 q3 q1
  472.     
  473.     psubw   mm3, mm1            ;; q-p
  474.     pand    mm5, mm7            ;; word a7 a5 a3 a1
  475.     pmullw  mm3, mm5
  476.     psrlw   mm3, 8              ;; alpha*(q-p) >> 8 for y7 y5 y3 y1
  477.     
  478.     por     mm2, mm3            ;; alpha*(q-p) >> 8 for y8 y7 y6 y5 y4 y3 y2 y1
  479.     paddb   mm2, mm0            ;; blended y8 y7 y6 y5 y4 y3 y2 y1
  480.     
  481.     movq    [ebx], mm2
  482.     
  483.     add esi, 8
  484.     add edi, 8
  485.     add ecx, 8
  486.     add ebx, 8
  487.     sub eax, 8
  488.     jg  a100
  489. ;;----------------------
  490. y_by_fours:
  491.     pxor    mm7, mm7        ;; set to zero for unpack
  492.     add eax, 4
  493.     jle  y_one_two_three
  494. a200:
  495.     ;; yuva 4 y's
  496.     movd    mm0, [esi]          ;; byte p4 p3 p2 p1
  497.     punpcklbw mm0, mm7          ;; p4 p3 p2 p1
  498.     ;; src I420 4 y's
  499.     movd    mm2, [edi]          ;; byte  q4 q3 q2 q1
  500.     punpcklbw mm2, mm7          ;; q4 q3 q2 q1
  501.     psubw   mm2, mm0            ;; q-p
  502.     ;; yuva 4 a's
  503.     movd    mm4, [ecx]          ;; byte a4 a3 a2 a1
  504.     punpcklbw mm4, mm7          ;; a4 a3 a2 a1
  505.     pmullw  mm2, mm4
  506.     psrlw   mm2, 8              ;; alpha*(q-p) >> 8 for y4 y3 y2 y1
  507.     paddb   mm2, mm0            ;; blended word y4 y3 y2 y1
  508.     
  509.     packuswb    mm2, mm7        ;; blended byte y4 y3 y2 y1 
  510.     ;;
  511.     movd    [ebx], mm2
  512.     add esi, 4
  513.     add edi, 4
  514.     add ecx, 4
  515.     add ebx, 4
  516.     sub eax, 4      ;; not needed if doing by_eights
  517.     jg  a200        ;; not needed if doing by_eights
  518. ;;
  519. ;;
  520. ;;----------------------
  521. ;; do one, two, or three odd bytes
  522. y_one_two_three:
  523.     add eax, 3      ;; number bytes to do
  524.     jle  line_done
  525.     mov edx, 4
  526.     sub edx, eax    ;; 4-eax = numbers bytes offset
  527.     ;;
  528.     movd mm6, edx   ;; number bytes to shift
  529.     psllq   mm6, 3              ;; number bits to shift 
  530.     ;;
  531.     ;; pointer adjustment, negative offset
  532.     neg edx     
  533. ;;
  534. ;;
  535.     ;; yuva 1-3 y's
  536.     movd    mm0, [esi]          ;; byte xx p3 p2 p1
  537.     punpcklbw mm0, mm7          ;; xx p3 p2 p1
  538.     ;; src I420 1-3 y's
  539.     movd    mm2, [edi]          ;; byte  xx q3 q2 q1
  540.     punpcklbw mm2, mm7          ;; xx p3 p2 p1
  541.     psubw   mm2, mm0            ;; q-p
  542.     ;; yuva 1-3 a's
  543.     movd    mm4, [ecx+edx]      ;; byte a3 a2 a1 xx
  544.     psrlq   mm4, mm6            ;; byte xx a3 a2 a1 
  545.     punpcklbw mm4, mm7          ;; xx a3 a2 a1
  546.     pmullw  mm2, mm4
  547.     psrlw   mm2, 8              ;; alpha*(q-p) >> 8 for xx y3 y2 y1
  548.     paddb   mm2, mm0            ;; blended word xx y3 y2 y1
  549.     
  550.     packuswb    mm2, mm7        ;; blended byte xx y3 y2 y1 
  551.     ;;
  552.     movd    dtmp0, mm2
  553.     ;; store result, byte by byte
  554.     ;; eax = bytes to do
  555. a300:
  556.     mov dl, btmp0(eax-1)
  557.     mov [ebx+eax-1], dl
  558.     dec eax
  559.     jg  a300
  560. ;;------
  561. line_done:
  562.     mov eax, yuva_pitch
  563.     mov esi, yuvay
  564.     add esi, eax
  565.     mov yuvay, esi
  566.     mov ecx, yuvaa
  567.     add ecx, eax
  568.     mov yuvaa, ecx
  569.         
  570.     mov eax, src_pitch
  571.     mov edi, sy
  572.     add edi, eax
  573.     mov sy, edi
  574.     
  575.     mov eax, dst_pitch
  576.     mov ebx, dy
  577.     add ebx, eax
  578.     mov dy, ebx
  579.     dec ebp
  580.     jg  near y100        ;; line loop
  581. ;;-----------------------------------------------
  582. ;;-----------------------------------------------
  583. ;; do u and v
  584. ;;
  585.     mov esi, yuvau
  586.     mov ecx, yuvaauv
  587.     add ecx, yuva_pitch    ;; use a's from second line
  588.     mov yuvaauv, ecx       ;; save for uv line loop
  589.     mov edi, su
  590.     mov ebx, du
  591.     mov ebp, height      ;; uv lines loop counter
  592.     shr ebp, 1
  593.     jle near exit
  594. uv100:
  595.     mov eax, width
  596.     shr eax, 1      ;; u v width = width/2
  597.     sub eax, 3
  598.     jle  near uv_one_two_three
  599. b200:
  600.     ;; yuva 4 u's
  601.     movd    mm0, [esi]          ;; byte pu4 pu3 pu2 pu1
  602.     punpcklbw mm0, mm7          ;; pu4 pu3 pu2 pu1
  603.     ;; src I420 4 u's
  604.     movd    mm2, [edi]          ;; byte  qu4 qu3 qu2 qu1
  605.     punpcklbw mm2, mm7          ;; qu4 qu3 qu2 qu1
  606.     psubw   mm2, mm0            ;; q-p
  607.     ;; yuva 8 a's
  608.     ;; We need to average the alpha values by 2's. In the C version
  609.     ;; In the C version we do the average by the whole 2x2 block.
  610.     ;;movq    mm4, [ecx]          ;; byte a8 a7 a6 a5 a4 a3 a2 a1
  611.     ;;psrlw   mm4, 8              ;; word a8 a6 a4 a2
  612.     movq    mm4, [ecx]
  613.     movq    mm7, mm4          ;; mm7=mm4= a8 a7 a6 a5 a4 a3 a2 a1
  614.     psllw   mm7, 8            ;; mm7    = a7 00 a5 00 a3 00 a1 00
  615.     psrlw   mm4, 8            ;; mm4    = 00 a8 00 a6 00 a4 00 a2 
  616.     psrlw   mm7, 8            ;; mm7    = 00 a7 00 a5 00 a3 00 a1
  617.     paddw   mm4, mm7          ;; mm4    = (a8+a7) (a6+a5) (a4+a3) (a2+a1)
  618.     pxor    mm7, mm7          ;; mm7    = 0...0
  619.     psrlw   mm4, 1            ;; mm4    = (a8+a7)/2 (a6+a5)/2 (a4+a3)/2 (a2+a1)/2
  620.     pmullw  mm2, mm4
  621.     psrlw   mm2, 8             ;; alpha*(q-p) >> 8 for u4 u3 u2 u1
  622.     paddb   mm2, mm0           ;; byte add -> blended word u4 u3 u2 u1
  623.     
  624.     packuswb    mm2, mm7       ;; blended byte u4 u3 u2 u1 
  625.     mov edx, yuvaoffsetv
  626.     ;; yuva 4 v's
  627.     movd    mm0, [esi+edx]      ;; byte pv4 pv3 pv2 pv1
  628.     punpcklbw mm0, mm7          ;; pv4 pv3 pv2 pv1
  629.     mov edx, soffsetv
  630.     ;; src I420 4 v's
  631.     movd    mm3, [edi+edx]      ;; byte  qv4 qv3 qv2 qv1
  632.     punpcklbw mm3, mm7          ;; qv4 qv3 qv2 qv1
  633.     psubw   mm3, mm0            ;; q-p
  634.     pmullw  mm3, mm4
  635.     psrlw   mm3, 8              ;; alpha*(q-p) >> 8 for v4 v3 v2 v1
  636.     paddb   mm3, mm0            ;; blended word v4 v3 v2 v1
  637.     
  638.     packuswb    mm3, mm7        ;; blended byte v4 v3 v2 v1 
  639.     movd    [ebx], mm2          ;; postpone store for src buf = dest buf
  640.     mov edx, doffsetv
  641.     movd    [ebx+edx], mm3
  642.     add esi, 4
  643.     add edi, 4
  644.     add ecx, 8
  645.     add ebx, 4
  646.     sub eax, 4
  647.     jg  near b200
  648. ;;----------------------
  649. ;; do one, two, or three odd bytes
  650. ;; reads are unaligned
  651. uv_one_two_three:
  652.     add eax, 3
  653.     jle  near uv_line_done
  654.     mov edx, 4
  655.     sub edx, eax    ;; 4-eax = numbers bytes offset
  656.     ;;
  657.     movd mm6, edx   ;; number bytes to shift
  658.     psllq   mm6, 3              ;; number bits to shift 
  659.     ;;
  660.     ;; pointer adjustment, negative offset
  661.     neg edx
  662.     add esi, edx
  663.     add edi, edx
  664.     lea ecx, [ecx+edx*2]
  665. ;;
  666.     ;; yuva 1-3 u's
  667.     movd    mm0, [esi]      ;; byte pu3 pu2 pu1 xxx
  668.     punpcklbw mm0, mm7          ;; pu3 pu2 pu1 xxx
  669.     ;; src I420 1-3 u's
  670.     movd    mm2, [edi]      ;; byte qu3 qu2 qu1 xxx
  671.     punpcklbw mm2, mm7          ;; qu3 qu2 qu1 xxx
  672.     psubw   mm2, mm0            ;; q-p
  673.     ;; yuva 1-3 a's
  674.     movq    mm4, [ecx]    ;; byte  a6 a5 a4 a3 a2 a1 xx xx
  675.     psrlw   mm4, 8              ;; word  a6 a4 a2 xx 
  676.     pmullw  mm2, mm4
  677.     psrlw   mm2, 8             ;; alpha*(q-p) >> 8 for u3 u2 u1 xx
  678.     paddb   mm2, mm0           ;; blended word u3 u2 u1 xx
  679.     
  680.     packuswb    mm2, mm7       ;; blended byte u3 u2 u1 xx
  681.     movd    dtmp0, mm2
  682.     mov edx, yuvaoffsetv
  683.     ;; yuva 2 v's
  684.     movd    mm0, [esi+edx]      ;; byte  pv3 pv2 pv1 xxx
  685.     punpcklbw mm0, mm7          ;; pv3 pv2 pv1 xxx
  686.     mov edx, soffsetv
  687.     ;; src I420 1-3 u's
  688.     movd    mm2, [edi+edx]      ;; byte  qv3 qv2 qv1 xx
  689.     punpcklbw mm2, mm7          ;; qv3 qv2 qv1 xx
  690.     psubw   mm2, mm0            ;; q-p
  691.     pmullw  mm2, mm4
  692.     psrlw   mm2, 8              ;; alpha*(q-p) >> 8 for v3 v2 v1 xx
  693.     paddb   mm2, mm0            ;; blended word v3 v2 v1 xx
  694.     
  695.     packuswb    mm2, mm7        ;; blended byte v3 v2 v1 xx
  696.     movd    dtmp1, mm2
  697.     
  698.     mov edx, doffsetv
  699.     ;; store result, byte by byte
  700.     ;; eax = bytes to do
  701.     neg eax
  702. b300:
  703.     mov cl, btmp0(4+eax)   ;; u     ;; ecx trashed
  704.     mov ch, btmp1(4+eax)   ;; v
  705.     mov [ebx], cl                   
  706.     mov [ebx+edx], ch
  707.     inc ebx
  708.     inc eax
  709.     jl  b300
  710. ;;------
  711. uv_line_done:
  712.     mov eax, yuvauvpitch
  713.     mov esi, yuvau
  714.     add esi, eax
  715.     mov yuvau, esi
  716.     mov eax, yuva_pitch
  717.     mov ecx, yuvaauv
  718.     lea ecx, [ecx + eax*2]  ;; down two lines
  719.     mov yuvaauv, ecx        ;; save for uv line loop
  720.     mov eax, suvpitch
  721.     mov edi, su
  722.     add edi, eax
  723.     mov su, edi
  724.     
  725.     mov eax, duvpitch
  726.     mov ebx, du
  727.     add ebx, eax
  728.     mov du, ebx
  729.     dec ebp
  730.     jg  near uv100           ;; uv line loop
  731. ;;------
  732. exit:
  733.     xor eax, eax    ;; return success
  734. exit2:
  735.     add esp, ntmps*4
  736.     pop ebx
  737.     pop ecx
  738.     pop edi
  739.     pop esi
  740.     pop ebp
  741.     emms
  742.     ret
  743. fail_exit:
  744.     mov eax, -1     ;; signal fail
  745.     jmp exit2
  746. ;_I420andYUVAtoI420_MMX endp
  747. ;====================================
  748. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  749. ;;
  750. ;; I420andYUVAtoYUY2
  751. ;;
  752. ;; This function alpha-blends two I420 buffers into a third
  753. ;; YUY2 buffer using the alpha info tacked to the 
  754. ;; end of the second I420 buffer
  755. ;;
  756. ;;  yuva = top
  757. ;;  inverted alpha
  758. ;;  uv size computed as: uvpitch*uvlines = (pitch/2)*(lines/2)
  759. ;;
  760. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  761. _I420andYUVAtoYUY2_MMX:
  762. ;;
  763. ;; int I420andYUVAtoYUY2_MMX(
  764. ;;    unsigned char* src,  int src_pels,    int src_lines,  int src_pitch,
  765. ;;                         int src_startx,  int src_starty,
  766. ;;    unsigned char* yuva, int yuva_pels,   int yuva_lines, int yuva_pitch,
  767. ;;                         int yuva_startx, int yuva_starty,
  768. ;;    unsigned char* dst,  int dst_pels,    int dst_lines,  int dst_pitch,
  769. ;;                         int dst_startx,  int dst_starty,
  770. ;;    int width,  int height);
  771. ;;
  772. make_labels  _I420andYUVAtoYUY2_MMX
  773. ;;
  774. ;; arguments
  775. %define src            dword [esp+4*(1+npush)]
  776. %define src_pels       dword [esp+4*(2+npush)]
  777. %define src_lines      dword [esp+4*(3+npush)]
  778. %define src_pitch      dword [esp+4*(4+npush)]
  779. %define src_startx     dword [esp+4*(5+npush)]
  780. %define src_starty     dword [esp+4*(6+npush)]
  781. %define yuva           dword [esp+4*(7+npush)]
  782. %define yuva_pels      dword [esp+4*(8+npush)]
  783. %define yuva_lines     dword [esp+4*(9+npush)]
  784. %define yuva_pitch     dword [esp+4*(10+npush)]
  785. %define yuva_startx    dword [esp+4*(11+npush)]
  786. %define yuva_starty    dword [esp+4*(12+npush)]
  787. %define dst            dword [esp+4*(13+npush)]
  788. %define dst_pels       dword [esp+4*(14+npush)]
  789. %define dst_lines      dword [esp+4*(15+npush)]
  790. %define dst_pitch      dword [esp+4*(16+npush)]
  791. %define dst_startx     dword [esp+4*(17+npush)]
  792. %define dst_starty     dword [esp+4*(18+npush)]
  793. %define width          dword [esp+4*(19+npush)]
  794. %define height         dword [esp+4*(20+npush)]
  795.     push    ebp
  796.     push    esi
  797.     push    edi
  798.     push    ecx
  799.     push    ebx
  800. ;; tmp on stack
  801. %assign ntmps 15
  802. %assign npush (5+ntmps)
  803.     sub esp, ntmps*4 
  804. %define yuvay        dword [esp + 0*4]
  805. %define yuvau        dword [esp + 1*4]
  806. %define yuvaoffsetv  dword [esp + 2*4]
  807. %define yuvaoffseta  dword [esp + 3*4]
  808. %define negyuvapitch dword [esp + 4*4]
  809. %define yuvayinc     dword [esp + 5*4]
  810. %define yuvauvinc    dword [esp + 6*4]
  811. %define sy           dword [esp + 7*4]
  812. %define su           dword [esp + 8*4]
  813. %define soffsetv     dword [esp + 9*4]
  814. %define syinc        dword [esp + 10*4]
  815. %define suvinc       dword [esp + 11*4]
  816. %define dy           dword [esp + 12*4]
  817. %define width0       dword [esp + 13*4]
  818. %define dyinc        dword [esp + 14*4]
  819. ;; 
  820.     mov edi, width
  821.     and edi, -4    ;; width truncated to multiple of 4 (width & ~ 3)
  822.     mov ebp, edi   ;; truncated for address increment computation only
  823.     shr ebp, 1              ;; (width & ~ 3)/2
  824. ;;-----
  825.     mov eax, dst
  826.     mov dy, eax
  827.     mov ecx, dst_pitch
  828.     add ecx, ecx
  829.     sub ecx, edi
  830.     sub ecx, edi
  831.     mov dyinc, ecx          ;; inc = 2*pitch - 2*(width & ~ 3)
  832. ;;-----
  833.     mov eax, src_lines
  834.     mov ecx, src_pitch
  835.     mov edx, eax
  836.     imul    eax, ecx        ;; pitch*lines
  837.     mov esi, src
  838.     mov sy, esi
  839.     add esi, eax
  840.     mov su, esi
  841.     shr edx, 1              ;; lines/2
  842.     shr ecx, 1              ;; pitch/2
  843.     imul    edx, ecx        ;; (pitch/2)*(lines*2)
  844.     mov soffsetv, edx
  845.     
  846.     sub ecx, ebp            ;; pitch/2 - width/2
  847.     mov suvinc, ecx
  848.     mov ecx, src_pitch
  849.     add ecx, ecx
  850.     sub ecx, edi
  851.     mov syinc, ecx          ;; inc = 2*pitch - (width & ~ 3)
  852. ;;-----
  853.     mov eax, yuva_lines
  854.     mov ecx, yuva_pitch
  855.     mov edx, ecx
  856.     neg edx
  857.     mov negyuvapitch, edx
  858.     mov edx, eax            ;; lines
  859.     imul    eax, ecx        ;; pitch*lines
  860.     mov esi, yuva
  861.     mov yuvay, esi
  862.     add esi, eax
  863.     mov yuvau, esi
  864.     shr ecx, 1              ;; pitch/2
  865.     shr edx, 1              ;; lines/2
  866.     imul    edx, ecx        ;; (lines/2)*(pitch/2)
  867.     mov yuvaoffsetv, edx
  868.     lea edx, [eax+edx*2]
  869.     mov yuvaoffseta, edx
  870.     sub ecx, ebp
  871.     mov yuvauvinc, ecx
  872.     mov ecx, yuva_pitch
  873.     add ecx, ecx
  874.     sub ecx, edi
  875.     mov yuvayinc, ecx          ;; inc = 2*pitch - (width & ~ 3)
  876. ;;-----
  877. ;;------------------
  878. ;; pointer adjustment to (x,y)
  879.     mov ecx, src_pitch
  880.     mov eax, src_starty
  881.     mov edx, eax
  882.     mov ebx, src_startx
  883.     imul    eax, ecx        ;; y*pitch
  884.     mov esi, sy             ;;
  885.     add esi, eax            ;;  sy + y*pitch
  886.     add esi, ebx            ;;  sy + y*pitch + x
  887.     mov sy, esi
  888.     shr ecx, 1          ;; pitch/2
  889.     shr edx, 1          ;; y/2
  890.     imul    edx, ecx    ;; (y/2)*(pitch/2)
  891.     shr ebx, 1          ;; x/2
  892.     mov esi, su             ;;
  893.     add esi, edx            ;;  su + (y/2)*(pitch/2)
  894.     add esi, ebx            ;;  su + (y/2)*(pitch/2) + x/2
  895.     mov su, esi
  896. ;;
  897. ;; pointer adjustment to (x,y)
  898.     mov ecx, yuva_pitch
  899.     mov eax, yuva_starty
  900.     mov edx, eax
  901.     mov ebx, yuva_startx
  902.     imul    eax, ecx        ;; y*pitch
  903.     add eax, ebx            ;; y*pitch + x
  904.     
  905.     mov esi, yuvay          ;;
  906.     add esi, eax            ;;  yuvay + y*pitch + x
  907.     mov yuvay, esi
  908.     
  909.     shr ecx, 1          ;; pitch/2
  910.     shr edx, 1          ;; y/2
  911.     imul    edx, ecx    ;; (y/2)*(pitch/2)
  912.     shr ebx, 1          ;; x/2
  913.     mov esi, yuvau          ;;
  914.     add esi, edx            ;;  yuvau + (y/2)*(pitch/2)
  915.     add esi, ebx            ;;  yuvau + (y/2)*(pitch/2) + x/2
  916.     mov yuvau, esi
  917. ;; pointer adjustment to (x,y)
  918.     mov ecx, dst_pitch
  919.     mov eax, dst_starty
  920.     mov ebx, dst_startx
  921.     imul    eax, ecx        ;; y*pitch
  922.     add ebx, ebx            ;; 2*x
  923.     mov esi, dy             ;;
  924.     add esi, eax            ;;  dy + y*pitch
  925.     add esi, ebx            ;;  dy + y*pitch + 2*x
  926.     mov dy, esi
  927. ;;-----
  928. ;; yuva   P = top
  929. ;; [Y01Y02][Y03Y04]
  930. ;; [Y11Y12][Y13Y04]
  931. ;;   [U1]    [U3]
  932. ;;   [V1]    [V3]
  933. ;; [A01A02][A03A04]
  934. ;; [A11Y12][A13A04]
  935. ;; I420 src  Q = bot
  936. ;; [Y01Y02][Y03Y04]
  937. ;; [Y11Y12][Y13Y04]
  938. ;;   [U1]    [U3]
  939. ;;   [V1]    [V3]
  940. ;; YUY2 dst 
  941. ;; [YUYV][YUYV]         ;; byte order [Y0][U][Y1][V]
  942. ;; [YUYV][YUYV]
  943. ;;-------
  944.     pxor    mm7, mm7
  945.     movq    mm6, [con1]
  946.     ;; set up line loop
  947.     mov eax, height
  948.     dec eax
  949.     mov height, eax
  950.     jle near exit
  951.     mov esi, yuvay
  952.     mov ebx, yuvau
  953.     mov edi, sy
  954.     mov edx, su
  955. y100:               ;; line loop
  956.     mov eax, width
  957.     sub eax, 3
  958.     mov width0, eax
  959.     jle near two_pels
  960. a100:
  961.     ;; do four pels per iteration
  962.     ;;
  963.     mov ecx, yuvaoffseta    
  964.     mov eax, src_pitch
  965.     ;; ------- first line --------
  966.     ;; yuva 4 y's
  967.     movd    mm0, [esi]          ;; p4 p3 p2 p1
  968.     punpcklbw   mm0, mm7        ;; word p4 p3 p2 p1 
  969.     ;; src I420 4 y's
  970.     movq    mm2, [edi]          ;; q4 q3 q2 q1
  971.     punpcklbw mm2, mm7          ;; word q4 q3 q2 q1 
  972.     psubw   mm2, mm0            ;; q-p
  973.     ;; yuva 4 a's
  974.     movd    mm4, [esi+ecx]      ;; a4 a3 a2 a1
  975.     punpcklbw mm4, mm7          ;; word a4 a3 a2 a1
  976.     pmullw  mm2, mm4            ;; word alpha*(q-p)  for y4 y3 y2 y1
  977.     psrlw   mm2, 8              ;; byte alpha*(q-p)  for 0 y4 0 y3 0 y2 0 y1
  978.     paddb   mm2, mm0            ;; blended for 0 y4 0 y3 0 y2 0 y1
  979.     pmaddwd mm4, mm6           ;; line 1 dword a4+a3 a2+a1
  980.     ;; 
  981.     ;;   mm2 = line 1 blended for 0 y4 0 y3 0 y2 0 y1
  982.     ;;   mm4 = line 1 dword ave(a4,a3) ave(a2,a1)
  983.     ;;
  984.     ;; ------ second line ---------
  985.     mov ebp, negyuvapitch
  986.     sub esi, ebp            ;; point to line 2
  987.     ;;add esi, yuva_pitch
  988.     ;;;;add edi, src_pitch
  989.     ;; yuva 4 y's
  990.     movd    mm1, [esi]          ;; p4 p3 p2 p1
  991.     punpcklbw   mm1, mm7        ;; word p4 p3 p2 p1 
  992.     ;; src I420 4 y's
  993.     movd    mm3, [edi+eax]          ;; q4 q3 q2 q1
  994.     punpcklbw mm3, mm7          ;; word q4 q3 q2 q1 
  995.     psubw   mm3, mm1            ;; q-p
  996.     ;; yuva 4 a's
  997.     movd    mm5, [esi+ecx]      ;; a4 a3 a2 a1
  998.     punpcklbw mm5, mm7          ;; word a4 a3 a2 a1
  999.     lea esi, [esi+ebp+4]        ;; back to line 1 and inc
  1000.     add edi, 4                  ;; inc sy
  1001.     pmullw  mm3, mm5            ;; word alpha*(q-p)  for y4 y3 y2 y1
  1002.     psrlw   mm3, 8              ;; byte alpha*(q-p)  for 0 y4 0 y3 0 y2 0 y1
  1003.     paddb   mm3, mm1            ;; blended for 0 y4 0 y3 0 y2 0 y1
  1004.     pmaddwd mm5, mm6           ;; line 2 dword a4+a3 a2+a1
  1005.     ;; 
  1006.     packssdw    mm4, mm5        ;; for u v sum a22 a21 a12 a11
  1007.     psrlw       mm4, 1          ;; for u v ave  a22 a21 a12 a11
  1008.     ;;
  1009.     ;;   mm2 = line 1 blended for 0 y4 0 y3 0 y2 0 y1
  1010.     ;;   mm3 = line 2 blended for 0 y4 0 y3 0 y2 0 y1 0
  1011.     ;;   mm4 = ave for line 2 line 1 =  a22 a21 a12 a11
  1012.     ;;
  1013.     ;; ----- U V --------
  1014.     ;;mov ebx, yuvau
  1015.     ;;mov edx, su
  1016.     mov ecx, yuvaoffsetv
  1017.     mov eax, soffsetv
  1018.     ;; --U--
  1019.     movd    mm0, [ebx]          ;; x x pu2 pu1
  1020.     punpcklwd    mm0, mm0       ;; byte pu2 pu1 pu2 pu1
  1021.     punpcklbw    mm0, mm7       ;; word pu2 pu1 pu2 pu1
  1022.     movd    mm1, [edx]          ;; x x qu2 qu1
  1023.     punpcklwd    mm1, mm1       ;; byte qu2 qu1 qu2 qu1
  1024.     punpcklbw    mm1, mm7       ;; word qu2 qu1 qu2 qu1
  1025.     psubw   mm1, mm0            ;; qu - pu
  1026.     pmullw  mm1, mm4            ;; alpha*(qu-pu)
  1027.     psrlw   mm1, 8
  1028.     paddb   mm1, mm0            ;; line 2 line 1 blended u2 u1 u2 u1 
  1029.     ;; --V--
  1030.     movd    mm0, [ebx+ecx]          ;; x x pv2 pv1
  1031.     punpcklwd    mm0, mm0       ;; byte pv2 pv1 pv2 pv1
  1032.     punpcklbw    mm0, mm7       ;; word pv2 pv1 pv2 pv1
  1033.     ;;movd    mm5, [edx+eax]            ;; x x qv2 qv1
  1034.     movzx   eax, word [edx+eax]     ;; prevent possible access vio
  1035.     movd    mm5, eax            ;;  0 0 qv2 qv1
  1036.     punpcklwd    mm5, mm5       ;; byte qv2 qv1 qv2 qv1
  1037.     punpcklbw    mm5, mm7       ;; word qv2 qv1 qv2 qv1
  1038.     psubw   mm5, mm0            ;; qv - pv
  1039.     add ebx, 2                  ;; inc yuvau address
  1040.     add edx, 2                  ;; inc su address
  1041.     pmullw  mm5, mm4            ;; alpha*(qv-pv)
  1042.     psrlw   mm5, 8
  1043.     paddb   mm5, mm0            ;; line 2 line 1 blended v2 v1 v2 v1 
  1044.     ;;   mm2 = line 1 blended for 0 y4 0 y3 0 y2 0 y1
  1045.     ;;   mm3 = line 2 blended for 0 y4 0 y3 0 y2 0 y1
  1046.     ;;   mm1 = line 2 line 1 blended 0 u2 0 u1 0 u2 0 u1 
  1047.     ;;   mm5 = line 2 line 1 blended 0 v2 0 v1 0 v2 0 v1 
  1048.     ;;
  1049.     mov ecx, dy
  1050.     mov eax, dst_pitch
  1051.     packuswb    mm2, mm3        ;; blended y24 y23 y22 y21 y14 y13 y12 y11 
  1052.     psllq   mm5, 8              ;;  v2 0 v1 0 v2 0 v1 0
  1053.     por mm1, mm5                ;;  v22 u22 v21 u21 v12 u12 v11 u11
  1054.     
  1055.     movq    mm3, mm2
  1056.     punpcklbw   mm3, mm1        ;;  v12 y14 u12 y13 v11 y12 u11 y11
  1057.     movq    [ecx], mm3          ;; line 1 result
  1058.     punpckhbw   mm2, mm1        ;;  v22 y24 u22 y23 v21 y22 u21 y21
  1059.     movq    [ecx+eax], mm2      ;; line 2 result
  1060.     add ecx, 8                  ;; inc dy address
  1061.     mov dy, ecx
  1062.     mov eax, width0             ;; pel loop
  1063.     sub eax, 4
  1064.     mov width0, eax
  1065.     jg  near a100
  1066. ;;------------------------------
  1067. two_pels:
  1068.     ;; do two pels if any
  1069.     ;; remaining pels = eax+3
  1070.     ;; compute 2 pels if remaining pels = 2 or 3, 1 not computed
  1071.     add eax, 2
  1072.     jle near line_done
  1073.     ;;
  1074.     ;;
  1075.     mov ecx, yuvaoffseta    
  1076.     mov eax, src_pitch
  1077.     ;; ------- first line --------
  1078.     ;; yuva 2 y's
  1079.     movd    mm0, [esi]          ;; p2 p1
  1080.     punpcklbw   mm0, mm7        ;; word p2 p1 
  1081.     ;; src I420 2 y's
  1082.     movq    mm2, [edi]          ;; q2 q1
  1083.     punpcklbw mm2, mm7          ;; word q2 q1 
  1084.     psubw   mm2, mm0            ;; q-p
  1085.     ;; yuva 2 a's
  1086.     movd    mm4, [esi+ecx]      ;; a2 a1
  1087.     punpcklbw mm4, mm7          ;; word a2 a1
  1088.     pmullw  mm2, mm4            ;; word alpha*(q-p)  for y2 y1
  1089.     psrlw   mm2, 8              ;; byte alpha*(q-p)  for 0 y2 0 y1
  1090.     paddb   mm2, mm0            ;; blended for 0 y2 0 y1
  1091.     pmaddwd mm4, mm6           ;; line 1 dword a2+a1
  1092.     ;; 
  1093.     ;;   mm2 = line 1 blended for 0 y2 0 y1
  1094.     ;;   mm4 = line 1 ave(a2,a1)
  1095.     ;;
  1096.     ;; ------ second line ---------
  1097.     mov ebp, negyuvapitch
  1098.     sub esi, ebp            ;; point to line 2
  1099.     ;; yuva 2 y's
  1100.     movd    mm1, [esi]          ;; p2 p1
  1101.     punpcklbw   mm1, mm7        ;; word p2 p1 
  1102.     ;; src I420 2 y's
  1103.     movd    mm3, [edi+eax]          ;; q2 q1
  1104.     punpcklbw mm3, mm7          ;; word q2 q1 
  1105.     psubw   mm3, mm1            ;; q-p
  1106.     ;; yuva 2 a's
  1107.     ;;movd    mm5, [esi+ecx]      ;; a2 a1
  1108.     movzx   eax, word [esi+ecx]     ;; prevent possible access vio
  1109.     movd    mm5, eax            ;; a2 a1
  1110.     punpcklbw mm5, mm7          ;; word a2 a1
  1111.     lea esi, [esi+ebp]        ;; back to line 1,  no inc
  1112.     ;;add edi, 4                  ;; inc sy
  1113.     pmullw  mm3, mm5            ;; word alpha*(q-p)  for y2 y1
  1114.     psrlw   mm3, 8              ;; byte alpha*(q-p)  for 0 y2 0 y1
  1115.     paddb   mm3, mm1            ;; blended for 0 y2 0 y1
  1116.     pmaddwd mm5, mm6           ;; line 2 dword a2+a1
  1117.     ;; 
  1118.     packssdw    mm4, mm5        ;; for uv sum xx a21 xx a11
  1119.     psrlw   mm4, 1              ;; for uv ave xx a21 xx a11
  1120.     ;;
  1121.     ;;   mm2 = line 1 blended for 0 y2 0 y1
  1122.     ;;   mm3 = line 2 blended for 0 y2 0 y1
  1123.     ;;   mm4 = ave =  a21 a11
  1124.     ;;
  1125.     ;; ----- U V --------
  1126.     mov ecx, yuvaoffsetv
  1127.     mov eax, soffsetv
  1128.     ;; --U--
  1129.     ;;movd    mm0, [ebx]          ;; x x x pu1
  1130.     ;;punpcklwd    mm0, mm0       ;; byte x pu1 x pu1
  1131.     ;;punpcklbw    mm0, mm7       ;; word x pu1 x pu1
  1132.     movzx ebp, byte [ebx]
  1133.     movd    mm0, ebp                ;; 0 0 0 pu1
  1134.     punpckldq   mm0, mm0            ;; word 0 pu1 0 pu1
  1135.     ;;movd    mm1, [edx]          ;; x x qu2 qu1
  1136.     ;;punpcklwd    mm1, mm1       ;; byte qu2 qu1 qu2 qu1
  1137.     ;;punpcklbw    mm1, mm7       ;; word qu2 qu1 qu2 qu1
  1138.     movzx   ebp, byte [edx]
  1139.     movd    mm1, ebp                ;; 0 0 0 qu1          
  1140.     punpckldq   mm1, mm1            ;; word 0 qu1 0 qu1   
  1141.     
  1142.     psubw   mm1, mm0            ;; qu - pu
  1143.     pmullw  mm1, mm4            ;; alpha*(qu-pu)
  1144.     psrlw   mm1, 8
  1145.     paddb   mm1, mm0            ;; line 2 line 1 blended u2 u1 u2 u1 
  1146.     ;; --V--
  1147.     ;;movd    mm0, [ebx+ecx]          ;; x x pv2 pv1
  1148.     movzx   ebp, byte [ebx+ecx]     ;; prevent possible access vio
  1149.     movd    mm0, ebp            ;; 0 0 0 pv1
  1150.     punpckldq    mm0, mm0       ;; word 0 pv1 0 pv1
  1151.     ;;movd    mm5, [edx+eax]            ;; qv1
  1152.     movzx   eax, byte [edx+eax]     ;; prevent possible access vio
  1153.     movd    mm5, eax            ;;  0 0 0 qv1
  1154.     punpckldq    mm5, mm5       ;; word 0 qv1 0 qv1
  1155.     psubw   mm5, mm0            ;; qv - pv
  1156.     ;;add ebx, 2                  ;; inc yuvau address
  1157.     ;;add edx, 2                  ;; inc su address
  1158.     pmullw  mm5, mm4            ;; alpha*(qv-pv)
  1159.     psrlw   mm5, 8
  1160.     paddb   mm5, mm0            ;; line 2 line 1 blended v2 v1 v2 v1 
  1161.     ;;   mm2 = line 1 blended for 0 y2 0 y1
  1162.     ;;   mm3 = line 2 blended for 0 y2 0 y1
  1163.     ;;   mm1 = line 2 line 1 blended 0 u2 0 u1 
  1164.     ;;   mm5 = line 2 line 1 blended 0 v2 0 v1 
  1165.     ;;
  1166.     mov ecx, dy
  1167.     mov eax, dst_pitch
  1168.     packuswb    mm2, mm3        ;; x x y22 y21 x x y12 y11
  1169.     psllq   mm5, 8              ;;  v2 0 v1 0 v2 0 v1 0
  1170.     por mm1, mm5                ;;  v22 u22 v21 u21 v12 u12 v11 u11
  1171.     
  1172.     movq    mm3, mm2
  1173.     punpcklbw   mm2, mm1        ;;  v11 y12 u11 y11
  1174.     movd    [ecx], mm2          ;; line 1 result
  1175.     punpckhbw   mm3, mm1        ;;  v21 y22 u21 y21 
  1176.     movd    [ecx+eax], mm3      ;; line 2 result
  1177. ;;-----------
  1178. ;; line loop
  1179. line_done:
  1180. ;;
  1181. ;;
  1182.     mov eax, yuvayinc      ;; move down two lines
  1183.     add esi, eax
  1184.     
  1185.     mov eax, yuvauvinc
  1186.     add ebx, eax
  1187.     
  1188.     mov eax, syinc
  1189.     add edi, eax
  1190.     mov eax, suvinc
  1191.     add edx, eax
  1192.     
  1193.     mov eax, dyinc
  1194.     mov ecx, dy
  1195.     add ecx, eax
  1196.     mov dy,  ecx
  1197.     mov eax, height
  1198.     sub eax, 2
  1199.     mov height, eax
  1200.     jg  near y100
  1201. ;;-----------
  1202. exit:
  1203.     xor eax, eax    ;; return success
  1204.     add esp, ntmps*4
  1205.     pop ebx
  1206.     pop ecx
  1207.     pop edi
  1208.     pop esi
  1209.     pop ebp
  1210.     emms
  1211.     ret
  1212. ;_I420andYUVAtoYUY2_MMX endp
  1213. ;====================================
  1214. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1215. ;;
  1216. ;; I420andYUVAtoUYVY
  1217. ;;
  1218. ;; This function alpha-blends two I420 buffers into a third
  1219. ;; UYVY buffer using the alpha info tacked to the 
  1220. ;; end of the second I420 buffer
  1221. ;;
  1222. ;;  yuva = top
  1223. ;;  inverted alpha
  1224. ;;  uv size computed as: uvpitch*uvlines = (pitch/2)*(lines/2)
  1225. ;;
  1226. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1227. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1228. _I420andYUVAtoUYVY_MMX:
  1229. ;;
  1230. ;; int I420andYUVAtoUYVY_MMX(
  1231. ;;    unsigned char* src,  int src_pels,    int src_lines,  int src_pitch,
  1232. ;;                         int src_startx,  int src_starty,
  1233. ;;    unsigned char* yuva, int yuva_pels,   int yuva_lines, int yuva_pitch,
  1234. ;;                         int yuva_startx, int yuva_starty,
  1235. ;;    unsigned char* dst,  int dst_pels,    int dst_lines,  int dst_pitch,
  1236. ;;                         int dst_startx,  int dst_starty,
  1237. ;;    int width,  int height);
  1238. ;;
  1239. ;;
  1240. make_labels _I420andYUVAtoUYVY_MMX
  1241. ;; arguments
  1242. %define src            dword [esp+4*(1+npush)]
  1243. %define src_pels       dword [esp+4*(2+npush)]
  1244. %define src_lines      dword [esp+4*(3+npush)]
  1245. %define src_pitch      dword [esp+4*(4+npush)]
  1246. %define src_startx     dword [esp+4*(5+npush)]
  1247. %define src_starty     dword [esp+4*(6+npush)]
  1248. %define yuva           dword [esp+4*(7+npush)]
  1249. %define yuva_pels      dword [esp+4*(8+npush)]
  1250. %define yuva_lines     dword [esp+4*(9+npush)]
  1251. %define yuva_pitch     dword [esp+4*(10+npush)]
  1252. %define yuva_startx    dword [esp+4*(11+npush)]
  1253. %define yuva_starty    dword [esp+4*(12+npush)]
  1254. %define dst            dword [esp+4*(13+npush)]
  1255. %define dst_pels       dword [esp+4*(14+npush)]
  1256. %define dst_lines      dword [esp+4*(15+npush)]
  1257. %define dst_pitch      dword [esp+4*(16+npush)]
  1258. %define dst_startx     dword [esp+4*(17+npush)]
  1259. %define dst_starty     dword [esp+4*(18+npush)]
  1260. %define width          dword [esp+4*(19+npush)]
  1261. %define height         dword [esp+4*(20+npush)]
  1262.     push    ebp
  1263.     push    esi
  1264.     push    edi
  1265.     push    ecx
  1266.     push    ebx
  1267. ;; tmp on stack
  1268. %assign ntmps 15
  1269. %assign npush (5+ntmps)
  1270.     sub esp, ntmps*4 
  1271. %define yuvay        dword [esp + 0*4]
  1272. %define yuvau        dword [esp + 1*4]
  1273. %define yuvaoffsetv  dword [esp + 2*4]
  1274. %define yuvaoffseta  dword [esp + 3*4]
  1275. %define negyuvapitch dword [esp + 4*4]
  1276. %define yuvayinc     dword [esp + 5*4]
  1277. %define yuvauvinc    dword [esp + 6*4]
  1278. %define sy           dword [esp + 7*4]
  1279. %define su           dword [esp + 8*4]
  1280. %define soffsetv     dword [esp + 9*4]
  1281. %define syinc        dword [esp + 10*4]
  1282. %define suvinc       dword [esp + 11*4]
  1283. %define dy           dword [esp + 12*4]
  1284. %define width0       dword [esp + 13*4]
  1285. %define dyinc        dword [esp + 14*4]
  1286.     mov edi, width
  1287.     and edi, -4         ;; pels truncated to multiple of 4 (width & ~ 3)
  1288.     mov ebp, edi
  1289.     shr ebp, 1              ;; (width & ~ 3)/2
  1290. ;;-----
  1291.     mov eax, dst
  1292.     mov dy, eax
  1293.     mov ecx, dst_pitch
  1294.     add ecx, ecx
  1295.     sub ecx, edi
  1296.     sub ecx, edi
  1297.     mov dyinc, ecx          ;; inc = 2*pitch - 2*(width & ~ 3)
  1298. ;;-----
  1299.     mov eax, src_lines
  1300.     mov ecx, src_pitch
  1301.     mov edx, eax
  1302.     imul    eax, ecx        ;; pitch*lines
  1303.     mov esi, src
  1304.     mov sy, esi
  1305.     add esi, eax
  1306.     mov su, esi
  1307.     shr edx, 1              ;; lines/2
  1308.     shr ecx, 1              ;; pitch/2
  1309.     imul    edx, ecx        ;; (pitch/2)*(lines*2)
  1310.     mov soffsetv, edx
  1311.     
  1312.     sub ecx, ebp            ;; pitch/2 - width/2
  1313.     mov suvinc, ecx
  1314.     mov ecx, src_pitch
  1315.     add ecx, ecx
  1316.     sub ecx, edi
  1317.     mov syinc, ecx          ;; inc = 2*pitch - (width & ~ 3)
  1318. ;;-----
  1319.     mov eax, yuva_lines
  1320.     mov ecx, yuva_pitch
  1321.     mov edx, ecx
  1322.     neg edx
  1323.     mov negyuvapitch, edx
  1324.     mov edx, eax            ;; lines
  1325.     imul    eax, ecx        ;; pitch*lines
  1326.     mov esi, yuva
  1327.     mov yuvay, esi
  1328.     add esi, eax
  1329.     mov yuvau, esi
  1330.     shr ecx, 1              ;; pitch/2
  1331.     shr edx, 1              ;; lines/2
  1332.     imul    edx, ecx        ;; (lines/2)*(pitch/2)
  1333.     mov yuvaoffsetv, edx
  1334.     lea edx, [eax+edx*2]
  1335.     mov yuvaoffseta, edx
  1336.     sub ecx, ebp
  1337.     mov yuvauvinc, ecx
  1338.     mov ecx, yuva_pitch
  1339.     add ecx, ecx
  1340.     sub ecx, edi
  1341.     mov yuvayinc, ecx          ;; inc = 2*pitch - (width & ~ 3)
  1342. ;;-----
  1343. ;;------------------
  1344. ;; pointer adjustment to (x,y)
  1345.     mov ecx, src_pitch
  1346.     mov eax, src_starty
  1347.     mov edx, eax
  1348.     mov ebx, src_startx
  1349.     imul    eax, ecx        ;; y*pitch
  1350.     mov esi, sy             ;;
  1351.     add esi, eax            ;;  sy + y*pitch
  1352.     add esi, ebx            ;;  sy + y*pitch + x
  1353.     mov sy, esi
  1354.     shr ecx, 1          ;; pitch/2
  1355.     shr edx, 1          ;; y/2
  1356.     imul    edx, ecx    ;; (y/2)*(pitch/2)
  1357.     shr ebx, 1          ;; x/2
  1358.     mov esi, su             ;;
  1359.     add esi, edx            ;;  su + (y/2)*(pitch/2)
  1360.     add esi, ebx            ;;  su + (y/2)*(pitch/2) + x/2
  1361.     mov su, esi
  1362. ;;
  1363. ;; pointer adjustment to (x,y)
  1364.     mov ecx, yuva_pitch
  1365.     mov eax, yuva_starty
  1366.     mov edx, eax
  1367.     mov ebx, yuva_startx
  1368.     imul    eax, ecx        ;; y*pitch
  1369.     add eax, ebx            ;; y*pitch + x
  1370.     
  1371.     mov esi, yuvay          ;;
  1372.     add esi, eax            ;;  yuvay + y*pitch + x
  1373.     mov yuvay, esi
  1374.     
  1375.     shr ecx, 1          ;; pitch/2
  1376.     shr edx, 1          ;; y/2
  1377.     imul    edx, ecx    ;; (y/2)*(pitch/2)
  1378.     shr ebx, 1          ;; x/2
  1379.     mov esi, yuvau          ;;
  1380.     add esi, edx            ;;  yuvau + (y/2)*(pitch/2)
  1381.     add esi, ebx            ;;  yuvau + (y/2)*(pitch/2) + x/2
  1382.     mov yuvau, esi
  1383. ;; pointer adjustment to (x,y)
  1384.     mov ecx, dst_pitch
  1385.     mov eax, dst_starty
  1386.     mov ebx, dst_startx
  1387.     imul    eax, ecx        ;; y*pitch
  1388.     add ebx, ebx            ;; 2*x
  1389.     mov esi, dy             ;;
  1390.     add esi, eax            ;;  dy + y*pitch
  1391.     add esi, ebx            ;;  dy + y*pitch + 2*x
  1392.     mov dy, esi
  1393. ;;-----
  1394. ;; yuva   P = top
  1395. ;; [Y01Y02][Y03Y04]
  1396. ;; [Y11Y12][Y13Y04]
  1397. ;;   [U1]    [U3]
  1398. ;;   [V1]    [V3]
  1399. ;; [A01A02][A03A04]
  1400. ;; [A11Y12][A13A04]
  1401. ;; I420 src  Q = bot
  1402. ;; [Y01Y02][Y03Y04]
  1403. ;; [Y11Y12][Y13Y04]
  1404. ;;   [U1]    [U3]
  1405. ;;   [V1]    [V3]
  1406. ;; UYVY dst 
  1407. ;; [UYVY][UYVY]         ;; byte order [U][Y0][V][Y1]
  1408. ;; [UYVY][UYVY]
  1409. ;;-------
  1410.     pxor    mm7, mm7
  1411.     movq    mm6, [con1]
  1412.     ;; set up line loop
  1413.     mov eax, height  
  1414.     dec eax
  1415.     mov height, eax
  1416.     jle near exit
  1417.     mov esi, yuvay
  1418.     mov ebx, yuvau
  1419.     mov edi, sy
  1420.     mov edx, su
  1421. y100:               ;; line loop
  1422.     mov eax, width
  1423.     sub eax, 3
  1424.     mov width0, eax
  1425.     jle near two_pels
  1426. a100:
  1427.     ;; do four pels per iteration
  1428.     ;;
  1429.     mov ecx, yuvaoffseta    
  1430.     mov eax, src_pitch
  1431.     ;; ------- first line --------
  1432.     ;; yuva 4 y's
  1433.     movd    mm0, [esi]          ;; p4 p3 p2 p1
  1434.     punpcklbw   mm0, mm7        ;; word p4 p3 p2 p1 
  1435.     ;; src I420 4 y's
  1436.     movq    mm2, [edi]          ;; q4 q3 q2 q1
  1437.     punpcklbw mm2, mm7          ;; word q4 q3 q2 q1 
  1438.     psubw   mm2, mm0            ;; q-p
  1439.     ;; yuva 4 a's
  1440.     movd    mm4, [esi+ecx]      ;; a4 a3 a2 a1
  1441.     punpcklbw mm4, mm7          ;; word a4 a3 a2 a1
  1442.     pmullw  mm2, mm4            ;; word alpha*(q-p)  for y4 y3 y2 y1
  1443.     psrlw   mm2, 8              ;; byte alpha*(q-p)  for 0 y4 0 y3 0 y2 0 y1
  1444.     paddb   mm2, mm0            ;; blended for 0 y4 0 y3 0 y2 0 y1
  1445.     pmaddwd mm4, mm6           ;; line 1 dword a4+a3 a2+a1
  1446.     ;; 
  1447.     ;;   mm2 = line 1 blended for 0 y4 0 y3 0 y2 0 y1
  1448.     ;;   mm4 = line 1 dword ave(a4,a3) ave(a2,a1)
  1449.     ;;
  1450.     ;; ------ second line ---------
  1451.     mov ebp, negyuvapitch
  1452.     sub esi, ebp            ;; point to line 2
  1453.     ;;add esi, yuva_pitch
  1454.     ;;;;add edi, src_pitch
  1455.     ;; yuva 4 y's
  1456.     movd    mm1, [esi]          ;; p4 p3 p2 p1
  1457.     punpcklbw   mm1, mm7        ;; word p4 p3 p2 p1 
  1458.     ;; src I420 4 y's
  1459.     movd    mm3, [edi+eax]          ;; q4 q3 q2 q1
  1460.     punpcklbw mm3, mm7          ;; word q4 q3 q2 q1 
  1461.     psubw   mm3, mm1            ;; q-p
  1462.     ;; yuva 4 a's
  1463.     movd    mm5, [esi+ecx]      ;; a4 a3 a2 a1
  1464.     punpcklbw mm5, mm7          ;; word a4 a3 a2 a1
  1465.     lea esi, [esi+ebp+4]        ;; back to line 1 and inc
  1466.     add edi, 4                  ;; inc sy
  1467.     pmullw  mm3, mm5            ;; word alpha*(q-p)  for y4 y3 y2 y1
  1468.     psrlw   mm3, 8              ;; byte alpha*(q-p)  for 0 y4 0 y3 0 y2 0 y1
  1469.     paddb   mm3, mm1            ;; blended for 0 y4 0 y3 0 y2 0 y1
  1470.     pmaddwd mm5, mm6           ;; line 2 dword a4+a3 a2+a1
  1471.     ;; 
  1472.     packssdw    mm4, mm5        ;; for u v sum a22 a21 a12 a11
  1473.     psrlw       mm4, 1          ;; for u v ave  a22 a21 a12 a11
  1474.     ;;
  1475.     ;;   mm2 = line 1 blended for 0 y4 0 y3 0 y2 0 y1
  1476.     ;;   mm3 = line 2 blended for 0 y4 0 y3 0 y2 0 y1 0
  1477.     ;;   mm4 = ave for line 2 line 1 =  a22 a21 a12 a11
  1478.     ;;
  1479.     ;; ----- U V --------
  1480.     ;;mov ebx, yuvau
  1481.     ;;mov edx, su
  1482.     mov ecx, yuvaoffsetv
  1483.     mov eax, soffsetv
  1484.     ;; --U--
  1485.     movd    mm0, [ebx]          ;; x x pu2 pu1
  1486.     punpcklwd    mm0, mm0       ;; byte pu2 pu1 pu2 pu1
  1487.     punpcklbw    mm0, mm7       ;; word pu2 pu1 pu2 pu1
  1488.     movd    mm1, [edx]          ;; x x qu2 qu1
  1489.     punpcklwd    mm1, mm1       ;; byte qu2 qu1 qu2 qu1
  1490.     punpcklbw    mm1, mm7       ;; word qu2 qu1 qu2 qu1
  1491.     psubw   mm1, mm0            ;; qu - pu
  1492.     pmullw  mm1, mm4            ;; alpha*(qu-pu)
  1493.     psrlw   mm1, 8
  1494.     paddb   mm1, mm0            ;; line 2 line 1 blended u2 u1 u2 u1 
  1495.     ;; --V--
  1496.     movd    mm0, [ebx+ecx]          ;; x x pv2 pv1
  1497.     punpcklwd    mm0, mm0       ;; byte pv2 pv1 pv2 pv1
  1498.     punpcklbw    mm0, mm7       ;; word pv2 pv1 pv2 pv1
  1499.     ;;movd    mm5, [edx+eax]            ;; x x qv2 qv1
  1500.     movzx   eax, word [edx+eax]     ;; prevent possible access vio
  1501.     movd    mm5, eax            ;;  0 0 qv2 qv1
  1502.     punpcklwd    mm5, mm5       ;; byte qv2 qv1 qv2 qv1
  1503.     punpcklbw    mm5, mm7       ;; word qv2 qv1 qv2 qv1
  1504.     psubw   mm5, mm0            ;; qv - pv
  1505.     add ebx, 2                  ;; inc yuvau address
  1506.     add edx, 2                  ;; inc su address
  1507.     pmullw  mm5, mm4            ;; alpha*(qv-pv)
  1508.     psrlw   mm5, 8
  1509.     paddb   mm5, mm0            ;; line 2 line 1 blended v2 v1 v2 v1 
  1510.     ;;   mm2 = line 1 blended for 0 y4 0 y3 0 y2 0 y1
  1511.     ;;   mm3 = line 2 blended for 0 y4 0 y3 0 y2 0 y1
  1512.     ;;   mm1 = line 2 line 1 blended 0 u2 0 u1 0 u2 0 u1 
  1513.     ;;   mm5 = line 2 line 1 blended 0 v2 0 v1 0 v2 0 v1 
  1514.     ;;
  1515.     mov ecx, dy
  1516.     mov eax, dst_pitch
  1517.     packuswb    mm2, mm3        ;; blended y24 y23 y22 y21 y14 y13 y12 y11 
  1518.     psllq   mm5, 8              ;;  v2 0 v1 0 v2 0 v1 0
  1519.     por mm1, mm5                ;;  v22 u22 v21 u21 v12 u12 v11 u11
  1520.     
  1521.     movq    mm3, mm1
  1522.     punpcklbw   mm1, mm2        ;;  y14 v12 y13 u12 y12 v11 y11 u11 
  1523.     movq    [ecx], mm1          ;; line 1 result
  1524.     punpckhbw   mm3, mm2        ;;  y24 v22 y23 u22 y22 v21 y21 u21
  1525.     movq    [ecx+eax], mm3      ;; line 2 result
  1526.     add ecx, 8                  ;; inc dy address
  1527.     mov dy, ecx
  1528.     mov eax, width0             ;; pel loop
  1529.     sub eax, 4
  1530.     mov width0, eax
  1531.     jg  near a100
  1532. ;;------------------------------
  1533. two_pels:
  1534.     ;; do two pels if any
  1535.     ;; remaining pels = eax+3
  1536.     ;; compute 2 pels if remaining pels = 2 or 3, 1 not computed
  1537.     add eax, 2
  1538.     jle near line_done
  1539.     ;;
  1540.     ;;
  1541.     mov ecx, yuvaoffseta    
  1542.     mov eax, src_pitch
  1543.     ;; ------- first line --------
  1544.     ;; yuva 2 y's
  1545.     movd    mm0, [esi]          ;; p2 p1
  1546.     punpcklbw   mm0, mm7        ;; word p2 p1 
  1547.     ;; src I420 2 y's
  1548.     movq    mm2, [edi]          ;; q2 q1
  1549.     punpcklbw mm2, mm7          ;; word q2 q1 
  1550.     psubw   mm2, mm0            ;; q-p
  1551.     ;; yuva 2 a's
  1552.     movd    mm4, [esi+ecx]      ;; a2 a1
  1553.     punpcklbw mm4, mm7          ;; word a2 a1
  1554.     pmullw  mm2, mm4            ;; word alpha*(q-p)  for y2 y1
  1555.     psrlw   mm2, 8              ;; byte alpha*(q-p)  for 0 y2 0 y1
  1556.     paddb   mm2, mm0            ;; blended for 0 y2 0 y1
  1557.     pmaddwd mm4, mm6           ;; line 1 dword a2+a1
  1558.     ;; 
  1559.     ;;   mm2 = line 1 blended for 0 y2 0 y1
  1560.     ;;   mm4 = line 1 ave(a2,a1)
  1561.     ;;
  1562.     ;; ------ second line ---------
  1563.     mov ebp, negyuvapitch
  1564.     sub esi, ebp            ;; point to line 2
  1565.     ;; yuva 2 y's
  1566.     movd    mm1, [esi]          ;; p2 p1
  1567.     punpcklbw   mm1, mm7        ;; word p2 p1 
  1568.     ;; src I420 2 y's
  1569.     movd    mm3, [edi+eax]          ;; q2 q1
  1570.     punpcklbw mm3, mm7          ;; word q2 q1 
  1571.     psubw   mm3, mm1            ;; q-p
  1572.     ;; yuva 2 a's
  1573.     ;;movd    mm5, [esi+ecx]      ;; a2 a1
  1574.     movzx   eax, word [esi+ecx]     ;; prevent possible access vio
  1575.     movd    mm5, eax            ;; a2 a1
  1576.     punpcklbw mm5, mm7          ;; word a2 a1
  1577.     lea esi, [esi+ebp]        ;; back to line 1,  no inc
  1578.     ;;add edi, 4                  ;; inc sy
  1579.     pmullw  mm3, mm5            ;; word alpha*(q-p)  for y2 y1
  1580.     psrlw   mm3, 8              ;; byte alpha*(q-p)  for 0 y2 0 y1
  1581.     paddb   mm3, mm1            ;; blended for 0 y2 0 y1
  1582.     pmaddwd mm5, mm6           ;; line 2 dword a2+a1
  1583.     ;; 
  1584.     packssdw    mm4, mm5        ;; for uv sum xx a21 xx a11
  1585.     psrlw   mm4, 1              ;; for uv ave xx a21 xx a11
  1586.     ;;
  1587.     ;;   mm2 = line 1 blended for 0 y2 0 y1
  1588.     ;;   mm3 = line 2 blended for 0 y2 0 y1
  1589.     ;;   mm4 = ave =  a21 a11
  1590.     ;;
  1591.     ;; ----- U V --------
  1592.     mov ecx, yuvaoffsetv
  1593.     mov eax, soffsetv
  1594.     ;; --U--
  1595.     ;;movd    mm0, [ebx]          ;; x x x pu1
  1596.     ;;punpcklwd    mm0, mm0       ;; byte x pu1 x pu1
  1597.     ;;punpcklbw    mm0, mm7       ;; word x pu1 x pu1
  1598.     movzx ebp, byte [ebx]
  1599.     movd    mm0, ebp                ;; 0 0 0 pu1
  1600.     punpckldq   mm0, mm0            ;; word 0 pu1 0 pu1
  1601.     ;;movd    mm1, [edx]          ;; x x qu2 qu1
  1602.     ;;punpcklwd    mm1, mm1       ;; byte qu2 qu1 qu2 qu1
  1603.     ;;punpcklbw    mm1, mm7       ;; word qu2 qu1 qu2 qu1
  1604.     movzx   ebp, byte [edx]
  1605.     movd    mm1, ebp                ;; 0 0 0 qu1          
  1606.     punpckldq   mm1, mm1            ;; word 0 qu1 0 qu1   
  1607.     
  1608.     psubw   mm1, mm0            ;; qu - pu
  1609.     pmullw  mm1, mm4            ;; alpha*(qu-pu)
  1610.     psrlw   mm1, 8
  1611.     paddb   mm1, mm0            ;; line 2 line 1 blended u2 u1 u2 u1 
  1612.     ;; --V--
  1613.     ;;movd    mm0, [ebx+ecx]          ;; x x pv2 pv1
  1614.     movzx   ebp, byte [ebx+ecx]     ;; prevent possible access vio
  1615.     movd    mm0, ebp            ;; 0 0 0 pv1
  1616.     punpckldq    mm0, mm0       ;; word 0 pv1 0 pv1
  1617.     ;;movd    mm5, [edx+eax]            ;; qv1
  1618.     movzx   eax, byte [edx+eax]     ;; prevent possible access vio
  1619.     movd    mm5, eax            ;;  0 0 0 qv1
  1620.     punpckldq    mm5, mm5       ;; word 0 qv1 0 qv1
  1621.     psubw   mm5, mm0            ;; qv - pv
  1622.     ;;add ebx, 2                  ;; inc yuvau address
  1623.     ;;add edx, 2                  ;; inc su address
  1624.     pmullw  mm5, mm4            ;; alpha*(qv-pv)
  1625.     psrlw   mm5, 8
  1626.     paddb   mm5, mm0            ;; line 2 line 1 blended v2 v1 v2 v1 
  1627.     ;;   mm2 = line 1 blended for 0 y2 0 y1
  1628.     ;;   mm3 = line 2 blended for 0 y2 0 y1
  1629.     ;;   mm1 = line 2 line 1 blended 0 u2 0 u1 
  1630.     ;;   mm5 = line 2 line 1 blended 0 v2 0 v1 
  1631.     ;;
  1632.     mov ecx, dy
  1633.     mov eax, dst_pitch
  1634.     packuswb    mm2, mm3        ;; x x y22 y21 x x y12 y11
  1635.     psllq   mm5, 8              ;;  v2 0 v1 0 v2 0 v1 0
  1636.     por mm1, mm5                ;;  v22 u22 v21 u21 v12 u12 v11 u11
  1637.     
  1638.     movq    mm3, mm1
  1639.     punpcklbw   mm1, mm2        ;;  v11 y12 u11 y11
  1640.     movd    [ecx], mm1          ;; line 1 result
  1641.     punpckhbw   mm3, mm2        ;;  v21 y22 u21 y21 
  1642.     movd    [ecx+eax], mm3      ;; line 2 result
  1643. ;;-----------
  1644. ;; line loop
  1645. line_done:
  1646.     mov eax, yuvayinc      ;; move down two lines
  1647.     add esi, eax
  1648.     
  1649.     mov eax, yuvauvinc
  1650.     add ebx, eax
  1651.     
  1652.     mov eax, syinc
  1653.     add edi, eax
  1654.     mov eax, suvinc
  1655.     add edx, eax
  1656.     
  1657.     mov eax, dyinc
  1658.     mov ecx, dy
  1659.     add ecx, eax
  1660.     mov dy,  ecx
  1661.     mov eax, height
  1662.     sub eax, 2
  1663.     mov height, eax
  1664.     jg  near y100
  1665. ;;-----------
  1666. exit:
  1667.     xor eax, eax    ;; return success
  1668.     add esp, ntmps*4
  1669.     pop ebx
  1670.     pop ecx
  1671.     pop edi
  1672.     pop esi
  1673.     pop ebp
  1674.     emms
  1675.     ret
  1676. ;_I420andYUVAtoUYVY_MMX endp
  1677. ;====================================
  1678. ;====================================
  1679. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1680. ;;int I420andI420toI420 (
  1681. ;;  unsigned char *src1_ptr, int src1_pels, int src1_lines, int src1_pitch,
  1682. ;;  unsigned char *src2_ptr, int src2_pels, int src2_lines, int src2_pitch,
  1683. ;;  unsigned char *dest_ptr, int dest_pels, int dest_lines, int dest_pitch,
  1684. ;;  int alpha)
  1685. ;;
  1686. ;;
  1687. ;;  src2 = top
  1688. ;;  inverted alpha
  1689. ;;  uv size computed as: uvpitch*uvlines = (pitch/2)*(lines/2)
  1690. ;;
  1691. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1692. _I420andI420toI420_MMX_sub:
  1693. ;;
  1694. ;; int I420andI420toI420_MMX_sub(
  1695. ;;  unsigned char *src1_ptr, int src1_pels,   int src1_lines,  int src1_pitch,
  1696. ;;             int src1_startx, int src1_starty,
  1697. ;;  unsigned char *src2_ptr, int src2_pels,   int src2_lines,  int src2_pitch,
  1698. ;;             int src2_startx, int src2_starty,
  1699. ;;  unsigned char *dest_ptr, int dest_pels,   int dest_lines,  int dest_pitch,
  1700. ;;             int dest_startx, int dest_starty,
  1701. ;;  int width,  int height,  int alpha );
  1702. ;;
  1703. make_labels _I420andI420toI420_MMX_sub
  1704. ;;
  1705. ;; arguments
  1706. %define src            dword [esp+4*(1+npush)]
  1707. %define src_pels       dword [esp+4*(2+npush)]
  1708. %define src_lines      dword [esp+4*(3+npush)]
  1709. %define src_pitch      dword [esp+4*(4+npush)]
  1710. %define src_startx     dword [esp+4*(5+npush)]
  1711. %define src_starty     dword [esp+4*(6+npush)]
  1712. %define top            dword [esp+4*(7+npush)]
  1713. %define top_pels       dword [esp+4*(8+npush)]
  1714. %define top_lines      dword [esp+4*(9+npush)]
  1715. %define top_pitch      dword [esp+4*(10+npush)]
  1716. %define top_startx     dword [esp+4*(11+npush)]
  1717. %define top_starty     dword [esp+4*(12+npush)]
  1718. %define dst            dword [esp+4*(13+npush)]
  1719. %define dst_pels       dword [esp+4*(14+npush)]
  1720. %define dst_lines      dword [esp+4*(15+npush)]
  1721. %define dst_pitch      dword [esp+4*(16+npush)]
  1722. %define dst_startx     dword [esp+4*(17+npush)]
  1723. %define dst_starty     dword [esp+4*(18+npush)]
  1724. %define width          dword [esp+4*(19+npush)]
  1725. %define height         dword [esp+4*(20+npush)]
  1726. %define alpha          dword [esp+4*(21+npush)]
  1727.     push    ebp
  1728.     push    esi
  1729.     push    edi
  1730.     push    ecx
  1731.     push    ebx
  1732. ;; tmp on stack
  1733. %assign ntmps 16
  1734. %assign npush (5+ntmps)
  1735.     sub esp, ntmps*4 
  1736. ;; cycle through pointers to y then u the v indexed by ecx
  1737. ;; structure below must agree
  1738. %define topptr       dword [esp + 0*4 + ecx*4]   ;; topy[ecx*4]
  1739. %define sptr         dword [esp + 4*4 + ecx*4]   ;; sy[ecx*4]
  1740. %define dptr         dword [esp + 8*4 + ecx*4]   ;; dy[ecx*4]
  1741. ;; 
  1742. %define topy         dword [esp + 0*4]
  1743. %define topu         dword [esp + 1*4]
  1744. %define topv         dword [esp + 2*4]
  1745. %define toppitch     dword [esp + 3*4]
  1746. %define sy           dword [esp + 4*4]
  1747. %define su           dword [esp + 5*4]
  1748. %define sv           dword [esp + 6*4]
  1749. %define spitch       dword [esp + 7*4]
  1750. %define dy           dword [esp + 8*4]
  1751. %define du           dword [esp + 9*4]
  1752. %define dv           dword [esp + 10*4]
  1753. %define dpitch       dword [esp + 11*4]
  1754. %define lines        dword [esp + 12*4]
  1755. %define pels         dword [esp + 13*4]
  1756. %define dtmp0        dword [esp + 14*4]
  1757. %define dtmp1        dword [esp + 15*4]
  1758. %define btmp0(x)     byte [esp + 14*4 + x]
  1759. %define btmp1(x)     byte [esp + 15*4 + x]
  1760. ;;-----
  1761.     mov eax, dst_lines
  1762.     mov ecx, dst_pitch
  1763.     mov dpitch, ecx
  1764.     mov edx, eax
  1765.     imul    eax, ecx        ;; pitch*lines
  1766.     mov esi, dst
  1767.     mov dy, esi
  1768.     add esi, eax
  1769.     mov du, esi
  1770.     shr edx, 1              ;; lines/2  = uv lines
  1771.     shr ecx, 1              ;; pitch/2  = uvpitch
  1772.     imul    edx, ecx        ;; 
  1773.     add esi, edx
  1774.     mov dv, esi
  1775. ;;-----
  1776.     mov eax, src_lines
  1777.     mov ecx, src_pitch
  1778.     mov spitch, ecx
  1779.     mov edx, eax
  1780.     imul    eax, ecx        ;; pitch*lines
  1781.     mov esi, src
  1782.     mov sy, esi
  1783.     add esi, eax
  1784.     mov su, esi
  1785.     shr edx, 1              ;; lines/2  = uv lines
  1786.     shr ecx, 1              ;; pitch/2  = uvpitch
  1787.     imul    edx, ecx        ;; 
  1788.     add esi, edx
  1789.     mov sv, esi
  1790. ;;-----
  1791.     mov eax, top_lines
  1792.     mov ecx, top_pitch
  1793.     mov toppitch, ecx
  1794.     mov edx, eax
  1795.     imul    eax, ecx        ;; pitch*lines
  1796.     mov esi, top
  1797.     mov topy, esi
  1798.     add esi, eax
  1799.     mov topu, esi
  1800.     shr edx, 1              ;; lines/2  = uv lines
  1801.     shr ecx, 1              ;; pitch/2  = uvpitch
  1802.     imul    edx, ecx        ;; 
  1803.     add esi, edx
  1804.     mov topv, esi
  1805. ;;-----
  1806.     mov eax, height
  1807.     mov lines, eax
  1808.     mov eax, width
  1809.     mov pels, eax
  1810. ;;------------------
  1811. ;;------------------
  1812. ;; pointer adjustment to (x,y)
  1813.     mov ecx, top_pitch
  1814.     mov eax, top_starty
  1815.     mov edx, eax
  1816.     mov ebx, top_startx
  1817.     imul    eax, ecx        ;; y*pitch
  1818.     mov esi, topy             ;;
  1819.     add esi, eax            ;;  sy + y*pitch
  1820.     add esi, ebx            ;;  sy + y*pitch + x
  1821.     mov topy, esi
  1822.     shr ecx, 1          ;; pitch/2
  1823.     shr edx, 1          ;; y/2
  1824.     imul    edx, ecx    ;; (y/2)*(pitch/2)
  1825.     shr ebx, 1          ;; x/2
  1826.     add edx, ebx        ;; (y/2)*(pitch/2) + x/2
  1827.     mov esi, topu             ;;
  1828.     add esi, edx            ;;  su + (y/2)*(pitch/2)
  1829.     mov topu, esi
  1830.     mov esi, topv             ;;
  1831.     add esi, edx            ;;  su + (y/2)*(pitch/2)
  1832.     mov topv, esi
  1833. ;;
  1834. ;; pointer adjustment to (x,y)
  1835.     mov ecx, src_pitch
  1836.     mov eax, src_starty
  1837.     mov edx, eax
  1838.     mov ebx, src_startx
  1839.     imul    eax, ecx        ;; y*pitch
  1840.     mov esi, sy             ;;
  1841.     add esi, eax            ;;  sy + y*pitch
  1842.     add esi, ebx            ;;  sy + y*pitch + x
  1843.     mov sy, esi
  1844.     shr ecx, 1          ;; pitch/2
  1845.     shr edx, 1          ;; y/2
  1846.     imul    edx, ecx    ;; (y/2)*(pitch/2)
  1847.     shr ebx, 1          ;; x/2
  1848.     add edx, ebx        ;; (y/2)*(pitch/2) + x/2
  1849.     mov esi, su             ;;
  1850.     add esi, edx            ;;  su + (y/2)*(pitch/2)
  1851.     mov su, esi
  1852.     mov esi, sv             ;;
  1853.     add esi, edx            ;;  su + (y/2)*(pitch/2)
  1854.     mov sv, esi
  1855. ;;;
  1856. ;; pointer adjustment to (x,y)
  1857.     mov ecx, dst_pitch
  1858.     mov eax, dst_starty
  1859.     mov edx, eax
  1860.     mov ebx, dst_startx
  1861.     imul    eax, ecx        ;; y*pitch
  1862.     mov esi, dy             ;;
  1863.     add esi, eax            ;;  sy + y*pitch
  1864.     add esi, ebx            ;;  sy + y*pitch + x
  1865.     mov dy, esi
  1866.     shr ecx, 1          ;; pitch/2
  1867.     shr edx, 1          ;; y/2
  1868.     imul    edx, ecx    ;; (y/2)*(pitch/2)
  1869.     shr ebx, 1          ;; x/2
  1870.     add edx, ebx        ;; (y/2)*(pitch/2) + x/2
  1871.     mov esi, du             ;;
  1872.     add esi, edx            ;;  su + (y/2)*(pitch/2)
  1873.     mov du, esi
  1874.     mov esi, dv             ;;
  1875.     add esi, edx            ;;  su + (y/2)*(pitch/2)
  1876.     mov dv, esi
  1877. ;;-----
  1878. ;; I420 top   P = top
  1879. ;; [Y01Y02][Y03Y04]
  1880. ;; [Y11Y12][Y13Y04]
  1881. ;;   [U1]    [U3]
  1882. ;;   [V1]    [V3]
  1883. ;; I420 src  Q = bot
  1884. ;; [Y01Y02][Y03Y04]
  1885. ;; [Y11Y12][Y13Y04]
  1886. ;;   [U1]    [U3]
  1887. ;;   [V1]    [V3]
  1888. ;; I420 dst
  1889. ;; [Y01Y02][Y03Y04]
  1890. ;; [Y11Y12][Y13Y04]
  1891. ;;   [U1]    [U3]
  1892. ;;   [V1]    [V3]
  1893.     xor ecx, ecx            ;; y then u then v counter
  1894. ;; load alpha
  1895.     movzx   eax, byte alpha
  1896.     movd    mm4, eax
  1897.     punpcklwd    mm4, mm4        ;;   0 0 a a 
  1898.     punpckldq    mm4, mm4        ;    a a a a 
  1899. ;;
  1900.     movq    mm7, [mask3]
  1901.     movq    mm6, [mask3b]
  1902.     pxor    mm5, mm5
  1903. ;;-------
  1904. yuv_loop:
  1905.     mov esi, topptr
  1906.     mov edi, sptr
  1907.     mov ebx, dptr
  1908.     mov ebp, lines      ;; y lines loop counter
  1909.     or  ebp, ebp
  1910.     jle near exit
  1911. y100:
  1912.     mov eax, pels
  1913.     sub eax, 7
  1914.     jle  y_by_fours
  1915. a100:
  1916.     ;;  mm4 = alpha
  1917.     ;; top 8 y's
  1918.     movq    mm0, [esi]          ;; p8 p7 p6 p5 p4 p3 p2 p1
  1919.     movq    mm1, mm0            ;; p8 p7 p6 p5 p4 p3 p2 p1
  1920.     psrlw   mm0, 8              ;; word p8 p6 p4 p2 
  1921.     ;; src I420 8 y's
  1922.     movq    mm2, [edi]          ;; q8 q7 q6 q5 q4 q3 q2 q1
  1923.     movq    mm3, mm2            ;; q8 q7 q6 q5 q4 q3 q2 q1
  1924.     psrlw   mm2, 8              ;; word q8 q6 q4 q2 
  1925.     psubw   mm2, mm0            ;; q-p
  1926.     pmullw  mm2, mm4            ;; word alpha*(q-p)  for y8 y6 y4 y2
  1927.     pand    mm2, mm6            ;; word hi-byte alpha*(q-p) for y8 y6 y4 y2
  1928.     ;;
  1929.     ;; 
  1930.     movq    mm0, mm1            ;; p8 p7 p6 p5 p4 p3 p2 p1
  1931.     pand    mm1, mm7            ;; word p7 p5 p3 p1
  1932.     pand    mm3, mm7            ;; word q7 q5 q3 q1
  1933.     
  1934.     psubw   mm3, mm1            ;; q-p
  1935.     pmullw  mm3, mm4
  1936.     psrlw   mm3, 8              ;; alpha*(q-p) >> 8 for y7 y5 y3 y1
  1937.     
  1938.     por     mm2, mm3            ;; alpha*(q-p) >> 8 for y8 y7 y6 y5 y4 y3 y2 y1
  1939.     paddb   mm2, mm0            ;; blended y8 y7 y6 y5 y4 y3 y2 y1
  1940.     
  1941.     movq    [ebx], mm2
  1942.     add esi, 8
  1943.     add edi, 8
  1944.     add ebx, 8
  1945.     sub eax, 8
  1946.     jg  a100
  1947. ;;----------------------
  1948. y_by_fours:
  1949.     add eax, 4
  1950.     jle  y_one_two_three
  1951. a200:
  1952.     ;; top 4 y's
  1953.     movd    mm0, [esi]          ;; byte p4 p3 p2 p1
  1954.     punpcklbw mm0, mm5          ;; p4 p3 p2 p1
  1955.     ;; src I420 4 y's
  1956.     movd    mm2, [edi]          ;; byte  q4 q3 q2 q1
  1957.     punpcklbw mm2, mm5          ;; q4 q3 q2 q1
  1958.     psubw   mm2, mm0            ;; q-p
  1959.     pmullw  mm2, mm4
  1960.     psrlw   mm2, 8              ;; alpha*(q-p) >> 8 for y4 y3 y2 y1
  1961.     paddb   mm2, mm0            ;; blended word y4 y3 y2 y1
  1962.                         
  1963.     packuswb    mm2, mm5        ;; blended byte y4 y3 y2 y1 
  1964.     ;;
  1965.     movd    [ebx], mm2
  1966.     add esi, 4
  1967.     add edi, 4
  1968.     add ebx, 4
  1969.     sub eax, 4      ;; not needed if doing by_eights
  1970.     jg  a200        ;; not needed if doing by_eights
  1971. ;;
  1972. ;;
  1973. ;;----------------------
  1974. ;; do one, two, or three odd bytes
  1975. y_one_two_three:
  1976.     add eax, 3      ;; number bytes to do
  1977.     jle  line_done
  1978.     
  1979.     xor edx, edx    ;; zero offset on y
  1980.     or  ecx, ecx    ;; check for y (not u pr v)
  1981.     je  a333
  1982.     mov edx, 4
  1983.     sub edx, eax    ;; 4 - eax = numbers bytes offset
  1984. a333:
  1985.     movd mm1, edx   ;; number bytes to shift
  1986.     psllq   mm1, 3  ;; number bits to shift 
  1987.     ;;
  1988.     ;; pointer adjustment, negative offset
  1989.     neg edx     
  1990. ;;
  1991. ;;
  1992.     ;; top I420 1-3 y's
  1993.     movd    mm0, [esi+edx]          ;; byte p3 p2 p1 xx
  1994.     psrlq   mm0, mm1            ;; byte xx p3 p2 p1 
  1995.     punpcklbw mm0, mm5          ;; xx p3 p2 p1
  1996.     ;; src I420 1-3 y's
  1997.     movd    mm2, [edi+edx]          ;; byte  q3 q2 q1 xx
  1998.     psrlq   mm2, mm1            ;; byte xx q3 q2 q1 
  1999.     punpcklbw mm2, mm5          ;; xx q3 q2 q1
  2000.     psubw   mm2, mm0            ;; q-p
  2001.     pmullw  mm2, mm4
  2002.     psrlw   mm2, 8              ;; alpha*(q-p) >> 8 for xx y3 y2 y1
  2003.     paddb   mm2, mm0            ;; blended word xx y3 y2 y1
  2004.     
  2005.     packuswb    mm2, mm5        ;; blended byte xx y3 y2 y1 
  2006.     ;;
  2007.     movd    dtmp0, mm2
  2008.     ;; store result, byte by byte
  2009.     ;; eax = bytes to do
  2010. a300:
  2011.     mov dl, btmp0(eax-1)
  2012.     mov [ebx+eax-1], dl
  2013.     dec eax
  2014.     jg  a300
  2015. ;;------
  2016. line_done:
  2017.     mov eax, toppitch
  2018.     mov esi, topptr
  2019.     add esi, eax
  2020.     mov topptr, esi
  2021.     mov eax, spitch
  2022.     mov edi, sptr
  2023.     add edi, eax
  2024.     mov sptr, edi
  2025.     
  2026.     mov eax, dpitch
  2027.     mov ebx, dptr
  2028.     add ebx, eax
  2029.     mov dptr, ebx
  2030.     dec ebp
  2031.     jg  near y100        ;; line loop
  2032. ;;------
  2033.     
  2034. ;;-----
  2035. ;; y then u then v loop
  2036. ;; adjust for u or v
  2037.     mov eax, top_pitch
  2038.     shr eax, 1
  2039.     mov toppitch, eax
  2040.  
  2041.     mov eax, src_pitch
  2042.     shr eax, 1
  2043.     mov spitch, eax
  2044.  
  2045.     mov eax, dst_pitch
  2046.     shr eax, 1
  2047.     mov dpitch, eax
  2048.     mov eax, height
  2049.     shr eax, 1
  2050.     mov lines, eax
  2051.     mov eax, width
  2052.     shr eax, 1
  2053.     mov pels, eax
  2054.     inc ecx
  2055.     cmp ecx, 3
  2056.     jl  near yuv_loop
  2057. ;;-----
  2058. ;;------
  2059. exit:
  2060.     xor eax, eax    ;; return success
  2061.     add esp, ntmps*4
  2062.     pop ebx
  2063.     pop ecx
  2064.     pop edi
  2065.     pop esi
  2066.     pop ebp
  2067.     emms
  2068.     ret
  2069. ;_I420andI420toI420_MMX_sub endp
  2070. ;====================================
  2071. ;_TEXT ENDS
  2072. ;====================================
  2073.           END