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.

559 lines
16 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: Lineto.c
  3. *
  4. * Implements DrvLineTo.
  5. *
  6. * Copyright (c) 1995 Microsoft Corporation
  7. \**************************************************************************/
  8. #include "precomp.h"
  9. LONG gai32LineBias[] = { 0, 0, 0, 1, 1, 1, 0, 1 };
  10. LONG gai64LineBias[] = { 0, 0, 1, 1, 0, 1, 0, 1 };
  11. /******************************Public*Routine******************************\
  12. * VOID vM64LineToTrivial
  13. *
  14. * Draws a single solid integer-only unclipped cosmetic line for the mach64.
  15. *
  16. \**************************************************************************/
  17. VOID vM64LineToTrivial(
  18. PDEV* ppdev,
  19. LONG x, // Passed in x1
  20. LONG y, // Passed in y1
  21. LONG dx, // Passed in x2
  22. LONG dy, // Passed in y2
  23. ULONG iSolidColor, // -1 means hardware is already set up
  24. MIX mix,
  25. RECTL* prclClip) // not used
  26. {
  27. BYTE* pjMmBase;
  28. FLONG flQuadrant;
  29. pjMmBase = ppdev->pjMmBase;
  30. if (iSolidColor == (ULONG) -1)
  31. {
  32. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 7);
  33. }
  34. else
  35. {
  36. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 10);
  37. M64_OD(pjMmBase, DP_MIX, gaul64HwMixFromMix[mix & 0xf]);
  38. M64_OD(pjMmBase, DP_FRGD_CLR, iSolidColor);
  39. M64_OD(pjMmBase, DP_SRC, DP_SRC_Always1 | DP_SRC_FrgdClr << 8);
  40. }
  41. M64_OD(pjMmBase, DST_Y_X, PACKXY(x, y));
  42. flQuadrant = (DST_CNTL_XDir | DST_CNTL_YDir);
  43. dx -= x;
  44. if (dx < 0)
  45. {
  46. dx = -dx;
  47. flQuadrant &= ~DST_CNTL_XDir;
  48. }
  49. dy -= y;
  50. if (dy < 0)
  51. {
  52. dy = -dy;
  53. flQuadrant &= ~DST_CNTL_YDir;
  54. }
  55. if (dy > dx)
  56. {
  57. register LONG l;
  58. l = dy;
  59. dy = dx;
  60. dx = l; // Swap 'dx' and 'dy'
  61. flQuadrant |= DST_CNTL_YMajor;
  62. }
  63. M64_OD(pjMmBase, DST_CNTL, flQuadrant | DST_CNTL_LastPel);
  64. M64_OD(pjMmBase, DST_BRES_ERR, (dy + dy - dx - gai64LineBias[flQuadrant]) >> 1);
  65. M64_OD(pjMmBase, DST_BRES_INC, dy);
  66. M64_OD(pjMmBase, DST_BRES_DEC, dy - dx);
  67. M64_OD(pjMmBase, DST_BRES_LNTH, dx);
  68. // Since we don't use a default context, we must restore registers:
  69. M64_OD(pjMmBase, DST_CNTL, DST_CNTL_XDir | DST_CNTL_YDir);
  70. }
  71. VOID vM64LineToTrivial24(
  72. PDEV* ppdev,
  73. LONG x, // Passed in x1
  74. LONG y, // Passed in y1
  75. LONG dx, // Passed in x2
  76. LONG dy, // Passed in y2
  77. ULONG iSolidColor, // -1 means hardware is already set up
  78. MIX mix,
  79. RECTL* prclClip) // required for Bresenham algorithm
  80. {
  81. BYTE* pjMmBase = ppdev->pjMmBase;
  82. FLONG flQuadrant;
  83. LONG x2 = dx, y2 = dy;
  84. if (iSolidColor != (ULONG) -1)
  85. {
  86. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 3);
  87. M64_OD(pjMmBase, DP_MIX, gaul64HwMixFromMix[mix & 0xf]);
  88. M64_OD(pjMmBase, DP_FRGD_CLR, iSolidColor);
  89. M64_OD(pjMmBase, DP_SRC, DP_SRC_Always1 | DP_SRC_FrgdClr << 8);
  90. }
  91. flQuadrant = (DST_CNTL_XDir | DST_CNTL_YDir);
  92. dx -= x;
  93. if (dx < 0)
  94. {
  95. dx = -dx;
  96. flQuadrant &= ~DST_CNTL_XDir;
  97. }
  98. dy -= y;
  99. if (dy < 0)
  100. {
  101. dy = -dy;
  102. flQuadrant &= ~DST_CNTL_YDir;
  103. }
  104. if (dy > dx)
  105. {
  106. register LONG l;
  107. l = dy;
  108. dy = dx;
  109. dx = l; // Swap 'dx' and 'dy'
  110. flQuadrant |= DST_CNTL_YMajor;
  111. }
  112. if (y == y2) // Horizontal line
  113. {
  114. x *= 3;
  115. dx *= 3;
  116. if (! (flQuadrant & DST_CNTL_XDir))
  117. x += 2; // From right to left, start with the Blue byte.
  118. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 5);
  119. M64_OD(pjMmBase, DP_SRC, DP_SRC_FrgdClr << 8 );
  120. M64_OD(pjMmBase, DST_CNTL, flQuadrant | DST_CNTL_24_RotEna | ((x/4 % 6) << 8) );
  121. M64_OD(pjMmBase, DST_Y_X, PACKXY(x, y) );
  122. M64_OD(pjMmBase, DST_HEIGHT_WIDTH, PACKPAIR(1, dx) );
  123. // Since we don't use a default context, we must restore registers:
  124. M64_OD(pjMmBase, DST_CNTL, DST_CNTL_XDir | DST_CNTL_YDir);
  125. }
  126. else if (x == x2) // Vertical line
  127. {
  128. x *= 3;
  129. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 5);
  130. M64_OD(pjMmBase, DP_SRC, DP_SRC_FrgdClr << 8 );
  131. M64_OD(pjMmBase, DST_CNTL, flQuadrant | DST_CNTL_24_RotEna | ((x/4 % 6) << 8) );
  132. M64_OD(pjMmBase, DST_Y_X, PACKXY(x, y) );
  133. M64_OD(pjMmBase, DST_HEIGHT_WIDTH, PACKPAIR(dx, 3) );
  134. // Since we don't use a default context, we must restore registers:
  135. M64_OD(pjMmBase, DST_CNTL, DST_CNTL_XDir | DST_CNTL_YDir);
  136. }
  137. else
  138. {
  139. BYTE *pjDest, *pjScreen = ppdev->pjScreen;
  140. BYTE red, green, blue;
  141. LONG bres_err, bres_inc, bres_dec, bres_len;
  142. LONG lDelta = ppdev->lDelta;
  143. MIX hw_mix;
  144. hw_mix = gaul64HwMixFromMix[mix & 0xf] >> 16;
  145. bres_err = (dy + dy - dx - gai64LineBias[flQuadrant]) >> 1;
  146. bres_inc = dy;
  147. bres_dec = dy - dx;
  148. bres_len = dx;
  149. // Separate into color bytes.
  150. red = (BYTE) ((iSolidColor & ppdev->flRed) >> REDSHIFT);
  151. green = (BYTE) ((iSolidColor & ppdev->flGreen) >> GREENSHIFT);
  152. blue = (BYTE) ((iSolidColor & ppdev->flBlue) >> BLUESHIFT);
  153. vM64QuietDown(ppdev, pjMmBase);
  154. // Execute 24bpp Bresenham algorithm.
  155. while (bres_len-- > 0)
  156. {
  157. // Write pel. Check for clipping. Last pel enabled.
  158. if (prclClip == NULL
  159. || x >= prclClip->left
  160. && x < prclClip->right
  161. && y >= prclClip->top
  162. && y < prclClip->bottom )
  163. {
  164. pjDest = pjScreen + y*lDelta + x*3;
  165. switch (hw_mix)
  166. {
  167. case 0: // NOT dst
  168. *pjDest = ~*pjDest++;
  169. *pjDest = ~*pjDest++;
  170. *pjDest = ~*pjDest;
  171. break;
  172. case 1: // "0"
  173. *pjDest++ = 0;
  174. *pjDest++ = 0;
  175. *pjDest = 0;
  176. break;
  177. case 2: // "1"
  178. *pjDest++ = 0xFF;
  179. *pjDest++ = 0xFF;
  180. *pjDest = 0xFF;
  181. break;
  182. case 3: // dst
  183. break;
  184. case 4: // NOT src
  185. *pjDest++ = ~blue;
  186. *pjDest++ = ~green;
  187. *pjDest = ~red;
  188. break;
  189. case 5: // dst XOR src
  190. *pjDest++ ^= blue;
  191. *pjDest++ ^= green;
  192. *pjDest ^= red;
  193. break;
  194. case 6: // NOT dst XOR src
  195. *pjDest = ~*pjDest++ ^ blue;
  196. *pjDest = ~*pjDest++ ^ green;
  197. *pjDest = ~*pjDest ^ red;
  198. break;
  199. case 7: // src
  200. *pjDest++ = blue;
  201. *pjDest++ = green;
  202. *pjDest = red;
  203. break;
  204. case 8: // NOT dst OR NOT src
  205. *pjDest = ~*pjDest++ | ~blue;
  206. *pjDest = ~*pjDest++ | ~green;
  207. *pjDest = ~*pjDest | ~red;
  208. break;
  209. case 9: // dst OR NOT src
  210. *pjDest++ |= ~blue;
  211. *pjDest++ |= ~green;
  212. *pjDest |= ~red;
  213. break;
  214. case 0xA: // NOT dst OR src
  215. *pjDest = ~*pjDest++ | blue;
  216. *pjDest = ~*pjDest++ | green;
  217. *pjDest = ~*pjDest | red;
  218. break;
  219. case 0xB: // dst OR src
  220. *pjDest++ |= blue;
  221. *pjDest++ |= green;
  222. *pjDest |= red;
  223. break;
  224. case 0xC: // dst AND src
  225. *pjDest++ &= blue;
  226. *pjDest++ &= green;
  227. *pjDest &= red;
  228. break;
  229. case 0xD: // NOT dst AND src
  230. *pjDest = ~*pjDest++ & blue;
  231. *pjDest = ~*pjDest++ & green;
  232. *pjDest = ~*pjDest & red;
  233. break;
  234. case 0xE: // dst AND NOT src
  235. *pjDest++ &= ~blue;
  236. *pjDest++ &= ~green;
  237. *pjDest &= ~red;
  238. break;
  239. case 0xF: // NOT dst AND NOT src
  240. *pjDest = ~*pjDest++ & ~blue;
  241. *pjDest = ~*pjDest++ & ~green;
  242. *pjDest = ~*pjDest & ~red;
  243. break;
  244. case 0x17:
  245. *pjDest = ((*pjDest++) + blue)/2;
  246. *pjDest = ((*pjDest++) + green)/2;
  247. *pjDest = (*pjDest + red)/2;
  248. break;
  249. }
  250. }
  251. if (flQuadrant & DST_CNTL_YMajor)
  252. {
  253. if (flQuadrant & DST_CNTL_YDir)
  254. y++;
  255. else
  256. y--;
  257. if (bres_err >= 0)
  258. {
  259. bres_err += bres_dec;
  260. if (flQuadrant & DST_CNTL_XDir)
  261. x++;
  262. else
  263. x--;
  264. }
  265. else
  266. bres_err += bres_inc;
  267. }
  268. else
  269. {
  270. if (flQuadrant & DST_CNTL_XDir)
  271. x++;
  272. else
  273. x--;
  274. if (bres_err >= 0)
  275. {
  276. bres_err += bres_dec;
  277. if (flQuadrant & DST_CNTL_YDir)
  278. y++;
  279. else
  280. y--;
  281. }
  282. else
  283. bres_err += bres_inc;
  284. }
  285. }
  286. }
  287. }
  288. /******************************Public*Routine******************************\
  289. * VOID vM32LineToTrivial
  290. *
  291. * Draws a single solid integer-only unclipped cosmetic line for the mach32
  292. * using memory-mapped I/O.
  293. *
  294. * See vSetStrips and bIntgerLine_M8 from the old driver.
  295. *
  296. \**************************************************************************/
  297. VOID vM32LineToTrivial(
  298. PDEV* ppdev,
  299. LONG x, // Passed in x1
  300. LONG y, // Passed in y1
  301. LONG dx, // Passed in x2
  302. LONG dy, // Passed in y2
  303. ULONG iSolidColor, // -1 means hardware is already set up
  304. MIX mix,
  305. RECTL* prclClip) // not used
  306. {
  307. BYTE* pjMmBase;
  308. FLONG flQuadrant;
  309. pjMmBase = ppdev->pjMmBase;
  310. if (iSolidColor == (ULONG) -1)
  311. {
  312. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 7);
  313. }
  314. else
  315. {
  316. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 11);
  317. M32_OW(pjMmBase, DP_CONFIG, FG_COLOR_SRC_FG | DRAW | WRITE);
  318. M32_OW(pjMmBase, FRGD_MIX, FOREGROUND_COLOR | gaul32HwMixFromMix[mix & 0xf]);
  319. M32_OW(pjMmBase, FRGD_COLOR, iSolidColor);
  320. M32_OW(pjMmBase, MULTIFUNC_CNTL, DATA_EXTENSION | ALL_ONES);
  321. }
  322. M32_OW(pjMmBase, CUR_X, x);
  323. M32_OW(pjMmBase, CUR_Y, y);
  324. flQuadrant = (XPOSITIVE | YPOSITIVE);
  325. dx -= x;
  326. if (dx < 0)
  327. {
  328. dx = -dx;
  329. flQuadrant &= ~XPOSITIVE;
  330. }
  331. dy -= y;
  332. if (dy < 0)
  333. {
  334. dy = -dy;
  335. flQuadrant &= ~YPOSITIVE;
  336. }
  337. if (dy > dx)
  338. {
  339. register LONG l;
  340. l = dy;
  341. dy = dx;
  342. dx = l; // Swap 'dx' and 'dy'
  343. flQuadrant |= YMAJOR;
  344. }
  345. M32_OW(pjMmBase, LINEDRAW_OPT, flQuadrant | LAST_PEL_OFF);
  346. M32_OW(pjMmBase, ERR_TERM, (dy + dy - dx - gai32LineBias[flQuadrant >> 5]) >> 1);
  347. M32_OW(pjMmBase, AXSTP, dy);
  348. M32_OW(pjMmBase, DIASTP, dy - dx);
  349. M32_OW(pjMmBase, BRES_COUNT, dx);
  350. }
  351. /******************************Public*Routine******************************\
  352. * VOID vI32LineToTrivial
  353. *
  354. * Draws a single solid integer-only unclipped cosmetic line for the mach32
  355. * using I/O-mapped registers.
  356. *
  357. * See vSetStrips and bIntgerLine_M8 from the old driver.
  358. *
  359. \**************************************************************************/
  360. VOID vI32LineToTrivial(
  361. PDEV* ppdev,
  362. LONG x, // Passed in x1
  363. LONG y, // Passed in y1
  364. LONG dx, // Passed in x2
  365. LONG dy, // Passed in y2
  366. ULONG iSolidColor, // -1 means hardware is already set up
  367. MIX mix,
  368. RECTL* prclClip) // not used
  369. {
  370. BYTE* pjIoBase;
  371. FLONG flQuadrant;
  372. pjIoBase = ppdev->pjIoBase;
  373. if (iSolidColor == (ULONG) -1)
  374. {
  375. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 7);
  376. }
  377. else
  378. {
  379. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 11);
  380. I32_OW(pjIoBase, DP_CONFIG, FG_COLOR_SRC_FG | DRAW | WRITE);
  381. I32_OW(pjIoBase, FRGD_MIX, FOREGROUND_COLOR | gaul32HwMixFromMix[mix & 0xf]);
  382. I32_OW(pjIoBase, FRGD_COLOR, iSolidColor);
  383. I32_OW(pjIoBase, MULTIFUNC_CNTL, DATA_EXTENSION | ALL_ONES);
  384. }
  385. I32_OW(pjIoBase, CUR_X, x);
  386. I32_OW(pjIoBase, CUR_Y, y);
  387. flQuadrant = (XPOSITIVE | YPOSITIVE);
  388. dx -= x;
  389. if (dx < 0)
  390. {
  391. dx = -dx;
  392. flQuadrant &= ~XPOSITIVE;
  393. }
  394. dy -= y;
  395. if (dy < 0)
  396. {
  397. dy = -dy;
  398. flQuadrant &= ~YPOSITIVE;
  399. }
  400. if (dy > dx)
  401. {
  402. register LONG l;
  403. l = dy;
  404. dy = dx;
  405. dx = l; // Swap 'dx' and 'dy'
  406. flQuadrant |= YMAJOR;
  407. }
  408. I32_OW(pjIoBase, LINEDRAW_OPT, flQuadrant | LAST_PEL_OFF);
  409. I32_OW(pjIoBase, ERR_TERM, (dy + dy - dx - gai32LineBias[flQuadrant >> 5]) >> 1);
  410. I32_OW(pjIoBase, AXSTP, dy);
  411. I32_OW(pjIoBase, DIASTP, dy - dx);
  412. I32_OW(pjIoBase, BRES_COUNT, dx);
  413. }
  414. /******************************Public*Routine******************************\
  415. * BOOL DrvLineTo(pso, pco, pbo, x1, y1, x2, y2, prclBounds, mix)
  416. *
  417. * Draws a single solid integer-only cosmetic line.
  418. *
  419. \**************************************************************************/
  420. #if TARGET_BUILD > 351
  421. BOOL DrvLineTo(
  422. SURFOBJ* pso,
  423. CLIPOBJ* pco,
  424. BRUSHOBJ* pbo,
  425. LONG x1,
  426. LONG y1,
  427. LONG x2,
  428. LONG y2,
  429. RECTL* prclBounds,
  430. MIX mix)
  431. {
  432. PDEV* ppdev;
  433. DSURF* pdsurf;
  434. OH* poh;
  435. LONG xOffset;
  436. LONG yOffset;
  437. BOOL bRet;
  438. // Pass the surface off to GDI if it's a device bitmap that we've
  439. // converted to a DIB:
  440. pdsurf = (DSURF*) pso->dhsurf;
  441. if (pdsurf->dt == DT_DIB)
  442. {
  443. return(EngLineTo(pdsurf->pso, pco, pbo, x1, y1, x2, y2, prclBounds, mix));
  444. }
  445. // We'll be drawing to the screen or an off-screen DFB; copy the surface's
  446. // offset now so that we won't need to refer to the DSURF again:
  447. poh = pdsurf->poh;
  448. ppdev = (PDEV*) pso->dhpdev;
  449. xOffset = poh->x;
  450. yOffset = poh->y;
  451. x1 += xOffset;
  452. x2 += xOffset;
  453. y1 += yOffset;
  454. y2 += yOffset;
  455. bRet = TRUE;
  456. if (pco == NULL)
  457. {
  458. ppdev->pfnLineToTrivial(ppdev, x1, y1, x2, y2, pbo->iSolidColor, mix, NULL);
  459. }
  460. else if ((pco->iDComplexity <= DC_RECT) &&
  461. (prclBounds->left >= MIN_INTEGER_BOUND) &&
  462. (prclBounds->top >= MIN_INTEGER_BOUND) &&
  463. (prclBounds->right <= MAX_INTEGER_BOUND) &&
  464. (prclBounds->bottom <= MAX_INTEGER_BOUND))
  465. {
  466. ppdev->xOffset = xOffset;
  467. ppdev->yOffset = yOffset;
  468. vSetClipping(ppdev, &pco->rclBounds);
  469. // may need rclBounds for clipping in 24bpp:
  470. ppdev->pfnLineToTrivial(ppdev, x1, y1, x2, y2, pbo->iSolidColor, mix, &pco->rclBounds);
  471. vResetClipping(ppdev);
  472. }
  473. else
  474. {
  475. bRet = FALSE;
  476. }
  477. return(bRet);
  478. }
  479. #endif
  480.