yuvammx.asm
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:69k
源码类别:

Symbian

开发平台:

C/C++

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