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

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: ati3200.c 624 2006-02-01 17:48:42Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23. #include "stdafx.h"
  24. #if defined(ARM)
  25. #define CLIENTVERSION "1.29.031201.07700" 
  26. #define MAXSCALE 2
  27. #define SCALE MAXIDCTBUF
  28. #define DCFACTOR 8
  29. static const char DevOpenName[0x50] = "TCPMP";
  30. enum
  31. {
  32. PLANE_Y = 0x10000000,
  33. PLANE_U = 0x20000000,
  34. PLANE_V = 0x40000000,
  35. SUCCESS = 0,
  36. FAIL = 1,
  37. ENDENUM = 5,
  38. FORMAT_PAL4 = 1,
  39. FORMAT_PAL8 = 2,
  40. FORMAT_RGB444 = 3,
  41. FORMAT_RGB555 = 4,
  42. FORMAT_RGB565 = 5,
  43. FORMAT_YUYV = 6,
  44. FORMAT_YVYU = 7,
  45. FORMAT_YUV422 = 8,
  46. FORMAT_YUV420 = 9,
  47. FORMAT_UYVY = 10,
  48. FORMAT_VYUY = 11,
  49. FORMAT_PAL2 = 12,
  50. MIRROR_UPDOWN = 1,
  51. MIRROR_LEFTRIGHT= 2,
  52. MEM_EXTERNAL = 0x20,
  53. MEM_INTERNAL = 0x40,
  54. MEM_ANY_INT = -1, // prefer internal
  55. MEM_ANY_EXT = -2, // prefer external
  56. MEM_ANY_CHG = -3, // even:external odd:internal
  57. MEM_PRIMARY = -4, // reused primary surface
  58. PROP_SCANTYPE = 0,
  59. PROP_PADDING = 1,
  60. PROP_BIAS = 2,
  61. PROP_ROUNDING = 3,
  62. PROP_FRAMENO = 4,
  63. PROP_CODING = 5,
  64. PROP_DEBUG = 6,
  65. };
  66. //---------------------------------------------------------------
  67. // ati format
  68. //
  69. // input is idct_ati_t[length] array
  70. // 8x8 idct matrix reconstruction:
  71. //
  72. // clear block
  73. // for (pos=0;length>0;--length,++data)
  74. //   repeat X=0..3
  75. //     if (data->skipX==-1) break;
  76. //     pos += data->skipX
  77. //     block[scan[pos++]] = data->dataX
  78. typedef struct idct_ati
  79. {
  80. char skip3,skip2,skip1,skip0;
  81. short data1,data0,data3,data2;
  82. } idct_ati;
  83. typedef struct devinfo
  84. {
  85. char Name[0x50];
  86. char Version[0x50];
  87. int Revision;
  88. int ChipId;
  89. int RevisionId;
  90. int TotalMemory;
  91. int BusInterfaceMode;
  92. int InternalMemSize;
  93. int ExternalMemSize;
  94. int Caps1;
  95. int Caps2;
  96. int Caps3;
  97. int Caps4;
  98. char Pad[128];
  99. } devinfo;
  100. typedef struct modeinfo
  101. {
  102. int Width;
  103. int Height;
  104. int PixelFormat;
  105. int Freq;
  106. int Rotation;
  107. int Mirror;
  108. } modeinfo;
  109. typedef struct surfinfo
  110. {
  111. int Width;
  112. int Height;
  113. void* Addr;
  114. int Pitch;
  115. int Size;
  116. int Class;
  117. int One;
  118. } surfinfo;
  119. typedef struct planeinfo
  120. {
  121. int Width;
  122. int Height;
  123. void* Addr;
  124. int Pitch;
  125. int One;
  126. } planeinfo;
  127. typedef struct ahirect
  128. {
  129. int Left;
  130. int Top;
  131. int Right;
  132. int Bottom;
  133. } ahirect;
  134. typedef struct ahipoint
  135. {
  136. int x;
  137. int y;
  138. } ahipoint;
  139. typedef void* ahidevice;
  140. typedef void* ahicontext;
  141. typedef void* ahisurface;
  142. typedef void* ahiidct;
  143. typedef struct ahioverlay
  144. {
  145. ahirect DstRect; //0x00
  146. ahirect SrcRect; //0x10
  147. int ColorKey;    //0x20
  148. int ColorMask;   //0x24
  149. int Rotate;      //0x28
  150. int Mirror;      //0x2C
  151. int Zero;        //0x30
  152. } ahioverlay;
  153. typedef struct ahi
  154. {
  155. overlay p;
  156. idct IdctVMT;
  157. bool_t Shrink;
  158. bool_t Stretch;
  159. bool_t StretchOnlyInternal;
  160. bool_t BlitMode;
  161. bool_t BlitDownScale;
  162. rect OverlayRect;
  163. video Overlay;
  164. blitfx SoftFX;
  165. int OvlFormat;
  166. int OvlUVX2;
  167. int OvlUVY2;
  168. int OvlPlaneY;
  169. int OvlPlaneU;
  170. int OvlPlaneV;
  171. // should be in the first part for lower offset
  172. int (*AhiIDCTMComp8x8)(ahiidct* IDCT, const idct_ati* Data, int Len, int* Back, int* Fwd, int No, int ZigZagType);
  173. int (*AhiIDCTMComp)(ahiidct* IDCT, int* Back, int* Fwd, int No);
  174. int (*AhiIDCT8x8)(ahiidct* IDCT, const idct_ati* Data, int Len, int No, int ZigZagType);
  175. ahiidct* IDCT;
  176. int DCAdd;
  177. //int DCAdj;
  178. int MacroWidth;
  179. int MacroNo;
  180. int MacroSubNo;
  181. int* MVBack;
  182. int* MVFwd;
  183. int MVBackTab[6];
  184. int MVFwdTab[6];
  185. idct_ati Data[16+2]; //+2 as safe because convert can write -1 after last item
  186. int SaveCount;
  187. int SaveScanType;
  188. idct_ati SaveData[16];
  189. int IDCTWidth;
  190. int IDCTHeight;
  191. int OverlayRPitch;
  192. int ScaleWidth;
  193. int ScaleHeight;
  194. int ScaleCurr;
  195. devinfo DevInfo;
  196. modeinfo ModeInfo;
  197. ahidevice* Device;
  198. ahicontext* Context;
  199. int MaxCount;
  200. int AllCount; //BufCount + TempCount
  201. int BufCount;
  202. int TempCount;
  203. int ShowNext;
  204. int ShowCurr;
  205. int ShowLast;
  206. bool_t ShowNextIdle;
  207. ahisurface* Primary; // only for blit mode
  208. ahisurface* Buf[MAXIDCTBUF+MAXSCALE];  
  209. ahisurface* BufR[MAXIDCTBUF+MAXSCALE]; 
  210. int BufMode[MAXIDCTBUF+MAXSCALE]; 
  211. int BufFrameNo[MAXIDCTBUF+MAXSCALE];
  212. ahioverlay Param;
  213. tchar_t Version[128];
  214. //idct
  215. pin IDCTOutput;
  216. int FrameNo;
  217. int Zero;
  218. bool_t IDCTRounding;
  219. idct_block_t Block[8*8];
  220. int (*AhiInit)(int Version);
  221. int (*AhiTerm)();
  222. int (*AhiDevEnum)(ahidevice** Device, devinfo* Info, int No);
  223. int (*AhiDevOpen)(ahicontext** ContextOut, ahidevice* Device, const char* Name, int v);
  224. int (*AhiDevClose)(ahicontext* Context);
  225. int (*AhiDevClientVersion)(ahicontext* Context, const char* s);
  226. int (*AhiDispModeGet)(ahicontext* Context, modeinfo* Info);
  227. int (*AhiDispModeEnum)(ahicontext* Context, modeinfo* Info, int No);
  228. int (*AhiDispModeClip)(ahicontext* Context, const ahirect*); //not sure
  229. int (*AhiDispSurfGet)(ahicontext* Context, ahisurface** SurfaceOut);
  230. int (*AhiSurfGetLargestFreeBlockSize)(ahicontext* Context, int Format, int* a, int* b, int Mem);
  231. int (*AhiSurfAlloc)(ahicontext* Context, ahisurface** SurfaceOut, int* Size, int Format, int Mem);
  232. int (*AhiSurfReuse)(ahicontext* Context, ahisurface** SurfaceOut, ahisurface* SurfaceReuse, int* Size, int Format, int Zero);
  233. int (*AhiSurfFree)(ahicontext* Context, ahisurface* s);
  234. int (*AhiSurfLock)(ahicontext* Context, ahisurface* s, void** Ptr, int Plane);
  235. int (*AhiSurfUnlock)(ahicontext* Context, ahisurface* s, int Plane);
  236. int (*AhiSurfInfo)(ahicontext* Context, ahisurface* s, surfinfo* Info);
  237. int (*AhiSurfPlaneInfo)(ahicontext* Context, ahisurface* s, planeinfo* Info, int Plane);
  238. int (*AhiDrawRopSet)(ahicontext* Context, int ROP);
  239. int (*AhiDrawSurfSrcSet)(ahicontext* Context, ahisurface* Src, int Plane);
  240. int (*AhiDrawSurfDstSet)(ahicontext* Context, ahisurface* Dst, int Plane);
  241. int (*AhiDrawIdle)(ahicontext* Context, int v);
  242. int (*AhiDispWaitVBlank)(ahicontext* Context, int v);
  243. int (*AhiDrawBitBlt)(ahicontext* Context, const ahirect* DstRect, const ahipoint* SrcPos);
  244. int (*AhiDrawStretchBlt)(ahicontext* Context, const ahirect* DstRect, const ahirect* SrcRect, int Mode);
  245. int (*AhiDrawRotateBlt)(ahicontext* Context, const ahirect* DstRect, const ahipoint* SrcPos, int Rotate, int Mirror, int Zero);
  246. int (*AhiDispOverlayCaps)(ahicontext* Context, int Mode, int* Caps);
  247. int (*AhiDispOverlayState)(ahicontext* Context, int State, int Zero);
  248. int (*AhiDispOverlayPos)(ahicontext* Context, const ahirect* Rect, int Zero);
  249. int (*AhiDispOverlaySurf)(ahicontext* Context, ahisurface* Surface, ahioverlay* Info, int Mode);
  250. int (*AhiIDCTOpen)(ahicontext* Context, ahiidct** IDCTOut, int Zero);
  251. int (*AhiIDCTClose)(ahiidct* IDCT);
  252. int (*AhiIDCTPropGet)(ahiidct* IDCT, int No, int* Data, int Size);
  253. int (*AhiIDCTPropSet)(ahiidct* IDCT, int No, const int* Data, int Size);
  254. int (*AhiIDCTFrameStart)(ahiidct* IDCT, ahisurface* Dst, ahisurface* Back, ahisurface* Fwd, int Frame, int Zero);
  255. int (*AhiIDCTFrameEnd)(ahiidct* IDCT, int Frame);
  256. int (*AhiUnmap)();
  257. bool_t TmpInited;
  258. bool_t NoRelease;
  259. bool_t AllowStretchFlip;
  260. bool_t AllowPrimaryReUse;
  261. bool_t AllowLowBitdepth;
  262. bool_t FullScreenOverlay;   // overlay covers fullscreen
  263. bool_t PrimaryReUse;
  264. bool_t LowBitdepth;
  265. bool_t Internal;   // IDCT is using internal memory (it's faster, but less memory)
  266. bool_t Landscape;   // avoid external memory overlays in landscape mode
  267. bool_t IDCTBug;
  268. bool_t IDCTInit;
  269. bool_t ErrorMemory;
  270. } ahi;
  271. const datatable AHIParams[] = 
  272. {
  273. { AHI_DEVICEBITMAP, TYPE_BOOL, DF_SETUP|DF_SOFTRESET|DF_NOSAVE|DF_CHECKLIST },
  274. { AHI_IDCTBUG, TYPE_BOOL, DF_SETUP|DF_CHECKLIST },
  275. { AHI_PRIMARYREUSE, TYPE_BOOL, DF_SETUP|DF_CHECKLIST },
  276. { AHI_LOWBITDEPTH, TYPE_BOOL, DF_SETUP|DF_CHECKLIST },
  277. { AHI_STRETCHFLIP, TYPE_BOOL, DF_SETUP|DF_CHECKLIST },
  278. { AHI_NORELEASE, TYPE_BOOL, DF_SETUP|DF_CHECKLIST },
  279. { AHI_NAME, TYPE_STRING, DF_SETUP | DF_RDONLY|DF_GAP },
  280. { AHI_VERSION, TYPE_STRING, DF_SETUP | DF_RDONLY },
  281. { AHI_REVISION, TYPE_INT, DF_SETUP | DF_RDONLY },
  282. { AHI_CHIPID, TYPE_INT, DF_SETUP | DF_RDONLY|DF_HEX },
  283. { AHI_REVISIONID, TYPE_INT, DF_SETUP | DF_RDONLY },
  284. { AHI_TOTALMEMORY, TYPE_INT, DF_SETUP | DF_RDONLY },
  285. { AHI_INTERNALTOTALMEM, TYPE_INT, DF_SETUP | DF_RDONLY },
  286. { AHI_INTERNALFREEMEM, TYPE_INT, DF_SETUP | DF_RDONLY },
  287. { AHI_EXTERNALTOTALMEM, TYPE_INT, DF_SETUP | DF_RDONLY },
  288. { AHI_EXTERNALFREEMEM, TYPE_INT, DF_SETUP | DF_RDONLY },
  289. { AHI_CAPS1, TYPE_INT, DF_SETUP | DF_RDONLY|DF_HEX },
  290. { AHI_CAPS2, TYPE_INT, DF_SETUP | DF_RDONLY|DF_HEX },
  291. { AHI_CAPS3, TYPE_INT, DF_SETUP | DF_RDONLY|DF_HEX },
  292. { AHI_CAPS4, TYPE_INT, DF_SETUP | DF_RDONLY|DF_HEX },
  293. { AHI_UNMAP, TYPE_INT, DF_SETUP | DF_RDONLY|DF_HEX },
  294. DATATABLE_END(AHI_ID)
  295. };
  296. const tchar_t* ATIBase = T("System\GDI\Drivers\ATI");
  297. const tchar_t* DisableDevice = T("DisableDeviceBitmap");
  298. static bool_t Ahi2PixelFormat(int Format, pixel* p)
  299. {
  300. switch (Format)
  301. {
  302. case FORMAT_PAL2:
  303. p->Flags = PF_PALETTE;
  304. p->BitCount = 2;
  305. break;
  306. case FORMAT_PAL4:
  307. p->Flags = PF_PALETTE;
  308. p->BitCount = 2;
  309. break;
  310. case FORMAT_PAL8:
  311. p->Flags = PF_PALETTE;
  312. p->BitCount = 2;
  313. break;
  314. case FORMAT_RGB444:
  315. DefaultRGB(p,16,4,4,4,0,0,0);
  316. break;
  317. case FORMAT_RGB555:
  318. DefaultRGB(p,16,5,5,5,0,0,0);
  319. break;
  320. case FORMAT_RGB565:
  321. DefaultRGB(p,16,5,6,5,0,0,0);
  322. break;
  323. case FORMAT_YUYV:
  324. p->Flags = PF_FOURCC;
  325. p->FourCC = FOURCC_YUYV;
  326. break;
  327. case FORMAT_YVYU:
  328. p->Flags = PF_FOURCC;
  329. p->FourCC = FOURCC_YVYU;
  330. break;
  331. case FORMAT_YUV420:
  332. p->Flags = PF_FOURCC;
  333. p->FourCC = FOURCC_I420;
  334. break;
  335. case FORMAT_UYVY:
  336. p->Flags = PF_FOURCC;
  337. p->FourCC = FOURCC_UYVY;
  338. break;
  339. case FORMAT_VYUY:
  340. p->Flags = PF_FOURCC;
  341. p->FourCC = FOURCC_VYUY;
  342. break;
  343. case FORMAT_YUV422:
  344. p->Flags = PF_FOURCC;
  345. p->FourCC = FOURCC_YV16;
  346. break;
  347. default:
  348. return 0;
  349. }
  350. return 1;
  351. }
  352. static void ClearPrimary(ahi* p)
  353. {
  354. ahisurface* Primary = NULL;
  355. p->AhiDispSurfGet(p->Context,&Primary);
  356. if (Primary)
  357. {
  358. void* Ptr;
  359. surfinfo Info;
  360. pixel Pixel;
  361. p->AhiSurfInfo(p->Context,Primary,&Info);
  362. if (p->AhiSurfLock(p->Context,Primary,&Ptr,0)==SUCCESS)
  363. {
  364. Ahi2PixelFormat(Info.Class,&Pixel);
  365. FillColor(Ptr,Info.Pitch,0,0,Info.Width,Info.Height,Pixel.BitCount,0);
  366. p->AhiSurfUnlock(p->Context,Primary,0);
  367. }
  368. }
  369. }
  370. static void SetLowBitdepth(ahi* p,bool_t Value)
  371. {
  372. if (p->LowBitdepth != Value && p->AllowLowBitdepth && p->DevInfo.ChipId == 0x57441002)
  373. {
  374. volatile int* Regs = ((int**)p->Context)[7];
  375. int Ctrl;
  376. p->LowBitdepth = Value;
  377. if (Value && !p->PrimaryReUse)
  378. ClearPrimary(p);
  379. while ((Regs[0x153] & 0x400)==0); // wait until not in vblank 
  380. while ((Regs[0x153] & 0x400)!=0); // wait until in vblank
  381. Ctrl = Regs[0x105];
  382. Ctrl &= ~7;
  383. Ctrl |= Value ? 2:6;
  384. Regs[0x105] = Ctrl;
  385. }
  386. }
  387. static bool_t Hide(ahi* p)
  388. {
  389. if (p->p.Show && p->AllCount)
  390. {
  391. SetLowBitdepth(p,0);
  392. p->AhiDispOverlayState(p->Context,0,0);
  393. p->AhiDispWaitVBlank(p->Context,0);
  394. }
  395. return 1;
  396. }
  397. static void FreeScale(ahi* p,bool_t* Hidden)
  398. {
  399. int No;
  400. for (No=SCALE;No<SCALE+2;++No)
  401. if (p->Buf[No])
  402. {
  403. if (Hidden && !*Hidden)
  404. *Hidden = Hide(p);
  405. p->AhiSurfFree(p->Context,p->Buf[No]);
  406. p->Buf[No] = NULL;
  407. if (p->BufMode[No] == MEM_PRIMARY)
  408. {
  409. p->PrimaryReUse = 0;
  410. WaitDisable(0);
  411. }
  412. p->BufMode[No] = 0;
  413. }
  414. p->ScaleWidth = 0;
  415. p->ScaleHeight = 0;
  416. p->ScaleCurr = 0;
  417. }
  418. static void FreeBuffer(ahi* p,int No,bool_t* Hidden)
  419. {
  420. if (Hidden && !*Hidden && p->ShowCurr == No)
  421. *Hidden = Hide(p);
  422. if (p->Buf[No])
  423. p->AhiSurfFree(p->Context,p->Buf[No]);
  424. p->Buf[No] = NULL;
  425. if (p->BufR[No])
  426. p->AhiSurfFree(p->Context,p->BufR[No]);
  427. p->BufR[No] = NULL;
  428. if (p->BufMode[No] == MEM_PRIMARY)
  429. {
  430. p->PrimaryReUse = 0;
  431. WaitDisable(0);
  432. }
  433. p->BufMode[No] = 0;
  434. }
  435. static int Lock(ahi* p,int No,planes Planes,bool_t Force)
  436. {
  437. if (!Force && (No<0 || No>=p->BufCount))
  438. {
  439. Planes[0] = NULL;
  440. Planes[1] = NULL;
  441. Planes[2] = NULL;
  442. return ERR_INVALID_PARAM;
  443. }
  444. p->AhiDrawIdle(p->Context,0);
  445. if (p->AhiSurfLock(p->Context,p->Buf[No],&Planes[0],p->OvlPlaneY)==SUCCESS)
  446. {
  447. if (!p->OvlPlaneU || p->AhiSurfLock(p->Context,p->Buf[No],&Planes[1],p->OvlPlaneU)==SUCCESS)
  448. {
  449. if (!p->OvlPlaneV || p->AhiSurfLock(p->Context,p->Buf[No],&Planes[2],p->OvlPlaneV)==SUCCESS)
  450. return ERR_NONE;
  451. if (p->OvlPlaneU) p->AhiSurfUnlock(p->Context,p->Buf[No],p->OvlPlaneU);
  452. }
  453. p->AhiSurfUnlock(p->Context,p->Buf[No],p->OvlPlaneY);
  454. }
  455. return ERR_DEVICE_ERROR;
  456. }
  457. static void Unlock(ahi* p,int No)
  458. {
  459. p->AhiSurfUnlock(p->Context,p->Buf[No],p->OvlPlaneY);
  460. if (p->OvlPlaneU) p->AhiSurfUnlock(p->Context,p->Buf[No],p->OvlPlaneU);
  461. if (p->OvlPlaneV) p->AhiSurfUnlock(p->Context,p->Buf[No],p->OvlPlaneV);
  462. }
  463. static bool_t CheckVersion(ahi* p,bool_t IDCT)
  464. {
  465. int c = IDCT?27:24;
  466. int a,b;
  467. StrToTcs(p->Version,TSIZEOF(p->Version),p->DevInfo.Version);
  468. if (sscanf(p->DevInfo.Version,"%d.%d",&a,&b)!=2)
  469. a = 2; // force true 
  470. return a>1 || (a==1 && b>=c);
  471. }
  472. static void GetMode(ahi* p)
  473. {
  474. // get current mode parameters
  475. p->AhiDispModeGet(p->Context,&p->ModeInfo);
  476. memset(&p->p.Output.Format.Video,0,sizeof(video));
  477. p->p.Output.Format.Video.Width = p->ModeInfo.Width;
  478. p->p.Output.Format.Video.Height = p->ModeInfo.Height;
  479. p->p.Output.Format.Video.Direction = 0;
  480. p->p.Output.Format.Video.Aspect = ASPECT_ONE;
  481. if (p->ModeInfo.Rotation!=0 && p->ModeInfo.Rotation!=2)
  482. p->p.Output.Format.Video.Direction ^= DIR_SWAPXY;
  483. switch (p->ModeInfo.Rotation)
  484. {
  485. case 1:
  486. p->p.Output.Format.Video.Direction ^= DIR_MIRRORLEFTRIGHT;
  487. break;
  488. case 2:
  489. p->p.Output.Format.Video.Direction ^= DIR_MIRRORLEFTRIGHT|DIR_MIRRORUPDOWN;
  490. break;
  491. case 3:
  492. p->p.Output.Format.Video.Direction ^= DIR_MIRRORUPDOWN;
  493. break;
  494. }
  495. if (p->ModeInfo.Mirror & MIRROR_LEFTRIGHT)
  496. p->p.Output.Format.Video.Direction ^= DIR_MIRRORLEFTRIGHT;
  497. if (p->ModeInfo.Mirror & MIRROR_UPDOWN)
  498. p->p.Output.Format.Video.Direction ^= DIR_MIRRORUPDOWN;
  499. Ahi2PixelFormat(p->ModeInfo.PixelFormat,&p->p.Output.Format.Video.Pixel);
  500. FillInfo(&p->p.Output.Format.Video.Pixel);
  501. AdjustOrientation(&p->p.Output.Format.Video,0);
  502. }
  503. static bool_t UpdateOverlay(ahi* p,int BufCount,int TempCount);
  504. static int IDCTUpdateFunc(ahi* p);
  505. static void Done(ahi* p);
  506. static bool_t SafeAhiInit(ahi* p)
  507. {
  508. if (p->TmpInited)
  509. {
  510. p->TmpInited = 0;
  511. return 1;
  512. }
  513. return p->AhiInit(0)==SUCCESS;
  514. }
  515. static void SafeAhiTerm(ahi* p)
  516. {
  517. if (p->NoRelease)
  518. p->TmpInited = 1;
  519. else
  520. {
  521. p->AhiTerm();
  522. if (p->AhiUnmap)
  523. p->AhiUnmap();
  524. }
  525. }
  526. static int UpdateNoRelease(ahi* p)
  527. {
  528. if (p->TmpInited && !p->NoRelease)
  529. {
  530. p->TmpInited = 0;
  531. SafeAhiTerm(p);
  532. }
  533. return ERR_NONE;
  534. }
  535. static int Enum(ahi* p, int* No, datadef* Param)
  536. {
  537. if (OverlayEnum(&p->p,No,Param)==ERR_NONE)
  538. return ERR_NONE;
  539. return NodeEnumTable(No,Param,AHIParams);
  540. }
  541. static int Set(ahi* p,int No,const void* Data,int Size)
  542. {
  543. int Result = OverlaySet(&p->p,No,Data,Size);
  544. switch (No)
  545. {
  546. case NODE_CRASH:
  547. Done(p);
  548. break;
  549. case AHI_DEVICEBITMAP:
  550. if (Size==sizeof(bool_t))
  551. {
  552. DWORD Disp;
  553. DWORD Value;
  554. HKEY Key;
  555. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, ATIBase, 0, NULL, 0, 0, NULL, &Key, &Disp) == ERROR_SUCCESS)
  556. {
  557. Value = *(bool_t*)Data;
  558. RegSetValueEx(Key, DisableDevice, 0, REG_DWORD, (LPBYTE)&Value, sizeof(Value));
  559. RegCloseKey(Key);
  560. Result = ERR_NONE;
  561. }
  562. }
  563. break;
  564. case AHI_STRETCHFLIP: SETVALUE(p->AllowStretchFlip,bool_t,ERR_NONE); break;
  565. case AHI_LOWBITDEPTH: SETVALUE(p->AllowLowBitdepth,bool_t,ERR_NONE); break;
  566. case AHI_PRIMARYREUSE: SETVALUE(p->AllowPrimaryReUse,bool_t,ERR_NONE); break;
  567. case AHI_NORELEASE: SETVALUE(p->NoRelease,bool_t,UpdateNoRelease(p)); break; // no compare
  568. case AHI_IDCTBUG: SETVALUE(p->IDCTBug,bool_t,IDCTUpdateFunc(p)); break;
  569. }
  570. return Result;
  571. }
  572. static int GetFreeMemory(ahi* p,int Mem)
  573. {
  574. int a=0;
  575. int b;
  576. if (p->AhiSurfGetLargestFreeBlockSize)
  577. {
  578. if (p->Context)
  579. p->AhiSurfGetLargestFreeBlockSize(p->Context,FORMAT_YUV420,&a,&b,Mem);
  580. else
  581. if (SafeAhiInit(p))
  582. {
  583. int No;
  584. for (No=0;;No++)
  585. {
  586. int Result = p->AhiDevEnum(&p->Device,&p->DevInfo,No);
  587. if (Result == SUCCESS && CheckVersion(p,0))
  588. {
  589. if (p->AhiDevOpen(&p->Context,p->Device,DevOpenName,2)==SUCCESS)
  590. {
  591. p->AhiDevClientVersion(p->Context,CLIENTVERSION);
  592. p->AhiSurfGetLargestFreeBlockSize(p->Context,FORMAT_YUV420,&a,&b,Mem);
  593. p->AhiDevClose(p->Context);
  594. }
  595. p->Context = NULL;
  596. break;
  597. }
  598. if (Result == ENDENUM)
  599. break;
  600. }
  601. SafeAhiTerm(p);
  602. }
  603. a = (a * 3) >> 1; // 12bit/pixel
  604. }
  605. return a;
  606. }
  607. static int Get(ahi* p,int No,void* Data,int Size)
  608. {
  609. int Result = OverlayGet(&p->p,No,Data,Size);
  610. switch (No)
  611. {
  612. case AHI_NAME: 
  613. StrToTcs((tchar_t*)Data,Size/sizeof(tchar_t),p->DevInfo.Name);
  614. Result = ERR_NONE;
  615. break;
  616. case AHI_VERSION: 
  617. StrToTcs((tchar_t*)Data,Size/sizeof(tchar_t),p->DevInfo.Version);
  618. Result = ERR_NONE;
  619. break;
  620. case AHI_DEVICEBITMAP:
  621. if (Size==sizeof(bool_t))
  622. {
  623. HKEY Key;
  624. Result = ERR_NONE;
  625. *(bool_t*)Data = 0;
  626. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, ATIBase, 0, 0, &Key) == ERROR_SUCCESS)
  627. {
  628. DWORD Value;
  629. DWORD RegSize = sizeof(Value);
  630. DWORD RegType;
  631. if (RegQueryValueEx(Key, DisableDevice, 0, &RegType, (LPBYTE)&Value, &RegSize) == ERROR_SUCCESS && 
  632. RegType == REG_DWORD && Value!=0)
  633. *(bool_t*)Data = 1;
  634. RegCloseKey(Key);
  635. }
  636. }
  637. break;
  638. case AHI_STRETCHFLIP: GETVALUE(p->AllowStretchFlip,bool_t); break;
  639. case AHI_LOWBITDEPTH: GETVALUE(p->AllowLowBitdepth,bool_t); break;
  640. case AHI_PRIMARYREUSE: GETVALUE(p->AllowPrimaryReUse,bool_t); break;
  641. case AHI_NORELEASE: GETVALUE(p->NoRelease,bool_t); break;
  642. case AHI_IDCTBUG: GETVALUE(p->IDCTBug,bool_t); break;
  643. case AHI_REVISION: GETVALUE(p->DevInfo.Revision,int); break;
  644. case AHI_CHIPID: GETVALUE(p->DevInfo.ChipId,int); break;
  645. case AHI_REVISIONID: GETVALUE(p->DevInfo.RevisionId,int); break;
  646. case AHI_TOTALMEMORY: GETVALUE(p->DevInfo.TotalMemory,int); break;
  647. case AHI_INTERNALTOTALMEM: GETVALUE(p->DevInfo.InternalMemSize,int); break;
  648. case AHI_EXTERNALTOTALMEM: GETVALUE(p->DevInfo.ExternalMemSize,int); break;
  649. case AHI_INTERNALFREEMEM: GETVALUE(GetFreeMemory(p,MEM_INTERNAL),int); break;
  650. case AHI_EXTERNALFREEMEM: GETVALUE(GetFreeMemory(p,MEM_EXTERNAL),int); break;
  651. case AHI_CAPS1: GETVALUE(p->DevInfo.Caps1,int); break;
  652. case AHI_CAPS2: GETVALUE(p->DevInfo.Caps2,int); break;
  653. case AHI_CAPS3: GETVALUE(p->DevInfo.Caps3,int); break;
  654. case AHI_CAPS4: GETVALUE(p->DevInfo.Caps4,int); break;
  655. case AHI_UNMAP: GETVALUE((int)p->AhiUnmap,int); break;
  656. }
  657. return Result;
  658. }
  659. static int GetPitch(ahi* p,ahisurface* Surf)
  660. {
  661. planeinfo Info;
  662. surfinfo SInfo;
  663. if (p->OvlPlaneY)
  664. {
  665. p->AhiSurfPlaneInfo(p->Context,Surf,&Info,p->OvlPlaneY);
  666. return Info.Pitch;
  667. }
  668. else
  669. {
  670. p->AhiSurfInfo(p->Context,Surf,&SInfo);
  671. return SInfo.Pitch;
  672. }
  673. }
  674. static bool_t AllocBuffer(ahi* p,int No,int Width,int Height,int Mode)
  675. {
  676. int FirstMode;
  677. int SecondMode;
  678. ahisurface* Surf = NULL;
  679. ahisurface* SurfR = NULL;
  680. int FinalMode = 0;
  681. int Size[2];
  682. Size[0] = Width;
  683. Size[1] = Height;
  684. if (Mode == MEM_ANY_CHG)
  685. Mode = (No & 1) ? MEM_ANY_INT : MEM_ANY_EXT;
  686. if (Mode == MEM_ANY_INT)
  687. {
  688. FirstMode = MEM_INTERNAL;
  689. SecondMode = MEM_EXTERNAL;
  690. }
  691. else
  692. if (Mode == MEM_ANY_EXT)
  693. {
  694. FirstMode = MEM_EXTERNAL;
  695. SecondMode = MEM_INTERNAL;
  696. }
  697. else
  698. {
  699. FirstMode = Mode;
  700. SecondMode = 0;
  701. }
  702. p->AhiSurfAlloc(p->Context,&Surf,Size,p->OvlFormat,FirstMode);
  703. if (Surf)
  704. FinalMode = FirstMode;
  705. if (!Surf && SecondMode)
  706. {
  707. p->AhiSurfAlloc(p->Context,&Surf,Size,p->OvlFormat,SecondMode);
  708. if (Surf)
  709. FinalMode = SecondMode;
  710. }
  711. if (!Surf && p->FullScreenOverlay && !p->Landscape && !p->PrimaryReUse && p->AllowPrimaryReUse)
  712. {
  713. ahisurface* Primary = NULL;
  714. p->AhiDispSurfGet(p->Context,&Primary);
  715. if (Primary)
  716. {
  717. p->AhiSurfReuse(p->Context,&Surf,Primary,Size,p->OvlFormat,0);
  718. if (Surf)
  719. {
  720. FinalMode = MEM_PRIMARY;
  721. p->PrimaryReUse = 1;
  722. WaitDisable(1);
  723. }
  724. }
  725. }
  726. DEBUG_MSG4(DEBUG_VIDEO,T("AHIALLOC %d: %d,%d %d"),No,Size[0],Size[1],FinalMode);
  727. if (Surf)
  728. {
  729. void* Ptr;
  730. if (No < SCALE)
  731. {
  732. p->Overlay.Pitch = GetPitch(p,Surf);
  733. Size[0] = Height;
  734. Size[1] = Width;
  735. p->AhiSurfReuse(p->Context,&SurfR,Surf,Size,p->OvlFormat,0);
  736. if (!SurfR)
  737. {
  738. // this shouldn't happen
  739. p->AhiSurfFree(p->Context,Surf);
  740. return 0;
  741. }
  742. p->OverlayRPitch = GetPitch(p,SurfR);
  743. }
  744. p->Buf[No] = Surf;
  745. p->BufR[No] = SurfR;
  746. p->BufMode[No] = FinalMode;
  747. p->BufFrameNo[No] = -1;
  748. if (p->OvlPlaneY)
  749. {
  750. planeinfo Info;
  751. p->AhiSurfPlaneInfo(p->Context,Surf,&Info,p->OvlPlaneY);
  752. if (p->AhiSurfLock(p->Context,Surf,&Ptr,p->OvlPlaneY)==SUCCESS)
  753. {
  754. FillColor(Ptr,Info.Pitch,0,0,Info.Width,Info.Height,8,0);
  755. p->AhiSurfUnlock(p->Context,Surf,p->OvlPlaneY);
  756. }
  757. p->AhiSurfPlaneInfo(p->Context,Surf,&Info,p->OvlPlaneU);
  758. if (p->AhiSurfLock(p->Context,Surf,&Ptr,p->OvlPlaneU)==SUCCESS)
  759. {
  760. FillColor(Ptr,Info.Pitch,0,0,Info.Width,Info.Height,8,128);
  761. p->AhiSurfUnlock(p->Context,Surf,p->OvlPlaneU);
  762. }
  763. p->AhiSurfPlaneInfo(p->Context,Surf,&Info,p->OvlPlaneV);
  764. if (p->AhiSurfLock(p->Context,Surf,&Ptr,p->OvlPlaneV)==SUCCESS)
  765. {
  766. FillColor(Ptr,Info.Pitch,0,0,Info.Width,Info.Height,8,128);
  767. p->AhiSurfUnlock(p->Context,Surf,p->OvlPlaneV);
  768. }
  769. }
  770. else
  771. {
  772. surfinfo SInfo;
  773. p->AhiSurfInfo(p->Context,Surf,&SInfo);
  774. if (p->AhiSurfLock(p->Context,Surf,&Ptr,0)==SUCCESS)
  775. {
  776. FillColor(Ptr,SInfo.Pitch,0,0,SInfo.Width,SInfo.Height,16,0);
  777. p->AhiSurfUnlock(p->Context,Surf,0);
  778. }
  779. }
  780. return 1;
  781. }
  782. return 0;
  783. }
  784. static void UpdateOverlaySurf(ahi* p,bool_t Idle)
  785. {
  786. int Show = p->ShowCurr;
  787. if (p->Buf[SCALE])
  788. {
  789. Show = SCALE + p->ScaleCurr;
  790. Idle = 1; // is this needed?
  791. }
  792. if (p->Buf[Show])
  793. {
  794. if (Idle) p->AhiDrawIdle(p->Context,0);
  795. p->AhiDispOverlaySurf(p->Context,p->Buf[Show],&p->Param,0);
  796. //DEBUG_MSG1(DEBUG_VIDEO,T("ATI %08x"),p->Buf[Show]);
  797. }
  798. }
  799. static void Stretch(ahi* p,bool_t Update,bool_t Flip)
  800. {
  801. ahisurface* Src;
  802. ahisurface* Dst;
  803. ahirect DstRect;
  804. ahirect SrcRect;
  805. int ScaleMode = (p->p.FX.Flags & (BLITFX_ARITHSTRETCH50|BLITFX_ARITHSTRETCHALWAYS)) ? 5:1;
  806. if (p->Buf[SCALE+1] && Flip)
  807. p->ScaleCurr ^= 1;
  808. Src = p->Buf[p->ShowCurr];
  809. Dst = p->Buf[SCALE+p->ScaleCurr];
  810. DstRect.Left = 0;
  811. DstRect.Top = 0;
  812. DstRect.Right = p->ScaleWidth >> p->OvlUVX2;
  813. DstRect.Bottom = p->ScaleHeight >> p->OvlUVY2;
  814. SrcRect.Left = p->OverlayRect.x >> p->OvlUVX2;
  815. SrcRect.Top = p->OverlayRect.y >> p->OvlUVY2;
  816. SrcRect.Right = (p->OverlayRect.x + p->OverlayRect.Width) >> p->OvlUVX2;
  817. SrcRect.Bottom = (p->OverlayRect.y + p->OverlayRect.Height) >> p->OvlUVY2;
  818. if (p->OvlPlaneU)
  819. {
  820. if (p->Shrink) p->AhiDrawIdle(p->Context,0);
  821. p->AhiDrawSurfSrcSet(p->Context,Src,p->OvlPlaneU);
  822. p->AhiDrawSurfDstSet(p->Context,Dst,p->OvlPlaneU);
  823. if (p->Stretch)
  824. p->AhiDrawStretchBlt(p->Context,&DstRect,&SrcRect,ScaleMode);
  825. else
  826. p->AhiDrawBitBlt(p->Context,&DstRect,(ahipoint*)&SrcRect.Left);
  827. }
  828. if (p->OvlPlaneV)
  829. {
  830. if (p->Shrink) p->AhiDrawIdle(p->Context,0);
  831. p->AhiDrawSurfSrcSet(p->Context,Src,p->OvlPlaneV);
  832. p->AhiDrawSurfDstSet(p->Context,Dst,p->OvlPlaneV);
  833. if (p->Stretch)
  834. p->AhiDrawStretchBlt(p->Context,&DstRect,&SrcRect,ScaleMode);
  835. else
  836. p->AhiDrawBitBlt(p->Context,&DstRect,(ahipoint*)&SrcRect.Left);
  837. }
  838. DstRect.Left <<= p->OvlUVX2;
  839. DstRect.Top <<= p->OvlUVY2;
  840. DstRect.Right <<= p->OvlUVX2;
  841. DstRect.Bottom <<= p->OvlUVY2;
  842. SrcRect.Left <<= p->OvlUVX2;
  843. SrcRect.Top <<= p->OvlUVY2;
  844. SrcRect.Right <<= p->OvlUVX2;
  845. SrcRect.Bottom <<= p->OvlUVY2;
  846. if (p->Shrink) p->AhiDrawIdle(p->Context,0);
  847. p->AhiDrawSurfSrcSet(p->Context,Src,p->OvlPlaneY);
  848. p->AhiDrawSurfDstSet(p->Context,Dst,p->OvlPlaneY);
  849. if (p->Stretch)
  850. p->AhiDrawStretchBlt(p->Context,&DstRect,&SrcRect,ScaleMode);
  851. else
  852. p->AhiDrawBitBlt(p->Context,&DstRect,(ahipoint*)&SrcRect.Left);
  853. if (p->Buf[SCALE+1] && Update && Flip)
  854. UpdateOverlaySurf(p,1);
  855. }
  856. static void SwapPtr(ahi* p,int a,int b,int SwapShow)
  857. {
  858. ahisurface* t;
  859. t = p->Buf[a];
  860. p->Buf[a] = p->Buf[b];
  861. p->Buf[b] = t;
  862. t = p->BufR[a];
  863. p->BufR[a] = p->BufR[b];
  864. p->BufR[b] = t;
  865. SwapInt(&p->BufMode[a],&p->BufMode[b]);
  866. if (SwapShow)
  867. {
  868. SwapInt(&p->BufFrameNo[a],&p->BufFrameNo[b]);
  869. if (p->ShowNext == a)
  870. p->ShowNext = b;
  871. else
  872. if (p->ShowNext == b)
  873. p->ShowNext = a;
  874. if (p->ShowLast == a)
  875. p->ShowLast = b;
  876. else
  877. if (p->ShowLast == b)
  878. p->ShowLast = a;
  879. if (p->ShowCurr == a)
  880. p->ShowCurr = b;
  881. else
  882. if (p->ShowCurr == b)
  883. p->ShowCurr = a;
  884. }
  885. }
  886. static void MoveBuf(ahi* p,int Src,int Dst)
  887. {
  888. ahirect DstRect;
  889. ahipoint SrcPos;
  890. DstRect.Left = DstRect.Top = 0;
  891. DstRect.Right = p->Overlay.Width;
  892. DstRect.Bottom = p->Overlay.Height;
  893. SrcPos.x = SrcPos.y = 0;
  894. p->AhiDrawSurfSrcSet(p->Context,p->Buf[Src],p->OvlPlaneY);
  895. p->AhiDrawSurfDstSet(p->Context,p->Buf[Dst],p->OvlPlaneY);
  896. p->AhiDrawBitBlt(p->Context,&DstRect,&SrcPos);
  897. DstRect.Right >>= p->OvlUVX2;
  898. DstRect.Bottom >>= p->OvlUVY2;
  899. if (p->OvlPlaneU)
  900. {
  901. p->AhiDrawSurfSrcSet(p->Context,p->Buf[Src],p->OvlPlaneU);
  902. p->AhiDrawSurfDstSet(p->Context,p->Buf[Dst],p->OvlPlaneU);
  903. p->AhiDrawBitBlt(p->Context,&DstRect,&SrcPos);
  904. }
  905. if (p->OvlPlaneV)
  906. {
  907. p->AhiDrawSurfSrcSet(p->Context,p->Buf[Src],p->OvlPlaneV);
  908. p->AhiDrawSurfDstSet(p->Context,p->Buf[Dst],p->OvlPlaneV);
  909. p->AhiDrawBitBlt(p->Context,&DstRect,&SrcPos);
  910. }
  911. }
  912. static void SwapBuf(ahi* p,int a,int b)
  913. {
  914. planes s,Tmp;
  915. if (SurfaceAlloc(Tmp,&p->Overlay)==ERR_NONE)
  916. {
  917. if (Lock(p,a,s,0)==ERR_NONE)
  918. {
  919. SurfaceCopy(&p->Overlay,&p->Overlay,s,Tmp,NULL); // save from a
  920. Unlock(p,a);
  921. MoveBuf(p,b,a); // move b->a
  922. if (Lock(p,b,s,0)==ERR_NONE)
  923. {
  924. SurfaceCopy(&p->Overlay,&p->Overlay,Tmp,s,NULL); // restore to b
  925. Unlock(p,b);
  926. }
  927. SwapPtr(p,a,b,0); // swap pointers
  928. }
  929. SurfaceFree(Tmp);
  930. }
  931. }
  932. static void Optimize(ahi* p)
  933. {
  934. if (p->Buf[SCALE] && p->BufCount==3 && 
  935. !(p->BufMode[0] == p->BufMode[1] && p->BufMode[1] == p->BufMode[2]))
  936. {
  937. // we have one buffer in different pool
  938. // b-frame motion compensation is faster if the two reference frames
  939. // are in different pool as the b-frame
  940. if (p->BufMode[1] == p->BufMode[2])
  941. SwapBuf(p,0,2);
  942. else
  943. if (p->BufMode[0] == p->BufMode[2])
  944. SwapBuf(p,1,2);
  945. }
  946. }
  947. static void UpdateBrightness(ahi* p,int Brightness)
  948. {
  949. int Delta,No;
  950. int DCAdd = Brightness * DCFACTOR;
  951. if (p->DCAdd != DCAdd)
  952. {
  953. Delta = DCAdd - p->DCAdd;
  954. p->DCAdd = DCAdd;
  955. if (p->IDCT)
  956. {
  957. planes s,Tmp;
  958. int ValidTmp = 0;
  959. int SwapNo = p->TempCount ? p->BufCount : 0;
  960. int MacroNo;
  961. int MacroCount = (p->Overlay.Width >> 4)*(p->Overlay.Height >> 4);
  962. // we need to save one buffer and adjust manually (if there are no temp buffers)
  963. if (p->BufCount && !p->TempCount && Lock(p,SwapNo,s,0)==ERR_NONE)
  964. {
  965. if (SurfaceAlloc(Tmp,&p->Overlay)==ERR_NONE)
  966. {
  967. ValidTmp = 1;
  968. SurfaceCopy(&p->Overlay,&p->Overlay,s,Tmp,NULL);
  969. }
  970. Unlock(p,SwapNo);
  971. }
  972. *(int32_t*)&p->Data[0] = -1;
  973. p->Data[0].skip0 = 0;
  974. p->Data[0].data0 = (idct_block_t)Delta;
  975. for (No=p->TempCount ? 0:1;No<p->BufCount;++No)
  976. {
  977. // swap context
  978. p->AhiIDCTFrameStart(p->IDCT,p->Buf[SwapNo],p->Buf[No],NULL,p->FrameNo,0);
  979. for (MacroNo=0;MacroNo<MacroCount;++MacroNo)
  980. {
  981. p->AhiIDCTMComp8x8(p->IDCT,p->Data,1,&p->Zero,NULL,MacroNo,1);
  982. p->AhiIDCTMComp8x8(p->IDCT,p->Data,1,&p->Zero,NULL,MacroNo,1);
  983. p->AhiIDCTMComp8x8(p->IDCT,p->Data,1,&p->Zero,NULL,MacroNo,1);
  984. p->AhiIDCTMComp8x8(p->IDCT,p->Data,1,&p->Zero,NULL,MacroNo,1);
  985. p->AhiIDCTMComp8x8(p->IDCT,NULL,0,&p->Zero,NULL,MacroNo,0);
  986. p->AhiIDCTMComp8x8(p->IDCT,NULL,0,&p->Zero,NULL,MacroNo,0);
  987. }
  988. p->AhiIDCTFrameEnd(p->IDCT,p->FrameNo++);
  989. // swap pointer
  990. SwapPtr(p,No,SwapNo,0);
  991. }
  992. if (ValidTmp)
  993. {
  994. if (Lock(p,SwapNo,s,0)==ERR_NONE)
  995. {
  996. blitfx FX;
  997. memset(&FX,0,sizeof(FX));
  998. FX.ScaleX = SCALE_ONE;
  999. FX.ScaleY = SCALE_ONE;
  1000. FX.Brightness = Delta / DCFACTOR;
  1001. SurfaceCopy(&p->Overlay,&p->Overlay,Tmp,s,&FX);
  1002. Unlock(p,SwapNo);
  1003. }
  1004. SurfaceFree(Tmp);
  1005. }
  1006. }
  1007. }
  1008. }
  1009. static void FreePrimaryReUse(ahi* p);
  1010. static void UpdateDirection(ahi* p,int Dir)
  1011. {
  1012. int No;
  1013. if (p->Overlay.Direction != Dir)
  1014. {
  1015. planes s,Tmp;
  1016. video TmpSurface;
  1017. int ValidTmp = 0;
  1018. int SwapNo;
  1019. // hide overlay
  1020. if (p->p.Show && p->AllCount)
  1021. {
  1022. if (p->PrimaryReUse)
  1023. FreePrimaryReUse(p);
  1024. p->AhiDispOverlayState(p->Context,0,0);
  1025. p->AhiDispWaitVBlank(p->Context,0);
  1026. }
  1027. SwapNo = p->TempCount ? p->BufCount : 0;
  1028. // we need to save one buffer and swap manually (if there are no temp buffers)
  1029. if (p->BufCount && !p->TempCount && Lock(p,SwapNo,s,0)==ERR_NONE)
  1030. {
  1031. if (SurfaceAlloc(Tmp,&p->Overlay)==ERR_NONE)
  1032. {
  1033. ValidTmp = 1;
  1034. TmpSurface = p->Overlay;
  1035. SurfaceCopy(&p->Overlay,&p->Overlay,s,Tmp,NULL);
  1036. }
  1037. Unlock(p,SwapNo);
  1038. }
  1039. p->Overlay.Direction = Dir;
  1040. SwapInt(&p->Overlay.Width,&p->Overlay.Height);
  1041. SwapInt(&p->Overlay.Pitch,&p->OverlayRPitch);
  1042. IDCTUpdateFunc(p);
  1043. // swap buffer pointers
  1044. for (No=0;No<p->AllCount;++No)
  1045. {
  1046. ahisurface* t = p->Buf[No];
  1047. p->Buf[No] = p->BufR[No];
  1048. p->BufR[No] = t;
  1049. }
  1050. // swapxy content of buffers
  1051. for (No=p->TempCount ? 0:1;No<p->BufCount;++No)
  1052. {
  1053. ahirect DstRect;
  1054. ahipoint SrcPos;
  1055. DstRect.Left = DstRect.Top = 0;
  1056. DstRect.Right = p->Overlay.Width;
  1057. DstRect.Bottom = p->Overlay.Height;
  1058. SrcPos.x = SrcPos.y = 0;
  1059. p->AhiDrawSurfSrcSet(p->Context,p->BufR[No],p->OvlPlaneY);
  1060. p->AhiDrawSurfDstSet(p->Context,p->Buf[SwapNo],p->OvlPlaneY);
  1061. p->AhiDrawRotateBlt(p->Context,&DstRect,&SrcPos,1,1,0);
  1062. DstRect.Right >>= p->OvlUVX2;
  1063. DstRect.Bottom >>= p->OvlUVY2;
  1064. if (p->OvlPlaneU)
  1065. {
  1066. p->AhiDrawSurfSrcSet(p->Context,p->BufR[No],p->OvlPlaneU);
  1067. p->AhiDrawSurfDstSet(p->Context,p->Buf[SwapNo],p->OvlPlaneU);
  1068. p->AhiDrawRotateBlt(p->Context,&DstRect,&SrcPos,1,1,0);
  1069. }
  1070. if (p->OvlPlaneV)
  1071. {
  1072. p->AhiDrawSurfSrcSet(p->Context,p->BufR[No],p->OvlPlaneV);
  1073. p->AhiDrawSurfDstSet(p->Context,p->Buf[SwapNo],p->OvlPlaneV);
  1074. p->AhiDrawRotateBlt(p->Context,&DstRect,&SrcPos,1,1,0);
  1075. }
  1076. SwapPtr(p,No,SwapNo,0);
  1077. }
  1078. if (ValidTmp)
  1079. {
  1080. if (Lock(p,SwapNo,s,0)==ERR_NONE)
  1081. {
  1082. SurfaceRotate(&TmpSurface,&p->Overlay,Tmp,s,DIR_SWAPXY);
  1083. Unlock(p,SwapNo);
  1084. }
  1085. SurfaceFree(Tmp);
  1086. }
  1087. if (p->ShowNext >= 0)
  1088. p->ShowCurr = p->ShowNext;
  1089. if (p->ShowCurr<0 || p->ShowCurr>=p->BufCount)
  1090. p->ShowCurr = 0;
  1091. }
  1092. }
  1093. static void UpdateColorKey(ahi* p)
  1094. {
  1095. int No;
  1096. p->p.ColorKey = COLORKEY; // use colorkey by default
  1097. if (p->p.FullScreenViewport)
  1098. p->p.ColorKey = CRGB(0,0,0); // black colorkey because of lowbitdepth
  1099. if (p->PrimaryReUse || p->OvlFormat != FORMAT_YUV420)
  1100. p->p.ColorKey = RGB_NULL;
  1101. if (p->Landscape)
  1102. {
  1103. // disable colorkey for external overlays in landscape mode
  1104. if (p->Buf[SCALE])
  1105. {
  1106. if (p->BufMode[SCALE] == MEM_EXTERNAL)
  1107. p->p.ColorKey = RGB_NULL;
  1108. if (p->BufMode[SCALE+1] == MEM_EXTERNAL)
  1109. p->p.ColorKey = RGB_NULL;
  1110. }
  1111. else
  1112. {
  1113. for (No=0;No<p->AllCount;++No)
  1114. if (p->BufMode[No] == MEM_EXTERNAL)
  1115. {
  1116. p->p.ColorKey = RGB_NULL;
  1117. break;
  1118. }
  1119. }
  1120. }
  1121. }
  1122. static void FreePrimaryReUse(ahi* p)
  1123. {
  1124. int No;
  1125. if (p->BufMode[SCALE] == MEM_PRIMARY || p->BufMode[SCALE+1] == MEM_PRIMARY)
  1126. FreeScale(p,NULL);
  1127. for (No=0;No<p->AllCount;++No)
  1128. if (p->BufMode[No] == MEM_PRIMARY)
  1129. {
  1130. if (No != p->AllCount-1)
  1131. {
  1132. MoveBuf(p,No,p->AllCount-1);
  1133. SwapPtr(p,No,p->AllCount-1,0);
  1134. }
  1135. FreeBuffer(p,p->AllCount-1,NULL);
  1136. p->AllCount--;
  1137. p->TempCount = p->AllCount - p->BufCount;
  1138. if (p->TempCount < 0)
  1139. {
  1140. p->BufCount = p->AllCount;
  1141. p->TempCount = 0;
  1142. }
  1143. }
  1144. ClearPrimary(p);
  1145. }
  1146. static void UpdateLowBitdepth(ahi* p)
  1147. {
  1148. SetLowBitdepth(p,p->p.Show && p->p.FullScreenViewport && !p->BlitMode);
  1149. }
  1150. static void UpdateAlign(ahi* p,int ScaleMode)
  1151. {
  1152. blitfx OvlFX = p->p.FX;
  1153. bool_t FullScreenOverlay;
  1154. rect FullScreen;
  1155. rect OverlayRect;
  1156. PhyToVirt(NULL,&FullScreen,&p->p.Output.Format.Video);
  1157. VirtToPhy(&p->p.Viewport,&p->p.DstAlignedRect,&p->p.Output.Format.Video);
  1158. VirtToPhy(NULL,&p->OverlayRect,&p->p.Input.Format.Video);
  1159. if (OvlFX.Direction & DIR_SWAPXY)
  1160. {
  1161. SwapInt(&p->OverlayRect.Width,&p->OverlayRect.Height);
  1162. SwapInt(&OvlFX.ScaleX,&OvlFX.ScaleY);
  1163. }
  1164. OvlFX.Direction &= ~DIR_SWAPXY;
  1165. if (!ScaleMode ||
  1166. (OvlFX.ScaleX == OvlFX.ScaleY &&
  1167.  OvlFX.ScaleX >= (SCALE_ONE*98)/100 && OvlFX.ScaleX < (SCALE_ONE*103)/100))
  1168. OvlFX.ScaleX = OvlFX.ScaleY = SCALE_ONE;
  1169. p->Stretch = OvlFX.ScaleX != SCALE_ONE || OvlFX.ScaleY != SCALE_ONE;
  1170. p->StretchOnlyInternal = (p->Stretch && ScaleMode==2);
  1171. p->Shrink = OvlFX.ScaleX < SCALE_ONE || OvlFX.ScaleY < SCALE_ONE;
  1172. if ((p->p.FX.Flags & (BLITFX_ARITHSTRETCH50|BLITFX_ARITHSTRETCHALWAYS)) && p->Stretch)
  1173. {
  1174. // avoid bilinear scale overrun (shrink source)
  1175. if (p->OverlayRect.Width>2) 
  1176. {
  1177. OvlFX.ScaleX = Scale(OvlFX.ScaleX,p->OverlayRect.Width,p->OverlayRect.Width-2);
  1178. p->OverlayRect.Width -= 2;
  1179. }
  1180. if (p->OverlayRect.Height>2) 
  1181. {
  1182. OvlFX.ScaleY = Scale(OvlFX.ScaleY,p->OverlayRect.Height,p->OverlayRect.Height-2);
  1183. p->OverlayRect.Height -= 2;
  1184. }
  1185. }
  1186. AnyAlign(&p->p.DstAlignedRect, &p->OverlayRect, &OvlFX, 2, 1, SCALE_ONE>>1,SCALE_ONE*16);
  1187. PhyToVirt(&p->p.DstAlignedRect,&p->p.GUIAlignedRect,&p->p.Output.Format.Video);
  1188. FullScreenOverlay = EqRect(&FullScreen,&p->p.GUIAlignedRect);
  1189. if (FullScreenOverlay != p->FullScreenOverlay)
  1190. {
  1191. p->FullScreenOverlay = FullScreenOverlay;
  1192. p->p.Overlay = !FullScreenOverlay;
  1193. p->MaxCount = MAXIDCTBUF;
  1194. }
  1195. if (p->PrimaryReUse && !p->FullScreenOverlay)
  1196. FreePrimaryReUse(p);
  1197. // if (ScaleMode>0 && p->IDCT && !p->Internal && p->Stretch && OvlFX.ScaleX < (SCALE_ONE*13/10))
  1198. // {
  1199. // external idct buffer with external scale buffer would be very slow
  1200. // not too much scale factor -> fall back to 100% if internal scale buffer not available
  1201. // p->StretchOnlyInternal = 1;
  1202. // }
  1203. if (ScaleMode>0 && p->IDCT && p->Landscape && !p->Stretch && !p->FullScreenOverlay)
  1204. {
  1205. // using idct with external memory and 100% zoom in landscape mode
  1206. // this means external overlay in landscape mode -> try internal scale buffer (100% scale)
  1207. // (except when the overlay covers the full screen)
  1208. p->Stretch = 1;
  1209. p->StretchOnlyInternal = 1; // but don't use external memory (it would make no sense)
  1210. }
  1211. if (p->Stretch)
  1212. {
  1213. p->SoftFX.Flags &= ~(BLITFX_AVOIDTEARING|BLITFX_VMEMROTATED|BLITFX_VMEMUPDOWN);
  1214. }
  1215. else
  1216. {
  1217. // no BLITFX_VMEMROTATED needed because overlay is always in lcd space
  1218. // (just the primary RGB surface is rotated)
  1219. p->SoftFX.Flags |= BLITFX_AVOIDTEARING;
  1220. if (p->p.FX.Direction & DIR_MIRRORUPDOWN)
  1221. p->SoftFX.Flags |= BLITFX_VMEMUPDOWN;
  1222. }
  1223. BlitRelease(p->p.Soft);
  1224. p->p.Soft = BlitCreate(&p->Overlay,&p->p.Input.Format.Video,&p->SoftFX,&p->p.Caps);
  1225. if (p->IDCT)
  1226. p->p.Caps = VC_BRIGHTNESS;
  1227. // because blit might use alignment enlarge the dest area
  1228. OverlayRect = p->OverlayRect;
  1229. OverlayRect.Width = (OverlayRect.Width + (OverlayRect.x & 15) + 15) & ~15;
  1230. OverlayRect.Height = (OverlayRect.Height + (OverlayRect.y & 15) + 15) & ~15;
  1231. OverlayRect.x &= ~15;
  1232. OverlayRect.y &= ~15;
  1233. VirtToPhy(NULL,&p->p.SrcAlignedRect,&p->p.Input.Format.Video);
  1234. BlitAlign(p->p.Soft, &OverlayRect, &p->p.SrcAlignedRect);
  1235. }
  1236. // build ahi overlay param
  1237. static void UpdateAHI(ahi* p)
  1238. {
  1239. if (p->Buf[SCALE])
  1240. {
  1241. p->Param.SrcRect.Left = 0;
  1242. p->Param.SrcRect.Top = 0;
  1243. }
  1244. else
  1245. {
  1246. p->Param.SrcRect.Left = p->OverlayRect.x;
  1247. p->Param.SrcRect.Top = p->OverlayRect.y;
  1248. }
  1249. p->Param.SrcRect.Right = p->Param.SrcRect.Left + p->p.DstAlignedRect.Width;
  1250. p->Param.SrcRect.Bottom = p->Param.SrcRect.Top + p->p.DstAlignedRect.Height;
  1251. p->Param.DstRect.Left = p->p.DstAlignedRect.x;
  1252. p->Param.DstRect.Top = p->p.DstAlignedRect.y;
  1253. p->Param.DstRect.Right = p->p.DstAlignedRect.x + p->p.DstAlignedRect.Width;
  1254. p->Param.DstRect.Bottom = p->p.DstAlignedRect.y + p->p.DstAlignedRect.Height;
  1255. DEBUG_MSG4(DEBUG_VIDEO,T("UpdateAHI %d,%d,%d,%d"),
  1256. p->Param.SrcRect.Left,
  1257. p->Param.SrcRect.Top,
  1258. p->Param.SrcRect.Right,
  1259. p->Param.SrcRect.Bottom);
  1260. p->Param.Mirror = 0;
  1261. if (p->p.FX.Direction & DIR_MIRRORLEFTRIGHT)
  1262. p->Param.Mirror |= MIRROR_LEFTRIGHT;
  1263. if (p->p.FX.Direction & DIR_MIRRORUPDOWN)
  1264. p->Param.Mirror |= MIRROR_UPDOWN;
  1265. if (p->p.ColorKey == CRGB(0,0,0)) {
  1266. // lowbitdepth
  1267. p->Param.ColorMask = 0xF;
  1268. p->Param.ColorKey = 0;
  1269. }
  1270. else
  1271. if (p->p.ColorKey != RGB_NULL) {
  1272. p->Param.ColorMask = 
  1273. p->p.Output.Format.Video.Pixel.BitMask[0] | 
  1274. p->p.Output.Format.Video.Pixel.BitMask[1] |
  1275. p->p.Output.Format.Video.Pixel.BitMask[2];
  1276. p->Param.ColorKey = RGBToFormat(p->p.ColorKey,&p->p.Output.Format.Video.Pixel);
  1277. }
  1278. else
  1279. {
  1280. p->Param.ColorMask = 0;
  1281. p->Param.ColorKey = 0;
  1282. }
  1283. }
  1284. static void UpdateAlloc(ahi* p,int BufCount,int AllCount,int ScaleMode,bool_t* Hidden)
  1285. {
  1286. int No;
  1287. int Mode;
  1288. if (ScaleMode==2)
  1289. Mode = MEM_EXTERNAL; // only accept external
  1290. else
  1291. if (p->IDCT)
  1292. Mode = MEM_ANY_CHG;
  1293. else
  1294. Mode = MEM_ANY_INT; // prefer internal memory transfer
  1295. if (!p->IDCT && p->Landscape && p->AllCount)
  1296. {
  1297. // try to reallocate buffer if it's not in the right memory
  1298. if ((Mode == MEM_EXTERNAL && p->BufMode[0] != MEM_EXTERNAL) ||
  1299. (Mode == MEM_ANY_INT && p->BufMode[0] != MEM_INTERNAL))
  1300. {
  1301. // free surfaces
  1302. FreeScale(p,Hidden);
  1303. for (No=p->AllCount-1;No>=0;--No)
  1304. FreeBuffer(p,No,Hidden);
  1305. p->AllCount = 0;
  1306. }
  1307. }
  1308. if (AllCount != p->AllCount)
  1309. {
  1310. FreeScale(p,Hidden);
  1311. if (AllCount < p->AllCount && p->PrimaryReUse)
  1312. FreePrimaryReUse(p);
  1313. //try to keep same number of internal and external buffers
  1314. if (Mode == MEM_ANY_CHG)
  1315. {
  1316. int Ext = 0;
  1317. int Int = 0;
  1318. for (No=0;No<AllCount;++No)
  1319. {
  1320. if (p->BufMode[No] == MEM_EXTERNAL)
  1321. Ext++;
  1322. if (p->BufMode[No] == MEM_INTERNAL)
  1323. Int++;
  1324. }
  1325. for (No=AllCount;No<p->AllCount;++No)
  1326. {
  1327. int Search = 0;
  1328. if (p->BufMode[No] == MEM_EXTERNAL && Ext<Int)
  1329. Search = MEM_INTERNAL;
  1330. if (p->BufMode[No] == MEM_INTERNAL && Int<Ext)
  1331. Search = MEM_EXTERNAL;
  1332. if (Search)
  1333. {
  1334. int No2;
  1335. for (No2=0;No2<AllCount;++No2)
  1336. if (p->BufMode[No2] == Search)
  1337. {
  1338. MoveBuf(p,No2,No);
  1339. SwapPtr(p,No2,No,0);
  1340. if (Search == MEM_EXTERNAL)
  1341. {
  1342. Ext--;
  1343. Int++;
  1344. }
  1345. else
  1346. {
  1347. Ext++;
  1348. Int--;
  1349. }
  1350. break;
  1351. }
  1352. }
  1353. }
  1354. }
  1355. //free unneccessary buffers
  1356. for (No=p->AllCount-1;No>=AllCount;--No)
  1357. FreeBuffer(p,No,Hidden);
  1358. if (p->AllCount > AllCount)
  1359. p->AllCount = AllCount;
  1360. if (p->IDCT && p->Internal)
  1361. {
  1362. //allocate neccessary buffers in internal memory (if possible)
  1363. for (No=p->AllCount;No<AllCount;++No)
  1364. {
  1365. if (!AllocBuffer(p,No,p->Overlay.Width,p->Overlay.Height,MEM_INTERNAL))
  1366. {
  1367. // failed? need use to external? (temp buffers doesn't count)
  1368. if (p->AllCount < BufCount && p->DevInfo.ExternalMemSize) 
  1369. {
  1370. p->Internal = 0;
  1371. // free all buffers, so they can be realloced as external
  1372. for (No=0;No<p->AllCount;++No)
  1373. FreeBuffer(p,No,Hidden);
  1374. p->AllCount = 0;
  1375. }
  1376. break;
  1377. }
  1378. p->AllCount = No+1;
  1379. }
  1380. }
  1381. //allocate neccessary buffers
  1382. for (No=p->AllCount;No<AllCount;++No)
  1383. {
  1384. if (!AllocBuffer(p,No,p->Overlay.Width,p->Overlay.Height,Mode))
  1385. {
  1386. p->MaxCount = max(1,p->AllCount);
  1387. break;
  1388. }
  1389. p->AllCount = No+1;
  1390. }
  1391. if (p->ShowCurr >= p->AllCount)
  1392. p->ShowCurr = 0;
  1393. if (p->ShowNext >= p->AllCount)
  1394. p->ShowNext = -1;
  1395. if (p->ShowLast >= p->AllCount)
  1396. p->ShowLast = -1;
  1397. p->BufCount = min(p->AllCount,BufCount);
  1398. p->TempCount = p->AllCount - p->BufCount;
  1399. }
  1400. }
  1401. static bool_t UpdateOverlay(ahi* p,int BufCount,int TempCount)
  1402. {
  1403. int ScaleMode;
  1404. bool_t Hidden = 0;
  1405. int AllCount = BufCount + TempCount;
  1406. if (AllCount>p->MaxCount) return 0;
  1407. p->SoftFX.Flags = 0;
  1408. p->SoftFX.Brightness = p->p.FX.Brightness;
  1409. p->SoftFX.Contrast = p->p.FX.Contrast;
  1410. p->SoftFX.Saturation = p->p.FX.Saturation;
  1411. p->SoftFX.Direction = p->p.FX.Direction & DIR_SWAPXY;
  1412. p->SoftFX.RGBAdjust[0] = p->p.FX.RGBAdjust[0];
  1413. p->SoftFX.RGBAdjust[1] = p->p.FX.RGBAdjust[1];
  1414. p->SoftFX.RGBAdjust[2] = p->p.FX.RGBAdjust[2];
  1415. ScaleMode = 1;
  1416. if (!p->IDCT && p->Landscape && (p->p.FX.ScaleX != SCALE_ONE || p->p.FX.ScaleY != SCALE_ONE))
  1417. ScaleMode = 2; // first try normal=external scale=internal
  1418. scaletry:
  1419. // alloc buffers
  1420. UpdateAlloc(p,BufCount,AllCount,ScaleMode,&Hidden);
  1421. // align
  1422. UpdateAlign(p,ScaleMode);
  1423. // allocate/free scale surface
  1424. if (p->AllCount && p->Stretch)
  1425. {
  1426. if (p->ScaleWidth != p->p.DstAlignedRect.Width ||
  1427. p->ScaleHeight != p->p.DstAlignedRect.Height)
  1428. {
  1429. int Mode;
  1430. FreeScale(p,&Hidden);
  1431. if (p->StretchOnlyInternal)
  1432. Mode = MEM_INTERNAL; // only accept internal
  1433. else
  1434. if (p->BufMode[0] == MEM_INTERNAL) // try opposite of normal buffer
  1435. Mode = MEM_ANY_EXT;  
  1436. else
  1437. Mode = MEM_ANY_INT;
  1438. AllocBuffer(p,SCALE,p->p.DstAlignedRect.Width,p->p.DstAlignedRect.Height,Mode);
  1439. if (p->AllowStretchFlip)
  1440. AllocBuffer(p,SCALE+1,p->p.DstAlignedRect.Width,p->p.DstAlignedRect.Height,Mode);
  1441. if (p->Buf[SCALE])
  1442. {
  1443. p->ScaleCurr = 0;
  1444. p->ScaleWidth = p->p.DstAlignedRect.Width;
  1445. p->ScaleHeight = p->p.DstAlignedRect.Height;
  1446. Optimize(p);
  1447. Stretch(p,0,0);
  1448. }
  1449. }
  1450. }
  1451. else
  1452. FreeScale(p,&Hidden);
  1453. if (p->Stretch && !p->Buf[SCALE] && p->AllCount)
  1454. {
  1455. --ScaleMode;
  1456. goto scaletry; // no memory for scale buffer -> try again
  1457. }
  1458. UpdateColorKey(p);
  1459. OverlayUpdateShow(&p->p,1);
  1460. if (p->p.ColorKey != RGB_NULL)
  1461. WinInvalidate(&p->p.Viewport,1);
  1462. UpdateAHI(p);
  1463. UpdateOverlaySurf(p,1);
  1464. if ((p->p.Show || p->PrimaryReUse) && p->BufCount)
  1465. {
  1466. p->AhiDispOverlayState(p->Context,p->p.Show || p->PrimaryReUse,0);
  1467. UpdateLowBitdepth(p);
  1468. }
  1469. if (!TempCount && p->AllCount != AllCount && p->BufCount<2 && !p->ErrorMemory)
  1470. {
  1471. p->ErrorMemory = 1;
  1472. ShowError(AHI_ID,AHI_ID,AHI_OUT_OF_MEMORY);
  1473. }
  1474. return p->AllCount == AllCount;
  1475. }
  1476. static int UpdateBlit(ahi* p)
  1477. {
  1478. blitfx OvlFX = p->p.FX;
  1479. video Overlay;
  1480. int BufWidth,BufHeight;
  1481. p->p.ColorKey = RGB_NULL;
  1482. ReTry:
  1483. p->SoftFX = p->p.FX;
  1484. p->SoftFX.ScaleX = SCALE_ONE; // scale handled by hardware
  1485. p->SoftFX.ScaleY = SCALE_ONE;
  1486. OvlFX.Direction = 0;
  1487. if (p->BlitDownScale)
  1488. {
  1489. p->SoftFX.ScaleX >>= 1;
  1490. p->SoftFX.ScaleY >>= 1;
  1491. OvlFX.ScaleX <<= 1;
  1492. OvlFX.ScaleY <<= 1;
  1493. }
  1494. //align to 100%
  1495. if (OvlFX.ScaleX > SCALE_ONE-(SCALE_ONE/16) && OvlFX.ScaleX < SCALE_ONE+(SCALE_ONE/16) &&
  1496. OvlFX.ScaleY > SCALE_ONE-(SCALE_ONE/16) && OvlFX.ScaleY < SCALE_ONE+(SCALE_ONE/16))
  1497. {
  1498. OvlFX.ScaleX = SCALE_ONE;
  1499. OvlFX.ScaleY = SCALE_ONE;
  1500. }
  1501. if (p->SoftFX.Direction & DIR_SWAPXY)
  1502. SwapInt(&OvlFX.ScaleX,&OvlFX.ScaleY);
  1503. p->Overlay.Direction = CombineDir(p->p.InputDirection,p->p.OrigFX.Direction,p->p.Output.Format.Video.Direction);
  1504. Overlay = p->Overlay;
  1505. Overlay.Width = p->p.Input.Format.Video.Width;
  1506. Overlay.Height = p->p.Input.Format.Video.Height;
  1507. if (p->BlitDownScale)
  1508. {
  1509. Overlay.Width >>= 1;
  1510. Overlay.Height >>= 1;
  1511. }
  1512. if (Overlay.Direction & DIR_SWAPXY)
  1513. SwapInt(&Overlay.Width,&Overlay.Height);
  1514. VirtToPhy(&p->p.Viewport,&p->p.DstAlignedRect,&p->p.Output.Format.Video);
  1515. VirtToPhy(NULL,&p->OverlayRect,&Overlay);
  1516. AnyAlign(&p->p.DstAlignedRect, &p->OverlayRect, &OvlFX, 2, 1, SCALE_ONE>>1,SCALE_ONE*16);
  1517. p->Stretch = (OvlFX.ScaleX != SCALE_ONE || OvlFX.ScaleY != SCALE_ONE) && 
  1518. (p->p.DstAlignedRect.Width != p->OverlayRect.Width && p->p.DstAlignedRect.Height != p->OverlayRect.Height);
  1519. VirtToPhy(NULL,&p->p.SrcAlignedRect,&p->p.Input.Format.Video);
  1520. BlitRelease(p->p.Soft);
  1521. p->p.Soft = BlitCreate(&Overlay,&p->p.Input.Format.Video,&p->SoftFX,&p->p.Caps);
  1522. BlitAlign(p->p.Soft,&p->OverlayRect,&p->p.SrcAlignedRect);
  1523. // pitch has to 16byte aligned, so to be able to rotate width we must align 8 pixels (16bit RGB)
  1524. BufWidth = (p->OverlayRect.Width+7) & ~7;
  1525. BufHeight = (p->OverlayRect.Height+7) & ~7;
  1526. if (!p->Buf[0] || p->Overlay.Width != BufWidth || p->Overlay.Height != BufHeight)
  1527. {
  1528. FreeBuffer(p,0,NULL);
  1529. p->Overlay.Width = BufWidth;
  1530. p->Overlay.Height = BufHeight;
  1531. if (!AllocBuffer(p,0,BufWidth,BufHeight,MEM_ANY_INT))
  1532. {
  1533. if (!p->BlitDownScale)
  1534. {
  1535. p->BlitDownScale = 1;
  1536. goto ReTry;
  1537. }
  1538. return ERR_OUT_OF_MEMORY;
  1539. }
  1540. }
  1541. BlitRelease(p->p.Soft);
  1542. p->p.Soft = BlitCreate(&p->Overlay,&p->p.Input.Format.Video,&p->SoftFX,&p->p.Caps);
  1543. BlitAlign(p->p.Soft,&p->OverlayRect,&p->p.SrcAlignedRect);
  1544. if (!p->Stretch) // no scaling -> adjust dst rectangle with soft yuv blitting alignement
  1545. {
  1546. p->p.DstAlignedRect.x += (p->p.DstAlignedRect.Width - p->OverlayRect.Width) >> 1;
  1547. p->p.DstAlignedRect.y += (p->p.DstAlignedRect.Height - p->OverlayRect.Height) >> 1;
  1548. p->p.DstAlignedRect.Width = p->OverlayRect.Width;
  1549. p->p.DstAlignedRect.Height = p->OverlayRect.Height;
  1550. }
  1551. PhyToVirt(&p->p.DstAlignedRect,&p->p.GUIAlignedRect,&p->p.Output.Format.Video);
  1552. return ERR_NONE;
  1553. }
  1554. static int Reset(ahi* p)
  1555. {
  1556. if (p->Context)
  1557. GetMode(p);
  1558. return ERR_NONE;
  1559. }
  1560. static int Orientation(void* This)
  1561. {
  1562. ahi* p = (ahi*)This;
  1563. if (!p->Context)
  1564. {
  1565. p->p.Output.Format.Video.Direction = -1;
  1566. if (SafeAhiInit(p))
  1567. {
  1568. int No;
  1569. for (No=0;;No++)
  1570. {
  1571. int Result = p->AhiDevEnum(&p->Device,&p->DevInfo,No);
  1572. if (Result == SUCCESS && CheckVersion(p,0))
  1573. {
  1574. if (p->AhiDevOpen(&p->Context,p->Device,DevOpenName,2)==SUCCESS)
  1575. {
  1576. p->AhiDevClientVersion(p->Context,CLIENTVERSION);
  1577. GetMode(p);
  1578. p->AhiDevClose(p->Context);
  1579. }
  1580. p->Context = NULL;
  1581. break;
  1582. }
  1583. if (Result == ENDENUM)
  1584. break;
  1585. }
  1586. SafeAhiTerm(p);
  1587. }
  1588. }
  1589. return p->p.Output.Format.Video.Direction;
  1590. }
  1591. static int Blit(ahi* p, const constplanes Data, const constplanes DataLast);
  1592. static int BlitOverlay(ahi* p, const constplanes Data, const constplanes DataLast);
  1593. static int Update(ahi* p);
  1594. static int UpdateShow(ahi* p);
  1595. /*
  1596. static void CheckMem(const tchar_t* s)
  1597. {
  1598. MEMORYSTATUS Status;
  1599. Status.dwLength = sizeof(Status);
  1600. GlobalMemoryStatus(&Status); 
  1601. DebugMessage(T("%s %d %d"),s,Status.dwAvailPhys,Status.dwAvailVirtual);
  1602. }
  1603. */
  1604. static int Init(ahi* p)
  1605. {
  1606. int No;
  1607. int Result = ERR_DEVICE_ERROR;
  1608. p->Device = NULL;
  1609. p->Context = NULL;
  1610. memset(&p->Param,0,sizeof(p->Param));
  1611. for (No=0;No<MAXIDCTBUF+MAXSCALE;++No)
  1612. {
  1613. p->Buf[No] = NULL;
  1614. p->BufR[No] = NULL;
  1615. p->BufMode[No] = 0;
  1616. p->BufFrameNo[No] = -1;
  1617. }
  1618. if (SafeAhiInit(p))
  1619. {
  1620. p->SoftFX = p->p.FX;
  1621. p->SoftFX.ScaleX = SCALE_ONE;
  1622. p->SoftFX.ScaleY = SCALE_ONE;
  1623. p->SoftFX.Direction = 0;
  1624. memset(&p->Overlay,0,sizeof(video));
  1625. p->Overlay.Width = ALIGN16(p->IDCTInit ? p->IDCTWidth:p->p.Input.Format.Video.Width);
  1626. p->Overlay.Height = ALIGN16(p->IDCTInit ? p->IDCTHeight:p->p.Input.Format.Video.Height);
  1627. p->Overlay.Direction = p->IDCTInit ? 0:p->p.Input.Format.Video.Direction;
  1628. p->Overlay.Aspect = ASPECT_ONE;
  1629. p->BlitDownScale = 0;
  1630. if (p->IDCTInit && !PlanarYUV420(&p->p.Input.Format.Video.Pixel))
  1631. {
  1632. SafeAhiTerm(p);
  1633. return ERR_NOT_SUPPORTED;
  1634. }
  1635. p->ErrorMemory = p->Overlay.Width==0 || p->Overlay.Height==0;
  1636. p->Landscape = 0;
  1637. p->Internal = 1;
  1638. p->ScaleWidth = 0;
  1639. p->ScaleHeight = 0;
  1640. p->ScaleCurr = 0;
  1641. p->ShowCurr = 0;
  1642. p->ShowNext = -1;
  1643. p->ShowNextIdle = 0;
  1644. p->ShowLast = -1;
  1645. p->MaxCount = MAXIDCTBUF;
  1646. p->AllCount = 0;
  1647. p->BufCount = 0;
  1648. p->TempCount = 0;
  1649. p->Zero = 0;
  1650. p->FrameNo = 0;
  1651. p->LowBitdepth = 0;
  1652. p->PrimaryReUse = 0;
  1653. p->Primary = NULL;
  1654. WaitDisable(0);
  1655. for (No=0;;No++)
  1656. {
  1657. int AtiResult = p->AhiDevEnum(&p->Device,&p->DevInfo,No);
  1658. if (AtiResult == SUCCESS)
  1659. {
  1660. if (!CheckVersion(p,p->IDCTInit))
  1661. {
  1662. ShowError(AHI_ID,AHI_ID,AHI_OLDVERSION,p->Version);
  1663. p->Context = NULL;
  1664. Result = ERR_NOT_SUPPORTED; // don't show device error message afterwards
  1665. break;
  1666. }
  1667. AtiResult = FAIL;
  1668. TRY_BEGIN
  1669. AtiResult = p->AhiDevOpen(&p->Context,p->Device,DevOpenName,2);
  1670. TRY_END;
  1671. if (AtiResult != SUCCESS)
  1672. {
  1673. ShowError(AHI_ID,AHI_ID,AHI_OPEN_ERROR);
  1674. p->Context = NULL;
  1675. Result = ERR_NOT_SUPPORTED; // don't show device error message afterwards
  1676. break;
  1677. }
  1678. p->AhiDevClientVersion(p->Context,CLIENTVERSION);
  1679. p->AhiDrawRopSet(p->Context,0xCCCC);
  1680. p->AhiDispOverlayState(p->Context,0,0);
  1681. p->AhiDispSurfGet(p->Context,&p->Primary);
  1682. GetMode(p);
  1683. if (p->DevInfo.ExternalMemSize>0 &&
  1684. PlanarYUV(&p->p.Input.Format.Video.Pixel,NULL,NULL,NULL))
  1685. {
  1686. // because of software rotation we can't use YUV422 
  1687. // even if the source is in this format. so we are using
  1688. // YUV420 with all YUV planar formats
  1689. p->Overlay.Pixel.Flags = PF_YUV420;
  1690. p->p.Overlay = 1;
  1691. p->BlitMode = 0;
  1692. p->OvlFormat = FORMAT_YUV420;
  1693. p->OvlUVX2 = 1;
  1694. p->OvlUVY2 = 1;
  1695. p->OvlPlaneY = PLANE_Y;
  1696. p->OvlPlaneU = PLANE_U;
  1697. p->OvlPlaneV = PLANE_V;
  1698. p->p.Blit = (ovlblit)BlitOverlay;
  1699. p->p.Update = (ovlfunc)Update;
  1700. p->p.UpdateShow = (ovlfunc)UpdateShow;
  1701. }
  1702. else
  1703. {
  1704. if (p->IDCTInit) // this shouldn't happen
  1705. {
  1706. p->AhiDevClose(p->Context);
  1707. p->Context = NULL;
  1708. break;
  1709. }
  1710. DefaultRGB(&p->Overlay.Pixel,16,5,6,5,0,0,0);
  1711. p->p.Overlay = 0;
  1712. p->BlitMode = 1;
  1713. p->OvlFormat = FORMAT_RGB565;
  1714. p->OvlUVX2 = 0;
  1715. p->OvlUVY2 = 0;
  1716. p->OvlPlaneY = 0;
  1717. p->OvlPlaneU = 0;
  1718. p->OvlPlaneV = 0;
  1719. p->p.Blit = (ovlblit)Blit;
  1720. p->p.Update = (ovlfunc)UpdateBlit;
  1721. p->p.UpdateShow = (ovlfunc)NULL;
  1722. }
  1723. // landscape mode doesn't like external memory overlays, 
  1724. // probably reading the external primary framebuffer conflicts with overlay readings
  1725. if ((p->ModeInfo.Rotation!=0 && p->ModeInfo.Rotation!=2) && p->DevInfo.ExternalMemSize>0)
  1726. {
  1727. p->Landscape = 1;
  1728. p->Internal = 0;
  1729. }
  1730. if (p->IDCTInit)
  1731. {
  1732. p->AhiIDCTOpen(p->Context,&p->IDCT,0);
  1733. if (!p->IDCT)
  1734. {
  1735. p->AhiDevClose(p->Context);
  1736. p->Context = NULL;
  1737. ShowError(AHI_ID,AHI_ID,AHI_OPEN_ERROR);
  1738. Result = ERR_NOT_SUPPORTED; // don't show device error message afterwards
  1739. break;
  1740. }
  1741. p->IDCTRounding = 1;
  1742. IDCTUpdateFunc(p);
  1743. p->AhiIDCTPropSet(p->IDCT,PROP_ROUNDING,&p->IDCTRounding,sizeof(int));
  1744. p->AhiIDCTPropSet(p->IDCT,PROP_BIAS,&p->Zero,sizeof(int));
  1745. }
  1746. Result = ERR_NONE;
  1747. break;
  1748. }
  1749. if (AtiResult == ENDENUM)
  1750. break;
  1751. }
  1752. if (!p->Context)
  1753. SafeAhiTerm(p);
  1754. }
  1755. return Result;
  1756. }
  1757. static void Done(ahi* p)
  1758. {
  1759. int No;
  1760. if (p->Context && p->IDCT)
  1761. {
  1762. p->AhiIDCTClose(p->IDCT);
  1763. p->IDCT = NULL;
  1764. }
  1765. FreeScale(p,NULL);
  1766. for (No=MAXIDCTBUF-1;No>=0;--No)
  1767. FreeBuffer(p,No,NULL);
  1768. p->TempCount = p->AllCount = p->BufCount = 0;
  1769. if (p->Context)
  1770. {
  1771. SetLowBitdepth(p,0);
  1772. p->AhiDispOverlayState(p->Context,0,0);
  1773. p->AhiDevClose(p->Context);
  1774. SafeAhiTerm(p);
  1775. p->Context = NULL;
  1776. }
  1777. }
  1778. static int Update(ahi* p)
  1779. {
  1780. UpdateDirection(p,(p->p.FX.Direction ^ p->p.Input.Format.Video.Direction) & DIR_SWAPXY);
  1781. UpdateBrightness(p,p->p.FX.Brightness);
  1782. if (!UpdateOverlay(p,p->IDCT?p->BufCount:1,0)) // temp buffers are freed!
  1783. return ERR_OUT_OF_MEMORY;
  1784. return ERR_NONE;
  1785. }
  1786. static int UpdateShow(ahi* p)
  1787. {
  1788. UpdateLowBitdepth(p);
  1789. p->AhiDispOverlayState(p->Context,p->p.Show,0);
  1790. return ERR_NONE;
  1791. }
  1792. static int Blit(ahi* p, const constplanes Data, const constplanes DataLast)
  1793. {
  1794. ahisurface* Src = p->Buf[0];
  1795. ahisurface* Dst = p->Primary;
  1796. ahirect DstRect;
  1797. ahirect SrcRect;
  1798. int ScaleMode = (p->p.FX.Flags & (BLITFX_ARITHSTRETCH50|BLITFX_ARITHSTRETCHALWAYS)) ? 5:1;
  1799. planes Planes;
  1800. p->AhiDrawIdle(p->Context,0);
  1801. if (Src && Dst && p->AhiSurfLock(p->Context,Src,&Planes[0],0)==SUCCESS)
  1802. {
  1803. BlitImage(p->p.Soft,Planes,Data,DataLast,-1,-1);
  1804. p->AhiSurfUnlock(p->Context,Src,0);
  1805. DstRect.Left = p->p.DstAlignedRect.x;
  1806. DstRect.Top = p->p.DstAlignedRect.y;
  1807. DstRect.Right = p->p.DstAlignedRect.x + p->p.DstAlignedRect.Width;
  1808. DstRect.Bottom = p->p.DstAlignedRect.y + p->p.DstAlignedRect.Height;
  1809. SrcRect.Left = p->OverlayRect.x;
  1810. SrcRect.Top = p->OverlayRect.y;
  1811. SrcRect.Right = p->OverlayRect.x + p->OverlayRect.Width;
  1812. SrcRect.Bottom = p->OverlayRect.y + p->OverlayRect.Height;
  1813. p->AhiDrawSurfSrcSet(p->Context,Src,0);
  1814. p->AhiDrawSurfDstSet(p->Context,Dst,0);
  1815. if (p->Stretch)
  1816. p->AhiDrawStretchBlt(p->Context,&DstRect,&SrcRect,ScaleMode);
  1817. else
  1818. p->AhiDrawBitBlt(p->Context,&DstRect,(ahipoint*)&SrcRect.Left);
  1819. }
  1820. return ERR_NONE;
  1821. }
  1822. static int BlitOverlay(ahi* p, const constplanes Data, const constplanes DataLast)
  1823. {
  1824. planes Planes;
  1825. int Result;
  1826. Result = Lock(p,p->ShowCurr,Planes,0);
  1827. if (Result == ERR_NONE)
  1828. {
  1829. BlitImage(p->p.Soft,Planes,Data,DataLast,-1,-1);
  1830. Unlock(p,p->ShowCurr);
  1831. if (p->Buf[SCALE])
  1832. Stretch(p,1,0);
  1833. }
  1834. return Result;
  1835. }
  1836. //**********************
  1837. //* IDCT               *
  1838. //**********************
  1839. const uint8_t ScanTable[3][64] = {
  1840. {
  1841.  0,  1,  8, 16,  9,  2,  3, 10, 
  1842. 17, 24, 32, 25, 18, 11,  4,  5,
  1843. 12, 19, 26, 33, 40, 48, 41, 34, 
  1844. 27, 20, 13,  6,  7, 14, 21, 28, 
  1845. 35, 42, 49, 56, 57, 50, 43, 36, 
  1846. 29, 22, 15, 23, 30, 37, 44, 51, 
  1847. 58, 59, 52, 45, 38, 31, 39, 46, 
  1848. 53, 60, 61, 54, 47, 55, 62, 63
  1849. },
  1850. {
  1851.    0,  1,  2,  3,  8,  9, 16, 17, 
  1852. 10, 11,  4,  5,  6,  7, 15, 14,
  1853. 13, 12, 19, 18, 24, 25, 32, 33, 
  1854. 26, 27, 20, 21, 22, 23, 28, 29,
  1855. 30, 31, 34, 35, 40, 41, 48, 49, 
  1856. 42, 43, 36, 37, 38, 39, 44, 45,
  1857. 46, 47, 50, 51, 56, 57, 58, 59, 
  1858. 52, 53, 54, 55, 60, 61, 62, 63
  1859. },
  1860. {
  1861.  0,  8, 16, 24,  1,  9,  2, 10, 
  1862. 17, 25, 32, 40, 48, 56, 57, 49,
  1863. 41, 33, 26, 18,  3, 11,  4, 12, 
  1864. 19, 27, 34, 42, 50, 58, 35, 43,
  1865. 51, 59, 20, 28,  5, 13,  6, 14, 
  1866. 21, 29, 36, 44, 52, 60, 37, 45,
  1867. 53, 61, 22, 30,  7, 15, 23, 31, 
  1868. 38, 46, 54, 62, 39, 47, 55, 63
  1869. }};
  1870. const uint8_t ZigZagSwap[64] = {
  1871.  0,  8,  1,  2,  9, 16, 24, 17, 
  1872. 10,  3,  4, 11, 18, 25, 32, 40,
  1873. 33, 26, 19, 12,  5,  6, 13, 20, 
  1874. 27, 34, 41, 48, 56, 49, 42, 35, 
  1875. 28, 21, 14,  7, 15, 22, 29, 36, 
  1876. 43, 50, 57, 58, 51, 44, 37, 30, 
  1877. 23, 31, 38, 45, 52, 59, 60, 53, 
  1878. 46, 39, 47, 54, 61, 62, 55, 63
  1879. };
  1880. const uint8_t ZigZagSwapLength[64] = {
  1881. 1,   3,  3,  6,  6,  6, 10, 10,
  1882. 10, 10, 15, 15, 15, 15, 15, 21, 
  1883. 21, 21, 21, 21, 21, 28, 28, 28,
  1884. 28, 28, 28, 28, 36, 36, 36, 36, 
  1885. 36, 36, 36, 36, 43, 43, 43, 43, 
  1886. 43, 43, 43, 49, 49, 49, 49, 49,
  1887. 49, 54, 54, 54, 54, 54, 58, 58, 
  1888. 58, 58, 61, 61, 61, 63, 63, 64
  1889. };
  1890. #define AHI(p) ((ahi*)((char*)(p)-(int)&(((ahi*)0)->IdctVMT)))
  1891. // input: Block, Length
  1892. #define AHIDCBLOCK(Offset)
  1893. {
  1894. if (Length < 1)
  1895. {
  1896. Block[0] = (idct_block_t)(Offset);
  1897. Length = 1;
  1898. }
  1899. else
  1900. Block[0] = (idct_block_t)(Block[0] + (Offset));
  1901. }
  1902. #define AHIMVINC
  1903. if (AHI(p)->MVBack) AHI(p)->MVBack++;
  1904. if (AHI(p)->MVFwd) AHI(p)->MVFwd++;
  1905. // ADJUST: don't care about MVFwd (only in b-frames which are not accumulated)
  1906. #define AHIMVADJBLOCK
  1907. if (AHI(p)->MVBack && (AHI(p)->MVBack[0] & 0x00020002)==0x00020002)
  1908. AHIDCBLOCK(2);
  1909. // Block, Length -> Dst, Count
  1910. #define AHIPACK(Dst)
  1911. ScanEnd = Scan + Length;
  1912. for (Data=Dst;;++Data)
  1913. {
  1914. int v;
  1915. *(int32_t*)Data = -1;
  1916. Last = Scan;
  1917. while (Scan != ScanEnd && !Block[*Scan]) ++Scan;
  1918. if (Scan == ScanEnd) break;
  1919. v = *Scan;
  1920. Data->skip0 = (char)(Scan++ - Last);
  1921. Data->data0 = Block[v];
  1922. Count++;
  1923. Last = Scan;
  1924. while (Scan != ScanEnd && !Block[*Scan]) ++Scan;
  1925. if (Scan == ScanEnd) break;
  1926. v = *Scan;
  1927. Data->skip1 = (char)(Scan++ - Last);
  1928. Data->data1 = Block[v];
  1929. Last = Scan;
  1930. while (Scan != ScanEnd && !Block[*Scan]) ++Scan;
  1931. if (Scan == ScanEnd) break;
  1932. v = *Scan;
  1933. Data->skip2 = (char)(Scan++ - Last);
  1934. Data->data2 = Block[v];
  1935. Last = Scan;
  1936. while (Scan != ScanEnd && !Block[*Scan]) ++Scan;
  1937. if (Scan == ScanEnd) break;
  1938. v = *Scan;
  1939. Data->skip3 = (char)(Scan++ - Last);
  1940. Data->data3 = Block[v];
  1941. }
  1942. #define AHIPACKNORMAL(ScanType)
  1943. {
  1944. const unsigned char *Scan = ScanTable[ScanType];
  1945. const unsigned char *ScanEnd;
  1946. const unsigned char *Last;
  1947. idct_ati *Data;
  1948. AHIPACK(AHI(p)->Data)
  1949. }
  1950. #define AHIPACKSWAP(Dst,ScanType)
  1951. {
  1952. const unsigned char *Scan;
  1953. const unsigned char *ScanEnd;
  1954. const unsigned char *Last;
  1955. idct_ati *Data;
  1956. if (ScanType == IDCTSCAN_ZIGZAG)
  1957. {
  1958. Scan = ZigZagSwap;
  1959. Length = ZigZagSwapLength[Length-1];
  1960. }
  1961. else
  1962. {
  1963. Scan = ScanTable[ScanType];
  1964. ScanType = 3 - ScanType;
  1965. }
  1966. AHIPACK(Dst)
  1967. }
  1968. #define AHIPACKSWAPZIGZAG(Dst)
  1969. {
  1970. const unsigned char *Scan;
  1971. const unsigned char *ScanEnd;
  1972. const unsigned char *Last;
  1973. idct_ati *Data;
  1974. Scan = ZigZagSwap;
  1975. Length = ZigZagSwapLength[Length-1];
  1976. AHIPACK(Dst)
  1977. }
  1978. #define AHIBLOCKSWAP(ScanType)
  1979. {
  1980. if (SubNo <= 4)
  1981. AHIDCBLOCK(AHI(p)->DCAdd)
  1982. Count = 0;
  1983. if (SubNo == 2)
  1984. {
  1985. if (Length>0 && Length<=64)
  1986. AHIPACKSWAP(AHI(p)->SaveData,ScanType)
  1987. AHI(p)->SaveCount = Count;
  1988. AHI(p)->SaveScanType = ScanType;
  1989. }
  1990. else
  1991. {
  1992. if (Length>0 && Length<=64)
  1993. AHIPACKSWAP(AHI(p)->Data,ScanType)
  1994. AHI(p)->AhiIDCT8x8(AHI(p)->IDCT,AHI(p)->Data,Count,AHI(p)->MacroNo,1 << ScanType); 
  1995. AHIMVINC;
  1996. if (SubNo == 3)
  1997. {
  1998. AHI(p)->AhiIDCT8x8(AHI(p)->IDCT,AHI(p)->SaveData,AHI(p)->SaveCount,AHI(p)->MacroNo,1 << AHI(p)->SaveScanType); 
  1999. AHIMVINC;
  2000. }
  2001. }
  2002. }
  2003. #define AHIMCOMPBLOCKSWAP
  2004. {
  2005. Count = 0;
  2006. if (SubNo == 2)
  2007. {
  2008. if (Length>0 && Length<=64)
  2009. AHIPACKSWAPZIGZAG(AHI(p)->SaveData)
  2010. AHI(p)->SaveCount = Count;
  2011. }
  2012. else
  2013. {
  2014. if (Length>0 && Length<=64)
  2015. AHIPACKSWAPZIGZAG(AHI(p)->Data)
  2016. AHI(p)->AhiIDCTMComp8x8(AHI(p)->IDCT,AHI(p)->Data,Count,AHI(p)->MVBack,AHI(p)->MVFwd,AHI(p)->MacroNo,1 << IDCTSCAN_ZIGZAG);
  2017. AHIMVINC;
  2018. if (SubNo == 3)
  2019. {
  2020. AHI(p)->AhiIDCTMComp8x8(AHI(p)->IDCT,AHI(p)->SaveData,AHI(p)->SaveCount,AHI(p)->MVBack,AHI(p)->MVFwd,AHI(p)->MacroNo,1 << IDCTSCAN_ZIGZAG);
  2021. AHIMVINC;
  2022. }
  2023. }
  2024. }
  2025. #define AHIQPEL(MVPtr)
  2026. MV = *(MVPtr++);
  2027. MV <<= 1;
  2028. MV &= ~0x00010000;
  2029. #define AHIQPELSWAP(MVPtr)
  2030. MV = *(MVPtr++);
  2031. MV = (MV << 17) |
  2032.  ((uint32_t)MV >> 15);
  2033. MV &= ~0x00010001;
  2034. static void IDCTMComp(void* p,const int* MVBack,const int* MVFwd)
  2035. {
  2036. if (MVBack)
  2037. {
  2038. int MV;
  2039. AHI(p)->MVBack = AHI(p)->MVBackTab;
  2040. AHIQPEL(MVBack); AHI(p)->MVBackTab[0] = MV;
  2041. AHIQPEL(MVBack); AHI(p)->MVBackTab[1] = MV;
  2042. AHIQPEL(MVBack); AHI(p)->MVBackTab[2] = MV;
  2043. AHIQPEL(MVBack); AHI(p)->MVBackTab[3] = MV;
  2044. AHIQPEL(MVBack); AHI(p)->MVBackTab[4] = MV;
  2045. AHIQPEL(MVBack); AHI(p)->MVBackTab[5] = MV;
  2046. }
  2047. else
  2048. AHI(p)->MVBack = NULL;
  2049. if (MVFwd)
  2050. {
  2051. int MV;
  2052. AHI(p)->MVFwd = AHI(p)->MVFwdTab;
  2053. AHIQPEL(MVFwd); AHI(p)->MVFwdTab[0] = MV;
  2054. AHIQPEL(MVFwd); AHI(p)->MVFwdTab[1] = MV;
  2055. AHIQPEL(MVFwd); AHI(p)->MVFwdTab[2] = MV;
  2056. AHIQPEL(MVFwd); AHI(p)->MVFwdTab[3] = MV;
  2057. AHIQPEL(MVFwd); AHI(p)->MVFwdTab[4] = MV;
  2058. AHIQPEL(MVFwd); AHI(p)->MVFwdTab[5] = MV;
  2059. }
  2060. else
  2061. AHI(p)->MVFwd = NULL;
  2062. }
  2063. static void IDCTMCompSwap(void* p,const int* MVBack,const int* MVFwd)
  2064. {
  2065. if (MVBack)
  2066. {
  2067. int MV;
  2068. AHI(p)->MVBack = AHI(p)->MVBackTab;
  2069. AHIQPELSWAP(MVBack); AHI(p)->MVBackTab[0] = MV;
  2070. AHIQPELSWAP(MVBack); AHI(p)->MVBackTab[2] = MV;
  2071. AHIQPELSWAP(MVBack); AHI(p)->MVBackTab[1] = MV;
  2072. AHIQPELSWAP(MVBack); AHI(p)->MVBackTab[3] = MV;
  2073. AHIQPELSWAP(MVBack); AHI(p)->MVBackTab[4] = MV;
  2074. AHIQPELSWAP(MVBack); AHI(p)->MVBackTab[5] = MV;
  2075. }
  2076. else
  2077. AHI(p)->MVBack = NULL;
  2078. if (MVFwd)
  2079. {
  2080. int MV;
  2081. AHI(p)->MVFwd = AHI(p)->MVFwdTab;
  2082. AHIQPELSWAP(MVFwd); AHI(p)->MVFwdTab[0] = MV;
  2083. AHIQPELSWAP(MVFwd); AHI(p)->MVFwdTab[2] = MV;
  2084. AHIQPELSWAP(MVFwd); AHI(p)->MVFwdTab[1] = MV;
  2085. AHIQPELSWAP(MVFwd); AHI(p)->MVFwdTab[3] = MV;
  2086. AHIQPELSWAP(MVFwd); AHI(p)->MVFwdTab[4] = MV;
  2087. AHIQPELSWAP(MVFwd); AHI(p)->MVFwdTab[5] = MV;
  2088. }
  2089. else
  2090. AHI(p)->MVFwd = NULL;
  2091. }
  2092. static void IDCTProcess(void* p,int x,int y)
  2093. {
  2094. AHI(p)->MacroSubNo = 0;
  2095. AHI(p)->MacroNo = x + y*AHI(p)->MacroWidth;
  2096. }
  2097. static void IDCTProcessSwap(void* p,int x,int y)
  2098. {
  2099. AHI(p)->MacroSubNo = 0;
  2100. AHI(p)->MacroNo = y + x*AHI(p)->MacroWidth;
  2101. }
  2102. static void IDCTIntra(void* p,idct_block_t *Block,int Length,int ScanType)
  2103. {
  2104. int Count = 0;
  2105. int SubNo = ++AHI(p)->MacroSubNo;
  2106. if (SubNo <= 4)
  2107. AHIDCBLOCK(AHI(p)->DCAdd)
  2108. if (Length>0 && Length<=64)
  2109. AHIPACKNORMAL(ScanType)
  2110. AHI(p)->AhiIDCT8x8(AHI(p)->IDCT,AHI(p)->Data,Count,AHI(p)->MacroNo,1 << ScanType);
  2111. }
  2112. static void IDCTInter(void* p,idct_block_t *Block,int Length)
  2113. {
  2114. int Count = 0;
  2115. if (Length>0 && Length<=64)
  2116. AHIPACKNORMAL(IDCTSCAN_ZIGZAG)
  2117. AHI(p)->AhiIDCTMComp8x8(AHI(p)->IDCT,AHI(p)->Data,Count,AHI(p)->MVBack,AHI(p)->MVFwd,AHI(p)->MacroNo,1 << IDCTSCAN_ZIGZAG);
  2118. AHIMVINC
  2119. }
  2120. static void IDCTInterAdj(void* p,idct_block_t *Block,int Length)
  2121. {
  2122. int Count = 0;
  2123. AHIMVADJBLOCK
  2124. if (Length>0 && Length<=64)
  2125. AHIPACKNORMAL(IDCTSCAN_ZIGZAG)
  2126. AHI(p)->AhiIDCTMComp8x8(AHI(p)->IDCT,AHI(p)->Data,Count,AHI(p)->MVBack,AHI(p)->MVFwd,AHI(p)->MacroNo,1 << IDCTSCAN_ZIGZAG);
  2127. AHIMVINC
  2128. }
  2129. static void IDCTIntraSwap(void* p,idct_block_t *Block,int Length,int ScanType)
  2130. {
  2131. int Count;
  2132. int SubNo = ++AHI(p)->MacroSubNo;
  2133. AHIBLOCKSWAP(ScanType);
  2134. }
  2135. static void IDCTInterSwap(void* p,idct_block_t *Block,int Length)
  2136. {
  2137. int Count;
  2138. int SubNo = ++AHI(p)->MacroSubNo;
  2139. AHIMCOMPBLOCKSWAP;
  2140. }
  2141. static void IDCTInterSwapAdj(void* p,idct_block_t *Block,int Length)
  2142. {
  2143. int Count;
  2144. int SubNo = ++AHI(p)->MacroSubNo;
  2145. AHIMVADJBLOCK
  2146. AHIMCOMPBLOCKSWAP
  2147. }
  2148. static void IDCTCopy16x16(void* p,int x,int y,int Forward)
  2149. {
  2150. int MacroNo = x + y*AHI(p)->MacroWidth;
  2151. int* Back = NULL;
  2152. int* Fwd = NULL;
  2153. if (Forward)
  2154. Fwd = &AHI(p)->Zero;
  2155. else
  2156. Back = &AHI(p)->Zero;
  2157. AHI(p)->AhiIDCTMComp8x8(AHI(p)->IDCT,NULL,0,Back,Fwd,MacroNo,0);
  2158. AHI(p)->AhiIDCTMComp8x8(AHI(p)->IDCT,NULL,0,Back,Fwd,MacroNo,0);
  2159. AHI(p)->AhiIDCTMComp8x8(AHI(p)->IDCT,NULL,0,Back,Fwd,MacroNo,0);
  2160. AHI(p)->AhiIDCTMComp8x8(AHI(p)->IDCT,NULL,0,Back,Fwd,MacroNo,0);
  2161. AHI(p)->AhiIDCTMComp8x8(AHI(p)->IDCT,NULL,0,Back,Fwd,MacroNo,0);
  2162. AHI(p)->AhiIDCTMComp8x8(AHI(p)->IDCT,NULL,0,Back,Fwd,MacroNo,0);
  2163. }
  2164. static void IDCTCopy16x16Swap(void* p,int x,int y,int Forward)
  2165. {
  2166. int MacroNo = y + x*AHI(p)->MacroWidth;
  2167. int* Back = NULL;
  2168. int* Fwd = NULL;
  2169. if (Forward)
  2170. Fwd = &AHI(p)->Zero;
  2171. else
  2172. Back = &AHI(p)->Zero;
  2173. AHI(p)->AhiIDCTMComp8x8(AHI(p)->IDCT,NULL,0,Back,Fwd,MacroNo,0);
  2174. AHI(p)->AhiIDCTMComp8x8(AHI(p)->IDCT,NULL,0,Back,Fwd,MacroNo,0);
  2175. AHI(p)->AhiIDCTMComp8x8(AHI(p)->IDCT,NULL,0,Back,Fwd,MacroNo,0);
  2176. AHI(p)->AhiIDCTMComp8x8(AHI(p)->IDCT,NULL,0,Back,Fwd,MacroNo,0);
  2177. AHI(p)->AhiIDCTMComp8x8(AHI(p)->IDCT,NULL,0,Back,Fwd,MacroNo,0);
  2178. AHI(p)->AhiIDCTMComp8x8(AHI(p)->IDCT,NULL,0,Back,Fwd,MacroNo,0);
  2179. }
  2180. static int IDCTUpdateFunc(ahi* p)
  2181. {
  2182. if (p->Overlay.Direction)
  2183. {
  2184. p->IdctVMT.Copy16x16 = IDCTCopy16x16Swap;
  2185. p->IdctVMT.Process = IDCTProcessSwap;
  2186. p->IdctVMT.MComp8x8 = IDCTMCompSwap;
  2187. p->IdctVMT.MComp16x16 = IDCTMCompSwap;
  2188. p->IdctVMT.Intra8x8 = (idctintra)IDCTIntraSwap;
  2189. p->IdctVMT.Inter8x8 = (idctinter)(p->IDCTBug ? IDCTInterSwapAdj : IDCTInterSwap);
  2190. }
  2191. else 
  2192. {
  2193. p->IdctVMT.Copy16x16 = IDCTCopy16x16;
  2194. p->IdctVMT.Process = IDCTProcess;
  2195. p->IdctVMT.MComp8x8 = IDCTMComp;
  2196. p->IdctVMT.MComp16x16 = IDCTMComp;
  2197. p->IdctVMT.Intra8x8 = (idctintra)IDCTIntra;
  2198. p->IdctVMT.Inter8x8 = (idctinter)(p->IDCTBug ? IDCTInterAdj : IDCTInter);
  2199. }
  2200. return ERR_NONE;
  2201. }
  2202. static int IDCTOutputFormat(ahi* p, const void* Data, int Size)
  2203. {
  2204. packetformat Format;
  2205. int Result;
  2206. p->IDCTInit = 1;
  2207. if (Size == sizeof(video))
  2208. {
  2209. memset(&Format,0,sizeof(Format));
  2210. Format.Type = PACKET_VIDEO;
  2211. Format.Format.Video = *(const video*)Data;
  2212. Data = &Format;
  2213. Size = sizeof(packetformat);
  2214. //IDCTWidth or IDCTHeight could have changes so invalidate current input format
  2215. memset(&p->p.Input.Format.Video,0,sizeof(video));
  2216. }
  2217. Result = p->p.Node.Set((node*)p,OUT_INPUT|PIN_FORMAT,Data,Size);
  2218. if (Size && Result != ERR_NONE)
  2219. p->p.Node.Set((node*)p,OUT_INPUT|PIN_FORMAT,NULL,0);
  2220. p->IDCTInit = 0;
  2221. return Result;
  2222. }
  2223. static int IDCTSend(void* p,tick_t RefTime,const flowstate* State);
  2224. static int IDCTSet(void* p, int No, const void* Data, int Size)
  2225. {
  2226. flowstate State;
  2227. int Result = ERR_INVALID_PARAM;
  2228. switch (No)
  2229. {
  2230. case IDCT_MODE: if (*(int*)Data==0) Result = ERR_NONE; break;
  2231. case IDCT_BUFFERWIDTH: SETVALUE(AHI(p)->IDCTWidth,int,ERR_NONE); break;
  2232. case IDCT_BUFFERHEIGHT: SETVALUE(AHI(p)->IDCTHeight,int,ERR_NONE); break;
  2233. case IDCT_FORMAT:
  2234. assert(Size == sizeof(video) || !Data);
  2235. Result = IDCTOutputFormat(AHI(p),Data,Size);
  2236. break;
  2237. case IDCT_BACKUP: 
  2238. if (Size == sizeof(idctbackup))
  2239. Result = IDCTRestore(p,(idctbackup*)Data);
  2240. break;
  2241. case IDCT_ROUNDING:
  2242. if (Size == sizeof(bool_t) && AHI(p)->IDCT)
  2243. {
  2244. AHI(p)->IDCTRounding = !*(const int*)Data;
  2245. AHI(p)->AhiIDCTPropSet(AHI(p)->IDCT,PROP_ROUNDING,&AHI(p)->IDCTRounding,sizeof(int));
  2246. Result = ERR_NONE;
  2247. }
  2248. break;
  2249. case IDCT_SHOW: 
  2250. SETVALUE(AHI(p)->ShowNext,int,ERR_NONE); 
  2251. if (AHI(p)->ShowNext >= AHI(p)->BufCount) AHI(p)->ShowNext = -1;
  2252. break;
  2253. case IDCT_BUFFERCOUNT:
  2254. assert(Size == sizeof(int));
  2255. Result = ERR_NONE;
  2256. if (AHI(p)->BufCount != *(const int*)Data &&
  2257. !UpdateOverlay(AHI(p),*(const int*)Data,0))
  2258. Result = ERR_OUT_OF_MEMORY;
  2259. break;
  2260. case FLOW_FLUSH:
  2261. AHI(p)->ShowNext = -1;
  2262. Result = ERR_NONE;
  2263. break;
  2264. case FLOW_RESEND:
  2265. State.CurrTime = TIME_RESEND;
  2266. State.DropLevel = 0;
  2267. Result = IDCTSend(p,-1,&State);
  2268. break;
  2269. }
  2270. if (No>=IDCT_FRAMENO && No<IDCT_FRAMENO+AHI(p)->AllCount)
  2271. SETVALUE(AHI(p)->BufFrameNo[No-IDCT_FRAMENO],int,ERR_NONE);
  2272. return Result;
  2273. }
  2274. static int IDCTEnumAHI(void* p, int* No, datadef* Param)
  2275. {
  2276. int Result = IDCTEnum(p,No,Param);
  2277. if (Result == ERR_NONE && Param->No == IDCT_OUTPUT)
  2278. Param->Flags |= DF_RDONLY;
  2279. return Result;
  2280. }
  2281. static int IDCTGet(void* p, int No, void* Data, int Size)
  2282. {
  2283. int Result = ERR_INVALID_PARAM;
  2284. switch (No)
  2285. {
  2286. case FLOW_BUFFERED: GETVALUE(1,bool_t); break;
  2287. case NODE_PARTOF: GETVALUE(AHI(p),ahi*); break;
  2288. case IDCT_OUTPUT|PIN_FORMAT: GETVALUECOND(AHI(p)->p.Input,packetformat,AHI(p)->IDCT); break;
  2289. case IDCT_OUTPUT|PIN_PROCESS: GETVALUE(NULL,packetprocess); break;
  2290. case IDCT_OUTPUT: GETVALUE(AHI(p)->IDCTOutput,pin); break;
  2291. case IDCT_FORMAT: 
  2292. assert(Size==sizeof(video));
  2293. if (AHI(p)->IDCT)
  2294. {
  2295. video* i = (video*)Data;
  2296. *i = AHI(p)->p.Input.Format.Video;
  2297. if ((AHI(p)->Overlay.Direction ^ i->Direction) & DIR_SWAPXY)
  2298. {
  2299. i->Direction ^= DIR_SWAPXY;
  2300. SwapInt(&i->Width,&i->Height);
  2301. }
  2302. Result = ERR_NONE;
  2303. }
  2304. break;
  2305. case IDCT_MODE: GETVALUE(0,int); break;
  2306. case IDCT_ROUNDING: GETVALUE(!AHI(p)->IDCTRounding,bool_t); break;
  2307. case IDCT_BUFFERCOUNT: GETVALUE(AHI(p)->IDCT?AHI(p)->BufCount:0,int); break;
  2308. case IDCT_BUFFERWIDTH: GETVALUE(AHI(p)->IDCTWidth,int); break;
  2309. case IDCT_BUFFERHEIGHT: GETVALUE(AHI(p)->IDCTHeight,int); break;
  2310. case IDCT_SHOW: GETVALUE(AHI(p)->ShowNext,int); break;
  2311. case IDCT_BACKUP: 
  2312. assert(Size == sizeof(idctbackup));
  2313. Result = IDCTBackup(p,(idctbackup*)Data);
  2314. break;
  2315. }
  2316. if (No>=IDCT_FRAMENO && No<IDCT_FRAMENO+AHI(p)->AllCount)
  2317. GETVALUE(AHI(p)->BufFrameNo[No-IDCT_FRAMENO],int);
  2318. return Result;
  2319. }
  2320. static int IDCTLock(void* p,int No,planes Planes,int* Brightness,video* Format)
  2321. {
  2322. if (Brightness)
  2323. *Brightness = AHI(p)->p.FX.Brightness;
  2324. if (Format)
  2325. *Format = AHI(p)->Overlay;
  2326. return Lock(AHI(p),No,Planes,0);
  2327. }
  2328. static void IDCTUnlock(void* p,int No)
  2329. {
  2330. Unlock(AHI(p),No);
  2331. }
  2332. static int IDCTFrameStart(void* p,int FrameNo,int *OldFrameNo,int DstNo,int BackNo,int FwdNo,int ShowNo,bool_t Drop)
  2333. {
  2334. ahisurface* Back;
  2335. ahisurface* Fwd;
  2336. ahisurface* Dst;
  2337. if (!AHI(p)->IDCT)
  2338. return ERR_DEVICE_ERROR;
  2339. // we will try to avoid overwrite currently displayed buffers:
  2340. //   ShowCurr currently displayed
  2341. //   ShowLast may be still on screen (because flip occurs only during vblank)
  2342. DEBUG_MSG6(DEBUG_VIDEO,T("ATI FrameStart %d,%d,%d (%d,%d,%d)"),DstNo,BackNo,FwdNo,ShowNo,AHI(p)->ShowCurr,AHI(p)->ShowLast);
  2343. if (!AHI(p)->Buf[SCALE] && (AHI(p)->ShowLast == DstNo || AHI(p)->ShowCurr == DstNo))
  2344. {
  2345. // try to find a free buffer
  2346. int SwapNo;
  2347. for (SwapNo=0;SwapNo<AHI(p)->AllCount;++SwapNo)
  2348. if (SwapNo != AHI(p)->ShowLast && SwapNo != AHI(p)->ShowCurr && 
  2349. SwapNo != BackNo && SwapNo != FwdNo && SwapNo != ShowNo)
  2350. break; 
  2351. if (SwapNo < AHI(p)->AllCount || UpdateOverlay(AHI(p),AHI(p)->BufCount,AHI(p)->TempCount+1))
  2352. {
  2353. // use free buffer
  2354. SwapPtr(AHI(p),SwapNo,DstNo,1);
  2355. DEBUG_MSG2(DEBUG_VIDEO,T("ATI Swap %d,%d"),DstNo,SwapNo);
  2356. }
  2357. else
  2358. if (AHI(p)->ShowLast >= 0 && AHI(p)->ShowCurr != AHI(p)->ShowLast &&
  2359. AHI(p)->ShowLast != BackNo && AHI(p)->ShowLast != FwdNo) 
  2360. {
  2361. // no free buffer found and couldn't allocate new temp buffer
  2362. // so we wait for vblank and use ShowLast
  2363. if (!Drop)
  2364. AHI(p)->AhiDispWaitVBlank(AHI(p)->Context,0);
  2365. DEBUG_MSG2(DEBUG_VIDEO,T("ATI VBlank %d,%d"),DstNo,AHI(p)->ShowLast);
  2366. if (DstNo != AHI(p)->ShowLast)
  2367. SwapPtr(AHI(p),AHI(p)->ShowLast,DstNo,1);
  2368. }
  2369. }
  2370. AHI(p)->ShowNext = ShowNo;
  2371. AHI(p)->ShowNextIdle = ShowNo == DstNo;
  2372. if (OldFrameNo)
  2373. *OldFrameNo = AHI(p)->BufFrameNo[DstNo];
  2374. AHI(p)->BufFrameNo[DstNo] = FrameNo;
  2375. Back = NULL;
  2376. Fwd = NULL;
  2377. Dst = AHI(p)->Buf[DstNo];
  2378. if (BackNo >= 0)
  2379. Back = AHI(p)->Buf[BackNo];
  2380. if (FwdNo >= 0)
  2381. Fwd = AHI(p)->Buf[FwdNo];
  2382. AHI(p)->MacroWidth = AHI(p)->Overlay.Width >> 4;
  2383. AHI(p)->AhiIDCTFrameStart(AHI(p)->IDCT,Dst,Back,Fwd,AHI(p)->FrameNo,0);
  2384. return ERR_NONE;
  2385. }
  2386. static void IDCTFrameEnd(void* p)
  2387. {
  2388. AHI(p)->AhiIDCTFrameEnd(AHI(p)->IDCT,AHI(p)->FrameNo++);
  2389. }
  2390. static void IDCTDrop(void* p)
  2391. {
  2392. int No;
  2393. for (No=0;No<AHI(p)->AllCount;++No)
  2394. AHI(p)->BufFrameNo[No] = -1;
  2395. }
  2396. static int IDCTNull(void* p,const flowstate* State,bool_t Empty)
  2397. {
  2398. if (Empty)
  2399. ++AHI(p)->p.Total;
  2400. if (!State || State->DropLevel)
  2401. ++AHI(p)->p.Dropped;
  2402. return ERR_NONE;
  2403. }
  2404. static int IDCTSend(void* p,tick_t RefTime,const flowstate* State)
  2405. {
  2406. bool_t Flip = 0;
  2407. if (AHI(p)->ShowNext < 0)
  2408. return ERR_NEED_MORE_DATA;
  2409. if (State->CurrTime >= 0)
  2410. {
  2411. tick_t Diff;
  2412. if (!AHI(p)->p.Play && State->CurrTime == AHI(p)->p.LastTime)
  2413. return ERR_BUFFER_FULL;
  2414. Diff = RefTime - (State->CurrTime + SHOWAHEAD);
  2415. if (Diff >= 0)
  2416. {
  2417. if (!AHI(p)->Buf[SCALE+1] || Diff>(TICKSPERSEC*8/1000))
  2418. return ERR_BUFFER_FULL;
  2419. // we have time for scale flipping
  2420. Flip = 1;
  2421. }
  2422. AHI(p)->p.LastTime = State->CurrTime;
  2423. }
  2424. else
  2425. AHI(p)->p.LastTime = RefTime;
  2426. if (State->CurrTime != TIME_RESEND)
  2427. ++AHI(p)->p.Total;
  2428. AHI(p)->ShowLast = AHI(p)->ShowCurr;
  2429. AHI(p)->ShowCurr = AHI(p)->ShowNext;
  2430. if (AHI(p)->Buf[SCALE])
  2431. {
  2432. if (State->DropLevel)
  2433. ++AHI(p)->p.Dropped;
  2434. else
  2435. Stretch(AHI(p),1,Flip);
  2436. }
  2437. else
  2438. UpdateOverlaySurf(AHI(p),AHI(p)->ShowNextIdle);
  2439. return ERR_NONE;
  2440. }
  2441. static int Create(ahi* p);
  2442. static void Delete(ahi* p);
  2443. static const nodedef AHI =
  2444. {
  2445. sizeof(ahi)|CF_GLOBAL|CF_SETTINGS,
  2446. AHI_ID,
  2447. OVERLAY_CLASS,
  2448. PRI_DEFAULT+200,
  2449. (nodecreate)Create,
  2450. (nodedelete)Delete,
  2451. };
  2452. static const nodedef AHI_IDCT =
  2453. {
  2454. CF_ABSTRACT,
  2455. AHI_IDCT_ID,
  2456. IDCT_CLASS,
  2457. PRI_DEFAULT+50,
  2458. };
  2459. static void FindUnmap(ahi* p)
  2460. {
  2461. uint8_t* Min;
  2462. uint8_t* Max;
  2463. uint32_t* q;
  2464. bool_t Found = 0;
  2465. int i;
  2466. CodeFindPages((void*)(int)p->AhiInit,&Min,&Max,NULL);
  2467. if (Min && Max>Min)
  2468. {
  2469. Max -= 8*4;
  2470. for (q=(uint32_t*)Min;q<(uint32_t*)Max;++q)
  2471. if (q[0] == 0xE3A06A06) //mov r6,#0x6000
  2472. {
  2473. for (i=1;i<8;++i)
  2474. if (q[i] == 0xE3866002) // or r6,r6,#2
  2475. {
  2476. for (i=-1;i>-16;--i)
  2477. if ((q[i] & 0xFFFF0000)==0xE92D0000)
  2478. {
  2479. if (Found)
  2480. p->AhiUnmap = NULL;
  2481. else
  2482. {
  2483. p->AhiUnmap = (int(*)())(q+i);
  2484. Found = 1;
  2485. }
  2486. break;
  2487. }
  2488. break;
  2489. }
  2490. }
  2491. }
  2492. }
  2493. static int Create(ahi* p) 
  2494. p->Context = NULL;
  2495. p->p.Node.Enum = (nodeenum)Enum;
  2496. p->p.Node.Get = (nodeget)Get;
  2497. p->p.Node.Set = (nodeset)Set;
  2498. p->p.Init = (ovlfunc)Init;
  2499. p->p.Done = (ovldone)Done;
  2500. p->p.Reset = (ovlfunc)Reset;
  2501. p->IdctVMT.Class = AHI_IDCT_ID;
  2502. p->IdctVMT.Enum = IDCTEnumAHI;
  2503. p->IdctVMT.Get = IDCTGet;
  2504. p->IdctVMT.Set = IDCTSet;
  2505. p->IdctVMT.Send = IDCTSend;
  2506. p->IdctVMT.Null = IDCTNull;
  2507. p->IdctVMT.Drop = IDCTDrop;
  2508. p->IdctVMT.Lock = IDCTLock;
  2509. p->IdctVMT.Unlock = IDCTUnlock;
  2510. p->IdctVMT.FrameStart = IDCTFrameStart;
  2511. p->IdctVMT.FrameEnd = IDCTFrameEnd;
  2512. p->IDCTOutput.Node = (node*)p;
  2513. p->IDCTOutput.No = OUT_INPUT;
  2514. p->IDCTBug = 0;
  2515. p->IDCTInit = 0;
  2516. p->AllowStretchFlip = 1;
  2517. p->AllowPrimaryReUse = 1;
  2518. p->AllowLowBitdepth = 1;
  2519. p->p.Module = LoadLibrary(T("ACE_DDI.DLL"));
  2520. GetProc(&p->p.Module,&p->AhiInit,T("AhiInit"),0);
  2521. GetProc(&p->p.Module,&p->AhiTerm,T("AhiTerm"),0);
  2522. GetProc(&p->p.Module,&p->AhiDevEnum,T("AhiDevEnum"),0);
  2523. GetProc(&p->p.Module,&p->AhiDevOpen,T("AhiDevOpen"),0);
  2524. GetProc(&p->p.Module,&p->AhiDevClose,T("AhiDevClose"),0);
  2525. GetProc(&p->p.Module,&p->AhiDevClientVersion,T("AhiDevClientVersion"),0);
  2526. GetProc(&p->p.Module,&p->AhiDispModeGet,T("AhiDispModeGet"),0);
  2527. GetProc(&p->p.Module,&p->AhiDispModeEnum,T("AhiDispModeEnum"),0);
  2528. GetProc(&p->p.Module,&p->AhiDispSurfGet,T("AhiDispSurfGet"),0);
  2529. GetProc(&p->p.Module,&p->AhiSurfGetLargestFreeBlockSize,T("AhiSurfGetLargestFreeBlockSize"),1);
  2530. GetProc(&p->p.Module,&p->AhiSurfAlloc,T("AhiSurfAlloc"),0);
  2531. GetProc(&p->p.Module,&p->AhiSurfReuse,T("AhiSurfReuse"),0);
  2532. GetProc(&p->p.Module,&p->AhiSurfFree,T("AhiSurfFree"),0);
  2533. GetProc(&p->p.Module,&p->AhiSurfLock,T("AhiSurfLock"),0);
  2534. GetProc(&p->p.Module,&p->AhiSurfUnlock,T("AhiSurfUnlock"),0);
  2535. GetProc(&p->p.Module,&p->AhiSurfInfo,T("AhiSurfInfo"),0);
  2536. GetProc(&p->p.Module,&p->AhiSurfPlaneInfo,T("AhiSurfPlaneInfo"),0);
  2537. GetProc(&p->p.Module,&p->AhiDrawRopSet,T("AhiDrawRopSet"),0);
  2538. GetProc(&p->p.Module,&p->AhiDrawSurfSrcSet,T("AhiDrawSurfSrcSet"),0);
  2539. GetProc(&p->p.Module,&p->AhiDrawSurfDstSet,T("AhiDrawSurfDstSet"),0);
  2540. GetProc(&p->p.Module,&p->AhiDrawIdle,T("AhiDrawIdle"),0);
  2541. GetProc(&p->p.Module,&p->AhiDispWaitVBlank,T("AhiDispWaitVBlank"),0);
  2542. GetProc(&p->p.Module,&p->AhiDrawBitBlt,T("AhiDrawBitBlt"),0);
  2543. GetProc(&p->p.Module,&p->AhiDrawStretchBlt,T("AhiDrawStretchBlt"),0);
  2544. GetProc(&p->p.Module,&p->AhiDrawRotateBlt,T("AhiDrawRotateBlt"),0);
  2545. GetProc(&p->p.Module,&p->AhiDispOverlayCaps,T("AhiDispOverlayCaps"),0);
  2546. GetProc(&p->p.Module,&p->AhiDispOverlayState,T("AhiDispOverlayState"),0);
  2547. GetProc(&p->p.Module,&p->AhiDispOverlayPos,T("AhiDispOverlayPos"),0);
  2548. GetProc(&p->p.Module,&p->AhiDispOverlaySurf,T("AhiDispOverlaySurf"),0);
  2549. GetProc(&p->p.Module,&p->AhiIDCTOpen,T("AhiIDCTOpen"),0);
  2550. GetProc(&p->p.Module,&p->AhiIDCTClose,T("AhiIDCTClose"),0);
  2551. GetProc(&p->p.Module,&p->AhiIDCTPropGet,T("AhiIDCTPropGet"),0);
  2552. GetProc(&p->p.Module,&p->AhiIDCTPropSet,T("AhiIDCTPropSet"),0);
  2553. GetProc(&p->p.Module,&p->AhiIDCTFrameStart,T("AhiIDCTFrameStart"),0);
  2554. GetProc(&p->p.Module,&p->AhiIDCTFrameEnd,T("AhiIDCTFrameEnd"),0);
  2555. GetProc(&p->p.Module,&p->AhiIDCTMComp8x8,T("AhiIDCTMComp8x8"),0);
  2556. GetProc(&p->p.Module,&p->AhiIDCTMComp,T("AhiIDCTMComp"),0);
  2557. GetProc(&p->p.Module,&p->AhiIDCT8x8,T("AhiIDCT8x8"),0);
  2558. if (!p->p.Module)
  2559. return ERR_NOT_SUPPORTED;
  2560. FindUnmap(p);
  2561. memset(&p->DevInfo,0,sizeof(p->DevInfo));
  2562. if (SafeAhiInit(p))
  2563. {
  2564. int No;
  2565. for (No=0;No<16;No++)
  2566. {
  2567. int Result = p->AhiDevEnum(&p->Device,&p->DevInfo,No);
  2568. if (Result == SUCCESS)
  2569. {
  2570. if (p->DevInfo.ChipId == 0x57441002)
  2571. p->IDCTBug = 1;
  2572. if (p->DevInfo.ExternalMemSize>0 && CheckVersion(p,1))
  2573. {
  2574. p->p.AccelIDCT = &p->IdctVMT;
  2575. NodeRegisterClass(&AHI_IDCT);
  2576. }
  2577. break;
  2578. }
  2579. if (Result == ENDENUM)
  2580. break;
  2581. }
  2582. p->TmpInited = 1; // assume NoRelease, later loading settings will call AhiTerm if needed
  2583. //SafeAhiTerm(p);
  2584. }
  2585. p->p.DoPowerOff = 1;
  2586. Context()->HwOrientation = Orientation;
  2587. Context()->HwOrientationContext = p;
  2588. return ERR_NONE;
  2589. }
  2590. static void Delete(ahi* p)
  2591. {
  2592. Context()->HwOrientation = NULL;
  2593. Context()->HwOrientationContext = NULL;
  2594. if (p->TmpInited)
  2595. {
  2596. p->TmpInited = 0;
  2597. p->AhiTerm();
  2598. // no unmap... maybe unmap casing problem too...
  2599. }
  2600. }
  2601. void ATI3200_Init()
  2602. {
  2603. NodeRegisterClass(&AHI);
  2604. }
  2605. void ATI3200_Done()
  2606. {
  2607. NodeUnRegisterClass(AHI_ID);
  2608. NodeUnRegisterClass(AHI_IDCT_ID);
  2609. }
  2610. #else
  2611. void ATI3200_Init() {}
  2612. void ATI3200_Done() {}
  2613. #endif