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

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: ati4200.c 545 2006-01-07 22:26:35Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23. #include "../common/common.h"
  24. #if defined(TARGET_PALMOS)
  25. #if defined(_M_IX86)
  26. //#define ATIEMU
  27. #endif
  28. #if _MSC_VER > 1000
  29. #pragma warning(disable : 4127)
  30. #endif
  31. #include "../common/palmos/pace.h"
  32. #define ATI4200_ID FOURCC('A','T','I','4')
  33. #define ATI4200_IDCT_ID VOUT_IDCT_CLASS(ATI4200_ID)
  34. #define DCFACTOR 8
  35. #define RING_NOP2 0
  36. #define RING_NOP3 ((1|0x80000)<<11)
  37. #define BUFFER_COUNT 3
  38. #define ALL_COUNT 5
  39. #define SCALE_COUNT 3
  40. #define REG_BASE 0x010000
  41. #define INT_BASE 0x100000
  42. #define EXT_BASE 0x800000
  43. #define PWRMGT_CNTL (0x0098/4)
  44. #define GRAPHIC_CTRL        (0x0414/4)
  45. #define GRAPHIC_OFFSET      (0x0418/4)
  46. #define GRAPHIC_PITCH       (0x041C/4)
  47. #define GRAPHIC_H_DISP      (0x042C/4)
  48. #define GRAPHIC_V_DISP      (0x0430/4)
  49. #define GEN_STATUS (0x054C/4)
  50. #define ACTIVE_H_DISP (0x0424/4)
  51. #define ACTIVE_V_DISP (0x0428/4)
  52. #define DISP_BUF (0x04D8/4)
  53. #define DISP_DEBUG (0x04D4/4)
  54. #define DISP_DEBUG2 (0x0538/4)
  55. #define VIDEO_CTRL (0x0434/4)
  56. #define VIDEO_Y_OFFSET (0x043C/4)
  57. #define VIDEO_Y_PITCH (0x0440/4)
  58. #define VIDEO_U_OFFSET (0x0444/4)
  59. #define VIDEO_U_PITCH (0x0448/4)
  60. #define VIDEO_V_OFFSET (0x044C/4)
  61. #define VIDEO_V_PITCH (0x0450/4)
  62. #define VIDEO_H_POS (0x0454/4)
  63. #define VIDEO_V_POS (0x0458/4)
  64. #define RING_CNTL (0x0210/4)
  65. #define RING_BASE (0x0214/4)
  66. #define RING_RPTR_ADDR (0x0218/4)
  67. #define RING_RPTR (0x021C/4)
  68. #define RING_RPTR_WR (0x02F8/4)
  69. #define RING_WPTR (0x0220/4)
  70. #define RBBM_STATUS (0x0140/4)
  71. #define RBBM_CNTL (0x0144/4)
  72. #define REF1_PITCH_OFFSET (0x10B8/4)
  73. #define REF2_PITCH_OFFSET (0x10BC/4)
  74. #define REF3_PITCH_OFFSET (0x10C0/4)
  75. #define REF4_PITCH_OFFSET (0x10C4/4)
  76. #define REF5_PITCH_OFFSET (0x10C8/4)
  77. #define REF6_PITCH_OFFSET (0x10CC/4)
  78. #define SRC_SC_BOTTOM_RIGHT (0x11C4/4)
  79. #define IDCT_CONTROL        (0x0C3C/4)
  80. #define DP_GUI_MASTER_CNTL 0x41B 
  81. #define DP_CNTL 0x472 
  82. #define DP_MIX 0x4B2 
  83. #define DP_DATATYPE 0x4B1 
  84. #define SC_TOP_LEFT 0x46F 
  85. #define SC_BOTTOM_RIGHT 0x470 
  86. #define DST_OFFSET 0x401 
  87. #define DST_PITCH 0x402 
  88. #define SRC_OFFSET 0x46B 
  89. #define SRC_PITCH 0x46C 
  90. #define E2_ARITHMETIC_CNTL 0x488 
  91. #define SRC2_X_Y 0x416
  92. #define SRC2_OFFSET 0x418 
  93. #define SRC2_PITCH 0x419 
  94. #define SRC_WIDTH 0x410 
  95. #define SRC_HEIGHT 0x411 
  96. #define SRC_INC 0x412 
  97. #define SRC2_WIDTH 0x420 
  98. #define SRC2_HEIGHT 0x421 
  99. #define SRC2_INC 0x422 
  100. #define SRC_X_Y 0x464 
  101. #define DST_X_Y 0x465 
  102. #define DST_WIDTH_HEIGHT 0x466 
  103. typedef struct atisurf
  104. {
  105. planes Planes;
  106. int YOffset;
  107. int YPitch;
  108. int UOffset;
  109. int UPitch;
  110. int VOffset;
  111. int VPitch;
  112. } atisurf;
  113. typedef struct idct_atidata
  114. {
  115. int8_t skip3,skip2,skip1,skip0;
  116. int16_t data1,data0,data3,data2;
  117. } idct_atidata;
  118. typedef struct idct_ati
  119. {
  120. union
  121. {
  122. idct_atidata d;
  123. int32_t v[3];
  124. };
  125. } idct_ati;
  126. #define BACKUP_LEN 16
  127. static const int BackupRegs[BACKUP_LEN] = 
  128. {
  129. DP_GUI_MASTER_CNTL,
  130. DP_CNTL,
  131. DP_MIX,
  132. DP_DATATYPE,
  133. DST_OFFSET,
  134. DST_PITCH,
  135. SRC_OFFSET,
  136. SRC_PITCH,
  137. E2_ARITHMETIC_CNTL,
  138. IDCT_CONTROL,
  139. REF1_PITCH_OFFSET,
  140. REF2_PITCH_OFFSET,
  141. REF3_PITCH_OFFSET,
  142. REF4_PITCH_OFFSET,
  143. REF5_PITCH_OFFSET,
  144. REF6_PITCH_OFFSET,
  145. };
  146. typedef struct ati4200
  147. {
  148. overlay p;
  149. idct IdctVMT;
  150. int RingMask;
  151. int RingPos;
  152. int RingPos0;
  153. int RingRdPos;
  154. volatile int* Ring;
  155. int DCAdd;
  156. int SubNo;
  157. int MacroPos;
  158. int MacroCoord;
  159. int LastMode;
  160. int LastScanType;
  161. int ArithMode;
  162. int InterIDCT;
  163. int MVBack;
  164. int32_t MVBackTab[6];
  165. int MVFwd;
  166. int32_t MVFwdTab[6];
  167. atisurf* Dst;
  168. int AllCount;
  169. int BufCount;
  170. int ShowLast;
  171. int ShowCurr;
  172. int ShowNext;
  173. int IDCTWidth;
  174. int IDCTHeight;
  175. pin IDCTOutput;
  176. bool_t Rounding;
  177. bool_t IDCT;
  178. bool_t IDCTInit;
  179. int SaveScanType;
  180. int SavePos;
  181. int SaveData[64]; //data:16*3+close:1
  182. int BufferEnd;
  183. atisurf Buffer[ALL_COUNT];
  184. atisurf Scale[SCALE_COUNT];
  185. rect OverlayRect;
  186. video Overlay;
  187. blitfx SoftFX;
  188. point Offset;
  189. bool_t LowBitdepth;
  190. int Memory;
  191. uint8_t* Device;
  192. volatile int* Regs;
  193. int ShowScale;
  194. int Mirror;
  195. int BufFrameNo[MAXIDCTBUF];
  196. int Backup[BACKUP_LEN];
  197. } ati4200;
  198. extern char* QueryScreen(video* Video,int* Offset,int* Mode);
  199. static bool_t Idle(ati4200* p)
  200. {
  201. if (p->Regs[RING_RPTR] != p->Regs[RING_WPTR])
  202. return 0;
  203. if (p->Regs[RBBM_STATUS] & 0x80000000)
  204. return 0;
  205. return 1;
  206. }
  207. static NOINLINE bool_t Wait(ati4200* p)
  208. {
  209. int n;
  210. for (n=0;n<100000;++n)
  211. {
  212. if (Idle(p))
  213. return 1;
  214. HALDelay(50);
  215. }
  216. return 0;
  217. }
  218. static INLINE void RingPush(ati4200* p, int Value)
  219. {
  220. p->Ring[p->RingPos] = Value;
  221. p->RingPos = (p->RingPos+1) & p->RingMask;
  222. }
  223. static NOINLINE void RingReg(ati4200* p, int Reg, int Value)
  224. {
  225. RingPush(p,Reg);
  226. RingPush(p,Value);
  227. }
  228. static INLINE void RingNOP2(ati4200* p)
  229. {
  230. p->Ring[p->RingPos] = RING_NOP2;
  231. p->RingPos = (p->RingPos+2) & p->RingMask;
  232. }
  233. static INLINE void RingNOP3(ati4200* p)
  234. {
  235. p->Ring[p->RingPos] = RING_NOP3;
  236. p->RingPos = (p->RingPos+3) & p->RingMask;
  237. }
  238. static NOINLINE void RingPrepair(ati4200* p, int Len)
  239. {
  240. if (((p->RingRdPos - p->RingPos - 1) & p->RingMask) < Len)
  241. {
  242. p->RingRdPos = p->Regs[RING_RPTR];
  243. while (((p->RingRdPos - p->RingPos - 1) & p->RingMask) < Len)
  244. {
  245. HALDelay(50);
  246. p->RingRdPos = p->Regs[RING_RPTR];
  247. }
  248. }
  249. }
  250. static INLINE void RingFlush(ati4200* p)
  251. {
  252. p->Regs[RING_WPTR] = p->RingPos;
  253. #ifdef ATIEMU
  254. if (p->Regs[RING_RPTR] != p->RingPos)
  255. {
  256. if (p->Ring[p->Regs[RING_RPTR]] == RING_NOP3 ||
  257. p->Ring[p->Regs[RING_RPTR]] == RING_NOP2)
  258. p->Regs[RING_RPTR] = p->RingPos;
  259. else
  260. {
  261. //DebugMessage("ATI Command");
  262. while (p->Regs[RING_RPTR] != p->RingPos)
  263. {
  264. //DebugMessage("ATI %08x",p->Ring[p->Regs[RING_RPTR]]);
  265. p->Regs[RING_RPTR] = (p->Regs[RING_RPTR] + 1) & p->RingMask;
  266. }
  267. }
  268. }
  269. #endif
  270. }
  271. static NOINLINE void RingFill(ati4200* p,int TargetPos)
  272. {
  273. int n = (TargetPos - p->RingPos) & p->RingMask;
  274. if (n)
  275. {
  276. if (n==1)
  277. n += p->RingMask+1; // bad luck
  278. while (n>1024*3+4)
  279. {
  280. int i;
  281. RingPrepair(p,1024*3);
  282. for (i=0;i<1024;++i)
  283. RingNOP3(p);
  284. RingFlush(p);
  285. n -= 1024*3;
  286. }
  287. RingPrepair(p,n);
  288. for (;n>4;n-=3) 
  289. RingNOP3(p);
  290. switch (n)
  291. {
  292. case 4: RingNOP2(p); //no break
  293. case 2: RingNOP2(p); break;
  294. case 3: RingNOP3(p); break;
  295. }
  296. RingFlush(p);
  297. }
  298. assert(p->RingPos == TargetPos);
  299. }
  300. static void RingBegin(ati4200* p,bool_t Small)
  301. {
  302. int v;
  303. p->RingRdPos = p->Regs[RING_RPTR];
  304. p->RingPos = p->Regs[RING_WPTR] & p->RingMask;
  305. v = p->RingPos == p->RingPos0 ? p->Ring[p->RingPos] : -1;
  306. p->RingPos0 = p->RingPos;
  307. if (v != RING_NOP3 && v != RING_NOP2)
  308. {
  309. // have to wait before doing the register backup
  310. int n;
  311. Wait(p); 
  312. for (n=0;n<BACKUP_LEN;++n) 
  313. p->Backup[n] = p->Regs[BackupRegs[n]];
  314. }
  315. if (Small)
  316. {
  317. int SmallPos = (p->RingPos - 256) & p->RingMask;
  318. if (v != RING_NOP3)
  319. RingFill(p,SmallPos);
  320. else
  321. {
  322. // assuming ring is already filled
  323. p->RingPos = SmallPos; 
  324. RingFlush(p);
  325. }
  326. }
  327. }
  328. static void RingEnd(ati4200* p)
  329. {
  330. int n;
  331. // restore backup registers
  332. RingPrepair(p,2*BACKUP_LEN+2*2);
  333. RingReg(p,SC_TOP_LEFT,0);
  334. RingReg(p,SC_BOTTOM_RIGHT,0x1FFF1FFF);
  335. RingReg(p,SRC_SC_BOTTOM_RIGHT,0x1FFF1FFF);
  336. for (n=0;n<BACKUP_LEN;++n) 
  337. RingReg(p,BackupRegs[n],p->Backup[n]);
  338. RingFlush(p);
  339. // restore ring write position
  340. RingFill(p,p->RingPos0); 
  341. // let some free space for the OS driver
  342. RingPrepair(p,p->RingMask >> 1); 
  343. // signal for next iteration that no backup required
  344. if (p->Ring[p->RingPos0] != RING_NOP3)
  345. p->Ring[p->RingPos0] = RING_NOP2; 
  346. }
  347. static void AllocBuffer(ati4200* p,atisurf* s,int w,int h,int* Offset)
  348. {
  349. int ofs = *Offset;
  350. int size;
  351. w = ALIGN16(w);
  352. h = ALIGN16(h);
  353. size = w*h;
  354. s->YOffset = ofs;
  355. ofs += size;
  356. s->YPitch = w;
  357. s->UOffset = ofs;
  358. ofs += size/4;
  359. s->UPitch = w/2;
  360. s->VOffset = ofs;
  361. ofs += size/4;
  362. s->VPitch = w/2;
  363. s->Planes[0] = p->Device + s->YOffset;
  364. s->Planes[1] = p->Device + s->UOffset;
  365. s->Planes[2] = p->Device + s->VOffset;
  366. memset(s->Planes[0],0,size);
  367. memset(s->Planes[1],128,size/4);
  368. memset(s->Planes[2],128,size/4);
  369. *Offset = ofs;
  370. }
  371. static void BeginUpdate(ati4200* p)
  372. {
  373. p->Regs[DISP_BUF] = 0x78;
  374. }
  375. static void EndUpdate(ati4200* p)
  376. {
  377. p->Regs[DISP_BUF] = 0x7B;
  378. }
  379. static void SetLowBitdepth(ati4200* p,bool_t Value)
  380. {
  381. /* if (p->LowBitdepth != Value)
  382. {
  383. int Ctrl;
  384. p->LowBitdepth = Value;
  385. //if (Value)
  386. // ClearPrimary(p);
  387. while ((p->Regs[GEN_STATUS] & 0x400)==0); // wait until not in vblank 
  388. while ((p->Regs[GEN_STATUS] & 0x400)!=0); // wait until in vblank
  389. Ctrl = p->Regs[GRAPHIC_CTRL];
  390. Ctrl &= ~7;
  391. Ctrl |= Value ? 2:6;
  392. p->Regs[GRAPHIC_CTRL] = Ctrl;
  393. }
  394. */
  395. }
  396. static void UpdateLowBitdepth(ati4200* p)
  397. {
  398. SetLowBitdepth(p,p->p.Show && p->p.FullScreenViewport);
  399. }
  400. static int Hide(ati4200* p)
  401. {
  402. SetLowBitdepth(p,0);
  403. BeginUpdate(p);
  404. p->Regs[VIDEO_CTRL] &= ~0x1C;
  405. EndUpdate(p);
  406. #ifndef ATIEMU
  407. while (p->Regs[DISP_BUF] & 2);
  408. #endif
  409. p->Regs[PWRMGT_CNTL] |= 1;
  410. return ERR_NONE;
  411. }
  412. static int Show(ati4200* p)
  413. {
  414. UpdateLowBitdepth(p);
  415. BeginUpdate(p);
  416. p->Regs[VIDEO_CTRL] |= 0x14;
  417. p->Regs[PWRMGT_CNTL] &= ~1;
  418. EndUpdate(p);
  419. return ERR_NONE;
  420. }
  421. static uint8_t* GetBits()
  422. {
  423. BitmapType* Bitmap;
  424. WinHandle Win = WinGetDisplayWindow();
  425. if (!Win)
  426. return NULL;
  427. Bitmap = WinGetBitmap(Win);
  428. if (!Bitmap)
  429. return NULL;
  430. return BmpGetBits(Bitmap);
  431. }
  432. static int IDCTUpdateFunc(ati4200* p);
  433. static void GetMode(ati4200* p)
  434. {
  435. QueryDesktop(&p->p.Output.Format.Video);
  436. p->p.Output.Format.Video.Direction = GetOrientation() ^ (DIR_MIRRORUPDOWN | DIR_MIRRORLEFTRIGHT);
  437. if (p->p.Output.Format.Video.Direction & DIR_SWAPXY)
  438. {
  439. int Ofs = GetBits() - (p->Device+INT_BASE);
  440. int h;
  441. h = p->Regs[ACTIVE_V_DISP];
  442. h = ((h >> 16) & 0x3FF) - (h & 0x3FF);
  443. SwapInt(&p->p.Output.Format.Video.Width,&p->p.Output.Format.Video.Height);
  444. if (Ofs>=0 && Ofs<h*2)
  445. h -= Ofs>>1;
  446. p->Offset.y = h - p->p.Output.Format.Video.Height;
  447. }
  448. else
  449. p->Offset.y = 0;
  450. }
  451. static int Init(ati4200* p)
  452. {
  453. p->p.SetFX = BLITFX_AVOIDTEARING;
  454. p->p.Overlay = 1;
  455. p->IDCT = 0;
  456. p->ShowScale = -1;
  457. p->ShowCurr = 0;
  458. p->ShowNext = -1;
  459. p->ShowLast = -1;
  460. p->AllCount = 0;
  461. p->BufCount = 0;
  462. p->BufferEnd = 0;
  463. p->LowBitdepth = 0;
  464. if (p->IDCTInit)
  465. {
  466. if (!PlanarYUV420(&p->p.Input.Format.Video.Pixel))
  467. return ERR_NOT_SUPPORTED;
  468. RingBegin(p,1);
  469. RingPrepair(p,2);
  470. RingReg(p,0x30E,0);
  471. RingFlush(p);
  472. RingEnd(p);
  473. p->IDCT = 1;
  474. p->Rounding = 0;
  475. IDCTUpdateFunc(p);
  476. }
  477. GetMode(p);
  478. return ERR_NONE;
  479. }
  480. static void Done(ati4200* p)
  481. {
  482. Wait(p);
  483. Hide(p);
  484. p->IDCT = 0;
  485. p->BufferEnd = 0;
  486. p->AllCount = 0;
  487. }
  488. static int Reset(ati4200* p)
  489. {
  490. GetMode(p);
  491. return ERR_NONE;
  492. }
  493. static int UpdateShow(ati4200* p)
  494. {
  495. if (p->p.Show)
  496. Show(p);
  497. else
  498. Hide(p);
  499. return ERR_NONE;
  500. }
  501. static int MirrorOffset(ati4200* p,atisurf* s,int Plane)
  502. {
  503. int Ofs = 0;
  504. int Width = p->p.DstAlignedRect.Width;
  505. int Height = p->p.DstAlignedRect.Height;
  506. int Pitch = s->YPitch;
  507. int x = 0;
  508. int y = 0;
  509. if (p->ShowScale<0)
  510. {
  511. x = p->OverlayRect.x & ~7;
  512. y = p->OverlayRect.y;
  513. }
  514. if (Plane)
  515. {
  516. Pitch >>= 1;
  517. Width >>= 1;
  518. Height >>= 1;
  519. x >>= 1;
  520. y >>= 1;
  521. }
  522. Ofs += x;
  523. Ofs += y * Pitch;
  524. if (p->Mirror & DIR_MIRRORLEFTRIGHT)
  525. Ofs += Width-1;
  526. if (p->Mirror & DIR_MIRRORUPDOWN)
  527. Ofs += (Height-1)*Pitch;
  528. return Ofs;
  529. }
  530. static void SwapPtr(ati4200* p,int a,int b,int SwapShow)
  531. {
  532. atisurf t;
  533. memcpy(&t,p->Buffer+a,sizeof(atisurf));
  534. memcpy(p->Buffer+a,p->Buffer+b,sizeof(atisurf));
  535. memcpy(p->Buffer+b,&t,sizeof(atisurf));
  536. if (SwapShow)
  537. {
  538. SwapInt(&p->BufFrameNo[a],&p->BufFrameNo[b]);
  539. if (p->ShowNext == a)
  540. p->ShowNext = b;
  541. else
  542. if (p->ShowNext == b)
  543. p->ShowNext = a;
  544. if (p->ShowLast == a)
  545. p->ShowLast = b;
  546. else
  547. if (p->ShowLast == b)
  548. p->ShowLast = a;
  549. if (p->ShowCurr == a)
  550. p->ShowCurr = b;
  551. else
  552. if (p->ShowCurr == b)
  553. p->ShowCurr = a;
  554. }
  555. }
  556. static void Stretch(ati4200* p,bool_t Flip);
  557. static int Update(ati4200* p)
  558. {
  559. video OldOverlay;
  560. blitfx OvlFX = p->p.FX;
  561. rect BufferRect;
  562. int Total;
  563. int Ctrl,n,x0,y0,x1,y1;
  564. int Offset = p->Memory;
  565. atisurf* s; 
  566. Wait(p);
  567. Hide(p);
  568. memcpy(&OldOverlay,&p->Overlay,sizeof(OldOverlay));
  569. OvlFX.Direction = 0;
  570. p->Mirror = 0;
  571. p->SoftFX = p->p.FX;
  572. p->SoftFX.ScaleX = SCALE_ONE; // scale handled by hardware
  573. p->SoftFX.ScaleY = SCALE_ONE;
  574. p->SoftFX.Flags |= BLITFX_ENLARGEIFNEEDED;
  575. if (p->IDCT)
  576. {
  577. // use overlay mirroring, because hardware idct can only swapxy
  578. p->SoftFX.Direction &= DIR_SWAPXY;
  579. p->Mirror = p->p.FX.Direction & ~DIR_SWAPXY;
  580. p->AllCount = ALL_COUNT;
  581. }
  582. else
  583. p->AllCount = BUFFER_COUNT;
  584. //align to 100%
  585. if (OvlFX.ScaleX > SCALE_ONE-(SCALE_ONE/16) && OvlFX.ScaleX < SCALE_ONE+(SCALE_ONE/16) &&
  586. OvlFX.ScaleY > SCALE_ONE-(SCALE_ONE/16) && OvlFX.ScaleY < SCALE_ONE+(SCALE_ONE/16))
  587. {
  588. OvlFX.ScaleX = SCALE_ONE;
  589. OvlFX.ScaleY = SCALE_ONE;
  590. }
  591. if (p->SoftFX.Direction & DIR_SWAPXY)
  592. SwapInt(&OvlFX.ScaleX,&OvlFX.ScaleY);
  593. memset(&p->Overlay,0,sizeof(p->Overlay));
  594. p->Overlay.Pixel.Flags = PF_YUV420;
  595. p->Overlay.Width = ALIGN16(p->IDCT?p->IDCTWidth:p->p.Input.Format.Video.Width);
  596. p->Overlay.Height = ALIGN16(p->IDCT?p->IDCTHeight:p->p.Input.Format.Video.Height);
  597. p->Overlay.Direction = (p->p.FX.Direction ^ p->p.Input.Format.Video.Direction) & DIR_SWAPXY;
  598. if ((p->IDCT?p->Overlay.Direction:p->p.FX.Direction) & DIR_SWAPXY)
  599. SwapInt(&p->Overlay.Width,&p->Overlay.Height);
  600. p->Overlay.Pitch = p->Overlay.Width;
  601. VirtToPhy(NULL,&p->OverlayRect,&p->p.Input.Format.Video);
  602. if (p->p.FX.Direction & DIR_SWAPXY)
  603. SwapInt(&p->OverlayRect.Width,&p->OverlayRect.Height);
  604. if (p->IDCT)
  605. IDCTUpdateFunc(p);
  606. VirtToPhy(&p->p.Viewport,&p->p.DstAlignedRect,&p->p.Output.Format.Video);
  607. if (OvlFX.ScaleX != SCALE_ONE || OvlFX.ScaleY != SCALE_ONE)
  608. {
  609. // avoid bilinear scale overrun (shrink source)
  610. if (p->OverlayRect.Width>2) 
  611. {
  612. OvlFX.ScaleX = Scale(OvlFX.ScaleX,p->OverlayRect.Width,p->OverlayRect.Width-2);
  613. p->OverlayRect.Width -= 2;
  614. }
  615. if (p->OverlayRect.Height>2) 
  616. {
  617. OvlFX.ScaleY = Scale(OvlFX.ScaleY,p->OverlayRect.Height,p->OverlayRect.Height-2);
  618. p->OverlayRect.Height -= 2;
  619. }
  620. }
  621. AnyAlign(&p->p.DstAlignedRect, &p->OverlayRect, &OvlFX, 2, 1, SCALE_ONE>>1, SCALE_ONE*16);
  622. VirtToPhy(NULL,&p->p.SrcAlignedRect,&p->p.Input.Format.Video);
  623. BufferRect.x = p->OverlayRect.x & ~15;
  624. BufferRect.y = p->OverlayRect.y & ~15;
  625. BufferRect.Width = ALIGN16(p->OverlayRect.Width + (p->OverlayRect.x & 15));
  626. BufferRect.Height = ALIGN16(p->OverlayRect.Height + (p->OverlayRect.y & 15));
  627. BlitRelease(p->p.Soft);
  628. p->p.Soft = BlitCreate(&p->Overlay,&p->p.Input.Format.Video,&p->SoftFX,&p->p.Caps);
  629. BlitAlign(p->p.Soft,&BufferRect,&p->p.SrcAlignedRect);
  630. if (!p->IDCT)
  631. {
  632. // adjust Overlay size if not all part of the input is needed
  633. p->BufferEnd = 0;
  634. p->Overlay.Width = ALIGN16(BufferRect.Width);
  635. p->Overlay.Height = ALIGN16(BufferRect.Height);
  636. p->Overlay.Pitch = p->Overlay.Width;
  637. // adjust OverlayRect
  638. BufferRect.x = p->p.SrcAlignedRect.x;
  639. BufferRect.y = p->p.SrcAlignedRect.y;
  640. if (p->SoftFX.Direction & DIR_SWAPXY)
  641. SwapInt(&BufferRect.x,&BufferRect.y);
  642. p->OverlayRect.x -= BufferRect.x;
  643. p->OverlayRect.y -= BufferRect.y;
  644. ClipRectPhy(&p->OverlayRect,&p->Overlay);
  645. BufferRect.x = 0;
  646. BufferRect.y = 0;
  647. BlitRelease(p->p.Soft);
  648. p->p.Soft = BlitCreate(&p->Overlay,&p->p.Input.Format.Video,&p->SoftFX,&p->p.Caps);
  649. BlitAlign(p->p.Soft,&BufferRect,&p->p.SrcAlignedRect);
  650. }
  651. else
  652. {
  653. int DCAdd;
  654. p->p.Caps = VC_BRIGHTNESS;
  655. // swapxy changed?
  656. if (p->BufferEnd && ((OldOverlay.Direction ^ p->Overlay.Direction) & DIR_SWAPXY))
  657. {
  658. for (n=0;n<p->AllCount;++n)
  659. {
  660. p->Buffer[n].YPitch = p->Overlay.Pitch;
  661. p->Buffer[n].UPitch = p->Overlay.Pitch >> 1;
  662. p->Buffer[n].VPitch = p->Overlay.Pitch >> 1;
  663. }
  664. if (p->AllCount > p->BufCount)
  665. for (n=0;n<p->BufCount;++n)
  666. {
  667. SurfaceRotate(&OldOverlay,&p->Overlay,p->Buffer[n].Planes,
  668.               p->Buffer[p->BufCount].Planes,DIR_SWAPXY);
  669. SwapPtr(p,n,p->BufCount,0);
  670. }
  671. }
  672. // brightness changed?
  673. DCAdd = p->p.FX.Brightness * DCFACTOR;
  674. if (p->DCAdd != DCAdd)
  675. {
  676. int Delta = (DCAdd - p->DCAdd) / DCFACTOR;
  677. p->DCAdd = DCAdd;
  678. if (p->BufferEnd)
  679. for (n=0;n<p->BufCount;++n)
  680. {
  681. uint8_t* v = p->Buffer[n].Planes[0];
  682. uint8_t* ve = v + p->Overlay.Width * p->Overlay.Height;
  683. for (;v!=ve;v+=4)
  684. {
  685. int a = v[0] + Delta;
  686. int b = v[1] + Delta;
  687. int c = v[2] + Delta;
  688. int d = v[3] + Delta;
  689. if (a>255) a=255; else if (a<0) a=0;
  690. if (b>255) b=255; else if (b<0) b=0;
  691. if (c>255) c=255; else if (c<0) c=0;
  692. if (d>255) d=255; else if (d<0) d=0;
  693. *(uint32_t*)v = a | (b<<8) | (c<<16) | (d<<24);
  694. }
  695. }
  696. }
  697. }
  698. if (!p->BufferEnd)
  699. {
  700. for (n=0;n<p->AllCount;++n)
  701. {
  702. AllocBuffer(p,&p->Buffer[n],p->Overlay.Width,p->Overlay.Height,&Offset);
  703. p->BufFrameNo[n] = -1;
  704. }
  705. p->BufferEnd = Offset;
  706. }
  707. else
  708. Offset = p->BufferEnd;
  709. if (OvlFX.ScaleX != SCALE_ONE || OvlFX.ScaleY != SCALE_ONE)
  710. {
  711. for (n=0;n<SCALE_COUNT;++n)
  712. AllocBuffer(p,&p->Scale[n],p->p.DstAlignedRect.Width,p->p.DstAlignedRect.Height,&Offset);
  713. p->ShowScale = 0;
  714. Stretch(p,0);
  715. s = p->Scale + p->ShowScale;
  716. }
  717. else
  718. {
  719. // no scaling -> adjust dst rectangle with soft yuv blitting alignement
  720. memset(p->Scale,0,sizeof(p->Scale));
  721. p->ShowScale = -1;
  722. p->p.DstAlignedRect.x += (p->p.DstAlignedRect.Width - p->OverlayRect.Width) >> 1;
  723. p->p.DstAlignedRect.y += (p->p.DstAlignedRect.Height - p->OverlayRect.Height) >> 1;
  724. p->p.DstAlignedRect.Width = p->OverlayRect.Width;
  725. p->p.DstAlignedRect.Height = p->OverlayRect.Height;
  726. s = p->Buffer + p->ShowCurr;
  727. }
  728. PhyToVirt(&p->p.DstAlignedRect,&p->p.GUIAlignedRect,&p->p.Output.Format.Video);
  729. BeginUpdate(p);
  730. p->Regs[DISP_DEBUG] &= ~0x1F0;
  731. Total = (p->p.DstAlignedRect.Width + 3) >> 2;
  732. Ctrl = 
  733. (1 << 0)| // yuv420 video mode
  734. ((Total & 511) << 9) |
  735. (1 << 22)| // yuv
  736. (1 << 23); // yuv option
  737. if (p->Mirror & DIR_MIRRORLEFTRIGHT)
  738. Ctrl |= 1 << 24;
  739. if (p->Mirror & DIR_MIRRORUPDOWN)
  740. Ctrl |= 1 << 25;
  741. p->Regs[VIDEO_CTRL] = Ctrl;
  742. x0 = p->Regs[ACTIVE_H_DISP] & 0x3FF;
  743. y0 = p->Regs[ACTIVE_V_DISP] & 0x3FF;
  744. x0 += p->Offset.x;
  745. y0 += p->Offset.y;
  746. x0 += p->p.DstAlignedRect.x;
  747. y0 += p->p.DstAlignedRect.y;
  748. x1 = x0 + p->p.DstAlignedRect.Width;
  749. y1 = y0 + p->p.DstAlignedRect.Height;
  750. p->Regs[VIDEO_H_POS] = x0 | (x1 << 16);
  751. p->Regs[VIDEO_V_POS] = y0 | (y1 << 16);
  752. p->Regs[VIDEO_Y_OFFSET] = s->YOffset+MirrorOffset(p,s,0);
  753. p->Regs[VIDEO_Y_PITCH] = s->YPitch;
  754. p->Regs[VIDEO_U_OFFSET] = s->UOffset+MirrorOffset(p,s,1);
  755. p->Regs[VIDEO_U_PITCH] = s->UPitch;
  756. p->Regs[VIDEO_V_OFFSET] = s->VOffset+MirrorOffset(p,s,2);
  757. p->Regs[VIDEO_V_PITCH] = s->VPitch;
  758. p->Regs[DISP_DEBUG2] |= 0x40000000;
  759. EndUpdate(p);
  760. return UpdateShow(p);
  761. }
  762. static void StretchPlane(ati4200* p, int SrcOffset, int SrcPitch, rect* SrcRect, int DstOffset, int DstPitch, rect* DstRect)
  763. {
  764. int DWidth,DHeight;
  765. int RScaleX = min(0x1FF,max(0x10,(SrcRect->Width << 8) / DstRect->Width));
  766. int RScaleY = min(0x1FF,max(0x10,(SrcRect->Height << 8) / DstRect->Height));
  767. DWidth = ((SrcRect->Width << 8)+RScaleX-1) / RScaleX;
  768. DHeight = ((SrcRect->Height << 8)+RScaleY-1) / RScaleY;
  769. RingReg(p,DP_GUI_MASTER_CNTL, 0xD598B2DF);
  770. RingReg(p,DP_CNTL , 0x0000003F);
  771. RingReg(p,DP_MIX , 0x01CC1200);
  772. RingReg(p,DP_DATATYPE , 0x40037D02);
  773. RingReg(p,E2_ARITHMETIC_CNTL, 0x02020008);
  774. RingReg(p,SC_TOP_LEFT,(DstRect->x & 0xFFFF) | (DstRect->y << 16));
  775. RingReg(p,SC_BOTTOM_RIGHT,((DstRect->x + DstRect->Width) & 0xFFFF) | ((DstRect->y + DstRect->Height) << 16));
  776. RingReg(p,DST_OFFSET,DstOffset);
  777. RingReg(p,DST_PITCH,DstPitch);
  778. RingReg(p,SRC_OFFSET,SrcOffset);
  779. RingReg(p,SRC_PITCH,SrcPitch);
  780. RingReg(p,SRC2_OFFSET,SrcOffset);
  781. RingReg(p,SRC2_PITCH,SrcPitch);
  782. RingReg(p,SRC_WIDTH,DWidth+1);
  783. RingReg(p,SRC_HEIGHT,DHeight);
  784. RingReg(p,SRC_INC,(RScaleX & 0xFFFF) | (RScaleY << 16));
  785. RingReg(p,SRC2_WIDTH,DWidth+1);
  786. RingReg(p,SRC2_HEIGHT,DHeight);
  787. RingReg(p,SRC2_INC,(RScaleX & 0xFFFF) | (RScaleY << 16));
  788. RingReg(p,SRC_X_Y,((SrcRect->y*4) & 0xFFFF) + ((SrcRect->x*4) << 16));
  789. RingReg(p,SRC2_X_Y,((SrcRect->y*4 + 4) & 0xFFFF) + ((SrcRect->x*4) << 16));
  790. RingReg(p,DST_X_Y,(DstRect->y & 0xFFFF) | (DstRect->x << 16));
  791. RingReg(p,DST_WIDTH_HEIGHT,(DHeight & 0xFFFF) | (DWidth << 16));
  792. }
  793. static void Stretch(ati4200* p,bool_t Flip)
  794. {
  795. rect SrcRect2;
  796. rect DstRect2;
  797. rect* SrcRect = &p->OverlayRect;
  798. rect DstRect;
  799. atisurf* Dst;
  800. atisurf* Src = p->Buffer+p->ShowCurr;
  801. if (++p->ShowScale >= SCALE_COUNT)
  802. p->ShowScale = 0;
  803. Dst = p->Scale + p->ShowScale;
  804. DstRect.x = 0;
  805. DstRect.y = 0;
  806. DstRect.Width = p->p.DstAlignedRect.Width;
  807. DstRect.Height = p->p.DstAlignedRect.Height;
  808. SrcRect2.x = SrcRect->x >> 1;
  809. SrcRect2.y = SrcRect->y >> 1;
  810. SrcRect2.Width = SrcRect->Width >> 1;
  811. SrcRect2.Height = SrcRect->Height >> 1;
  812. DstRect2.x = DstRect.x >> 1;
  813. DstRect2.y = DstRect.y >> 1;
  814. DstRect2.Width = DstRect.Width >> 1;
  815. DstRect2.Height = DstRect.Height >> 1;
  816. if (DstRect2.Width && DstRect2.Height)
  817. {
  818. bool_t PossibleBug = SrcRect2.Width*7 > DstRect2.Width*10;
  819. RingBegin(p,1);
  820. RingPrepair(p,128*2); // just an approx.
  821. StretchPlane(p,Src->UOffset,Src->UPitch,&SrcRect2,Dst->UOffset,Dst->UPitch,&DstRect2);
  822. if (PossibleBug)
  823. {
  824. RingFlush(p);
  825. Wait(p);
  826. }
  827. StretchPlane(p,Src->VOffset,Src->VPitch,&SrcRect2,Dst->VOffset,Dst->VPitch,&DstRect2);
  828. if (PossibleBug)
  829. {
  830. RingFlush(p);
  831. Wait(p);
  832. }
  833. StretchPlane(p,Src->YOffset,Src->YPitch,SrcRect,Dst->YOffset,Dst->YPitch,&DstRect);
  834. if ((p->Mirror & DIR_MIRRORUPDOWN) || !Flip)
  835. {
  836. RingFlush(p);
  837. Wait(p);
  838. }
  839. if (Flip)
  840. {
  841. RingReg(p,DISP_BUF,0x78);
  842. RingReg(p,VIDEO_Y_OFFSET,Dst->YOffset+MirrorOffset(p,Dst,0));
  843. RingReg(p,VIDEO_Y_PITCH,Dst->YPitch);
  844. RingReg(p,VIDEO_U_OFFSET,Dst->UOffset+MirrorOffset(p,Dst,1));
  845. RingReg(p,VIDEO_U_PITCH,Dst->UPitch);
  846. RingReg(p,VIDEO_V_OFFSET,Dst->VOffset+MirrorOffset(p,Dst,2));
  847. RingReg(p,VIDEO_V_PITCH,Dst->VPitch);
  848. RingReg(p,DISP_BUF,0x7B);
  849. RingFlush(p);
  850. }
  851. RingEnd(p);
  852. }
  853. }
  854. static void SetOverlay(ati4200* p)
  855. {
  856. atisurf* s = p->Buffer + p->ShowCurr;
  857. BeginUpdate(p);
  858. p->Regs[VIDEO_Y_OFFSET] = s->YOffset+MirrorOffset(p,s,0);
  859. p->Regs[VIDEO_Y_PITCH] = s->YPitch;
  860. p->Regs[VIDEO_U_OFFSET] = s->UOffset+MirrorOffset(p,s,1);
  861. p->Regs[VIDEO_U_PITCH] = s->UPitch;
  862. p->Regs[VIDEO_V_OFFSET] = s->VOffset+MirrorOffset(p,s,2);
  863. p->Regs[VIDEO_V_PITCH] = s->VPitch;
  864. EndUpdate(p);
  865. }
  866. static int Blit(ati4200* p, const constplanes Data, const constplanes DataLast )
  867. {
  868. if (++p->ShowCurr>=BUFFER_COUNT) 
  869. p->ShowCurr=0; 
  870. BlitImage(p->p.Soft,p->Buffer[p->ShowCurr].Planes,Data,DataLast,-1,-1);
  871. if (p->ShowScale<0)
  872. SetOverlay(p);
  873. else
  874. Stretch(p,1);
  875. return ERR_NONE;
  876. }
  877. //---------------------------------------------------------------------------------------------
  878. static const uint8_t ScanTable[3][64] = {
  879. {
  880.  0,  1,  8, 16,  9,  2,  3, 10, 
  881. 17, 24, 32, 25, 18, 11,  4,  5,
  882. 12, 19, 26, 33, 40, 48, 41, 34, 
  883. 27, 20, 13,  6,  7, 14, 21, 28, 
  884. 35, 42, 49, 56, 57, 50, 43, 36, 
  885. 29, 22, 15, 23, 30, 37, 44, 51, 
  886. 58, 59, 52, 45, 38, 31, 39, 46, 
  887. 53, 60, 61, 54, 47, 55, 62, 63
  888. },
  889. {
  890.    0,  1,  2,  3,  8,  9, 16, 17, 
  891. 10, 11,  4,  5,  6,  7, 15, 14,
  892. 13, 12, 19, 18, 24, 25, 32, 33, 
  893. 26, 27, 20, 21, 22, 23, 28, 29,
  894. 30, 31, 34, 35, 40, 41, 48, 49, 
  895. 42, 43, 36, 37, 38, 39, 44, 45,
  896. 46, 47, 50, 51, 56, 57, 58, 59, 
  897. 52, 53, 54, 55, 60, 61, 62, 63
  898. },
  899. {
  900.  0,  8, 16, 24,  1,  9,  2, 10, 
  901. 17, 25, 32, 40, 48, 56, 57, 49,
  902. 41, 33, 26, 18,  3, 11,  4, 12, 
  903. 19, 27, 34, 42, 50, 58, 35, 43,
  904. 51, 59, 20, 28,  5, 13,  6, 14, 
  905. 21, 29, 36, 44, 52, 60, 37, 45,
  906. 53, 61, 22, 30,  7, 15, 23, 31, 
  907. 38, 46, 54, 62, 39, 47, 55, 63
  908. }};
  909. static const uint8_t ZigZagSwap[64] = {
  910.  0,  8,  1,  2,  9, 16, 24, 17, 
  911. 10,  3,  4, 11, 18, 25, 32, 40,
  912. 33, 26, 19, 12,  5,  6, 13, 20, 
  913. 27, 34, 41, 48, 56, 49, 42, 35, 
  914. 28, 21, 14,  7, 15, 22, 29, 36, 
  915. 43, 50, 57, 58, 51, 44, 37, 30, 
  916. 23, 31, 38, 45, 52, 59, 60, 53, 
  917. 46, 39, 47, 54, 61, 62, 55, 63
  918. };
  919. static const uint8_t ZigZagSwapLength[64] = {
  920. 1,   3,  3,  6,  6,  6, 10, 10,
  921. 10, 10, 15, 15, 15, 15, 15, 21, 
  922. 21, 21, 21, 21, 21, 28, 28, 28,
  923. 28, 28, 28, 28, 36, 36, 36, 36, 
  924. 36, 36, 36, 36, 43, 43, 43, 43, 
  925. 43, 43, 43, 49, 49, 49, 49, 49,
  926. 49, 54, 54, 54, 54, 54, 58, 58, 
  927. 58, 58, 61, 61, 61, 63, 63, 64
  928. };
  929. #define AHI(p) ((ati4200*)((char*)(p)-(int)&(((ati4200*)0)->IdctVMT)))
  930. // input: Block, Length
  931. #define AHIDCBLOCK(Offset)
  932. {
  933. if (Length < 1)
  934. {
  935. Block[0] = (idct_block_t)(Offset);
  936. Length = 1;
  937. }
  938. else
  939. Block[0] = (idct_block_t)(Block[0] + (Offset));
  940. }
  941. // ADJUST: don't care about MVFwd (only in b-frames which are not accumulated)
  942. #define AHIMVADJBLOCK(SubNo)
  943. if (AHI(p)->MVBack && (AHI(p)->MVBackTab[SubNo-1] & 0x00020002)==0x00020002)
  944. AHIDCBLOCK(2);
  945. #define AHIPUSH(v)
  946. {
  947. Dst[DstPos] = v;
  948. DstPos = (DstPos+1) & DstMask;
  949. }
  950. // Block, Length, Scan, ScanEnd
  951. #define AHIPACK(ScanType,Inter,SkipLabel,Backup)
  952. ScanEnd = Scan + Length;
  953. Last = Scan;
  954. while (Scan != ScanEnd && !Block[*Scan]) ++Scan;
  955. if (Scan == ScanEnd)
  956. {
  957. if (!Backup && (!Inter || AHI(p)->InterIDCT))
  958. AHIPUSH(0);
  959. }
  960. else
  961. {
  962. int v;
  963. if (!Backup)
  964. {
  965. if (Inter && !AHI(p)->InterIDCT)
  966. {
  967. AHI(p)->InterIDCT = 1;
  968. for (v=SubNo;v>1;--v)
  969. AHIPUSH(0);
  970. }
  971. if (AHI(p)->LastScanType != ScanType)
  972. {
  973. AHI(p)->LastScanType = ScanType;
  974. AHIPUSH(7);
  975. v = ScanType?(ScanType==2 ? 0x10: 0x800):0;
  976. AHIPUSH(v);
  977. }
  978. else
  979. AHIPUSH(2);
  980. }
  981. LenPtr = Dst+DstPos;
  982. DstPos = (DstPos+1) & DstMask;
  983. for (Length=0;;)
  984. {
  985. Data.v[0] = -1;
  986. v = *Scan;
  987. Data.d.skip0 = (char)(Scan++ - Last);
  988. Data.d.data0 = Block[v];
  989. Last = Scan;
  990. while (Scan != ScanEnd && !Block[*Scan]) ++Scan;
  991. if (Scan == ScanEnd) break;
  992. v = *Scan;
  993. Data.d.skip1 = (char)(Scan++ - Last);
  994. Data.d.data1 = Block[v];
  995. Last = Scan;
  996. while (Scan != ScanEnd && !Block[*Scan]) ++Scan;
  997. if (Scan == ScanEnd) break;
  998. v = *Scan;
  999. Data.d.skip2 = (char)(Scan++ - Last);
  1000. Data.d.data2 = Block[v];
  1001. Last = Scan;
  1002. while (Scan != ScanEnd && !Block[*Scan]) ++Scan;
  1003. if (Scan == ScanEnd) break;
  1004. v = *Scan;
  1005. Data.d.skip3 = (char)(Scan++ - Last);
  1006. Data.d.data3 = Block[v];
  1007. AHIPUSH(Data.v[0]);
  1008. AHIPUSH(Data.v[1]);
  1009. AHIPUSH(Data.v[2]);
  1010. ++Length;
  1011. Last = Scan;
  1012. while (Scan != ScanEnd && !Block[*Scan]) ++Scan;
  1013. if (Scan == ScanEnd)
  1014. {
  1015. AHIPUSH(0);
  1016. goto SkipLabel;
  1017. }
  1018. }
  1019. AHIPUSH(Data.v[0]);
  1020. AHIPUSH(Data.v[1]);
  1021. AHIPUSH(Data.v[2]);
  1022. ++Length;
  1023. SkipLabel:
  1024. *LenPtr = Length;
  1025. }
  1026. #define AHIPACKNORMAL(ScanType,Inter)
  1027. {
  1028. const unsigned char *Scan = ScanTable[ScanType];
  1029. const unsigned char *ScanEnd;
  1030. const unsigned char *Last;
  1031. int* Dst = (int*)AHI(p)->Ring;
  1032. int DstPos = AHI(p)->RingPos;
  1033. int DstMask = AHI(p)->RingMask;
  1034. int* LenPtr;
  1035. idct_ati Data;
  1036. AHIPACK(ScanType,Inter,SkipLabel,0)
  1037. AHI(p)->RingPos = DstPos;
  1038. }
  1039. #define AHIPACKSWAP(ScanType,Inter,SkipLabel,_Dst,_DstPos,_DstMask,Backup) 
  1040. {
  1041. const unsigned char *Scan;
  1042. const unsigned char *ScanEnd;
  1043. const unsigned char *Last;
  1044. int* LenPtr;
  1045. int* Dst = (int*)_Dst;
  1046. int DstPos = _DstPos;
  1047. int DstMask = _DstMask;
  1048. idct_ati Data;
  1049. if (ScanType == IDCTSCAN_ZIGZAG)
  1050. {
  1051. Scan = ZigZagSwap;
  1052. Length = ZigZagSwapLength[Length-1];
  1053. }
  1054. else
  1055. {
  1056. Scan = ScanTable[ScanType];
  1057. ScanType = 3 - ScanType;
  1058. }
  1059. AHIPACK(ScanType,Inter,SkipLabel,Backup)
  1060. _DstPos = DstPos;
  1061. }
  1062. #define AHIPACKSWAPZIGZAG(Inter,SkipLabel,_Dst,_DstPos,_DstMask,Backup)
  1063. {
  1064. const unsigned char *Scan;
  1065. const unsigned char *ScanEnd;
  1066. const unsigned char *Last;
  1067. int* LenPtr;
  1068. int* Dst = (int*)_Dst;
  1069. int DstPos = _DstPos;
  1070. int DstMask = _DstMask;
  1071. idct_ati Data;
  1072. Scan = ZigZagSwap;
  1073. Length = ZigZagSwapLength[Length-1];
  1074. AHIPACK(IDCTSCAN_ZIGZAG,Inter,SkipLabel,Backup)
  1075. _DstPos = DstPos;
  1076. }
  1077. #define AHIQPEL(MVPtr)
  1078. MV = *(MVPtr++);
  1079. MV <<= 1;
  1080. MV &= ~0x00010000;
  1081. #define AHIQPELSWAP(MVPtr)
  1082. MV = *(MVPtr++);
  1083. MV = (MV << 17) |
  1084.  ((uint32_t)MV >> 15);
  1085. MV &= ~0x00010001;
  1086. static void IDCTMComp(void* p,const int* MVBack,const int* MVFwd)
  1087. {
  1088. int32_t* Tab;
  1089. int MV;
  1090. AHI(p)->MVBack = 0;
  1091. AHI(p)->MVFwd = 0;
  1092. if (MVBack)
  1093. {
  1094. AHI(p)->MVBack = 1;
  1095. Tab = AHI(p)->MVBackTab;
  1096. AHIQPELSWAP(MVBack); Tab[0] = MV;
  1097. AHIQPELSWAP(MVBack); Tab[1] = MV;
  1098. AHIQPELSWAP(MVBack); Tab[2] = MV;
  1099. AHIQPELSWAP(MVBack); Tab[3] = MV;
  1100. AHIQPELSWAP(MVBack); Tab[4] = MV;
  1101. AHIQPELSWAP(MVBack); Tab[5] = MV;
  1102. }
  1103. if (MVFwd)
  1104. {
  1105. AHI(p)->MVFwd = 1;
  1106. Tab = AHI(p)->MVFwdTab;
  1107. AHIQPELSWAP(MVFwd); Tab[0] = MV;
  1108. AHIQPELSWAP(MVFwd); Tab[1] = MV;
  1109. AHIQPELSWAP(MVFwd); Tab[2] = MV;
  1110. AHIQPELSWAP(MVFwd); Tab[3] = MV;
  1111. AHIQPELSWAP(MVFwd); Tab[4] = MV;
  1112. AHIQPELSWAP(MVFwd); Tab[5] = MV;
  1113. }
  1114. }
  1115. static void IDCTMCompSwap(void* p,const int* MVBack,const int* MVFwd)
  1116. {
  1117. int32_t* Tab;
  1118. int MV;
  1119. AHI(p)->MVBack = 0;
  1120. AHI(p)->MVFwd = 0;
  1121. if (MVBack)
  1122. {
  1123. AHI(p)->MVBack = 1;
  1124. Tab = AHI(p)->MVBackTab;
  1125. AHIQPEL(MVBack); Tab[0] = MV;
  1126. AHIQPEL(MVBack); Tab[2] = MV;
  1127. AHIQPEL(MVBack); Tab[1] = MV;
  1128. AHIQPEL(MVBack); Tab[3] = MV;
  1129. AHIQPEL(MVBack); Tab[4] = MV;
  1130. AHIQPEL(MVBack); Tab[5] = MV;
  1131. }
  1132. if (MVFwd)
  1133. {
  1134. AHI(p)->MVFwd = 1;
  1135. Tab = AHI(p)->MVFwdTab;
  1136. AHIQPEL(MVFwd); Tab[0] = MV;
  1137. AHIQPEL(MVFwd); Tab[2] = MV;
  1138. AHIQPEL(MVFwd); Tab[1] = MV;
  1139. AHIQPEL(MVFwd); Tab[3] = MV;
  1140. AHIQPEL(MVFwd); Tab[4] = MV;
  1141. AHIQPEL(MVFwd); Tab[5] = MV;
  1142. }
  1143. }
  1144. static void IDCTProcess(void* p,int x,int y)
  1145. {
  1146. AHI(p)->SubNo = 0;
  1147. AHI(p)->MacroCoord = (y << 4) | (x << 20);
  1148. }
  1149. static void IDCTProcessSwap(void* p,int x,int y)
  1150. {
  1151. AHI(p)->SubNo = 0;
  1152. AHI(p)->MacroCoord = (x << 4) | (y << 20);
  1153. }
  1154. static NOINLINE void IDCTIntraStart(ati4200* p)
  1155. {
  1156. RingPrepair(p,512);
  1157. if (p->LastMode != 0x0F)
  1158. {
  1159. p->LastMode = 0x0F;
  1160. RingPush(p,0x4A1);
  1161. }
  1162. else
  1163. RingPush(p,0xC0001000);
  1164. RingPush(p,0);
  1165. p->MacroPos = p->RingPos;
  1166. p->RingPos = (p->RingPos+1) & p->RingMask;
  1167. }
  1168. static NOINLINE void IDCTIntraEnd(ati4200* p)
  1169. {
  1170. atisurf* Dst = p->Dst;
  1171. int Pos;
  1172. RingPush(p,5);
  1173. RingPush(p,0xF|p->ArithMode); 
  1174. RingPush(p,0x2D000003 | Dst->YOffset);
  1175. Pos = p->MacroCoord;
  1176. RingPush(p,Pos);
  1177. RingPush(p,Pos*4);
  1178. Pos += 8 << 16;
  1179. RingPush(p,Pos);
  1180. RingPush(p,Pos*4);
  1181. Pos += 8 - (8 << 16);
  1182. RingPush(p,Pos);
  1183. RingPush(p,Pos*4);
  1184. Pos += 8 << 16;
  1185. RingPush(p,Pos);
  1186. RingPush(p,Pos*4);
  1187. Pos -= 8 + (8 << 16);
  1188. Pos >>= 1;
  1189. RingPush(p,Pos);
  1190. RingPush(p,Pos*4);
  1191. RingPush(p,0x2C000003 | Dst->UOffset);
  1192. RingPush(p,Pos);
  1193. RingPush(p,Pos*4);
  1194. RingPush(p,0x2C000003 | Dst->VOffset);
  1195. p->Ring[p->MacroPos] = 0xC0003200 | (((p->RingPos - (p->MacroPos+2)) & p->RingMask) << 16);
  1196. RingFlush(p);
  1197. }
  1198. static INLINE void IDCTInterStart(ati4200* p)
  1199. {
  1200. RingPrepair(p,512);
  1201. p->MacroPos = p->RingPos;
  1202. p->RingPos = (p->RingPos+3) & p->RingMask;
  1203. p->InterIDCT = 0;
  1204. }
  1205. static INLINE void PushMV(ati4200* p,int Pos,int n)
  1206. {
  1207. if (p->MVBack)
  1208. RingPush(p,(p->MVBackTab[n] + Pos) & ~0x00010000);
  1209. if (p->MVFwd)
  1210. RingPush(p,(p->MVFwdTab[n] + Pos) & ~0x00010000);
  1211. }
  1212. static NOINLINE void IDCTInterEnd(ati4200* p)
  1213. {
  1214. atisurf* Dst = p->Dst;
  1215. int Mode,Pos;
  1216. assert(p->MVBack || p->MVFwd);
  1217. if (p->MVBack && p->MVFwd)
  1218. {
  1219. Mode = 0x0E;
  1220. RingPush(p,6);
  1221. }
  1222. else
  1223. {
  1224. Mode = 0x0D;
  1225. RingPush(p,5);
  1226. }
  1227. if (!p->InterIDCT)
  1228. Mode -= 2;
  1229. RingPush(p,Mode|p->ArithMode);
  1230. RingPush(p,0x2D000000 | Dst->YOffset | (p->MVBack?0:3));
  1231. Pos = p->MacroCoord;
  1232. RingPush(p,Pos);
  1233. PushMV(p,Pos*4,0);
  1234. Pos += 8 << 16;
  1235. RingPush(p,Pos);
  1236. PushMV(p,Pos*4,1);
  1237. Pos += 8 - (8 << 16);
  1238. RingPush(p,Pos);
  1239. PushMV(p,Pos*4,2);
  1240. Pos += 8 << 16;
  1241. RingPush(p,Pos);
  1242. PushMV(p,Pos*4,3);
  1243. Pos -= 8 + (8 << 16);
  1244. Pos >>= 1;
  1245. RingPush(p,Pos);
  1246. PushMV(p,Pos*4,4);
  1247. RingPush(p,0x20000000 | (4<<26) | Dst->UOffset | (p->MVBack?1:4));
  1248. RingPush(p,Pos);
  1249. PushMV(p,Pos*4,5);
  1250. RingPush(p,0x20000000 | (5<<26) | Dst->VOffset | (p->MVBack?2:5));
  1251. Pos = p->MacroPos;
  1252. if (p->LastMode != Mode)
  1253. {
  1254. p->LastMode = Mode;
  1255. p->Ring[Pos] = 0x4A1;
  1256. }
  1257. else
  1258. p->Ring[Pos] = 0xC0001000;
  1259. Pos = (Pos+1) & p->RingMask;
  1260. p->Ring[Pos] = 0;
  1261. Pos = (Pos+1) & p->RingMask;
  1262. p->Ring[Pos] = 0xC0003200 | (((p->RingPos - (Pos+2)) & p->RingMask) << 16);
  1263. RingFlush(p);
  1264. }
  1265. void IDCTIntra(void* p,idct_block_t *Block,int Length,int ScanType)
  1266. {
  1267. int SubNo = ++AHI(p)->SubNo;
  1268. if (SubNo <= 4)
  1269. AHIDCBLOCK(AHI(p)->DCAdd)
  1270. if (SubNo == 1)
  1271. IDCTIntraStart(AHI(p));
  1272. if (Length>0 && Length<=64)
  1273. AHIPACKNORMAL(ScanType,0)
  1274. else
  1275. RingPush(AHI(p),0);
  1276. if (SubNo == 6)
  1277. IDCTIntraEnd(AHI(p));
  1278. }
  1279. void IDCTInter(void* p,idct_block_t *Block,int Length)
  1280. {
  1281. int SubNo = ++AHI(p)->SubNo;
  1282. AHIMVADJBLOCK(SubNo)
  1283. if (SubNo == 1)
  1284. IDCTInterStart(AHI(p));
  1285. if (Length>0 && Length<=64)
  1286. AHIPACKNORMAL(IDCTSCAN_ZIGZAG,1)
  1287. else
  1288. if (AHI(p)->InterIDCT)
  1289. RingPush(AHI(p),0);
  1290. if (SubNo == 6)
  1291. IDCTInterEnd(AHI(p));
  1292. }
  1293. void IDCTIntraSwap(void* p,idct_block_t *Block,int Length,int ScanType)
  1294. {
  1295. int SubNo = ++AHI(p)->SubNo;
  1296. if (SubNo <= 4)
  1297. AHIDCBLOCK(AHI(p)->DCAdd)
  1298. if (SubNo == 1)
  1299. IDCTIntraStart(AHI(p));
  1300. if (SubNo == 2)
  1301. {
  1302. AHI(p)->SavePos = 0;
  1303. if (Length>0 && Length<=64)
  1304. {
  1305. AHIPACKSWAP(ScanType,0,SkipLabel1,AHI(p)->SaveData,AHI(p)->SavePos,-1,1)
  1306. AHI(p)->SaveScanType = ScanType;
  1307. }
  1308. }
  1309. else
  1310. {
  1311. if (Length>0 && Length<=64)
  1312. AHIPACKSWAP(ScanType,0,SkipLabel2,AHI(p)->Ring,AHI(p)->RingPos,AHI(p)->RingMask,0)
  1313. else
  1314. RingPush(AHI(p),0);
  1315. if (SubNo == 3)
  1316. {
  1317. int j,i = AHI(p)->RingPos;
  1318. if (AHI(p)->SavePos)
  1319. {
  1320. j = AHI(p)->SaveScanType;
  1321. if (AHI(p)->LastScanType != j)
  1322. {
  1323. AHI(p)->LastScanType = j;
  1324. AHI(p)->Ring[i] = 7;
  1325. i = (i+1) & AHI(p)->RingMask;
  1326. if (j==2) j=0x10;
  1327. else if (j==1) j=0x800;
  1328. AHI(p)->Ring[i] = j;
  1329. i = (i+1) & AHI(p)->RingMask;
  1330. }
  1331. else
  1332. {
  1333. AHI(p)->Ring[i] = 2;
  1334. i = (i+1) & AHI(p)->RingMask;
  1335. }
  1336. for (j=0;j<AHI(p)->SavePos;++j)
  1337. {
  1338. AHI(p)->Ring[i] = AHI(p)->SaveData[j];
  1339. i = (i+1) & AHI(p)->RingMask;
  1340. }
  1341. }
  1342. else
  1343. {
  1344. AHI(p)->Ring[i] = 0;
  1345. i = (i+1) & AHI(p)->RingMask;
  1346. }
  1347. AHI(p)->RingPos = i;
  1348. }
  1349. else
  1350. if (SubNo == 6)
  1351. IDCTIntraEnd(AHI(p));
  1352. }
  1353. }
  1354. void IDCTInterSwap(void* p,idct_block_t *Block,int Length)
  1355. {
  1356. int SubNo = ++AHI(p)->SubNo;
  1357. AHIMVADJBLOCK(SubNo)
  1358. if (SubNo == 1)
  1359. IDCTInterStart(AHI(p));
  1360. if (SubNo == 2)
  1361. {
  1362. AHI(p)->SavePos = 0;
  1363. if (Length>0 && Length<=64)
  1364. AHIPACKSWAPZIGZAG(1,SkipLabel1,AHI(p)->SaveData,AHI(p)->SavePos,-1,1)
  1365. }
  1366. else
  1367. if (SubNo == 3)
  1368. {
  1369. if (Length>0 && Length<=64)
  1370. {
  1371. --SubNo;
  1372. AHIPACKSWAPZIGZAG(1,SkipLabel2,AHI(p)->Ring,AHI(p)->RingPos,AHI(p)->RingMask,0)
  1373. }
  1374. else
  1375. if (AHI(p)->InterIDCT)
  1376. RingPush(AHI(p),0);
  1377. if (AHI(p)->SavePos>0 || AHI(p)->InterIDCT)
  1378. {
  1379. int j,i = AHI(p)->RingPos;
  1380. if (!AHI(p)->InterIDCT)
  1381. {
  1382. AHI(p)->InterIDCT = 1;
  1383. AHI(p)->Ring[i] = 0; 
  1384. i = (i+1) & AHI(p)->RingMask;
  1385. AHI(p)->Ring[i] = 0; 
  1386. i = (i+1) & AHI(p)->RingMask;
  1387. }
  1388. if (AHI(p)->SavePos>0)
  1389. {
  1390. if (AHI(p)->LastScanType != IDCTSCAN_ZIGZAG)
  1391. {
  1392. AHI(p)->LastScanType = IDCTSCAN_ZIGZAG;
  1393. AHI(p)->Ring[i] = 7;
  1394. i = (i+1) & AHI(p)->RingMask;
  1395. AHI(p)->Ring[i] = 0;
  1396. i = (i+1) & AHI(p)->RingMask;
  1397. }
  1398. else
  1399. {
  1400. AHI(p)->Ring[i] = 2;
  1401. i = (i+1) & AHI(p)->RingMask;
  1402. }
  1403. for (j=0;j<AHI(p)->SavePos;++j)
  1404. {
  1405. AHI(p)->Ring[i] = AHI(p)->SaveData[j];
  1406. i = (i+1) & AHI(p)->RingMask;
  1407. }
  1408. }
  1409. else
  1410. {
  1411. AHI(p)->Ring[i] = 0;
  1412. i = (i+1) & AHI(p)->RingMask;
  1413. }
  1414. AHI(p)->RingPos = i;
  1415. }
  1416. }
  1417. else
  1418. {
  1419. if (Length>0 && Length<=64)
  1420. AHIPACKSWAPZIGZAG(1,SkipLabel3,AHI(p)->Ring,AHI(p)->RingPos,AHI(p)->RingMask,0)
  1421. else
  1422. if (AHI(p)->InterIDCT)
  1423. RingPush(AHI(p),0);
  1424. if (SubNo == 6)
  1425. IDCTInterEnd(AHI(p));
  1426. }
  1427. }
  1428. static void IDCTCopy16x16(void* p,int x,int y,int Forward)
  1429. {
  1430. int32_t* Tab;
  1431. AHI(p)->MacroCoord = (y << 4) | (x << 20);
  1432. if (Forward)
  1433. {
  1434. AHI(p)->MVBack = 0;
  1435. AHI(p)->MVFwd = 1;
  1436. Tab = AHI(p)->MVFwdTab;
  1437. }
  1438. else
  1439. {
  1440. AHI(p)->MVBack = 1;
  1441. AHI(p)->MVFwd = 0;
  1442. Tab = AHI(p)->MVBackTab;
  1443. }
  1444. Tab[0] = 0;
  1445. Tab[1] = 0;
  1446. Tab[2] = 0;
  1447. Tab[3] = 0;
  1448. Tab[4] = 0;
  1449. Tab[5] = 0;
  1450. IDCTInterStart(AHI(p));
  1451. IDCTInterEnd(AHI(p));
  1452. }
  1453. static void IDCTCopy16x16Swap(void* p,int x,int y,int Forward)
  1454. {
  1455. int32_t* Tab;
  1456. AHI(p)->MacroCoord = (x << 4) | (y << 20);
  1457. AHI(p)->InterIDCT = 0;
  1458. if (Forward)
  1459. {
  1460. AHI(p)->MVBack = 0;
  1461. AHI(p)->MVFwd = 1;
  1462. Tab = AHI(p)->MVFwdTab;
  1463. }
  1464. else
  1465. {
  1466. AHI(p)->MVBack = 1;
  1467. AHI(p)->MVFwd = 0;
  1468. Tab = AHI(p)->MVBackTab;
  1469. }
  1470. Tab[0] = 0;
  1471. Tab[1] = 0;
  1472. Tab[2] = 0;
  1473. Tab[3] = 0;
  1474. Tab[4] = 0;
  1475. Tab[5] = 0;
  1476. IDCTInterStart(AHI(p));
  1477. IDCTInterEnd(AHI(p));
  1478. }
  1479. static int IDCTUpdateFunc(ati4200* p)
  1480. {
  1481. if (p->Overlay.Direction)
  1482. {
  1483. p->IdctVMT.Copy16x16 = IDCTCopy16x16Swap;
  1484. p->IdctVMT.Process = IDCTProcessSwap;
  1485. p->IdctVMT.MComp8x8 = IDCTMCompSwap;
  1486. p->IdctVMT.MComp16x16 = IDCTMCompSwap;
  1487. p->IdctVMT.Intra8x8 = (idctintra)IDCTIntraSwap;
  1488. p->IdctVMT.Inter8x8 = (idctinter)IDCTInterSwap;
  1489. }
  1490. else 
  1491. {
  1492. p->IdctVMT.Copy16x16 = IDCTCopy16x16;
  1493. p->IdctVMT.Process = IDCTProcess;
  1494. p->IdctVMT.MComp8x8 = IDCTMComp;
  1495. p->IdctVMT.MComp16x16 = IDCTMComp;
  1496. p->IdctVMT.Intra8x8 = (idctintra)IDCTIntra;
  1497. p->IdctVMT.Inter8x8 = (idctinter)IDCTInter;
  1498. }
  1499. return ERR_NONE;
  1500. }
  1501. static int IDCTOutputFormat(ati4200* p, const void* Data, int Size)
  1502. {
  1503. packetformat Format;
  1504. int Result;
  1505. p->IDCTInit = 1;
  1506. if (Size == sizeof(video))
  1507. {
  1508. memset(&Format,0,sizeof(Format));
  1509. Format.Type = PACKET_VIDEO;
  1510. Format.Format.Video = *(const video*)Data;
  1511. Data = &Format;
  1512. Size = sizeof(packetformat);
  1513. //IDCTWidth or IDCTHeight could have changes so invalidate current input format
  1514. memset(&p->p.Input.Format.Video,0,sizeof(video));
  1515. }
  1516. Result = p->p.Node.Set((node*)p,OUT_INPUT|PIN_FORMAT,Data,Size);
  1517. if (Size && Result != ERR_NONE)
  1518. p->p.Node.Set((node*)p,OUT_INPUT|PIN_FORMAT,NULL,0);
  1519. p->IDCTInit = 0;
  1520. return Result;
  1521. }
  1522. static int IDCTSend(void* p,tick_t RefTime,const flowstate* State);
  1523. static int IDCTSet(void* p, int No, const void* Data, int Size)
  1524. {
  1525. flowstate State;
  1526. int Result = ERR_INVALID_PARAM;
  1527. switch (No)
  1528. {
  1529. case IDCT_MODE: if (*(int*)Data==0) Result = ERR_NONE; break;
  1530. case IDCT_BUFFERWIDTH: SETVALUE(AHI(p)->IDCTWidth,int,ERR_NONE); break;
  1531. case IDCT_BUFFERHEIGHT: SETVALUE(AHI(p)->IDCTHeight,int,ERR_NONE); break;
  1532. case IDCT_FORMAT:
  1533. assert(Size == sizeof(video) || !Data);
  1534. Result = IDCTOutputFormat(AHI(p),Data,Size);
  1535. break;
  1536. case IDCT_BACKUP:
  1537. if (Size == sizeof(idctbackup))
  1538. Result = IDCTRestore(p,(idctbackup*)Data);
  1539. break;
  1540. case IDCT_ROUNDING: SETVALUE(AHI(p)->Rounding,bool_t,ERR_NONE); break;
  1541. case IDCT_SHOW: 
  1542. SETVALUE(AHI(p)->ShowNext,int,ERR_NONE); 
  1543. if (AHI(p)->ShowNext >= AHI(p)->BufCount) AHI(p)->ShowNext = -1;
  1544. break;
  1545. case IDCT_BUFFERCOUNT:
  1546. assert(Size == sizeof(int));
  1547. if (*(const int*)Data > ALL_COUNT)
  1548. Result = ERR_OUT_OF_MEMORY;
  1549. else
  1550. {
  1551. AHI(p)->BufCount = *(const int*)Data;
  1552. Result = ERR_NONE;
  1553. }
  1554. break;
  1555. case FLOW_FLUSH:
  1556. AHI(p)->ShowNext = -1;
  1557. Result = ERR_NONE;
  1558. break;
  1559. case FLOW_RESEND:
  1560. State.CurrTime = TIME_RESEND;
  1561. State.DropLevel = 0;
  1562. Result = IDCTSend(p,-1,&State);
  1563. break;
  1564. }
  1565. if (No>=IDCT_FRAMENO && No<IDCT_FRAMENO+AHI(p)->AllCount)
  1566. SETVALUE(AHI(p)->BufFrameNo[No-IDCT_FRAMENO],int,ERR_NONE);
  1567. return Result;
  1568. }
  1569. static int IDCTEnumAHI(void* p, int* No, datadef* Param)
  1570. {
  1571. int Result = IDCTEnum(p,No,Param);
  1572. if (Result == ERR_NONE && Param->No == IDCT_OUTPUT)
  1573. Param->Flags |= DF_RDONLY;
  1574. return Result;
  1575. }
  1576. static int IDCTGet(void* p, int No, void* Data, int Size)
  1577. {
  1578. int Result = ERR_INVALID_PARAM;
  1579. switch (No)
  1580. {
  1581. case FLOW_BUFFERED: GETVALUE(1,bool_t); break;
  1582. case NODE_PARTOF: GETVALUE(AHI(p),ati4200*); break;
  1583. case IDCT_OUTPUT|PIN_FORMAT: GETVALUECOND(AHI(p)->p.Input,packetformat,AHI(p)->IDCT); break;
  1584. case IDCT_OUTPUT|PIN_PROCESS: GETVALUE(NULL,packetprocess); break;
  1585. case IDCT_OUTPUT: GETVALUE(AHI(p)->IDCTOutput,pin); break;
  1586. case IDCT_FORMAT: 
  1587. assert(Size==sizeof(video));
  1588. if (AHI(p)->IDCT)
  1589. {
  1590. video* i = (video*)Data;
  1591. *i = AHI(p)->p.Input.Format.Video;
  1592. if ((AHI(p)->Overlay.Direction ^ i->Direction) & DIR_SWAPXY)
  1593. {
  1594. i->Direction ^= DIR_SWAPXY;
  1595. SwapInt(&i->Width,&i->Height);
  1596. }
  1597. Result = ERR_NONE;
  1598. }
  1599. break;
  1600. case IDCT_MODE: GETVALUE(0,int); break;
  1601. case IDCT_ROUNDING: GETVALUE(AHI(p)->Rounding,bool_t); break;
  1602. case IDCT_BUFFERCOUNT: GETVALUE(AHI(p)->BufCount,int); break;
  1603. case IDCT_BUFFERWIDTH: GETVALUE(AHI(p)->IDCTWidth,int); break;
  1604. case IDCT_BUFFERHEIGHT: GETVALUE(AHI(p)->IDCTHeight,int); break;
  1605. case IDCT_SHOW: GETVALUE(AHI(p)->ShowNext,int); break;
  1606. case IDCT_BACKUP: 
  1607. assert(Size == sizeof(idctbackup));
  1608. Result = IDCTBackup(p,(idctbackup*)Data);
  1609. break;
  1610. }
  1611. if (No>=IDCT_FRAMENO && No<IDCT_FRAMENO+AHI(p)->AllCount)
  1612. GETVALUE(AHI(p)->BufFrameNo[No-IDCT_FRAMENO],int);
  1613. return Result;
  1614. }
  1615. static int IDCTLock(void* p,int No,planes Planes,int* Brightness,video* Format)
  1616. {
  1617. if (Brightness)
  1618. *Brightness = AHI(p)->p.FX.Brightness;
  1619. if (Format)
  1620. *Format = AHI(p)->Overlay;
  1621. if (No<0 || No>=AHI(p)->BufCount || No>=AHI(p)->AllCount)
  1622. {
  1623. Planes[0] = NULL;
  1624. Planes[1] = NULL;
  1625. Planes[2] = NULL;
  1626. return ERR_INVALID_PARAM;
  1627. }
  1628. Wait(AHI(p));
  1629. memcpy(Planes,AHI(p)->Buffer[No].Planes,sizeof(planes));
  1630. return ERR_NONE;
  1631. }
  1632. static void IDCTUnlock(void* p,int No)
  1633. {
  1634. }
  1635. static int IDCTFrameStart(void* p,int FrameNo,int *OldFrameNo,int DstNo,int BackNo,int FwdNo,int ShowNo,bool_t Drop)
  1636. {
  1637. if (!AHI(p)->IDCT)
  1638. return ERR_DEVICE_ERROR;
  1639. // we will try to avoid to overwrite currently displayed buffers:
  1640. //   ShowCurr currently displayed
  1641. //   ShowLast may be still on screen (because flip occurs only during vblank)
  1642. if (AHI(p)->ShowScale<0 && (AHI(p)->ShowLast == DstNo || AHI(p)->ShowCurr == DstNo))
  1643. {
  1644. // try to find a free buffer
  1645. int SwapNo;
  1646. for (SwapNo=0;SwapNo<AHI(p)->AllCount;++SwapNo)
  1647. if (SwapNo != AHI(p)->ShowLast && SwapNo != AHI(p)->ShowCurr && 
  1648. SwapNo != BackNo && SwapNo != FwdNo && SwapNo != ShowNo)
  1649. break; 
  1650. if (SwapNo < AHI(p)->AllCount)
  1651. SwapPtr(AHI(p),SwapNo,DstNo,1);
  1652. }
  1653. AHI(p)->ShowNext = ShowNo;
  1654. if (OldFrameNo)
  1655. *OldFrameNo = AHI(p)->BufFrameNo[DstNo];
  1656. AHI(p)->BufFrameNo[DstNo] = FrameNo;
  1657. AHI(p)->Dst = AHI(p)->Buffer+DstNo;
  1658. RingBegin(AHI(p),0);
  1659. RingPrepair(AHI(p),32);
  1660. RingReg(AHI(p),DP_MIX,0x01CC1200);
  1661. RingReg(AHI(p),DP_GUI_MASTER_CNTL,0xD598B2DF);
  1662. RingReg(AHI(p),DP_DATATYPE,0x40037D02);
  1663. RingReg(AHI(p),DST_PITCH,AHI(p)->Dst->UPitch);
  1664. RingReg(AHI(p),SC_TOP_LEFT,0);
  1665. RingReg(AHI(p),SC_BOTTOM_RIGHT,(AHI(p)->Overlay.Width & 0xFFFF) | (AHI(p)->Overlay.Height << 16));
  1666. RingReg(AHI(p),SRC_SC_BOTTOM_RIGHT,(((AHI(p)->Overlay.Width>>1)-1) & 0xFFFF) | (((AHI(p)->Overlay.Height>>1)-1) << 16));
  1667. if (BackNo >= 0)
  1668. {
  1669. atisurf* s = AHI(p)->Buffer+BackNo;
  1670. RingReg(AHI(p),REF1_PITCH_OFFSET,(s->YPitch << 19) | (s->YOffset >> 4));
  1671. RingReg(AHI(p),REF2_PITCH_OFFSET,(s->UPitch << 19) | (s->UOffset >> 4));
  1672. RingReg(AHI(p),REF3_PITCH_OFFSET,(s->VPitch << 19) | (s->VOffset >> 4));
  1673. }
  1674. if (FwdNo >= 0)
  1675. {
  1676. atisurf* s = AHI(p)->Buffer+FwdNo;
  1677. RingReg(AHI(p),REF4_PITCH_OFFSET,(s->YPitch << 19) | (s->YOffset >> 4));
  1678. RingReg(AHI(p),REF5_PITCH_OFFSET,(s->UPitch << 19) | (s->UOffset >> 4));
  1679. RingReg(AHI(p),REF6_PITCH_OFFSET,(s->VPitch << 19) | (s->VOffset >> 4));
  1680. }
  1681. AHI(p)->LastScanType = -1;
  1682. AHI(p)->LastMode = -1;
  1683. AHI(p)->ArithMode = (AHI(p)->Rounding?0x80000000:0)|0x200;
  1684. RingFlush(AHI(p));
  1685. return ERR_NONE;
  1686. }
  1687. static void IDCTFrameEnd(void* p)
  1688. {
  1689. if (AHI(p)->IDCT)
  1690. {
  1691. Wait(AHI(p)); // register restoring would mess up running IDCT
  1692. RingEnd(AHI(p));
  1693. }
  1694. }
  1695. static void IDCTDrop(void* p)
  1696. {
  1697. int No;
  1698. for (No=0;No<AHI(p)->AllCount;++No)
  1699. AHI(p)->BufFrameNo[No] = -1;
  1700. }
  1701. static int IDCTNull(void* p,const flowstate* State,bool_t Empty)
  1702. {
  1703. if (Empty)
  1704. ++AHI(p)->p.Total;
  1705. if (!State || State->DropLevel)
  1706. ++AHI(p)->p.Dropped;
  1707. return ERR_NONE;
  1708. }
  1709. static int IDCTSend(void* p,tick_t RefTime,const flowstate* State)
  1710. {
  1711. if (AHI(p)->ShowNext < 0)
  1712. return ERR_NEED_MORE_DATA;
  1713. if (State->CurrTime >= 0)
  1714. {
  1715. if (!AHI(p)->p.Play && State->CurrTime == AHI(p)->p.LastTime)
  1716. return ERR_BUFFER_FULL;
  1717. if (RefTime - (State->CurrTime + SHOWAHEAD) >= 0)
  1718. return ERR_BUFFER_FULL;
  1719. AHI(p)->p.LastTime = State->CurrTime;
  1720. }
  1721. else
  1722. AHI(p)->p.LastTime = RefTime;
  1723. if (State->CurrTime != TIME_RESEND)
  1724. ++AHI(p)->p.Total;
  1725. AHI(p)->ShowLast = AHI(p)->ShowCurr;
  1726. AHI(p)->ShowCurr = AHI(p)->ShowNext;
  1727. if (AHI(p)->ShowScale>=0)
  1728. {
  1729. if (State->DropLevel)
  1730. ++AHI(p)->p.Dropped;
  1731. else
  1732. Stretch(AHI(p),1);
  1733. }
  1734. else
  1735. SetOverlay(AHI(p));
  1736. return ERR_NONE;
  1737. }
  1738. static const nodedef ATI4200_IDCT =
  1739. {
  1740. CF_ABSTRACT,
  1741. ATI4200_IDCT_ID,
  1742. IDCT_CLASS,
  1743. PRI_DEFAULT-10, // don't use acceleration by default...
  1744. };
  1745. //---------------------------------------------------------------------------------------------
  1746. #if defined(_M_IX86)
  1747. extern void* __stdcall VirtualAlloc(void*,int,int,int);
  1748. #define MEM_COMMIT        0x1000     
  1749. #define PAGE_READWRITE    0x04     
  1750. #endif
  1751. static int Create(ati4200* p)
  1752. {
  1753. if (QueryPlatform(PLATFORM_MODEL)!=MODEL_ZODIAC)
  1754. return ERR_NOT_SUPPORTED;
  1755. p->p.Init = (ovlfunc)Init;
  1756. p->p.Done = (ovldone)Done;
  1757. p->p.Reset = (ovlfunc)Reset;
  1758. p->p.Blit = (ovlblit)Blit;
  1759. p->p.Update = (ovlfunc)Update;
  1760. p->p.UpdateShow = (ovlfunc)UpdateShow;
  1761. p->p.DoPowerOff = 1;
  1762. #if defined(_M_IX86)
  1763. #if !defined(ATIEMU)
  1764. return ERR_NOT_SUPPORTED;
  1765. #else
  1766. p->Device = VirtualAlloc(NULL,EXT_BASE+8*1024*1024,MEM_COMMIT,PAGE_READWRITE);
  1767. if (!p->Device)
  1768. return ERR_NOT_SUPPORTED;
  1769. memset(p->Device,0,EXT_BASE+8*1024*1024);
  1770. p->Regs = (int*)(p->Device + REG_BASE);
  1771. p->Regs[RING_CNTL] = 0x0800000D;
  1772. p->Regs[RING_BASE] = 0x00150000;
  1773. p->Regs[ACTIVE_V_DISP] = 480 << 16;
  1774. #endif
  1775. #else
  1776. p->Device = (uint8_t*)0x90000000;
  1777. p->Regs = (int*)(p->Device + REG_BASE);
  1778. #endif
  1779. p->Memory = EXT_BASE + 512*1024;
  1780. p->RingMask = (2 << (p->Regs[RING_CNTL] & 0x3F))-1;
  1781. p->Ring = (int*)(p->Device + p->Regs[RING_BASE]);
  1782. p->IdctVMT.Class = ATI4200_IDCT_ID;
  1783. p->IdctVMT.Enum = IDCTEnumAHI;
  1784. p->IdctVMT.Get = IDCTGet;
  1785. p->IdctVMT.Set = IDCTSet;
  1786. p->IdctVMT.Send = IDCTSend;
  1787. p->IdctVMT.Null = IDCTNull;
  1788. p->IdctVMT.Drop = IDCTDrop;
  1789. p->IdctVMT.Lock = IDCTLock;
  1790. p->IdctVMT.Unlock = IDCTUnlock;
  1791. p->IdctVMT.FrameStart = IDCTFrameStart;
  1792. p->IdctVMT.FrameEnd = IDCTFrameEnd;
  1793. p->IDCTOutput.Node = (node*)p;
  1794. p->IDCTOutput.No = OUT_INPUT;
  1795. p->p.AccelIDCT = &p->IdctVMT;
  1796. NodeRegisterClass(&ATI4200_IDCT);
  1797. GetMode(p);
  1798. return ERR_NONE;
  1799. }
  1800. static const nodedef ATI4200 = 
  1801. {
  1802. sizeof(ati4200)|CF_GLOBAL,
  1803. ATI4200_ID,
  1804. OVERLAY_CLASS,
  1805. PRI_DEFAULT+50,
  1806. (nodecreate)Create,
  1807. };
  1808. void ATI4200_Init() 
  1809. {
  1810. NodeRegisterClass(&ATI4200);
  1811. }
  1812. void ATI4200_Done() 
  1813. {
  1814. NodeUnRegisterClass(ATI4200_ID);
  1815. }
  1816. #else
  1817. void ATI4200_Init() {}
  1818. void ATI4200_Done() {}
  1819. #endif