Source code of Windows XP (NT5)
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.

5545 lines
182 KiB

  1. /******************************************************************************\
  2. *
  3. * Copyright (c) 1996-1997 Microsoft Corporation.
  4. * Copyright (c) 1996-1997 Cirrus Logic, Inc.
  5. *
  6. * Module Name:
  7. *
  8. * D D R A W . C
  9. *
  10. *
  11. * Implements all the DirectDraw components for the driver.
  12. *
  13. *
  14. * $Log: S:/projects/drivers/ntsrc/display/ddraw.c_v $
  15. *
  16. * Rev 1.14 07 Apr 1997 11:37:02 PLCHU
  17. *
  18. *
  19. * Rev 1.13 Apr 03 1997 15:38:44 unknown
  20. *
  21. *
  22. *
  23. * Rev 1.10 Jan 14 1997 15:15:12 unknown
  24. * Add new double clock detecting method.
  25. *
  26. * Rev 1.8 Jan 08 1997 11:23:34 unknown
  27. * Add 2x clock support and double scan line counter support
  28. *
  29. * Rev 1.7 Dec 17 1996 18:31:12 unknown
  30. * Update the bandwidth equation again.
  31. *
  32. * Rev 1.6 Dec 13 1996 12:15:04 unknown
  33. * update bandwith equation.
  34. *
  35. * Rev 1.5 Dec 12 1996 11:09:52 unknown
  36. * Add double scan line counter support
  37. *
  38. * Rev 1.5 Dec 12 1996 11:02:12 unknown
  39. * Add double scan line counter support.
  40. *
  41. * Rev 1.5 Nov 26 1996 14:29:58 unknown
  42. * Turn off the video window before the moving and then turn it on.
  43. *
  44. * Rev 1.4 Nov 25 1996 14:39:32 unknown
  45. * Fixed AVI file playback and 16bpp transparent Blt bugs.
  46. *
  47. * Rev 1.4 Nov 18 1996 13:58:58 JACKIEC
  48. *
  49. *
  50. * Rev 1.3 Nov 07 1996 16:47:56 unknown
  51. *
  52. *
  53. * Rev 1.2 Oct 16 1996 14:41:04 unknown
  54. * NT 3.51 does not have DDRAW support, So turn off overlay.h in NT 3.51
  55. *
  56. * Rev 1.1 Oct 10 1996 15:36:28 unknown
  57. *
  58. *
  59. * Rev 1.10 12 Aug 1996 16:51:04 frido
  60. * Added NT 3.5x/4.0 auto detection.
  61. *
  62. * Rev 1.9 06 Aug 1996 18:37:12 frido
  63. * DirectDraw works! Video mapping is the key!
  64. *
  65. * Rev 1.8 24 Jul 1996 14:38:44 frido
  66. * Cleaned up font cache after DirectDraw is done.
  67. *
  68. * Rev 1.7 24 Jul 1996 14:30:04 frido
  69. * Added a call to destroy all cached fonts to make more room.
  70. *
  71. * Rev 1.6 20 Jul 1996 00:00:44 frido
  72. * Fixed filling of DirectDraw in 24-bpp.
  73. * Changed off-screen alignment to 4 bytes.
  74. * Added compile switch to manage DirectDraw support in 24-bpp.
  75. *
  76. * Rev 1.5 16 Jul 1996 18:55:22 frido
  77. * Fixed DirectDraw in 24-bpp mode.
  78. *
  79. * Rev 1.4 15 Jul 1996 18:03:22 frido
  80. * Changed CP_MM_DST_ADDR to CP_MM_DST_ADDR_ABS.
  81. *
  82. * Rev 1.3 15 Jul 1996 10:58:28 frido
  83. * Changed back to S3 base.
  84. *
  85. * Rev 1.1 09 Jul 1996 14:52:30 frido
  86. * Only support chips 5436 and 5446.
  87. *
  88. * Rev 1.0 03 Jul 1996 13:53:02 frido
  89. * Ported from S3 DirectDraw code.
  90. *
  91. * jl01 10-08-96 Do Transparent BLT w/o Solid Fill. Refer to PDRs#5511/6817.
  92. *
  93. * chu01 11-17-96 For 24-bpp, aligned destination boundary/size values are
  94. * wrong. Refer to PDR#7312.
  95. *
  96. * sge01 11-19-96 Write CR37 at last For 5480.
  97. *
  98. *
  99. * sge02 11-21-96 We have to set the Color Expand Width even in
  100. * non-expand transparency mode.
  101. *
  102. *
  103. * sge03 12-04-96 Add double scan line counter support .
  104. *
  105. * sge04 12-13-96 Change bandwidth for 5446BE and later chips.
  106. *
  107. * sge05 01-07-97 Use dword align for double clock mode.
  108. *
  109. * chu02 01-08-97 Disable ActiveX/Active Movie Player for interlaced modes.
  110. * Refer to PDR#7312, 7866.
  111. *
  112. * jc01 10-18-96 Port Microsoft recent change.
  113. * tao1 10-21-96 Added direct draw support for CL-GD7555.
  114. * myf21 11-21-96 Change CAPS_IS_7555 to check ppdev->ulChipID
  115. *
  116. * sge06 01-27-97 Extend VCLK Denominator to 7 bits from 5 bits.
  117. * sge07 02-13-97 Use replication when in 1280x1024x8 mode.
  118. * myf31 02-24-97 Fixed enable HW Video, panning scrolling enable,screen move
  119. * video window have follow moving
  120. * chu03 03-26-97 Bandwidth eqution for the CL-GD5480.
  121. * myf33 :03-31-97 : Fixed PDR #8709, read true VCLK in getVCLK()
  122. * & panning scrolling enable, support HW Video
  123. * chu04 04-02-97 No matterwhat color depth is, always turn on COLORKEY and
  124. * SRCBLT in the DD/DD colorkey capabilities for the 5480.
  125. *
  126. \******************************************************************************/
  127. #include "PreComp.h"
  128. #if DIRECTDRAW
  129. #include "overlay.h"
  130. LONG MIN_OLAY_WIDTH = 4;
  131. //#define ONLY54x6 // Comment this line out if DirectDraw should be 'generic'
  132. // The next flag controls DirectDraw support in 24-bpp.
  133. #define DIRECTX_24 2 // 0 - no support
  134. // 1 - blt support, no heap (flip)
  135. // 2 - full support
  136. //
  137. // Some handy macros.
  138. //
  139. #define BLT_BUSY(ppdev, pjBase) (CP_MM_ACL_STAT(ppdev, pjBase) & 0x01)
  140. #ifdef ONLY54x6
  141. #define BLT_READY(ppdev, pjBase) (!(CP_MM_ACL_STAT(ppdev, pjBase) & 0x10))
  142. #else
  143. #define BLT_READY(ppdev, pjBase) (!(CP_MM_ACL_STAT(ppdev, pjBase) & \
  144. ((ppdev->flCaps & CAPS_AUTOSTART) ? 0x10 : 0x01)))
  145. #endif
  146. #define NUM_VBLANKS_TO_MEASURE 1
  147. #define NUM_MEASUREMENTS_TO_TAKE 8
  148. /******************************Public*Routine******************************\
  149. *
  150. * DWORD dwGetPaletteEntry
  151. *
  152. \**************************************************************************/
  153. DWORD dwGetPaletteEntry(
  154. PDEV* ppdev,
  155. DWORD iIndex)
  156. {
  157. BYTE* pjPorts;
  158. DWORD dwRed;
  159. DWORD dwGreen;
  160. DWORD dwBlue;
  161. pjPorts = ppdev->pjPorts;
  162. CP_OUT_BYTE(pjPorts, DAC_PEL_READ_ADDR, iIndex);
  163. dwRed = CP_IN_BYTE(pjPorts, DAC_PEL_DATA);
  164. dwGreen = CP_IN_BYTE(pjPorts, DAC_PEL_DATA);
  165. dwBlue = CP_IN_BYTE(pjPorts, DAC_PEL_DATA);
  166. return((dwRed << 16) | (dwGreen << 8) | (dwBlue));
  167. }
  168. /******************************Public*Routine******************************\
  169. * VOID vGetDisplayDuration
  170. *
  171. * Get the length, in EngQueryPerformanceCounter() ticks, of a refresh cycle.
  172. *
  173. * If we could trust the miniport to return back and accurate value for
  174. * the refresh rate, we could use that. Unfortunately, our miniport doesn't
  175. * ensure that it's an accurate value.
  176. *
  177. \**************************************************************************/
  178. VOID vGetDisplayDuration(
  179. PDEV* ppdev)
  180. {
  181. BYTE* pjPorts;
  182. DWORD dwTemp;
  183. LONG i, j;
  184. LONGLONG li;
  185. LONGLONG liMin;
  186. LONGLONG aliMeasurement[NUM_MEASUREMENTS_TO_TAKE + 1];
  187. pjPorts = ppdev->pjPorts;
  188. memset(&ppdev->flipRecord, 0, sizeof(ppdev->flipRecord));
  189. // Warm up EngQUeryPerformanceCounter to make sure it's in the working set.
  190. EngQueryPerformanceCounter(&li);
  191. // Unfortunately, since NT is a proper multitasking system, we can't just
  192. // disable interrupts to take an accurate reading. We also can't do anything
  193. // so goofy as dynamically change our thread's priority to real-time.
  194. //
  195. // So we just do a bunch of short measurements and take the minimum.
  196. //
  197. // It would be 'okay' if we got a result that's longer than the actual
  198. // VBlank cycle time -- nothing bad would happen except that the app would
  199. // run a little slower. We don't want to get a result that's shorter than
  200. // the actual VBlank cycle time -- that could cause us to start drawing over
  201. // a frame before the Flip has occured.
  202. while (CP_IN_BYTE(pjPorts, STATUS_1) & VBLANK_ACTIVE)
  203. ;
  204. while (!(CP_IN_BYTE(pjPorts, STATUS_1) & VBLANK_ACTIVE))
  205. ;
  206. for (i = 0; i < NUM_MEASUREMENTS_TO_TAKE; i++)
  207. {
  208. // We're at the start of the VBlank active cycle!
  209. EngQueryPerformanceCounter(&aliMeasurement[i]);
  210. // Okay, so life in a multi-tasking environment isn't all that simple.
  211. // What if we had taken a context switch just before the above
  212. // EngQueryPerformanceCounter call, and now were half way through the
  213. // VBlank inactive cycle? Then we would measure only half a VBlank
  214. // cycle, which is obviously bad. The worst thing we can do is get a
  215. // time shorter than the actual VBlank cycle time.
  216. //
  217. // So we solve this by making sure we're in the VBlank active time
  218. // before and after we query the time. If it's not, we'll sync up to the
  219. // next VBlank (it's okay to measure this period -- it will be
  220. // guaranteed to be longer than the VBlank cycle and will likely be
  221. // thrown out when we select the minimum sample). There's a chance that
  222. // we'll take a context switch and return just before the end of the
  223. // active VBlank time -- meaning that the actual measured time would be
  224. // less than the true amount -- but since the VBlank is active less than
  225. // 1% of the time, this means that we would have a maximum of 1% error
  226. // approximately 1% of the times we take a context switch. An acceptable
  227. // risk.
  228. //
  229. // This next line will cause us wait if we're no longer in the VBlank
  230. // active cycle as we should be at this point.
  231. while (!(CP_IN_BYTE(pjPorts, STATUS_1) & VBLANK_ACTIVE))
  232. ;
  233. for (j = 0; j < NUM_VBLANKS_TO_MEASURE; j++)
  234. {
  235. while (CP_IN_BYTE(pjPorts, STATUS_1) & VBLANK_ACTIVE)
  236. ;
  237. while (!(CP_IN_BYTE(pjPorts, STATUS_1) & VBLANK_ACTIVE))
  238. ;
  239. }
  240. }
  241. EngQueryPerformanceCounter(&aliMeasurement[NUM_MEASUREMENTS_TO_TAKE]);
  242. // Use the minimum.
  243. liMin = aliMeasurement[1] - aliMeasurement[0];
  244. DISPDBG((2, "Refresh count: %li - %li", 1, (ULONG) liMin));
  245. for (i = 2; i <= NUM_MEASUREMENTS_TO_TAKE; i++)
  246. {
  247. li = aliMeasurement[i] - aliMeasurement[i - 1];
  248. DISPDBG((2, " %li - %li", i, (ULONG) li));
  249. if (li < liMin)
  250. {
  251. liMin = li;
  252. }
  253. }
  254. // Round the result:
  255. ppdev->flipRecord.liFlipDuration =
  256. (DWORD) (liMin + (NUM_VBLANKS_TO_MEASURE / 2)) / NUM_VBLANKS_TO_MEASURE;
  257. DISPDBG((2, "Frequency %li.%03li Hz",
  258. (ULONG) (EngQueryPerformanceFrequency(&li),
  259. li / ppdev->flipRecord.liFlipDuration),
  260. (ULONG) (EngQueryPerformanceFrequency(&li),
  261. ((li * 1000) / ppdev->flipRecord.liFlipDuration) % 1000)));
  262. ppdev->flipRecord.liFlipTime = aliMeasurement[NUM_MEASUREMENTS_TO_TAKE];
  263. ppdev->flipRecord.bFlipFlag = FALSE;
  264. ppdev->flipRecord.fpFlipFrom = 0;
  265. // sge
  266. // Get the line on which the VSYNC occurs
  267. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x7);
  268. dwTemp = (DWORD)CP_IN_BYTE(pjPorts, CRTC_DATA);
  269. ppdev->dwVsyncLine = ((dwTemp & 0x80) << 2);
  270. ppdev->dwVsyncLine |= ((dwTemp & 0x04) << 6);
  271. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x10);
  272. ppdev->dwVsyncLine |= CP_IN_BYTE(pjPorts, CRTC_DATA);
  273. }
  274. /******************************Public*Routine******************************\
  275. * HRESULT dwUpdateFlipStatus
  276. *
  277. * Checks and sees if the most recent flip has occurred.
  278. *
  279. \**************************************************************************/
  280. HRESULT UpdateFlipStatus(PDEV* ppdev, FLATPTR fpVidMem)
  281. {
  282. BYTE* pjPorts;
  283. LONGLONG liTime;
  284. pjPorts = ppdev->pjPorts;
  285. if ((ppdev->flipRecord.bFlipFlag) &&
  286. //#jc01 ((fpVidMem == 0) || (fpVidMem == ppdev->flipRecord.fpFlipFrom)))
  287. ((fpVidMem == 0xffffffff) || (fpVidMem == ppdev->flipRecord.fpFlipFrom))) //#jc01
  288. {
  289. #if 0 // sge use scanline
  290. if (CP_IN_BYTE(pjPorts, STATUS_1) & VBLANK_ACTIVE)
  291. {
  292. if (ppdev->flipRecord.bWasEverInDisplay)
  293. {
  294. ppdev->flipRecord.bHaveEverCrossedVBlank = TRUE;
  295. }
  296. }
  297. else if (!(CP_IN_BYTE(pjPorts, STATUS_1) & DISPLAY_MODE_INACTIVE))
  298. {
  299. if( ppdev->flipRecord.bHaveEverCrossedVBlank )
  300. {
  301. ppdev->flipRecord.bFlipFlag = FALSE;
  302. return(DD_OK);
  303. }
  304. ppdev->flipRecord.bWasEverInDisplay = TRUE;
  305. }
  306. EngQueryPerformanceCounter(&liTime);
  307. if (liTime - ppdev->flipRecord.liFlipTime
  308. <= ppdev->flipRecord.liFlipDuration)
  309. {
  310. return(DDERR_WASSTILLDRAWING);
  311. }
  312. #else
  313. /*
  314. * if we aren't in the vertical retrace, we can use the scanline
  315. * to help decide on what to do
  316. */
  317. if( !(CP_IN_BYTE(pjPorts, STATUS_1) & VBLANK_ACTIVE) )
  318. {
  319. if( ppdev->flipRecord.bHaveEverCrossedVBlank == FALSE )
  320. {
  321. ppdev->flipRecord.bWasEverInDisplay = TRUE;
  322. if( GetCurrentVLine(ppdev) >= ppdev->flipRecord.dwFlipScanLine )
  323. {
  324. EngQueryPerformanceCounter(&liTime);
  325. if (liTime - ppdev->flipRecord.liFlipTime
  326. <= ppdev->flipRecord.liFlipDuration)
  327. {
  328. return(DDERR_WASSTILLDRAWING);
  329. }
  330. }
  331. }
  332. }
  333. /*
  334. * in the vertical retrace, scanline is useless
  335. */
  336. else
  337. {
  338. if( ppdev->flipRecord.bWasEverInDisplay )
  339. {
  340. ppdev->flipRecord.bHaveEverCrossedVBlank = TRUE;
  341. // return DD_OK;
  342. }
  343. EngQueryPerformanceCounter(&liTime);
  344. if (liTime - ppdev->flipRecord.liFlipTime
  345. <= ppdev->flipRecord.liFlipDuration)
  346. {
  347. return(DDERR_WASSTILLDRAWING);
  348. }
  349. }
  350. #endif // endif use scanline
  351. ppdev->flipRecord.bFlipFlag = FALSE;
  352. }
  353. return(DD_OK);
  354. }
  355. /******************************Public*Routine******************************\
  356. * DWORD DdBlt
  357. *
  358. \**************************************************************************/
  359. DWORD DdBlt(
  360. PDD_BLTDATA lpBlt)
  361. {
  362. PDD_SURFACE_GLOBAL srcSurf;
  363. PDD_SURFACE_GLOBAL dstSurf;
  364. PDEV* ppdev;
  365. BYTE* pjBase;
  366. DWORD dstOffset;
  367. DWORD dstPitch;
  368. DWORD dstX, dstY;
  369. DWORD dwFlags;
  370. DWORD width, height;
  371. DWORD srcOffset;
  372. DWORD srcPitch;
  373. DWORD srcX, srcY;
  374. ULONG ulBltCmd;
  375. DWORD xExt, yExt;
  376. DWORD xDiff, yDiff;
  377. ppdev = lpBlt->lpDD->dhpdev;
  378. pjBase = ppdev->pjBase;
  379. dstSurf = lpBlt->lpDDDestSurface->lpGbl;
  380. // Is a flip in progress?
  381. if (UpdateFlipStatus(ppdev, dstSurf->fpVidMem) != DD_OK)
  382. {
  383. lpBlt->ddRVal = DDERR_WASSTILLDRAWING;
  384. return(DDHAL_DRIVER_HANDLED);
  385. }
  386. dwFlags = lpBlt->dwFlags;
  387. if (dwFlags & DDBLT_ASYNC)
  388. {
  389. // If async, then only work if we won't have to wait on the accelerator
  390. // to start the command.
  391. if (!BLT_READY(ppdev, pjBase))
  392. {
  393. lpBlt->ddRVal = DDERR_WASSTILLDRAWING;
  394. return(DDHAL_DRIVER_HANDLED);
  395. }
  396. }
  397. DISPDBG((2, "DdBlt Entered"));
  398. // Calculate destination parameters.
  399. dstX = lpBlt->rDest.left;
  400. dstY = lpBlt->rDest.top;
  401. width = PELS_TO_BYTES(lpBlt->rDest.right - dstX) - 1;
  402. height = (lpBlt->rDest.bottom - dstY) - 1;
  403. dstPitch = dstSurf->lPitch;
  404. dstOffset = (DWORD)(dstSurf->fpVidMem + PELS_TO_BYTES(dstX)
  405. + (dstY * dstPitch));
  406. // Color fill?
  407. if (dwFlags & DDBLT_COLORFILL)
  408. {
  409. ULONG ulBltMode = ENABLE_COLOR_EXPAND
  410. | ENABLE_8x8_PATTERN_COPY
  411. | ppdev->jModeColor;
  412. // Wait for the accelerator.
  413. while (!BLT_READY(ppdev, pjBase))
  414. ;
  415. // Program bitblt engine.
  416. CP_MM_ROP(ppdev, pjBase, HW_P);
  417. CP_MM_DST_Y_OFFSET(ppdev, pjBase, dstPitch);
  418. CP_MM_BLT_MODE(ppdev, pjBase, ulBltMode);
  419. CP_MM_FG_COLOR(ppdev, pjBase, lpBlt->bltFX.dwFillColor);
  420. if (ppdev->flCaps & CAPS_AUTOSTART)
  421. {
  422. CP_MM_BLT_EXT_MODE(ppdev, pjBase, ENABLE_SOLID_FILL);
  423. }
  424. else
  425. {
  426. CP_MM_SRC_ADDR(ppdev, pjBase, ppdev->ulSolidColorOffset);
  427. }
  428. CP_MM_XCNT(ppdev, pjBase, width);
  429. CP_MM_YCNT(ppdev, pjBase, height);
  430. CP_MM_DST_ADDR_ABS(ppdev, pjBase, dstOffset);
  431. CP_MM_START_BLT(ppdev, pjBase);
  432. lpBlt->ddRVal = DD_OK;
  433. return(DDHAL_DRIVER_HANDLED);
  434. }
  435. // We specified with Our ddCaps.dwCaps that we handle a limited number of
  436. // commands, and by this point in our routine we've handled everything
  437. // except DDBLT_ROP. DirectDraw and GDI shouldn't pass us anything else;
  438. // we'll assert on debug builds to prove this.
  439. ASSERTDD((dwFlags & DDBLT_ROP) && (lpBlt->lpDDSrcSurface),
  440. "Expected dwFlags commands of only DDBLT_ASYNC and DDBLT_COLORFILL");
  441. // Get offset, width, and height for source.
  442. srcSurf = lpBlt->lpDDSrcSurface->lpGbl;
  443. srcX = lpBlt->rSrc.left;
  444. srcY = lpBlt->rSrc.top;
  445. srcPitch = srcSurf->lPitch;
  446. srcOffset = (DWORD)(srcSurf->fpVidMem + PELS_TO_BYTES(srcX)
  447. + (srcY * srcPitch));
  448. /*
  449. * Account for PackJR. If the start and the width are not 4 pixel
  450. * aligned, we need to BLT this by hand. Otherwsie, if they think
  451. * they are BLTing 16 bit data, we must adjust the parameters now.
  452. *
  453. * This is also a good place to check that YUV BLTs are 2 pixel
  454. * aligned.
  455. */
  456. if (lpBlt->lpDDDestSurface->dwReserved1 & (OVERLAY_FLG_PACKJR | OVERLAY_FLG_YUV422))
  457. {
  458. ASSERTDD(0, "Who will get here?");
  459. #if 0 // software blt
  460. /*
  461. * Check YUV first. We can fail this if incorrect because the client
  462. * should know better (since they are explicitly use YUV).
  463. */
  464. if ((lpBlt->lpDDDestSurface->dwReserved1 & OVERLAY_FLG_YUV422) &&
  465. ((lpBlt->rSrc.left & 0x01) != (lpBlt->rDest.left & 0x01)))
  466. {
  467. lpBlt->ddRVal = DDERR_XALIGN;
  468. return (DDHAL_DRIVER_HANDLED);
  469. }
  470. /*
  471. * If PackJR is wrong, we must make this work ourselves because we
  472. * may be converting to this w/o the client knowing.
  473. */
  474. else if (lpBlt->lpDDDestSurface->dwReserved1 & OVERLAY_FLG_PACKJR)
  475. {
  476. if (dwFlags & DDBLT_COLORFILL)
  477. {
  478. lpBlt->ddRVal = DDERR_XALIGN;
  479. return (DDHAL_DRIVER_HANDLED);
  480. }
  481. if ((lpBlt->rSrc.left & 0x03) || (lpBlt->rDest.left & 0x03))
  482. {
  483. /*
  484. * The start doesn't align - we have to do this the slow way
  485. */
  486. PackJRBltAlign ((LPBYTE) ppdev->pjScreen + srcOffset,
  487. (LPBYTE) ppdev->pjScreen + dstOffset,
  488. lpBlt->rDest.right - lpBlt->rDest.left,
  489. lpBlt->rDest.bottom - lpBlt->rDest.top,
  490. srcPitch, dstPitch);
  491. lpBlt->ddRVal = DD_OK;
  492. return (DDHAL_DRIVER_HANDLED);
  493. }
  494. else if (lpBlt->rSrc.right & 0x03)
  495. {
  496. /*
  497. * The end doesn't align - we will do the BLT as normal, but
  498. * write the last pixels the slow way
  499. */
  500. if (lpBlt->lpDDDestSurface->dwReserved1 & (OVERLAY_FLG_CONVERT_PACKJR | OVERLAY_FLG_MUST_RASTER))
  501. {
  502. srcPitch >>= 1;
  503. srcOffset = srcSurf->fpVidMem + PELS_TO_BYTES(srcX) + (srcY * srcPitch);
  504. dstPitch >>= 1;
  505. dstOffset = dstSurf->fpVidMem + PELS_TO_BYTES(dstX) + (dstY * dstPitch);
  506. }
  507. width = ((WORD)lpBlt->rSrc.right & ~0x03) - (WORD)lpBlt->rSrc.left;
  508. PackJRBltAlignEnd ((LPBYTE) ppdev->pjScreen + srcOffset + width,
  509. (LPBYTE) ppdev->pjScreen + dstOffset + width,
  510. lpBlt->rSrc.right & 0x03,
  511. lpBlt->rDest.bottom - lpBlt->rDest.top, srcPitch, dstPitch);
  512. }
  513. else if (lpBlt->lpDDDestSurface->dwReserved1 & (OVERLAY_FLG_CONVERT_PACKJR | OVERLAY_FLG_MUST_RASTER))
  514. {
  515. /*
  516. * Everything aligns, but we have to re-calculate the start
  517. * address and the pitch.
  518. */
  519. srcPitch >>= 1;
  520. srcOffset = srcSurf->fpVidMem + PELS_TO_BYTES(srcX) + (srcY * srcPitch);
  521. dstPitch >>= 1;
  522. dstOffset = dstSurf->fpVidMem + PELS_TO_BYTES(dstX) + (dstY * dstPitch);
  523. width >>= 1;
  524. }
  525. }
  526. #endif
  527. }
  528. if ((dstSurf == srcSurf) && (srcOffset < dstOffset))
  529. {
  530. // Okay, we have to do the blt bottom-to-top, right-to-left.
  531. ulBltCmd = DIR_BTRL;
  532. ;
  533. srcOffset += width + (srcPitch * height);
  534. dstOffset += width + (dstPitch * height);
  535. }
  536. else
  537. {
  538. // Okay, we have to do the blt top-to-bottom, left-to-right.
  539. ulBltCmd = DIR_TBLR;
  540. }
  541. // Wait for the accelerator.
  542. while (!BLT_READY(ppdev, pjBase))
  543. ;
  544. //
  545. // What about source color key
  546. //
  547. ASSERTDD((!(dwFlags & DDBLT_KEYSRC)), "Do not expected source color key");
  548. if (dwFlags & DDBLT_KEYSRCOVERRIDE)
  549. {
  550. ULONG ulColor;
  551. //
  552. // sge02
  553. //
  554. ulBltCmd |= ENABLE_TRANSPARENCY_COMPARE | ppdev->jModeColor;
  555. ulColor = lpBlt->bltFX.ddckSrcColorkey.dwColorSpaceLowValue;
  556. if (ppdev->cBpp == 1)
  557. {
  558. ulColor |= ulColor << 8;
  559. }
  560. CP_WRITE_USHORT(pjBase, MM_BLT_COLOR_KEY, ulColor);
  561. }
  562. if ( (ulBltCmd & DIR_BTRL)
  563. && (ulBltCmd & ENABLE_TRANSPARENCY_COMPARE)
  564. && (ppdev->cBpp > 1)
  565. )
  566. {
  567. ulBltCmd &= ~DIR_BTRL;
  568. xExt = lpBlt->rDest.right - lpBlt->rDest.left;
  569. yExt = lpBlt->rDest.bottom - lpBlt->rDest.top;
  570. xDiff = dstX - srcX;
  571. yDiff = dstY - srcY;
  572. if (yDiff == 0)
  573. {
  574. srcOffset -= srcPitch * height - 1;
  575. dstOffset -= dstPitch * height - 1;
  576. while (xExt)
  577. {
  578. width = PELS_TO_BYTES(min(xDiff, xExt));
  579. srcOffset -= width;
  580. dstOffset -= width;
  581. while (!BLT_READY(ppdev, pjBase)) ;
  582. CP_MM_ROP(ppdev, pjBase, CL_SRC_COPY);
  583. CP_MM_BLT_MODE(ppdev, pjBase, ulBltCmd);
  584. CP_MM_BLT_EXT_MODE(ppdev, pjBase, 0);
  585. CP_MM_SRC_Y_OFFSET(ppdev, pjBase, srcPitch);
  586. CP_MM_DST_Y_OFFSET(ppdev, pjBase, dstPitch);
  587. CP_MM_XCNT(ppdev, pjBase, width - 1);
  588. CP_MM_YCNT(ppdev, pjBase, height);
  589. CP_MM_SRC_ADDR(ppdev, pjBase, srcOffset);
  590. CP_MM_DST_ADDR_ABS(ppdev, pjBase, dstOffset);
  591. CP_MM_START_BLT(ppdev, pjBase);
  592. xExt -= min(xDiff, xExt);
  593. }
  594. }
  595. else
  596. {
  597. srcOffset -= width - srcPitch;
  598. dstOffset -= width - dstPitch;
  599. while (yExt)
  600. {
  601. height = min(yDiff, yExt);
  602. srcOffset -= height * srcPitch;
  603. dstOffset -= height * dstPitch;
  604. while (!BLT_READY(ppdev, pjBase)) ;
  605. CP_MM_ROP(ppdev, pjBase, CL_SRC_COPY);
  606. CP_MM_BLT_MODE(ppdev, pjBase, ulBltCmd);
  607. CP_MM_BLT_EXT_MODE(ppdev, pjBase, 0);
  608. CP_MM_SRC_Y_OFFSET(ppdev, pjBase, srcPitch);
  609. CP_MM_DST_Y_OFFSET(ppdev, pjBase, dstPitch);
  610. CP_MM_XCNT(ppdev, pjBase, width);
  611. CP_MM_YCNT(ppdev, pjBase, height - 1);
  612. CP_MM_SRC_ADDR(ppdev, pjBase, srcOffset);
  613. CP_MM_DST_ADDR_ABS(ppdev, pjBase, dstOffset);
  614. CP_MM_START_BLT(ppdev, pjBase);
  615. yExt -= min(yDiff, yExt);
  616. }
  617. }
  618. }
  619. else
  620. {
  621. CP_MM_ROP(ppdev, pjBase, CL_SRC_COPY);
  622. CP_MM_BLT_MODE(ppdev, pjBase, ulBltCmd);
  623. CP_MM_BLT_EXT_MODE(ppdev, pjBase, 0); // jl01
  624. CP_MM_SRC_Y_OFFSET(ppdev, pjBase, srcPitch);
  625. CP_MM_DST_Y_OFFSET(ppdev, pjBase, dstPitch);
  626. CP_MM_XCNT(ppdev, pjBase, width);
  627. CP_MM_YCNT(ppdev, pjBase, height);
  628. CP_MM_SRC_ADDR(ppdev, pjBase, srcOffset);
  629. CP_MM_DST_ADDR_ABS(ppdev, pjBase, dstOffset);
  630. CP_MM_START_BLT(ppdev, pjBase);
  631. }
  632. lpBlt->ddRVal = DD_OK;
  633. return(DDHAL_DRIVER_HANDLED);
  634. }
  635. /******************************Public*Routine******************************\
  636. * DWORD DdFlip
  637. *
  638. \**************************************************************************/
  639. DWORD DdFlip(
  640. PDD_FLIPDATA lpFlip)
  641. {
  642. PDEV* ppdev;
  643. BYTE* pjPorts;
  644. ULONG ulMemoryOffset;
  645. ULONG ulLowOffset;
  646. ULONG ulMiddleOffset;
  647. ULONG ulHighOffset1, ulHighOffset2;
  648. ppdev = lpFlip->lpDD->dhpdev;
  649. pjPorts = ppdev->pjPorts;
  650. DISPDBG((2, "DdFlip: %d x %d at %08x(%d, %d) Pitch=%d",
  651. lpFlip->lpSurfTarg->lpGbl->wWidth,
  652. lpFlip->lpSurfTarg->lpGbl->wHeight,
  653. lpFlip->lpSurfTarg->lpGbl->fpVidMem,
  654. lpFlip->lpSurfTarg->lpGbl->xHint,
  655. lpFlip->lpSurfTarg->lpGbl->yHint,
  656. lpFlip->lpSurfTarg->lpGbl->lPitch));
  657. // Is the current flip still in progress?
  658. //
  659. // Don't want a flip to work until after the last flip is done, so we ask
  660. // for the general flip status and ignore the vmem.
  661. //#jc01 if ((UpdateFlipStatus(ppdev, 0) != DD_OK) ||
  662. if ((UpdateFlipStatus(ppdev, 0xffffffff) != DD_OK) || /* #jc01 */
  663. (BLT_BUSY(ppdev, ppdev->pjBase)))
  664. {
  665. lpFlip->ddRVal = DDERR_WASSTILLDRAWING;
  666. return(DDHAL_DRIVER_HANDLED);
  667. }
  668. ulMemoryOffset = (ULONG)(lpFlip->lpSurfTarg->lpGbl->fpVidMem);
  669. // Make sure that the border/blanking period isn't active; wait if it is. We
  670. // could return DDERR_WASSTILLDRAWING in this case, but that will increase
  671. // the odds that we can't flip the next time.
  672. while (CP_IN_BYTE(pjPorts, STATUS_1) & DISPLAY_MODE_INACTIVE)
  673. ;
  674. DISPDBG((2, "DdFlip Entered"));
  675. #if 1 // OVERLAY #sge
  676. if (lpFlip->lpSurfCurr->ddsCaps.dwCaps & DDSCAPS_OVERLAY)
  677. {
  678. DWORD dwOffset;
  679. BYTE bRegCR3A;
  680. BYTE bRegCR3B;
  681. BYTE bRegCR3C;
  682. // Make sure that the overlay surface we're flipping from is
  683. // currently visible. If you don't do this check, you'll get
  684. // really weird results when someone starts up two ActiveMovie
  685. // or DirectVideo movies simultaneously!
  686. if (lpFlip->lpSurfCurr->lpGbl->fpVidMem == ppdev->fpVisibleOverlay)
  687. {
  688. ppdev->fpVisibleOverlay = ulMemoryOffset;
  689. /*
  690. * Determine the offset to the new area.
  691. */
  692. // dwOffset = ((ulMemoryOffset - (ULONG)ppdev->pjScreen) + ppdev->sOverlay1.lAdjustSource) >> 2; // sss
  693. dwOffset = ((ulMemoryOffset + ppdev->sOverlay1.lAdjustSource) >> 2);
  694. /*
  695. * Flip the overlay surface by changing CR3A, CR3B, and CR3C
  696. */
  697. bRegCR3A = (BYTE) dwOffset & 0xfe; // Align on word boundary (5446 bug)
  698. dwOffset >>= 8;
  699. bRegCR3B = (BYTE) dwOffset;
  700. dwOffset >>= 8;
  701. bRegCR3C = (BYTE) (dwOffset & 0x0f);
  702. // if(GetOverlayFlipStatus(0) != DD_OK || DRAW_ENGINE_BUSY || IN_VBLANK)
  703. // {
  704. // lpFlipData->ddRVal = DDERR_WASSTILLDRAWING;
  705. // return DDHAL_DRIVER_HANDLED;
  706. // }
  707. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x3C);
  708. CP_OUT_BYTE(pjPorts, CRTC_DATA, (CP_IN_BYTE(pjPorts, CRTC_DATA) & 0xf0) | bRegCR3C);
  709. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD)bRegCR3A << 8) | 0x3A);
  710. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD)bRegCR3B << 8) | 0x3B);
  711. }
  712. else
  713. {
  714. lpFlip->ddRVal = DDERR_OUTOFCAPS;
  715. return(DDHAL_DRIVER_HANDLED);
  716. }
  717. }
  718. else
  719. #endif // OVERLAY
  720. {
  721. // Do the flip.
  722. ulMemoryOffset >>= 2;
  723. ulLowOffset = 0x0D | ((ulMemoryOffset & 0x0000FF) << 8);
  724. ulMiddleOffset = 0x0C | ((ulMemoryOffset & 0x00FF00));
  725. ulHighOffset1 = 0x1B | ((ulMemoryOffset & 0x010000) >> 8)
  726. | ((ulMemoryOffset & 0x060000) >> 7)
  727. | ppdev->ulCR1B;
  728. ulHighOffset2 = 0x1D | ((ulMemoryOffset & 0x080000) >> 4)
  729. | ppdev->ulCR1D;
  730. // Too bad that the Cirrus flip can't be done in a single atomic register
  731. // write; as it is, we stand a small chance of being context-switched out
  732. // and exactly hitting the vertical blank in the middle of doing these outs,
  733. // possibly causing the screen to momentarily jump.
  734. //
  735. // There are some hoops we could jump through to minimize the chances of
  736. // this happening; we could try to align the flip buffer such that the minor
  737. // registers are ensured to be identical for either flip position, ans so
  738. // that only the high address need be written, an obviously atomic
  739. // operation.
  740. //
  741. // However, I'm simply not going to worry about it.
  742. CP_OUT_WORD(pjPorts, CRTC_INDEX, ulHighOffset2);
  743. CP_OUT_WORD(pjPorts, CRTC_INDEX, ulHighOffset1);
  744. CP_OUT_WORD(pjPorts, CRTC_INDEX, ulMiddleOffset);
  745. CP_OUT_WORD(pjPorts, CRTC_INDEX, ulLowOffset);
  746. }
  747. // Remember where and when we were when we did the flip.
  748. EngQueryPerformanceCounter(&ppdev->flipRecord.liFlipTime);
  749. ppdev->flipRecord.bFlipFlag = TRUE;
  750. ppdev->flipRecord.bHaveEverCrossedVBlank = FALSE;
  751. ppdev->flipRecord.fpFlipFrom = lpFlip->lpSurfCurr->lpGbl->fpVidMem;
  752. if((CP_IN_BYTE(pjPorts, STATUS_1) & VBLANK_ACTIVE))
  753. {
  754. ppdev->flipRecord.dwFlipScanLine = 0;
  755. ppdev->flipRecord.bWasEverInDisplay = FALSE;
  756. }
  757. else
  758. {
  759. ppdev->flipRecord.dwFlipScanLine = GetCurrentVLine(ppdev);
  760. ppdev->flipRecord.bWasEverInDisplay = TRUE;
  761. }
  762. lpFlip->ddRVal = DD_OK;
  763. return(DDHAL_DRIVER_HANDLED);
  764. }
  765. /******************************Public*Routine******************************\
  766. * DWORD DdLock
  767. *
  768. \**************************************************************************/
  769. DWORD DdLock(PDD_LOCKDATA lpLock)
  770. {
  771. PDEV* ppdev = lpLock->lpDD->dhpdev;
  772. BYTE* pjPorts = ppdev->pjPorts;
  773. // Check to see if any pending physical flip has occurred. Don't allow a
  774. // lock if a blt is in progress.
  775. if (UpdateFlipStatus(ppdev, lpLock->lpDDSurface->lpGbl->fpVidMem)
  776. != DD_OK)
  777. {
  778. lpLock->ddRVal = DDERR_WASSTILLDRAWING;
  779. return(DDHAL_DRIVER_HANDLED);
  780. }
  781. if (lpLock->dwFlags & DDLOCK_WAIT)
  782. {
  783. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, ppdev->pjBase);
  784. }
  785. if (BLT_BUSY(ppdev, ppdev->pjBase))
  786. {
  787. lpLock->ddRVal = DDERR_WASSTILLDRAWING;
  788. return(DDHAL_DRIVER_HANDLED);
  789. }
  790. /*
  791. * Force them to use the video apperture
  792. */
  793. if ((lpLock->lpDDSurface->dwReserved1 & OVERLAY_FLG_OVERLAY) &&
  794. (lpLock->dwFlags == DDLOCK_SURFACEMEMORYPTR) &&
  795. (ppdev->fpBaseOverlay != 0xffffffff))
  796. {
  797. if (lpLock->lpDDSurface->dwReserved1 & OVERLAY_FLG_DECIMATE)
  798. {
  799. /*
  800. * Turn on decimation
  801. */
  802. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x3f);
  803. CP_OUT_BYTE(pjPorts, CRTC_DATA, CP_IN_BYTE(pjPorts, CRTC_DATA) | 0x10);
  804. }
  805. if( lpLock->lpDDSurface->lpGbl->ddpfSurface.dwFourCC == FOURCC_YUY2)
  806. lpLock->lpSurfData = (LPVOID)(ppdev->fpBaseOverlay + lpLock->lpDDSurface->lpGbl->fpVidMem + 0x400000);
  807. else
  808. lpLock->lpSurfData = (LPVOID)(ppdev->fpBaseOverlay + lpLock->lpDDSurface->lpGbl->fpVidMem + 0x400000 * 3);
  809. // When a driver returns DD_OK and DDHAL_DRIVER_HANDLED from DdLock,
  810. // DirectDraw expects it to have adjusted the resulting pointer
  811. // to point to the upper left corner of the specified rectangle, if
  812. // any:
  813. if (lpLock->bHasRect)
  814. {
  815. lpLock->lpSurfData = (VOID*) ((BYTE*) lpLock->lpSurfData
  816. + lpLock->rArea.top * lpLock->lpDDSurface->lpGbl->lPitch
  817. + lpLock->rArea.left
  818. * (lpLock->lpDDSurface->lpGbl->ddpfSurface.dwYUVBitCount >> 3));
  819. }
  820. lpLock->ddRVal = DD_OK;
  821. return(DDHAL_DRIVER_HANDLED);
  822. }
  823. return(DDHAL_DRIVER_NOTHANDLED);
  824. }
  825. /******************************Public*Routine******************************\
  826. * DWORD DdUnlock
  827. *
  828. \**************************************************************************/
  829. DWORD DdUnlock(PDD_UNLOCKDATA lpUnlock)
  830. {
  831. PDEV* ppdev = lpUnlock->lpDD->dhpdev;
  832. BYTE* pjPorts = ppdev->pjPorts;
  833. if ((lpUnlock->lpDDSurface->dwReserved1 & OVERLAY_FLG_YUVPLANAR) &&
  834. !(lpUnlock->lpDDSurface->dwReserved1 & OVERLAY_FLG_ENABLED))
  835. {
  836. CP_OUT_WORD(pjPorts, CRTC_INDEX, (0x00 << 8) | 0x3f); // Turn off YUV Planar
  837. }
  838. else if (lpUnlock->lpDDSurface->dwReserved1 & OVERLAY_FLG_DECIMATE)
  839. {
  840. CP_OUT_WORD(pjPorts, CRTC_INDEX, (0x00 << 8) | 0x3f); // Turn off YUV Planar
  841. }
  842. return(DDHAL_DRIVER_NOTHANDLED);
  843. }
  844. /******************************Public*Routine******************************\
  845. * DWORD DdGetBltStatus
  846. *
  847. * Doesn't currently really care what surface is specified, just checks
  848. * and goes.
  849. *
  850. \**************************************************************************/
  851. DWORD DdGetBltStatus(PDD_GETBLTSTATUSDATA lpGetBltStatus)
  852. {
  853. PDEV* ppdev;
  854. HRESULT ddRVal;
  855. PBYTE pjBase;
  856. ppdev = lpGetBltStatus->lpDD->dhpdev;
  857. pjBase = ppdev->pjBase;
  858. ddRVal = DD_OK;
  859. if (lpGetBltStatus->dwFlags == DDGBS_CANBLT)
  860. {
  861. // DDGBS_CANBLT case: can we add a blt?
  862. ddRVal = UpdateFlipStatus(ppdev, lpGetBltStatus->lpDDSurface->lpGbl->fpVidMem);
  863. if (ddRVal == DD_OK)
  864. {
  865. // There was no flip going on, so can the blitter accept new
  866. // register writes?
  867. if (!BLT_READY(ppdev, pjBase))
  868. {
  869. ddRVal = DDERR_WASSTILLDRAWING;
  870. }
  871. }
  872. }
  873. else
  874. {
  875. // DDGBS_ISBLTDONE case: is a blt in progress?
  876. if (BLT_BUSY(ppdev, pjBase))
  877. {
  878. ddRVal = DDERR_WASSTILLDRAWING;
  879. }
  880. }
  881. lpGetBltStatus->ddRVal = ddRVal;
  882. return(DDHAL_DRIVER_HANDLED);
  883. }
  884. /******************************Public*Routine******************************\
  885. * DWORD DdMapMemory
  886. *
  887. * This is a new DDI call specific to Windows NT that is used to map
  888. * or unmap all the application modifiable portions of the frame buffer
  889. * into the specified process's address space.
  890. *
  891. \**************************************************************************/
  892. DWORD DdMapMemory(PDD_MAPMEMORYDATA lpMapMemory)
  893. {
  894. PDEV* ppdev;
  895. VIDEO_SHARE_MEMORY ShareMemory;
  896. VIDEO_SHARE_MEMORY_INFORMATION ShareMemoryInformation;
  897. DWORD ReturnedDataLength;
  898. ppdev = lpMapMemory->lpDD->dhpdev;
  899. if (lpMapMemory->bMap)
  900. {
  901. ShareMemory.ProcessHandle = lpMapMemory->hProcess;
  902. // 'RequestedVirtualAddress' isn't actually used for the SHARE IOCTL.
  903. ShareMemory.RequestedVirtualAddress = 0;
  904. // We map in starting at the top of the frame buffer.
  905. ShareMemory.ViewOffset = 0;
  906. // We map down to the end of the frame buffer.
  907. //
  908. // Note: There is a 64k granularity on the mapping (meaning that we
  909. // have to round up to 64k).
  910. //
  911. // Note: If there is any portion of the frame buffer that must not be
  912. // modified by an application, that portion of memory MUST NOT be
  913. // mapped in by this call. This would include any data that, if
  914. // modified by a malicious application, would cause the driver to
  915. // crash. This could include, for example, any DSP code that is
  916. // kept in off-screen memory.
  917. ShareMemory.ViewSize = ROUND_UP_TO_64K(ppdev->cyMemory * ppdev->lDelta + 0x400000 * 3);
  918. if (EngDeviceIoControl(ppdev->hDriver,
  919. IOCTL_VIDEO_SHARE_VIDEO_MEMORY,
  920. &ShareMemory,
  921. sizeof(VIDEO_SHARE_MEMORY),
  922. &ShareMemoryInformation,
  923. sizeof(VIDEO_SHARE_MEMORY_INFORMATION),
  924. &ReturnedDataLength))
  925. {
  926. DISPDBG((0, "Failed IOCTL_VIDEO_SHARE_MEMORY"));
  927. lpMapMemory->ddRVal = DDERR_GENERIC;
  928. return(DDHAL_DRIVER_HANDLED);
  929. }
  930. lpMapMemory->fpProcess =(FLATPTR)ShareMemoryInformation.VirtualAddress;
  931. ppdev->fpBaseOverlay = lpMapMemory->fpProcess;
  932. }
  933. else
  934. {
  935. ShareMemory.ProcessHandle = lpMapMemory->hProcess;
  936. ShareMemory.ViewOffset = 0;
  937. ShareMemory.ViewSize = 0;
  938. ShareMemory.RequestedVirtualAddress = (VOID*) lpMapMemory->fpProcess;
  939. //
  940. // Active movie will unmap memory twice
  941. //
  942. //if (ppdev->fpBaseOverlay == lpMapMemory->fpProcess)
  943. // ppdev->fpBaseOverlay = 0;
  944. if (EngDeviceIoControl(ppdev->hDriver,
  945. IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY,
  946. &ShareMemory,
  947. sizeof(VIDEO_SHARE_MEMORY),
  948. NULL,
  949. 0,
  950. &ReturnedDataLength))
  951. {
  952. RIP("Failed IOCTL_VIDEO_UNSHARE_MEMORY");
  953. }
  954. }
  955. lpMapMemory->ddRVal = DD_OK;
  956. return(DDHAL_DRIVER_HANDLED);
  957. }
  958. /******************************Public*Routine******************************\
  959. * DWORD DdGetFlipStatus
  960. *
  961. * If the display has gone through one refresh cycle since the flip
  962. * occurred, we return DD_OK. If it has not gone through one refresh
  963. * cycle we return DDERR_WASSTILLDRAWING to indicate that this surface
  964. * is still busy "drawing" the flipped page. We also return
  965. * DDERR_WASSTILLDRAWING if the bltter is busy and the caller wanted
  966. * to know if they could flip yet.
  967. *
  968. \**************************************************************************/
  969. DWORD DdGetFlipStatus(
  970. PDD_GETFLIPSTATUSDATA lpGetFlipStatus)
  971. {
  972. HRESULT ddRVal;
  973. PDEV* ppdev = lpGetFlipStatus->lpDD->dhpdev;
  974. // We don't want a flip to work until after the last flip is done, so we ask
  975. // for the general flip status and ignore the vmem.
  976. //#jc01 ddRVal = UpdateFlipStatus(ppdev, 0);
  977. ddRVal = UpdateFlipStatus(ppdev, 0xffffffff); //#jc01
  978. // Check if the blitter is busy if someone wants to know if they can flip.
  979. if ((lpGetFlipStatus->dwFlags == DDGFS_CANFLIP) && (ddRVal == DD_OK))
  980. {
  981. if (BLT_BUSY(ppdev, ppdev->pjBase))
  982. {
  983. ddRVal = DDERR_WASSTILLDRAWING;
  984. }
  985. }
  986. lpGetFlipStatus->ddRVal = ddRVal;
  987. return(DDHAL_DRIVER_HANDLED);
  988. }
  989. /******************************Public*Routine******************************\
  990. * DWORD DdWaitForVerticalBlank
  991. *
  992. \**************************************************************************/
  993. DWORD DdWaitForVerticalBlank(
  994. PDD_WAITFORVERTICALBLANKDATA lpWaitForVerticalBlank)
  995. {
  996. PDEV* ppdev;
  997. BYTE* pjPorts;
  998. ppdev = lpWaitForVerticalBlank->lpDD->dhpdev;
  999. pjPorts = ppdev->pjPorts;
  1000. lpWaitForVerticalBlank->ddRVal = DD_OK;
  1001. switch (lpWaitForVerticalBlank->dwFlags)
  1002. {
  1003. case DDWAITVB_I_TESTVB:
  1004. // If TESTVB, it's just a request for the current vertical blank status.
  1005. if (CP_IN_BYTE(pjPorts, STATUS_1) & VBLANK_ACTIVE)
  1006. lpWaitForVerticalBlank->bIsInVB = TRUE;
  1007. else
  1008. lpWaitForVerticalBlank->bIsInVB = FALSE;
  1009. return(DDHAL_DRIVER_HANDLED);
  1010. case DDWAITVB_BLOCKBEGIN:
  1011. // If BLOCKBEGIN is requested, we wait until the vertical blank is over,
  1012. // and then wait for the display period to end.
  1013. while (CP_IN_BYTE(pjPorts, STATUS_1) & VBLANK_ACTIVE)
  1014. ;
  1015. while (!(CP_IN_BYTE(pjPorts, STATUS_1) & VBLANK_ACTIVE))
  1016. ;
  1017. return(DDHAL_DRIVER_HANDLED);
  1018. case DDWAITVB_BLOCKEND:
  1019. // If BLOCKEND is requested, we wait for the vblank interval to end.
  1020. while (!(CP_IN_BYTE(pjPorts, STATUS_1) & VBLANK_ACTIVE))
  1021. ;
  1022. while (CP_IN_BYTE(pjPorts, STATUS_1) & VBLANK_ACTIVE)
  1023. ;
  1024. return(DDHAL_DRIVER_HANDLED);
  1025. }
  1026. return(DDHAL_DRIVER_NOTHANDLED);
  1027. }
  1028. /******************************Public*Routine******************************\
  1029. * DWORD DdGetScanLine
  1030. *
  1031. * Reads the scan line currently being scanned by the CRT.
  1032. *
  1033. \**************************************************************************/
  1034. DWORD DdGetScanLine(
  1035. PDD_GETSCANLINEDATA lpGetScanLine)
  1036. {
  1037. PDEV* ppdev;
  1038. BYTE* pjPorts;
  1039. ppdev = (PDEV*) lpGetScanLine->lpDD->dhpdev;
  1040. pjPorts = ppdev->pjPorts;
  1041. /*
  1042. * If a vertical blank is in progress the scan line is in
  1043. * indeterminant. If the scan line is indeterminant we return
  1044. * the error code DDERR_VERTICALBLANKINPROGRESS.
  1045. * Otherwise we return the scan line and a success code
  1046. */
  1047. if( CP_IN_BYTE(pjPorts, STATUS_1) & VBLANK_ACTIVE )
  1048. {
  1049. lpGetScanLine->ddRVal = DDERR_VERTICALBLANKINPROGRESS;
  1050. }
  1051. else
  1052. {
  1053. lpGetScanLine->dwScanLine = GetCurrentVLine(ppdev);
  1054. lpGetScanLine->ddRVal = DD_OK;
  1055. }
  1056. return(DDHAL_DRIVER_HANDLED);
  1057. }
  1058. /******************************Public*Routine******************************\
  1059. * DWORD DdCanCreateSurface
  1060. *
  1061. \**************************************************************************/
  1062. DWORD DdCanCreateSurface(
  1063. PDD_CANCREATESURFACEDATA lpCanCreateSurface)
  1064. {
  1065. PDEV* ppdev;
  1066. DWORD dwRet;
  1067. LPDDSURFACEDESC lpSurfaceDesc;
  1068. ppdev = (PDEV*) lpCanCreateSurface->lpDD->dhpdev;
  1069. lpSurfaceDesc = lpCanCreateSurface->lpDDSurfaceDesc;
  1070. dwRet = DDHAL_DRIVER_NOTHANDLED;
  1071. DISPDBG((2, "DdCanCreateSurface Entered"));
  1072. if (!lpCanCreateSurface->bIsDifferentPixelFormat)
  1073. {
  1074. // It's trivially easy to create plain surfaces that are the same
  1075. // type as the primary surface:
  1076. dwRet = DDHAL_DRIVER_HANDLED;
  1077. }
  1078. else if (ppdev->flStatus & STAT_STREAMS_ENABLED)
  1079. {
  1080. // When using the Streams processor, we handle only overlays of
  1081. // different pixel formats -- not any off-screen memory:
  1082. if (lpSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_OVERLAY)
  1083. {
  1084. /*
  1085. * YUV Planar surfaces cannot co-exist with other overlay surfaces.
  1086. */
  1087. if (ppdev->OvlyCnt >= 1)
  1088. {
  1089. lpCanCreateSurface->ddRVal = DDERR_OUTOFCAPS;
  1090. return (DDHAL_DRIVER_HANDLED);
  1091. }
  1092. if ((lpSurfaceDesc->ddpfPixelFormat.dwFourCC == FOURCC_YUVPLANAR) &&
  1093. ppdev->OvlyCnt)
  1094. {
  1095. lpCanCreateSurface->ddRVal = DDERR_INVALIDPIXELFORMAT;
  1096. return (DDHAL_DRIVER_HANDLED);
  1097. }
  1098. else if (ppdev->PlanarCnt)
  1099. {
  1100. lpCanCreateSurface->ddRVal = DDERR_INVALIDPIXELFORMAT;
  1101. return (DDHAL_DRIVER_HANDLED);
  1102. }
  1103. // We handle four types of YUV overlay surfaces:
  1104. if (lpSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_FOURCC)
  1105. {
  1106. // Check first for a supported YUV type:
  1107. if (lpSurfaceDesc->ddpfPixelFormat.dwFourCC == FOURCC_YUV422)
  1108. {
  1109. lpSurfaceDesc->ddpfPixelFormat.dwYUVBitCount = 16;
  1110. dwRet = DDHAL_DRIVER_HANDLED;
  1111. }
  1112. else if ((lpSurfaceDesc->ddpfPixelFormat.dwFourCC == FOURCC_YUY2) &&
  1113. ((ppdev->ulChipID != 0x40) && (ppdev->ulChipID != 0x4C)) ) //tao1
  1114. {
  1115. lpSurfaceDesc->ddpfPixelFormat.dwYUVBitCount = 16;
  1116. dwRet = DDHAL_DRIVER_HANDLED;
  1117. }
  1118. else if (lpSurfaceDesc->ddpfPixelFormat.dwFourCC == FOURCC_PACKJR)
  1119. {
  1120. if( ppdev->cBitsPerPixel <= 16)
  1121. {
  1122. lpSurfaceDesc->ddpfPixelFormat.dwYUVBitCount = 8;
  1123. dwRet = DDHAL_DRIVER_HANDLED;
  1124. }
  1125. }
  1126. else if (lpSurfaceDesc->ddpfPixelFormat.dwFourCC == FOURCC_YUVPLANAR)
  1127. {
  1128. lpSurfaceDesc->ddpfPixelFormat.dwYUVBitCount = 8;
  1129. dwRet = DDHAL_DRIVER_HANDLED;
  1130. }
  1131. }
  1132. else if (lpSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB)
  1133. {
  1134. if((lpSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) &&
  1135. ppdev->cBitsPerPixel == 16 )
  1136. {
  1137. dwRet = DDHAL_DRIVER_HANDLED;
  1138. }
  1139. else if (lpSurfaceDesc->ddpfPixelFormat.dwRGBBitCount == 16)
  1140. {
  1141. dwRet = DDHAL_DRIVER_HANDLED;
  1142. }
  1143. }
  1144. }
  1145. }
  1146. // Print some spew if this was a surface we refused to create:
  1147. if (dwRet == DDHAL_DRIVER_NOTHANDLED)
  1148. {
  1149. if (lpSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB)
  1150. {
  1151. DISPDBG((0, "Failed creation of %libpp RGB surface %lx %lx %lx",
  1152. lpSurfaceDesc->ddpfPixelFormat.dwRGBBitCount,
  1153. lpSurfaceDesc->ddpfPixelFormat.dwRBitMask,
  1154. lpSurfaceDesc->ddpfPixelFormat.dwGBitMask,
  1155. lpSurfaceDesc->ddpfPixelFormat.dwBBitMask));
  1156. }
  1157. else
  1158. {
  1159. DISPDBG((0, "Failed creation of type 0x%lx YUV 0x%lx surface",
  1160. lpSurfaceDesc->ddpfPixelFormat.dwFlags,
  1161. lpSurfaceDesc->ddpfPixelFormat.dwFourCC));
  1162. }
  1163. }
  1164. lpCanCreateSurface->ddRVal = DD_OK;
  1165. return(dwRet);
  1166. }
  1167. /******************************Public*Routine******************************\
  1168. * DWORD DdCreateSurface
  1169. *
  1170. \**************************************************************************/
  1171. DWORD DdCreateSurface(
  1172. PDD_CREATESURFACEDATA lpCreateSurface)
  1173. {
  1174. PDEV* ppdev;
  1175. DD_SURFACE_LOCAL* lpSurfaceLocal;
  1176. DD_SURFACE_GLOBAL* lpSurfaceGlobal;
  1177. LPDDSURFACEDESC lpSurfaceDesc;
  1178. DWORD dwByteCount;
  1179. LONG lLinearPitch;
  1180. DWORD dwHeight;
  1181. ppdev = (PDEV*) lpCreateSurface->lpDD->dhpdev;
  1182. DISPDBG((2, "DdCreateSurface Entered"));
  1183. // On Windows NT, dwSCnt will always be 1, so there will only ever
  1184. // be one entry in the 'lplpSList' array:
  1185. lpSurfaceLocal = lpCreateSurface->lplpSList[0];
  1186. lpSurfaceGlobal = lpSurfaceLocal->lpGbl;
  1187. lpSurfaceDesc = lpCreateSurface->lpDDSurfaceDesc;
  1188. // We repeat the same checks we did in 'DdCanCreateSurface' because
  1189. // it's possible that an application doesn't call 'DdCanCreateSurface'
  1190. // before calling 'DdCreateSurface'.
  1191. ASSERTDD(lpSurfaceGlobal->ddpfSurface.dwSize == sizeof(DDPIXELFORMAT),
  1192. "NT is supposed to guarantee that ddpfSurface.dwSize is valid");
  1193. // DdCanCreateSurface already validated whether the hardware supports
  1194. // the surface, so we don't need to do any validation here. We'll
  1195. // just go ahead and allocate it.
  1196. //
  1197. // Note that we don't do anything special for RGB surfaces that are
  1198. // the same pixel format as the display -- by returning DDHAL_DRIVER_
  1199. // NOTHANDLED, DirectDraw will automatically handle the allocation
  1200. // for us.
  1201. //
  1202. // Also, since we'll be making linear surfaces, make sure the width
  1203. // isn't unreasonably large.
  1204. //
  1205. // Note that on NT, an overlay can be created only if the driver
  1206. // okay's it here in this routine. Under Win95, the overlay will be
  1207. // created automatically if it's the same pixel format as the primary
  1208. // display.
  1209. if ((lpSurfaceLocal->ddsCaps.dwCaps & DDSCAPS_OVERLAY) ||
  1210. (lpSurfaceGlobal->ddpfSurface.dwFlags & DDPF_FOURCC) ||
  1211. (lpSurfaceGlobal->ddpfSurface.dwRBitMask != ppdev->flRed))
  1212. {
  1213. if (lpSurfaceGlobal->wWidth <= (DWORD) ppdev->cxMemory)
  1214. {
  1215. lLinearPitch = (lpSurfaceGlobal->wWidth + 7) & ~7;
  1216. if (lpSurfaceGlobal->ddpfSurface.dwFlags & DDPF_FOURCC)
  1217. {
  1218. ASSERTDD((lpSurfaceGlobal->ddpfSurface.dwFourCC == FOURCC_YUV422) ||
  1219. (lpSurfaceGlobal->ddpfSurface.dwFourCC == FOURCC_YUY2) ||
  1220. (lpSurfaceGlobal->ddpfSurface.dwFourCC == FOURCC_PACKJR) ||
  1221. (lpSurfaceGlobal->ddpfSurface.dwFourCC == FOURCC_YUVPLANAR),
  1222. "Expected our DdCanCreateSurface to allow only UYVY, YUY2, CLPJ, CLPL");
  1223. if((lpSurfaceGlobal->ddpfSurface.dwFourCC == FOURCC_YUV422) ||
  1224. (lpSurfaceGlobal->ddpfSurface.dwFourCC == FOURCC_YUY2))
  1225. {
  1226. dwByteCount = 2;
  1227. lLinearPitch <<= 1;
  1228. lpSurfaceLocal->dwReserved1 |= OVERLAY_FLG_YUV422;
  1229. }
  1230. else if((lpSurfaceGlobal->ddpfSurface.dwFourCC == FOURCC_PACKJR))
  1231. {
  1232. dwByteCount = 1;
  1233. lpSurfaceLocal->dwReserved1 |= OVERLAY_FLG_PACKJR;
  1234. }
  1235. else if((lpSurfaceGlobal->ddpfSurface.dwFourCC == FOURCC_YUVPLANAR))
  1236. {
  1237. dwByteCount = 1;
  1238. lpSurfaceLocal->dwReserved1 |= OVERLAY_FLG_YUVPLANAR;
  1239. }
  1240. else
  1241. {
  1242. dwByteCount = 1;
  1243. DISPDBG((1, "Created RGB %libpp: %li x %li Red: %lx",
  1244. 8 * dwByteCount, lpSurfaceGlobal->wWidth, lpSurfaceGlobal->wHeight,
  1245. lpSurfaceGlobal->ddpfSurface.dwRBitMask));
  1246. }
  1247. // We have to fill in the bit-count for FourCC surfaces:
  1248. lpSurfaceGlobal->ddpfSurface.dwYUVBitCount = 8 * dwByteCount;
  1249. lpSurfaceGlobal->ddpfSurface.dwYBitMask = (DWORD)-1;
  1250. lpSurfaceGlobal->ddpfSurface.dwUBitMask = (DWORD)-1;
  1251. lpSurfaceGlobal->ddpfSurface.dwVBitMask = (DWORD)-1;
  1252. DISPDBG((1, "Created YUV: %li x %li",
  1253. lpSurfaceGlobal->wWidth, lpSurfaceGlobal->wHeight));
  1254. }
  1255. else
  1256. {
  1257. dwByteCount = lpSurfaceGlobal->ddpfSurface.dwRGBBitCount >> 3;
  1258. if (dwByteCount == 2)
  1259. lLinearPitch <<= 1;
  1260. DISPDBG((1, "Created RGB %libpp: %li x %li Red: %lx",
  1261. 8 * dwByteCount, lpSurfaceGlobal->wWidth, lpSurfaceGlobal->wHeight,
  1262. lpSurfaceGlobal->ddpfSurface.dwRBitMask));
  1263. }
  1264. // We want to allocate a linear surface to store the FourCC
  1265. // surface, but DirectDraw is using a 2-D heap-manager because
  1266. // the rest of our surfaces have to be 2-D. So here we have to
  1267. // convert the linear size to a 2-D size.
  1268. //
  1269. // The stride has to be a dword multiple:
  1270. dwHeight = (lpSurfaceGlobal->wHeight * lLinearPitch
  1271. + ppdev->lDelta - 1) / ppdev->lDelta;
  1272. // Now fill in enough stuff to have the DirectDraw heap-manager
  1273. // do the allocation for us:
  1274. lpSurfaceGlobal->fpVidMem = DDHAL_PLEASEALLOC_BLOCKSIZE;
  1275. lpSurfaceGlobal->dwBlockSizeX = ppdev->lDelta; // Specified in bytes
  1276. lpSurfaceGlobal->dwBlockSizeY = dwHeight;
  1277. lpSurfaceGlobal->lPitch = lLinearPitch;
  1278. lpSurfaceDesc->lPitch = lLinearPitch;
  1279. lpSurfaceDesc->dwFlags |= DDSD_PITCH;
  1280. lpSurfaceLocal->dwReserved1 |= OVERLAY_FLG_OVERLAY;
  1281. if (lpSurfaceGlobal->ddpfSurface.dwFourCC == FOURCC_YUVPLANAR)
  1282. {
  1283. ppdev->PlanarCnt++;
  1284. }
  1285. else
  1286. {
  1287. ppdev->OvlyCnt++;
  1288. }
  1289. ppdev->fpBaseOverlay = 0xffffffff;
  1290. }
  1291. else
  1292. {
  1293. DISPDBG((1, "Refused to create surface with large width"));
  1294. }
  1295. }
  1296. return(DDHAL_DRIVER_NOTHANDLED);
  1297. }
  1298. /******************************Public*Routine******************************\
  1299. * DWORD DdDestroySurface
  1300. *
  1301. \**************************************************************************/
  1302. DWORD DdDestroySurface (PDD_DESTROYSURFACEDATA lpDestroySurface)
  1303. {
  1304. PDEV* ppdev;
  1305. BYTE* pjPorts;
  1306. ppdev = (PDEV*) lpDestroySurface->lpDD->dhpdev;
  1307. pjPorts = ppdev->pjPorts;
  1308. DISPDBG((2, "In DestroyOverlaySurface"));
  1309. if (lpDestroySurface->lpDDSurface->dwReserved1 & OVERLAY_FLG_ENABLED)
  1310. {
  1311. BYTE bTemp;
  1312. /*
  1313. * Turn the video off
  1314. */
  1315. DISPDBG((1,"Turning off video in DestroySurface"));
  1316. ppdev->pfnDisableOverlay(ppdev);
  1317. ppdev->pfnClearAltFIFOThreshold(ppdev);
  1318. if (lpDestroySurface->lpDDSurface->dwReserved1 & OVERLAY_FLG_COLOR_KEY)
  1319. {
  1320. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x1a);
  1321. bTemp = CP_IN_BYTE(pjPorts, CRTC_DATA); // Clear CR1A[3:2]
  1322. CP_OUT_BYTE(pjPorts, CRTC_DATA, bTemp & ~0x0C);
  1323. }
  1324. /*
  1325. * Turn off YUV Planar
  1326. */
  1327. if (lpDestroySurface->lpDDSurface->dwReserved1 & OVERLAY_FLG_YUVPLANAR)
  1328. {
  1329. CP_OUT_WORD(pjPorts, CRTC_INDEX, (0x00 << 8) | 0x3f); // Turn off YUV Planar
  1330. }
  1331. ppdev->fpVisibleOverlay = (FLATPTR)NULL;
  1332. ppdev->dwPanningFlag &= ~OVERLAY_OLAY_SHOW;
  1333. }
  1334. if (lpDestroySurface->lpDDSurface->dwReserved1 & OVERLAY_FLG_YUVPLANAR)
  1335. {
  1336. if (ppdev->PlanarCnt > 0)
  1337. ppdev->PlanarCnt--;
  1338. }
  1339. else
  1340. {
  1341. if (ppdev->OvlyCnt > 0)
  1342. ppdev->OvlyCnt--;
  1343. }
  1344. if (lpDestroySurface->lpDDSurface->ddsCaps.dwCaps & DDSCAPS_LIVEVIDEO)
  1345. {
  1346. BYTE bTemp;
  1347. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x51);
  1348. bTemp= CP_IN_BYTE(pjPorts, CRTC_DATA);
  1349. CP_OUT_BYTE(pjPorts, CRTC_DATA, bTemp & ~0x08);
  1350. }
  1351. return(DDHAL_DRIVER_NOTHANDLED);
  1352. }
  1353. /******************************Public*Routine******************************\
  1354. * DWORD DdSetColorKey
  1355. *
  1356. \**************************************************************************/
  1357. DWORD DdSetColorKey(
  1358. PDD_SETCOLORKEYDATA lpSetColorKey)
  1359. {
  1360. PDEV* ppdev;
  1361. BYTE* pjPorts;
  1362. BYTE* pjBase;
  1363. DD_SURFACE_GLOBAL* lpSurface;
  1364. DWORD dwKeyLow;
  1365. DWORD dwKeyHigh;
  1366. ppdev = (PDEV*) lpSetColorKey->lpDD->dhpdev;
  1367. DISPDBG((2, "DdSetColorKey Entered"));
  1368. ASSERTDD(ppdev->flStatus & STAT_STREAMS_ENABLED, "Shouldn't have hooked call");
  1369. pjPorts = ppdev->pjPorts;
  1370. pjBase = ppdev->pjBase;
  1371. lpSurface = lpSetColorKey->lpDDSurface->lpGbl;
  1372. // We don't have to do anything for normal blt source colour keys:
  1373. if (lpSetColorKey->dwFlags & DDCKEY_SRCBLT)
  1374. {
  1375. lpSetColorKey->ddRVal = DD_OK;
  1376. return(DDHAL_DRIVER_HANDLED);
  1377. }
  1378. else if ((lpSetColorKey->dwFlags & DDCKEY_DESTOVERLAY) &&
  1379. (lpSetColorKey->lpDDSurface == ppdev->lpColorSurface))
  1380. {
  1381. if (lpSurface->fpVidMem == ppdev->fpVisibleOverlay)
  1382. {
  1383. ppdev->wColorKey = (WORD) lpSetColorKey->ckNew.dwColorSpaceLowValue;
  1384. ppdev->pfnRegInitVideo(ppdev, lpSetColorKey->lpDDSurface);
  1385. }
  1386. lpSetColorKey->ddRVal = DD_OK;
  1387. return(DDHAL_DRIVER_HANDLED);
  1388. }
  1389. else if ((lpSetColorKey->dwFlags & DDCKEY_SRCOVERLAY) &&
  1390. (lpSetColorKey->lpDDSurface == ppdev->lpSrcColorSurface))
  1391. {
  1392. if (lpSurface->fpVidMem == ppdev->fpVisibleOverlay)
  1393. {
  1394. ppdev->dwSrcColorKeyLow = lpSetColorKey->ckNew.dwColorSpaceLowValue;
  1395. ppdev->dwSrcColorKeyHigh = lpSetColorKey->ckNew.dwColorSpaceHighValue;
  1396. if (ppdev->dwSrcColorKeyLow > ppdev->dwSrcColorKeyHigh)
  1397. {
  1398. ppdev->dwSrcColorKeyHigh = ppdev->dwSrcColorKeyLow;
  1399. }
  1400. ppdev->pfnRegInitVideo(ppdev, lpSetColorKey->lpDDSurface);
  1401. }
  1402. lpSetColorKey->ddRVal = DD_OK;
  1403. return(DDHAL_DRIVER_HANDLED);
  1404. }
  1405. DISPDBG((1, "DdSetColorKey: Invalid command"));
  1406. return(DDHAL_DRIVER_NOTHANDLED);
  1407. }
  1408. /******************************Public*Routine******************************\
  1409. * DWORD DdUpdateOverlay
  1410. *
  1411. \**************************************************************************/
  1412. DWORD DdUpdateOverlay(
  1413. PDD_UPDATEOVERLAYDATA lpUpdateOverlay)
  1414. {
  1415. PDEV* ppdev;
  1416. BYTE* pjPorts;
  1417. BYTE* pjBase;
  1418. DD_SURFACE_GLOBAL* lpSource;
  1419. DD_SURFACE_GLOBAL* lpDestination;
  1420. DWORD dwStride;
  1421. LONG srcWidth;
  1422. LONG srcHeight;
  1423. LONG dstWidth;
  1424. LONG dstHeight;
  1425. DWORD dwBitCount;
  1426. DWORD dwStart;
  1427. DWORD dwTmp;
  1428. BOOL bColorKey;
  1429. DWORD dwKeyLow;
  1430. DWORD dwKeyHigh;
  1431. DWORD dwBytesPerPixel;
  1432. DWORD dwSecCtrl;
  1433. DWORD dwBlendCtrl;
  1434. DWORD dwFourcc;
  1435. BOOL bCheckBandwidth;
  1436. WORD wBitCount;
  1437. DWORD_PTR dwOldStatus;
  1438. BYTE bTemp;
  1439. ppdev = (PDEV*) lpUpdateOverlay->lpDD->dhpdev;
  1440. DISPDBG((2, "DdUpdateOverlay Entered"));
  1441. ASSERTDD(ppdev->flStatus & STAT_STREAMS_ENABLED, "Shouldn't have hooked call");
  1442. pjPorts = ppdev->pjPorts;
  1443. pjBase = ppdev->pjBase;
  1444. //myf33 begin
  1445. // Initialize the bandwidth registers
  1446. Regs.bSR2F = 0;
  1447. Regs.bSR32 = 0;
  1448. Regs.bSR34 = 0;
  1449. Regs.bCR42 = 0;
  1450. //myf33 end
  1451. if (lpUpdateOverlay->lpDDSrcSurface->dwFlags & DDRAWISURF_HASPIXELFORMAT)
  1452. {
  1453. GetFormatInfo(ppdev, &(lpUpdateOverlay->lpDDSrcSurface->lpGbl->ddpfSurface),
  1454. &dwFourcc, &wBitCount);
  1455. }
  1456. else
  1457. {
  1458. // This needs to be changed when primary surface is RGB 5:6:5
  1459. dwFourcc = BI_RGB;
  1460. wBitCount = (WORD) ppdev->cBitsPerPixel;
  1461. }
  1462. /*
  1463. * Are we color keying?
  1464. */
  1465. bCheckBandwidth = TRUE;
  1466. ppdev->lpColorSurface = ppdev->lpSrcColorSurface = NULL;
  1467. dwOldStatus = lpUpdateOverlay->lpDDSrcSurface->dwReserved1;
  1468. if ((lpUpdateOverlay->dwFlags & (DDOVER_KEYDEST | DDOVER_KEYDESTOVERRIDE)) &&
  1469. (lpUpdateOverlay->dwFlags & (DDOVER_KEYSRC | DDOVER_KEYSRCOVERRIDE)))
  1470. {
  1471. /*
  1472. * Cannot perform src colorkey and dest colorkey at the same time
  1473. */
  1474. lpUpdateOverlay->ddRVal = DDERR_NOCOLORKEYHW;
  1475. return (DDHAL_DRIVER_HANDLED);
  1476. }
  1477. lpUpdateOverlay->lpDDSrcSurface->dwReserved1 &= ~(OVERLAY_FLG_COLOR_KEY|OVERLAY_FLG_SRC_COLOR_KEY);
  1478. if (lpUpdateOverlay->dwFlags & (DDOVER_KEYDEST | DDOVER_KEYDESTOVERRIDE))
  1479. {
  1480. if (ppdev->pfnIsSufficientBandwidth(ppdev, wBitCount, &(lpUpdateOverlay->rSrc),
  1481. &(lpUpdateOverlay->rDest), OVERLAY_FLG_COLOR_KEY))
  1482. {
  1483. bCheckBandwidth = FALSE;
  1484. lpUpdateOverlay->lpDDSrcSurface->dwReserved1 |= OVERLAY_FLG_COLOR_KEY;
  1485. if (lpUpdateOverlay->dwFlags & DDOVER_KEYDEST)
  1486. {
  1487. ppdev->wColorKey = (WORD)
  1488. lpUpdateOverlay->lpDDDestSurface->ddckCKDestOverlay.dwColorSpaceLowValue;
  1489. ppdev->lpColorSurface = lpUpdateOverlay->lpDDDestSurface;
  1490. }
  1491. else
  1492. {
  1493. ppdev->wColorKey = (WORD)
  1494. lpUpdateOverlay->overlayFX.dckDestColorkey.dwColorSpaceLowValue;
  1495. }
  1496. }
  1497. else
  1498. {
  1499. lpUpdateOverlay->ddRVal = DDERR_NOCOLORKEYHW;
  1500. return (DDHAL_DRIVER_HANDLED);
  1501. }
  1502. }
  1503. else if (lpUpdateOverlay->dwFlags & (DDOVER_KEYSRC | DDOVER_KEYSRCOVERRIDE))
  1504. {
  1505. if (ppdev->pfnIsSufficientBandwidth(ppdev, wBitCount, &(lpUpdateOverlay->rSrc),
  1506. &(lpUpdateOverlay->rDest), OVERLAY_FLG_SRC_COLOR_KEY))
  1507. {
  1508. bCheckBandwidth = FALSE;
  1509. lpUpdateOverlay->lpDDSrcSurface->dwReserved1 |= OVERLAY_FLG_SRC_COLOR_KEY;
  1510. ppdev->lpSrcColorSurface = lpUpdateOverlay->lpDDSrcSurface;
  1511. if (lpUpdateOverlay->dwFlags & DDOVER_KEYSRC)
  1512. {
  1513. ppdev->dwSrcColorKeyLow =
  1514. lpUpdateOverlay->lpDDSrcSurface->ddckCKSrcOverlay.dwColorSpaceLowValue;
  1515. ppdev->dwSrcColorKeyHigh =
  1516. lpUpdateOverlay->lpDDSrcSurface->ddckCKSrcOverlay.dwColorSpaceHighValue;
  1517. }
  1518. else
  1519. {
  1520. ppdev->dwSrcColorKeyLow =
  1521. lpUpdateOverlay->overlayFX.dckSrcColorkey.dwColorSpaceLowValue;
  1522. ppdev->dwSrcColorKeyHigh =
  1523. lpUpdateOverlay->overlayFX.dckSrcColorkey.dwColorSpaceHighValue;
  1524. }
  1525. if (ppdev->dwSrcColorKeyHigh < ppdev->dwSrcColorKeyHigh)
  1526. {
  1527. ppdev->dwSrcColorKeyHigh = ppdev->dwSrcColorKeyLow;
  1528. }
  1529. }
  1530. else
  1531. {
  1532. DISPDBG((0, "Insufficient bandwidth for colorkeying"));
  1533. lpUpdateOverlay->ddRVal = DDERR_NOCOLORKEYHW;
  1534. return (DDHAL_DRIVER_HANDLED);
  1535. }
  1536. }
  1537. // 'Source' is the overlay surface, 'destination' is the surface to
  1538. // be overlayed:
  1539. lpSource = lpUpdateOverlay->lpDDSrcSurface->lpGbl;
  1540. if (lpUpdateOverlay->dwFlags & DDOVER_HIDE)
  1541. {
  1542. if (lpSource->fpVidMem == ppdev->fpVisibleOverlay)
  1543. {
  1544. /*
  1545. * Turn the video off
  1546. */
  1547. ppdev->pfnDisableOverlay(ppdev);
  1548. ppdev->pfnClearAltFIFOThreshold(ppdev);
  1549. /*
  1550. * If we are color keying, we will disable that now
  1551. */
  1552. if (dwOldStatus & OVERLAY_FLG_COLOR_KEY)
  1553. {
  1554. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x1a);
  1555. bTemp = CP_IN_BYTE(pjPorts, CRTC_DATA); // Clear CR1A[3:2]
  1556. CP_OUT_BYTE(pjPorts, CRTC_DATA, bTemp & ~0x0C);
  1557. }
  1558. ppdev->dwPanningFlag &= ~OVERLAY_OLAY_SHOW;
  1559. lpUpdateOverlay->lpDDSrcSurface->dwReserved1 &= ~OVERLAY_FLG_ENABLED;
  1560. ppdev->fpVisibleOverlay = 0;
  1561. }
  1562. lpUpdateOverlay->ddRVal = DD_OK;
  1563. return(DDHAL_DRIVER_HANDLED);
  1564. }
  1565. // Dereference 'lpDDDestSurface' only after checking for the DDOVER_HIDE
  1566. // case:
  1567. #if 0
  1568. /*
  1569. * Turn the video off first to protect side effect when moving.
  1570. * Later RegIniVideo will turn it on if needed.
  1571. */
  1572. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x3e);
  1573. bTemp = CP_IN_BYTE(pjPorts, CRTC_DATA);
  1574. CP_OUT_BYTE(pjPorts, CRTC_DATA, bTemp & ~0x01); // Clear CR3E[0]
  1575. #endif
  1576. lpDestination = lpUpdateOverlay->lpDDDestSurface->lpGbl;
  1577. if (lpSource->fpVidMem != ppdev->fpVisibleOverlay)
  1578. {
  1579. if (lpUpdateOverlay->dwFlags & DDOVER_SHOW)
  1580. {
  1581. if (ppdev->fpVisibleOverlay != 0)
  1582. {
  1583. // Some other overlay is already visible:
  1584. DISPDBG((0, "DdUpdateOverlay: An overlay is already visible"));
  1585. lpUpdateOverlay->ddRVal = DDERR_OUTOFCAPS;
  1586. return(DDHAL_DRIVER_HANDLED);
  1587. }
  1588. else
  1589. {
  1590. // We're going to make the overlay visible, so mark it as
  1591. // such:
  1592. ppdev->fpVisibleOverlay = lpSource->fpVidMem;
  1593. }
  1594. }
  1595. else
  1596. {
  1597. // The overlay isn't visible, and we haven't been asked to make
  1598. // it visible, so this call is trivially easy:
  1599. lpUpdateOverlay->ddRVal = DD_OK;
  1600. return(DDHAL_DRIVER_HANDLED);
  1601. }
  1602. }
  1603. /*
  1604. * Is there sufficient bandwidth to work?
  1605. */
  1606. if (bCheckBandwidth && !ppdev->pfnIsSufficientBandwidth(ppdev, wBitCount,
  1607. &(lpUpdateOverlay->rSrc), &(lpUpdateOverlay->rDest), 0))
  1608. {
  1609. lpUpdateOverlay->ddRVal = DDERR_OUTOFCAPS;
  1610. return (DDHAL_DRIVER_HANDLED);
  1611. }
  1612. /*
  1613. * Save the rectangles
  1614. */
  1615. ppdev->rOverlaySrc = lpUpdateOverlay->rSrc;
  1616. ppdev->rOverlayDest = lpUpdateOverlay->rDest;
  1617. if (lpUpdateOverlay->lpDDSrcSurface->dwReserved1 & OVERLAY_FLG_DECIMATE)
  1618. {
  1619. ppdev->rOverlaySrc.right = ppdev->rOverlaySrc.left +
  1620. ((ppdev->rOverlaySrc.right - ppdev->rOverlaySrc.left) >> 1);
  1621. }
  1622. if (ppdev->rOverlaySrc.right - ppdev->rOverlaySrc.left <= MIN_OLAY_WIDTH)
  1623. {
  1624. lpUpdateOverlay->ddRVal = DDERR_OUTOFCAPS;
  1625. return (DDHAL_DRIVER_HANDLED);
  1626. }
  1627. lpUpdateOverlay->lpDDSrcSurface->dwReserved1 |= OVERLAY_FLG_ENABLED;
  1628. //
  1629. // Assign 5c to 1F when video is on while no color key for 5446BE.
  1630. //
  1631. // sge04
  1632. //if (bCheckBandwidth && ppdev->flCaps & CAPS_SECOND_APERTURE)
  1633. if (ppdev->flCaps & CAPS_SECOND_APERTURE)
  1634. ppdev->lFifoThresh = 0x0E;
  1635. ppdev->pfnRegInitVideo(ppdev, lpUpdateOverlay->lpDDSrcSurface);
  1636. lpUpdateOverlay->ddRVal = DD_OK;
  1637. return(DDHAL_DRIVER_HANDLED);
  1638. }
  1639. /******************************Public*Routine******************************\
  1640. * DWORD DdSetOverlayPosition
  1641. *
  1642. \**************************************************************************/
  1643. DWORD DdSetOverlayPosition(
  1644. PDD_SETOVERLAYPOSITIONDATA lpSetOverlayPosition)
  1645. {
  1646. PDEV* ppdev;
  1647. BYTE* pjPorts;
  1648. BYTE* pjBase;
  1649. ppdev = (PDEV*) lpSetOverlayPosition->lpDD->dhpdev;
  1650. pjPorts = ppdev->pjPorts;
  1651. pjBase = ppdev->pjBase;
  1652. DISPDBG((2, "DdSetOverlayPosition Entered"));
  1653. ASSERTDD(ppdev->flStatus & STAT_STREAMS_ENABLED, "Shouldn't have hooked call");
  1654. if(lpSetOverlayPosition->lpDDSrcSurface->lpGbl->fpVidMem == ppdev->fpVisibleOverlay)
  1655. {
  1656. /*
  1657. * Update the rectangles
  1658. */
  1659. ppdev->rOverlayDest.right = (ppdev->rOverlayDest.right - ppdev->rOverlayDest.left)
  1660. + lpSetOverlayPosition->lXPos;
  1661. ppdev->rOverlayDest.left = lpSetOverlayPosition->lXPos;
  1662. ppdev->rOverlayDest.bottom = (ppdev->rOverlayDest.bottom - ppdev->rOverlayDest.top)
  1663. + lpSetOverlayPosition->lYPos;
  1664. ppdev->rOverlayDest.top = lpSetOverlayPosition->lYPos;
  1665. //myf29 RegMoveVideo(ppdev, lpSetOverlayPosition->lpDDSrcSurface);
  1666. ppdev->pfnRegMoveVideo(ppdev, lpSetOverlayPosition->lpDDSrcSurface);
  1667. }
  1668. lpSetOverlayPosition->ddRVal = DD_OK;
  1669. return(DDHAL_DRIVER_HANDLED);
  1670. }
  1671. /******************************************************************************\
  1672. *
  1673. * Function: DrvGetDirectDrawInfo
  1674. *
  1675. * This function returns te capabilities of the DirectDraw implementation. It is
  1676. * called twice during the connect phase.
  1677. *
  1678. * Parameters: dhpdev Handle to physical device.
  1679. * pHalInfo Pointer to a DD_HALINFO structure.
  1680. * pdwNumHeaps Pointer to a variable that holds the number of
  1681. * heaps.
  1682. * pvmList Pointer to the heap array.
  1683. * pdwNumFourCC Pointer to a variable that holds the number of
  1684. * FourCC IDs.
  1685. * pdwFourCC Pointer to FourCC IDs.
  1686. *
  1687. * Returns: TRUE if successful.
  1688. *
  1689. \******************************************************************************/
  1690. BOOL DrvGetDirectDrawInfo(
  1691. DHPDEV dhpdev,
  1692. DD_HALINFO* pHalInfo,
  1693. DWORD* pdwNumHeaps,
  1694. VIDEOMEMORY* pvmList,
  1695. DWORD* pdwNumFourCC,
  1696. DWORD* pdwFourCC)
  1697. {
  1698. BOOL bCanFlip;
  1699. PDEV* ppdev = (PPDEV) dhpdev;
  1700. LONGLONG li;
  1701. OH* poh;
  1702. RECTL rSrc, rDest;
  1703. LONG lZoom;
  1704. BYTE* pjPorts = ppdev->pjPorts;
  1705. BYTE bTemp;
  1706. // We may not support DirectDraw on this card.
  1707. if (!(ppdev->flStatus & STAT_DIRECTDRAW))
  1708. {
  1709. return(FALSE);
  1710. }
  1711. DISPDBG((2, "DrvGetDirectDrawInfo Entered"));
  1712. pHalInfo->dwSize = sizeof(DD_HALINFO);
  1713. // Current primary surface attributes. Since HalInfo is zero-initialized by
  1714. // GDI, we only have to fill in the fields which should be non-zero.
  1715. pHalInfo->vmiData.pvPrimary = ppdev->pjScreen;
  1716. pHalInfo->vmiData.dwDisplayWidth = ppdev->cxScreen;
  1717. pHalInfo->vmiData.dwDisplayHeight = ppdev->cyScreen;
  1718. pHalInfo->vmiData.lDisplayPitch = ppdev->lDelta;
  1719. pHalInfo->vmiData.dwOffscreenAlign = 4;
  1720. pHalInfo->vmiData.ddpfDisplay.dwSize = sizeof(DDPIXELFORMAT);
  1721. pHalInfo->vmiData.ddpfDisplay.dwFlags = DDPF_RGB;
  1722. pHalInfo->vmiData.ddpfDisplay.dwRGBBitCount = ppdev->cBitsPerPixel;
  1723. if (ppdev->cBpp == 1)
  1724. {
  1725. pHalInfo->vmiData.ddpfDisplay.dwFlags |= DDPF_PALETTEINDEXED8;
  1726. }
  1727. // These masks will be zero at 8bpp.
  1728. pHalInfo->vmiData.ddpfDisplay.dwRBitMask = ppdev->flRed;
  1729. pHalInfo->vmiData.ddpfDisplay.dwGBitMask = ppdev->flGreen;
  1730. pHalInfo->vmiData.ddpfDisplay.dwBBitMask = ppdev->flBlue;
  1731. if (ppdev->cBpp == 4)
  1732. {
  1733. pHalInfo->vmiData.ddpfDisplay.dwRGBAlphaBitMask =
  1734. ~(ppdev->flRed | ppdev->flGreen | ppdev->flBlue);
  1735. }
  1736. // Set up the pointer to the first available video memory after the primary
  1737. // surface.
  1738. bCanFlip = FALSE;
  1739. *pdwNumHeaps = 0;
  1740. // Free up as much off-screen memory as possible.
  1741. bMoveAllDfbsFromOffscreenToDibs(ppdev); // Move all DFBs to DIB.s
  1742. vAssertModeText(ppdev, FALSE); // Destroy all cached fonts.
  1743. if ((ppdev->ulChipID == CL7555_ID) || (ppdev->ulChipID == CL7556_ID))//myf32
  1744. {
  1745. MIN_OLAY_WIDTH = 16;
  1746. #if (_WIN32_WINNT >= 0x0400)
  1747. ppdev->flCaps |= CAPS_VIDEO;
  1748. #endif
  1749. ppdev->pfnIsSufficientBandwidth=Is7555SufficientBandwidth;
  1750. ppdev->pfnRegInitVideo=RegInit7555Video;
  1751. ppdev->pfnRegMoveVideo=RegMove7555Video;
  1752. ppdev->pfnDisableOverlay=DisableVideoWindow;
  1753. ppdev->pfnClearAltFIFOThreshold=ClearAltFIFOThreshold;
  1754. }
  1755. else
  1756. {
  1757. ppdev->pfnIsSufficientBandwidth =
  1758. (ppdev->ulChipID != 0xBC) ?
  1759. IsSufficientBandwidth : Is5480SufficientBandwidth ; // chu03
  1760. ppdev->pfnRegInitVideo=RegInitVideo;
  1761. ppdev->pfnRegMoveVideo=RegMoveVideo;
  1762. ppdev->pfnDisableOverlay=DisableOverlay_544x;
  1763. ppdev->pfnClearAltFIFOThreshold=ClearAltFIFOThreshold_544x;
  1764. }
  1765. // Now simply reserve the biggest chunk for use by DirectDraw.
  1766. poh = ppdev->pohDirectDraw;
  1767. #if (DIRECTX_24 < 2)
  1768. if ((poh == NULL) && (ppdev->cBpp != 3))
  1769. #else
  1770. if (poh == NULL)
  1771. #endif
  1772. {
  1773. LONG cxMax, cyMax;
  1774. cxMax = ppdev->heap.cxMax & ~(HEAP_X_ALIGNMENT - 1);
  1775. cyMax = ppdev->heap.cyMax;
  1776. poh = pohAllocatePermanent(ppdev, cxMax, cyMax);
  1777. if (poh == NULL)
  1778. {
  1779. // Could not allocate all memory, find the biggest area now.
  1780. cxMax = cyMax = 0;
  1781. for (poh = ppdev->heap.ohAvailable.pohNext;
  1782. poh != &ppdev->heap.ohAvailable; poh = poh->pohNext)
  1783. {
  1784. if ((poh->cx * poh->cy) > (cxMax * cyMax))
  1785. {
  1786. cxMax = poh->cx & ~(HEAP_X_ALIGNMENT - 1);
  1787. cyMax = poh->cy;
  1788. }
  1789. }
  1790. poh = pohAllocatePermanent(ppdev, cxMax, cyMax);
  1791. }
  1792. ppdev->pohDirectDraw = poh;
  1793. }
  1794. if (poh != NULL)
  1795. {
  1796. *pdwNumHeaps = 1;
  1797. // Fill in the list of off-screen rectangles if we've been asked to do
  1798. // so.
  1799. if (pvmList != NULL)
  1800. {
  1801. DISPDBG((1, "DirectDraw gets %d x %d surface at (%d, %d)",
  1802. poh->cx, poh->cy, poh->x, poh->y));
  1803. #if 0
  1804. if (PELS_TO_BYTES(poh->cx) != ppdev->lDelta)
  1805. {
  1806. #endif
  1807. pvmList->dwFlags = VIDMEM_ISRECTANGULAR;
  1808. pvmList->fpStart = poh->xy;
  1809. pvmList->dwWidth = PELS_TO_BYTES(poh->cx);
  1810. pvmList->dwHeight = poh->cy;
  1811. #if 0
  1812. }
  1813. else
  1814. {
  1815. pvmList->dwFlags = VIDMEM_ISLINEAR;
  1816. pvmList->fpStart = poh->xy;
  1817. pvmList->fpEnd = poh->xy - 1
  1818. + PELS_TO_BYTES(poh->cx)
  1819. + poh->cy * ppdev->lDelta;
  1820. }
  1821. #endif
  1822. pvmList->ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  1823. if ((poh->cx >= ppdev->cxScreen) && (poh->cy >= ppdev->cyScreen))
  1824. {
  1825. bCanFlip = TRUE;
  1826. }
  1827. }
  1828. }
  1829. // Capabilities supported.
  1830. pHalInfo->ddCaps.dwFXCaps = 0;
  1831. pHalInfo->ddCaps.dwCaps = DDCAPS_BLT
  1832. | DDCAPS_BLTCOLORFILL
  1833. | DDCAPS_READSCANLINE; // sge08 add this bit
  1834. pHalInfo->ddCaps.dwCaps2 = DDCAPS2_COPYFOURCC;
  1835. if ( (ppdev->flCaps & CAPS_VIDEO) && (ppdev->cBpp <= 2) )
  1836. {
  1837. pHalInfo->ddCaps.dwCaps |= DDCAPS_COLORKEY;
  1838. pHalInfo->ddCaps.dwCKeyCaps = DDCKEYCAPS_SRCBLT;
  1839. }
  1840. pHalInfo->ddCaps.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN
  1841. | DDSCAPS_PRIMARYSURFACE;
  1842. if (bCanFlip)
  1843. {
  1844. pHalInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_FLIP;
  1845. }
  1846. // FourCCs supported.
  1847. *pdwNumFourCC = 0;
  1848. #if 0 // smac - disable overlays due to too many bugs
  1849. {
  1850. //
  1851. // Interlaced mode ?
  1852. //
  1853. BOOL Interlaced ; // chu02
  1854. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x1a) ;
  1855. Interlaced = CP_IN_BYTE(pjPorts, CRTC_DATA) & 0x01 ;
  1856. //
  1857. // Needs check more later
  1858. //
  1859. if ((ppdev->flCaps & CAPS_VIDEO) && (!Interlaced)) // chu02
  1860. ppdev->flStatus |= STAT_STREAMS_ENABLED;
  1861. if (ppdev->flStatus & STAT_STREAMS_ENABLED)
  1862. {
  1863. /*
  1864. * Are we double clocked?
  1865. */
  1866. ppdev->bDoubleClock = FALSE;
  1867. //
  1868. // use SR7 to check the double clock instead of hidden register
  1869. //
  1870. //
  1871. CP_OUT_BYTE(pjPorts, SR_INDEX, 0x7);
  1872. bTemp = CP_IN_BYTE(pjPorts, SR_DATA);
  1873. if ((((bTemp & 0x0E) == 0x06) && ppdev->cBitsPerPixel == 8) ||
  1874. (((bTemp & 0x0E) == 0x08) && ppdev->cBitsPerPixel == 16))
  1875. {
  1876. ppdev->bDoubleClock = TRUE;
  1877. }
  1878. pHalInfo->vmiData.dwOverlayAlign = 8;
  1879. pHalInfo->ddCaps.dwCaps |= DDCAPS_OVERLAY
  1880. | DDCAPS_OVERLAYSTRETCH
  1881. | DDCAPS_OVERLAYFOURCC
  1882. | DDCAPS_OVERLAYCANTCLIP
  1883. | DDCAPS_ALIGNSTRIDE;
  1884. pHalInfo->ddCaps.dwFXCaps |= DDFXCAPS_OVERLAYSTRETCHX
  1885. | DDFXCAPS_OVERLAYSTRETCHY
  1886. | DDFXCAPS_OVERLAYARITHSTRETCHY;
  1887. pHalInfo->ddCaps.dwCKeyCaps |= DDCKEYCAPS_DESTOVERLAY
  1888. | DDCKEYCAPS_DESTOVERLAYYUV
  1889. | DDCKEYCAPS_DESTOVERLAYONEACTIVE;
  1890. pHalInfo->ddCaps.dwCKeyCaps |= DDCKEYCAPS_SRCOVERLAY
  1891. | DDCKEYCAPS_SRCOVERLAYCLRSPACE
  1892. | DDCKEYCAPS_SRCOVERLAYCLRSPACEYUV
  1893. | DDCKEYCAPS_SRCOVERLAYONEACTIVE
  1894. | DDCKEYCAPS_SRCOVERLAYYUV;
  1895. pHalInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_OVERLAY;
  1896. *pdwNumFourCC = 3;
  1897. if ((ppdev->ulChipID == 0x40) || (ppdev->ulChipID == 0x4C)) //tao1
  1898. *pdwNumFourCC = 2; //tao1
  1899. if (pdwFourCC)
  1900. {
  1901. pdwFourCC[0] = FOURCC_YUV422;
  1902. pdwFourCC[1] = FOURCC_PACKJR;
  1903. if ((ppdev->ulChipID != 0x40) && (ppdev->ulChipID != 0x4C)) //tao1
  1904. pdwFourCC[2] = FOURCC_YUY2; //tao1
  1905. }
  1906. pHalInfo->ddCaps.dwMaxVisibleOverlays = 1;
  1907. pHalInfo->ddCaps.dwCurrVisibleOverlays = 0;
  1908. pHalInfo->ddCaps.dwNumFourCCCodes = 2;
  1909. # if 1
  1910. pHalInfo->ddCaps.dwAlignBoundarySrc = 1;
  1911. pHalInfo->ddCaps.dwAlignSizeSrc = 1;
  1912. // chu01 sge05
  1913. #if 1
  1914. if ((ppdev->cBpp == 3) || ppdev->bDoubleClock )
  1915. {
  1916. pHalInfo->ddCaps.dwAlignBoundaryDest = 4;
  1917. pHalInfo->ddCaps.dwAlignSizeDest = 4;
  1918. }
  1919. else
  1920. {
  1921. pHalInfo->ddCaps.dwAlignBoundaryDest = 1;
  1922. pHalInfo->ddCaps.dwAlignSizeDest = 1;
  1923. }
  1924. #else
  1925. pHalInfo->ddCaps.dwAlignBoundaryDest = 1;
  1926. pHalInfo->ddCaps.dwAlignSizeDest = 1;
  1927. #endif // 1
  1928. pHalInfo->ddCaps.dwAlignStrideAlign = 8;
  1929. pHalInfo->ddCaps.dwMinOverlayStretch = 8000;
  1930. pHalInfo->ddCaps.dwMinLiveVideoStretch = 8000;
  1931. pHalInfo->ddCaps.dwMinHwCodecStretch = 8000;
  1932. pHalInfo->ddCaps.dwMaxOverlayStretch = 8000;
  1933. pHalInfo->ddCaps.dwMaxLiveVideoStretch = 8000;
  1934. pHalInfo->ddCaps.dwMaxHwCodecStretch = 8000;
  1935. //
  1936. // maybe there are special requirement for VCLK > 85Hz
  1937. //
  1938. #endif
  1939. rSrc.left = rSrc.top = 0;
  1940. rSrc.right = 320;
  1941. rSrc.bottom = 240;
  1942. rDest.left = rDest.top = 0;
  1943. rDest.right = 1280;
  1944. rDest.bottom = 960;
  1945. lZoom = 1000;
  1946. do
  1947. {
  1948. rDest.right = (320 * lZoom)/ 1000;
  1949. rDest.bottom = (240 * lZoom)/1000;
  1950. if (ppdev->pfnIsSufficientBandwidth(ppdev, 16, (LPRECTL) &rSrc, (LPRECTL) &rDest, 0))
  1951. {
  1952. DISPDBG((1, "Minimum zoom factor: %d", lZoom));
  1953. pHalInfo->ddCaps.dwMinOverlayStretch = lZoom;
  1954. pHalInfo->ddCaps.dwMinLiveVideoStretch = lZoom;
  1955. pHalInfo->ddCaps.dwMinHwCodecStretch = lZoom;
  1956. lZoom = 4000;
  1957. }
  1958. lZoom += 100;
  1959. } while (lZoom < 4000);
  1960. }
  1961. }
  1962. #endif // smac
  1963. return(TRUE);
  1964. }
  1965. /******************************************************************************\
  1966. *
  1967. * Function: DrvEnableDirectDraw
  1968. *
  1969. * Enable DirectDraw. This function is called when an application opens a
  1970. * DirectDraw connection.
  1971. *
  1972. * Parameters: dhpdev Handle to physical device.
  1973. * pCallBacks Pointer to DirectDraw callbacks.
  1974. * pSurfaceCallBacks Pointer to surface callbacks.
  1975. * pPaletteCallBacks Pointer to palette callbacks.
  1976. *
  1977. * Returns: TRUE if successful.
  1978. *
  1979. \******************************************************************************/
  1980. BOOL DrvEnableDirectDraw(
  1981. DHPDEV dhpdev,
  1982. DD_CALLBACKS* pCallBacks,
  1983. DD_SURFACECALLBACKS* pSurfaceCallBacks,
  1984. DD_PALETTECALLBACKS* pPaletteCallBacks)
  1985. {
  1986. PDEV* ppdev = (PPDEV) dhpdev;
  1987. pCallBacks->WaitForVerticalBlank = DdWaitForVerticalBlank;
  1988. pCallBacks->MapMemory = DdMapMemory;
  1989. pCallBacks->GetScanLine = DdGetScanLine;
  1990. pCallBacks->dwFlags = DDHAL_CB32_WAITFORVERTICALBLANK
  1991. | DDHAL_CB32_MAPMEMORY
  1992. | DDHAL_CB32_GETSCANLINE;
  1993. pSurfaceCallBacks->Blt = DdBlt;
  1994. pSurfaceCallBacks->Flip = DdFlip;
  1995. pSurfaceCallBacks->Lock = DdLock;
  1996. pSurfaceCallBacks->GetBltStatus = DdGetBltStatus;
  1997. pSurfaceCallBacks->GetFlipStatus = DdGetFlipStatus;
  1998. pSurfaceCallBacks->dwFlags = DDHAL_SURFCB32_BLT
  1999. | DDHAL_SURFCB32_FLIP
  2000. | DDHAL_SURFCB32_LOCK
  2001. | DDHAL_SURFCB32_GETBLTSTATUS
  2002. | DDHAL_SURFCB32_GETFLIPSTATUS;
  2003. if (ppdev->flStatus & STAT_STREAMS_ENABLED)
  2004. {
  2005. pCallBacks->CreateSurface = DdCreateSurface;
  2006. pCallBacks->CanCreateSurface = DdCanCreateSurface;
  2007. pCallBacks->dwFlags |= DDHAL_CB32_CREATESURFACE
  2008. | DDHAL_CB32_CANCREATESURFACE;
  2009. pSurfaceCallBacks->SetColorKey = DdSetColorKey;
  2010. pSurfaceCallBacks->UpdateOverlay = DdUpdateOverlay;
  2011. pSurfaceCallBacks->SetOverlayPosition = DdSetOverlayPosition;
  2012. pSurfaceCallBacks->DestroySurface = DdDestroySurface;
  2013. pSurfaceCallBacks->dwFlags |= DDHAL_SURFCB32_SETCOLORKEY
  2014. | DDHAL_SURFCB32_UPDATEOVERLAY
  2015. | DDHAL_SURFCB32_SETOVERLAYPOSITION
  2016. | DDHAL_SURFCB32_DESTROYSURFACE;
  2017. // The DrvEnableDirectDraw call can occur while we're in full-
  2018. // screen DOS mode. Do not turn on the streams processor now
  2019. // if that's the case, instead wait until AssertMode switches
  2020. // us back to graphics mode:
  2021. }
  2022. // Note that we don't call 'vGetDisplayDuration' here, for a couple of
  2023. // reasons:
  2024. //
  2025. // o Because the system is already running, it would be disconcerting
  2026. // to pause the graphics for a good portion of a second just to read
  2027. // the refresh rate;
  2028. // o More importantly, we may not be in graphics mode right now.
  2029. //
  2030. // For both reasons, we always measure the refresh rate when we switch
  2031. // to a new mode.
  2032. return(TRUE);
  2033. }
  2034. /******************************************************************************\
  2035. *
  2036. * Function: DrvDisableDirectDraw
  2037. *
  2038. * Disable DirectDraw. This function is called when an application closes the
  2039. * DirectDraw connection.
  2040. *
  2041. * Parameters: dhpdev Handle to physical device.
  2042. *
  2043. * Returns: Nothing.
  2044. *
  2045. \******************************************************************************/
  2046. VOID DrvDisableDirectDraw(
  2047. DHPDEV dhpdev)
  2048. {
  2049. PDEV* ppdev;
  2050. OH* poh;
  2051. // DirectDraw is done with the display, so we can go back to using
  2052. // all of off-screen memory ourselves.
  2053. ppdev = (PPDEV) dhpdev;
  2054. poh = ppdev->pohDirectDraw;
  2055. if (poh)
  2056. {
  2057. DISPDBG((1, "Releasing DirectDraw surface %d x %d at (%d, %d)",
  2058. poh->cx, poh->cy, poh->x, poh->y));
  2059. }
  2060. pohFree(ppdev, poh);
  2061. ppdev->pohDirectDraw = NULL;
  2062. // Invalidate all cached fonts.
  2063. vAssertModeText(ppdev, TRUE);
  2064. }
  2065. /******************************************************************************\
  2066. *
  2067. * Function: vAssertModeDirectDraw
  2068. *
  2069. * Perform specific DirectDraw initialization when the screen switches focus
  2070. * (from graphics to full screen MS-DOS and vice versa).
  2071. *
  2072. * Parameters: ppdev Pointer to physical device.
  2073. * bEnabled True if the screen is in graphics mode.
  2074. *
  2075. * Returns: Nothing.
  2076. *
  2077. \******************************************************************************/
  2078. VOID vAssertModeDirectDraw(
  2079. PDEV* ppdev,
  2080. BOOL bEnabled)
  2081. {
  2082. }
  2083. /******************************************************************************\
  2084. *
  2085. * Function: bEnableDirectDraw
  2086. *
  2087. * Enable DirectDraw. Called from DrvEnableSurface.
  2088. *
  2089. * Parameters: ppdev Pointer to phsyical device.
  2090. *
  2091. * Returns: Nothing.
  2092. *
  2093. \******************************************************************************/
  2094. BOOL bEnableDirectDraw(
  2095. PDEV* ppdev)
  2096. {
  2097. if (DIRECT_ACCESS(ppdev) && // Direct access must be enabled.
  2098. #if (DIRECTX_24 < 1)
  2099. (ppdev->cBpp != 3) && // Turn off DirectDraw in 24-bpp.
  2100. #endif
  2101. (ppdev->flCaps & CAPS_ENGINEMANAGED) && // Only support CL-GD5436/5446.
  2102. (ppdev->flCaps & CAPS_MM_IO)) // Memory Mapped I/O must be on.
  2103. {
  2104. // We have to preserve the contents of the CR1B and CR1D registers on a
  2105. // page flip.
  2106. CP_OUT_BYTE(ppdev->pjPorts, CRTC_INDEX, 0x1B);
  2107. ppdev->ulCR1B = (CP_IN_BYTE(ppdev->pjPorts, CRTC_DATA) & 0xF2) << 8;
  2108. CP_OUT_BYTE(ppdev->pjPorts, CRTC_INDEX, 0x1D);
  2109. ppdev->ulCR1D = (CP_IN_BYTE(ppdev->pjPorts, CRTC_DATA) & 0x7F) << 8;
  2110. // Accurately measure the refresh rate for later.
  2111. vGetDisplayDuration(ppdev);
  2112. // DirectDraw is all set to be used on this card.
  2113. ppdev->flStatus |= STAT_DIRECTDRAW;
  2114. #if 1 // sge
  2115. EnableStartAddrDoubleBuffer(ppdev);
  2116. #endif // sge
  2117. }
  2118. return(TRUE);
  2119. }
  2120. /******************************************************************************\
  2121. *
  2122. * Function: vDisableDirectDraw
  2123. *
  2124. * Disbale DirectDraw. Called from DrvDisableSurface.
  2125. *
  2126. * Parameters: ppdev Pointer to physical device.
  2127. *
  2128. * Returns: Nothing.
  2129. *
  2130. \******************************************************************************/
  2131. VOID vDisableDirectDraw(
  2132. PDEV* ppdev)
  2133. {
  2134. }
  2135. #if 1 // OVERLAY #sge
  2136. /******************************************************************************\
  2137. *
  2138. * Function: GetFormatInfo
  2139. *
  2140. * Get DirectDraw information,
  2141. *
  2142. * Parameters: ppdev Pointer to physical device.
  2143. *
  2144. * Returns: Nothing.
  2145. *
  2146. \******************************************************************************/
  2147. VOID GetFormatInfo(PDEV* ppdev, LPDDPIXELFORMAT lpFormat, LPDWORD lpFourcc,
  2148. LPWORD lpBitCount)
  2149. {
  2150. if (lpFormat->dwFlags & DDPF_FOURCC)
  2151. {
  2152. *lpFourcc = lpFormat->dwFourCC;
  2153. if (lpFormat->dwFourCC == BI_RGB)
  2154. {
  2155. *lpBitCount = (WORD) lpFormat->dwRGBBitCount;
  2156. #ifdef DEBUG
  2157. if (lpFormat->dwRGBBitCount == 8)
  2158. {
  2159. DISPDBG((1, "Format: RGB 8"));
  2160. }
  2161. else if (lpFormat->dwRGBBitCount == 16)
  2162. {
  2163. DISPDBG ((1,"Format: RGB 5:5:5"));
  2164. }
  2165. #endif
  2166. }
  2167. else if (lpFormat->dwFourCC == BI_BITFIELDS)
  2168. {
  2169. if ((lpFormat->dwRGBBitCount != 16) ||
  2170. (lpFormat->dwRBitMask != 0xf800) ||
  2171. (lpFormat->dwGBitMask != 0x07e0) ||
  2172. (lpFormat->dwBBitMask != 0x001f))
  2173. {
  2174. *lpFourcc = (DWORD) -1;
  2175. }
  2176. else
  2177. {
  2178. *lpBitCount = 16;
  2179. DISPDBG((1,"Format: RGB 5:6:5"));
  2180. }
  2181. }
  2182. else
  2183. {
  2184. lpFormat->dwRBitMask = (DWORD) -1;
  2185. lpFormat->dwGBitMask = (DWORD) -1;
  2186. lpFormat->dwBBitMask = (DWORD) -1;
  2187. if (lpFormat->dwFourCC == FOURCC_PACKJR)
  2188. {
  2189. *lpBitCount = 8;
  2190. DISPDBG((1, "Format: CLJR"));
  2191. }
  2192. else if (lpFormat->dwFourCC == FOURCC_YUY2)
  2193. {
  2194. *lpBitCount = 16;
  2195. DISPDBG((1,"Format: YUY2"));
  2196. }
  2197. else
  2198. {
  2199. *lpBitCount = 16;
  2200. DISPDBG((1,"Format: UYVY"));
  2201. }
  2202. }
  2203. }
  2204. else if (lpFormat->dwFlags & DDPF_RGB)
  2205. {
  2206. if (lpFormat->dwRGBBitCount == 8)
  2207. {
  2208. *lpFourcc = BI_RGB;
  2209. DISPDBG((1, "Format: RGB 8"));
  2210. }
  2211. else if ((lpFormat->dwRGBBitCount == 16) &&
  2212. (lpFormat->dwRBitMask == 0xf800) &&
  2213. (lpFormat->dwGBitMask == 0x07e0) &&
  2214. (lpFormat->dwBBitMask == 0x001f))
  2215. {
  2216. *lpFourcc = BI_BITFIELDS;
  2217. DISPDBG((1,"Format: RGB 5:6:5"));
  2218. }
  2219. else if ((lpFormat->dwRGBBitCount == 16) &&
  2220. (lpFormat->dwRBitMask == 0x7C00) &&
  2221. (lpFormat->dwGBitMask == 0x03e0) &&
  2222. (lpFormat->dwBBitMask == 0x001f))
  2223. {
  2224. *lpFourcc = BI_RGB;
  2225. DISPDBG((1,"Format: RGB 5:5:5"));
  2226. }
  2227. else if (((lpFormat->dwRGBBitCount == 24) ||
  2228. (lpFormat->dwRGBBitCount == 32)) &&
  2229. (lpFormat->dwRBitMask == 0xff0000) &&
  2230. (lpFormat->dwGBitMask == 0x00ff00) &&
  2231. (lpFormat->dwBBitMask == 0x0000ff))
  2232. {
  2233. *lpFourcc = BI_RGB;
  2234. DISPDBG((1, "Format: RGB 8:8:8"));
  2235. }
  2236. else
  2237. {
  2238. *lpFourcc = (DWORD) -1;
  2239. }
  2240. *lpBitCount = (WORD) lpFormat->dwRGBBitCount;
  2241. }
  2242. else if (ppdev->cBitsPerPixel == 16)
  2243. {
  2244. *lpFourcc = BI_RGB;
  2245. *lpBitCount = (WORD) lpFormat->dwRGBBitCount;
  2246. }
  2247. else
  2248. {
  2249. *lpFourcc = (DWORD) -1;
  2250. }
  2251. }
  2252. /**********************************************************
  2253. *
  2254. * Name: RegInitVideo
  2255. *
  2256. * Module Abstract:
  2257. * ----------------
  2258. * This function is called to program the video format and
  2259. * the physicall offset of the video data in the frame buffer.
  2260. *
  2261. * Output Parameters:
  2262. * ------------------
  2263. * none
  2264. *
  2265. ***********************************************************
  2266. * Author: Shuhua Ge
  2267. * Date: 09/24/96
  2268. *
  2269. * Revision History:
  2270. * -----------------
  2271. * WHO WHEN WHAT/WHY/HOW
  2272. * --- ---- ------------
  2273. *
  2274. *********************************************************/
  2275. VOID RegInitVideo(PDEV* ppdev, PDD_SURFACE_LOCAL lpSurface)
  2276. {
  2277. DWORD dwTemp;
  2278. DWORD dwFourcc;
  2279. LONG lPitch;
  2280. LONG lLeft;
  2281. WORD wTemp;
  2282. WORD wBitCount = 0;
  2283. RECTL rVideoRect;
  2284. BYTE bRegCR31;
  2285. BYTE bRegCR32;
  2286. BYTE bRegCR33;
  2287. BYTE bRegCR34;
  2288. BYTE bRegCR35;
  2289. BYTE bRegCR36;
  2290. BYTE bRegCR37;
  2291. BYTE bRegCR38;
  2292. BYTE bRegCR39;
  2293. BYTE bRegCR3A;
  2294. BYTE bRegCR3B;
  2295. BYTE bRegCR3C;
  2296. BYTE bRegCR3D;
  2297. BYTE bRegCR3E;
  2298. BYTE bRegCR5C;
  2299. BYTE bRegCR5D;
  2300. BYTE bTemp;
  2301. DWORD dwTemp1;
  2302. BOOL bOverlayTooSmall = FALSE;
  2303. BYTE* pjPorts = ppdev->pjPorts;
  2304. /*
  2305. * Determine the format of the video data
  2306. */
  2307. if (lpSurface->dwFlags & DDRAWISURF_HASPIXELFORMAT)
  2308. {
  2309. GetFormatInfo(ppdev, &(lpSurface->lpGbl->ddpfSurface),
  2310. &dwFourcc, &wBitCount);
  2311. }
  2312. else
  2313. {
  2314. // This needs to be changed when primary surface is RGB 5:6:5
  2315. dwFourcc = BI_RGB;
  2316. wBitCount = (WORD) ppdev->cBitsPerPixel;
  2317. }
  2318. rVideoRect = ppdev->rOverlayDest;
  2319. lPitch = lpSurface->lpGbl->lPitch;
  2320. /*
  2321. * Determine value in CR31 (Horizontal Zoom Code)
  2322. */
  2323. if ((ppdev->rOverlayDest.right - ppdev->rOverlayDest.left) ==
  2324. (ppdev->rOverlaySrc.right - ppdev->rOverlaySrc.left))
  2325. {
  2326. /*
  2327. * No zooming is occuring
  2328. */
  2329. bRegCR31 = 0;
  2330. }
  2331. else
  2332. {
  2333. /*
  2334. * The zoom code = (256 * <src width>) / <dest width>
  2335. */
  2336. dwTemp = (DWORD) ((DWORD) (ppdev->rOverlaySrc.right
  2337. - ppdev->rOverlaySrc.left)) * 256;
  2338. if (ppdev->bDoubleClock)
  2339. {
  2340. dwTemp <<= 1;
  2341. }
  2342. dwTemp1= (DWORD) (ppdev->rOverlayDest.right - ppdev->rOverlayDest.left);
  2343. dwTemp= ((2 * dwTemp) + dwTemp1) / (2*dwTemp1);
  2344. bRegCR31= (BYTE) dwTemp;
  2345. }
  2346. /*
  2347. * Determine value in CR32 (Vertical Zoom Code)
  2348. */
  2349. if ((ppdev->rOverlayDest.bottom - ppdev->rOverlayDest.top) ==
  2350. (ppdev->rOverlaySrc.bottom - ppdev->rOverlaySrc.top))
  2351. {
  2352. /*
  2353. * No zooming is occuring
  2354. */
  2355. bRegCR32 = 0;
  2356. }
  2357. else
  2358. {
  2359. /*
  2360. * The zoom code = (256 * <src height>) / <dest height>
  2361. * The -1 is so that it won't mangle the last line by mixing it
  2362. * with garbage data while Y interpolating.
  2363. */
  2364. dwTemp = (DWORD) ((DWORD) ((ppdev->rOverlaySrc.bottom - 1)
  2365. - ppdev->rOverlaySrc.top)) * 256;
  2366. dwTemp /= (DWORD) (ppdev->rOverlayDest.bottom - ppdev->rOverlayDest.top);
  2367. bRegCR32 = (BYTE) dwTemp;
  2368. }
  2369. /*
  2370. * Determine value in CR33 (Region 1 Size)
  2371. */
  2372. wTemp = (WORD) rVideoRect.left;
  2373. if (ppdev->cBitsPerPixel == 8)
  2374. {
  2375. wTemp >>= 2; // 4 Pixels per DWORD
  2376. }
  2377. else if (ppdev->cBitsPerPixel == 16)
  2378. {
  2379. wTemp >>= 1; // 2 Pixels per DWORD
  2380. }
  2381. else if (ppdev->cBitsPerPixel == 24)
  2382. {
  2383. wTemp *= 3;
  2384. wTemp /= 4;
  2385. }
  2386. bRegCR33 = (BYTE) wTemp;
  2387. bRegCR36 = (BYTE) (WORD) (wTemp >> 8);
  2388. /*
  2389. * Determine value in CR34 (Region 2 size)
  2390. */
  2391. wTemp = (WORD) (rVideoRect.right - rVideoRect.left);
  2392. if (ppdev->cBitsPerPixel == 8)
  2393. {
  2394. wTemp >>= 2; // 4 Pixels per DWORD
  2395. }
  2396. else if (ppdev->cBitsPerPixel == 16)
  2397. {
  2398. wTemp >>= 1; // 2 Pixels per DWORD
  2399. }
  2400. else if (ppdev->cBitsPerPixel == 24)
  2401. {
  2402. wTemp *= 3;
  2403. wTemp /= 4;
  2404. }
  2405. bRegCR34 = (BYTE) wTemp;
  2406. wTemp >>= 6;
  2407. bRegCR36 |= (BYTE) (wTemp & 0x0C);
  2408. /*
  2409. * Determine value in CR35 (Region 2 SDSize)
  2410. */
  2411. dwTemp = (DWORD) (rVideoRect.right - rVideoRect.left);
  2412. dwTemp *= (DWORD) (ppdev->rOverlaySrc.right - ppdev->rOverlaySrc.left);
  2413. dwTemp /= (DWORD) (ppdev->rOverlayDest.right - ppdev->rOverlayDest.left);
  2414. wTemp = (WORD) dwTemp;
  2415. if ((dwFourcc == FOURCC_PACKJR) || (wBitCount == 8))
  2416. {
  2417. wTemp >>= 2; // 4 Pixels per DWORD
  2418. }
  2419. else
  2420. {
  2421. wTemp >>= 1; // 2 Pixels per DWORD
  2422. }
  2423. bRegCR35 = (BYTE) wTemp;
  2424. wTemp >>= 4;
  2425. bRegCR36 |= (BYTE) (wTemp & 0x30);
  2426. //
  2427. // Check double scan line counter feature
  2428. //
  2429. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x17);
  2430. bTemp = CP_IN_BYTE(pjPorts, CRTC_DATA);
  2431. if (bTemp & 0x04)
  2432. {
  2433. //
  2434. // Double scan line count
  2435. //
  2436. /*
  2437. * Determine value in CR37 (Vertical Start)
  2438. */
  2439. wTemp = (WORD) rVideoRect.top;
  2440. bRegCR37 = (BYTE)(wTemp >> 1);
  2441. if ( wTemp & 0x01 )
  2442. {
  2443. wTemp >>= 9;
  2444. bRegCR39 = (BYTE) wTemp | 0x10;
  2445. //
  2446. // Odd scan line trigger
  2447. // Hardware has a bug now.
  2448. // So reduce dest end by 1
  2449. //
  2450. wTemp = (WORD) rVideoRect.bottom - 1 - 1;
  2451. }
  2452. else
  2453. {
  2454. wTemp >>= 9;
  2455. bRegCR39 = (BYTE) wTemp;
  2456. /*
  2457. * Determine value in CR38 (Vertical End)
  2458. */
  2459. wTemp = (WORD) rVideoRect.bottom - 1;
  2460. }
  2461. bRegCR38 = (BYTE)(wTemp >> 1);
  2462. if (wTemp & 0x01)
  2463. bRegCR39 |= 0x20;
  2464. wTemp >>= 7;
  2465. bRegCR39 |= (BYTE) (wTemp & 0x0C);
  2466. }
  2467. else
  2468. {
  2469. /*
  2470. * Determine value in CR37 (Vertical Start)
  2471. */
  2472. wTemp = (WORD) rVideoRect.top;
  2473. bRegCR37 = (BYTE) wTemp;
  2474. wTemp >>= 8;
  2475. bRegCR39 = (BYTE) wTemp;
  2476. /*
  2477. * Determine value in CR38 (Vertical End)
  2478. */
  2479. wTemp = (WORD) rVideoRect.bottom - 1;
  2480. bRegCR38 = (BYTE) wTemp;
  2481. wTemp >>= 6;
  2482. bRegCR39 |= (BYTE) (wTemp & 0x0C);
  2483. }
  2484. /*
  2485. * Determine values in CR3A, CR3B, CR3C (Start Address)
  2486. */
  2487. dwTemp = 0;
  2488. if (bRegCR31 != 0)
  2489. {
  2490. //
  2491. // overlay is zoomed, re-initialize zoom factor
  2492. //
  2493. CalculateStretchCode(ppdev->rOverlaySrc.right - ppdev->rOverlaySrc.left,
  2494. ppdev->rOverlayDest.right - ppdev->rOverlayDest.left, ppdev->HorStretchCode);
  2495. }
  2496. //
  2497. // Here, we want to ensure the source rectangle's clipped width is bigger
  2498. // than what the HW can support, sigh!
  2499. //
  2500. if (!bOverlayTooSmall)
  2501. {
  2502. LONG lSrcPels;
  2503. //
  2504. // compute non-clip amount on right edge
  2505. //
  2506. lSrcPels = rVideoRect.right - rVideoRect.left;
  2507. if (bRegCR31 != 0) // source is zoomed if non-zero
  2508. {
  2509. WORD wRightCnt;
  2510. wRightCnt = 0;
  2511. while (lSrcPels > 0)
  2512. {
  2513. lSrcPels -= ppdev->HorStretchCode[wRightCnt];
  2514. if (lSrcPels >= 0)
  2515. {
  2516. wRightCnt++;
  2517. }
  2518. }
  2519. lSrcPels = (LONG)wRightCnt;
  2520. }
  2521. if ((lSrcPels == 0) || (lSrcPels <= MIN_OLAY_WIDTH))
  2522. {
  2523. bOverlayTooSmall = TRUE;
  2524. }
  2525. }
  2526. lLeft = ppdev->rOverlaySrc.left;
  2527. if (dwFourcc == FOURCC_PACKJR)
  2528. {
  2529. lLeft &= ~0x03;
  2530. }
  2531. else if (dwFourcc == FOURCC_YUV422 || dwFourcc == FOURCC_YUY2 )
  2532. {
  2533. lLeft &= ~0x01;
  2534. }
  2535. //
  2536. // dwTemp has adjusted dest. rect., add in source adjustment
  2537. //
  2538. dwTemp += (ppdev->rOverlaySrc.top * lPitch) + ((lLeft * wBitCount) >>3);
  2539. ppdev->sOverlay1.lAdjustSource = dwTemp;
  2540. // dwTemp += ((BYTE*)lpSurface->lpGbl->fpVidMem - ppdev->pjScreen); // sss
  2541. dwTemp += (DWORD)(lpSurface->lpGbl->fpVidMem);
  2542. bRegCR5D = (BYTE) ((dwTemp << 2) & 0x0C);
  2543. dwTemp >>= 2;
  2544. bRegCR3A = (BYTE) dwTemp & 0xfe; // Align to even byte (5446 bug)
  2545. dwTemp >>= 8;
  2546. bRegCR3B = (BYTE) dwTemp;
  2547. dwTemp >>= 8;
  2548. bRegCR3C = (BYTE) (dwTemp & 0x0f);
  2549. /*
  2550. * Determine value in CR3D (Address Offset/Pitch)
  2551. */
  2552. wTemp = (WORD) (lPitch >> 3);
  2553. if (lpSurface->dwReserved1 & OVERLAY_FLG_DECIMATE)
  2554. {
  2555. wTemp >>= 1;
  2556. }
  2557. bRegCR3D = (BYTE) wTemp;
  2558. wTemp >>= 3;
  2559. bRegCR3C |= (BYTE) (wTemp & 0x20);
  2560. /*
  2561. * Determine value in CR3E (Master Control Register)
  2562. */
  2563. bRegCR3E = 0;
  2564. if (lpSurface->dwReserved1 & OVERLAY_FLG_ENABLED)
  2565. {
  2566. bRegCR3E = 0x01;
  2567. }
  2568. if (dwFourcc == FOURCC_PACKJR)
  2569. {
  2570. bRegCR3E |= 0x20; // Always error difuse when using PackJR
  2571. }
  2572. if ((bRegCR32 == 0) || MustLineReplicate (ppdev, lpSurface, wBitCount))
  2573. {
  2574. bRegCR3E |= 0x10;
  2575. lpSurface->dwReserved1 &= ~OVERLAY_FLG_INTERPOLATE;
  2576. }
  2577. else
  2578. {
  2579. lpSurface->dwReserved1 |= OVERLAY_FLG_INTERPOLATE;
  2580. }
  2581. if (dwFourcc == FOURCC_PACKJR)
  2582. {
  2583. bRegCR3E |= 0x02;
  2584. }
  2585. else if (dwFourcc == BI_RGB)
  2586. {
  2587. if (wBitCount == 16)
  2588. {
  2589. bRegCR3E |= 0x08;
  2590. }
  2591. else if (wBitCount == 8)
  2592. {
  2593. bRegCR3E |= 0x04;
  2594. }
  2595. }
  2596. else if (dwFourcc == BI_BITFIELDS)
  2597. {
  2598. bRegCR3E |= 0x0A;
  2599. }
  2600. /*
  2601. * If we are color keying, we will set that up now
  2602. */
  2603. if (lpSurface->dwReserved1 & OVERLAY_FLG_COLOR_KEY)
  2604. {
  2605. bRegCR3E |= 0x80;
  2606. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x1a);
  2607. bTemp = CP_IN_BYTE(pjPorts, CRTC_DATA); // Set CR1A[3:2] to timing ANDed w/ color
  2608. bTemp &= ~0x0C;
  2609. CP_OUT_BYTE(pjPorts, CRTC_DATA, bTemp);
  2610. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x1d); // Clear CR1D[5:4]
  2611. bTemp = CP_IN_BYTE(pjPorts, CRTC_DATA);
  2612. if (ppdev->cBitsPerPixel == 8)
  2613. {
  2614. CP_OUT_BYTE(pjPorts, CRTC_DATA, bTemp & ~0x38);
  2615. CP_OUT_WORD(pjPorts, INDEX_REG, (ppdev->wColorKey << 8) | 0x0c); // Output color to GRC
  2616. CP_OUT_WORD(pjPorts, INDEX_REG, 0x0d); // Output color to GRD
  2617. }
  2618. else
  2619. {
  2620. CP_OUT_BYTE(pjPorts, CRTC_DATA, (bTemp & ~0x30) | 0x08);
  2621. CP_OUT_WORD(pjPorts, INDEX_REG, (ppdev->wColorKey << 8) | 0x0c); // Output color to GRC
  2622. CP_OUT_WORD(pjPorts, INDEX_REG, (ppdev->wColorKey & 0xff00) | 0x0d);// Output color to GRD
  2623. }
  2624. }
  2625. else if (lpSurface->dwReserved1 & OVERLAY_FLG_SRC_COLOR_KEY)
  2626. {
  2627. BYTE bYMax, bYMin, bUMax, bUMin, bVMax, bVMin;
  2628. bRegCR3E |= 0x80;
  2629. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x1a);
  2630. bTemp = CP_IN_BYTE(pjPorts, CRTC_DATA); // Set CR1A[3:2] to timing ANDed w/ color
  2631. bTemp &= ~0x0C;
  2632. CP_OUT_BYTE(pjPorts, CRTC_DATA, bTemp);
  2633. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x1d); // Set CR1D[5:4] to 10
  2634. CP_OUT_BYTE(pjPorts, CRTC_DATA, CP_IN_BYTE(pjPorts, CRTC_DATA) | 0x20);
  2635. /*
  2636. * Determine min/max values
  2637. */
  2638. if ((dwFourcc == FOURCC_YUV422) ||
  2639. (dwFourcc == FOURCC_YUY2) ||
  2640. (dwFourcc == FOURCC_PACKJR))
  2641. {
  2642. bYMax = (BYTE)(DWORD)(ppdev->dwSrcColorKeyHigh >> 16);
  2643. bYMin = (BYTE)(DWORD)(ppdev->dwSrcColorKeyLow >> 16);
  2644. bUMax = (BYTE)(DWORD)((ppdev->dwSrcColorKeyHigh >> 8) & 0xff);
  2645. bUMin = (BYTE)(DWORD)((ppdev->dwSrcColorKeyLow >> 8) & 0xff);
  2646. bVMax = (BYTE)(ppdev->dwSrcColorKeyHigh & 0xff);
  2647. bVMin = (BYTE)(ppdev->dwSrcColorKeyLow & 0xff);
  2648. if (dwFourcc == FOURCC_PACKJR)
  2649. {
  2650. bYMax |= 0x07;
  2651. bUMax |= 0x03;
  2652. bVMax |= 0x03;
  2653. bYMin &= ~0x07;
  2654. bUMin &= ~0x03;
  2655. bVMin &= ~0x03;
  2656. }
  2657. }
  2658. else if ((dwFourcc == 0) && (wBitCount == 16))
  2659. {
  2660. /*
  2661. * RGB 5:5:5
  2662. */
  2663. bYMax = (BYTE)(DWORD)((ppdev->dwSrcColorKeyHigh >> 7) & 0xF8);
  2664. bYMin = (BYTE)(DWORD)((ppdev->dwSrcColorKeyLow >> 7) & 0xF8);
  2665. bUMax = (BYTE)(DWORD)((ppdev->dwSrcColorKeyHigh >> 2) & 0xF8);
  2666. bUMin = (BYTE)(DWORD)((ppdev->dwSrcColorKeyLow >> 2) & 0xF8);
  2667. bVMax = (BYTE)(ppdev->dwSrcColorKeyHigh << 3);
  2668. bVMin = (BYTE)(ppdev->dwSrcColorKeyLow << 3);
  2669. bYMax |= 0x07;
  2670. bUMax |= 0x07;
  2671. bVMax |= 0x07;
  2672. }
  2673. else if (dwFourcc == BI_BITFIELDS)
  2674. {
  2675. /*
  2676. * RGB 5:6:5
  2677. */
  2678. bYMax = (BYTE)(DWORD)((ppdev->dwSrcColorKeyHigh >> 8) & 0xF8);
  2679. bYMin = (BYTE)(DWORD)((ppdev->dwSrcColorKeyLow >> 8) & 0xF8);
  2680. bUMax = (BYTE)(DWORD)((ppdev->dwSrcColorKeyHigh >> 3) & 0xFC);
  2681. bUMin = (BYTE)(DWORD)((ppdev->dwSrcColorKeyLow >> 3) & 0xFC);
  2682. bVMax = (BYTE)(ppdev->dwSrcColorKeyHigh << 3);
  2683. bVMin = (BYTE)(ppdev->dwSrcColorKeyLow << 3);
  2684. bYMax |= 0x07;
  2685. bUMax |= 0x03;
  2686. bVMax |= 0x07;
  2687. }
  2688. CP_OUT_WORD(pjPorts, INDEX_REG, ((WORD)bYMin << 8) | 0x0C); // GRC
  2689. CP_OUT_WORD(pjPorts, INDEX_REG, ((WORD)bYMax << 8) | 0x0D); // GRD
  2690. CP_OUT_WORD(pjPorts, INDEX_REG, ((WORD)bUMin << 8) | 0x1C); // GR1C
  2691. CP_OUT_WORD(pjPorts, INDEX_REG, ((WORD)bUMax << 8) | 0x1D); // GR1D
  2692. CP_OUT_WORD(pjPorts, INDEX_REG, ((WORD)bVMin << 8) | 0x1E); // GR1E
  2693. CP_OUT_WORD(pjPorts, INDEX_REG, ((WORD)bVMax << 8) | 0x1F); // GR1F
  2694. }
  2695. else
  2696. {
  2697. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x1a);
  2698. bTemp = CP_IN_BYTE(pjPorts, CRTC_DATA); // Clear CR1A[3:2]
  2699. CP_OUT_BYTE(pjPorts, CRTC_DATA, bTemp & ~0x0C);
  2700. }
  2701. /*
  2702. * Set up alignment info
  2703. */
  2704. if (ppdev->cBitsPerPixel != 24)
  2705. {
  2706. WORD wXAlign;
  2707. WORD wXSize;
  2708. if (ppdev->cBitsPerPixel == 8)
  2709. {
  2710. wXAlign = (WORD)rVideoRect.left & 0x03;
  2711. wXSize = (WORD)(rVideoRect.right - rVideoRect.left) & 0x03;
  2712. }
  2713. else
  2714. {
  2715. wXAlign = (WORD)(rVideoRect.left & 0x01) << 1;
  2716. wXSize = (WORD)((rVideoRect.right - rVideoRect.left) & 0x01) << 1;
  2717. }
  2718. bRegCR5D |= (BYTE) (wXAlign | (wXSize << 4));
  2719. }
  2720. else
  2721. {
  2722. bRegCR5D = 0;
  2723. }
  2724. /*
  2725. * Set up the FIFO threshold value. Make sure that the value we use is
  2726. * not less than the default value.
  2727. */
  2728. CP_OUT_BYTE(pjPorts, SR_INDEX, 0x16);
  2729. bTemp = CP_IN_BYTE(pjPorts, SR_DATA) & 0x0f;
  2730. if (bTemp > (ppdev->lFifoThresh & 0x0f))
  2731. {
  2732. ppdev->lFifoThresh = bTemp;
  2733. }
  2734. if (ppdev->lFifoThresh < 0x0f)
  2735. {
  2736. ppdev->lFifoThresh++; // Eliminates possible errata
  2737. }
  2738. bRegCR5C = 0x10 | ((BYTE) ppdev->lFifoThresh & 0x0f);
  2739. /*
  2740. * Now start programming the registers
  2741. */
  2742. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR31 << 8) | 0x31); // CR31
  2743. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR32 << 8) | 0x32); // CR32
  2744. if (lpSurface->dwReserved1 & OVERLAY_FLG_YUVPLANAR)
  2745. {
  2746. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) 0x10 << 8) | 0x3F); // CR3F
  2747. }
  2748. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR5C << 8) | 0x5C); // CR5C
  2749. //
  2750. // disable overlay if overlay is too small to be supported by HW
  2751. //
  2752. if (bOverlayTooSmall)
  2753. {
  2754. bRegCR3E &= ~0x01; // disable overlay
  2755. ppdev->dwPanningFlag |= OVERLAY_OLAY_REENABLE; // totally clipped
  2756. }
  2757. else
  2758. {
  2759. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR33 << 8) | 0x33); // CR33
  2760. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR34 << 8) | 0x34); // CR34
  2761. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR35 << 8) | 0x35); // CR35
  2762. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR36 << 8) | 0x36); // CR36
  2763. // CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR37 << 8) | 0x37); // CR37
  2764. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR38 << 8) | 0x38); // CR38
  2765. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR39 << 8) | 0x39); // CR39
  2766. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR3A << 8) | 0x3A); // CR3A
  2767. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR3B << 8) | 0x3B); // CR3B
  2768. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR3C << 8) | 0x3C); // CR3C
  2769. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR3D << 8) | 0x3D); // CR3D
  2770. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR5D << 8) | 0x5D); // CR5D
  2771. //
  2772. // Write Vertical start first
  2773. //
  2774. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR37 << 8) | 0x37); // CR37
  2775. }
  2776. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR3E << 8) | 0x3E); // CR3E
  2777. }
  2778. /**********************************************************
  2779. * Name: DisableOverlay_544x
  2780. *
  2781. * Module Abstract:
  2782. * ----------------
  2783. * This is called when an overlay window is totally clipped by
  2784. * the panning viewport.
  2785. **********************************************************/
  2786. VOID DisableOverlay_544x(PDEV* ppdev)
  2787. {
  2788. WORD wCR3E;
  2789. BYTE* pjPorts = ppdev->pjPorts;
  2790. ppdev->dwPanningFlag |= OVERLAY_OLAY_REENABLE;
  2791. CP_OUT_BYTE(pjPorts, CRTC_INDEX,0x3e); //Video Window Master Control
  2792. wCR3E = CP_IN_WORD(pjPorts, CRTC_INDEX) & ~0x100; //clear bit one
  2793. CP_OUT_WORD(pjPorts, CRTC_INDEX, wCR3E); //disable overlay window
  2794. }
  2795. /**********************************************************
  2796. * Name: EnableOverlay_544x
  2797. *
  2798. * Module Abstract:
  2799. * ----------------
  2800. * Show the overlay window.
  2801. **********************************************************/
  2802. VOID EnableOverlay_544x(PDEV* ppdev)
  2803. {
  2804. WORD wCR3E;
  2805. BYTE* pjPorts = ppdev->pjPorts;
  2806. ppdev->dwPanningFlag &= ~OVERLAY_OLAY_REENABLE;
  2807. CP_OUT_BYTE(pjPorts, CRTC_INDEX,0x3e); //Video Window Master Control
  2808. wCR3E = CP_IN_WORD(pjPorts, CRTC_INDEX) | 0x100; //clear bit one
  2809. CP_OUT_WORD(pjPorts, CRTC_INDEX, wCR3E); //disable overlay window
  2810. }
  2811. /**********************************************************
  2812. *
  2813. * Name: ClearAltFIFOThreshold_544x
  2814. *
  2815. * Module Abstract:
  2816. * ----------------
  2817. *
  2818. *
  2819. * Output Parameters:
  2820. * ------------------
  2821. * none
  2822. *
  2823. ***********************************************************
  2824. * Author: Shuhua Ge
  2825. * Date: 02/03/97
  2826. *
  2827. * Revision History:
  2828. * -----------------
  2829. * WHO WHEN WHAT/WHY/HOW
  2830. * --- ---- ------------
  2831. *
  2832. *********************************************************/
  2833. VOID ClearAltFIFOThreshold_544x(PDEV * ppdev)
  2834. {
  2835. UCHAR bTemp;
  2836. BYTE* pjPorts = ppdev->pjPorts;
  2837. DISPDBG((1, "ClearAltFIFOThreshold"));
  2838. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x5c); // Clear Alt FIFO Threshold
  2839. bTemp = CP_IN_BYTE(pjPorts, CRTC_DATA);
  2840. CP_OUT_BYTE(pjPorts, CRTC_DATA, bTemp & ~0x10);
  2841. }
  2842. /**********************************************************
  2843. *
  2844. * Name: RegMoveVideo
  2845. *
  2846. * Module Abstract:
  2847. * ----------------
  2848. * This function is called to move the video window that has
  2849. * already been programed.
  2850. *
  2851. * Output Parameters:
  2852. * ------------------
  2853. * none
  2854. *
  2855. ***********************************************************
  2856. * Author: Shuhua Ge
  2857. * Date: 09/25/96
  2858. *
  2859. * Revision History:
  2860. * -----------------
  2861. * WHO WHEN WHAT/WHY/HOW
  2862. * --- ---- ------------
  2863. *
  2864. *********************************************************/
  2865. VOID RegMoveVideo(PDEV* ppdev, PDD_SURFACE_LOCAL lpSurface)
  2866. {
  2867. BOOL bZoomX;
  2868. DWORD dwTemp;
  2869. DWORD dwFourcc;
  2870. LONG lLeft;
  2871. LONG lPitch;
  2872. WORD wTemp;
  2873. WORD wBitCount = 0;
  2874. RECTL rVideoRect;
  2875. BYTE bRegCR33;
  2876. BYTE bRegCR34;
  2877. BYTE bRegCR35;
  2878. BYTE bRegCR36;
  2879. BYTE bRegCR37;
  2880. BYTE bRegCR38;
  2881. BYTE bRegCR39;
  2882. BYTE bRegCR3A;
  2883. BYTE bRegCR3B;
  2884. BYTE bRegCR3C;
  2885. BYTE bRegCR3D;
  2886. BYTE bRegCR5D;
  2887. BYTE bTemp;
  2888. BYTE* pjPorts = ppdev->pjPorts;
  2889. /*
  2890. * Determine the format of the video data
  2891. */
  2892. if (lpSurface->dwFlags & DDRAWISURF_HASPIXELFORMAT)
  2893. {
  2894. GetFormatInfo(ppdev, &(lpSurface->lpGbl->ddpfSurface),
  2895. &dwFourcc, &wBitCount);
  2896. }
  2897. else
  2898. {
  2899. // This needs to be changed when primary surface is RGB 5:6:5
  2900. dwFourcc = BI_RGB;
  2901. wBitCount = (WORD) ppdev->cBitsPerPixel;
  2902. }
  2903. rVideoRect = ppdev->rOverlayDest;
  2904. //
  2905. // rVideoRect is now adjusted and clipped to the panning viewport.
  2906. // Disable overlay if totally clipped by viewport.
  2907. //
  2908. if (((rVideoRect.right - rVideoRect.left) <= 0) ||
  2909. ((rVideoRect.bottom- rVideoRect.top ) <= 0))
  2910. {
  2911. DisableOverlay_544x(ppdev); // #ew1 cannot display below min. overlay size
  2912. return;
  2913. }
  2914. lPitch = lpSurface->lpGbl->lPitch;
  2915. /*
  2916. * Determine value in CR33 (Region 1 Size)
  2917. */
  2918. wTemp = (WORD) rVideoRect.left;
  2919. if (ppdev->cBitsPerPixel == 8)
  2920. {
  2921. wTemp >>= 2; // 4 Pixels per DWORD
  2922. }
  2923. else if (ppdev->cBitsPerPixel == 16)
  2924. {
  2925. wTemp >>= 1; // 2 Pixels per DWORD
  2926. }
  2927. else if (ppdev->cBitsPerPixel == 24)
  2928. {
  2929. wTemp *= 3;
  2930. wTemp /= 4;
  2931. }
  2932. bRegCR33 = (BYTE) wTemp;
  2933. bRegCR36 = (BYTE) (WORD) (wTemp >> 8);
  2934. /*
  2935. * Determine value in CR34 (Region 2 size)
  2936. */
  2937. wTemp = (WORD) (rVideoRect.right - rVideoRect.left);
  2938. if (ppdev->cBitsPerPixel == 8)
  2939. {
  2940. wTemp >>= 2; // 4 Pixels per DWORD
  2941. }
  2942. else if (ppdev->cBitsPerPixel == 16)
  2943. {
  2944. wTemp >>= 1; // 2 Pixels per DWORD
  2945. }
  2946. else if (ppdev->cBitsPerPixel == 24)
  2947. {
  2948. wTemp *= 3;
  2949. wTemp /= 4;
  2950. }
  2951. bRegCR34 = (BYTE) wTemp;
  2952. wTemp >>= 6;
  2953. bRegCR36 |= (BYTE) (wTemp & 0x0C);
  2954. /*
  2955. * Determine value in CR35 (Region 2SD Size)
  2956. */
  2957. dwTemp = (DWORD) (rVideoRect.right - rVideoRect.left);
  2958. dwTemp *= (DWORD) (ppdev->rOverlaySrc.right - ppdev->rOverlaySrc.left);
  2959. dwTemp /= (DWORD) (ppdev->rOverlayDest.right - ppdev->rOverlayDest.left);
  2960. wTemp = (WORD) dwTemp;
  2961. if ((dwFourcc == FOURCC_PACKJR) || (wBitCount == 8))
  2962. {
  2963. wTemp >>= 2; // 4 Pixels per DWORD
  2964. }
  2965. else
  2966. {
  2967. wTemp >>= 1; // 2 Pixels per DWORD
  2968. }
  2969. bRegCR35 = (BYTE) wTemp;
  2970. wTemp >>= 4;
  2971. bRegCR36 |= (BYTE) (wTemp & 0x30);
  2972. //
  2973. // Check double scan line counter feature
  2974. //
  2975. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x17);
  2976. bTemp = CP_IN_BYTE(pjPorts, CRTC_DATA);
  2977. if (bTemp & 0x04)
  2978. {
  2979. //
  2980. // Double scan line count
  2981. //
  2982. /*
  2983. * Determine value in CR37 (Vertical Start)
  2984. */
  2985. wTemp = (WORD) rVideoRect.top;
  2986. bRegCR37 = (BYTE)(wTemp >> 1);
  2987. if ( wTemp & 0x01 )
  2988. {
  2989. wTemp >>= 9;
  2990. bRegCR39 = (BYTE) wTemp | 0x10;
  2991. //
  2992. // Odd scan line trigger
  2993. // Hardware has a bug now.
  2994. // So reduce dest end by 1
  2995. //
  2996. wTemp = (WORD) rVideoRect.bottom - 1 - 1;
  2997. }
  2998. else
  2999. {
  3000. wTemp >>= 9;
  3001. bRegCR39 = (BYTE) wTemp;
  3002. /*
  3003. * Determine value in CR38 (Vertical End)
  3004. */
  3005. wTemp = (WORD) rVideoRect.bottom - 1;
  3006. }
  3007. bRegCR38 = (BYTE)(wTemp >> 1);
  3008. if (wTemp & 0x01)
  3009. bRegCR39 |= 0x20;
  3010. wTemp >>= 7;
  3011. bRegCR39 |= (BYTE) (wTemp & 0x0C);
  3012. }
  3013. else
  3014. {
  3015. /*
  3016. * Determine value in CR37 (Vertical Start)
  3017. */
  3018. wTemp = (WORD) rVideoRect.top;
  3019. //if (ppdev->bDoubleClock)
  3020. //{
  3021. // wTemp >>= 1;
  3022. //}
  3023. bRegCR37 = (BYTE) wTemp;
  3024. wTemp >>= 8;
  3025. bRegCR39 = (BYTE) wTemp;
  3026. /*
  3027. * Determine value in CR38 (Vertical End)
  3028. */
  3029. wTemp = (WORD) rVideoRect.bottom - 1;
  3030. //if (ppdev->bDoubleClock)
  3031. //{
  3032. // wTemp >>= 1;
  3033. //}
  3034. bRegCR38 = (BYTE) wTemp;
  3035. wTemp >>= 6;
  3036. bRegCR39 |= (BYTE) (wTemp & 0x0C);
  3037. }
  3038. /*
  3039. * Determine values in CR3A, CR3B, CR3C (Start Address)
  3040. */
  3041. dwTemp = 0;
  3042. bZoomX = ((ppdev->rOverlayDest.right - ppdev->rOverlayDest.left) !=
  3043. (ppdev->rOverlaySrc.right - ppdev->rOverlaySrc.left));
  3044. if (bZoomX)
  3045. {
  3046. //
  3047. // overlay is zoomed, re-initialize zoom factor
  3048. //
  3049. CalculateStretchCode(ppdev->rOverlaySrc.right - ppdev->rOverlaySrc.left,
  3050. ppdev->rOverlayDest.right - ppdev->rOverlayDest.left, ppdev->HorStretchCode);
  3051. }
  3052. //
  3053. // Here, we want to ensure the source rectangle's clipped width is bigger
  3054. // than what the HW can support, sigh!
  3055. //
  3056. // if (grOverlayDest.right > sData->rViewport.right)
  3057. {
  3058. int iSrcPels;
  3059. //
  3060. // compute non-clip amount on right edge
  3061. //
  3062. iSrcPels = (int)(rVideoRect.right - rVideoRect.left);
  3063. if (bZoomX)
  3064. {
  3065. WORD wRightCnt;
  3066. wRightCnt = 0;
  3067. while (iSrcPels > 0)
  3068. {
  3069. iSrcPels -= ppdev->HorStretchCode[wRightCnt];
  3070. if (iSrcPels >= 0)
  3071. {
  3072. wRightCnt++;
  3073. }
  3074. }
  3075. iSrcPels = (int)wRightCnt;
  3076. }
  3077. if ((iSrcPels == 0) || (iSrcPels <= MIN_OLAY_WIDTH))
  3078. {
  3079. DisableOverlay_544x(ppdev); // cannot display below min. overlay size
  3080. return;
  3081. }
  3082. }
  3083. lLeft = ppdev->rOverlaySrc.left;
  3084. if (dwFourcc == FOURCC_PACKJR)
  3085. {
  3086. lLeft &= ~0x03;
  3087. }
  3088. else if (dwFourcc == FOURCC_YUV422 || dwFourcc == FOURCC_YUY2)
  3089. {
  3090. lLeft &= ~0x01;
  3091. }
  3092. //
  3093. // #ew1 dwTemp has adjusted dest. rect., add in source adjustment
  3094. //
  3095. dwTemp += (ppdev->rOverlaySrc.top * lPitch) + ((lLeft * wBitCount) >>3);
  3096. ppdev->sOverlay1.lAdjustSource = dwTemp;
  3097. // dwTemp += ((BYTE*)lpSurface->lpGbl->fpVidMem - ppdev->pjScreen); // sss
  3098. dwTemp += (DWORD)(lpSurface->lpGbl->fpVidMem);
  3099. bRegCR5D = (BYTE) ((dwTemp << 2) & 0x0C);
  3100. dwTemp >>= 2;
  3101. bRegCR3A = (BYTE) dwTemp & 0xfe; // Align to even byte (5446 bug)
  3102. dwTemp >>= 8;
  3103. bRegCR3B = (BYTE) dwTemp;
  3104. dwTemp >>= 8;
  3105. bRegCR3C = (BYTE) (dwTemp & 0x0f);
  3106. /*
  3107. * Determine value in CR3D (Address Offset/Pitch)
  3108. */
  3109. wTemp = (WORD) (lPitch >> 3);
  3110. if (lpSurface->dwReserved1 & OVERLAY_FLG_DECIMATE)
  3111. {
  3112. wTemp >>= 1;
  3113. }
  3114. bRegCR3D = (BYTE) wTemp;
  3115. wTemp >>= 3;
  3116. bRegCR3C |= (BYTE) (wTemp & 0x20);
  3117. /*
  3118. * Set up alignment info
  3119. */
  3120. if (ppdev->cBitsPerPixel != 24)
  3121. {
  3122. WORD wXAlign;
  3123. WORD wXSize;
  3124. if (ppdev->cBitsPerPixel == 8)
  3125. {
  3126. wXAlign = (WORD)rVideoRect.left & 0x03;
  3127. wXSize = (WORD)(rVideoRect.right - rVideoRect.left) & 0x03;
  3128. }
  3129. else
  3130. {
  3131. wXAlign = (WORD)(rVideoRect.left & 0x01) << 1;
  3132. wXSize = (WORD)((rVideoRect.right - rVideoRect.left) & 0x01) << 1;
  3133. }
  3134. bRegCR5D |= (BYTE) (wXAlign | (wXSize << 4));
  3135. }
  3136. /*
  3137. * Now we will write the actual register values.
  3138. */
  3139. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR33 << 8) | 0x33); // CR33
  3140. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR34 << 8) | 0x34); // CR34
  3141. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR35 << 8) | 0x35); // CR35
  3142. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR36 << 8) | 0x36); // CR36
  3143. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR38 << 8) | 0x38); // CR38
  3144. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR39 << 8) | 0x39); // CR39
  3145. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR3A << 8) | 0x3A); // CR3A
  3146. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR3B << 8) | 0x3B); // CR3B
  3147. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR3C << 8) | 0x3C); // CR3C
  3148. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR3D << 8) | 0x3D); // CR3D
  3149. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR5D << 8) | 0x5D); // CR5D
  3150. CP_OUT_WORD(pjPorts, CRTC_INDEX, ((WORD) bRegCR37 << 8) | 0x37); // CR37
  3151. if (ppdev->dwPanningFlag & OVERLAY_OLAY_REENABLE)
  3152. EnableOverlay_544x(ppdev);
  3153. }
  3154. /**********************************************************
  3155. *
  3156. * Name: CalculateStretchCode
  3157. *
  3158. * Module Abstract:
  3159. * ----------------
  3160. * This code was originally written by Intel and distributed
  3161. * with the DCI development kit.
  3162. *
  3163. * This function takes the zoom factor and determines exactly
  3164. * how many times we need to replicate each row/column.
  3165. *
  3166. * Output Parameters:
  3167. * ------------------
  3168. * none
  3169. *
  3170. ***********************************************************
  3171. * Author: Intel
  3172. * Date: ??/??/??
  3173. *
  3174. * Revision History:
  3175. * -----------------
  3176. * WHO WHEN WHAT/WHY/HOW
  3177. * --- ---- ------------
  3178. * Scott MacDonald 10/06/94 Incorporated code into DCI provider.
  3179. *
  3180. *********************************************************/
  3181. VOID CalculateStretchCode (LONG srcLength, LONG dstLength, LPBYTE code)
  3182. {
  3183. LONG dwDeltaX, dwDeltaY, dwConst1, dwConst2, dwP;
  3184. LONG i, j, k;
  3185. BYTE bStretchIndex = 0;
  3186. LONG total = 0;
  3187. /*
  3188. * for some strange reason I'd like to figure out but haven't got time to, the
  3189. * replication code generation seems to have a problem between 1:1 and 2:1 stretch
  3190. * ratios. Fix is to zero-initialize index (the problem occurs in the first one
  3191. * generated) when stretch is betw. those ratios, and one-initialize it otherwise.
  3192. */
  3193. if ((dstLength <= srcLength * 2L) && (dstLength >= srcLength))
  3194. {
  3195. bStretchIndex = 0;
  3196. }
  3197. else
  3198. {
  3199. bStretchIndex = 1;
  3200. }
  3201. /*
  3202. * initialize code array, to get rid of anything which might have been
  3203. * left over in it.
  3204. */
  3205. for (i = 0; i < srcLength; i++)
  3206. {
  3207. code[i] = 0;
  3208. }
  3209. /*
  3210. * Variable names roughly represent what you will find in any graphics
  3211. * text. Consult text for an explanation of Bresenham line alg., it's
  3212. * beyond the scope of my comments here.
  3213. */
  3214. dwDeltaX = srcLength;
  3215. dwDeltaY = dstLength;
  3216. if (dstLength < srcLength)
  3217. {
  3218. /*
  3219. * Size is shrinking, use standard Bresenham alg.
  3220. */
  3221. dwConst1 = 2L * dwDeltaY;
  3222. dwConst2 = 2L * (dwDeltaY - dwDeltaX);
  3223. dwP = 2L * dwDeltaY - dwDeltaX;
  3224. for (i = 0; i < dwDeltaX; i++)
  3225. {
  3226. if (dwP <= 0L)
  3227. {
  3228. dwP += dwConst1;
  3229. }
  3230. else
  3231. {
  3232. dwP += dwConst2;
  3233. code[i]++;
  3234. total++;
  3235. }
  3236. }
  3237. }
  3238. else
  3239. {
  3240. /*
  3241. * Size is increasing. Use Bresenham adapted for slope > 1, and
  3242. * use a loop invariant to generate code array. Run index i from
  3243. * 0 to dwDeltaY - 1, and when i = dwDeltaY - 1, j will
  3244. * be = dwDeltaX - 1.
  3245. */
  3246. dwConst1 = 2L * dwDeltaX;
  3247. dwConst2 = 2L * (dwDeltaX - dwDeltaY);
  3248. dwP = 2L * dwDeltaX - dwDeltaY;
  3249. j = 0;
  3250. for (i = 0; i < dwDeltaY; i++)
  3251. {
  3252. if (dwP <= 0L)
  3253. {
  3254. dwP += dwConst1;
  3255. bStretchIndex++;
  3256. }
  3257. else
  3258. {
  3259. dwP += dwConst2;
  3260. code[j++] = ++bStretchIndex;
  3261. bStretchIndex = 0;
  3262. total += (int)code[j - 1];
  3263. }
  3264. }
  3265. /*
  3266. * UGLY fix up for wacky bug which I have no time to fix properly.
  3267. * The 'total' of entries is messed up for slopes > 4, so add the
  3268. * difference back into the array.
  3269. */
  3270. if (total < dwDeltaY)
  3271. {
  3272. while (total < dwDeltaY)
  3273. {
  3274. j = (int)dwDeltaY - total;
  3275. k = (int)dwDeltaY / j;
  3276. for (i = 0; i < dwDeltaX; i++)
  3277. {
  3278. if (!(i % k) && (total < dwDeltaY))
  3279. {
  3280. code[i]++;
  3281. total++;
  3282. }
  3283. }
  3284. }
  3285. }
  3286. }
  3287. }
  3288. /**********************************************************
  3289. *
  3290. * Name: GetThresholdValue
  3291. *
  3292. * Module Abstract:
  3293. * ----------------
  3294. * Determines the best threshold for the specified
  3295. * surface.
  3296. *
  3297. * Output Parameters:
  3298. * ------------------
  3299. * Threshold
  3300. *
  3301. ***********************************************************
  3302. * Author: Shuhua Ge
  3303. * Date: 09/25/95
  3304. *
  3305. * Revision History:
  3306. * -----------------
  3307. * WHO WHEN WHAT/WHY/HOW
  3308. * --- ---- ------------
  3309. *
  3310. *********************************************************/
  3311. BYTE GetThresholdValue(VOID)
  3312. {
  3313. return ((BYTE) 0x0A);
  3314. }
  3315. /**********************************************************
  3316. *
  3317. * Name: MustLineRelicate
  3318. *
  3319. * Module Abstract:
  3320. * ----------------
  3321. * Checks to see if we must line replicate or if we can
  3322. * interpolate.
  3323. *
  3324. * Output Parameters:
  3325. * ------------------
  3326. * TRUE/FALSE
  3327. *
  3328. ***********************************************************
  3329. * Author: Shuhua Ge
  3330. * Date: 09/25/96
  3331. *
  3332. * Revision History:
  3333. * -----------------
  3334. * WHO WHEN WHAT/WHY/HOW
  3335. * --- ---- ------------
  3336. *
  3337. *********************************************************/
  3338. BOOL MustLineReplicate (PDEV* ppdev, PDD_SURFACE_LOCAL lpSurface, WORD wVideoDepth)
  3339. {
  3340. LONG lTempThresh;
  3341. /*
  3342. * If we are double clocking the data (1280x1024 mode), we must
  3343. * replicate. We should also always replicate in Performance mode
  3344. */
  3345. if (ppdev->bDoubleClock)
  3346. {
  3347. return (TRUE);
  3348. }
  3349. //
  3350. // Check the VCLK
  3351. //
  3352. // sge07
  3353. if (GetVCLK(ppdev) > 130000)
  3354. {
  3355. return (TRUE);
  3356. }
  3357. /*
  3358. * If we are using the chroma key feature, we can't interpolate
  3359. */
  3360. if (lpSurface->dwReserved1 & (OVERLAY_FLG_COLOR_KEY | OVERLAY_FLG_SRC_COLOR_KEY))
  3361. {
  3362. return (TRUE);
  3363. }
  3364. lTempThresh = ppdev->lFifoThresh;
  3365. if (ppdev->pfnIsSufficientBandwidth(ppdev, wVideoDepth,
  3366. &ppdev->rOverlaySrc, &ppdev->rOverlayDest, OVERLAY_FLG_INTERPOLATE))
  3367. {
  3368. ppdev->lFifoThresh = lTempThresh;
  3369. return (FALSE);
  3370. }
  3371. ppdev->lFifoThresh = lTempThresh;
  3372. return (TRUE);
  3373. }
  3374. /**********************************************************
  3375. *
  3376. * Name: IsSufficientBandwidth
  3377. *
  3378. * Module Abstract:
  3379. * ----------------
  3380. * Determines is sufficient bandwidth exists for the requested
  3381. * configuration.
  3382. *
  3383. * Output Parameters:
  3384. * ------------------
  3385. * TRUE/FALSE
  3386. * It also sets the global parameter lFifoThresh, which gets
  3387. * programed in RegInitVideo().
  3388. *
  3389. ***********************************************************
  3390. * Author: Shuhua Ge
  3391. * Date: 09/25/96
  3392. *
  3393. * Revision History:
  3394. * -----------------
  3395. * WHO WHEN WHAT/WHY/HOW
  3396. * --- ---- ------------
  3397. *
  3398. *********************************************************/
  3399. BOOL IsSufficientBandwidth(PDEV* ppdev, WORD wVideoDepth, LPRECTL lpSrc, LPRECTL lpDest, DWORD dwFlags)
  3400. {
  3401. LONG lVideoPixelsPerDWORD;
  3402. LONG lGraphicsPixelsPerDWORD;
  3403. LONG lVCLKPeriod;
  3404. LONG lTransferTime;
  3405. LONG lDWORDsWritten;
  3406. LONG lZoom;
  3407. LONG lReadPeriod;
  3408. LONG lEffReadPeriod;
  3409. LONG lWritePeriod;
  3410. LONG lEffWritePeriod;
  3411. LONG K1,K2;
  3412. LONG lTrFifoAFirst4;
  3413. LONG lTrFifoB2;
  3414. LONG lDWORDsRead;
  3415. LONG lFifoAReadPeriod;
  3416. LONG lFifoBReadPeriod;
  3417. LONG lFifoAEffWritePeriod;
  3418. LONG lFifoBEffWritePeriod;
  3419. LONG lFifoALevels;
  3420. LONG lFifoBLevels;
  3421. LONG lFifoAThresh;
  3422. LONG lFifoBThresh;
  3423. LONG lVCLK;
  3424. BYTE* pjPorts = ppdev->pjPorts;
  3425. //#define BLIT_LATENCY 8
  3426. #define CRT_FIFO_DEPTH 28
  3427. //
  3428. // Add 8 clock for BLT_LATENCY for 54446BE and later chips
  3429. //
  3430. // sge04
  3431. LONG BLIT_LATENCY = 8;
  3432. if (ppdev->flCaps & CAPS_SECOND_APERTURE)
  3433. BLIT_LATENCY += 2;
  3434. /*
  3435. * Convert input parameters
  3436. */
  3437. if (wVideoDepth == 16)
  3438. {
  3439. lVideoPixelsPerDWORD = 2;
  3440. }
  3441. else
  3442. {
  3443. lVideoPixelsPerDWORD = 4;
  3444. }
  3445. if (ppdev->cBitsPerPixel == 8)
  3446. {
  3447. lGraphicsPixelsPerDWORD = 4;
  3448. }
  3449. else if (ppdev->cBitsPerPixel == 16)
  3450. {
  3451. lGraphicsPixelsPerDWORD = 2;
  3452. }
  3453. else if (ppdev->cBitsPerPixel == 24)
  3454. {
  3455. lGraphicsPixelsPerDWORD = 1;
  3456. }
  3457. else
  3458. return (FALSE);
  3459. lZoom = ((lpDest->right - lpDest->left) * 256) /
  3460. (lpSrc->right - lpSrc->left);
  3461. /*
  3462. * If we are double clocked, fail if we are not zoomed at least 2X
  3463. */
  3464. if (ppdev->bDoubleClock && (lZoom < 512))
  3465. {
  3466. return (FALSE);
  3467. }
  3468. /*
  3469. * We need to get the VCLK every time since this can change
  3470. * at run-time
  3471. */
  3472. lVCLK = GetVCLK(ppdev);
  3473. if (lVCLK == 0)
  3474. {
  3475. return (FALSE);
  3476. }
  3477. lVCLKPeriod = (LONG) ((1000000/lVCLK) + 1);
  3478. /*
  3479. * We only need to setup the following variables once!
  3480. */
  3481. if (!ppdev->lBusWidth)
  3482. {
  3483. /*
  3484. * We will read the bus width from SR0F[4:3]
  3485. */
  3486. CP_OUT_BYTE(pjPorts, SR_INDEX, 0x0F);
  3487. if ((CP_IN_BYTE(pjPorts, SR_DATA) & 0x18) == 0x18)
  3488. {
  3489. ppdev->lBusWidth = 8; // 64 bit bus
  3490. }
  3491. else
  3492. {
  3493. ppdev->lBusWidth = 4; // 32 bit bus
  3494. }
  3495. }
  3496. if (!ppdev->lRandom)
  3497. {
  3498. /*
  3499. * Is this EDO or regular?
  3500. */
  3501. CP_OUT_BYTE(pjPorts, SR_INDEX, 0x0f);
  3502. if (!(CP_IN_BYTE(pjPorts, SR_DATA) & 0x4))
  3503. {
  3504. ppdev->lRandom = 7;
  3505. ppdev->lPageMiss = 7;
  3506. }
  3507. else
  3508. {
  3509. ppdev->lRandom = 6;
  3510. ppdev->lPageMiss = 6;
  3511. }
  3512. }
  3513. if (!ppdev->lMCLKPeriod)
  3514. {
  3515. LONG lMCLK;
  3516. /*
  3517. * The MCLK period is the amount of time required for one cycle.
  3518. * We will round up.
  3519. */
  3520. CP_OUT_BYTE(pjPorts, SR_INDEX, 0x1f); // First get the MCLK frequency
  3521. lMCLK = CP_IN_BYTE(pjPorts, SR_DATA);
  3522. lMCLK *= 14318;
  3523. lMCLK >>= 3;
  3524. ppdev->lMCLKPeriod = ((1000000/lMCLK) + 1);
  3525. }
  3526. /*
  3527. * Check for the case with no color key or Y interpolation
  3528. */
  3529. if (dwFlags == 0)
  3530. {
  3531. /*
  3532. * This mode utilizes only FIFO A. The fifo is filled with
  3533. * graphics data during regions 1 and 3, and video data during
  3534. * region 2.
  3535. *
  3536. * The normal memory sequence for this mode goes as follows.
  3537. *
  3538. * ------------------------------------------------
  3539. * | cpu/blit cycle | FIFO A fill | cpu/blit cycle ....
  3540. * ------------------------------------------------
  3541. *
  3542. * The cpu/blit cycle is interrupted when the CRT
  3543. * fifo is depleted to its threshold. Once the
  3544. * crt cycle is started, it continues until the
  3545. * FIFO A is full.
  3546. *
  3547. * Worst case condition for filling the CRT fifo :
  3548. *
  3549. * 1) CPU/blit latency ->
  3550. * 2) Random cycle for region 2 video ->
  3551. * 3) Page miss for region 2 video ->
  3552. * 4) Page miss for region 2 to region 3 transition ->
  3553. * 5) Page miss for region 3 graphics
  3554. *
  3555. * Conditions 3 and 5 depend on the location of the
  3556. * graphic screen within display memory. For 1024x768, where
  3557. * the graphics screen starts at location 0 and is offset by
  3558. * 1024 or 2048 bytes each line, condition 5 is never met.
  3559. * If a video window starts at beginning of a memory page,
  3560. * and is offset at the beggining of each line by an even
  3561. * multiple of a memory page, condition 3 is never met.
  3562. *
  3563. * Based on this worst case condition, the amount of time
  3564. * required to complete 4 transfers into the crt fifo
  3565. * is approximately:
  3566. * lTransferTime = (BLIT_LATENCY + lRandom + 3*(lPageMiss)) *
  3567. * lMCLKPeriod.
  3568. * the number of dwords transferred to the fifo
  3569. * during this time is 4 for 32 bit memory interface
  3570. * or 8 for 64 bit interface.
  3571. * lDWORDsWritten = 4 * (lBusWidth/4)
  3572. *
  3573. * During this period, data continues to be read from the crt
  3574. * fifo for screen refresh. The amount of data read,
  3575. * assuming a 1x scale is approximately:
  3576. * lDWORDsRead = tr_time/(lVideoPixelsPerDWORD * lVCLKPeriod)
  3577. *
  3578. * The difference between the dwords read and dwords
  3579. * written must be accounted for in the fifo trheshold setting
  3580. *
  3581. * lFifoThresh = (lDWORDsRead - lDWORDsWritten) rounded
  3582. * up to next even value.
  3583. *
  3584. * To determine if there is adequate bandwidth to support
  3585. * the mode, the lFifoThresh must not exceed the fifo depth.
  3586. * For the mode to work, the fifo read rate must not exceed the
  3587. * fifo write rate.
  3588. * read_rate = min(lGraphicsPixelsPerDWORD,lVideoPixelsPerDWORD) * lVCLKPeriod.
  3589. * write_rate = lMCLKPeriod * 2; -- 2 clocks per cas
  3590. *
  3591. * A special case occurs if the fifo read rate is very close to the peak
  3592. * fifo write rate. In this case the crt fill may result in a continuous
  3593. * page cycle for the entire active line. This could result in 1 extra
  3594. * page miss at the start of region2. To account for this, I will
  3595. * add 3 DWORDS to the trheshold if the read and write rates are very close
  3596. * (arbitrarily defined as within 10% of each other.
  3597. *
  3598. * Zooming
  3599. * Some modes can only be supported at video scale factors greater than 1X.
  3600. * Even when the video is zoomed, a small number of dwords must be read
  3601. * from the crt fifo at the unzoomed rate in order to prime the video
  3602. * pipeline. The video pipeline requires 10 pixel before it slows the fifo
  3603. * reads to the zoomed rate.
  3604. *
  3605. * tr_time - (lVCLKPeriod * 10/lVideoPixelsPerDWORD)
  3606. * lDWORDsRead = --------------------------------------------- + 10/lVideoPixelsPerDWORDord
  3607. * (lVideoPixelsPerDWORD * lVCLKPeriod * lZoom)
  3608. */
  3609. lTransferTime = (BLIT_LATENCY + ppdev->lRandom + (3*(ppdev->lPageMiss))) *
  3610. ppdev->lMCLKPeriod;
  3611. lDWORDsWritten = 3 * (ppdev->lBusWidth/4);
  3612. /*
  3613. * If read rate exceeds write rate, calculate minumum zoom
  3614. * to keep everything as ints, spec the zoom as 256 times
  3615. * the fractional zoom
  3616. */
  3617. lWritePeriod = ppdev->lMCLKPeriod * 2/(ppdev->lBusWidth/4);
  3618. lReadPeriod = lVideoPixelsPerDWORD * lVCLKPeriod;
  3619. /*
  3620. * Pick worst case of graphics and video depths for calculation
  3621. * of dwords read. This may be a little pessimistic for the
  3622. * when the graphics bits per pixel exceeds the video bits per pixel.
  3623. */
  3624. lEffReadPeriod = (lVideoPixelsPerDWORD * lVCLKPeriod * lZoom)/256;
  3625. if (lEffReadPeriod < lWritePeriod)
  3626. {
  3627. /*
  3628. * Cannot support overlay at this zoom factor
  3629. */
  3630. return (0);
  3631. }
  3632. if (lGraphicsPixelsPerDWORD > lVideoPixelsPerDWORD) // handle zoom factor
  3633. {
  3634. lDWORDsRead = ((lTransferTime -
  3635. (lVCLKPeriod * 10/lVideoPixelsPerDWORD))/
  3636. (lEffReadPeriod)) +
  3637. (10 / lVideoPixelsPerDWORD) + 1;
  3638. }
  3639. else
  3640. {
  3641. lDWORDsRead = (lTransferTime/
  3642. (lGraphicsPixelsPerDWORD * lVCLKPeriod)) + 1;
  3643. }
  3644. // Calculate the fifo threshold setting
  3645. ppdev->lFifoThresh = lDWORDsRead - lDWORDsWritten;
  3646. // if read rate is within 10% of write rate, up by 3 dwords
  3647. if ((11*lEffReadPeriod) < ((10*lWritePeriod*256)/lZoom))
  3648. {
  3649. ppdev->lFifoThresh += 3;
  3650. }
  3651. // fifo trheshold spec'd in QWORDS, so round up by 1 and divide by 2)
  3652. ppdev->lFifoThresh = (ppdev->lFifoThresh + 1)/2;
  3653. // Add a extra QWORD to account for fifo level sync logic
  3654. ppdev->lFifoThresh = ppdev->lFifoThresh + 1;
  3655. if (ppdev->bDoubleClock)
  3656. {
  3657. ppdev->lFifoThresh <<= 1;
  3658. }
  3659. if ((ppdev->lFifoThresh >= CRT_FIFO_DEPTH) ||
  3660. ((lEffReadPeriod) < lWritePeriod))
  3661. {
  3662. return (0);
  3663. }
  3664. else
  3665. {
  3666. return (1);
  3667. }
  3668. }
  3669. /*
  3670. * Check bandwidth for Y Interpolation
  3671. */
  3672. else if (dwFlags & OVERLAY_FLG_INTERPOLATE)
  3673. {
  3674. /*
  3675. * This mode utilizes both FIFOs A and B. During horizontal blank,
  3676. * both fifos are filled. FIFO a is then filled with graphics
  3677. * data during regions 1 and 3, and video data during region 2.
  3678. * FIFO B is filled with video data during region 2, and is idle
  3679. * during regions 1 and 3.
  3680. *
  3681. * The normal memory sequence for this mode goes as follows.
  3682. *
  3683. * ----------------------------------------------------------------
  3684. * | cpu/blit cycle | FIFO A fill | FIFO B fill | cpu/blit cycle .
  3685. * ----------------------------------------------------------------
  3686. * or
  3687. * ----------------------------------------------------------------
  3688. * | cpu/blit cycle | FIFO B fill | FIFO A fill | cpu/blit cycle .
  3689. * ----------------------------------------------------------------
  3690. *
  3691. * For this mode, the FIFO threshold must be set high enough to allow
  3692. * enough time to abort the cpu/blt, fill FIFO A, then transfer data
  3693. * into FIFO B before underflow occurs.
  3694. *
  3695. * Worst case condition for filling the CRT fifo :
  3696. *
  3697. * 1) CPU/blit latency ->
  3698. * 2) FIFO A random cycle for region 2 video ->
  3699. * 3) FIFO A page miss for region 2 video ->
  3700. * 4) FIFO A page miss for region 2 to region 3 transition ->
  3701. * 5) FIFO A page miss for region 3 graphics
  3702. * 6) FIFO A page mode fill
  3703. * 7) FIFO B random cycle
  3704. * 8) FIFO B page miss
  3705. *
  3706. * lTransferTime = lMCLKPeriod *
  3707. * (BLIT_LATENCY + lRandom + 3*(lPageMiss) +
  3708. * fifoa_remaining +
  3709. * lRandom + lPageMiss;
  3710. *
  3711. *
  3712. * The time required to fill FIFO A depends upon the read rate
  3713. * of FIFO A and the number of levels that must be filled,
  3714. * as determined by the threshold setting.
  3715. *
  3716. * The worst case fill time for the first four levels of fifo A is
  3717. * lTrFifoAFirst4 = (BLIT_LATENCY + lRandom + 3*(lPageMiss)) *
  3718. * lMCLKPeriod;
  3719. *
  3720. * The number of dwords depleted from fifo A during the
  3721. * fill of the first four levels is
  3722. * lReadPeriod = lVCLKPeriod * lVideoPixelsPerDWORD * lZoom;
  3723. * fifoa_reads_4 = lTrFifoAFirst4/lReadPeriod;
  3724. *
  3725. * The number of empty levels remaining in the fifo after
  3726. * the fill of the first four levels is
  3727. * fifoa_remaining = FIFO_DEPTH - lFifoThresh + ((4*ramwidth)/4)
  3728. * - lTrFifoAFirst4/lReadPeriod;
  3729. *
  3730. * The amount of time required to fill the remaining levels of
  3731. * fifo A is determined by the write rate and the read rate.
  3732. * lWritePeriod = lMCLKPeriod * 2; // 2 clks per cas
  3733. * lEffWritePeriod = ((lReadPeriod * lWritePeriod)/
  3734. * (lReadPeriod - lWritePeriod));
  3735. *
  3736. * tr_fifoa_remaining = fifoa_remaining * lEffWritePeriod;
  3737. *
  3738. *
  3739. * The total amount of time for the cpu/blt latency and the
  3740. * fifo A fill is
  3741. * tr_fifoa_total = lTrFifoAFirst4 + tr_fifoa_remaining;
  3742. *
  3743. * The worse case fill time for fifo B is as follows:
  3744. * lTrFifoB2 = (lRandom + lPageMiss) * lMCLKPeriod;
  3745. *
  3746. * The total amount of time elapsed from the crt request until
  3747. * the first 2 fifob cycles are completed is
  3748. * lTransferTime = tr_fifoa_total + lTrFifoB2;
  3749. *
  3750. * The number of dwords transferred to the fifo during this
  3751. * time is 2 for 32 bit memory interface or 4 for 64 bit interface.
  3752. * lDWORDsWritten = 2 * (lBusWidth/4)
  3753. *
  3754. * During this period, data continues to be read from the crt
  3755. * fifo B for screen refresh. The amount of data read,
  3756. * is approximately:
  3757. * dwords_read = lTransferTime/lReadPeriod
  3758. *
  3759. * The difference between the dwords read and dwords
  3760. * written must be accounted for in the fifo trheshold setting
  3761. *
  3762. * lFifoThresh = (dwords_read - lDWORDsWritten) rounded
  3763. * up to next even value.
  3764. *
  3765. * Since the lTransferTime and dwords_read depends on
  3766. * the threshold setting, a bit of algebra is required to determine
  3767. * the minimum setting to prevent fifo underflow.
  3768. *
  3769. * lFifoThresh = (lTransferTime/lReadPeriod) - lDWORDsWritten;
  3770. * = ((tr_fifoa_4 + lTrFifoB2 + tr_fifoa_remaining)/lReadPeriod)
  3771. * - lDWORDsWritten
  3772. * to simplify calcuation, break out constant part of equation
  3773. * K1 = ((tr_fifoa_4 + lTrFifoB2)/lReadPeriod) - lDWORDsWritten;
  3774. *
  3775. * lFifoThresh = K1 + (tr_fifoa_remaining/lReadPeriod);
  3776. * = K1 + (fifoa_remaining * lEffWritePeriod)/lReadPeriod;
  3777. * lFifoThresh = K1 +
  3778. * ((FIFO_DEPTH - lFifoThresh + 4 - (lTrFifoAFirst4/lReadPeriod)) *
  3779. * lEffWritePeriod)/lReadPeriod;
  3780. *
  3781. * break out another constant to simplify reduction
  3782. * K2 = (FIFO_DEPTH + 4 - (lTrFifoAFirst4/lReadPeriod))
  3783. * * (lEffWritePeriod/lReadPeriod);
  3784. * lFifoThresh = K1 + K2 - (lFifoThresh * (lEffWritePeriod/lReadPeriod));
  3785. * lFifoThresh * (1 + (lEffWritePeriod/lReadPeriod)) = K1 + K2;
  3786. * lFifoThresh = (K1 + K2)/(1 + (lEffWritePeriod/lReadPeriod);
  3787. *
  3788. * Once the threshold setting is determined, another calculation must
  3789. * be performed to determine if available bandwidth exists given the
  3790. * zoom factor. The worst case is assumed to be when FIFO A and
  3791. * FIFO B reach the threshold point at the same time. The sequence
  3792. * is then to abort the cpu/blt, fill fifo a, then fill fifo b.
  3793. *
  3794. * Since FIFO A is full when the fill B operation starts, I only have
  3795. * to determine how long it takes to fill FIFO B and then calculate
  3796. * the the number of dwords read from A during that time.
  3797. *
  3798. * lTransferTime = (lTrFifoB2 + (CRT_FIFO_DEPTH * lEffWritePeriod))/lReadPeriod;
  3799. * lFifoALevels = CRT_FIFO_DEPTH - (lTransferTime/lReadPeriod);
  3800. *
  3801. * if lFifoALevels < 1, then underflow condition may occur.
  3802. */
  3803. if (lZoom < 512)
  3804. {
  3805. // 5446 requires at least a 2X zoom for Y interpolation
  3806. return (FALSE);
  3807. }
  3808. lWritePeriod = ppdev->lMCLKPeriod * 2/(ppdev->lBusWidth/4);
  3809. lReadPeriod = (lVideoPixelsPerDWORD * lVCLKPeriod * lZoom)/256;
  3810. lEffWritePeriod = ((lReadPeriod * lWritePeriod)/
  3811. (lReadPeriod - lWritePeriod));
  3812. lTrFifoAFirst4 = (BLIT_LATENCY + ppdev->lRandom + 3*(ppdev->lPageMiss)) *
  3813. ppdev->lMCLKPeriod;
  3814. lTrFifoB2 = (ppdev->lRandom + ppdev->lPageMiss) * ppdev->lMCLKPeriod;
  3815. lDWORDsWritten = 2 * (ppdev->lBusWidth/4);
  3816. K1 = ((lTrFifoAFirst4 + lTrFifoB2)/lReadPeriod) - lDWORDsWritten;
  3817. K2 = (CRT_FIFO_DEPTH + (4*(ppdev->lBusWidth/4)) -
  3818. (lTrFifoAFirst4/lReadPeriod))
  3819. * (lEffWritePeriod/lReadPeriod);
  3820. ppdev->lFifoThresh = (1 + ((K1 + K2)/(1 + (lEffWritePeriod/lReadPeriod))));
  3821. ppdev->lFifoThresh += 3;
  3822. lTransferTime = (lTrFifoB2 + (CRT_FIFO_DEPTH * lEffWritePeriod));
  3823. lFifoALevels = ((CRT_FIFO_DEPTH - (lTransferTime/lReadPeriod))/2);
  3824. if (ppdev->bDoubleClock)
  3825. {
  3826. ppdev->lFifoThresh <<= 1;
  3827. }
  3828. if ((lFifoALevels < 2) || (ppdev->lFifoThresh > (CRT_FIFO_DEPTH/2)))
  3829. {
  3830. return (0);
  3831. }
  3832. else
  3833. {
  3834. return (1);
  3835. }
  3836. }
  3837. /*
  3838. * Check bandwidth for color keying
  3839. */
  3840. else if (dwFlags & (OVERLAY_FLG_COLOR_KEY | OVERLAY_FLG_SRC_COLOR_KEY))
  3841. {
  3842. /*
  3843. * This mode utilizes both FIFOs A and B. During horizontal blank,
  3844. * both fifos are filled. FIFO a is then filled with graphics data
  3845. * during regions 1,2 and 3. FIFO B is filled with video data
  3846. * during region 2, and is idle during regions 1 and 3.
  3847. *
  3848. * The normal memory sequence for this mode goes as follows.
  3849. *
  3850. * ----------------------------------------------------------------
  3851. * | cpu/blit cycle | FIFO A fill | FIFO B fill | cpu/blit cycle .
  3852. * ----------------------------------------------------------------
  3853. * or
  3854. * ----------------------------------------------------------------
  3855. * | cpu/blit cycle | FIFO B fill | FIFO A fill | cpu/blit cycle .
  3856. * ----------------------------------------------------------------
  3857. *
  3858. * For this mode, the FIFO threshold must be set high enough to allow
  3859. * enough time to abort the cpu/blt, fill FIFO A, then transfer data
  3860. * into FIFO B before underflow occurs. If the fifob read rate is
  3861. * greater than the fifoa read rate, then allow eough time for
  3862. * a t CPU/blt abort, followed by a fifo B fill, then a FIFO A fill.
  3863. *
  3864. * Worst case condition for filling the CRT fifo :
  3865. *
  3866. * 1) CPU/blit latency ->
  3867. * 2) FIFO A random ->
  3868. * 3) FIFO A page miss ->
  3869. * 6) FIFO A page mode fill -->
  3870. * 7) FIFO B random -->
  3871. * 8) FIFO B page miss
  3872. *
  3873. * or
  3874. *
  3875. * 1) CPU/blit latency ->
  3876. * 2) FIFO B random ->
  3877. * 3) FIFO A page miss ->
  3878. * 6) FIFO A page mode fill -->
  3879. * 7) FIFO B random -->
  3880. * 8) FIFO B page miss
  3881. *
  3882. *
  3883. * 1) lTransferTime = lMCLKPeriod *
  3884. * (BLIT_LATENCY + lRandom + lPageMiss +
  3885. * fifoa_remaining +
  3886. * lRandom + lPageMiss;
  3887. *
  3888. * or
  3889. * 2) lTransferTime = lMCLKPeriod *
  3890. * (BLIT_LATENCY + lRandom + lPageMiss +
  3891. * fifob_remaining +
  3892. * lRandom + lPageMiss;
  3893. *
  3894. *
  3895. * lFifoAReadPeriod = lVCLKPeriod * lGraphicsPixelsPerDWORD;
  3896. * lFifoBReadPeriod = (lVCLKPeriod * lVideoPixelsPerDWORD * lZoom)*256;
  3897. *
  3898. * if (lFifoAReadPeriod > lFifoBReadPeriod), then
  3899. * first fifo is fifo B, otherwise first is fifo A.
  3900. * The followinf euqations are written for a fifoa->fifob,
  3901. * sequence, but the fifob->fifoa sequence can be obtained simply
  3902. * by swapping the fifo read periods.
  3903. *
  3904. * The time required to fill a FIFO depends upon the read rate
  3905. * of the FIFO and the number of levels that must be filled,
  3906. * as determined by the threshold setting.
  3907. *
  3908. * The worst case fill time for the first four levels of fifo A is
  3909. * lTrFifoAFirst4 = (BLIT_LATENCY + lRandom + lPageMiss) *
  3910. * lMCLKPeriod;
  3911. *
  3912. * The number of dwords depleted from fifo A during the
  3913. * fill of the first four levels is
  3914. * fifoa_reads_4 = lTrFifoAFirst4/lFifoAReadPeriod;
  3915. *
  3916. * The number of empty levels remaining in the fifo after
  3917. * the fill of the first four levels is
  3918. * fifoa_remaining = FIFO_DEPTH - lFifoThresh + ((4*ramwidth)/4)
  3919. * - lTrFifoAFirst4/lFifoAReadPeriod;
  3920. *
  3921. * The amount of time required to fill the remaining levels of
  3922. * fifo A is determined by the write rate and the read rate.
  3923. * lWritePeriod = lMCLKPeriod * 2; * 2 clks per cas
  3924. * eff_write_period = ((lFifoAReadPeriod * lWritePeriod)/
  3925. * (lFifoAReadPeriod - lWritePeriod));
  3926. *
  3927. * tr_fifoa_remaining = fifoa_remaining * eff_write_period;
  3928. *
  3929. *
  3930. * The total amount of time for the cpu/blt latency and the
  3931. * fifo A fill is
  3932. * tr_fifoa_total = lTrFifoAFirst4 + tr_fifoa_remaining;
  3933. *
  3934. * The worse case fill time for fifo B is as follows:
  3935. * lTrFifoB2 = (lRandom + lPageMiss) * lMCLKPeriod;
  3936. *
  3937. * The total amount of time elapsed from the crt request until
  3938. * the first 2 fifob cycles are completed is
  3939. * lTransferTime = tr_fifoa_total + lTrFifoB2;
  3940. *
  3941. * The number of dwords transferred to the fifo during this time
  3942. * is 2 for 32 bit memory interface or 4 for 64 bit interface.
  3943. * lDWORDsWritten = 2 * (lBusWidth/4)
  3944. *
  3945. * During this period, data continues to be read from the crt
  3946. * fifo B for screen refresh. The amount of data read,
  3947. * is approximately:
  3948. * lFifoBReadPeriod = (lVCLKPeriod * lVideoPixelsPerDWORD * lZoom)/256;
  3949. * dwords_read = lTransferTime/lFifoBReadPeriod
  3950. *
  3951. * The difference between the dwords read and dwords
  3952. * written must be accounted for in the fifo trheshold setting
  3953. *
  3954. * lFifoThresh = (dwords_read - lDWORDsWritten) rounded
  3955. * up to next even value.
  3956. *
  3957. * Since the lTransferTime and dwords_read depends on the
  3958. * threshold setting, a bit of algebra is required to determine
  3959. * the minimum setting to prevent fifo underflow.
  3960. *
  3961. * lFifoThresh = (lTransferTime/lFifoBReadPeriod) - lDWORDsWritten;
  3962. * = ((tr_fifoa_4 + lTrFifoB2 + tr_fifoa_remaining)/lFifoBReadPeriod)
  3963. * - lDWORDsWritten
  3964. * to simplify calcuation, break out constant part of equation
  3965. * K1 = ((tr_fifoa_4 + lTrFifoB2)/lFifoBReadPeriod) - lDWORDsWritten;
  3966. *
  3967. * lFifoThresh = K1 + (tr_fifoa_remaining/lFifoBReadPeriod);
  3968. * = K1 + (fifoa_remaining * eff_write_period)/lFifoBReadPeriod;
  3969. * lFifoThresh = K1 +
  3970. * ((FIFO_DEPTH - lFifoThresh + 4 - (lTrFifoAFirst4/lFifoAReadPeriod)) *
  3971. * eff_write_period)/read_period;
  3972. *
  3973. * break out another constant to simplify reduction
  3974. * K2 = (FIFO_DEPTH + 4 - (lTrFifoAFirst4/lFifoAReadPeriod))
  3975. * * (eff_write_period/lFifoBReadPeriod);
  3976. * lFifoThresh = K1 + K2 - (lFifoThresh * (eff_write_period/lFifoBReadPeriod));
  3977. * lFifoThresh * (1 + (eff_write_period/read_period)) = K1 + K2;
  3978. * lFifoThresh = (K1 + K2)/(1 + (eff_write_period/lFifoBReadPeriod);
  3979. *
  3980. * Once the threshold setting is determined, another calculation must
  3981. * be performed to determine if available bandwidth exists given the
  3982. * zoom factor. The worst case is assumed to be when FIFO A and
  3983. * FIFO B reach the threshold point at the same time. The sequence
  3984. * is then to abort the cpu/blt, fill fifo a, then fill fifo b.
  3985. *
  3986. * Since FIFO A is full when the fill B operation starts, I only have
  3987. * to determine how long it takes to fill FIFO B and then calculate
  3988. * the the number of dwords read from A during that time.
  3989. *
  3990. * lTransferTime = (lTrFifoB2 + (CRT_FIFO_DEPTH * fifob_eff_write_period))/read_period;
  3991. * fifoa_levels = CRT_FIFO_DEPTH - (lTransferTime/read_period);
  3992. *
  3993. * if fifoa_levels < 1, then underflow condition may occur.
  3994. */
  3995. lWritePeriod = ppdev->lMCLKPeriod * 2/(ppdev->lBusWidth/4);
  3996. lFifoAReadPeriod = lGraphicsPixelsPerDWORD * lVCLKPeriod;
  3997. lFifoBReadPeriod = (lVideoPixelsPerDWORD * lVCLKPeriod * lZoom)/256;
  3998. if (lFifoAReadPeriod <= lWritePeriod) // this fails, so set a big#
  3999. {
  4000. lFifoAEffWritePeriod = 5000;
  4001. }
  4002. else
  4003. {
  4004. lFifoAEffWritePeriod = ((lFifoAReadPeriod * lWritePeriod)/
  4005. (lFifoAReadPeriod - lWritePeriod));
  4006. }
  4007. if (lFifoBReadPeriod <= lWritePeriod) // this fails, so set a big#
  4008. {
  4009. lFifoBEffWritePeriod = 5000;
  4010. }
  4011. else
  4012. {
  4013. lFifoBEffWritePeriod = ((lFifoBReadPeriod * lWritePeriod)/
  4014. (lFifoBReadPeriod - lWritePeriod));
  4015. }
  4016. if ((lFifoAReadPeriod == 0) || (lFifoBReadPeriod == 0) ||
  4017. (lWritePeriod == 0))
  4018. {
  4019. return (FALSE);
  4020. }
  4021. // These values should be the same for bot the fifoa->fifob
  4022. // and fifob->fifoa sequences
  4023. lTrFifoAFirst4 = (BLIT_LATENCY + ppdev->lRandom + 2*(ppdev->lPageMiss)) *
  4024. ppdev->lMCLKPeriod;
  4025. lTrFifoB2 = (ppdev->lRandom + ppdev->lPageMiss) * ppdev->lMCLKPeriod;
  4026. lDWORDsWritten = 2 * (ppdev->lBusWidth/4);
  4027. // Since I'm not sure which sequence is worse
  4028. // Try both then pick worse case results
  4029. // For fifoa->fifob sequence
  4030. K1 = ((lTrFifoAFirst4 + lTrFifoB2)/lFifoBReadPeriod) - lDWORDsWritten;
  4031. K2 = (CRT_FIFO_DEPTH + (4*(ppdev->lBusWidth/4)) -
  4032. (lTrFifoAFirst4/lFifoAReadPeriod))
  4033. * (lFifoAEffWritePeriod/lFifoBReadPeriod);
  4034. lFifoAThresh = (1 + ((K1 + K2)/
  4035. (1 + (lFifoAEffWritePeriod/lFifoBReadPeriod))));
  4036. lFifoAThresh += 3;
  4037. lTransferTime = (lTrFifoB2 + (CRT_FIFO_DEPTH * lFifoBEffWritePeriod));
  4038. lFifoALevels = ((CRT_FIFO_DEPTH - (lTransferTime/lFifoAReadPeriod))/2);
  4039. // For fifob->fifoa sequence
  4040. K1 = ((lTrFifoAFirst4 + lTrFifoB2)/lFifoAReadPeriod) - lDWORDsWritten;
  4041. K2 = (CRT_FIFO_DEPTH + (4*(ppdev->lBusWidth/4)) -
  4042. (lTrFifoAFirst4/lFifoBReadPeriod))
  4043. * (lFifoBEffWritePeriod/lFifoAReadPeriod);
  4044. lFifoBThresh = (1 + ((K1 + K2)/
  4045. (1 + (lFifoBEffWritePeriod/lFifoAReadPeriod))));
  4046. lFifoBThresh += 3;
  4047. lTransferTime = (lTrFifoB2 + (CRT_FIFO_DEPTH * lFifoAEffWritePeriod));
  4048. lFifoBLevels = ((CRT_FIFO_DEPTH - (lTransferTime/lFifoBReadPeriod))/2);
  4049. if (lFifoAThresh > lFifoBThresh)
  4050. {
  4051. ppdev->lFifoThresh = lFifoAThresh;
  4052. }
  4053. else
  4054. {
  4055. ppdev->lFifoThresh = lFifoBThresh;
  4056. }
  4057. if (ppdev->bDoubleClock)
  4058. {
  4059. ppdev->lFifoThresh <<= 1;
  4060. }
  4061. if ((lFifoBLevels <0) || (lFifoALevels < 0) ||
  4062. (ppdev->lFifoThresh > (CRT_FIFO_DEPTH/2)))
  4063. {
  4064. return (0);
  4065. }
  4066. else
  4067. {
  4068. return (1);
  4069. }
  4070. }
  4071. return (1); // Should never get here!!
  4072. }
  4073. // chu03
  4074. /**********************************************************
  4075. *
  4076. * Name: Is5480SufficientBandwidth
  4077. *
  4078. * Module Abstract:
  4079. * ----------------
  4080. * This function reads the current MCLK, VLCK, bus width, etc.
  4081. * and determines whether the chip has sufficient bandwidth
  4082. * to handle the requested mode.
  4083. *
  4084. * Output Parameters:
  4085. * ------------------
  4086. * none
  4087. *
  4088. ***********************************************************/
  4089. // -------------------------------------------------------------
  4090. // Overview by John Schafer
  4091. // -------------------------------------------------------------
  4092. // The memory arbitration scheme for the 5480 has changed
  4093. // significantly from the 5446. The 5480 is set up on a first
  4094. // come, first serve basis. If more than 1 request arrive at
  4095. // the same clock edge, then the BankSelect is used to determine
  4096. // which request to acknowledge first. Using SDRAM, the row
  4097. // access to a differennt bank can be hidden, which saves up to
  4098. // 7 MCLKs. If all bank selects for the concurrent requests are
  4099. // the same, the default prority is FIFOA->FIFOB->FIFOC->VCAP.
  4100. //
  4101. // The FIFO sizes for the 5480 are as follows:
  4102. // FIFOA, FIFOB, FIFOC : 32x64
  4103. // VCAP : 16x64 (two 8x64 fifos)
  4104. //
  4105. // The Y interpolation mode for the 5480 is "free" due to
  4106. // the embedded line store. The available mode combinations
  4107. // for the 5480 which effect bandwidth are :
  4108. //
  4109. // 1) Capture enabled, 1 video window, no occlusion, not 420 format
  4110. // 2) Capture enabled, 1 video window, no occlusion, 420 format
  4111. // 3) Capture enabled, 1 video window, occlusion, not 420 format
  4112. // 4) Capture enabled, 1 video window, occlusion, 420 format
  4113. // 5) Capture enabled, 2 video windows (occlusion implied)
  4114. // 6) Capture disabled, 1 video window, no occlusion, not 420 format
  4115. // 7) Capture disabled, 1 video window, no occlusion, 420 format
  4116. // 8) Capture disabled, 1 video window, occlusion, not 420 format
  4117. // 9) Capture disabled, 1 video window, occlusion, 420 format
  4118. // 10) Capture disabled, 2 video windows (occlusion implied)
  4119. //
  4120. //
  4121. // -------------------------------------------------------------
  4122. // FIFO threshold description
  4123. // -------------------------------------------------------------
  4124. // The memory requests are generated based on the threshold settings
  4125. // of each FIFO. CRT FIFO thresholds during non-video window lines
  4126. // are determined by SR16(3:0). CRT FIFO thresholds during video
  4127. // window lines are determined by CR5C(3:0).
  4128. // The VCAP fifo threshold is a fixed setting of 8 QWORDS (half).
  4129. //
  4130. // The 4 bit threshold for FIFOs A,B, and C indicate the FIFO
  4131. // level in double QWORDS at which the FIFO request is asserted.
  4132. // For example, a setting of 4 indicates that the request is
  4133. // generated when the FIFO level is reduced to 8 QWORDS.
  4134. // A setting of 0 is a special case which indicates that the
  4135. // FIFO must be full to prevent a request (i.e. 32 QWORDS).
  4136. //
  4137. // The objective of the bandwidth equations is to calculate
  4138. // the optimum threshold setting and determine which display
  4139. // modes may be supported for given MCLK and VCLK frequencies.
  4140. //
  4141. // The critical parameters which determine the bandwidth limits
  4142. // are the read and effective write rates for each FIFO.
  4143. //
  4144. // -------------------------------------------------------------
  4145. // FIFO read/write rates for CRT FIFOs
  4146. // -------------------------------------------------------------
  4147. // The read rate for FIFO A (graphics FIFO) is determined by
  4148. // the graphics pixel depth and the VCLK frequency.
  4149. // fa_read_rate = gr_bytes_per_pixel * vclk_period
  4150. //
  4151. // The read rates for FIFO B and C are determined differently
  4152. // depending on display mode. For 420 format the read periods
  4153. // in nanosecs per byte are as follows:
  4154. // fb_read_period = ((vclk_period*4) * hzoom) / hdecimate;
  4155. // fc_read_period = ((vclk_period*4) * hzoom) / hdecimate;
  4156. //
  4157. // In this equation hdecimate is specified as 1/decimation_scale,
  4158. // i.e a 1/2 decimate implies hdecimate = 2
  4159. //
  4160. // For non 420 format the rates are:
  4161. // fb_read_period = ((vclk_period/vw_bytes_per_pixel) * hzoom) /
  4162. // hdecimate;
  4163. // fc_read_period = (vclk_period/vw_bytes_per_pixel);
  4164. //
  4165. // Since the FIFOs can be read and written simultaneously,
  4166. // the effective write rate is determined by the actual fifo
  4167. // write rate and tje fifo read rate. The actual write rate is based
  4168. // on single mclk display memory reads. The memory read period is
  4169. // calculated in terms of nanoseconds per byte.
  4170. //
  4171. // bytes_per_memory_transfer is equal to 4 for 32 bit i/f, 8 for 64 bit i/f
  4172. // mem_read_period = mclk_period/bytes_per_mem_transfer
  4173. // fa_eff_write_period = (mem_read_period * fa_read_period)/
  4174. // (fa_read_period - mem_read_period);
  4175. // fb_eff_write_period = (mem_read_period * fb_read_period)/
  4176. // (fb_read_period - mem_read_period);
  4177. // fc_eff_write_period = (mem_read_period * fc_read_period)/
  4178. // (fc_read_period - mem_read_period);
  4179. // -------------------------------------------------------------
  4180. // FIFO read/write rates for VCAP fifo
  4181. // -------------------------------------------------------------
  4182. // The video capture write rate is based on the data rate
  4183. // from the video capture interface. Since the video capture
  4184. // interface can perform format conversion (e.g. 422->PackJR) and
  4185. // decimation, the capture data rate may be smaller than the actual
  4186. // video port data rate. The capture period in the following equation
  4187. // is defined in terms of nanoseconds per byte. The decimation factor
  4188. // may vary from 1 to 1/256.
  4189. //
  4190. // vcap_write_period = (vport_pixel_period/capture_bytes_per_pixel) *
  4191. // (vport_decimation);
  4192. // In this equation vport_decimation is specified as 1/decimation_scale,
  4193. // i.e a 1/2 decimate implies vport_decimation = 2
  4194. //
  4195. //
  4196. // Since the VCAP fifo can be read and written simultaneously,
  4197. // the effective read rate is determined by the fifo write rate as well
  4198. // as the actual fifo read rate. The actual fifo read rate is based on two
  4199. // memory clock cycle display memory writes. The calculations are in terms
  4200. // of nanoseconds per byte.
  4201. // bytes_per_memory_transfer = 4 for 32 bit i/f, or 8 for 64 bit i/f
  4202. // mem_write_period = 2 * mclk_period/bytes_per_mem_transfer
  4203. //
  4204. // vcap_eff_read_period = (mem_write_period * vcap_write_period)/
  4205. // (vcap_write_period - mem_write_period);
  4206. //
  4207. // -------------------------------------------------------------------
  4208. // How to determine if FIFO ABC underflow or VCAP fifo overflow occurs
  4209. // -------------------------------------------------------------------
  4210. //
  4211. // I will examine a few worst case scenarios to determine if adequate
  4212. // bandwidth exists to support a given mode.
  4213. //
  4214. // Case #1 - start of graphics line where all 3 CRT fifos must be filled
  4215. //
  4216. // This condition occurs after hsync when the 3 CRT FIFOs are being
  4217. // prefilled before the start of the active line. The only risk here is
  4218. // that the video capture fifo may overflow during the consecutive fills
  4219. // of fifos A,B, and C. The threshold setting does not matter since the
  4220. // CRT fifos are cleared on reset and thus guaranteed to be empty.
  4221. //
  4222. // For a 32 bit memory interface :
  4223. // fabc_fill_time = (BLIT_LATENCY * mclk_period) +
  4224. // 3 * ((RAS_PRECHARGE + 64) * mclk_period)
  4225. //
  4226. // For a 64 bit memory interface :
  4227. // fabc_fill_time = (BLIT_LATENCY * mclk_period) +
  4228. // 3 * ((RAS_PRECHARGE + 32) * mclk_period)
  4229. //
  4230. // A capture fifo overflow occurs if fabc_fill_time is greater than
  4231. // VCAP fill time based on the worst case 30 MB/s capture rate.
  4232. //
  4233. // For a worst case memory interface scenario, let's assume a 32 bit
  4234. // interface with a 66 MHz memory clock, a blit latency of 10 mclks,
  4235. // and a ras precharge of 7 mclks. The fabc_fill_time is
  4236. // then
  4237. // fabc_fill_time = (10 * 15.2) +
  4238. // 3 * ((64 + 7) * 15.2) = 3390 ns
  4239. //
  4240. // Assuming the worst case 30 MB/s capture rate, the number of
  4241. // bytes written to the capture fifo during the fabc_fill_time is
  4242. // 3390 ns * (1 byte/33 ns) = 103 bytes
  4243. //
  4244. // Since the capture fifo is 128 bytes deep, the worst case scenario
  4245. // is OK so long as the capture fifo is emptied prior to the fabc_fill.
  4246. //
  4247. //
  4248. //
  4249. // Case #2 - Consecutive requests
  4250. //
  4251. // It seems that the worst case for servicing of requests is when the requests occur
  4252. // on consecutive mclks with the order of requests being from the slowest to the
  4253. // fastest data consumer. In other words, the first to be serviced is the capture fifo,
  4254. // then the 3 CRT fifos in the order of decreasing read_period.
  4255. //
  4256. // First calculate actual and effective read and write periods as decribed above.
  4257. // Then determine how many requests are active, this is a maximum of 4 if capture
  4258. // is enabled and all 3 CRT fifos are enabled. Assume that the capture rate
  4259. // is the slowest and thus is always serviced first. Then order the active
  4260. // CRT requests as f1 through f3, where f1 has the longest read period and
  4261. // f3 has the shortest.
  4262. //
  4263. // The sequence of events then becomes:
  4264. // empty vcap -> fill 1 -> fill 2 -> fill 3
  4265. //
  4266. //
  4267. // Depending on the number of active crt fifos, the fill 2 and fill 3 operations may
  4268. // be ommitted. The vcap empty is obviously ommitted if capture is not enabled.
  4269. //
  4270. // Now step through the sequence and verify that crt fifo underflows and capture
  4271. // underflows do not occur.
  4272. //
  4273. // If capture is enabled, calculate the latency and empty times
  4274. // vcap_latency = (BLIT_LATENCY + RAS_PRECHARGE) * mclk_period;
  4275. // vcap_bytes_to_empty = CAP_FIFO_DEPTH;
  4276. // vcap_empty_time = (vcap_read_period * vcap_bytes_to_empty);
  4277. // Since one of the capture fifos continues to fill while the other is being
  4278. // emptied, calculate the number of filled levels in the capture fifo at
  4279. // the end of the memory transfer.
  4280. // vcap_levels_remaining = (vcap_latency + vcap_empty_time)/vcap_write_period;
  4281. // If the number of levels filled exceeds the fifo depth, then an overflow occurred.
  4282. //
  4283. // Note that the VCAP FIFO operates differently than the CRT fifos. The VCAP
  4284. // FIFO operates as 2 8x64 FIFOs. A memory request is asserted when one of the
  4285. // FIFOs is full. The capture interface then fills the other fifo while the
  4286. // full fifo is being serviced by the sequencer. Using this method, the transfer
  4287. // to memory is always 16 QWORDs for VCAP data (except special end of line conditions).
  4288. //
  4289. // Now check fifo 1. If capture was enabled then the latency for fifo 1 is:
  4290. // f1_latency = vcap_latency + vcap_empty_time +
  4291. // (BLIT_LATENCY + RAS_PRECHARGE) * mclk_period;
  4292. //
  4293. // otherwise the latency is:
  4294. // f1_latency = (BLIT_LATENCY + RAS_PRECHARGE) * mclk_period;
  4295. //
  4296. // Calculate the number of empty levels in fifo 1, i.e. the number of bytes
  4297. // that must be filled.
  4298. // f1_bytes_to_fill = ((16-threshold) * 16) + (f1_latency/f1_read_period);
  4299. // If the number of levels to be filled exceeds the fifo depth, then an underflow occurred.
  4300. // Calculate the fill time based on the effective fifo write rate.
  4301. // f1_fill_time = (f1_eff_write_period * f1_bytes_to_fill);
  4302. //
  4303. // If fifo_2 is active, calculate its latency and bytes to be filled.
  4304. // f2_latency = f1_latency + f1_fill_time +
  4305. // (RAS_PRECHARGE * mclk_period);
  4306. // f2_bytes_to_fill = ((16-threshold) * 16) + (f2_latency/f2_read_period);
  4307. // If the number of levels to be filled exceeds the fifo depth, then an underflow occurred.
  4308. // Calculate the fill time based on the effective fifo write rate.
  4309. // f2_fill_time = (f2_eff_write_period * f2_bytes_to_fill);
  4310. //
  4311. // If fifo_2 is active, calculate its latency and bytes to be filled.
  4312. // f3_latency = f2_latency + f2_fill_time +
  4313. // (RAS_PRECHARGE * mclk_period);
  4314. // f3_bytes_to_fill = ((16-threshold) * 16) + (f3_latency/f3_read_period);
  4315. // If the number of levels to be filled exceeds the fifo depth, then an underflow occurred.
  4316. // Calculate the fill time based on the effective fifo write rate.
  4317. // f3_fill_time = (f3_eff_write_period * f3_bytes_to_fill);
  4318. //
  4319. // Now go back to the start of sequence and make sure that none of the FIFOs
  4320. // have already initiated another request. The totla latency is the amount
  4321. // of time required to execute the entire sequence.
  4322. //
  4323. // Check vcap fif status if capture is enabled,
  4324. // vcap_latency = total_latency;
  4325. // vcap_bytes_to_empty = (total_latency/vcap_write_period);
  4326. //
  4327. // Check fifo 1 status
  4328. // f1_latency = (total_latency - f1_latency - f1_fill_time);
  4329. // f1_bytes_to_fill = (f1_latency/f1_read_period);
  4330. //
  4331. // Check fifo 2 status if active
  4332. // f2_latency = (total_latency - f1_latency - f1_fill_time);
  4333. // f3_bytes_to_fill = (f1_latency/f1_read_period);
  4334. //
  4335. //***************************************************************************
  4336. static BOOL Is5480SufficientBandwidth (PDEV* ppdev,
  4337. WORD wVideoDepth,
  4338. LPRECTL lpSrc,
  4339. LPRECTL lpDest,
  4340. DWORD dwFlags)
  4341. {
  4342. long lVideoPixelsPerDWORD;
  4343. long lGraphicsPixelsPerDWORD;
  4344. long lCapturePixelsPerDWORD;
  4345. long lVideoBytesPerPixel;
  4346. long lGraphicsBytesPerPixel;
  4347. long lCaptureBytesPerPixel;
  4348. long lVCLKPeriod;
  4349. long lZoom;
  4350. long lFifoAReadPeriod;
  4351. long lFifoBReadPeriod;
  4352. long lFifoCReadPeriod;
  4353. long lFifoAEffWritePeriod;
  4354. long lFifoBEffWritePeriod;
  4355. long lFifoCEffWritePeriod;
  4356. long lMemReadPeriod;
  4357. long lVPortPixelPeriod;
  4358. long lVCapReadPeriod;
  4359. long lVCapWritePeriod;
  4360. long lFifo1ReadPeriod;
  4361. long lFifo2ReadPeriod;
  4362. long lFifo3ReadPeriod;
  4363. long lFifo1EffWritePeriod;
  4364. long lFifo2EffWritePeriod;
  4365. long lFifo3EffWritePeriod;
  4366. long lVCapLatency;
  4367. long lVCapBytesToEmpty;
  4368. long lVCapEmptyTime;
  4369. long lVCapLevelRemaining;
  4370. long lFifo1Latency;
  4371. long lFifo1BytesToFill;
  4372. long lFifo1FillTime;
  4373. long lFifo2Latency;
  4374. long lFifo2BytesToFill;
  4375. long lFifo2FillTime;
  4376. long lFifo3Latency;
  4377. long lFifo3BytesToFill;
  4378. long lFifo3FillTime;
  4379. long lThreshold;
  4380. int CrtFifoCount;
  4381. BOOL bCapture;
  4382. BOOL bFifoAEnable;
  4383. BOOL bFifoBEnable;
  4384. BOOL bFifoCEnable;
  4385. BOOL bModePass;
  4386. long lHorizDecimate;
  4387. long lVPortDecimate;
  4388. long lTotalLatency;
  4389. long lVCLK;
  4390. UCHAR tempB ;
  4391. BYTE* pjPorts = ppdev->pjPorts ;
  4392. #define CAP_FIFO_DEPTH 64
  4393. #define RAS_PRECHARGE 7
  4394. #define BLIT_LATENCY 9
  4395. //
  4396. // Parameter checking
  4397. //
  4398. lHorizDecimate = 1;
  4399. lVPortDecimate = 1;
  4400. //
  4401. // Convert input parameters
  4402. //
  4403. if (wVideoDepth == 16)
  4404. {
  4405. lVideoPixelsPerDWORD = 2;
  4406. lCapturePixelsPerDWORD = 2;
  4407. }
  4408. else if (wVideoDepth == 8)
  4409. {
  4410. lVideoPixelsPerDWORD = 4;
  4411. lCapturePixelsPerDWORD = 4;
  4412. }
  4413. else return (FALSE);
  4414. if (ppdev->cBitsPerPixel == 8)
  4415. {
  4416. lGraphicsPixelsPerDWORD = 4;
  4417. }
  4418. else if (ppdev->cBitsPerPixel == 16)
  4419. {
  4420. lGraphicsPixelsPerDWORD = 2;
  4421. }
  4422. else if (ppdev->cBitsPerPixel == 24)
  4423. {
  4424. lGraphicsPixelsPerDWORD = 1;
  4425. }
  4426. else return (FALSE);
  4427. lGraphicsBytesPerPixel = 4 / lGraphicsPixelsPerDWORD;
  4428. lVideoBytesPerPixel = 4 / lVideoPixelsPerDWORD;
  4429. lCaptureBytesPerPixel = 4 / lCapturePixelsPerDWORD;
  4430. lZoom = (lpDest->right - lpDest->left) /
  4431. (lpSrc->right - lpSrc->left);
  4432. if (lZoom < 1)
  4433. lZoom = 1;
  4434. //
  4435. // We need to get the VCLK every time since this can change at run-time
  4436. //
  4437. lVCLK = GetVCLK(ppdev);
  4438. lVCLKPeriod = (long) ((1024000000l/lVCLK) + 1);
  4439. //
  4440. // Video port at 13.5 MHz
  4441. //
  4442. lVPortPixelPeriod = (long) ((10240000) / 135);
  4443. //
  4444. // Graphics CRT FIFO read rate
  4445. //
  4446. lFifoAReadPeriod = lGraphicsBytesPerPixel * lVCLKPeriod;
  4447. //
  4448. // Video FIFO read rate
  4449. //
  4450. if(dwFlags & OVERLAY_FLG_YUVPLANAR)
  4451. {
  4452. lFifoBReadPeriod = ((lVCLKPeriod * 4) * lZoom) / lHorizDecimate;
  4453. lFifoCReadPeriod = ((lVCLKPeriod * 4) * lZoom) / lHorizDecimate;
  4454. }
  4455. else
  4456. {
  4457. lFifoBReadPeriod = ((lVCLKPeriod / lVideoBytesPerPixel) * lZoom)
  4458. / lHorizDecimate;
  4459. lFifoCReadPeriod = lVCLKPeriod / lVideoBytesPerPixel;
  4460. }
  4461. DISPDBG ((2, "lFifoAReadPeriod = %ld, lFifoBReadPeriod=%ld\n",
  4462. lFifoAReadPeriod, lFifoBReadPeriod));
  4463. DISPDBG ((2, "lFifoCReadPeriod = %ld\n", lFifoCReadPeriod));
  4464. //
  4465. // Video capture write period
  4466. //
  4467. lVCapWritePeriod = (lVPortPixelPeriod / lCaptureBytesPerPixel)
  4468. * lVPortDecimate;
  4469. if (!ppdev->lBusWidth)
  4470. {
  4471. //
  4472. // We will read the bus width from SR0F[4:3]
  4473. //
  4474. CP_OUT_BYTE (pjPorts, SR_INDEX, 0x0F) ;
  4475. if ((CP_IN_BYTE(pjPorts, SR_DATA) & 0x18) == 0x18)
  4476. ppdev->lBusWidth = 8; // 64 bit bus
  4477. else
  4478. ppdev->lBusWidth = 4; // 32 bit bus
  4479. }
  4480. if (!ppdev->lMCLKPeriod)
  4481. {
  4482. LONG lMCLK;
  4483. //
  4484. // The MCLK period is the amount of time required for one cycle.
  4485. // We will round up.
  4486. //
  4487. CP_OUT_BYTE (pjPorts, SR_INDEX, 0x1F) ; // First get the MCLK frequency
  4488. lMCLK = CP_IN_BYTE(pjPorts, SR_DATA);
  4489. lMCLK *= 14318;
  4490. lMCLK >>= 3;
  4491. ppdev->lMCLKPeriod = (long) ((1024000000l/lMCLK) + 1);
  4492. }
  4493. //
  4494. // Calculate CRT effective read and write periods
  4495. //
  4496. lMemReadPeriod = ppdev->lMCLKPeriod / ppdev->lBusWidth;
  4497. if (lFifoAReadPeriod == lMemReadPeriod)
  4498. lFifoAEffWritePeriod = 1000000000;
  4499. else
  4500. lFifoAEffWritePeriod = (lMemReadPeriod * lFifoAReadPeriod) /
  4501. (lFifoAReadPeriod - lMemReadPeriod);
  4502. if (lFifoBReadPeriod == lMemReadPeriod)
  4503. lFifoBEffWritePeriod = 1000000000;
  4504. else
  4505. lFifoBEffWritePeriod = (lMemReadPeriod * lFifoBReadPeriod) /
  4506. (lFifoBReadPeriod - lMemReadPeriod);
  4507. if (lFifoCReadPeriod == lMemReadPeriod)
  4508. lFifoCEffWritePeriod = 1000000000;
  4509. else
  4510. lFifoCEffWritePeriod = (lMemReadPeriod * lFifoCReadPeriod) /
  4511. (lFifoCReadPeriod - lMemReadPeriod);
  4512. //
  4513. // Video capture read period
  4514. //
  4515. lVCapReadPeriod = (2 * ppdev->lMCLKPeriod) / ppdev->lBusWidth;
  4516. if (dwFlags & OVERLAY_FLG_CAPTURE) // is capture enable ?
  4517. bCapture = TRUE;
  4518. else
  4519. bCapture = FALSE;
  4520. if (dwFlags & OVERLAY_FLG_YUVPLANAR) // is 420 format
  4521. {
  4522. if (dwFlags & (OVERLAY_FLG_COLOR_KEY | OVERLAY_FLG_SRC_COLOR_KEY)) // occlusion
  4523. { // one video window, occlusion, 420 format
  4524. bFifoAEnable = TRUE;
  4525. bFifoBEnable = TRUE;
  4526. bFifoCEnable = TRUE;
  4527. }
  4528. else
  4529. { // one video window, no occlusion, 420 format
  4530. bFifoAEnable = FALSE;
  4531. bFifoBEnable = TRUE;
  4532. bFifoCEnable = TRUE;
  4533. }
  4534. }
  4535. else // not 420 format
  4536. {
  4537. if (dwFlags & (OVERLAY_FLG_COLOR_KEY | OVERLAY_FLG_SRC_COLOR_KEY)) // occlusion
  4538. {
  4539. if (dwFlags & OVERLAY_FLG_TWO_VIDEO)
  4540. { // Two video windows, occlusion, not 420 format
  4541. bFifoAEnable = TRUE;
  4542. bFifoBEnable = TRUE;
  4543. bFifoCEnable = TRUE;
  4544. }
  4545. else
  4546. { // one video window, occlusion, not 420 format
  4547. bFifoAEnable = TRUE;
  4548. bFifoBEnable = TRUE;
  4549. bFifoCEnable = FALSE;
  4550. }
  4551. }
  4552. else
  4553. {
  4554. // one video window, no occlusion, not 420 format
  4555. bFifoAEnable = FALSE;
  4556. bFifoBEnable = TRUE;
  4557. bFifoCEnable = FALSE;
  4558. }
  4559. }
  4560. DISPDBG ((4, " FIFOA = %s, FIFOB= %s, FIFOC = %s\n",
  4561. bFifoAEnable ? "yes" : "no",
  4562. bFifoBEnable ? "yes" : "no",
  4563. bFifoCEnable ? "yes" : "no"));
  4564. lFifo1ReadPeriod = 0;
  4565. lFifo2ReadPeriod = 0;
  4566. lFifo3ReadPeriod = 0;
  4567. if (bFifoAEnable)
  4568. {
  4569. if (((lFifoAReadPeriod >= lFifoBReadPeriod) || !bFifoBEnable) &&
  4570. // A slower than or equal than B) and
  4571. ((lFifoAReadPeriod >= lFifoCReadPeriod) || !bFifoCEnable))
  4572. // A slower than or equal C
  4573. {
  4574. lFifo1ReadPeriod = lFifoAReadPeriod;
  4575. lFifo1EffWritePeriod = lFifoAEffWritePeriod;
  4576. }
  4577. else if (((lFifoAReadPeriod >= lFifoBReadPeriod) || !bFifoBEnable) ||
  4578. // A slower than or equal B
  4579. ((lFifoAReadPeriod >= lFifoCReadPeriod) || !bFifoCEnable))
  4580. // A slower than or equal C
  4581. {
  4582. lFifo2ReadPeriod = lFifoAReadPeriod;
  4583. lFifo2EffWritePeriod = lFifoAEffWritePeriod;
  4584. }
  4585. else // A not slower than A or B
  4586. {
  4587. lFifo3ReadPeriod = lFifoAReadPeriod;
  4588. lFifo3EffWritePeriod = lFifoAEffWritePeriod;
  4589. }
  4590. }
  4591. DISPDBG ((2, "After bFifoAEnable")) ;
  4592. DISPDBG ((2, "lFifo1ReadPeriod = %ld, lFifo2ReadPeriod=%ld",
  4593. lFifo1ReadPeriod, lFifo2ReadPeriod)) ;
  4594. DISPDBG ((2, "lFifo3ReadPeriod = %ld", lFifo3ReadPeriod)) ;
  4595. if (bFifoBEnable)
  4596. {
  4597. if (((lFifoBReadPeriod > lFifoAReadPeriod) || !bFifoAEnable) &&
  4598. // B slower than A and
  4599. ((lFifoBReadPeriod >= lFifoCReadPeriod) || !bFifoCEnable))
  4600. // slower than or equal A
  4601. {
  4602. lFifo1ReadPeriod = lFifoBReadPeriod;
  4603. lFifo1EffWritePeriod = lFifoBEffWritePeriod;
  4604. }
  4605. else if (((lFifoBReadPeriod > lFifoAReadPeriod) || !bFifoAEnable) ||
  4606. // B slower than A or
  4607. ((lFifoBReadPeriod >= lFifoCReadPeriod) || !bFifoCEnable))
  4608. // B slower than or equal C
  4609. {
  4610. lFifo2ReadPeriod = lFifoBReadPeriod;
  4611. lFifo2EffWritePeriod = lFifoBEffWritePeriod;
  4612. }
  4613. else
  4614. // (B not slower than A ) and (B not slower than or equal C)
  4615. {
  4616. lFifo3ReadPeriod = lFifoBReadPeriod;
  4617. lFifo3EffWritePeriod = lFifoBEffWritePeriod;
  4618. }
  4619. }
  4620. DISPDBG ((4, "After bFifoBEnable")) ;
  4621. DISPDBG ((4, "lFifo1ReadPeriod = %ld, lFifo2ReadPeriod=%ld",
  4622. lFifo1ReadPeriod, lFifo2ReadPeriod)) ;
  4623. DISPDBG ((4, "lFifo3ReadPeriod = %ld", lFifo3ReadPeriod)) ;
  4624. if (bFifoCEnable)
  4625. {
  4626. if (((lFifoCReadPeriod > lFifoAReadPeriod) || !bFifoAEnable) &&
  4627. // C slower than A and
  4628. ((lFifoCReadPeriod > lFifoBReadPeriod) || !bFifoBEnable))
  4629. // C slower than B
  4630. {
  4631. lFifo1ReadPeriod = lFifoCReadPeriod;
  4632. lFifo1EffWritePeriod = lFifoCEffWritePeriod;
  4633. }
  4634. else if (((lFifoCReadPeriod > lFifoAReadPeriod) || !bFifoAEnable) ||
  4635. // C slower than A or
  4636. ((lFifoCReadPeriod > lFifoBReadPeriod) || !bFifoBEnable))
  4637. // C slower than B
  4638. {
  4639. lFifo2ReadPeriod = lFifoCReadPeriod;
  4640. lFifo2EffWritePeriod = lFifoCEffWritePeriod;
  4641. }
  4642. else
  4643. {
  4644. // C not slower than A and C not slower than B
  4645. lFifo3ReadPeriod = lFifoCReadPeriod;
  4646. lFifo3EffWritePeriod = lFifoCEffWritePeriod;
  4647. }
  4648. }
  4649. DISPDBG ((4, "After bFifoCEnable")) ;
  4650. DISPDBG ((4, "lFifo1ReadPeriod = %ld, lFifo2ReadPeriod=%ld",
  4651. lFifo1ReadPeriod, lFifo2ReadPeriod)) ;
  4652. DISPDBG ((4, "lFifo3ReadPeriod = %ld", lFifo3ReadPeriod)) ;
  4653. DISPDBG ((4, "lFifo1EffWritePeriod = %ld, lFifo2EffWritePeriod = %ld",
  4654. lFifo1EffWritePeriod, lFifo2EffWritePeriod)) ;
  4655. DISPDBG ((4, " lFifo3EffWritePeriod = %ld", lFifo3EffWritePeriod)) ;
  4656. DISPDBG ((4, " lFifoAEffWritePeriod = %ld, lFifoBEffWritePeriod = %ld",
  4657. lFifoAEffWritePeriod, lFifoBEffWritePeriod)) ;
  4658. DISPDBG ((4, " lFifoCEffWritePeriod = %ld", lFifoCEffWritePeriod)) ;
  4659. bModePass = FALSE;
  4660. lThreshold = 1;
  4661. CrtFifoCount = 0;
  4662. if (bFifoAEnable) CrtFifoCount++;
  4663. if (bFifoBEnable) CrtFifoCount++;
  4664. if (bFifoCEnable) CrtFifoCount++;
  4665. while ((!bModePass) && (lThreshold < 16))
  4666. {
  4667. bModePass = TRUE; // assume pass until proven otherwise.
  4668. //
  4669. // Checking capture
  4670. //
  4671. if (bCapture)
  4672. {
  4673. lVCapLatency = (BLIT_LATENCY + RAS_PRECHARGE) * ppdev->lMCLKPeriod;
  4674. lVCapBytesToEmpty = CAP_FIFO_DEPTH;
  4675. lVCapEmptyTime = lVCapReadPeriod * lVCapBytesToEmpty;
  4676. lVCapLevelRemaining = (lVCapLatency + lVCapEmptyTime) / lVCapWritePeriod;
  4677. if (lVCapLevelRemaining > CAP_FIFO_DEPTH)
  4678. return(FALSE);
  4679. }
  4680. //
  4681. // Fill FIFO 1
  4682. //
  4683. if (bCapture)
  4684. lFifo1Latency = lVCapLatency + lVCapEmptyTime + (BLIT_LATENCY + RAS_PRECHARGE) * ppdev->lMCLKPeriod;
  4685. else
  4686. lFifo1Latency = (BLIT_LATENCY + RAS_PRECHARGE) * ppdev->lMCLKPeriod;
  4687. lFifo1BytesToFill = ((16 - lThreshold) * 16)
  4688. + (lFifo1Latency / lFifo1ReadPeriod);
  4689. lFifo1FillTime = lFifo1EffWritePeriod * lFifo1BytesToFill;
  4690. if (lFifo1BytesToFill > 256)
  4691. bModePass = FALSE;
  4692. DISPDBG ((4, "After Fill FIFO1, lFifo1BytesToFillb=%ld, ModePass = %s",
  4693. lFifo1BytesToFill, bModePass ? "yes" : "no")) ;
  4694. DISPDBG ((4, "f1_latency=%ld, f1_read_period=%ld",
  4695. lFifo1Latency, lFifo1ReadPeriod)) ;
  4696. DISPDBG ((4, "mclkperiod= %ld, vclkperiod=%ld",
  4697. ppdev->lMCLKPeriod, lVCLKPeriod)) ;
  4698. //
  4699. // Fill FIFO 2
  4700. //
  4701. if (CrtFifoCount > 1)
  4702. {
  4703. lFifo2Latency = lFifo1Latency + lFifo1FillTime +
  4704. (RAS_PRECHARGE * ppdev->lMCLKPeriod);
  4705. lFifo2BytesToFill = ((16 - lThreshold) * 16) +
  4706. (lFifo2Latency / lFifo2ReadPeriod);
  4707. lFifo2FillTime = lFifo2EffWritePeriod * lFifo2BytesToFill;
  4708. if (lFifo2BytesToFill > 256)
  4709. bModePass = FALSE;
  4710. }
  4711. else
  4712. {
  4713. lFifo2Latency = lFifo1Latency + lFifo1FillTime;
  4714. lFifo2BytesToFill = 0;
  4715. lFifo2FillTime = 0;
  4716. }
  4717. DISPDBG ((4, "After Fill FIFO2, lFifo2BytesToFill=%ld, ModePass = %s",
  4718. lFifo2BytesToFill, bModePass ? "yes" : "no"));
  4719. //
  4720. // Fill FIFO 3
  4721. //
  4722. if (CrtFifoCount > 2)
  4723. {
  4724. lFifo3Latency = lFifo2Latency + lFifo2FillTime + (RAS_PRECHARGE * ppdev->lMCLKPeriod);
  4725. lFifo3BytesToFill = ((16 - lThreshold) * 16) + (lFifo3Latency / lFifo3ReadPeriod);
  4726. lFifo3FillTime = lFifo3EffWritePeriod * lFifo3BytesToFill;
  4727. if (lFifo3BytesToFill > 256)
  4728. bModePass = FALSE;
  4729. }
  4730. else
  4731. {
  4732. lFifo3Latency = lFifo2Latency + lFifo2FillTime;
  4733. lFifo3BytesToFill = 0;
  4734. lFifo3FillTime = 0;
  4735. }
  4736. DISPDBG ((4, "After Fill FIFO3, lFifo3BytesToFill=%ld, ModePass = %s",
  4737. lFifo3BytesToFill, bModePass ? "yes" : "no")) ;
  4738. //
  4739. // Determine total latency through the sequence
  4740. //
  4741. lTotalLatency = lFifo3Latency + lFifo3FillTime;
  4742. //
  4743. // Now back to start of sequence, make sure that none of the FIFOs
  4744. // have already initiated another request.
  4745. //
  4746. //
  4747. // Check capture FIFO status
  4748. //
  4749. if (bCapture)
  4750. {
  4751. lVCapLatency = lTotalLatency;
  4752. lVCapBytesToEmpty = lTotalLatency / lVCapWritePeriod;
  4753. if (lVCapBytesToEmpty > CAP_FIFO_DEPTH)
  4754. bModePass = FALSE;
  4755. }
  4756. //
  4757. // Check FIFO 1 status
  4758. //
  4759. lFifo1Latency = lTotalLatency - lFifo1Latency - lFifo1FillTime;
  4760. lFifo1BytesToFill = lFifo1Latency / lFifo1ReadPeriod;
  4761. if (lFifo1BytesToFill > ((16 - lThreshold) * 16))
  4762. bModePass = FALSE;
  4763. DISPDBG ((4, "After CheckF FIFO1, fifo1bytestofill %ld,bModePass = %s",
  4764. lFifo1BytesToFill, bModePass ? "yes" : "no")) ;
  4765. //
  4766. // Check FIFO 2 status
  4767. //
  4768. if (CrtFifoCount > 1)
  4769. {
  4770. lFifo2Latency = lTotalLatency - lFifo2Latency - lFifo2FillTime;
  4771. lFifo2BytesToFill = lFifo2Latency / lFifo2ReadPeriod;
  4772. if (lFifo2BytesToFill > ((16 - lThreshold) * 16))
  4773. bModePass = FALSE;
  4774. DISPDBG ((4, "After Check FIFO 2, fifo1bytestofill=%ld, bModePass = %s",
  4775. lFifo2BytesToFill, bModePass ? "yes" : "no")) ;
  4776. }
  4777. if (!bModePass)
  4778. lThreshold++;
  4779. }
  4780. if (bModePass)
  4781. {
  4782. DISPDBG ((1, "Is sufficient Bandwidth, thresh = %ld, return TRUE\n", lThreshold));
  4783. if (ppdev->cBitsPerPixel == 24)
  4784. lThreshold = 0x0F;
  4785. ppdev->lFifoThresh = lThreshold;
  4786. return TRUE ;
  4787. }
  4788. DISPDBG ((2, "Is sufficient Bandwidth, thresh = %ld, rerurn FALSE", lThreshold));
  4789. return FALSE;
  4790. }
  4791. /**********************************************************
  4792. *
  4793. * Name: GetVCLK
  4794. *
  4795. * Module Abstract:
  4796. * ----------------
  4797. * Returns the VCLK frequency * 1000.
  4798. *
  4799. * Input Parameters:
  4800. * -----------------
  4801. * none
  4802. *
  4803. * Output Parameters:
  4804. * ------------------
  4805. * MCLK
  4806. *
  4807. ***********************************************************
  4808. * Author: Shuhua Ge
  4809. * Date: 09/25/96
  4810. *
  4811. * Revision History:
  4812. * -----------------
  4813. * WHO WHEN WHAT/WHY/HOW
  4814. * --- ---- ------------
  4815. *
  4816. *********************************************************/
  4817. LONG GetVCLK(PDEV* ppdev)
  4818. {
  4819. LONG lTemp;
  4820. LONG lRegSR1F;
  4821. LONG lRegMISC;
  4822. LONG lNR;
  4823. LONG lDR;
  4824. LONG lPS;
  4825. BYTE* pjPorts = ppdev->pjPorts;
  4826. /*
  4827. * First read SR1F. This tells us if VCLK is derived from MCLK
  4828. * or if it's derived normally.
  4829. */
  4830. CP_OUT_BYTE(pjPorts, SR_INDEX, 0x1f);
  4831. lRegSR1F = (LONG) CP_IN_BYTE(pjPorts, SR_DATA);
  4832. if (lRegSR1F & 0x40)
  4833. {
  4834. LONG lMCLK;
  4835. /*
  4836. * It is derived from MCLK, but now we need to read SR1E to see
  4837. * if VCLK = MCLK or if VCLK = MCLK/2.
  4838. */
  4839. lMCLK = (lRegSR1F & 0x3F) * 14318;
  4840. CP_OUT_BYTE(pjPorts, SR_INDEX, 0x1e);
  4841. if (CP_IN_BYTE(pjPorts, SR_DATA) & 0x01)
  4842. {
  4843. return (lMCLK >> 4);
  4844. }
  4845. else
  4846. {
  4847. return (lMCLK >> 3);
  4848. }
  4849. }
  4850. else
  4851. {
  4852. /*
  4853. * Read MISC[3:2], which tells us where to find our VCLK
  4854. */
  4855. lRegMISC = (LONG) CP_IN_BYTE(pjPorts, 0x3cc);
  4856. lRegMISC >>= 2;
  4857. //myf33 begin
  4858. CP_OUT_BYTE(pjPorts, CRTC_INDEX, (BYTE)0x80);
  4859. if (((ppdev->ulChipID == CL7555_ID) || (ppdev->ulChipID == CL7556_ID)) &&
  4860. (CP_IN_BYTE(pjPorts, CRTC_DATA) & 0x01))
  4861. lRegMISC &= 0x02; // Fixed PDR 8709
  4862. else
  4863. //myf33 end
  4864. lRegMISC &= 0x03;
  4865. lNR = 0x0B + lRegMISC;
  4866. lDR = 0x1B + lRegMISC;
  4867. /*
  4868. * Read the values for bP, bDR, and bNR
  4869. */
  4870. CP_OUT_BYTE(pjPorts, SR_INDEX, (BYTE) lDR);
  4871. lPS = lDR = (LONG)CP_IN_BYTE(pjPorts, SR_DATA);
  4872. CP_OUT_BYTE(pjPorts, SR_INDEX, (BYTE) lNR);
  4873. lNR = (LONG)CP_IN_BYTE(pjPorts, SR_DATA);
  4874. lPS &= 0x01;
  4875. lPS += 1;
  4876. lDR >>= 1;
  4877. //
  4878. // Extended the VCLK bits.
  4879. //
  4880. // sge06
  4881. lDR &= 0x7f;
  4882. lNR &= 0x7f;
  4883. /*
  4884. * VCLK = (14.31818 * bNR) / (bDR * bPS)
  4885. */
  4886. lTemp = (14318 * lNR);
  4887. if (!lPS || !lDR)
  4888. {
  4889. return (0);
  4890. }
  4891. lTemp /= (lDR * lPS);
  4892. }
  4893. return (lTemp);
  4894. }
  4895. /**********************************************************
  4896. *
  4897. * Name: EnableStartAddrDoubleBuffer
  4898. *
  4899. * Module Abstract:
  4900. * ----------------
  4901. * Enable the double buffering of the start addresses. This allows the page
  4902. * flipping operation to proceed without the system CPU waiting for VRT.
  4903. *
  4904. * Input Parameters:
  4905. * -----------------
  4906. * none
  4907. *
  4908. * Output Parameters:
  4909. * ------------------
  4910. *
  4911. ***********************************************************
  4912. * Author: Shuhua Ge
  4913. * Date: 10/01/96
  4914. *
  4915. * Revision History:
  4916. * -----------------
  4917. * WHO WHEN WHAT/WHY/HOW
  4918. * --- ---- ------------
  4919. *
  4920. *********************************************************/
  4921. VOID EnableStartAddrDoubleBuffer(PDEV* ppdev)
  4922. {
  4923. BYTE* pjPorts = ppdev->pjPorts;
  4924. BYTE cTemp;
  4925. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x1a);
  4926. cTemp = CP_IN_BYTE(pjPorts, CRTC_DATA);
  4927. CP_OUT_BYTE(pjPorts, CRTC_DATA, cTemp | 2);
  4928. }
  4929. /**********************************************************
  4930. *
  4931. * Name: GetCurrentVLine
  4932. *
  4933. * Module Abstract:
  4934. * ----------------
  4935. * Get the current scan line
  4936. *
  4937. * Input Parameters:
  4938. * -----------------
  4939. * none
  4940. *
  4941. * Output Parameters:
  4942. * ------------------
  4943. *
  4944. ***********************************************************
  4945. * Author: Shuhua Ge
  4946. * Date: 10/01/96
  4947. *
  4948. * Revision History:
  4949. * -----------------
  4950. * WHO WHEN WHAT/WHY/HOW
  4951. * --- ---- ------------
  4952. *
  4953. *********************************************************/
  4954. DWORD GetCurrentVLine(PDEV* ppdev)
  4955. {
  4956. DWORD dwLine;
  4957. BYTE cTemp;
  4958. BYTE* pjPorts = ppdev->pjPorts;
  4959. CP_OUT_BYTE(pjPorts, INDEX_REG, 0x16); /* Index to the low byte. */
  4960. dwLine = (ULONG)CP_IN_BYTE(pjPorts, DATA_REG);
  4961. CP_OUT_BYTE(pjPorts, INDEX_REG, 0x17); /* Index to the high bits. */
  4962. cTemp = CP_IN_BYTE(pjPorts, DATA_REG);
  4963. dwLine |= (cTemp & 3) << 8;
  4964. CP_OUT_BYTE(pjPorts, INDEX_REG, 0x16); /* Index to the low byte. */
  4965. /* If we wrapped around while getting the high bits we have a problem. */
  4966. /* The high bits may be wrong. */
  4967. if((CP_IN_BYTE(pjPorts, DATA_REG)) < (dwLine & 0xff))
  4968. {
  4969. DISPDBG((1, "Recursive call to GetCurrentVLine."));
  4970. return GetCurrentVLine(ppdev);
  4971. }
  4972. if (dwLine > ppdev->dwVsyncLine)
  4973. {
  4974. return 0;
  4975. }
  4976. return dwLine;
  4977. }
  4978. #endif
  4979. #endif // DIRECTDRAW