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

2290 lines
75 KiB

  1. /******************************************************************************\
  2. *
  3. * $Workfile: bltmm.c $
  4. *
  5. * Contains the low-level MM blt functions.
  6. *
  7. * Hopefully, if you're basing your display driver on this code, to support all
  8. * of DrvBitBlt and DrvCopyBits, you'll only have to implement the following
  9. * routines. You shouldn't have to modify much in 'bitblt.c'. I've tried to make
  10. * these routines as few, modular, simple, and efficient as I could, while still
  11. * accelerating as many calls as possible that would be cost-effective in terms
  12. * of performance wins versus size and effort.
  13. *
  14. * Note: In the following, 'relative' coordinates refers to coordinates that
  15. * haven't yet had the offscreen bitmap (DFB) offset applied. 'Absolute'
  16. * coordinates have had the offset applied. For example, we may be told to
  17. * blt to (1, 1) of the bitmap, but the bitmap may be sitting in offscreen
  18. * memory starting at coordinate (0, 768) -- (1, 1) would be the
  19. * 'relative' start coordinate, and (1, 769) would be the 'absolute' start
  20. * coordinate'.
  21. *
  22. * Copyright (c) 1992-1995 Microsoft Corporation
  23. * Copyright (c) 1996 Cirrus Logic, Inc.
  24. *
  25. * $Log: S:/projects/drivers/ntsrc/display/bltmm.c_v $
  26. *
  27. * Rev 1.4 Jan 14 1997 15:16:14 unknown
  28. * take out GR33 clearing after 80 blt.
  29. *
  30. * Rev 1.2 Nov 07 1996 16:47:52 unknown
  31. *
  32. *
  33. * Rev 1.1 Oct 10 1996 15:36:14 unknown
  34. *
  35. *
  36. * Rev 1.4 12 Aug 1996 16:58:56 frido
  37. * Removed unaccessed local variables.
  38. * Renamed vMmPatternBlt into vMmFillPat36.
  39. *
  40. * Rev 1.3 08 Aug 1996 16:55:10 frido
  41. * Added new vMmCopyBlt36 routine.
  42. *
  43. * Rev 1.2 08 Aug 1996 12:59:28 frido
  44. * bank#1 - Removed banking code since MMIO is always linear.
  45. *
  46. * Rev 1.1 31 Jul 1996 15:43:14 frido
  47. * Added new pattern blit.
  48. *
  49. * jl01 10-08-96 Do Transparent BLT w/o Solid Fill. Refer to PDRs#5511/6817.
  50. * chu01 01-09-97 Make sure to reset GR33.
  51. *
  52. \******************************************************************************/
  53. #include "precomp.h"
  54. /**************************************************************************
  55. * VOID vMmFastPatRealize
  56. *
  57. * Realizes a pattern into offscreen memory.
  58. *
  59. **************************************************************************/
  60. VOID vMmFastPatRealize(
  61. PDEV* ppdev,
  62. RBRUSH* prb) // Points to brush realization structure
  63. {
  64. BRUSHENTRY* pbe;
  65. LONG iBrushCache;
  66. BYTE* pjPattern;
  67. LONG cjPattern;
  68. BYTE* pjBase = ppdev->pjBase;
  69. LONG lDelta = ppdev->lDelta;
  70. LONG lDeltaPat;
  71. LONG lDeltaSrc;
  72. LONG xCnt;
  73. LONG yCnt;
  74. ULONG ulDst;
  75. DISPDBG((10,"vFastPatRealize called"));
  76. pbe = prb->pbe;
  77. if ((pbe == NULL) || (pbe->prbVerify != prb))
  78. {
  79. // We have to allocate a new offscreen cache brush entry for
  80. // the brush:
  81. iBrushCache = ppdev->iBrushCache;
  82. pbe = &ppdev->abe[iBrushCache];
  83. iBrushCache++;
  84. if (iBrushCache >= ppdev->cBrushCache)
  85. iBrushCache = 0;
  86. ppdev->iBrushCache = iBrushCache;
  87. // Update our links:
  88. pbe->prbVerify = prb;
  89. prb->pbe = pbe;
  90. }
  91. //
  92. // Download brush into cache
  93. //
  94. pjPattern = (PBYTE) &prb->aulPattern[0]; // Copy from brush buffer
  95. cjPattern = PELS_TO_BYTES(TOTAL_BRUSH_SIZE);
  96. lDeltaPat = PELS_TO_BYTES(8);
  97. xCnt = PELS_TO_BYTES(8);
  98. yCnt = 8;
  99. if (ppdev->cBitsPerPixel == 24)
  100. {
  101. lDeltaSrc = 32; // same as PELS_TO_BYTES(8) for 32bpp
  102. }
  103. else
  104. {
  105. lDeltaSrc = lDeltaPat; // PELS_TO_BYTES(8)
  106. }
  107. ulDst = (pbe->y * ppdev->lDelta) + PELS_TO_BYTES(pbe->x);
  108. #if BANKING //bank#1
  109. ppdev->pfnBankMap(ppdev, ppdev->lXferBank);
  110. #endif
  111. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  112. CP_MM_DST_Y_OFFSET(ppdev, pjBase, (lDeltaSrc * 2));
  113. CP_MM_XCNT(ppdev, pjBase, (xCnt - 1));
  114. CP_MM_YCNT(ppdev, pjBase, (yCnt - 1));
  115. #if 1 // D5480
  116. CP_MM_BLT_MODE_PACKED(ppdev, pjBase, CL_PACKED_SRC_COPY | SRC_CPU_DATA);
  117. #else
  118. CP_MM_BLT_MODE(ppdev, pjBase, SRC_CPU_DATA);
  119. CP_MM_BLT_EXT_MODE(ppdev, pjBase, 0);
  120. CP_MM_ROP(ppdev, pjBase, CL_SRC_COPY);
  121. #endif // D5480
  122. CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDst);
  123. CP_MM_START_BLT(ppdev, pjBase);
  124. vImageTransfer(ppdev, pjPattern, lDeltaPat, xCnt, yCnt);
  125. //
  126. // Duplicate brush horizontally
  127. //
  128. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  129. CP_MM_XCNT(ppdev, pjBase, (xCnt - 1));
  130. CP_MM_YCNT(ppdev, pjBase, (yCnt - 1));
  131. CP_MM_BLT_MODE(ppdev, pjBase, 0);
  132. CP_MM_SRC_Y_OFFSET(ppdev, pjBase, (lDeltaSrc * 2));
  133. CP_MM_SRC_ADDR(ppdev, pjBase, ulDst);
  134. CP_MM_DST_ADDR_ABS(ppdev, pjBase, (ulDst + lDeltaPat));
  135. CP_MM_START_BLT(ppdev, pjBase);
  136. //
  137. // Duplicate brush vertically
  138. //
  139. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  140. CP_MM_SRC_Y_OFFSET(ppdev, pjBase, (lDeltaSrc * 2));
  141. CP_MM_DST_Y_OFFSET(ppdev, pjBase, (lDeltaSrc * 2));
  142. CP_MM_BLT_MODE(ppdev, pjBase, 0);
  143. CP_MM_XCNT(ppdev, pjBase, ((lDeltaSrc * 2) - 1));
  144. CP_MM_YCNT(ppdev, pjBase, (yCnt - 1));
  145. CP_MM_SRC_ADDR(ppdev, pjBase, ulDst);
  146. if (ppdev->cBitsPerPixel == 24)
  147. {
  148. CP_MM_DST_ADDR_ABS(ppdev, pjBase, (ulDst + 512)); // 128 * 4
  149. }
  150. else
  151. {
  152. CP_MM_DST_ADDR_ABS(ppdev, pjBase, (ulDst + PELS_TO_BYTES(128)));
  153. }
  154. CP_MM_START_BLT(ppdev, pjBase);
  155. #if 0
  156. {
  157. ////////////////////////////////////////////////////////////////
  158. // DEBUG TILED PATTERNS
  159. //
  160. // The following code helps to debug patterns if you break the
  161. // realization code. It copies the 2x2 tiled copy of the brush
  162. // to the visible screen.
  163. //
  164. POINTL ptl;
  165. RECTL rcl;
  166. ptl.x = pbe->x;
  167. ptl.y = pbe->y;
  168. rcl.left = 10;
  169. rcl.right = 10 + 16;
  170. rcl.top = ppdev->cyScreen - 10 - 16;
  171. rcl.bottom = ppdev->cyScreen - 10;
  172. {
  173. LONG lDelta = ppdev->lDelta;
  174. BYTE jHwRop;
  175. BYTE jMode;
  176. //
  177. // Make sure we can write to the video registers.
  178. //
  179. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  180. CP_MM_ROP(ppdev, pjBase, CL_SRC_COPY);
  181. CP_MM_SRC_Y_OFFSET(ppdev, pjBase, PELS_TO_BYTES(16));
  182. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  183. {
  184. //
  185. // Top to Bottom - Left to Right
  186. //
  187. jMode |= DIR_TBLR;
  188. CP_MM_BLT_MODE(ppdev, pjBase, ppdev->jModeColor);
  189. {
  190. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  191. CP_MM_XCNT(ppdev, pjBase, (PELS_TO_BYTES(rcl.right - rcl.left) - 1));
  192. CP_MM_YCNT(ppdev, pjBase, (rcl.bottom - rcl.top - 1));
  193. CP_MM_SRC_ADDR(ppdev, pjBase, (0 + ((ptl.y) * lDelta) + PELS_TO_BYTES(ptl.x)));
  194. CP_MM_DST_ADDR_ABS(ppdev, pjBase, ((rcl.top * lDelta) + PELS_TO_BYTES(rcl.left)));
  195. CP_MM_START_BLT(ppdev, pjBase);
  196. }
  197. }
  198. }
  199. }
  200. #endif
  201. }
  202. /**************************************************************************
  203. * VOID vMmFillPat
  204. *
  205. * This routine uses the pattern hardware to draw a patterned list of
  206. * rectangles.
  207. *
  208. **************************************************************************/
  209. VOID vMmFillPat(
  210. PDEV* ppdev,
  211. LONG c, // Can't be zero
  212. RECTL* prcl, // Array of relative coordinate destination rects
  213. ROP4 rop4, // Obvious?
  214. RBRUSH_COLOR rbc, // Drawing color is rbc.iSolidColor
  215. POINTL* pptlBrush) //
  216. {
  217. BYTE* pjBase = ppdev->pjBase;
  218. LONG lDelta = ppdev->lDelta;
  219. ULONG ulAlignedPatternOffset = ppdev->ulAlignedPatternOffset;
  220. ULONG ulPatternAddrBase;
  221. BYTE jHwRop;
  222. BYTE jMode;
  223. BRUSHENTRY* pbe; // Pointer to brush entry data, which is used
  224. // for keeping track of the location and status
  225. // of the pattern bits cached in off-screen
  226. // memory
  227. DISPDBG((10,"vFillPat called"));
  228. ASSERTDD(c > 0, "Can't handle zero rectangles");
  229. ASSERTDD(ppdev->cBpp < 4, "vFillPat only works at 8bpp, 16bpp, and 24bpp");
  230. if ((rbc.prb->pbe == NULL) ||
  231. (rbc.prb->pbe->prbVerify != rbc.prb))
  232. {
  233. vMmFastPatRealize(ppdev, rbc.prb);
  234. DISPDBG((5, " -- Brush cache miss, put it at (%d,%d)", rbc.prb->pbe->x, rbc.prb->pbe->y));
  235. }
  236. else
  237. {
  238. DISPDBG((5, " -- Brush cache hit on brush at (%d,%d)", rbc.prb->pbe->x, rbc.prb->pbe->y));
  239. }
  240. pbe = rbc.prb->pbe;
  241. //
  242. // Fill the list of rectangles
  243. //
  244. ulPatternAddrBase = pbe->xy;
  245. jHwRop = gajHwMixFromRop2[(rop4 >> 2) & 0xf];
  246. jMode = ppdev->jModeColor | ENABLE_8x8_PATTERN_COPY;
  247. do {
  248. ULONG offset = 0;
  249. ULONG XOffset, YOffset;
  250. YOffset = ((prcl->top - pptlBrush->y) & 7) << 4;
  251. XOffset = (prcl->left - pptlBrush->x) & 7;
  252. // align the pattern to a new location
  253. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  254. #if 1 // D5480
  255. CP_MM_BLT_MODE_PACKED(ppdev, pjBase, CL_PACKED_SRC_COPY);
  256. #else
  257. CP_MM_BLT_MODE(ppdev, pjBase, 0);
  258. CP_MM_ROP(ppdev, pjBase, CL_SRC_COPY);
  259. #endif // D5480
  260. if (ppdev->cBitsPerPixel == 24)
  261. {
  262. offset = (YOffset * 4) + (XOffset * 3);
  263. CP_MM_SRC_Y_OFFSET(ppdev, pjBase, 64);
  264. CP_MM_DST_Y_OFFSET(ppdev, pjBase, 32);
  265. }
  266. else
  267. {
  268. offset = PELS_TO_BYTES(YOffset + XOffset);
  269. CP_MM_SRC_Y_OFFSET(ppdev, pjBase, PELS_TO_BYTES(16));
  270. CP_MM_DST_Y_OFFSET(ppdev, pjBase, PELS_TO_BYTES(8));
  271. }
  272. CP_MM_SRC_ADDR(ppdev, pjBase, (ulPatternAddrBase + offset));
  273. CP_MM_XCNT(ppdev, pjBase, (PELS_TO_BYTES(8) - 1));
  274. CP_MM_YCNT(ppdev, pjBase, (8 - 1));
  275. CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulAlignedPatternOffset);
  276. CP_MM_START_BLT(ppdev, pjBase);
  277. // fill using aligned pattern
  278. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  279. CP_MM_BLT_MODE(ppdev, pjBase, jMode);
  280. CP_MM_ROP(ppdev, pjBase, jHwRop);
  281. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  282. CP_MM_SRC_ADDR(ppdev, pjBase, ulAlignedPatternOffset);
  283. CP_MM_XCNT(ppdev, pjBase, (PELS_TO_BYTES(prcl->right - prcl->left) - 1));
  284. CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top - 1));
  285. CP_MM_DST_ADDR(ppdev, pjBase, ((prcl->top * lDelta) + PELS_TO_BYTES(prcl->left)));
  286. CP_MM_START_BLT(ppdev, pjBase);
  287. prcl++;
  288. } while (--c != 0);
  289. }
  290. /**************************************************************************
  291. * VOID vMmFillSolid
  292. *
  293. * Does a solid fill to a list of rectangles.
  294. *
  295. **************************************************************************/
  296. VOID vMmFillSolid(
  297. PDEV* ppdev,
  298. LONG c, // Can't be zero
  299. RECTL* prcl, // Array of relative coordinate destination rects
  300. ROP4 rop4, // Obvious?
  301. RBRUSH_COLOR rbc, // Drawing color is rbc.iSolidColor
  302. POINTL* pptlBrush) // Not used
  303. {
  304. BYTE* pjBase = ppdev->pjBase;
  305. LONG lDelta = ppdev->lDelta;
  306. LONG cBpp = ppdev->cBpp;
  307. ULONG ulSolidColor;
  308. BYTE jHwRop;
  309. DISPDBG((10,"vFillSolid called"));
  310. ASSERTDD(c > 0, "Can't handle zero rectangles");
  311. ulSolidColor = rbc.iSolidColor;
  312. if (cBpp == 1)
  313. {
  314. ulSolidColor |= ulSolidColor << 8;
  315. ulSolidColor |= ulSolidColor << 16;
  316. }
  317. else if (cBpp == 2)
  318. {
  319. ulSolidColor |= ulSolidColor << 16;
  320. }
  321. jHwRop = gajHwMixFromRop2[(rop4 >> 2) & 0xf];
  322. //
  323. // Make sure we can write to the video registers.
  324. //
  325. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  326. CP_MM_ROP(ppdev, pjBase, jHwRop);
  327. CP_MM_SRC_ADDR(ppdev, pjBase, ppdev->ulSolidColorOffset);
  328. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  329. CP_MM_BLT_MODE(ppdev, pjBase, ENABLE_COLOR_EXPAND |
  330. ENABLE_8x8_PATTERN_COPY |
  331. ppdev->jModeColor);
  332. CP_MM_FG_COLOR(ppdev, pjBase, ulSolidColor);
  333. if (ppdev->flCaps & CAPS_AUTOSTART)
  334. {
  335. CP_MM_BLT_EXT_MODE(ppdev, pjBase, ENABLE_SOLID_FILL);
  336. }
  337. //
  338. // Fill the list of rectangles
  339. //
  340. while (TRUE)
  341. {
  342. CP_MM_XCNT(ppdev, pjBase, (PELS_TO_BYTES(prcl->right - prcl->left) - 1));
  343. CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top - 1));
  344. CP_MM_DST_ADDR(ppdev, pjBase, ((prcl->top * lDelta) + PELS_TO_BYTES(prcl->left)));
  345. CP_MM_START_BLT(ppdev, pjBase);
  346. if (--c == 0)
  347. return;
  348. prcl++;
  349. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  350. }
  351. }
  352. /**************************************************************************
  353. * VOID vMmCopyBlt
  354. *
  355. * Does a screen-to-screen blt of a list of rectangles.
  356. *
  357. **************************************************************************/
  358. VOID vMmCopyBlt(
  359. PDEV* ppdev,
  360. LONG c, // Can't be zero
  361. RECTL* prcl, // Array of relative coordinates destination rectangles
  362. ROP4 rop4, // Obvious?
  363. POINTL* pptlSrc, // Original unclipped source point
  364. RECTL* prclDst) // Original unclipped destination rectangle
  365. {
  366. LONG dx;
  367. LONG dy; // Add delta to destination to get source
  368. LONG xyOffset = ppdev->xyOffset;
  369. BYTE* pjBase = ppdev->pjBase;
  370. LONG lDelta = ppdev->lDelta;
  371. BYTE jHwRop;
  372. DISPDBG((10,"vCopyBlt called"));
  373. ASSERTDD(c > 0, "Can't handle zero rectangles");
  374. //
  375. // The src-dst delta will be the same for all rectangles
  376. //
  377. dx = pptlSrc->x - prclDst->left;
  378. dy = pptlSrc->y - prclDst->top;
  379. //
  380. // Make sure we can write to the video registers.
  381. //
  382. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  383. jHwRop = gajHwMixFromRop2[rop4 & 0xf];
  384. CP_MM_ROP(ppdev, pjBase, jHwRop);
  385. CP_MM_SRC_Y_OFFSET(ppdev, pjBase, lDelta);
  386. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  387. //
  388. // The accelerator may not be as fast at doing right-to-left copies, so
  389. // only do them when the rectangles truly overlap:
  390. //
  391. if (!OVERLAP(prclDst, pptlSrc) ||
  392. (prclDst->top < pptlSrc->y) ||
  393. ((prclDst->top == pptlSrc->y) && (prclDst->left <= pptlSrc->x))
  394. )
  395. {
  396. //
  397. // Top to Bottom - Left to Right
  398. //
  399. DISPDBG((12,"Top to Bottom - Left to Right"));
  400. CP_MM_BLT_MODE(ppdev, pjBase, DIR_TBLR);
  401. while (TRUE)
  402. {
  403. CP_MM_XCNT(ppdev, pjBase, (PELS_TO_BYTES(prcl->right - prcl->left) - 1));
  404. CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top - 1));
  405. CP_MM_SRC_ADDR(ppdev, pjBase, (xyOffset + ((prcl->top + dy) * lDelta) + PELS_TO_BYTES(prcl->left + dx)));
  406. CP_MM_DST_ADDR(ppdev, pjBase, ((prcl->top * lDelta) + PELS_TO_BYTES(prcl->left)));
  407. CP_MM_START_BLT(ppdev, pjBase);
  408. if (--c == 0)
  409. return;
  410. prcl++;
  411. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  412. }
  413. }
  414. else
  415. {
  416. //
  417. // Bottom to Top - Right to Left
  418. //
  419. DISPDBG((12,"Bottom to Top - Right to Left"));
  420. CP_MM_BLT_MODE(ppdev, pjBase, DIR_BTRL);
  421. while (TRUE)
  422. {
  423. CP_MM_XCNT(ppdev, pjBase, (PELS_TO_BYTES(prcl->right - prcl->left) - 1));
  424. CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top - 1));
  425. CP_MM_SRC_ADDR(ppdev, pjBase, (xyOffset + ((prcl->bottom - 1 + dy) * lDelta) + PELS_TO_BYTES(prcl->right + dx) - 1));
  426. CP_MM_DST_ADDR(ppdev, pjBase, (((prcl->bottom - 1) * lDelta) + PELS_TO_BYTES(prcl->right) - 1));
  427. CP_MM_START_BLT(ppdev, pjBase);
  428. if (--c == 0)
  429. return;
  430. prcl++;
  431. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  432. }
  433. }
  434. }
  435. /******************************Public*Routine******************************\
  436. * VOID vMmXfer1bpp
  437. *
  438. * Low-level routine used to transfer monochrome data to the screen using
  439. * DWORD writes to the blt engine.
  440. *
  441. * This can handle opaque or transparent expansions. It does opaque
  442. * expansions by drawing the opaque rectangle first and then transparently
  443. * expands the foreground bits.
  444. *
  445. \**************************************************************************/
  446. VOID vMmXfer1bpp(
  447. PDEV* ppdev,
  448. LONG c, // Count of rectangles, can't be zero
  449. RECTL* prcl, // List of destination rectangles, in relative
  450. // coordinates
  451. ROP4 rop4, // Actually had better be a rop3
  452. SURFOBJ* psoSrc, // Source surface
  453. POINTL* pptlSrc, // Original unclipped source point
  454. RECTL* prclDst, // Original unclipped destination rectangle
  455. XLATEOBJ* pxlo) // Translate that provides color-expansion information
  456. {
  457. ULONG* pulXfer;
  458. ULONG* pul;
  459. LONG ix;
  460. LONG iy;
  461. LONG cxWidthInBytes;
  462. BYTE* pjBits;
  463. POINTL ptlDst;
  464. POINTL ptlSrc;
  465. SIZEL sizlDst;
  466. LONG cxLeftMask;
  467. LONG cxRightMask;
  468. ULONG ulDstAddr;
  469. INT nDwords;
  470. ULONG ulLeftMask;
  471. ULONG ulRightMask;
  472. LONG dx;
  473. LONG dy;
  474. BYTE* pjBase = ppdev->pjBase;
  475. LONG lDelta = ppdev->lDelta;
  476. LONG lDeltaSrc = psoSrc->lDelta;
  477. LONG cBpp = ppdev->cBpp;
  478. ULONG ulFgColor = pxlo->pulXlate[1];
  479. ULONG ulBgColor = pxlo->pulXlate[0];
  480. // Since the hardware clipping on some of the Cirrus chips is broken, we
  481. // do the clipping by rounding out the edges to dword boundaries and then
  482. // doing the blt transparently. In the event that we want the expansion
  483. // to be opaque, we do the opaquing blt in advance. One side effect of
  484. // this is that the destination bits are no longer valid for processing
  485. // the rop. This could probably be optimized by doing the edges seperately
  486. // and then doing the middle section in one pass. However, this is
  487. // complicated by a 5434 bug that breaks blts less than 10 pixels wide.
  488. ASSERTDD(c > 0, "Can't handle zero rectangles");
  489. ASSERTDD(((rop4 & 0xff00) == 0xcc00), "Expected foreground rop of 0xcc");
  490. //
  491. // The src-dst delta will be the same for all rectangles
  492. //
  493. dx = pptlSrc->x - prclDst->left;
  494. dy = pptlSrc->y - prclDst->top;
  495. if (cBpp == 1)
  496. {
  497. ulFgColor = (ulFgColor << 8) | (ulFgColor & 0xff);
  498. ulBgColor = (ulBgColor << 8) | (ulBgColor & 0xff);
  499. ulFgColor = (ulFgColor << 16) | (ulFgColor & 0xffff);
  500. ulBgColor = (ulBgColor << 16) | (ulBgColor & 0xffff);
  501. }
  502. else if (cBpp == 2)
  503. {
  504. ulFgColor = (ulFgColor << 16) | (ulFgColor & 0xffff);
  505. ulBgColor = (ulBgColor << 16) | (ulBgColor & 0xffff);
  506. }
  507. pulXfer = ppdev->pulXfer;
  508. #if BANKING //bank#1
  509. ppdev->pfnBankMap(ppdev, ppdev->lXferBank);
  510. #endif
  511. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  512. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  513. if (rop4 != 0xCCAA)
  514. {
  515. LONG lCnt = c;
  516. RECTL* prclTmp = prcl;
  517. BYTE jHwBgRop = gajHwMixFromRop2[rop4 & 0xf];
  518. CP_MM_ROP(ppdev, pjBase, jHwBgRop);
  519. CP_MM_FG_COLOR(ppdev, pjBase, ulBgColor);
  520. CP_MM_SRC_ADDR(ppdev, pjBase, ppdev->ulSolidColorOffset);
  521. CP_MM_BLT_MODE(ppdev, pjBase, ppdev->jModeColor |
  522. ENABLE_COLOR_EXPAND |
  523. ENABLE_8x8_PATTERN_COPY);
  524. do
  525. {
  526. // calculate the size of the blt
  527. ptlDst.x = prclTmp->left;
  528. ptlDst.y = prclTmp->top;
  529. sizlDst.cx = prclTmp->right - ptlDst.x;
  530. sizlDst.cy = prclTmp->bottom - ptlDst.y;
  531. //
  532. // Fill the background rectangle with the background color
  533. //
  534. // Set the dest addresses
  535. ulDstAddr = (ptlDst.y * lDelta) + PELS_TO_BYTES(ptlDst.x);
  536. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  537. CP_MM_XCNT(ppdev, pjBase, PELS_TO_BYTES(sizlDst.cx) - 1);
  538. CP_MM_YCNT(ppdev, pjBase, sizlDst.cy - 1);
  539. CP_MM_DST_ADDR(ppdev, pjBase, ulDstAddr);
  540. // Start the blt operation
  541. CP_MM_START_BLT(ppdev, pjBase);
  542. prclTmp++;
  543. } while (--lCnt != 0);
  544. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  545. }
  546. CP_MM_FG_COLOR(ppdev, pjBase, ulFgColor);
  547. CP_MM_BG_COLOR(ppdev, pjBase, ~ulFgColor);
  548. CP_IO_XPAR_COLOR(ppdev, pjBase, ~ulFgColor);
  549. CP_MM_ROP(ppdev, pjBase, CL_SRC_COPY);
  550. CP_MM_BLT_MODE(ppdev, pjBase, ppdev->jModeColor |
  551. ENABLE_COLOR_EXPAND |
  552. ENABLE_TRANSPARENCY_COMPARE |
  553. SRC_CPU_DATA);
  554. CP_MM_BLT_EXT_MODE(ppdev, pjBase, 0); // jl01
  555. do
  556. {
  557. // calculate the size of the blt
  558. ptlDst.x = prcl->left;
  559. ptlDst.y = prcl->top;
  560. sizlDst.cx = prcl->right - ptlDst.x;
  561. sizlDst.cy = prcl->bottom - ptlDst.y;
  562. // calculate the number of dwords per scan line
  563. ptlSrc.x = prcl->left + dx;
  564. ptlSrc.y = prcl->top + dy;
  565. // Floor the source.
  566. // Extend the width by the amount required to floor to a dword boundary.
  567. // Set the size of the left mask.
  568. // Floor the dest, so it aligns with the floored source.
  569. if ((cxLeftMask = (ptlSrc.x & 31)))
  570. {
  571. sizlDst.cx += cxLeftMask;
  572. ptlSrc.x &= ~31;
  573. ptlDst.x -= cxLeftMask;
  574. }
  575. ulLeftMask = gaulLeftClipMask[cxLeftMask];
  576. // Ceil the cx to a dword boundary.
  577. if (cxRightMask = (sizlDst.cx & 31))
  578. {
  579. cxRightMask = 32 - cxRightMask;
  580. sizlDst.cx = (sizlDst.cx + 31) & ~31;
  581. }
  582. ulRightMask = gaulRightClipMask[cxRightMask];
  583. if (sizlDst.cx == 32)
  584. {
  585. ulLeftMask &= ulRightMask;
  586. ulRightMask = 0;
  587. }
  588. // Note: At this point sizlDst.cx is the width of the blt in pixels,
  589. // floored to a dword boundary, and ceiled to a dword boundary.
  590. // Calculate the width in Bytes
  591. cxWidthInBytes = sizlDst.cx >> 3;
  592. // Calculate the number of Dwords and any remaining bytes
  593. nDwords = cxWidthInBytes >> 2;
  594. ASSERTDD(((cxWidthInBytes & 0x03) == 0),
  595. "cxWidthInBytes is not a DWORD multiple");
  596. // Calculate the address of the source bitmap
  597. // This is to a byte boundary.
  598. pjBits = (PBYTE) psoSrc->pvScan0;
  599. pjBits += ptlSrc.y * lDeltaSrc;
  600. pjBits += ptlSrc.x >> 3;
  601. ASSERTDD((((ULONG_PTR)pjBits & 0x03) == 0),
  602. "pjBits not DWORD aligned like it should be");
  603. //
  604. // Blt the 1 bpp bitmap
  605. //
  606. ulDstAddr = (ptlDst.y * lDelta) + PELS_TO_BYTES(ptlDst.x);
  607. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  608. //
  609. // Tell the hardware that we want to write (sizlDst.cx) X amd (sizlDst.cy) Y bytes
  610. //
  611. CP_MM_XCNT(ppdev, pjBase, PELS_TO_BYTES(sizlDst.cx) - 1);
  612. CP_MM_YCNT(ppdev, pjBase, sizlDst.cy - 1);
  613. //
  614. // The 542x chips require a write to the Src Address Register when
  615. // doing a host transfer with color expansion. The value is
  616. // irrelevant, but the write is crucial. This is documented in
  617. // the manual, not the errata. Go figure.
  618. //
  619. CP_MM_SRC_ADDR(ppdev, pjBase, 0);
  620. CP_MM_DST_ADDR(ppdev, pjBase, ulDstAddr);
  621. CP_MM_START_BLT(ppdev, pjBase);
  622. //
  623. // Transfer the host bitmap.
  624. //
  625. if (ulRightMask)
  626. {
  627. //
  628. // Blt is > 1 DWORD wide (nDwords > 1)
  629. //
  630. for (iy = 0; iy < sizlDst.cy; iy++)
  631. {
  632. pul = (ULONG*) pjBits;
  633. //*pulXfer++ = *(((ULONG*)pul)++) & ulLeftMask;
  634. WRITE_REGISTER_ULONG(pulXfer, (*((ULONG*)pul) & ulLeftMask));
  635. pul++;
  636. for (ix = 0; ix < (nDwords-2); ix++)
  637. {
  638. //*pulXfer++ = *(((ULONG*)pul)++);
  639. WRITE_REGISTER_ULONG(pulXfer, (*((ULONG*)pul)));
  640. pul++;
  641. }
  642. //*pulXfer++ = *(((ULONG*)pul)++) & ulRightMask;
  643. WRITE_REGISTER_ULONG(pulXfer, (*((ULONG*)pul) & ulRightMask));
  644. pul++;
  645. pjBits += lDeltaSrc;
  646. //pulXfer = ppdev->pulXfer;
  647. CP_MEMORY_BARRIER(); // Flush memory cache when we reset the address
  648. }
  649. }
  650. else
  651. {
  652. //
  653. // Blt is 1 DWORD wide (nDwords == 1)
  654. //
  655. for (iy = 0; iy < sizlDst.cy; iy++)
  656. {
  657. //*pulXfer = *((ULONG*)pjBits) & ulLeftMask;
  658. WRITE_REGISTER_ULONG(pulXfer, (*((ULONG*)pjBits) & ulLeftMask));
  659. pjBits += lDeltaSrc;
  660. CP_MEMORY_BARRIER(); // Flush memory cache
  661. }
  662. }
  663. prcl++;
  664. } while (--c != 0);
  665. }
  666. /******************************Public*Routine******************************\
  667. * VOID vMmXfer4bpp
  668. *
  669. * Does a 4bpp transfer from a bitmap to the screen.
  670. *
  671. * NOTE: The screen must be 8bpp for this function to be called!
  672. *
  673. * The reason we implement this is that a lot of resources are kept as 4bpp,
  674. * and used to initialize DFBs, some of which we of course keep off-screen.
  675. *
  676. \**************************************************************************/
  677. // XLATE_BUFFER_SIZE defines the size of the stack-based buffer we use
  678. // for doing the translate. Note that in general stack buffers should
  679. // be kept as small as possible. The OS guarantees us only 8k for stack
  680. // from GDI down to the display driver in low memory situations; if we
  681. // ask for more, we'll access violate. Note also that at any time the
  682. // stack buffer cannot be larger than a page (4k) -- otherwise we may
  683. // miss touching the 'guard page' and access violate then too.
  684. #define XLATE_BUFFER_SIZE 256
  685. VOID vMmXfer4bpp(
  686. PDEV* ppdev,
  687. LONG c, // Count of rectangles, can't be zero
  688. RECTL* prcl, // List of destination rectangles, in relative coordinates
  689. ULONG rop4, // rop4
  690. SURFOBJ* psoSrc, // Source surface
  691. POINTL* pptlSrc, // Original unclipped source point
  692. RECTL* prclDst, // Original unclipped destination rectangle
  693. XLATEOBJ* pxlo) // Translate that provides colour-expansion information
  694. {
  695. ULONG ulDstAddr;
  696. LONG dx;
  697. LONG dy;
  698. LONG cx;
  699. LONG cy;
  700. LONG lSrcDelta;
  701. BYTE* pjSrcScan0;
  702. BYTE* pjScan;
  703. BYTE* pjSrc;
  704. BYTE* pjDst;
  705. LONG cxThis;
  706. LONG cxToGo;
  707. LONG xSrc;
  708. LONG iLoop;
  709. BYTE jSrc;
  710. ULONG* pulXlate;
  711. LONG cdwThis;
  712. BYTE* pjBuf;
  713. BYTE ajBuf[XLATE_BUFFER_SIZE];
  714. ULONG* pulXfer = ppdev->pulXfer;
  715. BYTE* pjBase = ppdev->pjBase;
  716. LONG lDelta = ppdev->lDelta;
  717. ASSERTDD(ppdev->iBitmapFormat == BMF_8BPP, "Screen must be 8bpp");
  718. ASSERTDD(psoSrc->iBitmapFormat == BMF_4BPP, "Source must be 4bpp");
  719. ASSERTDD(c > 0, "Can't handle zero rectangles");
  720. ASSERTDD(((rop4 & 0xff00) >> 8) == (rop4 & 0xff),
  721. "Expect only a rop2");
  722. DISPDBG((5, "vXfer4bpp: entry"));
  723. dx = pptlSrc->x - prclDst->left;
  724. dy = pptlSrc->y - prclDst->top; // Add to destination to get source
  725. lSrcDelta = psoSrc->lDelta;
  726. pjSrcScan0 = psoSrc->pvScan0;
  727. #if BANKING //bank#1
  728. ppdev->pfnBankMap(ppdev, ppdev->lXferBank);
  729. #endif
  730. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  731. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  732. #if 1 // D5480
  733. CP_MM_BLT_MODE_PACKED(ppdev, pjBase, gajHwPackedMixFromRop2[rop4 & 0xf] | SRC_CPU_DATA);
  734. #else
  735. CP_MM_ROP(ppdev, pjBase, gajHwMixFromRop2[rop4 & 0xf]);
  736. CP_MM_BLT_MODE(ppdev, pjBase, SRC_CPU_DATA);
  737. #endif
  738. while(TRUE)
  739. {
  740. ulDstAddr = (prcl->top * lDelta) + PELS_TO_BYTES(prcl->left);
  741. cx = prcl->right - prcl->left;
  742. cy = prcl->bottom - prcl->top;
  743. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  744. CP_MM_XCNT(ppdev, pjBase, PELS_TO_BYTES(cx) - 1);
  745. CP_MM_YCNT(ppdev, pjBase, cy - 1);
  746. CP_MM_DST_ADDR(ppdev, pjBase, ulDstAddr);
  747. pulXlate = pxlo->pulXlate;
  748. xSrc = prcl->left + dx;
  749. pjScan = pjSrcScan0 + (prcl->top + dy) * lSrcDelta + (xSrc >> 1);
  750. CP_MM_START_BLT(ppdev, pjBase);
  751. do {
  752. pjSrc = pjScan;
  753. cxToGo = cx; // # of pels per scan in 4bpp source
  754. do {
  755. cxThis = XLATE_BUFFER_SIZE;
  756. // We can handle XLATE_BUFFER_SIZE number
  757. // of pels in this xlate batch
  758. cxToGo -= cxThis; // cxThis will be the actual number of
  759. // pels we'll do in this xlate batch
  760. if (cxToGo < 0)
  761. cxThis += cxToGo;
  762. pjDst = ajBuf; // Points to our temporary batch buffer
  763. // We handle alignment ourselves because it's easy to
  764. // do, rather than pay the cost of setting/resetting
  765. // the scissors register:
  766. if (xSrc & 1)
  767. {
  768. // When unaligned, we have to be careful not to read
  769. // past the end of the 4bpp bitmap (that could
  770. // potentially cause us to access violate):
  771. iLoop = cxThis >> 1; // Each loop handles 2 pels;
  772. // we'll handle odd pel
  773. // separately
  774. jSrc = *pjSrc;
  775. while (iLoop-- != 0)
  776. {
  777. *pjDst++ = (BYTE) pulXlate[jSrc & 0xf];
  778. jSrc = *(++pjSrc);
  779. *pjDst++ = (BYTE) pulXlate[jSrc >> 4];
  780. }
  781. if (cxThis & 1)
  782. *pjDst = (BYTE) pulXlate[jSrc & 0xf];
  783. }
  784. else
  785. {
  786. iLoop = (cxThis + 1) >> 1; // Each loop handles 2 pels
  787. do {
  788. jSrc = *pjSrc++;
  789. *pjDst++ = (BYTE) pulXlate[jSrc >> 4];
  790. *pjDst++ = (BYTE) pulXlate[jSrc & 0xf];
  791. } while (--iLoop != 0);
  792. }
  793. // The number of bytes we'll transfer is equal to the number
  794. // of pels we've processed in the batch. Since we're
  795. // transferring words, we have to round up to get the word
  796. // count:
  797. cdwThis = (cxThis + 3) >> 2;
  798. pjBuf = ajBuf;
  799. TRANSFER_DWORD_ALIGNED(ppdev, pulXfer, pjBuf, cdwThis);
  800. } while (cxToGo > 0);
  801. pjScan += lSrcDelta; // Advance to next source scan. Note
  802. // that we could have computed the
  803. // value to advance 'pjSrc' directly,
  804. // but this method is less
  805. // error-prone.
  806. } while (--cy != 0);
  807. if (--c == 0)
  808. return;
  809. prcl++;
  810. }
  811. }
  812. /******************************Public*Routine******************************\
  813. * VOID vMmXferNative
  814. *
  815. * Transfers a bitmap that is the same color depth as the display to
  816. * the screen via the data transfer register, with no translation.
  817. *
  818. \**************************************************************************/
  819. VOID vMmXferNative(
  820. PDEV* ppdev,
  821. LONG c, // Count of rectangles, can't be zero
  822. RECTL* prcl, // Array of relative coordinates destination rectangles
  823. ULONG rop4, // rop4
  824. SURFOBJ* psoSrc, // Source surface
  825. POINTL* pptlSrc, // Original unclipped source point
  826. RECTL* prclDst, // Original unclipped destination rectangle
  827. XLATEOBJ* pxlo) // Not used
  828. {
  829. ULONG ulDstAddr;
  830. LONG dx;
  831. LONG dy;
  832. LONG cx;
  833. LONG cy;
  834. LONG lSrcDelta;
  835. BYTE* pjSrcScan0;
  836. BYTE* pjSrc;
  837. LONG cjSrc;
  838. ULONG* pulXfer = ppdev->pulXfer;
  839. BYTE* pjBase = ppdev->pjBase;
  840. LONG lDelta = ppdev->lDelta;
  841. ASSERTDD((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL),
  842. "Can handle trivial xlate only");
  843. ASSERTDD(psoSrc->iBitmapFormat == ppdev->iBitmapFormat,
  844. "Source must be same color depth as screen");
  845. ASSERTDD(c > 0, "Can't handle zero rectangles");
  846. ASSERTDD(((rop4 & 0xff00) >> 8) == (rop4 & 0xff),
  847. "Expect only a rop2");
  848. dx = pptlSrc->x - prclDst->left;
  849. dy = pptlSrc->y - prclDst->top; // Add to destination to get source
  850. lSrcDelta = psoSrc->lDelta;
  851. pjSrcScan0 = psoSrc->pvScan0;
  852. #if BANKING //bank#1
  853. ppdev->pfnBankMap(ppdev, ppdev->lXferBank);
  854. #endif
  855. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  856. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  857. #if 1 // D5480
  858. CP_MM_BLT_MODE_PACKED(ppdev, pjBase, gajHwPackedMixFromRop2[rop4 & 0xf] | SRC_CPU_DATA);
  859. #else
  860. CP_MM_ROP(ppdev, pjBase, gajHwMixFromRop2[rop4 & 0xf]);
  861. CP_MM_BLT_MODE(ppdev, pjBase, SRC_CPU_DATA);
  862. #endif
  863. while(TRUE)
  864. {
  865. ulDstAddr = (prcl->top * lDelta) + PELS_TO_BYTES(prcl->left);
  866. cx = prcl->right - prcl->left;
  867. cy = prcl->bottom - prcl->top;
  868. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  869. CP_MM_XCNT(ppdev, pjBase, PELS_TO_BYTES(cx) - 1);
  870. CP_MM_YCNT(ppdev, pjBase, cy - 1);
  871. CP_MM_DST_ADDR(ppdev, pjBase, ulDstAddr);
  872. cjSrc = PELS_TO_BYTES(cx);
  873. pjSrc = pjSrcScan0 + (prcl->top + dy) * lSrcDelta
  874. + (PELS_TO_BYTES(prcl->left + dx));
  875. CP_MM_START_BLT(ppdev, pjBase);
  876. vImageTransfer(ppdev, pjSrc, lSrcDelta, cjSrc, cy);
  877. if (--c == 0)
  878. return;
  879. prcl++;
  880. }
  881. }
  882. ////////////////////////////////////////////////////////////////////////////////
  883. // //
  884. // N E W B L T R O U T I N E S F O R B R U S H C A C H E //
  885. // //
  886. ////////////////////////////////////////////////////////////////////////////////
  887. VOID vMmFillSolid36(
  888. PDEV* ppdev,
  889. LONG c,
  890. RECTL* prcl,
  891. ROP4 rop4,
  892. RBRUSH_COLOR rbc,
  893. POINTL* pptlBrush)
  894. {
  895. BYTE* pjBase = ppdev->pjBase;
  896. LONG lDelta = ppdev->lDelta;
  897. BYTE jHwRop = gajHwMixFromRop2[(rop4 >> 2) & 0x0F];
  898. BYTE jMode = ppdev->jModeColor
  899. | ENABLE_8x8_PATTERN_COPY
  900. | ENABLE_COLOR_EXPAND;
  901. while (c-- > 0)
  902. {
  903. ULONG ulDstOffset;
  904. SIZEL sizlDst;
  905. // Calculate the destination address and size.
  906. ulDstOffset = (prcl->top * lDelta) + PELS_TO_BYTES(prcl->left);
  907. sizlDst.cx = PELS_TO_BYTES(prcl->right - prcl->left) - 1;
  908. sizlDst.cy = (prcl->bottom - prcl->top) - 1;
  909. // Wait for the bitblt engine.
  910. WAIT_BUSY_BLT(ppdev, pjBase);
  911. // Setup the bitblt registers.
  912. CP_MM_FG_COLOR(ppdev, pjBase, rbc.iSolidColor);
  913. CP_MM_XCNT(ppdev, pjBase, sizlDst.cx);
  914. CP_MM_YCNT(ppdev, pjBase, sizlDst.cy);
  915. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  916. CP_MM_DST_WRITE_MASK(ppdev, pjBase, 0); // Disable clipping.
  917. CP_MM_BLT_MODE(ppdev, pjBase, jMode);
  918. CP_MM_ROP(ppdev, pjBase, jHwRop);
  919. CP_MM_BLT_EXT_MODE(ppdev, pjBase, ENABLE_SOLID_FILL);
  920. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  921. // Next rectangle.
  922. prcl++;
  923. }
  924. }
  925. VOID vMmFillPat36(
  926. PDEV* ppdev,
  927. LONG c,
  928. RECTL* prcl,
  929. ROP4 rop4,
  930. RBRUSH_COLOR rbc,
  931. POINTL* pptlBrush)
  932. {
  933. BYTE* pjBase = ppdev->pjBase;
  934. LONG lDelta = ppdev->lDelta;
  935. BYTE jHwRop = gajHwMixFromRop2[(rop4 >> 2) & 0x0F];
  936. CP_MM_BLT_EXT_MODE(ppdev, pjBase, 0) ; // chu01
  937. // Dithered brush...
  938. if (rbc.prb->fl == RBRUSH_DITHER)
  939. {
  940. DITHERCACHE* pdc;
  941. pdc = (DITHERCACHE*) ((ULONG_PTR)ppdev + rbc.prb->ulSlot);
  942. if (pdc->ulColor != rbc.prb->ulUniq)
  943. {
  944. // Cache entry is invalid, realize the brush again.
  945. bCacheDither(ppdev, rbc.prb);
  946. }
  947. while (c-- > 0)
  948. {
  949. ULONG ulDstOffset, ulSrcOffset;
  950. SIZEL sizlDst;
  951. LONG xOffset, yOffset;
  952. LONG x;
  953. // Calculate the brush rotation.
  954. xOffset = (prcl->left - pptlBrush->x) & 7;
  955. yOffset = (prcl->top - pptlBrush->y) & 7;
  956. ulSrcOffset = rbc.prb->ulBrush | yOffset;
  957. // Calculate the destination and size.
  958. x = prcl->left - xOffset;
  959. ulDstOffset = (prcl->top * lDelta) + x;
  960. sizlDst.cx = (prcl->right - x) - 1;
  961. sizlDst.cy = (prcl->bottom - prcl->top) - 1;
  962. // Wait for the bitblt engine.
  963. WAIT_BUSY_BLT(ppdev, pjBase);
  964. // Setup the bitblt registers.
  965. CP_MM_XCNT(ppdev, pjBase, sizlDst.cx);
  966. CP_MM_YCNT(ppdev, pjBase, sizlDst.cy);
  967. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  968. CP_MM_SRC_ADDR(ppdev, pjBase, ulSrcOffset);
  969. CP_MM_DST_WRITE_MASK(ppdev, pjBase, xOffset);
  970. CP_MM_BLT_MODE(ppdev, pjBase, ENABLE_8x8_PATTERN_COPY);
  971. CP_MM_ROP(ppdev, pjBase, jHwRop);
  972. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  973. // Next rectangle.
  974. prcl++;
  975. }
  976. }
  977. // Monochrome brush...
  978. else if (rbc.prb->fl == RBRUSH_MONOCHROME)
  979. {
  980. MONOCACHE* pmc;
  981. BYTE jMode;
  982. ULONG ulBgColor, ulFgColor;
  983. pmc = (MONOCACHE*) ((ULONG_PTR)ppdev + rbc.prb->ulSlot);
  984. if (pmc->ulUniq != rbc.prb->ulUniq)
  985. {
  986. // Cache entry is invalid, realize the brush again.
  987. bCacheMonochrome(ppdev, rbc.prb);
  988. }
  989. // Setup the common parameters.
  990. jMode = ppdev->jModeColor
  991. | ENABLE_8x8_PATTERN_COPY
  992. | ENABLE_COLOR_EXPAND;
  993. ulBgColor = rbc.prb->ulBackColor;
  994. ulFgColor = rbc.prb->ulForeColor;
  995. // Monochrome brushes in 24-bpp are already cached expanded.
  996. if (ppdev->cBpp == 3)
  997. {
  998. jMode = ppdev->jModeColor
  999. | ENABLE_8x8_PATTERN_COPY;
  1000. }
  1001. // Walk through all rectangles.
  1002. while (c-- > 0)
  1003. {
  1004. ULONG ulDstOffset, ulSrcOffset;
  1005. SIZEL sizlDst;
  1006. LONG xOffset, yOffset;
  1007. LONG x;
  1008. // Calculate the brush rotation.
  1009. xOffset = (prcl->left - pptlBrush->x) & 7;
  1010. yOffset = (prcl->top - pptlBrush->y) & 7;
  1011. ulSrcOffset = rbc.prb->ulBrush | yOffset;
  1012. // Calculate the destination and size.
  1013. x = prcl->left - xOffset;
  1014. ulDstOffset = (prcl->top * lDelta) + PELS_TO_BYTES(x);
  1015. sizlDst.cx = PELS_TO_BYTES(prcl->right - x) - 1;
  1016. sizlDst.cy = (prcl->bottom - prcl->top) - 1;
  1017. if (ppdev->cBpp == 3)
  1018. {
  1019. xOffset *= 3;
  1020. }
  1021. // Wait for the bitblt engine.
  1022. WAIT_BUSY_BLT(ppdev, pjBase);
  1023. // Setup the bitblt registers.
  1024. CP_MM_BG_COLOR(ppdev, pjBase, ulBgColor);
  1025. CP_MM_FG_COLOR(ppdev, pjBase, ulFgColor);
  1026. CP_MM_XCNT(ppdev, pjBase, sizlDst.cx);
  1027. CP_MM_YCNT(ppdev, pjBase, sizlDst.cy);
  1028. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  1029. CP_MM_SRC_ADDR(ppdev, pjBase, ulSrcOffset);
  1030. CP_MM_DST_WRITE_MASK(ppdev, pjBase, xOffset);
  1031. CP_MM_BLT_MODE(ppdev, pjBase, jMode);
  1032. CP_MM_ROP(ppdev, pjBase, jHwRop);
  1033. CP_MM_BLT_EXT_MODE(ppdev, pjBase, 0);
  1034. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  1035. // Next rectangle.
  1036. prcl++;
  1037. }
  1038. }
  1039. // Patterned brush...
  1040. else if (ppdev->flStatus & STAT_PATTERN_CACHE)
  1041. {
  1042. PATTERNCACHE* ppc;
  1043. BYTE jMode = ppdev->jModeColor
  1044. | ENABLE_8x8_PATTERN_COPY;
  1045. ppc = (PATTERNCACHE*) ((ULONG_PTR)ppdev + rbc.prb->ulSlot);
  1046. if (ppc->prbUniq != rbc.prb)
  1047. {
  1048. // Cache entry is invalid, realize the brush again.
  1049. bCachePattern(ppdev, rbc.prb);
  1050. }
  1051. while (c-- > 0)
  1052. {
  1053. ULONG ulDstOffset, ulSrcOffset;
  1054. SIZEL sizlDst;
  1055. LONG xOffset, yOffset;
  1056. LONG x;
  1057. // Calculate the brush rotation.
  1058. xOffset = (prcl->left - pptlBrush->x) & 7;
  1059. yOffset = (prcl->top - pptlBrush->y) & 7;
  1060. ulSrcOffset = rbc.prb->ulBrush | yOffset;
  1061. // Calculate the destination and size.
  1062. x = prcl->left - xOffset;
  1063. ulDstOffset = (prcl->top * lDelta) + PELS_TO_BYTES(x);
  1064. sizlDst.cx = PELS_TO_BYTES(prcl->right - x) - 1;
  1065. sizlDst.cy = (prcl->bottom - prcl->top) - 1;
  1066. if (ppdev->cBpp == 3)
  1067. {
  1068. xOffset *= 3;
  1069. }
  1070. // Wait for the bitblt engine.
  1071. WAIT_BUSY_BLT(ppdev, pjBase);
  1072. // Setup the bitblt registers.
  1073. CP_MM_XCNT(ppdev, pjBase, sizlDst.cx);
  1074. CP_MM_YCNT(ppdev, pjBase, sizlDst.cy);
  1075. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  1076. CP_MM_SRC_ADDR(ppdev, pjBase, ulSrcOffset);
  1077. CP_MM_DST_WRITE_MASK(ppdev, pjBase, xOffset);
  1078. CP_MM_BLT_MODE(ppdev, pjBase, jMode);
  1079. CP_MM_ROP(ppdev, pjBase, jHwRop);
  1080. CP_MM_BLT_EXT_MODE(ppdev, pjBase, 0);
  1081. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  1082. // Next rectangle.
  1083. prcl++;
  1084. }
  1085. }
  1086. // Old-style brush cache.
  1087. else
  1088. {
  1089. vMmFillPat(ppdev, c, prcl, rop4, rbc, pptlBrush);
  1090. }
  1091. }
  1092. VOID vMmCopyBlt36(
  1093. PDEV* ppdev,
  1094. LONG c,
  1095. RECTL* prcl,
  1096. ROP4 rop4,
  1097. POINTL* pptlSrc,
  1098. RECTL* prclDst)
  1099. {
  1100. LONG xy;
  1101. LONG cx, cy;
  1102. ULONG ulSrc, ulDst;
  1103. BYTE jHwRop = gajHwMixFromRop2[rop4 & 0x0F];
  1104. LONG xyOffset = ppdev->xyOffset;
  1105. BYTE* pjBase = ppdev->pjBase;
  1106. LONG lDelta = ppdev->lDelta;
  1107. DISPDBG((10, "vMmCopyBlt36 called"));
  1108. // The src-dst delta will be the same for all rectangles.
  1109. xy = ((pptlSrc->y - prclDst->top) * lDelta)
  1110. + PELS_TO_BYTES(pptlSrc->x - prclDst->left);
  1111. // Determine the direction of the blit.
  1112. if ((xy >= 0) || !OVERLAP(prclDst, pptlSrc))
  1113. {
  1114. DISPDBG((12, "Top to Bottom - Left to Right"));
  1115. while (c-- > 0)
  1116. {
  1117. // Calculate the blit size and offsets.
  1118. cx = PELS_TO_BYTES(prcl->right - prcl->left) - 1;
  1119. cy = (prcl->bottom - prcl->top) - 1;
  1120. ulDst = xyOffset + (prcl->top * lDelta) + PELS_TO_BYTES(prcl->left);
  1121. ulSrc = ulDst + xy;
  1122. // Wait for the bitblt engine.
  1123. WAIT_BUSY_BLT(ppdev, pjBase);
  1124. // Perform the move.
  1125. CP_MM_XCNT(ppdev, pjBase, cx);
  1126. CP_MM_YCNT(ppdev, pjBase, cy);
  1127. CP_MM_SRC_Y_OFFSET(ppdev, pjBase, lDelta);
  1128. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  1129. CP_MM_SRC_ADDR(ppdev, pjBase, ulSrc);
  1130. CP_MM_BLT_MODE(ppdev, pjBase, DIR_TBLR);
  1131. CP_MM_ROP(ppdev, pjBase, jHwRop);
  1132. CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDst);
  1133. // Next rectangle.
  1134. prcl++;
  1135. }
  1136. }
  1137. else
  1138. {
  1139. DISPDBG((12, "Bottom to Top - Right to Left"));
  1140. while (c-- > 0)
  1141. {
  1142. // Calculate the blit size and offsets.
  1143. cx = PELS_TO_BYTES(prcl->right - prcl->left) - 1;
  1144. cy = (prcl->bottom - prcl->top) - 1;
  1145. ulDst = xyOffset + ((prcl->bottom - 1) * lDelta)
  1146. + (PELS_TO_BYTES(prcl->right) - 1);
  1147. ulSrc = ulDst + xy;
  1148. // Wait for the bitblt engine.
  1149. WAIT_BUSY_BLT(ppdev, pjBase);
  1150. // Perform the move.
  1151. CP_MM_XCNT(ppdev, pjBase, cx);
  1152. CP_MM_YCNT(ppdev, pjBase, cy);
  1153. CP_MM_SRC_Y_OFFSET(ppdev, pjBase, lDelta);
  1154. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  1155. CP_MM_SRC_ADDR(ppdev, pjBase, ulSrc);
  1156. CP_MM_BLT_MODE(ppdev, pjBase, DIR_BTRL);
  1157. CP_MM_ROP(ppdev, pjBase, jHwRop);
  1158. CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDst);
  1159. // Next rectangle.
  1160. prcl++;
  1161. }
  1162. }
  1163. }
  1164. #if 1 // D5480
  1165. VOID vMmFillSolid80(
  1166. PDEV* ppdev,
  1167. LONG c,
  1168. RECTL* prcl,
  1169. ROP4 rop4,
  1170. RBRUSH_COLOR rbc,
  1171. POINTL* pptlBrush)
  1172. {
  1173. ULONG_PTR* ulCLStart;
  1174. ULONG ulWidthHeight;
  1175. ULONG xCLOffset;
  1176. ULONG ulDstOffset = 0;
  1177. BYTE* pjBase = ppdev->pjBase;
  1178. LONG lDelta = ppdev->lDelta;
  1179. DWORD jHwRop = gajHwPackedMixFromRop2[(rop4 >> 2) & 0x0F];
  1180. DWORD jExtMode = ENABLE_SOLID_FILL_PACKED
  1181. | ENABLE_XY_POSITION_PACKED
  1182. | ppdev->jModeColor
  1183. | ENABLE_8x8_PATTERN_COPY
  1184. | ENABLE_COLOR_EXPAND;
  1185. //
  1186. // Make sure we can write to the video registers.
  1187. //
  1188. // We need to change to wait for buffer ready
  1189. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  1190. // Setup the bitblt registers.
  1191. CP_MM_FG_COLOR(ppdev, pjBase, rbc.iSolidColor);
  1192. // Do we really need to set it every time?
  1193. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  1194. // Do we need to clear Source XY?
  1195. CP_MM_SRC_XY_PACKED(ppdev, pjBase, 0);
  1196. CP_MM_DST_WRITE_MASK(ppdev, pjBase, 0); // Disable clipping.
  1197. // Setup first set registers
  1198. xCLOffset = prcl->left;
  1199. CP_MM_DST_Y(ppdev, pjBase, prcl->top);
  1200. CP_MM_XCNT(ppdev, pjBase, (prcl->right - prcl->left) - 1);
  1201. CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top) - 1);
  1202. if (--c)
  1203. {
  1204. // There are more than one rectangle
  1205. prcl++;
  1206. jExtMode |= ENABLE_COMMAND_LIST_PACKED;
  1207. ulCLStart = ppdev->pCommandList;
  1208. ulDstOffset |= ((ULONG)((ULONG_PTR)ulCLStart
  1209. - (ULONG_PTR)ppdev->pjScreen) << 14);
  1210. CP_MM_CL_SWITCH(ppdev);
  1211. while (TRUE)
  1212. {
  1213. // Command List
  1214. // Calculate the destination address and size.
  1215. ulWidthHeight = PACKXY_FAST((prcl->right - prcl->left) - 1,
  1216. (prcl->bottom - prcl->top) - 1);
  1217. ulWidthHeight |= COMMAND_NOSRC_NOTHING;
  1218. // XY
  1219. *(ulCLStart + 1) = PACKXY_FAST(prcl->left, prcl->top);
  1220. // Source Start address
  1221. *(ulCLStart + 2) = 0;
  1222. if (c == 1)
  1223. {
  1224. ulWidthHeight |= COMMAND_LAST_PACKET;
  1225. *ulCLStart = ulWidthHeight;
  1226. // Last Command
  1227. break;
  1228. }
  1229. *ulCLStart = ulWidthHeight;
  1230. // Next rectangle.
  1231. prcl++;
  1232. c--;
  1233. ulCLStart += 4;
  1234. }
  1235. }
  1236. CP_MM_BLT_MODE_PACKED(ppdev, pjBase, jExtMode | jHwRop );
  1237. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  1238. CP_MM_DST_X(ppdev, pjBase, xCLOffset);
  1239. }
  1240. VOID vMmFillPat80(
  1241. PDEV* ppdev,
  1242. LONG c,
  1243. RECTL* prcl,
  1244. ROP4 rop4,
  1245. RBRUSH_COLOR rbc,
  1246. POINTL* pptlBrush)
  1247. {
  1248. ULONG xOffset, yOffset;
  1249. ULONG ulSrcOffset;
  1250. ULONG_PTR* ulCLStart;
  1251. ULONG ulWidthHeight;
  1252. ULONG xCLOffset;
  1253. ULONG ulDstOffset = 0;
  1254. BYTE* pjBase = ppdev->pjBase;
  1255. LONG lDelta = ppdev->lDelta;
  1256. DWORD jHwRop = gajHwPackedMixFromRop2[(rop4 >> 2) & 0x0F];
  1257. DWORD jExtMode = ENABLE_XY_POSITION_PACKED
  1258. | ENABLE_8x8_PATTERN_COPY;
  1259. // Dithered brush...
  1260. if (rbc.prb->fl == RBRUSH_DITHER)
  1261. {
  1262. DITHERCACHE* pdc;
  1263. pdc = (DITHERCACHE*) ((ULONG_PTR)ppdev + rbc.prb->ulSlot);
  1264. if (pdc->ulColor != rbc.prb->ulUniq)
  1265. {
  1266. // Cache entry is invalid, realize the brush again.
  1267. bCacheDither(ppdev, rbc.prb);
  1268. }
  1269. // Calculate the brush rotation.
  1270. xOffset = (prcl->left - pptlBrush->x) & 7;
  1271. yOffset = (prcl->top - pptlBrush->y) & 7;
  1272. ulSrcOffset = rbc.prb->ulBrush | yOffset | (xOffset << 24);
  1273. // Calculate the destination and size.
  1274. xCLOffset = prcl->left - xOffset;
  1275. //
  1276. // Make sure we can write to the video registers.
  1277. //
  1278. // We need to change to wait for buffer ready
  1279. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  1280. // Do we really need to set it every time?
  1281. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  1282. // Do we need to clear Source XY?
  1283. CP_MM_SRC_XY_PACKED(ppdev, pjBase, 0);
  1284. // Setup first set registers
  1285. CP_MM_SRC_ADDR(ppdev, pjBase, ulSrcOffset);
  1286. CP_MM_DST_Y(ppdev, pjBase, prcl->top);
  1287. CP_MM_XCNT(ppdev, pjBase, (prcl->right - xCLOffset) - 1);
  1288. CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top) - 1);
  1289. if (--c)
  1290. {
  1291. // There are more than one rectangle
  1292. prcl++;
  1293. jExtMode |= ENABLE_COMMAND_LIST_PACKED;
  1294. ulCLStart = ppdev->pCommandList;
  1295. ulDstOffset |= ((ULONG)((ULONG_PTR)ulCLStart
  1296. - (ULONG_PTR)ppdev->pjScreen) << 14);
  1297. CP_MM_CL_SWITCH(ppdev);
  1298. while (TRUE)
  1299. {
  1300. // Command List
  1301. // Calculate the brush rotation.
  1302. xOffset = (prcl->left - pptlBrush->x) & 7;
  1303. yOffset = (prcl->top - pptlBrush->y) & 7;
  1304. // Calculate the destination address and size.
  1305. ulWidthHeight = PACKXY_FAST((prcl->right - prcl->left + xOffset ) - 1,
  1306. (prcl->bottom - prcl->top) - 1);
  1307. ulWidthHeight |= COMMAND_FOURTH_NOTHING;
  1308. // XY
  1309. *(ulCLStart + 1) = PACKXY_FAST(prcl->left - xOffset, prcl->top);
  1310. // Source Start address
  1311. *(ulCLStart + 2) = rbc.prb->ulBrush | yOffset | (xOffset << 24);
  1312. if (c == 1)
  1313. {
  1314. ulWidthHeight |= COMMAND_LAST_PACKET;
  1315. *ulCLStart = ulWidthHeight;
  1316. // Last Command
  1317. break;
  1318. }
  1319. *ulCLStart = ulWidthHeight;
  1320. // Next rectangle.
  1321. prcl++;
  1322. c--;
  1323. ulCLStart += 4;
  1324. }
  1325. }
  1326. CP_MM_BLT_MODE_PACKED(ppdev, pjBase, jExtMode | jHwRop );
  1327. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  1328. CP_MM_DST_X(ppdev, pjBase, xCLOffset);
  1329. }
  1330. // Monochrome brush...
  1331. else if (rbc.prb->fl == RBRUSH_MONOCHROME)
  1332. {
  1333. MONOCACHE* pmc;
  1334. BYTE jMode;
  1335. ULONG ulBgColor, ulFgColor;
  1336. pmc = (MONOCACHE*) ((ULONG_PTR) ppdev + rbc.prb->ulSlot);
  1337. if (pmc->ulUniq != rbc.prb->ulUniq)
  1338. {
  1339. // Cache entry is invalid, realize the brush again.
  1340. bCacheMonochrome(ppdev, rbc.prb);
  1341. }
  1342. ulBgColor = rbc.prb->ulBackColor;
  1343. ulFgColor = rbc.prb->ulForeColor;
  1344. // Calculate the brush rotation.
  1345. xOffset = (prcl->left - pptlBrush->x) & 7;
  1346. yOffset = (prcl->top - pptlBrush->y) & 7;
  1347. // Monochrome brushes in 24-bpp are already cached expanded.
  1348. if (ppdev->cBpp == 3)
  1349. {
  1350. jExtMode |= ppdev->jModeColor;
  1351. ulSrcOffset = rbc.prb->ulBrush | yOffset | ((xOffset * 3) << 24);
  1352. }
  1353. else
  1354. {
  1355. jExtMode |= (ppdev->jModeColor | ENABLE_COLOR_EXPAND);
  1356. ulSrcOffset = rbc.prb->ulBrush | yOffset | (xOffset << 24);
  1357. }
  1358. // Calculate the destination and size.
  1359. xCLOffset = prcl->left - xOffset;
  1360. //
  1361. // Make sure we can write to the video registers.
  1362. //
  1363. // We need to change to wait for buffer ready
  1364. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  1365. // Do we really need to set it every time?
  1366. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  1367. // Do we need to clear Source XY?
  1368. CP_MM_SRC_XY_PACKED(ppdev, pjBase, 0);
  1369. // Setup first set registers
  1370. CP_MM_SRC_ADDR(ppdev, pjBase, ulSrcOffset);
  1371. CP_MM_DST_Y(ppdev, pjBase, prcl->top);
  1372. CP_MM_XCNT(ppdev, pjBase, (prcl->right - xCLOffset) - 1);
  1373. CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top) - 1);
  1374. CP_MM_BG_COLOR(ppdev, pjBase, ulBgColor);
  1375. CP_MM_FG_COLOR(ppdev, pjBase, ulFgColor);
  1376. if (--c)
  1377. {
  1378. // There are more than one rectangle
  1379. prcl++;
  1380. jExtMode |= ENABLE_COMMAND_LIST_PACKED;
  1381. ulCLStart = ppdev->pCommandList;
  1382. ulDstOffset
  1383. |= (ULONG)(((ULONG_PTR)ulCLStart - (ULONG_PTR)ppdev->pjScreen)<<14);
  1384. CP_MM_CL_SWITCH(ppdev);
  1385. while (TRUE)
  1386. {
  1387. // Command List
  1388. // Calculate the brush rotation.
  1389. xOffset = (prcl->left - pptlBrush->x) & 7;
  1390. yOffset = (prcl->top - pptlBrush->y) & 7;
  1391. // Calculate the destination address and size.
  1392. ulWidthHeight = PACKXY_FAST((prcl->right - prcl->left + xOffset ) - 1,
  1393. (prcl->bottom - prcl->top) - 1);
  1394. ulWidthHeight |= COMMAND_FOURTH_NOTHING;
  1395. // XY
  1396. *(ulCLStart + 1) = PACKXY_FAST(prcl->left - xOffset, prcl->top);
  1397. // Source Start address
  1398. if(ppdev->cBpp == 3)
  1399. *(ulCLStart + 2) = rbc.prb->ulBrush | yOffset | ((xOffset * 3) << 24);
  1400. else
  1401. *(ulCLStart + 2) = rbc.prb->ulBrush | yOffset | (xOffset << 24);
  1402. if (c == 1)
  1403. {
  1404. ulWidthHeight |= COMMAND_LAST_PACKET;
  1405. *ulCLStart = ulWidthHeight;
  1406. // Last Command
  1407. break;
  1408. }
  1409. *ulCLStart = ulWidthHeight;
  1410. // Next rectangle.
  1411. prcl++;
  1412. c--;
  1413. ulCLStart += 4;
  1414. }
  1415. }
  1416. CP_MM_BLT_MODE_PACKED(ppdev, pjBase, jExtMode | jHwRop );
  1417. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  1418. CP_MM_DST_X(ppdev, pjBase, xCLOffset);
  1419. }
  1420. // Patterned brush...
  1421. else if (ppdev->flStatus & STAT_PATTERN_CACHE)
  1422. {
  1423. PATTERNCACHE* ppc;
  1424. ppc = (PATTERNCACHE*) ((ULONG_PTR) ppdev + rbc.prb->ulSlot);
  1425. if (ppc->prbUniq != rbc.prb)
  1426. {
  1427. // Cache entry is invalid, realize the brush again.
  1428. bCachePattern(ppdev, rbc.prb);
  1429. }
  1430. // Calculate the brush rotation.
  1431. xOffset = (prcl->left - pptlBrush->x) & 7;
  1432. yOffset = (prcl->top - pptlBrush->y) & 7;
  1433. // Monochrome brushes in 24-bpp are already cached expanded.
  1434. jExtMode |= ppdev->jModeColor;
  1435. if (ppdev->cBpp == 3)
  1436. {
  1437. ulSrcOffset = rbc.prb->ulBrush | yOffset | ((xOffset * 3) << 24);
  1438. }
  1439. else
  1440. {
  1441. ulSrcOffset = rbc.prb->ulBrush | yOffset | (xOffset << 24);
  1442. }
  1443. // Calculate the destination and size.
  1444. xCLOffset = prcl->left - xOffset;
  1445. //
  1446. // Make sure we can write to the video registers.
  1447. //
  1448. // We need to change to wait for buffer ready
  1449. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  1450. // Do we really need to set it every time?
  1451. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  1452. // Do we need to clear Source XY?
  1453. CP_MM_SRC_XY_PACKED(ppdev, pjBase, 0);
  1454. // Setup first set registers
  1455. CP_MM_SRC_ADDR(ppdev, pjBase, ulSrcOffset);
  1456. CP_MM_DST_Y(ppdev, pjBase, prcl->top);
  1457. CP_MM_XCNT(ppdev, pjBase, (prcl->right - xCLOffset) - 1);
  1458. CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top) - 1);
  1459. if (--c)
  1460. {
  1461. // There are more than one rectangle
  1462. prcl++;
  1463. jExtMode |= ENABLE_COMMAND_LIST_PACKED;
  1464. ulCLStart = ppdev->pCommandList;
  1465. ulDstOffset
  1466. |= (ULONG)(((ULONG_PTR)ulCLStart-(ULONG_PTR)ppdev->pjScreen)<<14);
  1467. CP_MM_CL_SWITCH(ppdev);
  1468. while (TRUE)
  1469. {
  1470. // Command List
  1471. // Calculate the brush rotation.
  1472. xOffset = (prcl->left - pptlBrush->x) & 7;
  1473. yOffset = (prcl->top - pptlBrush->y) & 7;
  1474. // Calculate the destination address and size.
  1475. ulWidthHeight = PACKXY_FAST((prcl->right - prcl->left + xOffset ) - 1,
  1476. (prcl->bottom - prcl->top) - 1);
  1477. ulWidthHeight |= COMMAND_FOURTH_NOTHING;
  1478. // XY
  1479. *(ulCLStart + 1) = PACKXY_FAST(prcl->left - xOffset, prcl->top);
  1480. // Source Start address
  1481. if(ppdev->cBpp == 3)
  1482. *(ulCLStart + 2) = rbc.prb->ulBrush | yOffset | ((xOffset * 3) << 24);
  1483. else
  1484. *(ulCLStart + 2) = rbc.prb->ulBrush | yOffset | (xOffset << 24);
  1485. if (c == 1)
  1486. {
  1487. ulWidthHeight |= COMMAND_LAST_PACKET;
  1488. *ulCLStart = ulWidthHeight;
  1489. // Last Command
  1490. break;
  1491. }
  1492. *ulCLStart = ulWidthHeight;
  1493. // Next rectangle.
  1494. prcl++;
  1495. c--;
  1496. ulCLStart += 4;
  1497. }
  1498. }
  1499. CP_MM_BLT_MODE_PACKED(ppdev, pjBase, jExtMode | jHwRop );
  1500. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  1501. CP_MM_DST_X(ppdev, pjBase, xCLOffset);
  1502. }
  1503. // Old-style brush cache.
  1504. else
  1505. {
  1506. vMmFillPat(ppdev, c, prcl, rop4, rbc, pptlBrush);
  1507. }
  1508. }
  1509. VOID vMmCopyBlt80(
  1510. PDEV* ppdev,
  1511. LONG c, // Can't be zero
  1512. RECTL* prcl, // Array of relative coordinates destination rectangles
  1513. ROP4 rop4, // Obvious?
  1514. POINTL* pptlSrc, // Original unclipped source point
  1515. RECTL* prclDst) // Original unclipped destination rectangle
  1516. {
  1517. LONG dx;
  1518. LONG dy; // Add delta to destination to get source
  1519. ULONG jHwRop;
  1520. ULONG_PTR* ulCLStart;
  1521. ULONG ulWidthHeight;
  1522. ULONG xCLOffset;
  1523. ULONG ulDstOffset = 0;
  1524. LONG xyOffset = ppdev->xyOffset;
  1525. BYTE* pjBase = ppdev->pjBase;
  1526. LONG lDelta = ppdev->lDelta;
  1527. DWORD jExtMode = ENABLE_XY_POSITION_PACKED |
  1528. ppdev->jModeColor;
  1529. DISPDBG((10,"vCopyBlt called"));
  1530. ASSERTDD(c > 0, "Can't handle zero rectangles");
  1531. //
  1532. // The src-dst delta will be the same for all rectangles
  1533. //
  1534. dx = pptlSrc->x - prclDst->left;
  1535. dy = pptlSrc->y - prclDst->top;
  1536. //
  1537. // Make sure we can write to the video registers.
  1538. //
  1539. // We need to change to wait for buffer ready
  1540. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  1541. jHwRop = gajHwPackedMixFromRop2[rop4 & 0xf];
  1542. CP_MM_SRC_Y_OFFSET(ppdev, pjBase, lDelta);
  1543. // Do we really need to set it every time?
  1544. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  1545. //
  1546. // The accelerator may not be as fast at doing right-to-left copies, so
  1547. // only do them when the rectangles truly overlap:
  1548. //
  1549. if (!OVERLAP(prclDst, pptlSrc) ||
  1550. (prclDst->top < pptlSrc->y) ||
  1551. ((prclDst->top == pptlSrc->y) && (prclDst->left <= pptlSrc->x))
  1552. )
  1553. {
  1554. //
  1555. // Top to Bottom - Left to Right
  1556. //
  1557. DISPDBG((12,"Top to Bottom - Left to Right"));
  1558. // Setup first set registers
  1559. xCLOffset = prcl->left;
  1560. CP_MM_DST_Y(ppdev, pjBase, prcl->top);
  1561. CP_MM_XCNT(ppdev, pjBase, (prcl->right - prcl->left) - 1);
  1562. CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top) - 1);
  1563. CP_MM_SRC_ADDR(ppdev, pjBase, (xyOffset + ((prcl->top + dy) * lDelta) + PELS_TO_BYTES(prcl->left + dx)));
  1564. CP_MM_SRC_XY_PACKED(ppdev, pjBase, 0);
  1565. if (--c)
  1566. {
  1567. // There are more than one rectangle
  1568. prcl++;
  1569. jExtMode |= ENABLE_COMMAND_LIST_PACKED;
  1570. ulCLStart = ppdev->pCommandList;
  1571. ulDstOffset
  1572. |= (ULONG)(((ULONG_PTR)ulCLStart - (ULONG_PTR)ppdev->pjScreen)<<14);
  1573. CP_MM_CL_SWITCH(ppdev);
  1574. while (TRUE)
  1575. {
  1576. // Command List
  1577. // Calculate the destination address and size.
  1578. ulWidthHeight = PACKXY_FAST((prcl->right - prcl->left) - 1,
  1579. (prcl->bottom - prcl->top) - 1);
  1580. ulWidthHeight |= COMMAND_FOURTH_NOTHING;
  1581. // XY
  1582. *(ulCLStart + 1) = PACKXY_FAST(prcl->left, prcl->top);
  1583. // Source Start address
  1584. *(ulCLStart + 2) = xyOffset + (prcl->top + dy) * lDelta + PELS_TO_BYTES(prcl->left + dx);
  1585. if (c == 1)
  1586. {
  1587. ulWidthHeight |= COMMAND_LAST_PACKET;
  1588. *ulCLStart = ulWidthHeight;
  1589. // Last Command
  1590. break;
  1591. }
  1592. *ulCLStart = ulWidthHeight;
  1593. // Next rectangle.
  1594. prcl++;
  1595. c--;
  1596. ulCLStart += 4;
  1597. }
  1598. }
  1599. CP_MM_BLT_MODE_PACKED(ppdev, pjBase, jExtMode | jHwRop);
  1600. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  1601. CP_MM_DST_X(ppdev, pjBase, xCLOffset);
  1602. }
  1603. else
  1604. {
  1605. //
  1606. // Bottom to Top - Right to Left
  1607. //
  1608. DISPDBG((12,"Bottom to Top - Right to Left"));
  1609. // Setup first set registers
  1610. xCLOffset = prcl->right - 1;
  1611. CP_MM_DST_Y(ppdev, pjBase, prcl->bottom - 1);
  1612. CP_MM_XCNT(ppdev, pjBase, (prcl->right - prcl->left) - 1);
  1613. CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top) - 1);
  1614. CP_MM_SRC_ADDR(ppdev, pjBase, (xyOffset + ((prcl->bottom - 1 + dy) * lDelta) + PELS_TO_BYTES(prcl->right + dx - 1)));
  1615. CP_MM_SRC_XY_PACKED(ppdev, pjBase, 0);
  1616. if (--c)
  1617. {
  1618. // There are more than one rectangle
  1619. prcl++;
  1620. jExtMode |= ENABLE_COMMAND_LIST_PACKED;
  1621. ulCLStart = ppdev->pCommandList;
  1622. ulDstOffset
  1623. |=(ULONG)(((ULONG_PTR)ulCLStart - (ULONG_PTR)ppdev->pjScreen) << 14);
  1624. CP_MM_CL_SWITCH(ppdev);
  1625. while (TRUE)
  1626. {
  1627. // Command List
  1628. // Calculate the destination address and size.
  1629. ulWidthHeight = PACKXY_FAST((prcl->right - prcl->left) - 1,
  1630. (prcl->bottom - prcl->top) - 1);
  1631. ulWidthHeight |= COMMAND_FOURTH_NOTHING;
  1632. // XY
  1633. *(ulCLStart + 1) = PACKXY_FAST(prcl->right - 1, prcl->bottom - 1);
  1634. // Source Start address
  1635. *(ulCLStart + 2) = xyOffset + (prcl->bottom - 1 + dy) * lDelta + PELS_TO_BYTES(prcl->right + dx - 1);
  1636. if (c == 1)
  1637. {
  1638. ulWidthHeight |= COMMAND_LAST_PACKET;
  1639. *ulCLStart = ulWidthHeight;
  1640. // Last Command
  1641. break;
  1642. }
  1643. *ulCLStart = ulWidthHeight;
  1644. // Next rectangle.
  1645. prcl++;
  1646. c--;
  1647. ulCLStart += 4;
  1648. }
  1649. }
  1650. CP_MM_BLT_MODE_PACKED(ppdev, pjBase, jExtMode | jHwRop | DIR_BTRL);
  1651. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  1652. CP_MM_DST_X(ppdev, pjBase, xCLOffset);
  1653. }
  1654. }
  1655. /******************************Public*Routine******************************\
  1656. * VOID vMmXfer1bpp80
  1657. *
  1658. * Low-level routine used to transfer monochrome data to the screen using
  1659. * DWORD writes to the blt engine.
  1660. *
  1661. * This can handle opaque or transparent expansions. It does opaque
  1662. * expansions by drawing the opaque rectangle first and then transparently
  1663. * expands the foreground bits.
  1664. *
  1665. \**************************************************************************/
  1666. VOID vMmXfer1bpp80(
  1667. PDEV* ppdev,
  1668. LONG c, // Count of rectangles, can't be zero
  1669. RECTL* prcl, // List of destination rectangles, in relative
  1670. // coordinates
  1671. ROP4 rop4, // Actually had better be a rop3
  1672. SURFOBJ* psoSrc, // Source surface
  1673. POINTL* pptlSrc, // Original unclipped source point
  1674. RECTL* prclDst, // Original unclipped destination rectangle
  1675. XLATEOBJ* pxlo) // Translate that provides color-expansion information
  1676. {
  1677. ULONG* pulXfer;
  1678. ULONG* pul;
  1679. LONG ix;
  1680. LONG iy;
  1681. LONG cxWidthInBytes;
  1682. BYTE* pjBits;
  1683. POINTL ptlDst;
  1684. POINTL ptlSrc;
  1685. SIZEL sizlDst;
  1686. LONG cxLeftMask;
  1687. LONG cxRightMask;
  1688. ULONG ulDstAddr;
  1689. INT nDwords;
  1690. ULONG ulLeftMask;
  1691. ULONG ulRightMask;
  1692. LONG dx;
  1693. LONG dy;
  1694. BYTE* pjBase = ppdev->pjBase;
  1695. LONG lDelta = ppdev->lDelta;
  1696. LONG lDeltaSrc = psoSrc->lDelta;
  1697. LONG cBpp = ppdev->cBpp;
  1698. ULONG ulFgColor = pxlo->pulXlate[1];
  1699. ULONG ulBgColor = pxlo->pulXlate[0];
  1700. // Since the hardware clipping on some of the Cirrus chips is broken, we
  1701. // do the clipping by rounding out the edges to dword boundaries and then
  1702. // doing the blt transparently. In the event that we want the expansion
  1703. // to be opaque, we do the opaquing blt in advance. One side effect of
  1704. // this is that the destination bits are no longer valid for processing
  1705. // the rop. This could probably be optimized by doing the edges seperately
  1706. // and then doing the middle section in one pass. However, this is
  1707. // complicated by a 5434 bug that breaks blts less than 10 pixels wide.
  1708. ASSERTDD(c > 0, "Can't handle zero rectangles");
  1709. ASSERTDD(((rop4 & 0xff00) == 0xcc00), "Expected foreground rop of 0xcc");
  1710. //
  1711. // The src-dst delta will be the same for all rectangles
  1712. //
  1713. dx = pptlSrc->x - prclDst->left;
  1714. dy = pptlSrc->y - prclDst->top;
  1715. #if 0
  1716. if (cBpp == 1)
  1717. {
  1718. ulFgColor = (ulFgColor << 8) | (ulFgColor & 0xff);
  1719. ulBgColor = (ulBgColor << 8) | (ulBgColor & 0xff);
  1720. ulFgColor = (ulFgColor << 16) | (ulFgColor & 0xffff);
  1721. ulBgColor = (ulBgColor << 16) | (ulBgColor & 0xffff);
  1722. }
  1723. else if (cBpp == 2)
  1724. {
  1725. ulFgColor = (ulFgColor << 16) | (ulFgColor & 0xffff);
  1726. ulBgColor = (ulBgColor << 16) | (ulBgColor & 0xffff);
  1727. }
  1728. #endif
  1729. pulXfer = ppdev->pulXfer;
  1730. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  1731. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  1732. CP_MM_SRC_XY_PACKED(ppdev, pjBase, 0);
  1733. if (rop4 != 0xCCAA)
  1734. {
  1735. LONG lCnt = c;
  1736. RECTL* prclTmp = prcl;
  1737. DWORD jHwBgRop = gajHwPackedMixFromRop2[rop4 & 0xf];
  1738. CP_MM_FG_COLOR(ppdev, pjBase, ulBgColor);
  1739. CP_MM_BLT_MODE_PACKED(ppdev, pjBase, ENABLE_XY_POSITION_PACKED |
  1740. ENABLE_SOLID_FILL_PACKED |
  1741. jHwBgRop |
  1742. ppdev->jModeColor |
  1743. ENABLE_COLOR_EXPAND |
  1744. ENABLE_8x8_PATTERN_COPY);
  1745. CP_MM_DST_ADDR(ppdev, pjBase, 0);
  1746. do
  1747. {
  1748. // calculate the size of the blt
  1749. ptlDst.x = prclTmp->left;
  1750. ptlDst.y = prclTmp->top;
  1751. //
  1752. // Fill the background rectangle with the background color
  1753. //
  1754. // Set the dest addresses
  1755. ulDstAddr = (ptlDst.y * lDelta) + PELS_TO_BYTES(ptlDst.x);
  1756. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  1757. CP_MM_XCNT(ppdev, pjBase, prclTmp->right - ptlDst.x - 1);
  1758. CP_MM_YCNT(ppdev, pjBase, prclTmp->bottom - ptlDst.y - 1);
  1759. CP_MM_DST_Y(ppdev, pjBase, ptlDst.y);
  1760. CP_MM_DST_X(ppdev, pjBase, ptlDst.x);
  1761. prclTmp++;
  1762. } while (--lCnt != 0);
  1763. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  1764. }
  1765. CP_MM_FG_COLOR(ppdev, pjBase, ulFgColor);
  1766. CP_MM_BG_COLOR(ppdev, pjBase, ~ulFgColor);
  1767. // CP_IO_XPAR_COLOR(ppdev, pjBase, ~ulFgColor);
  1768. CP_MM_BLT_MODE_PACKED(ppdev, pjBase, ENABLE_XY_POSITION_PACKED |
  1769. ENABLE_CLIP_RECT_PACKED |
  1770. CL_PACKED_SRC_COPY |
  1771. ppdev->jModeColor |
  1772. ENABLE_COLOR_EXPAND |
  1773. ENABLE_TRANSPARENCY_COMPARE |
  1774. SRC_CPU_DATA |
  1775. SOURCE_GRANULARITY_PACKED);
  1776. CP_MM_DST_ADDR(ppdev, pjBase, 0);
  1777. do
  1778. {
  1779. // calculate the size of the blt
  1780. ptlDst.x = prcl->left;
  1781. ptlDst.y = prcl->top;
  1782. sizlDst.cx = prcl->right - ptlDst.x;
  1783. sizlDst.cy = prcl->bottom - ptlDst.y;
  1784. // calculate the number of dwords per scan line
  1785. ptlSrc.x = prcl->left + dx;
  1786. ptlSrc.y = prcl->top + dy;
  1787. // Floor the source.
  1788. // Extend the width by the amount required to floor to a dword boundary.
  1789. // Set the size of the left mask.
  1790. // Floor the dest, so it aligns with the floored source.
  1791. if ((cxLeftMask = (ptlSrc.x & 31)))
  1792. {
  1793. sizlDst.cx += cxLeftMask;
  1794. ptlSrc.x &= ~31;
  1795. ptlDst.x -= cxLeftMask;
  1796. }
  1797. // Calculate the width in Bytes
  1798. cxWidthInBytes = (sizlDst.cx + 7) >> 3;
  1799. // Calculate the address of the source bitmap
  1800. // This is to a byte boundary.
  1801. pjBits = (PBYTE) psoSrc->pvScan0;
  1802. pjBits += ptlSrc.y * lDeltaSrc;
  1803. pjBits += ptlSrc.x >> 3;
  1804. ASSERTDD((((ULONG_PTR)pjBits & 0x03) == 0),
  1805. "pjBits not DWORD aligned like it should be");
  1806. //
  1807. // Blt the 1 bpp bitmap
  1808. //
  1809. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  1810. // set clipping register
  1811. CP_MM_CLIP_ULXY(ppdev, pjBase, prcl->left, prcl->top);
  1812. CP_MM_CLIP_LRXY(ppdev, pjBase, prcl->right - 1, prcl->bottom - 1);
  1813. CP_MM_DST_Y(ppdev, pjBase, ptlDst.y);
  1814. CP_MM_XCNT(ppdev, pjBase, sizlDst.cx - 1);
  1815. CP_MM_YCNT(ppdev, pjBase, sizlDst.cy - 1);
  1816. CP_MM_DST_X(ppdev, pjBase, ptlDst.x);
  1817. //
  1818. // Transfer the host bitmap.
  1819. //
  1820. vImageTransfer(ppdev, pjBits, lDeltaSrc, cxWidthInBytes, sizlDst.cy);
  1821. prcl++;
  1822. } while (--c != 0);
  1823. }
  1824. /******************************Public*Routine******************************\
  1825. * VOID vMmXferNative80
  1826. *
  1827. * Transfers a bitmap that is the same color depth as the display to
  1828. * the screen via the data transfer register, with no translation.
  1829. *
  1830. \**************************************************************************/
  1831. VOID vMmXferNative80(
  1832. PDEV* ppdev,
  1833. LONG c, // Count of rectangles, can't be zero
  1834. RECTL* prcl, // Array of relative coordinates destination rectangles
  1835. ULONG rop4, // rop4
  1836. SURFOBJ* psoSrc, // Source surface
  1837. POINTL* pptlSrc, // Original unclipped source point
  1838. RECTL* prclDst, // Original unclipped destination rectangle
  1839. XLATEOBJ* pxlo) // Not used
  1840. {
  1841. LONG dx;
  1842. LONG dy;
  1843. LONG cx;
  1844. LONG cy;
  1845. LONG lSrcDelta;
  1846. BYTE* pjSrcScan0;
  1847. BYTE* pjSrc;
  1848. LONG cjSrc;
  1849. BYTE* pjBase = ppdev->pjBase;
  1850. LONG lDelta = ppdev->lDelta;
  1851. DWORD jHwRop = gajHwPackedMixFromRop2[rop4 & 0x0F];
  1852. DWORD jExtMode= ENABLE_XY_POSITION_PACKED |
  1853. SRC_CPU_DATA |
  1854. ppdev->jModeColor;
  1855. ASSERTDD((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL),
  1856. "Can handle trivial xlate only");
  1857. ASSERTDD(psoSrc->iBitmapFormat == ppdev->iBitmapFormat,
  1858. "Source must be same color depth as screen");
  1859. ASSERTDD(c > 0, "Can't handle zero rectangles");
  1860. ASSERTDD(((rop4 & 0xff00) >> 8) == (rop4 & 0xff),
  1861. "Expect only a rop2");
  1862. dx = pptlSrc->x - prclDst->left;
  1863. dy = pptlSrc->y - prclDst->top; // Add to destination to get source
  1864. lSrcDelta = psoSrc->lDelta;
  1865. pjSrcScan0 = psoSrc->pvScan0;
  1866. //
  1867. // Make sure we can write to the video registers.
  1868. //
  1869. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  1870. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  1871. CP_MM_BLT_MODE_PACKED(ppdev, pjBase, jHwRop | jExtMode);
  1872. CP_MM_SRC_XY_PACKED(ppdev, pjBase, 0);
  1873. while(TRUE)
  1874. {
  1875. cx = prcl->right - prcl->left;
  1876. cy = prcl->bottom - prcl->top;
  1877. cjSrc = PELS_TO_BYTES(cx);
  1878. pjSrc = pjSrcScan0 + (prcl->top + dy) * lSrcDelta
  1879. + (PELS_TO_BYTES(prcl->left + dx));
  1880. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  1881. CP_MM_XCNT(ppdev, pjBase, cx - 1);
  1882. CP_MM_YCNT(ppdev, pjBase, cy - 1);
  1883. CP_MM_DST_Y(ppdev, pjBase, prcl->top);
  1884. CP_MM_DST_ADDR(ppdev, pjBase, 0);
  1885. CP_MM_DST_X(ppdev, pjBase, prcl->left);
  1886. vImageTransfer(ppdev, pjSrc, lSrcDelta, cjSrc, cy);
  1887. if (--c == 0)
  1888. break;
  1889. prcl++;
  1890. }
  1891. }
  1892. #endif // endif D5480