yuvalpha.c
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:29k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "hxtypes.h"
  36. #include "hxcom.h"
  37. #include "env.h"
  38. #include "yuvalpha.h"
  39. #ifdef _USE_MMX_BLENDERS
  40. //MMX alphablending only available on linux and windows right now.
  41. //Should work just fine on any IA plaform though (intel solaris for example)
  42. #include "mmx_util.h" //for checkMmxAvailablity()
  43. BOOL z_bMMXAvailable = FALSE;
  44. BOOL z_bCheckedForMMX = FALSE;
  45. #endif
  46. /////////////////////////////////////////////////////////////
  47. // Note:  Output buffer can be the same as one of the input
  48. //        buffers for I420 and YV12 output only.  Common 
  49. //        input/output buffer must have same pitch and lines
  50. //        width and height.
  51. /////////////////////////////////////////////////////////////
  52. /////////////////////////////////////////////////////////////
  53. //
  54. // Define the bit offsets for components in both
  55. // YUY2 and UYVU color formats.
  56. //
  57. /////////////////////////////////////////////////////////////
  58. #if BYTE_ORDER == LITTLE_ENDIAN
  59. // YUY2
  60. #define YUY2_Y0_SHIFT 0
  61. #define YUY2_U_SHIFT  8
  62. #define YUY2_Y1_SHIFT 16
  63. #define YUY2_V_SHIFT  24
  64. // UYVY
  65. #define UYVY_U_SHIFT  0
  66. #define UYVY_Y0_SHIFT 8
  67. #define UYVY_V_SHIFT  16
  68. #define UYVY_Y1_SHIFT 24
  69. #else /* BYTE_ORDER != LITTLE_ENDIAN */
  70. // YUY2
  71. #define YUY2_Y0_SHIFT 24
  72. #define YUY2_U_SHIFT  16
  73. #define YUY2_Y1_SHIFT 8
  74. #define YUY2_V_SHIFT  0
  75. // UYVY
  76. #define UYVY_U_SHIFT  24
  77. #define UYVY_Y0_SHIFT 16
  78. #define UYVY_V_SHIFT  8
  79. #define UYVY_Y1_SHIFT 0
  80. #endif
  81. /////////////////////////////////////////////////////////////
  82. //
  83. // I420andYUVAtoI420orYV12
  84. //
  85. // This function alpha-blends two I420 buffers into a third
  86. // I420 or YV12 buffer using the alpha info tacked to the 
  87. // end of the second I420 buffer
  88. //
  89. // The alpha used for chroma is merely one (lower-right) of
  90. // the alpha used in the corresponding 2x2 luma pels.
  91. //
  92. /////////////////////////////////////////////////////////////
  93. int I420andYUVAtoI420orYV12 (
  94. unsigned char *src1_ptr, int src1_pels,   int src1_lines,  int src1_pitch,
  95.                          int src1_startx, int src1_starty,
  96. unsigned char *src2_ptr, int src2_pels,   int src2_lines,  int src2_pitch,
  97.                          int src2_startx, int src2_starty,
  98. unsigned char *dest_ptr, int dest_pels,   int dest_lines,  int dest_pitch,
  99.                          int dest_startx, int dest_starty,
  100. int width,  int height,  int output_format)
  101. {
  102. int i, j;
  103. unsigned char *sy1, *su1, *sv1;
  104. unsigned char *sy2, *su2, *sv2, *sa2;
  105. unsigned char *dy, *du, *dv;
  106. // Initialize color plane pointers to beginning of image
  107. sy1 = src1_ptr;
  108. su1 = src1_ptr + src1_lines * src1_pitch;
  109. sv1 = su1 + src1_lines * src1_pitch / 4;
  110. sy2 = src2_ptr;
  111. su2 = src2_ptr + src2_lines * src2_pitch;
  112. sv2 = su2 + src2_lines * src2_pitch / 4;
  113. sa2 = sv2 + src2_lines * src2_pitch / 4;
  114. dy  = dest_ptr;
  115. if (output_format == CID_I420)
  116. {
  117. du  = dest_ptr + dest_lines * dest_pitch;
  118. dv  = du + dest_lines * dest_pitch / 4;
  119. }
  120. else if (output_format == CID_YV12)
  121. {
  122. dv  = dest_ptr + dest_lines * dest_pitch;
  123. du  = dv + dest_lines * dest_pitch / 4;
  124. }
  125. else
  126. {
  127. return -1;
  128. }
  129. // Move color plane pointers to start points
  130. sy1 += src1_starty * src1_pitch + src1_startx;
  131. su1 += (src1_starty * src1_pitch / 4) + src1_startx / 2;
  132. sv1 += (src1_starty * src1_pitch / 4) + src1_startx / 2;
  133. sy2 += src2_starty * src2_pitch + src2_startx;
  134. su2 += (src2_starty * src2_pitch / 4) + src2_startx / 2;
  135. sv2 += (src2_starty * src2_pitch / 4) + src2_startx / 2;
  136. sa2 += src2_starty * src2_pitch + src2_startx;
  137. dy += dest_starty * dest_pitch + dest_startx;
  138. du += (dest_starty * dest_pitch / 4) + dest_startx / 2;
  139. dv += (dest_starty * dest_pitch / 4) + dest_startx / 2;
  140. for (i = 0; i < height; i += 2)
  141. {
  142. // First line
  143. for (j = 0; j < width - 3; j += 4)
  144. {
  145. int x1, x2;
  146. // Y
  147. x1 = *(sy1 + 0);
  148. x2 = *(sy2 + 0);
  149. x1 -= x2;
  150. x1 *= *(sa2 + 0);
  151. x1 >>= 8;
  152. x1 += x2;
  153. *(dy + 0) = x1;
  154. x1 = *(sy1 + 1);
  155. x2 = *(sy2 + 1);
  156. x1 -= x2;
  157. x1 *= *(sa2 + 1);
  158. x1 >>= 8;
  159. x1 += x2;
  160. *(dy + 1) = x1;
  161. x1 = *(sy1 + 2);
  162. x2 = *(sy2 + 2);
  163. x1 -= x2;
  164. x1 *= *(sa2 + 2);
  165. x1 >>= 8;
  166. x1 += x2;
  167. *(dy + 2) = x1;
  168. x1 = *(sy1 + 3);
  169. x2 = *(sy2 + 3);
  170. x1 -= x2;
  171. x1 *= *(sa2 + 3);
  172. x1 >>= 8;
  173. x1 += x2;
  174. *(dy + 3) = x1;
  175. sy1 += 4;
  176. sy2 += 4;
  177. sa2 += 4;
  178. dy  += 4;
  179. }
  180. while (j < width)
  181. {
  182. int x1, x2;
  183. // Y
  184. x1 = *sy1++;
  185. x2 = *sy2++;
  186. x1 -= x2;
  187. x1 *= *sa2++;
  188. x1 >>= 8;
  189. x1 += x2;
  190. *dy++ = x1; 
  191. j++;
  192. }
  193. // move to next line
  194. sy1 += src1_pitch - width;
  195. sy2 += src2_pitch - width;
  196. sa2 += src2_pitch - width;
  197. dy  += dest_pitch - width;
  198. // Second line
  199. for (j = 0; j < width; j += 2)
  200. {
  201. int x1, x2, x1b, a;
  202. // Y
  203. x1 = *(sy1 + 0);
  204. x2 = *(sy2 + 0);
  205. x1 -= x2;
  206. x1 *= *(sa2 + 0);
  207. x1 >>= 8;
  208. x1 += x2;
  209. *(dy + 0) = x1;
  210. // Y
  211. x1 = *(sy1 + 1);
  212. x2 = *(sy2 + 1);
  213. x1 -= x2;
  214. a  = *(sa2 + 1);
  215. x1 *= a;
  216. x1 >>= 8;
  217. x1 += x2;
  218. *(dy + 1) = x1; 
  219. //We need to do something with the four alpha values
  220. //and this chroma value. We can average/mean/max/min?????
  221. //Avaerage alpha values....
  222. a += *(sa2+0);
  223. a += *((sa2-src2_pitch)+0);
  224. a += *((sa2-src2_pitch)+1);
  225. a >>= 2;
  226. //Max/Min?
  227. //a = max( *(sa2+0), *(sa2+1));
  228. sy1 += 2;
  229. sy2 += 2;
  230. sa2 += 2;
  231. dy  += 2;
  232. // U
  233. x1 = *su1++;
  234. x2 = *su2++;
  235. x1 -= x2;
  236. x1 *= a;
  237. x1 >>= 8;
  238. x1 += x2;
  239. // V
  240. x1b = *sv1++;
  241. x2  = *sv2++;
  242. x1b -= x2;
  243. x1b *= a;
  244. x1b >>= 8;
  245. x1b += x2;
  246. *du++ = x1;     // postpone store to allow inplace YV12
  247. *dv++ = x1b;
  248. }
  249. // move to next line
  250. sy1 += src1_pitch - width;
  251. su1 += (src1_pitch - width) / 2;
  252. sv1 += (src1_pitch - width) / 2;
  253. sy2 += src2_pitch - width;
  254. su2 += (src2_pitch - width) / 2;
  255. sv2 += (src2_pitch - width) / 2;
  256. sa2 += src2_pitch - width;
  257. dy  += dest_pitch - width;
  258. du  += (dest_pitch - width) / 2;
  259. dv  += (dest_pitch - width) / 2;
  260.                 
  261. /*                  sy1 = src1_ptr; */
  262. /*                  su1 = src1_ptr + src1_lines * src1_pitch; */
  263. /*                  sv1 = su1 + src1_lines * src1_pitch / 4; */
  264.                 
  265. /*                  sy2 = src2_ptr; */
  266. /*                  su2 = src2_ptr + src2_lines * src2_pitch; */
  267. /*                  sv2 = su2 + src2_lines * src2_pitch / 4; */
  268. /*                  sa2 = sv2 + src2_lines * src2_pitch / 4; */
  269. /*                  dy  = dest_ptr; */
  270.                 
  271. /*                  if (output_format == CID_I420) */
  272. /*                  { */
  273. /*                      du  = dest_ptr + dest_lines * dest_pitch; */
  274. /*                      dv  = du + dest_lines * dest_pitch / 4; */
  275. /*                  } */
  276. /*                  else if (output_format == CID_YV12) */
  277. /*                  { */
  278. /*                      dv  = dest_ptr + dest_lines * dest_pitch; */
  279. /*                      du  = dv + dest_lines * dest_pitch / 4; */
  280. /*                  } */
  281.         
  282. /*                  sy1 +=  (src1_starty+i) * src1_pitch + src1_startx; */
  283. /*                  su1 += ((src1_starty+i) * src1_pitch / 4) + src1_startx / 2; */
  284. /*                  sv1 += ((src1_starty+i) * src1_pitch / 4) + src1_startx / 2; */
  285.                 
  286. /*                  sy2 +=  (src2_starty+i) * src2_pitch + src2_startx; */
  287. /*                  su2 += ((src2_starty+i) * src2_pitch / 4) + src2_startx / 2; */
  288. /*                  sv2 += ((src2_starty+i) * src2_pitch / 4) + src2_startx / 2; */
  289. /*                  sa2 +=  (src2_starty+i) * src2_pitch + src2_startx; */
  290.                 
  291. /*                  dy +=  (dest_starty+i) * dest_pitch + dest_startx; */
  292. /*                  du += ((dest_starty+i) * dest_pitch / 4) + dest_startx / 2; */
  293. /*                  dv += ((dest_starty+i) * dest_pitch / 4) + dest_startx / 2; */
  294. }
  295. return 0;
  296. }
  297. /////////////////////////////////////////////////////////////
  298. //
  299. // I420andYUVAtoYUY2
  300. //
  301. // This function alpha-blends two I420 buffers into a third
  302. // YUY2 buffer using the alpha info tacked to the 
  303. // end of the second I420 buffer
  304. //
  305. /////////////////////////////////////////////////////////////
  306. int I420andYUVAtoYUY2 (
  307. unsigned char *src1_ptr, int src1_pels,   int src1_lines,  int src1_pitch,
  308.                          int src1_startx, int src1_starty,
  309. unsigned char *src2_ptr, int src2_pels,   int src2_lines,  int src2_pitch,
  310.                          int src2_startx, int src2_starty,
  311. unsigned char *dest_ptr, int dest_pels,   int dest_lines,  int dest_pitch,
  312.                          int dest_startx, int dest_starty,
  313. int width,  int height)
  314. {
  315. int i, j;
  316. unsigned char *sy11, *sy12, *su1, *sv1;
  317. unsigned char *sy21, *sy22, *su2, *sv2, *sa21, *sa22;
  318. unsigned int  *dst1, *dst2;
  319. sy11 = src1_ptr;
  320. su1  = src1_ptr + src1_lines * src1_pitch;
  321. sv1  = su1 + src1_lines * src1_pitch / 4;
  322. sy21 = src2_ptr;
  323. su2  = src2_ptr + src2_lines * src2_pitch;
  324. sv2  = su2 + src2_lines * src2_pitch / 4;
  325. sa21 = sv2 + src2_lines * src2_pitch / 4;
  326. dst1 = (unsigned int *)(dest_ptr);
  327. // Move color planes to start point
  328. sy11 += src1_starty * src1_pitch + src1_startx;
  329. sy12  = sy11 + src1_pitch;
  330. su1  += src1_starty * src1_pitch / 4 + src1_startx / 2;
  331. sv1  += src1_starty * src1_pitch / 4 + src1_startx / 2;
  332. sy21 += src2_starty * src2_pitch + src2_startx;
  333. sy22  = sy21 + src2_pitch;
  334. su2  += src2_starty * src2_pitch / 4 + src2_startx / 2;
  335. sv2  += src2_starty * src2_pitch / 4 + src2_startx / 2;
  336. sa21 += src2_starty * src2_pitch + src2_startx;
  337. sa22  = sa21 + src2_pitch;
  338. dst1 += dest_starty * dest_pitch / 4 + dest_startx / 2;
  339. dst2  = dst1 + dest_pitch / 4;
  340. for (i = 0; i < height / 2; i++)
  341. {
  342. for (j = 0; j < width / 2; j++)
  343. {
  344. int x1, x2, a1, a2, d;
  345. int u1, u2, v1, v2;
  346. // First line
  347. // Y0
  348. x1 = *(sy11 + 0);
  349. x2 = *(sy21 + 0);
  350. x1 -= x2;
  351. a1 = *(sa21 + 0);
  352. x1 *= a1;
  353. x1 >>= 8;
  354. x1 += x2;
  355. d = (x1 << YUY2_Y0_SHIFT);
  356. // Y1
  357. x1 = *(sy11 + 1);
  358. x2 = *(sy21 + 1);
  359. x1 -= x2;
  360. a2 = *(sa21 + 1);
  361. x1 *= a2;
  362. x1 >>= 8;
  363. x1 += x2;
  364. d |= (x1 << YUY2_Y1_SHIFT);
  365. sy11 += 2;
  366. sy21 += 2;
  367. sa21 += 2;
  368. // Average Alphas
  369. a1 += a2;
  370. a1 >>= 1;
  371. // U
  372. x1 = u1 = *su1;
  373. x2 = u2 = *su2;
  374. x1 -= x2;
  375. x1 *= a1;
  376. x1 >>= 8;
  377. x1 += x2;
  378. d |= (x1 << YUY2_U_SHIFT);
  379. // V
  380. x1 = v1 = *sv1;
  381. x2 = v2 = *sv2;
  382. x1 -= x2;
  383. x1 *= a1;
  384. x1 >>= 8;
  385. x1 += x2;
  386. d |= (x1 << YUY2_V_SHIFT);
  387. su1++;
  388. su2++;
  389. sv1++;
  390. sv2++;
  391. // Store YUY2 pel
  392. *dst1++ = d;
  393. // Second line
  394. // Y0
  395. x1 = *(sy12 + 0);
  396. x2 = *(sy22 + 0);
  397. x1 -= x2;
  398. a1 = *(sa22 + 0);
  399. x1 *= a1;
  400. x1 >>= 8;
  401. x1 += x2;
  402. d = (x1 << YUY2_Y0_SHIFT);
  403. // Y1
  404. x1 = *(sy12 + 1);
  405. x2 = *(sy22 + 1);
  406. x1 -= x2;
  407. a2 = *(sa22 + 1);
  408. x1 *= a2;
  409. x1 >>= 8;
  410. x1 += x2;
  411. d |= (x1 << YUY2_Y1_SHIFT);
  412. sy12 += 2;
  413. sy22 += 2;
  414. sa22 += 2;
  415. // Average Alphas
  416. a1 += a2;
  417. a1 >>= 1;
  418. // U
  419. u1 -= u2;
  420. u1 *= a1;
  421. u1 >>= 8;
  422. u1 += u2;
  423. d |= (u1 << YUY2_U_SHIFT);
  424. // V
  425. v1 -= v2;
  426. v1 *= a1;
  427. v1 >>= 8;
  428. v1 += v2;
  429. d |= (v1 << YUY2_V_SHIFT);
  430. // Store YUY2 pel
  431. *dst2++ = d;
  432. }
  433. // move down two lines
  434. sy11 += 2 * src1_pitch - width;
  435. sy12 += 2 * src1_pitch - width;
  436. su1 += (src1_pitch - width) / 2;
  437. sv1 += (src1_pitch - width) / 2;
  438. sy21 += 2 * src2_pitch - width;
  439. sy22 += 2 * src2_pitch - width;
  440. su2 += (src2_pitch - width) / 2;
  441. sv2 += (src2_pitch - width) / 2;
  442. sa21 += 2 * src2_pitch - width;
  443. sa22 += 2 * src2_pitch - width;
  444. dst1 += (dest_pitch / 2) - (width / 2);
  445. dst2 += (dest_pitch / 2) - (width / 2);
  446. }
  447. return 0;
  448. }
  449. /////////////////////////////////////////////////////////////
  450. //
  451. // I420andYUVAtoUYVY
  452. //
  453. // This function alpha-blends two I420 buffers into a third
  454. // UYVY buffer using the alpha info tacked to the 
  455. // end of the second I420 buffer
  456. //
  457. /////////////////////////////////////////////////////////////
  458. int I420andYUVAtoUYVY (
  459. unsigned char *src1_ptr, int src1_pels,   int src1_lines,  int src1_pitch,
  460.                          int src1_startx, int src1_starty,
  461. unsigned char *src2_ptr, int src2_pels,   int src2_lines,  int src2_pitch,
  462.                          int src2_startx, int src2_starty,
  463. unsigned char *dest_ptr, int dest_pels,   int dest_lines,  int dest_pitch,
  464.                          int dest_startx, int dest_starty,
  465. int width,  int height)
  466. {
  467. int i, j;
  468. unsigned char *sy11, *sy12, *su1, *sv1;
  469. unsigned char *sy21, *sy22, *su2, *sv2, *sa21, *sa22;
  470. unsigned int  *dst1, *dst2;
  471. // Initialize color plane pointers
  472. sy11 = src1_ptr;
  473. su1  = src1_ptr + src1_lines * src1_pitch;
  474. sv1  = su1 + src1_lines * src1_pitch / 4;
  475. sy21 = src2_ptr;
  476. su2  = src2_ptr + src2_lines * src2_pitch;
  477. sv2  = su2 + src2_lines * src2_pitch / 4;
  478. sa21 = sv2 + src2_lines * src2_pitch / 4;
  479. dst1 = (unsigned int *)(dest_ptr);
  480. // Move color planes to start point
  481. sy11 += src1_starty * src1_pitch + src1_startx;
  482. sy12  = sy11 + src1_pitch;
  483. su1  += src1_starty * src1_pitch / 4 + src1_startx / 2;
  484. sv1  += src1_starty * src1_pitch / 4 + src1_startx / 2;
  485. sy21 += src2_starty * src2_pitch + src2_startx;
  486. sy22  = sy21 + src2_pitch;
  487. su2  += src2_starty * src2_pitch / 4 + src2_startx / 2;
  488. sv2  += src2_starty * src2_pitch / 4 + src2_startx / 2;
  489. sa21 += src2_starty * src2_pitch + src2_startx;
  490. sa22  = sa21 + src2_pitch;
  491. dst1 += dest_starty * dest_pitch / 4 + dest_startx / 2;
  492. dst2  = dst1 + dest_pitch / 4;
  493. for (i = 0; i < height / 2; i++)
  494. {
  495. for (j = 0; j < width / 2; j++)
  496. {
  497. int x1, x2, a1, a2, d;
  498. int u1, u2, v1, v2;
  499. // First line
  500. // Y0
  501. x1 = *(sy11 + 0);
  502. x2 = *(sy21 + 0);
  503. x1 -= x2;
  504. a1 = *(sa21 + 0);
  505. x1 *= a1;
  506. x1 >>= 8;
  507. x1 += x2;
  508. d = (x1 << UYVY_Y0_SHIFT);
  509. // Y1
  510. x1 = *(sy11 + 1);
  511. x2 = *(sy21 + 1);
  512. x1 -= x2;
  513. a2 = *(sa21 + 1);
  514. x1 *= a2; 
  515. x1 >>= 8;
  516. x1 += x2;
  517. d |= (x1 << UYVY_Y1_SHIFT);
  518. sy11 += 2;
  519. sy21 += 2;
  520. sa21 += 2;
  521. // Average Alphas
  522. a1 += a2;
  523. a1 >>= 1;
  524. // U
  525. x1 = u1 = *su1;
  526. x2 = u2 = *su2;
  527. x1 -= x2;
  528. x1 *= a1;
  529. x1 >>= 8;
  530. x1 += x2;
  531. d |= (x1 << UYVY_U_SHIFT);
  532. // V
  533. x1 = v1 = *sv1;
  534. x2 = v2 = *sv2;
  535. x1 -= x2;
  536. x1 *= a1;
  537. x1 >>= 8;
  538. x1 += x2;
  539. d |= (x1 << UYVY_V_SHIFT);
  540. su1++;
  541. su2++;
  542. sv1++;
  543. sv2++;
  544. // Store YUY2 pel
  545. *dst1++ = d;
  546. // Second line
  547. // Y0
  548. x1 = *(sy12 + 0);
  549. x2 = *(sy22 + 0);
  550. x1 -= x2;
  551. a1 = *(sa22 + 0);
  552. x1 *= a1;
  553. x1 >>= 8;
  554. x1 += x2;
  555. d = (x1 << UYVY_Y0_SHIFT);
  556. // Y1
  557. x1 = *(sy12 + 1);
  558. x2 = *(sy22 + 1);
  559. x1 -= x2;
  560. a2 = *(sa22 + 1);
  561. x1 *= a2;
  562. x1 >>= 8;
  563. x1 += x2;
  564. d |= (x1 << UYVY_Y1_SHIFT);
  565. sy12 += 2;
  566. sy22 += 2;
  567. sa22 += 2;
  568. // Average Alphas
  569. a1 += a2;
  570. a1 >>= 1;
  571. // U
  572. u1 -= u2;
  573. u1 *= a1;
  574. u1 >>= 8;
  575. u1 += u2;
  576. d |= (u1 << UYVY_U_SHIFT);
  577. // V
  578. v1 -= v2;
  579. v1 *= a1;
  580. v1 >>= 8;
  581. v1 += v2;
  582. d |= (v1 << UYVY_V_SHIFT);
  583. // Store YUY2 pel
  584. *dst2++ = d;
  585. }
  586. // move down two lines
  587. sy11 += 2 * src1_pitch - width;
  588. sy12 += 2 * src1_pitch - width;
  589. su1 += (src1_pitch - width) / 2;
  590. sv1 += (src1_pitch - width) / 2;
  591. sy21 += 2 * src2_pitch - width;
  592. sy22 += 2 * src2_pitch - width;
  593. su2 += (src2_pitch - width) / 2;
  594. sv2 += (src2_pitch - width) / 2;
  595. sa21 += 2 * src2_pitch - width;
  596. sa22 += 2 * src2_pitch - width;
  597. dst1 += (dest_pitch / 2) - (width / 2);
  598. dst2 += (dest_pitch / 2) - (width / 2);
  599. }
  600. return 0;
  601. }
  602. /////////////////////////////////////////////////////////////
  603. //
  604. // I420andYUVAtoI420
  605. //
  606. // This function alpha-blends two I420 buffers into a third
  607. // I420 buffer using the alpha info tacked to the 
  608. // end of the second I420 buffer
  609. //
  610. /////////////////////////////////////////////////////////////
  611. int I420andYUVAtoI420 (
  612. unsigned char *src1_ptr, int src1_pels,   int src1_lines,  int src1_pitch,
  613.                          int src1_startx, int src1_starty,
  614. unsigned char *src2_ptr, int src2_pels,   int src2_lines,  int src2_pitch,
  615.                          int src2_startx, int src2_starty,
  616. unsigned char *dest_ptr, int dest_pels,   int dest_lines,  int dest_pitch,
  617.                          int dest_startx, int dest_starty,
  618. int width,  int height)
  619. {
  620. return I420andYUVAtoI420orYV12 (
  621. src1_ptr, src1_pels, src1_lines, src1_pitch, src1_startx, src1_starty,
  622. src2_ptr, src2_pels, src2_lines, src2_pitch, src2_startx, src2_starty,
  623. dest_ptr, dest_pels, dest_lines, dest_pitch, dest_startx, dest_starty,
  624. width, height, CID_I420);
  625. }
  626. /////////////////////////////////////////////////////////////
  627. //
  628. // I420andYUVAtoYV12
  629. //
  630. // This function alpha-blends two I420 buffers into a third
  631. // YV12 buffer using the alpha info tacked to the 
  632. // end of the second I420 buffer
  633. //
  634. /////////////////////////////////////////////////////////////
  635. int I420andYUVAtoYV12 (
  636. unsigned char *src1_ptr, int src1_pels,   int src1_lines,  int src1_pitch,
  637.                          int src1_startx, int src1_starty,
  638. unsigned char *src2_ptr, int src2_pels,   int src2_lines,  int src2_pitch,
  639.                          int src2_startx, int src2_starty,
  640. unsigned char *dest_ptr, int dest_pels,   int dest_lines,  int dest_pitch,
  641.                          int dest_startx, int dest_starty,
  642. int width,  int height)
  643. {
  644. return I420andYUVAtoI420orYV12 (
  645. src1_ptr, src1_pels, src1_lines, src1_pitch, src1_startx, src1_starty,
  646. src2_ptr, src2_pels, src2_lines, src2_pitch, src2_startx, src2_starty,
  647. dest_ptr, dest_pels, dest_lines, dest_pitch, dest_startx, dest_starty,
  648. width, height, CID_YV12);
  649. }
  650. /////////////////////////////////////////////////////////////
  651. //
  652. // I420andYUVA
  653. //
  654. // This function alpha-blends two I420 buffers into a third
  655. // YV12 buffer using the alpha info tacked to the 
  656. // end of the second I420 buffer
  657. //
  658. /////////////////////////////////////////////////////////////
  659. int HXEXPORT ENTRYPOINT(I420andYUVA) (
  660. unsigned char *src1_ptr, int src1_pels,   int src1_lines,  int src1_pitch,
  661.                          int src1_startx, int src1_starty,
  662. unsigned char *src2_ptr, int src2_pels,   int src2_lines,  int src2_pitch,
  663.                          int src2_startx, int src2_starty,
  664. unsigned char *dest_ptr, int dest_pels,   int dest_lines,  int dest_pitch,
  665.                          int dest_startx, int dest_starty,
  666. int width,  int height,  int color_format)
  667. {
  668. #ifdef _USE_MMX_BLENDERS
  669.     if( !z_bCheckedForMMX )
  670.     {
  671.         z_bMMXAvailable = (checkMmxAvailablity()&CPU_HAS_MMX)?1:0;
  672.         z_bCheckedForMMX = TRUE;
  673.     }
  674.     
  675.     if( z_bMMXAvailable )
  676.     {
  677.         switch (color_format)
  678.         {
  679.            case CID_I420:
  680.                return I420andYUVAtoI420_MMX (
  681.                    src1_ptr, src1_pels, src1_lines, src1_pitch, src1_startx, src1_starty,
  682.                    src2_ptr, src2_pels, src2_lines, src2_pitch, src2_startx, src2_starty,
  683.                    dest_ptr, dest_pels, dest_lines, dest_pitch, dest_startx, dest_starty,
  684.                    width, height);
  685.            case CID_YV12:
  686.                return I420andYUVAtoYV12_MMX (
  687.                    src1_ptr, src1_pels, src1_lines, src1_pitch, src1_startx, src1_starty,
  688.                    src2_ptr, src2_pels, src2_lines, src2_pitch, src2_startx, src2_starty,
  689.                    dest_ptr, dest_pels, dest_lines, dest_pitch, dest_startx, dest_starty,
  690.                    width, height);
  691.            case CID_YUY2:
  692.                return I420andYUVAtoYUY2_MMX (
  693.                    src1_ptr, src1_pels, src1_lines, src1_pitch, src1_startx, src1_starty,
  694.                    src2_ptr, src2_pels, src2_lines, src2_pitch, src2_startx, src2_starty,
  695.                    dest_ptr, dest_pels, dest_lines, dest_pitch, dest_startx, dest_starty,
  696.                    width, height);
  697.            case CID_UYVY:
  698.                return I420andYUVAtoUYVY_MMX (
  699.                    src1_ptr, src1_pels, src1_lines, src1_pitch, src1_startx, src1_starty,
  700.                    src2_ptr, src2_pels, src2_lines, src2_pitch, src2_startx, src2_starty,
  701.                    dest_ptr, dest_pels, dest_lines, dest_pitch, dest_startx, dest_starty,
  702.                    width, height);
  703.            default:
  704.                return -1;
  705.         }
  706.     }
  707. #endif
  708.     switch (color_format)
  709.     {
  710.        case CID_I420:
  711.        case CID_YV12:
  712.            return I420andYUVAtoI420orYV12 (
  713.                src1_ptr, src1_pels, src1_lines, src1_pitch, src1_startx, src1_starty,
  714.                src2_ptr, src2_pels, src2_lines, src2_pitch, src2_startx, src2_starty,
  715.                dest_ptr, dest_pels, dest_lines, dest_pitch, dest_startx, dest_starty,
  716.                width, height, color_format);
  717.        case CID_YUY2:
  718.            return I420andYUVAtoYUY2 (
  719.                src1_ptr, src1_pels, src1_lines, src1_pitch, src1_startx, src1_starty,
  720.                src2_ptr, src2_pels, src2_lines, src2_pitch, src2_startx, src2_starty,
  721.                dest_ptr, dest_pels, dest_lines, dest_pitch, dest_startx, dest_starty,
  722.                width, height);
  723.        case CID_UYVY:
  724.            return I420andYUVAtoUYVY (
  725.                src1_ptr, src1_pels, src1_lines, src1_pitch, src1_startx, src1_starty,
  726.                src2_ptr, src2_pels, src2_lines, src2_pitch, src2_startx, src2_starty,
  727.                dest_ptr, dest_pels, dest_lines, dest_pitch, dest_startx, dest_starty,
  728.                width, height);
  729.        default:
  730.            return -1;
  731.     }
  732.     
  733. }
  734. /////////////////////////////////////////////////////////////
  735. //
  736. // I420andI420toI420
  737. //
  738. // This function alpha-blends two I420 buffers into a third
  739. // I420 buffer using the constant alpha given in the params.
  740. //
  741. /////////////////////////////////////////////////////////////
  742. int HXEXPORT ENTRYPOINT(I420andI420toI420) (
  743.     unsigned char *src1_ptr, int src1_pels,   int src1_lines,  int src1_pitch,
  744.     int src1_startx, int src1_starty,
  745.     unsigned char *src2_ptr, int src2_pels,   int src2_lines,  int src2_pitch,
  746.     int src2_startx, int src2_starty,
  747.     unsigned char *dest_ptr, int dest_pels,   int dest_lines,  int dest_pitch,
  748.     int dest_startx, int dest_starty,
  749.     int width,  int height,  int alpha )
  750. {
  751.     int ALPHA_tab[511];
  752.     
  753.     int i, j, c;
  754.     unsigned char *s1, *s2, *d;
  755.     int s1_lineskip, s2_lineskip, d_lineskip;
  756. #ifdef _USE_MMX_BLENDERS
  757.     if( !z_bCheckedForMMX )
  758.     {
  759.         z_bMMXAvailable = (checkMmxAvailablity()&CPU_HAS_MMX)?1:0;
  760.         z_bCheckedForMMX = TRUE;
  761.     }
  762.     if( z_bMMXAvailable )
  763.     {
  764.         return I420andI420toI420_MMX_sub (
  765.             src1_ptr, src1_pels,   src1_lines,  src1_pitch,
  766.             src1_startx, src1_starty,
  767.             src2_ptr, src2_pels,   src2_lines,  src2_pitch,
  768.             src2_startx, src2_starty,
  769.             dest_ptr, dest_pels,   dest_lines,  dest_pitch,
  770.             dest_startx, dest_starty,
  771.             width,  height,  alpha );
  772.     }
  773. #endif
  774.     for (i = 0; i < 511; i++)
  775.     {
  776.         ALPHA_tab[i] = (i - 255) * alpha;
  777.     }
  778.     
  779.     for (c = 0; c < 3; c++)
  780.     {
  781.         switch (c)
  782.         {
  783.            case 0:
  784.                // Y
  785.                s1 = src1_ptr + src1_starty * src1_pitch + src1_startx;
  786.                s2 = src2_ptr + src2_starty * src2_pitch + src2_startx;
  787.                d  = dest_ptr + dest_starty * dest_pitch + dest_startx;
  788.                s1_lineskip = src1_pitch - width;
  789.                s2_lineskip = src2_pitch - width;
  790.                d_lineskip  = dest_pitch - width; 
  791.                break;
  792.            case 1:
  793.                // U
  794.                s1  = src1_ptr + src1_pitch * src1_lines;
  795.                s1 += (src1_starty * src1_pitch / 4) + src1_startx / 2;
  796.                s2  = src2_ptr + src2_pitch * src2_lines;
  797.                s2 += (src2_starty * src2_pitch / 4) + src2_startx / 2;
  798.                d   = dest_ptr + dest_pitch * dest_lines;
  799.                d  += (dest_starty * dest_pitch / 4) + dest_startx / 2;
  800.                s1_lineskip = (src1_pitch - width) / 2;
  801.                s2_lineskip = (src2_pitch - width) / 2;
  802.                d_lineskip  = (dest_pitch - width) / 2;
  803.                width >>= 1;
  804.                height >>= 1;
  805.                break;
  806.            case 2:
  807.                // V
  808.                s1  = src1_ptr + 5 * src1_pitch * src1_lines / 4;
  809.                s1 += (src1_starty * src1_pitch / 4) + src1_startx / 2;
  810.                s2  = src2_ptr + 5 * src2_pitch * src2_lines / 4;
  811.                s2 += (src2_starty * src2_pitch / 4) + src2_startx / 2;
  812.                d   = dest_ptr + 5 * dest_pitch * dest_lines / 4;
  813.                d  += (dest_starty * dest_pitch / 4) + dest_startx / 2;
  814.                break;
  815.         }
  816.         for (i = 0; i < height; i++)
  817.         {
  818.             for (j = 0; j < (width-3); j += 4)
  819.             {
  820.                 int x1, x2;
  821.                 x1 = *(s1 + 0);
  822.                 x2 = *(s2 + 0);
  823.                 x1 -= x2;
  824.                 x1 = *(ALPHA_tab + x1 + 255);
  825.                 x1 >>= 8;
  826.                 x1 += x2;
  827.                 *(d + 0) = (unsigned char)x1;
  828.                 x1 = *(s1 + 1);
  829.                 x2 = *(s2 + 1);
  830.                 x1 -= x2;
  831.                 x1 = *(ALPHA_tab + x1 + 255);
  832.                 x1 >>= 8;
  833.                 x1 += x2;
  834.                 *(d + 1) = (unsigned char)x1;
  835.                 x1 = *(s1 + 2);
  836.                 x2 = *(s2 + 2);
  837.                 x1 -= x2;
  838.                 x1 = *(ALPHA_tab + x1 + 255);
  839.                 x1 >>= 8;
  840.                 x1 += x2;
  841.                 *(d + 2) = (unsigned char)x1;
  842.                 x1 = *(s1 + 3);
  843.                 x2 = *(s2 + 3);
  844.                 x1 -= x2;
  845.                 x1 = *(ALPHA_tab + x1 + 255);
  846.                 x1 >>= 8;
  847.                 x1 += x2;
  848.                 *(d + 3) = (unsigned char)x1;
  849.                 s1 += 4;
  850.                 s2 += 4;
  851.                 d  += 4;
  852.             }
  853.             while (j < width)
  854.             {
  855.                 int x1, x2;
  856.                 x1 = *s1;
  857.                 x2 = *s2;
  858.                 x1 -= x2;
  859.                 x1 = *(ALPHA_tab + x1 + 255);
  860.                 x1 >>= 8;
  861.                 x1 += x2;
  862.                 *d++ = (unsigned char)x1;
  863.                 s1++;
  864.                 s2++;
  865.                 j++;
  866.             }
  867.             s1 += s1_lineskip;
  868.             s2 += s2_lineskip;
  869.             d  += d_lineskip;
  870.         }
  871.     }
  872.     return 0;
  873. }
  874. #if 0
  875. void main (void)
  876. {
  877. unsigned char *s1, *s2, *dst;
  878. int pels = 64;
  879. int lines = 32;
  880. int pitch = 64;
  881. s1  = malloc (lines*pitch*3/2);
  882. s2  = malloc (lines*pitch*5/2);
  883. dst = malloc (lines*pitch*3/2);
  884. memset (s1, 64, lines*pitch*3/2);
  885. memset (s2, 192, lines*pitch*3/2);
  886. memset (s2 + lines*pitch*3/2, 64, lines*pitch);
  887. I420andYUVAtoI420orYV12 (
  888. s1, pels, lines, pitch, pels, lines,
  889. s2, pels, lines, pitch, pels, lines,
  890. dst, pels, lines, pitch, pels, lines,
  891. pels, lines, CID_I420);
  892. free (s1);
  893. free (s2);
  894. free (dst);
  895. }
  896. #endif