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.

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