Leaked source code of windows server 2003
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.

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