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.

1090 lines
35 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: blt.c
  3. *
  4. * Contains the low-level in/out blt functions.
  5. *
  6. * Hopefully, if you're basing your display driver on this code, to
  7. * support all of DrvBitBlt and DrvCopyBits, you'll only have to implement
  8. * the following routines. You shouldn't have to modify much in
  9. * 'bitblt.c'. I've tried to make these routines as few, modular, simple,
  10. * and efficient as I could, while still accelerating as many calls as
  11. * possible that would be cost-effective in terms of performance wins
  12. * versus size and effort.
  13. *
  14. * Note: In the following, 'relative' coordinates refers to coordinates
  15. * that haven't yet had the offscreen bitmap (DFB) offset applied.
  16. * 'Absolute' coordinates have had the offset applied. For example,
  17. * we may be told to blt to (1, 1) of the bitmap, but the bitmap may
  18. * be sitting in offscreen memory starting at coordinate (0, 768) --
  19. * (1, 1) would be the 'relative' start coordinate, and (1, 769)
  20. * would be the 'absolute' start coordinate'.
  21. *
  22. * Copyright (c) 1992-1995 Microsoft Corporation
  23. *
  24. \**************************************************************************/
  25. #include "precomp.h"
  26. /******************************Public*Table********************************\
  27. * BYTE gaulP9000OpaqueFromRop2[]
  28. *
  29. * Convert an opaque Rop2 to a P9000 minterm.
  30. *
  31. \**************************************************************************/
  32. #define P9000_P ((P9000_S & P9000_F) | (~P9000_S & P9000_B))
  33. #define P9000_DSo (P9000_S | P9000_D)
  34. #define P9000_DSna (~P9000_S & P9000_D)
  35. ULONG gaulP9000OpaqueFromRop2[] = {
  36. (0 ) & 0xFFFF, // 0 -- 0
  37. (~(P9000_P | P9000_D)) & 0xFFFF, // 1 -- DPon
  38. (~P9000_P & P9000_D ) & 0xFFFF, // 2 -- DPna
  39. (~P9000_P ) & 0xFFFF, // 3 -- Pn
  40. (~P9000_D & P9000_P ) & 0xFFFF, // 4 -- PDna
  41. (~P9000_D ) & 0xFFFF, // 5 -- Dn
  42. (P9000_D ^ P9000_P ) & 0xFFFF, // 6 -- DPx
  43. (~(P9000_P & P9000_D)) & 0xFFFF, // 7 -- DPan
  44. (P9000_P & P9000_D ) & 0xFFFF, // 8 -- DPa
  45. (~(P9000_P ^ P9000_D)) & 0xFFFF, // 9 -- DPxn
  46. (P9000_D ) & 0xFFFF, // 10 -- D
  47. (~P9000_P | P9000_D ) & 0xFFFF, // 11 -- DPno
  48. (P9000_P ) & 0xFFFF, // 12 -- P
  49. (~P9000_D | P9000_P ) & 0xFFFF, // 13 -- PDno
  50. (P9000_P | P9000_D ) & 0xFFFF, // 14 -- DPo
  51. (~0 ) & 0xFFFF, // 15 -- 1
  52. };
  53. /******************************Public*Table********************************\
  54. * BYTE gaulP9000TransparentFromRop2[]
  55. *
  56. * Convert a transparent Rop2 to a P9000 minterm.
  57. *
  58. \**************************************************************************/
  59. ULONG gaulP9000TransparentFromRop2[] = {
  60. (((0 ) & P9000_DSo) | P9000_DSna) & 0xFFFF, // 0 -- 0
  61. (((~(P9000_P | P9000_D)) & P9000_DSo) | P9000_DSna) & 0xFFFF, // 1 -- DPon
  62. (((~P9000_P & P9000_D ) & P9000_DSo) | P9000_DSna) & 0xFFFF, // 2 -- DPna
  63. (((~P9000_P ) & P9000_DSo) | P9000_DSna) & 0xFFFF, // 3 -- Pn
  64. (((~P9000_D & P9000_P ) & P9000_DSo) | P9000_DSna) & 0xFFFF, // 4 -- PDna
  65. (((~P9000_D ) & P9000_DSo) | P9000_DSna) & 0xFFFF, // 5 -- Dn
  66. (((P9000_D ^ P9000_P ) & P9000_DSo) | P9000_DSna) & 0xFFFF, // 6 -- DPx
  67. (((~(P9000_P & P9000_D)) & P9000_DSo) | P9000_DSna) & 0xFFFF, // 7 -- DPan
  68. (((P9000_P & P9000_D ) & P9000_DSo) | P9000_DSna) & 0xFFFF, // 8 -- DPa
  69. (((~(P9000_P ^ P9000_D)) & P9000_DSo) | P9000_DSna) & 0xFFFF, // 9 -- DPxn
  70. (((P9000_D ) & P9000_DSo) | P9000_DSna) & 0xFFFF, // 10 -- D
  71. (((~P9000_P | P9000_D ) & P9000_DSo) | P9000_DSna) & 0xFFFF, // 11 -- DPno
  72. (((P9000_P ) & P9000_DSo) | P9000_DSna) & 0xFFFF, // 12 -- P
  73. (((~P9000_D | P9000_P ) & P9000_DSo) | P9000_DSna) & 0xFFFF, // 13 -- PDno
  74. (((P9000_P | P9000_D ) & P9000_DSo) | P9000_DSna) & 0xFFFF, // 14 -- DPo
  75. (((~0 ) & P9000_DSo) | P9000_DSna) & 0xFFFF, // 15 -- 1
  76. };
  77. /******************************Public*Routine******************************\
  78. * VOID vFillSolid
  79. *
  80. * Fills a list of rectangles with a solid colour.
  81. *
  82. \**************************************************************************/
  83. VOID vFillSolid( // Type FNFILL
  84. PDEV* ppdev,
  85. LONG c, // Can't be zero
  86. RECTL* prcl, // List of rectangles to be filled, in relative
  87. // coordinates
  88. ULONG ulHwMix, // Hardware mix mode
  89. RBRUSH_COLOR rbc, // Drawing colour is rbc.iSolidColor
  90. POINTL* pptlBrush) // Not used
  91. {
  92. BYTE* pjBase;
  93. ASSERTDD(c > 0, "Can't handle zero rectangles");
  94. pjBase = ppdev->pjBase;
  95. CP_METARECT(ppdev, pjBase, prcl->left, prcl->top);
  96. CP_METARECT(ppdev, pjBase, prcl->right, prcl->bottom);
  97. CP_WAIT(ppdev, pjBase);
  98. if (P9000(ppdev))
  99. {
  100. CP_BACKGROUND(ppdev, pjBase, rbc.iSolidColor);
  101. CP_RASTER(ppdev, pjBase, ulHwMix);
  102. }
  103. else
  104. {
  105. CP_COLOR0(ppdev, pjBase, rbc.iSolidColor);
  106. CP_RASTER(ppdev, pjBase, ulHwMix & 0xff);
  107. }
  108. CP_START_QUAD(ppdev, pjBase);
  109. while (prcl++, --c)
  110. {
  111. CP_METARECT(ppdev, pjBase, prcl->left, prcl->top);
  112. CP_METARECT(ppdev, pjBase, prcl->right, prcl->bottom);
  113. CP_START_QUAD_WAIT(ppdev, pjBase);
  114. }
  115. }
  116. /******************************Public*Routine******************************\
  117. * VOID vSlowPatRealize
  118. *
  119. * This routine transfers an 8x8 pattern to off-screen display memory, and
  120. * duplicates it to make a 64x64 cached realization which is then used by
  121. * vFillPatSlow as the basic building block for doing 'slow' pattern output
  122. * via repeated screen-to-screen blts.
  123. *
  124. \**************************************************************************/
  125. VOID vSlowPatRealize(
  126. PDEV* ppdev,
  127. RBRUSH* prb) // Points to brush realization structure
  128. {
  129. BYTE* pjBase;
  130. LONG cjPel;
  131. BRUSHENTRY* pbe;
  132. LONG iBrushCache;
  133. LONG x;
  134. LONG y;
  135. ULONG* pulSrc;
  136. LONG i;
  137. ASSERTDD(!(prb->fl & (RBRUSH_2COLOR | RBRUSH_4COLOR)),
  138. "Shouldn't realize hardware brushes");
  139. pbe = prb->apbe[IBOARD(ppdev)];
  140. if ((pbe == NULL) || (pbe->prbVerify != prb))
  141. {
  142. // We have to allocate a new off-screen cache brush entry for
  143. // the brush:
  144. iBrushCache = ppdev->iBrushCache;
  145. pbe = &ppdev->abe[iBrushCache];
  146. iBrushCache++;
  147. if (iBrushCache >= ppdev->cBrushCache)
  148. iBrushCache = 0;
  149. ppdev->iBrushCache = iBrushCache;
  150. // Update our links:
  151. pbe->prbVerify = prb;
  152. prb->apbe[IBOARD(ppdev)] = pbe;
  153. }
  154. pjBase = ppdev->pjBase;
  155. cjPel = ppdev->cjPel;
  156. // Load some pointer variables onto the stack, so that we don't have
  157. // to keep dereferencing their pointers:
  158. x = pbe->x;
  159. y = pbe->y;
  160. CP_ABS_XY0(ppdev, pjBase, x * cjPel, y);
  161. CP_ABS_XY1(ppdev, pjBase, x * cjPel, y);
  162. CP_ABS_XY2(ppdev, pjBase, (x + 8) * cjPel, y);
  163. CP_ABS_Y3(ppdev, pjBase, 1);
  164. pulSrc = (ULONG*) &prb->aulPattern[0];
  165. CP_WAIT(ppdev, pjBase);
  166. CP_RASTER(ppdev, pjBase, P9000(ppdev) ? P9000_S : P9100_S);
  167. for (i = 4 * cjPel; i != 0; i--)
  168. {
  169. CP_PIXEL8(ppdev, pjBase, *(pulSrc));
  170. CP_PIXEL8(ppdev, pjBase, *(pulSrc + 1));
  171. CP_PIXEL8(ppdev, pjBase, *(pulSrc + 2));
  172. CP_PIXEL8(ppdev, pjBase, *(pulSrc + 3));
  173. pulSrc += 4;
  174. }
  175. // �����������������Ŀ
  176. // �0�1�2�3 �4 � We now have an 8x8 colour-expanded copy of
  177. // �����������������Ĵ the pattern sitting in off-screen memory,
  178. // �5 � represented here by square '0'.
  179. // �����������������Ĵ
  180. // �6 � We're now going to expand the pattern to
  181. // �����������������Ĵ 72x72 by repeatedly copying larger rectangles
  182. // �7 � in the indicated order.
  183. // � �
  184. // � �
  185. // �����������������Ĵ
  186. // �8 �
  187. // � �
  188. // � �
  189. // � �
  190. // � �
  191. // �������������������
  192. // Copy '1':
  193. CP_ABS_XY1(ppdev, pjBase, x + 7, y + 7);
  194. CP_ABS_XY3(ppdev, pjBase, x + 15, y + 7);
  195. CP_WAIT(ppdev, pjBase);
  196. CP_START_BLT(ppdev, pjBase);
  197. // Copy '2':
  198. CP_ABS_X2(ppdev, pjBase, x + 16);
  199. CP_ABS_X3(ppdev, pjBase, x + 23);
  200. CP_START_BLT_WAIT(ppdev, pjBase);
  201. // Copy '3':
  202. CP_ABS_X1(ppdev, pjBase, x + 15);
  203. CP_ABS_X2(ppdev, pjBase, x + 24);
  204. CP_ABS_X3(ppdev, pjBase, x + 39);
  205. CP_START_BLT_WAIT(ppdev, pjBase);
  206. // Copy '4':
  207. CP_ABS_X1(ppdev, pjBase, x + 31);
  208. CP_ABS_X2(ppdev, pjBase, x + 40);
  209. CP_ABS_X3(ppdev, pjBase, x + 71);
  210. CP_START_BLT_WAIT(ppdev, pjBase);
  211. // Copy '5':
  212. CP_ABS_XY1(ppdev, pjBase, x + 71, y + 7);
  213. CP_ABS_XY2(ppdev, pjBase, x, y + 8);
  214. CP_ABS_XY3(ppdev, pjBase, x + 71, y + 15);
  215. CP_START_BLT_WAIT(ppdev, pjBase);
  216. // Copy '6':
  217. CP_ABS_Y2(ppdev, pjBase, y + 16);
  218. CP_ABS_Y3(ppdev, pjBase, y + 23);
  219. CP_START_BLT_WAIT(ppdev, pjBase);
  220. // Copy '7':
  221. CP_ABS_Y1(ppdev, pjBase, y + 15);
  222. CP_ABS_Y2(ppdev, pjBase, y + 24);
  223. CP_ABS_Y3(ppdev, pjBase, y + 39);
  224. CP_START_BLT_WAIT(ppdev, pjBase);
  225. // Copy '8':
  226. CP_ABS_Y1(ppdev, pjBase, y + 31);
  227. CP_ABS_Y2(ppdev, pjBase, y + 40);
  228. CP_ABS_Y3(ppdev, pjBase, y + 71);
  229. CP_START_BLT_WAIT(ppdev, pjBase);
  230. }
  231. /******************************Public*Routine******************************\
  232. * VOID vFillSlowPat
  233. *
  234. \**************************************************************************/
  235. VOID vFillSlowPat( // Type FNFILL
  236. PDEV* ppdev,
  237. LONG c, // Can't be zero
  238. RECTL* prcl, // List of rectangles to be filled, in relative
  239. // coordinates
  240. ULONG ulHwMix, // Hardware mix mode
  241. RBRUSH_COLOR rbc, // rbc.prb points to brush realization structure
  242. POINTL* pptlBrush) // Pattern alignment
  243. {
  244. BYTE* pjBase;
  245. BOOL bExponential;
  246. ULONG ulRaster;
  247. LONG xBrush;
  248. LONG yBrush;
  249. LONG xSrc;
  250. LONG ySrc;
  251. LONG x;
  252. LONG y;
  253. LONG xFrom;
  254. LONG yFrom;
  255. LONG cxToGo;
  256. LONG cyToGo;
  257. LONG cxThis;
  258. LONG cyThis;
  259. LONG xOrg;
  260. LONG yOrg;
  261. LONG cyOriginal;
  262. LONG yOriginal;
  263. LONG xOriginal;
  264. BRUSHENTRY* pbe; // Pointer to brush entry data, which is used
  265. // for keeping track of the location and status
  266. // of the pattern bits cached in off-screen
  267. // memory
  268. if (rbc.prb->apbe[IBOARD(ppdev)]->prbVerify != rbc.prb)
  269. {
  270. vSlowPatRealize(ppdev, rbc.prb);
  271. }
  272. pjBase = ppdev->pjBase;
  273. // We special case PATCOPY mixes because we can implement
  274. // an exponential fill: every blt will double the size of
  275. // the current rectangle by using the portion of the pattern
  276. // that has already been done for this rectangle as the source.
  277. //
  278. // Note that there's no point in also checking for BLACK
  279. // or WHITE because those will be taken care of by the
  280. // solid fill routines, and I can't be bothered to check for
  281. // NOTCOPYPEN:
  282. bExponential = (ulHwMix == 0xf0f0);
  283. // Convert the rop from a Rop3 between P and D to the corresponding
  284. // Rop3 between S and D:
  285. ulRaster = (ulHwMix & 0x3C) >> 2;
  286. ulRaster |= (ulRaster << 4);
  287. if (P9000(ppdev))
  288. {
  289. // Make the Rop3 into a true P9000 minterm:
  290. ulRaster |= (ulRaster << 8);
  291. }
  292. // Note that since we do our brush alignment calculations in
  293. // relative coordinates, we should keep the brush origin in
  294. // relative coordinates as well:
  295. xOrg = pptlBrush->x;
  296. yOrg = pptlBrush->y;
  297. pbe = rbc.prb->apbe[IBOARD(ppdev)];
  298. xBrush = pbe->x;
  299. yBrush = pbe->y;
  300. do {
  301. x = prcl->left;
  302. y = prcl->top;
  303. xSrc = xBrush + ((x - xOrg) & 7);
  304. ySrc = yBrush + ((y - yOrg) & 7);
  305. cxToGo = prcl->right - x;
  306. cyToGo = prcl->bottom - y;
  307. if ((cxToGo <= SLOW_BRUSH_DIMENSION) &&
  308. (cyToGo <= SLOW_BRUSH_DIMENSION))
  309. {
  310. CP_ABS_XY0(ppdev, pjBase, xSrc, ySrc);
  311. CP_ABS_XY1(ppdev, pjBase, xSrc + cxToGo - 1, ySrc + cyToGo - 1);
  312. CP_XY2(ppdev, pjBase, x, y);
  313. CP_XY3(ppdev, pjBase, x + cxToGo - 1, y + cyToGo - 1);
  314. CP_WAIT(ppdev, pjBase);
  315. CP_RASTER(ppdev, pjBase, ulRaster);
  316. CP_START_BLT(ppdev, pjBase);
  317. }
  318. else if (bExponential)
  319. {
  320. cyThis = SLOW_BRUSH_DIMENSION;
  321. cyToGo -= cyThis;
  322. if (cyToGo < 0)
  323. cyThis += cyToGo;
  324. cxThis = SLOW_BRUSH_DIMENSION;
  325. cxToGo -= cxThis;
  326. if (cxToGo < 0)
  327. cxThis += cxToGo;
  328. CP_ABS_XY0(ppdev, pjBase, xSrc, ySrc);
  329. CP_ABS_XY1(ppdev, pjBase, xSrc + cxThis - 1, ySrc + cyThis - 1);
  330. CP_XY2(ppdev, pjBase, x, y);
  331. CP_XY3(ppdev, pjBase, x + cxThis - 1, y + cyThis - 1);
  332. CP_WAIT(ppdev, pjBase);
  333. CP_RASTER(ppdev, pjBase, ulRaster);
  334. CP_START_BLT(ppdev, pjBase);
  335. CP_XY0(ppdev, pjBase, x, y);
  336. xOriginal = x;
  337. x += cxThis;
  338. y += cyThis;
  339. while (cxToGo > 0)
  340. {
  341. // First, expand out to the right, doubling our size
  342. // each time:
  343. xFrom = x;
  344. cxToGo -= cxThis;
  345. if (cxToGo < 0)
  346. {
  347. cxThis += cxToGo;
  348. xFrom += cxToGo;
  349. }
  350. CP_XY1(ppdev, pjBase, xFrom - 1, y - 1);
  351. CP_X2(ppdev, pjBase, x);
  352. CP_X3(ppdev, pjBase, x + cxThis - 1);
  353. CP_START_BLT_WAIT(ppdev, pjBase);
  354. x += cxThis;
  355. cxThis *= 2;
  356. }
  357. while (cyToGo > 0)
  358. {
  359. // Now do the same thing vertically:
  360. yFrom = y;
  361. cyToGo -= cyThis;
  362. if (cyToGo < 0)
  363. {
  364. cyThis += cyToGo;
  365. yFrom += cyToGo;
  366. }
  367. CP_XY1(ppdev, pjBase, x - 1, yFrom - 1);
  368. CP_XY2(ppdev, pjBase, xOriginal, y);
  369. CP_Y3(ppdev, pjBase, y + cyThis - 1);
  370. CP_START_BLT_WAIT(ppdev, pjBase);
  371. y += cyThis;
  372. cyThis *= 2;
  373. }
  374. }
  375. else
  376. {
  377. // We handle arbitrary mixes simply by repeatedly tiling
  378. // our cached pattern over the entire rectangle:
  379. CP_ABS_XY0(ppdev, pjBase, xSrc, ySrc);
  380. CP_WAIT(ppdev, pjBase);
  381. CP_RASTER(ppdev, pjBase, ulRaster);
  382. cyOriginal = cyToGo; // Have to remember for later...
  383. yOriginal = y;
  384. do {
  385. cxThis = SLOW_BRUSH_DIMENSION;
  386. cxToGo -= cxThis;
  387. if (cxToGo < 0)
  388. cxThis += cxToGo;
  389. cyToGo = cyOriginal; // Have to reset for each new column
  390. y = yOriginal;
  391. do {
  392. cyThis = SLOW_BRUSH_DIMENSION;
  393. cyToGo -= cyThis;
  394. if (cyToGo < 0)
  395. cyThis += cyToGo;
  396. CP_ABS_XY1(ppdev, pjBase, xSrc + cxThis - 1,
  397. ySrc + cyThis - 1);
  398. CP_XY2(ppdev, pjBase, x, y);
  399. CP_XY3(ppdev, pjBase, x + cxThis - 1,
  400. y + cyThis - 1);
  401. CP_START_BLT_WAIT(ppdev, pjBase);
  402. y += cyThis;
  403. } while (cyToGo > 0);
  404. x += cxThis; // Get ready for next column
  405. } while (cxToGo > 0);
  406. }
  407. prcl++;
  408. } while (--c != 0);
  409. }
  410. /******************************Public*Routine******************************\
  411. * VOID vFillPat
  412. *
  413. \**************************************************************************/
  414. VOID vFillPat( // Type FNFILL
  415. PDEV* ppdev,
  416. LONG c, // Can't be zero
  417. RECTL* prcl, // List of rectangles to be filled, in relative
  418. // coordinates
  419. ULONG ulHwMix, // Hardware mix mode
  420. RBRUSH_COLOR rbc, // rbc.prb points to brush realization structure
  421. POINTL* pptlBrush) // Pattern alignment
  422. {
  423. BYTE* pjBase;
  424. LONG i;
  425. ULONG* pulPattern;
  426. ULONG ulPattern;
  427. ASSERTDD(((ulHwMix >> 8) == (ulHwMix & 0xff)) ||
  428. ((ulHwMix & 0xff00) == 0xaa00),
  429. "This routine handles only opaque or transparent mixes");
  430. if (rbc.prb->fl & (RBRUSH_2COLOR | RBRUSH_4COLOR))
  431. {
  432. // Hardware pattern
  433. pjBase = ppdev->pjBase;
  434. CP_METARECT(ppdev, pjBase, prcl->left, prcl->top);
  435. CP_METARECT(ppdev, pjBase, prcl->right, prcl->bottom);
  436. CP_WAIT(ppdev, pjBase);
  437. if (P9000(ppdev))
  438. {
  439. CP_PATTERN_ORGX(ppdev, pjBase, ppdev->xOffset + pptlBrush->x);
  440. CP_PATTERN_ORGY(ppdev, pjBase, ppdev->yOffset + pptlBrush->y);
  441. CP_BACKGROUND(ppdev, pjBase, rbc.prb->ulColor[0]);
  442. CP_FOREGROUND(ppdev, pjBase, rbc.prb->ulColor[1]);
  443. pulPattern = &rbc.prb->aulPattern[0];
  444. for (i = 0; i < 4; i++)
  445. {
  446. ulPattern = *pulPattern++;
  447. CP_PATTERN(ppdev, pjBase, i, ulPattern);
  448. CP_PATTERN(ppdev, pjBase, i + 4, ulPattern);
  449. }
  450. if (((ulHwMix >> 8) & 0xff) == (ulHwMix & 0xff))
  451. {
  452. ulHwMix = gaulP9000OpaqueFromRop2[(ulHwMix & 0x3C) >> 2];
  453. CP_RASTER(ppdev, pjBase, ulHwMix | P9000_ENABLE_PATTERN);
  454. }
  455. else
  456. {
  457. ulHwMix = gaulP9000TransparentFromRop2[(ulHwMix & 0x3C) >> 2];
  458. CP_RASTER(ppdev, pjBase, ulHwMix | P9000_ENABLE_PATTERN);
  459. }
  460. }
  461. else
  462. {
  463. CP_PATTERN_ORGX(ppdev, pjBase, -(ppdev->xOffset + pptlBrush->x));
  464. CP_PATTERN_ORGY(ppdev, pjBase, -(ppdev->yOffset + pptlBrush->y));
  465. CP_COLOR0_FAST(ppdev, pjBase, rbc.prb->ulColor[0]);
  466. CP_COLOR1_FAST(ppdev, pjBase, rbc.prb->ulColor[1]);
  467. CP_PATTERN(ppdev, pjBase, 0, rbc.prb->aulPattern[0]);
  468. CP_PATTERN(ppdev, pjBase, 1, rbc.prb->aulPattern[1]);
  469. CP_PATTERN(ppdev, pjBase, 2, rbc.prb->aulPattern[2]);
  470. CP_PATTERN(ppdev, pjBase, 3, rbc.prb->aulPattern[3]);
  471. if (rbc.prb->fl & RBRUSH_2COLOR)
  472. {
  473. if (((ulHwMix >> 8) & 0xff) == (ulHwMix & 0xff))
  474. {
  475. CP_RASTER(ppdev, pjBase, (ulHwMix & 0xff)
  476. | P9100_ENABLE_PATTERN);
  477. }
  478. else
  479. {
  480. CP_RASTER(ppdev, pjBase, (ulHwMix & 0xff)
  481. | P9100_ENABLE_PATTERN | P9100_TRANSPARENT_PATTERN);
  482. }
  483. }
  484. else
  485. {
  486. CP_COLOR2_FAST(ppdev, pjBase, rbc.prb->ulColor[2]);
  487. CP_COLOR3_FAST(ppdev, pjBase, rbc.prb->ulColor[3]);
  488. CP_RASTER(ppdev, pjBase, (ulHwMix & 0xff)
  489. | P9100_ENABLE_PATTERN | P9100_FOUR_COLOR_PATTERN);
  490. }
  491. }
  492. CP_START_QUAD(ppdev, pjBase);
  493. while (prcl++, --c)
  494. {
  495. CP_METARECT(ppdev, pjBase, prcl->left, prcl->top);
  496. CP_METARECT(ppdev, pjBase, prcl->right, prcl->bottom);
  497. CP_START_QUAD_WAIT(ppdev, pjBase);
  498. }
  499. }
  500. else
  501. {
  502. vFillSlowPat(ppdev, c, prcl, ulHwMix, rbc, pptlBrush);
  503. }
  504. }
  505. /******************************Public*Routine******************************\
  506. * VOID vXfer1bpp
  507. *
  508. * This routine colour expands a monochrome bitmap.
  509. *
  510. \**************************************************************************/
  511. VOID vXfer1bpp( // Type FNXFER
  512. PDEV* ppdev,
  513. LONG c, // Count of rectangles, can't be zero
  514. RECTL* prcl, // List of destination rectangles, in relative
  515. // coordinates
  516. ULONG ulHwMix, // Foreground and background hardware mix
  517. SURFOBJ* psoSrc, // Source surface
  518. POINTL* pptlSrc, // Original unclipped source point
  519. RECTL* prclDst, // Original unclipped destination rectangle
  520. XLATEOBJ* pxlo) // Translate that provides colour-expansion information
  521. {
  522. BYTE* pjBase;
  523. LONG dx;
  524. LONG dy;
  525. LONG lSrcDelta;
  526. BYTE* pjSrcScan0;
  527. ULONG* pulXlate;
  528. LONG xLeft;
  529. LONG xRight;
  530. LONG yTop;
  531. LONG cyScan;
  532. LONG xBias;
  533. LONG culScan;
  534. LONG lSrcSkip;
  535. ULONG* pulSrc;
  536. LONG cRem;
  537. LONG i;
  538. ASSERTDD(((ulHwMix >> 8) & 0xff) == (ulHwMix & 0xff),
  539. "Expected only an opaquing rop");
  540. pjBase = ppdev->pjBase;
  541. dx = pptlSrc->x - prclDst->left;
  542. dy = pptlSrc->y - prclDst->top;
  543. lSrcDelta = psoSrc->lDelta;
  544. pjSrcScan0 = psoSrc->pvScan0;
  545. do {
  546. xLeft = prcl->left;
  547. xRight = prcl->right;
  548. yTop = prcl->top;
  549. xBias = (xLeft + dx) & 31;
  550. xLeft -= xBias;
  551. CP_XY1(ppdev, pjBase, xLeft, yTop);
  552. CP_X0(ppdev, pjBase, xLeft);
  553. CP_X2(ppdev, pjBase, xRight);
  554. CP_ABS_Y3(ppdev, pjBase, 1);
  555. culScan = ((xRight - xLeft) >> 5);
  556. cRem = ((xRight - xLeft) & 31) - 1;
  557. if (cRem < 0)
  558. {
  559. culScan--;
  560. cRem = 31;
  561. }
  562. pulSrc = (ULONG*) (pjSrcScan0 + (yTop + dy) * lSrcDelta
  563. + ((xLeft + dx) >> 3));
  564. lSrcSkip = lSrcDelta - (culScan << 2);
  565. cyScan = (prcl->bottom - yTop);
  566. CP_WAIT(ppdev, pjBase);
  567. CP_WLEFT(ppdev, pjBase, prcl->left);
  568. // The following three accelerator states are invariant to this
  569. // loop, but we set them each time anyway because we expect
  570. // usually to have only to do one iteration of this loop, and this
  571. // state must to be set after doing a CP_WAIT, which we want to
  572. // delay until we get as much processing done as possible, for
  573. // maximum overlap.
  574. pulXlate = pxlo->pulXlate;
  575. if (P9000(ppdev))
  576. {
  577. CP_BACKGROUND(ppdev, pjBase, pulXlate[0]);
  578. CP_FOREGROUND(ppdev, pjBase, pulXlate[1]);
  579. CP_RASTER(ppdev, pjBase, gaulP9000OpaqueFromRop2[ulHwMix & 0xf]);
  580. }
  581. else
  582. {
  583. CP_COLOR0(ppdev, pjBase, pulXlate[0]);
  584. CP_COLOR1(ppdev, pjBase, pulXlate[1]);
  585. CP_RASTER(ppdev, pjBase, ulHwMix & 0xff);
  586. }
  587. CP_START_PIXEL1(ppdev, pjBase);
  588. do {
  589. for (i = culScan; i != 0; i--)
  590. {
  591. CP_PIXEL1(ppdev, pjBase, *pulSrc);
  592. pulSrc++;
  593. }
  594. CP_PIXEL1_REM(ppdev, pjBase, cRem, *pulSrc);
  595. pulSrc = (ULONG*) ((BYTE*) pulSrc + lSrcSkip);
  596. } while (--cyScan != 0);
  597. CP_END_PIXEL1(ppdev, pjBase);
  598. } while (prcl++, --c);
  599. // Don't forget to reset the clip register:
  600. CP_WAIT(ppdev, pjBase);
  601. CP_ABS_WMIN(ppdev, pjBase, 0, 0);
  602. }
  603. /******************************Public*Routine******************************\
  604. * VOID vXfer4bpp
  605. *
  606. * Does a 4bpp transfer from a bitmap to the screen.
  607. *
  608. * NOTE: The screen must be 8bpp for this function to be called!
  609. *
  610. * The reason we implement this is that a lot of resources are kept as 4bpp,
  611. * and used to initialize DFBs, some of which we of course keep off-screen.
  612. *
  613. \**************************************************************************/
  614. VOID vXfer4bpp( // Type FNXFER
  615. PDEV* ppdev,
  616. LONG c, // Count of rectangles, can't be zero
  617. RECTL* prcl, // List of destination rectangles, in relative
  618. // coordinates
  619. ULONG ulHwMix, // Hardware mix
  620. SURFOBJ* psoSrc, // Source surface
  621. POINTL* pptlSrc, // Original unclipped source point
  622. RECTL* prclDst, // Original unclipped destination rectangle
  623. XLATEOBJ* pxlo) // Translate that provides colour-expansion information
  624. {
  625. BYTE* pjBase;
  626. LONG dx;
  627. LONG dy;
  628. LONG lSrcDelta;
  629. BYTE* pjSrcScan0;
  630. ULONG* pulXlate;
  631. LONG xLeft;
  632. LONG xRight;
  633. LONG yTop;
  634. LONG cyScan;
  635. LONG xBias;
  636. LONG cwSrc;
  637. LONG lSrcSkip;
  638. LONG cw;
  639. BYTE* pjSrc;
  640. BYTE jSrc;
  641. ULONG ul;
  642. ASSERTDD(ppdev->cjPel == 1, "This function assumes 8bpp");
  643. pjBase = ppdev->pjBase;
  644. dx = pptlSrc->x - prclDst->left;
  645. dy = pptlSrc->y - prclDst->top;
  646. lSrcDelta = psoSrc->lDelta;
  647. pjSrcScan0 = psoSrc->pvScan0;
  648. pulXlate = pxlo->pulXlate;
  649. do {
  650. xLeft = prcl->left;
  651. xRight = prcl->right;
  652. yTop = prcl->top;
  653. // We compute 'xBias' in order to word-align the source pointer.
  654. // This way, since we're processing a word of the source at a
  655. // time, we're guaranteed not to read even a byte past the end of
  656. // the bitmap.
  657. xBias = ((xLeft + dx) & 3);
  658. xLeft -= xBias;
  659. CP_XY1(ppdev, pjBase, xLeft, yTop);
  660. CP_X0(ppdev, pjBase, xLeft);
  661. CP_X2(ppdev, pjBase, xRight);
  662. CP_ABS_Y3(ppdev, pjBase, 1);
  663. // Every word in the source is one dword in the destination:
  664. cwSrc = ((xRight - xLeft) + 3) >> 2;
  665. lSrcSkip = lSrcDelta - (cwSrc << 1);
  666. pjSrc = pjSrcScan0 + (yTop + dy) * lSrcDelta + ((xLeft + dx) >> 1);
  667. cyScan = prcl->bottom - yTop;
  668. ASSERTDD(((ULONG_PTR) pjSrc & 1) == 0, "Source should be word aligned");
  669. // Yes, we're setting the raster every time in the loop. But we
  670. // have to wait for not-busy before setting the raster, and the
  671. // chances are that we'll only have one rectangle to blt, so
  672. // we do this here:
  673. CP_WAIT(ppdev, pjBase);
  674. CP_WLEFT(ppdev, pjBase, prcl->left);
  675. CP_RASTER(ppdev, pjBase, P9000(ppdev) ? ulHwMix : (ulHwMix & 0xff));
  676. CP_START_PIXEL8(ppdev, pjBase);
  677. do {
  678. cw = cwSrc;
  679. do {
  680. jSrc = *(pjSrc + 1);
  681. ul = pulXlate[jSrc & 0xf];
  682. ul <<= 8;
  683. ul |= pulXlate[jSrc >> 4];
  684. jSrc = *(pjSrc);
  685. ul <<= 8;
  686. ul |= pulXlate[jSrc & 0xf];
  687. ul <<= 8;
  688. ul |= pulXlate[jSrc >> 4];
  689. CP_PIXEL8(ppdev, pjBase, ul);
  690. pjSrc += 2;
  691. } while (--cw != 0);
  692. pjSrc += lSrcSkip;
  693. } while (--cyScan != 0);
  694. CP_END_PIXEL8(ppdev, pjBase);
  695. } while (prcl++, --c);
  696. // Don't forget to reset the clip register:
  697. CP_WAIT(ppdev, pjBase);
  698. CP_ABS_WMIN(ppdev, pjBase, 0, 0);
  699. }
  700. /******************************Public*Routine******************************\
  701. * VOID vXferNative
  702. *
  703. * Transfers a bitmap that is the same colour depth as the display to
  704. * the screen via the data transfer register, with no translation.
  705. *
  706. \**************************************************************************/
  707. VOID vXferNative( // Type FNXFER
  708. PDEV* ppdev,
  709. LONG c, // Count of rectangles, can't be zero
  710. RECTL* prcl, // Array of relative coordinates destination rectangles
  711. ULONG ulHwMix, // Hardware mix
  712. SURFOBJ* psoSrc, // Source surface
  713. POINTL* pptlSrc, // Original unclipped source point
  714. RECTL* prclDst, // Original unclipped destination rectangle
  715. XLATEOBJ* pxlo) // Not used
  716. {
  717. BYTE* pjBase;
  718. LONG cjPel;
  719. LONG xOffset;
  720. LONG yOffset;
  721. LONG dx;
  722. LONG dy;
  723. LONG lSrcDelta;
  724. BYTE* pjSrcScan0;
  725. LONG xLeft;
  726. LONG xRight;
  727. LONG yTop;
  728. LONG cyScan;
  729. LONG xBias;
  730. LONG culScan;
  731. LONG lSrcSkip;
  732. LONG cu;
  733. ULONG* pulSrc;
  734. pjBase = ppdev->pjBase;
  735. cjPel = ppdev->cjPel;
  736. xOffset = ppdev->xOffset;
  737. yOffset = ppdev->yOffset;
  738. dx = pptlSrc->x - prclDst->left;
  739. dy = pptlSrc->y - prclDst->top;
  740. lSrcDelta = psoSrc->lDelta;
  741. pjSrcScan0 = psoSrc->pvScan0;
  742. do {
  743. xLeft = prcl->left;
  744. xRight = prcl->right;
  745. yTop = prcl->top;
  746. // We compute 'xBias' in order to dword-align the source pointer.
  747. // This way, we don't have to do unaligned reads of the source,
  748. // and we're guaranteed not to read even a byte past the end of
  749. // the bitmap.
  750. //
  751. // Note that this bias works at 24bpp, too:
  752. xBias = ((xLeft + dx) & 3);
  753. xLeft -= xBias;
  754. CP_ABS_XY1(ppdev, pjBase, (xLeft + xOffset) * cjPel, yTop + yOffset);
  755. CP_ABS_X0(ppdev, pjBase, (xLeft + xOffset) * cjPel);
  756. CP_ABS_X2(ppdev, pjBase, (xRight + xOffset) * cjPel);
  757. CP_ABS_Y3(ppdev, pjBase, 1);
  758. culScan = ((xRight - xLeft) * cjPel + 3) >> 2;
  759. lSrcSkip = lSrcDelta - (culScan << 2);
  760. pulSrc = (ULONG*) (pjSrcScan0 + (yTop + dy) * lSrcDelta
  761. + (xLeft + dx) * cjPel);
  762. cyScan = prcl->bottom - yTop;
  763. ASSERTDD(((ULONG_PTR)pulSrc & 3) == 0, "Source should be dword aligned");
  764. // Yes, we're setting the raster every time in the loop. But we
  765. // have to wait for not-busy before setting the raster, and the
  766. // chances are that we'll only have one rectangle to blt, so
  767. // we do this here:
  768. CP_WAIT(ppdev, pjBase);
  769. CP_ABS_WLEFT(ppdev, pjBase, prcl->left + xOffset);
  770. CP_RASTER(ppdev, pjBase, P9000(ppdev) ? ulHwMix : (ulHwMix & 0xff));
  771. CP_START_PIXEL8(ppdev, pjBase);
  772. do {
  773. cu = culScan;
  774. do {
  775. CP_PIXEL8(ppdev, pjBase, *pulSrc);
  776. pulSrc++;
  777. } while (--cu != 0);
  778. pulSrc = (ULONG*) ((BYTE*) pulSrc + lSrcSkip);
  779. } while (--cyScan != 0);
  780. CP_END_PIXEL8(ppdev, pjBase);
  781. } while (prcl++, --c);
  782. // Don't forget to reset the clip register:
  783. CP_WAIT(ppdev, pjBase);
  784. CP_ABS_WMIN(ppdev, pjBase, 0, 0);
  785. }
  786. /******************************Public*Routine******************************\
  787. * VOID vCopyBlt
  788. *
  789. * Does a screen-to-screen blt of a list of rectangles.
  790. *
  791. * Note: We may call this function with weird ROPs to do colour-expansion
  792. * from off-screen monochrome bitmaps.
  793. *
  794. \**************************************************************************/
  795. VOID vCopyBlt( // Type FNCOPY
  796. PDEV* ppdev,
  797. LONG c, // Can't be zero
  798. RECTL* prcl, // Array of relative coordinates destination rectangles
  799. ULONG ulHwMix, // Hardware mix
  800. POINTL* pptlSrc, // Original unclipped source point
  801. RECTL* prclDst) // Original unclipped destination rectangle
  802. {
  803. BYTE* pjBase;
  804. LONG cjPel;
  805. LONG xOffset;
  806. LONG yOffset;
  807. LONG dx;
  808. LONG dy;
  809. LONG xSrc;
  810. LONG ySrc;
  811. pjBase = ppdev->pjBase;
  812. cjPel = ppdev->cjPel;
  813. // Our DFB xOffset has to be scaled by the pixel size too:
  814. xOffset = ppdev->xOffset;
  815. yOffset = ppdev->yOffset;
  816. dx = pptlSrc->x - prclDst->left;
  817. dy = pptlSrc->y - prclDst->top;
  818. xSrc = prcl->left + dx;
  819. ySrc = prcl->top + dy;
  820. CP_ABS_XY0(ppdev, pjBase, (xOffset + xSrc) * cjPel,
  821. (yOffset + ySrc));
  822. CP_ABS_XY1(ppdev, pjBase, (xOffset + xSrc + prcl->right - prcl->left) * cjPel - 1,
  823. (yOffset + ySrc + prcl->bottom - prcl->top - 1));
  824. CP_ABS_XY2(ppdev, pjBase, (xOffset + prcl->left) * cjPel,
  825. (yOffset + prcl->top));
  826. CP_ABS_XY3(ppdev, pjBase, (xOffset + prcl->right) * cjPel - 1,
  827. (yOffset + prcl->bottom - 1));
  828. CP_WAIT(ppdev, pjBase);
  829. CP_RASTER(ppdev, pjBase, P9000(ppdev) ? ulHwMix : (ulHwMix & 0xff));
  830. CP_START_BLT(ppdev, pjBase);
  831. while (prcl++, --c)
  832. {
  833. xSrc = prcl->left + dx;
  834. ySrc = prcl->top + dy;
  835. CP_ABS_XY0(ppdev, pjBase, (xOffset + xSrc) * cjPel,
  836. (yOffset + ySrc));
  837. CP_ABS_XY1(ppdev, pjBase, (xOffset + xSrc + prcl->right - prcl->left) * cjPel - 1,
  838. (yOffset + ySrc + prcl->bottom - prcl->top - 1));
  839. CP_ABS_XY2(ppdev, pjBase, (xOffset + prcl->left) * cjPel,
  840. (yOffset + prcl->top));
  841. CP_ABS_XY3(ppdev, pjBase, (xOffset + prcl->right) * cjPel - 1,
  842. (yOffset + prcl->bottom - 1));
  843. CP_START_BLT_WAIT(ppdev, pjBase);
  844. }
  845. }
  846. /******************************Public*Routine******************************\
  847. * VOID vFillSolidP9000HighColor
  848. *
  849. * Fills a list of rectangles with a solid colour when running at 16bpp
  850. * on the P9000, using the pattern hardware.
  851. *
  852. \**************************************************************************/
  853. VOID vFillSolidP9000HighColor( // Type FNFILL
  854. PDEV* ppdev,
  855. LONG c, // Can't be zero
  856. RECTL* prcl, // List of rectangles to be filled, in relative
  857. // coordinates
  858. ULONG ulHwMix, // Hardware mix mode
  859. RBRUSH_COLOR rbc, // Drawing colour is rbc.iSolidColor
  860. POINTL* pptlBrush) // Not used
  861. {
  862. BYTE* pjBase;
  863. LONG xOffset;
  864. LONG yOffset;
  865. ASSERTDD(c > 0, "Can't handle zero rectangles");
  866. ASSERTDD(P9000(ppdev), "Shouldn't need to be called on the P9100");
  867. ASSERTDD(ppdev->iBitmapFormat == BMF_16BPP, "Only handle 16bpp for now");
  868. pjBase = ppdev->pjBase;
  869. // Our DFB xOffset has to be scaled by the pixel size too:
  870. xOffset = 2 * ppdev->xOffset;
  871. yOffset = ppdev->yOffset;
  872. CP_ABS_METARECT(ppdev, pjBase, xOffset + 2 * prcl->left,
  873. yOffset + prcl->top);
  874. CP_ABS_METARECT(ppdev, pjBase, xOffset + 2 * prcl->right,
  875. yOffset + prcl->bottom);
  876. // We've already downloaded and set the pattern origin in
  877. // vAssertModeBrushCache:
  878. CP_WAIT(ppdev, pjBase);
  879. CP_RASTER(ppdev, pjBase, P9000_ENABLE_PATTERN |
  880. gaulP9000OpaqueFromRop2[(ulHwMix & 0x3C) >> 2]);
  881. CP_FOREGROUND(ppdev, pjBase, rbc.iSolidColor);
  882. CP_BACKGROUND(ppdev, pjBase, rbc.iSolidColor >> 8);
  883. CP_START_QUAD(ppdev, pjBase);
  884. while (prcl++, --c)
  885. {
  886. CP_ABS_METARECT(ppdev, pjBase, xOffset + 2 * prcl->left,
  887. yOffset + prcl->top);
  888. CP_ABS_METARECT(ppdev, pjBase, xOffset + 2 * prcl->right,
  889. yOffset + prcl->bottom);
  890. CP_START_QUAD_WAIT(ppdev, pjBase);
  891. }
  892. }