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.

570 lines
14 KiB

  1. /******************************************************************************\
  2. *
  3. * $Workfile: stripio.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-1995 Microsoft Corporation
  13. * Copyright (c) 1996 Cirrus Logic, Inc.
  14. *
  15. * $Log: S:/projects/drivers/ntsrc/display/stripio.c_v $
  16. *
  17. * Rev 1.1 Oct 10 1996 15:39:12 unknown
  18. *
  19. *
  20. * Rev 1.1 12 Aug 1996 16:55:04 frido
  21. * Removed unaccessed local variables.
  22. *
  23. \******************************************************************************/
  24. #include "precomp.h"
  25. #define IO_DRAW_HORZ_STRIP(xy, cx, lDelta, cBpp)\
  26. {\
  27. ULONG ulDstAddr;\
  28. \
  29. ulDstAddr = xy;\
  30. \
  31. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);\
  32. CP_IO_XCNT(ppdev, pjPorts, (PELS_TO_BYTES(cx) - 1));\
  33. CP_IO_YCNT(ppdev, pjPorts, 0);\
  34. CP_IO_DST_ADDR(ppdev, pjPorts, ulDstAddr);\
  35. CP_IO_START_BLT(ppdev, pjPorts);\
  36. }
  37. #define IO_DRAW_VERT_STRIP(xy, cy, lDelta, cBpp)\
  38. {\
  39. ULONG ulDstAddr;\
  40. \
  41. ulDstAddr = xy;\
  42. \
  43. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);\
  44. CP_IO_XCNT(ppdev, pjPorts, (cBpp - 1));\
  45. CP_IO_YCNT(ppdev, pjPorts, (cy - 1));\
  46. CP_IO_DST_ADDR(ppdev, pjPorts, ulDstAddr);\
  47. CP_IO_START_BLT(ppdev, pjPorts);\
  48. }
  49. #define IO_DRAW_VERT_STRIP_FLIPPED(xy, cy, lDelta, cBpp)\
  50. {\
  51. ULONG ulDstAddr;\
  52. \
  53. ulDstAddr = xy - ((cy - 1) * lDelta);\
  54. \
  55. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);\
  56. CP_IO_XCNT(ppdev, pjPorts, (cBpp - 1));\
  57. CP_IO_YCNT(ppdev, pjPorts, (cy - 1));\
  58. CP_IO_DST_ADDR(ppdev, pjPorts, ulDstAddr);\
  59. CP_IO_START_BLT(ppdev, pjPorts);\
  60. }
  61. /******************************Public*Routine******************************\
  62. * VOID vIoSolidHorizontal
  63. *
  64. * Draws left-to-right x-major near-horizontal lines using solid fills.
  65. *
  66. * Assumes fgRop, BgRop, and Color are already set correctly.
  67. *
  68. \**************************************************************************/
  69. VOID vIoSolidHorizontal(
  70. PDEV* ppdev,
  71. STRIP* pStrip,
  72. LINESTATE* pLineState)
  73. {
  74. BYTE* pjPorts = ppdev->pjPorts;
  75. LONG cBpp = ppdev->cBpp;
  76. LONG lDelta = ppdev->lDelta;
  77. LONG cStrips = pStrip->cStrips;
  78. PLONG pStrips = pStrip->alStrips;
  79. LONG x = pStrip->ptlStart.x;
  80. LONG y = pStrip->ptlStart.y;
  81. LONG xy = PELS_TO_BYTES(x) + (lDelta * y);
  82. LONG yInc = 1;
  83. LONG i;
  84. DISPDBG((2,"vIoSolidHorizontal"));
  85. if (!(pStrip->flFlips & FL_FLIP_V))
  86. {
  87. //
  88. // Horizontal strips ->
  89. // ->
  90. //
  91. for (i = 0; i < cStrips; i++)
  92. {
  93. IO_DRAW_HORZ_STRIP(xy, *pStrips, lDelta, cBpp);
  94. x += *pStrips;
  95. xy += PELS_TO_BYTES(*pStrips); // x+
  96. xy += lDelta; // y+
  97. pStrips++;
  98. }
  99. y += cStrips;
  100. }
  101. else
  102. {
  103. //
  104. // ->
  105. // Horizontal strips ->
  106. //
  107. for (i = 0; i < cStrips; i++)
  108. {
  109. IO_DRAW_HORZ_STRIP(xy, *pStrips, lDelta, cBpp);
  110. x += *pStrips;
  111. xy += PELS_TO_BYTES(*pStrips); // x+
  112. xy -= lDelta; // y+
  113. pStrips++;
  114. }
  115. y -= cStrips;
  116. }
  117. pStrip->ptlStart.x = x;
  118. pStrip->ptlStart.y = y;
  119. }
  120. /******************************Public*Routine******************************\
  121. * VOID vIoSolidVertical
  122. *
  123. * Draws left-to-right y-major near-vertical lines using solid fills.
  124. *
  125. \**************************************************************************/
  126. VOID vIoSolidVertical(
  127. PDEV* ppdev,
  128. STRIP* pStrip,
  129. LINESTATE* pLineState)
  130. {
  131. BYTE* pjPorts = ppdev->pjPorts;
  132. LONG cBpp = ppdev->cBpp;
  133. LONG lDelta = ppdev->lDelta;
  134. LONG cStrips = pStrip->cStrips;
  135. PLONG pStrips = pStrip->alStrips;
  136. LONG x = pStrip->ptlStart.x;
  137. LONG y = pStrip->ptlStart.y;
  138. LONG xy = PELS_TO_BYTES(x) + (lDelta * y);
  139. LONG i;
  140. DISPDBG((2,"vIoSolidVertical"));
  141. if (!(pStrip->flFlips & FL_FLIP_V))
  142. {
  143. //
  144. // |
  145. // Vertical strips v
  146. // |
  147. // v
  148. //
  149. for (i = 0; i < cStrips; i++)
  150. {
  151. IO_DRAW_VERT_STRIP(xy, *pStrips, lDelta, cBpp);
  152. y += *pStrips;
  153. xy += cBpp; // x+
  154. xy += (*pStrips * lDelta); // y+
  155. pStrips++;
  156. }
  157. }
  158. else
  159. {
  160. //
  161. // ^
  162. // Vertical strips |
  163. // ^
  164. // |
  165. //
  166. for (i = 0; i < cStrips; i++)
  167. {
  168. IO_DRAW_VERT_STRIP_FLIPPED(xy, *pStrips, lDelta, cBpp);
  169. y -= *pStrips;
  170. xy += cBpp; // x+
  171. xy -= (*pStrips * lDelta); // y-
  172. pStrips++;
  173. }
  174. }
  175. x += cStrips;
  176. pStrip->ptlStart.x = x;
  177. pStrip->ptlStart.y = y;
  178. }
  179. /******************************Public*Routine******************************\
  180. * VOID vIoStyledHorizontal
  181. *
  182. * Takes the list of strips that define the pixels that would be lit for
  183. * a solid line, and breaks them into styling chunks according to the
  184. * styling information that is passed in.
  185. *
  186. * This particular routine handles x-major lines that run left-to-right,
  187. * and are comprised of horizontal strips. It draws the dashes using
  188. * short-stroke vectors.
  189. *
  190. * The performance of this routine could be improved significantly if
  191. * anyone cared enough about styled lines improve it.
  192. *
  193. \**************************************************************************/
  194. VOID vIoStyledHorizontal(
  195. PDEV* ppdev,
  196. STRIP* pstrip,
  197. LINESTATE* pls)
  198. {
  199. BYTE* pjPorts = ppdev->pjPorts;
  200. LONG cBpp = ppdev->cBpp;
  201. LONG lDelta = ppdev->lDelta;
  202. LONG x = pstrip->ptlStart.x; // x position of start of first strip
  203. LONG y = pstrip->ptlStart.y; // y position of start of first strip
  204. LONG xy = PELS_TO_BYTES(x) + (lDelta * y);
  205. LONG* plStrip = pstrip->alStrips; // Points to current strip
  206. LONG cStrips = pstrip->cStrips; // Total number of strips we'll do
  207. LONG dy;
  208. LONG dylDelta;
  209. LONG cStyle;
  210. LONG cStrip;
  211. LONG cThis;
  212. ULONG bIsGap;
  213. if (pstrip->flFlips & FL_FLIP_V)
  214. {
  215. // The minor direction of the line is 90 degrees, and the major
  216. // direction is 0 (it's a left-to-right x-major line going up):
  217. dy = -1;
  218. dylDelta = -lDelta;
  219. }
  220. else
  221. {
  222. // The minor direction of the line is 270 degrees, and the major
  223. // direction is 0 (it's a left-to-right x-major line going down):
  224. dy = 1;
  225. dylDelta = lDelta;
  226. }
  227. cStrip = *plStrip; // Number of pels in first strip
  228. cStyle = pls->spRemaining; // Number of pels in first 'gap' or 'dash'
  229. bIsGap = pls->ulStyleMask; // Tells whether in a 'gap' or a 'dash'
  230. // ulStyleMask is non-zero if we're in the middle of a 'gap',
  231. // and zero if we're in the middle of a 'dash':
  232. if (bIsGap)
  233. goto SkipAGap;
  234. else
  235. goto OutputADash;
  236. PrepareToSkipAGap:
  237. // Advance in the style-state array, so that we can find the next
  238. // 'dot' that we'll have to display:
  239. bIsGap = ~bIsGap;
  240. pls->psp++;
  241. if (pls->psp > pls->pspEnd)
  242. pls->psp = pls->pspStart;
  243. cStyle = *pls->psp;
  244. // If 'cStrip' is zero, we also need a new strip:
  245. if (cStrip != 0)
  246. goto SkipAGap;
  247. // Here, we're in the middle of a 'gap' where we don't have to
  248. // display anything. We simply cycle through all the strips
  249. // we can, keeping track of the current position, until we run
  250. // out of 'gap':
  251. while (TRUE)
  252. {
  253. // Each time we loop, we move to a new scan and need a new strip:
  254. y += dy;
  255. xy += dylDelta;
  256. plStrip++;
  257. cStrips--;
  258. if (cStrips == 0)
  259. goto AllDone;
  260. cStrip = *plStrip;
  261. SkipAGap:
  262. cThis = min(cStrip, cStyle);
  263. cStyle -= cThis;
  264. cStrip -= cThis;
  265. x += cThis;
  266. xy += PELS_TO_BYTES(cThis);
  267. if (cStyle == 0)
  268. goto PrepareToOutputADash;
  269. }
  270. PrepareToOutputADash:
  271. // Advance in the style-state array, so that we can find the next
  272. // 'dot' that we'll have to display:
  273. bIsGap = ~bIsGap;
  274. pls->psp++;
  275. if (pls->psp > pls->pspEnd)
  276. pls->psp = pls->pspStart;
  277. cStyle = *pls->psp;
  278. // If 'cStrip' is zero, we also need a new strip.
  279. if (cStrip != 0)
  280. {
  281. // There's more to be done in the current strip:
  282. goto OutputADash;
  283. }
  284. // We've finished with the current strip:
  285. while (TRUE)
  286. {
  287. // Each time we loop, we move to a new scan and need a new strip:
  288. y += dy;
  289. xy += dylDelta;
  290. plStrip++;
  291. cStrips--;
  292. if (cStrips == 0)
  293. goto AllDone;
  294. cStrip = *plStrip;
  295. OutputADash:
  296. cThis = min(cStrip, cStyle);
  297. cStyle -= cThis;
  298. cStrip -= cThis;
  299. IO_DRAW_HORZ_STRIP(xy, cThis, lDelta, cBpp);
  300. x += cThis;
  301. xy += PELS_TO_BYTES(cThis); // x+
  302. if (cStyle == 0)
  303. goto PrepareToSkipAGap;
  304. }
  305. AllDone:
  306. // Update our state variables so that the next line can continue
  307. // where we left off:
  308. pls->spRemaining = cStyle;
  309. pls->ulStyleMask = bIsGap;
  310. pstrip->ptlStart.x = x;
  311. pstrip->ptlStart.y = y;
  312. }
  313. /******************************Public*Routine******************************\
  314. * VOID vIoStyledVertical
  315. *
  316. * Takes the list of strips that define the pixels that would be lit for
  317. * a solid line, and breaks them into styling chunks according to the
  318. * styling information that is passed in.
  319. *
  320. * This particular routine handles y-major lines that run left-to-right,
  321. * and are comprised of vertical strips. It draws the dashes using
  322. * short-stroke vectors.
  323. *
  324. * The performance of this routine could be improved significantly if
  325. * anyone cared enough about styled lines improve it.
  326. *
  327. \**************************************************************************/
  328. VOID vIoStyledVertical(
  329. PDEV* ppdev,
  330. STRIP* pstrip,
  331. LINESTATE* pls)
  332. {
  333. BYTE* pjPorts = ppdev->pjPorts;
  334. LONG cBpp = ppdev->cBpp;
  335. LONG lDelta = ppdev->lDelta;
  336. LONG x = pstrip->ptlStart.x; // x position of start of first strip
  337. LONG y = pstrip->ptlStart.y; // y position of start of first strip
  338. LONG xy = PELS_TO_BYTES(x) + (lDelta * y);
  339. LONG* plStrip = pstrip->alStrips; // Points to current strip
  340. LONG cStrips = pstrip->cStrips; // Total number of strips we'll do
  341. LONG dy;
  342. LONG dylDelta;
  343. LONG cStyle;
  344. LONG cStrip;
  345. LONG cThis;
  346. ULONG bIsGap;
  347. if (pstrip->flFlips & FL_FLIP_V)
  348. {
  349. // The minor direction of the line is 0 degrees, and the major
  350. // direction is 90 (it's a left-to-right y-major line going up):
  351. dy = -1;
  352. dylDelta = -lDelta;
  353. }
  354. else
  355. {
  356. // The minor direction of the line is 0 degrees, and the major
  357. // direction is 270 (it's a left-to-right y-major line going down):
  358. dy = 1;
  359. dylDelta = lDelta;
  360. }
  361. cStrip = *plStrip; // Number of pels in first strip
  362. cStyle = pls->spRemaining; // Number of pels in first 'gap' or 'dash'
  363. bIsGap = pls->ulStyleMask; // Tells whether in a 'gap' or a 'dash'
  364. // ulStyleMask is non-zero if we're in the middle of a 'gap',
  365. // and zero if we're in the middle of a 'dash':
  366. if (bIsGap)
  367. goto SkipAGap;
  368. else
  369. goto OutputADash;
  370. PrepareToSkipAGap:
  371. // Advance in the style-state array, so that we can find the next
  372. // 'dot' that we'll have to display:
  373. bIsGap = ~bIsGap;
  374. pls->psp++;
  375. if (pls->psp > pls->pspEnd)
  376. pls->psp = pls->pspStart;
  377. cStyle = *pls->psp;
  378. // If 'cStrip' is zero, we also need a new strip:
  379. if (cStrip != 0)
  380. goto SkipAGap;
  381. // Here, we're in the middle of a 'gap' where we don't have to
  382. // display anything. We simply cycle through all the strips
  383. // we can, keeping track of the current position, until we run
  384. // out of 'gap':
  385. while (TRUE)
  386. {
  387. // Each time we loop, we move to a new column and need a new strip:
  388. xy += cBpp;
  389. x++;
  390. plStrip++;
  391. cStrips--;
  392. if (cStrips == 0)
  393. goto AllDone;
  394. cStrip = *plStrip;
  395. SkipAGap:
  396. cThis = min(cStrip, cStyle);
  397. cStyle -= cThis;
  398. cStrip -= cThis;
  399. if (dy > 0)
  400. {
  401. y += cThis;
  402. xy += (cThis * lDelta);
  403. }
  404. else
  405. {
  406. y -= cThis;
  407. xy -= (cThis * lDelta);
  408. }
  409. if (cStyle == 0)
  410. goto PrepareToOutputADash;
  411. }
  412. PrepareToOutputADash:
  413. // Advance in the style-state array, so that we can find the next
  414. // 'dot' that we'll have to display:
  415. bIsGap = ~bIsGap;
  416. pls->psp++;
  417. if (pls->psp > pls->pspEnd)
  418. pls->psp = pls->pspStart;
  419. cStyle = *pls->psp;
  420. // If 'cStrip' is zero, we also need a new strip.
  421. if (cStrip != 0)
  422. {
  423. // There's more to be done in the current strip:
  424. goto OutputADash;
  425. }
  426. // We've finished with the current strip:
  427. while (TRUE)
  428. {
  429. // Each time we loop, we move to a new column and need a new strip:
  430. xy += cBpp;
  431. x++;
  432. plStrip++;
  433. cStrips--;
  434. if (cStrips == 0)
  435. goto AllDone;
  436. cStrip = *plStrip;
  437. OutputADash:
  438. cThis = min(cStrip, cStyle);
  439. cStyle -= cThis;
  440. cStrip -= cThis;
  441. if (dy <= 0)
  442. {
  443. IO_DRAW_VERT_STRIP_FLIPPED(xy, cThis, lDelta, cBpp);
  444. y -= cThis; // y-
  445. xy -= (cThis * lDelta); // y-
  446. }
  447. else
  448. {
  449. IO_DRAW_VERT_STRIP(xy, cThis, lDelta, cBpp);
  450. y += cThis; // y+
  451. xy += (cThis * lDelta); // y+
  452. }
  453. if (cStyle == 0)
  454. goto PrepareToSkipAGap;
  455. }
  456. AllDone:
  457. // Update our state variables so that the next line can continue
  458. // where we left off:
  459. pls->spRemaining = cStyle;
  460. pls->ulStyleMask = bIsGap;
  461. pstrip->ptlStart.x = x;
  462. pstrip->ptlStart.y = y;
  463. }