processingMMX.inl
上传用户:fengshi120
上传日期:2014-07-17
资源大小:6155k
文件大小:54k
源码类别:

3D图形编程

开发平台:

C/C++

  1. /*************************************************************************** 
  2. *
  3. * Copyright 2000 by David Demirdjian.   All rights reserved. 
  4. *  
  5. * Developed  by David Demirdjian
  6. *  
  7. * Permission to use, copy, or modify this software and  its documentation 
  8. * for  educational  and  research purposes only and without fee  is hereby 
  9. * granted, provided  that this copyright notice and the original authors's 
  10. * names appear  on all copies and supporting documentation.  If individual 
  11. * files are  separated from  this  distribution directory  structure, this 
  12. * copyright notice must be included.  For any other uses of this software, 
  13. * in original or  modified form, including but not limited to distribution 
  14. * in whole or in  part, specific  prior permission  must be  obtained from 
  15. * MIT.  These programs shall not  be  used, rewritten, or  adapted as  the 
  16. * basis  of  a  commercial  software  or  hardware product  without  first 
  17. * obtaining appropriate  licenses from David Demirdjian.  The author makes 
  18. * no representations about the suitability of this software for any purpose.  
  19. * It is provided "as is" without express or implied warranty. 
  20. *  
  21. **************************************************************************/
  22. #include "stereoMatching.h"
  23. #include "processingMMX.h"
  24. // ************************************************************
  25. // ************************************************************
  26. // *** List of functions (MMX) for image processing
  27. // ************************************************************
  28. // ************************************************************
  29. // shrink images by a factor 'fact'. eg if fact = 2, out will be twice as small as src
  30. inline void shrinkImages(uchar* dst, const uchar* src, int width, int height, int fact)
  31. {
  32. int width_f = width/fact;
  33. int siz = width*height/(fact*fact);
  34. int src_idx = 0;
  35. if (fact>0) {
  36. for (int i=0,j=0; i<siz && src_idx<width*height; ++i,++j,++dst,src+=fact,src_idx+=fact) {
  37. *dst = *src;
  38. if (j==width_f-1) {
  39. src+=((fact-1)*width);
  40. src_idx+=((fact-1)*width);
  41. j=0;
  42. }
  43. }
  44. }
  45. }
  46. // translate image of 'tx' pixels to the right
  47. // (or left if tx<0)
  48. void translateImage(int tx, uchar* data, int siz)
  49. {
  50. if (tx==0) return; 
  51. if (tx>0) {
  52. // dest. must be after src... to avoid overwriting data
  53. data += (siz-tx);
  54. uchar* dataDst = data+tx;
  55. for (int i=0; i<siz-tx; ++i,--dataDst,--data) {
  56. *dataDst = *data;
  57. }
  58. } else { // tx<0
  59. data -= tx;
  60. uchar* dataDst = data+tx;
  61. for (int i=0; i<siz-tx; ++i,++dataDst,++data) {
  62. *dataDst = *data;
  63. }
  64. }
  65. }
  66. void normalizeImages(uchar* data1, uchar* data2, uchar* data3, int siz)
  67. {
  68. float a1 = pixelMean(data1,siz);
  69. float a2 = pixelMean(data2,siz);
  70. float a3 = pixelMean(data3,siz);
  71. float minI = __min(a1, __min(a2,a3));
  72. if (a2==minI) {
  73. multiply(data1, a2/a1, siz);
  74. multiply(data3, a2/a3, siz);
  75. } else if (a1==minI) {
  76. multiply(data2, a1/a2, siz);
  77. multiply(data3, a1/a3, siz);
  78. } else {
  79. multiply(data2, a3/a2, siz);
  80. multiply(data1, a3/a1, siz);
  81. }
  82. }
  83. void normalizeImages(const uchar* data1, const uchar* data2, const uchar* data3, 
  84.  uchar* out1, uchar* out2, uchar* out3, int siz)
  85. {
  86. float a1 = pixelMean(data1,siz);
  87. float a2 = pixelMean(data2,siz);
  88. float a3 = pixelMean(data3,siz);
  89. float minI = __min(a1, __min(a2,a3));
  90. if (a2==minI) {
  91. multiply(data1, out1, a2/a1, siz);
  92. multiply(data3, out3, a2/a3, siz);
  93. copyMMX(out2, data2, siz);
  94. } else if (a1==minI) {
  95. multiply(data2, out2, a1/a2, siz);
  96. multiply(data3, out3, a1/a3, siz);
  97. copyMMX(out1, data1, siz);
  98. } else {
  99. multiply(data2, out2, a3/a2, siz);
  100. multiply(data1, out1, a3/a1, siz);
  101. copyMMX(out3, data3, siz);
  102. }
  103. }
  104. void normalizeImages(uchar* data1, uchar* data2, int siz)
  105. {
  106. float a1 = pixelMean(data1,siz);
  107. float a2 = pixelMean(data2,siz);
  108. // normalize the image which average intensity is the highest
  109. if (a1>a2) 
  110. multiply(data1, a2/a1, siz);
  111. else 
  112. multiply(data2, a1/a2, siz);
  113. }
  114. void normalizeImages(const uchar* data1, const uchar* data2, 
  115.  uchar* out1, uchar* out2, int siz)
  116. {
  117. float a1 = pixelMean(data1,siz);
  118. float a2 = pixelMean(data2,siz);
  119. // normalize the image which average intensity is the highest
  120. if (a1>a2) {
  121. multiply(data1, out1, a2/a1, siz);
  122. copyMMX(out2, data2, siz);
  123. } else {
  124. multiply(data2, out2, a1/a2, siz);
  125. copyMMX(out1, data1, siz);
  126. }
  127. }
  128. //  ImgSub2: D = saturation0(|S1 - S2| + |S1 - S3|)
  129. // TODO? divide the result by 2 (shift)
  130. inline int ImgSubandAdd(const unsigned char *Src1, const unsigned char *Src2, 
  131.  const unsigned char *Src3, unsigned char *Dest, int l)
  132. {
  133. if (l < 8) return 0;              // image size must be at least 8 bytes 
  134.   __asm 
  135.   {
  136.         mov eax, Src1     
  137.         mov ebx, Src2
  138. mov edx, Src3
  139.         mov edi, Dest    
  140.         mov ecx, l   
  141.         shr ecx, 3
  142. align 16
  143. inner_loop:
  144. movq mm1,[eax] // mm1=src1
  145. movq mm2,[ebx] // mm2=src2
  146. movq mm4,mm1 // mm4=mm1
  147. psubusb mm4,mm2 // mm4 = src1 - src2
  148. movq mm3,[edx] // mm3=src3
  149. psubusb mm2,mm1 // mm2 = src2 - src1
  150.         
  151. movq mm5,mm1 // mm5=src1
  152. por mm2,mm4 // mm2=|src1-src2|
  153.         psubusb mm5,mm3 // mm4=src1-src3
  154.         psubusb mm3,mm1   // mm3=src3-src1
  155. por mm3,mm5 // mm3=|src1-src3|
  156. paddusb mm2,mm3 // mm2 = |src1-src2|+|src1-src3|
  157.         movq    [edi], mm2  
  158.         add eax,8         
  159.         add ebx,8     
  160.         add edx,8     
  161.         add edi,8
  162.         dec ecx      
  163.         jnz inner_loop    
  164.         emms   
  165.   }
  166.   return 1;
  167. }
  168. //  ImgSub2: D = saturation0(|S1 - S2|)
  169. // TODO? divide the result by 2 (shift)
  170. inline int ImgSubandAdd(const unsigned char *Src1, const unsigned char *Src2, 
  171.  const unsigned char *Dest, int l)
  172. {
  173. if (l < 8) return 0;              // image size must be at least 8 bytes 
  174.   __asm 
  175.   {
  176.         mov eax, Src1     
  177.         mov ebx, Src2
  178.         mov edi, Dest    
  179.         mov ecx, l   
  180.         shr ecx, 3
  181. align 16
  182. inner_loop:
  183. movq mm1,[eax] // mm1=src1
  184. movq mm2,[ebx] // mm2=src2
  185. movq mm4,mm1 // mm4=mm1
  186. psubusb mm4,mm2 // mm4 = src1 - src2
  187. psubusb mm2,mm1 // mm2 = src2 - src1  
  188. por mm2,mm4 // mm2=|src1-src2|
  189.         movq    [edi], mm2  
  190.         add eax,8         
  191.         add ebx,8     
  192.         add edi,8
  193.         dec ecx      
  194.         jnz inner_loop    
  195.         emms   
  196.   }
  197.   return 1;
  198. }
  199. #define _ABS_DIFF_TRI(Z) __asm 
  200. __asm movq mm4,mm1 /* mm4=mm1 */ 
  201. __asm add ebx, width  
  202. __asm add edi, imageSize 
  203. __asm por mm3,mm7 /* here mm2=new src2 mm3=new src3 */ 
  204. __asm movq mm7, mm0 
  205. __asm psubusb mm4,mm2 /* mm4 = src1 - src2 */ 
  206. __asm psubusb mm2,mm1 /* mm2 = src2 - src1 */ 
  207. __asm psllq mm7,Z
  208. __asm movq mm5,mm1 /* mm5=src1 */ 
  209. __asm por mm4,mm2 /* mm2=|src1-src2| */ 
  210. __asm movq mm2,[ebx] /* mm2= src2 + 'width' = new src2*/ 
  211. __asm psubusb mm5,mm3 /* mm5=src1-src3*/ 
  212. __asm movq mm6,mm3 /* mm6=src3*/ 
  213.     __asm   psubusb mm6,mm1   /* mm3=src3-src1*/ 
  214. __asm por mm6,mm5 /* mm6=|src1-src3|*/ 
  215. __asm paddusb mm4,mm6 /* mm4 = |src1-src2|+|src1-src3|*/ 
  216. __asm movq    [edi], mm4  /* here mm1=src1*/  
  217. __asm psrlq mm3, 8 /* mm3 = src3 + '1' ... with [x00000000] at the end*/
  218. }
  219. #define _ABS_DIFF_TRI_prefetch(Z, X) __asm 
  220. __asm movq mm4,mm1 /* mm4=mm1 */ 
  221. __asm add ebx, width  
  222. __asm add edi, imageSize 
  223. __asm por mm3,mm7 /* here mm2=new src2 mm3=new src3 */ 
  224. __asm movq mm7, mm0 
  225. __asm psubusb mm4,mm2 /* mm4 = src1 - src2 */ 
  226. __asm psubusb mm2,mm1 /* mm2 = src2 - src1 */ 
  227. __asm   prefetcht0 [ebx + X] 
  228. __asm psllq mm7,Z
  229. __asm movq mm5,mm1 /* mm5=src1 */ 
  230. __asm por mm4,mm2 /* mm2=|src1-src2| */ 
  231. __asm movq mm2,[ebx] /* mm2= src2 + 'width' = new src2*/ 
  232. __asm psubusb mm5,mm3 /* mm5=src1-src3*/ 
  233. __asm movq mm6,mm3 /* mm6=src3*/ 
  234.     __asm   psubusb mm6,mm1   /* mm3=src3-src1*/ 
  235. __asm por mm6,mm5 /* mm6=|src1-src3|*/ 
  236. __asm paddusb mm4,mm6 /* mm4 = |src1-src2|+|src1-src3|*/ 
  237. __asm movq    [edi], mm4  /* here mm1=src1*/  
  238. __asm psrlq mm3, 8 /* mm3 = src3 + '1' ... with [x00000000] at the end*/
  239. }
  240. //  ImgSubandAdd2: D = saturation0(|S1 - S2| + |S1 - S3|)
  241. // process 8 disparities at a time
  242. //
  243. // Src1: right
  244. // Src2: top
  245. // Src3: left
  246. //
  247. // TODO? divide the result by 2 (shift)
  248. inline int ImgSubandAdd2(const unsigned char *Src1, const unsigned char *Src2, 
  249.  const unsigned char *Src3, 
  250.  unsigned char* Dest1, int l, int imageSize, int width)
  251. {
  252. if (l < 8) return 0;              // image size must be at least 8 bytes 
  253. const int back_step1 = 7*width;
  254. const int back_step2 = 7*imageSize;
  255.   __asm 
  256.   {
  257.         mov eax, Src1     
  258.         mov ebx, Src2
  259. mov edx, Src3
  260.         mov edi, Dest1   
  261.         mov ecx, l   
  262.         shr ecx, 3
  263. movq mm0,[edx] // mm0=src3
  264. movq mm0,[edx] // mm0=src3
  265. align 16
  266. inner_loop:
  267. movq mm1,[eax] // mm1=src1
  268. movq mm3,mm0 // mm3=src3
  269. movq mm2,[ebx] // mm2=src2
  270.         add eax,8         
  271.  
  272. // -- 1 --------- in : mm1,mm2,mm3     out: mm4=SAD  mm2=new mm2 --
  273. movq mm4,mm1 // mm4=mm1
  274. add ebx,width
  275. psubusb mm4,mm2 // mm4 = src1 - src2
  276. //prefetcht0 [ebx + 32 + 2*320]
  277. movq mm0,[edx+8]
  278. psubusb mm2,mm1 // mm2 = src2 - src1
  279.         
  280. movq mm5,mm1 // mm5=src1
  281. por mm4,mm2 // mm2=|src1-src2|
  282. movq mm2,[ebx] // mm2= src2 + 'width' = new src2
  283. psubusb mm5,mm3 // mm5=src1-src3
  284. movq mm6,mm3 // mm6=src3
  285.         psubusb mm6,mm1   // mm3=src3-src1
  286. movq mm7, mm0
  287. psrlq mm3, 8 // mm3 = src3 + '1' ... with [x00000000] at the end
  288. por mm6,mm5 // mm6=|src1-src3|
  289. paddusb mm4,mm6 // mm4 = |src1-src2|+|src1-src3|
  290.         movq    [edi], mm4  
  291. psllq mm7, 56 // here mm1=src1 mm2=NEW src2 mm3=begin of NEWsrc3    mm7=end of NEWsrc3
  292. // -------------------------------------------------------------
  293. // - 2 ----------------
  294. _ABS_DIFF_TRI(48)
  295.   // - 3 ----------------
  296. _ABS_DIFF_TRI(40)
  297.   // - 4 ----------------
  298. _ABS_DIFF_TRI(32)
  299. // _ABS_DIFF_TRI_prefetch(32,24 + 3*320)
  300. // - 5 ----------------
  301. _ABS_DIFF_TRI(24)
  302. // - 6 ----------------
  303. _ABS_DIFF_TRI(16)
  304. // - 7 ----------------
  305. _ABS_DIFF_TRI(8)
  306. // - 8 ----------------
  307. movq mm4,mm1 // mm4=mm1
  308. por mm3,mm7 // here mm2=new src2 mm3=new src3
  309. psubusb mm4,mm2 // mm4 = src1 - src2
  310. psubusb mm2,mm1 // mm2 = src2 - src1
  311.         
  312. movq mm5,mm1 // mm5=src1
  313. por mm4,mm2 // mm2=|src1-src2|
  314. psubusb mm5,mm3 // mm5=src1-src3
  315.         psubusb mm3,mm1   // mm3=src3-src1
  316. por mm3,mm5 // mm6=|src1-src3|
  317. paddusb mm4,mm3 // mm4 = |src1-src2|+|src1-src3|
  318. add edi, imageSize
  319.         movq    [edi], mm4  // here mm1=src1
  320. // -------------------------------------------------------------
  321.   // 
  322. sub ebx, back_step1
  323.         add ebx,8
  324.         add edx,8     
  325. sub edi, back_step2
  326.         add edi,8
  327.         dec ecx      
  328.         jnz inner_loop    
  329.         emms   
  330.   }
  331.   return 1;
  332. }
  333. // macro: in: mm1,mm2
  334. #define _ABS_DIFF_ __asm 
  335. __asm  movq mm4,mm1  /* mm4=mm1 */ 
  336. __asm  psubusb mm4,mm2  /* mm4 = src1 - src2 */ 
  337. __asm  psubusb mm2,mm1  /* mm2 = src2 - src1 */ 
  338. __asm  por  mm4,mm2  /* mm2=|src1-src2| */ 
  339. __asm  add ebx, width 
  340. __asm  add edi, imageSize 
  341.     __asm  movq mm2,[ebx] 
  342. __asm  movq [edi], mm4   /* here mm1=src1  */ 
  343. }
  344. //  ImgSubandAdd2: D = saturation0(|S1 - S2| + |S1 - S3|)
  345. // process 8 disparities at a time
  346. // Src1: right
  347. // Src2: top
  348. // TODO? divide the result by 2 (shift)
  349. inline int ImgSubandAdd2_Vert(const unsigned char *Src1, const unsigned char *Src2, 
  350. unsigned char* Dest1, int l, int imageSize, int width)
  351. {
  352. if (l < 8) return 0;              // image size must be at least 8 bytes 
  353. const int back_step1 = 7*width;
  354. const int back_step2 = 7*imageSize;
  355.   __asm 
  356.   {
  357.         mov eax, Src1     
  358.         mov ebx, Src2
  359.         mov edi, Dest1   
  360.         mov ecx, l   
  361.         shr ecx, 3
  362. align 16
  363. inner_loop:
  364. movq mm1,[eax] // mm1=src1
  365. movq mm2,[ebx] // mm2=src2
  366.         add eax,8         
  367.  
  368. // -- 1 --------- in : mm1,mm2,mm3     out: mm4=SAD  mm2=new mm2 --
  369. _ABS_DIFF_
  370. _ABS_DIFF_
  371. _ABS_DIFF_
  372. _ABS_DIFF_
  373. _ABS_DIFF_
  374. _ABS_DIFF_
  375. _ABS_DIFF_
  376. // - 8 ----------------
  377. movq mm4,mm1 // mm4=mm1
  378. psubusb mm4,mm2 // mm4 = src1 - src2
  379. psubusb mm2,mm1 // mm2 = src2 - src1
  380.         
  381. por mm4,mm2 // mm2=|src1-src2|
  382. add edi, imageSize
  383.         movq    [edi], mm4  // here mm1=src1
  384. // -------------------------------------------------------------
  385.   // 
  386. sub ebx, back_step1
  387.         add ebx,8
  388.   sub edi, back_step2
  389.         add edi,8
  390.         dec ecx      
  391.         jnz inner_loop    
  392.         emms   
  393.   }
  394.   return 1;
  395. }
  396. // macro: in: mm1,mm2
  397. #define _ABS_DIFF_HORIZ(Z) __asm 
  398. __asm  movq mm7, mm0 
  399. __asm  add edi, imageSize 
  400. __asm  movq mm5,mm1 /* mm5=src1 */ 
  401. __asm  psllq mm7, Z 
  402. __asm  psubusb mm5,mm3 /* mm5=src1-src3 */ 
  403. __asm  movq mm6,mm3 /* mm6=src3 */ 
  404.     __asm  psubusb mm6,mm1   /* mm3=src3-src1 */ 
  405. __asm  por mm6,mm5 /* mm6=|src1-src3| */ 
  406.     __asm  movq    [edi], mm6  /* here mm1=src1 */ 
  407. __asm  psrlq mm3, 8 /* mm3 = src3 + '1' ... with [x00000000] at the end */ 
  408. __asm  por mm3,mm7 /* here mm3=new src3 */ 
  409. }
  410. //  ImgSubandAdd2: D = saturation0(|S1 - S2| + |S1 - S3|)
  411. // process 8 disparities at a time
  412. //
  413. // Src1: right
  414. // Src2: top
  415. // Src3: left
  416. //
  417. // TODO? divide the result by 2 (shift)
  418. inline int ImgSubandAdd_Horiz(const unsigned char *rightIm, const unsigned char *leftIm, 
  419.  unsigned char* Dest, int l, int imageSize, int width)
  420. {
  421. if (l < 8) return 0;              // image size must be at least 8 bytes 
  422. const int back_step2 = 7*imageSize;
  423.   __asm 
  424.   {
  425.         mov eax, rightIm     
  426.   mov edx, leftIm
  427.         mov edi, Dest 
  428.         mov ecx, l   
  429.         shr ecx, 3
  430. movq mm0,[edx] // mm0=src3
  431. movq mm0,[edx] // mm0=src3
  432. align 16
  433. inner_loop:
  434. movq mm1,[eax] // mm1=src1
  435. movq mm3,mm0 // mm3=src3
  436. // -- 1 --------- in : mm1,mm2,mm3     out: mm4=SAD  mm2=new mm2 --
  437. movq mm0,[edx+8]
  438.         add eax,8         
  439.    
  440. movq mm5,mm1 // mm5=src1
  441. psubusb mm5,mm3 // mm5=src1-src3
  442. movq mm6,mm3 // mm6=src3
  443.         psubusb mm6,mm1   // mm3=src3-src1
  444. movq mm7, mm0
  445. psrlq mm3, 8 // mm3 = src3 + '1' ... with [x00000000] at the end
  446. por mm6,mm5 // mm6=|src1-src3|
  447.         movq    [edi], mm6  
  448. psllq mm7, 56 // here mm1=src1 mm3=begin of NEWsrc3    mm7=end of NEWsrc3
  449. por mm3,mm7 // here mm3=new src3
  450. // - 2 ----------------
  451. _ABS_DIFF_HORIZ(48)
  452. _ABS_DIFF_HORIZ(40)
  453. _ABS_DIFF_HORIZ(32)
  454. _ABS_DIFF_HORIZ(24)
  455. _ABS_DIFF_HORIZ(16)
  456. _ABS_DIFF_HORIZ(8)
  457. // - 8 ----------------
  458. movq mm5,mm1 // mm5=src1
  459. add edi, imageSize
  460. psubusb mm5,mm3 // mm5=src1-src3
  461.         psubusb mm3,mm1   // mm3=src3-src1
  462. por mm3,mm5 // mm6=|src1-src3|
  463.         movq    [edi], mm3  
  464. // -------------------------------------------------------------
  465.   // 
  466.         add edx,8     
  467. sub edi, back_step2
  468.         add edi,8
  469.         dec ecx      
  470.         jnz inner_loop    
  471.         emms   
  472.   }
  473.   return 1;
  474. }
  475. // ----------------------
  476. // FULL IMAGE, BEST ONLY : Keith's code
  477. inline int findMinimumCorrelation_mmx(
  478. const unsigned char *CurrentCorrelation,
  479. unsigned char CurrentDisparity,
  480. unsigned char *Disparity,
  481. unsigned char *BestCorrelation, int bytecount) 
  482. {
  483. if ((bytecount < 8) || ((bytecount % 8) != 0)) {
  484. return 0;
  485. }
  486. __asm {
  487. // load ecx with the pixelblock count = bytecount / 8
  488. mov ecx, bytecount
  489. shr ecx, 3
  490. // setup mm0 with 8 copies of the disparity constant
  491. mov al,  CurrentDisparity
  492. mov ah,  al
  493. mov bx,  ax
  494. shl eax,  16
  495. mov ax,  bx
  496. movd mm0,  eax
  497. movd mm1,  eax
  498. punpckldq mm0,  mm1
  499. // setup mm1 with 8 copies of the xor constant for unsigned => signed conversion
  500. mov eax, 0x80808080
  501. movd mm1, eax
  502. movd mm2, eax
  503. punpckldq mm1, mm2
  504. // setup the image pointers
  505. mov eax,  BestCorrelation
  506. mov esi,  CurrentCorrelation
  507. mov edi,  Disparity
  508. pixel_loop:
  509. movq mm2, [esi] // current correlation
  510. movq mm3, [eax] // best correlation
  511. // check for updates
  512. movq mm5, mm2 // copy the current correlation
  513. pxor mm5, mm1 // convert from unsigned range to signed range
  514. movq mm6, mm3 // copy the best correlation
  515. pxor mm6, mm1 // convert from unsigned range to signed range
  516. pcmpgtb mm5, mm6 // mm5 := (current signed> best) mask
  517. // 1 indicates current >  best, so keep best
  518. // 0 indicates current <= best, so use new value
  519. // BYPASS
  520. // this phase adds 8 additional instructions, but could skip 2 writes and 1 read
  521. // abort remainder if not updating best correlation
  522. pcmpeqb mm6, mm6 // mm6 = 0xFFFFFFFF
  523. pxor mm6,  mm5 // mm6 = mm5 xor 0xFFFFFFFF = not mm5
  524. // 0 indicates current >  best, so keep best
  525. // 1 indicates current <= best, so use new value
  526. packsswb mm6, mm6 // pack it into the lower dword of mm6 (unsigned saturation)
  527. //  11111111 11111111 => 11111111 some replaced
  528. // 11111111 00000000 => 11111111 some replaced
  529. // 00000000 11111111 => 11111111 some replaced
  530. // 00000000 00000000 => 00000000 no replacements
  531. // we don't need to backup ebx because its not used in this routine
  532. // movd mm7, ebx // make a backup of eax
  533. movd ebx, mm6 // get the saturated mask
  534. test ebx, ebx // test ebx => yields 0 iff no substitutions will occur
  535. // movd ebx, mm7 // restore ebx
  536. jz bypass // store mm4 (second correlation) to [ebx]
  537. // Update best Correlation
  538. movq mm6, mm5 // mm6 := mask
  539. movq mm7, mm5 // mm7 := mask
  540. pand mm6, mm3 // best correlation values to keep
  541. pandn mm7, mm2 // current correlation value to move to best correlation
  542. por mm6, mm7 // merge values
  543. movq [eax], mm6 // store values
  544. // update disparity
  545. movq mm2, [edi] // get disparity map
  546. movq mm6, mm5 // mm6 := mask
  547. pand mm5, mm2 // select disparity map values to keep
  548. pandn mm6, mm0 // select current disparity values to move to disparity map
  549. por mm5, mm6 // merge values
  550. movq [edi], mm5 // store values
  551. bypass:
  552. add eax, 8
  553. add esi, 8
  554. add edi, 8
  555. dec ecx
  556. jnz pixel_loop
  557. emms;
  558. }
  559. return 1;
  560. }
  561. /*int initMinimumCorrelation(
  562. const unsigned char *CurrentCorrelation,
  563. unsigned char disparityInit,
  564. unsigned char *Disparity,
  565. unsigned char *BestCorrelation,
  566. unsigned char *SecondCorrelation,
  567. int bytecount) 
  568. {
  569. for (int i=0; i<bytecount; ++i)
  570. {
  571. BestCorrelation[i]=255;
  572. SecondCorrelation[i]=255;
  573. Disparity[i]=0;
  574. }
  575. return 0;
  576. }*/
  577. inline int initMinimumCorrelation(
  578. const unsigned char *CurrentCorrelation,
  579. unsigned char disparityInit,
  580. unsigned char *Disparity,
  581. unsigned char *BestCorrelation,
  582. unsigned char *SecondCorrelation,
  583. int bytecount) 
  584. {
  585. if ((bytecount < 8) || ((bytecount % 8) != 0)) {
  586. return 0;
  587. }
  588. __asm {
  589. // setup mm0 with 8 copies of the disparity constant
  590. mov al,  disparityInit
  591. mov ah,  al
  592. mov bx,  ax
  593. shl eax,  16
  594. mov ax,  bx
  595. movd mm0,  eax
  596. movd mm1,  eax
  597. punpckldq mm0,  mm1
  598. // load ecx with the pixelblock count = bytecount / 8
  599. mov ecx, bytecount
  600. shr ecx, 3
  601. mov eax,  BestCorrelation
  602. mov ebx,  SecondCorrelation
  603. mov esi,  CurrentCorrelation
  604. mov edx, Disparity
  605. pixel_loop:
  606. movq mm1, [esi]
  607. movq [eax], mm1 // Best = Current
  608. movq [ebx], mm1 // Second = Current
  609. movq [edx], mm0 // Disparity = disparityInit
  610. add eax, 8
  611. add ebx, 8
  612. add edx, 8
  613. add esi, 8
  614. dec ecx
  615. jnz pixel_loop
  616. jmp done
  617. done:
  618. emms;
  619. }
  620. }
  621. inline int findMinimumCorrelation(
  622. const unsigned char *CurrentCorrelation,
  623. unsigned char CurrentDisparity,
  624. unsigned char *Disparity,
  625. unsigned char *BestCorrelation,
  626. unsigned char *SecondCorrelation,
  627. int bytecount) 
  628. {
  629. for (int i=0; i<bytecount; ++i,++CurrentCorrelation,++Disparity,++BestCorrelation, ++SecondCorrelation) 
  630. {
  631. if (*CurrentCorrelation<*BestCorrelation) {
  632. *Disparity = CurrentDisparity;
  633. *SecondCorrelation = *BestCorrelation;
  634. *BestCorrelation = *CurrentCorrelation;
  635. }
  636. }
  637. return 1;
  638. }
  639. // ----------------------
  640. // FULL IMAGE, BEST+SECOND .. Keith's code
  641. inline int findMinimumCorrelation_mmx(
  642. const unsigned char *CurrentCorrelation,
  643. unsigned char CurrentDisparity,
  644. unsigned char *Disparity,
  645. unsigned char *BestCorrelation,
  646. unsigned char *SecondCorrelation,
  647. int bytecount) 
  648. {
  649. if ((bytecount < 8) || ((bytecount % 8) != 0)) {
  650. return 0;
  651. }
  652. __asm {
  653. // load ecx with the pixelblock count = bytecount / 8
  654. mov ecx, bytecount
  655. shr ecx, 3
  656. // setup mm0 with 8 copies of the disparity constant
  657. mov al,  CurrentDisparity
  658. mov ah,  al
  659. mov bx,  ax
  660. shl eax,  16
  661. mov ax,  bx
  662. movd mm0,  eax
  663. movd mm1,  eax
  664. punpckldq mm0,  mm1
  665. // setup mm1 with 8 copies of the xor constant for unsigned => signed conversion
  666. mov eax, 0x80808080
  667. movd mm1, eax
  668. movd mm2, eax
  669. punpckldq mm1, mm2
  670. // setup the image pointers
  671. mov eax,  BestCorrelation
  672. mov ebx,  SecondCorrelation
  673. mov esi,  CurrentCorrelation
  674. mov edi,  Disparity
  675. pixel_loop:
  676. movq mm2, [esi] // current correlation
  677. movq mm4, [ebx] // second correlation
  678. // convert the current correlation from unsigned range to signed range
  679. movq mm5, mm2 // copy the current correlation
  680. pxor mm5, mm1 // convert from unsigned range to signed range
  681. movq mm7, mm5 // copy converted to mm7
  682. // check for second correlation updates
  683. movq mm6, mm4 // copy second best correlation
  684. pxor mm6, mm1 // convert from unsigned range to signed range
  685. pcmpgtb mm7, mm6 // mm7 := (current signed> second best) mask
  686. // BYPASS 1
  687. // skip remainder if second correlation is not to be updated
  688. // this phase adds an addition 8 instructions, but it could save as 1 memory read and 3 writes
  689. pcmpeqb mm6, mm6 // mm6 = 0xFFFFFFFF
  690. pxor mm6,  mm7 // mm6 = mm7 xor 0xFFFFFFFF = not mm7
  691. // 0 indicates current >  second, so keep old value
  692. // 1 indicates current <= second, so use new value
  693. packsswb mm6, mm6 // pack it into the lower dword of mm6 (unsigned saturation)
  694. //  11111111 11111111 => 11111111 some replaced
  695. // 11111111 00000000 => 11111111 some replaced
  696. // 00000000 11111111 => 11111111 some replaced
  697. // 00000000 00000000 => 00000000 no replacements
  698. // don't need to backup edx because its not used in this routine
  699. // movd mm3, edx // make a backup of edx
  700. movd edx, mm6 // get the saturated mask
  701. test edx, edx // test edx => yields 0 iff no replacements will occur
  702. // movd edx, mm3 // restore edx
  703. jz bypass1
  704. // direct update second correlation (get values from current)
  705. // mm7 already has mask
  706. // movq mm6, mm7 // mm6 := mask
  707. // pand mm6, mm4 // second correlation values to keep
  708. // pandn mm7, mm2 // current correlation values to move to second correlation
  709. // por mm6, mm7 // merge value => direct updated second correlation
  710. // movq mm4, mm6 // store values (*** this instruction could be eliminated!) 
  711. pand mm4, mm7 // second correlation values to keep
  712. pandn mm7, mm2 // current correlation values to move to second correlation
  713. por mm4, mm7 // merge value => direct updated second correlation
  714. // check for best correlation updates
  715. movq mm3, [eax] // best correlation
  716. // mm5 has converted current correlation
  717. movq mm6, mm3 // copy the best correlation
  718. pxor mm6, mm1 // convert from unsigned range to signed range
  719. pcmpgtb mm5, mm6 // mm5 := (current signed> best) mask
  720. // 1 indicates current >  best, so keep best
  721. // 0 indicates current <= best, so use new value
  722. // BYPASS 2
  723. // this phase adds 8 additional instructions, but could skip 2 writes and 1 read
  724. // abort remainder if not updating best correlation
  725. pcmpeqb mm6, mm6 // mm6 = 0xFFFFFFFF
  726. pxor mm6,  mm5 // mm6 = mm5 xor 0xFFFFFFFF = not mm5
  727. // 0 indicates current >  best, so keep best
  728. // 1 indicates current <= best, so use new value
  729. packsswb mm6, mm6 // pack it into the lower dword of mm6 (unsigned saturation)
  730. //  11111111 11111111 => 11111111 some replaced
  731. // 11111111 00000000 => 11111111 some replaced
  732. // 00000000 11111111 => 11111111 some replaced
  733. // 00000000 00000000 => 00000000 no replacements
  734. // don't need to backup edx because its not used in this routine
  735. // movd mm7, edx // make a backup of edx
  736. movd edx, mm6 // get the saturated mask
  737. test edx, edx // test edx => yields 0 iff no substitutions will occur
  738. // movd edx, mm7 // restore edx
  739. jz bypass2 // store mm4 (second correlation) to [ebx]
  740. // indirect update second correlation (pushed down from best)
  741. movq mm6, mm5 // mm6 := mask
  742. movq mm7, mm5 // mm7 := mask
  743. pand mm6, mm4 // second correlation values to keep
  744. pandn mm7, mm3 // best correlations to move to second correlation
  745. por mm6, mm7 // merge values
  746. movq [ebx], mm6 // store values
  747. // direct Update best Correlation
  748. movq mm6, mm5 // mm6 := mask
  749. movq mm7, mm5 // mm7 := mask
  750. pand mm6, mm3 // best correlation values to keep
  751. pandn mm7, mm2 // current correlation value to move to best correlation
  752. por mm6, mm7 // merge values
  753. movq [eax], mm6 // store values
  754. // update disparity
  755. movq mm2, [edi] // get disparity map
  756. movq mm6, mm5 // mm6 := mask
  757. pand mm5, mm2 // select disparity map values to keep
  758. pandn mm6, mm0 // select current disparity values to move to disparity map
  759. por mm5, mm6 // merge values
  760. movq [edi], mm5 // store values
  761. bypass1:
  762. next_pixel:
  763. add eax, 8
  764. add ebx, 8
  765. add esi, 8
  766. add edi, 8
  767. dec ecx
  768. jnz pixel_loop
  769. jmp done
  770. bypass2:
  771. movq [ebx], mm4;
  772. jmp next_pixel
  773. done:
  774. emms;
  775. }
  776. return 1;
  777. }
  778. inline void sum_Row(uchar* im, unsigned short* im_out, int rowSize, int maskSize) 
  779. {
  780. im += maskSize/2;
  781. im_out += maskSize/2;
  782. for (int i=0; i<rowSize; ++i) {
  783. int s=0;
  784. for (int j=-maskSize/2; j<=maskSize/2; ++j) {
  785. s+=*(im+j);
  786. }
  787. *im_out=s/maskSize;
  788. ++im;++im_out;
  789. }
  790. }
  791. inline void sum_Row_mmx(uchar* im, unsigned short* im_out, int rowSize, int maskSize) 
  792. {
  793. sum_Row_5_mmx(im, im_out, rowSize);
  794. for (int i=0; i<(maskSize-5)/2; ++i)
  795. sum_Row_5_mmx(im_out, im_out, rowSize);
  796. }
  797. inline  void sum_Row_mmx(unsigned short* im, unsigned short* im_out, int rowSize, int maskSize) 
  798. {
  799. sum_Row_5_mmx(im, im_out, rowSize);
  800. for (int i=0; i<(maskSize-5)/2; ++i)
  801. sum_Row_5_mmx(im_out, im_out, rowSize);
  802. }
  803. #define aim_Sum_Words_In_MM1 __asm 
  804. {
  805. __asm movq mm4, mm1 
  806. __asm movq mm2, mm1 
  807. __asm movq mm3, mm1 
  808. __asm psllq mm1, 16 
  809. __asm psrlq mm2, 16 
  810. __asm paddw mm4, mm2 
  811. __asm paddw mm3, mm1 
  812. __asm psrlq mm2, 16 
  813. __asm psllq mm1, 16 
  814. __asm paddw mm4, mm2 
  815. __asm psrlq mm2, 16 
  816. __asm paddw mm3, mm1 
  817. __asm psllq mm1, 16 
  818. __asm paddw mm4, mm2 
  819. __asm paddw mm3, mm1 
  820. }
  821. // apply the mask [1 1 1 1 1] to the 1-D array im (bytes)
  822. // output : im_out (words)
  823. inline void sum_Row_5_mmx(uchar* im, unsigned short* im_out, int rowSize) 
  824. {
  825. // temp: for debugging
  826. //return sum_Row_5(im,im_out,rowSize);
  827. __asm {
  828. mov eax, rowSize
  829. mov ebx, im
  830. mov ecx, im_out
  831. pxor mm6, mm6 // mm6 = x00000000
  832. //Process the first quad word, but save only the second result" 
  833. test eax, eax // Is there anything to do?" 
  834. jz end_sum_loop // Jump out if necessary 
  835. //Process low word 
  836. movq mm1, [ebx] // Copy... 
  837. punpcklbw mm1, mm6 // Expand low word bytes into words // mm1 =[D C B A]
  838. aim_Sum_Words_In_MM1
  839. //Store the result Only in the accumulator 
  840. movq mm7, mm4 // Update accumulator    mm4=[D  C+D   B+C+D   A+B+C+D]
  841. //Process high word 
  842. movq mm1, [ebx] // Copy... 
  843. punpckhbw mm1, mm6 // Expand high word bytes into words   // mm1 =[H G F E]
  844. add ebx, 8 // Update input pointer 
  845.     aim_Sum_Words_In_MM1
  846. //Add to the previous data ... 
  847. // mm3=[E+F+G+H  E+F+G  E+F   E]
  848. // mm4=[H G+H    F+G+H   E+F+G+H]
  849. paddw mm7, mm3 // The current word of the accum   // mm7=[D+E+F+G+H  C+D+E+F+G  B+C+D+E+F  A+B+C+D+E]
  850. // translate everything to 2 words on the left
  851. movq mm1, mm7 // mm1 = [D+E+F+G+H  C+D+E+F+G  B+C+D+E+F  A+B+C+D+E]
  852. psrlq   mm1, 32 // mm1 = [0  0  D+E+F+G+H  C+D+E+F+G]
  853. movq mm0, mm1 // mm0 = [D+E+F+G+H  C+D+E+F+G]
  854. psllq mm7, 32 // mm7 = [B+C+D+E+F  A+B+C+D+E  0   0]
  855. movq [ecx], mm7 // Store the final result 
  856. add ecx, 8 // Update output pointer 
  857. movq mm7, mm4 // Update accumulator    mm4=[H G+H    F+G+H   E+F+G+H]
  858. sub eax, 8 // Update the number of points left 
  859. // Start the loop 
  860. row_sum_loop:
  861. test eax, eax // Is there anything to do? 
  862. jz end_sum_loop // Jump out if necessary 
  863. movq mm1, [ebx] // Load data 
  864. //Process low word 
  865. punpcklbw mm1, mm6 // Expand low word bytes into words 
  866. aim_Sum_Words_In_MM1
  867. //Add to the previous data 
  868. //prefetcht1 [ecx+16]
  869. paddw mm7, mm3 // The current word of the accum 
  870. // translate everything to 2 words on the left
  871. // mm0 = [0 0 D C]  mm7 = [H G F E] ----> mm7=[0 0 H G]  [ecx]=[F E D C]
  872. punpckldq mm0, mm7 // mm0 = [F E D C]
  873. movq [ecx], mm0
  874. sub eax, 8 // Update the number of points left 
  875. movq mm0, mm4 // Update accumulator 
  876. psrlq mm7, 32 // mm7 = [0 0 H G]
  877. //Process high word 
  878. movq mm1, [ebx] // Copy... 
  879. punpckhbw mm1, mm6 // Expand high word bytes into words 
  880. aim_Sum_Words_In_MM1
  881. //Add to the previous data 
  882. paddw mm0, mm3 // The current word of the accum 
  883. // translate everything to 2 words on the left
  884. // mm7 = [0 0 D C]  mm0 = [H G F E] ----> mm0=[0 0 H G]  [ecx+8]=[F E D C]
  885. punpckldq mm7, mm0 // mm7 = [F E D C]
  886. add ebx, 8 // Update input pointer 
  887. movq [ecx+8], mm7
  888. psrlq mm0, 32 // mm0 = [0 0 H G] 
  889. movq mm7, mm4 // Update accumulator 
  890. add ecx, 16 // Update output pointer 
  891. jmp row_sum_loop // Loop 
  892. //Cleanup 
  893. end_sum_loop:
  894. emms 
  895. }
  896. }
  897. // apply the mask (1/4)*[1 1 1 1 1] to the 1-D array im (words)
  898. // output : im_out (words)
  899. inline void sum_Row_5_mmx(ushort* im, ushort* im_out, int rowSize) 
  900. {
  901. // temp: for debugging
  902. //return sum_Row_5(im,im_out,rowSize);
  903. __asm {
  904. mov eax, rowSize
  905. mov ebx, im
  906. mov ecx, im_out
  907. //Process the first quad word, but save only the second result" 
  908. test eax, eax // Is there anything to do?" 
  909. jz end_sum_loop // Jump out if necessary 
  910. movq mm1, [ebx] // Load data (4 words)
  911. add ebx, 8 // Update input pointer 
  912. //Process low word 
  913. aim_Sum_Words_In_MM1
  914. //Store the result Only in the accumulator 
  915. movq mm7, mm4 // Update accumulator 
  916. //Process high word 
  917. movq mm1, [ebx] // Copy... 
  918. aim_Sum_Words_In_MM1
  919. add ebx, 8
  920. //Add to the previous data 
  921. paddw mm7, mm3 // The current word of the accum 
  922. // translate everything to 2 words on the left
  923. movq mm1, mm7 // mm1 = [D+E+F+G+H  C+D+E+F+G  B+C+D+E+F  A+B+C+D+E]
  924. psrlq   mm1, 32 // mm1 = [0  0  D+E+F+G+H  C+D+E+F+G]
  925. movq mm0, mm1 // mm0 = [0  0  D+E+F+G+H  C+D+E+F+G]
  926. psllq mm7, 32 // mm7 = [B+C+D+E+F  A+B+C+D+E  0   0]
  927. movq [ecx], mm7 // Store the final result 
  928. movq mm7, mm4 // Update accumulator 
  929. add ecx, 8 // Update output pointer 
  930. sub eax, 8 // Update the number of points left 
  931. // Start the loop 
  932. row_sum_loop:
  933. test eax, eax // Is there anything to do? 
  934. jz end_sum_loop // Jump out if necessary 
  935. movq mm1, [ebx] // Load data 
  936. aim_Sum_Words_In_MM1
  937. //Add to the previous data 
  938. //prefetcht0 [ecx + 32]
  939. //prefetcht0 [ebx + 48]
  940. paddw mm7, mm3 // The current word of the accum 
  941. psrlw mm7, 2 // divide result by ...
  942. // translate everything to 2 words on the left
  943. // mm0 = [0 0 D C]  mm7 = [H G F E] ----> mm7 =[0 0 H G]  [ecx]=[F E D C]
  944. punpckldq mm0, mm7  // mm0 = [F E D C]
  945. movq [ecx], mm0
  946. sub eax, 8 // Update the number of points left 
  947. movq mm0, mm4 // Update accumulator 
  948. psrlq mm7, 32 // mm7 =[0 0 H G]
  949. //Process high word 
  950. movq mm1, [ebx+8] // Copy... 
  951. aim_Sum_Words_In_MM1
  952. //Add to the previous data 
  953. paddw mm0, mm3 // The current word of the accum 
  954. psrlw mm0, 2 // divide result by ...
  955. // translate everything to 2 words on the left
  956. // mm7 = [0 0 D C]  mm0 = [H G F E] ----> mm0=[0 0 H G]  [ecx+8]=[F E D C]
  957. punpckldq mm7, mm0 // mm7 = [F E D C]
  958. add ebx, 16 // Update input pointer 
  959. movq [ecx+8], mm7
  960. psrlq mm0, 32 // mm0 = [0 0 H G]
  961. movq mm7, mm4 // Update accumulator 
  962. add ecx, 16 // Update output pointer */
  963. jmp row_sum_loop // Loop 
  964. //Cleanup 
  965. end_sum_loop:
  966. emms 
  967. }
  968. }
  969. template<class T> void sum_Row_5(T* im, ushort* im_out, int rowSize)
  970. {
  971. im += 2;
  972. im_out +=2;
  973. int s = 0;
  974. for (int i=0; i<rowSize-5; ++i, ++im, ++im_out) {
  975. s = *(im-2);
  976. s += *(im-1);
  977. s += *(im);
  978. s += *(im+1);
  979. s += *(im+2);
  980. *im_out = s/5;
  981. }
  982. }
  983. inline void avg_Col(ushort* im, uchar* im_out, int dataSize, int width, int sizeMask)
  984. {
  985. int offset = width*(sizeMask/2);
  986. im += offset;
  987. im_out += offset;
  988. for (int i=0; i<dataSize-width*sizeMask; ++i, ++im, ++im_out) {
  989. int s = 0;
  990. for (int j=-sizeMask/2; j<=sizeMask/2; ++j) s += *(im+j*width);
  991. *im_out = s/(sizeMask);
  992. }
  993. }
  994. // apply vertical mask 1/16*[1 1 1 ... 1]^T to 'im'
  995. // result in 'im_out'
  996. inline void avg_Col_mmx(ushort* im, uchar* im_out, int dataSize, int width, int sizeMask)
  997. {
  998. // temp: for debugging
  999. //return avg_Col(im,im_out,dataSize,width,sizeMask);
  1000. switch (sizeMask)
  1001. {
  1002. case 5: avg_Col_5(im,im_out,dataSize,width);
  1003. break;
  1004. case 7: avg_Col_7(im,im_out,dataSize,width);
  1005. break;
  1006. case 9: avg_Col_9(im,im_out,dataSize,width);
  1007. break;
  1008. case 11: avg_Col_11(im,im_out,dataSize,width);
  1009. break;
  1010. case 13: avg_Col_13(im,im_out,dataSize,width);
  1011. break;
  1012. case 15: avg_Col_15(im,im_out,dataSize,width);
  1013. break;
  1014. case 17: avg_Col_17(im,im_out,dataSize,width);
  1015. break;
  1016. default: if (sizeMask<5) avg_Col_5(im,im_out,dataSize,width);
  1017.  else if (sizeMask>17) avg_Col_17(im,im_out,dataSize,width);
  1018. break;
  1019. }
  1020. }
  1021. #define macro_add __asm 
  1022. {
  1023. __asm  paddusw mm3, [edx]
  1024. __asm paddusw mm2, [edx+8]  
  1025. __asm add edx, edi
  1026. }
  1027. inline void avg_Col_5(ushort* im, uchar* im_out, int dataSize, int width)
  1028. {
  1029. __asm {
  1030. mov edi, width
  1031. shl edi, 1  // edi = 2*width
  1032. mov eax, dataSize
  1033. mov ecx, im_out
  1034. mov ebx, im
  1035. sub ebx, edi
  1036. sub ebx, edi // ebx = ebx-4*width
  1037. test eax, eax // Is there anything to do?" 
  1038. jz end_sum_loop // Jump out if necessary 
  1039. row_sum_loop:
  1040. test eax, eax // Is there anything to do? 
  1041. jz end_sum_loop // Jump out if necessary 
  1042. mov edx, ebx
  1043. add ebx, 16
  1044. // 1
  1045. movq mm3, [edx] // mm3 = 4 words of im
  1046. movq mm2, [edx+8] // mm2 = next 4 words of im
  1047. add edx, edi
  1048. macro_add
  1049. macro_add
  1050. macro_add
  1051. macro_add
  1052. // divide results by ...
  1053. psrlw mm3, 3
  1054. psrlw mm2, 3
  1055. // convert [mm2 mm3] as 8 bytes
  1056. packuswb mm3,mm2
  1057. movq [ecx], mm3
  1058. sub eax, 8 // Update the number of points left 
  1059. add ecx, 8 // Update output pointer 
  1060. jmp row_sum_loop // Loop 
  1061. //Cleanup 
  1062. end_sum_loop:
  1063. emms 
  1064. }
  1065. }
  1066. inline void avg_Col_7(ushort* im, uchar* im_out, int dataSize, int width)
  1067. {
  1068. __asm {
  1069. mov edi, width
  1070. shl edi, 1  // edi = 2*width
  1071. mov eax, dataSize
  1072. mov ecx, im_out
  1073. mov ebx, im
  1074. sub ebx, edi
  1075. sub ebx, edi
  1076. sub ebx, edi // ebx = ebx-6*width
  1077. test eax, eax // Is there anything to do?" 
  1078. jz end_sum_loop // Jump out if necessary 
  1079. row_sum_loop:
  1080. test eax, eax // Is there anything to do? 
  1081. jz end_sum_loop // Jump out if necessary 
  1082. mov edx, ebx
  1083. // 1
  1084. movq mm3, [edx] // mm3 = 4 words of im
  1085. add ebx, 16
  1086. movq mm2, [edx+8] // mm2 = next 4 words of im
  1087. add edx, edi
  1088. macro_add
  1089. macro_add
  1090. macro_add
  1091. macro_add
  1092. macro_add
  1093. macro_add
  1094. // divide results by ...
  1095. psrlw mm3, 3
  1096. psrlw mm2, 3
  1097. // convert [mm2 mm3] as 8 bytes
  1098. packuswb mm3,mm2
  1099. movq [ecx], mm3
  1100. sub eax, 8 // Update the number of points left 
  1101. add ecx, 8 // Update output pointer 
  1102. jmp row_sum_loop // Loop 
  1103. //Cleanup 
  1104. end_sum_loop:
  1105. emms 
  1106. }
  1107. }
  1108. inline void avg_Col_9(ushort* im, uchar* im_out, int dataSize, int width)
  1109. {
  1110. __asm {
  1111. mov edi, width
  1112. shl edi, 1  // edi = 2*width
  1113. mov eax, dataSize
  1114. mov ecx, im_out
  1115. mov ebx, im
  1116. sub ebx, edi
  1117. sub ebx, edi
  1118. sub ebx, edi
  1119. sub ebx, edi // ebx = ebx-8*width
  1120. test eax, eax // Is there anything to do?" 
  1121. jz end_sum_loop // Jump out if necessary 
  1122. row_sum_loop:
  1123. test eax, eax // Is there anything to do? 
  1124. jz end_sum_loop // Jump out if necessary 
  1125. mov edx, ebx
  1126. add ebx, 16
  1127. // 1
  1128. movq mm3, [edx] // mm3 = 4 words of im
  1129. movq mm2, [edx+8] // mm2 = next 4 words of im
  1130. add edx, edi
  1131. macro_add
  1132. macro_add
  1133. macro_add
  1134. macro_add
  1135. macro_add
  1136. macro_add
  1137. macro_add
  1138. macro_add
  1139. // divide results by ...
  1140. psrlw mm3, 3
  1141. psrlw mm2, 3
  1142. // convert [mm2 mm3] as 8 bytes
  1143. packuswb mm3,mm2
  1144. movq [ecx], mm3
  1145. sub eax, 8 // Update the number of points left 
  1146. add ecx, 8 // Update output pointer 
  1147. jmp row_sum_loop // Loop 
  1148. //Cleanup 
  1149. end_sum_loop:
  1150. emms 
  1151. }
  1152. }
  1153. inline void avg_Col_11(ushort* im, uchar* im_out, int dataSize, int width)
  1154. {
  1155. __asm {
  1156. mov edi, width
  1157. shl edi, 1  // edi = 2*width
  1158. mov eax, dataSize
  1159. mov ecx, im_out
  1160. mov ebx, im
  1161. sub ebx, edi
  1162. sub ebx, edi
  1163. sub ebx, edi
  1164. sub ebx, edi 
  1165. sub ebx, edi // ebx = ebx-10*width
  1166. test eax, eax // Is there anything to do?" 
  1167. jz end_sum_loop // Jump out if necessary 
  1168. row_sum_loop:
  1169. test eax, eax // Is there anything to do? 
  1170. jz end_sum_loop // Jump out if necessary 
  1171. mov edx, ebx
  1172. add ebx, 16
  1173. // 1
  1174. movq mm3, [edx] // mm3 = 4 words of im
  1175. movq mm2, [edx+8] // mm2 = next 4 words of im
  1176. add edx, edi
  1177. macro_add
  1178. macro_add
  1179. macro_add
  1180. macro_add
  1181. macro_add
  1182. macro_add
  1183. macro_add
  1184. macro_add
  1185. macro_add
  1186. macro_add
  1187. // divide results by ...
  1188. psrlw mm3, 4
  1189. psrlw mm2, 4
  1190. // convert [mm2 mm3] as 8 bytes
  1191. packuswb mm3,mm2
  1192. movq [ecx], mm3
  1193. sub eax, 8 // Update the number of points left 
  1194. add ecx, 8 // Update output pointer 
  1195. jmp row_sum_loop // Loop 
  1196. //Cleanup 
  1197. end_sum_loop:
  1198. emms 
  1199. }
  1200. }
  1201. inline void avg_Col_13(ushort* im, uchar* im_out, int dataSize, int width)
  1202. {
  1203. __asm {
  1204. mov edi, width
  1205. shl edi, 1  // edi = 2*width
  1206. mov eax, dataSize
  1207. mov ecx, im_out
  1208. mov ebx, im
  1209. sub ebx, edi
  1210. sub ebx, edi
  1211. sub ebx, edi
  1212. sub ebx, edi 
  1213. sub ebx, edi
  1214. sub ebx, edi // ebx = ebx-12*width
  1215. test eax, eax // Is there anything to do?" 
  1216. jz end_sum_loop // Jump out if necessary 
  1217. row_sum_loop:
  1218. test eax, eax // Is there anything to do? 
  1219. jz end_sum_loop // Jump out if necessary 
  1220. mov edx, ebx
  1221. add ebx, 16
  1222. // 1
  1223. movq mm3, [edx] // mm3 = 4 words of im
  1224. movq mm2, [edx+8] // mm2 = next 4 words of im
  1225. add edx, edi
  1226. macro_add
  1227. macro_add
  1228. macro_add
  1229. macro_add
  1230. macro_add
  1231. macro_add
  1232. macro_add
  1233. macro_add
  1234. macro_add
  1235. macro_add
  1236. macro_add
  1237. macro_add
  1238. // divide results by ...
  1239. psrlw mm3, 4
  1240. psrlw mm2, 4
  1241. // convert [mm2 mm3] as 8 bytes
  1242. packuswb mm3,mm2
  1243. movq [ecx], mm3
  1244. sub eax, 8 // Update the number of points left 
  1245. add ecx, 8 // Update output pointer 
  1246. jmp row_sum_loop // Loop 
  1247. //Cleanup 
  1248. end_sum_loop:
  1249. emms 
  1250. }
  1251. }
  1252. inline void avg_Col_15(ushort* im, uchar* im_out, int dataSize, int width)
  1253. {
  1254. __asm {
  1255. mov edi, width
  1256. shl edi, 1  // edi = 2*width
  1257. mov eax, dataSize
  1258. mov ecx, im_out
  1259. mov ebx, im
  1260. sub ebx, edi
  1261. sub ebx, edi
  1262. sub ebx, edi
  1263. sub ebx, edi
  1264. sub ebx, edi 
  1265. sub ebx, edi
  1266. sub ebx, edi // ebx = ebx-14*width
  1267. test eax, eax // Is there anything to do?" 
  1268. jz end_sum_loop // Jump out if necessary 
  1269. row_sum_loop:
  1270. test eax, eax // Is there anything to do? 
  1271. jz end_sum_loop // Jump out if necessary 
  1272. mov edx, ebx
  1273. add ebx, 16
  1274. // 1
  1275. movq mm3, [edx] // mm3 = 4 words of im
  1276. movq mm2, [edx+8] // mm2 = next 4 words of im
  1277. add edx, edi
  1278. macro_add
  1279. macro_add
  1280. macro_add
  1281. macro_add
  1282. macro_add
  1283. macro_add
  1284. macro_add
  1285. macro_add
  1286. macro_add
  1287. macro_add
  1288. macro_add
  1289. macro_add
  1290. macro_add
  1291. macro_add
  1292. // divide results by ...
  1293. psrlw mm3, 4
  1294. psrlw mm2, 4
  1295. // convert [mm2 mm3] as 8 bytes
  1296. packuswb mm3,mm2
  1297. movq [ecx], mm3
  1298. sub eax, 8 // Update the number of points left 
  1299. add ecx, 8 // Update output pointer 
  1300. jmp row_sum_loop // Loop 
  1301. //Cleanup 
  1302. end_sum_loop:
  1303. emms 
  1304. }
  1305. }
  1306. inline void avg_Col_17(ushort* im, uchar* im_out, int dataSize, int width)
  1307. {
  1308. __asm {
  1309. mov edi, width
  1310. shl edi, 1  // edi = 2*width
  1311. mov eax, dataSize
  1312. mov ecx, im_out
  1313. mov ebx, im
  1314. sub ebx, edi
  1315. sub ebx, edi
  1316. sub ebx, edi
  1317. sub ebx, edi
  1318. sub ebx, edi
  1319. sub ebx, edi 
  1320. sub ebx, edi
  1321. sub ebx, edi // ebx = ebx-16*width
  1322. test eax, eax // Is there anything to do?" 
  1323. jz end_sum_loop // Jump out if necessary 
  1324. row_sum_loop:
  1325. test eax, eax // Is there anything to do? 
  1326. jz end_sum_loop // Jump out if necessary 
  1327. mov edx, ebx
  1328. add ebx, 16
  1329. // 1
  1330. movq mm3, [edx] // mm3 = 4 words of im
  1331. movq mm2, [edx+8] // mm2 = next 4 words of im
  1332. add edx, edi
  1333. macro_add
  1334. macro_add
  1335. macro_add
  1336. macro_add
  1337. macro_add
  1338. macro_add
  1339. macro_add
  1340. macro_add
  1341. macro_add
  1342. macro_add
  1343. macro_add
  1344. macro_add
  1345. macro_add
  1346. macro_add
  1347. macro_add
  1348. macro_add
  1349. // divide results by ...
  1350. psrlw mm3, 4
  1351. psrlw mm2, 4
  1352. // convert [mm2 mm3] as 8 bytes
  1353. packuswb mm3,mm2
  1354. movq [ecx], mm3
  1355. sub eax, 8 // Update the number of points left 
  1356. add ecx, 8 // Update output pointer 
  1357. jmp row_sum_loop // Loop 
  1358. //Cleanup 
  1359. end_sum_loop:
  1360. emms 
  1361. }
  1362. }
  1363. inline void add_Col_5_wb(ushort* im, uchar* im_out, int dataSize, int width)
  1364. {
  1365. __asm {
  1366. mov edi, width
  1367. shl edi, 1  // edi = 2*width
  1368. mov eax, dataSize
  1369. mov ecx, im_out
  1370. mov ebx, im
  1371. sub ebx, edi
  1372. sub ebx, edi // ebx = ebx-4*width
  1373. test eax, eax // Is there anything to do?" 
  1374. jz end_sum_loop // Jump out if necessary 
  1375. row_sum_loop:
  1376. test eax, eax // Is there anything to do? 
  1377. jz end_sum_loop // Jump out if necessary 
  1378. mov edx, ebx
  1379. add ebx, 16
  1380. // 1
  1381. movq mm3, [edx] // mm3 = 4 words of im
  1382. movq mm2, [edx+8] // mm2 = next 4 words of im
  1383. add edx, edi
  1384. macro_add
  1385. macro_add
  1386. macro_add
  1387. macro_add
  1388. // save [mm2 mm3] as 8 bytes
  1389. packuswb mm3,mm2
  1390. movq [ecx], mm3
  1391. sub eax, 8 // Update the number of points left 
  1392. add ecx, 8 // Update output pointer 
  1393. jmp row_sum_loop // Loop 
  1394. //Cleanup 
  1395. end_sum_loop:
  1396. emms 
  1397. }
  1398. }
  1399. inline void add_Col_5_ww(ushort* im, ushort* im_out, int dataSize, int width)
  1400. {
  1401. __asm {
  1402. mov edi, width
  1403. shl edi, 1  // edi = 2*width
  1404. mov eax, dataSize
  1405. mov ecx, im_out
  1406. mov ebx, im
  1407. sub ebx, edi
  1408. sub ebx, edi // ebx = ebx-4*width
  1409. test eax, eax // Is there anything to do?" 
  1410. jz end_sum_loop // Jump out if necessary 
  1411. row_sum_loop:
  1412. test eax, eax // Is there anything to do? 
  1413. jz end_sum_loop // Jump out if necessary 
  1414. mov edx, ebx
  1415. add ebx, 16
  1416. // 1
  1417. movq mm3, [edx] // mm3 = 4 words of im
  1418. movq mm2, [edx+8] // mm2 = next 4 words of im
  1419. add edx, edi
  1420. macro_add
  1421. macro_add
  1422. macro_add
  1423. macro_add
  1424. // save [mm2 mm3] as words
  1425. movq [ecx], mm3
  1426. movq [ecx+8], mm2
  1427. sub eax, 8 // Update the number of points left 
  1428. add ecx, 16 // Update output pointer 
  1429. jmp row_sum_loop // Loop 
  1430. //Cleanup 
  1431. end_sum_loop:
  1432. emms 
  1433. }
  1434. }
  1435. // compare bestScores and secondScores. if second<best+'thresh' the disp.
  1436. // is set to 'valForReplacement' (usually 0)
  1437. inline void compareBestAndSecond(uchar* bestScores, uchar* secondScores, char thresh, 
  1438.   uchar undefined_val, 
  1439.   uchar* disp, int dataSize)
  1440. {
  1441. __asm {
  1442. // setup mm0 with 8 copies of 'thresh'
  1443. mov al,  thresh
  1444. mov ah,  al
  1445. mov bx,  ax
  1446. shl eax,  16
  1447. mov ax,  bx
  1448. movd mm0,  eax
  1449. movd mm1,  eax
  1450. punpckldq mm0,  mm1
  1451. // setup mm7 with 8 copies of 'valForReplacement'
  1452. mov al,  undefined_val
  1453. mov ah,  al
  1454. mov bx,  ax
  1455. shl eax,  16
  1456. mov ax,  bx
  1457. movd mm7,  eax
  1458. movd mm1,  eax
  1459. punpckldq mm7,  mm1
  1460. mov eax, dataSize
  1461. mov ebx, bestScores
  1462. mov ecx, secondScores
  1463. mov edx, disp
  1464. test eax, eax // Is there anything to do?" 
  1465. jz end_loop // Jump out if necessary 
  1466. comp_loop:
  1467. test eax, eax // Is there anything to do? 
  1468. jz end_loop // Jump out if necessary 
  1469. movq mm2, [ecx]
  1470. psubusb mm2, [ebx] // mm2 = secondScores - bestScores
  1471. movq mm3, [edx] // mm3 = disp
  1472. pcmpgtb mm2, mm0 // mm2 = 1 if mm2>thresh
  1473. //  0 otherwise
  1474. pand mm3, mm2
  1475. pandn mm2, mm7
  1476. por mm3, mm2
  1477. movq [edx], mm3
  1478. sub eax, 8 // Update the number of points left 
  1479. add ebx, 8 // Update output pointer 
  1480. add ecx, 8 
  1481. add edx, 8
  1482. jmp comp_loop // Loop 
  1483. //Cleanup 
  1484. end_loop:
  1485. emms 
  1486. }
  1487. }
  1488. // windowWidth must be multiple of 8
  1489. inline void cropImage(const uchar* imSrc, int width, int height, 
  1490.    uchar* imDest, int x0, int y0, int windowWidth, int windowHeight)
  1491. {
  1492. int w8 = windowWidth/8;
  1493. int step = width-windowWidth;
  1494. const uchar* srcNewOrigin = imSrc+x0+y0*width;
  1495. __asm {
  1496. mov ecx, windowHeight
  1497. mov edx, w8
  1498. mov eax,  srcNewOrigin
  1499. mov ebx,  imDest
  1500. pixel_loop:
  1501. movq mm1, [eax]
  1502. movq [ebx], mm1
  1503. add eax, 8
  1504. add ebx, 8
  1505. dec edx
  1506. jnz pixel_loop
  1507. mov edx, w8
  1508. add eax, step
  1509. dec ecx
  1510. jnz pixel_loop
  1511. jmp done
  1512. done:
  1513. emms;
  1514. }
  1515. }
  1516. // return the average pixel value
  1517. inline float pixelMean(const uchar* im, int imageSize)
  1518. {
  1519. int sum;
  1520. __asm {
  1521. mov ecx, imageSize
  1522. shr ecx, 3
  1523. mov eax, im
  1524. pxor mm7,mm7 // mm7 used as accumulator
  1525. pxor mm0,mm0 // mm0 = 0
  1526. pixel_loop:
  1527. movq mm1, [eax]
  1528. movq mm2,mm1
  1529. punpcklbw mm2, mm0
  1530. punpckhbw mm1, mm0
  1531. paddw mm2,mm1
  1532. movq mm1,mm2
  1533. punpcklwd mm2, mm0
  1534. punpckhwd mm1, mm0
  1535. paddd mm2,mm1
  1536. paddd mm7,mm2
  1537. add eax, 8
  1538. dec ecx
  1539. jnz pixel_loop
  1540. jmp done
  1541. done:
  1542. movd ebx, mm7
  1543. psrlq mm7, 32
  1544. movd edx, mm7
  1545. add ebx, edx
  1546. mov sum, ebx
  1547. emms
  1548. }
  1549. return sum / (float)imageSize;
  1550. }
  1551. // -------------------------------------------------------------
  1552. // apply mask:
  1553. // if mask[]=undefined_val im[]->im[]
  1554. // otherwise, im[]->mask[]
  1555. // ....... this one may not be exact :-(
  1556. inline void overrideImageMMX(uchar* im, const uchar* mask, uchar undefined_val, int imageSize)
  1557. {
  1558. __asm {
  1559. // setup mm0 with 8 copies of 'undefined_val'
  1560. mov al,  undefined_val
  1561. mov ah,  al
  1562. mov bx,  ax
  1563. shl eax,  16
  1564. mov ax,  bx
  1565. movd mm0,  eax
  1566. movd mm1,  eax
  1567. punpckldq mm0,  mm1
  1568. mov ecx, imageSize
  1569. shr ecx, 3
  1570. mov eax, im
  1571. mov ebx, mask
  1572. pixel_loop:
  1573. movq mm1, [eax]
  1574. movq mm2, [ebx]
  1575. movq mm3, mm2
  1576. pcmpeqb mm3, mm0 // mm3[] -> xFF if mm2[]==undefined_val
  1577. // -> x00 otherwise
  1578. pand mm3, mm1 // mm3[] = mm1[] if mm2[]==undefined_val
  1579. //  = x00   otherwise
  1580. por mm3, mm2
  1581. movq [eax], mm3
  1582. add eax, 8
  1583. add ebx, 8
  1584. dec ecx
  1585. jnz pixel_loop
  1586. jmp done
  1587. done:
  1588. emms
  1589. }
  1590. }
  1591. inline void overrideImage(uchar* im, const uchar* mask, uchar undefined_val, int imageSize)
  1592. {
  1593. for (int i=0; i<imageSize; ++i, ++im,++mask)
  1594. {
  1595. if (*mask != undefined_val) *im=*mask;
  1596. }
  1597. }
  1598. inline void divide( ushort* im,  uchar* div, uchar* result, int imageSize)
  1599. {
  1600. for (int i=0; i<imageSize; ++i,++im,++div,++result)
  1601. {
  1602. *result = (*div)?(uchar)(*im / *div):0;
  1603. }
  1604. }
  1605. // 5x5 sum filters
  1606. inline void sum_5x5_mmx( uchar* im, ushort* im_out, int dataSize, int width, ushort* buff)
  1607. {
  1608. sum_Row_5_mmx(im, buff, dataSize);
  1609. add_Col_5_ww(buff+2*width, im_out+2*width, dataSize-4*width , width);
  1610. }
  1611. inline void sum_5x5_mmx( uchar* im, uchar* im_out, int dataSize, int width, ushort* buff)
  1612. {
  1613. sum_Row_5_mmx(im, buff, dataSize);
  1614. add_Col_5_wb(buff+2*width, im_out+2*width, dataSize-4*width , width);
  1615. }
  1616. inline void binarize(uchar* im, uchar* im_out, uchar undefined_val, int dataSize)
  1617. {
  1618. for (int i=0; i<dataSize; ++i,++im,++im_out)
  1619. {
  1620. *im_out = (*im != undefined_val);
  1621. }
  1622. }
  1623. inline void set_undefined_to_zero(uchar* im, uchar* im_out, uchar undefined_val, int dataSize)
  1624. {
  1625. for (int i=0; i<dataSize; ++i,++im,++im_out)
  1626. {
  1627. if (*im == undefined_val) *im_out=0;
  1628. }
  1629. }
  1630. inline void set_zero_to_undefined(uchar* im, uchar* im_out, uchar undefined_val, int dataSize)
  1631. {
  1632. for (int i=0; i<dataSize; ++i,++im,++im_out)
  1633. {
  1634. if (*im == 0) *im_out=undefined_val;
  1635. }
  1636. }
  1637. inline void copyMMX(void* imDest, const void* imSrc, int dataSize)
  1638. {
  1639. __asm {
  1640. mov ecx, dataSize
  1641. shr ecx, 3
  1642. mov eax, imSrc
  1643. mov ebx, imDest
  1644. sub ebx, 8
  1645. pixel_loop:
  1646. movq mm1, [eax]
  1647. add ebx, 8
  1648. movq [ebx], mm1
  1649. add eax, 8
  1650. dec ecx
  1651. jnz pixel_loop
  1652. jmp done
  1653. done:
  1654. emms
  1655. }
  1656. }
  1657. inline void copySSE(void* imDest, const void* imSrc, int dataSize)
  1658. {
  1659. __asm {
  1660. mov ecx, dataSize
  1661. shr ecx, 4
  1662. mov eax, imSrc
  1663. mov ebx, imDest
  1664. sub ebx, 16
  1665. pixel_loop:
  1666. movdqa xmm1, [eax]
  1667. add ebx, 16
  1668. movdqa [ebx], xmm1
  1669. add eax, 16
  1670. dec ecx
  1671. jnz pixel_loop
  1672. jmp done
  1673. done:
  1674. emms
  1675. }
  1676. }
  1677. inline void setMMX(float* imDest, const float value, int dataSize)
  1678. {
  1679. __asm {
  1680. // make 4 copies of the constant 'value' in xmm0
  1681. movss xmm0, value
  1682. movss xmm1, xmm0
  1683. unpcklps xmm0, xmm1        
  1684. movlhps xmm0, xmm0
  1685. mov ecx, dataSize
  1686. shr ecx, 2
  1687. mov ebx, imDest
  1688. pixel_loop:
  1689. movaps [ebx], xmm0
  1690. add ebx, 16
  1691. dec ecx
  1692. jnz pixel_loop
  1693. jmp done
  1694. done:
  1695. emms
  1696. }
  1697. }
  1698. inline void setMMX(char* imDest, const char value, int dataSize)
  1699. {
  1700. __asm {
  1701. // setup mm0 with 8 copies of 'value'
  1702. mov al,  value
  1703. mov ah,  al
  1704. mov bx,  ax
  1705. shl eax,  16
  1706. mov ax,  bx
  1707. movd mm0,  eax
  1708. movd mm1,  eax
  1709. punpckldq mm0,  mm1
  1710. mov ecx, dataSize
  1711. shr ecx, 3
  1712. mov ebx, imDest
  1713. pixel_loop:
  1714. movq [ebx], mm0
  1715. add ebx, 8
  1716. dec ecx
  1717. jnz pixel_loop
  1718. jmp done
  1719. done:
  1720. emms
  1721. }
  1722. }
  1723. /*
  1724. void copyRGBAtoRGB(const uchar* imSrc, uchar* imred,uchar* imgreen,uchar* imblue, int dataSize)
  1725. {
  1726. __asm {
  1727. mov esi, dataSize
  1728. shr esi, 3
  1729. mov eax, imSrc
  1730. mov ebx, imred
  1731. mov ecx, imred
  1732. mov edx, imred
  1733. pixel_loop:
  1734. movq mm1, [eax]
  1735. movq [ebx], mm1
  1736. add eax, 8
  1737. add ebx, 8
  1738. add ecx, 8
  1739. add edx, 8
  1740. dec esi
  1741. jnz pixel_loop
  1742. jmp done
  1743. done:
  1744. emms
  1745. }
  1746. }*/
  1747. inline void multiply(uchar* im, float fact, int imageSize)
  1748. {
  1749. __asm {
  1750. mov ecx, imageSize
  1751. shr ecx, 3
  1752. // make 4 copies of the constant 'fact' in xmm0
  1753. movss xmm0, fact
  1754. movss xmm1, xmm0
  1755. unpcklps xmm0, xmm1        
  1756. movlhps xmm0, xmm0
  1757. mov eax, im
  1758. pxor mm7,mm7 // mm7 = 0 
  1759. pixel_loop:
  1760. movq mm1, [eax]
  1761. movq mm2, mm1
  1762. punpcklbw mm2, mm0
  1763. punpckhbw mm1, mm0
  1764. movq mm3,mm2
  1765. punpckhwd mm3, mm0
  1766. punpcklwd mm2, mm0
  1767. movq mm4,mm1
  1768. punpcklwd mm4, mm0
  1769. punpckhwd mm1, mm0
  1770. // here, the first 8 bytes are in d-words [mm1 mm4 mm3 mm2]
  1771. // --------
  1772. cvtpi2ps xmm3, mm3 // put mm3 in low part of xmm3
  1773. cvtpi2ps xmm2, mm2 // put mm2 in low part of xmm2
  1774. movlhps xmm2, xmm3 // xmm2 = [xmm3(low part) xmm2(low part)]
  1775. mulps xmm2, xmm0
  1776. cvtps2pi mm2, xmm2 // convert low 2 floats from xmm2 to mm2
  1777. movhlps xmm3,xmm2 // mov high 2 floats from xmm2 to low 2 floats in xmm3
  1778. cvtps2pi mm3, xmm3 // convert low 2 floats from xmm3 to mm3
  1779. packssdw mm2, mm3 // mm2 = (word)[mm2 mm3]
  1780. // --------
  1781. cvtpi2ps xmm4, mm4
  1782. cvtpi2ps xmm1, mm1
  1783. movlhps xmm4, xmm1
  1784. mulps xmm4, xmm0
  1785. cvtps2pi mm4, xmm4 // convert low 2 floats from xmm4 to mm4
  1786. movhlps xmm1,xmm4 // mov high 2 floats from xmm4 to low 2 floats in xmm1
  1787. cvtps2pi mm1, xmm1 // convert low 2 floats from xmm1 to mm1
  1788. packssdw mm4, mm1 // mm4 = (word)[mm1 mm4]
  1789. // ------
  1790. packuswb mm2, mm4 // mm2 = [[mm4] [mm2]] = [mm1 mm4 mm2 mm3]
  1791. movq [eax], mm2
  1792. add eax, 8
  1793. dec ecx
  1794. jnz pixel_loop
  1795. jmp done
  1796. done:
  1797. emms
  1798. }
  1799. }
  1800. inline void multiply(const uchar* imSrc, uchar* imDest, float fact, int imageSize)
  1801. {
  1802. __asm {
  1803. mov ecx, imageSize
  1804. shr ecx, 3
  1805. // make 4 copies of the constant 'fact' in xmm0
  1806. movss xmm0, fact
  1807. movss xmm1, xmm0
  1808. unpcklps xmm0, xmm1        
  1809. movlhps xmm0, xmm0
  1810. mov eax, imSrc
  1811. mov ebx, imDest
  1812. pxor mm7,mm7 // mm7 = 0 
  1813. pixel_loop:
  1814. movq mm1, [eax]
  1815. movq mm2, mm1
  1816. punpcklbw mm2, mm0
  1817. punpckhbw mm1, mm0
  1818. movq mm3,mm2
  1819. punpckhwd mm3, mm0
  1820. punpcklwd mm2, mm0
  1821. movq mm4,mm1
  1822. punpcklwd mm4, mm0
  1823. punpckhwd mm1, mm0
  1824. // here, the first 8 bytes are in d-words [mm1 mm4 mm3 mm2]
  1825. // --------
  1826. cvtpi2ps xmm3, mm3 // put mm3 in low part of xmm3
  1827. cvtpi2ps xmm2, mm2 // put mm2 in low part of xmm2
  1828. movlhps xmm2, xmm3 // xmm2 = [xmm3(low part) xmm2(low part)]
  1829. mulps xmm2, xmm0
  1830. cvtps2pi mm2, xmm2 // convert low 2 floats from xmm2 to mm2
  1831. movhlps xmm3,xmm2 // mov high 2 floats from xmm2 to low 2 floats in xmm3
  1832. cvtps2pi mm3, xmm3 // convert low 2 floats from xmm3 to mm3
  1833. packssdw mm2, mm3 // mm2 = (word)[mm2 mm3]
  1834. // --------
  1835. cvtpi2ps xmm4, mm4
  1836. cvtpi2ps xmm1, mm1
  1837. movlhps xmm4, xmm1
  1838. mulps xmm4, xmm0
  1839. cvtps2pi mm4, xmm4 // convert low 2 floats from xmm4 to mm4
  1840. movhlps xmm1,xmm4 // mov high 2 floats from xmm4 to low 2 floats in xmm1
  1841. cvtps2pi mm1, xmm1 // convert low 2 floats from xmm1 to mm1
  1842. packssdw mm4, mm1 // mm4 = (word)[mm1 mm4]
  1843. // ------
  1844. packuswb mm2, mm4 // mm2 = [[mm4] [mm2]] = [mm1 mm4 mm2 mm3]
  1845. movq [ebx], mm2
  1846. add eax, 8
  1847. add ebx, 8
  1848. dec ecx
  1849. jnz pixel_loop
  1850. jmp done
  1851. done:
  1852. emms
  1853. }
  1854. }