Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3763 lines
142 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * **************************
  4. * * DirectDraw SAMPLE CODE *
  5. * **************************
  6. *
  7. * Module Name: ddvideo.c
  8. *
  9. * Content: DirectDraw Videoports implementation
  10. *
  11. * Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
  12. * Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
  13. \*****************************************************************************/
  14. #include "glint.h"
  15. #include "tag.h"
  16. //#include <mmsystem.h>
  17. #include "dma.h"
  18. //@@BEGIN_DDKSPLIT
  19. #ifdef W95_DDRAW_VIDEO
  20. // Define P3R3DX_VIDEO to allow use of 32bit Macros in ramdac.h
  21. #define P3R3DX_VIDEO 1
  22. #include "ramdac.h"
  23. #include <dvp.h>
  24. extern DWORD CALLBACK __VD_AutoflipOverlay ( void );
  25. extern DWORD CALLBACK __VD_AutoupdateOverlay ( void );
  26. #if 0
  27. #define P2_VIDPORT_WIDTH 768
  28. #define P2_VIDPORT_HEIGHT 288
  29. #endif
  30. // how many DrawOverlay calls to wait after an UpdateOverlay()
  31. // generally 1
  32. #define OVERLAY_UPDATE_WAIT 1
  33. // how many DrawOverlay calls to wait after a SetPosition()
  34. // generally 1
  35. #define OVERLAY_SETPOS_WAIT 1
  36. // how many DrawOverlay calls between repaints (0=no repaints)
  37. // generally 5-15
  38. #define OVERLAY_CYCLE_WAIT 15
  39. // How many "DrawOverlay calls" a speedy DrawOverlay is worth.
  40. // Generally 1
  41. #define OVERLAY_DRAWOVERLAY_SPEED 1
  42. // How many "DrawOverlay calls" a pretty DrawOverlay is worth.
  43. // Generally the same as OVERLAY_CYCLE_WAIT, or 1 if it is 0.
  44. #define OVERLAY_DRAWOVERLAY_PRETTY 15
  45. // How long in milliseconds to wait for the videoport before timing out.
  46. #define OVERLAY_VIDEO_PORT_TIMEOUT 100
  47. static BOOL g_bFlipVideoPortDoingAutoflip = FALSE;
  48. //-----------------------------------------------------------------------------
  49. //
  50. // __VD_PixelOffsetFromMemoryBase
  51. //
  52. // Calculates the offset from the memory base as the chip sees it. This is
  53. // relative to the base address in the chip and is in pixels
  54. //
  55. //-----------------------------------------------------------------------------
  56. long __inline
  57. __VD_PixelOffsetFromMemoryBase(
  58. P3_THUNKEDDATA* pThisDisplay,
  59. LPDDRAWI_DDRAWSURFACE_LCL pLcl)
  60. {
  61. DWORD lOffset;
  62. lOffset = DDSurf_SurfaceOffsetFromMemoryBase(pThisDisplay, pLcl);
  63. // Work out pixel offset into the framestore
  64. if (DDSurf_BitDepth(pLcl) == 24)
  65. {
  66. lOffset = lOffset / 3;
  67. }
  68. else
  69. {
  70. lOffset = lOffset >> DDSurf_GetPixelShift(pLcl);
  71. }
  72. return lOffset;
  73. } // __VD_PixelOffsetFromMemoryBase
  74. // Debug function to dump a video port description
  75. #if DBG
  76. //-----------------------------------------------------------------------------
  77. //
  78. // __VD_FillYUVSurface
  79. //
  80. //-----------------------------------------------------------------------------
  81. static void
  82. __VD_FillYUVSurface(
  83. LPDDRAWI_DDRAWSURFACE_LCL lpLcl,
  84. DWORD Value)
  85. {
  86. BYTE* pCurrentLine = (BYTE*)lpLcl->lpGbl->fpVidMem;
  87. WORD x, y;
  88. WORD* pSurface;
  89. WORD CurrentColor = (WORD)(Value & 0xFFFF);
  90. for (y = 0; y < lpLcl->lpGbl->wHeight; y++)
  91. {
  92. pSurface = (WORD*)pCurrentLine;
  93. for (x = 0; x < lpLcl->lpGbl->wWidth; x++)
  94. {
  95. // YUV Surface is 16Bits
  96. *pSurface++ = CurrentColor;
  97. }
  98. pCurrentLine += lpLcl->lpGbl->lPitch;
  99. if ((pCurrentLine - (31 << 1)) <= (BYTE*)pSurface)
  100. {
  101. while (pSurface++ < (WORD*)pCurrentLine)
  102. {
  103. *pSurface = 0xFFFF;
  104. }
  105. }
  106. }
  107. } // __VD_FillYUVSurface
  108. //-----------------------------------------------------------------------------
  109. //
  110. // __VD_DumpVPDesc
  111. //
  112. //-----------------------------------------------------------------------------
  113. static void
  114. __VD_DumpVPDesc(
  115. int Level,
  116. DDVIDEOPORTDESC vp)
  117. {
  118. #define CONNECT_REPORT(param) \
  119. if (vp.VideoPortType.dwFlags & DDVPCONNECT_##param) \
  120. { \
  121. DISPDBG((Level, " " #param)); \
  122. }
  123. DISPDBG((Level,"Port Size: %d x %d", vp.dwFieldWidth, vp.dwFieldHeight));
  124. DISPDBG((Level,"VBI Width: %d", vp.dwVBIWidth));
  125. DISPDBG((Level,"uS/Field: %d", vp.dwMicrosecondsPerField));
  126. DISPDBG((Level,"Pixels/Sec: %d", vp.dwMaxPixelsPerSecond));
  127. DISPDBG((Level,"Port ID: %d", vp.dwVideoPortID));
  128. DISPDBG((Level,"Flags: "));
  129. CONNECT_REPORT(INTERLACED);
  130. CONNECT_REPORT(VACT);
  131. CONNECT_REPORT(INVERTPOLARITY);
  132. CONNECT_REPORT(DOUBLECLOCK);
  133. CONNECT_REPORT(DISCARDSVREFDATA);
  134. CONNECT_REPORT(HALFLINE);
  135. CONNECT_REPORT(SHAREEVEN);
  136. CONNECT_REPORT(SHAREODD);
  137. DISPDBG((Level,"Connection GUID:"));
  138. if (MATCH_GUID((vp.VideoPortType.guidTypeID), DDVPTYPE_E_HREFH_VREFH))
  139. {
  140. DISPDBG((Level, " DDVPTYPE_E_HREFH_VREFH"));
  141. }
  142. else if (MATCH_GUID((vp.VideoPortType.guidTypeID), DDVPTYPE_E_HREFH_VREFL))
  143. {
  144. DISPDBG((Level, " DDVPTYPE_E_HREFH_VREFL"));
  145. }
  146. else if (MATCH_GUID((vp.VideoPortType.guidTypeID), DDVPTYPE_E_HREFL_VREFH))
  147. {
  148. DISPDBG((Level, " DDVPTYPE_E_HREFL_VREFH"));
  149. }
  150. else if (MATCH_GUID((vp.VideoPortType.guidTypeID), DDVPTYPE_E_HREFL_VREFL))
  151. {
  152. DISPDBG((Level, " DDVPTYPE_E_HREFL_VREFL"));
  153. }
  154. else if (MATCH_GUID((vp.VideoPortType.guidTypeID), DDVPTYPE_CCIR656))
  155. {
  156. DISPDBG((Level, " CCIR656"));
  157. }
  158. else if (MATCH_GUID((vp.VideoPortType.guidTypeID), DDVPTYPE_BROOKTREE))
  159. {
  160. DISPDBG((Level, " BROOKTREE"));
  161. }
  162. else if (MATCH_GUID((vp.VideoPortType.guidTypeID), DDVPTYPE_PHILIPS))
  163. {
  164. DISPDBG((Level, " PHILIPS"));
  165. }
  166. else
  167. {
  168. DISPDBG((ERRLVL," ERROR: Unknown connection type!"));
  169. }
  170. } // __VD_DumpVPDesc
  171. #define DUMPVPORT(a, b) __VD_DumpVPDesc(a, b);
  172. #define FILLYUV(a, c) __VD_FillYUVSurface(a, c);
  173. #else
  174. #define DUMPVPORT(a, b)
  175. #define FILLYUV(a, c)
  176. #endif
  177. //-----------------------------------------------------------------------------
  178. //
  179. // __VD_CheckVideoPortStatus
  180. //
  181. // Checks to see if the videoport seems to be OK. If it is,
  182. // we return TRUE. if bWait is set then we hang around and
  183. // try to decide if the Video is OK.
  184. //
  185. //-----------------------------------------------------------------------------
  186. #define ERROR_TIMOUT_VP 470000
  187. #define ERROR_TIMOUT_COUNT 50
  188. BOOL
  189. __VD_CheckVideoPortStatus(
  190. P3_THUNKEDDATA* pThisDisplay,
  191. BOOL bWait)
  192. {
  193. DWORD dwMClock;
  194. DWORD dwCurrentLine;
  195. DWORD dwCurrentIndex;
  196. DWORD dwNewLine;
  197. DWORD dwNewMClock;
  198. // Is the videoport on?
  199. if (!pThisDisplay->VidPort.bActive) return FALSE;
  200. // Read the current MClock
  201. dwMClock = READ_GLINT_CTRL_REG(MClkCount);
  202. if (bWait) pThisDisplay->VidPort.bResetStatus = TRUE;
  203. if (pThisDisplay->VidPort.bResetStatus)
  204. {
  205. dwCurrentLine = READ_GLINT_CTRL_REG(VSACurrentLine);
  206. dwCurrentIndex = READ_GLINT_CTRL_REG(VSAVideoAddressIndex);
  207. // At start of day, record the MClock time for the start of the line
  208. pThisDisplay->VidPort.dwStartLineTime = dwMClock;
  209. // Also record the starting line
  210. pThisDisplay->VidPort.dwStartLine = dwCurrentLine;
  211. pThisDisplay->VidPort.dwStartIndex = dwCurrentIndex;
  212. pThisDisplay->VidPort.bResetStatus = FALSE;
  213. return TRUE;
  214. }
  215. if (bWait)
  216. {
  217. do
  218. {
  219. // Read the current line
  220. dwCurrentLine = READ_GLINT_CTRL_REG(VSACurrentLine);
  221. // OK, a line of video should take approx:
  222. // 1 Second / 50-60 fields/second / 300 lines =
  223. // 0.000066 = 66uS.
  224. // If the MClock is running at, say 70Mhz that is 0.000000014 seconds/clock
  225. // So a line should take 0.000066 / 0.000000014 MClocks = ~4700 MClocks
  226. // Wait for 100 times longer than it should take to draw a line....
  227. do
  228. {
  229. dwNewMClock = READ_GLINT_CTRL_REG(MClkCount);
  230. } while (dwNewMClock < (dwMClock + ERROR_TIMOUT_VP));
  231. dwNewLine = READ_GLINT_CTRL_REG(VSACurrentLine);
  232. // Has the line count advanced?
  233. if (dwNewLine == dwCurrentLine)
  234. {
  235. dwCurrentIndex = READ_GLINT_CTRL_REG(VSAVideoAddressIndex);
  236. if (dwCurrentIndex == pThisDisplay->VidPort.dwStartIndex)
  237. {
  238. // Disable the videoport if the error count goes to high
  239. pThisDisplay->VidPort.dwErrorCount++;
  240. // Reset the status as we need to make sure the timer restarts.
  241. pThisDisplay->VidPort.bResetStatus = TRUE;
  242. if (pThisDisplay->VidPort.dwErrorCount > ERROR_TIMOUT_COUNT)
  243. {
  244. DISPDBG((WRNLVL,"StartLine: %d, CurrentLine: %d, StartIndex: %d, CurrentIndex: %d", pThisDisplay->VidPort.dwStartLine,
  245. dwCurrentLine, pThisDisplay->VidPort.dwStartIndex, dwCurrentIndex));
  246. DISPDBG((ERRLVL,"ERROR: VideoStream not working!"));
  247. pThisDisplay->VidPort.bActive = FALSE;
  248. return FALSE;
  249. }
  250. }
  251. else
  252. {
  253. pThisDisplay->VidPort.dwErrorCount = 0;
  254. pThisDisplay->VidPort.bResetStatus = TRUE;
  255. }
  256. }
  257. // If it has flag a reset and break
  258. else
  259. {
  260. pThisDisplay->VidPort.dwErrorCount = 0;
  261. pThisDisplay->VidPort.bResetStatus = TRUE;
  262. }
  263. } while (pThisDisplay->VidPort.dwErrorCount);
  264. }
  265. else
  266. {
  267. // Has the line count advanced?
  268. if (dwMClock > (pThisDisplay->VidPort.dwStartLineTime + ERROR_TIMOUT_VP))
  269. {
  270. dwCurrentLine = READ_GLINT_CTRL_REG(VSACurrentLine);
  271. if (pThisDisplay->VidPort.dwStartLine == dwCurrentLine)
  272. {
  273. dwCurrentIndex = READ_GLINT_CTRL_REG(VSAVideoAddressIndex);
  274. if (dwCurrentIndex == pThisDisplay->VidPort.dwStartIndex)
  275. {
  276. // Disable the videoport if the error count goes to high
  277. pThisDisplay->VidPort.dwErrorCount++;
  278. DISPDBG((WRNLVL,"ERROR: Timeout at %d", dwMClock));
  279. // Reset the status as we need to make sure the timer restarts.
  280. pThisDisplay->VidPort.bResetStatus = TRUE;
  281. // Disable the videoport
  282. if (pThisDisplay->VidPort.dwErrorCount > ERROR_TIMOUT_COUNT)
  283. {
  284. DISPDBG((WRNLVL,"StartLine: %d, CurrentLine: %d, StartIndex: %d, CurrentIndex: %d", pThisDisplay->VidPort.dwStartLine,
  285. dwCurrentLine, pThisDisplay->VidPort.dwStartIndex, dwCurrentIndex));
  286. DISPDBG((ERRLVL,"ERROR: VideoStream not working!"));
  287. pThisDisplay->VidPort.bActive = FALSE;
  288. }
  289. }
  290. else
  291. {
  292. pThisDisplay->VidPort.dwErrorCount = 0;
  293. pThisDisplay->VidPort.bResetStatus = TRUE;
  294. }
  295. }
  296. else
  297. {
  298. // Reset the error status
  299. pThisDisplay->VidPort.dwErrorCount = 0;
  300. pThisDisplay->VidPort.bResetStatus = TRUE;
  301. }
  302. }
  303. }
  304. return pThisDisplay->VidPort.bActive;
  305. } // __VD_CheckVideoPortStatus
  306. //-----------------------------------------------------------------------------
  307. //
  308. // DdUpdateVideoPort
  309. //
  310. // This required function sets up the video port
  311. //
  312. //-----------------------------------------------------------------------------
  313. DWORD CALLBACK
  314. DdUpdateVideoPort (
  315. LPDDHAL_UPDATEVPORTDATA pInput)
  316. {
  317. DWORD i;
  318. P3_THUNKEDDATA* pThisDisplay;
  319. DWORD dwCurrentDisplay;
  320. DWORD dwLineScale;
  321. DWORD dwEnable;
  322. DWORD dwDiscard;
  323. DWORD XScale = 0;
  324. DWORD YScale = 0;
  325. VMIREQUEST In;
  326. VMIREQUEST Out;
  327. DWORD dwSrcPixelWidth;
  328. DWORD dwSrcHeight;
  329. DWORD dwDstPixelWidth;
  330. DWORD dwDstHeight;
  331. StreamsRegister_Settings PortSettings;
  332. StreamsRegister_VSPartialConfigA VSPartialA;
  333. GET_THUNKEDDATA(pThisDisplay, pInput->lpDD->lpGbl);
  334. DISPDBG((DBGLVL,"** In DdUpdateVideoPort, dwFlags = %d", pInput->dwFlags));
  335. DUMPVPORT(DBGLVL ,pInput->lpVideoPort->ddvpDesc);
  336. pThisDisplay->pGLInfo->dwVSACaughtFrames = 0;
  337. pThisDisplay->pGLInfo->dwVSADroppedFrames = 0;
  338. pThisDisplay->pGLInfo->dwVSALastDropped = 0;
  339. if (pInput->dwFlags == DDRAWI_VPORTSTOP)
  340. {
  341. DISPDBG((DBGLVL," Stopping VideoPort"));
  342. // Stop any autoflipping.
  343. if ( pThisDisplay->pGLInfo->dwPeriodVideoVBL != 0 )
  344. {
  345. if ( pThisDisplay->pGLInfo->dwVideoEventHandle == (DWORD)NULL )
  346. {
  347. DISPDBG((DBGLVL,"** DdUpdateVideoPort - VPORTSTOP - was autoflipping on bogus event handle."));
  348. }
  349. pThisDisplay->pGLInfo->dwPeriodVideoVBL = 0;
  350. pThisDisplay->pGLInfo->dwCountdownVideoVBL = 0;
  351. DISPDBG((DBGLVL,"** DdUpdateVideoPort - VPORTSTOP - autoflipping now disabled."));
  352. }
  353. WAIT_GLINT_FIFO(2);
  354. pThisDisplay->VidPort.bActive = FALSE;
  355. pThisDisplay->VidPort.bResetStatus = TRUE;
  356. pThisDisplay->VidPort.dwErrorCount = 0;
  357. pThisDisplay->VidPort.lpSurf[0] = NULL;
  358. pThisDisplay->VidPort.lpSurf[1] = NULL;
  359. pThisDisplay->VidPort.lpSurf[2] = NULL;
  360. // Disable the interrupt.
  361. dwEnable = READ_GLINT_CTRL_REG(IntEnable);
  362. dwEnable &= ~INTR_ENABLE_VIDSTREAM_A;
  363. LOAD_GLINT_REG(IntEnable, dwEnable);
  364. // Disable the videoport
  365. LOAD_GLINT_REG(VSAControl, __PERMEDIA_DISABLE);
  366. }
  367. else if ((pInput->dwFlags == DDRAWI_VPORTSTART) ||
  368. (pInput->dwFlags == DDRAWI_VPORTUPDATE))
  369. {
  370. DISPDBG((DBGLVL," Starting/Updating VideoPort"));
  371. pThisDisplay->VidPort.lpSurf[0] = NULL;
  372. pThisDisplay->VidPort.lpSurf[1] = NULL;
  373. pThisDisplay->VidPort.lpSurf[2] = NULL;
  374. // Videoport only on P2's, therefore much more fifo room
  375. WAIT_GLINT_FIFO(100);
  376. // Disable the videoport so we can setup a new configuration
  377. LOAD_GLINT_REG(VSAControl, __PERMEDIA_DISABLE);
  378. // How many surfaces do we have?
  379. if (pInput->lpVideoInfo->dwVPFlags & DDVP_AUTOFLIP)
  380. {
  381. if (pInput->dwNumAutoflip == 0) pThisDisplay->VidPort.dwNumSurfaces = 1;
  382. else pThisDisplay->VidPort.dwNumSurfaces = pInput->dwNumAutoflip;
  383. DISPDBG((DBGLVL,"Surfaces passed in (AUTOFLIP) = %d", pThisDisplay->VidPort.dwNumSurfaces));
  384. for(i = 0; i < pThisDisplay->VidPort.dwNumSurfaces; i++)
  385. {
  386. LPDDRAWI_DDRAWSURFACE_LCL pLcl = (pInput->lplpDDSurface[i])->lpLcl;
  387. if (pLcl->ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
  388. {
  389. DISPDBG((DBGLVL,"Surface %d is the FRONTBUFFER", i));
  390. dwCurrentDisplay = i;
  391. }
  392. FILLYUV(pLcl, i * 0x4444);
  393. // Store away the offset to this surface
  394. pThisDisplay->VidPort.dwSurfacePointer[i] = pLcl->lpGbl->fpVidMem;
  395. pThisDisplay->VidPort.lpSurf[i] = pLcl;
  396. }
  397. // Start or continue any autoflipping.
  398. #if DBG
  399. if ( pThisDisplay->pGLInfo->dwVideoEventHandle == (DWORD)NULL )
  400. {
  401. DISPDBG((DBGLVL,"** DdUpdateVideoPort - trying to autoflipping using bogus event handle."));
  402. }
  403. #endif
  404. if ( pThisDisplay->pGLInfo->dwPeriodVideoVBL == 0 )
  405. {
  406. pThisDisplay->pGLInfo->dwPeriodVideoVBL = OVERLAY_AUTOFLIP_PERIOD;
  407. pThisDisplay->pGLInfo->dwCountdownVideoVBL = OVERLAY_AUTOFLIP_PERIOD;
  408. DISPDBG((DBGLVL,"** DdUpdateVideoPort - autoflipping now enabled."));
  409. }
  410. }
  411. else
  412. {
  413. LPDDRAWI_DDRAWSURFACE_LCL lpNextSurf = (pInput->lplpDDSurface[0])->lpLcl;
  414. i = 0;
  415. // Stop any autoflipping.
  416. if ( pThisDisplay->pGLInfo->dwPeriodVideoVBL != 0 )
  417. {
  418. #if DBG
  419. if ( pThisDisplay->pGLInfo->dwVideoEventHandle == (DWORD)NULL )
  420. {
  421. DISPDBG((DBGLVL,"** DdUpdateVideoPort - was trying to autoflip using bogus event handle."));
  422. }
  423. #endif
  424. pThisDisplay->pGLInfo->dwPeriodVideoVBL = 0;
  425. pThisDisplay->pGLInfo->dwCountdownVideoVBL = 0;
  426. DISPDBG((DBGLVL,"** DdUpdateVideoPort - autoflipping now disabled."));
  427. }
  428. while (lpNextSurf != NULL)
  429. {
  430. if (lpNextSurf->ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
  431. {
  432. DISPDBG((DBGLVL,"Surface %d is the FRONTBUFFER", i));
  433. dwCurrentDisplay = i;
  434. }
  435. // Store away the offset to this surface
  436. pThisDisplay->VidPort.dwSurfacePointer[i] = lpNextSurf->lpGbl->fpVidMem;
  437. pThisDisplay->VidPort.lpSurf[i] = lpNextSurf;
  438. FILLYUV(lpNextSurf, i * 0x4444);
  439. // Is there another surface in the chain?
  440. if (lpNextSurf->lpAttachList)
  441. {
  442. lpNextSurf = lpNextSurf->lpAttachList->lpAttached;
  443. if (lpNextSurf == NULL) break;
  444. }
  445. else break;
  446. // Have we spun around the loop?
  447. if (lpNextSurf == (pInput->lplpDDSurface[0])->lpLcl) break;
  448. i++;
  449. }
  450. pThisDisplay->VidPort.dwNumSurfaces = i + 1;
  451. DISPDBG((DBGLVL,"Surfaces passed in (Not AutoFlip) = %d", (i + 1)));
  452. }
  453. DISPDBG((DBGLVL," Addresses: 0x%x, 0x%x, 0x%x",
  454. pThisDisplay->VidPort.dwSurfacePointer[0],
  455. pThisDisplay->VidPort.dwSurfacePointer[1],
  456. pThisDisplay->VidPort.dwSurfacePointer[2]));
  457. // Remember the size of the vertical blanking interval and the size of the frame.
  458. pThisDisplay->VidPort.dwFieldWidth = pInput->lpVideoPort->ddvpDesc.dwFieldWidth;
  459. pThisDisplay->VidPort.dwFieldHeight = pInput->lpVideoPort->ddvpDesc.dwFieldHeight;
  460. // Setup the Host register so that it points to the same surface we will display.
  461. pThisDisplay->VidPort.dwCurrentHostFrame = dwCurrentDisplay;
  462. dwSrcPixelWidth = (pInput->lpVideoInfo->dwVPFlags & DDVP_CROP) ?
  463. (pInput->lpVideoInfo->rCrop.right - pInput->lpVideoInfo->rCrop.left) :
  464. pInput->lpVideoPort->ddvpDesc.dwFieldWidth;
  465. dwSrcHeight = (pInput->lpVideoInfo->dwVPFlags & DDVP_CROP) ?
  466. (pInput->lpVideoInfo->rCrop.bottom - pInput->lpVideoInfo->rCrop.top) :
  467. pInput->lpVideoPort->ddvpDesc.dwFieldHeight;
  468. DISPDBG((DBGLVL,"Source Width: %d", dwSrcPixelWidth));
  469. DISPDBG((DBGLVL,"Source Height: %d", dwSrcHeight));
  470. // Do we need to prescale the surface?
  471. if (pInput->lpVideoInfo->dwVPFlags & DDVP_PRESCALE)
  472. {
  473. DISPDBG((DBGLVL,"Prescale Width:%d, Height:%d",
  474. pInput->lpVideoInfo->dwPrescaleWidth,
  475. pInput->lpVideoInfo->dwPrescaleHeight));
  476. if ((pInput->lpVideoInfo->dwPrescaleWidth != 0) &&
  477. (pInput->lpVideoInfo->dwPrescaleWidth != pInput->lpVideoPort->ddvpDesc.dwFieldWidth))
  478. {
  479. XScale = pInput->lpVideoPort->ddvpDesc.dwFieldWidth / pInput->lpVideoInfo->dwPrescaleWidth;
  480. switch(XScale)
  481. {
  482. case 2:
  483. XScale = 1;
  484. break;
  485. case 4:
  486. XScale = 2;
  487. break;
  488. case 8:
  489. XScale = 3;
  490. break;
  491. default:
  492. XScale = 0;
  493. break;
  494. }
  495. }
  496. if ((pInput->lpVideoInfo->dwPrescaleHeight != 0) &&
  497. (pInput->lpVideoInfo->dwPrescaleHeight != pInput->lpVideoPort->ddvpDesc.dwFieldHeight))
  498. {
  499. YScale = pInput->lpVideoPort->ddvpDesc.dwFieldHeight / pInput->lpVideoInfo->dwPrescaleHeight;
  500. switch(YScale)
  501. {
  502. case 2:
  503. YScale = 1;
  504. break;
  505. case 4:
  506. YScale = 2;
  507. break;
  508. case 8:
  509. YScale = 3;
  510. break;
  511. default:
  512. YScale = 0;
  513. break;
  514. }
  515. }
  516. // HACK! HACK!
  517. dwDstPixelWidth = pInput->lpVideoInfo->dwPrescaleWidth;
  518. dwDstHeight = pInput->lpVideoInfo->dwPrescaleHeight;
  519. }
  520. else
  521. {
  522. dwDstPixelWidth = dwSrcPixelWidth;
  523. dwDstHeight = dwSrcHeight;
  524. }
  525. DISPDBG((DBGLVL,"Dest Width: %d", dwDstPixelWidth));
  526. DISPDBG((DBGLVL,"Dest Height: %d", dwDstHeight));
  527. // Need to setup the registers differently if we are mirroring top to bottom
  528. if (pInput->lpVideoInfo->dwVPFlags & DDVP_MIRRORUPDOWN)
  529. {
  530. // Make sure we aren't prescaling...
  531. if (YScale == 0)
  532. {
  533. pThisDisplay->VidPort.dwSurfacePointer[0] += (pInput->lplpDDSurface[0])->lpLcl->lpGbl->lPitch * (pInput->lpVideoPort->ddvpDesc.dwFieldHeight);
  534. pThisDisplay->VidPort.dwSurfacePointer[1] += (pInput->lplpDDSurface[0])->lpLcl->lpGbl->lPitch * (pInput->lpVideoPort->ddvpDesc.dwFieldHeight);
  535. pThisDisplay->VidPort.dwSurfacePointer[2] += (pInput->lplpDDSurface[0])->lpLcl->lpGbl->lPitch * (pInput->lpVideoPort->ddvpDesc.dwFieldHeight);
  536. }
  537. else
  538. {
  539. pThisDisplay->VidPort.dwSurfacePointer[0] += (pInput->lplpDDSurface[0])->lpLcl->lpGbl->lPitch * (pInput->lpVideoInfo->dwPrescaleHeight);
  540. pThisDisplay->VidPort.dwSurfacePointer[1] += (pInput->lplpDDSurface[0])->lpLcl->lpGbl->lPitch * (pInput->lpVideoInfo->dwPrescaleHeight);
  541. pThisDisplay->VidPort.dwSurfacePointer[2] += (pInput->lplpDDSurface[0])->lpLcl->lpGbl->lPitch * (pInput->lpVideoInfo->dwPrescaleHeight);
  542. }
  543. }
  544. if (pInput->lpVideoPort->ddvpDesc.VideoPortType.dwPortWidth == 8) dwLineScale = 0;
  545. else dwLineScale = 1;
  546. // Setup the configuration of the VideoPort
  547. // This is done by a call to the VXD as the registers that are touched have bits
  548. // that are shared with the TV Out and the ROM.
  549. // ***********************
  550. // UnitMode: Typically setup for 8 or 16 bit YUV input port.
  551. // GPMode: Not used.
  552. // HREF_POL_A: Polarity active of HREF
  553. // VREF_POL_A: Polarity active of VREF
  554. // VActive: Wether the VACT signal is active high or low (if there is one).
  555. // Can be set to the inverse of the HREF as a good guess(?)
  556. // UseField: Stream A on or off
  557. // FieldPolA: How to treat the field polarity of stream A
  558. // FieldEdgeA:
  559. // VActiveVBIA:
  560. // InterlaceA: Interlaced data on A?
  561. // ReverseA: Should we reverse the YUV data on A
  562. // ***********************
  563. PortSettings.UnitMode = ((pInput->lpVideoPort->ddvpDesc.VideoPortType.dwPortWidth == 8) ? STREAMS_MODE_STREAMA_STREAMB : STREAMS_MODE_STREAMA_WIDE16);
  564. In.dwSize = sizeof(VMIREQUEST);
  565. In.dwRegister = P2_VSSettings;
  566. In.dwCommand = *((DWORD*)(&PortSettings));
  567. In.dwDevNode = pThisDisplay->dwDevNode;
  568. In.dwOperation = GLINT_VMI_WRITE;
  569. VXDCommand(GLINT_VMI_COMMAND, &In, sizeof(VMIREQUEST), &Out, sizeof(VMIREQUEST));
  570. VSPartialA.HRefPolarityA = ((pThisDisplay->VidPort.dwStreamAFlags & VIDEOPORT_HREF_ACTIVE_HIGH) ? __PERMEDIA_ENABLE : __PERMEDIA_DISABLE);
  571. VSPartialA.VRefPolarityA = ((pThisDisplay->VidPort.dwStreamAFlags & VIDEOPORT_VREF_ACTIVE_HIGH) ? __PERMEDIA_ENABLE : __PERMEDIA_DISABLE);
  572. // There is no setting in DirectX for the polarity of the active signal. Therefore we must assume one value. This
  573. // has been chosen based on the setting that gives the correct effect for a Bt827/829
  574. VSPartialA.VActivePolarityA = __PERMEDIA_ENABLE;
  575. VSPartialA.UseFieldA = __PERMEDIA_DISABLE;
  576. VSPartialA.FieldPolarityA = ((pInput->lpVideoPort->ddvpDesc.VideoPortType.dwFlags & DDVPCONNECT_INVERTPOLARITY) ? __PERMEDIA_ENABLE : __PERMEDIA_DISABLE);
  577. VSPartialA.FieldEdgeA = __PERMEDIA_DISABLE;
  578. VSPartialA.VActiveVBIA = __PERMEDIA_DISABLE;
  579. VSPartialA.InterlaceA = __PERMEDIA_ENABLE;
  580. VSPartialA.ReverseDataA = __PERMEDIA_ENABLE;
  581. In.dwSize = sizeof(VMIREQUEST);
  582. In.dwRegister = P2_VSAPartialConfig;
  583. In.dwCommand = *((DWORD*)(&VSPartialA));
  584. In.dwDevNode = pThisDisplay->dwDevNode;
  585. In.dwOperation = GLINT_VMI_WRITE;
  586. VXDCommand( GLINT_VMI_COMMAND, &In, sizeof(VMIREQUEST), &Out, sizeof(VMIREQUEST));
  587. // Setup Stream A
  588. if (pInput->lpVideoInfo->dwVPFlags & DDVP_SKIPEVENFIELDS)
  589. {
  590. dwDiscard = PM_VSACONTROL_DISCARD_1;
  591. DISPDBG((DBGLVL,"Skipping Even Fields"));
  592. }
  593. else if(pInput->lpVideoInfo->dwVPFlags & DDVP_SKIPODDFIELDS)
  594. {
  595. dwDiscard = PM_VSACONTROL_DISCARD_2;
  596. DISPDBG((DBGLVL,"Skipping Odd Fields"));
  597. }
  598. else dwDiscard = __PERMEDIA_DISABLE;
  599. LOAD_GLINT_REG(VSAControl, PM_VSACONTROL_VIDEO(__PERMEDIA_ENABLE) |
  600. PM_VSACONTROL_VBI(__PERMEDIA_DISABLE) |
  601. PM_VSACONTROL_BUFFER((pThisDisplay->VidPort.dwNumSurfaces == 3) ? 1 : 0) |
  602. PM_VSACONTROL_SCALEX(XScale) |
  603. PM_VSACONTROL_SCALEY(YScale) |
  604. PM_VSACONTROL_MIRRORY((pInput->lpVideoInfo->dwVPFlags & DDVP_MIRRORUPDOWN) ? __PERMEDIA_ENABLE : __PERMEDIA_DISABLE) |
  605. PM_VSACONTROL_MIRRORX((pInput->lpVideoInfo->dwVPFlags & DDVP_MIRRORLEFTRIGHT) ? __PERMEDIA_ENABLE : __PERMEDIA_DISABLE) |
  606. PM_VSACONTROL_DISCARD(dwDiscard) |
  607. PM_VSACONTROL_COMBINE((pInput->lpVideoInfo->dwVPFlags & DDVP_INTERLEAVE) ? __PERMEDIA_ENABLE : __PERMEDIA_DISABLE) |
  608. PM_VSACONTROL_LOCKTOB(__PERMEDIA_DISABLE));
  609. // Point the register at the surface being used
  610. LOAD_GLINT_REG(VSAVideoAddressHost, pThisDisplay->VidPort.dwCurrentHostFrame);
  611. // Check on the video stride
  612. LOAD_GLINT_REG(VSAVideoStride, (((pInput->lplpDDSurface[0])->lpLcl->lpGbl->lPitch) >> 3));
  613. // Vertical data
  614. if (pInput->lpVideoInfo->dwVPFlags & DDVP_CROP)
  615. {
  616. LOAD_GLINT_REG(VSAVideoStartLine, pInput->lpVideoInfo->rCrop.top);
  617. LOAD_GLINT_REG(VSAVideoEndLine, pInput->lpVideoInfo->rCrop.top + dwDstHeight);
  618. }
  619. else
  620. {
  621. LOAD_GLINT_REG(VSAVideoStartLine, 0);
  622. LOAD_GLINT_REG(VSAVideoEndLine, dwDstHeight);
  623. }
  624. // Not using VBI, must disable (P2ST may not start up in a fixed state)
  625. LOAD_GLINT_REG(VSAVBIAddressHost, 0);
  626. LOAD_GLINT_REG(VSAVBIAddressIndex, 0);
  627. LOAD_GLINT_REG(VSAVBIAddress0, 0);
  628. LOAD_GLINT_REG(VSAVBIAddress1, 0);
  629. LOAD_GLINT_REG(VSAVBIAddress2, 0);
  630. LOAD_GLINT_REG(VSAVBIStride, 0);
  631. LOAD_GLINT_REG(VSAVBIStartLine, 0);
  632. LOAD_GLINT_REG(VSAVBIEndLine, 0);
  633. LOAD_GLINT_REG(VSAVBIStartData, 0);
  634. LOAD_GLINT_REG(VSAVBIEndData, 0);
  635. #define CLOCKS_PER_PIXEL 2
  636. // Horizontal data
  637. // If the
  638. if (pInput->lpVideoPort->ddvpDesc.VideoPortType.dwFlags & DDVPCONNECT_VACT)
  639. {
  640. // Set StartData and EndData to their limits and
  641. // let VACT tell us when we are getting active data.
  642. LOAD_GLINT_REG(VSAVideoStartData, 0);
  643. LOAD_GLINT_REG(VSAVideoEndData, (VIDEOPORT_MAX_FIELD_WIDTH) - 1);
  644. }
  645. else
  646. {
  647. if (pInput->lpVideoInfo->dwVPFlags & DDVP_CROP)
  648. {
  649. LOAD_GLINT_REG(VSAVideoStartData, (pInput->lpVideoInfo->rCrop.left * CLOCKS_PER_PIXEL));
  650. LOAD_GLINT_REG(VSAVideoEndData, (pInput->lpVideoInfo->rCrop.left * CLOCKS_PER_PIXEL) +
  651. ((dwDstPixelWidth / 2) * CLOCKS_PER_PIXEL));
  652. }
  653. else
  654. {
  655. LOAD_GLINT_REG(VSAVideoStartData, 0);
  656. LOAD_GLINT_REG(VSAVideoEndData, (dwDstPixelWidth * CLOCKS_PER_PIXEL));
  657. }
  658. }
  659. // Point at the surfaces
  660. LOAD_GLINT_REG(VSAVideoAddress0, ((pThisDisplay->VidPort.dwSurfacePointer[0] - pThisDisplay->dwScreenFlatAddr) >> 3));
  661. LOAD_GLINT_REG(VSAVideoAddress1, ((pThisDisplay->VidPort.dwSurfacePointer[1] - pThisDisplay->dwScreenFlatAddr) >> 3));
  662. LOAD_GLINT_REG(VSAVideoAddress2, ((pThisDisplay->VidPort.dwSurfacePointer[2] - pThisDisplay->dwScreenFlatAddr) >> 3));
  663. // Hook the VSYNC interrupt
  664. dwEnable = READ_GLINT_CTRL_REG(IntEnable);
  665. dwEnable |= INTR_ENABLE_VIDSTREAM_A;
  666. LOAD_GLINT_REG(IntEnable, dwEnable);
  667. LOAD_GLINT_REG(VSAInterruptLine, 0);
  668. pThisDisplay->VidPort.bActive = TRUE;
  669. pThisDisplay->VidPort.bResetStatus = TRUE;
  670. pThisDisplay->VidPort.dwErrorCount = 0;
  671. }
  672. pInput->ddRVal = DD_OK;
  673. return DDHAL_DRIVER_HANDLED;
  674. } // DdUpdateVideoPort
  675. //-----------------------------------------------------------------------------
  676. //
  677. // DDGetVideoPortConnectInfo
  678. //
  679. // Passes back the connect info to a client. Can be an array of
  680. // available VideoPort Type
  681. //
  682. //-----------------------------------------------------------------------------
  683. DWORD CALLBACK
  684. DDGetVideoPortConnectInfo(
  685. LPDDHAL_GETVPORTCONNECTDATA pInput)
  686. {
  687. P3_THUNKEDDATA* pThisDisplay;
  688. GET_THUNKEDDATA(pThisDisplay, pInput->lpDD->lpGbl);
  689. DISPDBG((DBGLVL,"** In DDGetVideoPortConnectInfo"));
  690. // P2 has 1 input and 1 output port, but DirectDraw
  691. // VPE only understands input ports (for now).
  692. if (pInput->dwPortId != 0)
  693. {
  694. DISPDBG((WRNLVL, " Invalid port ID: 0x%x", pInput->dwPortId));
  695. pInput->ddRVal = DDERR_INVALIDPARAMS;
  696. return(DDHAL_DRIVER_HANDLED);
  697. }
  698. // Fill in an array of connect info's.
  699. if (pInput->lpConnect == NULL)
  700. {
  701. DISPDBG((DBGLVL," Request for connect number, Port: 0x%x", pInput->dwPortId));
  702. pInput->dwNumEntries = VIDEOPORT_NUM_CONNECT_INFO;
  703. pInput->ddRVal = DD_OK;
  704. }
  705. else
  706. {
  707. DWORD dwNum;
  708. DDVIDEOPORTCONNECT ConnectInfo;
  709. DISPDBG((DBGLVL," Request for connect info, Port: 0x%x", pInput->dwPortId));
  710. ZeroMemory(&ConnectInfo, sizeof(DDVIDEOPORTCONNECT));
  711. ConnectInfo.dwSize = sizeof(DDVIDEOPORTCONNECT);
  712. ConnectInfo.dwFlags = DDVPCONNECT_VACT | DDVPCONNECT_DISCARDSVREFDATA
  713. | DDVPCONNECT_HALFLINE | DDVPCONNECT_INVERTPOLARITY;
  714. // 4 GUIDs, 2 Port widths (8 and 16 bits)
  715. for (dwNum = 0; dwNum < VIDEOPORT_NUM_CONNECT_INFO; dwNum++)
  716. {
  717. switch(dwNum)
  718. {
  719. case 0:
  720. ConnectInfo.guidTypeID = DDVPTYPE_E_HREFH_VREFH;
  721. ConnectInfo.dwPortWidth = 8;
  722. break;
  723. case 1:
  724. ConnectInfo.guidTypeID = DDVPTYPE_E_HREFH_VREFH;
  725. ConnectInfo.dwPortWidth = 16;
  726. break;
  727. case 2:
  728. ConnectInfo.guidTypeID = DDVPTYPE_E_HREFH_VREFL;
  729. ConnectInfo.dwPortWidth = 8;
  730. break;
  731. case 3:
  732. ConnectInfo.guidTypeID = DDVPTYPE_E_HREFH_VREFL;
  733. ConnectInfo.dwPortWidth = 16;
  734. break;
  735. case 4:
  736. ConnectInfo.guidTypeID = DDVPTYPE_E_HREFL_VREFH;
  737. ConnectInfo.dwPortWidth = 8;
  738. break;
  739. case 5:
  740. ConnectInfo.guidTypeID = DDVPTYPE_E_HREFL_VREFH;
  741. ConnectInfo.dwPortWidth = 16;
  742. break;
  743. case 6:
  744. ConnectInfo.guidTypeID = DDVPTYPE_E_HREFL_VREFL;
  745. ConnectInfo.dwPortWidth = 8;
  746. break;
  747. case 7:
  748. ConnectInfo.guidTypeID = DDVPTYPE_E_HREFL_VREFL;
  749. ConnectInfo.dwPortWidth = 16;
  750. break;
  751. }
  752. memcpy((pInput->lpConnect + dwNum), &ConnectInfo, sizeof(DDVIDEOPORTCONNECT));
  753. }
  754. pInput->dwNumEntries = VIDEOPORT_NUM_CONNECT_INFO;
  755. pInput->ddRVal = DD_OK;
  756. }
  757. return DDHAL_DRIVER_HANDLED;
  758. } // DDGetVideoPortConnectInfo
  759. //-----------------------------------------------------------------------------
  760. //
  761. // DdCanCreateVideoPort
  762. //
  763. // Can the VideoPort be created?
  764. //
  765. //-----------------------------------------------------------------------------
  766. DWORD CALLBACK
  767. DdCanCreateVideoPort (
  768. LPDDHAL_CANCREATEVPORTDATA pInput)
  769. {
  770. DWORD dwFlags = 0;
  771. LPDDVIDEOPORTDESC lpVPDesc;
  772. LPDDVIDEOPORTCONNECT lpVPConn;
  773. P3_THUNKEDDATA* pThisDisplay;
  774. lpVPDesc = pInput->lpDDVideoPortDesc;
  775. lpVPConn = &(pInput->lpDDVideoPortDesc->VideoPortType);
  776. GET_THUNKEDDATA(pThisDisplay, pInput->lpDD->lpGbl);
  777. DISPDBG((DBGLVL,"** In DdCanCreateVideoPort"));
  778. DUMPVPORT(DBGLVL,*pInput->lpDDVideoPortDesc);
  779. // Start with DD_OK. If we are asked for parameters that we don't
  780. // support, then set the flag to DDERR_INVALIDPARAMS.
  781. pInput->ddRVal = DD_OK;
  782. // Check the video port ID
  783. if (lpVPDesc->dwVideoPortID != 0)
  784. {
  785. DISPDBG((DBGLVL, " Invalid port ID: %d", lpVPDesc->dwVideoPortID));
  786. pInput->ddRVal = DDERR_INVALIDPARAMS;
  787. }
  788. // Check the video field width
  789. if (lpVPDesc->dwFieldWidth > VIDEOPORT_MAX_FIELD_WIDTH)
  790. {
  791. pInput->ddRVal = DDERR_INVALIDPARAMS;
  792. DISPDBG((DBGLVL, " Invalid video field width: %d", lpVPDesc->dwFieldWidth));
  793. }
  794. // Check the VBI field width
  795. if (lpVPDesc->dwVBIWidth > VIDEOPORT_MAX_VBI_WIDTH)
  796. {
  797. pInput->ddRVal = DDERR_INVALIDPARAMS;
  798. DISPDBG((DBGLVL, " Invalid VBI field width: %d", lpVPDesc->dwVBIWidth));
  799. }
  800. // Check the field height
  801. if (lpVPDesc->dwFieldHeight > VIDEOPORT_MAX_FIELD_HEIGHT)
  802. {
  803. pInput->ddRVal = DDERR_INVALIDPARAMS;
  804. DISPDBG((DBGLVL, " Invalid video field height: %d", lpVPDesc->dwFieldHeight));
  805. }
  806. // Check the connection GUID
  807. if ( MATCH_GUID((lpVPConn->guidTypeID), DDVPTYPE_CCIR656) ||
  808. MATCH_GUID((lpVPConn->guidTypeID), DDVPTYPE_BROOKTREE) ||
  809. MATCH_GUID((lpVPConn->guidTypeID), DDVPTYPE_PHILIPS) )
  810. {
  811. pInput->ddRVal = DDERR_INVALIDPARAMS;
  812. DISPDBG((DBGLVL, " Invalid connection GUID"));
  813. }
  814. // Check the port width
  815. if ( !((lpVPConn->dwPortWidth == 8) || (lpVPConn->dwPortWidth == 16)) )
  816. {
  817. pInput->ddRVal = DDERR_INVALIDPARAMS;
  818. DISPDBG((DBGLVL, " Invalid port width: %d", lpVPConn->dwPortWidth));
  819. }
  820. // All the flags we don't support
  821. dwFlags = DDVPCONNECT_DOUBLECLOCK | DDVPCONNECT_SHAREEVEN | DDVPCONNECT_SHAREODD;
  822. // Check the flags
  823. if (lpVPConn->dwFlags & dwFlags)
  824. {
  825. pInput->ddRVal = DDERR_INVALIDPARAMS;
  826. DISPDBG((DBGLVL, " Invalid flags: 0x%x", lpVPConn->dwFlags));
  827. }
  828. return DDHAL_DRIVER_HANDLED;
  829. } // DdCanCreateVideoPort
  830. //-----------------------------------------------------------------------------
  831. //
  832. // DdCreateVideoPort
  833. //
  834. // This function is optional
  835. //
  836. //-----------------------------------------------------------------------------
  837. DWORD CALLBACK
  838. DdCreateVideoPort (
  839. LPDDHAL_CREATEVPORTDATA pInput)
  840. {
  841. VMIREQUEST vmi_inreq;
  842. VMIREQUEST vmi_outreq;
  843. BOOL bRet;
  844. int SurfaceNum = 0;
  845. P3_THUNKEDDATA* pThisDisplay;
  846. GET_THUNKEDDATA(pThisDisplay, pInput->lpDD->lpGbl);
  847. DISPDBG((DBGLVL,"** In DdCreateVideoPort"));
  848. // Reset the structure for the videoport info
  849. memset(&pThisDisplay->VidPort, 0, sizeof(pThisDisplay->VidPort));
  850. ZeroMemory(&vmi_inreq, sizeof(VMIREQUEST));
  851. ZeroMemory(&vmi_outreq, sizeof(VMIREQUEST));
  852. vmi_inreq.dwSize = sizeof(VMIREQUEST);
  853. vmi_inreq.dwDevNode = pThisDisplay->dwDevNode;
  854. vmi_inreq.dwOperation = GLINT_VMI_GETMUTEX_A;
  855. vmi_inreq.dwMutex = 0;
  856. bRet = VXDCommand(GLINT_VMI_COMMAND, &vmi_inreq, sizeof(VMIREQUEST), &vmi_outreq, sizeof(VMIREQUEST));
  857. if (!bRet || (vmi_outreq.dwMutex == 0))
  858. {
  859. DISPDBG((WRNLVL,"WARNING: Couldn't get Mutex for stream A - VFW running?"));
  860. pInput->ddRVal = DDERR_GENERIC;
  861. return DDHAL_DRIVER_HANDLED;
  862. }
  863. pThisDisplay->VidPort.dwMutexA = vmi_outreq.dwMutex;
  864. // Ensure the port is marked as not created and not on
  865. pThisDisplay->VidPort.bCreated = FALSE;
  866. pThisDisplay->VidPort.bActive = FALSE;
  867. WAIT_GLINT_FIFO(2);
  868. // Make sure the port is disabled.
  869. LOAD_GLINT_REG(VSAControl, __PERMEDIA_DISABLE);
  870. // Keep a copy of the videoport description
  871. DUMPVPORT(0,*pInput->lpDDVideoPortDesc);
  872. // Succesfully created the VideoPort.
  873. pThisDisplay->VidPort.bCreated = TRUE;
  874. // Depending on the GUID, decide on the Status of the HREF and VREF lines
  875. if (MATCH_GUID((pInput->lpDDVideoPortDesc->VideoPortType.guidTypeID), DDVPTYPE_E_HREFH_VREFH))
  876. {
  877. DISPDBG((DBGLVL," GUID: DDVPTYPE_E_HREFH_VREFH"));
  878. pThisDisplay->VidPort.dwStreamAFlags = VIDEOPORT_HREF_ACTIVE_HIGH | VIDEOPORT_VREF_ACTIVE_HIGH;
  879. }
  880. else if (MATCH_GUID((pInput->lpDDVideoPortDesc->VideoPortType.guidTypeID), DDVPTYPE_E_HREFH_VREFL))
  881. {
  882. DISPDBG((DBGLVL," GUID: DDVPTYPE_E_HREFH_VREFH"));
  883. pThisDisplay->VidPort.dwStreamAFlags = VIDEOPORT_HREF_ACTIVE_HIGH;
  884. }
  885. else if (MATCH_GUID((pInput->lpDDVideoPortDesc->VideoPortType.guidTypeID), DDVPTYPE_E_HREFL_VREFH))
  886. {
  887. DISPDBG((DBGLVL," GUID: DDVPTYPE_E_HREFH_VREFH"));
  888. pThisDisplay->VidPort.dwStreamAFlags = VIDEOPORT_VREF_ACTIVE_HIGH;
  889. }
  890. else if (MATCH_GUID((pInput->lpDDVideoPortDesc->VideoPortType.guidTypeID), DDVPTYPE_E_HREFL_VREFL))
  891. {
  892. DISPDBG((DBGLVL," GUID: DDVPTYPE_E_HREFH_VREFH"));
  893. pThisDisplay->VidPort.dwStreamAFlags = 0;
  894. }
  895. else
  896. {
  897. DISPDBG((ERRLVL,"ERROR: Unsupported VideoType GUID!"));
  898. pThisDisplay->VidPort.dwStreamAFlags = 0;
  899. }
  900. pInput->ddRVal = DD_OK;
  901. return DDHAL_DRIVER_NOTHANDLED;
  902. } // DdCreateVideoPort
  903. //-----------------------------------------------------------------------------
  904. //
  905. // DdFlipVideoPort
  906. //
  907. // This function is required
  908. //
  909. //-----------------------------------------------------------------------------
  910. DWORD CALLBACK
  911. DdFlipVideoPort (
  912. LPDDHAL_FLIPVPORTDATA pInput)
  913. {
  914. P3_THUNKEDDATA* pThisDisplay;
  915. DWORD dwChipIndex;
  916. DWORD OutCount = 0;
  917. GET_THUNKEDDATA(pThisDisplay, pInput->lpDD->lpGbl);
  918. DISPDBG((DBGLVL,"** In DdFlipVideoPort"));
  919. if (pThisDisplay->VidPort.bActive)
  920. {
  921. #if DBG
  922. if ( pThisDisplay->pGLInfo->dwPeriodVideoVBL != 0 )
  923. {
  924. if ( pThisDisplay->pGLInfo->dwVideoEventHandle == (DWORD)NULL )
  925. {
  926. DISPDBG((WRNLVL,"** DdFlipVideoPort: was autoflipping on bogus event handle."));
  927. }
  928. if ( !g_bFlipVideoPortDoingAutoflip )
  929. {
  930. DISPDBG((DBGLVL,"** DdFlipVideoPort: already autoflipping!"));
  931. }
  932. }
  933. #endif
  934. // Don't allow us to catch up with the video
  935. do
  936. {
  937. dwChipIndex = READ_GLINT_CTRL_REG(VSAVideoAddressIndex);
  938. } while (dwChipIndex == pThisDisplay->VidPort.dwCurrentHostFrame);
  939. pThisDisplay->VidPort.dwCurrentHostFrame++;
  940. if (pThisDisplay->VidPort.dwCurrentHostFrame >= pThisDisplay->VidPort.dwNumSurfaces)
  941. {
  942. pThisDisplay->VidPort.dwCurrentHostFrame = 0;
  943. }
  944. // Need to sync to ensure that a blit from the source surface has finished..
  945. SYNC_WITH_GLINT;
  946. // Advance the count
  947. LOAD_GLINT_REG(VSAVideoAddressHost, pThisDisplay->VidPort.dwCurrentHostFrame);
  948. }
  949. pInput->ddRVal = DD_OK;
  950. return DDHAL_DRIVER_HANDLED;
  951. } // DdFlipVideoPort
  952. //-----------------------------------------------------------------------------
  953. //
  954. // DdGetVideoPortBandwidth
  955. //
  956. // This function is required
  957. //
  958. //-----------------------------------------------------------------------------
  959. DWORD CALLBACK
  960. DdGetVideoPortBandwidth (
  961. LPDDHAL_GETVPORTBANDWIDTHDATA pInput)
  962. {
  963. P3_THUNKEDDATA* pThisDisplay;
  964. DDVIDEOPORTBANDWIDTH *lpOutput = pInput->lpBandwidth;
  965. DDVIDEOPORTINFO *pInfo = &(pInput->lpVideoPort->ddvpInfo);
  966. DDVIDEOPORTDESC *pDesc = &(pInput->lpVideoPort->ddvpDesc);
  967. GET_THUNKEDDATA(pThisDisplay, pInput->lpDD->lpGbl);
  968. DISPDBG((DBGLVL,"** In DdGetVideoPortBandwidth"));
  969. lpOutput->dwSize = sizeof(DDVIDEOPORTBANDWIDTH);
  970. lpOutput->dwCaps = DDVPBCAPS_DESTINATION;
  971. if (!(pInput->dwFlags & DDVPB_TYPE))
  972. {
  973. lpOutput->dwOverlay = 20;
  974. lpOutput->dwColorkey = 20;
  975. lpOutput->dwYInterpolate = 20;
  976. lpOutput->dwYInterpAndColorkey = 20;
  977. }
  978. pInput->ddRVal = DD_OK;
  979. return DDHAL_DRIVER_HANDLED;
  980. } // DdGetVideoPortBandwidth
  981. //-----------------------------------------------------------------------------
  982. //
  983. // GetVideoPortInputFormat32
  984. //
  985. // This function is required
  986. //
  987. //-----------------------------------------------------------------------------
  988. DWORD CALLBACK
  989. DdGetVideoPortInputFormats (
  990. LPDDHAL_GETVPORTINPUTFORMATDATA pInput)
  991. {
  992. P3_THUNKEDDATA* pThisDisplay;
  993. DDPIXELFORMAT pf[] =
  994. {
  995. {sizeof(DDPIXELFORMAT),DDPF_FOURCC, FOURCC_YUV422 ,16,(DWORD)-1,(DWORD)-1,(DWORD)-1},
  996. };
  997. GET_THUNKEDDATA(pThisDisplay, pInput->lpDD->lpGbl);
  998. DISPDBG((DBGLVL,"** In DdGetVideoPortInputFormats"));
  999. //
  1000. // The HAL is gaurenteed that the buffer in pInput->lpddpfFormat
  1001. // is large enough to hold the information
  1002. //
  1003. pInput->dwNumFormats = 1;
  1004. if (pInput->lpddpfFormat != NULL)
  1005. {
  1006. memcpy (pInput->lpddpfFormat, pf, sizeof (DDPIXELFORMAT));
  1007. }
  1008. pInput->ddRVal = DD_OK;
  1009. return DDHAL_DRIVER_HANDLED;
  1010. } // GetVideoPortInputFormat32
  1011. //-----------------------------------------------------------------------------
  1012. //
  1013. // DdGetVideoPortOutputFormats
  1014. //
  1015. // This function is required
  1016. //
  1017. //-----------------------------------------------------------------------------
  1018. DWORD CALLBACK
  1019. DdGetVideoPortOutputFormats (
  1020. LPDDHAL_GETVPORTOUTPUTFORMATDATA pInput)
  1021. {
  1022. P3_THUNKEDDATA* pThisDisplay;
  1023. DDPIXELFORMAT pf[] =
  1024. {
  1025. {sizeof(DDPIXELFORMAT),DDPF_FOURCC, FOURCC_YUV422 ,16,(DWORD)-1,(DWORD)-1,(DWORD)-1},
  1026. };
  1027. GET_THUNKEDDATA(pThisDisplay, pInput->lpDD->lpGbl);
  1028. DISPDBG((DBGLVL,"** In DdGetVideoPortOutputFormats"));
  1029. // This says that if the input format of the videoport is YUV then the output will also be
  1030. // YUV to the surface
  1031. if (pInput->lpddpfInputFormat->dwFlags & DDPF_FOURCC )
  1032. {
  1033. if (pInput->lpddpfInputFormat->dwFourCC == FOURCC_YUV422)
  1034. {
  1035. pInput->dwNumFormats = 1;
  1036. if (pInput->lpddpfOutputFormats != NULL)
  1037. {
  1038. memcpy (pInput->lpddpfOutputFormats, pf, sizeof (DDPIXELFORMAT));
  1039. }
  1040. }
  1041. }
  1042. pInput->ddRVal = DD_OK;
  1043. return DDHAL_DRIVER_HANDLED;
  1044. } // DdGetVideoPortOutputFormats
  1045. //-----------------------------------------------------------------------------
  1046. //
  1047. // DdGetVideoPortField
  1048. //
  1049. // This function is only required if readback of the current
  1050. // field is supported.
  1051. //
  1052. //-----------------------------------------------------------------------------
  1053. DWORD CALLBACK
  1054. DdGetVideoPortField (
  1055. LPDDHAL_GETVPORTFIELDDATA pInput)
  1056. {
  1057. DWORD i = 0;
  1058. DWORD dwIndex = 0;
  1059. DWORD dwMask = 0;
  1060. DWORD dwStatus = 0;
  1061. P3_THUNKEDDATA* pThisDisplay;
  1062. GET_THUNKEDDATA(pThisDisplay, pInput->lpDD->lpGbl);
  1063. DISPDBG((DBGLVL,"** In DdGetVideoPortField"));
  1064. //
  1065. // Make sure the video port is ON. If not, set
  1066. // pInput->ddRVal to DDERR_VIDEONOTACTIVE and return.
  1067. //
  1068. if (pThisDisplay->VidPort.bActive == FALSE)
  1069. {
  1070. pInput->ddRVal = DDERR_VIDEONOTACTIVE;
  1071. }
  1072. else
  1073. {
  1074. DWORD dwCurrentIndex;
  1075. // Read the current index and compare with us. If the same then
  1076. // we haven't finished drawing.
  1077. do
  1078. {
  1079. dwCurrentIndex = READ_GLINT_CTRL_REG(VSAVideoAddressIndex);
  1080. } while (pThisDisplay->VidPort.dwCurrentHostFrame == dwCurrentIndex);
  1081. pInput->bField = (BOOL)((pThisDisplay->pGLInfo->dwVSAPolarity >> pThisDisplay->VidPort.dwCurrentHostFrame) & 0x1);
  1082. //pInput->bField = !pInput->bField;
  1083. DISPDBG((DBGLVL,"Returning Field %d's Polarity "
  1084. "- %d (dwVSAPolarity = 0x%x)",
  1085. pThisDisplay->VidPort.dwCurrentHostFrame,
  1086. pInput->bField,
  1087. pThisDisplay->pGLInfo->dwVSAPolarity));
  1088. pInput->ddRVal = DD_OK;
  1089. }
  1090. return DDHAL_DRIVER_HANDLED;
  1091. } // DdGetVideoPortField
  1092. //-----------------------------------------------------------------------------
  1093. //
  1094. // DdGetVideoPortLine
  1095. //
  1096. // This function is only required if readback of the current
  1097. // video line number (0 relative) is supported.
  1098. //
  1099. //-----------------------------------------------------------------------------
  1100. DWORD CALLBACK
  1101. DdGetVideoPortLine (
  1102. LPDDHAL_GETVPORTLINEDATA pInput)
  1103. {
  1104. P3_THUNKEDDATA* pThisDisplay;
  1105. DWORD dwCurrentLine;
  1106. GET_THUNKEDDATA(pThisDisplay, pInput->lpDD->lpGbl);
  1107. DISPDBG((DBGLVL,"** In DdGetVideoPortLine"));
  1108. if (pThisDisplay->VidPort.bActive == FALSE)
  1109. {
  1110. pInput->ddRVal = DDERR_VIDEONOTACTIVE;
  1111. }
  1112. else
  1113. {
  1114. dwCurrentLine = READ_GLINT_CTRL_REG(VSACurrentLine);
  1115. pInput->dwLine = dwCurrentLine;
  1116. pInput->ddRVal = DD_OK;
  1117. }
  1118. return DDHAL_DRIVER_HANDLED;
  1119. } // DdGetVideoPortLine
  1120. //-----------------------------------------------------------------------------
  1121. //
  1122. // DdDestroyVideoPort
  1123. //
  1124. // This optional function notifies the HAL when the video port
  1125. // has been destroyed.
  1126. //
  1127. //-----------------------------------------------------------------------------
  1128. DWORD CALLBACK
  1129. DdDestroyVideoPort (
  1130. LPDDHAL_DESTROYVPORTDATA pInput)
  1131. {
  1132. P3_THUNKEDDATA* pThisDisplay;
  1133. VMIREQUEST vmi_inreq;
  1134. VMIREQUEST vmi_outreq;
  1135. BOOL bRet;
  1136. GET_THUNKEDDATA(pThisDisplay, pInput->lpDD->lpGbl);
  1137. DISPDBG((DBGLVL,"** In DdDestroyVideoPort"));
  1138. // Ensure the port is off.
  1139. WAIT_GLINT_FIFO(2);
  1140. // Disablet the videoport
  1141. LOAD_GLINT_REG(VSAControl, __PERMEDIA_DISABLE);
  1142. // Ensure the port is marked as not created and not on
  1143. pThisDisplay->VidPort.bCreated = FALSE;
  1144. pThisDisplay->VidPort.bActive = FALSE;
  1145. // Release the mutex on Stream A
  1146. if (pThisDisplay->VidPort.dwMutexA != 0)
  1147. {
  1148. DISPDBG((DBGLVL," Releasing StreamA Mutex"));
  1149. ZeroMemory(&vmi_inreq, sizeof(VMIREQUEST));
  1150. ZeroMemory(&vmi_outreq, sizeof(VMIREQUEST));
  1151. vmi_inreq.dwSize = sizeof(VMIREQUEST);
  1152. vmi_inreq.dwDevNode = pThisDisplay->dwDevNode;
  1153. vmi_inreq.dwOperation = GLINT_VMI_RELEASEMUTEX_A;
  1154. vmi_inreq.dwMutex = pThisDisplay->VidPort.dwMutexA;
  1155. bRet = VXDCommand(GLINT_VMI_COMMAND, &vmi_inreq, sizeof(VMIREQUEST), &vmi_outreq, sizeof(VMIREQUEST));
  1156. ASSERTDD(bRet,"ERROR: Couldn't release Mutex on Stream A");
  1157. }
  1158. // Reset the structure
  1159. memset(&pThisDisplay->VidPort, 0, sizeof(pThisDisplay->VidPort));
  1160. // Stop any autoflipping.
  1161. if ( pThisDisplay->pGLInfo->dwPeriodVideoVBL != 0 )
  1162. {
  1163. #if DBG
  1164. if ( pThisDisplay->pGLInfo->dwVideoEventHandle == (DWORD)NULL )
  1165. {
  1166. DISPDBG((WRNLVL,"** DdDestroyVideoPort: "
  1167. "was autoflipping on bogus event handle."));
  1168. }
  1169. #endif
  1170. pThisDisplay->pGLInfo->dwPeriodVideoVBL = 0;
  1171. pThisDisplay->pGLInfo->dwCountdownVideoVBL = 0;
  1172. DISPDBG((DBGLVL,"** DdDestroyVideoPort: autoflipping now disabled."));
  1173. }
  1174. // Make sure the videoport is turned off
  1175. pInput->ddRVal = DD_OK;
  1176. return DDHAL_DRIVER_NOTHANDLED;
  1177. } // DdDestroyVideoPort
  1178. //-----------------------------------------------------------------------------
  1179. //
  1180. // DdGetVideoSignalStatus
  1181. //
  1182. //-----------------------------------------------------------------------------
  1183. DWORD CALLBACK
  1184. DdGetVideoSignalStatus(
  1185. LPDDHAL_GETVPORTSIGNALDATA pInput)
  1186. {
  1187. P3_THUNKEDDATA* pThisDisplay;
  1188. DWORD dwCurrentIndex;
  1189. BOOL bOK = FALSE;
  1190. GET_THUNKEDDATA(pThisDisplay, pInput->lpDD->lpGbl);
  1191. dwCurrentIndex = READ_GLINT_CTRL_REG(VSAVideoAddressIndex);
  1192. // If the host count matches the index count then the video may be stuck
  1193. if (pThisDisplay->VidPort.dwCurrentHostFrame == dwCurrentIndex)
  1194. {
  1195. bOK = __VD_CheckVideoPortStatus(pThisDisplay, TRUE);
  1196. }
  1197. else
  1198. {
  1199. bOK = TRUE;
  1200. }
  1201. if (!bOK)
  1202. {
  1203. pInput->dwStatus = DDVPSQ_NOSIGNAL;
  1204. }
  1205. else
  1206. {
  1207. pInput->dwStatus = DDVPSQ_SIGNALOK;
  1208. }
  1209. pInput->ddRVal = DD_OK;
  1210. return DDHAL_DRIVER_HANDLED;
  1211. } // DdGetVideoSignalStatus
  1212. //-----------------------------------------------------------------------------
  1213. //
  1214. // DdGetVideoPortFlipStatus
  1215. //
  1216. // This required function allows DDRAW to restrict access to a surface
  1217. // until the physical flip has occurred, allowing doubled buffered capture.
  1218. //
  1219. //-----------------------------------------------------------------------------
  1220. DWORD CALLBACK
  1221. DdGetVideoPortFlipStatus (
  1222. LPDDHAL_GETVPORTFLIPSTATUSDATA pInput)
  1223. {
  1224. P3_THUNKEDDATA* pThisDisplay;
  1225. DWORD dwCurrentIndex;
  1226. GET_THUNKEDDATA(pThisDisplay, pInput->lpDD->lpGbl);
  1227. DISPDBG((DBGLVL,"** In DdGetVideoPortFlipStatus"));
  1228. pInput->ddRVal = DD_OK;
  1229. if (pThisDisplay->VidPort.bActive == TRUE)
  1230. {
  1231. // If we are flipping, check the currently rendered frame
  1232. // Read the current index and compare with us. If the same then
  1233. // we haven't finished drawing.
  1234. dwCurrentIndex = READ_GLINT_CTRL_REG(VSAVideoAddressIndex);
  1235. if (pThisDisplay->VidPort.dwCurrentHostFrame == dwCurrentIndex)
  1236. {
  1237. // If the videoport is not stuck return that we are still drawing
  1238. if (__VD_CheckVideoPortStatus(pThisDisplay, FALSE))
  1239. {
  1240. pInput->ddRVal = DDERR_WASSTILLDRAWING;
  1241. }
  1242. else
  1243. {
  1244. pInput->ddRVal = DD_OK;
  1245. }
  1246. }
  1247. }
  1248. return DDHAL_DRIVER_HANDLED;
  1249. } // DdGetVideoPortFlipStatus
  1250. //-----------------------------------------------------------------------------
  1251. //
  1252. // DdWaitForVideoPortSync
  1253. //
  1254. // This function is required
  1255. //
  1256. //-----------------------------------------------------------------------------
  1257. DWORD CALLBACK
  1258. DdWaitForVideoPortSync (
  1259. LPDDHAL_WAITFORVPORTSYNCDATA pInput)
  1260. {
  1261. P3_THUNKEDDATA* pThisDisplay;
  1262. GET_THUNKEDDATA(pThisDisplay, pInput->lpDD->lpGbl);
  1263. DISPDBG((DBGLVL,"** In DdWaitForVideoPortSync"));
  1264. //@@BEGIN_DDKSPLIT
  1265. /*
  1266. * Make sure the video port is ON. If not, set
  1267. * pInput->ddRVal to DDERR_VIDEONOTACTIVE and return.
  1268. */
  1269. /*
  1270. if (pInput->dwFlags == DDVPEVENT_BEGIN)
  1271. {
  1272. pInput->ddRVal = DD_OK;
  1273. }
  1274. else if (pInput->dwFlags == DDVPEVENT_END)
  1275. {
  1276. pInput->ddRVal = DD_OK;
  1277. }
  1278. */
  1279. //@@END_DDKSPLIT
  1280. pInput->ddRVal = DD_OK;
  1281. return DDHAL_DRIVER_HANDLED;
  1282. } // DdWaitForVideoPortSync
  1283. //-----------------------------------------------------------------------------
  1284. //
  1285. // DdSyncSurfaceData
  1286. //
  1287. //-----------------------------------------------------------------------------
  1288. DWORD CALLBACK
  1289. DdSyncSurfaceData(
  1290. LPDDHAL_SYNCSURFACEDATA pInput)
  1291. {
  1292. P3_THUNKEDDATA* pThisDisplay;
  1293. GET_THUNKEDDATA(pThisDisplay, pInput->lpDD->lpGbl);
  1294. DISPDBG((DBGLVL,"** In DdSyncSurfaceData"));
  1295. DBGDUMP_DDRAWSURFACE_LCL(3, pInput->lpDDSurface);
  1296. if (!(pInput->lpDDSurface->ddsCaps.dwCaps & DDSCAPS_OVERLAY))
  1297. {
  1298. DISPDBG((DBGLVL, "Surface is not an overlay - not handling"));
  1299. pInput->ddRVal = DD_OK;
  1300. return DDHAL_DRIVER_NOTHANDLED;
  1301. }
  1302. if (pInput->lpDDSurface->lpGbl->dwGlobalFlags &
  1303. DDRAWISURFGBL_SOFTWAREAUTOFLIP)
  1304. {
  1305. DISPDBG((DBGLVL, "Autoflipping in software"));
  1306. }
  1307. pInput->dwSurfaceOffset = pInput->lpDDSurface->lpGbl->fpVidMem -
  1308. pThisDisplay->dwScreenFlatAddr;
  1309. pInput->dwOverlayOffset = pInput->dwSurfaceOffset;
  1310. pInput->ddRVal = DD_OK;
  1311. return DDHAL_DRIVER_HANDLED;
  1312. } // DdSyncSurfaceData
  1313. //-----------------------------------------------------------------------------
  1314. //
  1315. // DdSyncVideoPortData
  1316. //
  1317. //-----------------------------------------------------------------------------
  1318. DWORD CALLBACK
  1319. DdSyncVideoPortData(
  1320. LPDDHAL_SYNCVIDEOPORTDATA pInput)
  1321. {
  1322. P3_THUNKEDDATA* pThisDisplay;
  1323. GET_THUNKEDDATA(pThisDisplay, pInput->lpDD->lpGbl);
  1324. DISPDBG((DBGLVL,"** In DdSyncVideoPortData"));
  1325. pInput->ddRVal = DD_OK;
  1326. return DDHAL_DRIVER_HANDLED;
  1327. } // DdSyncVideoPortData
  1328. //-----------------------------------------------------------------------------
  1329. //
  1330. // UpdateOverlay32
  1331. //
  1332. //-----------------------------------------------------------------------------
  1333. DWORD CALLBACK
  1334. UpdateOverlay32(
  1335. LPDDHAL_UPDATEOVERLAYDATA puod)
  1336. {
  1337. P3_THUNKEDDATA* pThisDisplay;
  1338. LPDDRAWI_DDRAWSURFACE_LCL lpSrcSurf;
  1339. HDC hDC;
  1340. DWORD dwDstColourKey;
  1341. DWORD dwSrcColourKey;
  1342. GET_THUNKEDDATA(pThisDisplay, puod->lpDD);
  1343. /*
  1344. * A puod looks like this:
  1345. *
  1346. * LPDDRAWI_DIRECTDRAW_GBL lpDD; // driver struct
  1347. * LPDDRAWI_DDRAWSURFACE_LCL lpDDDestSurface; // dest surface
  1348. * RECTL rDest; // dest rect
  1349. * LPDDRAWI_DDRAWSURFACE_LCL lpDDSrcSurface; // src surface
  1350. * RECTL rSrc; // src rect
  1351. * DWORD dwFlags; // flags
  1352. * DDOVERLAYFX overlayFX; // overlay FX
  1353. * HRESULT ddRVal; // return value
  1354. * LPDDHALSURFCB_UPDATEOVERLAY UpdateOverlay; // PRIVATE: ptr to callback
  1355. */
  1356. DISPDBG ((DBGLVL,"**In UpdateOverlay32"));
  1357. lpSrcSurf = puod->lpDDSrcSurface;
  1358. /*
  1359. * In the LPDDRAWI_DDRAWSURFACE_LCL, we have the following cool data,
  1360. * making life much easier:
  1361. *
  1362. * HOWEVER! It appears that UpdateOverlay32 is called before any of these
  1363. * values are changed, so use the values passed in instead.
  1364. *
  1365. * DDCOLORKEY ddckCKSrcOverlay; // color key for source overlay use
  1366. * DDCOLORKEY ddckCKDestOverlay; // color key for destination overlay use
  1367. * LPDDRAWI_DDRAWSURFACE_INT lpSurfaceOverlaying; // surface we are overlaying
  1368. * DBLNODE dbnOverlayNode;
  1369. *
  1370. * //
  1371. * //overlay rectangle, used by DDHEL
  1372. * //
  1373. * RECT rcOverlaySrc;
  1374. * RECT rcOverlayDest;
  1375. * //
  1376. * //the below values are kept here for ddhel. they're set by UpdateOverlay,
  1377. * //they're used whenever the overlays are redrawn.
  1378. * //
  1379. * DWORD dwClrXparent; // the *actual* color key (override, colorkey, or CLR_INVALID)
  1380. * DWORD dwAlpha; // the per surface alpha
  1381. * //
  1382. * //overlay position
  1383. * //
  1384. * LONG lOverlayX; // current x position
  1385. * LONG lOverlayY; // current y position
  1386. */
  1387. #if DBG
  1388. // Standard integrity test.
  1389. if ( pThisDisplay->bOverlayVisible == 0 )
  1390. {
  1391. if ( (LPDDRAWI_DDRAWSURFACE_LCL)pThisDisplay->OverlaySrcSurfLcl != NULL )
  1392. {
  1393. // If overlay is not visible, the current surface should be NULL.
  1394. DISPDBG((DBGLVL,"** UpdateOverlay32 - vis==0,srcsurf!=NULL"));
  1395. }
  1396. }
  1397. else
  1398. {
  1399. if ( (LPDDRAWI_DDRAWSURFACE_LCL)pThisDisplay->OverlaySrcSurfLcl == NULL )
  1400. {
  1401. // If overlay is visible, the current surface should not be NULL.
  1402. DISPDBG((DBGLVL,"** UpdateOverlay32 - vis!=0,srcsurf==NULL"));
  1403. }
  1404. }
  1405. #endif //DBG
  1406. if ( ( puod->dwFlags & DDOVER_HIDE ) != 0 )
  1407. {
  1408. DISPDBG((DBGLVL,"** UpdateOverlay32 - hiding."));
  1409. // Hide the overlay.
  1410. if ( pThisDisplay->bOverlayVisible == 0 )
  1411. {
  1412. // No overlay being shown.
  1413. DISPDBG((WRNLVL,"** UpdateOverlay32 - DDOVER_HIDE - already hidden."));
  1414. puod->ddRVal = DDERR_OUTOFCAPS;
  1415. return DDHAL_DRIVER_HANDLED;
  1416. }
  1417. if ( pThisDisplay->OverlaySrcSurfLcl != (ULONG_PTR)lpSrcSurf )
  1418. {
  1419. // This overlay isn't being shown.
  1420. DISPDBG((WRNLVL,"** UpdateOverlay32 - DDOVER_HIDE - not current overlay surface."));
  1421. puod->ddRVal = DDERR_OUTOFCAPS;
  1422. return DDHAL_DRIVER_HANDLED;
  1423. }
  1424. // Stop any autoflipping.
  1425. if ( pThisDisplay->pGLInfo->dwPeriodVideoVBL != 0 )
  1426. {
  1427. #if DBG
  1428. if ( pThisDisplay->pGLInfo->dwVideoEventHandle == (DWORD)NULL )
  1429. {
  1430. DISPDBG((WRNLVL,"** UpdateOverlay32 - DDOVER_HIDE - was autoflipping on bogus event handle."));
  1431. }
  1432. #endif
  1433. pThisDisplay->pGLInfo->dwPeriodVideoVBL = 0;
  1434. pThisDisplay->pGLInfo->dwCountdownVideoVBL = 0;
  1435. DISPDBG((DBGLVL,"** UpdateOverlay32 - DDOVER_HIDE - autoflipping now disabled."));
  1436. }
  1437. if ( pThisDisplay->pGLInfo->dwPeriodMonitorVBL != 0 )
  1438. {
  1439. if ( pThisDisplay->pGLInfo->dwMonitorEventHandle == (DWORD)NULL )
  1440. {
  1441. DISPDBG((DBGLVL,"** UpdateOverlay32 - DDOVER_HIDE - was autoupdating on bogus event handle."));
  1442. }
  1443. pThisDisplay->pGLInfo->dwPeriodMonitorVBL = 0;
  1444. pThisDisplay->pGLInfo->dwCountdownMonitorVBL = 0;
  1445. DISPDBG((DBGLVL,"** UpdateOverlay32 - DDOVER_HIDE - autoupdate now disabled."));
  1446. }
  1447. // DISPDBG((DBGLVL,"** UpdateOverlay32 (hiding) destroying rect memory."));
  1448. // Free the rect memory
  1449. if ( (void *)pThisDisplay->OverlayClipRgnMem != NULL )
  1450. {
  1451. HEAP_FREE ((void *)pThisDisplay->OverlayClipRgnMem);
  1452. }
  1453. pThisDisplay->OverlayClipRgnMem = (ULONG_PTR)NULL;
  1454. pThisDisplay->OverlayClipRgnMemSize = (DWORD)0;
  1455. // DISPDBG((DBGLVL,"** UpdateOverlay32 (hiding) destroyed rect memory."));
  1456. pThisDisplay->bOverlayVisible = FALSE;
  1457. pThisDisplay->OverlayDstRectL = (DWORD)0;
  1458. pThisDisplay->OverlayDstRectR = (DWORD)0;
  1459. pThisDisplay->OverlayDstRectT = (DWORD)0;
  1460. pThisDisplay->OverlayDstRectB = (DWORD)0;
  1461. pThisDisplay->OverlaySrcRectL = (DWORD)0;
  1462. pThisDisplay->OverlaySrcRectR = (DWORD)0;
  1463. pThisDisplay->OverlaySrcRectT = (DWORD)0;
  1464. pThisDisplay->OverlaySrcRectB = (DWORD)0;
  1465. pThisDisplay->OverlayDstSurfLcl = (ULONG_PTR)NULL;
  1466. pThisDisplay->OverlaySrcSurfLcl = (ULONG_PTR)NULL;
  1467. pThisDisplay->OverlayDstColourKey = (DWORD)CLR_INVALID;
  1468. pThisDisplay->OverlaySrcColourKey = (DWORD)CLR_INVALID;
  1469. pThisDisplay->OverlayUpdateCountdown = 0;
  1470. pThisDisplay->bOverlayFlippedThisVbl = (DWORD)FALSE;
  1471. pThisDisplay->bOverlayUpdatedThisVbl = (DWORD)FALSE;
  1472. pThisDisplay->pGLInfo->bOverlayEnabled = (DWORD)FALSE;
  1473. pThisDisplay->pGLInfo->dwOverlayRectL = (DWORD)0;
  1474. pThisDisplay->pGLInfo->dwOverlayRectR = (DWORD)0;
  1475. pThisDisplay->pGLInfo->dwOverlayRectT = (DWORD)0;
  1476. pThisDisplay->pGLInfo->dwOverlayRectB = (DWORD)0;
  1477. pThisDisplay->pGLInfo->bOverlayColourKeyEnabled = (DWORD)FALSE;
  1478. pThisDisplay->pGLInfo->dwOverlayDstColourKeyChip = (DWORD)-1;
  1479. pThisDisplay->pGLInfo->dwOverlayDstColourKeyFB = (DWORD)-1;
  1480. pThisDisplay->pGLInfo->dwOverlayAlphaSetFB = (DWORD)-1;
  1481. // Clean up the temporary buffer, if any.
  1482. if ( pThisDisplay->OverlayTempSurf.VidMem != (ULONG_PTR)NULL )
  1483. {
  1484. FreeStretchBuffer ( pThisDisplay, pThisDisplay->OverlayTempSurf.VidMem );
  1485. pThisDisplay->OverlayTempSurf.VidMem = (ULONG_PTR)NULL;
  1486. pThisDisplay->OverlayTempSurf.Pitch = (DWORD)0;
  1487. }
  1488. // Restart the 2D renderer with non-overlay functions.
  1489. hDC = CREATE_DRIVER_DC ( pThisDisplay->pGLInfo );
  1490. if ( hDC != NULL )
  1491. {
  1492. ExtEscape ( hDC, GLINT_OVERLAY_ESCAPE, 0, NULL, 0, NULL );
  1493. DELETE_DRIVER_DC ( hDC );
  1494. }
  1495. else
  1496. {
  1497. DISPDBG((ERRLVL,"** UpdateOverlay32 - CREATE_DRIVER_DC failed"));
  1498. }
  1499. puod->ddRVal = DD_OK;
  1500. return DDHAL_DRIVER_HANDLED;
  1501. }
  1502. else if ( ( ( puod->dwFlags & DDOVER_SHOW ) != 0 ) || ( pThisDisplay->bOverlayVisible != 0 ) )
  1503. {
  1504. {
  1505. // Catch the dodgy call made by the Demon helper.
  1506. // This is very bad, but it's the only way I can see to
  1507. // get Demon to call these two functions.
  1508. // Remember that the various surfaces and so on are just
  1509. // to get DD to relax and accept life.
  1510. // The first three numbers are just that - magic numbers,
  1511. // and the last one shows which of a range of calls need to be made,
  1512. // as well as being a magic number itself.
  1513. if (
  1514. ( ( puod->dwFlags & DDOVER_SHOW ) != 0 ) &&
  1515. ( ( puod->dwFlags & DDOVER_KEYDESTOVERRIDE ) != 0 ) &&
  1516. ( ( puod->dwFlags & DDOVER_DDFX ) != 0 ) )
  1517. {
  1518. // OK, looks like a valid call from Demon.
  1519. if (
  1520. ( puod->overlayFX.dckDestColorkey.dwColorSpaceLowValue == GLDD_MAGIC_AUTOFLIPOVERLAY_DL ) &&
  1521. ( puod->overlayFX.dckDestColorkey.dwColorSpaceHighValue == GLDD_MAGIC_AUTOFLIPOVERLAY_DH ) )
  1522. {
  1523. puod->ddRVal = __VD_AutoflipOverlay();
  1524. // the return value is actually a benign DD error
  1525. // value, but GLDD_AUTO_RET_* are also aliased to the
  1526. // right one for useabiliy.
  1527. return DDHAL_DRIVER_HANDLED;
  1528. }
  1529. else if (
  1530. ( puod->overlayFX.dckDestColorkey.dwColorSpaceLowValue == GLDD_MAGIC_AUTOUPDATEOVERLAY_DL ) &&
  1531. ( puod->overlayFX.dckDestColorkey.dwColorSpaceHighValue == GLDD_MAGIC_AUTOUPDATEOVERLAY_DH ) )
  1532. {
  1533. puod->ddRVal = __VD_AutoupdateOverlay();
  1534. // the return value is actually a benign DD error
  1535. // value, but GLDD_AUTO_RET_* are also aliased to the
  1536. // right one for useabiliy.
  1537. return DDHAL_DRIVER_HANDLED;
  1538. }
  1539. }
  1540. }
  1541. DISPDBG((DBGLVL,"** UpdateOverlay32 - showing or reshowing."));
  1542. // Either we need to show this, or it is already being shown.
  1543. if ( ( pThisDisplay->bOverlayVisible != 0 ) && ( pThisDisplay->OverlaySrcSurfLcl != (ULONG_PTR)lpSrcSurf ) )
  1544. {
  1545. // Overlay being shown and source surfaces don't match.
  1546. // i.e. someone else wants an overlay, but it's already in use.
  1547. DISPDBG((DBGLVL,"** UpdateOverlay32 - overlay already being shown, returning DDERR_OUTOFCAPS"));
  1548. puod->ddRVal = DDERR_OUTOFCAPS;
  1549. return DDHAL_DRIVER_HANDLED;
  1550. }
  1551. // Clean up the temporary buffer, if any.
  1552. if ( pThisDisplay->OverlayTempSurf.VidMem != (ULONG_PTR)NULL )
  1553. {
  1554. FreeStretchBuffer ( pThisDisplay, pThisDisplay->OverlayTempSurf.VidMem );
  1555. pThisDisplay->OverlayTempSurf.VidMem = (ULONG_PTR)NULL;
  1556. pThisDisplay->OverlayTempSurf.Pitch = (DWORD)0;
  1557. }
  1558. // Store all the data in the display's data block.
  1559. pThisDisplay->bOverlayVisible = TRUE;
  1560. pThisDisplay->OverlayDstRectL = (DWORD)puod->rDest.left;
  1561. pThisDisplay->OverlayDstRectR = (DWORD)puod->rDest.right;
  1562. pThisDisplay->OverlayDstRectT = (DWORD)puod->rDest.top;
  1563. pThisDisplay->OverlayDstRectB = (DWORD)puod->rDest.bottom;
  1564. pThisDisplay->OverlaySrcRectL = (DWORD)puod->rSrc.left;
  1565. pThisDisplay->OverlaySrcRectR = (DWORD)puod->rSrc.right;
  1566. pThisDisplay->OverlaySrcRectT = (DWORD)puod->rSrc.top;
  1567. pThisDisplay->OverlaySrcRectB = (DWORD)puod->rSrc.bottom;
  1568. pThisDisplay->OverlayDstSurfLcl = (ULONG_PTR)puod->lpDDDestSurface;
  1569. pThisDisplay->OverlaySrcSurfLcl = (ULONG_PTR)lpSrcSurf;
  1570. pThisDisplay->OverlayUpdateCountdown = 0;
  1571. pThisDisplay->bOverlayFlippedThisVbl = (DWORD)FALSE;
  1572. pThisDisplay->bOverlayUpdatedThisVbl = (DWORD)FALSE;
  1573. pThisDisplay->OverlayDstColourKey = (DWORD)CLR_INVALID;
  1574. pThisDisplay->OverlaySrcColourKey = (DWORD)CLR_INVALID;
  1575. pThisDisplay->pGLInfo->bOverlayEnabled = (DWORD)TRUE;
  1576. // Make sure someone hasn't changed video mode behind our backs.
  1577. // If an overlay is started in a 16-bit mode and then you change to
  1578. // an 8-bit mode, the caps bits are rarely checked again,
  1579. // and certainly not by DirectShow.
  1580. if ( ( pThisDisplay->bPixShift != GLINTDEPTH16 ) &&
  1581. ( pThisDisplay->bPixShift != GLINTDEPTH32 ) )
  1582. {
  1583. DISPDBG((WRNLVL,"** UpdateOverlay32 - overlay asked for in non-16 or non-32 bit mode. Returning DDERR_OUTOFCAPS"));
  1584. goto update_overlay_outofcaps_cleanup;
  1585. }
  1586. #if 1
  1587. // See if there is a clipper or not. If not, this is trying to fly over the
  1588. // desktop instead of being bound in a window, so object nicely.
  1589. if ( ( ((LPDDRAWI_DDRAWSURFACE_LCL)pThisDisplay->OverlayDstSurfLcl) != NULL ) &&
  1590. ( ((LPDDRAWI_DDRAWSURFACE_LCL)pThisDisplay->OverlayDstSurfLcl)->lpSurfMore != NULL ) &&
  1591. ( ((LPDDRAWI_DDRAWSURFACE_LCL)pThisDisplay->OverlayDstSurfLcl)->lpSurfMore->lpDDIClipper != NULL ) )
  1592. {
  1593. // Yep, there's a clipper
  1594. }
  1595. else
  1596. {
  1597. // No clipper. Someone's doing a WHQL test! :-)
  1598. DISPDBG((WRNLVL,"** UpdateOverlay32 - no clipper on dest surface, returning DDERR_OUTOFCAPS"));
  1599. goto update_overlay_outofcaps_cleanup;
  1600. }
  1601. #endif
  1602. #if 1
  1603. {
  1604. // Get the cliprect list, and see if it is larger than the
  1605. // target rectangle. That is a pretty good indication of
  1606. // Overfly (and indeed anything else that tries anything similar)
  1607. LPRGNDATA lpRgn;
  1608. int NumRects;
  1609. LPRECT lpCurRect;
  1610. lpRgn = GetOverlayVisibleRects ( pThisDisplay );
  1611. if ( lpRgn != NULL )
  1612. {
  1613. // Got a clip region.
  1614. NumRects = lpRgn->rdh.nCount;
  1615. if ( NumRects > 0 )
  1616. {
  1617. lpCurRect = (LPRECT)lpRgn->Buffer;
  1618. while ( NumRects > 0 )
  1619. {
  1620. // The +-5 is a fudge factor to cope with Xing's slight insanities.
  1621. if ( ( lpCurRect->left < puod->rDest.left - 5 ) ||
  1622. ( lpCurRect->right > puod->rDest.right + 5 ) ||
  1623. ( lpCurRect->top < puod->rDest.top - 5 ) ||
  1624. ( lpCurRect->bottom > puod->rDest.bottom + 5 ) )
  1625. {
  1626. DISPDBG((WRNLVL,"** UpdateOverlay32 - out of range cliprect(s). Returning DDERR_OUTOFCAPS"));
  1627. goto update_overlay_outofcaps_cleanup;
  1628. }
  1629. // Next rect
  1630. NumRects--;
  1631. lpCurRect++;
  1632. }
  1633. }
  1634. }
  1635. }
  1636. #endif
  1637. dwDstColourKey = CLR_INVALID;
  1638. if ( puod->dwFlags & DDOVER_KEYDEST )
  1639. {
  1640. // Use destination surface's destination colourkey for dst key.
  1641. dwDstColourKey = puod->lpDDDestSurface->ddckCKDestOverlay.dwColorSpaceLowValue;
  1642. }
  1643. if ( puod->dwFlags & DDOVER_KEYDESTOVERRIDE )
  1644. {
  1645. // Use DDOVERLAYFX dest colour for dst key.
  1646. dwDstColourKey = puod->overlayFX.dckDestColorkey.dwColorSpaceLowValue;
  1647. }
  1648. dwSrcColourKey = CLR_INVALID;
  1649. if ( puod->dwFlags & DDOVER_KEYSRC )
  1650. {
  1651. // Use source surface's source colourkey for src key.
  1652. dwSrcColourKey = puod->lpDDSrcSurface->ddckCKSrcOverlay.dwColorSpaceLowValue;
  1653. DISPDBG((WRNLVL,"UpdateOverlay32:ERROR! Cannot do source colour key on overlays."));
  1654. }
  1655. if ( puod->dwFlags & DDOVER_KEYSRCOVERRIDE )
  1656. {
  1657. // Use DDOVERLAYFX src colour for src key.
  1658. dwSrcColourKey = puod->overlayFX.dckSrcColorkey.dwColorSpaceLowValue;
  1659. DISPDBG((WRNLVL,"UpdateOverlay32:ERROR! Cannot do source colour key overrides on overlays."));
  1660. }
  1661. if ( dwDstColourKey != CLR_INVALID )
  1662. {
  1663. DWORD dwChipColourKey;
  1664. DWORD dwFBColourKey;
  1665. DWORD dwFBAlphaSet;
  1666. // Find the chip's colour key for this display mode.
  1667. dwChipColourKey = (DWORD)-1;
  1668. switch ( pThisDisplay->bPixShift )
  1669. {
  1670. case GLINTDEPTH16:
  1671. if ( pThisDisplay->ddpfDisplay.dwRBitMask == 0x7C00 )
  1672. {
  1673. // 5551 format, as it should be.
  1674. dwFBColourKey = ( puod->lpDDDestSurface->ddckCKDestOverlay.dwColorSpaceLowValue ) & 0xffff;
  1675. dwChipColourKey = CHROMA_LOWER_ALPHA(FORMAT_5551_32BIT_BGR(dwFBColourKey));
  1676. // Replicate in both words.
  1677. dwFBColourKey |= dwFBColourKey << 16;
  1678. dwFBAlphaSet = 0x80008000;
  1679. }
  1680. else
  1681. {
  1682. // 565 format. Oops.
  1683. DISPDBG((WRNLVL, "** UpdateOverlay32 error: called for a colourkeyed 565 surface."));
  1684. }
  1685. break;
  1686. case GLINTDEPTH32:
  1687. dwFBColourKey = puod->lpDDDestSurface->ddckCKDestOverlay.dwColorSpaceLowValue;
  1688. dwChipColourKey = CHROMA_LOWER_ALPHA(FORMAT_8888_32BIT_BGR(dwFBColourKey));
  1689. dwFBAlphaSet = 0xff000000;
  1690. break;
  1691. case GLINTDEPTH8:
  1692. case GLINTDEPTH24:
  1693. default:
  1694. DISPDBG((WRNLVL, "** UpdateOverlay32 error: called for an 8, 24 or unknown surface bPixShift=%d", pThisDisplay->bPixShift));
  1695. DISPDBG((ERRLVL,"** UpdateOverlay32 error: see above."));
  1696. goto update_overlay_outofcaps_cleanup;
  1697. break;
  1698. }
  1699. if ( dwChipColourKey == (DWORD)-1 )
  1700. {
  1701. DISPDBG((WRNLVL,"UpdateOverlay32:ERROR:Cannot do overlay dest colour keying..."));
  1702. DISPDBG((WRNLVL,"...in anything but 5551 or 8888 mode - returning DDERR_OUTOFCAPS"));
  1703. goto update_overlay_outofcaps_cleanup;
  1704. }
  1705. pThisDisplay->pGLInfo->bOverlayEnabled = (DWORD)TRUE;
  1706. pThisDisplay->pGLInfo->dwOverlayDstColourKeyFB = dwFBColourKey;
  1707. pThisDisplay->pGLInfo->dwOverlayDstColourKeyChip = dwChipColourKey;
  1708. pThisDisplay->pGLInfo->bOverlayColourKeyEnabled = (DWORD)TRUE;
  1709. pThisDisplay->pGLInfo->dwOverlayAlphaSetFB = dwFBAlphaSet;
  1710. // Try to allocate the temporary buffer needed for colourkey stuff.
  1711. pThisDisplay->OverlayTempSurf.VidMem = AllocStretchBuffer (pThisDisplay,
  1712. (pThisDisplay->OverlayDstRectR - pThisDisplay->OverlayDstRectL), // width
  1713. (pThisDisplay->OverlayDstRectB - pThisDisplay->OverlayDstRectT), // height
  1714. DDSurf_GetChipPixelSize((LPDDRAWI_DDRAWSURFACE_LCL)(pThisDisplay->OverlayDstSurfLcl)), // PixelSize
  1715. (ULONG_PTR)((LPDDRAWI_DDRAWSURFACE_LCL)(pThisDisplay->OverlayDstSurfLcl))->ddsCaps.dwCaps,
  1716. (int*)&(pThisDisplay->OverlayTempSurf.Pitch));
  1717. if ( pThisDisplay->OverlayTempSurf.VidMem == (ULONG_PTR)NULL )
  1718. {
  1719. // Not enough space - have to fail the overlay
  1720. DISPDBG((WRNLVL,"UpdateOverlay32:ERROR: not enough memory for buffer - returning DDERR_OUTOFCAPS"));
  1721. pThisDisplay->OverlayTempSurf.Pitch = (DWORD)0;
  1722. goto update_overlay_outofcaps_cleanup;
  1723. }
  1724. // Restart the 2D renderer with overlay functions.
  1725. hDC = CREATE_DRIVER_DC ( pThisDisplay->pGLInfo );
  1726. if ( hDC != NULL )
  1727. {
  1728. ExtEscape ( hDC, GLINT_OVERLAY_ESCAPE, 0, NULL, 0, NULL );
  1729. DELETE_DRIVER_DC ( hDC );
  1730. }
  1731. else
  1732. {
  1733. DISPDBG((ERRLVL,"** UpdateOverlay32 - CREATE_DRIVER_DC failed"));
  1734. }
  1735. // update the alpha channel
  1736. UpdateAlphaOverlay ( pThisDisplay );
  1737. pThisDisplay->OverlayUpdateCountdown = OVERLAY_UPDATE_WAIT;
  1738. }
  1739. else
  1740. {
  1741. // No colour key, just an overlay.
  1742. pThisDisplay->pGLInfo->bOverlayEnabled = (DWORD)TRUE;
  1743. pThisDisplay->pGLInfo->bOverlayColourKeyEnabled = (DWORD)FALSE;
  1744. pThisDisplay->pGLInfo->dwOverlayDstColourKeyChip = (DWORD)-1;
  1745. pThisDisplay->pGLInfo->dwOverlayDstColourKeyFB = (DWORD)-1;
  1746. pThisDisplay->pGLInfo->dwOverlayAlphaSetFB = (DWORD)-1;
  1747. // Restart the 2D renderer with non-overlay functions.
  1748. hDC = CREATE_DRIVER_DC ( pThisDisplay->pGLInfo );
  1749. if ( hDC != NULL )
  1750. {
  1751. ExtEscape ( hDC, GLINT_OVERLAY_ESCAPE, 0, NULL, 0, NULL );
  1752. DELETE_DRIVER_DC ( hDC );
  1753. }
  1754. else
  1755. {
  1756. DISPDBG((ERRLVL,"** UpdateOverlay32 - CREATE_DRIVER_DC failed"));
  1757. }
  1758. }
  1759. // Safely got any memory required, so we can set these up now.
  1760. pThisDisplay->OverlayDstColourKey = dwDstColourKey;
  1761. pThisDisplay->OverlaySrcColourKey = dwSrcColourKey;
  1762. pThisDisplay->pGLInfo->dwOverlayRectL = pThisDisplay->OverlayDstRectL;
  1763. pThisDisplay->pGLInfo->dwOverlayRectR = pThisDisplay->OverlayDstRectR;
  1764. pThisDisplay->pGLInfo->dwOverlayRectT = pThisDisplay->OverlayDstRectT;
  1765. pThisDisplay->pGLInfo->dwOverlayRectB = pThisDisplay->OverlayDstRectB;
  1766. // Do the update itself.
  1767. P3TestDrawOverlay ( pThisDisplay, lpSrcSurf, FALSE );
  1768. pThisDisplay->bOverlayUpdatedThisVbl = (DWORD)TRUE;
  1769. if ( ( puod->dwFlags & DDOVER_AUTOFLIP ) == 0 )
  1770. {
  1771. // Start or continue any autoupdates - this is not autoflipping.
  1772. #if DBG
  1773. if ( pThisDisplay->pGLInfo->dwMonitorEventHandle == (DWORD)NULL )
  1774. {
  1775. DISPDBG((WRNLVL,"** UpdateOverlay32 - trying to autoupdate using bogus event handle."));
  1776. }
  1777. #endif
  1778. if ( pThisDisplay->pGLInfo->dwPeriodMonitorVBL == 0 )
  1779. {
  1780. pThisDisplay->pGLInfo->dwPeriodMonitorVBL = OVERLAY_AUTOUPDATE_CYCLE_PERIOD;
  1781. pThisDisplay->pGLInfo->dwCountdownMonitorVBL = OVERLAY_AUTOUPDATE_RESET_PERIOD;
  1782. DISPDBG((DBGLVL,"** UpdateOverlay32 - autoupdate now enabled."));
  1783. }
  1784. }
  1785. else
  1786. {
  1787. // This autoflips - stop any autoupdates.
  1788. if ( pThisDisplay->pGLInfo->dwPeriodMonitorVBL != 0 )
  1789. {
  1790. pThisDisplay->pGLInfo->dwPeriodMonitorVBL = 0;
  1791. pThisDisplay->pGLInfo->dwCountdownMonitorVBL = 0;
  1792. DISPDBG((DBGLVL,"** UpdateOverlay32 - autoupdate now disabled because of autoflipping."));
  1793. }
  1794. }
  1795. // And tell the world about it
  1796. DISPDBG((DBGLVL,"** In UpdateOverlay32"));
  1797. DISPDBG((DBGLVL,"** ...Src rect %d,%d -> %d,%d", pThisDisplay->OverlaySrcRectL, pThisDisplay->OverlaySrcRectT, pThisDisplay->OverlaySrcRectR, pThisDisplay->OverlaySrcRectB ));
  1798. DISPDBG((DBGLVL,"** ...Dst rect %d,%d -> %d,%d", pThisDisplay->OverlayDstRectL, pThisDisplay->OverlayDstRectT, pThisDisplay->OverlayDstRectR, pThisDisplay->OverlayDstRectB ));
  1799. DISPDBG((DBGLVL,"** ...Src colour key 0x%08x, dst colour key 0x%08x", pThisDisplay->OverlaySrcColourKey, pThisDisplay->OverlayDstColourKey ));
  1800. }
  1801. puod->ddRVal = DD_OK;
  1802. return DDHAL_DRIVER_HANDLED;
  1803. update_overlay_outofcaps_cleanup:
  1804. // This cleans up after any partial setup, and returns DDERR_OUTOFCAPS.
  1805. // It's a clean and easy way of failing at any stage.
  1806. DISPDBG((DBGLVL,"** UpdateOverlay32 - cleaning up and returning DDERR_OUTOFCAPS."));
  1807. // Stop any autoflipping.
  1808. if ( pThisDisplay->pGLInfo->dwPeriodVideoVBL != 0 )
  1809. {
  1810. #if DBG
  1811. if ( pThisDisplay->pGLInfo->dwVideoEventHandle == (DWORD)NULL )
  1812. {
  1813. DISPDBG((DBGLVL,"** UpdateOverlay32 - DDOVER_HIDE - was autoflipping on bogus event handle."));
  1814. }
  1815. #endif
  1816. pThisDisplay->pGLInfo->dwPeriodVideoVBL = 0;
  1817. pThisDisplay->pGLInfo->dwCountdownVideoVBL = 0;
  1818. DISPDBG((DBGLVL,"** UpdateOverlay32 - DDOVER_HIDE - autoflipping now disabled."));
  1819. }
  1820. if ( pThisDisplay->pGLInfo->dwPeriodMonitorVBL != 0 )
  1821. {
  1822. #if DBG
  1823. if ( pThisDisplay->pGLInfo->dwMonitorEventHandle == (DWORD)NULL )
  1824. {
  1825. DISPDBG((DBGLVL,"** UpdateOverlay32 - DDOVER_HIDE - was autoupdating on bogus event handle."));
  1826. }
  1827. #endif
  1828. pThisDisplay->pGLInfo->dwPeriodMonitorVBL = 0;
  1829. pThisDisplay->pGLInfo->dwCountdownMonitorVBL = 0;
  1830. DISPDBG((DBGLVL,"** UpdateOverlay32 - DDOVER_HIDE - autoupdate now disabled."));
  1831. }
  1832. // Free the rect memory
  1833. if ( (void *)pThisDisplay->OverlayClipRgnMem != NULL )
  1834. {
  1835. HEAP_FREE ((void *)pThisDisplay->OverlayClipRgnMem);
  1836. }
  1837. pThisDisplay->OverlayClipRgnMem = (ULONG_PTR)NULL;
  1838. pThisDisplay->OverlayClipRgnMemSize = (DWORD)0;
  1839. pThisDisplay->bOverlayVisible = FALSE;
  1840. pThisDisplay->OverlayDstRectL = (DWORD)0;
  1841. pThisDisplay->OverlayDstRectR = (DWORD)0;
  1842. pThisDisplay->OverlayDstRectT = (DWORD)0;
  1843. pThisDisplay->OverlayDstRectB = (DWORD)0;
  1844. pThisDisplay->OverlaySrcRectL = (DWORD)0;
  1845. pThisDisplay->OverlaySrcRectR = (DWORD)0;
  1846. pThisDisplay->OverlaySrcRectT = (DWORD)0;
  1847. pThisDisplay->OverlaySrcRectB = (DWORD)0;
  1848. pThisDisplay->OverlayDstSurfLcl = (ULONG_PTR)NULL;
  1849. pThisDisplay->OverlaySrcSurfLcl = (ULONG_PTR)NULL;
  1850. pThisDisplay->OverlayDstColourKey = (DWORD)CLR_INVALID;
  1851. pThisDisplay->OverlaySrcColourKey = (DWORD)CLR_INVALID;
  1852. pThisDisplay->OverlayUpdateCountdown = 0;
  1853. pThisDisplay->bOverlayFlippedThisVbl = (DWORD)FALSE;
  1854. pThisDisplay->bOverlayUpdatedThisVbl = (DWORD)FALSE;
  1855. pThisDisplay->pGLInfo->bOverlayEnabled = (DWORD)FALSE;
  1856. pThisDisplay->pGLInfo->dwOverlayRectL = (DWORD)0;
  1857. pThisDisplay->pGLInfo->dwOverlayRectR = (DWORD)0;
  1858. pThisDisplay->pGLInfo->dwOverlayRectT = (DWORD)0;
  1859. pThisDisplay->pGLInfo->dwOverlayRectB = (DWORD)0;
  1860. pThisDisplay->pGLInfo->bOverlayColourKeyEnabled = (DWORD)FALSE;
  1861. pThisDisplay->pGLInfo->dwOverlayDstColourKeyChip = (DWORD)-1;
  1862. pThisDisplay->pGLInfo->dwOverlayDstColourKeyFB = (DWORD)-1;
  1863. pThisDisplay->pGLInfo->dwOverlayAlphaSetFB = (DWORD)-1;
  1864. // Clean up the temporary buffer, if any.
  1865. if ( pThisDisplay->OverlayTempSurf.VidMem != (ULONG_PTR)NULL )
  1866. {
  1867. FreeStretchBuffer ( pThisDisplay, pThisDisplay->OverlayTempSurf.VidMem );
  1868. pThisDisplay->OverlayTempSurf.VidMem = (ULONG_PTR)NULL;
  1869. pThisDisplay->OverlayTempSurf.Pitch = (DWORD)0;
  1870. }
  1871. // Restart the 2D renderer with non-overlay functions.
  1872. hDC = CREATE_DRIVER_DC ( pThisDisplay->pGLInfo );
  1873. if ( hDC != NULL )
  1874. {
  1875. ExtEscape ( hDC, GLINT_OVERLAY_ESCAPE, 0, NULL, 0, NULL );
  1876. DELETE_DRIVER_DC ( hDC );
  1877. }
  1878. else
  1879. {
  1880. DISPDBG((ERRLVL,"** UpdateOverlay32 - CREATE_DRIVER_DC failed"));
  1881. }
  1882. puod->ddRVal = DDERR_OUTOFCAPS;
  1883. return DDHAL_DRIVER_HANDLED;
  1884. }
  1885. DWORD CALLBACK SetOverlayPosition32(LPDDHAL_SETOVERLAYPOSITIONDATA psopd)
  1886. {
  1887. P3_THUNKEDDATA* pThisDisplay;
  1888. GET_THUNKEDDATA(pThisDisplay, psopd->lpDD);
  1889. // /*
  1890. // * A psopd looks like this:
  1891. // *
  1892. // * LPDDRAWI_DIRECTDRAW_GBL lpDD; // driver struct
  1893. // * LPDDRAWI_DDRAWSURFACE_LCL lpDDSrcSurface; // src surface
  1894. // * LPDDRAWI_DDRAWSURFACE_LCL lpDDDestSurface; // dest surface
  1895. // * LONG lXPos; // x position
  1896. // * LONG lYPos; // y position
  1897. // * HRESULT ddRVal; // return value
  1898. // * LPDDHALSURFCB_SETOVERLAYPOSITION SetOverlayPosition; // PRIVATE: ptr to callback
  1899. // */
  1900. #if DBG
  1901. // Standard integrity test.
  1902. if ( pThisDisplay->bOverlayVisible == 0 )
  1903. {
  1904. if ( (LPDDRAWI_DDRAWSURFACE_LCL)pThisDisplay->OverlaySrcSurfLcl != NULL )
  1905. {
  1906. // If overlay is not visible, the current surface should be NULL.
  1907. DISPDBG((DBGLVL,"** SetOverlayPosition32 - vis==0,srcsurf!=NULL"));
  1908. }
  1909. }
  1910. else
  1911. {
  1912. if ( (LPDDRAWI_DDRAWSURFACE_LCL)pThisDisplay->OverlaySrcSurfLcl == NULL )
  1913. {
  1914. // If overlay is visible, the current surface should not be NULL.
  1915. DISPDBG((DBGLVL,"** SetOverlayPosition32 - vis!=0,srcsurf==NULL"));
  1916. }
  1917. }
  1918. #endif //DBG
  1919. if ( pThisDisplay->bOverlayVisible == 0 )
  1920. {
  1921. // No overlay is visible.
  1922. psopd->ddRVal = DDERR_OVERLAYNOTVISIBLE;
  1923. return DDHAL_DRIVER_HANDLED;
  1924. }
  1925. if ( pThisDisplay->OverlaySrcSurfLcl != (ULONG_PTR)psopd->lpDDSrcSurface )
  1926. {
  1927. // This overlay isn't visible.
  1928. psopd->ddRVal = DDERR_OVERLAYNOTVISIBLE;
  1929. return DDHAL_DRIVER_HANDLED;
  1930. }
  1931. #if DBG
  1932. if ( pThisDisplay->OverlayDstSurfLcl != (ULONG_PTR)psopd->lpDDDestSurface )
  1933. {
  1934. // Oh dear. The destination surfaces don't agree.
  1935. DISPDBG((DBGLVL,"** SetOverlayPosition32 - dest surfaces don't agree"));
  1936. }
  1937. #endif //DBG
  1938. // Move the rect
  1939. pThisDisplay->OverlayDstRectR += (DWORD)( psopd->lXPos - (LONG)pThisDisplay->OverlayDstRectL );
  1940. pThisDisplay->OverlayDstRectB += (DWORD)( psopd->lYPos - (LONG)pThisDisplay->OverlayDstRectT );
  1941. pThisDisplay->OverlayDstRectL = (DWORD)psopd->lXPos;
  1942. pThisDisplay->OverlayDstRectT = (DWORD)psopd->lYPos;
  1943. pThisDisplay->pGLInfo->dwOverlayRectL = pThisDisplay->OverlayDstRectL;
  1944. pThisDisplay->pGLInfo->dwOverlayRectR = pThisDisplay->OverlayDstRectR;
  1945. pThisDisplay->pGLInfo->dwOverlayRectT = pThisDisplay->OverlayDstRectT;
  1946. pThisDisplay->pGLInfo->dwOverlayRectB = pThisDisplay->OverlayDstRectB;
  1947. if ( pThisDisplay->OverlayDstColourKey != CLR_INVALID )
  1948. {
  1949. // update the alpha channel
  1950. UpdateAlphaOverlay ( pThisDisplay );
  1951. pThisDisplay->OverlayUpdateCountdown = OVERLAY_UPDATE_WAIT;
  1952. }
  1953. // Do the update itself.
  1954. P3TestDrawOverlay ( pThisDisplay, psopd->lpDDSrcSurface, FALSE );
  1955. pThisDisplay->bOverlayUpdatedThisVbl = (DWORD)TRUE;
  1956. // And tell the world about it
  1957. DISPDBG((DBGLVL,"** In SetOverlayPosition32"));
  1958. DISPDBG((DBGLVL,"** ...Dst rect %d,%d -> %d,%d", pThisDisplay->OverlayDstRectL, pThisDisplay->OverlayDstRectT, pThisDisplay->OverlayDstRectR, pThisDisplay->OverlayDstRectB ));
  1959. psopd->ddRVal = DD_OK;
  1960. return DDHAL_DRIVER_HANDLED;
  1961. }
  1962. /****************************************************************************
  1963. *
  1964. * LPRGNDATA GetOverlayVisibleRects ( P3_THUNKEDDATA* pThisDisplay );
  1965. *
  1966. * In:
  1967. * P3_THUNKEDDATA* pThisDisplay; This display's pointer
  1968. *
  1969. * Out:
  1970. * LPRGNDATA; A pointer to the list of rects.
  1971. *
  1972. * Notes:
  1973. * Returns a pointer to a list of rects that shows the visible
  1974. * sections of the currently overlaid surface. This list is clipped by
  1975. * the overlay's intended rectange, so no other bounds checking needs to
  1976. * be done.
  1977. * Note that the memory returned is private and may only be read by
  1978. * other functions. The actual memory is owned by
  1979. * pThisDisplay->OverlayClipRgnMem, and should only be changed by this
  1980. * function (or freed in selected other places). The memory may change
  1981. * every time this function is called, or when various other overlay
  1982. * functions are called.
  1983. *
  1984. ***************************************************************************/
  1985. LPRGNDATA GetOverlayVisibleRects ( P3_THUNKEDDATA* pThisDisplay )
  1986. {
  1987. // Use any clipper available.
  1988. LPDDRAWI_DDRAWCLIPPER_INT lpDDIClipper;
  1989. HRESULT hRes;
  1990. int ClipSize;
  1991. RECT rBound;
  1992. rBound.left = pThisDisplay->OverlayDstRectL;
  1993. rBound.right = pThisDisplay->OverlayDstRectR;
  1994. rBound.top = pThisDisplay->OverlayDstRectT;
  1995. rBound.bottom = pThisDisplay->OverlayDstRectB;
  1996. // No WinWatch. Try doing an immediate call.
  1997. lpDDIClipper = NULL;
  1998. if ( ((LPDDRAWI_DDRAWSURFACE_LCL)pThisDisplay->OverlayDstSurfLcl) != NULL )
  1999. {
  2000. if ( ((LPDDRAWI_DDRAWSURFACE_LCL)pThisDisplay->OverlayDstSurfLcl)->lpSurfMore != NULL )
  2001. {
  2002. lpDDIClipper = ((LPDDRAWI_DDRAWSURFACE_LCL)pThisDisplay->OverlayDstSurfLcl)->lpSurfMore->lpDDIClipper;
  2003. }
  2004. }
  2005. if ( lpDDIClipper != NULL )
  2006. {
  2007. #ifdef __cplusplus
  2008. hRes = ((IDirectDrawClipper*)(lpDDIClipper->lpVtbl))->GetClipList (&rBound, NULL, (unsigned long*)&ClipSize );
  2009. #else
  2010. hRes = ((IDirectDrawClipperVtbl *)(lpDDIClipper->lpVtbl))->GetClipList ( (IDirectDrawClipper *)lpDDIClipper, &rBound, NULL, &ClipSize );
  2011. #endif
  2012. if ( hRes == DD_OK )
  2013. {
  2014. // Reallocate if need be.
  2015. if ( ClipSize > (int)pThisDisplay->OverlayClipRgnMemSize )
  2016. {
  2017. if (pThisDisplay->OverlayClipRgnMem != 0 )
  2018. {
  2019. HEAP_FREE ((void *)pThisDisplay->OverlayClipRgnMem);
  2020. pThisDisplay->OverlayClipRgnMem = 0;
  2021. }
  2022. pThisDisplay->OverlayClipRgnMem = (ULONG_PTR)HEAP_ALLOC (0,
  2023. ClipSize,
  2024. ALLOC_TAG_DX(F));
  2025. if ( (void *)pThisDisplay->OverlayClipRgnMem == NULL )
  2026. {
  2027. DISPDBG((ERRLVL,"ERROR: Flip32: Could not allocate heap memory for clip region"));
  2028. pThisDisplay->OverlayClipRgnMemSize = 0;
  2029. return ( NULL );
  2030. }
  2031. else
  2032. {
  2033. pThisDisplay->OverlayClipRgnMemSize = ClipSize;
  2034. }
  2035. }
  2036. if ( (void *)pThisDisplay->OverlayClipRgnMem != NULL )
  2037. {
  2038. // OK, got some good memory.
  2039. #ifdef __cplusplus
  2040. hRes = ((IDirectDrawClipper*)(lpDDIClipper->lpVtbl))->GetClipList (&rBound, (LPRGNDATA)pThisDisplay->OverlayClipRgnMem, (unsigned long*)&ClipSize );
  2041. #else
  2042. hRes = ((IDirectDrawClipperVtbl *)(lpDDIClipper->lpVtbl))->GetClipList ( (IDirectDrawClipper *)lpDDIClipper, &rBound, (LPRGNDATA)pThisDisplay->OverlayClipRgnMem, &ClipSize );
  2043. #endif
  2044. if ( hRes != DD_OK )
  2045. {
  2046. DISPDBG((ERRLVL,"ERROR: Flip32: GetClipList failed."));
  2047. return ( NULL );
  2048. }
  2049. else
  2050. {
  2051. LPRECT lpCurRect;
  2052. RECT rBound;
  2053. int NumRects;
  2054. LPRGNDATA lpRgn;
  2055. // Adjust their bounding rect so it actually does bound all the
  2056. // rects.
  2057. lpRgn = (LPRGNDATA)pThisDisplay->OverlayClipRgnMem;
  2058. lpCurRect = (LPRECT)lpRgn->Buffer;
  2059. NumRects = lpRgn->rdh.nCount;
  2060. if ( NumRects > 0 )
  2061. {
  2062. rBound = *lpCurRect;
  2063. NumRects--;
  2064. lpCurRect++;
  2065. while ( NumRects > 0 )
  2066. {
  2067. if ( rBound.left > lpCurRect->left )
  2068. {
  2069. rBound.left = lpCurRect->left;
  2070. }
  2071. if ( rBound.top > lpCurRect->top )
  2072. {
  2073. rBound.top = lpCurRect->top;
  2074. }
  2075. if ( rBound.right < lpCurRect->right )
  2076. {
  2077. rBound.right = lpCurRect->right;
  2078. }
  2079. if ( rBound.bottom < lpCurRect->bottom )
  2080. {
  2081. rBound.bottom = lpCurRect->bottom;
  2082. }
  2083. NumRects--;
  2084. lpCurRect++;
  2085. }
  2086. #if DBG
  2087. // Were the two bounding rectangles the same?
  2088. if ( ( rBound.left != lpRgn->rdh.rcBound.left ) ||
  2089. ( rBound.right != lpRgn->rdh.rcBound.right ) ||
  2090. ( rBound.top != lpRgn->rdh.rcBound.top ) ||
  2091. ( rBound.bottom != lpRgn->rdh.rcBound.bottom ) )
  2092. {
  2093. DISPDBG((DBGLVL,"GetOverlayVisibleRects: area bounding box does not actually bound!"));
  2094. DISPDBG((DBGLVL,"My bounding rect %d,%d->%d,%d", rBound.left, rBound.top, rBound.right, rBound.bottom ));
  2095. DISPDBG((DBGLVL,"Their bounding rect %d,%d->%d,%d", lpRgn->rdh.rcBound.left, lpRgn->rdh.rcBound.top, lpRgn->rdh.rcBound.right, lpRgn->rdh.rcBound.bottom ));
  2096. }
  2097. #endif
  2098. lpRgn->rdh.rcBound = rBound;
  2099. // Phew - we finally got a clip region.
  2100. return ( (LPRGNDATA)pThisDisplay->OverlayClipRgnMem );
  2101. }
  2102. else
  2103. {
  2104. // No cliplist.
  2105. return ( NULL );
  2106. }
  2107. }
  2108. }
  2109. else
  2110. {
  2111. return ( NULL );
  2112. }
  2113. }
  2114. else
  2115. {
  2116. return ( NULL );
  2117. }
  2118. }
  2119. return ( NULL );
  2120. }
  2121. /****************************************************************************
  2122. *
  2123. * DWORD GLDD__Autoflip_Overlay ( void );
  2124. *
  2125. * In:
  2126. * None.
  2127. *
  2128. * Out:
  2129. * Error code:
  2130. * GLDD_AUTO_RET_DID_UPDATE = no error - did update.
  2131. * GLDD_AUTO_RET_ERR_GENERAL = general error.
  2132. * GLDD_AUTO_RET_ERR_NO_OVERLAY = no autoflipping overlay(s).
  2133. *
  2134. * Notes:
  2135. * This is called by the Demon helper program that sits waiting for
  2136. * video-in VBLANKS, then calls this.
  2137. * This flips the current overlay if it is marked as autoflipping. If
  2138. * there is such an overlay, it returns 0, otherwise it returns 1.
  2139. *
  2140. ***************************************************************************/
  2141. DWORD CALLBACK __VD_AutoflipOverlay ( void )
  2142. {
  2143. P3_THUNKEDDATA* pThisDisplay;
  2144. LPDDRAWI_DIRECTDRAW_GBL lpDD;
  2145. LPDDRAWI_DDRAWSURFACE_LCL pCurSurf;
  2146. DDHAL_FLIPVPORTDATA ddhFVPD;
  2147. // This is hard-coded and doesn't on work multi-monitors.
  2148. // But then nothing does, so...
  2149. pThisDisplay = g_pDriverData;
  2150. DISPDBG((DBGLVL,"**In __VD_AutoflipOverlay"));
  2151. if ( pThisDisplay->VidPort.bActive )
  2152. {
  2153. // Video port is active.
  2154. // Find the buffer to show.
  2155. pCurSurf = pThisDisplay->VidPort.lpSurf [ pThisDisplay->VidPort.dwCurrentHostFrame ];
  2156. if ( pCurSurf == NULL )
  2157. {
  2158. DISPDBG((WRNLVL,"ERROR:__VD_AutoflipOverlay: pCurSurf is NULL."));
  2159. return ( GLDD_AUTO_RET_ERR_NO_OVERLAY );
  2160. }
  2161. if ( pCurSurf->lpGbl == NULL )
  2162. {
  2163. DISPDBG((WRNLVL,"ERROR:__VD_AutoflipOverlay: lpGbl is NULL."));
  2164. return ( GLDD_AUTO_RET_ERR_GENERAL );
  2165. }
  2166. lpDD = pCurSurf->lpGbl->lpDD;
  2167. if ( lpDD == NULL )
  2168. {
  2169. DISPDBG((WRNLVL,"ERROR:__VD_AutoflipOverlay: lpDD is NULL."));
  2170. return ( GLDD_AUTO_RET_ERR_GENERAL );
  2171. }
  2172. DISPDBG((DBGLVL,"__VD_AutoflipOverlay: GetDriverLock succeeded."));
  2173. // Find the current front surface.
  2174. pCurSurf = pThisDisplay->VidPort.lpSurf [ pThisDisplay->VidPort.dwCurrentHostFrame ];
  2175. P3TestDrawOverlay ( pThisDisplay, pCurSurf, TRUE );
  2176. pThisDisplay->bOverlayFlippedThisVbl = (DWORD)TRUE;
  2177. // And then flip.
  2178. // Fake up an LPDDHAL_FLIPVPORTDATA.
  2179. // Only item ever used is lpDD.
  2180. g_bFlipVideoPortDoingAutoflip = TRUE;
  2181. ddhFVPD.lpDD = pCurSurf->lpSurfMore->lpDD_lcl;
  2182. DdFlipVideoPort ( &ddhFVPD );
  2183. g_bFlipVideoPortDoingAutoflip = FALSE;
  2184. return ( GLDD_AUTO_RET_DID_UPDATE );
  2185. }
  2186. else
  2187. {
  2188. DISPDBG((DBGLVL,"ERROR:__VD_AutoflipOverlay: video port not active."));
  2189. return ( GLDD_AUTO_RET_ERR_NO_OVERLAY );
  2190. }
  2191. }
  2192. /****************************************************************************
  2193. *
  2194. * DWORD __VD_AutoupdateOverlay ( void );
  2195. *
  2196. * In:
  2197. * None.
  2198. *
  2199. * Out:
  2200. * Error code:
  2201. * GLDD_AUTO_RET_NO_UPDATE = no need to do update.
  2202. * GLDD_AUTO_RET_DID_UPDATE = did update.
  2203. * GLDD_AUTO_RET_ERR_GENERAL = general error.
  2204. * GLDD_AUTO_RET_ERR_NO_OVERLAY = no standard overlay(s).
  2205. *
  2206. * Notes:
  2207. * This is called by the Demon helper program that sits waiting for
  2208. * monitor VBLANKS, then calls this.
  2209. * This checks any non-autoflipping overlay(s), and if they have not
  2210. * been flipped or updated this VBL, it redraws them. Then it resets the
  2211. * VBL flags.
  2212. *
  2213. ***************************************************************************/
  2214. DWORD CALLBACK __VD_AutoupdateOverlay ( void )
  2215. {
  2216. P3_THUNKEDDATA* pThisDisplay;
  2217. LPDDRAWI_DIRECTDRAW_GBL lpDD;
  2218. LPDDRAWI_DDRAWSURFACE_LCL pCurSurf;
  2219. DWORD iRet;
  2220. // This is hard-coded and doesn't on work multi-monitors.
  2221. // But then nothing does, so...
  2222. pThisDisplay = g_pDriverData;
  2223. if ( pThisDisplay->VidPort.bActive )
  2224. {
  2225. // Video port is active.
  2226. DISPDBG((WRNLVL,"ERROR:__VD_AutoupdateOverlay: video port is active."));
  2227. return ( GLDD_AUTO_RET_ERR_NO_OVERLAY );
  2228. }
  2229. else
  2230. {
  2231. // Find the buffer to show.
  2232. pCurSurf = (LPDDRAWI_DDRAWSURFACE_LCL)pThisDisplay->OverlaySrcSurfLcl;
  2233. if ( pCurSurf == NULL )
  2234. {
  2235. DISPDBG((WRNLVL,"ERROR:__VD_AutoupdateOverlay: pCurSurf is NULL."));
  2236. return ( GLDD_AUTO_RET_ERR_NO_OVERLAY );
  2237. }
  2238. if ( pCurSurf->lpGbl == NULL )
  2239. {
  2240. DISPDBG((WRNLVL,"ERROR:__VD_AutoupdateOverlay: lpGbl is NULL."));
  2241. return ( GLDD_AUTO_RET_ERR_NO_OVERLAY );
  2242. }
  2243. lpDD = pCurSurf->lpGbl->lpDD;
  2244. if ( lpDD == NULL )
  2245. {
  2246. DISPDBG((WRNLVL,"ERROR:__VD_AutoupdateOverlay: lpDD is NULL."));
  2247. return ( GLDD_AUTO_RET_ERR_GENERAL );
  2248. }
  2249. // See if the overlay needs showing.
  2250. if ( pThisDisplay->bOverlayFlippedThisVbl || pThisDisplay->bOverlayUpdatedThisVbl )
  2251. {
  2252. // Already done.
  2253. pThisDisplay->bOverlayFlippedThisVbl = FALSE;
  2254. pThisDisplay->bOverlayUpdatedThisVbl = FALSE;
  2255. iRet = GLDD_AUTO_RET_NO_UPDATE;
  2256. }
  2257. else
  2258. {
  2259. // OK, draw this.
  2260. P3TestDrawOverlay ( pThisDisplay, pCurSurf, TRUE );
  2261. // And clear the flags.
  2262. pThisDisplay->bOverlayFlippedThisVbl = FALSE;
  2263. pThisDisplay->bOverlayUpdatedThisVbl = FALSE;
  2264. iRet = GLDD_AUTO_RET_DID_UPDATE;
  2265. }
  2266. return ( iRet );
  2267. }
  2268. }
  2269. /****************************************************************************
  2270. *
  2271. * void DrawOverlay ( P3_THUNKEDDATA* pThisDisplay,
  2272. * LPDDRAWI_DDRAWSURFACE_LCL lpSurfOverlay,
  2273. * BOOL bSpeed );
  2274. *
  2275. * In:
  2276. * P3_THUNKEDDATA* pThisDisplay; This display's pointer
  2277. * LPDDRAWI_DDRAWSURFACE_LCL lpSurfOverlay; The overlay surface to draw.
  2278. * BOOL bSpeed; TRUE if this is a speedy call.
  2279. *
  2280. * Out:
  2281. * None.
  2282. *
  2283. * Notes:
  2284. * Takes the data in pThisDisplay and draws lpSurfOverlay onto
  2285. * its overlayed surface. All the other data comes from lpSurfOverlay.
  2286. * This allows you to call this from Flip32() without kludging the source
  2287. * surface pointer.
  2288. * This will find the cliprect list of the clipper attached to the
  2289. * overlaid surface, clipped by the overlay rectangle.. If there is no
  2290. * clipper, it just uses the rectangle of the overlay.
  2291. * The next operation depends on which colour keys are set:
  2292. * If no colour keys are set, the rects are just blitted on.
  2293. * If the destination colour key is set, three blits are done.
  2294. * The first stretches the YUV buffer to its final size. The second converts
  2295. * any of the given colour key to set its alpha bits. The third puts
  2296. * the overlay surface onto the screen where the alpha bits have been set,
  2297. * settign the alpha bits as it does so.
  2298. * If you cross your fingers and wish very very hard, this might
  2299. * actually work. It depends on nothing writing anything but 0 to the
  2300. * alpha bits, and on having alpha bits in the first place.
  2301. * bSpeed will be TRUE if we are aiming for out-and-out speed,
  2302. * otherwise the aim is to look pretty with as few artefacts as possible.
  2303. * Generally, speed tests are done single-buffered, so a call from
  2304. * Unlock32() will pass TRUE. Pretty tests are done with single-buffering,
  2305. * so Flip32() will pass FALSE. This is only a general guide, and some
  2306. * apps don't know about double-buffering at all. Such is life.
  2307. *
  2308. ***************************************************************************/
  2309. void DrawOverlay ( P3_THUNKEDDATA* pThisDisplay, LPDDRAWI_DDRAWSURFACE_LCL lpSurfOverlay, BOOL bSpeed )
  2310. {
  2311. RECTL rOverlay;
  2312. RECTL rTemp;
  2313. RECTL rFB;
  2314. LPDDRAWI_DDRAWSURFACE_LCL pOverlayLcl;
  2315. LPDDRAWI_DDRAWSURFACE_GBL pOverlayGbl;
  2316. DDRAWI_DDRAWSURFACE_LCL TempLcl;
  2317. DDRAWI_DDRAWSURFACE_GBL TempGbl;
  2318. LPDDRAWI_DDRAWSURFACE_LCL pFBLcl;
  2319. LPDDRAWI_DDRAWSURFACE_GBL pFBGbl;
  2320. P3_SURF_FORMAT* pFormatOverlay;
  2321. P3_SURF_FORMAT* pFormatTemp;
  2322. P3_SURF_FORMAT* pFormatFB;
  2323. DWORD localfpVidMem;
  2324. LONG localPitch;
  2325. LPDDRAWI_DIRECTDRAW_GBL lpDD;
  2326. DWORD dwColourKeyValue;
  2327. DWORD dwAlphaMask;
  2328. DWORD windowBaseOverlay;
  2329. DWORD windowBaseFB;
  2330. DWORD windowBaseTemp;
  2331. float OffsetX, OffsetY;
  2332. float ScaleX, ScaleY;
  2333. float fTemp;
  2334. int NumRects;
  2335. LPRECT lpCurRect;
  2336. LPRGNDATA lpRgn;
  2337. DWORD dwCurrentIndex, dwStartTime;
  2338. DWORD xScale;
  2339. DWORD yScale;
  2340. DWORD DestWidth;
  2341. DWORD DestHeight;
  2342. DWORD SourceWidth;
  2343. DWORD SourceHeight;
  2344. DWORD LowerBound;
  2345. DWORD UpperBound;
  2346. RECT TempRect;
  2347. P3_DMA_DEFS();
  2348. // Find the clipping rectangles for the overlay.
  2349. lpRgn = GetOverlayVisibleRects ( pThisDisplay );
  2350. if ( lpRgn != NULL )
  2351. {
  2352. pOverlayLcl = lpSurfOverlay;
  2353. pFBLcl = (LPDDRAWI_DDRAWSURFACE_LCL)pThisDisplay->OverlayDstSurfLcl;
  2354. lpDD = lpSurfOverlay->lpGbl->lpDD;
  2355. // Find the scale and offset from screen rects to overlay rects.
  2356. ScaleX = (float)( pThisDisplay->OverlaySrcRectR - pThisDisplay->OverlaySrcRectL ) / (float)( pThisDisplay->OverlayDstRectR - pThisDisplay->OverlayDstRectL );
  2357. ScaleY = (float)( pThisDisplay->OverlaySrcRectB - pThisDisplay->OverlaySrcRectT ) / (float)( pThisDisplay->OverlayDstRectB - pThisDisplay->OverlayDstRectT );
  2358. OffsetX = ( (float)pThisDisplay->OverlaySrcRectL / ScaleX ) - (float)pThisDisplay->OverlayDstRectL;
  2359. OffsetY = ( (float)pThisDisplay->OverlaySrcRectT / ScaleY ) - (float)pThisDisplay->OverlayDstRectT;
  2360. rFB.left = lpRgn->rdh.rcBound.left;
  2361. rFB.right = lpRgn->rdh.rcBound.right;
  2362. rFB.top = lpRgn->rdh.rcBound.top;
  2363. rFB.bottom = lpRgn->rdh.rcBound.bottom;
  2364. // Find the size of the screen bounding box.
  2365. if ( lpRgn->rdh.rcBound.left != (int)pThisDisplay->OverlayDstRectL )
  2366. {
  2367. fTemp = ( ( (float)lpRgn->rdh.rcBound.left + OffsetX ) * ScaleX + 0.499f );
  2368. myFtoi ( (int*)&(rOverlay.left), fTemp );
  2369. }
  2370. else
  2371. {
  2372. rOverlay.left = (int)pThisDisplay->OverlaySrcRectL;
  2373. }
  2374. if ( lpRgn->rdh.rcBound.right != (int)pThisDisplay->OverlayDstRectR )
  2375. {
  2376. fTemp = ( ( (float)lpRgn->rdh.rcBound.right + OffsetX ) * ScaleX + 0.499f );
  2377. myFtoi ( (int*)&(rOverlay.right), fTemp );
  2378. }
  2379. else
  2380. {
  2381. rOverlay.right = (int)pThisDisplay->OverlaySrcRectR;
  2382. }
  2383. if ( lpRgn->rdh.rcBound.top != (int)pThisDisplay->OverlayDstRectT )
  2384. {
  2385. fTemp = ( ( (float)lpRgn->rdh.rcBound.top + OffsetY ) * ScaleY + 0.499f );
  2386. myFtoi ( (int*)&(rOverlay.top), fTemp );
  2387. }
  2388. else
  2389. {
  2390. rOverlay.top = (int)pThisDisplay->OverlaySrcRectT;
  2391. }
  2392. if ( lpRgn->rdh.rcBound.bottom = (int)pThisDisplay->OverlayDstRectB )
  2393. {
  2394. fTemp = ( ( (float)lpRgn->rdh.rcBound.bottom + OffsetY ) * ScaleY + 0.499f );
  2395. myFtoi ( (int*)&(rOverlay.bottom), fTemp );
  2396. }
  2397. else
  2398. {
  2399. rOverlay.bottom = pThisDisplay->OverlaySrcRectB;
  2400. }
  2401. // Sync with the specific source surface.
  2402. // Videoport playing?
  2403. if ( ( pThisDisplay->VidPort.bActive == TRUE ) &&
  2404. ( ( pOverlayLcl->ddsCaps.dwCaps & DDSCAPS_VIDEOPORT ) != 0 ) )
  2405. {
  2406. dwStartTime = timeGetTime();
  2407. while ( TRUE )
  2408. {
  2409. dwCurrentIndex = READ_GLINT_CTRL_REG(VSAVideoAddressIndex);
  2410. if (pThisDisplay->VidPort.dwCurrentHostFrame == dwCurrentIndex)
  2411. {
  2412. // If the videoport is not stuck we are still drawing
  2413. if (!__VD_CheckVideoPortStatus(pThisDisplay, FALSE))
  2414. {
  2415. break;
  2416. }
  2417. }
  2418. else
  2419. {
  2420. break;
  2421. }
  2422. // Have we timed out?
  2423. if ( ( timeGetTime() - dwStartTime ) > OVERLAY_VIDEO_PORT_TIMEOUT )
  2424. {
  2425. return;
  2426. }
  2427. }
  2428. }
  2429. else
  2430. {
  2431. // Not a videoport blit, so wait for the framebuffer flip
  2432. // status to be good.
  2433. //@@BEGIN_DDKSPLIT
  2434. // Not actually sure if we want this in or not.
  2435. //@@END_DDKSPLIT
  2436. {
  2437. HRESULT ddrval;
  2438. do
  2439. {
  2440. ddrval = _DX_QueryFlipStatus(pThisDisplay, pFBLcl->lpGbl->fpVidMem, TRUE );
  2441. }
  2442. while ( ddrval != DD_OK );
  2443. }
  2444. }
  2445. if ( pThisDisplay->OverlayDstColourKey != CLR_INVALID )
  2446. {
  2447. // This is destination colourkeyed.
  2448. rTemp.left = 0;
  2449. rTemp.right = rFB.right - rFB.left;
  2450. rTemp.top = 0;
  2451. rTemp.bottom = rFB.bottom - rFB.top;
  2452. if ( pThisDisplay->OverlayUpdateCountdown != 0 )
  2453. {
  2454. pThisDisplay->OverlayUpdateCountdown -= OVERLAY_DRAWOVERLAY_SPEED;
  2455. if ( !bSpeed )
  2456. {
  2457. // This is a pretty call, not a fast one.
  2458. pThisDisplay->OverlayUpdateCountdown -= ( OVERLAY_DRAWOVERLAY_PRETTY - OVERLAY_DRAWOVERLAY_SPEED );
  2459. }
  2460. if ( ( (signed int)pThisDisplay->OverlayUpdateCountdown ) <= 0 )
  2461. {
  2462. // Update the overlay.
  2463. UpdateAlphaOverlay ( pThisDisplay );
  2464. // If you set this to 0, the overlay will never update again
  2465. // until a SetOverlayPosition() or UpdateOverlay32()
  2466. // Otherwise, set it to a positive value to update every now
  2467. // and then.
  2468. pThisDisplay->OverlayUpdateCountdown = OVERLAY_CYCLE_WAIT;
  2469. }
  2470. }
  2471. VALIDATE_MODE_AND_STATE(pThisDisplay);
  2472. // First stop dual cursor accesses
  2473. // Must be done before switching to DD context.
  2474. STOP_SOFTWARE_CURSOR(pThisDisplay);
  2475. // Switch to DirectDraw context
  2476. DDRAW_OPERATION(pContext, pThisDisplay);
  2477. DISPDBG((DBGLVL,"** In DrawOverlay"));
  2478. pOverlayGbl = pOverlayLcl->lpGbl;
  2479. pFBGbl = pFBLcl->lpGbl;
  2480. pFormatOverlay = _DD_SUR_GetSurfaceFormat(pOverlayLcl);
  2481. pFormatFB = _DD_SUR_GetSurfaceFormat(pFBLcl);
  2482. // Temp buffer will be same format as framebuffer.
  2483. pFormatTemp = pFormatFB;
  2484. DISPDBG((DBGLVL, "Overlay Surface:"));
  2485. DBGDUMP_DDRAWSURFACE_LCL(DBGLVL, pOverlayLcl);
  2486. DISPDBG((DBGLVL, "FB Surface:"));
  2487. DBGDUMP_DDRAWSURFACE_LCL(DBGLVL, pFBLcl);
  2488. dwColourKeyValue = pThisDisplay->OverlayDstColourKey;
  2489. switch ( pThisDisplay->bPixShift )
  2490. {
  2491. case GLINTDEPTH16:
  2492. if ( pThisDisplay->ddpfDisplay.dwRBitMask == 0x7C00 )
  2493. {
  2494. // 5551 format, as it should be.
  2495. dwAlphaMask = 0x8000;
  2496. }
  2497. else
  2498. {
  2499. // 565 format. Oops.
  2500. DISPDBG((WRNLVL, "** DrawOverlay error: called for a 565 surface"));
  2501. return;
  2502. }
  2503. break;
  2504. case GLINTDEPTH32:
  2505. dwAlphaMask = 0xff000000;
  2506. break;
  2507. case GLINTDEPTH8:
  2508. case GLINTDEPTH24:
  2509. default:
  2510. DISPDBG((WRNLVL, "** DrawOverlay error: called for an 8, 24 or unknown surface bPixShift=%d", pThisDisplay->bPixShift));
  2511. return;
  2512. break;
  2513. }
  2514. // dwColourKeyValue &= ~dwAlphaMask;
  2515. localfpVidMem = pThisDisplay->OverlayTempSurf.VidMem;
  2516. localPitch = pThisDisplay->OverlayTempSurf.Pitch;
  2517. if ( (void *)localfpVidMem == NULL )
  2518. {
  2519. // Nothing has been reserved for us! Panic stations!
  2520. DISPDBG((ERRLVL,"ERROR: DrawOverlay has no temporary surface allocated."));
  2521. return;
  2522. }
  2523. if ( localPitch < ( ( rTemp.right - rTemp.left ) << ( DDSurf_GetChipPixelSize(pFBLcl) ) ) )
  2524. {
  2525. // Reserved pitch is too small! Panic stations!
  2526. DISPDBG((WRNLVL,"DrawOverlay has left,right %d,%d, and overlay has left,right %d,%d", rFB.left, rFB.right, pThisDisplay->OverlayDstRectL, pThisDisplay->OverlayDstRectR ));
  2527. DISPDBG((WRNLVL,"ERROR: DrawOverlay has pitch %d and should be at least %d", localPitch, ( ( rTemp.right - rTemp.left ) << ( DDSurf_GetChipPixelSize(pFBLcl) ) ) ));
  2528. DISPDBG((ERRLVL,"ERROR: DrawOverlay has pitch too small to be right."));
  2529. return;
  2530. }
  2531. // Set the surface up.
  2532. TempLcl = *pFBLcl;
  2533. TempGbl = *(pFBLcl->lpGbl);
  2534. TempLcl.lpGbl = &TempGbl;
  2535. TempGbl.fpVidMem = localfpVidMem;
  2536. DDSurf_Pitch(&TempLcl) = localPitch;
  2537. // get bpp and pitches for surfaces.
  2538. windowBaseOverlay = __VD_PixelOffsetFromMemoryBase(pThisDisplay, pOverlayLcl);
  2539. windowBaseFB = __VD_PixelOffsetFromMemoryBase(pThisDisplay, pFBLcl);
  2540. windowBaseTemp = __VD_PixelOffsetFromMemoryBase(pThisDisplay, &TempLcl);
  2541. // Do the colourspace conversion and stretch/shrink of the overlay
  2542. {
  2543. DestWidth = rTemp.right - rTemp.left;
  2544. DestHeight = rTemp.bottom - rTemp.top;
  2545. SourceWidth = rOverlay.right - rOverlay.left;
  2546. SourceHeight = rOverlay.bottom - rOverlay.top;
  2547. xScale = (SourceWidth << 20) / DestWidth;
  2548. yScale = (SourceHeight << 20) / DestHeight;
  2549. P3_DMA_GET_BUFFER();
  2550. P3_ENSURE_DX_SPACE(80);
  2551. WAIT_FIFO(40);
  2552. SEND_P3_DATA(DitherMode, (COLOR_MODE << PM_DITHERMODE_COLORORDER) |
  2553. (SURFFORMAT_FORMAT_BITS(pFormatTemp) << PM_DITHERMODE_COLORFORMAT) |
  2554. (SURFFORMAT_FORMATEXTENSION_BITS(pFormatTemp) << PM_DITHERMODE_COLORFORMATEXTENSION) |
  2555. (1 << PM_DITHERMODE_ENABLE) |
  2556. (2 << PM_DITHERMODE_FORCEALPHA) |
  2557. (1 << PM_DITHERMODE_DITHERENABLE));
  2558. SEND_P3_DATA(FBReadPixel, DDSurf_GetChipPixelSize((&TempLcl)) );
  2559. SEND_P3_DATA(FBWindowBase, windowBaseTemp);
  2560. // set no read of source.
  2561. SEND_P3_DATA(FBReadMode, PACKED_PP_LOOKUP(DDSurf_GetPixelPitch((&TempLcl))));
  2562. SEND_P3_DATA(LogicalOpMode, __PERMEDIA_DISABLE);
  2563. // set base of source
  2564. SEND_P3_DATA(TextureBaseAddress, windowBaseOverlay);
  2565. SEND_P3_DATA(TextureAddressMode, PM_TEXADDRESSMODE_ENABLE(__PERMEDIA_ENABLE));
  2566. SEND_P3_DATA(TextureColorMode, PM_TEXCOLORMODE_ENABLE(__PERMEDIA_ENABLE) |
  2567. PM_TEXCOLORMODE_APPLICATIONMODE(__GLINT_TEXCOLORMODE_APPLICATION_COPY));
  2568. SEND_P3_DATA(TextureReadMode, PM_TEXREADMODE_ENABLE(__PERMEDIA_ENABLE) |
  2569. PM_TEXREADMODE_FILTER(__PERMEDIA_DISABLE) |
  2570. PM_TEXREADMODE_WIDTH(11) |
  2571. PM_TEXREADMODE_HEIGHT(11) );
  2572. SEND_P3_DATA(TextureMapFormat, PACKED_PP_LOOKUP(DDSurf_GetPixelPitch(pOverlayLcl)) |
  2573. (DDSurf_GetChipPixelSize(pOverlayLcl) << PM_TEXMAPFORMAT_TEXELSIZE) );
  2574. if ( pFormatOverlay->DeviceFormat == SURF_YUV422 )
  2575. {
  2576. // Turn on the YUV unit
  2577. SEND_P3_DATA(TextureDataFormat, PM_TEXDATAFORMAT_FORMAT(SURFFORMAT_FORMAT_BITS(pFormatOverlay)) |
  2578. PM_TEXDATAFORMAT_FORMATEXTENSION(SURFFORMAT_FORMATEXTENSION_BITS(pFormatOverlay)) |
  2579. PM_TEXDATAFORMAT_COLORORDER(INV_COLOR_MODE));
  2580. SEND_P3_DATA(YUVMode, 0x1);
  2581. }
  2582. else
  2583. {
  2584. SEND_P3_DATA(TextureDataFormat, PM_TEXDATAFORMAT_FORMAT(SURFFORMAT_FORMAT_BITS(pFormatOverlay)) |
  2585. PM_TEXDATAFORMAT_FORMATEXTENSION(SURFFORMAT_FORMATEXTENSION_BITS(pFormatOverlay)) |
  2586. PM_TEXDATAFORMAT_COLORORDER(COLOR_MODE));
  2587. // Shouldn't actually need this - it's the default setting.
  2588. SEND_P3_DATA(YUVMode, 0x0);
  2589. }
  2590. SEND_P3_DATA(LogicalOpMode, 0);
  2591. // set offset of source
  2592. SEND_P3_DATA(SStart, rOverlay.left << 20);
  2593. SEND_P3_DATA(TStart, rOverlay.top<< 20);
  2594. SEND_P3_DATA(dSdx, xScale);
  2595. SEND_P3_DATA(dSdyDom, 0);
  2596. WAIT_FIFO(24);
  2597. SEND_P3_DATA(dTdx, 0);
  2598. SEND_P3_DATA(dTdyDom, yScale);
  2599. /*
  2600. * Render the rectangle
  2601. */
  2602. SEND_P3_DATA(StartXDom, rTemp.left << 16);
  2603. SEND_P3_DATA(StartXSub, rTemp.right << 16);
  2604. SEND_P3_DATA(StartY, rTemp.top << 16);
  2605. SEND_P3_DATA(dY, 1 << 16);
  2606. SEND_P3_DATA(Count, rTemp.bottom - rTemp.top);
  2607. SEND_P3_DATA(Render, __RENDER_TRAPEZOID_PRIMITIVE | __RENDER_TEXTURED_PRIMITIVE);
  2608. SEND_P3_DATA(DitherMode, 0);
  2609. // Turn off the YUV unit
  2610. SEND_P3_DATA(YUVMode, 0x0);
  2611. SEND_P3_DATA(TextureAddressMode, PM_TEXADDRESSMODE_ENABLE(__PERMEDIA_DISABLE));
  2612. SEND_P3_DATA(TextureColorMode, PM_TEXCOLORMODE_ENABLE(__PERMEDIA_DISABLE));
  2613. P3_DMA_COMMIT_BUFFER();
  2614. }
  2615. // Blit the expanded overlay to the framebuffer, colourkeying off the alpha.
  2616. {
  2617. // Select anything with full alpha.
  2618. LowerBound = 0xff000000;
  2619. UpperBound = 0xffffffff;
  2620. P3_DMA_GET_BUFFER();
  2621. P3_ENSURE_DX_SPACE(40);
  2622. WAIT_FIFO(20);
  2623. // don't need to twiddle the source (which is actually the framebuffer).
  2624. SEND_P3_DATA(DitherMode,0);
  2625. // Accept range, disable updates
  2626. SEND_P3_DATA(YUVMode, (0x1 << 1)|0x20);
  2627. // set a read of source.
  2628. // Note - as we are enabling reads, we might have to do a WaitForCompleteion
  2629. // (see the P2 Programmer's Reference Manual about the FBReamMode for more details.
  2630. // but I think we should be OK - we are unlikely to have just written this data.
  2631. SEND_P3_DATA(FBReadMode,(PACKED_PP_LOOKUP(DDSurf_GetPixelPitch((&TempLcl)))) |
  2632. PM_FBREADMODE_READSOURCE(__PERMEDIA_ENABLE) );
  2633. SEND_P3_DATA(LogicalOpMode, __PERMEDIA_DISABLE);
  2634. // set FB write point
  2635. SEND_P3_DATA(FBWindowBase, windowBaseFB);
  2636. // set up FBWrite mode. This _must_ be done after setting up FBReadMode.
  2637. SEND_P3_DATA(FBWriteConfig,(PACKED_PP_LOOKUP(DDSurf_GetPixelPitch((pFBLcl)))));
  2638. // offset the source point (point it at the temp thingie)
  2639. SEND_P3_DATA(FBSourceOffset, windowBaseTemp - windowBaseFB - rFB.left - ( ( rFB.top * DDSurf_GetPixelPitch((&TempLcl)) ) ) );
  2640. // set base of source
  2641. SEND_P3_DATA(TextureBaseAddress, windowBaseFB);
  2642. SEND_P3_DATA(TextureAddressMode, PM_TEXADDRESSMODE_ENABLE(__PERMEDIA_ENABLE));
  2643. SEND_P3_DATA(TextureColorMode, PM_TEXCOLORMODE_ENABLE(__PERMEDIA_ENABLE) |
  2644. PM_TEXCOLORMODE_APPLICATIONMODE(__GLINT_TEXCOLORMODE_APPLICATION_COPY));
  2645. SEND_P3_DATA(TextureReadMode, PM_TEXREADMODE_ENABLE(__PERMEDIA_ENABLE) |
  2646. PM_TEXREADMODE_FILTER(__PERMEDIA_DISABLE) |
  2647. PM_TEXREADMODE_WIDTH(11) |
  2648. PM_TEXREADMODE_HEIGHT(11) );
  2649. SEND_P3_DATA(TextureDataFormat, PM_TEXDATAFORMAT_FORMAT(SURFFORMAT_FORMAT_BITS(pFormatFB)) |
  2650. PM_TEXDATAFORMAT_FORMATEXTENSION(SURFFORMAT_FORMATEXTENSION_BITS(pFormatFB)) |
  2651. PM_TEXDATAFORMAT_COLORORDER(COLOR_MODE));
  2652. SEND_P3_DATA(TextureMapFormat, ((PACKED_PP_LOOKUP(DDSurf_GetPixelPitch(pFBLcl)))) |
  2653. (DDSurf_GetChipPixelSize(pFBLcl) << PM_TEXMAPFORMAT_TEXELSIZE) );
  2654. SEND_P3_DATA(ChromaLowerBound, LowerBound);
  2655. SEND_P3_DATA(ChromaUpperBound, UpperBound);
  2656. SEND_P3_DATA(dSdx, 1 << 20);
  2657. SEND_P3_DATA(dSdyDom, 0);
  2658. SEND_P3_DATA(dTdx, 0);
  2659. SEND_P3_DATA(dTdyDom, 1 << 20);
  2660. SEND_P3_DATA(dY, 1 << 16);
  2661. lpCurRect = (LPRECT)lpRgn->Buffer;
  2662. NumRects = lpRgn->rdh.nCount;
  2663. while ( NumRects > 0 )
  2664. {
  2665. P3_ENSURE_DX_SPACE(14);
  2666. WAIT_FIFO(7);
  2667. SEND_P3_DATA(SStart, lpCurRect->left << 20);
  2668. SEND_P3_DATA(TStart, lpCurRect->top << 20);
  2669. // SEND_P3_DATA(dSdx, 1 << 20);
  2670. // SEND_P3_DATA(dSdyDom, 0);
  2671. // SEND_P3_DATA(dTdx, 0);
  2672. // SEND_P3_DATA(dTdyDom, 1 << 20);
  2673. SEND_P3_DATA(StartXDom, lpCurRect->left << 16);
  2674. SEND_P3_DATA(StartXSub, lpCurRect->right << 16);
  2675. SEND_P3_DATA(StartY, lpCurRect->top << 16);
  2676. // SEND_P3_DATA(dY, 1 << 16);
  2677. SEND_P3_DATA(Count, lpCurRect->bottom - lpCurRect->top);
  2678. SEND_P3_DATA(Render, __RENDER_TRAPEZOID_PRIMITIVE | __RENDER_TEXTURED_PRIMITIVE);
  2679. // Next rect
  2680. NumRects--;
  2681. lpCurRect++;
  2682. }
  2683. P3_ENSURE_DX_SPACE(10);
  2684. WAIT_FIFO(5);
  2685. SEND_P3_DATA(DitherMode, 0);
  2686. SEND_P3_DATA(YUVMode, 0x0);
  2687. SEND_P3_DATA(TextureAddressMode, __PERMEDIA_DISABLE);
  2688. SEND_P3_DATA(TextureColorMode, __PERMEDIA_DISABLE);
  2689. SEND_P3_DATA(TextureReadMode, __PERMEDIA_DISABLE);
  2690. P3_DMA_COMMIT_BUFFER();
  2691. }
  2692. #ifdef WANT_DMA
  2693. if (pThisDisplay->pGLInfo->InterfaceType == GLINT_DMA)
  2694. {
  2695. // If we have queued up a DMA, we must send it now.
  2696. P3_DMA_DEFS();
  2697. P3_DMA_GET_BUFFER();
  2698. // Flush DMA buffer
  2699. P3_DMA_FLUSH_BUFFER();
  2700. }
  2701. #endif
  2702. START_SOFTWARE_CURSOR(pThisDisplay);
  2703. }
  2704. else
  2705. {
  2706. // Not colourkeyed, so just blit directly to the screen.
  2707. DISPDBG((DBGLVL,"** In DrawOverlay"));
  2708. VALIDATE_MODE_AND_STATE(pThisDisplay);
  2709. pOverlayGbl = pOverlayLcl->lpGbl;
  2710. pFBGbl = pFBLcl->lpGbl;
  2711. pFormatOverlay = _DD_SUR_GetSurfaceFormat(pOverlayLcl);
  2712. pFormatFB = _DD_SUR_GetSurfaceFormat(pFBLcl);
  2713. // Temp buffer will be same format as framebuffer.
  2714. DISPDBG((DBGLVL, "Overlay Surface:"));
  2715. DBGDUMP_DDRAWSURFACE_LCL(DBGLVL, pOverlayLcl);
  2716. DISPDBG((DBGLVL, "FB Surface:"));
  2717. DBGDUMP_DDRAWSURFACE_LCL(DBGLVL, pFBLcl);
  2718. // First stop dual cursor accesses
  2719. STOP_SOFTWARE_CURSOR(pThisDisplay);
  2720. // Switch to DirectDraw context
  2721. DDRAW_OPERATION(pContext, pThisDisplay);
  2722. windowBaseOverlay = __VD_PixelOffsetFromMemoryBase(pThisDisplay, pOverlayLcl);
  2723. windowBaseFB = __VD_PixelOffsetFromMemoryBase(pThisDisplay, pFBLcl);
  2724. {
  2725. P3_DMA_GET_BUFFER();
  2726. P3_ENSURE_DX_SPACE(70);
  2727. WAIT_FIFO(16);
  2728. SEND_P3_DATA(DitherMode, (COLOR_MODE << PM_DITHERMODE_COLORORDER) |
  2729. (SURFFORMAT_FORMAT_BITS(pFormatFB) << PM_DITHERMODE_COLORFORMAT) |
  2730. (SURFFORMAT_FORMATEXTENSION_BITS(pFormatFB) << PM_DITHERMODE_COLORFORMATEXTENSION) |
  2731. (1 << PM_DITHERMODE_ENABLE) |
  2732. (1 << PM_DITHERMODE_DITHERENABLE));
  2733. SEND_P3_DATA(FBReadPixel, DDSurf_GetChipPixelSize((pFBLcl)) );
  2734. SEND_P3_DATA(FBWindowBase, windowBaseFB);
  2735. // set no read of source.
  2736. SEND_P3_DATA(FBReadMode, PACKED_PP_LOOKUP(DDSurf_GetPixelPitch((pFBLcl))));
  2737. SEND_P3_DATA(LogicalOpMode, __PERMEDIA_DISABLE);
  2738. // set base of source
  2739. SEND_P3_DATA(TextureBaseAddress, windowBaseOverlay);
  2740. SEND_P3_DATA(TextureAddressMode, PM_TEXADDRESSMODE_ENABLE(__PERMEDIA_ENABLE));
  2741. SEND_P3_DATA(TextureColorMode, PM_TEXCOLORMODE_ENABLE(__PERMEDIA_ENABLE) |
  2742. PM_TEXCOLORMODE_APPLICATIONMODE(__GLINT_TEXCOLORMODE_APPLICATION_COPY));
  2743. SEND_P3_DATA(TextureReadMode, PM_TEXREADMODE_ENABLE(__PERMEDIA_ENABLE) |
  2744. PM_TEXREADMODE_FILTER(__PERMEDIA_DISABLE) |
  2745. PM_TEXREADMODE_WIDTH(11) |
  2746. PM_TEXREADMODE_HEIGHT(11) );
  2747. SEND_P3_DATA(TextureMapFormat, PACKED_PP_LOOKUP(DDSurf_GetPixelPitch(pOverlayLcl)) |
  2748. (DDSurf_GetChipPixelSize(pOverlayLcl) << PM_TEXMAPFORMAT_TEXELSIZE) );
  2749. if ( pFormatOverlay->DeviceFormat == SURF_YUV422 )
  2750. {
  2751. // Turn on the YUV unit
  2752. SEND_P3_DATA(TextureDataFormat, PM_TEXDATAFORMAT_FORMAT(SURFFORMAT_FORMAT_BITS(pFormatOverlay)) |
  2753. PM_TEXDATAFORMAT_FORMATEXTENSION(SURFFORMAT_FORMATEXTENSION_BITS(pFormatOverlay)) |
  2754. PM_TEXDATAFORMAT_COLORORDER(INV_COLOR_MODE));
  2755. SEND_P3_DATA(YUVMode, 0x1);
  2756. }
  2757. else
  2758. {
  2759. SEND_P3_DATA(TextureDataFormat, PM_TEXDATAFORMAT_FORMAT(SURFFORMAT_FORMAT_BITS(pFormatOverlay)) |
  2760. PM_TEXDATAFORMAT_FORMATEXTENSION(SURFFORMAT_FORMATEXTENSION_BITS(pFormatOverlay)) |
  2761. PM_TEXDATAFORMAT_COLORORDER(COLOR_MODE));
  2762. // Shouldn't actually need this - it's the default setting.
  2763. SEND_P3_DATA(YUVMode, 0x0);
  2764. }
  2765. SEND_P3_DATA(LogicalOpMode, 0);
  2766. // Constant values in the rectangle loop.
  2767. SEND_P3_DATA(dSdyDom, 0);
  2768. SEND_P3_DATA(dTdx, 0);
  2769. SEND_P3_DATA(dY, 1 << 16);
  2770. lpCurRect = (LPRECT)lpRgn->Buffer;
  2771. NumRects = lpRgn->rdh.nCount;
  2772. while ( NumRects > 0 )
  2773. {
  2774. // Transform the source rect.
  2775. fTemp = ( ( (float)lpCurRect->left + OffsetX ) * ScaleX + 0.499f );
  2776. myFtoi ( (int*)&(TempRect.left), fTemp );
  2777. fTemp = ( ( (float)lpCurRect->right + OffsetX ) * ScaleX + 0.499f );
  2778. myFtoi ( (int*)&(TempRect.right), fTemp );
  2779. fTemp = ( ( (float)lpCurRect->top + OffsetY ) * ScaleY + 0.499f );
  2780. myFtoi ( (int*)&(TempRect.top), fTemp );
  2781. fTemp = ( ( (float)lpCurRect->bottom + OffsetY ) * ScaleY + 0.499f );
  2782. myFtoi ( (int*)&(TempRect.bottom), fTemp );
  2783. xScale = ( ( TempRect.right - TempRect.left ) << 20) / ( lpCurRect->right - lpCurRect->left );
  2784. yScale = ( ( TempRect.bottom - TempRect.top ) << 20) / ( lpCurRect->bottom - lpCurRect->top );
  2785. P3_ENSURE_DX_SPACE(18);
  2786. WAIT_FIFO(9);
  2787. // set offset of source
  2788. SEND_P3_DATA(SStart, TempRect.left << 20);
  2789. SEND_P3_DATA(TStart, TempRect.top << 20);
  2790. SEND_P3_DATA(dSdx, xScale);
  2791. // SEND_P3_DATA(dSdyDom, 0);
  2792. // SEND_P3_DATA(dTdx, 0);
  2793. SEND_P3_DATA(dTdyDom, yScale);
  2794. SEND_P3_DATA(StartXDom, lpCurRect->left << 16);
  2795. SEND_P3_DATA(StartXSub, lpCurRect->right << 16);
  2796. SEND_P3_DATA(StartY, lpCurRect->top << 16);
  2797. // SEND_P3_DATA(dY, 1 << 16);
  2798. SEND_P3_DATA(Count, lpCurRect->bottom - lpCurRect->top);
  2799. SEND_P3_DATA(Render, __RENDER_TRAPEZOID_PRIMITIVE | __RENDER_TEXTURED_PRIMITIVE);
  2800. // Next rect
  2801. NumRects--;
  2802. lpCurRect++;
  2803. }
  2804. P3_ENSURE_DX_SPACE(10);
  2805. WAIT_FIFO(5);
  2806. SEND_P3_DATA(DitherMode, 0);
  2807. // Turn off YUV conversion.
  2808. if ( pFormatOverlay->DeviceFormat == SURF_YUV422 )
  2809. {
  2810. SEND_P3_DATA(YUVMode, 0x0);
  2811. }
  2812. SEND_P3_DATA(TextureAddressMode, __PERMEDIA_DISABLE);
  2813. SEND_P3_DATA(TextureColorMode, __PERMEDIA_DISABLE);
  2814. SEND_P3_DATA(TextureReadMode, __PERMEDIA_DISABLE);
  2815. P3_DMA_COMMIT_BUFFER();
  2816. }
  2817. #ifdef WANT_DMA
  2818. if (pThisDisplay->pGLInfo->InterfaceType == GLINT_DMA)
  2819. {
  2820. // If we have queued up a DMA, we must send it now.
  2821. P3_DMA_DEFS();
  2822. P3_DMA_GET_BUFFER();
  2823. if( (DWORD)dmaPtr != pThisDisplay->pGLInfo->DMAPartition[pThisDisplay->pGLInfo->CurrentPartition].VirtAddr )
  2824. {
  2825. // Flush DMA buffer
  2826. P3_DMA_FLUSH_BUFFER();
  2827. }
  2828. }
  2829. #endif
  2830. START_SOFTWARE_CURSOR(pThisDisplay);
  2831. }
  2832. // And that's all.
  2833. }
  2834. return;
  2835. }
  2836. /****************************************************************************
  2837. *
  2838. * void UpdateAlphaOverlay ( P3_THUNKEDDATA* pThisDisplay );
  2839. *
  2840. * In:
  2841. * P3_THUNKEDDATA* pThisDisplay; This display's pointer
  2842. *
  2843. * Out:
  2844. * None.
  2845. *
  2846. * Notes:
  2847. * Takes the data in pThisDisplay and changes everything of the right
  2848. * colourkey to black with a full alpha, ready for calls to DrawOverlay()
  2849. *
  2850. ***************************************************************************/
  2851. void UpdateAlphaOverlay ( P3_THUNKEDDATA* pThisDisplay )
  2852. {
  2853. RECTL rFB;
  2854. LPDDRAWI_DDRAWSURFACE_LCL pFBLcl;
  2855. LPDDRAWI_DDRAWSURFACE_GBL pFBGbl;
  2856. P3_SURF_FORMAT* pFormatFB;
  2857. LPDDRAWI_DIRECTDRAW_GBL lpDD;
  2858. DWORD dwColourKeyValue;
  2859. DWORD dwAlphaMask;
  2860. DWORD windowBaseFB;
  2861. LONG lPixPitchFB;
  2862. DWORD LowerBound;
  2863. DWORD UpperBound;
  2864. P3_DMA_DEFS();
  2865. REPORTSTAT(pThisDisplay, ST_Blit, 1);
  2866. rFB.left = (LONG)pThisDisplay->OverlayDstRectL;
  2867. rFB.right = (LONG)pThisDisplay->OverlayDstRectR;
  2868. rFB.top = (LONG)pThisDisplay->OverlayDstRectT;
  2869. rFB.bottom = (LONG)pThisDisplay->OverlayDstRectB;
  2870. pFBLcl = (LPDDRAWI_DDRAWSURFACE_LCL)pThisDisplay->OverlayDstSurfLcl;
  2871. DISPDBG((DBGLVL,"** In UpdateAlphaOverlay"));
  2872. VALIDATE_MODE_AND_STATE(pThisDisplay);
  2873. pFBGbl = pFBLcl->lpGbl;
  2874. pFormatFB = _DD_SUR_GetSurfaceFormat(pFBLcl);
  2875. DISPDBG((DBGLVL, "FB Surface:"));
  2876. DBGDUMP_DDRAWSURFACE_LCL(10, pFBLcl);
  2877. dwColourKeyValue = pThisDisplay->OverlayDstColourKey;
  2878. switch ( pThisDisplay->bPixShift )
  2879. {
  2880. case GLINTDEPTH16:
  2881. if ( pThisDisplay->ddpfDisplay.dwRBitMask == 0x7C00 )
  2882. {
  2883. // 5551 format, as it should be.
  2884. dwAlphaMask = 0x8000;
  2885. }
  2886. else
  2887. {
  2888. // 565 format. Oops.
  2889. DISPDBG((WRNLVL, "** DrawOverlay error: called for a 565 surface"));
  2890. return;
  2891. }
  2892. break;
  2893. case GLINTDEPTH32:
  2894. dwAlphaMask = 0xff000000;
  2895. break;
  2896. case GLINTDEPTH8:
  2897. case GLINTDEPTH24:
  2898. default:
  2899. DISPDBG((WRNLVL, "** DrawOverlay error: called for an 8, 24 or unknown surface bPixShift=%d", pThisDisplay->bPixShift));
  2900. return;
  2901. break;
  2902. }
  2903. dwColourKeyValue &= ~dwAlphaMask;
  2904. lpDD = pFBLcl->lpGbl->lpDD;
  2905. // First stop dual cursor accesses
  2906. STOP_SOFTWARE_CURSOR(pThisDisplay);
  2907. // Switch to DirectDraw context
  2908. DDRAW_OPERATION(pContext, pThisDisplay);
  2909. // get bpp and pitches for surfaces.
  2910. lPixPitchFB = pFBGbl->lPitch;
  2911. windowBaseFB = (pFBGbl->fpVidMem - pThisDisplay->dwScreenFlatAddr) >> DDSurf_GetPixelShift(pFBLcl);
  2912. lPixPitchFB = lPixPitchFB >> DDSurf_GetPixelShift(pFBLcl);
  2913. // Do the colourkey(no alpha) to colourkey+alpha blit.
  2914. DISPDBG((DBGLVL, "Source Surface:"));
  2915. DBGDUMP_DDRAWSURFACE_LCL(DBGLVL, pFBLcl);
  2916. LowerBound = dwColourKeyValue;
  2917. UpperBound = dwColourKeyValue;
  2918. switch (pFormatFB->DeviceFormat)
  2919. {
  2920. case SURF_5551_FRONT:
  2921. LowerBound = FORMAT_5551_32BIT_BGR(LowerBound);
  2922. UpperBound = FORMAT_5551_32BIT_BGR(UpperBound);
  2923. LowerBound = LowerBound & 0x00F8F8F8; // Account for 'missing bits'
  2924. UpperBound = UpperBound & 0x00FFFFFF; // and vape any alpha
  2925. UpperBound = UpperBound | 0x00070707;
  2926. break;
  2927. case SURF_8888:
  2928. LowerBound = FORMAT_8888_32BIT_BGR(LowerBound);
  2929. UpperBound = FORMAT_8888_32BIT_BGR(UpperBound);
  2930. LowerBound = LowerBound & 0x00FFFFFF; // Bin any alpha.
  2931. UpperBound = UpperBound & 0x00FFFFFF;
  2932. break;
  2933. default:
  2934. DISPDBG((WRNLVL,"** DrawOverlay: invalid source pixel format passed (DeviceFormat=%d)",pFormatFB->DeviceFormat));
  2935. break;
  2936. }
  2937. P3_DMA_GET_BUFFER();
  2938. P3_ENSURE_DX_SPACE(70);
  2939. WAIT_FIFO(36);
  2940. // if (DDSurf_GetChipPixelSize(pSrcLcl) != __GLINT_8BITPIXEL)
  2941. // {
  2942. SEND_P3_DATA(DitherMode, (COLOR_MODE << PM_DITHERMODE_COLORORDER) |
  2943. (SURFFORMAT_FORMAT_BITS(pFormatFB) << PM_DITHERMODE_COLORFORMAT) |
  2944. (SURFFORMAT_FORMATEXTENSION_BITS(pFormatFB) << PM_DITHERMODE_COLORFORMATEXTENSION) |
  2945. (1 << PM_DITHERMODE_ENABLE));
  2946. // }
  2947. SEND_P3_DATA(FBReadPixel, pThisDisplay->bPixShift);
  2948. // Accept range, disable updates
  2949. SEND_P3_DATA(YUVMode, (0x1 << 1)|0x20);
  2950. SEND_P3_DATA(FBWindowBase, windowBaseFB);
  2951. // set the colour to be written (rather than the texture colour)
  2952. // use the colour key with alpha set.
  2953. SEND_P3_DATA(ConstantColor, ( LowerBound | 0xff000000 ) );
  2954. // Enable colour, disable DDAs.
  2955. SEND_P3_DATA(ColorDDAMode, 0x1);
  2956. // Disable reads of FBsource or FBdest - all data comes from the texture unit.
  2957. SEND_P3_DATA(FBReadMode,(PACKED_PP_LOOKUP(DDSurf_GetPixelPitch(pFBLcl))));
  2958. SEND_P3_DATA(LogicalOpMode, __PERMEDIA_DISABLE);
  2959. // set base of source
  2960. SEND_P3_DATA(TextureBaseAddress, windowBaseFB);
  2961. SEND_P3_DATA(TextureAddressMode, PM_TEXADDRESSMODE_ENABLE(__PERMEDIA_ENABLE));
  2962. SEND_P3_DATA(TextureColorMode, PM_TEXCOLORMODE_ENABLE(__PERMEDIA_ENABLE) |
  2963. PM_TEXCOLORMODE_APPLICATIONMODE(__GLINT_TEXCOLORMODE_APPLICATION_COPY));
  2964. SEND_P3_DATA(TextureReadMode, PM_TEXREADMODE_ENABLE(__PERMEDIA_ENABLE) |
  2965. PM_TEXREADMODE_FILTER(__PERMEDIA_DISABLE) |
  2966. PM_TEXREADMODE_WIDTH(11) |
  2967. PM_TEXREADMODE_HEIGHT(11) );
  2968. SEND_P3_DATA(TextureDataFormat, PM_TEXDATAFORMAT_FORMAT(SURFFORMAT_FORMAT_BITS(pFormatFB)) |
  2969. PM_TEXDATAFORMAT_FORMATEXTENSION(SURFFORMAT_FORMATEXTENSION_BITS(pFormatFB)) |
  2970. PM_TEXDATAFORMAT_COLORORDER(COLOR_MODE));
  2971. SEND_P3_DATA(TextureMapFormat, ((PACKED_PP_LOOKUP(DDSurf_GetPixelPitch(pFBLcl)))) |
  2972. (DDSurf_GetChipPixelSize(pFBLcl) << PM_TEXMAPFORMAT_TEXELSIZE) );
  2973. SEND_P3_DATA(ChromaLowerBound, LowerBound);
  2974. SEND_P3_DATA(ChromaUpperBound, UpperBound);
  2975. /*
  2976. * Render the rectangle
  2977. */
  2978. // set offset of source
  2979. SEND_P3_DATA(SStart, rFB.left << 20);
  2980. SEND_P3_DATA(TStart, rFB.top << 20);
  2981. SEND_P3_DATA(dSdx, 1 << 20);
  2982. SEND_P3_DATA(dSdyDom, 0);
  2983. SEND_P3_DATA(dTdx, 0);
  2984. SEND_P3_DATA(dTdyDom, 1 << 20);
  2985. // set destination
  2986. SEND_P3_DATA(StartXDom, rFB.left << 16);
  2987. SEND_P3_DATA(StartXSub, rFB.right << 16);
  2988. SEND_P3_DATA(StartY, rFB.top << 16);
  2989. SEND_P3_DATA(dY, 1 << 16);
  2990. SEND_P3_DATA(Count, rFB.bottom - rFB.top);
  2991. SEND_P3_DATA(Render, __RENDER_TRAPEZOID_PRIMITIVE | __RENDER_TEXTURED_PRIMITIVE);
  2992. // if (DDSurf_GetChipPixelSize(pSrcLcl) != __GLINT_8BITPIXEL)
  2993. // {
  2994. SEND_P3_DATA(DitherMode, 0);
  2995. // }
  2996. // Turn off chroma key and all the other unusual features
  2997. SEND_P3_DATA(YUVMode, 0x0);
  2998. SEND_P3_DATA(ColorDDAMode, 0x0);
  2999. SEND_P3_DATA(TextureAddressMode, __PERMEDIA_DISABLE);
  3000. SEND_P3_DATA(TextureColorMode, __PERMEDIA_DISABLE);
  3001. SEND_P3_DATA(TextureReadMode, __PERMEDIA_DISABLE);
  3002. P3_DMA_COMMIT_BUFFER();
  3003. #ifdef WANT_DMA
  3004. if (pThisDisplay->pGLInfo->InterfaceType == GLINT_DMA)
  3005. {
  3006. // If we have queued up a DMA, we must send it now.
  3007. P3_DMA_DEFS();
  3008. P3_DMA_GET_BUFFER();
  3009. if( (DWORD)dmaPtr != pThisDisplay->pGLInfo->DMAPartition[pThisDisplay->pGLInfo->CurrentPartition].VirtAddr )
  3010. {
  3011. // Flush DMA buffer
  3012. P3_DMA_FLUSH_BUFFER();
  3013. }
  3014. }
  3015. #endif
  3016. START_SOFTWARE_CURSOR(pThisDisplay);
  3017. return;
  3018. }
  3019. #endif // W95_DDRAW_VIDEO
  3020. //@@END_DDKSPLIT
  3021. //@@BEGIN_DDKSPLIT
  3022. void PermediaBltYUVRGB(
  3023. P3_THUNKEDDATA* pThisDisplay,
  3024. LPDDRAWI_DDRAWSURFACE_LCL pSource,
  3025. LPDDRAWI_DDRAWSURFACE_LCL pDest,
  3026. P3_SURF_FORMAT* pFormatSource,
  3027. P3_SURF_FORMAT* pFormatDest,
  3028. DDBLTFX* lpBltFX,
  3029. RECTL *rSrc,
  3030. RECTL *rDest,
  3031. DWORD windowBase,
  3032. DWORD SourceOffset)
  3033. {
  3034. DWORD xScale;
  3035. DWORD yScale;
  3036. DWORD DestWidth = rDest->right - rDest->left;
  3037. DWORD DestHeight = rDest->bottom - rDest->top;
  3038. DWORD SourceWidth = rSrc->right - rSrc->left;
  3039. DWORD SourceHeight = rSrc->bottom - rSrc->top;
  3040. P3_DMA_DEFS();
  3041. ASSERTDD(pDest, "Not valid surface in destination");
  3042. ASSERTDD(pSource, "Not valid surface in source");
  3043. xScale = (SourceWidth << 20) / DestWidth;
  3044. yScale = (SourceHeight << 20) / DestHeight;
  3045. P3_DMA_GET_BUFFER();
  3046. P3_ENSURE_DX_SPACE(50);
  3047. WAIT_FIFO(17);
  3048. SEND_P3_DATA(FBReadPixel, DDSurf_GetChipPixelSize(pDest));
  3049. if (DDSurf_GetChipPixelSize(pSource) != __GLINT_8BITPIXEL)
  3050. {
  3051. SEND_P3_DATA(DitherMode, (COLOR_MODE << PM_DITHERMODE_COLORORDER) |
  3052. (SURFFORMAT_FORMAT_BITS(pFormatDest) << PM_DITHERMODE_COLORFORMAT) |
  3053. (SURFFORMAT_FORMATEXTENSION_BITS(pFormatDest) << PM_DITHERMODE_COLORFORMATEXTENSION) |
  3054. (1 << PM_DITHERMODE_ENABLE) |
  3055. (1 << PM_DITHERMODE_DITHERENABLE));
  3056. }
  3057. SEND_P3_DATA(FBWindowBase, windowBase);
  3058. // set no read of source.
  3059. SEND_P3_DATA(FBReadMode, PACKED_PP_LOOKUP(DDSurf_GetPixelPitch(pDest)));
  3060. SEND_P3_DATA(LogicalOpMode, __PERMEDIA_DISABLE);
  3061. // set base of source
  3062. SEND_P3_DATA(TextureBaseAddress, SourceOffset);
  3063. SEND_P3_DATA(TextureAddressMode, PM_TEXADDRESSMODE_ENABLE(__PERMEDIA_ENABLE));
  3064. SEND_P3_DATA(TextureColorMode, PM_TEXCOLORMODE_ENABLE(__PERMEDIA_ENABLE) |
  3065. PM_TEXCOLORMODE_APPLICATIONMODE(__GLINT_TEXCOLORMODE_APPLICATION_COPY));
  3066. SEND_P3_DATA(TextureReadMode, PM_TEXREADMODE_ENABLE(__PERMEDIA_ENABLE) |
  3067. PM_TEXREADMODE_FILTER(__PERMEDIA_DISABLE) |
  3068. PM_TEXREADMODE_WIDTH(11) |
  3069. PM_TEXREADMODE_HEIGHT(11) );
  3070. SEND_P3_DATA(TextureDataFormat, PM_TEXDATAFORMAT_FORMAT(SURFFORMAT_FORMAT_BITS(pFormatSource)) |
  3071. PM_TEXDATAFORMAT_FORMATEXTENSION(SURFFORMAT_FORMATEXTENSION_BITS(pFormatSource)) |
  3072. PM_TEXDATAFORMAT_COLORORDER(INV_COLOR_MODE));
  3073. SEND_P3_DATA(TextureMapFormat, PACKED_PP_LOOKUP(DDSurf_GetPixelPitch(pSource)) |
  3074. (DDSurf_GetChipPixelSize(pSource) << PM_TEXMAPFORMAT_TEXELSIZE) );
  3075. // Turn on the YUV unit
  3076. SEND_P3_DATA(YUVMode, 0x1);
  3077. SEND_P3_DATA(LogicalOpMode, 0);
  3078. // set offset of source
  3079. SEND_P3_DATA(SStart, rSrc->left << 20);
  3080. SEND_P3_DATA(TStart, (rSrc->top<< 20));
  3081. SEND_P3_DATA(dSdx, xScale);
  3082. SEND_P3_DATA(dSdyDom, 0);
  3083. WAIT_FIFO(14);
  3084. SEND_P3_DATA(dTdx, 0);
  3085. SEND_P3_DATA(dTdyDom, yScale);
  3086. /*
  3087. * Render the rectangle
  3088. */
  3089. SEND_P3_DATA(StartXDom, rDest->left << 16);
  3090. SEND_P3_DATA(StartXSub, rDest->right << 16);
  3091. SEND_P3_DATA(StartY, rDest->top << 16);
  3092. SEND_P3_DATA(dY, 1 << 16);
  3093. SEND_P3_DATA(Count, rDest->bottom - rDest->top);
  3094. SEND_P3_DATA(Render, __RENDER_TRAPEZOID_PRIMITIVE | __RENDER_TEXTURED_PRIMITIVE);
  3095. if (DDSurf_GetChipPixelSize(pSource) != __GLINT_8BITPIXEL)
  3096. {
  3097. SEND_P3_DATA(DitherMode, 0);
  3098. }
  3099. // Turn off the YUV unit
  3100. SEND_P3_DATA(YUVMode, 0x0);
  3101. SEND_P3_DATA(TextureAddressMode, PM_TEXADDRESSMODE_ENABLE(__PERMEDIA_DISABLE));
  3102. SEND_P3_DATA(TextureColorMode, PM_TEXCOLORMODE_ENABLE(__PERMEDIA_DISABLE));
  3103. SEND_P3_DATA(TextureReadMode, __PERMEDIA_DISABLE);
  3104. P3_DMA_COMMIT_BUFFER();
  3105. }
  3106. //@@END_DDKSPLIT