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.

444 lines
12 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: misc.c
  3. *
  4. * Miscellaneous common routines.
  5. *
  6. * Copyright (c) 1992-1996 Microsoft Corporation
  7. * Copyright (c) 1993-1996 Matrox Electronic Systems, Ltd.
  8. \**************************************************************************/
  9. #include "precomp.h"
  10. /******************************Public*Routine******************************\
  11. * BOOL bIntersect
  12. *
  13. * If 'prcl1' and 'prcl2' intersect, has a return value of TRUE and returns
  14. * the intersection in 'prclResult'. If they don't intersect, has a return
  15. * value of FALSE, and 'prclResult' is undefined.
  16. *
  17. \**************************************************************************/
  18. BOOL bIntersect(
  19. RECTL* prcl1,
  20. RECTL* prcl2,
  21. RECTL* prclResult)
  22. {
  23. prclResult->left = max(prcl1->left, prcl2->left);
  24. prclResult->right = min(prcl1->right, prcl2->right);
  25. if (prclResult->left < prclResult->right)
  26. {
  27. prclResult->top = max(prcl1->top, prcl2->top);
  28. prclResult->bottom = min(prcl1->bottom, prcl2->bottom);
  29. if (prclResult->top < prclResult->bottom)
  30. {
  31. return(TRUE);
  32. }
  33. }
  34. return(FALSE);
  35. }
  36. /******************************Public*Routine******************************\
  37. * LONG cIntersect
  38. *
  39. * This routine takes a list of rectangles from 'prclIn' and clips them
  40. * in-place to the rectangle 'prclClip'. The input rectangles don't
  41. * have to intersect 'prclClip'; the return value will reflect the
  42. * number of input rectangles that did intersect, and the intersecting
  43. * rectangles will be densely packed.
  44. *
  45. \**************************************************************************/
  46. LONG cIntersect(
  47. RECTL* prclClip,
  48. RECTL* prclIn, // List of rectangles
  49. LONG c) // Can be zero
  50. {
  51. LONG cIntersections;
  52. RECTL* prclOut;
  53. cIntersections = 0;
  54. prclOut = prclIn;
  55. for (; c != 0; prclIn++, c--)
  56. {
  57. prclOut->left = max(prclIn->left, prclClip->left);
  58. prclOut->right = min(prclIn->right, prclClip->right);
  59. if (prclOut->left < prclOut->right)
  60. {
  61. prclOut->top = max(prclIn->top, prclClip->top);
  62. prclOut->bottom = min(prclIn->bottom, prclClip->bottom);
  63. if (prclOut->top < prclOut->bottom)
  64. {
  65. prclOut++;
  66. cIntersections++;
  67. }
  68. }
  69. }
  70. return(cIntersections);
  71. }
  72. /******************************Public*Routine******************************\
  73. * VOID vResetClipping
  74. *
  75. \**************************************************************************/
  76. VOID vResetClipping(
  77. PDEV* ppdev)
  78. {
  79. BYTE* pjBase;
  80. ULONG ulYDstOrg;
  81. pjBase = ppdev->pjBase;
  82. ulYDstOrg = ppdev->ulYDstOrg; // MGA's linear offset
  83. CHECK_FIFO_SPACE(pjBase, 4);
  84. CP_WRITE(pjBase, DWG_CXLEFT, 0);
  85. CP_WRITE(pjBase, DWG_CXRIGHT, ppdev->cxMemory - 1);
  86. CP_WRITE(pjBase, DWG_CYTOP, ulYDstOrg);
  87. CP_WRITE(pjBase, DWG_CYBOT,
  88. (ppdev->cyMemory - 1) * ppdev->cxMemory + ulYDstOrg);
  89. }
  90. /******************************Public*Routine******************************\
  91. * VOID vSetClipping
  92. *
  93. \**************************************************************************/
  94. VOID vSetClipping(
  95. PDEV* ppdev,
  96. RECTL* prclClip) // In relative coordinates
  97. {
  98. BYTE* pjBase;
  99. ULONG ulYDstOrg;
  100. LONG xOffset;
  101. LONG yOffset;
  102. LONG cxMemory;
  103. pjBase = ppdev->pjBase;
  104. xOffset = ppdev->xOffset;
  105. CHECK_FIFO_SPACE(pjBase, 4);
  106. CP_WRITE(pjBase, DWG_CXLEFT, xOffset + prclClip->left);
  107. CP_WRITE(pjBase, DWG_CXRIGHT, xOffset + prclClip->right - 1);
  108. ulYDstOrg = ppdev->ulYDstOrg; // MGA's linear offset
  109. yOffset = ppdev->yOffset;
  110. cxMemory = ppdev->cxMemory;
  111. CP_WRITE(pjBase, DWG_CYTOP,
  112. (yOffset + prclClip->top) * cxMemory + ulYDstOrg);
  113. CP_WRITE(pjBase, DWG_CYBOT,
  114. (yOffset + prclClip->bottom - 1) * cxMemory + ulYDstOrg);
  115. }
  116. /******************************Public*Routine******************************\
  117. * VOID vAlignedCopy
  118. *
  119. * Copies the given portion of a bitmap, using dword alignment for the
  120. * screen. Note that this routine has no notion of banking.
  121. *
  122. * Updates ppjDst and ppjSrc to point to the beginning of the next scan.
  123. *
  124. \**************************************************************************/
  125. VOID vAlignedCopy(
  126. PDEV* ppdev,
  127. BYTE** ppjDst,
  128. LONG lDstDelta,
  129. BYTE** ppjSrc,
  130. LONG lSrcDelta,
  131. LONG cjScan,
  132. LONG cyScan,
  133. BOOL bDstIsScreen)
  134. {
  135. BYTE* pjDst;
  136. BYTE* pjSrc;
  137. LONG cjMiddle;
  138. LONG culMiddle;
  139. LONG cjStartPhase;
  140. LONG cjEndPhase;
  141. LONG i;
  142. BYTE* pjBase;
  143. pjBase= ppdev->pjBase;
  144. pjSrc = *ppjSrc;
  145. pjDst = *ppjDst;
  146. cjStartPhase = (LONG)((0 - ((bDstIsScreen) ? (ULONG_PTR) pjDst
  147. : (ULONG_PTR) pjSrc)) & 3);
  148. cjMiddle = cjScan - cjStartPhase;
  149. if (cjMiddle < 0)
  150. {
  151. cjStartPhase = 0;
  152. cjMiddle = cjScan;
  153. }
  154. lSrcDelta -= cjScan;
  155. lDstDelta -= cjScan; // Account for middle
  156. cjEndPhase = cjMiddle & 3;
  157. culMiddle = cjMiddle >> 2;
  158. ///////////////////////////////////////////////////////////////////
  159. // Portable bus-aligned copy
  160. //
  161. // 'memcpy' usually aligns to the destination, so we could call
  162. // it for that case, but unfortunately we can't be sure. We
  163. // always want to align to the frame buffer:
  164. if (bDstIsScreen)
  165. {
  166. START_DIRECT_ACCESS_STORM(ppdev, pjBase);
  167. // Align to the destination (implying that the source may be
  168. // unaligned):
  169. for (; cyScan > 0; cyScan--)
  170. {
  171. for (i = cjStartPhase; i > 0; i--)
  172. {
  173. *pjDst++ = *pjSrc++;
  174. }
  175. for (i = culMiddle; i > 0; i--)
  176. {
  177. *((ULONG*) pjDst) = *((ULONG UNALIGNED *) pjSrc);
  178. pjSrc += sizeof(ULONG);
  179. pjDst += sizeof(ULONG);
  180. }
  181. for (i = cjEndPhase; i > 0; i--)
  182. {
  183. *pjDst++ = *pjSrc++;
  184. }
  185. pjSrc += lSrcDelta;
  186. pjDst += lDstDelta;
  187. }
  188. }
  189. else
  190. {
  191. START_DIRECT_ACCESS_STORM_FOR_READ(ppdev, pjBase);
  192. // Align to the source (implying that the destination may be
  193. // unaligned):
  194. for (; cyScan > 0; cyScan--)
  195. {
  196. for (i = cjStartPhase; i > 0; i--)
  197. {
  198. *pjDst++ = *pjSrc++;
  199. }
  200. for (i = culMiddle; i > 0; i--)
  201. {
  202. *((ULONG UNALIGNED *) pjDst) = *((ULONG*) (pjSrc));
  203. pjSrc += sizeof(ULONG);
  204. pjDst += sizeof(ULONG);
  205. }
  206. for (i = cjEndPhase; i > 0; i--)
  207. {
  208. *pjDst++ = *pjSrc++;
  209. }
  210. pjSrc += lSrcDelta;
  211. pjDst += lDstDelta;
  212. }
  213. }
  214. END_DIRECT_ACCESS_STORM(ppdev, pjBase);
  215. *ppjSrc = pjSrc; // Save the updated pointers
  216. *ppjDst = pjDst;
  217. }
  218. /******************************Public*Routine******************************\
  219. * VOID vMilGetBitsLinear
  220. *
  221. * Copies the bits to the given surface from the screen, using the memory
  222. * aperture. Must be pre-clipped.
  223. *
  224. \**************************************************************************/
  225. VOID vMilGetBitsLinear(
  226. PDEV* ppdev,
  227. SURFOBJ* psoDst,
  228. RECTL* prclDst, // Absolute coordinates!
  229. POINTL* pptlSrc) // Absolute coordinates!
  230. {
  231. RECTL rclDraw;
  232. LONG cjOffset;
  233. LONG cyScan;
  234. LONG lDstDelta;
  235. LONG lSrcDelta;
  236. BYTE* pjDst;
  237. BYTE* pjSrc;
  238. LONG cjScan;
  239. LONG cjRemainder;
  240. DISPDBG((5, "vGetBitsLinear -- enter"));
  241. rclDraw.left = pptlSrc->x;
  242. rclDraw.top = pptlSrc->y;
  243. rclDraw.right = rclDraw.left + (prclDst->right - prclDst->left);
  244. rclDraw.bottom = rclDraw.top + (prclDst->bottom - prclDst->top);
  245. ASSERTDD((rclDraw.left >= 0) &&
  246. (rclDraw.top >= 0) &&
  247. (rclDraw.right <= ppdev->cxMemory) &&
  248. (rclDraw.bottom <= ppdev->cyMemory),
  249. "vGetBitsLinear: rectangle wasn't fully clipped");
  250. // Calculate the pointer to the upper-left corner of both rectangles:
  251. lSrcDelta = ppdev->lDelta;
  252. pjSrc = ppdev->pjScreen + rclDraw.top * lSrcDelta
  253. + (ppdev->cjPelSize * (rclDraw.left + ppdev->ulYDstOrg));
  254. lDstDelta = psoDst->lDelta;
  255. pjDst = (BYTE*) psoDst->pvScan0 + prclDst->top * lDstDelta
  256. + (ppdev->cjPelSize * prclDst->left);
  257. cjScan = ppdev->cjPelSize * (rclDraw.right - rclDraw.left);
  258. cyScan = (rclDraw.bottom - rclDraw.top);
  259. vAlignedCopy(ppdev, &pjDst, lDstDelta, &pjSrc, lSrcDelta, cjScan, cyScan,
  260. FALSE); // Screen is the source
  261. DISPDBG((5, "vGetBitsLinear -- exit"));
  262. }
  263. /******************************Public*Routine******************************\
  264. * VOID vMilPutBitsLinear
  265. *
  266. * Copies the bits from the given surface to the screen, using the memory
  267. * aperture. Must be pre-clipped.
  268. *
  269. \**************************************************************************/
  270. VOID vMilPutBitsLinear(
  271. PDEV* ppdev,
  272. SURFOBJ* psoSrc,
  273. RECTL* prclDst, // Absolute coordinates!
  274. POINTL* pptlSrc) // Absolute coordinates!
  275. {
  276. RECTL rclDraw;
  277. LONG cjOffset;
  278. LONG cyScan;
  279. LONG lDstDelta;
  280. LONG lSrcDelta;
  281. BYTE* pjDst;
  282. BYTE* pjSrc;
  283. LONG cjScan;
  284. LONG cjRemainder;
  285. DISPDBG((5, "vPutBitsLinear -- enter"));
  286. rclDraw = *prclDst;
  287. ASSERTDD((rclDraw.left >= 0) &&
  288. (rclDraw.top >= 0) &&
  289. (rclDraw.right <= ppdev->cxMemory) &&
  290. (rclDraw.bottom <= ppdev->cyMemory),
  291. "vPutBitsLinear: rectangle wasn't fully clipped");
  292. // Calculate the pointer to the upper-left corner of both rectangles:
  293. lDstDelta = ppdev->lDelta;
  294. pjDst = ppdev->pjScreen + rclDraw.top * lDstDelta
  295. + (ppdev->cjPelSize * (rclDraw.left + ppdev->ulYDstOrg));
  296. lSrcDelta = psoSrc->lDelta;
  297. pjSrc = (BYTE*) psoSrc->pvScan0 + (pptlSrc->y * lSrcDelta)
  298. + (ppdev->cjPelSize * pptlSrc->x);
  299. cjScan = ppdev->cjPelSize * (rclDraw.right - rclDraw.left);
  300. cyScan = (rclDraw.bottom - rclDraw.top);
  301. vAlignedCopy(ppdev, &pjDst, lDstDelta, &pjSrc, lSrcDelta, cjScan, cyScan,
  302. TRUE); // Screen is the dest
  303. DISPDBG((5, "vPutBitsLinear -- exit"));
  304. }
  305. /******************************Public*Routine******************************\
  306. * VOID vGetBits
  307. *
  308. * Copies the bits to the given surface from the screen, using the memory
  309. * aperture. Must be pre-clipped.
  310. *
  311. \**************************************************************************/
  312. VOID vGetBits(
  313. PDEV* ppdev,
  314. SURFOBJ* psoDst,
  315. RECTL* prclDst, // Absolute coordinates!
  316. POINTL* pptlSrc) // Absolute coordinates!
  317. {
  318. if (ppdev->ulBoardId == MGA_STORM)
  319. {
  320. vMilGetBitsLinear(ppdev, psoDst, prclDst, pptlSrc);
  321. }
  322. else if (ppdev->iBitmapFormat == BMF_8BPP)
  323. {
  324. vMgaGetBits8bpp(ppdev, psoDst, prclDst, pptlSrc);
  325. }
  326. else if (ppdev->iBitmapFormat == BMF_16BPP)
  327. {
  328. vMgaGetBits16bpp(ppdev, psoDst, prclDst, pptlSrc);
  329. }
  330. else
  331. {
  332. vMgaGetBits24bpp(ppdev, psoDst, prclDst, pptlSrc);
  333. }
  334. }
  335. /******************************Public*Routine******************************\
  336. * VOID vPutBits
  337. *
  338. * Copies the bits from the given surface to the screen, using the memory
  339. * aperture. Must be pre-clipped.
  340. *
  341. \**************************************************************************/
  342. VOID vPutBits(
  343. PDEV* ppdev,
  344. SURFOBJ* psoSrc,
  345. RECTL* prclDst, // Absolute coordinates!
  346. POINTL* pptlSrc) // Absolute coordinates!
  347. {
  348. LONG xOffset;
  349. LONG yOffset;
  350. if (ppdev->ulBoardId == MGA_STORM)
  351. {
  352. vMilPutBitsLinear(ppdev, psoSrc, prclDst, pptlSrc);
  353. }
  354. else
  355. {
  356. // 'vXferNative' takes relative coordinates, but we have absolute
  357. // coordinates here. Temporarily adjust our offset variables:
  358. xOffset = ppdev->xOffset;
  359. yOffset = ppdev->yOffset;
  360. ppdev->xOffset = 0;
  361. ppdev->yOffset = 0;
  362. vXferNative(ppdev, 1, prclDst, 0xCCCC, psoSrc, pptlSrc, prclDst, NULL);
  363. ppdev->xOffset = xOffset;
  364. ppdev->yOffset = yOffset;
  365. }
  366. }