rgb2rgb_template.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:66k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*
  2.  *
  3.  *  rgb2rgb.c, Software RGB to RGB convertor
  4.  *  pluralize by Software PAL8 to RGB convertor
  5.  *               Software YUV to YUV convertor
  6.  *               Software YUV to RGB convertor
  7.  *  Written by Nick Kurshev.
  8.  *  palette & yuv & runtime cpu stuff by Michael (michaelni@gmx.at) (under GPL)
  9.  */
  10. #include <stddef.h>
  11. #include <inttypes.h> /* for __WORDSIZE */
  12. #ifndef __WORDSIZE
  13. // #warning You have misconfigured system and probably will lose performance!
  14. #define __WORDSIZE MP_WORDSIZE
  15. #endif
  16. #undef PREFETCH
  17. #undef MOVNTQ
  18. #undef EMMS
  19. #undef SFENCE
  20. #undef MMREG_SIZE
  21. #undef PREFETCHW
  22. #undef PAVGB
  23. #ifdef HAVE_SSE2
  24. #define MMREG_SIZE 16
  25. #else
  26. #define MMREG_SIZE 8
  27. #endif
  28. #ifdef HAVE_3DNOW
  29. #define PREFETCH  "prefetch"
  30. #define PREFETCHW "prefetchw"
  31. #define PAVGB   "pavgusb"
  32. #elif defined ( HAVE_MMX2 )
  33. #define PREFETCH "prefetchnta"
  34. #define PREFETCHW "prefetcht0"
  35. #define PAVGB   "pavgb"
  36. #else
  37. #define PREFETCH "/nop"
  38. #define PREFETCHW "/nop"
  39. #endif
  40. #ifdef HAVE_3DNOW
  41. /* On K6 femms is faster of emms. On K7 femms is directly mapped on emms. */
  42. #define EMMS     "femms"
  43. #else
  44. #define EMMS     "emms"
  45. #endif
  46. #ifdef HAVE_MMX2
  47. #define MOVNTQ "movntq"
  48. #define SFENCE "sfence"
  49. #else
  50. #define MOVNTQ "movq"
  51. #define SFENCE "/nop"
  52. #endif
  53. static inline void RENAME(rgb24to32)(const uint8_t *src,uint8_t *dst,unsigned src_size)
  54. {
  55.   uint8_t *dest = dst;
  56.   const uint8_t *s = src;
  57.   const uint8_t *end;
  58. #ifdef HAVE_MMX
  59.   const uint8_t *mm_end;
  60. #endif
  61.   end = s + src_size;
  62. #ifdef HAVE_MMX
  63.   __asm __volatile(PREFETCH" %0"::"m"(*s):"memory");
  64.   mm_end = end - 23;
  65.   __asm __volatile("movq %0, %%mm7"::"m"(mask32):"memory");
  66.   while(s < mm_end)
  67.   {
  68.     __asm __volatile(
  69. PREFETCH" 32%1nt"
  70. "movd %1, %%mm0nt"
  71. "punpckldq 3%1, %%mm0nt"
  72. "movd 6%1, %%mm1nt"
  73. "punpckldq 9%1, %%mm1nt"
  74. "movd 12%1, %%mm2nt"
  75. "punpckldq 15%1, %%mm2nt"
  76. "movd 18%1, %%mm3nt"
  77. "punpckldq 21%1, %%mm3nt"
  78. "pand %%mm7, %%mm0nt"
  79. "pand %%mm7, %%mm1nt"
  80. "pand %%mm7, %%mm2nt"
  81. "pand %%mm7, %%mm3nt"
  82. MOVNTQ" %%mm0, %0nt"
  83. MOVNTQ" %%mm1, 8%0nt"
  84. MOVNTQ" %%mm2, 16%0nt"
  85. MOVNTQ" %%mm3, 24%0"
  86. :"=m"(*dest)
  87. :"m"(*s)
  88. :"memory");
  89.     dest += 32;
  90.     s += 24;
  91.   }
  92.   __asm __volatile(SFENCE:::"memory");
  93.   __asm __volatile(EMMS:::"memory");
  94. #endif
  95.   while(s < end)
  96.   {
  97.     *dest++ = *s++;
  98.     *dest++ = *s++;
  99.     *dest++ = *s++;
  100.     *dest++ = 0;
  101.   }
  102. }
  103. static inline void RENAME(rgb32to24)(const uint8_t *src,uint8_t *dst,unsigned src_size)
  104. {
  105.   uint8_t *dest = dst;
  106.   const uint8_t *s = src;
  107.   const uint8_t *end;
  108. #ifdef HAVE_MMX
  109.   const uint8_t *mm_end;
  110. #endif
  111.   end = s + src_size;
  112. #ifdef HAVE_MMX
  113.   __asm __volatile(PREFETCH" %0"::"m"(*s):"memory");
  114.   mm_end = end - 31;
  115.   while(s < mm_end)
  116.   {
  117.     __asm __volatile(
  118. PREFETCH" 32%1nt"
  119. "movq %1, %%mm0nt"
  120. "movq 8%1, %%mm1nt"
  121. "movq 16%1, %%mm4nt"
  122. "movq 24%1, %%mm5nt"
  123. "movq %%mm0, %%mm2nt"
  124. "movq %%mm1, %%mm3nt"
  125. "movq %%mm4, %%mm6nt"
  126. "movq %%mm5, %%mm7nt"
  127. "psrlq $8, %%mm2nt"
  128. "psrlq $8, %%mm3nt"
  129. "psrlq $8, %%mm6nt"
  130. "psrlq $8, %%mm7nt"
  131. "pand %2, %%mm0nt"
  132. "pand %2, %%mm1nt"
  133. "pand %2, %%mm4nt"
  134. "pand %2, %%mm5nt"
  135. "pand %3, %%mm2nt"
  136. "pand %3, %%mm3nt"
  137. "pand %3, %%mm6nt"
  138. "pand %3, %%mm7nt"
  139. "por %%mm2, %%mm0nt"
  140. "por %%mm3, %%mm1nt"
  141. "por %%mm6, %%mm4nt"
  142. "por %%mm7, %%mm5nt"
  143. "movq %%mm1, %%mm2nt"
  144. "movq %%mm4, %%mm3nt"
  145. "psllq $48, %%mm2nt"
  146. "psllq $32, %%mm3nt"
  147. "pand %4, %%mm2nt"
  148. "pand %5, %%mm3nt"
  149. "por %%mm2, %%mm0nt"
  150. "psrlq $16, %%mm1nt"
  151. "psrlq $32, %%mm4nt"
  152. "psllq $16, %%mm5nt"
  153. "por %%mm3, %%mm1nt"
  154. "pand %6, %%mm5nt"
  155. "por %%mm5, %%mm4nt"
  156. MOVNTQ" %%mm0, %0nt"
  157. MOVNTQ" %%mm1, 8%0nt"
  158. MOVNTQ" %%mm4, 16%0"
  159. :"=m"(*dest)
  160. :"m"(*s),"m"(mask24l),
  161.  "m"(mask24h),"m"(mask24hh),"m"(mask24hhh),"m"(mask24hhhh)
  162. :"memory");
  163.     dest += 24;
  164.     s += 32;
  165.   }
  166.   __asm __volatile(SFENCE:::"memory");
  167.   __asm __volatile(EMMS:::"memory");
  168. #endif
  169.   while(s < end)
  170.   {
  171.     *dest++ = *s++;
  172.     *dest++ = *s++;
  173.     *dest++ = *s++;
  174.     s++;
  175.   }
  176. }
  177. /*
  178.  Original by Strepto/Astral
  179.  ported to gcc & bugfixed : A'rpi
  180.  MMX2, 3DNOW optimization by Nick Kurshev
  181.  32bit c version, and and&add trick by Michael Niedermayer
  182. */
  183. static inline void RENAME(rgb15to16)(const uint8_t *src,uint8_t *dst,unsigned src_size)
  184. {
  185.   register const uint8_t* s=src;
  186.   register uint8_t* d=dst;
  187.   register const uint8_t *end;
  188.   const uint8_t *mm_end;
  189.   end = s + src_size;
  190. #ifdef HAVE_MMX
  191.   __asm __volatile(PREFETCH" %0"::"m"(*s));
  192.   __asm __volatile("movq %0, %%mm4"::"m"(mask15s));
  193.   mm_end = end - 15;
  194.   while(s<mm_end)
  195.   {
  196. __asm __volatile(
  197. PREFETCH" 32%1nt"
  198. "movq %1, %%mm0nt"
  199. "movq 8%1, %%mm2nt"
  200. "movq %%mm0, %%mm1nt"
  201. "movq %%mm2, %%mm3nt"
  202. "pand %%mm4, %%mm0nt"
  203. "pand %%mm4, %%mm2nt"
  204. "paddw %%mm1, %%mm0nt"
  205. "paddw %%mm3, %%mm2nt"
  206. MOVNTQ" %%mm0, %0nt"
  207. MOVNTQ" %%mm2, 8%0"
  208. :"=m"(*d)
  209. :"m"(*s)
  210. );
  211. d+=16;
  212. s+=16;
  213.   }
  214.   __asm __volatile(SFENCE:::"memory");
  215.   __asm __volatile(EMMS:::"memory");
  216. #endif
  217.     mm_end = end - 3;
  218.     while(s < mm_end)
  219.     {
  220. register unsigned x= *((uint32_t *)s);
  221. *((uint32_t *)d) = (x&0x7FFF7FFF) + (x&0x7FE07FE0);
  222. d+=4;
  223. s+=4;
  224.     }
  225.     if(s < end)
  226.     {
  227. register unsigned short x= *((uint16_t *)s);
  228. *((uint16_t *)d) = (x&0x7FFF) + (x&0x7FE0);
  229.     }
  230. }
  231. static inline void RENAME(rgb16to15)(const uint8_t *src,uint8_t *dst,unsigned src_size)
  232. {
  233.   register const uint8_t* s=src;
  234.   register uint8_t* d=dst;
  235.   register const uint8_t *end;
  236.   const uint8_t *mm_end;
  237.   end = s + src_size;
  238. #ifdef HAVE_MMX
  239.   __asm __volatile(PREFETCH" %0"::"m"(*s));
  240.   __asm __volatile("movq %0, %%mm7"::"m"(mask15rg));
  241.   __asm __volatile("movq %0, %%mm6"::"m"(mask15b));
  242.   mm_end = end - 15;
  243.   while(s<mm_end)
  244.   {
  245. __asm __volatile(
  246. PREFETCH" 32%1nt"
  247. "movq %1, %%mm0nt"
  248. "movq 8%1, %%mm2nt"
  249. "movq %%mm0, %%mm1nt"
  250. "movq %%mm2, %%mm3nt"
  251. "psrlq $1, %%mm0nt"
  252. "psrlq $1, %%mm2nt"
  253. "pand %%mm7, %%mm0nt"
  254. "pand %%mm7, %%mm2nt"
  255. "pand %%mm6, %%mm1nt"
  256. "pand %%mm6, %%mm3nt"
  257. "por %%mm1, %%mm0nt"
  258. "por %%mm3, %%mm2nt"
  259. MOVNTQ" %%mm0, %0nt"
  260. MOVNTQ" %%mm2, 8%0"
  261. :"=m"(*d)
  262. :"m"(*s)
  263. );
  264. d+=16;
  265. s+=16;
  266.   }
  267.   __asm __volatile(SFENCE:::"memory");
  268.   __asm __volatile(EMMS:::"memory");
  269. #endif
  270.     mm_end = end - 3;
  271.     while(s < mm_end)
  272.     {
  273. register uint32_t x= *((uint32_t *)s);
  274. *((uint32_t *)d) = ((x>>1)&0x7FE07FE0) | (x&0x001F001F);
  275. s+=4;
  276. d+=4;
  277.     }
  278.     if(s < end)
  279.     {
  280. register uint16_t x= *((uint16_t *)s);
  281. *((uint16_t *)d) = ((x>>1)&0x7FE0) | (x&0x001F);
  282. s+=2;
  283. d+=2;
  284.     }
  285. }
  286. static inline void RENAME(rgb32to16)(const uint8_t *src, uint8_t *dst, unsigned src_size)
  287. {
  288. const uint8_t *s = src;
  289. const uint8_t *end;
  290. #ifdef HAVE_MMX
  291. const uint8_t *mm_end;
  292. #endif
  293. uint16_t *d = (uint16_t *)dst;
  294. end = s + src_size;
  295. #ifdef HAVE_MMX
  296. mm_end = end - 15;
  297. #if 1 //is faster only if multiplies are reasonable fast (FIXME figure out on which cpus this is faster, on Athlon its slightly faster)
  298. asm volatile(
  299. "movq %3, %%mm5 nt"
  300. "movq %4, %%mm6 nt"
  301. "movq %5, %%mm7 nt"
  302. ".balign 16 nt"
  303. "1: nt"
  304. PREFETCH" 32(%1) nt"
  305. "movd (%1), %%mm0 nt"
  306. "movd 4(%1), %%mm3 nt"
  307. "punpckldq 8(%1), %%mm0 nt"
  308. "punpckldq 12(%1), %%mm3 nt"
  309. "movq %%mm0, %%mm1 nt"
  310. "movq %%mm3, %%mm4 nt"
  311. "pand %%mm6, %%mm0 nt"
  312. "pand %%mm6, %%mm3 nt"
  313. "pmaddwd %%mm7, %%mm0 nt"
  314. "pmaddwd %%mm7, %%mm3 nt"
  315. "pand %%mm5, %%mm1 nt"
  316. "pand %%mm5, %%mm4 nt"
  317. "por %%mm1, %%mm0 nt"
  318. "por %%mm4, %%mm3 nt"
  319. "psrld $5, %%mm0 nt"
  320. "pslld $11, %%mm3 nt"
  321. "por %%mm3, %%mm0 nt"
  322. MOVNTQ" %%mm0, (%0) nt"
  323. "addl $16, %1 nt"
  324. "addl $8, %0 nt"
  325. "cmpl %2, %1 nt"
  326. " jb 1b nt"
  327. : "+r" (d), "+r"(s)
  328. : "r" (mm_end), "m" (mask3216g), "m" (mask3216br), "m" (mul3216)
  329. );
  330. #else
  331. __asm __volatile(PREFETCH" %0"::"m"(*src):"memory");
  332. __asm __volatile(
  333.     "movq %0, %%mm7nt"
  334.     "movq %1, %%mm6nt"
  335.     ::"m"(red_16mask),"m"(green_16mask));
  336. while(s < mm_end)
  337. {
  338.     __asm __volatile(
  339. PREFETCH" 32%1nt"
  340. "movd %1, %%mm0nt"
  341. "movd 4%1, %%mm3nt"
  342. "punpckldq 8%1, %%mm0nt"
  343. "punpckldq 12%1, %%mm3nt"
  344. "movq %%mm0, %%mm1nt"
  345. "movq %%mm0, %%mm2nt"
  346. "movq %%mm3, %%mm4nt"
  347. "movq %%mm3, %%mm5nt"
  348. "psrlq $3, %%mm0nt"
  349. "psrlq $3, %%mm3nt"
  350. "pand %2, %%mm0nt"
  351. "pand %2, %%mm3nt"
  352. "psrlq $5, %%mm1nt"
  353. "psrlq $5, %%mm4nt"
  354. "pand %%mm6, %%mm1nt"
  355. "pand %%mm6, %%mm4nt"
  356. "psrlq $8, %%mm2nt"
  357. "psrlq $8, %%mm5nt"
  358. "pand %%mm7, %%mm2nt"
  359. "pand %%mm7, %%mm5nt"
  360. "por %%mm1, %%mm0nt"
  361. "por %%mm4, %%mm3nt"
  362. "por %%mm2, %%mm0nt"
  363. "por %%mm5, %%mm3nt"
  364. "psllq $16, %%mm3nt"
  365. "por %%mm3, %%mm0nt"
  366. MOVNTQ" %%mm0, %0nt"
  367. :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
  368. d += 4;
  369. s += 16;
  370. }
  371. #endif
  372. __asm __volatile(SFENCE:::"memory");
  373. __asm __volatile(EMMS:::"memory");
  374. #endif
  375. while(s < end)
  376. {
  377. const int src= *s; s += 4;
  378. *d++ = ((src&0xFF)>>3) + ((src&0xFC00)>>5) + ((src&0xF80000)>>8);
  379. // *d++ = ((src>>3)&0x1F) + ((src>>5)&0x7E0) + ((src>>8)&0xF800);
  380. }
  381. }
  382. static inline void RENAME(rgb32tobgr16)(const uint8_t *src, uint8_t *dst, unsigned int src_size)
  383. {
  384. const uint8_t *s = src;
  385. const uint8_t *end;
  386. #ifdef HAVE_MMX
  387. const uint8_t *mm_end;
  388. #endif
  389. uint16_t *d = (uint16_t *)dst;
  390. end = s + src_size;
  391. #ifdef HAVE_MMX
  392. __asm __volatile(PREFETCH" %0"::"m"(*src):"memory");
  393. __asm __volatile(
  394.     "movq %0, %%mm7nt"
  395.     "movq %1, %%mm6nt"
  396.     ::"m"(red_16mask),"m"(green_16mask));
  397. mm_end = end - 15;
  398. while(s < mm_end)
  399. {
  400.     __asm __volatile(
  401. PREFETCH" 32%1nt"
  402. "movd %1, %%mm0nt"
  403. "movd 4%1, %%mm3nt"
  404. "punpckldq 8%1, %%mm0nt"
  405. "punpckldq 12%1, %%mm3nt"
  406. "movq %%mm0, %%mm1nt"
  407. "movq %%mm0, %%mm2nt"
  408. "movq %%mm3, %%mm4nt"
  409. "movq %%mm3, %%mm5nt"
  410. "psllq $8, %%mm0nt"
  411. "psllq $8, %%mm3nt"
  412. "pand %%mm7, %%mm0nt"
  413. "pand %%mm7, %%mm3nt"
  414. "psrlq $5, %%mm1nt"
  415. "psrlq $5, %%mm4nt"
  416. "pand %%mm6, %%mm1nt"
  417. "pand %%mm6, %%mm4nt"
  418. "psrlq $19, %%mm2nt"
  419. "psrlq $19, %%mm5nt"
  420. "pand %2, %%mm2nt"
  421. "pand %2, %%mm5nt"
  422. "por %%mm1, %%mm0nt"
  423. "por %%mm4, %%mm3nt"
  424. "por %%mm2, %%mm0nt"
  425. "por %%mm5, %%mm3nt"
  426. "psllq $16, %%mm3nt"
  427. "por %%mm3, %%mm0nt"
  428. MOVNTQ" %%mm0, %0nt"
  429. :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
  430. d += 4;
  431. s += 16;
  432. }
  433. __asm __volatile(SFENCE:::"memory");
  434. __asm __volatile(EMMS:::"memory");
  435. #endif
  436. while(s < end)
  437. {
  438. const int src= *s; s += 4;
  439. *d++ = ((src&0xF8)<<8) + ((src&0xFC00)>>5) + ((src&0xF80000)>>19);
  440. }
  441. }
  442. static inline void RENAME(rgb32to15)(const uint8_t *src, uint8_t *dst, unsigned src_size)
  443. {
  444. const uint8_t *s = src;
  445. const uint8_t *end;
  446. #ifdef HAVE_MMX
  447. const uint8_t *mm_end;
  448. #endif
  449. uint16_t *d = (uint16_t *)dst;
  450. end = s + src_size;
  451. #ifdef HAVE_MMX
  452. mm_end = end - 15;
  453. #if 1 //is faster only if multiplies are reasonable fast (FIXME figure out on which cpus this is faster, on Athlon its slightly faster)
  454. asm volatile(
  455. "movq %3, %%mm5 nt"
  456. "movq %4, %%mm6 nt"
  457. "movq %5, %%mm7 nt"
  458. ".balign 16 nt"
  459. "1: nt"
  460. PREFETCH" 32(%1) nt"
  461. "movd (%1), %%mm0 nt"
  462. "movd 4(%1), %%mm3 nt"
  463. "punpckldq 8(%1), %%mm0 nt"
  464. "punpckldq 12(%1), %%mm3 nt"
  465. "movq %%mm0, %%mm1 nt"
  466. "movq %%mm3, %%mm4 nt"
  467. "pand %%mm6, %%mm0 nt"
  468. "pand %%mm6, %%mm3 nt"
  469. "pmaddwd %%mm7, %%mm0 nt"
  470. "pmaddwd %%mm7, %%mm3 nt"
  471. "pand %%mm5, %%mm1 nt"
  472. "pand %%mm5, %%mm4 nt"
  473. "por %%mm1, %%mm0 nt"
  474. "por %%mm4, %%mm3 nt"
  475. "psrld $6, %%mm0 nt"
  476. "pslld $10, %%mm3 nt"
  477. "por %%mm3, %%mm0 nt"
  478. MOVNTQ" %%mm0, (%0) nt"
  479. "addl $16, %1 nt"
  480. "addl $8, %0 nt"
  481. "cmpl %2, %1 nt"
  482. " jb 1b nt"
  483. : "+r" (d), "+r"(s)
  484. : "r" (mm_end), "m" (mask3215g), "m" (mask3216br), "m" (mul3215)
  485. );
  486. #else
  487. __asm __volatile(PREFETCH" %0"::"m"(*src):"memory");
  488. __asm __volatile(
  489.     "movq %0, %%mm7nt"
  490.     "movq %1, %%mm6nt"
  491.     ::"m"(red_15mask),"m"(green_15mask));
  492. while(s < mm_end)
  493. {
  494.     __asm __volatile(
  495. PREFETCH" 32%1nt"
  496. "movd %1, %%mm0nt"
  497. "movd 4%1, %%mm3nt"
  498. "punpckldq 8%1, %%mm0nt"
  499. "punpckldq 12%1, %%mm3nt"
  500. "movq %%mm0, %%mm1nt"
  501. "movq %%mm0, %%mm2nt"
  502. "movq %%mm3, %%mm4nt"
  503. "movq %%mm3, %%mm5nt"
  504. "psrlq $3, %%mm0nt"
  505. "psrlq $3, %%mm3nt"
  506. "pand %2, %%mm0nt"
  507. "pand %2, %%mm3nt"
  508. "psrlq $6, %%mm1nt"
  509. "psrlq $6, %%mm4nt"
  510. "pand %%mm6, %%mm1nt"
  511. "pand %%mm6, %%mm4nt"
  512. "psrlq $9, %%mm2nt"
  513. "psrlq $9, %%mm5nt"
  514. "pand %%mm7, %%mm2nt"
  515. "pand %%mm7, %%mm5nt"
  516. "por %%mm1, %%mm0nt"
  517. "por %%mm4, %%mm3nt"
  518. "por %%mm2, %%mm0nt"
  519. "por %%mm5, %%mm3nt"
  520. "psllq $16, %%mm3nt"
  521. "por %%mm3, %%mm0nt"
  522. MOVNTQ" %%mm0, %0nt"
  523. :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
  524. d += 4;
  525. s += 16;
  526. }
  527. #endif
  528. __asm __volatile(SFENCE:::"memory");
  529. __asm __volatile(EMMS:::"memory");
  530. #endif
  531. while(s < end)
  532. {
  533. const int src= *s; s += 4;
  534. *d++ = ((src&0xFF)>>3) + ((src&0xF800)>>6) + ((src&0xF80000)>>9);
  535. }
  536. }
  537. static inline void RENAME(rgb32tobgr15)(const uint8_t *src, uint8_t *dst, unsigned src_size)
  538. {
  539. const uint8_t *s = src;
  540. const uint8_t *end;
  541. #ifdef HAVE_MMX
  542. const uint8_t *mm_end;
  543. #endif
  544. uint16_t *d = (uint16_t *)dst;
  545. end = s + src_size;
  546. #ifdef HAVE_MMX
  547. __asm __volatile(PREFETCH" %0"::"m"(*src):"memory");
  548. __asm __volatile(
  549.     "movq %0, %%mm7nt"
  550.     "movq %1, %%mm6nt"
  551.     ::"m"(red_15mask),"m"(green_15mask));
  552. mm_end = end - 15;
  553. while(s < mm_end)
  554. {
  555.     __asm __volatile(
  556. PREFETCH" 32%1nt"
  557. "movd %1, %%mm0nt"
  558. "movd 4%1, %%mm3nt"
  559. "punpckldq 8%1, %%mm0nt"
  560. "punpckldq 12%1, %%mm3nt"
  561. "movq %%mm0, %%mm1nt"
  562. "movq %%mm0, %%mm2nt"
  563. "movq %%mm3, %%mm4nt"
  564. "movq %%mm3, %%mm5nt"
  565. "psllq $7, %%mm0nt"
  566. "psllq $7, %%mm3nt"
  567. "pand %%mm7, %%mm0nt"
  568. "pand %%mm7, %%mm3nt"
  569. "psrlq $6, %%mm1nt"
  570. "psrlq $6, %%mm4nt"
  571. "pand %%mm6, %%mm1nt"
  572. "pand %%mm6, %%mm4nt"
  573. "psrlq $19, %%mm2nt"
  574. "psrlq $19, %%mm5nt"
  575. "pand %2, %%mm2nt"
  576. "pand %2, %%mm5nt"
  577. "por %%mm1, %%mm0nt"
  578. "por %%mm4, %%mm3nt"
  579. "por %%mm2, %%mm0nt"
  580. "por %%mm5, %%mm3nt"
  581. "psllq $16, %%mm3nt"
  582. "por %%mm3, %%mm0nt"
  583. MOVNTQ" %%mm0, %0nt"
  584. :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
  585. d += 4;
  586. s += 16;
  587. }
  588. __asm __volatile(SFENCE:::"memory");
  589. __asm __volatile(EMMS:::"memory");
  590. #endif
  591. while(s < end)
  592. {
  593. const int src= *s; s += 4;
  594. *d++ = ((src&0xF8)<<7) + ((src&0xF800)>>6) + ((src&0xF80000)>>19);
  595. }
  596. }
  597. static inline void RENAME(rgb24to16)(const uint8_t *src, uint8_t *dst, unsigned src_size)
  598. {
  599. const uint8_t *s = src;
  600. const uint8_t *end;
  601. #ifdef HAVE_MMX
  602. const uint8_t *mm_end;
  603. #endif
  604. uint16_t *d = (uint16_t *)dst;
  605. end = s + src_size;
  606. #ifdef HAVE_MMX
  607. __asm __volatile(PREFETCH" %0"::"m"(*src):"memory");
  608. __asm __volatile(
  609.     "movq %0, %%mm7nt"
  610.     "movq %1, %%mm6nt"
  611.     ::"m"(red_16mask),"m"(green_16mask));
  612. mm_end = end - 11;
  613. while(s < mm_end)
  614. {
  615.     __asm __volatile(
  616. PREFETCH" 32%1nt"
  617. "movd %1, %%mm0nt"
  618. "movd 3%1, %%mm3nt"
  619. "punpckldq 6%1, %%mm0nt"
  620. "punpckldq 9%1, %%mm3nt"
  621. "movq %%mm0, %%mm1nt"
  622. "movq %%mm0, %%mm2nt"
  623. "movq %%mm3, %%mm4nt"
  624. "movq %%mm3, %%mm5nt"
  625. "psrlq $3, %%mm0nt"
  626. "psrlq $3, %%mm3nt"
  627. "pand %2, %%mm0nt"
  628. "pand %2, %%mm3nt"
  629. "psrlq $5, %%mm1nt"
  630. "psrlq $5, %%mm4nt"
  631. "pand %%mm6, %%mm1nt"
  632. "pand %%mm6, %%mm4nt"
  633. "psrlq $8, %%mm2nt"
  634. "psrlq $8, %%mm5nt"
  635. "pand %%mm7, %%mm2nt"
  636. "pand %%mm7, %%mm5nt"
  637. "por %%mm1, %%mm0nt"
  638. "por %%mm4, %%mm3nt"
  639. "por %%mm2, %%mm0nt"
  640. "por %%mm5, %%mm3nt"
  641. "psllq $16, %%mm3nt"
  642. "por %%mm3, %%mm0nt"
  643. MOVNTQ" %%mm0, %0nt"
  644. :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
  645. d += 4;
  646. s += 12;
  647. }
  648. __asm __volatile(SFENCE:::"memory");
  649. __asm __volatile(EMMS:::"memory");
  650. #endif
  651. while(s < end)
  652. {
  653. const int b= *s++;
  654. const int g= *s++;
  655. const int r= *s++;
  656. *d++ = (b>>3) | ((g&0xFC)<<3) | ((r&0xF8)<<8);
  657. }
  658. }
  659. static inline void RENAME(rgb24tobgr16)(const uint8_t *src, uint8_t *dst, unsigned int src_size)
  660. {
  661. const uint8_t *s = src;
  662. const uint8_t *end;
  663. #ifdef HAVE_MMX
  664. const uint8_t *mm_end;
  665. #endif
  666. uint16_t *d = (uint16_t *)dst;
  667. end = s + src_size;
  668. #ifdef HAVE_MMX
  669. __asm __volatile(PREFETCH" %0"::"m"(*src):"memory");
  670. __asm __volatile(
  671.     "movq %0, %%mm7nt"
  672.     "movq %1, %%mm6nt"
  673.     ::"m"(red_16mask),"m"(green_16mask));
  674. mm_end = end - 15;
  675. while(s < mm_end)
  676. {
  677.     __asm __volatile(
  678. PREFETCH" 32%1nt"
  679. "movd %1, %%mm0nt"
  680. "movd 3%1, %%mm3nt"
  681. "punpckldq 6%1, %%mm0nt"
  682. "punpckldq 9%1, %%mm3nt"
  683. "movq %%mm0, %%mm1nt"
  684. "movq %%mm0, %%mm2nt"
  685. "movq %%mm3, %%mm4nt"
  686. "movq %%mm3, %%mm5nt"
  687. "psllq $8, %%mm0nt"
  688. "psllq $8, %%mm3nt"
  689. "pand %%mm7, %%mm0nt"
  690. "pand %%mm7, %%mm3nt"
  691. "psrlq $5, %%mm1nt"
  692. "psrlq $5, %%mm4nt"
  693. "pand %%mm6, %%mm1nt"
  694. "pand %%mm6, %%mm4nt"
  695. "psrlq $19, %%mm2nt"
  696. "psrlq $19, %%mm5nt"
  697. "pand %2, %%mm2nt"
  698. "pand %2, %%mm5nt"
  699. "por %%mm1, %%mm0nt"
  700. "por %%mm4, %%mm3nt"
  701. "por %%mm2, %%mm0nt"
  702. "por %%mm5, %%mm3nt"
  703. "psllq $16, %%mm3nt"
  704. "por %%mm3, %%mm0nt"
  705. MOVNTQ" %%mm0, %0nt"
  706. :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
  707. d += 4;
  708. s += 12;
  709. }
  710. __asm __volatile(SFENCE:::"memory");
  711. __asm __volatile(EMMS:::"memory");
  712. #endif
  713. while(s < end)
  714. {
  715. const int r= *s++;
  716. const int g= *s++;
  717. const int b= *s++;
  718. *d++ = (b>>3) | ((g&0xFC)<<3) | ((r&0xF8)<<8);
  719. }
  720. }
  721. static inline void RENAME(rgb24to15)(const uint8_t *src, uint8_t *dst, unsigned src_size)
  722. {
  723. const uint8_t *s = src;
  724. const uint8_t *end;
  725. #ifdef HAVE_MMX
  726. const uint8_t *mm_end;
  727. #endif
  728. uint16_t *d = (uint16_t *)dst;
  729. end = s + src_size;
  730. #ifdef HAVE_MMX
  731. __asm __volatile(PREFETCH" %0"::"m"(*src):"memory");
  732. __asm __volatile(
  733.     "movq %0, %%mm7nt"
  734.     "movq %1, %%mm6nt"
  735.     ::"m"(red_15mask),"m"(green_15mask));
  736. mm_end = end - 11;
  737. while(s < mm_end)
  738. {
  739.     __asm __volatile(
  740. PREFETCH" 32%1nt"
  741. "movd %1, %%mm0nt"
  742. "movd 3%1, %%mm3nt"
  743. "punpckldq 6%1, %%mm0nt"
  744. "punpckldq 9%1, %%mm3nt"
  745. "movq %%mm0, %%mm1nt"
  746. "movq %%mm0, %%mm2nt"
  747. "movq %%mm3, %%mm4nt"
  748. "movq %%mm3, %%mm5nt"
  749. "psrlq $3, %%mm0nt"
  750. "psrlq $3, %%mm3nt"
  751. "pand %2, %%mm0nt"
  752. "pand %2, %%mm3nt"
  753. "psrlq $6, %%mm1nt"
  754. "psrlq $6, %%mm4nt"
  755. "pand %%mm6, %%mm1nt"
  756. "pand %%mm6, %%mm4nt"
  757. "psrlq $9, %%mm2nt"
  758. "psrlq $9, %%mm5nt"
  759. "pand %%mm7, %%mm2nt"
  760. "pand %%mm7, %%mm5nt"
  761. "por %%mm1, %%mm0nt"
  762. "por %%mm4, %%mm3nt"
  763. "por %%mm2, %%mm0nt"
  764. "por %%mm5, %%mm3nt"
  765. "psllq $16, %%mm3nt"
  766. "por %%mm3, %%mm0nt"
  767. MOVNTQ" %%mm0, %0nt"
  768. :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
  769. d += 4;
  770. s += 12;
  771. }
  772. __asm __volatile(SFENCE:::"memory");
  773. __asm __volatile(EMMS:::"memory");
  774. #endif
  775. while(s < end)
  776. {
  777. const int b= *s++;
  778. const int g= *s++;
  779. const int r= *s++;
  780. *d++ = (b>>3) | ((g&0xF8)<<2) | ((r&0xF8)<<7);
  781. }
  782. }
  783. static inline void RENAME(rgb24tobgr15)(const uint8_t *src, uint8_t *dst, unsigned src_size)
  784. {
  785. const uint8_t *s = src;
  786. const uint8_t *end;
  787. #ifdef HAVE_MMX
  788. const uint8_t *mm_end;
  789. #endif
  790. uint16_t *d = (uint16_t *)dst;
  791. end = s + src_size;
  792. #ifdef HAVE_MMX
  793. __asm __volatile(PREFETCH" %0"::"m"(*src):"memory");
  794. __asm __volatile(
  795.     "movq %0, %%mm7nt"
  796.     "movq %1, %%mm6nt"
  797.     ::"m"(red_15mask),"m"(green_15mask));
  798. mm_end = end - 15;
  799. while(s < mm_end)
  800. {
  801.     __asm __volatile(
  802. PREFETCH" 32%1nt"
  803. "movd %1, %%mm0nt"
  804. "movd 3%1, %%mm3nt"
  805. "punpckldq 6%1, %%mm0nt"
  806. "punpckldq 9%1, %%mm3nt"
  807. "movq %%mm0, %%mm1nt"
  808. "movq %%mm0, %%mm2nt"
  809. "movq %%mm3, %%mm4nt"
  810. "movq %%mm3, %%mm5nt"
  811. "psllq $7, %%mm0nt"
  812. "psllq $7, %%mm3nt"
  813. "pand %%mm7, %%mm0nt"
  814. "pand %%mm7, %%mm3nt"
  815. "psrlq $6, %%mm1nt"
  816. "psrlq $6, %%mm4nt"
  817. "pand %%mm6, %%mm1nt"
  818. "pand %%mm6, %%mm4nt"
  819. "psrlq $19, %%mm2nt"
  820. "psrlq $19, %%mm5nt"
  821. "pand %2, %%mm2nt"
  822. "pand %2, %%mm5nt"
  823. "por %%mm1, %%mm0nt"
  824. "por %%mm4, %%mm3nt"
  825. "por %%mm2, %%mm0nt"
  826. "por %%mm5, %%mm3nt"
  827. "psllq $16, %%mm3nt"
  828. "por %%mm3, %%mm0nt"
  829. MOVNTQ" %%mm0, %0nt"
  830. :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
  831. d += 4;
  832. s += 12;
  833. }
  834. __asm __volatile(SFENCE:::"memory");
  835. __asm __volatile(EMMS:::"memory");
  836. #endif
  837. while(s < end)
  838. {
  839. const int r= *s++;
  840. const int g= *s++;
  841. const int b= *s++;
  842. *d++ = (b>>3) | ((g&0xF8)<<2) | ((r&0xF8)<<7);
  843. }
  844. }
  845. /*
  846.   I use here less accurate approximation by simply
  847.  left-shifting the input
  848.   value and filling the low order bits with
  849.  zeroes. This method improves png's
  850.   compression but this scheme cannot reproduce white exactly, since it does not
  851.   generate an all-ones maximum value; the net effect is to darken the
  852.   image slightly.
  853.   The better method should be "left bit replication":
  854.    4 3 2 1 0
  855.    ---------
  856.    1 1 0 1 1
  857.    7 6 5 4 3  2 1 0
  858.    ----------------
  859.    1 1 0 1 1  1 1 0
  860.    |=======|  |===|
  861.        |      Leftmost Bits Repeated to Fill Open Bits
  862.        |
  863.    Original Bits
  864. */
  865. static inline void RENAME(rgb15to24)(const uint8_t *src, uint8_t *dst, unsigned src_size)
  866. {
  867. const uint16_t *end;
  868. #ifdef HAVE_MMX
  869. const uint16_t *mm_end;
  870. #endif
  871. uint8_t *d = (uint8_t *)dst;
  872. const uint16_t *s = (uint16_t *)src;
  873. end = s + src_size/2;
  874. #ifdef HAVE_MMX
  875. __asm __volatile(PREFETCH" %0"::"m"(*s):"memory");
  876. mm_end = end - 7;
  877. while(s < mm_end)
  878. {
  879.     __asm __volatile(
  880. PREFETCH" 32%1nt"
  881. "movq %1, %%mm0nt"
  882. "movq %1, %%mm1nt"
  883. "movq %1, %%mm2nt"
  884. "pand %2, %%mm0nt"
  885. "pand %3, %%mm1nt"
  886. "pand %4, %%mm2nt"
  887. "psllq $3, %%mm0nt"
  888. "psrlq $2, %%mm1nt"
  889. "psrlq $7, %%mm2nt"
  890. "movq %%mm0, %%mm3nt"
  891. "movq %%mm1, %%mm4nt"
  892. "movq %%mm2, %%mm5nt"
  893. "punpcklwd %5, %%mm0nt"
  894. "punpcklwd %5, %%mm1nt"
  895. "punpcklwd %5, %%mm2nt"
  896. "punpckhwd %5, %%mm3nt"
  897. "punpckhwd %5, %%mm4nt"
  898. "punpckhwd %5, %%mm5nt"
  899. "psllq $8, %%mm1nt"
  900. "psllq $16, %%mm2nt"
  901. "por %%mm1, %%mm0nt"
  902. "por %%mm2, %%mm0nt"
  903. "psllq $8, %%mm4nt"
  904. "psllq $16, %%mm5nt"
  905. "por %%mm4, %%mm3nt"
  906. "por %%mm5, %%mm3nt"
  907. "movq %%mm0, %%mm6nt"
  908. "movq %%mm3, %%mm7nt"
  909. "movq 8%1, %%mm0nt"
  910. "movq 8%1, %%mm1nt"
  911. "movq 8%1, %%mm2nt"
  912. "pand %2, %%mm0nt"
  913. "pand %3, %%mm1nt"
  914. "pand %4, %%mm2nt"
  915. "psllq $3, %%mm0nt"
  916. "psrlq $2, %%mm1nt"
  917. "psrlq $7, %%mm2nt"
  918. "movq %%mm0, %%mm3nt"
  919. "movq %%mm1, %%mm4nt"
  920. "movq %%mm2, %%mm5nt"
  921. "punpcklwd %5, %%mm0nt"
  922. "punpcklwd %5, %%mm1nt"
  923. "punpcklwd %5, %%mm2nt"
  924. "punpckhwd %5, %%mm3nt"
  925. "punpckhwd %5, %%mm4nt"
  926. "punpckhwd %5, %%mm5nt"
  927. "psllq $8, %%mm1nt"
  928. "psllq $16, %%mm2nt"
  929. "por %%mm1, %%mm0nt"
  930. "por %%mm2, %%mm0nt"
  931. "psllq $8, %%mm4nt"
  932. "psllq $16, %%mm5nt"
  933. "por %%mm4, %%mm3nt"
  934. "por %%mm5, %%mm3nt"
  935. :"=m"(*d)
  936. :"m"(*s),"m"(mask15b),"m"(mask15g),"m"(mask15r), "m"(mmx_null)
  937. :"memory");
  938.     /* Borrowed 32 to 24 */
  939.     __asm __volatile(
  940. "movq %%mm0, %%mm4nt"
  941. "movq %%mm3, %%mm5nt"
  942. "movq %%mm6, %%mm0nt"
  943. "movq %%mm7, %%mm1nt"
  944. "movq %%mm4, %%mm6nt"
  945. "movq %%mm5, %%mm7nt"
  946. "movq %%mm0, %%mm2nt"
  947. "movq %%mm1, %%mm3nt"
  948. "psrlq $8, %%mm2nt"
  949. "psrlq $8, %%mm3nt"
  950. "psrlq $8, %%mm6nt"
  951. "psrlq $8, %%mm7nt"
  952. "pand %2, %%mm0nt"
  953. "pand %2, %%mm1nt"
  954. "pand %2, %%mm4nt"
  955. "pand %2, %%mm5nt"
  956. "pand %3, %%mm2nt"
  957. "pand %3, %%mm3nt"
  958. "pand %3, %%mm6nt"
  959. "pand %3, %%mm7nt"
  960. "por %%mm2, %%mm0nt"
  961. "por %%mm3, %%mm1nt"
  962. "por %%mm6, %%mm4nt"
  963. "por %%mm7, %%mm5nt"
  964. "movq %%mm1, %%mm2nt"
  965. "movq %%mm4, %%mm3nt"
  966. "psllq $48, %%mm2nt"
  967. "psllq $32, %%mm3nt"
  968. "pand %4, %%mm2nt"
  969. "pand %5, %%mm3nt"
  970. "por %%mm2, %%mm0nt"
  971. "psrlq $16, %%mm1nt"
  972. "psrlq $32, %%mm4nt"
  973. "psllq $16, %%mm5nt"
  974. "por %%mm3, %%mm1nt"
  975. "pand %6, %%mm5nt"
  976. "por %%mm5, %%mm4nt"
  977. MOVNTQ" %%mm0, %0nt"
  978. MOVNTQ" %%mm1, 8%0nt"
  979. MOVNTQ" %%mm4, 16%0"
  980. :"=m"(*d)
  981. :"m"(*s),"m"(mask24l),"m"(mask24h),"m"(mask24hh),"m"(mask24hhh),"m"(mask24hhhh)
  982. :"memory");
  983. d += 24;
  984. s += 8;
  985. }
  986. __asm __volatile(SFENCE:::"memory");
  987. __asm __volatile(EMMS:::"memory");
  988. #endif
  989. while(s < end)
  990. {
  991. register uint16_t bgr;
  992. bgr = *s++;
  993. *d++ = (bgr&0x1F)<<3;
  994. *d++ = (bgr&0x3E0)>>2;
  995. *d++ = (bgr&0x7C00)>>7;
  996. }
  997. }
  998. static inline void RENAME(rgb16to24)(const uint8_t *src, uint8_t *dst, unsigned src_size)
  999. {
  1000. const uint16_t *end;
  1001. #ifdef HAVE_MMX
  1002. const uint16_t *mm_end;
  1003. #endif
  1004. uint8_t *d = (uint8_t *)dst;
  1005. const uint16_t *s = (const uint16_t *)src;
  1006. end = s + src_size/2;
  1007. #ifdef HAVE_MMX
  1008. __asm __volatile(PREFETCH" %0"::"m"(*s):"memory");
  1009. mm_end = end - 7;
  1010. while(s < mm_end)
  1011. {
  1012.     __asm __volatile(
  1013. PREFETCH" 32%1nt"
  1014. "movq %1, %%mm0nt"
  1015. "movq %1, %%mm1nt"
  1016. "movq %1, %%mm2nt"
  1017. "pand %2, %%mm0nt"
  1018. "pand %3, %%mm1nt"
  1019. "pand %4, %%mm2nt"
  1020. "psllq $3, %%mm0nt"
  1021. "psrlq $3, %%mm1nt"
  1022. "psrlq $8, %%mm2nt"
  1023. "movq %%mm0, %%mm3nt"
  1024. "movq %%mm1, %%mm4nt"
  1025. "movq %%mm2, %%mm5nt"
  1026. "punpcklwd %5, %%mm0nt"
  1027. "punpcklwd %5, %%mm1nt"
  1028. "punpcklwd %5, %%mm2nt"
  1029. "punpckhwd %5, %%mm3nt"
  1030. "punpckhwd %5, %%mm4nt"
  1031. "punpckhwd %5, %%mm5nt"
  1032. "psllq $8, %%mm1nt"
  1033. "psllq $16, %%mm2nt"
  1034. "por %%mm1, %%mm0nt"
  1035. "por %%mm2, %%mm0nt"
  1036. "psllq $8, %%mm4nt"
  1037. "psllq $16, %%mm5nt"
  1038. "por %%mm4, %%mm3nt"
  1039. "por %%mm5, %%mm3nt"
  1040. "movq %%mm0, %%mm6nt"
  1041. "movq %%mm3, %%mm7nt"
  1042. "movq 8%1, %%mm0nt"
  1043. "movq 8%1, %%mm1nt"
  1044. "movq 8%1, %%mm2nt"
  1045. "pand %2, %%mm0nt"
  1046. "pand %3, %%mm1nt"
  1047. "pand %4, %%mm2nt"
  1048. "psllq $3, %%mm0nt"
  1049. "psrlq $3, %%mm1nt"
  1050. "psrlq $8, %%mm2nt"
  1051. "movq %%mm0, %%mm3nt"
  1052. "movq %%mm1, %%mm4nt"
  1053. "movq %%mm2, %%mm5nt"
  1054. "punpcklwd %5, %%mm0nt"
  1055. "punpcklwd %5, %%mm1nt"
  1056. "punpcklwd %5, %%mm2nt"
  1057. "punpckhwd %5, %%mm3nt"
  1058. "punpckhwd %5, %%mm4nt"
  1059. "punpckhwd %5, %%mm5nt"
  1060. "psllq $8, %%mm1nt"
  1061. "psllq $16, %%mm2nt"
  1062. "por %%mm1, %%mm0nt"
  1063. "por %%mm2, %%mm0nt"
  1064. "psllq $8, %%mm4nt"
  1065. "psllq $16, %%mm5nt"
  1066. "por %%mm4, %%mm3nt"
  1067. "por %%mm5, %%mm3nt"
  1068. :"=m"(*d)
  1069. :"m"(*s),"m"(mask16b),"m"(mask16g),"m"(mask16r),"m"(mmx_null)
  1070. :"memory");
  1071.     /* Borrowed 32 to 24 */
  1072.     __asm __volatile(
  1073. "movq %%mm0, %%mm4nt"
  1074. "movq %%mm3, %%mm5nt"
  1075. "movq %%mm6, %%mm0nt"
  1076. "movq %%mm7, %%mm1nt"
  1077. "movq %%mm4, %%mm6nt"
  1078. "movq %%mm5, %%mm7nt"
  1079. "movq %%mm0, %%mm2nt"
  1080. "movq %%mm1, %%mm3nt"
  1081. "psrlq $8, %%mm2nt"
  1082. "psrlq $8, %%mm3nt"
  1083. "psrlq $8, %%mm6nt"
  1084. "psrlq $8, %%mm7nt"
  1085. "pand %2, %%mm0nt"
  1086. "pand %2, %%mm1nt"
  1087. "pand %2, %%mm4nt"
  1088. "pand %2, %%mm5nt"
  1089. "pand %3, %%mm2nt"
  1090. "pand %3, %%mm3nt"
  1091. "pand %3, %%mm6nt"
  1092. "pand %3, %%mm7nt"
  1093. "por %%mm2, %%mm0nt"
  1094. "por %%mm3, %%mm1nt"
  1095. "por %%mm6, %%mm4nt"
  1096. "por %%mm7, %%mm5nt"
  1097. "movq %%mm1, %%mm2nt"
  1098. "movq %%mm4, %%mm3nt"
  1099. "psllq $48, %%mm2nt"
  1100. "psllq $32, %%mm3nt"
  1101. "pand %4, %%mm2nt"
  1102. "pand %5, %%mm3nt"
  1103. "por %%mm2, %%mm0nt"
  1104. "psrlq $16, %%mm1nt"
  1105. "psrlq $32, %%mm4nt"
  1106. "psllq $16, %%mm5nt"
  1107. "por %%mm3, %%mm1nt"
  1108. "pand %6, %%mm5nt"
  1109. "por %%mm5, %%mm4nt"
  1110. MOVNTQ" %%mm0, %0nt"
  1111. MOVNTQ" %%mm1, 8%0nt"
  1112. MOVNTQ" %%mm4, 16%0"
  1113. :"=m"(*d)
  1114. :"m"(*s),"m"(mask24l),"m"(mask24h),"m"(mask24hh),"m"(mask24hhh),"m"(mask24hhhh)
  1115. :"memory");
  1116. d += 24;
  1117. s += 8;
  1118. }
  1119. __asm __volatile(SFENCE:::"memory");
  1120. __asm __volatile(EMMS:::"memory");
  1121. #endif
  1122. while(s < end)
  1123. {
  1124. register uint16_t bgr;
  1125. bgr = *s++;
  1126. *d++ = (bgr&0x1F)<<3;
  1127. *d++ = (bgr&0x7E0)>>3;
  1128. *d++ = (bgr&0xF800)>>8;
  1129. }
  1130. }
  1131. static inline void RENAME(rgb15to32)(const uint8_t *src, uint8_t *dst, unsigned src_size)
  1132. {
  1133. const uint16_t *end;
  1134. #ifdef HAVE_MMX
  1135. const uint16_t *mm_end;
  1136. #endif
  1137. uint8_t *d = (uint8_t *)dst;
  1138. const uint16_t *s = (const uint16_t *)src;
  1139. end = s + src_size/2;
  1140. #ifdef HAVE_MMX
  1141. __asm __volatile(PREFETCH" %0"::"m"(*s):"memory");
  1142. __asm __volatile("pxor %%mm7,%%mm7nt":::"memory");
  1143. mm_end = end - 3;
  1144. while(s < mm_end)
  1145. {
  1146.     __asm __volatile(
  1147. PREFETCH" 32%1nt"
  1148. "movq %1, %%mm0nt"
  1149. "movq %1, %%mm1nt"
  1150. "movq %1, %%mm2nt"
  1151. "pand %2, %%mm0nt"
  1152. "pand %3, %%mm1nt"
  1153. "pand %4, %%mm2nt"
  1154. "psllq $3, %%mm0nt"
  1155. "psrlq $2, %%mm1nt"
  1156. "psrlq $7, %%mm2nt"
  1157. "movq %%mm0, %%mm3nt"
  1158. "movq %%mm1, %%mm4nt"
  1159. "movq %%mm2, %%mm5nt"
  1160. "punpcklwd %%mm7, %%mm0nt"
  1161. "punpcklwd %%mm7, %%mm1nt"
  1162. "punpcklwd %%mm7, %%mm2nt"
  1163. "punpckhwd %%mm7, %%mm3nt"
  1164. "punpckhwd %%mm7, %%mm4nt"
  1165. "punpckhwd %%mm7, %%mm5nt"
  1166. "psllq $8, %%mm1nt"
  1167. "psllq $16, %%mm2nt"
  1168. "por %%mm1, %%mm0nt"
  1169. "por %%mm2, %%mm0nt"
  1170. "psllq $8, %%mm4nt"
  1171. "psllq $16, %%mm5nt"
  1172. "por %%mm4, %%mm3nt"
  1173. "por %%mm5, %%mm3nt"
  1174. MOVNTQ" %%mm0, %0nt"
  1175. MOVNTQ" %%mm3, 8%0nt"
  1176. :"=m"(*d)
  1177. :"m"(*s),"m"(mask15b),"m"(mask15g),"m"(mask15r)
  1178. :"memory");
  1179. d += 16;
  1180. s += 4;
  1181. }
  1182. __asm __volatile(SFENCE:::"memory");
  1183. __asm __volatile(EMMS:::"memory");
  1184. #endif
  1185. while(s < end)
  1186. {
  1187. #if 0 //slightly slower on athlon
  1188. int bgr= *s++;
  1189. *((uint32_t*)d)++ = ((bgr&0x1F)<<3) + ((bgr&0x3E0)<<6) + ((bgr&0x7C00)<<9);
  1190. #else
  1191. //FIXME this is very likely wrong for bigendian (and the following converters too)
  1192. register uint16_t bgr;
  1193. bgr = *s++;
  1194. *d++ = (bgr&0x1F)<<3;
  1195. *d++ = (bgr&0x3E0)>>2;
  1196. *d++ = (bgr&0x7C00)>>7;
  1197. *d++ = 0;
  1198. #endif
  1199. }
  1200. }
  1201. static inline void RENAME(rgb16to32)(const uint8_t *src, uint8_t *dst, unsigned src_size)
  1202. {
  1203. const uint16_t *end;
  1204. #ifdef HAVE_MMX
  1205. const uint16_t *mm_end;
  1206. #endif
  1207. uint8_t *d = (uint8_t *)dst;
  1208. const uint16_t *s = (uint16_t *)src;
  1209. end = s + src_size/2;
  1210. #ifdef HAVE_MMX
  1211. __asm __volatile(PREFETCH" %0"::"m"(*s):"memory");
  1212. __asm __volatile("pxor %%mm7,%%mm7nt":::"memory");
  1213. mm_end = end - 3;
  1214. while(s < mm_end)
  1215. {
  1216.     __asm __volatile(
  1217. PREFETCH" 32%1nt"
  1218. "movq %1, %%mm0nt"
  1219. "movq %1, %%mm1nt"
  1220. "movq %1, %%mm2nt"
  1221. "pand %2, %%mm0nt"
  1222. "pand %3, %%mm1nt"
  1223. "pand %4, %%mm2nt"
  1224. "psllq $3, %%mm0nt"
  1225. "psrlq $3, %%mm1nt"
  1226. "psrlq $8, %%mm2nt"
  1227. "movq %%mm0, %%mm3nt"
  1228. "movq %%mm1, %%mm4nt"
  1229. "movq %%mm2, %%mm5nt"
  1230. "punpcklwd %%mm7, %%mm0nt"
  1231. "punpcklwd %%mm7, %%mm1nt"
  1232. "punpcklwd %%mm7, %%mm2nt"
  1233. "punpckhwd %%mm7, %%mm3nt"
  1234. "punpckhwd %%mm7, %%mm4nt"
  1235. "punpckhwd %%mm7, %%mm5nt"
  1236. "psllq $8, %%mm1nt"
  1237. "psllq $16, %%mm2nt"
  1238. "por %%mm1, %%mm0nt"
  1239. "por %%mm2, %%mm0nt"
  1240. "psllq $8, %%mm4nt"
  1241. "psllq $16, %%mm5nt"
  1242. "por %%mm4, %%mm3nt"
  1243. "por %%mm5, %%mm3nt"
  1244. MOVNTQ" %%mm0, %0nt"
  1245. MOVNTQ" %%mm3, 8%0nt"
  1246. :"=m"(*d)
  1247. :"m"(*s),"m"(mask16b),"m"(mask16g),"m"(mask16r)
  1248. :"memory");
  1249. d += 16;
  1250. s += 4;
  1251. }
  1252. __asm __volatile(SFENCE:::"memory");
  1253. __asm __volatile(EMMS:::"memory");
  1254. #endif
  1255. while(s < end)
  1256. {
  1257. register uint16_t bgr;
  1258. bgr = *s++;
  1259. *d++ = (bgr&0x1F)<<3;
  1260. *d++ = (bgr&0x7E0)>>3;
  1261. *d++ = (bgr&0xF800)>>8;
  1262. *d++ = 0;
  1263. }
  1264. }
  1265. static inline void RENAME(rgb32tobgr32)(const uint8_t *src, uint8_t *dst, unsigned int src_size)
  1266. {
  1267. #ifdef HAVE_MMX
  1268. /* TODO: unroll this loop */
  1269. asm volatile (
  1270. "xorl %%eax, %%eax nt"
  1271. ".balign 16 nt"
  1272. "1: nt"
  1273. PREFETCH" 32(%0, %%eax) nt"
  1274. "movq (%0, %%eax), %%mm0 nt"
  1275. "movq %%mm0, %%mm1 nt"
  1276. "movq %%mm0, %%mm2 nt"
  1277. "pslld $16, %%mm0 nt"
  1278. "psrld $16, %%mm1 nt"
  1279. "pand "MANGLE(mask32r)", %%mm0 nt"
  1280. "pand "MANGLE(mask32g)", %%mm2 nt"
  1281. "pand "MANGLE(mask32b)", %%mm1 nt"
  1282. "por %%mm0, %%mm2 nt"
  1283. "por %%mm1, %%mm2 nt"
  1284. MOVNTQ" %%mm2, (%1, %%eax) nt"
  1285. "addl $8, %%eax nt"
  1286. "cmpl %2, %%eax nt"
  1287. " jb 1b nt"
  1288. :: "r" (src), "r"(dst), "r" (src_size-7)
  1289. : "%eax"
  1290. );
  1291. __asm __volatile(SFENCE:::"memory");
  1292. __asm __volatile(EMMS:::"memory");
  1293. #else
  1294. unsigned i;
  1295. unsigned num_pixels = src_size >> 2;
  1296. for(i=0; i<num_pixels; i++)
  1297. {
  1298. #ifdef WORDS_BIGENDIAN  
  1299.   dst[4*i + 1] = src[4*i + 3];
  1300.   dst[4*i + 2] = src[4*i + 2];
  1301.   dst[4*i + 3] = src[4*i + 1];
  1302. #else
  1303.   dst[4*i + 0] = src[4*i + 2];
  1304.   dst[4*i + 1] = src[4*i + 1];
  1305.   dst[4*i + 2] = src[4*i + 0];
  1306. #endif
  1307. }
  1308. #endif
  1309. }
  1310. static inline void RENAME(rgb24tobgr24)(const uint8_t *src, uint8_t *dst, unsigned int src_size)
  1311. {
  1312. unsigned i;
  1313. #ifdef HAVE_MMX
  1314. int mmx_size= 23 - src_size;
  1315. asm volatile (
  1316. "movq "MANGLE(mask24r)", %%mm5 nt"
  1317. "movq "MANGLE(mask24g)", %%mm6 nt"
  1318. "movq "MANGLE(mask24b)", %%mm7 nt"
  1319. ".balign 16 nt"
  1320. "1: nt"
  1321. PREFETCH" 32(%1, %%eax) nt"
  1322. "movq   (%1, %%eax), %%mm0 nt" // BGR BGR BG
  1323. "movq   (%1, %%eax), %%mm1 nt" // BGR BGR BG
  1324. "movq  2(%1, %%eax), %%mm2 nt" // R BGR BGR B
  1325. "psllq $16, %%mm0 nt" // 00 BGR BGR
  1326. "pand %%mm5, %%mm0 nt"
  1327. "pand %%mm6, %%mm1 nt"
  1328. "pand %%mm7, %%mm2 nt"
  1329. "por %%mm0, %%mm1 nt"
  1330. "por %%mm2, %%mm1 nt"                
  1331. "movq  6(%1, %%eax), %%mm0 nt" // BGR BGR BG
  1332. MOVNTQ" %%mm1,   (%2, %%eax) nt" // RGB RGB RG
  1333. "movq  8(%1, %%eax), %%mm1 nt" // R BGR BGR B
  1334. "movq 10(%1, %%eax), %%mm2 nt" // GR BGR BGR
  1335. "pand %%mm7, %%mm0 nt"
  1336. "pand %%mm5, %%mm1 nt"
  1337. "pand %%mm6, %%mm2 nt"
  1338. "por %%mm0, %%mm1 nt"
  1339. "por %%mm2, %%mm1 nt"                
  1340. "movq 14(%1, %%eax), %%mm0 nt" // R BGR BGR B
  1341. MOVNTQ" %%mm1,  8(%2, %%eax) nt" // B RGB RGB R
  1342. "movq 16(%1, %%eax), %%mm1 nt" // GR BGR BGR
  1343. "movq 18(%1, %%eax), %%mm2 nt" // BGR BGR BG
  1344. "pand %%mm6, %%mm0 nt"
  1345. "pand %%mm7, %%mm1 nt"
  1346. "pand %%mm5, %%mm2 nt"
  1347. "por %%mm0, %%mm1 nt"
  1348. "por %%mm2, %%mm1 nt"                
  1349. MOVNTQ" %%mm1, 16(%2, %%eax) nt"
  1350. "addl $24, %%eax nt"
  1351. " js 1b nt"
  1352. : "+a" (mmx_size)
  1353. : "r" (src-mmx_size), "r"(dst-mmx_size)
  1354. );
  1355. __asm __volatile(SFENCE:::"memory");
  1356. __asm __volatile(EMMS:::"memory");
  1357. if(mmx_size==23) return; //finihsed, was multiple of 8
  1358. src+= src_size;
  1359. dst+= src_size;
  1360. src_size= 23-mmx_size;
  1361. src-= src_size;
  1362. dst-= src_size;
  1363. #endif
  1364. for(i=0; i<src_size; i+=3)
  1365. {
  1366. register uint8_t x;
  1367. x          = src[i + 2];
  1368. dst[i + 1] = src[i + 1];
  1369. dst[i + 2] = src[i + 0];
  1370. dst[i + 0] = x;
  1371. }
  1372. }
  1373. static inline void RENAME(yuvPlanartoyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
  1374. unsigned int width, unsigned int height,
  1375. int lumStride, int chromStride, int dstStride, int vertLumPerChroma)
  1376. {
  1377. unsigned y;
  1378. const unsigned chromWidth= width>>1;
  1379. for(y=0; y<height; y++)
  1380. {
  1381. #ifdef HAVE_MMX
  1382. //FIXME handle 2 lines a once (fewer prefetch, reuse some chrom, but very likely limited by mem anyway)
  1383. asm volatile(
  1384. "xorl %%eax, %%eax nt"
  1385. ".balign 16 nt"
  1386. "1: nt"
  1387. PREFETCH" 32(%1, %%eax, 2) nt"
  1388. PREFETCH" 32(%2, %%eax) nt"
  1389. PREFETCH" 32(%3, %%eax) nt"
  1390. "movq (%2, %%eax), %%mm0 nt" // U(0)
  1391. "movq %%mm0, %%mm2 nt" // U(0)
  1392. "movq (%3, %%eax), %%mm1 nt" // V(0)
  1393. "punpcklbw %%mm1, %%mm0 nt" // UVUV UVUV(0)
  1394. "punpckhbw %%mm1, %%mm2 nt" // UVUV UVUV(8)
  1395. "movq (%1, %%eax,2), %%mm3 nt" // Y(0)
  1396. "movq 8(%1, %%eax,2), %%mm5 nt" // Y(8)
  1397. "movq %%mm3, %%mm4 nt" // Y(0)
  1398. "movq %%mm5, %%mm6 nt" // Y(8)
  1399. "punpcklbw %%mm0, %%mm3 nt" // YUYV YUYV(0)
  1400. "punpckhbw %%mm0, %%mm4 nt" // YUYV YUYV(4)
  1401. "punpcklbw %%mm2, %%mm5 nt" // YUYV YUYV(8)
  1402. "punpckhbw %%mm2, %%mm6 nt" // YUYV YUYV(12)
  1403. MOVNTQ" %%mm3, (%0, %%eax, 4) nt"
  1404. MOVNTQ" %%mm4, 8(%0, %%eax, 4) nt"
  1405. MOVNTQ" %%mm5, 16(%0, %%eax, 4) nt"
  1406. MOVNTQ" %%mm6, 24(%0, %%eax, 4) nt"
  1407. "addl $8, %%eax nt"
  1408. "cmpl %4, %%eax nt"
  1409. " jb 1b nt"
  1410. ::"r"(dst), "r"(ysrc), "r"(usrc), "r"(vsrc), "g" (chromWidth)
  1411. : "%eax"
  1412. );
  1413. #else
  1414. #if defined ARCH_ALPHA && defined HAVE_MVI
  1415. #define pl2yuy2(n)
  1416. y1 = yc[n];
  1417. y2 = yc2[n];
  1418. u = uc[n];
  1419. v = vc[n];
  1420. asm("unpkbw %1, %0" : "=r"(y1) : "r"(y1));
  1421. asm("unpkbw %1, %0" : "=r"(y2) : "r"(y2));
  1422. asm("unpkbl %1, %0" : "=r"(u) : "r"(u));
  1423. asm("unpkbl %1, %0" : "=r"(v) : "r"(v));
  1424. yuv1 = (u << 8) + (v << 24);
  1425. yuv2 = yuv1 + y2;
  1426. yuv1 += y1;
  1427. qdst[n] = yuv1;
  1428. qdst2[n] = yuv2;
  1429. int i;
  1430. uint64_t *qdst = (uint64_t *) dst;
  1431. uint64_t *qdst2 = (uint64_t *) (dst + dstStride);
  1432. const uint32_t *yc = (uint32_t *) ysrc;
  1433. const uint32_t *yc2 = (uint32_t *) (ysrc + lumStride);
  1434. const uint16_t *uc = (uint16_t*) usrc, *vc = (uint16_t*) vsrc;
  1435. for(i = 0; i < chromWidth; i += 8){
  1436. uint64_t y1, y2, yuv1, yuv2;
  1437. uint64_t u, v;
  1438. /* Prefetch */
  1439. asm("ldq $31,64(%0)" :: "r"(yc));
  1440. asm("ldq $31,64(%0)" :: "r"(yc2));
  1441. asm("ldq $31,64(%0)" :: "r"(uc));
  1442. asm("ldq $31,64(%0)" :: "r"(vc));
  1443. pl2yuy2(0);
  1444. pl2yuy2(1);
  1445. pl2yuy2(2);
  1446. pl2yuy2(3);
  1447. yc += 4;
  1448. yc2 += 4;
  1449. uc += 4;
  1450. vc += 4;
  1451. qdst += 4;
  1452. qdst2 += 4;
  1453. }
  1454. y++;
  1455. ysrc += lumStride;
  1456. dst += dstStride;
  1457. #elif __WORDSIZE >= 64
  1458. int i;
  1459. uint64_t *ldst = (uint64_t *) dst;
  1460. const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
  1461. for(i = 0; i < chromWidth; i += 2){
  1462. uint64_t k, l;
  1463. k = yc[0] + (uc[0] << 8) +
  1464.     (yc[1] << 16) + (vc[0] << 24);
  1465. l = yc[2] + (uc[1] << 8) +
  1466.     (yc[3] << 16) + (vc[1] << 24);
  1467. *ldst++ = k + (l << 32);
  1468. yc += 4;
  1469. uc += 2;
  1470. vc += 2;
  1471. }
  1472. #else
  1473. int i, *idst = (int32_t *) dst;
  1474. const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
  1475. for(i = 0; i < chromWidth; i++){
  1476. #ifdef WORDS_BIGENDIAN
  1477. *idst++ = (yc[0] << 24)+ (uc[0] << 16) +
  1478.     (yc[1] << 8) + (vc[0] << 0);
  1479. #else
  1480. *idst++ = yc[0] + (uc[0] << 8) +
  1481.     (yc[1] << 16) + (vc[0] << 24);
  1482. #endif
  1483. yc += 2;
  1484. uc++;
  1485. vc++;
  1486. }
  1487. #endif
  1488. #endif
  1489. if((y&(vertLumPerChroma-1))==(vertLumPerChroma-1) )
  1490. {
  1491. usrc += chromStride;
  1492. vsrc += chromStride;
  1493. }
  1494. ysrc += lumStride;
  1495. dst += dstStride;
  1496. }
  1497. #ifdef HAVE_MMX
  1498. asm(    EMMS" nt"
  1499.         SFENCE" nt"
  1500.         :::"memory");
  1501. #endif
  1502. }
  1503. /**
  1504.  *
  1505.  * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
  1506.  * problem for anyone then tell me, and ill fix it)
  1507.  */
  1508. static inline void RENAME(yv12toyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
  1509. unsigned int width, unsigned int height,
  1510. int lumStride, int chromStride, int dstStride)
  1511. {
  1512. //FIXME interpolate chroma
  1513. RENAME(yuvPlanartoyuy2)(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride, 2);
  1514. }
  1515. static inline void RENAME(yuvPlanartouyvy)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
  1516. unsigned int width, unsigned int height,
  1517. int lumStride, int chromStride, int dstStride, int vertLumPerChroma)
  1518. {
  1519. unsigned y;
  1520. const unsigned chromWidth= width>>1;
  1521. for(y=0; y<height; y++)
  1522. {
  1523. #ifdef HAVE_MMX
  1524. //FIXME handle 2 lines a once (fewer prefetch, reuse some chrom, but very likely limited by mem anyway)
  1525. asm volatile(
  1526. "xorl %%eax, %%eax nt"
  1527. ".balign 16 nt"
  1528. "1: nt"
  1529. PREFETCH" 32(%1, %%eax, 2) nt"
  1530. PREFETCH" 32(%2, %%eax) nt"
  1531. PREFETCH" 32(%3, %%eax) nt"
  1532. "movq (%2, %%eax), %%mm0 nt" // U(0)
  1533. "movq %%mm0, %%mm2 nt" // U(0)
  1534. "movq (%3, %%eax), %%mm1 nt" // V(0)
  1535. "punpcklbw %%mm1, %%mm0 nt" // UVUV UVUV(0)
  1536. "punpckhbw %%mm1, %%mm2 nt" // UVUV UVUV(8)
  1537. "movq (%1, %%eax,2), %%mm3 nt" // Y(0)
  1538. "movq 8(%1, %%eax,2), %%mm5 nt" // Y(8)
  1539. "movq %%mm0, %%mm4 nt" // Y(0)
  1540. "movq %%mm2, %%mm6 nt" // Y(8)
  1541. "punpcklbw %%mm3, %%mm0 nt" // YUYV YUYV(0)
  1542. "punpckhbw %%mm3, %%mm4 nt" // YUYV YUYV(4)
  1543. "punpcklbw %%mm5, %%mm2 nt" // YUYV YUYV(8)
  1544. "punpckhbw %%mm5, %%mm6 nt" // YUYV YUYV(12)
  1545. MOVNTQ" %%mm0, (%0, %%eax, 4) nt"
  1546. MOVNTQ" %%mm4, 8(%0, %%eax, 4) nt"
  1547. MOVNTQ" %%mm2, 16(%0, %%eax, 4) nt"
  1548. MOVNTQ" %%mm6, 24(%0, %%eax, 4) nt"
  1549. "addl $8, %%eax nt"
  1550. "cmpl %4, %%eax nt"
  1551. " jb 1b nt"
  1552. ::"r"(dst), "r"(ysrc), "r"(usrc), "r"(vsrc), "g" (chromWidth)
  1553. : "%eax"
  1554. );
  1555. #else
  1556. //FIXME adapt the alpha asm code from yv12->yuy2
  1557. #if __WORDSIZE >= 64
  1558. int i;
  1559. uint64_t *ldst = (uint64_t *) dst;
  1560. const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
  1561. for(i = 0; i < chromWidth; i += 2){
  1562. uint64_t k, l;
  1563. k = uc[0] + (yc[0] << 8) +
  1564.     (vc[0] << 16) + (yc[1] << 24);
  1565. l = uc[1] + (yc[2] << 8) +
  1566.     (vc[1] << 16) + (yc[3] << 24);
  1567. *ldst++ = k + (l << 32);
  1568. yc += 4;
  1569. uc += 2;
  1570. vc += 2;
  1571. }
  1572. #else
  1573. int i, *idst = (int32_t *) dst;
  1574. const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
  1575. for(i = 0; i < chromWidth; i++){
  1576. #ifdef WORDS_BIGENDIAN
  1577. *idst++ = (uc[0] << 24)+ (yc[0] << 16) +
  1578.     (vc[0] << 8) + (yc[1] << 0);
  1579. #else
  1580. *idst++ = uc[0] + (yc[0] << 8) +
  1581.     (vc[0] << 16) + (yc[1] << 24);
  1582. #endif
  1583. yc += 2;
  1584. uc++;
  1585. vc++;
  1586. }
  1587. #endif
  1588. #endif
  1589. if((y&(vertLumPerChroma-1))==(vertLumPerChroma-1) )
  1590. {
  1591. usrc += chromStride;
  1592. vsrc += chromStride;
  1593. }
  1594. ysrc += lumStride;
  1595. dst += dstStride;
  1596. }
  1597. #ifdef HAVE_MMX
  1598. asm(    EMMS" nt"
  1599.         SFENCE" nt"
  1600.         :::"memory");
  1601. #endif
  1602. }
  1603. /**
  1604.  *
  1605.  * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
  1606.  * problem for anyone then tell me, and ill fix it)
  1607.  */
  1608. static inline void RENAME(yv12touyvy)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
  1609. unsigned int width, unsigned int height,
  1610. int lumStride, int chromStride, int dstStride)
  1611. {
  1612. //FIXME interpolate chroma
  1613. RENAME(yuvPlanartouyvy)(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride, 2);
  1614. }
  1615. /**
  1616.  *
  1617.  * width should be a multiple of 16
  1618.  */
  1619. static inline void RENAME(yuv422ptoyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
  1620. unsigned int width, unsigned int height,
  1621. int lumStride, int chromStride, int dstStride)
  1622. {
  1623. RENAME(yuvPlanartoyuy2)(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride, 1);
  1624. }
  1625. /**
  1626.  *
  1627.  * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
  1628.  * problem for anyone then tell me, and ill fix it)
  1629.  */
  1630. static inline void RENAME(yuy2toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
  1631. unsigned int width, unsigned int height,
  1632. int lumStride, int chromStride, int srcStride)
  1633. {
  1634. unsigned y;
  1635. const unsigned chromWidth= width>>1;
  1636. for(y=0; y<height; y+=2)
  1637. {
  1638. #ifdef HAVE_MMX
  1639. asm volatile(
  1640. "xorl %%eax, %%eax nt"
  1641. "pcmpeqw %%mm7, %%mm7 nt"
  1642. "psrlw $8, %%mm7 nt" // FF,00,FF,00...
  1643. ".balign 16 nt"
  1644. "1: nt"
  1645. PREFETCH" 64(%0, %%eax, 4) nt"
  1646. "movq (%0, %%eax, 4), %%mm0 nt" // YUYV YUYV(0)
  1647. "movq 8(%0, %%eax, 4), %%mm1 nt" // YUYV YUYV(4)
  1648. "movq %%mm0, %%mm2 nt" // YUYV YUYV(0)
  1649. "movq %%mm1, %%mm3 nt" // YUYV YUYV(4)
  1650. "psrlw $8, %%mm0 nt" // U0V0 U0V0(0)
  1651. "psrlw $8, %%mm1 nt" // U0V0 U0V0(4)
  1652. "pand %%mm7, %%mm2 nt" // Y0Y0 Y0Y0(0)
  1653. "pand %%mm7, %%mm3 nt" // Y0Y0 Y0Y0(4)
  1654. "packuswb %%mm1, %%mm0 nt" // UVUV UVUV(0)
  1655. "packuswb %%mm3, %%mm2 nt" // YYYY YYYY(0)
  1656. MOVNTQ" %%mm2, (%1, %%eax, 2) nt"
  1657. "movq 16(%0, %%eax, 4), %%mm1 nt" // YUYV YUYV(8)
  1658. "movq 24(%0, %%eax, 4), %%mm2 nt" // YUYV YUYV(12)
  1659. "movq %%mm1, %%mm3 nt" // YUYV YUYV(8)
  1660. "movq %%mm2, %%mm4 nt" // YUYV YUYV(12)
  1661. "psrlw $8, %%mm1 nt" // U0V0 U0V0(8)
  1662. "psrlw $8, %%mm2 nt" // U0V0 U0V0(12)
  1663. "pand %%mm7, %%mm3 nt" // Y0Y0 Y0Y0(8)
  1664. "pand %%mm7, %%mm4 nt" // Y0Y0 Y0Y0(12)
  1665. "packuswb %%mm2, %%mm1 nt" // UVUV UVUV(8)
  1666. "packuswb %%mm4, %%mm3 nt" // YYYY YYYY(8)
  1667. MOVNTQ" %%mm3, 8(%1, %%eax, 2) nt"
  1668. "movq %%mm0, %%mm2 nt" // UVUV UVUV(0)
  1669. "movq %%mm1, %%mm3 nt" // UVUV UVUV(8)
  1670. "psrlw $8, %%mm0 nt" // V0V0 V0V0(0)
  1671. "psrlw $8, %%mm1 nt" // V0V0 V0V0(8)
  1672. "pand %%mm7, %%mm2 nt" // U0U0 U0U0(0)
  1673. "pand %%mm7, %%mm3 nt" // U0U0 U0U0(8)
  1674. "packuswb %%mm1, %%mm0 nt" // VVVV VVVV(0)
  1675. "packuswb %%mm3, %%mm2 nt" // UUUU UUUU(0)
  1676. MOVNTQ" %%mm0, (%3, %%eax) nt"
  1677. MOVNTQ" %%mm2, (%2, %%eax) nt"
  1678. "addl $8, %%eax nt"
  1679. "cmpl %4, %%eax nt"
  1680. " jb 1b nt"
  1681. ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
  1682. : "memory", "%eax"
  1683. );
  1684. ydst += lumStride;
  1685. src  += srcStride;
  1686. asm volatile(
  1687. "xorl %%eax, %%eax nt"
  1688. ".balign 16 nt"
  1689. "1: nt"
  1690. PREFETCH" 64(%0, %%eax, 4) nt"
  1691. "movq (%0, %%eax, 4), %%mm0 nt" // YUYV YUYV(0)
  1692. "movq 8(%0, %%eax, 4), %%mm1 nt" // YUYV YUYV(4)
  1693. "movq 16(%0, %%eax, 4), %%mm2 nt" // YUYV YUYV(8)
  1694. "movq 24(%0, %%eax, 4), %%mm3 nt" // YUYV YUYV(12)
  1695. "pand %%mm7, %%mm0 nt" // Y0Y0 Y0Y0(0)
  1696. "pand %%mm7, %%mm1 nt" // Y0Y0 Y0Y0(4)
  1697. "pand %%mm7, %%mm2 nt" // Y0Y0 Y0Y0(8)
  1698. "pand %%mm7, %%mm3 nt" // Y0Y0 Y0Y0(12)
  1699. "packuswb %%mm1, %%mm0 nt" // YYYY YYYY(0)
  1700. "packuswb %%mm3, %%mm2 nt" // YYYY YYYY(8)
  1701. MOVNTQ" %%mm0, (%1, %%eax, 2) nt"
  1702. MOVNTQ" %%mm2, 8(%1, %%eax, 2) nt"
  1703. "addl $8, %%eax nt"
  1704. "cmpl %4, %%eax nt"
  1705. " jb 1b nt"
  1706. ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
  1707. : "memory", "%eax"
  1708. );
  1709. #else
  1710. unsigned i;
  1711. for(i=0; i<chromWidth; i++)
  1712. {
  1713. ydst[2*i+0]  = src[4*i+0];
  1714. udst[i]  = src[4*i+1];
  1715. ydst[2*i+1]  = src[4*i+2];
  1716. vdst[i]  = src[4*i+3];
  1717. }
  1718. ydst += lumStride;
  1719. src  += srcStride;
  1720. for(i=0; i<chromWidth; i++)
  1721. {
  1722. ydst[2*i+0]  = src[4*i+0];
  1723. ydst[2*i+1]  = src[4*i+2];
  1724. }
  1725. #endif
  1726. udst += chromStride;
  1727. vdst += chromStride;
  1728. ydst += lumStride;
  1729. src  += srcStride;
  1730. }
  1731. #ifdef HAVE_MMX
  1732. asm volatile(   EMMS" nt"
  1733.          SFENCE" nt"
  1734.          :::"memory");
  1735. #endif
  1736. }
  1737. static inline void RENAME(yvu9toyv12)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc,
  1738. uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
  1739. unsigned int width, unsigned int height, int lumStride, int chromStride)
  1740. {
  1741. /* Y Plane */
  1742. memcpy(ydst, ysrc, width*height);
  1743. /* XXX: implement upscaling for U,V */
  1744. }
  1745. static inline void RENAME(planar2x)(const uint8_t *src, uint8_t *dst, int srcWidth, int srcHeight, int srcStride, int dstStride)
  1746. {
  1747. int x,y;
  1748. dst[0]= src[0];
  1749.         
  1750. // first line
  1751. for(x=0; x<srcWidth-1; x++){
  1752. dst[2*x+1]= (3*src[x] +   src[x+1])>>2;
  1753. dst[2*x+2]= (  src[x] + 3*src[x+1])>>2;
  1754. }
  1755. dst[2*srcWidth-1]= src[srcWidth-1];
  1756.         dst+= dstStride;
  1757. for(y=1; y<srcHeight; y++){
  1758. #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
  1759. const int mmxSize= srcWidth&~15;
  1760. asm volatile(
  1761. "movl %4, %%eax nt"
  1762. "1: nt"
  1763. "movq (%0, %%eax), %%mm0 nt"
  1764. "movq (%1, %%eax), %%mm1 nt"
  1765. "movq 1(%0, %%eax), %%mm2 nt"
  1766. "movq 1(%1, %%eax), %%mm3 nt"
  1767. "movq -1(%0, %%eax), %%mm4 nt"
  1768. "movq -1(%1, %%eax), %%mm5 nt"
  1769. PAVGB" %%mm0, %%mm5 nt"
  1770. PAVGB" %%mm0, %%mm3 nt"
  1771. PAVGB" %%mm0, %%mm5 nt"
  1772. PAVGB" %%mm0, %%mm3 nt"
  1773. PAVGB" %%mm1, %%mm4 nt"
  1774. PAVGB" %%mm1, %%mm2 nt"
  1775. PAVGB" %%mm1, %%mm4 nt"
  1776. PAVGB" %%mm1, %%mm2 nt"
  1777. "movq %%mm5, %%mm7 nt"
  1778. "movq %%mm4, %%mm6 nt"
  1779. "punpcklbw %%mm3, %%mm5 nt"
  1780. "punpckhbw %%mm3, %%mm7 nt"
  1781. "punpcklbw %%mm2, %%mm4 nt"
  1782. "punpckhbw %%mm2, %%mm6 nt"
  1783. #if 1
  1784. MOVNTQ" %%mm5, (%2, %%eax, 2) nt"
  1785. MOVNTQ" %%mm7, 8(%2, %%eax, 2) nt"
  1786. MOVNTQ" %%mm4, (%3, %%eax, 2) nt"
  1787. MOVNTQ" %%mm6, 8(%3, %%eax, 2) nt"
  1788. #else
  1789. "movq %%mm5, (%2, %%eax, 2) nt"
  1790. "movq %%mm7, 8(%2, %%eax, 2) nt"
  1791. "movq %%mm4, (%3, %%eax, 2) nt"
  1792. "movq %%mm6, 8(%3, %%eax, 2) nt"
  1793. #endif
  1794. "addl $8, %%eax nt"
  1795. " js 1b nt"
  1796. :: "r" (src + mmxSize  ), "r" (src + srcStride + mmxSize  ),
  1797.    "r" (dst + mmxSize*2), "r" (dst + dstStride + mmxSize*2),
  1798.    "g" (-mmxSize)
  1799. : "%eax"
  1800. );
  1801. #else
  1802. const int mmxSize=1;
  1803. #endif
  1804. dst[0        ]= (3*src[0] +   src[srcStride])>>2;
  1805. dst[dstStride]= (  src[0] + 3*src[srcStride])>>2;
  1806. for(x=mmxSize-1; x<srcWidth-1; x++){
  1807. dst[2*x          +1]= (3*src[x+0] +   src[x+srcStride+1])>>2;
  1808. dst[2*x+dstStride+2]= (  src[x+0] + 3*src[x+srcStride+1])>>2;
  1809. dst[2*x+dstStride+1]= (  src[x+1] + 3*src[x+srcStride  ])>>2;
  1810. dst[2*x          +2]= (3*src[x+1] +   src[x+srcStride  ])>>2;
  1811. }
  1812. dst[srcWidth*2 -1            ]= (3*src[srcWidth-1] +   src[srcWidth-1 + srcStride])>>2;
  1813. dst[srcWidth*2 -1 + dstStride]= (  src[srcWidth-1] + 3*src[srcWidth-1 + srcStride])>>2;
  1814. dst+=dstStride*2;
  1815. src+=srcStride;
  1816. }
  1817. // last line
  1818. #if 1
  1819. dst[0]= src[0];
  1820.         
  1821. for(x=0; x<srcWidth-1; x++){
  1822. dst[2*x+1]= (3*src[x] +   src[x+1])>>2;
  1823. dst[2*x+2]= (  src[x] + 3*src[x+1])>>2;
  1824. }
  1825. dst[2*srcWidth-1]= src[srcWidth-1];
  1826. #else
  1827. for(x=0; x<srcWidth; x++){
  1828. dst[2*x+0]=
  1829. dst[2*x+1]= src[x];
  1830. }
  1831. #endif
  1832. #ifdef HAVE_MMX
  1833. asm volatile(   EMMS" nt"
  1834.          SFENCE" nt"
  1835.          :::"memory");
  1836. #endif
  1837. }
  1838. /**
  1839.  *
  1840.  * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
  1841.  * problem for anyone then tell me, and ill fix it)
  1842.  * chrominance data is only taken from every secound line others are ignored FIXME write HQ version
  1843.  */
  1844. static inline void RENAME(uyvytoyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
  1845. unsigned int width, unsigned int height,
  1846. int lumStride, int chromStride, int srcStride)
  1847. {
  1848. unsigned y;
  1849. const unsigned chromWidth= width>>1;
  1850. for(y=0; y<height; y+=2)
  1851. {
  1852. #ifdef HAVE_MMX
  1853. asm volatile(
  1854. "xorl %%eax, %%eax nt"
  1855. "pcmpeqw %%mm7, %%mm7 nt"
  1856. "psrlw $8, %%mm7 nt" // FF,00,FF,00...
  1857. ".balign 16 nt"
  1858. "1: nt"
  1859. PREFETCH" 64(%0, %%eax, 4) nt"
  1860. "movq (%0, %%eax, 4), %%mm0 nt" // UYVY UYVY(0)
  1861. "movq 8(%0, %%eax, 4), %%mm1 nt" // UYVY UYVY(4)
  1862. "movq %%mm0, %%mm2 nt" // UYVY UYVY(0)
  1863. "movq %%mm1, %%mm3 nt" // UYVY UYVY(4)
  1864. "pand %%mm7, %%mm0 nt" // U0V0 U0V0(0)
  1865. "pand %%mm7, %%mm1 nt" // U0V0 U0V0(4)
  1866. "psrlw $8, %%mm2 nt" // Y0Y0 Y0Y0(0)
  1867. "psrlw $8, %%mm3 nt" // Y0Y0 Y0Y0(4)
  1868. "packuswb %%mm1, %%mm0 nt" // UVUV UVUV(0)
  1869. "packuswb %%mm3, %%mm2 nt" // YYYY YYYY(0)
  1870. MOVNTQ" %%mm2, (%1, %%eax, 2) nt"
  1871. "movq 16(%0, %%eax, 4), %%mm1 nt" // UYVY UYVY(8)
  1872. "movq 24(%0, %%eax, 4), %%mm2 nt" // UYVY UYVY(12)
  1873. "movq %%mm1, %%mm3 nt" // UYVY UYVY(8)
  1874. "movq %%mm2, %%mm4 nt" // UYVY UYVY(12)
  1875. "pand %%mm7, %%mm1 nt" // U0V0 U0V0(8)
  1876. "pand %%mm7, %%mm2 nt" // U0V0 U0V0(12)
  1877. "psrlw $8, %%mm3 nt" // Y0Y0 Y0Y0(8)
  1878. "psrlw $8, %%mm4 nt" // Y0Y0 Y0Y0(12)
  1879. "packuswb %%mm2, %%mm1 nt" // UVUV UVUV(8)
  1880. "packuswb %%mm4, %%mm3 nt" // YYYY YYYY(8)
  1881. MOVNTQ" %%mm3, 8(%1, %%eax, 2) nt"
  1882. "movq %%mm0, %%mm2 nt" // UVUV UVUV(0)
  1883. "movq %%mm1, %%mm3 nt" // UVUV UVUV(8)
  1884. "psrlw $8, %%mm0 nt" // V0V0 V0V0(0)
  1885. "psrlw $8, %%mm1 nt" // V0V0 V0V0(8)
  1886. "pand %%mm7, %%mm2 nt" // U0U0 U0U0(0)
  1887. "pand %%mm7, %%mm3 nt" // U0U0 U0U0(8)
  1888. "packuswb %%mm1, %%mm0 nt" // VVVV VVVV(0)
  1889. "packuswb %%mm3, %%mm2 nt" // UUUU UUUU(0)
  1890. MOVNTQ" %%mm0, (%3, %%eax) nt"
  1891. MOVNTQ" %%mm2, (%2, %%eax) nt"
  1892. "addl $8, %%eax nt"
  1893. "cmpl %4, %%eax nt"
  1894. " jb 1b nt"
  1895. ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
  1896. : "memory", "%eax"
  1897. );
  1898. ydst += lumStride;
  1899. src  += srcStride;
  1900. asm volatile(
  1901. "xorl %%eax, %%eax nt"
  1902. ".balign 16 nt"
  1903. "1: nt"
  1904. PREFETCH" 64(%0, %%eax, 4) nt"
  1905. "movq (%0, %%eax, 4), %%mm0 nt" // YUYV YUYV(0)
  1906. "movq 8(%0, %%eax, 4), %%mm1 nt" // YUYV YUYV(4)
  1907. "movq 16(%0, %%eax, 4), %%mm2 nt" // YUYV YUYV(8)
  1908. "movq 24(%0, %%eax, 4), %%mm3 nt" // YUYV YUYV(12)
  1909. "psrlw $8, %%mm0 nt" // Y0Y0 Y0Y0(0)
  1910. "psrlw $8, %%mm1 nt" // Y0Y0 Y0Y0(4)
  1911. "psrlw $8, %%mm2 nt" // Y0Y0 Y0Y0(8)
  1912. "psrlw $8, %%mm3 nt" // Y0Y0 Y0Y0(12)
  1913. "packuswb %%mm1, %%mm0 nt" // YYYY YYYY(0)
  1914. "packuswb %%mm3, %%mm2 nt" // YYYY YYYY(8)
  1915. MOVNTQ" %%mm0, (%1, %%eax, 2) nt"
  1916. MOVNTQ" %%mm2, 8(%1, %%eax, 2) nt"
  1917. "addl $8, %%eax nt"
  1918. "cmpl %4, %%eax nt"
  1919. " jb 1b nt"
  1920. ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
  1921. : "memory", "%eax"
  1922. );
  1923. #else
  1924. unsigned i;
  1925. for(i=0; i<chromWidth; i++)
  1926. {
  1927. udst[i]  = src[4*i+0];
  1928. ydst[2*i+0]  = src[4*i+1];
  1929. vdst[i]  = src[4*i+2];
  1930. ydst[2*i+1]  = src[4*i+3];
  1931. }
  1932. ydst += lumStride;
  1933. src  += srcStride;
  1934. for(i=0; i<chromWidth; i++)
  1935. {
  1936. ydst[2*i+0]  = src[4*i+1];
  1937. ydst[2*i+1]  = src[4*i+3];
  1938. }
  1939. #endif
  1940. udst += chromStride;
  1941. vdst += chromStride;
  1942. ydst += lumStride;
  1943. src  += srcStride;
  1944. }
  1945. #ifdef HAVE_MMX
  1946. asm volatile(   EMMS" nt"
  1947.          SFENCE" nt"
  1948.          :::"memory");
  1949. #endif
  1950. }
  1951. /**
  1952.  *
  1953.  * height should be a multiple of 2 and width should be a multiple of 2 (if this is a
  1954.  * problem for anyone then tell me, and ill fix it)
  1955.  * chrominance data is only taken from every secound line others are ignored in the C version FIXME write HQ version
  1956.  */
  1957. static inline void RENAME(rgb24toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
  1958. unsigned int width, unsigned int height,
  1959. int lumStride, int chromStride, int srcStride)
  1960. {
  1961. unsigned y;
  1962. const unsigned chromWidth= width>>1;
  1963. #ifdef HAVE_MMX
  1964. for(y=0; y<height-2; y+=2)
  1965. {
  1966. unsigned i;
  1967. for(i=0; i<2; i++)
  1968. {
  1969. asm volatile(
  1970. "movl %2, %%eax nt"
  1971. "movq "MANGLE(bgr2YCoeff)", %%mm6 nt"
  1972. "movq "MANGLE(w1111)", %%mm5 nt"
  1973. "pxor %%mm7, %%mm7 nt"
  1974. "leal (%%eax, %%eax, 2), %%ebx nt"
  1975. ".balign 16 nt"
  1976. "1: nt"
  1977. PREFETCH" 64(%0, %%ebx) nt"
  1978. "movd (%0, %%ebx), %%mm0 nt"
  1979. "movd 3(%0, %%ebx), %%mm1 nt"
  1980. "punpcklbw %%mm7, %%mm0 nt"
  1981. "punpcklbw %%mm7, %%mm1 nt"
  1982. "movd 6(%0, %%ebx), %%mm2 nt"
  1983. "movd 9(%0, %%ebx), %%mm3 nt"
  1984. "punpcklbw %%mm7, %%mm2 nt"
  1985. "punpcklbw %%mm7, %%mm3 nt"
  1986. "pmaddwd %%mm6, %%mm0 nt"
  1987. "pmaddwd %%mm6, %%mm1 nt"
  1988. "pmaddwd %%mm6, %%mm2 nt"
  1989. "pmaddwd %%mm6, %%mm3 nt"
  1990. #ifndef FAST_BGR2YV12
  1991. "psrad $8, %%mm0 nt"
  1992. "psrad $8, %%mm1 nt"
  1993. "psrad $8, %%mm2 nt"
  1994. "psrad $8, %%mm3 nt"
  1995. #endif
  1996. "packssdw %%mm1, %%mm0 nt"
  1997. "packssdw %%mm3, %%mm2 nt"
  1998. "pmaddwd %%mm5, %%mm0 nt"
  1999. "pmaddwd %%mm5, %%mm2 nt"
  2000. "packssdw %%mm2, %%mm0 nt"
  2001. "psraw $7, %%mm0 nt"
  2002. "movd 12(%0, %%ebx), %%mm4 nt"
  2003. "movd 15(%0, %%ebx), %%mm1 nt"
  2004. "punpcklbw %%mm7, %%mm4 nt"
  2005. "punpcklbw %%mm7, %%mm1 nt"
  2006. "movd 18(%0, %%ebx), %%mm2 nt"
  2007. "movd 21(%0, %%ebx), %%mm3 nt"
  2008. "punpcklbw %%mm7, %%mm2 nt"
  2009. "punpcklbw %%mm7, %%mm3 nt"
  2010. "pmaddwd %%mm6, %%mm4 nt"
  2011. "pmaddwd %%mm6, %%mm1 nt"
  2012. "pmaddwd %%mm6, %%mm2 nt"
  2013. "pmaddwd %%mm6, %%mm3 nt"
  2014. #ifndef FAST_BGR2YV12
  2015. "psrad $8, %%mm4 nt"
  2016. "psrad $8, %%mm1 nt"
  2017. "psrad $8, %%mm2 nt"
  2018. "psrad $8, %%mm3 nt"
  2019. #endif
  2020. "packssdw %%mm1, %%mm4 nt"
  2021. "packssdw %%mm3, %%mm2 nt"
  2022. "pmaddwd %%mm5, %%mm4 nt"
  2023. "pmaddwd %%mm5, %%mm2 nt"
  2024. "addl $24, %%ebx nt"
  2025. "packssdw %%mm2, %%mm4 nt"
  2026. "psraw $7, %%mm4 nt"
  2027. "packuswb %%mm4, %%mm0 nt"
  2028. "paddusb "MANGLE(bgr2YOffset)", %%mm0 nt"
  2029. MOVNTQ" %%mm0, (%1, %%eax) nt"
  2030. "addl $8, %%eax nt"
  2031. " js 1b nt"
  2032. : : "r" (src+width*3), "r" (ydst+width), "g" (-width)
  2033. : "%eax", "%ebx"
  2034. );
  2035. ydst += lumStride;
  2036. src  += srcStride;
  2037. }
  2038. src -= srcStride*2;
  2039. asm volatile(
  2040. "movl %4, %%eax nt"
  2041. "movq "MANGLE(w1111)", %%mm5 nt"
  2042. "movq "MANGLE(bgr2UCoeff)", %%mm6 nt"
  2043. "pxor %%mm7, %%mm7 nt"
  2044. "leal (%%eax, %%eax, 2), %%ebx nt"
  2045. "addl %%ebx, %%ebx nt"
  2046. ".balign 16 nt"
  2047. "1: nt"
  2048. PREFETCH" 64(%0, %%ebx) nt"
  2049. PREFETCH" 64(%1, %%ebx) nt"
  2050. #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
  2051. "movq (%0, %%ebx), %%mm0 nt"
  2052. "movq (%1, %%ebx), %%mm1 nt"
  2053. "movq 6(%0, %%ebx), %%mm2 nt"
  2054. "movq 6(%1, %%ebx), %%mm3 nt"
  2055. PAVGB" %%mm1, %%mm0 nt"
  2056. PAVGB" %%mm3, %%mm2 nt"
  2057. "movq %%mm0, %%mm1 nt"
  2058. "movq %%mm2, %%mm3 nt"
  2059. "psrlq $24, %%mm0 nt"
  2060. "psrlq $24, %%mm2 nt"
  2061. PAVGB" %%mm1, %%mm0 nt"
  2062. PAVGB" %%mm3, %%mm2 nt"
  2063. "punpcklbw %%mm7, %%mm0 nt"
  2064. "punpcklbw %%mm7, %%mm2 nt"
  2065. #else
  2066. "movd (%0, %%ebx), %%mm0 nt"
  2067. "movd (%1, %%ebx), %%mm1 nt"
  2068. "movd 3(%0, %%ebx), %%mm2 nt"
  2069. "movd 3(%1, %%ebx), %%mm3 nt"
  2070. "punpcklbw %%mm7, %%mm0 nt"
  2071. "punpcklbw %%mm7, %%mm1 nt"
  2072. "punpcklbw %%mm7, %%mm2 nt"
  2073. "punpcklbw %%mm7, %%mm3 nt"
  2074. "paddw %%mm1, %%mm0 nt"
  2075. "paddw %%mm3, %%mm2 nt"
  2076. "paddw %%mm2, %%mm0 nt"
  2077. "movd 6(%0, %%ebx), %%mm4 nt"
  2078. "movd 6(%1, %%ebx), %%mm1 nt"
  2079. "movd 9(%0, %%ebx), %%mm2 nt"
  2080. "movd 9(%1, %%ebx), %%mm3 nt"
  2081. "punpcklbw %%mm7, %%mm4 nt"
  2082. "punpcklbw %%mm7, %%mm1 nt"
  2083. "punpcklbw %%mm7, %%mm2 nt"
  2084. "punpcklbw %%mm7, %%mm3 nt"
  2085. "paddw %%mm1, %%mm4 nt"
  2086. "paddw %%mm3, %%mm2 nt"
  2087. "paddw %%mm4, %%mm2 nt"
  2088. "psrlw $2, %%mm0 nt"
  2089. "psrlw $2, %%mm2 nt"
  2090. #endif
  2091. "movq "MANGLE(bgr2VCoeff)", %%mm1 nt"
  2092. "movq "MANGLE(bgr2VCoeff)", %%mm3 nt"
  2093. "pmaddwd %%mm0, %%mm1 nt"
  2094. "pmaddwd %%mm2, %%mm3 nt"
  2095. "pmaddwd %%mm6, %%mm0 nt"
  2096. "pmaddwd %%mm6, %%mm2 nt"
  2097. #ifndef FAST_BGR2YV12
  2098. "psrad $8, %%mm0 nt"
  2099. "psrad $8, %%mm1 nt"
  2100. "psrad $8, %%mm2 nt"
  2101. "psrad $8, %%mm3 nt"
  2102. #endif
  2103. "packssdw %%mm2, %%mm0 nt"
  2104. "packssdw %%mm3, %%mm1 nt"
  2105. "pmaddwd %%mm5, %%mm0 nt"
  2106. "pmaddwd %%mm5, %%mm1 nt"
  2107. "packssdw %%mm1, %%mm0 nt" // V1 V0 U1 U0
  2108. "psraw $7, %%mm0 nt"
  2109. #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
  2110. "movq 12(%0, %%ebx), %%mm4 nt"
  2111. "movq 12(%1, %%ebx), %%mm1 nt"
  2112. "movq 18(%0, %%ebx), %%mm2 nt"
  2113. "movq 18(%1, %%ebx), %%mm3 nt"
  2114. PAVGB" %%mm1, %%mm4 nt"
  2115. PAVGB" %%mm3, %%mm2 nt"
  2116. "movq %%mm4, %%mm1 nt"
  2117. "movq %%mm2, %%mm3 nt"
  2118. "psrlq $24, %%mm4 nt"
  2119. "psrlq $24, %%mm2 nt"
  2120. PAVGB" %%mm1, %%mm4 nt"
  2121. PAVGB" %%mm3, %%mm2 nt"
  2122. "punpcklbw %%mm7, %%mm4 nt"
  2123. "punpcklbw %%mm7, %%mm2 nt"
  2124. #else
  2125. "movd 12(%0, %%ebx), %%mm4 nt"
  2126. "movd 12(%1, %%ebx), %%mm1 nt"
  2127. "movd 15(%0, %%ebx), %%mm2 nt"
  2128. "movd 15(%1, %%ebx), %%mm3 nt"
  2129. "punpcklbw %%mm7, %%mm4 nt"
  2130. "punpcklbw %%mm7, %%mm1 nt"
  2131. "punpcklbw %%mm7, %%mm2 nt"
  2132. "punpcklbw %%mm7, %%mm3 nt"
  2133. "paddw %%mm1, %%mm4 nt"
  2134. "paddw %%mm3, %%mm2 nt"
  2135. "paddw %%mm2, %%mm4 nt"
  2136. "movd 18(%0, %%ebx), %%mm5 nt"
  2137. "movd 18(%1, %%ebx), %%mm1 nt"
  2138. "movd 21(%0, %%ebx), %%mm2 nt"
  2139. "movd 21(%1, %%ebx), %%mm3 nt"
  2140. "punpcklbw %%mm7, %%mm5 nt"
  2141. "punpcklbw %%mm7, %%mm1 nt"
  2142. "punpcklbw %%mm7, %%mm2 nt"
  2143. "punpcklbw %%mm7, %%mm3 nt"
  2144. "paddw %%mm1, %%mm5 nt"
  2145. "paddw %%mm3, %%mm2 nt"
  2146. "paddw %%mm5, %%mm2 nt"
  2147. "movq "MANGLE(w1111)", %%mm5 nt"
  2148. "psrlw $2, %%mm4 nt"
  2149. "psrlw $2, %%mm2 nt"
  2150. #endif
  2151. "movq "MANGLE(bgr2VCoeff)", %%mm1 nt"
  2152. "movq "MANGLE(bgr2VCoeff)", %%mm3 nt"
  2153. "pmaddwd %%mm4, %%mm1 nt"
  2154. "pmaddwd %%mm2, %%mm3 nt"
  2155. "pmaddwd %%mm6, %%mm4 nt"
  2156. "pmaddwd %%mm6, %%mm2 nt"
  2157. #ifndef FAST_BGR2YV12
  2158. "psrad $8, %%mm4 nt"
  2159. "psrad $8, %%mm1 nt"
  2160. "psrad $8, %%mm2 nt"
  2161. "psrad $8, %%mm3 nt"
  2162. #endif
  2163. "packssdw %%mm2, %%mm4 nt"
  2164. "packssdw %%mm3, %%mm1 nt"
  2165. "pmaddwd %%mm5, %%mm4 nt"
  2166. "pmaddwd %%mm5, %%mm1 nt"
  2167. "addl $24, %%ebx nt"
  2168. "packssdw %%mm1, %%mm4 nt" // V3 V2 U3 U2
  2169. "psraw $7, %%mm4 nt"
  2170. "movq %%mm0, %%mm1 nt"
  2171. "punpckldq %%mm4, %%mm0 nt"
  2172. "punpckhdq %%mm4, %%mm1 nt"
  2173. "packsswb %%mm1, %%mm0 nt"
  2174. "paddb "MANGLE(bgr2UVOffset)", %%mm0 nt"
  2175. "movd %%mm0, (%2, %%eax) nt"
  2176. "punpckhdq %%mm0, %%mm0 nt"
  2177. "movd %%mm0, (%3, %%eax) nt"
  2178. "addl $4, %%eax nt"
  2179. " js 1b nt"
  2180. : : "r" (src+chromWidth*6), "r" (src+srcStride+chromWidth*6), "r" (udst+chromWidth), "r" (vdst+chromWidth), "g" (-chromWidth)
  2181. : "%eax", "%ebx"
  2182. );
  2183. udst += chromStride;
  2184. vdst += chromStride;
  2185. src  += srcStride*2;
  2186. }
  2187. asm volatile(   EMMS" nt"
  2188. SFENCE" nt"
  2189. :::"memory");
  2190. #else
  2191. y=0;
  2192. #endif
  2193. for(; y<height; y+=2)
  2194. {
  2195. unsigned i;
  2196. for(i=0; i<chromWidth; i++)
  2197. {
  2198. unsigned int b= src[6*i+0];
  2199. unsigned int g= src[6*i+1];
  2200. unsigned int r= src[6*i+2];
  2201. unsigned int Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
  2202. unsigned int V  =  ((RV*r + GV*g + BV*b)>>RGB2YUV_SHIFT) + 128;
  2203. unsigned int U  =  ((RU*r + GU*g + BU*b)>>RGB2YUV_SHIFT) + 128;
  2204. udst[i]  = U;
  2205. vdst[i]  = V;
  2206. ydst[2*i]  = Y;
  2207. b= src[6*i+3];
  2208. g= src[6*i+4];
  2209. r= src[6*i+5];
  2210. Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
  2211. ydst[2*i+1]  = Y;
  2212. }
  2213. ydst += lumStride;
  2214. src  += srcStride;
  2215. for(i=0; i<chromWidth; i++)
  2216. {
  2217. unsigned int b= src[6*i+0];
  2218. unsigned int g= src[6*i+1];
  2219. unsigned int r= src[6*i+2];
  2220. unsigned int Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
  2221. ydst[2*i]  = Y;
  2222. b= src[6*i+3];
  2223. g= src[6*i+4];
  2224. r= src[6*i+5];
  2225. Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
  2226. ydst[2*i+1]  = Y;
  2227. }
  2228. udst += chromStride;
  2229. vdst += chromStride;
  2230. ydst += lumStride;
  2231. src  += srcStride;
  2232. }
  2233. }
  2234. void RENAME(interleaveBytes)(uint8_t *src1, uint8_t *src2, uint8_t *dest,
  2235.     unsigned width, unsigned height, int src1Stride,
  2236.     int src2Stride, int dstStride){
  2237. unsigned h;
  2238. for(h=0; h < height; h++)
  2239. {
  2240. unsigned w;
  2241. #ifdef HAVE_MMX
  2242. #ifdef HAVE_SSE2
  2243. asm(
  2244. "xorl %%eax, %%eax nt"
  2245. "1: nt"
  2246. PREFETCH" 64(%1, %%eax) nt"
  2247. PREFETCH" 64(%2, %%eax) nt"
  2248. "movdqa (%1, %%eax), %%xmm0 nt"
  2249. "movdqa (%1, %%eax), %%xmm1 nt"
  2250. "movdqa (%2, %%eax), %%xmm2 nt"
  2251. "punpcklbw %%xmm2, %%xmm0 nt"
  2252. "punpckhbw %%xmm2, %%xmm1 nt"
  2253. "movntdq %%xmm0, (%0, %%eax, 2) nt"
  2254. "movntdq %%xmm1, 16(%0, %%eax, 2)nt"
  2255. "addl $16, %%eax nt"
  2256. "cmpl %3, %%eax nt"
  2257. " jb 1b nt"
  2258. ::"r"(dest), "r"(src1), "r"(src2), "r" (width-15)
  2259. : "memory", "%eax"
  2260. );
  2261. #else
  2262. asm(
  2263. "xorl %%eax, %%eax nt"
  2264. "1: nt"
  2265. PREFETCH" 64(%1, %%eax) nt"
  2266. PREFETCH" 64(%2, %%eax) nt"
  2267. "movq (%1, %%eax), %%mm0 nt"
  2268. "movq 8(%1, %%eax), %%mm2 nt"
  2269. "movq %%mm0, %%mm1 nt"
  2270. "movq %%mm2, %%mm3 nt"
  2271. "movq (%2, %%eax), %%mm4 nt"
  2272. "movq 8(%2, %%eax), %%mm5 nt"
  2273. "punpcklbw %%mm4, %%mm0 nt"
  2274. "punpckhbw %%mm4, %%mm1 nt"
  2275. "punpcklbw %%mm5, %%mm2 nt"
  2276. "punpckhbw %%mm5, %%mm3 nt"
  2277. MOVNTQ" %%mm0, (%0, %%eax, 2) nt"
  2278. MOVNTQ" %%mm1, 8(%0, %%eax, 2) nt"
  2279. MOVNTQ" %%mm2, 16(%0, %%eax, 2) nt"
  2280. MOVNTQ" %%mm3, 24(%0, %%eax, 2) nt"
  2281. "addl $16, %%eax nt"
  2282. "cmpl %3, %%eax nt"
  2283. " jb 1b nt"
  2284. ::"r"(dest), "r"(src1), "r"(src2), "r" (width-15)
  2285. : "memory", "%eax"
  2286. );
  2287. #endif
  2288. for(w= (width&(~15)); w < width; w++)
  2289. {
  2290. dest[2*w+0] = src1[w];
  2291. dest[2*w+1] = src2[w];
  2292. }
  2293. #else
  2294. for(w=0; w < width; w++)
  2295. {
  2296. dest[2*w+0] = src1[w];
  2297. dest[2*w+1] = src2[w];
  2298. }
  2299. #endif
  2300. dest += dstStride;
  2301.                 src1 += src1Stride;
  2302.                 src2 += src2Stride;
  2303. }
  2304. #ifdef HAVE_MMX
  2305. asm(
  2306. EMMS" nt"
  2307. SFENCE" nt"
  2308. ::: "memory"
  2309. );
  2310. #endif
  2311. }
  2312. static inline void RENAME(vu9_to_vu12)(const uint8_t *src1, const uint8_t *src2,
  2313. uint8_t *dst1, uint8_t *dst2,
  2314. unsigned width, unsigned height,
  2315. int srcStride1, int srcStride2,
  2316. int dstStride1, int dstStride2)
  2317. {
  2318.     unsigned int y,x,h;
  2319.     int w;
  2320.     w=width/2; h=height/2;
  2321. #ifdef HAVE_MMX
  2322.     asm volatile(
  2323. PREFETCH" %0nt"
  2324. PREFETCH" %1nt"
  2325. ::"m"(*(src1+srcStride1)),"m"(*(src2+srcStride2)):"memory");
  2326. #endif
  2327.     for(y=0;y<h;y++){
  2328. const uint8_t* s1=src1+srcStride1*(y>>1);
  2329. uint8_t* d=dst1+dstStride1*y;
  2330. x=0;
  2331. #ifdef HAVE_MMX
  2332. for(;x<w-31;x+=32)
  2333. {
  2334.     asm volatile(
  2335. PREFETCH" 32%1nt"
  2336.         "movq %1, %%mm0nt"
  2337.         "movq 8%1, %%mm2nt"
  2338.         "movq 16%1, %%mm4nt"
  2339.         "movq 24%1, %%mm6nt"
  2340.         "movq %%mm0, %%mm1nt"
  2341.         "movq %%mm2, %%mm3nt"
  2342.         "movq %%mm4, %%mm5nt"
  2343.         "movq %%mm6, %%mm7nt"
  2344. "punpcklbw %%mm0, %%mm0nt"
  2345. "punpckhbw %%mm1, %%mm1nt"
  2346. "punpcklbw %%mm2, %%mm2nt"
  2347. "punpckhbw %%mm3, %%mm3nt"
  2348. "punpcklbw %%mm4, %%mm4nt"
  2349. "punpckhbw %%mm5, %%mm5nt"
  2350. "punpcklbw %%mm6, %%mm6nt"
  2351. "punpckhbw %%mm7, %%mm7nt"
  2352. MOVNTQ" %%mm0, %0nt"
  2353. MOVNTQ" %%mm1, 8%0nt"
  2354. MOVNTQ" %%mm2, 16%0nt"
  2355. MOVNTQ" %%mm3, 24%0nt"
  2356. MOVNTQ" %%mm4, 32%0nt"
  2357. MOVNTQ" %%mm5, 40%0nt"
  2358. MOVNTQ" %%mm6, 48%0nt"
  2359. MOVNTQ" %%mm7, 56%0"
  2360. :"=m"(d[2*x])
  2361. :"m"(s1[x])
  2362. :"memory");
  2363. }
  2364. #endif
  2365. for(;x<w;x++) d[2*x]=d[2*x+1]=s1[x];
  2366.     }
  2367.     for(y=0;y<h;y++){
  2368. const uint8_t* s2=src2+srcStride2*(y>>1);
  2369. uint8_t* d=dst2+dstStride2*y;
  2370. x=0;
  2371. #ifdef HAVE_MMX
  2372. for(;x<w-31;x+=32)
  2373. {
  2374.     asm volatile(
  2375. PREFETCH" 32%1nt"
  2376.         "movq %1, %%mm0nt"
  2377.         "movq 8%1, %%mm2nt"
  2378.         "movq 16%1, %%mm4nt"
  2379.         "movq 24%1, %%mm6nt"
  2380.         "movq %%mm0, %%mm1nt"
  2381.         "movq %%mm2, %%mm3nt"
  2382.         "movq %%mm4, %%mm5nt"
  2383.         "movq %%mm6, %%mm7nt"
  2384. "punpcklbw %%mm0, %%mm0nt"
  2385. "punpckhbw %%mm1, %%mm1nt"
  2386. "punpcklbw %%mm2, %%mm2nt"
  2387. "punpckhbw %%mm3, %%mm3nt"
  2388. "punpcklbw %%mm4, %%mm4nt"
  2389. "punpckhbw %%mm5, %%mm5nt"
  2390. "punpcklbw %%mm6, %%mm6nt"
  2391. "punpckhbw %%mm7, %%mm7nt"
  2392. MOVNTQ" %%mm0, %0nt"
  2393. MOVNTQ" %%mm1, 8%0nt"
  2394. MOVNTQ" %%mm2, 16%0nt"
  2395. MOVNTQ" %%mm3, 24%0nt"
  2396. MOVNTQ" %%mm4, 32%0nt"
  2397. MOVNTQ" %%mm5, 40%0nt"
  2398. MOVNTQ" %%mm6, 48%0nt"
  2399. MOVNTQ" %%mm7, 56%0"
  2400. :"=m"(d[2*x])
  2401. :"m"(s2[x])
  2402. :"memory");
  2403. }
  2404. #endif
  2405. for(;x<w;x++) d[2*x]=d[2*x+1]=s2[x];
  2406.     }
  2407. #ifdef HAVE_MMX
  2408. asm(
  2409. EMMS" nt"
  2410. SFENCE" nt"
  2411. ::: "memory"
  2412. );
  2413. #endif
  2414. }
  2415. static inline void RENAME(yvu9_to_yuy2)(const uint8_t *src1, const uint8_t *src2, const uint8_t *src3,
  2416. uint8_t *dst,
  2417. unsigned width, unsigned height,
  2418. int srcStride1, int srcStride2,
  2419. int srcStride3, int dstStride)
  2420. {
  2421.     unsigned y,x,w,h;
  2422.     w=width/2; h=height;
  2423.     for(y=0;y<h;y++){
  2424. const uint8_t* yp=src1+srcStride1*y;
  2425. const uint8_t* up=src2+srcStride2*(y>>2);
  2426. const uint8_t* vp=src3+srcStride3*(y>>2);
  2427. uint8_t* d=dst+dstStride*y;
  2428. x=0;
  2429. #ifdef HAVE_MMX
  2430. for(;x<w-7;x+=8)
  2431. {
  2432.     asm volatile(
  2433. PREFETCH" 32(%1, %0)nt"
  2434. PREFETCH" 32(%2, %0)nt"
  2435. PREFETCH" 32(%3, %0)nt"
  2436. "movq (%1, %0, 4), %%mm0nt"       /* Y0Y1Y2Y3Y4Y5Y6Y7 */
  2437. "movq (%2, %0), %%mm1nt"       /* U0U1U2U3U4U5U6U7 */
  2438. "movq (%3, %0), %%mm2nt"      /* V0V1V2V3V4V5V6V7 */
  2439. "movq %%mm0, %%mm3nt"    /* Y0Y1Y2Y3Y4Y5Y6Y7 */
  2440. "movq %%mm1, %%mm4nt"    /* U0U1U2U3U4U5U6U7 */
  2441. "movq %%mm2, %%mm5nt"    /* V0V1V2V3V4V5V6V7 */
  2442. "punpcklbw %%mm1, %%mm1nt" /* U0U0 U1U1 U2U2 U3U3 */
  2443. "punpcklbw %%mm2, %%mm2nt" /* V0V0 V1V1 V2V2 V3V3 */
  2444. "punpckhbw %%mm4, %%mm4nt" /* U4U4 U5U5 U6U6 U7U7 */
  2445. "punpckhbw %%mm5, %%mm5nt" /* V4V4 V5V5 V6V6 V7V7 */
  2446. "movq %%mm1, %%mm6nt"
  2447. "punpcklbw %%mm2, %%mm1nt" /* U0V0 U0V0 U1V1 U1V1*/
  2448. "punpcklbw %%mm1, %%mm0nt" /* Y0U0 Y1V0 Y2U0 Y3V0*/
  2449. "punpckhbw %%mm1, %%mm3nt" /* Y4U1 Y5V1 Y6U1 Y7V1*/
  2450. MOVNTQ" %%mm0, (%4, %0, 8)nt"
  2451. MOVNTQ" %%mm3, 8(%4, %0, 8)nt"
  2452. "punpckhbw %%mm2, %%mm6nt" /* U2V2 U2V2 U3V3 U3V3*/
  2453. "movq 8(%1, %0, 4), %%mm0nt"
  2454. "movq %%mm0, %%mm3nt"
  2455. "punpcklbw %%mm6, %%mm0nt" /* Y U2 Y V2 Y U2 Y V2*/
  2456. "punpckhbw %%mm6, %%mm3nt" /* Y U3 Y V3 Y U3 Y V3*/
  2457. MOVNTQ" %%mm0, 16(%4, %0, 8)nt"
  2458. MOVNTQ" %%mm3, 24(%4, %0, 8)nt"
  2459. "movq %%mm4, %%mm6nt"
  2460. "movq 16(%1, %0, 4), %%mm0nt"
  2461. "movq %%mm0, %%mm3nt"
  2462. "punpcklbw %%mm5, %%mm4nt"
  2463. "punpcklbw %%mm4, %%mm0nt" /* Y U4 Y V4 Y U4 Y V4*/
  2464. "punpckhbw %%mm4, %%mm3nt" /* Y U5 Y V5 Y U5 Y V5*/
  2465. MOVNTQ" %%mm0, 32(%4, %0, 8)nt"
  2466. MOVNTQ" %%mm3, 40(%4, %0, 8)nt"
  2467. "punpckhbw %%mm5, %%mm6nt"
  2468. "movq 24(%1, %0, 4), %%mm0nt"
  2469. "movq %%mm0, %%mm3nt"
  2470. "punpcklbw %%mm6, %%mm0nt" /* Y U6 Y V6 Y U6 Y V6*/
  2471. "punpckhbw %%mm6, %%mm3nt" /* Y U7 Y V7 Y U7 Y V7*/
  2472. MOVNTQ" %%mm0, 48(%4, %0, 8)nt"
  2473. MOVNTQ" %%mm3, 56(%4, %0, 8)nt"
  2474. : "+r" (x)
  2475.                 : "r"(yp), "r" (up), "r"(vp), "r"(d)
  2476. :"memory");
  2477. }
  2478. #endif
  2479. for(; x<w; x++)
  2480. {
  2481.     const int x2= x<<2;
  2482.     d[8*x+0]=yp[x2];
  2483.     d[8*x+1]=up[x];
  2484.     d[8*x+2]=yp[x2+1];
  2485.     d[8*x+3]=vp[x];
  2486.     d[8*x+4]=yp[x2+2];
  2487.     d[8*x+5]=up[x];
  2488.     d[8*x+6]=yp[x2+3];
  2489.     d[8*x+7]=vp[x];
  2490. }
  2491.     }
  2492. #ifdef HAVE_MMX
  2493. asm(
  2494. EMMS" nt"
  2495. SFENCE" nt"
  2496. ::: "memory"
  2497. );
  2498. #endif
  2499. }