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.

801 lines
28 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: bltmm.c
  3. *
  4. * Contains the low-level memory-mapped blt functions. This module mirrors
  5. * 'bltio.c'.
  6. *
  7. * Hopefully, if you're basing your display driver on this code, to
  8. * support all of DrvBitBlt and DrvCopyBits, you'll only have to implement
  9. * the following routines. You shouldn't have to modify much in
  10. * 'bitblt.c'. I've tried to make these routines as few, modular, simple,
  11. * and efficient as I could, while still accelerating as many calls as
  12. * possible that would be cost-effective in terms of performance wins
  13. * versus size and effort.
  14. *
  15. * Note: In the following, 'relative' coordinates refers to coordinates
  16. * that haven't yet had the offscreen bitmap (DFB) offset applied.
  17. * 'Absolute' coordinates have had the offset applied. For example,
  18. * we may be told to blt to (1, 1) of the bitmap, but the bitmap may
  19. * be sitting in offscreen memory starting at coordinate (0, 768) --
  20. * (1, 1) would be the 'relative' start coordinate, and (1, 769)
  21. * would be the 'absolute' start coordinate'.
  22. *
  23. * Copyright (c) 1992-1995 Microsoft Corporation
  24. *
  25. \**************************************************************************/
  26. #include "precomp.h"
  27. /******************************Public*Routine******************************\
  28. * VOID vMmFillSolid
  29. *
  30. * Fills a list of rectangles with a solid colour.
  31. *
  32. \**************************************************************************/
  33. VOID vMmFillSolid( // Type FNFILL
  34. PDEV* ppdev,
  35. LONG c, // Can't be zero
  36. RECTL* prcl, // List of rectangles to be filled, in relative
  37. // coordinates
  38. ULONG rop4, // Mix
  39. RBRUSH_COLOR rbc, // Drawing colour is rbc.iSolidColor
  40. POINTL* pptlBrush) // Not used
  41. {
  42. BYTE* pjMmBase;
  43. ASSERTDD((rop4 >> 8) == (rop4 & 0xff), "Illegal mix");
  44. pjMmBase = ppdev->pjMmBase;
  45. MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
  46. MM_PREG_COLOR_8(ppdev, pjMmBase, rbc.iSolidColor);
  47. MM_BLT_CMD_1(ppdev, pjMmBase, XY_SRC_ADDR |
  48. XY_DEST_ADDR);
  49. if (rop4 == 0xf0f0)
  50. {
  51. // Note block write:
  52. MM_CTRL_REG_1(ppdev, pjMmBase, PACKED_PIXEL_VIEW |
  53. BLOCK_WRITE |
  54. BITS_PER_PIX_8 |
  55. ENAB_TRITON_MODE);
  56. MM_DATAPATH_CTRL(ppdev, pjMmBase, ROPSELECT_NO_ROPS |
  57. PIXELMASK_ONLY |
  58. PLANARMASK_NONE_0XFF |
  59. SRC_IS_PATTERN_REGS);
  60. }
  61. else
  62. {
  63. MM_CTRL_REG_1(ppdev, pjMmBase, PACKED_PIXEL_VIEW |
  64. BITS_PER_PIX_8 |
  65. ENAB_TRITON_MODE);
  66. MM_DATAPATH_CTRL(ppdev, pjMmBase, ROPSELECT_ALL |
  67. PIXELMASK_ONLY |
  68. PLANARMASK_NONE_0XFF |
  69. SRC_IS_PATTERN_REGS);
  70. MM_ROP_A(ppdev, pjMmBase, rop4 >> 2);
  71. }
  72. MM_BITMAP_HEIGHT(ppdev, pjMmBase, prcl->bottom - prcl->top);
  73. MM_BITMAP_WIDTH(ppdev, pjMmBase, prcl->right - prcl->left);
  74. MM_DEST_XY(ppdev, pjMmBase, prcl->left, prcl->top);
  75. MM_BLT_CMD_0(ppdev, pjMmBase, START_BLT);
  76. while (prcl++, --c)
  77. {
  78. MM_WAIT_BUFFER_NOT_BUSY(ppdev, pjMmBase);
  79. MM_BITMAP_HEIGHT(ppdev, pjMmBase, prcl->bottom - prcl->top);
  80. MM_BITMAP_WIDTH(ppdev, pjMmBase, prcl->right - prcl->left);
  81. MM_DEST_XY(ppdev, pjMmBase, prcl->left, prcl->top);
  82. MM_BLT_CMD_0(ppdev, pjMmBase, START_BLT);
  83. }
  84. }
  85. /******************************Public*Routine******************************\
  86. * VOID vMmFillPat2Color
  87. *
  88. * This routine uses the QVision pattern hardware to draw a patterned list of
  89. * rectangles.
  90. *
  91. \**************************************************************************/
  92. VOID vMmFillPat2Color( // Type FNFILL
  93. PDEV* ppdev,
  94. LONG c, // Can't be zero
  95. RECTL* prcl, // List of rectangles to be filled, in relative
  96. // coordinates
  97. ULONG rop4, // Mix
  98. RBRUSH_COLOR rbc, // rbc.prb points to brush realization structure
  99. POINTL* pptlBrush) // Pattern alignment
  100. {
  101. BYTE* pjMmBase;
  102. LONG xAlign;
  103. LONG yAlign;
  104. ASSERTDD(((rop4 >> 8) == (rop4 & 0xff)) || ((rop4 & 0xff00) == 0xaa00),
  105. "Illegal mix");
  106. pjMmBase = ppdev->pjMmBase;
  107. xAlign = pptlBrush->x;
  108. yAlign = pptlBrush->y;
  109. MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
  110. MM_FG_COLOR(ppdev, pjMmBase, rbc.prb->ulForeColor);
  111. MM_BG_COLOR(ppdev, pjMmBase, rbc.prb->ulBackColor);
  112. MM_PREG_PATTERN(ppdev, pjMmBase, rbc.prb->aulPattern);
  113. MM_CTRL_REG_1(ppdev, pjMmBase, EXPAND_TO_FG |
  114. BITS_PER_PIX_8 |
  115. ENAB_TRITON_MODE);
  116. MM_BLT_CMD_1(ppdev, pjMmBase, XY_SRC_ADDR |
  117. XY_DEST_ADDR);
  118. if (rop4 == 0xf0f0)
  119. {
  120. // Opaque brush with PATCOPY rop:
  121. MM_DATAPATH_CTRL(ppdev, pjMmBase, ROPSELECT_NO_ROPS |
  122. PIXELMASK_ONLY |
  123. PLANARMASK_NONE_0XFF |
  124. SRC_IS_PATTERN_REGS);
  125. }
  126. else if (((rop4 >> 8) & 0xff) == (rop4 & 0xff))
  127. {
  128. // Opaque brush with rop other than PATCOPY:
  129. MM_ROP_A(ppdev, pjMmBase, rop4 >> 2);
  130. MM_DATAPATH_CTRL(ppdev, pjMmBase, ROPSELECT_ALL |
  131. PIXELMASK_ONLY |
  132. PLANARMASK_NONE_0XFF |
  133. SRC_IS_PATTERN_REGS);
  134. }
  135. else if ((rop4 & 0xff) == 0xcc)
  136. {
  137. // Transparent brush with PATCOPY rop:
  138. MM_DATAPATH_CTRL(ppdev, pjMmBase, ROPSELECT_NO_ROPS |
  139. PIXELMASK_AND_SRC_DATA |
  140. PLANARMASK_NONE_0XFF |
  141. SRC_IS_PATTERN_REGS);
  142. }
  143. else
  144. {
  145. // Transparent brush with rop other than PATCOPY:
  146. MM_ROP_A(ppdev, pjMmBase, rop4 >> 2);
  147. MM_DATAPATH_CTRL(ppdev, pjMmBase, ROPSELECT_ALL |
  148. PIXELMASK_AND_SRC_DATA |
  149. PLANARMASK_NONE_0XFF |
  150. SRC_IS_PATTERN_REGS);
  151. }
  152. MM_BITMAP_HEIGHT(ppdev, pjMmBase, prcl->bottom - prcl->top);
  153. MM_BITMAP_WIDTH(ppdev, pjMmBase, prcl->right - prcl->left);
  154. MM_DEST_XY(ppdev, pjMmBase, prcl->left, prcl->top);
  155. MM_SRC_ALIGN(ppdev, pjMmBase, ((prcl->left - xAlign) & 7) |
  156. ((prcl->top - yAlign) << 3));
  157. MM_BLT_CMD_0(ppdev, pjMmBase, START_BLT);
  158. while (prcl++, --c)
  159. {
  160. MM_WAIT_BUFFER_NOT_BUSY(ppdev, pjMmBase);
  161. MM_BITMAP_HEIGHT(ppdev, pjMmBase, prcl->bottom - prcl->top);
  162. MM_BITMAP_WIDTH(ppdev, pjMmBase, prcl->right - prcl->left);
  163. MM_DEST_XY(ppdev, pjMmBase, prcl->left, prcl->top);
  164. MM_SRC_ALIGN(ppdev, pjMmBase, ((prcl->left - xAlign) & 7) |
  165. ((prcl->top - yAlign) << 3));
  166. MM_BLT_CMD_0(ppdev, pjMmBase, START_BLT);
  167. }
  168. }
  169. /******************************Public*Routine******************************\
  170. * VOID vMmFillPatArbitraryRop
  171. *
  172. * This routine uses the QVision pattern hardware to draw a patterned list of
  173. * rectangles.
  174. *
  175. \**************************************************************************/
  176. VOID vMmFillPatArbitraryRop( // Type FNFILL
  177. PDEV* ppdev,
  178. LONG c, // Can't be zero
  179. RECTL* prcl, // List of rectangles to be filled, in relative
  180. // coordinates
  181. ULONG rop4, // Mix
  182. RBRUSH_COLOR rbc, // rbc.prb points to brush realization structure
  183. POINTL* pptlBrush) // Pattern alignment
  184. {
  185. BYTE* pjMmBase;
  186. LONG xAlign;
  187. LONG yAlign;
  188. LONG lLinearDelta;
  189. BYTE* pjPatternStart;
  190. LONG xLeft;
  191. LONG yTop;
  192. LONG yBottom;
  193. LONG lLinearDest;
  194. LONG cy;
  195. LONG iPattern;
  196. LONG cyHeightOfEachBlt;
  197. LONG cBltsBeforeHeightChange;
  198. LONG cBlts;
  199. ASSERTDD((rop4 >> 8) == (rop4 & 0xff), "Illegal mix");
  200. pjMmBase = ppdev->pjMmBase;
  201. xAlign = pptlBrush->x;
  202. yAlign = pptlBrush->y;
  203. lLinearDelta = ppdev->lDelta << 3;
  204. pjPatternStart = (BYTE*) rbc.prb->aulPattern;
  205. MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
  206. MM_DEST_PITCH(ppdev, pjMmBase, (ppdev->lDelta << rbc.prb->cyLog2) >> 2);
  207. MM_CTRL_REG_1(ppdev, pjMmBase, PACKED_PIXEL_VIEW |
  208. BITS_PER_PIX_8 |
  209. ENAB_TRITON_MODE);
  210. MM_BLT_CMD_1(ppdev, pjMmBase, XY_SRC_ADDR |
  211. LIN_DEST_ADDR);
  212. if (rop4 == 0xf0f0)
  213. {
  214. MM_DATAPATH_CTRL(ppdev, pjMmBase, ROPSELECT_NO_ROPS |
  215. PIXELMASK_ONLY |
  216. PLANARMASK_NONE_0XFF |
  217. SRC_IS_PATTERN_REGS);
  218. }
  219. else
  220. {
  221. MM_DATAPATH_CTRL(ppdev, pjMmBase, ROPSELECT_ALL |
  222. PIXELMASK_ONLY |
  223. PLANARMASK_NONE_0XFF |
  224. SRC_IS_PATTERN_REGS);
  225. MM_ROP_A(ppdev, pjMmBase, rop4 >> 2);
  226. }
  227. while (TRUE)
  228. {
  229. xLeft = prcl->left;
  230. yTop = prcl->top;
  231. lLinearDest = ((yTop + ppdev->yOffset) * lLinearDelta)
  232. + ((xLeft + ppdev->xOffset) << 3);
  233. // Note that any registers we set now before the
  234. // WAIT_FOR_IDLE must be buffered, as this loop may be
  235. // executed multiple times when doing more than one
  236. // rectangle:
  237. MM_BITMAP_WIDTH(ppdev, pjMmBase, prcl->right - xLeft);
  238. MM_DEST_X(ppdev, pjMmBase, xLeft);
  239. MM_SRC_ALIGN(ppdev, pjMmBase, xLeft - xAlign);
  240. yBottom = prcl->bottom;
  241. cy = yBottom - yTop;
  242. iPattern = 8 * (yTop - yAlign);
  243. cyHeightOfEachBlt = (cy >> rbc.prb->cyLog2) + 1;
  244. cBlts = min(cy, rbc.prb->cy);
  245. cBltsBeforeHeightChange = (cy & (rbc.prb->cy - 1)) + 1;
  246. if (cBltsBeforeHeightChange != 1)
  247. MM_BITMAP_HEIGHT(ppdev, pjMmBase, cyHeightOfEachBlt);
  248. do {
  249. // Need to wait for idle because we're about to modify the
  250. // pattern registers, which aren't buffered:
  251. MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
  252. MM_PREG_PATTERN(ppdev, pjMmBase, pjPatternStart + (iPattern & 63));
  253. iPattern += 8;
  254. MM_DEST_LIN(ppdev, pjMmBase, lLinearDest);
  255. lLinearDest += lLinearDelta;
  256. cBltsBeforeHeightChange--;
  257. if (cBltsBeforeHeightChange == 0)
  258. MM_BITMAP_HEIGHT(ppdev, pjMmBase, cyHeightOfEachBlt - 1);
  259. MM_BLT_CMD_0(ppdev, pjMmBase, START_BLT);
  260. } while (--cBlts != 0);
  261. if (--c == 0)
  262. break;
  263. prcl++;
  264. }
  265. }
  266. /******************************Public*Routine******************************\
  267. * VOID vMmFillPat
  268. *
  269. * This routine uses the QVision pattern hardware to draw a patterned list of
  270. * rectangles.
  271. *
  272. \**************************************************************************/
  273. VOID vMmFillPat( // Type FNFILL
  274. PDEV* ppdev,
  275. LONG c, // Can't be zero
  276. RECTL* prcl, // List of rectangles to be filled, in relative
  277. // coordinates
  278. ULONG rop4, // Mix
  279. RBRUSH_COLOR rbc, // rbc.prb points to brush realization structure
  280. POINTL* pptlBrush) // Pattern alignment
  281. {
  282. BYTE* pjMmBase;
  283. LONG xAlign;
  284. LONG yAlign;
  285. LONG iMax;
  286. LONG lLinearDelta;
  287. BYTE* pjPatternStart;
  288. LONG xLeft;
  289. LONG yTop;
  290. LONG yBottom;
  291. LONG lLinearDest;
  292. LONG cy;
  293. LONG iPattern;
  294. LONG cyHeightOfEachBlt;
  295. LONG cBltsBeforeHeightChange;
  296. LONG cBlts;
  297. BYTE* pjSrc;
  298. BYTE* pjDst;
  299. LONG i;
  300. LONG j;
  301. ULONG* pulPattern;
  302. BOOL bWriteMaskSet;
  303. if (!(rbc.prb->fl & RBRUSH_2COLOR))
  304. {
  305. if (rop4 == 0xf0f0)
  306. {
  307. pjMmBase = ppdev->pjMmBase;
  308. xAlign = ((pptlBrush->x + ppdev->xOffset) & 7);
  309. iMax = (8 << rbc.prb->cyLog2) - 1;
  310. // The pattern must be pre-aligned to use the QVision's
  311. // block-write capability for patterns. We keep a cached
  312. // aligned copy in the brush itself:
  313. if (xAlign != rbc.prb->xBlockAlign)
  314. {
  315. rbc.prb->xBlockAlign = xAlign;
  316. pjSrc = (BYTE*) rbc.prb->aulPattern;
  317. pjDst = (BYTE*) rbc.prb->aulBlockPattern;
  318. i = rbc.prb->cy;
  319. do {
  320. for (j = 0; j != 8; j++)
  321. pjDst[(xAlign + j) & 7] = *pjSrc++;
  322. pjDst += 8;
  323. } while (--i != 0);
  324. }
  325. bWriteMaskSet = FALSE;
  326. pjPatternStart = (BYTE*) rbc.prb->aulBlockPattern;
  327. yAlign = pptlBrush->y;
  328. lLinearDelta = ppdev->lDelta << 3;
  329. MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
  330. MM_DEST_PITCH(ppdev, pjMmBase, (ppdev->lDelta << rbc.prb->cyLog2) >> 2);
  331. MM_CTRL_REG_1(ppdev, pjMmBase, PACKED_PIXEL_VIEW |
  332. BLOCK_WRITE |
  333. BITS_PER_PIX_8 |
  334. ENAB_TRITON_MODE);
  335. MM_BLT_CMD_1(ppdev, pjMmBase, XY_SRC_ADDR |
  336. LIN_DEST_ADDR);
  337. MM_DATAPATH_CTRL(ppdev, pjMmBase, ROPSELECT_NO_ROPS |
  338. PIXELMASK_ONLY |
  339. PLANARMASK_NONE_0XFF |
  340. SRC_IS_PATTERN_REGS);
  341. while (TRUE)
  342. {
  343. xLeft = prcl->left;
  344. yTop = prcl->top;
  345. lLinearDest = ((yTop + ppdev->yOffset) * lLinearDelta)
  346. + ((xLeft + ppdev->xOffset) << 3);
  347. // Note that any registers we set now before the
  348. // WAIT_FOR_IDLE must be buffered, as this loop may be
  349. // executed multiple times when doing more than one
  350. // rectangle:
  351. MM_BITMAP_WIDTH(ppdev, pjMmBase, prcl->right - xLeft);
  352. MM_DEST_X(ppdev, pjMmBase, xLeft);
  353. yBottom = prcl->bottom;
  354. cy = yBottom - yTop;
  355. iPattern = 8 * (yTop - yAlign);
  356. cyHeightOfEachBlt = (cy >> rbc.prb->cyLog2) + 1;
  357. cBlts = min(cy, rbc.prb->cy);
  358. cBltsBeforeHeightChange = (cy & (rbc.prb->cy - 1)) + 1;
  359. if (cBltsBeforeHeightChange != 1)
  360. MM_BITMAP_HEIGHT(ppdev, pjMmBase, cyHeightOfEachBlt);
  361. do {
  362. // Need to wait for idle because we're about to modify the
  363. // pattern registers, which aren't buffered:
  364. MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
  365. MM_DEST_LIN(ppdev, pjMmBase, lLinearDest);
  366. lLinearDest += lLinearDelta;
  367. cBltsBeforeHeightChange--;
  368. if (cBltsBeforeHeightChange == 0)
  369. MM_BITMAP_HEIGHT(ppdev, pjMmBase, cyHeightOfEachBlt - 1);
  370. pulPattern = (ULONG*) (pjPatternStart + (iPattern & iMax));
  371. iPattern += 8;
  372. if (*(pulPattern) == *(pulPattern + 1))
  373. {
  374. // The pattern on this scan is 4 pixels wide, so we can
  375. // do it in one pass:
  376. MM_PREG_BLOCK(ppdev, pjMmBase, (pulPattern));
  377. if (bWriteMaskSet)
  378. {
  379. bWriteMaskSet = FALSE;
  380. MM_PIXEL_WRITE_MASK(ppdev, pjMmBase, 0xff);
  381. }
  382. MM_BLT_CMD_0(ppdev, pjMmBase, START_BLT);
  383. }
  384. else
  385. {
  386. // The pattern on this scan is 8 pixels wide, so we
  387. // have to do it in two passes, using the pixel mask
  388. // register:
  389. bWriteMaskSet = TRUE;
  390. MM_PREG_BLOCK(ppdev, pjMmBase, (pulPattern));
  391. MM_PIXEL_WRITE_MASK(ppdev, pjMmBase, 0xf0);
  392. MM_BLT_CMD_0(ppdev, pjMmBase, START_BLT);
  393. MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
  394. MM_PREG_BLOCK(ppdev, pjMmBase, (pulPattern + 1));
  395. MM_PIXEL_WRITE_MASK(ppdev, pjMmBase, 0x0f);
  396. MM_BLT_CMD_0(ppdev, pjMmBase, START_BLT);
  397. }
  398. } while (--cBlts != 0);
  399. if (--c == 0)
  400. break;
  401. prcl++;
  402. }
  403. // Don't forget to reset the write mask when we're done:
  404. if (bWriteMaskSet)
  405. {
  406. MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
  407. MM_PIXEL_WRITE_MASK(ppdev, pjMmBase, 0xff);
  408. }
  409. }
  410. else
  411. {
  412. vMmFillPatArbitraryRop(ppdev, c, prcl, rop4, rbc, pptlBrush);
  413. }
  414. }
  415. else
  416. {
  417. vMmFillPat2Color(ppdev, c, prcl, rop4, rbc, pptlBrush);
  418. }
  419. }
  420. /******************************Public*Routine******************************\
  421. * VOID vMmXfer1bpp
  422. *
  423. * This routine colours expands a monochrome bitmap, possibly with different
  424. * Rop2's for the foreground and background. It will be called in the
  425. * following cases:
  426. *
  427. * 1) To colour-expand the monochrome text buffer for the vFastText routine.
  428. * 2) To blt a 1bpp source with a simple Rop2 between the source and
  429. * destination.
  430. * 3) To blt a true Rop3 when the source is a 1bpp bitmap that expands to
  431. * white and black, and the pattern is a solid colour.
  432. * 4) To handle a true Rop4 that works out to be Rop2's between the pattern
  433. * and destination.
  434. *
  435. * Needless to say, making this routine fast can leverage a lot of
  436. * performance.
  437. *
  438. \**************************************************************************/
  439. VOID vMmXfer1bpp( // Type FNXFER
  440. PDEV* ppdev,
  441. LONG c, // Count of rectangles, can't be zero
  442. RECTL* prcl, // List of destination rectangles, in relative
  443. // coordinates
  444. ULONG rop4, // Mix
  445. SURFOBJ* psoSrc, // Source surface
  446. POINTL* pptlSrc, // Original unclipped source point
  447. RECTL* prclDst, // Original unclipped destination rectangle
  448. XLATEOBJ* pxlo) // Translate that provides colour-expansion information
  449. {
  450. BYTE* pjMmBase;
  451. LONG dxSrc;
  452. LONG dySrc; // Add delta to destination to get source
  453. LONG lSrcDelta;
  454. BYTE* pjSrcScan0;
  455. BYTE* pjDstStart;
  456. LONG yTop;
  457. LONG xLeft;
  458. LONG xRight;
  459. LONG cx;
  460. LONG cy; // Dimensions of blt rectangle
  461. LONG xBias;
  462. LONG cjSrc;
  463. LONG cdSrc;
  464. LONG lSrcSkip;
  465. BYTE* pjSrc;
  466. BYTE* pjDst;
  467. LONG i;
  468. LONG j;
  469. ASSERTDD((rop4 >> 8) == (rop4 & 0xff), "Illegal mix");
  470. pjMmBase = ppdev->pjMmBase;
  471. dxSrc = pptlSrc->x - prclDst->left;
  472. dySrc = pptlSrc->y - prclDst->top;
  473. lSrcDelta = psoSrc->lDelta;
  474. pjSrcScan0 = psoSrc->pvScan0;
  475. pjDstStart = ppdev->pjScreen;
  476. MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
  477. MM_CTRL_REG_1(ppdev, pjMmBase, EXPAND_TO_FG |
  478. BITS_PER_PIX_8 |
  479. ENAB_TRITON_MODE);
  480. MM_BLT_CMD_1(ppdev, pjMmBase, XY_SRC_ADDR |
  481. XY_DEST_ADDR);
  482. MM_FG_COLOR(ppdev, pjMmBase, pxlo->pulXlate[1]);
  483. MM_BG_COLOR(ppdev, pjMmBase, pxlo->pulXlate[0]);
  484. if (rop4 == 0xcccc)
  485. {
  486. MM_DATAPATH_CTRL(ppdev, pjMmBase, ROPSELECT_NO_ROPS |
  487. PIXELMASK_ONLY |
  488. PLANARMASK_NONE_0XFF |
  489. SRC_IS_CPU_DATA);
  490. }
  491. else
  492. {
  493. MM_DATAPATH_CTRL(ppdev, pjMmBase, ROPSELECT_ALL |
  494. PIXELMASK_ONLY |
  495. PLANARMASK_NONE_0XFF |
  496. SRC_IS_CPU_DATA);
  497. MM_ROP_A(ppdev, pjMmBase, rop4);
  498. }
  499. while (TRUE)
  500. {
  501. yTop = prcl->top;
  502. xLeft = prcl->left;
  503. xRight = prcl->right;
  504. cy = prcl->bottom - yTop;
  505. cx = xRight - xLeft;
  506. MM_BITMAP_WIDTH(ppdev, pjMmBase, cx);
  507. MM_BITMAP_HEIGHT(ppdev, pjMmBase, cy);
  508. MM_DEST_XY(ppdev, pjMmBase, xLeft, yTop);
  509. xBias = (xLeft + dxSrc) & 7;
  510. MM_SRC_ALIGN(ppdev, pjMmBase, xBias);
  511. xLeft -= xBias;
  512. cjSrc = (xRight - xLeft + 7) >> 3;
  513. cdSrc = cjSrc >> 2;
  514. lSrcSkip = lSrcDelta - (cdSrc << 2);
  515. pjSrc = pjSrcScan0 + (yTop + dySrc) * lSrcDelta
  516. + ((xLeft + dxSrc) >> 3);
  517. MM_BLT_CMD_0(ppdev, pjMmBase, START_BLT);
  518. switch(cjSrc & 3)
  519. {
  520. case 0:
  521. for (i = cy; i != 0; i--)
  522. {
  523. MEMORY_BARRIER();
  524. pjDst = pjDstStart;
  525. for (j = cdSrc; j != 0; j--)
  526. {
  527. WRITE_REGISTER_ULONG(pjDst, *((ULONG UNALIGNED *) pjSrc));
  528. pjDst += sizeof(ULONG);
  529. pjSrc += sizeof(ULONG);
  530. }
  531. pjSrc += lSrcSkip;
  532. }
  533. break;
  534. case 1:
  535. for (i = cy; i != 0; i--)
  536. {
  537. MEMORY_BARRIER();
  538. pjDst = pjDstStart;
  539. for (j = cdSrc; j != 0; j--)
  540. {
  541. WRITE_REGISTER_ULONG(pjDst, *((ULONG UNALIGNED *) pjSrc));
  542. pjDst += sizeof(ULONG);
  543. pjSrc += sizeof(ULONG);
  544. }
  545. WRITE_REGISTER_UCHAR(pjDst, *pjSrc);
  546. pjSrc += lSrcSkip;
  547. }
  548. break;
  549. case 2:
  550. for (i = cy; i != 0; i--)
  551. {
  552. MEMORY_BARRIER();
  553. pjDst = pjDstStart;
  554. for (j = cdSrc; j != 0; j--)
  555. {
  556. WRITE_REGISTER_ULONG(pjDst, *((ULONG UNALIGNED *) pjSrc));
  557. pjDst += sizeof(ULONG);
  558. pjSrc += sizeof(ULONG);
  559. }
  560. WRITE_REGISTER_USHORT(pjDst, *((USHORT UNALIGNED *) pjSrc));
  561. pjSrc += lSrcSkip;
  562. }
  563. break;
  564. case 3:
  565. for (i = cy; i != 0; i--)
  566. {
  567. MEMORY_BARRIER();
  568. pjDst = pjDstStart;
  569. for (j = cdSrc; j != 0; j--)
  570. {
  571. WRITE_REGISTER_ULONG(pjDst, *((ULONG UNALIGNED *) pjSrc));
  572. pjDst += sizeof(ULONG);
  573. pjSrc += sizeof(ULONG);
  574. }
  575. WRITE_REGISTER_USHORT(pjDst, *((USHORT UNALIGNED *) pjSrc));
  576. WRITE_REGISTER_UCHAR((pjDst + 2), *(pjSrc + 2));
  577. pjSrc += lSrcSkip;
  578. }
  579. break;
  580. }
  581. MM_WAIT_TRANSFER_DONE(ppdev, pjMmBase);
  582. if (--c == 0)
  583. break;
  584. prcl++;
  585. MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
  586. }
  587. }
  588. /******************************Public*Routine******************************\
  589. * VOID vMmCopyBlt
  590. *
  591. * Does a screen-to-screen blt of a list of rectangles.
  592. *
  593. \**************************************************************************/
  594. VOID vMmCopyBlt( // Type FNCOPY
  595. PDEV* ppdev,
  596. LONG c, // Can't be zero
  597. RECTL* prcl, // Array of relative coordinates destination rectangles
  598. ULONG rop4, // Hardware mix
  599. POINTL* pptlSrc, // Original unclipped source point
  600. RECTL* prclDst) // Original unclipped destination rectangle
  601. {
  602. BYTE* pjMmBase;
  603. LONG dxSrc;
  604. LONG dySrc; // Add delta to destination to get source
  605. LONG cx;
  606. LONG cy; // Dimensions of blt rectangle
  607. LONG xDst;
  608. LONG yDst; // Start point of destination
  609. ASSERTDD((rop4 >> 8) == (rop4 & 0xff), "Illegal mix");
  610. pjMmBase = ppdev->pjMmBase;
  611. dxSrc = pptlSrc->x - prclDst->left;
  612. dySrc = pptlSrc->y - prclDst->top;
  613. MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
  614. MM_CTRL_REG_1(ppdev, pjMmBase, PACKED_PIXEL_VIEW | // !!! Need this each time?
  615. BITS_PER_PIX_8 |
  616. ENAB_TRITON_MODE);
  617. MM_BLT_CMD_1(ppdev, pjMmBase, XY_SRC_ADDR |
  618. XY_DEST_ADDR);
  619. if (rop4 == 0xcccc)
  620. {
  621. MM_DATAPATH_CTRL(ppdev, pjMmBase, ROPSELECT_NO_ROPS |
  622. PIXELMASK_ONLY |
  623. PLANARMASK_NONE_0XFF |
  624. SRC_IS_SCRN_LATCHES);
  625. }
  626. else
  627. {
  628. MM_DATAPATH_CTRL(ppdev, pjMmBase, ROPSELECT_ALL |
  629. PIXELMASK_ONLY |
  630. PLANARMASK_NONE_0XFF |
  631. SRC_IS_SCRN_LATCHES);
  632. MM_ROP_A(ppdev, pjMmBase, rop4);
  633. }
  634. if ((prclDst->top < pptlSrc->y) ||
  635. (prclDst->top == pptlSrc->y) && (prclDst->left <= pptlSrc->x))
  636. {
  637. // Forward blt:
  638. cx = prcl->right - prcl->left;
  639. cy = prcl->bottom - prcl->top;
  640. xDst = prcl->left;
  641. yDst = prcl->top;
  642. MM_BITMAP_WIDTH(ppdev, pjMmBase, cx);
  643. MM_BITMAP_HEIGHT(ppdev, pjMmBase, cy);
  644. MM_DEST_XY(ppdev, pjMmBase, xDst, yDst);
  645. MM_SRC_XY(ppdev, pjMmBase, xDst + dxSrc, yDst + dySrc);
  646. MM_BLT_CMD_0(ppdev, pjMmBase, START_BLT);
  647. while (prcl++, --c)
  648. {
  649. cx = prcl->right - prcl->left;
  650. cy = prcl->bottom - prcl->top;
  651. xDst = prcl->left;
  652. yDst = prcl->top;
  653. MM_WAIT_BUFFER_NOT_BUSY(ppdev, pjMmBase);
  654. MM_BITMAP_WIDTH(ppdev, pjMmBase, cx);
  655. MM_BITMAP_HEIGHT(ppdev, pjMmBase, cy);
  656. MM_DEST_XY(ppdev, pjMmBase, xDst, yDst);
  657. MM_SRC_XY(ppdev, pjMmBase, xDst + dxSrc, yDst + dySrc);
  658. MM_BLT_CMD_0(ppdev, pjMmBase, START_BLT);
  659. }
  660. }
  661. else
  662. {
  663. // Backward blt:
  664. cx = prcl->right - prcl->left;
  665. cy = prcl->bottom - prcl->top;
  666. xDst = prcl->left + cx - 1;
  667. yDst = prcl->top + cy - 1;
  668. MM_BITMAP_WIDTH(ppdev, pjMmBase, cx);
  669. MM_BITMAP_HEIGHT(ppdev, pjMmBase, cy);
  670. MM_DEST_XY(ppdev, pjMmBase, xDst, yDst);
  671. MM_SRC_XY(ppdev, pjMmBase, xDst + dxSrc, yDst + dySrc);
  672. MM_BLT_CMD_0(ppdev, pjMmBase, START_BLT | BACKWARD);
  673. while (prcl++, --c)
  674. {
  675. cx = prcl->right - prcl->left;
  676. cy = prcl->bottom - prcl->top;
  677. xDst = prcl->left + cx - 1;
  678. yDst = prcl->top + cy - 1;
  679. MM_WAIT_BUFFER_NOT_BUSY(ppdev, pjMmBase);
  680. MM_BITMAP_WIDTH(ppdev, pjMmBase, cx);
  681. MM_BITMAP_HEIGHT(ppdev, pjMmBase, cy);
  682. MM_DEST_XY(ppdev, pjMmBase, xDst, yDst);
  683. MM_SRC_XY(ppdev, pjMmBase, xDst + dxSrc, yDst + dySrc);
  684. MM_BLT_CMD_0(ppdev, pjMmBase, START_BLT | BACKWARD);
  685. }
  686. }
  687. }