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.

375 lines
9.9 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: str.c
  3. *
  4. * Contains some 'C' inner-loop routines for our special-case StretchBlt.
  5. *
  6. * Copyright (c) 1993-1995 Microsoft Corporation
  7. \**************************************************************************/
  8. #include "precomp.h"
  9. /******************************Public*Routine******************************\
  10. *
  11. * Routine Name
  12. *
  13. * vDirectStretch8
  14. *
  15. * Routine Description:
  16. *
  17. * Stretch blt 8->8
  18. *
  19. * NOTE: This routine doesn't handle cases where the blt stretch starts
  20. * and ends in the same destination dword! vDirectStretchNarrow
  21. * is expected to have been called for that case.
  22. *
  23. * Arguments:
  24. *
  25. * pStrBlt - contains all params for blt
  26. *
  27. * Return Value:
  28. *
  29. * VOID
  30. *
  31. \**************************************************************************/
  32. VOID vDirectStretch8(
  33. STR_BLT* pStrBlt)
  34. {
  35. BYTE* pjSrc;
  36. BYTE* pjDstEnd;
  37. LONG WidthXAln;
  38. ULONG ulDst;
  39. ULONG xAccum;
  40. ULONG xTmp;
  41. ULONG yTmp;
  42. BYTE* pjOldScan;
  43. BYTE* pjBase;
  44. LONG cyDuplicate;
  45. PDEV* ppdev = pStrBlt->ppdev;
  46. LONG xDst = pStrBlt->XDstStart;
  47. LONG xSrc = pStrBlt->XSrcStart;
  48. BYTE* pjSrcScan = pStrBlt->pjSrcScan + xSrc;
  49. BYTE* pjDst = pStrBlt->pjDstScan + xDst;
  50. LONG yDst = pStrBlt->YDstStart;// + ppdev->yOffset;
  51. LONG yCount = pStrBlt->YDstCount;
  52. ULONG StartAln = (ULONG)((ULONG_PTR)pjDst & 0x03);
  53. LONG WidthX = pStrBlt->XDstEnd - xDst;
  54. ULONG EndAln = (ULONG)((ULONG_PTR)(pjDst + WidthX) & 0x03);
  55. ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
  56. ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
  57. ULONG yAccum = pStrBlt->ulYFracAccumulator;
  58. ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
  59. ULONG yInt = 0;
  60. LONG lDstStride = pStrBlt->lDeltaDst - WidthX;
  61. pjBase = ppdev->pjBase;
  62. WidthXAln = WidthX - EndAln - ((- (LONG) StartAln) & 0x03);
  63. //
  64. // if this is a shrinking blt, calc src scan line stride
  65. //
  66. if (pStrBlt->ulYDstToSrcIntCeil != 0)
  67. {
  68. yInt = pStrBlt->lDeltaSrc * pStrBlt->ulYDstToSrcIntCeil;
  69. }
  70. //
  71. // loop drawing each scan line
  72. //
  73. //
  74. // at least 7 wide (DST) blt
  75. //
  76. do {
  77. BYTE jSrc0,jSrc1,jSrc2,jSrc3;
  78. ULONG yTmp;
  79. pjSrc = pjSrcScan;
  80. xAccum = pStrBlt->ulXFracAccumulator;
  81. //
  82. // a single src scan line is being written
  83. //
  84. switch (StartAln) {
  85. case 1:
  86. jSrc0 = *pjSrc;
  87. xTmp = xAccum + xFrac;
  88. pjSrc = pjSrc + xInt + (xTmp < xAccum);
  89. *pjDst++ = jSrc0;
  90. xAccum = xTmp;
  91. case 2:
  92. jSrc0 = *pjSrc;
  93. xTmp = xAccum + xFrac;
  94. pjSrc = pjSrc + xInt + (xTmp < xAccum);
  95. *pjDst++ = jSrc0;
  96. xAccum = xTmp;
  97. case 3:
  98. jSrc0 = *pjSrc;
  99. xTmp = xAccum + xFrac;
  100. pjSrc = pjSrc + xInt + (xTmp < xAccum);
  101. *pjDst++ = jSrc0;
  102. xAccum = xTmp;
  103. }
  104. pjDstEnd = pjDst + WidthXAln;
  105. while (pjDst != pjDstEnd)
  106. {
  107. jSrc0 = *pjSrc;
  108. xTmp = xAccum + xFrac;
  109. pjSrc = pjSrc + xInt + (xTmp < xAccum);
  110. jSrc1 = *pjSrc;
  111. xAccum = xTmp + xFrac;
  112. pjSrc = pjSrc + xInt + (xAccum < xTmp);
  113. jSrc2 = *pjSrc;
  114. xTmp = xAccum + xFrac;
  115. pjSrc = pjSrc + xInt + (xTmp < xAccum);
  116. jSrc3 = *pjSrc;
  117. xAccum = xTmp + xFrac;
  118. pjSrc = pjSrc + xInt + (xAccum < xTmp);
  119. ulDst = (jSrc3 << 24) | (jSrc2 << 16) | (jSrc1 << 8) | jSrc0;
  120. *(PULONG)pjDst = ulDst;
  121. pjDst += 4;
  122. }
  123. switch (EndAln) {
  124. case 3:
  125. jSrc0 = *pjSrc;
  126. xTmp = xAccum + xFrac;
  127. pjSrc = pjSrc + xInt + (xTmp < xAccum);
  128. *pjDst++ = jSrc0;
  129. xAccum = xTmp;
  130. case 2:
  131. jSrc0 = *pjSrc;
  132. xTmp = xAccum + xFrac;
  133. pjSrc = pjSrc + xInt + (xTmp < xAccum);
  134. *pjDst++ = jSrc0;
  135. xAccum = xTmp;
  136. case 1:
  137. jSrc0 = *pjSrc;
  138. xTmp = xAccum + xFrac;
  139. pjSrc = pjSrc + xInt + (xTmp < xAccum);
  140. *pjDst++ = jSrc0;
  141. }
  142. pjOldScan = pjSrcScan;
  143. pjSrcScan += yInt;
  144. yTmp = yAccum + yFrac;
  145. if (yTmp < yAccum)
  146. {
  147. pjSrcScan += pStrBlt->lDeltaSrc;
  148. }
  149. yAccum = yTmp;
  150. pjDst = (pjDst + lDstStride);
  151. yDst++;
  152. yCount--;
  153. if ((yCount != 0) && (pjSrcScan == pjOldScan))
  154. {
  155. // It's an expanding stretch in 'y'; the scan we just laid down
  156. // will be copied at least once using the hardware:
  157. cyDuplicate = 0;
  158. do {
  159. cyDuplicate++;
  160. pjSrcScan += yInt;
  161. yTmp = yAccum + yFrac;
  162. if (yTmp < yAccum)
  163. {
  164. pjSrcScan += pStrBlt->lDeltaSrc;
  165. }
  166. yAccum = yTmp;
  167. pjDst = (pjDst + pStrBlt->lDeltaDst);
  168. yCount--;
  169. } while ((yCount != 0) && (pjSrcScan == pjOldScan));
  170. // The scan is to be copied 'cyDuplicate' times using the
  171. // hardware.
  172. do {
  173. CP_Y0(ppdev, pjBase, yDst - 1);
  174. CP_Y1(ppdev, pjBase, yDst - 1);
  175. CP_Y2(ppdev, pjBase, yDst);
  176. CP_Y3(ppdev, pjBase, yDst);
  177. yDst++;
  178. CP_START_BLT_WAIT(ppdev, pjBase);
  179. } while (--cyDuplicate != 0);
  180. }
  181. } while (yCount != 0);
  182. }
  183. /******************************Public*Routine******************************\
  184. *
  185. * Routine Name
  186. *
  187. * vDirectStretch16
  188. *
  189. * Routine Description:
  190. *
  191. * Stretch blt 16->16
  192. *
  193. * Arguments:
  194. *
  195. * pStrBlt - contains all params for blt
  196. *
  197. * Return Value:
  198. *
  199. * VOID
  200. *
  201. \**************************************************************************/
  202. VOID vDirectStretch16(
  203. STR_BLT* pStrBlt)
  204. {
  205. BYTE* pjOldScan;
  206. USHORT* pusSrc;
  207. USHORT* pusDstEnd;
  208. LONG WidthXAln;
  209. ULONG ulDst;
  210. ULONG xAccum;
  211. ULONG xTmp;
  212. ULONG yTmp;
  213. LONG cyDuplicate;
  214. BYTE* pjBase;
  215. PDEV* ppdev = pStrBlt->ppdev;
  216. LONG xDst = pStrBlt->XDstStart;
  217. LONG xSrc = pStrBlt->XSrcStart;
  218. BYTE* pjSrcScan = (pStrBlt->pjSrcScan) + xSrc * 2;
  219. USHORT* pusDst = (USHORT*)(pStrBlt->pjDstScan) + xDst;
  220. LONG yDst = pStrBlt->YDstStart;// + ppdev->yOffset;
  221. LONG yCount = pStrBlt->YDstCount;
  222. ULONG StartAln = (ULONG)(((ULONG_PTR)pusDst & 0x02) >> 1);
  223. LONG WidthX = pStrBlt->XDstEnd - xDst;
  224. ULONG EndAln = (ULONG)(((ULONG_PTR)(pusDst + WidthX) & 0x02) >> 1);
  225. ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
  226. ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
  227. ULONG yAccum = pStrBlt->ulYFracAccumulator;
  228. ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
  229. LONG lDstStride = pStrBlt->lDeltaDst - 2 * WidthX;
  230. ULONG yInt = 0;
  231. pjBase = ppdev->pjBase;
  232. WidthXAln = WidthX - EndAln - StartAln;
  233. //
  234. // if this is a shrinking blt, calc src scan line stride
  235. //
  236. if (pStrBlt->ulYDstToSrcIntCeil != 0)
  237. {
  238. yInt = pStrBlt->lDeltaSrc * pStrBlt->ulYDstToSrcIntCeil;
  239. }
  240. // Loop stretching each scan line
  241. do {
  242. USHORT usSrc0,usSrc1;
  243. ULONG yTmp;
  244. pusSrc = (USHORT*) pjSrcScan;
  245. xAccum = pStrBlt->ulXFracAccumulator;
  246. // A single source scan line is being written:
  247. if (StartAln)
  248. {
  249. usSrc0 = *pusSrc;
  250. xTmp = xAccum + xFrac;
  251. pusSrc = pusSrc + xInt + (xTmp < xAccum);
  252. *pusDst++ = usSrc0;
  253. xAccum = xTmp;
  254. }
  255. pusDstEnd = pusDst + WidthXAln;
  256. while (pusDst != pusDstEnd)
  257. {
  258. usSrc0 = *pusSrc;
  259. xTmp = xAccum + xFrac;
  260. pusSrc = pusSrc + xInt + (xTmp < xAccum);
  261. usSrc1 = *pusSrc;
  262. xAccum = xTmp + xFrac;
  263. pusSrc = pusSrc + xInt + (xAccum < xTmp);
  264. ulDst = (ULONG)((usSrc1 << 16) | usSrc0);
  265. *(ULONG*)pusDst = ulDst;
  266. pusDst+=2;
  267. }
  268. if (EndAln)
  269. {
  270. usSrc0 = *pusSrc;
  271. xTmp = xAccum + xFrac;
  272. pusSrc = pusSrc + xInt + (xTmp < xAccum);
  273. *pusDst++ = usSrc0;
  274. }
  275. pjOldScan = pjSrcScan;
  276. pjSrcScan += yInt;
  277. yTmp = yAccum + yFrac;
  278. if (yTmp < yAccum)
  279. {
  280. pjSrcScan += pStrBlt->lDeltaSrc;
  281. }
  282. yAccum = yTmp;
  283. pusDst = (USHORT*) ((BYTE*) pusDst + lDstStride);
  284. yDst++;
  285. yCount--;
  286. if ((yCount != 0) && (pjSrcScan == pjOldScan))
  287. {
  288. // It's an expanding stretch in 'y'; the scan we just laid down
  289. // will be copied at least once using the hardware:
  290. cyDuplicate = 0;
  291. do {
  292. cyDuplicate++;
  293. pjSrcScan += yInt;
  294. yTmp = yAccum + yFrac;
  295. if (yTmp < yAccum)
  296. {
  297. pjSrcScan += pStrBlt->lDeltaSrc;
  298. }
  299. yAccum = yTmp;
  300. pusDst = (USHORT*) ((BYTE*) pusDst + pStrBlt->lDeltaDst);
  301. yCount--;
  302. } while ((yCount != 0) && (pjSrcScan == pjOldScan));
  303. // The scan is to be copied 'cyDuplicate' times using the
  304. // hardware.
  305. do {
  306. CP_Y0(ppdev, pjBase, yDst - 1);
  307. CP_Y1(ppdev, pjBase, yDst - 1);
  308. CP_Y2(ppdev, pjBase, yDst);
  309. CP_Y3(ppdev, pjBase, yDst);
  310. yDst++;
  311. CP_START_BLT_WAIT(ppdev, pjBase);
  312. } while (--cyDuplicate != 0);
  313. }
  314. } while (yCount != 0);
  315. }