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

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: overlay.c 551 2006-01-09 11:55:09Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23. #include "common.h"
  24. int OverlayDefaultBlit(overlay* p, const constplanes Data, const constplanes DataLast)
  25. {
  26. planes Planes;
  27. int Result = p->Lock(p,Planes,1);
  28. if (Result==ERR_NONE)
  29. {
  30. BlitImage(p->Soft,Planes,Data,DataLast,p->Output.Format.Video.Pitch,-1);
  31. p->Unlock(p);
  32. }
  33. return Result;
  34. }
  35. int OverlayEnum(overlay* p, int* No, datadef* Param)
  36. {
  37. return VOutEnum(p,No,Param);
  38. }
  39. static int Create(overlay* p)
  40. {
  41. p->Node.Enum = (nodeenum)OverlayEnum;
  42. p->Node.Get = (nodeget)OverlayGet;
  43. p->Node.Set = (nodeset)OverlaySet;
  44. p->Blit = (ovlblit)OverlayDefaultBlit;
  45. p->Update = (ovlfunc)OverlayUpdateAlign;
  46. p->Caps = -1;
  47. p->Soft = NULL;
  48. p->Primary = 1;
  49. p->Overlay = 0;
  50. p->DoPowerOff = 0;
  51. memset(&p->Backup,0,sizeof(idctbackup));
  52. memset(&p->OrigFX,0,sizeof(blitfx));
  53. p->OrigFX.ScaleX = SCALE_ONE;
  54. p->OrigFX.ScaleY = SCALE_ONE;
  55. p->AutoPrerotate = 0;
  56. p->ColorKey = RGB_NULL;
  57. p->Aspect.Num = 0;
  58. p->Aspect.Den = 1;
  59. p->Output.Type = PACKET_VIDEO;
  60. return ERR_NONE;
  61. }
  62. static void Delete(overlay* p)
  63. {
  64. BlitRelease(p->Soft);
  65. ReleaseModule(&p->Module);
  66. }
  67. void OverlayClearBorder(overlay* p)
  68. {
  69. planes Planes;
  70. p->Dirty = 1;
  71. if (p->Lock && p->Lock(p,Planes,0) == ERR_NONE)
  72. {
  73. uint32_t c = RGBToFormat(CRGB(0,0,0),&p->Output.Format.Video.Pixel);
  74. rect Viewport;
  75. VirtToPhy(&p->Viewport,&Viewport,&p->Output.Format.Video);
  76. FillColor(Planes[0],p->Output.Format.Video.Pitch,Viewport.x,Viewport.y,
  77. Viewport.Width,p->DstAlignedRect.y-Viewport.y,
  78. p->Output.Format.Video.Pixel.BitCount,c);
  79. FillColor(Planes[0],p->Output.Format.Video.Pitch,Viewport.x,p->DstAlignedRect.y,
  80. p->DstAlignedRect.x-Viewport.x,p->DstAlignedRect.Height,
  81. p->Output.Format.Video.Pixel.BitCount,c);
  82. FillColor(Planes[0],p->Output.Format.Video.Pitch,p->DstAlignedRect.x+p->DstAlignedRect.Width,p->DstAlignedRect.y,
  83. (Viewport.x+Viewport.Width)-(p->DstAlignedRect.x+p->DstAlignedRect.Width),p->DstAlignedRect.Height,
  84. p->Output.Format.Video.Pixel.BitCount,c);
  85. FillColor(Planes[0],p->Output.Format.Video.Pitch,Viewport.x,p->DstAlignedRect.y+p->DstAlignedRect.Height,
  86. Viewport.Width,(Viewport.y+Viewport.Height)-(p->DstAlignedRect.y+p->DstAlignedRect.Height),
  87. p->Output.Format.Video.Pixel.BitCount,c);
  88. p->Unlock(p);
  89. }
  90. }
  91. int OverlayUpdateAlign(overlay* p)
  92. {
  93. rect OldGUI = p->GUIAlignedRect;
  94. rect Old = p->DstAlignedRect;
  95. DEBUG_MSG4(DEBUG_TEST,T("BLIT Viewport:%d %d %d %d"),p->Viewport.x,p->Viewport.y,p->Viewport.Width,p->Viewport.Height);
  96. VirtToPhy(&p->Viewport,&p->DstAlignedRect,&p->Output.Format.Video);
  97. VirtToPhy(NULL,&p->SrcAlignedRect,&p->Input.Format.Video);
  98. BlitRelease(p->Soft);
  99. p->Soft = BlitCreate(&p->Output.Format.Video,&p->Input.Format.Video,&p->FX,&p->Caps);
  100. BlitAlign(p->Soft,&p->DstAlignedRect, &p->SrcAlignedRect);
  101. PhyToVirt(&p->DstAlignedRect,&p->GUIAlignedRect,&p->Output.Format.Video);
  102. //DEBUG_MSG4(DEBUG_TEST,T("BLIT DstRect:%d %d %d %d"),p->DstAlignedRect.x,p->DstAlignedRect.y,p->DstAlignedRect.Width,p->DstAlignedRect.Height);
  103. //DEBUG_MSG4(DEBUG_TEST,T("BLIT SrcRect:%d %d %d %d"),p->SrcAlignedRect.x,p->SrcAlignedRect.y,p->SrcAlignedRect.Width,p->SrcAlignedRect.Height);
  104. if (!EqRect(&Old,&p->DstAlignedRect) && p->Show && p->Primary)
  105. {
  106. WinInvalidate(&OldGUI,0);
  107. WinInvalidate(&p->Viewport,1);
  108. WinValidate(&p->GUIAlignedRect);
  109. }
  110. if (p->Show && (p->FullScreenViewport || !p->Primary))
  111. OverlayClearBorder(p);
  112. return ERR_NONE;
  113. }
  114. static int Blit(overlay* p,const packet* Packet,const flowstate* State)
  115. {
  116. int Result = ERR_NONE;
  117. if (Packet)
  118. {
  119. if (State->DropLevel)
  120. {
  121. ++p->Dropped;
  122. return ERR_NONE;
  123. }
  124. if (State->CurrTime >= 0)
  125. {
  126. if (!p->Play && State->CurrTime == p->LastTime)
  127. return ERR_BUFFER_FULL;
  128. if (Packet->RefTime >= (State->CurrTime + SHOWAHEAD))
  129. return ERR_BUFFER_FULL;
  130. p->LastTime = State->CurrTime;
  131. }
  132. else
  133. p->LastTime = Packet->RefTime;
  134. p->CurrTime = State->CurrTime;
  135. if (State->CurrTime != TIME_RESEND)
  136. ++p->Total;
  137. if (p->Soft && p->Inited && p->Show && Packet->Data[0])
  138. {
  139. const constplanes* LastData = &Packet->LastData;
  140. if (p->Dirty)
  141. LastData = NULL;
  142. /* { static tick_t Last = 0;
  143. DebugMessage("%d %d",Packet->RefTime,Packet->RefTime-Last);
  144. Last = Packet->RefTime; } */
  145. Result = p->Blit(p,Packet->Data,*LastData);
  146. if (Result == ERR_NONE)
  147. p->Dirty = 0;
  148. }
  149. }
  150. else
  151. if (State->DropLevel)
  152. ++p->Dropped;
  153. return Result;
  154. }
  155. int OverlayGet(overlay* p,int No,void* Data,int Size)
  156. {
  157. int Result = ERR_INVALID_PARAM;
  158. switch (No)
  159. {
  160. case OUT_INPUT: GETVALUE(p->Pin,pin); break;
  161. case OUT_OUTPUT|PIN_FORMAT: GETVALUE(p->Output,packetformat); break;
  162. case OUT_INPUT|PIN_FORMAT: GETVALUE(p->Input,packetformat); break;
  163. case OUT_INPUT|PIN_PROCESS: GETVALUE((packetprocess)Blit,packetprocess); break;
  164. case OUT_TOTAL: GETVALUE(p->Total,int); break;
  165. case OUT_DROPPED: GETVALUE(p->Dropped,int); break;
  166. case VOUT_PRIMARY: GETVALUE(p->Primary,bool_t); break;
  167. case VOUT_OVERLAY: GETVALUE(p->Overlay,bool_t); break;
  168. case VOUT_IDCT: GETVALUE(p->AccelIDCT,idct*); break;
  169. case VOUT_VISIBLE: GETVALUE(p->Visible,bool_t); break;
  170. case VOUT_CLIPPING: GETVALUE(p->Clipping,bool_t); break;
  171. case VOUT_FX: GETVALUE(p->OrigFX,blitfx); break;
  172. case VOUT_VIEWPORT: GETVALUE(p->Viewport,rect); break;
  173. case VOUT_FULLSCREEN: GETVALUE(p->FullScreenViewport,bool_t); break;
  174. case VOUT_OUTPUTRECT: GETVALUECOND(p->GUIAlignedRect,rect,!p->Disabled); break;
  175. case VOUT_AUTOPREROTATE: GETVALUE(p->AutoPrerotate,bool_t); break;
  176. case VOUT_UPDATING: GETVALUE(p->Updating,bool_t); break;
  177. case VOUT_PLAY: GETVALUE(p->Play,bool_t); break;
  178. case VOUT_CAPS: GETVALUE(p->Caps,int); break;
  179. case VOUT_COLORKEY: GETVALUECOND(p->ColorKey,rgbval_t,!p->Disabled && p->ColorKey!=RGB_NULL); break;
  180. case VOUT_ASPECT: GETVALUE(p->Aspect,fraction); break;
  181. case FLOW_BACKGROUND: GETVALUECOND(p->Background,bool_t,p->DoPowerOff); break;
  182. }
  183. return Result;
  184. }
  185. static NOINLINE void UpdateInputFormat(overlay* p)
  186. {
  187. if (p->Inited && !p->UpdateInputFormat && p->PrefDirection != p->Input.Format.Video.Direction && p->Pin.Node)
  188. {
  189. packetformat Format = p->Input;
  190. if ((p->PrefDirection ^ Format.Format.Video.Direction) & DIR_SWAPXY)
  191. SwapInt(&Format.Format.Video.Width,&Format.Format.Video.Height);
  192. Format.Format.Video.Direction = p->PrefDirection;
  193. p->UpdateInputFormat = 1;
  194. p->Pin.Node->Set(p->Pin.Node,p->Pin.No|PIN_FORMAT,&Format,sizeof(Format));
  195. p->UpdateInputFormat = 0;
  196. }
  197. }
  198. int OverlayUpdateFX(overlay* p, bool_t ForceUpdate)
  199. {
  200. fraction Aspect = p->Aspect;
  201. blitfx LastFX = p->FX;
  202. int Width,Height,ScaleX,ScaleY;
  203. if (!p->Inited || p->Updating) return ERR_NONE;
  204. if (Aspect.Num==0) // source
  205. {
  206. Aspect.Num = p->Input.Format.Video.Aspect;
  207. Aspect.Den = ASPECT_ONE;
  208. if (Aspect.Num == ASPECT_ONE || !Aspect.Num)
  209. Aspect.Num = DefaultAspect(p->Input.Format.Video.Width,p->Input.Format.Video.Height);
  210. }
  211. else
  212. if (Aspect.Num<0)
  213. {
  214. // screen aspect ratio -> pixel aspect ratio
  215. if (p->InputDirection & DIR_SWAPXY)
  216. {
  217. Aspect.Num *= -p->Input.Format.Video.Width;
  218. Aspect.Den *= p->Input.Format.Video.Height;
  219. }
  220. else
  221. {
  222. Aspect.Num *= -p->Input.Format.Video.Height;
  223. Aspect.Den *= p->Input.Format.Video.Width;
  224. }
  225. }
  226. p->FX = p->OrigFX;
  227. p->FX.Flags |= p->SetFX;
  228. p->FX.Flags &= ~p->ClearFX;
  229. p->FX.Direction = CombineDir(p->InputDirection,p->OrigFX.Direction,p->Output.Format.Video.Direction);
  230. p->PrefDirection = CombineDir(p->FX.Direction,0,p->Input.Format.Video.Direction);
  231. if (p->OrigFX.ScaleX<=0)
  232. {
  233. int v = p->OrigFX.ScaleX;
  234. Width = p->Viewport.Width;
  235. Height = p->Viewport.Height;
  236. if ((p->InputDirection ^ p->OrigFX.Direction) & DIR_SWAPXY)
  237. SwapInt(&Width,&Height);
  238. if (p->InputDirection & DIR_SWAPXY)
  239. {
  240. ScaleX = Scale(Width,SCALE_ONE,p->Input.Format.Video.Width);
  241. ScaleY = Scale(Height,SCALE_ONE,Scale(p->Input.Format.Video.Height,Aspect.Num,Aspect.Den));
  242. }
  243. else
  244. {
  245. ScaleX = Scale(Width,SCALE_ONE,Scale(p->Input.Format.Video.Width,Aspect.Num,Aspect.Den));
  246. ScaleY = Scale(Height,SCALE_ONE,p->Input.Format.Video.Height);
  247. }
  248. if ((p->InputDirection & DIR_SWAPXY) && (v == -1 || v == -2))
  249. v = -3-v; // swap 'fit width' and 'fit height'
  250. if (v==-3)
  251. {
  252. //todo: fill screen, but always using the fullscreen aspect ratio!
  253. p->FX.ScaleY = ScaleY;
  254. p->FX.ScaleX = ScaleX;
  255. }
  256. else
  257. {
  258. if ((v == -2) || (v!=-1 && v!=-4 && ScaleX>ScaleY) || (v==-4 && ScaleX<ScaleY))
  259. ScaleX = ScaleY;
  260. if (v<-4)
  261. ScaleX = Scale(ScaleX,-v,SCALE_ONE);
  262. p->FX.ScaleY = ScaleX;
  263. p->FX.ScaleX = Scale(ScaleX,Aspect.Num,Aspect.Den);
  264. if (p->InputDirection & DIR_SWAPXY)
  265. SwapInt(&p->FX.ScaleX,&p->FX.ScaleY);
  266. }
  267. }
  268. else
  269. {
  270. // prefer source horizontal scaling (because of smooth scale option)
  271. if (p->InputDirection & DIR_SWAPXY)
  272. p->FX.ScaleY = Scale(p->FX.ScaleY,Aspect.Num,Aspect.Den);
  273. else
  274. p->FX.ScaleX = Scale(p->FX.ScaleX,Aspect.Num,Aspect.Den);
  275. }
  276. if (p->Output.Format.Video.Pixel.Flags & PF_PIXELDOUBLE)
  277. {
  278. p->FX.ScaleX >>= 1;
  279. p->FX.ScaleY >>= 1;
  280. }
  281. if ((p->FX.Flags & BLITFX_ONLYDIFF) && p->FX.ScaleX < (SCALE_ONE*2)/3)
  282. p->FX.Flags &= ~BLITFX_ONLYDIFF;
  283. if (p->ForceUpdate)
  284. {
  285. p->ForceUpdate = 0;
  286. ForceUpdate = 1;
  287. }
  288. if (ForceUpdate || !EqBlitFX(&p->FX,&LastFX))
  289. {
  290. p->Update(p);
  291. p->Dirty = 1;
  292. p->LastTime = -1;
  293. UpdateInputFormat(p);
  294. }
  295. return ERR_NONE;
  296. }
  297. static int UpdateInputDirection(overlay* p,bool_t Update)
  298. {
  299. if (p->Inited && !p->Updating)
  300. {
  301. p->InputDirection = p->Input.Format.Video.Direction;
  302. p->PreRotate = 0;
  303. if (p->AutoPrerotate && !(p->Input.Format.Video.Pixel.Flags & PF_NOPREROTATE))
  304. {
  305. rect r;
  306. PhyToVirt(NULL,&r,&p->Input.Format.Video);
  307. // portrait?
  308. if (r.Width < r.Height)
  309. {
  310. p->PreRotate = 1;
  311. if (p->InputDirection & DIR_SWAPXY)
  312. p->InputDirection ^= DIR_SWAPXY | DIR_MIRRORLEFTRIGHT;
  313. else
  314. p->InputDirection ^= DIR_SWAPXY | DIR_MIRRORUPDOWN;
  315. }
  316. }
  317. if (Update)
  318. OverlayUpdateFX(p,0);
  319. }
  320. return ERR_NONE;
  321. }
  322. int OverlayUpdateShow(overlay* p,bool_t Temp)
  323. {
  324. bool_t Show = !p->Disabled && p->Visible && (p->ColorKey != RGB_NULL || !p->Clipping || !p->Primary);
  325. if (!p->Updating && p->Show != Show)
  326. {
  327. p->Show = Show;
  328. p->Dirty = 1;
  329. p->LastTime = -1;
  330. if (p->Inited && !Temp)
  331. {
  332. if (p->Primary && p->Overlay && p->ColorKey != RGB_NULL && !p->Show)
  333. {
  334. // clear colorkey before turning off overlay
  335. WinInvalidate(&p->Viewport,1);
  336. WinUpdate(); 
  337. }
  338. if (p->UpdateShow)
  339. p->UpdateShow(p);
  340. if (p->Primary)
  341. {
  342. if (p->Overlay)
  343. {
  344. if (p->ColorKey != RGB_NULL && p->Show)
  345. WinInvalidate(&p->Viewport,1);
  346. }
  347. else
  348. if (p->Show)
  349. {
  350. WinInvalidate(&p->Viewport,1); // redraw border (zoom may have changed)
  351. WinValidate(&p->GUIAlignedRect);
  352. }
  353. else
  354. {
  355. WinInvalidate(&p->Viewport,0); // redraw other windows
  356. WinValidate(&p->Viewport); // own window is fine
  357. }
  358. }
  359. }
  360. }
  361. return ERR_NONE;
  362. }
  363. static int Updating(overlay* p)
  364. {
  365. if (!p->Updating)
  366. {
  367. UpdateInputDirection(p,0);
  368. OverlayUpdateFX(p,0);
  369. OverlayUpdateShow(p,0);
  370. }
  371. return ERR_NONE;
  372. }
  373. static int UpdateInput(overlay* p)
  374. {
  375. if (p->Inited)
  376. {
  377. if (p->Show)
  378. {
  379. bool_t Old = p->Visible;
  380. p->Visible = 0;
  381. p->Show = 0;
  382. if (p->UpdateShow)
  383. p->UpdateShow(p); // maybe calls OverlayUpdateShow
  384. p->Visible = Old;
  385. }
  386. p->Done(p);
  387. BlitRelease(p->Soft);
  388. p->Soft = NULL;
  389. p->Inited = 0;
  390. memset(&p->GUIAlignedRect,0,sizeof(rect));
  391. if (p->Primary)
  392. WinInvalidate(&p->Viewport,1);
  393. }
  394. if (!p->TurningOff)
  395. IDCTRestore(NULL,&p->Backup);
  396. memset(&p->FX,0,sizeof(blitfx));
  397. memset(&p->DstAlignedRect,0,sizeof(rect));
  398. memset(&p->SrcAlignedRect,0,sizeof(rect));
  399. memset(&p->GUIAlignedRect,0,sizeof(rect));
  400. p->Total = 0;
  401. p->Dropped = 0;
  402. p->Disabled = 0;
  403. p->Updating = 0;
  404. p->Show = 0;
  405. p->Dirty = 1;
  406. p->LastTime = -1;
  407. p->ColorKey = RGB_NULL;
  408. if (p->Input.Type == PACKET_VIDEO)
  409. {
  410. if (Compressed(&p->Input.Format.Video.Pixel))
  411. return ERR_INVALID_DATA;
  412. if (p->Input.Format.Video.Width<=0) 
  413. {
  414. p->Disabled = 1;
  415. p->Input.Format.Video.Width = 2;
  416. }
  417. if (p->Input.Format.Video.Height<=0) 
  418. {
  419. p->Disabled = 1;
  420. p->Input.Format.Video.Height = 2;
  421. }
  422. if (!p->Background)
  423. {
  424. int Result = p->Init(p);
  425. if (Result != ERR_NONE)
  426. {
  427. if (Result == ERR_DEVICE_ERROR)
  428. ShowError(p->Node.Class,ERR_ID,ERR_DEVICE_ERROR);
  429. return Result;
  430. }
  431. p->Inited = 1;
  432. p->ForceUpdate = 1;
  433. UpdateInputDirection(p,0);
  434. OverlayUpdateFX(p,1);
  435. OverlayUpdateShow(p,0);
  436. if (p->Primary && !p->TurningOff)
  437. WinInvalidate(&p->Viewport,1);
  438. }
  439. }
  440. else
  441. if (p->Input.Type != PACKET_NONE)
  442. return ERR_INVALID_DATA;
  443. return ERR_NONE;
  444. }
  445. static int UpdateBackground(overlay* p)
  446. {
  447. if (p->DoPowerOff)
  448. {
  449. p->TurningOff = 1;
  450. if (p->Background)
  451. {
  452. IDCTRestore(NULL,&p->Backup); // free old backup
  453. if (!p->AccelIDCT || p->AccelIDCT->Get(p->AccelIDCT,IDCT_BACKUP,&p->Backup,sizeof(idctbackup))!=ERR_NONE)
  454. UpdateInput(p);
  455. }
  456. else
  457. {
  458. if (p->AccelIDCT && p->Backup.Format.Pixel.Flags)
  459. {
  460. p->AccelIDCT->Set(p->AccelIDCT,IDCT_BACKUP,&p->Backup,sizeof(idctbackup));
  461. p->AccelIDCT->Set(p->AccelIDCT,FLOW_RESEND,NULL,0);
  462. }
  463. else
  464. {
  465. node* Player = Context()->Player;
  466. UpdateInput(p);
  467. if (p->Inited && Player)
  468. Player->Set(Player,PLAYER_UPDATEVIDEO,NULL,0); 
  469. }
  470. IDCTRestore(NULL,&p->Backup); // free backup in any case
  471. }
  472. p->TurningOff = 0;
  473. }
  474. return ERR_NONE;
  475. }
  476. static bool_t PitchChanged(const packetformat* Current, const packetformat* New)
  477. {
  478. if (Current && Current->Type == PACKET_VIDEO && New && New->Type == PACKET_VIDEO)
  479. {
  480. video Tmp = New->Format.Video;
  481. Tmp.Pitch = Current->Format.Video.Pitch;
  482. return EqVideo(&Current->Format.Video,&Tmp);
  483. }
  484. return 0;
  485. }
  486. int OverlaySet(overlay* p,int No,const void* Data,int Size)
  487. {
  488. int Result = ERR_INVALID_PARAM;
  489. switch (No)
  490. {
  491. case NODE_SETTINGSCHANGED:
  492. p->ForceUpdate = 1;
  493. break;
  494. case OUT_INPUT: SETVALUE(p->Pin,pin,ERR_NONE); break;
  495. case OUT_TOTAL: SETVALUE(p->Total,int,ERR_NONE); break;
  496. case OUT_DROPPED: SETVALUE(p->Dropped,int,ERR_NONE); break;
  497. case OUT_INPUT|PIN_FORMAT:
  498. if (p->Inited && (
  499. PitchChanged(&p->Input,(const packetformat*)Data) ||
  500. PacketFormatRotatedVideo(&p->Input,(const packetformat*)Data,DIR_SWAPXY|DIR_MIRRORLEFTRIGHT|DIR_MIRRORUPDOWN)))
  501. {
  502. PacketFormatCopy(&p->Input,(const packetformat*)Data);
  503. UpdateInputDirection(p,0);
  504. Result = OverlayUpdateFX(p,1);
  505. }
  506. else
  507. SETPACKETFORMAT(p->Input,packetformat,UpdateInput(p)); 
  508. break;
  509. case FLOW_BACKGROUND: SETVALUECMP(p->Background,bool_t,UpdateBackground(p),EqBool); break;
  510. case VOUT_PLAY: SETVALUE(p->Play,bool_t,ERR_NONE); break;
  511. case VOUT_UPDATING: SETVALUECMP(p->Updating,bool_t,Updating(p),EqBool); break;
  512. case VOUT_CLIPPING: SETVALUE(p->Clipping,bool_t,OverlayUpdateShow(p,0)); break;
  513. case VOUT_VISIBLE: SETVALUE(p->Visible,bool_t,OverlayUpdateShow(p,0)); break;
  514. case VOUT_AUTOPREROTATE: SETVALUE(p->AutoPrerotate,bool_t,UpdateInputDirection(p,1)); break;
  515. case VOUT_ASPECT: SETVALUECMP(p->Aspect,fraction,OverlayUpdateFX(p,0),EqFrac); break;
  516. case VOUT_FX: SETVALUE(p->OrigFX,blitfx,OverlayUpdateFX(p,0)); break;
  517. case VOUT_FULLSCREEN: SETVALUECMP(p->FullScreenViewport,bool_t,OverlayUpdateFX(p,0),EqBool); break;
  518. case VOUT_VIEWPORT:
  519. if (Size == sizeof(rect))
  520. {
  521. Result = ERR_NONE;
  522. if (!EqRect(&p->Viewport,(const rect*)Data))
  523. {
  524. p->Viewport = *(const rect*)Data;
  525. p->ForceUpdate = 1; // when in updating
  526. OverlayUpdateFX(p,1);
  527. }
  528. }
  529. break;
  530. case FLOW_FLUSH:
  531. p->Dirty = 1;
  532. break;
  533. case VOUT_RESET:
  534. if (p->Inited && p->Reset)
  535. {
  536. p->Reset(p);
  537. OverlayUpdateFX(p,1);
  538. }
  539. Result = ERR_NONE;
  540. break;
  541. }
  542. return Result;
  543. }
  544. static const nodedef Overlay =
  545. {
  546. sizeof(overlay)|CF_ABSTRACT,
  547. OVERLAY_CLASS,
  548. VOUT_CLASS,
  549. PRI_DEFAULT,
  550. (nodecreate)Create,
  551. (nodedelete)Delete,
  552. };
  553. void Overlay_Init()
  554. {
  555. NodeRegisterClass(&Overlay);
  556. }
  557. void Overlay_Done()
  558. {
  559. NodeUnRegisterClass(OVERLAY_CLASS);
  560. }