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

1584 lines
50 KiB

  1. /******************************Module*Header*******************************\
  2. *
  3. * *******************
  4. * * GDI SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: bank.c
  8. *
  9. * Contains all the banking code for the display driver.
  10. *
  11. * It's helpful not to have to implement all the DDI drawing functionality
  12. * in a driver (who wants to write the code to support true ROP4's with
  13. * arbitrary sized patterns?). Fortunately, we can punt to GDI for any
  14. * drawing we don't want to do. And if GDI can write directly on the frame
  15. * buffer bits, performance won't even be toooo bad.
  16. *
  17. * NT's GDI can draw on any standard format frame buffer. When the entire
  18. * frame buffer can be mapped into main memory, it's very simple to set up:
  19. * the display driver tells GDI the frame buffer format and location, and
  20. * GDI can then just draw directly.
  21. *
  22. * When only one bank of the frame buffer can be mapped into main memory
  23. * at one time (e.g., there is a moveable 64k aperture) things are not
  24. * nearly so easy. For every bank spanned by a drawing operation, we have
  25. * to set the hardware to the bank, and call back to GDI. We tell GDI
  26. * to draw only on the mapped-in bank by mucking with the drawing call's
  27. * CLIPOBJ.
  28. *
  29. * This module contains the code for doing all banking support.
  30. *
  31. * This code supports 8, 16 and 32bpp colour depths, arbitrary bank
  32. * sizes, and handles 'broken rasters' (which happens when the bank size
  33. * is not a multiple of the scan length; some scans will end up being
  34. * split over two separate banks).
  35. *
  36. * Note: If you mess with this code and break it, you can expect to get
  37. * random access violations on call-backs in internal GDI routines
  38. * that are very hard to debug.
  39. *
  40. * Copyright (c) 1993-1998 Microsoft Corporation
  41. \**************************************************************************/
  42. #include "precomp.h"
  43. ////////////////////////////////////////////////////////////////////////////
  44. // Old 911/924 Banking
  45. //
  46. // NOTE: It is the caller's responsibility to acquire the CRTC crtical
  47. // section before calling these routines, in all cases!
  48. VOID vOldBankSelectMode( // Note: If this function changes, must
  49. PDEV* ppdev, // change Asm routines!
  50. BANKDATA* pbd,
  51. BANK_MODE bankm)
  52. {
  53. BYTE jMemCfg;
  54. if (bankm == BANK_ON)
  55. {
  56. // Make sure the processor graphics engine is idle before we start
  57. // drawing:
  58. while (INPW(ppdev->pjIoBase, pbd->ulGp_stat_cmd) & 0x0200)
  59. ;
  60. }
  61. else if (bankm == BANK_ENABLE)
  62. {
  63. // Enable the memory aperture after exiting full-screen:
  64. OUTP(ppdev->pjIoBase, CRTC_INDEX, S3R1);
  65. jMemCfg = INP(ppdev->pjIoBase, CRTC_DATA);
  66. OUTP(ppdev->pjIoBase, CRTC_DATA, jMemCfg | CPUA_BASE);
  67. }
  68. }
  69. VOID vOldBankMap(
  70. PDEV* ppdev,
  71. BANKDATA* pbd,
  72. LONG iBank)
  73. {
  74. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulRegisterLock_35 | ((iBank & 0x0F) << 8));
  75. // Supposedly, there's a chip bug and we have to read this back in:
  76. INP(ppdev->pjIoBase, CRTC_DATA);
  77. }
  78. VOID vOldBankInitialize(
  79. PDEV* ppdev,
  80. BANKDATA* pbd,
  81. BOOL bMmIo)
  82. {
  83. BYTE jMemCfg;
  84. // Enable the memory aperture:
  85. OUTP(ppdev->pjIoBase, CRTC_INDEX, S3R1);
  86. jMemCfg = INP(ppdev->pjIoBase, CRTC_DATA);
  87. OUTP(ppdev->pjIoBase, CRTC_DATA, jMemCfg | CPUA_BASE);
  88. // Read the default values of the registers that we'll be using:
  89. OUTP(ppdev->pjIoBase, CRTC_INDEX, 0x35);
  90. pbd->ulRegisterLock_35
  91. = ((INP(ppdev->pjIoBase, CRTC_DATA) << 8) | 0x35) & ~0x0F00;
  92. pbd->ulGp_stat_cmd = 0x9ae8;
  93. }
  94. ////////////////////////////////////////////////////////////////////////////
  95. // New 801/805/805i/928/928PCI Banking
  96. //
  97. // NOTE: It is the caller's responsibility to acquire the CRTC crtical
  98. // section before calling these routines, in all cases!
  99. VOID vNewBankSelectMode( // Note: If this function changes, must
  100. PDEV* ppdev, // change Asm routines!
  101. BANKDATA* pbd,
  102. BANK_MODE bankm)
  103. {
  104. BYTE jMemCfg;
  105. if ((bankm == BANK_ON) || (bankm == BANK_ON_NO_WAIT))
  106. {
  107. //////////////////////////////////////////////////////////////////
  108. // Enable Banking
  109. //
  110. // Make sure the processor graphics engine is idle before we start
  111. // drawing:
  112. if (bankm != BANK_ON_NO_WAIT)
  113. {
  114. do {;} while (INPW(ppdev->pjIoBase, pbd->ulGp_stat_cmd) & 0x0200);
  115. }
  116. // Disable memory mapped I/O:
  117. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulExtendedMemoryControl_53);
  118. // Disable enhanced register access and enable fast write buffer:
  119. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulSystemConfiguration_40 | 0x0800);
  120. // Enable linear addressing:
  121. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulLinearAddressWindowControl_58 | 0x1000);
  122. }
  123. else
  124. {
  125. //////////////////////////////////////////////////////////////////
  126. // Disable Banking
  127. //
  128. // Be it BANK_OFF, BANK_ENABLE, or BANK_DISABLE, we'll turn off
  129. // direct access to the frame buffer.
  130. if (bankm == BANK_ENABLE)
  131. {
  132. // Enable the memory aperture:
  133. OUTP(ppdev->pjIoBase, CRTC_INDEX, S3R1);
  134. jMemCfg = INP(ppdev->pjIoBase, CRTC_DATA);
  135. OUTP(ppdev->pjIoBase, CRTC_DATA, jMemCfg | CPUA_BASE);
  136. }
  137. // Disable linear addressing:
  138. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulLinearAddressWindowControl_58);
  139. // Enable enhanced register access and disable fast write buffer:
  140. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulSystemConfiguration_40 | 0x0100);
  141. // Enable memory mapped I/O:
  142. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulExtendedMemoryControl_53 |
  143. pbd->ulEnableMemoryMappedIo);
  144. }
  145. }
  146. VOID vNewBankMap(
  147. PDEV* ppdev,
  148. BANKDATA* pbd,
  149. LONG iBank)
  150. {
  151. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulRegisterLock_35 | ((iBank & 0x0F) << 8));
  152. // The 801/805/928 chipsets have a timing bug where a word OUT cannot
  153. // be used to set register 0x51:
  154. OUTP(ppdev->pjIoBase, CRTC_INDEX, pbd->ulExtendedSystemControl2_51);
  155. OUTP(ppdev->pjIoBase, CRTC_DATA, ((pbd->ulExtendedSystemControl2_51) >> 8) |
  156. ((iBank & 0x30) >> 2));
  157. // Supposedly, there's another S3 chip bug and we have to read this
  158. // back in:
  159. INP(ppdev->pjIoBase, CRTC_DATA);
  160. CP_EIEIO();
  161. }
  162. VOID vNewBankInitialize(
  163. PDEV* ppdev,
  164. BANKDATA* pbd,
  165. BOOL bMmIo)
  166. {
  167. // Read the default values of the registers that we'll be using:
  168. OUTP(ppdev->pjIoBase, CRTC_INDEX, 0x35);
  169. pbd->ulRegisterLock_35
  170. = ((INP(ppdev->pjIoBase, CRTC_DATA) << 8) | 0x35) & ~0x0F00;
  171. OUTP(ppdev->pjIoBase, CRTC_INDEX, 0x51);
  172. pbd->ulExtendedSystemControl2_51
  173. = ((INP(ppdev->pjIoBase, CRTC_DATA) << 8) | 0x51) & ~0x0C00;
  174. OUTP(ppdev->pjIoBase, CRTC_INDEX, 0x53);
  175. pbd->ulExtendedMemoryControl_53
  176. = ((INP(ppdev->pjIoBase, CRTC_DATA) << 8) | 0x53) & ~0x1000;
  177. OUTP(ppdev->pjIoBase, CRTC_INDEX, 0x40);
  178. pbd->ulSystemConfiguration_40
  179. = ((INP(ppdev->pjIoBase, CRTC_DATA) << 8) | 0x40) & ~0x0900;
  180. // Only enable memory-mapped I/O if we're really going to use it
  181. // (some cards would crash when memory-mapped I/O was enabled):
  182. pbd->ulEnableMemoryMappedIo = (bMmIo) ? 0x1000 : 0x0000;
  183. // Make sure we use the current window size:
  184. OUTP(ppdev->pjIoBase, CRTC_INDEX, 0x58);
  185. pbd->ulLinearAddressWindowControl_58
  186. = ((INP(ppdev->pjIoBase, CRTC_DATA) << 8) | 0x58) & ~0x1000;
  187. pbd->ulGp_stat_cmd = 0x9ae8;
  188. }
  189. ////////////////////////////////////////////////////////////////////////////
  190. // Newer 864/964 Banking
  191. //
  192. // NOTE: It is the caller's responsibility to acquire the CRTC crtical
  193. // section before calling these routines, in all cases!
  194. VOID vNewerBankSelectMode( // Note: If this function changes, must
  195. PDEV* ppdev, // change Asm routines!
  196. BANKDATA* pbd,
  197. BANK_MODE bankm)
  198. {
  199. BYTE jMemCfg;
  200. if ((bankm == BANK_ON) || (bankm == BANK_ON_NO_WAIT))
  201. {
  202. //////////////////////////////////////////////////////////////////
  203. // Enable Banking
  204. //
  205. // Make sure the processor graphics engine is idle before we start
  206. // drawing:
  207. if (bankm != BANK_ON_NO_WAIT)
  208. {
  209. do {;} while (INPW(ppdev->pjIoBase, pbd->ulGp_stat_cmd) & 0x0200);
  210. }
  211. // Disable memory mapped I/O:
  212. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulExtendedMemoryControl_53);
  213. // Disable enhanced register access and enable fast write buffer:
  214. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulSystemConfiguration_40 | 0x0800);
  215. // Enable linear addressing:
  216. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulLinearAddressWindowControl_58 | 0x1000);
  217. }
  218. else
  219. {
  220. //////////////////////////////////////////////////////////////////
  221. // Disable Banking
  222. //
  223. // Be it BANK_OFF, BANK_ENABLE, or BANK_DISABLE, we'll turn off
  224. // direct access to the frame buffer.
  225. if (bankm == BANK_ENABLE)
  226. {
  227. // Enable the memory aperture:
  228. OUTP(ppdev->pjIoBase, CRTC_INDEX, S3R1);
  229. jMemCfg = INP(ppdev->pjIoBase, CRTC_DATA);
  230. OUTP(ppdev->pjIoBase, CRTC_DATA, jMemCfg | CPUA_BASE);
  231. // Since a zero in 'CR6A' causes 'CR31' and 'CR51' to be used
  232. // as the bank index, we have to make sure they map to bank zero:
  233. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulRegisterLock_35);
  234. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulExtendedSystemControl2_51);
  235. }
  236. // Disable linear addressing:
  237. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulLinearAddressWindowControl_58);
  238. // Enable enhanced register access:
  239. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulSystemConfiguration_40 | 0x0100);
  240. // Enable memory mapped I/O:
  241. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulExtendedMemoryControl_53 | 0x1000);
  242. }
  243. }
  244. VOID vNewerBankMap(
  245. PDEV* ppdev,
  246. BANKDATA* pbd,
  247. LONG iBank)
  248. {
  249. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulExtendedSystemControl4_6a | (iBank << 8));
  250. }
  251. VOID vNewerBankInitialize(
  252. PDEV* ppdev,
  253. BANKDATA* pbd,
  254. BOOL bMmIo)
  255. {
  256. // Read the default values of the registers that we'll be using:
  257. pbd->ulExtendedSystemControl4_6a = 0x6a;
  258. OUTP(ppdev->pjIoBase, CRTC_INDEX, 0x35);
  259. pbd->ulRegisterLock_35
  260. = ((INP(ppdev->pjIoBase, CRTC_DATA) << 8) | 0x35) & ~0x0F00;
  261. OUTP(ppdev->pjIoBase, CRTC_INDEX, 0x51);
  262. pbd->ulExtendedSystemControl2_51
  263. = ((INP(ppdev->pjIoBase, CRTC_DATA) << 8) | 0x51) & ~0x0C00;
  264. OUTP(ppdev->pjIoBase, CRTC_INDEX, 0x53);
  265. pbd->ulExtendedMemoryControl_53
  266. = ((INP(ppdev->pjIoBase, CRTC_DATA) << 8) | 0x53) & ~0x1000;
  267. OUTP(ppdev->pjIoBase, CRTC_INDEX, 0x40);
  268. pbd->ulSystemConfiguration_40
  269. = ((INP(ppdev->pjIoBase, CRTC_DATA) << 8) | 0x40) & ~0x0100;
  270. // Make sure we select the current window size:
  271. OUTP(ppdev->pjIoBase, CRTC_INDEX, 0x58);
  272. pbd->ulLinearAddressWindowControl_58
  273. = ((INP(ppdev->pjIoBase, CRTC_DATA) << 8) | 0x58) & ~0x1000;
  274. pbd->ulGp_stat_cmd = 0x9ae8;
  275. }
  276. ////////////////////////////////////////////////////////////////////////////
  277. // New MM I/O Banking
  278. //
  279. // NOTE: It is the caller's responsibility to acquire the CRTC crtical
  280. // section before calling these routines, in all cases!
  281. VOID vNwBankSelectMode(
  282. PDEV* ppdev,
  283. BANKDATA* pbd,
  284. BANK_MODE bankm)
  285. {
  286. BYTE jMemCfg;
  287. if (bankm == BANK_ON)
  288. {
  289. do {;} while (INPW(ppdev->pjIoBase, pbd->ulGp_stat_cmd) & 0x0200);
  290. }
  291. else if (bankm == BANK_ENABLE)
  292. {
  293. // Enable the memory aperture:
  294. OUTP(ppdev->pjIoBase, CRTC_INDEX, S3R1);
  295. jMemCfg = INP(ppdev->pjIoBase, CRTC_DATA);
  296. OUTP(ppdev->pjIoBase, CRTC_DATA, jMemCfg | CPUA_BASE);
  297. // Since a zero in 'CR6A' causes 'CR31' and 'CR51' to be used
  298. // as the bank index, we have to make sure they map to bank zero:
  299. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulRegisterLock_35);
  300. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulExtendedSystemControl2_51);
  301. // Enable linear addressing:
  302. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulLinearAddressWindowControl_58 | 0x1000);
  303. // Enable enhanced register access:
  304. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulSystemConfiguration_40 | 0x0100);
  305. // Enable memory-mapped I/O:
  306. OUTPW(ppdev->pjIoBase, CRTC_INDEX, pbd->ulExtendedMemoryControl_53 | 0x1000);
  307. }
  308. }
  309. VOID vNwBankMap(
  310. PDEV* ppdev,
  311. BANKDATA* pbd,
  312. LONG iBank)
  313. {
  314. }
  315. VOID vNwBankInitialize(
  316. PDEV* ppdev,
  317. BANKDATA* pbd,
  318. BOOL bMmIo)
  319. {
  320. // Read the default values of the registers that we'll be using:
  321. pbd->ulExtendedSystemControl4_6a = 0x6a;
  322. OUTP(ppdev->pjIoBase, CRTC_INDEX, 0x35);
  323. pbd->ulRegisterLock_35
  324. = ((INP(ppdev->pjIoBase, CRTC_DATA) << 8) | 0x35) & ~0x0F00;
  325. OUTP(ppdev->pjIoBase, CRTC_INDEX, 0x51);
  326. pbd->ulExtendedSystemControl2_51
  327. = ((INP(ppdev->pjIoBase, CRTC_DATA) << 8) | 0x51) & ~0x0C00;
  328. OUTP(ppdev->pjIoBase, CRTC_INDEX, 0x53);
  329. pbd->ulExtendedMemoryControl_53
  330. = ((INP(ppdev->pjIoBase, CRTC_DATA) << 8) | 0x53) & ~0x1000;
  331. OUTP(ppdev->pjIoBase, CRTC_INDEX, 0x40);
  332. pbd->ulSystemConfiguration_40
  333. = ((INP(ppdev->pjIoBase, CRTC_DATA) << 8) | 0x40);
  334. // Make sure we select the current window size:
  335. OUTP(ppdev->pjIoBase, CRTC_INDEX, 0x58);
  336. pbd->ulLinearAddressWindowControl_58
  337. = ((INP(ppdev->pjIoBase, CRTC_DATA) << 8) | 0x58) & ~0x1000;
  338. pbd->ulGp_stat_cmd = 0x9ae8;
  339. }
  340. /******************************Public*Routine******************************\
  341. * BOOL bEnableBanking
  342. *
  343. \**************************************************************************/
  344. BOOL bEnableBanking(
  345. PDEV* ppdev)
  346. {
  347. CLIPOBJ* pcoBank;
  348. SURFOBJ* psoBank;
  349. SIZEL sizl;
  350. HSURF hsurf;
  351. FNBANKINITIALIZE* pfnBankInitialize;
  352. LONG lDelta;
  353. LONG cjBank;
  354. LONG cPower2;
  355. // Create a temporary clip object that we'll use for the bank
  356. // when we're given a Null or DC_TRIVIAL clip object:
  357. pcoBank = EngCreateClip();
  358. if (pcoBank == NULL)
  359. goto ReturnFalse;
  360. // We break every per-bank GDI call-back into simple rectangles:
  361. pcoBank->iDComplexity = DC_RECT;
  362. pcoBank->fjOptions = OC_BANK_CLIP;
  363. // Create a GDI surface that we'll wrap around our bank in
  364. // call-backs:
  365. sizl.cx = ppdev->cxMemory;
  366. sizl.cy = ppdev->cyMemory;
  367. hsurf = (HSURF) EngCreateBitmap(sizl,
  368. ppdev->lDelta,
  369. ppdev->iBitmapFormat,
  370. BMF_TOPDOWN,
  371. ppdev->pjScreen);
  372. // Note that we hook zero calls -- after all, the entire point
  373. // of all this is to have GDI do all the drawing on the bank.
  374. // Once we're done the association, we can leave the surface
  375. // permanently locked:
  376. if ((hsurf == 0) ||
  377. (!EngAssociateSurface(hsurf, ppdev->hdevEng, 0)) ||
  378. (!(psoBank = EngLockSurface(hsurf))))
  379. {
  380. DISPDBG((0, "Failed wrapper surface creation"));
  381. EngDeleteSurface(hsurf);
  382. EngDeleteClip(pcoBank);
  383. goto ReturnFalse;
  384. }
  385. ppdev->pcoBank = pcoBank;
  386. ppdev->psoBank = psoBank;
  387. ppdev->pvBankData = &ppdev->aulBankData[0];
  388. if (ppdev->flCaps & CAPS_NEW_MMIO)
  389. {
  390. ppdev->bankmOnOverlapped = BANK_ON;
  391. ppdev->pfnBankMap = vNwBankMap;
  392. ppdev->pfnBankSelectMode = vNwBankSelectMode;
  393. pfnBankInitialize = vNwBankInitialize;
  394. }
  395. else if (ppdev->flCaps & CAPS_NEWER_BANK_CONTROL)
  396. {
  397. ppdev->bankmOnOverlapped = BANK_ON;
  398. ppdev->pfnBankMap = vNewerBankMap;
  399. ppdev->pfnBankSelectMode = vNewerBankSelectMode;
  400. pfnBankInitialize = vNewerBankInitialize;
  401. }
  402. else if (ppdev->flCaps & CAPS_NEW_BANK_CONTROL)
  403. {
  404. ppdev->bankmOnOverlapped = BANK_ON;
  405. ppdev->pfnBankMap = vNewBankMap;
  406. ppdev->pfnBankSelectMode = vNewBankSelectMode;
  407. pfnBankInitialize = vNewBankInitialize;
  408. }
  409. else
  410. {
  411. ppdev->bankmOnOverlapped = BANK_ON;
  412. ppdev->pfnBankMap = vOldBankMap;
  413. ppdev->pfnBankSelectMode = vOldBankSelectMode;
  414. pfnBankInitialize = vOldBankInitialize;
  415. }
  416. lDelta = ppdev->lDelta;
  417. cjBank = ppdev->cjBank;
  418. ASSERTDD(lDelta > 0, "Bad things happen with negative lDeltas");
  419. ASSERTDD(cjBank > lDelta, "Worse things happen with bad bank sizes");
  420. if (((lDelta & (lDelta - 1)) != 0) || ((cjBank & (cjBank - 1)) != 0))
  421. {
  422. // When either the screen stride or the bank size is not a power
  423. // of two, we have to use the slower 'bBankComputeNonPower2'
  424. // function for bank calculations, 'cause there can be broken
  425. // rasters and stuff:
  426. ppdev->pfnBankCompute = bBankComputeNonPower2;
  427. }
  428. else
  429. {
  430. // We can use the super duper fast bank calculator. Yippie,
  431. // yahoo! (I am easily amused.)
  432. cPower2 = 0;
  433. while (cjBank != lDelta)
  434. {
  435. cjBank >>= 1;
  436. cPower2++;
  437. }
  438. // We've just calculated that cjBank / lDelta = 2 ^ cPower2:
  439. ppdev->cPower2ScansPerBank = cPower2;
  440. while (cjBank != 1)
  441. {
  442. cjBank >>= 1;
  443. cPower2++;
  444. }
  445. // Continuing on, we've calculated that cjBank = 2 ^ cPower2:
  446. ppdev->cPower2BankSizeInBytes = cPower2;
  447. ppdev->pfnBankCompute = bBankComputePower2;
  448. }
  449. // Warm up the hardware:
  450. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  451. pfnBankInitialize(ppdev, ppdev->pvBankData,
  452. ppdev->flCaps & (CAPS_MM_TRANSFER | CAPS_MM_IO));
  453. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_ENABLE);
  454. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  455. DISPDBG((5, "Passed bEnableBanking"));
  456. return(TRUE);
  457. ReturnFalse:
  458. DISPDBG((0, "Failed bEnableBanking!"));
  459. return(FALSE);
  460. }
  461. /******************************Public*Routine******************************\
  462. * VOID vDisableBanking
  463. *
  464. \**************************************************************************/
  465. VOID vDisableBanking(PDEV* ppdev)
  466. {
  467. HSURF hsurf;
  468. if (ppdev->psoBank != NULL)
  469. {
  470. hsurf = ppdev->psoBank->hsurf;
  471. EngUnlockSurface(ppdev->psoBank);
  472. EngDeleteSurface(hsurf);
  473. }
  474. if (ppdev->pcoBank != NULL)
  475. EngDeleteClip(ppdev->pcoBank);
  476. }
  477. /******************************Public*Routine******************************\
  478. * VOID vAssertModeBanking
  479. *
  480. \**************************************************************************/
  481. VOID vAssertModeBanking(
  482. PDEV* ppdev,
  483. BOOL bEnable)
  484. {
  485. // Inform the miniport bank code about the change in state:
  486. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  487. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData,
  488. bEnable ? BANK_ENABLE : BANK_DISABLE);
  489. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  490. }
  491. /******************************Public*Routine******************************\
  492. * BOOL bBankComputeNonPower2
  493. *
  494. * Given the bounds of the drawing operation described by 'prclDraw',
  495. * computes the bank number and rectangle bounds for the first engine
  496. * call back.
  497. *
  498. * Returns the bank number, 'prclBank' is the bounds for the first
  499. * call-back, and 'pcjOffset' is the adjustment for 'pvScan0'.
  500. *
  501. * This routine does a couple of divides for the bank calculation. We
  502. * don't use a look-up table for banks because it's not straight forward
  503. * to use with broken rasters, and with large amounts of video memory
  504. * and small banks, the tables could get large. We'd probably use it
  505. * infrequently enough that the memory manager would be swapping it
  506. * in and out whenever we touched it.
  507. *
  508. * Returns TRUE if prclDraw is entirely contained in one bank; FALSE if
  509. * prclDraw spans multiple banks.
  510. *
  511. \**************************************************************************/
  512. BOOL bBankComputeNonPower2( // Type FNBANKCOMPUTE
  513. PDEV* ppdev,
  514. RECTL* prclDraw, // Extents of drawing operation, in absolute
  515. // coordinates
  516. RECTL* prclBank, // Returns bounds of drawing operation for this
  517. // bank, in absolute coordinates
  518. LONG* pcjOffset, // Returns the byte offset for this bank
  519. LONG* piBank) // Returns the bank number
  520. {
  521. LONG cjBufferOffset;
  522. LONG iBank;
  523. LONG cjBank;
  524. LONG cjBankOffset;
  525. LONG cjBankRemainder;
  526. LONG cjScan;
  527. LONG cScansInBank;
  528. LONG cjScanRemainder;
  529. LONG lDelta;
  530. BOOL bOneBank;
  531. bOneBank = FALSE;
  532. lDelta = ppdev->lDelta;
  533. cjBufferOffset = prclDraw->top * lDelta
  534. + CONVERT_TO_BYTES(prclDraw->left, ppdev);
  535. cjBank = ppdev->cjBank;
  536. // iBank = cjBufferOffset / cjBank;
  537. // cjBankOffset = cjBufferOffset % cjBank;
  538. QUOTIENT_REMAINDER(cjBufferOffset, cjBank, iBank, cjBankOffset);
  539. *piBank = iBank;
  540. *pcjOffset = iBank * cjBank;
  541. cjBankRemainder = cjBank - cjBankOffset;
  542. cjScan = CONVERT_TO_BYTES((prclDraw->right - prclDraw->left),
  543. ppdev);
  544. if (cjBankRemainder < cjScan)
  545. {
  546. // Oh no, we've got a broken raster!
  547. prclBank->left = prclDraw->left;
  548. prclBank->right = prclDraw->left +
  549. CONVERT_FROM_BYTES(cjBankRemainder, ppdev);
  550. prclBank->top = prclDraw->top;
  551. prclBank->bottom = prclDraw->top + 1;
  552. }
  553. else
  554. {
  555. // cScansInBank = cjBankRemainder / lDelta;
  556. // cjScanRemainder = cjBankRemainder % lDelta;
  557. ASSERTDD(lDelta > 0, "We assume positive lDelta here");
  558. QUOTIENT_REMAINDER(cjBankRemainder, lDelta,
  559. cScansInBank, cjScanRemainder);
  560. if (cjScanRemainder >= cjScan)
  561. {
  562. // The bottom scan of the bank may be broken, but it breaks after
  563. // any drawing we'll be doing on that scan. So we can simply
  564. // add the scan to this bank:
  565. cScansInBank++;
  566. }
  567. prclBank->left = prclDraw->left;
  568. prclBank->right = prclDraw->right;
  569. prclBank->top = prclDraw->top;
  570. prclBank->bottom = prclDraw->top + cScansInBank;
  571. if (prclBank->bottom >= prclDraw->bottom)
  572. {
  573. prclBank->bottom = prclDraw->bottom;
  574. bOneBank = TRUE;
  575. }
  576. }
  577. return(bOneBank);
  578. }
  579. /******************************Public*Routine******************************\
  580. * BOOL bBankComputePower2
  581. *
  582. * Functions the same as 'bBankComputeNonPower2', except that it is
  583. * an accelerated special case for when both the screen stride and bank
  584. * size are powers of 2.
  585. *
  586. \**************************************************************************/
  587. BOOL bBankComputePower2( // Type FNBANKCOMPUTE
  588. PDEV* ppdev,
  589. RECTL* prclDraw, // Extents of drawing operation, in absolute
  590. // coordinates
  591. RECTL* prclBank, // Returns bounds of drawing operation for this
  592. // bank, in absolute coordinates
  593. LONG* pcjOffset, // Returns the byte offset for this bank
  594. LONG* piBank) // Returns the bank number
  595. {
  596. LONG iBank;
  597. LONG yTopNextBank;
  598. BOOL bOneBank;
  599. iBank = prclDraw->top >> ppdev->cPower2ScansPerBank;
  600. yTopNextBank = (iBank + 1) << ppdev->cPower2ScansPerBank;
  601. *piBank = iBank;
  602. *pcjOffset = iBank << ppdev->cPower2BankSizeInBytes;
  603. prclBank->left = prclDraw->left;
  604. prclBank->right = prclDraw->right;
  605. prclBank->top = prclDraw->top;
  606. prclBank->bottom = yTopNextBank;
  607. bOneBank = FALSE;
  608. if (prclBank->bottom >= prclDraw->bottom)
  609. {
  610. prclBank->bottom = prclDraw->bottom;
  611. bOneBank = TRUE;
  612. }
  613. return(bOneBank);
  614. }
  615. /******************************Public*Routine******************************\
  616. * VOID vBankStart
  617. *
  618. * Given the bounds of the drawing operation described by 'prclDraw' and
  619. * the original clip object, maps in the first bank and returns in
  620. * 'pbnk->pco' and 'pbnk->pso' the CLIPOBJ and SURFOBJ to be passed to the
  621. * engine for the first banked call-back.
  622. *
  623. * Note: This routine only supports the screen being the destination, and
  624. * not the source. We have a separate, faster routine for doing
  625. * SRCCOPY reads from the screen, so it isn't worth the extra code
  626. * size to implement.
  627. *
  628. \**************************************************************************/
  629. VOID vBankStart(
  630. PDEV* ppdev, // Physical device information.
  631. RECTL* prclDraw, // Rectangle bounding the draw area, in relative
  632. // coordinates. Note that 'left' and 'right'
  633. // should be set for correct handling with broken
  634. // rasters.
  635. CLIPOBJ* pco, // Original drawing clip object (may be modified).
  636. BANK* pbnk) // Resulting bank information.
  637. {
  638. LONG cjOffset;
  639. LONG xOffset;
  640. LONG yOffset;
  641. xOffset = ppdev->xOffset;
  642. yOffset = ppdev->yOffset;
  643. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  644. {
  645. pco = ppdev->pcoBank;
  646. // Reset the clipping flag to trivial because we may have left
  647. // it as rectangular in a previous call:
  648. pco->iDComplexity = DC_TRIVIAL;
  649. // At the same time we convert to absolute coordinates, make sure
  650. // we won't try to enumerate past the bounds of the screen:
  651. pbnk->rclDraw.left = prclDraw->left + xOffset;
  652. pbnk->rclDraw.right = prclDraw->right + xOffset;
  653. pbnk->rclDraw.top
  654. = max(0, prclDraw->top + yOffset);
  655. pbnk->rclDraw.bottom
  656. = min(ppdev->cyMemory, prclDraw->bottom + yOffset);
  657. }
  658. else
  659. {
  660. pbnk->rclSaveBounds = pco->rclBounds;
  661. pbnk->iSaveDComplexity = pco->iDComplexity;
  662. pbnk->fjSaveOptions = pco->fjOptions;
  663. // Let GDI know that it has to pay attention to the clip object:
  664. pco->fjOptions |= OC_BANK_CLIP;
  665. // We have to honour the original clip object's rclBounds, so
  666. // intersect the drawing region with it, then convert to absolute
  667. // coordinates:
  668. pbnk->rclDraw.left
  669. = max(prclDraw->left, pco->rclBounds.left) + xOffset;
  670. pbnk->rclDraw.right
  671. = min(prclDraw->right, pco->rclBounds.right) + xOffset;
  672. pbnk->rclDraw.top
  673. = max(prclDraw->top, pco->rclBounds.top) + yOffset;
  674. pbnk->rclDraw.bottom
  675. = min(prclDraw->bottom, pco->rclBounds.bottom) + yOffset;
  676. }
  677. if ((pbnk->rclDraw.left > pbnk->rclDraw.right)
  678. || (pbnk->rclDraw.top > pbnk->rclDraw.bottom))
  679. {
  680. // It's conceivable that we could get a situation where we have
  681. // an empty draw rectangle.
  682. pbnk->rclDraw.left = 0;
  683. pbnk->rclDraw.right = 0;
  684. pbnk->rclDraw.top = 0;
  685. pbnk->rclDraw.bottom = 0;
  686. }
  687. if (!ppdev->pfnBankCompute(ppdev, &pbnk->rclDraw, &pco->rclBounds,
  688. &cjOffset, &pbnk->iBank))
  689. {
  690. // The drawing operation spans multiple banks. If the original
  691. // clip object was marked as trivial, we have to make sure to
  692. // change it to rectangular so that GDI knows to pay attention
  693. // to the bounds of the bank:
  694. if (pco->iDComplexity == DC_TRIVIAL)
  695. pco->iDComplexity = DC_RECT;
  696. }
  697. pbnk->ppdev = ppdev;
  698. pbnk->pco = pco;
  699. pbnk->pso = ppdev->psoBank;
  700. // Convert rclBounds and pvScan0 from absolute coordinates back to
  701. // relative. When GDI calculates where to start drawing, it computes
  702. // pjDst = pso->pvScan0 + y * pso->lDelta + CONVERT_TO_BYTES(x, ppdev), where 'x'
  703. // and 'y' are relative coordinates. We'll muck with pvScan0 to get
  704. // it pointing to the correct spot in the bank:
  705. pbnk->pso->pvScan0 = ppdev->pjScreen - cjOffset
  706. + yOffset * ppdev->lDelta
  707. + CONVERT_TO_BYTES(xOffset, ppdev);
  708. pbnk->pso->lDelta = ppdev->lDelta; // Other functions muck with this value
  709. ASSERTDD((((ULONG_PTR) pbnk->pso->pvScan0) & 3) == 0,
  710. "Off-screen bitmaps must be dword aligned");
  711. pco->rclBounds.left -= xOffset;
  712. pco->rclBounds.right -= xOffset;
  713. pco->rclBounds.top -= yOffset;
  714. pco->rclBounds.bottom -= yOffset;
  715. // Enable banking and map in bank iBank:
  716. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  717. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_ON);
  718. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, pbnk->iBank);
  719. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  720. }
  721. /******************************Public*Routine******************************\
  722. * BOOL bBankEnum
  723. *
  724. * If there is another bank to be drawn on, maps in the bank and returns
  725. * TRUE and the CLIPOBJ and SURFOBJ to be passed in the banked call-back.
  726. *
  727. * If there were no more banks to be drawn, returns FALSE.
  728. *
  729. \**************************************************************************/
  730. BOOL bBankEnum(
  731. BANK* pbnk)
  732. {
  733. LONG iBank;
  734. LONG cjOffset;
  735. PDEV* ppdev;
  736. CLIPOBJ* pco;
  737. LONG xOffset;
  738. LONG yOffset;
  739. ppdev = pbnk->ppdev;
  740. pco = pbnk->pco;
  741. xOffset = ppdev->xOffset;
  742. yOffset = ppdev->yOffset;
  743. // We check here to see if we have to handle the second part of
  744. // a broken raster. Recall that pbnk->rclDraw is in absolute
  745. // coordinates, but pco->rclBounds is in relative coordinates:
  746. if (pbnk->rclDraw.right - xOffset != pco->rclBounds.right)
  747. {
  748. // The clip object's 'top' and 'bottom' are already correct:
  749. pco->rclBounds.left = pco->rclBounds.right;
  750. pco->rclBounds.right = pbnk->rclDraw.right - xOffset;
  751. pbnk->pso->pvScan0 = (BYTE*) pbnk->pso->pvScan0 - ppdev->cjBank;
  752. pbnk->iBank++;
  753. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  754. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, pbnk->iBank);
  755. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  756. return(TRUE);
  757. }
  758. if (pbnk->rclDraw.bottom > pco->rclBounds.bottom + yOffset)
  759. {
  760. // Advance the drawing area 'top' to account for the bank we've
  761. // just finished, and map in the new bank:
  762. pbnk->rclDraw.top = pco->rclBounds.bottom + yOffset;
  763. ppdev->pfnBankCompute(ppdev, &pbnk->rclDraw, &pco->rclBounds,
  764. &cjOffset, &iBank);
  765. // Convert rclBounds back from absolute to relative coordinates:
  766. pco->rclBounds.left -= xOffset;
  767. pco->rclBounds.right -= xOffset;
  768. pco->rclBounds.top -= yOffset;
  769. pco->rclBounds.bottom -= yOffset;
  770. // If we just finished handling a broken raster, we've already
  771. // got the bank mapped in:
  772. if (iBank != pbnk->iBank)
  773. {
  774. pbnk->iBank = iBank;
  775. pbnk->pso->pvScan0 = (BYTE*) pbnk->pso->pvScan0 - ppdev->cjBank;
  776. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  777. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, iBank);
  778. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  779. }
  780. return(TRUE);
  781. }
  782. // We're done! Turn off banking and reset the clip object if necessary:
  783. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  784. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_OFF);
  785. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  786. if (pco != ppdev->pcoBank)
  787. {
  788. pco->rclBounds = pbnk->rclSaveBounds;
  789. pco->iDComplexity = pbnk->iSaveDComplexity;
  790. pco->fjOptions = pbnk->fjSaveOptions;
  791. }
  792. return(FALSE);
  793. }
  794. /******************************Public*Routine******************************\
  795. * VOID vAlignedCopy
  796. *
  797. * Copies the given portion of a bitmap, using dword alignment for the
  798. * screen. Note that this routine has no notion of banking.
  799. *
  800. * Updates ppjDst and ppjSrc to point to the beginning of the next scan.
  801. *
  802. \**************************************************************************/
  803. VOID vAlignedCopy(
  804. PDEV* ppdev,
  805. BYTE** ppjDst,
  806. LONG lDstDelta,
  807. BYTE** ppjSrc,
  808. LONG lSrcDelta,
  809. LONG cjScan,
  810. LONG cyScan,
  811. BOOL bDstIsScreen)
  812. {
  813. BYTE* pjDst;
  814. BYTE* pjSrc;
  815. LONG cjMiddle;
  816. LONG culMiddle;
  817. LONG cjStartPhase;
  818. LONG cjEndPhase;
  819. pjSrc = *ppjSrc;
  820. pjDst = *ppjDst;
  821. cjStartPhase = (LONG)((0 - ((bDstIsScreen) ? (ULONG_PTR) pjDst
  822. : (ULONG_PTR) pjSrc)) & 3);
  823. cjMiddle = cjScan - cjStartPhase;
  824. if (cjMiddle < 0)
  825. {
  826. cjStartPhase = 0;
  827. cjMiddle = cjScan;
  828. }
  829. lSrcDelta -= cjScan;
  830. lDstDelta -= cjScan; // Account for middle
  831. cjEndPhase = cjMiddle & 3;
  832. culMiddle = cjMiddle >> 2;
  833. if (DIRECT_ACCESS(ppdev))
  834. {
  835. LONG i;
  836. ///////////////////////////////////////////////////////////////////
  837. // Portable bus-aligned copy
  838. //
  839. // 'memcpy' usually aligns to the destination, so we could call
  840. // it for that case, but unfortunately we can't be sure. We
  841. // always want to align to the frame buffer:
  842. CP_MEMORY_BARRIER();
  843. if (bDstIsScreen)
  844. {
  845. // Align to the destination (implying that the source may be
  846. // unaligned):
  847. for (; cyScan > 0; cyScan--)
  848. {
  849. for (i = cjStartPhase; i > 0; i--)
  850. {
  851. *pjDst++ = *pjSrc++;
  852. }
  853. for (i = culMiddle; i > 0; i--)
  854. {
  855. *((ULONG*) pjDst) = *((ULONG UNALIGNED *) pjSrc);
  856. pjSrc += sizeof(ULONG);
  857. pjDst += sizeof(ULONG);
  858. }
  859. for (i = cjEndPhase; i > 0; i--)
  860. {
  861. *pjDst++ = *pjSrc++;
  862. }
  863. pjSrc += lSrcDelta;
  864. pjDst += lDstDelta;
  865. }
  866. }
  867. else
  868. {
  869. // Align to the source (implying that the destination may be
  870. // unaligned):
  871. for (; cyScan > 0; cyScan--)
  872. {
  873. for (i = cjStartPhase; i > 0; i--)
  874. {
  875. *pjDst++ = *pjSrc++;
  876. }
  877. if (ppdev->flCaps & CAPS_BAD_DWORD_READS)
  878. {
  879. // #9 and Diamond 764 boards randomly fail in different
  880. // spots on the HCTs, unless we do byte reads:
  881. for (i = culMiddle; i > 0; i--)
  882. {
  883. *(pjDst) = *(pjSrc);
  884. *(pjDst + 1) = *(pjSrc + 1);
  885. *(pjDst + 2) = *(pjSrc + 2);
  886. *(pjDst + 3) = *(pjSrc + 3);
  887. pjSrc += sizeof(ULONG);
  888. pjDst += sizeof(ULONG);
  889. }
  890. }
  891. else
  892. {
  893. for (i = culMiddle; i > 0; i--)
  894. {
  895. if (ppdev->flCaps & CAPS_FORCE_DWORD_REREADS)
  896. {
  897. //
  898. // On fast MIPS machines, the cpu overdrives
  899. // the card, so this code slows it down as
  900. // little as possible while checking for
  901. // consistency.
  902. //
  903. ULONG cnt = 4;
  904. while (cnt)
  905. {
  906. ULONG tmp = *((volatile ULONG*) (pjSrc));
  907. *((ULONG UNALIGNED *) pjDst) =
  908. *((volatile ULONG*) (pjSrc));
  909. if (tmp == *((volatile ULONG UNALIGNED *) pjDst))
  910. break;
  911. --cnt;
  912. }
  913. }
  914. else
  915. {
  916. *((ULONG UNALIGNED *) pjDst) = *((ULONG*) (pjSrc));
  917. }
  918. pjSrc += sizeof(ULONG);
  919. pjDst += sizeof(ULONG);
  920. }
  921. }
  922. for (i = cjEndPhase; i > 0; i--)
  923. {
  924. *pjDst++ = *pjSrc++;
  925. }
  926. pjSrc += lSrcDelta;
  927. pjDst += lDstDelta;
  928. }
  929. }
  930. *ppjSrc = pjSrc; // Save the updated pointers
  931. *ppjDst = pjDst;
  932. }
  933. else
  934. {
  935. LONG i;
  936. ///////////////////////////////////////////////////////////////////
  937. // No direct dword reads bus-aligned copy
  938. //
  939. // Because we support the S3 on ancient Jensen Alpha's, we also
  940. // have to support a sparse view of the frame buffer -- which
  941. // means using the 'ioaccess.h' macros.
  942. //
  943. // We also go through this code path if doing dword reads would
  944. // crash a non-x86 system.
  945. MEMORY_BARRIER();
  946. if (bDstIsScreen)
  947. {
  948. // Align to the destination (implying that the source may be
  949. // unaligned):
  950. for (; cyScan > 0; cyScan--)
  951. {
  952. for (i = cjStartPhase; i > 0; i--)
  953. {
  954. WRITE_REGISTER_UCHAR(pjDst, *pjSrc);
  955. pjSrc++;
  956. pjDst++;
  957. }
  958. for (i = culMiddle; i > 0; i--)
  959. {
  960. WRITE_REGISTER_ULONG(pjDst, *((ULONG UNALIGNED *) pjSrc));
  961. pjSrc += sizeof(ULONG);
  962. pjDst += sizeof(ULONG);
  963. }
  964. for (i = cjEndPhase; i > 0; i--)
  965. {
  966. WRITE_REGISTER_UCHAR(pjDst, *pjSrc);
  967. pjSrc++;
  968. pjDst++;
  969. }
  970. pjSrc += lSrcDelta;
  971. pjDst += lDstDelta;
  972. }
  973. }
  974. else
  975. {
  976. // Align to the source (implying that the destination may be
  977. // unaligned):
  978. for (; cyScan > 0; cyScan--)
  979. {
  980. for (i = cjStartPhase; i > 0; i--)
  981. {
  982. *pjDst = READ_REGISTER_UCHAR(pjSrc);
  983. pjSrc++;
  984. pjDst++;
  985. }
  986. for (i = culMiddle; i > 0; i--)
  987. {
  988. // There are some board 864/964 boards where we can't
  989. // do dword reads from the frame buffer without
  990. // crashing the system.
  991. *((ULONG UNALIGNED *) pjDst) =
  992. ((ULONG) READ_REGISTER_UCHAR(pjSrc + 3) << 24) |
  993. ((ULONG) READ_REGISTER_UCHAR(pjSrc + 2) << 16) |
  994. ((ULONG) READ_REGISTER_UCHAR(pjSrc + 1) << 8) |
  995. ((ULONG) READ_REGISTER_UCHAR(pjSrc));
  996. pjSrc += sizeof(ULONG);
  997. pjDst += sizeof(ULONG);
  998. }
  999. for (i = cjEndPhase; i > 0; i--)
  1000. {
  1001. *pjDst = READ_REGISTER_UCHAR(pjSrc);
  1002. pjSrc++;
  1003. pjDst++;
  1004. }
  1005. pjSrc += lSrcDelta;
  1006. pjDst += lDstDelta;
  1007. }
  1008. }
  1009. *ppjSrc = pjSrc; // Save the updated pointers
  1010. *ppjDst = pjDst;
  1011. }
  1012. }
  1013. /******************************Public*Routine******************************\
  1014. * VOID vPutBits
  1015. *
  1016. * Copies the bits from the given surface to the screen, using the memory
  1017. * aperture. Must be pre-clipped.
  1018. *
  1019. \**************************************************************************/
  1020. VOID vPutBits(
  1021. PDEV* ppdev,
  1022. SURFOBJ* psoSrc,
  1023. RECTL* prclDst, // Absolute coordinates!
  1024. POINTL* pptlSrc) // Absolute coordinates!
  1025. {
  1026. RECTL rclDraw;
  1027. RECTL rclBank;
  1028. LONG iBank;
  1029. LONG cjOffset;
  1030. LONG cyScan;
  1031. LONG lDstDelta;
  1032. LONG lSrcDelta;
  1033. BYTE* pjDst;
  1034. BYTE* pjSrc;
  1035. LONG cjScan;
  1036. LONG iNewBank;
  1037. LONG cjRemainder;
  1038. // We need a local copy of 'rclDraw' because we'll be iteratively
  1039. // modifying 'top' and passing the modified rectangle back into
  1040. // bBankComputeNonPower2:
  1041. rclDraw = *prclDst;
  1042. ASSERTDD((rclDraw.left >= 0) &&
  1043. (rclDraw.top >= 0) &&
  1044. (rclDraw.right <= ppdev->cxMemory) &&
  1045. (rclDraw.bottom <= ppdev->cyMemory),
  1046. "Rectangle wasn't fully clipped");
  1047. //
  1048. // Wait for engine idle.
  1049. //
  1050. IO_GP_WAIT(ppdev);
  1051. // Compute the first bank, enable banking, then map in iBank:
  1052. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  1053. ppdev->pfnBankCompute(ppdev, &rclDraw, &rclBank, &cjOffset, &iBank);
  1054. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_ON);
  1055. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, iBank);
  1056. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  1057. // Calculate the pointer to the upper-left corner of both rectangles:
  1058. lDstDelta = ppdev->lDelta;
  1059. pjDst = ppdev->pjScreen + rclDraw.top * lDstDelta
  1060. + CONVERT_TO_BYTES(rclDraw.left, ppdev)
  1061. - cjOffset;
  1062. lSrcDelta = psoSrc->lDelta;
  1063. pjSrc = (BYTE*) psoSrc->pvScan0 + pptlSrc->y * lSrcDelta
  1064. + CONVERT_TO_BYTES(pptlSrc->x, ppdev);
  1065. while (TRUE)
  1066. {
  1067. cjScan = CONVERT_TO_BYTES((rclBank.right - rclBank.left), ppdev);
  1068. cyScan = (rclBank.bottom - rclBank.top);
  1069. vAlignedCopy(ppdev, &pjDst, lDstDelta, &pjSrc, lSrcDelta, cjScan, cyScan,
  1070. TRUE); // Screen is the destination
  1071. if (rclDraw.right != rclBank.right)
  1072. {
  1073. // Handle the second part of the broken raster:
  1074. iBank++;
  1075. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  1076. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, iBank);
  1077. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  1078. // Number of bytes we've yet to do on the broken scan:
  1079. cjRemainder = CONVERT_TO_BYTES((rclDraw.right - rclBank.right),
  1080. ppdev);
  1081. // Account for the fact that we're now one bank lower in the
  1082. // destination:
  1083. pjDst -= ppdev->cjBank;
  1084. // Implicitly back up the source and destination pointers to the
  1085. // unfinished portion of the scan:
  1086. if (DIRECT_ACCESS(ppdev))
  1087. {
  1088. memcpy(pjDst + (cjScan - lDstDelta),
  1089. pjSrc + (cjScan - lSrcDelta),
  1090. cjRemainder);
  1091. }
  1092. else
  1093. {
  1094. BYTE* pjTmpDst = pjDst + (cjScan - lDstDelta);
  1095. BYTE* pjTmpSrc = pjSrc + (cjScan - lSrcDelta);
  1096. vAlignedCopy(ppdev, &pjTmpDst, 0, &pjTmpSrc, 0, cjRemainder, 1,
  1097. TRUE); // Screen is the destination
  1098. }
  1099. }
  1100. if (rclDraw.bottom > rclBank.bottom)
  1101. {
  1102. rclDraw.top = rclBank.bottom;
  1103. ppdev->pfnBankCompute(ppdev, &rclDraw, &rclBank, &cjOffset,
  1104. &iNewBank);
  1105. // If we just handled the second part of a broken raster,
  1106. // then we've already got the bank correctly mapped in:
  1107. if (iNewBank != iBank)
  1108. {
  1109. pjDst -= ppdev->cjBank;
  1110. iBank = iNewBank;
  1111. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  1112. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, iBank);
  1113. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  1114. }
  1115. }
  1116. else
  1117. {
  1118. // We're done! Turn off banking and leave:
  1119. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  1120. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_OFF);
  1121. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  1122. return;
  1123. }
  1124. }
  1125. }
  1126. /******************************Public*Routine******************************\
  1127. * VOID vGetBits
  1128. *
  1129. * Copies the bits to the given surface from the screen, using the memory
  1130. * aperture. Must be pre-clipped.
  1131. *
  1132. \**************************************************************************/
  1133. VOID vGetBits(
  1134. PDEV* ppdev,
  1135. SURFOBJ* psoDst,
  1136. RECTL* prclDst, // Absolute coordinates!
  1137. POINTL* pptlSrc) // Absolute coordinates!
  1138. {
  1139. RECTL rclDraw;
  1140. RECTL rclBank;
  1141. LONG iBank;
  1142. LONG cjOffset;
  1143. LONG cyScan;
  1144. LONG lDstDelta;
  1145. LONG lSrcDelta;
  1146. BYTE* pjDst;
  1147. BYTE* pjSrc;
  1148. LONG cjScan;
  1149. LONG iNewBank;
  1150. LONG cjRemainder;
  1151. rclDraw.left = pptlSrc->x;
  1152. rclDraw.top = pptlSrc->y;
  1153. rclDraw.right = rclDraw.left + (prclDst->right - prclDst->left);
  1154. rclDraw.bottom = rclDraw.top + (prclDst->bottom - prclDst->top);
  1155. ASSERTDD((rclDraw.left >= 0) &&
  1156. (rclDraw.top >= 0) &&
  1157. (rclDraw.right <= ppdev->cxMemory) &&
  1158. (rclDraw.bottom <= ppdev->cyMemory),
  1159. "Rectangle wasn't fully clipped");
  1160. //
  1161. // Wait for engine idle.
  1162. //
  1163. IO_GP_WAIT(ppdev);
  1164. // Compute the first bank, enable banking, then map in iBank.
  1165. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  1166. ppdev->pfnBankCompute(ppdev, &rclDraw, &rclBank, &cjOffset, &iBank);
  1167. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_ON);
  1168. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, iBank);
  1169. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  1170. // Calculate the pointer to the upper-left corner of both rectangles:
  1171. lSrcDelta = ppdev->lDelta;
  1172. pjSrc = ppdev->pjScreen + rclDraw.top * lSrcDelta
  1173. + CONVERT_TO_BYTES(rclDraw.left, ppdev)
  1174. - cjOffset;
  1175. lDstDelta = psoDst->lDelta;
  1176. pjDst = (BYTE*) psoDst->pvScan0 + prclDst->top * lDstDelta
  1177. + CONVERT_TO_BYTES(prclDst->left, ppdev);
  1178. while (TRUE)
  1179. {
  1180. cjScan = CONVERT_TO_BYTES((rclBank.right - rclBank.left), ppdev);
  1181. cyScan = (rclBank.bottom - rclBank.top);
  1182. vAlignedCopy(ppdev, &pjDst, lDstDelta, &pjSrc, lSrcDelta, cjScan, cyScan,
  1183. FALSE); // Screen is the source
  1184. if (rclDraw.right != rclBank.right)
  1185. {
  1186. // Handle the second part of the broken raster:
  1187. iBank++;
  1188. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  1189. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, iBank);
  1190. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  1191. // Number of bytes we've yet to do on the broken scan:
  1192. cjRemainder = CONVERT_TO_BYTES((rclDraw.right - rclBank.right),
  1193. ppdev);
  1194. // Account for the fact that we're now one bank lower in the
  1195. // source:
  1196. pjSrc -= ppdev->cjBank;
  1197. // Implicitly back up the source and destination pointers to the
  1198. // unfinished portion of the scan. Note that we don't have to
  1199. // advance the pointers because they're already pointing to the
  1200. // beginning of the next scan:
  1201. if (DIRECT_ACCESS(ppdev))
  1202. {
  1203. memcpy(pjDst + (cjScan - lDstDelta),
  1204. pjSrc + (cjScan - lSrcDelta),
  1205. cjRemainder);
  1206. }
  1207. else
  1208. {
  1209. BYTE* pjTmpDst = pjDst + (cjScan - lDstDelta);
  1210. BYTE* pjTmpSrc = pjSrc + (cjScan - lSrcDelta);
  1211. vAlignedCopy(ppdev, &pjTmpDst, 0, &pjTmpSrc, 0, cjRemainder, 1,
  1212. FALSE); // Screen is the source
  1213. }
  1214. }
  1215. if (rclDraw.bottom > rclBank.bottom)
  1216. {
  1217. rclDraw.top = rclBank.bottom;
  1218. ppdev->pfnBankCompute(ppdev, &rclDraw, &rclBank, &cjOffset,
  1219. &iNewBank);
  1220. // If we just handled the second part of a broken raster,
  1221. // then we've already got the bank correctly mapped in:
  1222. if (iNewBank != iBank)
  1223. {
  1224. pjSrc -= ppdev->cjBank;
  1225. iBank = iNewBank;
  1226. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  1227. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, iBank);
  1228. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  1229. }
  1230. }
  1231. else
  1232. {
  1233. // We're done! Turn off banking and leave:
  1234. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  1235. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_OFF);
  1236. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  1237. return;
  1238. }
  1239. }
  1240. }