blit_soft.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:63k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*****************************************************************************
  2.  *
  3.  * This program is free software ; you can redistribute it and/or modify
  4.  * it under the terms of the GNU General Public License as published by
  5.  * the Free Software Foundation; either version 2 of the License, or
  6.  * (at your option) any later version.
  7.  *
  8.  * This program is distributed in the hope that it will be useful,
  9.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11.  * GNU General Public License for more details.
  12.  *
  13.  * You should have received a copy of the GNU General Public License
  14.  * along with this program; if not, write to the Free Software
  15.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  16.  *
  17.  * $Id: blit_soft.c 607 2006-01-22 20:58:29Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23. #include "../common.h"
  24. #include "../dyncode/dyncode.h"
  25. #include "../cpu/cpu.h"
  26. #include "blit_soft.h"
  27. //#define BLITTEST
  28. /*
  29. TV range:
  30. +16  (219)
  31. +128 (224)
  32. +128 (224)
  33. PC range:
  34. +0   (255)
  35. +128 (255)
  36. +128 (255)
  37. ranges:
  38. R,G,B,Y [0..1]
  39. Cb,Cr   [-0.5..0.5]
  40. Y' = Kr * R' + (1 - Kr - Kb) * G' + Kb * B'
  41. Cb = 0.5 * (B' - Y') / (1 - Kb)
  42. Cr = 0.5 * (R' - Y') / (1 - Kr)
  43. Kb = 0.114
  44. Kr = 0.299
  45. ITU-R BT 601
  46.     Y'= 0.299   *R' + 0.587   *G' + 0.114   *B'
  47.     Cb=-0.168736*R' - 0.331264*G' + 0.5     *B'
  48.     Cr= 0.5     *R' - 0.418688*G' - 0.081312*B'
  49.     R'= Y'            + 1.403*Cr
  50.     G'= Y' - 0.344*Cb - 0.714*Cr
  51.     B'= Y' + 1.773*Cb 
  52. Kb = 0.0722
  53. Kr = 0.2126
  54. ITU-R BT 709
  55.     Y'= 0.2215*R' + 0.7154*G' + 0.0721*B'
  56.     Cb=-0.1145*R' - 0.3855*G' + 0.5000*B'
  57.     Cr= 0.5016*R' - 0.4556*G' - 0.0459*B'
  58.     R'= Y'             + 1.5701*Cr
  59.     G'= Y' - 0.1870*Cb - 0.4664*Cr
  60.     B'= Y' - 1.8556*Cb 
  61. */
  62. #define CM(i) ((int16_t)((i)*8192))
  63. #if defined(_M_IX86) && !defined(TARGET_SYMBIAN)
  64. static const int16_t YUVToRGB[4][8] =
  65. {
  66. // TV range BT-601
  67. { CM(1.164),-16,CM(1.596),CM(-0.813),-128,CM(2.017),CM(-0.392),-128 },
  68. // TV range BT-709
  69. { CM(1.164),-16,CM(1.786),CM(-0.530),-128,CM(2.111),CM(-0.213),-128 },
  70. // PC range BT-601
  71. { CM(1),0,CM(1.402),CM(-0.71414),-128,CM(1.772),CM(-0.34414),-128 },
  72. // PC range BT-709
  73. { CM(1),0,CM(1.5701),CM(-0.4664),-128,CM(1.8556),CM(-0.1870),-128 },
  74. };
  75. static const int16_t* GetYUVToRGB(const pixel* Src)
  76. {
  77. int i = 0;
  78. if (Src->Flags & PF_YUV_BT709)
  79. i += 1;
  80. if (Src->Flags & PF_YUV_PC)
  81. i += 2;
  82. return YUVToRGB[i];
  83. }
  84. #endif
  85. #define SAT(Value) (Value < 0 ? 0: (Value > 255 ? 255: Value))
  86. static const rgbval_t Gray1[2] = { 
  87. CRGB(0,0,0),CRGB(255,255,255)
  88. };
  89. static const rgbval_t Gray2[4] = { 
  90. CRGB(0,0,0),CRGB(85,85,85),CRGB(170,170,170),CRGB(255,255,255) 
  91. };
  92. static const rgbval_t Gray4[16] = {
  93. CRGB(0,0,0),CRGB(17,17,17),CRGB(34,34,34),CRGB(51,51,51),
  94. CRGB(68,68,68),CRGB(85,85,85),CRGB(102,102,102),CRGB(119,119,119),
  95. CRGB(136,136,136),CRGB(153,153,153),CRGB(170,170,170),CRGB(187,187,187),
  96. CRGB(204,204,204),CRGB(221,221,221),CRGB(238,238,238),CRGB(255,255,255)
  97. };
  98. #if defined(_M_IX86) && !defined(TARGET_SYMBIAN)
  99. #define DECLARE_BLITMMX(name) 
  100. extern void STDCALL name##_mmx(blit_soft* This, uint8_t** DstPtr,uint8_t** SrcPtr,int DstPitch,int SrcPitch,int Width,int Height,uintptr_t Src2SrcLast); 
  101. extern void STDCALL name##_mmx2(blit_soft* This, uint8_t** DstPtr,uint8_t** SrcPtr,int DstPitch,int SrcPitch,int Width,int Height,uintptr_t Src2SrcLast); 
  102. extern void STDCALL name##_3dnow(blit_soft* This, uint8_t** DstPtr,uint8_t** SrcPtr,int DstPitch,int SrcPitch,int Width,int Height,uintptr_t Src2SrcLast);
  103. DECLARE_BLITMMX(blit_i420_i420)
  104. DECLARE_BLITMMX(blit_i420_yuy2)
  105. DECLARE_BLITMMX(blit_i420_rgb32)
  106. DECLARE_BLITMMX(blit_i420_rgb24)
  107. DECLARE_BLITMMX(blit_i420_bgr32)
  108. DECLARE_BLITMMX(blit_i420_bgr24)
  109. DECLARE_BLITMMX(blit_rgb32_rgb32)
  110. DECLARE_BLITMMX(blit_rgb24_rgb24)
  111. DECLARE_BLITMMX(blit_rgb16_rgb16)
  112. typedef struct blitmmx
  113. {
  114. uint32_t In;
  115. uint32_t Out;
  116. blitsoftentry Func[3];
  117. } blitmmx;
  118. static const blitmmx BlitMMX[] = 
  119. {
  120. { FOURCC_I420, FOURCC_I420, { blit_i420_i420_mmx, blit_i420_i420_mmx2, blit_i420_i420_3dnow }},
  121. { FOURCC_I420, FOURCC_YUY2, { blit_i420_yuy2_mmx, blit_i420_yuy2_mmx2, blit_i420_yuy2_3dnow }},
  122. { FOURCC_I420, FOURCC_RGB32,{ blit_i420_rgb32_mmx,blit_i420_rgb32_mmx2,blit_i420_rgb32_3dnow }},
  123. { FOURCC_I420, FOURCC_RGB24,{ blit_i420_rgb24_mmx,blit_i420_rgb24_mmx2,blit_i420_rgb24_3dnow }},
  124. { FOURCC_I420, FOURCC_BGR32,{ blit_i420_bgr32_mmx,blit_i420_bgr32_mmx2,blit_i420_bgr32_3dnow }},
  125. { FOURCC_I420, FOURCC_BGR24,{ blit_i420_bgr24_mmx,blit_i420_bgr24_mmx2,blit_i420_bgr24_3dnow }},
  126. { FOURCC_RGB32,FOURCC_RGB32,{ blit_rgb32_rgb32_mmx,blit_rgb32_rgb32_mmx2,blit_rgb32_rgb32_3dnow }},
  127. { FOURCC_RGB24,FOURCC_RGB24,{ blit_rgb24_rgb24_mmx,blit_rgb24_rgb24_mmx2,blit_rgb24_rgb24_3dnow }},
  128. { FOURCC_RGB16,FOURCC_RGB16,{ blit_rgb16_rgb16_mmx,blit_rgb16_rgb16_mmx2,blit_rgb16_rgb16_3dnow }},
  129. { FOURCC_RGB15,FOURCC_RGB15,{ blit_rgb16_rgb16_mmx,blit_rgb16_rgb16_mmx2,blit_rgb16_rgb16_3dnow }},
  130. { FOURCC_BGR32,FOURCC_BGR32,{ blit_rgb32_rgb32_mmx,blit_rgb32_rgb32_mmx2,blit_rgb32_rgb32_3dnow }},
  131. { FOURCC_BGR24,FOURCC_BGR24,{ blit_rgb24_rgb24_mmx,blit_rgb24_rgb24_mmx2,blit_rgb24_rgb24_3dnow }},
  132. { FOURCC_BGR16,FOURCC_BGR16,{ blit_rgb16_rgb16_mmx,blit_rgb16_rgb16_mmx2,blit_rgb16_rgb16_3dnow }},
  133. { FOURCC_BGR15,FOURCC_BGR15,{ blit_rgb16_rgb16_mmx,blit_rgb16_rgb16_mmx2,blit_rgb16_rgb16_3dnow }},
  134. {0},
  135. };
  136. #endif
  137. typedef struct blitpack
  138. {
  139. blitfx FX;
  140. video Dst;
  141. video Src;
  142. rect DstRect;
  143. rect SrcRect;
  144. blit_soft Code[2];
  145. bool_t SafeBorder;
  146. int RScaleX;
  147. int RScaleY;
  148. struct blitpack* Next;
  149. } blitpack;
  150. static NOINLINE void FreeBlit(blit_soft* p)
  151. {
  152. CodeDone(&p->Code);
  153. free(p->LookUp_Data);
  154. p->LookUp_Data = NULL;
  155. }
  156. static INLINE struct blitpack* _BlitAlloc()
  157. {
  158. blitpack* p = (blitpack*) malloc(sizeof(blitpack));
  159. if (!p) return NULL;
  160. memset(p,0,sizeof(blitpack));
  161. CodeInit(&p->Code[0].Code);
  162. CodeInit(&p->Code[1].Code);
  163. return p;
  164. }
  165. static INLINE void _BlitFree(struct blitpack* p)
  166. {
  167. FreeBlit(&p->Code[0]);
  168. FreeBlit(&p->Code[1]);
  169. free(p);
  170. }
  171. #ifdef CONFIG_CONTEXT
  172. void Blit_Init()
  173. {
  174. }
  175. void Blit_Done()
  176. {
  177. blitpack* p;
  178. while ((p = Context()->Blit)!=NULL)
  179. {
  180. Context()->Blit = p->Next;
  181. _BlitFree(p);
  182. }
  183. }
  184. static INLINE void BlitFree(struct blitpack* p)
  185. {
  186. p->Next = Context()->Blit;
  187. Context()->Blit = p;
  188. }
  189. static INLINE struct blitpack* BlitAlloc()
  190. {
  191. blitpack* p = Context()->Blit;
  192. if (p)
  193. Context()->Blit = p->Next;
  194. else
  195. p = _BlitAlloc();
  196. return p;
  197. }
  198. #else
  199. #define BlitAlloc _BlitAlloc
  200. #define BlitFree _BlitFree
  201. #endif
  202. static const rgb* DefaultPal(const pixel* Format)
  203. {
  204. if (Format->Flags & PF_PALETTE)
  205. {
  206. if (!Format->Palette)
  207. switch (Format->BitCount)
  208. {
  209. case 1: return (const rgb*)Gray1;
  210. case 2: return (const rgb*)Gray2;
  211. case 4: return (const rgb*)Gray4;
  212. }
  213. return Format->Palette;
  214. }
  215. return NULL;
  216. }
  217. static int CalcScale(int v, int Min, int Max)
  218. {
  219. if (v > Max) v = Max;
  220. if (v < Min) v = Min;
  221. return v;
  222. }
  223. static int CalcRScale(int v, int Gray)
  224. {
  225. if (v<=0) return 16;
  226. v = (16*1024 << 16) / v;
  227. if (Gray) // only 100% and 200% scale
  228. return v > 12288 ? 16:8;
  229. //align to 100%
  230. if (v > 16834-1024 && v < 16384+1024) 
  231. v = 16384;
  232. //align to 200%
  233. if (v > 8192-1024 && v < 8192+1024) 
  234. v = 8192;
  235. //align to 50%
  236. if (v > 32768-2048 && v < 32768+2048) 
  237. v = 32768;
  238. #if defined(SH3)
  239. if (v < 12288)
  240. return 8;
  241. return 16;
  242. // if (v<1024) v=1024;
  243. // return ((v+1024) >> 11) << 1;
  244. #else
  245. if (v<512) v=512;
  246. return (v+512) >> 10;
  247. #endif
  248. }
  249. static NOINLINE bool_t EnlargeIfNeeded(int* v,int Align,int Side,int Limit)
  250. {
  251. int Needed = Align - (*v & (Align-1));
  252. if (Needed < Align && Needed <= (Limit-Side))
  253. {
  254. *v += Needed;
  255. return 1;
  256. }
  257. return 0;
  258. }
  259. void BlitAlign(blitpack* p, rect* DstRect, rect* SrcRect)
  260. {
  261. int i;
  262. int ShrinkX,ShrinkY;
  263. int SrcRight;
  264. int SrcBottom;
  265. int SrcAdjWidth,SrcAdjHeight;
  266. int RScaleX,RScaleY;
  267. blit_soft* Code;
  268. if (!p) return;
  269. RScaleX = p->RScaleX;
  270. RScaleY = p->RScaleY;
  271. Code = &p->Code[0];
  272. p->SafeBorder = 0;
  273. if (Code->ArithStretch && (RScaleX != 16) && (RScaleX != 32))
  274. {
  275. //avoid bilinear scale overrun (shrink source)
  276. if ((p->Src.Pixel.Flags & PF_SAFEBORDER) && Code->DstAlignSize > 2)
  277. p->SafeBorder = 1; // build a one pixel border before blitting on right and bottom side
  278. else
  279. {
  280. //only horizontal bilinear filtering is supported (arm_stretch)
  281. if (SrcRect->Width>2) 
  282. SrcRect->Width -= 2;
  283. }
  284. }
  285. // convert source to destination space
  286. if (p->FX.Direction & DIR_SWAPXY)
  287. {
  288. SwapInt(&RScaleX,&RScaleY);
  289. SwapRect(SrcRect);
  290. }
  291. SrcRight = SrcRect->x + SrcRect->Width;
  292. SrcBottom = SrcRect->y + SrcRect->Height;
  293. SrcAdjWidth = SrcRect->Width * 16 / RScaleX;
  294. SrcAdjHeight = SrcRect->Height * 16 / RScaleY;
  295. if (p->FX.Flags & BLITFX_ENLARGEIFNEEDED)
  296. {
  297. SrcRight = p->Src.Width;
  298. SrcBottom = p->Src.Height;
  299. if (p->FX.Direction & DIR_SWAPXY)
  300. SwapInt(&SrcRight,&SrcBottom);
  301. if (p->Src.Pixel.Flags & PF_SAFEBORDER)
  302. {
  303. SrcRight += 16;
  304. SrcBottom += 16;
  305. }
  306. if (EnlargeIfNeeded(&SrcAdjWidth,Code->DstAlignSize,SrcRect->x+SrcRect->Width,SrcRight))
  307. SrcRect->Width = -1; // need calc
  308. if (EnlargeIfNeeded(&SrcAdjHeight,Code->DstAlignSize,SrcRect->y+SrcRect->Height,SrcBottom))
  309. SrcRect->Height = -1; // need calc
  310. }
  311. ShrinkX = DstRect->Width - SrcAdjWidth;
  312. if (ShrinkX>=0) //shrink destination?
  313. {
  314. ShrinkX >>= 1;
  315. DstRect->x += ShrinkX;
  316. DstRect->Width = SrcAdjWidth;
  317. }
  318. else //adjust source position
  319. {
  320. ShrinkX = 0;
  321. SrcRect->x += (SrcAdjWidth - DstRect->Width) * RScaleX >> 5;
  322. SrcRect->Width = -1; // need calc
  323. }
  324. ShrinkY = DstRect->Height - SrcAdjHeight;
  325. if (ShrinkY>=0) //shrink Dst?
  326. {
  327. ShrinkY >>= 1;
  328. DstRect->y += ShrinkY;
  329. DstRect->Height = SrcAdjHeight;
  330. }
  331. else //adjust source position
  332. {
  333. ShrinkY = 0;
  334. SrcRect->y += (SrcAdjHeight - DstRect->Height) * RScaleY >> 5;
  335. SrcRect->Height = -1; // need calc
  336. }
  337. i = DstRect->Width & (Code->DstAlignSize-1); 
  338. DstRect->Width -= i; 
  339. i >>= 1;
  340. ShrinkX += i;
  341. DstRect->x += i;
  342. i = DstRect->Height & (Code->DstAlignSize-1);
  343. DstRect->Height -= i;
  344. i >>= 1;
  345. ShrinkY += i;
  346. DstRect->y += i;
  347. i = DstRect->x & (Code->DstAlignPos-1);
  348. if (i && ShrinkX < i)
  349. {
  350. DstRect->Width -= Code->DstAlignPos - i;
  351. DstRect->Width &= ~(Code->DstAlignSize-1); 
  352. DstRect->x += Code->DstAlignPos - i;
  353. }
  354. else
  355. DstRect->x -= i;
  356. i = DstRect->y & (Code->DstAlignPos-1);
  357. if (i && ShrinkY < i)
  358. {
  359. DstRect->Height -= Code->DstAlignPos - i;
  360. DstRect->Height &= ~(Code->DstAlignSize-1);
  361. DstRect->y += Code->DstAlignPos - i;
  362. }
  363. else
  364. DstRect->y -= i;
  365. SrcRect->x &= ~(Code->SrcAlignPos-1);
  366. SrcRect->y &= ~(Code->SrcAlignPos-1);
  367. // convert source back to it's space (if needed)
  368. if (SrcRect->Width < 0)
  369. SrcRect->Width = (DstRect->Width * RScaleX / 16 + 1) & ~1;
  370. if (SrcRect->Height < 0)
  371. SrcRect->Height = (DstRect->Height * RScaleY / 16 + 1) & ~1;
  372. if (SrcRect->x + SrcRect->Width > SrcRight)
  373. SrcRect->Width = SrcRight - SrcRect->x;
  374. if (SrcRect->y + SrcRect->Height > SrcBottom)
  375. SrcRect->Height = SrcBottom - SrcRect->y;
  376. if (p->FX.Direction & DIR_SWAPXY)
  377. SwapRect(SrcRect);
  378. p->DstRect = *DstRect;
  379. p->SrcRect = *SrcRect;
  380. }
  381. static NOINLINE void CodeRelease(blit_soft* p)
  382. {
  383. //todo... better palette handling
  384. if (p->Dst.Palette)
  385. memset(&p->Dst,0,sizeof(p->Dst));
  386. if (p->Src.Palette)
  387. memset(&p->Src,0,sizeof(p->Src));
  388. }
  389. void BlitRelease(blitpack* p)
  390. {
  391. if (p)
  392. {
  393. CodeRelease(&p->Code[0]);
  394. CodeRelease(&p->Code[1]);
  395. BlitFree(p);
  396. }
  397. }
  398. int AnyAlign(rect* DstRect, rect* SrcRect, const blitfx* FX, 
  399.   int DstAlignSize, int DstAlignPos,
  400.   int MinScale, int MaxScale)
  401. {
  402. int i,ShrinkX,ShrinkY;
  403. int ScaleX,ScaleY;
  404. int SrcRight;
  405. int SrcBottom;
  406. int SrcAdjWidth,SrcAdjHeight;
  407. if (!DstRect || !SrcRect || !FX)
  408. return ERR_INVALID_PARAM;
  409. ScaleX = CalcScale(FX->ScaleX,MinScale,MaxScale);
  410. ScaleY = CalcScale(FX->ScaleY,MinScale,MaxScale);
  411. SrcRight = SrcRect->x + SrcRect->Width;
  412. SrcBottom = SrcRect->y + SrcRect->Height;
  413. // convert source to destination space
  414. if (FX->Direction & DIR_SWAPXY)
  415. {
  416. SwapInt(&ScaleX,&ScaleY);
  417. SwapRect(SrcRect);
  418. }
  419. SrcAdjWidth = (SrcRect->Width * ScaleX + 32768) >> 16;
  420. SrcAdjHeight = (SrcRect->Height * ScaleY + 32768) >> 16;
  421. ShrinkX = DstRect->Width - SrcAdjWidth;
  422. if (ShrinkX>0) //shrink destination?
  423. {
  424. ShrinkX >>= 1;
  425. DstRect->x += ShrinkX;
  426. DstRect->Width = SrcAdjWidth;
  427. }
  428. else //adjust source position
  429. {
  430. ShrinkX = 0;
  431. SrcRect->x += ((SrcAdjWidth - DstRect->Width) << 15) / ScaleX;
  432. SrcRect->Width = -1;
  433. }
  434. ShrinkY = DstRect->Height - SrcAdjHeight;
  435. if (ShrinkY>0) //shrink Dst?
  436. {
  437. ShrinkY >>= 1;
  438. DstRect->y += ShrinkY;
  439. DstRect->Height = SrcAdjHeight;
  440. }
  441. else //adjust source position
  442. {
  443. ShrinkY = 0;
  444. SrcRect->y += ((SrcAdjHeight - DstRect->Height) << 15) / ScaleY;
  445. SrcRect->Height = -1;
  446. }
  447. // final alignment
  448. i = DstRect->Width & (DstAlignSize-1); 
  449. DstRect->Width -= i; 
  450. i >>= 1;
  451. ShrinkX += i;
  452. DstRect->x += i;
  453. i = DstRect->Height & (DstAlignSize-1);
  454. DstRect->Height -= i;
  455. i >>= 1;
  456. ShrinkY += i;
  457. DstRect->y += i;
  458. i = DstRect->x & (DstAlignPos-1);
  459. if (i && ShrinkX < i)
  460. {
  461. DstRect->Width -= DstAlignPos - i;
  462. DstRect->Width &= ~(DstAlignSize-1); 
  463. DstRect->x += DstAlignPos - i;
  464. }
  465. else
  466. DstRect->x -= i;
  467. i = DstRect->y & (DstAlignPos-1);
  468. if (i && ShrinkY < i)
  469. {
  470. DstRect->Height -= DstAlignPos - i;
  471. DstRect->Height &= ~(DstAlignSize-1);
  472. DstRect->y += DstAlignPos - i;
  473. }
  474. else
  475. DstRect->y -= i;
  476. SrcRect->x &= ~1;
  477. SrcRect->y &= ~1;
  478. if (SrcRect->Width < 0)
  479. SrcRect->Width = ((DstRect->Width << 16) / ScaleX +1) & ~1;
  480. if (SrcRect->Height < 0)
  481. SrcRect->Height = ((DstRect->Height << 16) / ScaleY +1) & ~1;
  482. if (FX->Direction & DIR_SWAPXY)
  483. SwapRect(SrcRect);
  484. if (SrcRect->x + SrcRect->Width > SrcRight)
  485. SrcRect->Width = SrcRight - SrcRect->x;
  486. if (SrcRect->y + SrcRect->Height > SrcBottom)
  487. SrcRect->Height = SrcBottom - SrcRect->y;
  488. return ERR_NONE;
  489. }
  490. static INLINE void SurfacePtr(uint8_t** Ptr, const planes Planes, const video* Format, int BPP, int x, int y, int Pitch)
  491. {
  492. int Adj = (x & 1) << 1;
  493.     Ptr[0] = (uint8_t*)Planes[0] + ((x * BPP) >> 3) + y * Pitch;
  494. if (Format->Pixel.Flags & (PF_YUV420|PF_YUV422|PF_YUV444|PF_YUV410))
  495. {
  496. if (Format->Pixel.Flags & PF_YUV420)
  497. {
  498. Ptr[1] = (uint8_t*)Planes[1] + (x >> 1) + (y >> 1) * (Pitch >> 1);
  499. Ptr[2] = (uint8_t*)Planes[2] + (x >> 1) + (y >> 1) * (Pitch >> 1);
  500. }
  501. else
  502. if (Format->Pixel.Flags & PF_YUV422)
  503. {
  504. Ptr[1] = (uint8_t*)Planes[1] + (x >> 1) + y * (Pitch >> 1);
  505. Ptr[2] = (uint8_t*)Planes[2] + (x >> 1) + y * (Pitch >> 1);
  506. }
  507. else
  508. if (Format->Pixel.Flags & PF_YUV444)
  509. {
  510. Ptr[1] = (uint8_t*)Planes[1] + x + y * Pitch;
  511. Ptr[2] = (uint8_t*)Planes[2] + x + y * Pitch;
  512. }
  513. else
  514. if (Format->Pixel.Flags & PF_YUV410)
  515. {
  516. Ptr[1] = (uint8_t*)Planes[1] + (x >> 2) + (y >> 2) * (Pitch >> 2);
  517. Ptr[2] = (uint8_t*)Planes[2] + (x >> 2) + (y >> 2) * (Pitch >> 2);
  518. }
  519. }
  520. else
  521. if (Format->Pixel.Flags & PF_FOURCC)
  522. switch (Format->Pixel.FourCC)
  523. {
  524. case FOURCC_IMC2:
  525. Ptr[2] = (uint8_t*)Planes[0] + Format->Height * Pitch + (x >> 1) + (y >> 1) * Pitch;
  526. Ptr[1] = Ptr[1] + (Pitch >> 1);
  527. break;
  528. case FOURCC_IMC4:
  529. Ptr[1] = (uint8_t*)Planes[0] + Format->Height * Pitch + (x >> 1) + (y >> 1) * Pitch;
  530. Ptr[2] = Ptr[1] + (Pitch >> 1);
  531. break;
  532. case FOURCC_I420:
  533. case FOURCC_IYUV:
  534. Ptr[1] = (uint8_t*)Planes[0] + Format->Height * Pitch + (x >> 1) + (y >> 1) * (Pitch >> 1);
  535. Ptr[2] = Ptr[1] + ((Format->Height * Pitch) >> 2);
  536. break;
  537. case FOURCC_YV16: 
  538. Ptr[2] = (uint8_t*)Planes[0] + Format->Height * Pitch + (x >> 1) + y * (Pitch >> 1);
  539. Ptr[1] = Ptr[2] + ((Format->Height * Pitch) >> 1);
  540. break;
  541. case FOURCC_YVU9: 
  542. Ptr[2] = (uint8_t*)Planes[0] + Format->Height * Pitch + (x >> 2) + (y >> 2) * (Pitch >> 2);
  543. Ptr[1] = Ptr[2] + ((Format->Height * Pitch) >> 4);
  544. break;
  545. case FOURCC_YUV9: 
  546. Ptr[1] = (uint8_t*)Planes[0] + Format->Height * Pitch + (x >> 2) + (y >> 2) * (Pitch >> 2);
  547. Ptr[2] = Ptr[1] + ((Format->Height * Pitch) >> 4);
  548. break;
  549. case FOURCC_YV12: 
  550. Ptr[2] = (uint8_t*)Planes[0] + Format->Height * Pitch + (x >> 1) + (y >> 1) * (Pitch >> 1);
  551. Ptr[1] = Ptr[2] + ((Format->Height * Pitch) >> 2);
  552. break;
  553. case FOURCC_YUY2:
  554. case FOURCC_YUNV:
  555. case FOURCC_V422:
  556. case FOURCC_YUYV:
  557. Ptr[1] = Ptr[0]+1-Adj;
  558. Ptr[2] = Ptr[0]+3-Adj;
  559. break;
  560. case FOURCC_YVYU:
  561. Ptr[1] = Ptr[0]+3-Adj;
  562. Ptr[2] = Ptr[0]+1-Adj;
  563. break;
  564. case FOURCC_UYVY:
  565. case FOURCC_Y422:
  566. case FOURCC_UYNV:
  567. Ptr[1] = Ptr[0]-Adj;
  568. Ptr[2] = Ptr[0]+2-Adj;
  569. Ptr[0]++;
  570. break;
  571. case FOURCC_VYUY:
  572. Ptr[2] = Ptr[0]-Adj;
  573. Ptr[1] = Ptr[0]+2-Adj;
  574. Ptr[0]++;
  575. break;
  576. }
  577. }
  578. void BlitImage(blitpack* Pack, const planes Dst, const constplanes Src, const constplanes SrcLast, int DstPitch, int SrcPitch)
  579. {
  580. uint8_t* DstPtr[MAXPLANES];
  581. uint8_t* SrcPtr[MAXPLANES];
  582. bool_t OnlyDiff;
  583. int Width,Height;
  584. blit_soft* p;
  585. uintptr_t Src2SrcLast;
  586. int DstStepX;
  587. int DstStepY;
  588. int DstX;
  589. int DstY;
  590. int SrcY;
  591. // nothing to do?
  592. if (!Pack || Pack->DstRect.Width<=0 || Pack->DstRect.Height<=0)
  593. return;
  594. OnlyDiff = (Pack->FX.Flags & BLITFX_ONLYDIFF) && SrcLast && SrcLast[0] != NULL;
  595. p = &Pack->Code[OnlyDiff];
  596. // calculate the Src and Dst pointers
  597. //   Src: always upperleft corner
  598. //   Dst: according to swapxy and mirroring
  599. Width = Pack->DstRect.Width;
  600. Height = Pack->DstRect.Height;
  601. if (p->SwapXY)
  602. SwapInt(&Width,&Height);
  603. if (DstPitch < 0)
  604. DstPitch = Pack->Dst.Pitch;
  605. if (SrcPitch < 0)
  606. SrcPitch = Pack->Src.Pitch;
  607. SrcY = Pack->SrcRect.y;
  608. if (p->SrcUpDown)
  609. SrcY += Pack->SrcRect.Height-1;
  610. SurfacePtr(SrcPtr,*(const planes*)Src,&Pack->Src,p->SrcBPP,Pack->SrcRect.x,SrcY,SrcPitch);
  611. if (p->SrcUpDown)
  612. SrcPitch = -SrcPitch;
  613. Src2SrcLast = 0;
  614. if (OnlyDiff)
  615. Src2SrcLast = (uint8_t*)SrcLast[0] - (uint8_t*)Src[0];
  616. DstStepX = p->DstBPP;
  617. DstStepY = DstPitch*8;
  618. DstX = Pack->DstRect.x;
  619. DstY = Pack->DstRect.y;
  620. if (p->DstLeftRight)
  621. {
  622. DstX += Pack->DstRect.Width-1;
  623. DstStepX = -DstStepX;
  624. }
  625. if (p->DstUpDown)
  626. {
  627. DstY += Pack->DstRect.Height-1;
  628. DstStepY = -DstStepY;
  629. }
  630. if (p->SwapXY)
  631. SwapInt(&DstStepX,&DstStepY);
  632. SurfacePtr(DstPtr,Dst,&Pack->Dst,p->DstBPP,DstX,DstY,DstPitch);
  633. if (p->DstUpDown)
  634. DstPitch = -DstPitch;
  635. if (p->Slices)
  636. {
  637. const int DstBlock2 = 5;
  638. const int DstBlock = 32;
  639. int SrcBlock = (DstBlock * p->RScaleX) >> 4; //SrcBlock has to be even because of YUV
  640. int DstNext = (DstBlock * DstStepX) >> 3;
  641. int DstNextUV = DstNext >> (p->SwapXY ? p->DstUVPitch2+p->DstUVY2 : p->DstUVX2);
  642. int SrcNext = (SrcBlock * p->SrcBPP) >> 3;
  643. int SrcNextUV = SrcNext >> p->SrcUVX2;
  644. if (Width > DstBlock && p->SlicesReverse) // reverse order?
  645. {
  646. int Quot = Width >> DstBlock2;
  647. int Rem = Width & (DstBlock-1);
  648. DstPtr[0] += Quot*DstNext;
  649. DstPtr[1] += Quot*DstNextUV;
  650. DstPtr[2] += Quot*DstNextUV;
  651. SrcPtr[0] += Quot*SrcNext;
  652. SrcPtr[1] += Quot*SrcNextUV;
  653. SrcPtr[2] += Quot*SrcNextUV;
  654. if (Rem)
  655. {
  656. p->Entry(p,DstPtr,SrcPtr,DstPitch,SrcPitch,Rem,Height,Src2SrcLast);
  657. Width -= Rem;
  658. }
  659. DstNext = -DstNext;
  660. DstNextUV = -DstNextUV;
  661. SrcNext = -SrcNext;
  662. SrcNextUV = -SrcNextUV;
  663. DstPtr[0] += DstNext;
  664. DstPtr[1] += DstNextUV;
  665. DstPtr[2] += DstNextUV;
  666. SrcPtr[0] += SrcNext;
  667. SrcPtr[1] += SrcNextUV;
  668. SrcPtr[2] += SrcNextUV;
  669. }
  670. for (;Width > DstBlock;Width -= DstBlock)
  671. {
  672. p->Entry(p,DstPtr,SrcPtr,DstPitch,SrcPitch,DstBlock,Height,Src2SrcLast);
  673. DstPtr[0] += DstNext;
  674. DstPtr[1] += DstNextUV;
  675. DstPtr[2] += DstNextUV;
  676. SrcPtr[0] += SrcNext;
  677. SrcPtr[1] += SrcNextUV;
  678. SrcPtr[2] += SrcNextUV;
  679. }
  680. }
  681. p->Entry(p,DstPtr,SrcPtr,DstPitch,SrcPitch,Width,Height,Src2SrcLast); 
  682. }
  683. void BuildPalLookUp(blit_soft* p,bool_t YUV)
  684. {
  685. //create a palette lookup with 3x3 bits RGB input
  686. int a,b,c;
  687. int Size = 1 << p->Dst.BitCount;
  688. uint8_t* LookUp;
  689. p->LookUp_Data = malloc(16*16*16*4);
  690. if (p->LookUp_Data)
  691. {
  692. LookUp = (uint8_t*) p->LookUp_Data;
  693. for (a=16;a<512;a+=32)
  694. for (b=16;b<512;b+=32)
  695. for (c=16;c<512;c+=32)
  696. {
  697. const rgb* q = p->DstPalette;
  698. int BestMatch = 0;
  699. int BestDiff = 0x7FFFFFFF;
  700. int i,v[3];
  701. v[0] = a; 
  702. v[1] = b;
  703. v[2] = c;
  704. if (v[0] >= 384) v[0] -= 512;
  705. if (v[1] >= 384) v[1] -= 512;
  706. if (v[2] >= 384) v[2] -= 512;
  707. if (YUV)
  708. {
  709. int w[3];
  710. w[0] = (v[0]*p->_YMul +                  v[2]*p->_RVMul + p->_RAdd) >> 16;
  711. w[1] = (v[0]*p->_YMul + v[1]*p->_GUMul + v[2]*p->_GVMul + p->_GAdd) >> 16;
  712. w[2] = (v[0]*p->_YMul + v[1]*p->_BUMul +               p->_BAdd) >> 16;
  713. v[0]=w[0];
  714. v[1]=w[1];
  715. v[2]=w[2];
  716. }
  717. for (i=0;i<Size;++i,++q)
  718. {
  719. int Diff = (q->c.r-v[0])*(q->c.r-v[0])+
  720.    (q->c.g-v[1])*(q->c.g-v[1])+
  721.    (q->c.b-v[2])*(q->c.b-v[2]);
  722. if (Diff < BestDiff)
  723. {
  724. BestMatch = i;
  725. BestDiff = Diff;
  726. }
  727. }
  728. q = p->DstPalette + BestMatch;
  729. if (YUV)
  730. {
  731. v[0] = ((2105 * q->c.r) + (4128 * q->c.g) + (802 * q->c.b))/0x2000 + 16;
  732. v[1] = (-(1212 * q->c.r) - (2384 * q->c.g) + (3596 * q->c.b))/0x2000 + 128;
  733. v[2] = ((3596 * q->c.r) - (3015 * q->c.g) - (582 * q->c.b))/0x2000 + 128;
  734. v[0]=SAT(v[0]);
  735. v[1]=SAT(v[1]);
  736. v[2]=SAT(v[2]);
  737. }
  738. else
  739. {
  740. v[0] = q->c.r;
  741. v[1] = q->c.g;
  742. v[2] = q->c.b;
  743. }
  744. LookUp[0] = (uint8_t)BestMatch;
  745. #if defined(SH3)
  746. LookUp[3] = (uint8_t)(v[0] >> 1);
  747. LookUp[1] = (uint8_t)(v[1] >> 1);
  748. LookUp[2] = (uint8_t)(v[2] >> 1);
  749. #else
  750. LookUp[1] = (uint8_t)v[0];
  751. LookUp[2] = (uint8_t)v[1];
  752. LookUp[3] = (uint8_t)v[2];
  753. #endif
  754. LookUp += 4;
  755. }
  756. }
  757. }
  758. int UniversalType(const pixel* p, bool_t YUV)
  759. {
  760. if (PlanarYUV(p,NULL,NULL,NULL)) return YUV ? 12:10;
  761. if (PackedYUV(p)) return YUV ? 13:11;
  762. if (p->Flags & PF_PALETTE)
  763. {
  764. if (p->BitCount==1) return 1;
  765. if (p->BitCount==2) return 2;
  766. if (p->BitCount==4) return 3;
  767. if (p->BitCount==8) return YUV ? 14:4;
  768. }
  769. if (p->Flags & PF_RGB)
  770. {
  771. if (p->BitCount==8)  return 5;
  772. if (p->BitCount==16) return 6;
  773. if (p->BitCount==24) return 7;
  774. if (p->BitCount==32) return 8;
  775. }
  776. return -1;
  777. }
  778. // !SwapXY
  779. // !DstLeftRight
  780. // SrcType == 12
  781. // DstType == 12
  782. // RScaleX == 32/16/8
  783. // RScaleY == 32/16/8 
  784. // SrcUVX2 == DstUVX2
  785. // SrcUVY2 == DstUVY2
  786. static void Blit_PYUV_PYUV_2Plane(const uint8_t* Src,uint8_t* Dst,int Width,int Height,int SrcPitch,int DstPitch,int ScaleX,int ScaleY)
  787. {
  788. int y;
  789. for (y=0;y<Height;++y)
  790. {
  791. const uint8_t* s = Src;
  792. uint8_t* d = Dst;
  793. uint8_t* de = Dst + Width;
  794. switch (ScaleX)
  795. {
  796. case 4:
  797. while (d<de)
  798. {
  799. d[0] = d[1] = d[2] = d[3] = *s;
  800. ++s;
  801. d+=4;
  802. }
  803. break;
  804. case 8:
  805. while (d<de)
  806. {
  807. d[0] = *s;
  808. d[1] = *s;
  809. ++s;
  810. d+=2;
  811. }
  812. break;
  813. case 16:
  814. memcpy(d,s,Width);
  815. break;
  816. case 32:
  817. while (d<de)
  818. {
  819. *d = *s;
  820. ++d;
  821. s+=2;
  822. }
  823. break;
  824. case 64:
  825. while (d<de)
  826. {
  827. *d = *s;
  828. ++d;
  829. s+=4;
  830. }
  831. break;
  832. }
  833. Dst += DstPitch;
  834. switch (ScaleY)
  835. {
  836. case 4:
  837. if ((y&3)==3) Src += SrcPitch;
  838. break;
  839. case 8:
  840. if (y&1) Src += SrcPitch;
  841. break;
  842. case 16:
  843. Src += SrcPitch;
  844. break;
  845. case 32:
  846. Src += SrcPitch*2;
  847. break;
  848. case 64:
  849. Src += SrcPitch*4;
  850. break;
  851. }
  852. }
  853. }
  854. // needed for half/quarter software idct mode changes
  855. static void STDCALL Blit_PYUV_PYUV_2(blit_soft* This, uint8_t** DstPtr,uint8_t** SrcPtr,int DstPitch,int SrcPitch,
  856.                   int Width,int Height,uintptr_t Src2SrcLast) 
  857. {
  858. Blit_PYUV_PYUV_2Plane(SrcPtr[0],DstPtr[0],Width,Height,SrcPitch,DstPitch,This->RScaleX,This->RScaleY);
  859. Width >>= This->SrcUVX2;
  860. Height >>= This->SrcUVY2;
  861. SrcPitch >>= This->SrcUVPitch2;
  862. DstPitch >>= This->DstUVPitch2;
  863. Blit_PYUV_PYUV_2Plane(SrcPtr[1],DstPtr[1],Width,Height,SrcPitch,DstPitch,This->RScaleX,This->RScaleY);
  864. Blit_PYUV_PYUV_2Plane(SrcPtr[2],DstPtr[2],Width,Height,SrcPitch,DstPitch,This->RScaleX,This->RScaleY);
  865. }
  866. #if defined(_M_IX86) || !defined(CONFIG_DYNCODE) || defined(BLITTEST)
  867. // !SwapXY
  868. // !DstLeftRight
  869. // SrcType == 12
  870. // DstType == 12
  871. // RScaleX == 16 && RScaleY == 16
  872. // SrcUVX2 == DstUVX2
  873. static void STDCALL Blit_PYUV_PYUV(blit_soft* This, uint8_t** DstPtr,uint8_t** SrcPtr,int DstPitch,int SrcPitch,
  874.                int Width,int Height,uintptr_t Src2SrcLast) 
  875. {
  876. uint8_t* Src[3];
  877. uint8_t* Dst[3];
  878. uint8_t* LookUp = This->LookUp_Data;
  879. int UVY = 1 << This->DstUVY2;
  880. int UVDup = 1;
  881. int SrcPitchUV = SrcPitch >> This->SrcUVPitch2;
  882. int DstPitchUV = DstPitch >> This->DstUVPitch2;
  883. int WidthUV = Width >> This->SrcUVX2;
  884. int YAdd = This->FX.Brightness;
  885. int x,y,i;
  886. for (i=0;i<3;++i)
  887. {
  888. Src[i] = SrcPtr[i];
  889. Dst[i] = DstPtr[i];
  890. }
  891. // skip some UV lines?
  892. if (This->DstUVY2 > This->SrcUVY2)
  893. SrcPitchUV <<= This->DstUVY2 - This->SrcUVY2;
  894. else
  895. UVDup = 1 << (This->SrcUVY2 - This->DstUVY2);
  896. Height >>= This->DstUVY2;
  897. for (y=0;y<Height;++y)
  898. {
  899. for (i=0;i<UVY;++i)
  900. {
  901. if (LookUp)
  902. {
  903. uint8_t* s = Src[0];
  904. uint8_t* d = Dst[0];
  905. for (x=0;x<Width;++x,++s,++d)
  906. *d = LookUp[*s];
  907. }
  908. else
  909. if (YAdd)
  910. {
  911. uint8_t* s = Src[0];
  912. uint8_t* d = Dst[0];
  913. for (x=0;x<Width;++x,++s,++d)
  914. {
  915. int Y = *s + YAdd;
  916. Y = SAT(Y);
  917. *d = (uint8_t)Y;
  918. }
  919. }
  920. else
  921. memcpy(Dst[0],Src[0],Width);
  922. Src[0] += SrcPitch;
  923. Dst[0] += DstPitch;
  924. }
  925. for (i=0;i<UVDup;++i)
  926. {
  927. if (LookUp)
  928. {
  929. for (x=0;x<WidthUV;++x)
  930. {
  931. Dst[1][x] = LookUp[256+Src[1][x]];
  932. Dst[2][x] = LookUp[512+Src[2][x]];
  933. }
  934. }
  935. else
  936. {
  937. memcpy(Dst[1],Src[1],WidthUV);
  938. memcpy(Dst[2],Src[2],WidthUV);
  939. }
  940. Dst[1] += DstPitchUV;
  941. Dst[2] += DstPitchUV;
  942. }
  943. Src[1] += SrcPitchUV;
  944. Src[2] += SrcPitchUV;
  945. }
  946. }
  947. // !SwapXY
  948. // !DstLeftRight
  949. // SrcType == 10
  950. // SrcUVX2 == 1
  951. // DstType == 8 00000000rrrrrrrrggggggggbbbbbbbb
  952. static void STDCALL Blit_PYUV_RGB32(blit_soft* This, uint8_t** DstPtr,uint8_t** SrcPtr,int DstPitch,int SrcPitch,
  953.                  int Width,int Height,uintptr_t Src2SrcLast) 
  954. {
  955. int i,x,y;
  956. uint8_t* Src[3];
  957. uint8_t* Dst;
  958. int SrcStepX[16];
  959. int SrcStepY[16];
  960. int SrcUVY2 = This->SrcUVY2;
  961. int SrcUVPitch2 = This->SrcUVPitch2;
  962. int YAdd = This->FX.Brightness;
  963. int sy0;
  964. int sy=0;
  965. for (i=0;i<3;++i)
  966. Src[i] = SrcPtr[i];
  967. Dst = DstPtr[0];
  968. for (i=0;i<16;++i)
  969. {
  970. SrcStepX[i] = ((This->RScaleX * (i+1)) >> 4) - ((This->RScaleX * i) >> 4);
  971. SrcStepY[i] = ((This->RScaleY * (i+1)) >> 4) - ((This->RScaleY * i) >> 4);
  972. }
  973. for (y=0;y<Height;++y)
  974. {
  975. uint8_t* dx = Dst;
  976. int sx = 0;
  977. for (x=0;x<Width;++x)
  978. {
  979. int cR,cG,cB;
  980. int sx2 = sx>>1;
  981. cR = ((Src[0][sx]+YAdd-16)*0x2568       + 0x3343*(Src[2][sx2]-128)) /0x2000;
  982. cG = ((Src[0][sx]+YAdd-16)*0x2568 - 0x0c92*(Src[1][sx2]-128)  - 0x1a1e*(Src[2][sx2]-128)) /0x2000;
  983. cB = ((Src[0][sx]+YAdd-16)*0x2568 + 0x40cf*(Src[1][sx2]-128))                             /0x2000;
  984. cR = SAT(cR);
  985. cG = SAT(cG);
  986. cB = SAT(cB);
  987. do
  988. {
  989. dx[0]=(uint8_t)cB;
  990. dx[1]=(uint8_t)cG;
  991. dx[2]=(uint8_t)cR;
  992. dx+=4;
  993. } while (SrcStepX[x&15]==0 && ++x<Width);
  994. sx += SrcStepX[x&15];
  995. }
  996. Dst += DstPitch;
  997. while (SrcStepY[y&15]==0 && ++y<Height)
  998. {
  999. memcpy(Dst,Dst-DstPitch,4*Width);
  1000. Dst += DstPitch;
  1001. }
  1002. sy0 = sy;
  1003. sy += SrcStepY[y&15];
  1004. Src[0] += SrcPitch * (sy - sy0);
  1005. Src[1] += (SrcPitch >> SrcUVPitch2) * ((sy >> SrcUVY2) - (sy0 >> SrcUVY2));
  1006. Src[2] += (SrcPitch >> SrcUVPitch2) * ((sy >> SrcUVY2) - (sy0 >> SrcUVY2));
  1007. }
  1008. }
  1009. // !SwapXY
  1010. // !DstLeftRight
  1011. // SrcType == 10
  1012. // SrcUVX2 == 1
  1013. // DstType == 6 rrrrrggggggbbbbb
  1014. static void STDCALL Blit_PYUV_RGB16(blit_soft* This, uint8_t** DstPtr,uint8_t** SrcPtr,int DstPitch,int SrcPitch,
  1015.                  int Width,int Height,uintptr_t Src2SrcLast) 
  1016. {
  1017. int i,x,y;
  1018. uint8_t* Src[3];
  1019. uint8_t* Dst;
  1020. int SrcStepX[16];
  1021. int SrcStepY[16];
  1022. int SrcUVY2 = This->SrcUVY2;
  1023. int SrcUVPitch2 = This->SrcUVPitch2;
  1024. int YAdd = This->FX.Brightness;
  1025. int sy0;
  1026. int sy=0;
  1027. for (i=0;i<3;++i)
  1028. Src[i] = SrcPtr[i];
  1029. Dst = DstPtr[0];
  1030. for (i=0;i<16;++i)
  1031. {
  1032. SrcStepX[i] = ((This->RScaleX * (i+1)) >> 4) - ((This->RScaleX * i) >> 4);
  1033. SrcStepY[i] = ((This->RScaleY * (i+1)) >> 4) - ((This->RScaleY * i) >> 4);
  1034. }
  1035. for (y=0;y<Height;++y)
  1036. {
  1037. uint16_t* dx = (uint16_t*)Dst;
  1038. int sx = 0;
  1039. for (x=0;x<Width;++x)
  1040. {
  1041. int cR,cG,cB;
  1042. int sx2 = sx>>1;
  1043. cR = ((Src[0][sx]+YAdd-16)*0x2568       + 0x3343*(Src[2][sx2]-128)) /0x2000;
  1044. cG = ((Src[0][sx]+YAdd-16)*0x2568 - 0x0c92*(Src[1][sx2]-128)  - 0x1a1e*(Src[2][sx2]-128)) /0x2000;
  1045. cB = ((Src[0][sx]+YAdd-16)*0x2568 + 0x40cf*(Src[1][sx2]-128))                             /0x2000;
  1046. cR = SAT(cR);
  1047. cG = SAT(cG);
  1048. cB = SAT(cB);
  1049. do
  1050. {
  1051. *dx = (uint16_t)(((cR << 8)&0xF800)|((cG << 3)&0x07E0)|(cB >> 3));
  1052. ++dx;
  1053. } while (SrcStepX[x&15]==0 && ++x<Width);
  1054. sx += SrcStepX[x&15];
  1055. }
  1056. Dst += DstPitch;
  1057. while (SrcStepY[y&15]==0 && ++y<Height)
  1058. {
  1059. memcpy(Dst,Dst-DstPitch,2*Width);
  1060. Dst += DstPitch;
  1061. }
  1062. sy0 = sy;
  1063. sy += SrcStepY[y&15];
  1064. Src[0] += SrcPitch * (sy - sy0);
  1065. Src[1] += (SrcPitch >> SrcUVPitch2) * ((sy >> SrcUVY2) - (sy0 >> SrcUVY2));
  1066. Src[2] += (SrcPitch >> SrcUVPitch2) * ((sy >> SrcUVY2) - (sy0 >> SrcUVY2));
  1067. }
  1068. }
  1069. static void STDCALL BlitUniversal(blit_soft* This, uint8_t** DstPtr,uint8_t** SrcPtr,int DstPitch,int SrcPitch,
  1070.                int Width,int Height,uintptr_t Src2SrcLast) 
  1071. {
  1072. //this will be very-very slow, only for compability and testing
  1073. int i,j,x,y;
  1074. uint8_t* Src[3];
  1075. uint8_t* Dst[3];
  1076. int SrcType = This->SrcType;
  1077. int DstType = This->DstType;
  1078. int DstMask[3],DstPos[3];
  1079. int SrcMask[3],SrcPos[3];
  1080. int DitherMask[3];
  1081. uint8_t* PalLookUp = (uint8_t*)This->LookUp_Data;
  1082. uint8_t* wp;
  1083. int Flags = This->FX.Flags;
  1084. bool_t Dither = (Flags & BLITFX_DITHER) != 0 && !(This->Dst.Flags & PF_FOURCC);
  1085. bool_t PalDither = Dither && (This->Dst.Flags & PF_PALETTE);
  1086. const rgb* SrcPalette = This->SrcPalette;
  1087. int SrcStepX[16];
  1088. int SrcStepY[16];
  1089. int RScaleX = This->RScaleX;
  1090. int RScaleY = This->RScaleY;
  1091. int SrcUVPitch2 = This->SrcUVPitch2;
  1092. int SrcUVX2 = This->SrcUVX2;
  1093. int SrcUVY2 = This->SrcUVY2;
  1094. int DstUVX2 = This->DstUVX2;
  1095. int DstUVY2 = This->DstUVY2;
  1096. int DstStepX = This->DstBPP;
  1097. int DstStepX2 = This->DstBPP;
  1098. int DstStepY = DstPitch << 3;
  1099. int DstStepY2 = DstStepY >> This->DstUVPitch2;
  1100. int dy = 0;
  1101. int dy2 = 0;
  1102. int cR,cG,cB;
  1103. int Y,U,V;
  1104. int sy0;
  1105. int sy=0;
  1106. int YAdd = This->FX.Brightness;
  1107. uint32_t SrcInvert = 0;
  1108. uint32_t DstInvert = 0;
  1109. SrcMask[0] = This->Src.BitMask[0];
  1110. SrcMask[1] = This->Src.BitMask[1];
  1111. SrcMask[2] = This->Src.BitMask[2];
  1112. DstMask[0] = This->Dst.BitMask[0];
  1113. DstMask[1] = This->Dst.BitMask[1];
  1114. DstMask[2] = This->Dst.BitMask[2];
  1115. for (i=0;i<3;++i)
  1116. {
  1117. DitherMask[i] = Dither ? (1 << (8 - BitMaskSize(DstMask[i]))) - 1 : 0;
  1118. SrcPos[i] = BitMaskPos(SrcMask[i]) + BitMaskSize(SrcMask[i]);
  1119. DstPos[i] = BitMaskPos(DstMask[i]) + BitMaskSize(DstMask[i]);
  1120. SrcMask[i] <<= 8;
  1121. DstMask[i] <<= 8;
  1122. Src[i] = SrcPtr[i];
  1123. Dst[i] = DstPtr[i];
  1124. }
  1125. if (This->DstPalette)
  1126. {
  1127. DstPos[0] = 11;
  1128. DstPos[1] = 7;
  1129. DstPos[2] = 3; 
  1130. DstMask[0] = 0xF0000;
  1131. DstMask[1] = 0x0F000;
  1132. DstMask[2] = 0x00F00;
  1133. }
  1134. for (j=0;j<16;++j)
  1135. {
  1136. SrcStepX[j] = ((RScaleX * (j+1)) >> 4) - ((RScaleX * j) >> 4);
  1137. SrcStepY[j] = ((RScaleY * (j+1)) >> 4) - ((RScaleY * j) >> 4);
  1138. }
  1139. if (This->DstLeftRight)
  1140. {
  1141. DstStepX = -DstStepX;
  1142. DstStepX2 = -DstStepX2;
  1143. if (This->DstBPP < 8)
  1144. dy = 8 - This->DstBPP;
  1145. }
  1146. if (This->SwapXY)
  1147. {
  1148. SwapInt(&DstUVX2,&DstUVY2);
  1149. SwapInt(&DstStepX,&DstStepY);
  1150. SwapInt(&DstStepX2,&DstStepY2);
  1151. }
  1152. cR = (DitherMask[0] >> 1);
  1153. cG = (DitherMask[1] >> 1);
  1154. cB = (DitherMask[2] >> 1);
  1155. Y=U=V=0;
  1156. if (This->Src.Flags & PF_INVERTED)
  1157. SrcInvert = (This->Src.BitCount>=32?0:(1 << This->Src.BitCount))-1;
  1158. if (This->Dst.Flags & PF_INVERTED)
  1159. DstInvert = (This->Dst.BitCount>=32?0:(1 << This->Dst.BitCount))-1;
  1160. for (y=0;y<Height;++y)
  1161. {
  1162. int dx=dy;
  1163. int dx2=dy2;
  1164. int sx=0;
  1165. for (x=0;x<Width;sx+=SrcStepX[x&15],++x,dx+=DstStepX)
  1166. {
  1167. uint8_t* q;
  1168. const rgb* p;
  1169. uint32_t v,w;
  1170. switch (SrcType)
  1171. {
  1172. case 10: //Planar YUV->RGB
  1173. cR += ((Src[0][sx]+YAdd-16)*0x2568               + 0x3343*(Src[2][sx>>SrcUVX2]-128)) /0x2000;
  1174. cG += ((Src[0][sx]+YAdd-16)*0x2568 - 0x0c92*(Src[1][sx>>SrcUVX2]-128)  - 0x1a1e*(Src[2][sx>>SrcUVX2]-128)) /0x2000;
  1175. cB += ((Src[0][sx]+YAdd-16)*0x2568 + 0x40cf*(Src[1][sx>>SrcUVX2]-128))                                     /0x2000;
  1176. cR=SAT(cR);
  1177. cG=SAT(cG);
  1178. cB=SAT(cB);
  1179. break;
  1180. case 11: //Packed YUV->RGB
  1181. cR += ((Src[0][sx*2]+YAdd-16)*0x2568   + 0x3343*(Src[2][4*(sx>>1)]-128)) /0x2000;
  1182. cG += ((Src[0][sx*2]+YAdd-16)*0x2568 - 0x0c92*(Src[1][4*(sx>>1)]-128)  - 0x1a1e*(Src[2][4*(sx>>1)]-128)) /0x2000;
  1183. cB += ((Src[0][sx*2]+YAdd-16)*0x2568 + 0x40cf*(Src[1][4*(sx>>1)]-128))                                   /0x2000;
  1184. cR=SAT(cR);
  1185. cG=SAT(cG);
  1186. cB=SAT(cB);
  1187. break;
  1188. case 12: //Planar YUV->YUV
  1189. Y += Src[0][sx];
  1190. U += Src[1][sx>>SrcUVX2];
  1191. V += Src[2][sx>>SrcUVX2];
  1192. //Y=SAT(Y);
  1193. //U=SAT(U);
  1194. //V=SAT(V);
  1195. break;
  1196. case 13: //Packed YUV->YUV
  1197. Y += Src[0][sx*2];
  1198. U += Src[1][4*(sx>>1)];
  1199. V += Src[2][4*(sx>>1)];
  1200. //Y=SAT(Y);
  1201. //U=SAT(U);
  1202. //V=SAT(V);
  1203. break;
  1204. case 1: //Pal1->RGB
  1205. p = &SrcPalette[ ((Src[0][sx>>3] >> ((~sx)&7)) & 1) ^ SrcInvert];
  1206. cR += p->c.r; cG += p->c.g; cB += p->c.b;
  1207. cR=SAT(cR);
  1208. cG=SAT(cG);
  1209. cB=SAT(cB);
  1210. break;
  1211. case 2: //Pal2->RGB
  1212. p = &SrcPalette[ ((Src[0][sx>>2] >> (((~sx)&3)*2)) & 3) ^ SrcInvert];
  1213. cR += p->c.r; cG += p->c.g; cB += p->c.b;
  1214. cR=SAT(cR);
  1215. cG=SAT(cG);
  1216. cB=SAT(cB);
  1217. break;
  1218. case 3: //Pal4->RGB
  1219. p = &SrcPalette[ ((Src[0][sx>>1] >> (((~sx)&1)*4)) & 15) ^ SrcInvert];
  1220. cR += p->c.r; cG += p->c.g; cB += p->c.b;
  1221. cR=SAT(cR);
  1222. cG=SAT(cG);
  1223. cB=SAT(cB);
  1224. break;
  1225. case 4: //Pal8->RGB
  1226. p = &SrcPalette[Src[0][sx] ^ SrcInvert];
  1227. cR += p->c.r; cG += p->c.g; cB += p->c.b;
  1228. cR=SAT(cR);
  1229. cG=SAT(cG);
  1230. cB=SAT(cB);
  1231. break;
  1232. case 5: //RGB8->RGB
  1233. v = Src[0][sx];
  1234. v ^= SrcInvert;
  1235. v <<= 8;
  1236. cR += (v & SrcMask[0]) >> SrcPos[0];
  1237. cG += (v & SrcMask[1]) >> SrcPos[1];
  1238. cB += (v & SrcMask[2]) >> SrcPos[2];
  1239. cR=SAT(cR);
  1240. cG=SAT(cG);
  1241. cB=SAT(cB);
  1242. break;
  1243. case 6: //RGB16->RGB
  1244. v = ((uint16_t*)Src[0])[sx];
  1245. v ^= SrcInvert;
  1246. v <<= 8;
  1247. cR += (v & SrcMask[0]) >> SrcPos[0];
  1248. cG += (v & SrcMask[1]) >> SrcPos[1];
  1249. cB += (v & SrcMask[2]) >> SrcPos[2];
  1250. cR=SAT(cR);
  1251. cG=SAT(cG);
  1252. cB=SAT(cB);
  1253. break;
  1254. case 7: //RGB24->RGB
  1255. v = Src[0][sx*3] | (Src[0][sx*3+1] << 8) | (Src[0][sx*3+2] << 16);
  1256. v ^= SrcInvert;
  1257. v <<= 8;
  1258. cR += (v & SrcMask[0]) >> SrcPos[0];
  1259. cG += (v & SrcMask[1]) >> SrcPos[1];
  1260. cB += (v & SrcMask[2]) >> SrcPos[2];
  1261. cR=SAT(cR);
  1262. cG=SAT(cG);
  1263. cB=SAT(cB);
  1264. break;
  1265. default: //RGB32->RGB
  1266. v = ((uint32_t*)Src[0])[sx];
  1267. v ^= SrcInvert;
  1268. v <<= 8;
  1269. cR += (v & SrcMask[0]) >> SrcPos[0];
  1270. cG += (v & SrcMask[1]) >> SrcPos[1];
  1271. cB += (v & SrcMask[2]) >> SrcPos[2];
  1272. cR=SAT(cR);
  1273. cG=SAT(cG);
  1274. cB=SAT(cB);
  1275. break;
  1276. }
  1277. q = Dst[0]+(dx >> 3);
  1278. switch (DstType)
  1279. {
  1280. case 10: //RGB->Planar YUV
  1281. Y = ((2105 * cR) + (4128 * cG) + (802 * cB))/0x2000 + 16;
  1282. U = (-(1212 * cR) - (2384 * cG) + (3596 * cB))/0x2000 + 128;
  1283. V = ((3596 * cR) - (3015 * cG) - (582 * cB))/0x2000 + 128;
  1284. *q = (uint8_t)Y;
  1285. Dst[1][dx2 >> 3] = (uint8_t)U;
  1286. Dst[2][dx2 >> 3] = (uint8_t)V;
  1287. if ((x & 1) || DstUVX2==0)
  1288. dx2+=DstStepX2;
  1289. cR=cG=cB=0;
  1290. break;
  1291. case 11: //RGB->Packed YUV
  1292. Y = ((2105 * cR) + (4128 * cG) + (802 * cB))/0x2000 + 16;
  1293. U = (-(1212 * cR) - (2384 * cG) + (3596 * cB))/0x2000 + 128;
  1294. V = ((3596 * cR) - (3015 * cG) - (582 * cB))/0x2000 + 128;
  1295. Y=SAT(Y);
  1296. U=SAT(U);
  1297. V=SAT(V);
  1298. *q = (uint8_t)Y;
  1299. Dst[1][4*(dx >> 5)] = (uint8_t)U;
  1300. Dst[2][4*(dx >> 5)] = (uint8_t)V;
  1301. cR=cG=cB=0;
  1302. break;
  1303. case 12: //YUV->Planar YUV
  1304. Y += YAdd;
  1305. Y=SAT(Y);
  1306. *q = (uint8_t)Y;
  1307. Dst[1][dx2 >> 3] = (uint8_t)U;
  1308. Dst[2][dx2 >> 3] = (uint8_t)V;
  1309. if ((x & 1) || DstUVX2==0)
  1310. dx2+=DstStepX2;
  1311. Y=U=V=0;
  1312. break;
  1313. case 13: //YUV->Packed YUV
  1314. Y += YAdd;
  1315. Y=SAT(Y);
  1316. *q = (uint8_t)Y;
  1317. Dst[1][4*(dx >> 5)] = (uint8_t)U;
  1318. Dst[2][4*(dx >> 5)] = (uint8_t)V;
  1319. Y=U=V=0;
  1320. break;
  1321. case 1: //RGB->Pal1
  1322. w = ((cR << DstPos[0]) & DstMask[0]) |
  1323. ((cG << DstPos[1]) & DstMask[1]) |
  1324. ((cB << DstPos[2]) & DstMask[2]);
  1325. wp = PalLookUp + (w >> 8)*4;
  1326. w = wp[0];
  1327. w ^= DstInvert;
  1328. *q &= ~(1 << ((~dx)&7));
  1329. *q |=  (w << ((~dx)&7));
  1330. if (PalDither)
  1331. {
  1332. cR -= wp[1];
  1333. cG -= wp[2];
  1334. cB -= wp[3];
  1335. }
  1336. else
  1337. cR=cG=cB=0;
  1338. break;
  1339. case 2: //RGB->Pal2
  1340. w = ((cR << DstPos[0]) & DstMask[0]) |
  1341. ((cG << DstPos[1]) & DstMask[1]) |
  1342. ((cB << DstPos[2]) & DstMask[2]);
  1343. wp = PalLookUp + (w >> 8)*4;
  1344. w = wp[0];
  1345. w ^= DstInvert;
  1346. *q &= ~(3 << ((~dx)&6));
  1347. *q |=  (w << ((~dx)&6));
  1348. if (PalDither)
  1349. {
  1350. cR -= wp[1];
  1351. cG -= wp[2];
  1352. cB -= wp[3];
  1353. }
  1354. else
  1355. cR=cG=cB=0;
  1356. break;
  1357. case 3: //RGB->Pal4
  1358. w = ((cR << DstPos[0]) & DstMask[0]) |
  1359. ((cG << DstPos[1]) & DstMask[1]) |
  1360. ((cB << DstPos[2]) & DstMask[2]);
  1361. wp = PalLookUp + (w >> 8)*4;
  1362. w = wp[0];
  1363. w ^= DstInvert;
  1364. *q &= ~(15 << ((~dx)&4));
  1365. *q |=  (w  << ((~dx)&4));
  1366. if (PalDither)
  1367. {
  1368. cR -= wp[1];
  1369. cG -= wp[2];
  1370. cB -= wp[3];
  1371. }
  1372. else
  1373. cR=cG=cB=0;
  1374. break;
  1375. case 14: //YUV->Pal8
  1376. w = ((Y << DstPos[0]) & DstMask[0]) |
  1377. ((U << DstPos[1]) & DstMask[1]) |
  1378. ((V << DstPos[2]) & DstMask[2]);
  1379. wp = PalLookUp + (w >> 8)*4;
  1380. w = wp[0];
  1381. w ^= DstInvert;
  1382. *q = (uint8_t)w;
  1383. if (PalDither)
  1384. {
  1385. Y -= wp[1];
  1386. U -= wp[2];
  1387. V -= wp[3];
  1388. }
  1389. else
  1390. Y=U=V=0;
  1391. break;
  1392. case 4: //RGB->Pal8
  1393. w = ((cR << DstPos[0]) & DstMask[0]) |
  1394. ((cG << DstPos[1]) & DstMask[1]) |
  1395. ((cB << DstPos[2]) & DstMask[2]);
  1396. wp = PalLookUp + (w >> 8)*4;
  1397. w = wp[0];
  1398. w ^= DstInvert;
  1399. *q = (uint8_t)w;
  1400. if (PalDither)
  1401. {
  1402. cR -= wp[1];
  1403. cG -= wp[2];
  1404. cB -= wp[3];
  1405. }
  1406. else
  1407. cR=cG=cB=0;
  1408. break;
  1409. case 5: //RGB->RGB8
  1410. w = ((cR << DstPos[0]) & DstMask[0]) |
  1411. ((cG << DstPos[1]) & DstMask[1]) |
  1412. ((cB << DstPos[2]) & DstMask[2]);
  1413. *q = (uint8_t)((w >> 8) ^ DstInvert);
  1414. cR &= DitherMask[0];
  1415. cG &= DitherMask[1];
  1416. cB &= DitherMask[2];
  1417. break;
  1418. case 6: //RGB->RGB16
  1419. w = ((cR << DstPos[0]) & DstMask[0]) |
  1420. ((cG << DstPos[1]) & DstMask[1]) |
  1421. ((cB << DstPos[2]) & DstMask[2]);
  1422. *(uint16_t*)q = (uint16_t)((w >> 8) ^ DstInvert);
  1423. cR &= DitherMask[0];
  1424. cG &= DitherMask[1];
  1425. cB &= DitherMask[2];
  1426. break;
  1427. case 7: //RGB->RGB24
  1428. w = ((cR << DstPos[0]) & DstMask[0]) |
  1429. ((cG << DstPos[1]) & DstMask[1]) |
  1430. ((cB << DstPos[2]) & DstMask[2]);
  1431. w >>= 8;
  1432. w ^= DstInvert;
  1433. q[0] = (uint8_t)(w);
  1434. q[1] = (uint8_t)(w >> 8);
  1435. q[2] = (uint8_t)(w >> 16);
  1436. cR &= DitherMask[0];
  1437. cG &= DitherMask[1];
  1438. cB &= DitherMask[2];
  1439. break;
  1440. default: //RGB->RGB32
  1441. w = ((cR << DstPos[0]) & DstMask[0]) |
  1442. ((cG << DstPos[1]) & DstMask[1]) |
  1443. ((cB << DstPos[2]) & DstMask[2]);
  1444. *(uint32_t*)q = (w >> 8) ^ DstInvert;
  1445. cR &= DitherMask[0];
  1446. cG &= DitherMask[1];
  1447. cB &= DitherMask[2];
  1448. break;
  1449. }
  1450. }
  1451. dy += DstStepY;
  1452. if ((y & 1) || DstUVY2==0)
  1453. dy2 += DstStepY2;
  1454. sy0 = sy;
  1455. sy += SrcStepY[y&15];
  1456. Src[0] += SrcPitch * (sy - sy0);
  1457. Src[1] += (SrcPitch >> SrcUVPitch2) * ((sy >> SrcUVY2) - (sy0 >> SrcUVY2));
  1458. Src[2] += (SrcPitch >> SrcUVPitch2) * ((sy >> SrcUVY2) - (sy0 >> SrcUVY2));
  1459. }
  1460. }
  1461. #endif
  1462. static bool_t BlitCompile(blit_soft* p,
  1463.    const pixel* NewDst,const pixel* NewSrc,
  1464.       const blitfx* NewFX,bool_t NewOnlyDiff)
  1465. {
  1466. int i;
  1467. bool_t Gray,SrcPlanarYUV,DstPlanarYUV;
  1468. if (EqPixel(&p->Dst,NewDst) && 
  1469. EqPixel(&p->Src,NewSrc) && 
  1470. EqBlitFX(&p->FX,NewFX) &&
  1471. NewOnlyDiff == p->OnlyDiff)
  1472. return p->Entry != NULL;
  1473. CodeStart(&p->Code);
  1474. // defaults
  1475. p->Caps = VC_BRIGHTNESS|VC_DITHER|VC_SATURATION|VC_CONTRAST|VC_RGBADJUST;
  1476. p->SrcAlignPos = 2;
  1477. p->DstAlignPos = 2;
  1478. p->DstAlignSize = 2;
  1479. p->Dst = *NewDst;
  1480. p->Src = *NewSrc;
  1481. p->FX = *NewFX;
  1482. p->OnlyDiff = (boolmem_t)NewOnlyDiff;
  1483. p->SwapXY = (boolmem_t)((p->FX.Direction & DIR_SWAPXY) != 0);
  1484. p->DstLeftRight = (boolmem_t)((p->FX.Direction & DIR_MIRRORLEFTRIGHT) != 0);
  1485. p->DstUpDown = (boolmem_t)((p->FX.Direction & DIR_MIRRORUPDOWN) != 0);
  1486. p->SrcUpDown = (boolmem_t)((p->FX.Flags & BLITFX_AVOIDTEARING) && !p->SwapXY && p->DstUpDown != ((p->FX.Flags & BLITFX_VMEMUPDOWN) != 0));
  1487. if (p->SrcUpDown)
  1488. p->DstUpDown = (boolmem_t)!p->DstUpDown;
  1489. // it's faster using slices with rotation (not just with AVOIDTEARING)
  1490. // probably because of ram page trashing (during vertical writing)
  1491. p->Slices = (boolmem_t)(p->SwapXY != ((p->FX.Flags & BLITFX_VMEMROTATED) != 0));
  1492. p->SlicesReverse = (boolmem_t)((p->SwapXY ? p->DstUpDown : p->DstLeftRight) == ((p->FX.Flags & BLITFX_VMEMUPDOWN) != 0));
  1493. Gray = (p->Dst.Flags & PF_PALETTE) && (p->Dst.BitCount == 4 || p->Dst.BitCount == 2);
  1494. p->RScaleX = CalcRScale(p->FX.ScaleX,Gray);
  1495. p->RScaleY = CalcRScale(p->FX.ScaleY,Gray);
  1496. // important these integeres should be 1 or 0
  1497. p->DstHalfX = p->SrcHalfX = p->RScaleX == 32;
  1498. p->DstHalfY = p->SrcHalfY = p->RScaleY == 32;
  1499. p->DstDoubleX = p->SrcDoubleX = p->RScaleX == 8;
  1500. p->DstDoubleY = p->SrcDoubleY = p->RScaleY == 8;
  1501. if (p->SwapXY)
  1502. {
  1503. SwapInt(&p->DstHalfX,&p->DstHalfY);
  1504. SwapInt(&p->DstDoubleX,&p->DstDoubleY);
  1505. }
  1506. p->SrcBPP = GetBPP(&p->Src);
  1507. p->SrcBPP2 = -3;
  1508. for (i=p->SrcBPP;i>1;i>>=1)
  1509. ++p->SrcBPP2;
  1510. p->DstBPP = GetBPP(&p->Dst);
  1511. p->DstBPP2 = -3;
  1512. for (i=p->DstBPP;i>1;i>>=1)
  1513. ++p->DstBPP2;
  1514. p->SrcYUV = (boolmem_t)AnyYUV(&p->Src);
  1515. p->SrcPalette = DefaultPal(&p->Src);
  1516. p->DstPalette = DefaultPal(&p->Dst);
  1517. free(p->LookUp_Data);
  1518. p->LookUp_Data = NULL;
  1519. p->ColorLookup = (boolmem_t)((p->FX.Flags & BLITFX_COLOR_LOOKUP) != 0);
  1520. #ifdef ARM
  1521. p->ARM5 = (boolmem_t)((QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_5E)!=0);
  1522. p->WMMX = (boolmem_t)((QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_WMMX)!=0 && 
  1523.           !QueryAdvanced(ADVANCED_NOWMMX) && (p->Dst.Flags & PF_16ALIGNED) && (p->Src.Flags & PF_16ALIGNED));
  1524. p->QAdd = (boolmem_t)((QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_5E)!=0 && 
  1525.       !p->DstPalette && !p->WMMX && !(p->FX.Flags & BLITFX_DITHER) && !p->ColorLookup);
  1526. #endif
  1527. CalcColor(p);
  1528. if (p->DstPalette)
  1529. BuildPalLookUp(p,p->SrcYUV);
  1530. p->ArithStretch = (boolmem_t)((p->FX.Flags & BLITFX_ARITHSTRETCHALWAYS) != 0);
  1531. if ((p->FX.Flags & BLITFX_ARITHSTRETCH50) && p->RScaleX==32 && p->RScaleY==32)
  1532. p->ArithStretch = 1;
  1533. if (p->DstPalette)
  1534. p->ArithStretch = 0;
  1535. SrcPlanarYUV = PlanarYUV(&p->Src,&p->SrcUVX2,&p->SrcUVY2,&p->SrcUVPitch2);
  1536. DstPlanarYUV = PlanarYUV(&p->Dst,&p->DstUVX2,&p->DstUVY2,&p->DstUVPitch2);
  1537. p->DirX = p->DstLeftRight ? -1:1;
  1538. for (i=0;i<3;++i)
  1539. {
  1540. p->DstSize[i] = BitMaskSize(p->Dst.BitMask[i]);
  1541. p->DstPos[i] = BitMaskPos(p->Dst.BitMask[i]);
  1542. p->SrcSize[i] = BitMaskSize(p->Src.BitMask[i]);
  1543. p->SrcPos[i] = BitMaskPos(p->Src.BitMask[i]);
  1544. }
  1545. #if defined(ARM)
  1546. if ((p->Dst.Flags & PF_RGB) && p->Dst.BitCount==16 && !p->SrcYUV)
  1547. Any_RGB_RGB(p);
  1548. if (!p->SrcYUV && DstPlanarYUV && p->RScaleX==16 && p->RScaleY==16)
  1549. Fix_Any_YUV(p);
  1550. #endif
  1551. #if (defined(ARM) || defined(SH3) || defined(MIPS)) && defined(CONFIG_DYNCODE)
  1552. if (SrcPlanarYUV)
  1553. {
  1554. #if defined(ARM)
  1555. if (DstPlanarYUV && p->RScaleX==16 && p->RScaleY==16 && 
  1556. ((p->SrcUVX2==p->DstUVX2 && p->SrcUVY2==p->DstUVY2 && !(p->SwapXY && p->SrcUVX2 != p->SrcUVY2)) || 
  1557. (p->DstUVX2==1 && p->DstUVY2==1)))
  1558. Fix_Any_YUV(p);
  1559. if (PackedYUV(&p->Dst) && p->RScaleX==16 && p->RScaleY==16 && p->SrcUVY2<2 && p->SrcUVX2<2)
  1560. Fix_PackedYUV_YUV(p);
  1561. #endif
  1562. if ((p->Dst.Flags & (PF_RGB|PF_PALETTE)) && (p->Dst.BitCount == 8 || p->Dst.BitCount == 16 || p->Dst.BitCount == 32))
  1563. {
  1564. #if defined(ARM)
  1565. if (p->Dst.BitCount == 16 && p->WMMX && PlanarYUV420(&p->Src) && 
  1566. (p->RScaleX==16 || p->RScaleX==8 || p->RScaleX==32) && (p->RScaleY==16 || p->RScaleY==8 || p->RScaleY==32))
  1567. WMMXFix_RGB_UV(p);
  1568. else
  1569. if ((p->Dst.BitCount == 16 || p->Dst.BitCount==32) && p->SrcUVX2==1 && p->SrcUVY2==1 && p->RScaleX == 16 && p->RScaleY == 16)
  1570. Fix_RGB_UV(p);
  1571. else
  1572. if (p->Dst.BitCount == 16 && p->SrcUVX2==1 && p->SrcUVY2==1 &&
  1573. (p->RScaleX == 8 || p->RScaleX == 16) && 
  1574. (p->RScaleY == 8 || p->RScaleY == 16) && !p->ArithStretch)
  1575. Fix_RGB_UV(p);
  1576. else
  1577. if (p->Dst.BitCount == 16 && p->SrcUVX2==1 && p->SrcUVY2==1 && p->RScaleX == 32 && p->RScaleY == 32)
  1578. Half_RGB_UV(p);
  1579. else
  1580. Stretch_RGB_UV(p);
  1581. #else
  1582. #if !defined(MIPS)
  1583. if (p->SrcUVX2==1 && p->SrcUVY2==1 && 
  1584. (p->RScaleX == 8 || p->RScaleX == 16) &&
  1585. (p->RScaleY == 8 || p->RScaleY == 16))
  1586. #endif
  1587. Fix_RGB_UV(p);
  1588. #endif
  1589. }
  1590. else
  1591. if (Gray)
  1592. Fix_Gray_UV(p);
  1593. }
  1594. #endif
  1595. CodeBuild(&p->Code);
  1596. if (p->Code.Size)
  1597. p->Entry = (blitsoftentry)p->Code.Code;
  1598. else
  1599. p->Entry = NULL;
  1600. #if defined(_M_IX86) && !defined(TARGET_SYMBIAN)
  1601. if (p->FX.Direction==0 && p->RScaleX==16 && p->RScaleY==16)
  1602. {
  1603. uint32_t In = DefFourCC(&p->Src);
  1604. uint32_t Out = DefFourCC(&p->Dst);
  1605. #ifdef CONFIG_CONTEXT
  1606. int Caps = QueryPlatform(PLATFORM_CAPS);
  1607. #else
  1608. int Caps = CPUCaps();
  1609. #endif
  1610. const blitmmx* i;
  1611. for (i=BlitMMX;i->In;++i)
  1612. if (i->In==In && i->Out==Out)
  1613. {
  1614. p->Caps &= ~VC_DITHER;
  1615. if (AnyYUV(&p->Src))
  1616. CalcYUVMMX(p);
  1617. if (Caps & CAPS_X86_MMX2)
  1618. p->Entry = i->Func[1];
  1619. else if (Caps & CAPS_X86_3DNOW)
  1620. p->Entry = i->Func[2];
  1621. else
  1622. p->Entry = i->Func[0];
  1623. break;
  1624. }
  1625. }
  1626. #endif
  1627. if (!p->Entry)
  1628. {
  1629. // use YUV internal calulaction?
  1630. bool_t YUV = (AnyYUV(&p->Dst) || 
  1631. (p->Dst.BitCount==8 && p->Dst.Flags & PF_PALETTE)) && p->SrcYUV;
  1632. p->DstType = UniversalType(&p->Dst,YUV);
  1633. p->SrcType = UniversalType(&p->Src,YUV);
  1634. #if defined(_M_IX86) || !defined(CONFIG_DYNCODE) || defined(BLITTEST)
  1635. if (p->SrcType>=0 && p->DstType>=0)
  1636. {
  1637. // universal
  1638. if (AnyYUV(&p->Dst)) 
  1639. p->Caps &= ~VC_DITHER;
  1640. else
  1641. p->Caps = VC_BRIGHTNESS | VC_DITHER;
  1642. p->Entry = BlitUniversal; 
  1643. }
  1644. if (p->SrcUVX2 == 1 && !p->SwapXY && !p->DstLeftRight && p->SrcType == 10)
  1645. {
  1646. if (p->DstType == 8 && 
  1647. p->Dst.BitMask[0] == 0xFF0000 &&
  1648. p->Dst.BitMask[1] == 0x00FF00 &&
  1649. p->Dst.BitMask[2] == 0x0000FF)
  1650. {
  1651. p->Caps = VC_BRIGHTNESS;
  1652. p->Entry = Blit_PYUV_RGB32;
  1653. }
  1654. if (p->DstType == 6 && 
  1655. p->Dst.BitMask[0] == 0xF800 &&
  1656. p->Dst.BitMask[1] == 0x07E0 &&
  1657. p->Dst.BitMask[2] == 0x001F)
  1658. {
  1659. p->Caps = VC_BRIGHTNESS;
  1660. p->Entry = Blit_PYUV_RGB16;
  1661. }
  1662. }
  1663. if (p->SrcUVX2 == p->DstUVX2 && !p->SwapXY && !p->DstLeftRight &&
  1664. p->RScaleX == 16 && p->RScaleY==16 &&
  1665. p->SrcType == 12 && p->DstType == 12)
  1666. {
  1667. CalcYUVLookUp(p);
  1668. p->Caps &= ~VC_DITHER;
  1669. p->Entry = Blit_PYUV_PYUV;
  1670. }
  1671. #endif
  1672. if (p->SrcUVX2 == p->DstUVX2 &&
  1673. p->SrcUVY2 == p->DstUVY2 && !p->SwapXY && !p->DstLeftRight &&
  1674. (p->RScaleX != 16 || p->RScaleY != 16) &&
  1675. (p->RScaleX == 16 || p->RScaleX == 8 || p->RScaleX == 32 || p->RScaleX == 4 || p->RScaleX == 64) && 
  1676. (p->RScaleY == 16 || p->RScaleY == 8 || p->RScaleY == 32 || p->RScaleX == 4 || p->RScaleX == 64) && 
  1677. p->SrcType == 12 && p->DstType == 12 &&
  1678. !p->FX.Saturation && !p->FX.Contrast && !p->FX.RGBAdjust[0] && 
  1679. !p->FX.RGBAdjust[1] && !p->FX.RGBAdjust[2] && !p->FX.Brightness)
  1680. {
  1681. p->Caps = 0;
  1682. p->Entry = Blit_PYUV_PYUV_2;
  1683. }
  1684. }
  1685. return p->Entry != NULL;
  1686. }
  1687. blitpack* BlitCreate(const video* Dst, 
  1688.          const video* Src, const blitfx* FX, int* OutCaps)
  1689. {
  1690. blitfx CopyFX;
  1691. bool_t Gray;
  1692. blitpack* p = BlitAlloc();
  1693. if (!p) return NULL;
  1694. if (!FX)
  1695. {
  1696. memset(&CopyFX,0,sizeof(CopyFX));
  1697. CopyFX.ScaleX = SCALE_ONE;
  1698. CopyFX.ScaleY = SCALE_ONE;
  1699. FX = &CopyFX;
  1700. }
  1701. if (!BlitCompile(&p->Code[0],&Dst->Pixel,&Src->Pixel,FX,0) ||
  1702. ((FX->Flags & BLITFX_ONLYDIFF) && !BlitCompile(&p->Code[1],&Dst->Pixel,&Src->Pixel,FX,1)))
  1703. {
  1704. BlitRelease(p);
  1705. return NULL;
  1706. }
  1707. p->FX = *FX;
  1708. p->Dst = *Dst;
  1709. p->Src = *Src;
  1710. Gray = (Dst->Pixel.Flags & PF_PALETTE) && 
  1711.    (Dst->Pixel.BitCount == 4 || Dst->Pixel.BitCount == 2);
  1712. p->RScaleX = CalcRScale(FX->ScaleX,Gray);
  1713. p->RScaleY = CalcRScale(FX->ScaleY,Gray);
  1714. if (OutCaps)
  1715. *OutCaps = p->Code[0].Caps;
  1716. return p;
  1717. }
  1718. static NOINLINE int CMul(blit_soft* p, int64_t* r, int64_t v, bool_t UV)
  1719. {
  1720. int m;
  1721. if (UV)
  1722. {
  1723. m = p->FX.Saturation;
  1724. if (m<0) m >>= 1; // adjust negtive interval: -128..0 -> -64..0
  1725. m = 4*m+256;
  1726. v *= m;
  1727. if (v<0) 
  1728. v -= 128; 
  1729. else 
  1730. v += 128;
  1731. v >>= 8;
  1732. }
  1733. m = p->FX.Contrast;
  1734. if (m<0) m >>= 1; // adjust negtive interval: -128..0 -> -64..0
  1735. m = 4*m + 256;
  1736. v *= m;
  1737. if (v<0) 
  1738. v -= 128; 
  1739. else 
  1740. v += 128;
  1741. v >>= 8;
  1742. if (r) *r = v;
  1743. return (int)v;
  1744. }
  1745. static NOINLINE int CAdd(blit_soft* p, int64_t* r, int64_t v, int v0, int vUV)
  1746. {
  1747. int m;
  1748. m = p->FX.Saturation;
  1749. if (m<0) m >>= 1; // adjust negtive interval: -128..0 -> -64..0
  1750. m = 4*m+256;
  1751. v += ((256 - m) * vUV) >> 1;
  1752. m = p->FX.Contrast;
  1753. if (m<0) m >>= 1; // adjust negtive interval: -128..0 -> -64..0
  1754. m = 4*m + 256;
  1755. v += ((256 - m)*(v0 - v)) >> 8;
  1756. if (r) *r = v;
  1757. return (int)v;
  1758. }
  1759. static INLINE bool_t InRange32(int64_t v)
  1760. {
  1761. return v >= -MAX_INT && v <= MAX_INT;
  1762. }
  1763. static INLINE uint8_t RotateRight8(int v,int Bits)
  1764. {
  1765. Bits &= 7;
  1766. return (uint8_t)(((v >> Bits) & ((1 << (8-Bits))-1)) | (v << (8-Bits)));
  1767. }
  1768. void CalcPalYUVLookUp(blit_soft* p)
  1769. {
  1770. p->LookUp_Size = 256+4+256+256;
  1771. p->LookUp_Data = malloc(p->LookUp_Size);
  1772. if (p->LookUp_Data)
  1773. {
  1774. int v,i,n = 1<<p->Src.BitCount;
  1775. rgb* Pal = p->Src.Palette;
  1776. uint8_t* LookUp = p->LookUp_Data;
  1777. for (i=0;i<n;++i)
  1778. {
  1779. v = (2105*Pal[i].c.r + 4128*Pal[i].c.g + 802*Pal[i].c.b)/0x2000 + 16 + p->FX.Brightness;
  1780. LookUp[i] = (uint8_t)SAT(v);
  1781. v = (-1212*Pal[i].c.r -2384*Pal[i].c.g + 3596*Pal[i].c.b)/0x2000 + 128;
  1782. LookUp[i+256+4] = (uint8_t)SAT(v);
  1783. v = (3596*Pal[i].c.r -3015*Pal[i].c.g -582*Pal[i].c.b)/0x2000 + 128;
  1784. LookUp[i+256+4+256] = (uint8_t)SAT(v);
  1785. }
  1786. }
  1787. }
  1788. void CalcPalRGBLookUp(blit_soft* p)
  1789. {
  1790. int i,n = 1<<p->Src.BitCount;
  1791. int w = p->Dst.BitCount>>3;
  1792. if (w<2 || w>4) return;
  1793. if (w==3) w=4;
  1794. p->LookUp_Size = w*n;
  1795. p->LookUp_Data = malloc(p->LookUp_Size);
  1796. if (p->LookUp_Data)
  1797. {
  1798. uint16_t* Pal = p->LookUp_Data;
  1799. for (i=0;i<n;++i)
  1800. {
  1801. uint32_t c = RGBToFormat(p->Src.Palette[i].v,&p->Dst);
  1802. if (w==2)
  1803. *(Pal++) = (uint16_t)c;
  1804. else
  1805. {
  1806. *(uint32_t*)Pal = c;
  1807. Pal += 2;
  1808. }
  1809. }
  1810. }
  1811. }
  1812. void CalcYUVLookUp(blit_soft* p)
  1813. {
  1814. if (p->FX.Saturation || p->FX.Contrast || (p->FX.Flags & BLITFX_DITHER) ||
  1815. p->FX.RGBAdjust[0] || p->FX.RGBAdjust[1] || p->FX.RGBAdjust[2])
  1816. {
  1817. p->LookUp_Size = 3*256+4;
  1818. p->LookUp_Data = malloc(p->LookUp_Size);
  1819. if (p->LookUp_Data)
  1820. {
  1821. int Ofs = (p->FX.Flags & BLITFX_DITHER)?-2:0;
  1822. int n;
  1823. uint8_t* i=p->LookUp_Data;
  1824. for (n=0;n<256+4;++n,++i)
  1825. {
  1826. int y = CMul(p,NULL,n+Ofs+p->FX.Brightness+p->FX.RGBAdjust[1]-128,0)+128;
  1827. *i = (uint8_t)SAT(y);
  1828. }
  1829. for (n=0;n<256;++n,++i)
  1830. {
  1831. int u = CMul(p,NULL,n-128-p->FX.RGBAdjust[1]+p->FX.RGBAdjust[2],1)+128;
  1832. *i = (uint8_t)SAT(u);
  1833. }
  1834. for (n=0;n<256;++n,++i)
  1835. {
  1836. int v = CMul(p,NULL,n-128-p->FX.RGBAdjust[1]+p->FX.RGBAdjust[0],1)+128;
  1837. *i = (uint8_t)SAT(v);
  1838. }
  1839. }
  1840. }
  1841. }
  1842. void CalcLookUp(blit_soft* p, bool_t Dither)
  1843. {
  1844. #if defined(ARM)
  1845. const int Safe = 512;
  1846. // 4*256:Y + (256+Safe*2)*n:SAT + 4*256:U + 4*256:V 
  1847. int SatOfsR = 4*256+Safe;
  1848. int SatOfsG = 4*256+Safe;
  1849. int SatOfsB = 4*256+Safe;
  1850. p->LookUp_Size = 4*256*3 + (256+Safe*2);
  1851. if (Dither)
  1852. {
  1853. if (p->DstSize[1] == p->DstSize[0])
  1854. SatOfsG = SatOfsR;
  1855. else
  1856. {
  1857. p->LookUp_Size += (256+Safe*2);
  1858. SatOfsG = SatOfsR + (256+Safe*2);
  1859. }
  1860. if (p->DstSize[2] == p->DstSize[0])
  1861. SatOfsB = SatOfsR;
  1862. else
  1863. if (p->DstSize[2] == p->DstSize[1])
  1864. SatOfsB = SatOfsG;
  1865. else
  1866. {
  1867. p->LookUp_Size += (256+Safe*2);
  1868. SatOfsB = SatOfsG + (256+Safe*2);
  1869. }
  1870. }
  1871. p->LookUp_U = (p->LookUp_Size - 4*256*2) >> 2;
  1872. p->LookUp_V = (p->LookUp_Size - 4*256) >> 2;
  1873. p->LookUp_Data = malloc(p->LookUp_Size);
  1874. if (p->LookUp_Data)
  1875. {
  1876. int v;
  1877. int32_t* YMul = (int32_t*)p->LookUp_Data;
  1878. int32_t* UMul = (int32_t*)p->LookUp_Data + p->LookUp_U;
  1879. int32_t* VMul = (int32_t*)p->LookUp_Data + p->LookUp_V;
  1880. uint8_t* SatR = (uint8_t*)p->LookUp_Data + SatOfsR;
  1881. uint8_t* SatG = (uint8_t*)p->LookUp_Data + SatOfsG;
  1882. uint8_t* SatB = (uint8_t*)p->LookUp_Data + SatOfsB;
  1883. memset(p->LookUp_Data,0,p->LookUp_Size);
  1884. for (v=0;v<256;++v)
  1885. {
  1886. *YMul = (p->_YMul * v) << LOOKUP_FIX;
  1887. *UMul = (((p->_BUMul * v + p->_BAdd + (SatOfsB << 16)) << LOOKUP_FIX) & 0xFFFF0000) |
  1888. (((p->_GUMul * v) >> (16-LOOKUP_FIX)) & 0xFFFF); //BUMul | GUMul
  1889. *VMul = (((p->_RVMul * v + p->_RAdd + (SatOfsR << 16)) << LOOKUP_FIX) & 0xFFFF0000) |
  1890. (((p->_GVMul * v + p->_GAdd + (SatOfsG << 16)) >> (16-LOOKUP_FIX)) & 0xFFFF); //BUMul | GUMul
  1891. ++YMul;
  1892. ++UMul;
  1893. ++VMul;
  1894. }
  1895. if (Dither)
  1896. {
  1897. for (v=-Safe;v<256+Safe;++v)
  1898. {
  1899. SatR[v] = RotateRight8(SAT(v),8-p->DstSize[0]);
  1900. SatG[v] = RotateRight8(SAT(v),8-p->DstSize[1]);
  1901. SatB[v] = RotateRight8(SAT(v),8-p->DstSize[2]);
  1902. }
  1903. }
  1904. else
  1905. {
  1906. for (v=-Safe;v<256+Safe;++v)
  1907. SatR[v] = (uint8_t)SAT(v);
  1908. }
  1909. }
  1910. #elif defined(MIPS)
  1911. const int Safe = 256;
  1912. // 256:Y + (128+Safe*2)*n:SAT + 8*256:U + 8*256:V 
  1913. int SatOfsR = 256+Safe;
  1914. int SatOfsG = 256+Safe;
  1915. int SatOfsB = 256+Safe;
  1916. p->LookUp_Size = 256+8*256*2 + (128+Safe*2);
  1917. if (p->DstSize[1] == p->DstSize[0])
  1918. SatOfsG = SatOfsR;
  1919. else
  1920. {
  1921. p->LookUp_Size += (128+Safe*2);
  1922. SatOfsG = SatOfsR + (128+Safe*2);
  1923. }
  1924. if (p->DstSize[2] == p->DstSize[0])
  1925. SatOfsB = SatOfsR;
  1926. else
  1927. if (p->DstSize[2] == p->DstSize[1])
  1928. SatOfsB = SatOfsG;
  1929. else
  1930. {
  1931. p->LookUp_Size += (128+Safe*2);
  1932. SatOfsB = SatOfsG + (128+Safe*2);
  1933. }
  1934. p->LookUp_U = p->LookUp_Size - 8*256*2;
  1935. p->LookUp_V = p->LookUp_Size - 8*256;
  1936. p->LookUp_Data = malloc(p->LookUp_Size);
  1937. if (p->LookUp_Data)
  1938. {
  1939. int v;
  1940. uint8_t* YMul = (uint8_t*)p->LookUp_Data;
  1941. uint8_t** UMul = (uint8_t**)((uint8_t*)p->LookUp_Data + p->LookUp_U);
  1942. uint8_t** VMul = (uint8_t**)((uint8_t*)p->LookUp_Data + p->LookUp_V);
  1943. uint8_t* SatR = (uint8_t*)p->LookUp_Data + SatOfsR;
  1944. uint8_t* SatG = (uint8_t*)p->LookUp_Data + SatOfsG;
  1945. uint8_t* SatB = (uint8_t*)p->LookUp_Data + SatOfsB;
  1946. memset(p->LookUp_Data,0,p->LookUp_Size);
  1947. for (v=0;v<256;++v)
  1948. {
  1949. *YMul = (uint8_t)((p->_YMul * v) >> 17);
  1950. UMul[0] = SatB + ((p->_BUMul * v + p->_BAdd) >> 17);
  1951. *(int*)&UMul[1] = (p->_GUMul * v) >> 17;
  1952. VMul[0] = SatR + ((p->_RVMul * v + p->_RAdd) >> 17);
  1953. VMul[1] = SatG + ((p->_GVMul * v + p->_GAdd) >> 17);
  1954. ++YMul;
  1955. UMul+=2;
  1956. VMul+=2;
  1957. }
  1958. for (v=-Safe;v<128+Safe;++v)
  1959. {
  1960. SatR[v] = (uint8_t)(SAT(v*2) >> (8-p->DstSize[0]));
  1961. SatG[v] = (uint8_t)(SAT(v*2) >> (8-p->DstSize[1]));
  1962. SatB[v] = (uint8_t)(SAT(v*2) >> (8-p->DstSize[2]));
  1963. }
  1964. }
  1965. #elif defined(SH3)
  1966. const int Safe = 256;
  1967. //LookUp_Data:
  1968. // [128..255|0..127]Y + 384 empty + 4*[128..255|0..127]U + 4*[128..255|0..127]V + (128+Safe*2)*n:SAT 
  1969. int SatOfsR = 256+384+4*256*2+Safe;
  1970. int SatOfsG = 256+384+4*256*2+Safe;
  1971. int SatOfsB = 256+384+4*256*2+Safe;
  1972. p->LookUp_Size = 256+384+4*256*2 + (128+Safe*2);
  1973. if (p->DstSize[1] == p->DstSize[0])
  1974. SatOfsG = SatOfsR;
  1975. else
  1976. {
  1977. p->LookUp_Size += (128+Safe*2);
  1978. SatOfsG = SatOfsR + (128+Safe*2);
  1979. }
  1980. if (p->DstSize[2] == p->DstSize[0])
  1981. SatOfsB = SatOfsR;
  1982. else
  1983. if (p->DstSize[2] == p->DstSize[1])
  1984. SatOfsB = SatOfsG;
  1985. else
  1986. {
  1987. p->LookUp_Size += (128+Safe*2);
  1988. SatOfsB = SatOfsG + (128+Safe*2);
  1989. }
  1990. p->LookUp_U = 128 + 384 + 4*128;
  1991. p->LookUp_V = 128 + 384 + 4*256 + 4*128;
  1992. p->LookUp_Data = malloc(p->LookUp_Size + Safe*2); //additional safe
  1993. if (p->LookUp_Data)
  1994. {
  1995. int v;
  1996. int8_t* YMul = (int8_t*)p->LookUp_Data;
  1997. int16_t* UMul = (int16_t*)((uint8_t*)p->LookUp_Data + 256 + 384);
  1998. int16_t* VMul = (int16_t*)((uint8_t*)p->LookUp_Data + 256 + 384 + 4*256);
  1999. int8_t* SatR = (int8_t*)p->LookUp_Data + SatOfsR;
  2000. int8_t* SatG = (int8_t*)p->LookUp_Data + SatOfsG;
  2001. int8_t* SatB = (int8_t*)p->LookUp_Data + SatOfsB;
  2002. memset(p->LookUp_Data,0,p->LookUp_Size + Safe*2);
  2003. for (v=0;v<256;++v)
  2004. {
  2005. *YMul = (int8_t)(((p->_YMul * ((v+128)&255)) >> 17)-128);
  2006. UMul[0] = (int16_t)(SatOfsB + ((p->_BUMul * ((v+128)&255) + p->_BAdd) >> 17));
  2007. UMul[1] = (int16_t)((p->_GUMul * ((v+128)&255)) >> 17);
  2008. VMul[0] = (int16_t)(SatOfsR + ((p->_RVMul * ((v+128)&255) + p->_RAdd) >> 17));
  2009. VMul[1] = (int16_t)(SatOfsG + ((p->_GVMul * ((v+128)&255) + p->_GAdd) >> 17));
  2010. ++YMul;
  2011. UMul+=2;
  2012. VMul+=2;
  2013. }
  2014. for (v=-Safe;v<128+Safe;++v)
  2015. {
  2016. SatR[v] = (int8_t)(SAT(v*2) >> (8-p->DstSize[0]));
  2017. SatG[v] = (int8_t)(SAT(v*2) >> (8-p->DstSize[1]));
  2018. SatB[v] = (int8_t)(SAT(v*2) >> (8-p->DstSize[2]));
  2019. }
  2020. }
  2021. #endif
  2022. }
  2023. void CalcColor(blit_soft* p)
  2024. {
  2025. #ifdef ARM
  2026. if (p->QAdd)
  2027. {
  2028. //saturation: signed 32bit / 3 (qdadd will triple)
  2029. int64_t YMul;
  2030. int64_t RVMul;
  2031. int64_t RAdd;
  2032. int64_t GUMul;
  2033. int64_t GVMul;
  2034. int64_t GAdd;
  2035. int64_t BUMul;
  2036. int64_t BAdd;
  2037. CMul(p,&YMul,0x63C000,0);
  2038. CMul(p,&RVMul,0x88B2AA,1);
  2039. CAdd(p,&RAdd,(p->FX.Brightness+p->FX.RGBAdjust[0])*0x63C000 - (int64_t)0x75400000,0x2AAAAAAA,0x88B2AA);
  2040. CMul(p,&GUMul,-0x218555,1);
  2041. CMul(p,&GVMul,-0x45A555,1);
  2042. CAdd(p,&GAdd,(p->FX.Brightness+p->FX.RGBAdjust[1])*0x63C000 + (int64_t)0x02AEAAAA,0x2AAAAAAA,-0x218555-0x45A555);
  2043. CMul(p,&BUMul,0xACD2AA,1);
  2044. CAdd(p,&BAdd,(p->FX.Brightness+p->FX.RGBAdjust[2])*0x63C000 - (int64_t)0x87500000,0x2AAAAAAA,0xACD2AA);
  2045. if (InRange32(YMul*0xF0) && 
  2046. InRange32(RVMul*0x10+RAdd) &&
  2047. InRange32(RVMul*0xF0+RAdd) &&
  2048. InRange32((GVMul+GUMul)*0x10+GAdd) &&
  2049. InRange32((GVMul+GUMul)*0xF0+GAdd) &&
  2050. InRange32(BUMul*0x10+BAdd) &&
  2051. InRange32(BUMul*0xF0+BAdd))
  2052. {
  2053. p->_YMul = (int)YMul;
  2054. p->_RVMul = (int)RVMul;
  2055. p->_RAdd = (int)RAdd;
  2056. p->_GUMul = (int)GUMul;
  2057. p->_GVMul = (int)GVMul;
  2058. p->_GAdd = (int)GAdd;
  2059. p->_BUMul = (int)BUMul;
  2060. p->_BAdd = (int)BAdd;
  2061. }
  2062. else
  2063. p->QAdd = 0;
  2064. }
  2065. if (!p->QAdd)
  2066. #endif
  2067. {
  2068. //saturation: unsigned 24bit
  2069. p->_YMul = CMul(p,NULL,0x12B40,0);
  2070. p->_RVMul = CMul(p,NULL,0x19A18,1);
  2071. p->_RAdd = CAdd(p,NULL,(p->FX.Brightness+p->FX.RGBAdjust[0])*0x12B40 - 0x0DFC000,0x800000,0x19A18);
  2072. p->_GUMul = CMul(p,NULL,-0x06490,1);
  2073. p->_GVMul = CMul(p,NULL,-0x0D0F0,1);
  2074. p->_GAdd = CAdd(p,NULL,(p->FX.Brightness+p->FX.RGBAdjust[1])*0x12B40 + 0x0880C00,0x800000,-0x06490-0x0D0F0);
  2075. p->_BUMul = CMul(p,NULL,0x20678,1);
  2076. p->_BAdd = CAdd(p,NULL,(p->FX.Brightness+p->FX.RGBAdjust[2])*0x12B40 - 0x115F000,0x800000,0x20678);
  2077. }
  2078. }
  2079. #if defined(_M_IX86) && !defined(TARGET_SYMBIAN)
  2080. static void ColMMX(blit_soft* p, int i, int ofs)
  2081. {
  2082. int mul = 2048;
  2083. int m;
  2084. int o = 128;
  2085. if (i>0)
  2086. {
  2087. m = p->FX.Saturation;
  2088. if (m<0) m >>= 1; // adjust negtive interval: -128..0 -> -64..0
  2089. m = 4*m+256;
  2090. mul = (mul*m+128) >> 8;
  2091. ofs += 128 - (m>>1);
  2092. o = (o*m+128)>>8;
  2093. }
  2094. m = p->FX.Contrast;
  2095. if (m<0) m >>= 1; // adjust negtive interval: -128..0 -> -64..0
  2096. m = 4*m + 256;
  2097. mul = (mul*m+128)>>8;
  2098. ofs += o - ((m*o)>>8);
  2099. if ((p->Src.Flags & PF_YUV_PC) && !(p->Dst.Flags & PF_YUV_PC))
  2100. {
  2101. if (i==0) //y [0..255]->[16..235]
  2102. {
  2103. mul = (mul*219+127)/255;
  2104. ofs = (ofs*219+127)/255+16;
  2105. }
  2106. else //uv [0..255]->[16..240]
  2107. mul = (mul*224+127)/255;
  2108. ofs = (ofs*224+127)/255+16;
  2109. }
  2110. }
  2111. else
  2112. if (!(p->Src.Flags & PF_YUV_PC) && (p->Dst.Flags & PF_YUV_PC))
  2113. {
  2114. if (i==0) //y [16..235]->[0..255]
  2115. {
  2116. mul = (mul*255+109)/219;
  2117. ofs = ((ofs-16)*255+109)/219;
  2118. }
  2119. else //uv [16..240]->[0..255]
  2120. mul = (mul*255+112)/224;
  2121. ofs = ((ofs-16)*255+112)/224;
  2122. }
  2123. }
  2124. if (mul<-32768) mul=32768;
  2125. if (mul>32767) mul=32767;
  2126. p->Col[i][0][3] = p->Col[i][0][2] = p->Col[i][0][1] = p->Col[i][0][0] = (int16_t)mul;
  2127. p->Col[i][1][3] = p->Col[i][1][2] = p->Col[i][1][1] = p->Col[i][1][0] = (int16_t)ofs;
  2128. }
  2129. static int16_t MulMMX(blit_soft* p, int i, int mul)
  2130. {
  2131. int m;
  2132. if (i>0)
  2133. {
  2134. m = p->FX.Saturation;
  2135. if (m<0) m >>= 1; // adjust negtive interval: -128..0 -> -64..0
  2136. m = 4*m+256;
  2137. mul = (mul*m+128) >> 8;
  2138. }
  2139. m = p->FX.Contrast;
  2140. if (m<0) m >>= 1; // adjust negtive interval: -128..0 -> -64..0
  2141. m = 4*m + 256;
  2142. mul = (mul*m+128)>>8;
  2143. if (mul<-32768) mul=32768;
  2144. if (mul>32767) mul=32767;
  2145. return (int16_t)mul;
  2146. }
  2147. void CalcYUVMMX(blit_soft* p)
  2148. {
  2149. if (AnyYUV(&p->Dst))
  2150. {
  2151. ColMMX(p,0,p->FX.Brightness+p->FX.RGBAdjust[1]);
  2152. ColMMX(p,1,p->FX.RGBAdjust[2]-p->FX.RGBAdjust[1]);
  2153. ColMMX(p,2,p->FX.RGBAdjust[0]-p->FX.RGBAdjust[1]);
  2154. }
  2155. else
  2156. {
  2157. const int16_t* m = GetYUVToRGB(&p->Src);
  2158. p->Col[0][0][3] = p->Col[0][0][2] = p->Col[0][0][1] = p->Col[0][0][0] = MulMMX(p,0,m[0]);
  2159. p->Col[0][1][3] = p->Col[0][1][2] = p->Col[0][1][1] = p->Col[0][1][0] = (int16_t)(m[1]+p->FX.Brightness+p->FX.RGBAdjust[1]);
  2160. p->Col[1][0][1] = p->Col[1][0][0] = MulMMX(p,1,m[2]); //u_b
  2161. p->Col[1][0][3] = p->Col[1][0][2] = MulMMX(p,1,m[3]); //u_g
  2162. p->Col[1][1][3] = p->Col[1][1][2] = p->Col[1][1][1] = p->Col[1][1][0] = (int16_t)(m[4]+p->FX.RGBAdjust[2]-p->FX.RGBAdjust[1]);
  2163. p->Col[2][0][1] = p->Col[2][0][0] = MulMMX(p,2,m[5]); //v_r
  2164. p->Col[2][0][3] = p->Col[2][0][2] = MulMMX(p,2,m[6]); //v_g
  2165. p->Col[2][1][3] = p->Col[2][1][2] = p->Col[2][1][1] = p->Col[2][1][0] = (int16_t)(m[7]+p->FX.RGBAdjust[0]-p->FX.RGBAdjust[1]);
  2166. }
  2167. }
  2168. #endif