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.

1133 lines
35 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: bank.c
  3. *
  4. * Contains all the banking code for the display driver.
  5. *
  6. * It's helpful not to have to implement all the DDI drawing functionality
  7. * in a driver (who wants to write the code to support true ROP4's with
  8. * arbitrary sized patterns?). Fortunately, we can punt to GDI for any
  9. * drawing we don't want to do. And if GDI can write directly on the frame
  10. * buffer bits, performance won't even be toooo bad.
  11. *
  12. * NT's GDI can draw on any standard format frame buffer. When the entire
  13. * frame buffer can be mapped into main memory, it's very simple to set up:
  14. * the display driver tells GDI the frame buffer format and location, and
  15. * GDI can then just draw directly.
  16. *
  17. * When only one bank of the frame buffer can be mapped into main memory
  18. * at one time (e.g., there is a moveable 64k aperture) things are not
  19. * nearly so easy. For every bank spanned by a drawing operation, we have
  20. * to set the hardware to the bank, and call back to GDI. We tell GDI
  21. * to draw only on the mapped-in bank by mucking with the drawing call's
  22. * CLIPOBJ.
  23. *
  24. * This module contains the code for doing all banking support.
  25. *
  26. * This code supports 8, 16 and 32bpp colour depths, arbitrary bank
  27. * sizes, and handles 'broken rasters' (which happens when the bank size
  28. * is not a multiple of the scan length; some scans will end up being
  29. * split over two separate banks).
  30. *
  31. * Note: If you mess with this code and break it, you can expect to get
  32. * random access violations on call-backs in internal GDI routines
  33. * that are very hard to debug.
  34. *
  35. * Copyright (c) 1993-1995 Microsoft Corporation
  36. \**************************************************************************/
  37. #include "precomp.h"
  38. ////////////////////////////////////////////////////////////////////////////
  39. VOID vI32BankSelectMode( // Note: If this function changes, must
  40. PDEV* ppdev, // change Asm routines!
  41. BANKDATA* pbd,
  42. BANK_MODE bankm)
  43. {
  44. BYTE* pjIoBase;
  45. if (bankm == BANK_ON)
  46. {
  47. // Make sure the processor's graphics engine is idle before we
  48. // start drawing. See wait_for_idle_M8.
  49. pjIoBase = ppdev->pjIoBase;
  50. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 16);
  51. do {} while (I32_IW(pjIoBase, EXT_GE_STATUS) & GE_ACTIVE);
  52. }
  53. }
  54. VOID vI32BankMap(
  55. PDEV* ppdev,
  56. BANKDATA* pbd,
  57. LONG iBank)
  58. {
  59. I32_OW_DIRECT(ppdev->pjIoBase, 0x01CE, ((iBank & 0x0f) << 9) | 0xb2);
  60. I32_OW_DIRECT(ppdev->pjIoBase, 0x01CE, ((iBank & 0x30) << 4) | 0xae);
  61. }
  62. VOID vI32BankInitialize(
  63. PDEV* ppdev,
  64. BANKDATA* pbd)
  65. {
  66. }
  67. ////////////////////////////////////////////////////////////////////////////
  68. VOID vM64BankSelectMode( // Note: If this function changes, must
  69. PDEV* ppdev, // change Asm routines!
  70. BANKDATA* pbd,
  71. BANK_MODE bankm)
  72. {
  73. BYTE* pjMmBase;
  74. if (bankm == BANK_ON)
  75. {
  76. // Make sure the processor's graphics engine is idle before we
  77. // start drawing. See wait_for_idle_M64.
  78. pjMmBase = ppdev->pjMmBase;
  79. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 16);
  80. do {} while (M64_ID(pjMmBase, GUI_STAT) & 1);
  81. }
  82. }
  83. VOID vM64BankMap(
  84. PDEV* ppdev,
  85. BANKDATA* pbd,
  86. LONG iBank)
  87. {
  88. M64_OD_DIRECT(ppdev->pjMmBase, MEM_VGA_WP_SEL,
  89. (iBank*2) | ((iBank*2 + 1) << 16));
  90. M64_OD_DIRECT(ppdev->pjMmBase, MEM_VGA_RP_SEL,
  91. (iBank*2) | ((iBank*2 + 1) << 16));
  92. }
  93. VOID vM64BankInitialize(
  94. PDEV* ppdev,
  95. BANKDATA* pbd)
  96. {
  97. }
  98. /******************************Public*Routine******************************\
  99. * BOOL bEnableBanking
  100. *
  101. \**************************************************************************/
  102. BOOL bEnableBanking(
  103. PDEV* ppdev)
  104. {
  105. CLIPOBJ* pcoBank;
  106. SURFOBJ* psoBank;
  107. SIZEL sizl;
  108. HSURF hsurf;
  109. FNBANKINITIALIZE* pfnBankInitialize;
  110. LONG lDelta;
  111. LONG cjBank;
  112. LONG cPower2;
  113. // Create a temporary clip object that we'll use for the bank
  114. // when we're given a Null or DC_TRIVIAL clip object:
  115. pcoBank = EngCreateClip();
  116. if (pcoBank == NULL)
  117. goto ReturnFalse;
  118. // We break every per-bank GDI call-back into simple rectangles:
  119. pcoBank->iDComplexity = DC_RECT;
  120. pcoBank->fjOptions = OC_BANK_CLIP;
  121. // Create a GDI surface that we'll wrap around our bank in
  122. // call-backs:
  123. sizl.cx = ppdev->cxMemory;
  124. sizl.cy = ppdev->cyMemory;
  125. hsurf = (HSURF) EngCreateBitmap(sizl,
  126. ppdev->lDelta,
  127. ppdev->iBitmapFormat,
  128. BMF_TOPDOWN,
  129. ppdev->pjScreen);
  130. // Note that we hook zero calls -- after all, the entire point
  131. // of all this is to have GDI do all the drawing on the bank.
  132. // Once we're done the association, we can leave the surface
  133. // permanently locked:
  134. if ((hsurf == 0) ||
  135. (!EngAssociateSurface(hsurf, ppdev->hdevEng, 0)) ||
  136. (!(psoBank = EngLockSurface(hsurf))))
  137. {
  138. DISPDBG((0, "Failed wrapper surface creation"));
  139. EngDeleteSurface(hsurf);
  140. EngDeleteClip(pcoBank);
  141. goto ReturnFalse;
  142. }
  143. ppdev->hsurfPunt = hsurf; // Just for 24bpp mach32 with linear aperture
  144. ppdev->pcoBank = pcoBank;
  145. ppdev->psoBank = psoBank;
  146. ppdev->pvBankData = &ppdev->aulBankData[0];
  147. if ((ppdev->iMachType == MACH_MM_32) || (ppdev->iMachType == MACH_IO_32))
  148. {
  149. ppdev->bankmOnOverlapped = BANK_ON;
  150. ppdev->pfnBankMap = vI32BankMap;
  151. ppdev->pfnBankSelectMode = vI32BankSelectMode;
  152. pfnBankInitialize = vI32BankInitialize;
  153. }
  154. else
  155. {
  156. ppdev->bankmOnOverlapped = BANK_ON;
  157. ppdev->pfnBankMap = vM64BankMap;
  158. ppdev->pfnBankSelectMode = vM64BankSelectMode;
  159. pfnBankInitialize = vM64BankInitialize;
  160. }
  161. #if !defined(ALPHA)
  162. // For mach8, we only need the psoBank and function pointers
  163. // initialized. Because cjBank will be zero, if we continue
  164. // we will be in trouble.
  165. if (ppdev->iAperture == APERTURE_NONE)
  166. return TRUE;
  167. #endif
  168. lDelta = ppdev->lDelta;
  169. cjBank = ppdev->cjBank;
  170. ASSERTDD(lDelta > 0, "Bad things happen with negative lDeltas");
  171. ASSERTDD(cjBank > lDelta, "Worse things happen with bad bank sizes");
  172. if (((lDelta & (lDelta - 1)) != 0) || ((cjBank & (cjBank - 1)) != 0))
  173. {
  174. // When either the screen stride or the bank size is not a power
  175. // of two, we have to use the slower 'bBankComputeNonPower2'
  176. // function for bank calculations, 'cause there can be broken
  177. // rasters and stuff:
  178. ppdev->pfnBankCompute = bBankComputeNonPower2;
  179. }
  180. else
  181. {
  182. // We can use the super duper fast bank calculator. Yippie,
  183. // yahoo! (I am easily amused.)
  184. cPower2 = 0;
  185. while (cjBank != lDelta)
  186. {
  187. cjBank >>= 1;
  188. cPower2++;
  189. }
  190. // We've just calculated that cjBank / lDelta = 2 ^ cPower2:
  191. ppdev->cPower2ScansPerBank = cPower2;
  192. while (cjBank != 1)
  193. {
  194. cjBank >>= 1;
  195. cPower2++;
  196. }
  197. // Continuing on, we've calculated that cjBank = 2 ^ cPower2:
  198. ppdev->cPower2BankSizeInBytes = cPower2;
  199. ppdev->pfnBankCompute = bBankComputePower2;
  200. }
  201. // Warm up the hardware:
  202. pfnBankInitialize(ppdev, ppdev->pvBankData);
  203. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_ENABLE);
  204. DISPDBG((5, "Passed bEnableBanking"));
  205. return(TRUE);
  206. ReturnFalse:
  207. DISPDBG((0, "Failed bEnableBanking!"));
  208. return(FALSE);
  209. }
  210. /******************************Public*Routine******************************\
  211. * VOID vDisableBanking
  212. *
  213. \**************************************************************************/
  214. VOID vDisableBanking(PDEV* ppdev)
  215. {
  216. HSURF hsurf;
  217. if (ppdev->psoBank != NULL)
  218. {
  219. hsurf = ppdev->psoBank->hsurf;
  220. EngUnlockSurface(ppdev->psoBank);
  221. EngDeleteSurface(hsurf);
  222. }
  223. if (ppdev->pcoBank != NULL)
  224. EngDeleteClip(ppdev->pcoBank);
  225. }
  226. /******************************Public*Routine******************************\
  227. * VOID vAssertModeBanking
  228. *
  229. \**************************************************************************/
  230. VOID vAssertModeBanking(
  231. PDEV* ppdev,
  232. BOOL bEnable)
  233. {
  234. // Inform the miniport bank code about the change in state:
  235. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData,
  236. bEnable ? BANK_ENABLE : BANK_DISABLE);
  237. }
  238. /******************************Public*Routine******************************\
  239. * BOOL bBankComputeNonPower2
  240. *
  241. * Given the bounds of the drawing operation described by 'prclDraw',
  242. * computes the bank number and rectangle bounds for the first engine
  243. * call back.
  244. *
  245. * Returns the bank number, 'prclBank' is the bounds for the first
  246. * call-back, and 'pcjOffset' is the adjustment for 'pvScan0'.
  247. *
  248. * This routine does a couple of divides for the bank calculation. We
  249. * don't use a look-up table for banks because it's not straight forward
  250. * to use with broken rasters, and with large amounts of video memory
  251. * and small banks, the tables could get large. We'd probably use it
  252. * infrequently enough that the memory manager would be swapping it
  253. * in and out whenever we touched it.
  254. *
  255. * Returns TRUE if prclDraw is entirely contained in one bank; FALSE if
  256. * prclDraw spans multiple banks.
  257. *
  258. \**************************************************************************/
  259. BOOL bBankComputeNonPower2( // Type FNBANKCOMPUTE
  260. PDEV* ppdev,
  261. RECTL* prclDraw, // Extents of drawing operation, in absolute
  262. // coordinates
  263. RECTL* prclBank, // Returns bounds of drawing operation for this
  264. // bank, in absolute coordinates
  265. LONG* pcjOffset, // Returns the byte offset for this bank
  266. LONG* piBank) // Returns the bank number
  267. {
  268. LONG cjBufferOffset;
  269. LONG iBank;
  270. LONG cjBank;
  271. LONG cjBankOffset;
  272. LONG cjBankRemainder;
  273. LONG cjScan;
  274. LONG cScansInBank;
  275. LONG cjScanRemainder;
  276. LONG lDelta;
  277. BOOL bOneBank;
  278. bOneBank = FALSE;
  279. lDelta = ppdev->lDelta;
  280. cjBufferOffset = prclDraw->top * lDelta
  281. + (prclDraw->left * ppdev->cjPelSize);
  282. cjBank = ppdev->cjBank;
  283. // iBank = cjBufferOffset / cjBank;
  284. // cjBankOffset = cjBufferOffset % cjBank;
  285. QUOTIENT_REMAINDER(cjBufferOffset, cjBank, iBank, cjBankOffset);
  286. *piBank = iBank;
  287. *pcjOffset = iBank * cjBank;
  288. cjBankRemainder = cjBank - cjBankOffset;
  289. cjScan = (prclDraw->right - prclDraw->left) * ppdev->cjPelSize;
  290. if (cjBankRemainder < cjScan)
  291. {
  292. // Oh no, we've got a broken raster!
  293. prclBank->left = prclDraw->left;
  294. prclBank->right = prclDraw->left +
  295. (cjBankRemainder / ppdev->cjPelSize);
  296. prclBank->top = prclDraw->top;
  297. prclBank->bottom = prclDraw->top + 1;
  298. }
  299. else
  300. {
  301. // cScansInBank = cjBankRemainder / lDelta;
  302. // cjScanRemainder = cjBankRemainder % lDelta;
  303. ASSERTDD(lDelta > 0, "We assume positive lDelta here");
  304. QUOTIENT_REMAINDER(cjBankRemainder, lDelta,
  305. cScansInBank, cjScanRemainder);
  306. if (cjScanRemainder >= cjScan)
  307. {
  308. // The bottom scan of the bank may be broken, but it breaks after
  309. // any drawing we'll be doing on that scan. So we can simply
  310. // add the scan to this bank:
  311. cScansInBank++;
  312. }
  313. prclBank->left = prclDraw->left;
  314. prclBank->right = prclDraw->right;
  315. prclBank->top = prclDraw->top;
  316. prclBank->bottom = prclDraw->top + cScansInBank;
  317. if (prclBank->bottom >= prclDraw->bottom)
  318. {
  319. prclBank->bottom = prclDraw->bottom;
  320. bOneBank = TRUE;
  321. }
  322. }
  323. return(bOneBank);
  324. }
  325. /******************************Public*Routine******************************\
  326. * BOOL bBankComputePower2
  327. *
  328. * Functions the same as 'bBankComputeNonPower2', except that it is
  329. * an accelerated special case for when both the screen stride and bank
  330. * size are powers of 2.
  331. *
  332. \**************************************************************************/
  333. BOOL bBankComputePower2( // Type FNBANKCOMPUTE
  334. PDEV* ppdev,
  335. RECTL* prclDraw, // Extents of drawing operation, in absolute
  336. // coordinates
  337. RECTL* prclBank, // Returns bounds of drawing operation for this
  338. // bank, in absolute coordinates
  339. LONG* pcjOffset, // Returns the byte offset for this bank
  340. LONG* piBank) // Returns the bank number
  341. {
  342. LONG iBank;
  343. LONG yTopNextBank;
  344. BOOL bOneBank;
  345. iBank = prclDraw->top >> ppdev->cPower2ScansPerBank;
  346. yTopNextBank = (iBank + 1) << ppdev->cPower2ScansPerBank;
  347. *piBank = iBank;
  348. *pcjOffset = iBank << ppdev->cPower2BankSizeInBytes;
  349. prclBank->left = prclDraw->left;
  350. prclBank->right = prclDraw->right;
  351. prclBank->top = prclDraw->top;
  352. prclBank->bottom = yTopNextBank;
  353. bOneBank = FALSE;
  354. if (prclBank->bottom >= prclDraw->bottom)
  355. {
  356. prclBank->bottom = prclDraw->bottom;
  357. bOneBank = TRUE;
  358. }
  359. return(bOneBank);
  360. }
  361. /******************************Public*Routine******************************\
  362. * VOID vBankStart
  363. *
  364. * Given the bounds of the drawing operation described by 'prclDraw' and
  365. * the original clip object, maps in the first bank and returns in
  366. * 'pbnk->pco' and 'pbnk->pso' the CLIPOBJ and SURFOBJ to be passed to the
  367. * engine for the first banked call-back.
  368. *
  369. * Note: This routine only supports the screen being the destination, and
  370. * not the source. We have a separate, faster routine for doing
  371. * SRCCOPY reads from the screen, so it isn't worth the extra code
  372. * size to implement.
  373. *
  374. \**************************************************************************/
  375. VOID vBankStart(
  376. PDEV* ppdev, // Physical device information.
  377. RECTL* prclDraw, // Rectangle bounding the draw area, in relative
  378. // coordinates. Note that 'left' and 'right'
  379. // should be set for correct handling with broken
  380. // rasters.
  381. CLIPOBJ* pco, // Original drawing clip object (may be modified).
  382. BANK* pbnk) // Resulting bank information.
  383. {
  384. LONG cjOffset;
  385. LONG xOffset;
  386. LONG yOffset;
  387. xOffset = ppdev->xOffset;
  388. yOffset = ppdev->yOffset;
  389. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  390. {
  391. pco = ppdev->pcoBank;
  392. // Reset the clipping flag to trivial because we may have left
  393. // it as rectangular in a previous call:
  394. pco->iDComplexity = DC_TRIVIAL;
  395. // At the same time we convert to absolute coordinates, make sure
  396. // we won't try to enumerate past the bounds of the screen:
  397. pbnk->rclDraw.left = prclDraw->left + xOffset;
  398. pbnk->rclDraw.right = prclDraw->right + xOffset;
  399. pbnk->rclDraw.top
  400. = max(0, prclDraw->top + yOffset);
  401. pbnk->rclDraw.bottom
  402. = min(ppdev->cyMemory, prclDraw->bottom + yOffset);
  403. }
  404. else
  405. {
  406. pbnk->rclSaveBounds = pco->rclBounds;
  407. pbnk->iSaveDComplexity = pco->iDComplexity;
  408. pbnk->fjSaveOptions = pco->fjOptions;
  409. // Let GDI know that it has to pay attention to the clip object:
  410. pco->fjOptions |= OC_BANK_CLIP;
  411. // We have to honour the original clip object's rclBounds, so
  412. // intersect the drawing region with it, then convert to absolute
  413. // coordinates:
  414. pbnk->rclDraw.left
  415. = max(prclDraw->left, pco->rclBounds.left) + xOffset;
  416. pbnk->rclDraw.right
  417. = min(prclDraw->right, pco->rclBounds.right) + xOffset;
  418. pbnk->rclDraw.top
  419. = max(prclDraw->top, pco->rclBounds.top) + yOffset;
  420. pbnk->rclDraw.bottom
  421. = min(prclDraw->bottom, pco->rclBounds.bottom) + yOffset;
  422. }
  423. if ((pbnk->rclDraw.left > pbnk->rclDraw.right)
  424. || (pbnk->rclDraw.top > pbnk->rclDraw.bottom))
  425. {
  426. // It's conceivable that we could get a situation where we have
  427. // an empty draw rectangle. Make sure we won't puke on our shoes:
  428. pbnk->rclDraw.left = 0;
  429. pbnk->rclDraw.right = 0;
  430. pbnk->rclDraw.top = 0;
  431. pbnk->rclDraw.bottom = 0;
  432. }
  433. if (!ppdev->pfnBankCompute(ppdev, &pbnk->rclDraw, &pco->rclBounds,
  434. &cjOffset, &pbnk->iBank))
  435. {
  436. // The drawing operation spans multiple banks. If the original
  437. // clip object was marked as trivial, we have to make sure to
  438. // change it to rectangular so that GDI knows to pay attention
  439. // to the bounds of the bank:
  440. if (pco->iDComplexity == DC_TRIVIAL)
  441. pco->iDComplexity = DC_RECT;
  442. }
  443. pbnk->ppdev = ppdev;
  444. pbnk->pco = pco;
  445. pbnk->pso = ppdev->psoBank;
  446. // Convert rclBounds and pvScan0 from absolute coordinates back to
  447. // relative. When GDI calculates where to start drawing, it computes
  448. // pjDst = pso->pvScan0 + y * pso->lDelta + (x * cjPelSize), where 'x'
  449. // and 'y' are relative coordinates. We'll muck with pvScan0 to get
  450. // it pointing to the correct spot in the bank:
  451. pbnk->pso->pvScan0 = ppdev->pjScreen - cjOffset
  452. + yOffset * ppdev->lDelta
  453. + (xOffset * ppdev->cjPelSize);
  454. pbnk->pso->lDelta = ppdev->lDelta; // Other functions muck with this value
  455. ASSERTDD((((ULONG_PTR) pbnk->pso->pvScan0) & 3) == 0,
  456. "Off-screen bitmaps must be dword aligned");
  457. pco->rclBounds.left -= xOffset;
  458. pco->rclBounds.right -= xOffset;
  459. pco->rclBounds.top -= yOffset;
  460. pco->rclBounds.bottom -= yOffset;
  461. // Enable banking and map in bank iBank:
  462. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_ON);
  463. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, pbnk->iBank);
  464. }
  465. /******************************Public*Routine******************************\
  466. * BOOL bBankEnum
  467. *
  468. * If there is another bank to be drawn on, maps in the bank and returns
  469. * TRUE and the CLIPOBJ and SURFOBJ to be passed in the banked call-back.
  470. *
  471. * If there were no more banks to be drawn, returns FALSE.
  472. *
  473. \**************************************************************************/
  474. BOOL bBankEnum(
  475. BANK* pbnk)
  476. {
  477. LONG iBank;
  478. LONG cjOffset;
  479. PDEV* ppdev;
  480. CLIPOBJ* pco;
  481. LONG xOffset;
  482. LONG yOffset;
  483. ppdev = pbnk->ppdev;
  484. pco = pbnk->pco;
  485. xOffset = ppdev->xOffset;
  486. yOffset = ppdev->yOffset;
  487. // We check here to see if we have to handle the second part of
  488. // a broken raster. Recall that pbnk->rclDraw is in absolute
  489. // coordinates, but pco->rclBounds is in relative coordinates:
  490. if (pbnk->rclDraw.right - xOffset != pco->rclBounds.right)
  491. {
  492. // The clip object's 'top' and 'bottom' are already correct:
  493. pco->rclBounds.left = pco->rclBounds.right;
  494. pco->rclBounds.right = pbnk->rclDraw.right - xOffset;
  495. pbnk->pso->pvScan0 = (BYTE*) pbnk->pso->pvScan0 - ppdev->cjBank;
  496. pbnk->iBank++;
  497. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, pbnk->iBank);
  498. return(TRUE);
  499. }
  500. if (pbnk->rclDraw.bottom > pco->rclBounds.bottom + yOffset)
  501. {
  502. // Advance the drawing area 'top' to account for the bank we've
  503. // just finished, and map in the new bank:
  504. pbnk->rclDraw.top = pco->rclBounds.bottom + yOffset;
  505. ppdev->pfnBankCompute(ppdev, &pbnk->rclDraw, &pco->rclBounds,
  506. &cjOffset, &iBank);
  507. // Convert rclBounds back from absolute to relative coordinates:
  508. pco->rclBounds.left -= xOffset;
  509. pco->rclBounds.right -= xOffset;
  510. pco->rclBounds.top -= yOffset;
  511. pco->rclBounds.bottom -= yOffset;
  512. // If we just finished handling a broken raster, we've already
  513. // got the bank mapped in:
  514. if (iBank != pbnk->iBank)
  515. {
  516. pbnk->iBank = iBank;
  517. pbnk->pso->pvScan0 = (BYTE*) pbnk->pso->pvScan0 - ppdev->cjBank;
  518. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, iBank);
  519. }
  520. return(TRUE);
  521. }
  522. // We're done! Turn off banking and reset the clip object if necessary:
  523. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_OFF);
  524. if (pco != ppdev->pcoBank)
  525. {
  526. pco->rclBounds = pbnk->rclSaveBounds;
  527. pco->iDComplexity = pbnk->iSaveDComplexity;
  528. pco->fjOptions = pbnk->fjSaveOptions;
  529. }
  530. return(FALSE);
  531. }
  532. /******************************Public*Routine******************************\
  533. * VOID vAlignedCopy
  534. *
  535. * Copies the given portion of a bitmap, using dword alignment for the
  536. * screen. Note that this routine has no notion of banking.
  537. *
  538. * Updates ppjDst and ppjSrc to point to the beginning of the next scan.
  539. *
  540. \**************************************************************************/
  541. VOID vAlignedCopy(
  542. PDEV* ppdev,
  543. BYTE** ppjDst,
  544. LONG lDstDelta,
  545. BYTE** ppjSrc,
  546. LONG lSrcDelta,
  547. LONG cjScan,
  548. LONG cyScan,
  549. BOOL bDstIsScreen)
  550. {
  551. BYTE* pjDst;
  552. BYTE* pjSrc;
  553. LONG cjMiddle;
  554. LONG culMiddle;
  555. LONG cjStartPhase;
  556. LONG cjEndPhase;
  557. pjSrc = *ppjSrc;
  558. pjDst = *ppjDst;
  559. cjStartPhase = (LONG)(0 - ((bDstIsScreen) ? (ULONG_PTR) pjDst
  560. : (ULONG_PTR) pjSrc)) & 3;
  561. cjMiddle = cjScan - cjStartPhase;
  562. if (cjMiddle < 0)
  563. {
  564. cjStartPhase = 0;
  565. cjMiddle = cjScan;
  566. }
  567. lSrcDelta -= cjScan;
  568. lDstDelta -= cjScan; // Account for middle
  569. cjEndPhase = cjMiddle & 3;
  570. culMiddle = cjMiddle >> 2;
  571. if (DIRECT_ACCESS(ppdev))
  572. {
  573. LONG i;
  574. ///////////////////////////////////////////////////////////////////
  575. // Portable bus-aligned copy
  576. //
  577. // 'memcpy' usually aligns to the destination, so we could call
  578. // it for that case, but unfortunately we can't be sure. We
  579. // always want to align to the frame buffer:
  580. CP_MEMORY_BARRIER();
  581. if (bDstIsScreen)
  582. {
  583. // Align to the destination (implying that the source may be
  584. // unaligned):
  585. for (; cyScan > 0; cyScan--)
  586. {
  587. for (i = cjStartPhase; i > 0; i--)
  588. {
  589. *pjDst++ = *pjSrc++;
  590. }
  591. for (i = culMiddle; i > 0; i--)
  592. {
  593. *((ULONG*) pjDst) = *((ULONG UNALIGNED *) pjSrc);
  594. pjSrc += sizeof(ULONG);
  595. pjDst += sizeof(ULONG);
  596. }
  597. for (i = cjEndPhase; i > 0; i--)
  598. {
  599. *pjDst++ = *pjSrc++;
  600. }
  601. pjSrc += lSrcDelta;
  602. pjDst += lDstDelta;
  603. }
  604. }
  605. else
  606. {
  607. // Align to the source (implying that the destination may be
  608. // unaligned):
  609. for (; cyScan > 0; cyScan--)
  610. {
  611. for (i = cjStartPhase; i > 0; i--)
  612. {
  613. *pjDst++ = *pjSrc++;
  614. }
  615. for (i = culMiddle; i > 0; i--)
  616. {
  617. *((ULONG UNALIGNED *) pjDst) = *((ULONG*) (pjSrc));
  618. pjSrc += sizeof(ULONG);
  619. pjDst += sizeof(ULONG);
  620. }
  621. for (i = cjEndPhase; i > 0; i--)
  622. {
  623. *pjDst++ = *pjSrc++;
  624. }
  625. pjSrc += lSrcDelta;
  626. pjDst += lDstDelta;
  627. }
  628. }
  629. *ppjSrc = pjSrc; // Save the updated pointers
  630. *ppjDst = pjDst;
  631. }
  632. else
  633. {
  634. LONG i;
  635. ///////////////////////////////////////////////////////////////////
  636. // No direct dword reads bus-aligned copy
  637. //
  638. // Because we support the ATI on ancient Jensen Alpha's, we also
  639. // have to support a sparse view of the frame buffer -- which
  640. // means using the 'ioaccess.h' macros.
  641. //
  642. // We also go through this code path if doing dword reads would
  643. // crash a non-x86 system.
  644. MEMORY_BARRIER();
  645. if (bDstIsScreen)
  646. {
  647. // Align to the destination (implying that the source may be
  648. // unaligned):
  649. for (; cyScan > 0; cyScan--)
  650. {
  651. for (i = cjStartPhase; i > 0; i--)
  652. {
  653. WRITE_REGISTER_UCHAR(pjDst, *pjSrc);
  654. pjSrc++;
  655. pjDst++;
  656. }
  657. for (i = culMiddle; i > 0; i--)
  658. {
  659. WRITE_REGISTER_ULONG(pjDst, *((ULONG UNALIGNED *) pjSrc));
  660. pjSrc += sizeof(ULONG);
  661. pjDst += sizeof(ULONG);
  662. }
  663. for (i = cjEndPhase; i > 0; i--)
  664. {
  665. WRITE_REGISTER_UCHAR(pjDst, *pjSrc);
  666. pjSrc++;
  667. pjDst++;
  668. }
  669. pjSrc += lSrcDelta;
  670. pjDst += lDstDelta;
  671. }
  672. }
  673. else
  674. {
  675. // Align to the source (implying that the destination may be
  676. // unaligned):
  677. for (; cyScan > 0; cyScan--)
  678. {
  679. for (i = cjStartPhase; i > 0; i--)
  680. {
  681. *pjDst = READ_REGISTER_UCHAR(pjSrc);
  682. pjSrc++;
  683. pjDst++;
  684. }
  685. for (i = culMiddle; i > 0; i--)
  686. {
  687. // There are some board 864/964 boards where we can't
  688. // do dword reads from the frame buffer without
  689. // crashing the system.
  690. *((ULONG UNALIGNED *) pjDst) =
  691. ((ULONG) READ_REGISTER_UCHAR(pjSrc + 3) << 24) |
  692. ((ULONG) READ_REGISTER_UCHAR(pjSrc + 2) << 16) |
  693. ((ULONG) READ_REGISTER_UCHAR(pjSrc + 1) << 8) |
  694. ((ULONG) READ_REGISTER_UCHAR(pjSrc));
  695. pjSrc += sizeof(ULONG);
  696. pjDst += sizeof(ULONG);
  697. }
  698. for (i = cjEndPhase; i > 0; i--)
  699. {
  700. *pjDst = READ_REGISTER_UCHAR(pjSrc);
  701. pjSrc++;
  702. pjDst++;
  703. }
  704. pjSrc += lSrcDelta;
  705. pjDst += lDstDelta;
  706. }
  707. }
  708. *ppjSrc = pjSrc; // Save the updated pointers
  709. *ppjDst = pjDst;
  710. }
  711. }
  712. /******************************Public*Routine******************************\
  713. * VOID vPutBits
  714. *
  715. * Copies the bits from the given surface to the screen, using the memory
  716. * aperture. Must be pre-clipped.
  717. *
  718. \**************************************************************************/
  719. VOID vPutBits(
  720. PDEV* ppdev,
  721. SURFOBJ* psoSrc,
  722. RECTL* prclDst, // Absolute coordinates!
  723. POINTL* pptlSrc) // Absolute coordinates!
  724. {
  725. RECTL rclDraw;
  726. RECTL rclBank;
  727. LONG iBank;
  728. LONG cjOffset;
  729. LONG cyScan;
  730. LONG lDstDelta;
  731. LONG lSrcDelta;
  732. BYTE* pjDst;
  733. BYTE* pjSrc;
  734. LONG cjScan;
  735. LONG iNewBank;
  736. LONG cjRemainder;
  737. // We need a local copy of 'rclDraw' because we'll be iteratively
  738. // modifying 'top' and passing the modified rectangle back into
  739. // bBankComputeNonPower2:
  740. rclDraw = *prclDst;
  741. ASSERTDD((rclDraw.left >= 0) &&
  742. (rclDraw.top >= 0) &&
  743. (rclDraw.right <= ppdev->cxMemory) &&
  744. (rclDraw.bottom <= ppdev->cyMemory),
  745. "Rectangle wasn't fully clipped");
  746. // Compute the first bank, enable banking, then map in iBank:
  747. ppdev->pfnBankCompute(ppdev, &rclDraw, &rclBank, &cjOffset, &iBank);
  748. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_ON);
  749. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, iBank);
  750. // Calculate the pointer to the upper-left corner of both rectangles:
  751. lDstDelta = ppdev->lDelta;
  752. pjDst = ppdev->pjScreen + rclDraw.top * lDstDelta
  753. + (rclDraw.left * ppdev->cjPelSize)
  754. - cjOffset;
  755. lSrcDelta = psoSrc->lDelta;
  756. pjSrc = (BYTE*) psoSrc->pvScan0 + pptlSrc->y * lSrcDelta
  757. + (pptlSrc->x * ppdev->cjPelSize);
  758. while (TRUE)
  759. {
  760. cjScan = (rclBank.right - rclBank.left) * ppdev->cjPelSize;
  761. cyScan = (rclBank.bottom - rclBank.top);
  762. vAlignedCopy(ppdev, &pjDst, lDstDelta, &pjSrc, lSrcDelta, cjScan, cyScan,
  763. TRUE); // Screen is the destination
  764. if (rclDraw.right != rclBank.right)
  765. {
  766. // Handle the second part of the broken raster:
  767. iBank++;
  768. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, iBank);
  769. // Number of bytes we've yet to do on the broken scan:
  770. cjRemainder = (rclDraw.right - rclBank.right) * ppdev->cjPelSize;
  771. // Account for the fact that we're now one bank lower in the
  772. // destination:
  773. pjDst -= ppdev->cjBank;
  774. // Implicitly back up the source and destination pointers to the
  775. // unfinished portion of the scan:
  776. if (DIRECT_ACCESS(ppdev))
  777. {
  778. memcpy(pjDst + (cjScan - lDstDelta),
  779. pjSrc + (cjScan - lSrcDelta),
  780. cjRemainder);
  781. }
  782. else
  783. {
  784. BYTE* pjTmpDst = pjDst + (cjScan - lDstDelta);
  785. BYTE* pjTmpSrc = pjSrc + (cjScan - lSrcDelta);
  786. vAlignedCopy(ppdev, &pjTmpDst, 0, &pjTmpSrc, 0, cjRemainder, 1,
  787. TRUE); // Screen is the destination
  788. }
  789. }
  790. if (rclDraw.bottom > rclBank.bottom)
  791. {
  792. rclDraw.top = rclBank.bottom;
  793. ppdev->pfnBankCompute(ppdev, &rclDraw, &rclBank, &cjOffset,
  794. &iNewBank);
  795. // If we just handled the second part of a broken raster,
  796. // then we've already got the bank correctly mapped in:
  797. if (iNewBank != iBank)
  798. {
  799. pjDst -= ppdev->cjBank;
  800. iBank = iNewBank;
  801. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, iBank);
  802. }
  803. }
  804. else
  805. {
  806. // We're done! Turn off banking and leave:
  807. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_OFF);
  808. return;
  809. }
  810. }
  811. }
  812. /******************************Public*Routine******************************\
  813. * VOID vGetBits
  814. *
  815. * Copies the bits to the given surface from the screen, using the memory
  816. * aperture. Must be pre-clipped.
  817. *
  818. \**************************************************************************/
  819. VOID vGetBits(
  820. PDEV* ppdev,
  821. SURFOBJ* psoDst,
  822. RECTL* prclDst, // Absolute coordinates!
  823. POINTL* pptlSrc) // Absolute coordinates!
  824. {
  825. RECTL rclDraw;
  826. RECTL rclBank;
  827. LONG iBank;
  828. LONG cjOffset;
  829. LONG cyScan;
  830. LONG lDstDelta;
  831. LONG lSrcDelta;
  832. BYTE* pjDst;
  833. BYTE* pjSrc;
  834. LONG cjScan;
  835. LONG iNewBank;
  836. LONG cjRemainder;
  837. rclDraw.left = pptlSrc->x;
  838. rclDraw.top = pptlSrc->y;
  839. rclDraw.right = rclDraw.left + (prclDst->right - prclDst->left);
  840. rclDraw.bottom = rclDraw.top + (prclDst->bottom - prclDst->top);
  841. ASSERTDD((rclDraw.left >= 0) &&
  842. (rclDraw.top >= 0) &&
  843. (rclDraw.right <= ppdev->cxMemory) &&
  844. (rclDraw.bottom <= ppdev->cyMemory),
  845. "Rectangle wasn't fully clipped");
  846. // Compute the first bank, enable banking, then map in iBank.
  847. ppdev->pfnBankCompute(ppdev, &rclDraw, &rclBank, &cjOffset, &iBank);
  848. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_ON);
  849. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, iBank);
  850. // Calculate the pointer to the upper-left corner of both rectangles:
  851. lSrcDelta = ppdev->lDelta;
  852. pjSrc = ppdev->pjScreen + rclDraw.top * lSrcDelta
  853. + (rclDraw.left * ppdev->cjPelSize)
  854. - cjOffset;
  855. lDstDelta = psoDst->lDelta;
  856. pjDst = (BYTE*) psoDst->pvScan0 + prclDst->top * lDstDelta
  857. + (prclDst->left * ppdev->cjPelSize);
  858. while (TRUE)
  859. {
  860. cjScan = (rclBank.right - rclBank.left) * ppdev->cjPelSize;
  861. cyScan = (rclBank.bottom - rclBank.top);
  862. vAlignedCopy(ppdev, &pjDst, lDstDelta, &pjSrc, lSrcDelta, cjScan, cyScan,
  863. FALSE); // Screen is the source
  864. if (rclDraw.right != rclBank.right)
  865. {
  866. // Handle the second part of the broken raster:
  867. iBank++;
  868. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, iBank);
  869. // Number of bytes we've yet to do on the broken scan:
  870. cjRemainder = (rclDraw.right - rclBank.right) * ppdev->cjPelSize;
  871. // Account for the fact that we're now one bank lower in the
  872. // source:
  873. pjSrc -= ppdev->cjBank;
  874. // Implicitly back up the source and destination pointers to the
  875. // unfinished portion of the scan. Note that we don't have to
  876. // advance the pointers because they're already pointing to the
  877. // beginning of the next scan:
  878. if (DIRECT_ACCESS(ppdev))
  879. {
  880. memcpy(pjDst + (cjScan - lDstDelta),
  881. pjSrc + (cjScan - lSrcDelta),
  882. cjRemainder);
  883. }
  884. else
  885. {
  886. BYTE* pjTmpDst = pjDst + (cjScan - lDstDelta);
  887. BYTE* pjTmpSrc = pjSrc + (cjScan - lSrcDelta);
  888. vAlignedCopy(ppdev, &pjTmpDst, 0, &pjTmpSrc, 0, cjRemainder, 1,
  889. FALSE); // Screen is the source
  890. }
  891. }
  892. if (rclDraw.bottom > rclBank.bottom)
  893. {
  894. rclDraw.top = rclBank.bottom;
  895. ppdev->pfnBankCompute(ppdev, &rclDraw, &rclBank, &cjOffset,
  896. &iNewBank);
  897. // If we just handled the second part of a broken raster,
  898. // then we've already got the bank correctly mapped in:
  899. if (iNewBank != iBank)
  900. {
  901. pjSrc -= ppdev->cjBank;
  902. iBank = iNewBank;
  903. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, iBank);
  904. }
  905. }
  906. else
  907. {
  908. // We're done! Turn off banking and leave:
  909. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_OFF);
  910. return;
  911. }
  912. }
  913. }