overlay_xscale.c
Upload User: wstnjxml
Upload Date: 2014-04-03
Package Size: 7248k
Code Size: 24k
Category:

Windows CE

Development Platform:

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: overlay_xscale.c 615 2006-01-26 16:57:51Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23. #include "../common.h"
  24. #define X50V // included in official version
  25. #if defined(ARM)
  26. #define WIN32_LEAN_AND_MEAN
  27. #ifndef STRICT
  28. #define STRICT
  29. #endif
  30. #include <windows.h>
  31. #define MAXDESC 1024
  32. #define MAXORIGBLOCK 8
  33. #define MAXCOUNT 3
  34. #define MAXDESCBLOCK 4
  35. typedef struct xscaledesc
  36. {
  37. uint32_t Next;
  38. uint32_t Base;
  39. uint32_t Id;
  40. uint32_t Cmd;
  41. } xscaledesc;
  42. typedef struct xscaledriver
  43. {
  44. node Node;
  45. int Width;
  46. int Height;
  47. int BufferSize;
  48. int MaxBlock;
  49. bool_t AllocAtStart;
  50. bool_t SetupFlip;
  51. bool_t SetupStretch;
  52. bool_t InAlloc;
  53. bool_t AtStart;
  54. struct xscale* Used;
  55. int DescPhyCount[MAXCOUNT];
  56. phymemblock DescPhy[MAXCOUNT][MAXDESCBLOCK];
  57. xscaledesc* Desc[MAXCOUNT];
  58. xscaledesc* DescLast[MAXCOUNT];
  59. int* Map;
  60. int BufferPhyCount[MAXCOUNT];
  61. phymemblock* BufferPhy; // [MAXCOUNT][MaxBlock]
  62. void* Buffer[MAXCOUNT];
  63. int Count;
  64. #ifdef X50V
  65. uint32_t* GPIO;
  66. uint32_t* Marathon;
  67. bool_t X50v;
  68. #endif
  69. uint32_t* Regs;
  70. uint32_t OrigDescPhy[MAXORIGBLOCK];
  71. phymemblock OrigBufferPhy[MAXORIGBLOCK];
  72. int OrigDescCount;
  73. void* OrigBuffer;
  74. int OrigBufferSize;
  75. xscaledesc* OrigDescEnd;
  76. bool_t OrigDescEndSet;
  77. bool_t NotOrig;
  78. } xscaledriver;
  79. typedef struct xscale
  80. {
  81. overlay Overlay;
  82. xscaledriver* Driver;
  83. bool_t Flip;
  84. int Next;
  85. } xscale;
  86. #define MAGIC 0xBABE0000
  87. #define GPIO_BASE 0x40E00000
  88. #define GPIO_SIZE 0x1000
  89. #define LCD_BASE 0x44000000
  90. #define LCD_SIZE 0x1000
  91. #define LCCR0 (0x000/4)
  92. #define LCCR1 (0x004/4)
  93. #define LCCR2 (0x008/4)
  94. #define LCCR3 (0x00C/4)
  95. #define LCCR4 (0x010/4)
  96. #define LCCR5 (0x014/4)
  97. #define LCSR0 (0x038/4)
  98. #define LCSR1 (0x034/4)
  99. #define FBR0 (0x020/4)
  100. #define FDADR0 (0x200/4)
  101. #define FSADR0 (0x204/4)
  102. #define FIDR0 (0x208/4)
  103. #define GAFR1_U (0x060/4)
  104. #define GAFR2_L (0x064/4)
  105. #define LCD_CONFIG (0x03fe0060/4)
  106. static void FreeOrig(xscaledriver* p)
  107. {
  108. int n;
  109. // be sure that the old orig is not referenced by the buffers
  110. for (n=0;n<p->Count;++n)
  111. p->DescLast[n]->Next = p->DescPhy[n]->Addr;
  112. // restore and release end descriptor
  113. if (p->OrigDescEnd)
  114. {
  115. if (p->OrigDescEndSet)
  116. {
  117. p->OrigDescEnd->Next = p->OrigDescPhy[0];
  118. p->OrigDescEndSet = 0;
  119. }
  120. PhyMemEnd(p->OrigDescEnd);
  121. p->OrigDescEnd = NULL;
  122. }
  123. // release framebuffer
  124. if (p->OrigBuffer)
  125. {
  126. PhyMemEnd(p->OrigBuffer);
  127. p->OrigBuffer = NULL;
  128. }
  129. p->OrigDescCount = 0;
  130. p->OrigBufferSize = 0;
  131. p->NotOrig = 0;
  132. }
  133. static void GetOrig(xscaledriver* p)
  134. {
  135. uint32_t DescPhy[MAXORIGBLOCK]; // original descriptor head
  136. xscaledesc Desc[MAXORIGBLOCK];
  137. uint32_t Phy;
  138. #ifdef X50V
  139. if (p->X50v)
  140. {
  141. // create a fake desc chain with SRAM usage (like Loox720)
  142. /*
  143. int Left = 640*480*2 - 256*1024;
  144. phymemblock Block2;
  145. phymemblock Block;
  146. int One = 1;
  147. xscaledesc* d = (xscaledesc*) PhyMemAlloc(sizeof(xscaledesc)*2,&Block,&One);
  148. if (!d)
  149. return;
  150. One = 1;
  151. if (!PhyMemAlloc(Left,&Block2,&One))
  152. return;
  153. d[0].Base = Block2.Addr;
  154. d[0].Cmd = Block2.Length;
  155. d[0].Id = 0;
  156. d[0].Next = Block.Addr + sizeof(xscaledesc);
  157. d[1].Base = 0x5C000000;
  158. d[1].Cmd = 256*1024 | (1<<21);
  159. d[1].Id = 0;
  160. d[1].Next = Block.Addr;
  161. Phy = Block.Addr;
  162. */
  163. Phy = 0;
  164. }
  165. else
  166. #endif
  167. {
  168. Phy = p->Regs[FDADR0] & ~15;
  169. p->Width = (p->Regs[LCCR1] & 1023)+1;
  170. p->Height = (p->Regs[LCCR2] & 1023)+1;
  171. }
  172. if (Phy)
  173. {
  174. int n,m;
  175. FreeOrig(p);
  176. for (n=0;n<MAXORIGBLOCK;)
  177. {
  178. xscaledesc* d = (xscaledesc*) PhyMemBegin(Phy,sizeof(xscaledesc),0);
  179. if (!d)
  180. break;
  181. DescPhy[n] = Phy;
  182. Desc[n] = *d;
  183. DEBUG_MSG4(-1,T("XScale %08x (%08x %08x %08x)"),Phy,Desc[n].Base,Desc[n].Cmd,Desc[n].Next);
  184. ++n;
  185. Phy = d->Next & ~15;
  186. PhyMemEnd(d);
  187. for (m=0;m<n;++m)
  188. if (DescPhy[m] == Phy)
  189. {
  190. int i,j;
  191. if (n-m>1) // need to find end
  192. {
  193. for (i=m;i<n;++i)
  194. if (Desc[i].Cmd & (1<<21))
  195. {
  196. ++i;
  197. if (i==n) i=m;
  198. break;
  199. }
  200. if (i==n)
  201. return; // failed
  202. }
  203. else
  204. i=m; // there is only one desc
  205. j=i;
  206. do
  207. {
  208. p->OrigDescPhy[p->OrigDescCount] = DescPhy[j];
  209. p->OrigBufferPhy[p->OrigDescCount].Addr = Desc[j].Base;
  210. p->OrigBufferPhy[p->OrigDescCount].Length = Desc[j].Cmd & 0x1FFFFF;
  211. p->OrigBufferSize += p->OrigBufferPhy[p->OrigDescCount].Length;
  212. p->OrigDescCount++;
  213. if (++j==n) j=m;
  214. }
  215. while (i!=j);
  216. // map end descriptor so we don't have to use disable/enable for flipping (with multiple desc displays)
  217. p->OrigDescEnd = (xscaledesc*) PhyMemBegin(p->OrigDescPhy[p->OrigDescCount-1],sizeof(xscaledesc),0);
  218. if (p->OrigDescEnd && p->OrigDescEnd->Next != p->OrigDescPhy[0])
  219. {
  220. PhyMemEnd(p->OrigDescEnd);
  221. p->OrigDescEnd = NULL;
  222. }
  223. // reuse original framebuffer
  224. if (p->OrigBufferSize >= p->Width*2*p->Height)
  225. p->OrigBuffer = PhyMemBeginEx(p->OrigBufferPhy,p->OrigDescCount,1);
  226. return;
  227. }
  228. }
  229. }
  230. }
  231. static bool_t FreeBuffer(xscaledriver* p)
  232. {
  233. int n;
  234. if (!p->BufferPhy || p->InAlloc || p->Used)
  235. return 0;
  236. for (n=0;n<p->Count;++n)
  237. {
  238. PhyMemFree(p->Desc[n],p->DescPhy[n],p->DescPhyCount[n]);
  239. if (n>0 || !p->OrigDescCount)
  240. PhyMemFree(p->Buffer[n],p->BufferPhy+p->MaxBlock*n,p->BufferPhyCount[n]);
  241. }
  242. p->Count = 0;
  243. p->MaxBlock = 0;
  244. free(p->Map);
  245. p->Map = NULL;
  246. free(p->BufferPhy);
  247. p->BufferPhy = NULL;
  248. DEBUG_MSG(-1,T("XSCALE Freed"));
  249. return 1;
  250. }
  251. static bool_t AllocBuffer(xscaledriver* p)
  252. {
  253. if (!p->BufferPhy && p->OrigBuffer)
  254. {
  255. int n;
  256. p->BufferSize = (p->Width*2 * p->Height) & ~3;
  257. p->MaxBlock = (p->BufferSize / 4096)+1;
  258. p->BufferPhy = (phymemblock*) malloc(sizeof(phymemblock)*p->MaxBlock*MAXCOUNT);
  259. if (!p->BufferPhy)
  260. return 0;
  261. p->Map = (int*) malloc(sizeof(int)*p->Height);
  262. if (!p->Map)
  263. {
  264. free(p->BufferPhy);
  265. p->BufferPhy = NULL;
  266. return 0;
  267. }
  268. p->InAlloc = 1;
  269. for (n=0;n<(p->SetupFlip?MAXCOUNT:1);++n)
  270. {
  271. // allocate desc table
  272. p->DescPhyCount[n] = MAXDESCBLOCK;
  273. p->Desc[n] = p->DescLast[n] = PhyMemAlloc(MAXDESC*sizeof(xscaledesc),p->DescPhy[n],&p->DescPhyCount[n]);
  274. if (!p->Desc[n])
  275. break;
  276. if (n==0 && p->OrigBufferSize >= p->BufferSize)
  277. {
  278. // use original surface
  279. p->Buffer[n] = p->OrigBuffer;
  280. p->BufferPhyCount[n] = p->OrigDescCount;
  281. memcpy(p->BufferPhy+p->MaxBlock*n,p->OrigBufferPhy,sizeof(phymemblock)*p->OrigDescCount);
  282. }
  283. else
  284. {
  285. // allocate new surface
  286. p->BufferPhyCount[n] = p->MaxBlock;
  287. p->Buffer[n] = PhyMemAlloc(p->BufferSize,p->BufferPhy+p->MaxBlock*n,&p->BufferPhyCount[n]);
  288. }
  289. if (!p->Buffer[n])
  290. {
  291. PhyMemFree(p->Desc[n],p->DescPhy[n],p->DescPhyCount[n]);
  292. break;
  293. }
  294. }
  295. if (n==2)
  296. {
  297. // can't flip chain with 2 surfaces (minimum is 3)
  298. PhyMemFree(p->Desc[1],p->DescPhy[1],p->DescPhyCount[1]);
  299. PhyMemFree(p->Buffer[1],p->BufferPhy+p->MaxBlock*1,p->BufferPhyCount[1]);
  300. --n;
  301. }
  302. p->Count = n;
  303. p->InAlloc = 0;
  304. DEBUG_MSG5(-1,T("XSCALE %d %d %d %d %d"),p->Count,p->BufferPhyCount[0],p->BufferPhyCount[1],p->BufferPhyCount[2],AvailMemory());
  305. }
  306. return 1;
  307. }
  308. static void GetMode(xscale* p)
  309. {
  310. p->Overlay.Output.Format.Video.Width = p->Driver->Width;
  311. p->Overlay.Output.Format.Video.Height = p->Driver->Height;
  312. p->Overlay.Output.Format.Video.Direction = 0;
  313. p->Overlay.Output.Format.Video.Aspect = ASPECT_ONE;
  314. p->Overlay.Output.Format.Video.Pitch = p->Overlay.Output.Format.Video.Width*2;
  315. DefaultRGB(&p->Overlay.Output.Format.Video.Pixel,16,5,6,5,0,0,0);
  316. AdjustOrientation(&p->Overlay.Output.Format.Video,1);
  317. if (p->Overlay.Output.Format.Video.Direction & DIR_SWAPXY)
  318. {
  319. int Model = QueryPlatform(PLATFORM_MODEL);
  320. if (Model == MODEL_IPAQ_H3800 || Model == MODEL_IPAQ_H3900 ||
  321. (Model == MODEL_NOVOGO && QueryPlatform(PLATFORM_VER)<500 && p->Driver->Width==240 && p->Driver->Height==320))
  322. p->Overlay.Output.Format.Video.Direction ^= DIR_MIRRORLEFTRIGHT|DIR_MIRRORUPDOWN;
  323. }
  324. if (!((uint32_t)p->Driver->OrigBuffer & 15))
  325. p->Overlay.Output.Format.Video.Pixel.Flags |= PF_16ALIGNED;
  326. }
  327. static int Init(xscale* p)
  328. {
  329. if (!p->Driver->OrigBuffer)
  330. {
  331. GetOrig(p->Driver);
  332. if (!p->Driver->OrigBuffer)
  333. return ERR_NOT_SUPPORTED;
  334. }
  335. GetMode(p);
  336. p->Next = 0;
  337. p->Flip = 0;
  338. p->Overlay.SetFX = BLITFX_AVOIDTEARING;
  339. if (p->Driver->Used)
  340. return ERR_DEVICE_ERROR;
  341. p->Driver->Used = p;
  342. if (!AllocBuffer(p->Driver))
  343. return ERR_OUT_OF_MEMORY;
  344. if (p->Driver->Count >= 3)
  345. p->Overlay.ClearFX = BLITFX_ONLYDIFF;
  346. return ERR_NONE;
  347. }
  348. static void QuickDisable(xscaledriver* p)
  349. {
  350. int n = p->Regs[LCCR0];
  351. n &= ~(1<<10); //DIS
  352. n &= ~1;    //ENB
  353. p->Regs[LCCR0] = n;
  354. Sleep(1);
  355. }
  356. static void Disable(xscaledriver* p)
  357. {
  358. int i;
  359. int n = p->Regs[LCCR0];
  360. if (n & 1)
  361. {
  362. n |= 1<<10; //DIS
  363. p->Regs[LCCR0] = n;
  364. for (i=0;i<30;++i)
  365. {
  366. if (!(p->Regs[LCCR0] & 1)) 
  367. break;
  368. Sleep(1);
  369. }
  370. if (i==30)
  371. QuickDisable(p);
  372. }
  373. }
  374. static void Enable(xscaledriver* p)
  375. {
  376. int n = p->Regs[LCCR0];
  377. n &= ~(1<<10); //DIS
  378. n |= 1; //EN;
  379. p->Regs[LCCR0] = n;
  380. Sleep(1);
  381. }
  382. static int GetCurrent2(xscaledriver* p)
  383. {
  384. int n;
  385. int Id = p->Regs[FIDR0] & ~15;
  386. uint32_t Phy = p->Regs[FDADR0] & ~15;
  387. if ((Id & 0xFFFF0000) == MAGIC)
  388. return (Id >> 4) & 0xFF;
  389. for (n=0;n<p->OrigDescCount;++n)
  390. if (Phy == p->OrigDescPhy[n] || Phy == p->OrigDescPhy[n]+sizeof(xscaledesc))
  391. return -1;
  392. return -2; // unknown
  393. }
  394. static int GetCurrent(xscaledriver* p)
  395. {
  396. int Current;
  397. if (!(p->Regs[LCCR0] & 1))
  398. return -2; // turned off lcd
  399. Current = GetCurrent2(p);
  400. if (Current >= -1)
  401. return Current;
  402. Sleep(50); // original desc chain has changed. maybe it's just temporary
  403. Current = GetCurrent2(p);
  404. if (Current >= -1)
  405. return Current;
  406. GetOrig(p); // reread original desc chain 
  407. return GetCurrent2(p);
  408. }
  409. #ifdef X50V
  410. static void X50vDisable(xscaledriver* p)
  411. {
  412. if (p->Marathon[LCD_CONFIG] & (1<<16))
  413. {
  414. uint32_t v;
  415. while ((v = p->Marathon[LCD_CONFIG]) & (1<<16))
  416. p->Marathon[LCD_CONFIG] = v & ~0x1000A;
  417. Disable(p);
  418. v = p->GPIO[GAFR1_U];
  419. if (v & 0xFFF00000)
  420. p->GPIO[GAFR1_U] = v & 0xFFFFF;
  421. v = p->GPIO[GAFR2_L];
  422. if (v & 0xFFFFFFF)
  423. p->GPIO[GAFR2_L] = v & 0xF0000000;
  424. }
  425. }
  426. static bool_t X50vEnable(xscaledriver* p,uint32_t Desc)
  427. {
  428. bool_t Changed = 0;
  429. if (!(p->Marathon[LCD_CONFIG] & (1<<16)))
  430. {
  431. uint32_t v;
  432. Changed = 1;
  433. Disable(p);
  434. p->Regs[LCCR0] = 0x1B008F8;
  435. p->Regs[LCCR1] = 0x1056FDDF; 
  436. p->Regs[LCCR2] = 0x104067F;  
  437. p->Regs[LCCR3] = 0x4f00001;  
  438. p->Regs[LCCR4] = 0;
  439. p->Regs[LCCR5] = 0x3F3F3F3F;
  440. p->Regs[FDADR0] = 0;
  441. p->Regs[LCSR0] = 0;
  442. v = p->GPIO[GAFR1_U];
  443. if ((v & 0xFFF00000) != 0xAAA00000)
  444. p->GPIO[GAFR1_U] = (v & 0xFFFFF) | 0xAAA00000;
  445. v = p->GPIO[GAFR2_L];
  446. if ((v & 0xFFFFFFF) != 0xAAAAAAA)
  447. p->GPIO[GAFR2_L] = (v & 0xF0000000) | 0xAAAAAAA;
  448. p->Regs[FDADR0] = Desc;
  449. Enable(p);
  450. QuickDisable(p);
  451. p->Regs[FDADR0] = Desc;
  452. Enable(p);
  453. while (!((v = p->Marathon[LCD_CONFIG]) & (1<<16)))
  454. {
  455. p->Marathon[LCD_CONFIG] = v | 0x1000A;
  456. Sleep(1);
  457. }
  458. }
  459. return Changed;
  460. }
  461. #endif
  462. static void SetOrig(xscaledriver* p)
  463. {
  464. int n;
  465. #ifdef X50V
  466. if (p->X50v)
  467. X50vDisable(p);
  468. else
  469. #endif
  470. {
  471. if (p->NotOrig)
  472. {
  473. if (p->OrigDescEnd && p->OrigDescEndSet)
  474. {
  475. p->OrigDescEnd->Next = p->OrigDescPhy[0];
  476. p->OrigDescEndSet = 0;
  477. }
  478. for (n=0;n<p->Count;++n)
  479. p->DescLast[n]->Next = p->OrigDescPhy[0];
  480. // wait for primary to be restored
  481. for (n=0;n<100;++n)
  482. {
  483. if (GetCurrent(p)<0)
  484. break;
  485. Sleep(1);
  486. }
  487. p->NotOrig = 0;
  488. }
  489. }
  490. }
  491. static void Done(xscale* p)
  492. {
  493. SetOrig(p->Driver);
  494. if (p->Driver->Used == p)
  495. p->Driver->Used = NULL;
  496. }
  497. static int Reset(xscale* p)
  498. {
  499. Done(p);
  500. Init(p);
  501. return ERR_NONE;
  502. }
  503. static xscaledesc* BuildDesc(xscaledesc* Desc,phymemblock* DescPhy,int DescPhyCount,phymemblock* BufferPhy,int BufferPhyCount,
  504.  int* Map,int Pitch,int Height,int Id)
  505. {
  506. uint32_t First = DescPhy->Addr;
  507. uint32_t Last = 0;
  508. uint32_t DescAddr = 0;
  509. int n,m;
  510. for (n=0;n<Height;++n)
  511. {
  512. uint32_t Pos = Pitch * Map[n];
  513. int Length = Pitch;
  514. for (m=0;Length>0 && m<BufferPhyCount;++m)
  515. {
  516. if (Pos < BufferPhy[m].Length)
  517. {
  518. uint32_t Addr = BufferPhy[m].Addr + Pos;
  519. int Size = BufferPhy[m].Length - Pos;
  520. if (Size > Length)
  521. Size = Length;
  522. if (Size & 3) return NULL; // this shouldn't happen
  523. // add desc 
  524. if (Addr != Last)
  525. {
  526. DescAddr += sizeof(xscaledesc);
  527. if (DescAddr > DescPhy->Length)
  528. {
  529. // next desc block
  530. if (--DescPhyCount==0) return NULL; // not enough desc...
  531. ++DescPhy;
  532. DescAddr = 0;
  533. }
  534. Desc->Next = DescPhy->Addr + DescAddr;
  535. Desc->Base = Addr;
  536. Desc->Id = Id;
  537. Desc->Cmd = Size;
  538. ++Desc;
  539. }
  540. else
  541. Desc[-1].Cmd += Size;
  542. Last = Addr + Size;
  543. Length -= Size;
  544. Pos += Size;
  545. }
  546. Pos -= BufferPhy[m].Length;
  547. }
  548. }
  549. --Desc;
  550. Desc->Next = First;
  551. Desc->Cmd |= (1<<21);
  552. return Desc;
  553. }
  554. static bool_t Build(xscaledriver* p)
  555. {
  556. int n;
  557. for (n=0;n<p->Count;++n)
  558. {
  559. p->DescLast[n] = BuildDesc(p->Desc[n],p->DescPhy[n],p->DescPhyCount[n],p->BufferPhy+p->MaxBlock*n,
  560. p->BufferPhyCount[n],p->Map,p->Width*2,p->Height,MAGIC | (n<<4));
  561. if (!p->DescLast[n])
  562. break;
  563. }
  564. if (n==p->Count)
  565. {
  566. for (n=p->OrigDescCount?1:0;n<p->Count;++n)
  567. memset(p->Buffer[n],0,p->BufferSize);
  568. return 1;
  569. }
  570. return 0;
  571. }
  572. static int UpdateAlign(xscale* p)
  573. {
  574. rect FullScreen;
  575. int* ScaleY;
  576. blitfx FX = p->Overlay.FX;
  577. bool_t FullView;
  578. if (FX.Direction & DIR_SWAPXY)
  579. ScaleY = &FX.ScaleX;
  580. else
  581. ScaleY = &FX.ScaleY;
  582. PhyToVirt(NULL,&FullScreen,&p->Overlay.Output.Format.Video);
  583. FullView = p->Driver->Count && EqRect(&FullScreen,&p->Overlay.Viewport);
  584. if (FullView && p->Driver->Count>=3)
  585. p->Overlay.FX.Flags &= ~BLITFX_AVOIDTEARING; //flipping used
  586. p->Flip = 0;
  587. p->Next = 0;
  588. SetOrig(p->Driver);
  589. OverlayUpdateAlign(&p->Overlay);
  590. if (FullView && p->Driver->Count)
  591. {
  592. int n;
  593. for (n=0;n<p->Overlay.Output.Format.Video.Height;++n)
  594. p->Driver->Map[n]=n;
  595. if (p->Driver->SetupStretch && 
  596. ((p->Overlay.Node.Class == XSCALE_LOW_ID && *ScaleY > SCALE_ONE/2) || *ScaleY > SCALE_ONE) && 
  597. !(p->Overlay.Output.Format.Video.Width & 1) && p->Overlay.Output.Format.Video.Height>0)
  598. {
  599. int Num,Den;
  600. int Adj;
  601. int LowSrc,HighSrc,CenterSrc;
  602. rect DstAlignedRect;
  603. rect SrcAlignedRect;
  604. *ScaleY = p->Overlay.Node.Class == XSCALE_LOW_ID ? SCALE_ONE/2 : SCALE_ONE;
  605. VirtToPhy(&p->Overlay.Viewport,&DstAlignedRect,&p->Overlay.Output.Format.Video);
  606. VirtToPhy(NULL,&SrcAlignedRect,&p->Overlay.Input.Format.Video);
  607. BlitRelease(p->Overlay.Soft);
  608. p->Overlay.Soft = BlitCreate(&p->Overlay.Output.Format.Video,&p->Overlay.Input.Format.Video,&FX,&p->Overlay.Caps);
  609. BlitAlign(p->Overlay.Soft, &DstAlignedRect, &SrcAlignedRect );
  610. LowSrc = -(DstAlignedRect.Height/2);
  611. HighSrc = LowSrc + DstAlignedRect.Height;
  612. CenterSrc = DstAlignedRect.y - LowSrc;
  613. Num = DstAlignedRect.Height;
  614. Den = p->Overlay.DstAlignedRect.Height;
  615. if (FX.Direction & DIR_SWAPXY)
  616. {
  617. Num *= p->Overlay.SrcAlignedRect.Width;
  618. Den *= SrcAlignedRect.Width;
  619. }
  620. else
  621. {
  622. Num *= p->Overlay.SrcAlignedRect.Height;
  623. Den *= SrcAlignedRect.Height;
  624. }
  625. Adj = Scale(p->Overlay.DstAlignedRect.Height,Num,2*Den);
  626. for (n=0;n<p->Overlay.DstAlignedRect.Height;++n)
  627. {
  628. int i = Scale(n,Num,Den) - Adj;
  629. if (i >= HighSrc) i=HighSrc-1;
  630. if (i < LowSrc) i=LowSrc;
  631. p->Driver->Map[p->Overlay.DstAlignedRect.y+n] = CenterSrc + i;
  632. }
  633. }
  634. if (Build(p->Driver))
  635. {
  636. p->Overlay.FX.Flags |= BLITFX_AVOIDTEARING; //restore
  637. p->Flip = 1;
  638. }
  639. }
  640. return ERR_NONE;
  641. }
  642. static void Restore(xscaledriver* p,int Next)
  643. {
  644. int n;
  645. char *s,*d;
  646. char *Src = (char*)p->Buffer[Next];
  647. char *Dst = (char*)p->OrigBuffer;
  648. int Middle = p->Height/2;
  649. int Pitch = p->Width*2;
  650. for (n=0;n<Middle;++n)
  651. {
  652. s = Src + p->Map[n] * Pitch;
  653. d = Dst + n*Pitch;
  654. if (s != d)
  655. memcpy(d,s,Pitch);
  656. }
  657. for (n=p->Height-1;n>=Middle;--n)
  658. {
  659. s = Src + p->Map[n] * Pitch;
  660. d = Dst + n*Pitch;
  661. if (s != d)
  662. memcpy(d,s,Pitch);
  663. }
  664. }
  665. static int UpdateShow(xscale* p)
  666. {
  667. if (!p->Overlay.Show)
  668. {
  669. SetOrig(p->Driver);
  670. if (p->Flip)
  671. {
  672. // restore after SetOrig because it's vsynced and restore starts for upper part anyway
  673. Restore(p->Driver,p->Next); 
  674. }
  675. p->Next = 0;
  676. }
  677. return ERR_NONE;
  678. }
  679. static int Lock(xscale* p, planes Planes, bool_t OnlyAligned )
  680. {
  681. if (p->Flip)
  682. {
  683. int Next = p->Next+1;
  684. if (Next == p->Driver->Count) 
  685. Next = 0;
  686. // use new buffer only if it's not the current
  687. if (GetCurrent(p->Driver) != Next) 
  688. p->Next = Next;
  689. Planes[0] = p->Driver->Buffer[p->Next];
  690. }
  691. else
  692. Planes[0] = p->Driver->OrigBuffer;
  693. return ERR_NONE;
  694. }
  695. static int Unlock(xscale* p )
  696. {
  697. if (p->Flip)
  698. {
  699. int Current = GetCurrent(p->Driver);
  700. uint32_t DescPhy = p->Driver->DescPhy[p->Next]->Addr;
  701. // close chain
  702. p->Driver->DescLast[p->Next]->Next = DescPhy;
  703. #ifdef X50V
  704. if (p->Driver->X50v && X50vEnable(p->Driver,DescPhy))
  705. Current = p->Next;
  706. #endif
  707. DEBUG_MSG4(-1,T("%08x %08x %08x %d"),p->Driver->Regs[LCCR0],p->Driver->Regs[LCCR3],p->Driver->Regs[FDADR0],Current);
  708. if (Current<-1)
  709. return ERR_DEVICE_ERROR;
  710. if (Current<0)
  711. {
  712. if (p->Driver->OrigDescEnd)
  713. {
  714. p->Driver->OrigDescEnd->Next = DescPhy;
  715. p->Driver->OrigDescEndSet = 1;
  716. }
  717. else
  718. if (p->Driver->OrigDescCount>1) 
  719. {
  720. // multi desc original
  721. bool_t Old = (p->Driver->Regs[LCCR0] & 1);
  722. Disable(p->Driver);
  723. p->Driver->Regs[FBR0] = 0;
  724. p->Driver->Regs[FDADR0] = DescPhy;
  725. if (Old) Enable(p->Driver);
  726. }
  727. else // simply branch
  728. p->Driver->Regs[FBR0] = DescPhy | 1; 
  729. }
  730. else
  731. {
  732. // modify last frames tail to new frame
  733. Current = p->Next-1;
  734. if (Current<0)
  735. Current = p->Driver->Count-1;
  736. p->Driver->DescLast[Current]->Next = DescPhy;
  737. }
  738. p->Driver->NotOrig = 1;
  739. }
  740. return ERR_NONE;
  741. }
  742. static int UpdateStretch(xscaledriver* Driver)
  743. {
  744. if (Driver->Used)
  745. UpdateAlign(Driver->Used);
  746. return ERR_NONE;
  747. }
  748. static int UpdateFlip(xscaledriver* Driver)
  749. {
  750. if (Driver->Used)
  751. {
  752. xscale* p = Driver->Used;
  753. Done(p);
  754. FreeBuffer(Driver);
  755. Init(p);
  756. UpdateAlign(p);
  757. p->Overlay.Dirty = 1;
  758. p->Overlay.LastTime = -1;
  759. }
  760. return ERR_NONE;
  761. }
  762. static const datatable Params[] = 
  763. {
  764. { XSCALEDRIVER_STRETCH, TYPE_BOOL, DF_SETUP|DF_CHECKLIST },
  765. { XSCALEDRIVER_FLIP, TYPE_BOOL, DF_SETUP|DF_CHECKLIST },
  766. { XSCALEDRIVER_ALLOC_AT_START, TYPE_BOOL, DF_SETUP|DF_CHECKLIST },
  767. DATATABLE_END(XSCALEDRIVER_ID)
  768. };
  769. static int Enum(xscaledriver* p, int* No, datadef* Param)
  770. {
  771. return NodeEnumTable(No,Param,Params);
  772. }
  773. static int Get(xscaledriver* p,int No,void* Data,int Size)
  774. {
  775. int Result = ERR_INVALID_PARAM;
  776. switch (No) 
  777. {
  778. case XSCALEDRIVER_STRETCH: GETVALUE(p->SetupStretch,bool_t); break;
  779. case XSCALEDRIVER_FLIP: GETVALUE(p->SetupFlip,bool_t); break;
  780. case XSCALEDRIVER_ALLOC_AT_START: GETVALUE(p->AllocAtStart,bool_t); break;
  781. }
  782. return Result;
  783. }
  784. static bool_t Selected()
  785. {
  786. int Id;
  787. return NodeRegLoadValue(PLAYER_ID,PLAYER_VOUTPUTID,&Id,sizeof(Id),TYPE_INT) && (Id == XSCALE_ID || Id == XSCALE_LOW_ID);
  788. }
  789. static int Set(xscaledriver* p,int No,const void* Data,int Size)
  790. {
  791. int Result = ERR_INVALID_PARAM;
  792. switch (No)
  793. {
  794. case XSCALEDRIVER_STRETCH: SETVALUECMP(p->SetupStretch,bool_t,UpdateStretch(p),EqBool); break;
  795. case XSCALEDRIVER_FLIP: SETVALUECMP(p->SetupFlip,bool_t,UpdateFlip(p),EqBool); break;
  796. case XSCALEDRIVER_ALLOC_AT_START: SETVALUE(p->AllocAtStart,bool_t,ERR_NONE); break;
  797. case NODE_SETTINGSCHANGED:
  798. if (p->AllocAtStart && p->AtStart && Selected())
  799. {
  800. if (!p->OrigBuffer)
  801. GetOrig(p);
  802. AllocBuffer(p);
  803. }
  804. p->AtStart = 0;
  805. break;
  806. case NODE_HIBERNATE:
  807. if (!p->Used && FreeBuffer(p))
  808. Result = ERR_NONE;
  809. break;
  810. }
  811. return Result;
  812. }
  813. static int Create(xscale* p)
  814. {
  815. p->Driver = (xscaledriver*)NodeEnumObject(NULL,XSCALEDRIVER_ID);
  816. if (!p->Driver)
  817. return ERR_NOT_SUPPORTED;
  818. if (p->Overlay.Node.Class == XSCALE_LOW_ID && (p->Driver->Width*p->Driver->Height <= 320*240 || 
  819. (QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_WMMX)!=0))
  820. return ERR_NOT_SUPPORTED;
  821. GetMode(p);
  822. p->Overlay.Init = Init;
  823. p->Overlay.Done= Done;
  824. p->Overlay.Reset = Reset;
  825. p->Overlay.Update = UpdateAlign;
  826. p->Overlay.UpdateShow = UpdateShow;
  827. p->Overlay.Lock = Lock;
  828. p->Overlay.Unlock = Unlock;
  829. return ERR_NONE;
  830. }
  831. static int CreateDriver(xscaledriver* p)
  832. {
  833. bool_t Detected;
  834. int Caps = QueryPlatform(PLATFORM_CAPS);
  835. if (!(Caps & CAPS_ARM_XSCALE))
  836. return ERR_NOT_SUPPORTED;
  837. p->Node.Enum = Enum;
  838. p->Node.Get = Get;
  839. p->Node.Set = Set;
  840. p->AtStart = 1;
  841. p->OrigBuffer = NULL;
  842. p->OrigDescCount = 0;
  843. p->Regs = (uint32_t*)PhyMemBegin(LCD_BASE,LCD_SIZE,0);
  844. if (!p->Regs)
  845. return ERR_NOT_SUPPORTED;
  846. #ifdef X50V
  847. p->X50v = QueryPlatform(PLATFORM_MODEL)==MODEL_AXIM_X50 && CheckModule(T("pvrvadd.dll"));
  848. if (p->X50v)
  849. {
  850. p->Width = 480;
  851. p->Height = 640;
  852. p->Marathon = (uint32_t*) 0xBC000000;
  853. p->GPIO = (uint32_t*) PhyMemBegin(GPIO_BASE,GPIO_SIZE,0);
  854. if (p->GPIO)
  855. {
  856. RawFrameBufferInfo Info;
  857. HDC DC= GetDC(NULL);
  858. memset(&Info,0,sizeof(Info));
  859. ExtEscape(DC, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char*)&Info);
  860. ReleaseDC(NULL,DC);
  861. p->OrigBuffer = Info.pFramePointer;
  862. }
  863. }
  864. else
  865. #endif
  866. if (!(p->Regs[LCCR0] & 1) || ((p->Regs[LCCR3] >> 24) & 7)!=4) // LCD enabled, RGB 16bit
  867. return ERR_NOT_SUPPORTED;
  868. if (!NodeRegLoadValue(XSCALEDRIVER_ID, XSCALEDRIVER_DETECTED, &Detected, sizeof(Detected), TYPE_BOOL) || !Detected)
  869. {
  870. GetOrig(p);
  871. if (!p->OrigBuffer)
  872. {
  873. PhyMemEnd(p->Regs);
  874. p->Regs = NULL;
  875. return ERR_NOT_SUPPORTED;
  876. }
  877. Detected = 1;
  878. NodeRegSaveValue(XSCALEDRIVER_ID, XSCALEDRIVER_DETECTED, &Detected, sizeof(Detected), TYPE_BOOL);
  879. }
  880. p->AllocAtStart = 1;
  881. p->SetupFlip = 1;
  882. p->SetupStretch = (QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_WMMX)==0;
  883. return ERR_NONE;
  884. }
  885. static void DeleteDriver(xscaledriver* p)
  886. {
  887. if (p->Regs)
  888. SetOrig(p);
  889. FreeBuffer(p);
  890. FreeOrig(p);
  891. #ifdef X50V
  892. if (p->GPIO)
  893. {
  894. PhyMemEnd(p->GPIO);
  895. p->GPIO = NULL;
  896. }
  897. #endif
  898. if (p->Regs)
  899. {
  900. PhyMemEnd(p->Regs);
  901. p->Regs = NULL;
  902. }
  903. }
  904. static const nodedef XScaleDriver = 
  905. {
  906. sizeof(xscaledriver)|CF_GLOBAL|CF_SETTINGS,
  907. XSCALEDRIVER_ID,
  908. NODE_CLASS,
  909. PRI_DEFAULT,
  910. (nodecreate)CreateDriver,
  911. (nodedelete)DeleteDriver,
  912. };
  913. static const nodedef XScale = 
  914. {
  915. sizeof(xscale)|CF_GLOBAL,
  916. XSCALE_ID,
  917. OVERLAY_CLASS,
  918. PRI_DEFAULT+97,
  919. (nodecreate)Create,
  920. };
  921. static const nodedef XScaleLow = 
  922. {
  923. sizeof(xscale)|CF_GLOBAL,
  924. XSCALE_LOW_ID,
  925. XSCALE_ID,
  926. PRI_DEFAULT+96,
  927. };
  928. void OverlayXScale_Init() 
  929. NodeRegisterClass(&XScaleDriver);
  930. NodeRegisterClass(&XScale);
  931. NodeRegisterClass(&XScaleLow);
  932. }
  933. void OverlayXScale_Done()
  934. {
  935. NodeUnRegisterClass(XSCALE_LOW_ID);
  936. NodeUnRegisterClass(XSCALE_ID);
  937. NodeUnRegisterClass(XSCALEDRIVER_ID);
  938. }
  939. #else
  940. void OverlayXScale_Init() {}
  941. void OverlayXScale_Done() {}
  942. #endif