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.

420 lines
11 KiB

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