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.

1093 lines
29 KiB

  1. /******************************************************************************\
  2. *
  3. * $Workfile: stripmm.c $
  4. *
  5. * Do what you can with no line support.
  6. *
  7. * I implemented the horizontal and vertical strip functions using
  8. * solid fills, and removed the usage of diagonal strips. With a little
  9. * effort you could implement diagonal strips by doing solid fills while
  10. * playing with lDelta. This is probably not worth the trouble.
  11. *
  12. * Copyright (c) 1992-1997 Microsoft Corporation
  13. * Copyright (c) 1996-1997 Cirrus Logic, Inc.,
  14. *
  15. * $Log: S:/projects/drivers/ntsrc/display/STRIPMM.C_V $
  16. *
  17. * Rev 1.2 10 Jan 1997 15:40:18 PLCHU
  18. *
  19. *
  20. * Rev 1.1 Oct 10 1996 15:39:22 unknown
  21. *
  22. *
  23. * Rev 1.1 12 Aug 1996 16:55:04 frido
  24. * Removed unaccessed local variables.
  25. *
  26. * chu01 : 01-02-97 5480 BitBLT enhancement
  27. * chu02 : 01-09-97 Macro redefinition
  28. *
  29. \******************************************************************************/
  30. #include "precomp.h"
  31. #define count COMMAND_TOTAL_PACKETS
  32. #define MM_DRAW_HORZ_STRIP(xy, cx, lDelta, cBpp)\
  33. {\
  34. ULONG ulDstAddr;\
  35. \
  36. ulDstAddr = xy;\
  37. \
  38. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);\
  39. CP_MM_XCNT(ppdev, pjBase, (PELS_TO_BYTES(cx) - 1));\
  40. CP_MM_YCNT(ppdev, pjBase, 0);\
  41. CP_MM_DST_ADDR(ppdev, pjBase, ulDstAddr);\
  42. CP_MM_START_BLT(ppdev, pjBase);\
  43. }
  44. #define MM_DRAW_VERT_STRIP(xy, cy, lDelta, cBpp)\
  45. {\
  46. ULONG ulDstAddr;\
  47. \
  48. ulDstAddr = xy;\
  49. \
  50. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);\
  51. CP_MM_XCNT(ppdev, pjBase, (cBpp - 1));\
  52. CP_MM_YCNT(ppdev, pjBase, (cy - 1));\
  53. CP_MM_DST_ADDR(ppdev, pjBase, ulDstAddr);\
  54. CP_MM_START_BLT(ppdev, pjBase);\
  55. }
  56. #define MM_DRAW_VERT_STRIP_FLIPPED(xy, cy, lDelta, cBpp)\
  57. {\
  58. ULONG ulDstAddr;\
  59. \
  60. ulDstAddr = xy - ((cy - 1) * lDelta);\
  61. \
  62. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);\
  63. CP_MM_XCNT(ppdev, pjBase, (cBpp - 1));\
  64. CP_MM_YCNT(ppdev, pjBase, (cy - 1));\
  65. CP_MM_DST_ADDR(ppdev, pjBase, ulDstAddr);\
  66. CP_MM_START_BLT(ppdev, pjBase);\
  67. }
  68. // chu01, chu02
  69. #define MM_DRAW_HORZ_STRIP80(x, y, cx)\
  70. {\
  71. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);\
  72. CP_MM_BLT_EXT_MODE(ppdev, pjBase, ENABLE_XY_POSITION);\
  73. CP_MM_XCNT(ppdev, pjBase, (cx - 1));\
  74. CP_MM_YCNT(ppdev, pjBase, 0);\
  75. CP_MM_DST_ADDR(ppdev, pjBase, 0);\
  76. CP_MM_DST_Y(ppdev, pjBase, y);\
  77. CP_MM_DST_X(ppdev, pjBase, x);\
  78. }
  79. #define MM_DRAW_VERT_STRIP80(x, y, cy)\
  80. {\
  81. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);\
  82. CP_MM_BLT_EXT_MODE(ppdev, pjBase, ENABLE_XY_POSITION);\
  83. CP_MM_XCNT(ppdev, pjBase, 0);\
  84. CP_MM_YCNT(ppdev, pjBase, (cy - 1));\
  85. CP_MM_DST_ADDR(ppdev, pjBase, 0);\
  86. CP_MM_DST_Y(ppdev, pjBase, y);\
  87. CP_MM_DST_X(ppdev, pjBase, x);\
  88. }
  89. #define MM_DRAW_VERT_STRIP_FLIPPED80(x, y, cy)\
  90. {\
  91. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);\
  92. CP_MM_BLT_EXT_MODE(ppdev, pjBase, ENABLE_XY_POSITION);\
  93. CP_MM_XCNT(ppdev, pjBase, 0);\
  94. CP_MM_YCNT(ppdev, pjBase, (cy - 1));\
  95. CP_MM_DST_ADDR(ppdev, pjBase, 0);\
  96. CP_MM_DST_Y(ppdev, pjBase, ((y - cy) + 1));\
  97. CP_MM_DST_X(ppdev, pjBase, x);\
  98. }
  99. /******************************Public*Routine******************************\
  100. * VOID vMmSolidHorizontal
  101. *
  102. * Draws left-to-right x-major near-horizontal lines using solid fills.
  103. *
  104. * Assumes fgRop, BgRop, and Color are already set correctly.
  105. *
  106. \**************************************************************************/
  107. VOID vMmSolidHorizontal(
  108. PDEV* ppdev,
  109. STRIP* pStrip,
  110. LINESTATE* pLineState)
  111. {
  112. BYTE* pjBase = ppdev->pjBase;
  113. LONG cBpp = ppdev->cBpp;
  114. LONG lDelta = ppdev->lDelta;
  115. LONG cStrips = pStrip->cStrips;
  116. PLONG pStrips = pStrip->alStrips;
  117. LONG x = pStrip->ptlStart.x;
  118. LONG y = pStrip->ptlStart.y;
  119. LONG xy = PELS_TO_BYTES(x) + (lDelta * y);
  120. LONG yInc = 1;
  121. LONG i;
  122. DISPDBG((2, "vMmSolidHorizontal"));
  123. if (!(pStrip->flFlips & FL_FLIP_V))
  124. {
  125. //
  126. // Horizontal strips ->
  127. // ->
  128. //
  129. for (i = 0; i < cStrips; i++)
  130. {
  131. MM_DRAW_HORZ_STRIP(xy, *pStrips, lDelta, cBpp);
  132. x += *pStrips;
  133. xy += PELS_TO_BYTES(*pStrips); // x+
  134. xy += lDelta; // y+
  135. pStrips++;
  136. }
  137. y += cStrips;
  138. }
  139. else
  140. {
  141. //
  142. // ->
  143. // Horizontal strips ->
  144. //
  145. for (i = 0; i < cStrips; i++)
  146. {
  147. MM_DRAW_HORZ_STRIP(xy, *pStrips, lDelta, cBpp);
  148. x += *pStrips;
  149. xy += PELS_TO_BYTES(*pStrips); // x+
  150. xy -= lDelta; // y+
  151. pStrips++;
  152. }
  153. y -= cStrips;
  154. }
  155. pStrip->ptlStart.x = x;
  156. pStrip->ptlStart.y = y;
  157. }
  158. /******************************Public*Routine******************************\
  159. * VOID vMmSolidVertical
  160. *
  161. * Draws left-to-right y-major near-vertical lines using solid fills.
  162. *
  163. \**************************************************************************/
  164. VOID vMmSolidVertical(
  165. PDEV* ppdev,
  166. STRIP* pStrip,
  167. LINESTATE* pLineState)
  168. {
  169. BYTE* pjBase = ppdev->pjBase;
  170. LONG cBpp = ppdev->cBpp;
  171. LONG lDelta = ppdev->lDelta;
  172. LONG cStrips = pStrip->cStrips;
  173. PLONG pStrips = pStrip->alStrips;
  174. LONG x = pStrip->ptlStart.x;
  175. LONG y = pStrip->ptlStart.y;
  176. LONG xy = PELS_TO_BYTES(x) + (lDelta * y);
  177. LONG i;
  178. DISPDBG((2, "vMmSolidVertical"));
  179. if (!(pStrip->flFlips & FL_FLIP_V))
  180. {
  181. //
  182. // |
  183. // Vertical strips v
  184. // |
  185. // v
  186. //
  187. for (i = 0; i < cStrips; i++)
  188. {
  189. MM_DRAW_VERT_STRIP(xy, *pStrips, lDelta, cBpp);
  190. y += *pStrips;
  191. xy += cBpp; // x+
  192. xy += (*pStrips * lDelta); // y+
  193. pStrips++;
  194. }
  195. }
  196. else
  197. {
  198. //
  199. // ^
  200. // Vertical strips |
  201. // ^
  202. // |
  203. //
  204. for (i = 0; i < cStrips; i++)
  205. {
  206. MM_DRAW_VERT_STRIP_FLIPPED(xy, *pStrips, lDelta, cBpp);
  207. y -= *pStrips;
  208. xy += cBpp; // x+
  209. xy -= (*pStrips * lDelta); // y-
  210. pStrips++;
  211. }
  212. }
  213. x += cStrips;
  214. pStrip->ptlStart.x = x;
  215. pStrip->ptlStart.y = y;
  216. }
  217. /******************************Public*Routine******************************\
  218. * VOID vMmStyledHorizontal
  219. *
  220. * Takes the list of strips that define the pixels that would be lit for
  221. * a solid line, and breaks them into styling chunks according to the
  222. * styling information that is passed in.
  223. *
  224. * This particular routine handles x-major lines that run left-to-right,
  225. * and are comprised of horizontal strips. It draws the dashes using
  226. * short-stroke vectors.
  227. *
  228. * The performance of this routine could be improved significantly if
  229. * anyone cared enough about styled lines improve it.
  230. *
  231. \**************************************************************************/
  232. VOID vMmStyledHorizontal(
  233. PDEV* ppdev,
  234. STRIP* pstrip,
  235. LINESTATE* pls)
  236. {
  237. BYTE* pjBase = ppdev->pjBase;
  238. LONG cBpp = ppdev->cBpp;
  239. LONG lDelta = ppdev->lDelta;
  240. LONG x = pstrip->ptlStart.x; // x position of start of first strip
  241. LONG y = pstrip->ptlStart.y; // y position of start of first strip
  242. LONG xy = PELS_TO_BYTES(x) + (lDelta * y);
  243. LONG* plStrip = pstrip->alStrips; // Points to current strip
  244. LONG cStrips = pstrip->cStrips; // Total number of strips we'll do
  245. LONG dy;
  246. LONG dylDelta;
  247. LONG cStyle;
  248. LONG cStrip;
  249. LONG cThis;
  250. ULONG bIsGap;
  251. DISPDBG((2, "vMmStyledHorizontal"));
  252. if (pstrip->flFlips & FL_FLIP_V)
  253. {
  254. // The minor direction of the line is 90 degrees, and the major
  255. // direction is 0 (it's a left-to-right x-major line going up):
  256. dy = -1;
  257. dylDelta = -lDelta;
  258. }
  259. else
  260. {
  261. // The minor direction of the line is 270 degrees, and the major
  262. // direction is 0 (it's a left-to-right x-major line going down):
  263. dy = 1;
  264. dylDelta = lDelta;
  265. }
  266. cStrip = *plStrip; // Number of pels in first strip
  267. cStyle = pls->spRemaining; // Number of pels in first 'gap' or 'dash'
  268. bIsGap = pls->ulStyleMask; // Tells whether in a 'gap' or a 'dash'
  269. // ulStyleMask is non-zero if we're in the middle of a 'gap',
  270. // and zero if we're in the middle of a 'dash':
  271. if (bIsGap)
  272. goto SkipAGap;
  273. else
  274. goto OutputADash;
  275. PrepareToSkipAGap:
  276. // Advance in the style-state array, so that we can find the next
  277. // 'dot' that we'll have to display:
  278. bIsGap = ~bIsGap;
  279. pls->psp++;
  280. if (pls->psp > pls->pspEnd)
  281. pls->psp = pls->pspStart;
  282. cStyle = *pls->psp;
  283. // If 'cStrip' is zero, we also need a new strip:
  284. if (cStrip != 0)
  285. goto SkipAGap;
  286. // Here, we're in the middle of a 'gap' where we don't have to
  287. // display anything. We simply cycle through all the strips
  288. // we can, keeping track of the current position, until we run
  289. // out of 'gap':
  290. while (TRUE)
  291. {
  292. // Each time we loop, we move to a new scan and need a new strip:
  293. y += dy;
  294. xy += dylDelta;
  295. plStrip++;
  296. cStrips--;
  297. if (cStrips == 0)
  298. goto AllDone;
  299. cStrip = *plStrip;
  300. SkipAGap:
  301. cThis = min(cStrip, cStyle);
  302. cStyle -= cThis;
  303. cStrip -= cThis;
  304. x += cThis;
  305. xy += PELS_TO_BYTES(cThis);
  306. if (cStyle == 0)
  307. goto PrepareToOutputADash;
  308. }
  309. PrepareToOutputADash:
  310. // Advance in the style-state array, so that we can find the next
  311. // 'dot' that we'll have to display:
  312. bIsGap = ~bIsGap;
  313. pls->psp++;
  314. if (pls->psp > pls->pspEnd)
  315. pls->psp = pls->pspStart;
  316. cStyle = *pls->psp;
  317. // If 'cStrip' is zero, we also need a new strip.
  318. if (cStrip != 0)
  319. {
  320. // There's more to be done in the current strip:
  321. goto OutputADash;
  322. }
  323. // We've finished with the current strip:
  324. while (TRUE)
  325. {
  326. // Each time we loop, we move to a new scan and need a new strip:
  327. y += dy;
  328. xy += dylDelta;
  329. plStrip++;
  330. cStrips--;
  331. if (cStrips == 0)
  332. goto AllDone;
  333. cStrip = *plStrip;
  334. OutputADash:
  335. cThis = min(cStrip, cStyle);
  336. cStyle -= cThis;
  337. cStrip -= cThis;
  338. MM_DRAW_HORZ_STRIP(xy, cThis, lDelta, cBpp);
  339. x += cThis;
  340. xy += PELS_TO_BYTES(cThis); // x+
  341. if (cStyle == 0)
  342. goto PrepareToSkipAGap;
  343. }
  344. AllDone:
  345. // Update our state variables so that the next line can continue
  346. // where we left off:
  347. pls->spRemaining = cStyle;
  348. pls->ulStyleMask = bIsGap;
  349. pstrip->ptlStart.x = x;
  350. pstrip->ptlStart.y = y;
  351. }
  352. /******************************Public*Routine******************************\
  353. * VOID vMmStyledVertical
  354. *
  355. * Takes the list of strips that define the pixels that would be lit for
  356. * a solid line, and breaks them into styling chunks according to the
  357. * styling information that is passed in.
  358. *
  359. * This particular routine handles y-major lines that run left-to-right,
  360. * and are comprised of vertical strips. It draws the dashes using
  361. * short-stroke vectors.
  362. *
  363. * The performance of this routine could be improved significantly if
  364. * anyone cared enough about styled lines improve it.
  365. *
  366. \**************************************************************************/
  367. VOID vMmStyledVertical(
  368. PDEV* ppdev,
  369. STRIP* pstrip,
  370. LINESTATE* pls)
  371. {
  372. BYTE* pjBase = ppdev->pjBase;
  373. LONG cBpp = ppdev->cBpp;
  374. LONG lDelta = ppdev->lDelta;
  375. LONG x = pstrip->ptlStart.x; // x position of start of first strip
  376. LONG y = pstrip->ptlStart.y; // y position of start of first strip
  377. LONG xy = PELS_TO_BYTES(x) + (lDelta * y);
  378. LONG* plStrip = pstrip->alStrips; // Points to current strip
  379. LONG cStrips = pstrip->cStrips; // Total number of strips we'll do
  380. LONG dy;
  381. LONG dylDelta;
  382. LONG cStyle;
  383. LONG cStrip;
  384. LONG cThis;
  385. ULONG bIsGap;
  386. DISPDBG((2, "vMmStyledVertical")) ;
  387. if (pstrip->flFlips & FL_FLIP_V)
  388. {
  389. // The minor direction of the line is 0 degrees, and the major
  390. // direction is 90 (it's a left-to-right y-major line going up):
  391. dy = -1;
  392. dylDelta = -lDelta;
  393. }
  394. else
  395. {
  396. // The minor direction of the line is 0 degrees, and the major
  397. // direction is 270 (it's a left-to-right y-major line going down):
  398. dy = 1;
  399. dylDelta = lDelta;
  400. }
  401. cStrip = *plStrip; // Number of pels in first strip
  402. cStyle = pls->spRemaining; // Number of pels in first 'gap' or 'dash'
  403. bIsGap = pls->ulStyleMask; // Tells whether in a 'gap' or a 'dash'
  404. // ulStyleMask is non-zero if we're in the middle of a 'gap',
  405. // and zero if we're in the middle of a 'dash':
  406. if (bIsGap)
  407. goto SkipAGap;
  408. else
  409. goto OutputADash;
  410. PrepareToSkipAGap:
  411. // Advance in the style-state array, so that we can find the next
  412. // 'dot' that we'll have to display:
  413. bIsGap = ~bIsGap;
  414. pls->psp++;
  415. if (pls->psp > pls->pspEnd)
  416. pls->psp = pls->pspStart;
  417. cStyle = *pls->psp;
  418. // If 'cStrip' is zero, we also need a new strip:
  419. if (cStrip != 0)
  420. goto SkipAGap;
  421. // Here, we're in the middle of a 'gap' where we don't have to
  422. // display anything. We simply cycle through all the strips
  423. // we can, keeping track of the current position, until we run
  424. // out of 'gap':
  425. while (TRUE)
  426. {
  427. // Each time we loop, we move to a new column and need a new strip:
  428. xy += cBpp;
  429. x++;
  430. plStrip++;
  431. cStrips--;
  432. if (cStrips == 0)
  433. goto AllDone;
  434. cStrip = *plStrip;
  435. SkipAGap:
  436. cThis = min(cStrip, cStyle);
  437. cStyle -= cThis;
  438. cStrip -= cThis;
  439. if (dy > 0)
  440. {
  441. y += cThis;
  442. xy += (cThis * lDelta);
  443. }
  444. else
  445. {
  446. y -= cThis;
  447. xy -= (cThis * lDelta);
  448. }
  449. if (cStyle == 0)
  450. goto PrepareToOutputADash;
  451. }
  452. PrepareToOutputADash:
  453. // Advance in the style-state array, so that we can find the next
  454. // 'dot' that we'll have to display:
  455. bIsGap = ~bIsGap;
  456. pls->psp++;
  457. if (pls->psp > pls->pspEnd)
  458. pls->psp = pls->pspStart;
  459. cStyle = *pls->psp;
  460. // If 'cStrip' is zero, we also need a new strip.
  461. if (cStrip != 0)
  462. {
  463. // There's more to be done in the current strip:
  464. goto OutputADash;
  465. }
  466. // We've finished with the current strip:
  467. while (TRUE)
  468. {
  469. // Each time we loop, we move to a new column and need a new strip:
  470. xy += cBpp;
  471. x++;
  472. plStrip++;
  473. cStrips--;
  474. if (cStrips == 0)
  475. goto AllDone;
  476. cStrip = *plStrip;
  477. OutputADash:
  478. cThis = min(cStrip, cStyle);
  479. cStyle -= cThis;
  480. cStrip -= cThis;
  481. if (dy <= 0)
  482. {
  483. MM_DRAW_VERT_STRIP_FLIPPED(xy, cThis, lDelta, cBpp);
  484. y -= cThis; // y-
  485. xy -= (cThis * lDelta); // y-
  486. }
  487. else
  488. {
  489. MM_DRAW_VERT_STRIP(xy, cThis, lDelta, cBpp);
  490. y += cThis; // y+
  491. xy += (cThis * lDelta); // y+
  492. }
  493. if (cStyle == 0)
  494. goto PrepareToSkipAGap;
  495. }
  496. AllDone:
  497. // Update our state variables so that the next line can continue
  498. // where we left off:
  499. pls->spRemaining = cStyle;
  500. pls->ulStyleMask = bIsGap;
  501. pstrip->ptlStart.x = x;
  502. pstrip->ptlStart.y = y;
  503. }
  504. /******************************Public*Routine******************************\
  505. * VOID vInvalidStrip
  506. *
  507. * Put this in the function table for entries that shouldn't get hit.
  508. *
  509. \**************************************************************************/
  510. VOID vInvalidStrip(
  511. PDEV* ppdev, // unused
  512. STRIP* pStrip, // unused
  513. LINESTATE* pLineState) // unused
  514. {
  515. RIP("vInvalidStrip called");
  516. return;
  517. }
  518. // chu01
  519. /******************************Public*Routine******************************\
  520. *
  521. * B i t B L T E n h a n c e m e n t F o r C L - G D 5 4 8 0
  522. *
  523. \**************************************************************************/
  524. VOID vMmSolidHorizontal80(
  525. PDEV* ppdev,
  526. STRIP* pStrip,
  527. LINESTATE* pLineState)
  528. {
  529. BYTE* pjBase = ppdev->pjBase ;
  530. LONG cBpp = ppdev->cBpp ;
  531. LONG lDelta = ppdev->lDelta ;
  532. LONG cStrips = pStrip->cStrips ;
  533. PLONG pStrips = pStrip->alStrips ; // cx for each stroke
  534. LONG x = pStrip->ptlStart.x ; // X-position
  535. LONG y = pStrip->ptlStart.y ; // Y-position
  536. LONG yOrg = y ;
  537. LONG yInc = 1 ;
  538. LONG x0, y0, cx ;
  539. ULONG ulDstOffset = 0 ;
  540. ULONG_PTR* ulCLStart ;
  541. ULONG ulWidthHeight ;
  542. LONG i = 0 ;
  543. BYTE MM1B ;
  544. DISPDBG((2, "vMmSolidHorizontal80")) ;
  545. if (!(pStrip->flFlips & FL_FLIP_V))
  546. {
  547. //
  548. // Horizontal strips -> 1.
  549. // -> 2.
  550. //
  551. if (cStrips != 1)
  552. {
  553. MM1B = ENABLE_COMMAND_LIST | ENABLE_XY_POSITION | SRC_CPU_DATA ;
  554. CP_MM_BLT_EXT_MODE(ppdev, pjBase, MM1B) ;
  555. Loop_H1:
  556. ulCLStart = ppdev->pCommandList ;
  557. ulDstOffset = (ULONG)(((ULONG_PTR)ulCLStart
  558. - (ULONG_PTR)ppdev->pjScreen) << 14) ;
  559. CP_MM_CL_SWITCH(ppdev) ;
  560. // First strip
  561. x0 = x ;
  562. y0 = y ;
  563. cx = *pStrips ;
  564. i++ ;
  565. // Next strip
  566. y++ ;
  567. x += cx ;
  568. pStrips++ ;
  569. while (TRUE)
  570. {
  571. // GR20, GR21, GR22, GR23
  572. ulWidthHeight = PACKXY_FAST((*pStrips - 1), 0) ;
  573. ulWidthHeight |= COMMAND_NOSRC_NOTHING ;
  574. // GR40, GR41, GR42, GR43
  575. *(ulCLStart + 1) = PACKXY_FAST(x, y) ;
  576. // GR2C, GR2D, GR2E
  577. *(ulCLStart + 2) = 0 ;
  578. i++ ;
  579. if ((i == cStrips) || ((i % count) == 0))
  580. {
  581. // Last Command
  582. ulWidthHeight |= COMMAND_LAST_PACKET ;
  583. *ulCLStart = ulWidthHeight ;
  584. break ;
  585. }
  586. *ulCLStart = ulWidthHeight ;
  587. // Next strip
  588. y++ ;
  589. x += *pStrips ;
  590. pStrips++ ;
  591. ulCLStart += 4 ;
  592. }
  593. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase) ;
  594. CP_MM_XCNT(ppdev, pjBase, (cx - 1)) ;
  595. CP_MM_YCNT(ppdev, pjBase, 0) ;
  596. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset) ;
  597. CP_MM_DST_Y(ppdev, pjBase, y0) ;
  598. CP_MM_DST_X(ppdev, pjBase, x0) ;
  599. if (i == cStrips)
  600. x += *pStrips ;
  601. else if ((i % count) == 0)
  602. {
  603. //
  604. // Resume a new command list
  605. //
  606. y++ ;
  607. cx = *pStrips ;
  608. x += cx ;
  609. pStrips++ ;
  610. if (i != (cStrips - 1))
  611. {
  612. goto Loop_H1 ;
  613. }
  614. else
  615. {
  616. MM_DRAW_HORZ_STRIP80(x, y, *pStrips) ;
  617. x += *pStrips ;
  618. pStrips++;
  619. }
  620. }
  621. }
  622. else
  623. {
  624. MM_DRAW_HORZ_STRIP80(x, y, *pStrips) ;
  625. x += *pStrips ;
  626. pStrips++;
  627. }
  628. yOrg += cStrips;
  629. }
  630. else
  631. {
  632. //
  633. // -> 2.
  634. // Horizontal strips -> 1.
  635. //
  636. if (cStrips != 1)
  637. {
  638. MM1B = ENABLE_COMMAND_LIST | ENABLE_XY_POSITION | SRC_CPU_DATA ;
  639. CP_MM_BLT_EXT_MODE(ppdev, pjBase, MM1B) ;
  640. Loop_H2:
  641. ulCLStart = ppdev->pCommandList;
  642. ulDstOffset = (ULONG)(((ULONG_PTR)ulCLStart
  643. - (ULONG_PTR)ppdev->pjScreen) << 14) ;
  644. CP_MM_CL_SWITCH(ppdev) ;
  645. // First strip
  646. x0 = x ;
  647. y0 = y ;
  648. cx = *pStrips ;
  649. i++ ;
  650. // Next strip
  651. y-- ;
  652. x += cx ;
  653. pStrips++ ;
  654. while (TRUE)
  655. {
  656. // GR20, GR21, GR22, GR23
  657. ulWidthHeight = PACKXY_FAST((*pStrips - 1), 0) ;
  658. ulWidthHeight |= COMMAND_NOSRC_NOTHING ;
  659. // GR40, GR41, GR42, GR43
  660. *(ulCLStart + 1) = PACKXY_FAST(x, y) ;
  661. // GR2C, GR2D, GR2E
  662. *(ulCLStart + 2) = 0 ;
  663. i++ ;
  664. if ((i == cStrips) || ((i % count) == 0))
  665. {
  666. // Last Command
  667. ulWidthHeight |= COMMAND_LAST_PACKET ;
  668. *ulCLStart = ulWidthHeight ;
  669. break ;
  670. }
  671. *ulCLStart = ulWidthHeight ;
  672. // Next strip
  673. y-- ;
  674. x += *pStrips ;
  675. pStrips++ ;
  676. ulCLStart += 4 ;
  677. }
  678. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase) ;
  679. CP_MM_XCNT(ppdev, pjBase, (cx - 1)) ;
  680. CP_MM_YCNT(ppdev, pjBase, 0) ;
  681. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset) ;
  682. CP_MM_DST_Y(ppdev, pjBase, y0) ;
  683. CP_MM_DST_X(ppdev, pjBase, x0) ;
  684. if (i == cStrips)
  685. x += *pStrips ;
  686. else if ((i % count) == 0)
  687. {
  688. //
  689. // Resume a new command list
  690. //
  691. y-- ;
  692. cx = *pStrips ;
  693. x += cx ;
  694. pStrips++ ;
  695. if (i != (cStrips - 1))
  696. {
  697. goto Loop_H2 ;
  698. }
  699. else
  700. {
  701. MM_DRAW_HORZ_STRIP80(x, y, *pStrips) ;
  702. x += *pStrips ;
  703. pStrips++;
  704. }
  705. }
  706. }
  707. else
  708. {
  709. MM_DRAW_HORZ_STRIP80(x, y, *pStrips) ;
  710. x += *pStrips ;
  711. pStrips++;
  712. }
  713. yOrg -= cStrips;
  714. }
  715. pStrip->ptlStart.x = x ;
  716. pStrip->ptlStart.y = yOrg ;
  717. }
  718. /******************************Public*Routine******************************\
  719. * VOID vMmSolidVertical80
  720. *
  721. * Draws left-to-right y-major near-vertical lines using solid fills.
  722. *
  723. \**************************************************************************/
  724. VOID vMmSolidVertical80(
  725. PDEV* ppdev,
  726. STRIP* pStrip,
  727. LINESTATE* pLineState)
  728. {
  729. BYTE* pjBase = ppdev->pjBase ;
  730. LONG cBpp = ppdev->cBpp ;
  731. LONG lDelta = ppdev->lDelta ;
  732. LONG cStrips = pStrip->cStrips ;
  733. PLONG pStrips = pStrip->alStrips ;
  734. LONG x = pStrip->ptlStart.x ;
  735. LONG y = pStrip->ptlStart.y ;
  736. LONG xOrg = x ;
  737. LONG x0, y0, cy ;
  738. ULONG ulDstOffset = 0 ;
  739. ULONG_PTR* ulCLStart ;
  740. ULONG ulWidthHeight ;
  741. LONG i = 0 ;
  742. BYTE MM1B ;
  743. DISPDBG((2, "vMmSolidVertical80")) ;
  744. if (!(pStrip->flFlips & FL_FLIP_V))
  745. {
  746. //
  747. // | 1.
  748. // Vertical strips v
  749. // | 2.
  750. // v
  751. //
  752. if (cStrips != 1)
  753. {
  754. MM1B = ENABLE_COMMAND_LIST | ENABLE_XY_POSITION | SRC_CPU_DATA ;
  755. CP_MM_BLT_EXT_MODE(ppdev, pjBase, MM1B) ;
  756. Loop_V1:
  757. ulCLStart = ppdev->pCommandList ;
  758. ulDstOffset = (ULONG)(((ULONG_PTR)ulCLStart
  759. - (ULONG_PTR)ppdev->pjScreen) << 14) ;
  760. CP_MM_CL_SWITCH(ppdev) ;
  761. // First strip
  762. x0 = x ;
  763. y0 = y ;
  764. cy = *pStrips ;
  765. i++ ;
  766. // Next strip
  767. x++ ;
  768. y += cy ;
  769. pStrips++ ;
  770. while (TRUE)
  771. {
  772. // GR20, GR21, GR22, GR23
  773. ulWidthHeight = PACKXY_FAST(0, (*pStrips - 1)) ;
  774. ulWidthHeight |= COMMAND_NOSRC_NOTHING ;
  775. // GR40, GR41, GR42, GR43
  776. *(ulCLStart + 1) = PACKXY_FAST(x, y) ;
  777. // GR2C, GR2D, GR2E
  778. *(ulCLStart + 2) = 0 ;
  779. i++ ;
  780. if ((i == cStrips) || ((i % count) == 0))
  781. {
  782. // Last Command
  783. ulWidthHeight |= COMMAND_LAST_PACKET ;
  784. *ulCLStart = ulWidthHeight ;
  785. break ;
  786. }
  787. *ulCLStart = ulWidthHeight ;
  788. // Next strip
  789. x++ ;
  790. y += *pStrips ;
  791. pStrips++ ;
  792. ulCLStart += 4 ;
  793. }
  794. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase) ;
  795. CP_MM_XCNT(ppdev, pjBase, 0) ;
  796. CP_MM_YCNT(ppdev, pjBase, (cy - 1)) ;
  797. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset) ;
  798. CP_MM_DST_Y(ppdev, pjBase, y0) ;
  799. CP_MM_DST_X(ppdev, pjBase, x0) ;
  800. if (i == cStrips)
  801. y += *pStrips ;
  802. else if ((i % count) == 0)
  803. {
  804. //
  805. // Resume a new command list
  806. //
  807. x++ ;
  808. cy = *pStrips ;
  809. y += cy ;
  810. pStrips++ ;
  811. if (i != (cStrips - 1))
  812. {
  813. goto Loop_V1 ;
  814. }
  815. else
  816. {
  817. MM_DRAW_VERT_STRIP80(x, y, *pStrips) ;
  818. y += *pStrips ;
  819. pStrips++;
  820. }
  821. }
  822. }
  823. else
  824. {
  825. MM_DRAW_VERT_STRIP80(x, y, *pStrips) ;
  826. y += *pStrips ;
  827. pStrips++;
  828. }
  829. }
  830. else
  831. {
  832. //
  833. // ^
  834. // Vertical strips | 2.
  835. // ^
  836. // | 1.
  837. //
  838. if (cStrips != 1)
  839. {
  840. MM1B = ENABLE_COMMAND_LIST | ENABLE_XY_POSITION | SRC_CPU_DATA ;
  841. CP_MM_BLT_EXT_MODE(ppdev, pjBase, MM1B) ;
  842. Loop_V2:
  843. ulCLStart = ppdev->pCommandList ;
  844. ulDstOffset = (ULONG)(((ULONG_PTR)ulCLStart
  845. - (ULONG_PTR)ppdev->pjScreen) << 14) ;
  846. CP_MM_CL_SWITCH(ppdev) ;
  847. // First strip
  848. x0 = x ;
  849. cy = *pStrips ;
  850. y -= (cy - 1) ;
  851. y0 = y ;
  852. i++ ;
  853. pStrips++ ;
  854. // Next strip
  855. x++ ;
  856. y -= *pStrips ;
  857. while (TRUE)
  858. {
  859. // GR20, GR21, GR22, GR23
  860. ulWidthHeight = PACKXY_FAST(0, (*pStrips - 1)) ;
  861. ulWidthHeight |= COMMAND_NOSRC_NOTHING ;
  862. // GR40, GR41, GR42, GR43
  863. *(ulCLStart + 1) = PACKXY_FAST(x, y) ;
  864. // GR2C, GR2D, GR2E
  865. *(ulCLStart + 2) = 0 ;
  866. i++ ;
  867. if ((i == cStrips) || ((i % count) == 0))
  868. {
  869. // Last Command
  870. ulWidthHeight |= COMMAND_LAST_PACKET ;
  871. *ulCLStart = ulWidthHeight ;
  872. break ;
  873. }
  874. *ulCLStart = ulWidthHeight ;
  875. // Next strip
  876. x++ ;
  877. pStrips++ ;
  878. y -= *pStrips ;
  879. ulCLStart += 4 ;
  880. }
  881. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase) ;
  882. CP_MM_XCNT(ppdev, pjBase, 0) ;
  883. CP_MM_YCNT(ppdev, pjBase, (cy - 1)) ;
  884. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset) ;
  885. CP_MM_DST_Y(ppdev, pjBase, y0) ;
  886. CP_MM_DST_X(ppdev, pjBase, x0);
  887. if (i == cStrips)
  888. y -= *pStrips ;
  889. else if ((i % count) == 0)
  890. {
  891. //
  892. // Resume a new command list
  893. //
  894. x++ ;
  895. y-- ;
  896. pStrips++ ;
  897. if (i != (cStrips - 1))
  898. {
  899. goto Loop_V2 ;
  900. }
  901. else
  902. {
  903. MM_DRAW_VERT_STRIP80(x, y, *pStrips) ;
  904. y -= *pStrips ;
  905. pStrips++;
  906. }
  907. }
  908. }
  909. else
  910. {
  911. MM_DRAW_VERT_STRIP_FLIPPED80(x, y, *pStrips) ;
  912. y -= *pStrips ;
  913. pStrips++;
  914. }
  915. }
  916. xOrg += cStrips ;
  917. pStrip->ptlStart.x = xOrg ;
  918. pStrip->ptlStart.y = y ;
  919. }