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.

1467 lines
41 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: stretch.c
  3. *
  4. * Copyright (c) 1993-1995 Microsoft Corporation
  5. \**************************************************************************/
  6. #include "precomp.h"
  7. #define STRETCH_MAX_EXTENT 32767
  8. typedef DWORDLONG ULONGLONG;
  9. /******************************Public*Routine******************************\
  10. *
  11. * Routine Name
  12. *
  13. * vDirectStretch8Narrow
  14. *
  15. * Routine Description:
  16. *
  17. * Stretch blt 8->8 when the width is 7 or less
  18. *
  19. * Arguments:
  20. *
  21. * pStrBlt - contains all params for blt
  22. *
  23. * Return Value:
  24. *
  25. * VOID
  26. *
  27. \**************************************************************************/
  28. VOID vDirectStretch8Narrow(
  29. STR_BLT* pStrBlt)
  30. {
  31. BYTE* pjSrc;
  32. ULONG xAccum;
  33. ULONG xTmp;
  34. LONG xDst = pStrBlt->XDstStart;
  35. LONG xSrc = pStrBlt->XSrcStart;
  36. BYTE* pjSrcScan = pStrBlt->pjSrcScan + xSrc;
  37. BYTE* pjDst = pStrBlt->pjDstScan + xDst;
  38. LONG yCount = pStrBlt->YDstCount;
  39. LONG WidthX = pStrBlt->XDstEnd - xDst;
  40. ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
  41. ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
  42. ULONG yAccum = pStrBlt->ulYFracAccumulator;
  43. ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
  44. LONG lDstStride = pStrBlt->lDeltaDst - WidthX;
  45. ULONG yInt = 0;
  46. yInt = pStrBlt->lDeltaSrc * pStrBlt->ulYDstToSrcIntCeil;
  47. //
  48. // Narrow blt
  49. //
  50. do {
  51. ULONG yTmp = yAccum + yFrac;
  52. BYTE jSrc0;
  53. BYTE* pjDstEndNarrow = pjDst + WidthX;
  54. pjSrc = pjSrcScan;
  55. xAccum = pStrBlt->ulXFracAccumulator;
  56. do {
  57. jSrc0 = *pjSrc;
  58. xTmp = xAccum + xFrac;
  59. pjSrc = pjSrc + xInt + (xTmp < xAccum);
  60. *pjDst++ = jSrc0;
  61. xAccum = xTmp;
  62. } while (pjDst != pjDstEndNarrow);
  63. pjSrcScan += yInt;
  64. if (yTmp < yAccum)
  65. {
  66. pjSrcScan += pStrBlt->lDeltaSrc;
  67. }
  68. yAccum = yTmp;
  69. pjDst += lDstStride;
  70. } while (--yCount);
  71. }
  72. /******************************Public*Routine******************************\
  73. *
  74. * Routine Name
  75. *
  76. * vDirectStretch32
  77. *
  78. * Routine Description:
  79. *
  80. * Stretch blt 32->32
  81. *
  82. * Arguments:
  83. *
  84. * pStrBlt - contains all params for blt
  85. *
  86. * Return Value:
  87. *
  88. * VOID
  89. *
  90. \**************************************************************************/
  91. VOID vM64DirectStretch32(
  92. STR_BLT* pStrBlt)
  93. {
  94. BYTE* pjOldScan;
  95. ULONG* pulSrc;
  96. ULONG* pulDstEnd;
  97. ULONG xAccum;
  98. ULONG xTmp;
  99. ULONG yTmp;
  100. LONG cyDuplicate;
  101. PDEV* ppdev = pStrBlt->ppdev;
  102. LONG xDst = pStrBlt->XDstStart;
  103. LONG xSrc = pStrBlt->XSrcStart;
  104. BYTE* pjSrcScan = pStrBlt->pjSrcScan + xSrc * 4;
  105. ULONG* pulDst = (ULONG*)(pStrBlt->pjDstScan) + xDst;
  106. LONG yDst = pStrBlt->YDstStart + ppdev->yOffset;
  107. LONG yCount = pStrBlt->YDstCount;
  108. LONG WidthX = pStrBlt->XDstEnd - xDst;
  109. ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
  110. ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
  111. ULONG yAccum = pStrBlt->ulYFracAccumulator;
  112. ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
  113. LONG lDstStride = pStrBlt->lDeltaDst - 4*WidthX;
  114. ULONG yInt = 0;
  115. ULONG ulSrc;
  116. BYTE* pjMmBase = ppdev->pjMmBase;
  117. xDst += ppdev->xOffset;
  118. //
  119. // if this is a shrinking blt, calc src scan line stride
  120. //
  121. if (pStrBlt->ulYDstToSrcIntCeil != 0)
  122. {
  123. yInt = pStrBlt->lDeltaSrc * pStrBlt->ulYDstToSrcIntCeil;
  124. }
  125. do {
  126. pulSrc = (ULONG*) pjSrcScan;
  127. xAccum = pStrBlt->ulXFracAccumulator;
  128. //
  129. // a single src scan line is being written
  130. //
  131. pulDstEnd = pulDst + WidthX;
  132. while (pulDst != pulDstEnd)
  133. {
  134. ulSrc = *pulSrc;
  135. xTmp = xAccum + xFrac;
  136. pulSrc = pulSrc + xInt + (xTmp < xAccum);
  137. *(ULONG*)pulDst = ulSrc;
  138. pulDst++;
  139. xAccum = xTmp;
  140. }
  141. pjOldScan = pjSrcScan;
  142. pjSrcScan += yInt;
  143. yTmp = yAccum + yFrac;
  144. if (yTmp < yAccum)
  145. {
  146. pjSrcScan += pStrBlt->lDeltaSrc;
  147. }
  148. yAccum = yTmp;
  149. pulDst = (ULONG*) ((BYTE*) pulDst + lDstStride);
  150. yDst++;
  151. yCount--;
  152. if ((yCount != 0) && (pjSrcScan == pjOldScan))
  153. {
  154. // It's an expanding stretch in 'y'; the scan we just laid down
  155. // will be copied at least once using the hardware:
  156. cyDuplicate = 0;
  157. do {
  158. cyDuplicate++;
  159. pjSrcScan += yInt;
  160. yTmp = yAccum + yFrac;
  161. if (yTmp < yAccum)
  162. {
  163. pjSrcScan += pStrBlt->lDeltaSrc;
  164. }
  165. yAccum = yTmp;
  166. pulDst = (ULONG*) ((BYTE*) pulDst + pStrBlt->lDeltaDst);
  167. yCount--;
  168. } while ((yCount != 0) && (pjSrcScan == pjOldScan));
  169. // The scan is to be copied 'cyDuplicate' times using the
  170. // hardware.
  171. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 4);
  172. M64_OD(pjMmBase, SRC_Y_X, (yDst - 1) | (xDst << 16) );
  173. M64_OD(pjMmBase, DST_Y_X, yDst | (xDst << 16) );
  174. M64_OD(pjMmBase, SRC_HEIGHT1_WIDTH1, 1 | (WidthX << 16) );
  175. M64_OD(pjMmBase, DST_HEIGHT_WIDTH, cyDuplicate | (WidthX << 16) );
  176. yDst += cyDuplicate;
  177. }
  178. } while (yCount != 0);
  179. }
  180. /******************************Public*Routine******************************\
  181. *
  182. * Routine Description:
  183. *
  184. * StretchBlt using integer math. Must be from one surface to another
  185. * surface of the same format.
  186. *
  187. * Arguments:
  188. *
  189. * ppdev - PDEV for device
  190. * pvDst - Pointer to start of dst bitmap
  191. * lDeltaDst - Bytes from start of dst scan line to start of next
  192. * DstCx - Width of Dst Bitmap in pixels
  193. * DstCy - Height of Dst Bitmap in pixels
  194. * prclDst - Pointer to rectangle of Dst extents
  195. * pvSrc - Pointer to start of Src bitmap
  196. * lDeltaSrc - Bytes from start of Src scan line to start of next
  197. * SrcCx - Width of Src Bitmap in pixels
  198. * SrcCy - Height of Src Bitmap in pixels
  199. * prclSrc - Pointer to rectangle of Src extents
  200. * prclSClip - Clip Dest to this rect
  201. *
  202. * Return Value:
  203. *
  204. * Status
  205. *
  206. \**************************************************************************/
  207. BOOL bM64StretchDIB(
  208. PDEV* ppdev,
  209. VOID* pvDst,
  210. LONG lDeltaDst,
  211. RECTL* prclDst,
  212. VOID* pvSrc,
  213. LONG lDeltaSrc,
  214. RECTL* prclSrc,
  215. RECTL* prclClip)
  216. {
  217. STR_BLT StrBlt;
  218. ULONG ulXDstToSrcIntCeil;
  219. ULONG ulXDstToSrcFracCeil;
  220. ULONG ulYDstToSrcIntCeil;
  221. ULONG ulYDstToSrcFracCeil;
  222. ULONG ulXFracAccumulator;
  223. ULONG ulYFracAccumulator;
  224. LONG LeftClipDistance;
  225. LONG TopClipDistance;
  226. BOOL bStretch;
  227. BYTE* pjMmBase = ppdev->pjMmBase;
  228. union {
  229. LARGE_INTEGER large;
  230. ULONGLONG li;
  231. } liInit;
  232. PFN_DIRSTRETCH pfnStr;
  233. //
  234. // Calculate exclusive start and end points:
  235. //
  236. LONG WidthDst = prclDst->right - prclDst->left;
  237. LONG HeightDst = prclDst->bottom - prclDst->top;
  238. LONG WidthSrc = prclSrc->right - prclSrc->left;
  239. LONG HeightSrc = prclSrc->bottom - prclSrc->top;
  240. LONG XSrcStart = prclSrc->left;
  241. LONG XSrcEnd = prclSrc->right;
  242. LONG XDstStart = prclDst->left;
  243. LONG XDstEnd = prclDst->right;
  244. LONG YSrcStart = prclSrc->top;
  245. LONG YSrcEnd = prclSrc->bottom;
  246. LONG YDstStart = prclDst->top;
  247. LONG YDstEnd = prclDst->bottom;
  248. //
  249. // Validate parameters:
  250. //
  251. ASSERTDD(pvDst != (VOID*)NULL, "Bad destination bitmap pointer");
  252. ASSERTDD(pvSrc != (VOID*)NULL, "Bad source bitmap pointer");
  253. ASSERTDD(prclDst != (RECTL*)NULL, "Bad destination rectangle");
  254. ASSERTDD(prclSrc != (RECTL*)NULL, "Bad source rectangle");
  255. ASSERTDD((WidthDst > 0) && (HeightDst > 0) &&
  256. (WidthSrc > 0) && (HeightSrc > 0),
  257. "Can't do mirroring or empty rectangles here");
  258. ASSERTDD((WidthDst <= STRETCH_MAX_EXTENT) &&
  259. (HeightDst <= STRETCH_MAX_EXTENT) &&
  260. (WidthSrc <= STRETCH_MAX_EXTENT) &&
  261. (HeightSrc <= STRETCH_MAX_EXTENT), "Stretch exceeds limits");
  262. ASSERTDD(prclClip != NULL, "Bad clip rectangle");
  263. //
  264. // Calculate X Dst to Src mapping
  265. //
  266. //
  267. // dst->src = ( CEIL( (2k*WidthSrc)/WidthDst) ) / 2k
  268. //
  269. // = ( FLOOR( (2k*WidthSrc -1) / WidthDst) + 1) / 2k
  270. //
  271. // where 2k = 2 ^ 32
  272. //
  273. {
  274. ULONGLONG liWidthSrc;
  275. ULONGLONG liQuo;
  276. ULONG ulTemp;
  277. //
  278. // Work around a compiler bug dealing with the assignment
  279. // 'liHeightSrc = (((LONGLONG)HeightSrc) << 32) - 1':
  280. //
  281. liInit.large.LowPart = (ULONG) -1;
  282. liInit.large.HighPart = WidthSrc - 1;
  283. liWidthSrc = liInit.li;
  284. liQuo = liWidthSrc / (ULONGLONG) WidthDst;
  285. ulXDstToSrcIntCeil = (ULONG)(liQuo >> 32);
  286. ulXDstToSrcFracCeil = (ULONG)liQuo;
  287. //
  288. // Now add 1, use fake carry:
  289. //
  290. ulTemp = ulXDstToSrcFracCeil + 1;
  291. ulXDstToSrcIntCeil += (ulTemp < ulXDstToSrcFracCeil);
  292. ulXDstToSrcFracCeil = ulTemp;
  293. }
  294. //
  295. // Calculate Y Dst to Src mapping
  296. //
  297. //
  298. // dst->src = ( CEIL( (2k*HeightSrc)/HeightDst) ) / 2k
  299. //
  300. // = ( FLOOR( (2k*HeightSrc -1) / HeightDst) + 1) / 2k
  301. //
  302. // where 2k = 2 ^ 32
  303. //
  304. {
  305. ULONGLONG liHeightSrc;
  306. ULONGLONG liQuo;
  307. ULONG ulTemp;
  308. //
  309. // Work around a compiler bug dealing with the assignment
  310. // 'liHeightSrc = (((LONGLONG)HeightSrc) << 32) - 1':
  311. //
  312. liInit.large.LowPart = (ULONG) -1;
  313. liInit.large.HighPart = HeightSrc - 1;
  314. liHeightSrc = liInit.li;
  315. liQuo = liHeightSrc / (ULONGLONG) HeightDst;
  316. ulYDstToSrcIntCeil = (ULONG)(liQuo >> 32);
  317. ulYDstToSrcFracCeil = (ULONG)liQuo;
  318. //
  319. // Now add 1, use fake carry:
  320. //
  321. ulTemp = ulYDstToSrcFracCeil + 1;
  322. ulYDstToSrcIntCeil += (ulTemp < ulYDstToSrcFracCeil);
  323. ulYDstToSrcFracCeil = ulTemp;
  324. }
  325. //
  326. // Now clip Dst in X, and/or calc src clipping effect on dst
  327. //
  328. // adjust left and right edges if needed, record
  329. // distance adjusted for fixing the src
  330. //
  331. if (XDstStart < prclClip->left)
  332. {
  333. XDstStart = prclClip->left;
  334. }
  335. if (XDstEnd > prclClip->right)
  336. {
  337. XDstEnd = prclClip->right;
  338. }
  339. //
  340. // Check for totally clipped out destination:
  341. //
  342. if (XDstEnd <= XDstStart)
  343. {
  344. return(TRUE);
  345. }
  346. LeftClipDistance = XDstStart - prclDst->left;
  347. {
  348. ULONG ulTempInt;
  349. ULONG ulTempFrac;
  350. //
  351. // Calculate displacement for .5 in destination and add:
  352. //
  353. ulTempFrac = (ulXDstToSrcFracCeil >> 1) | (ulXDstToSrcIntCeil << 31);
  354. ulTempInt = (ulXDstToSrcIntCeil >> 1);
  355. XSrcStart += ulTempInt;
  356. ulXFracAccumulator = ulTempFrac;
  357. if (LeftClipDistance != 0)
  358. {
  359. ULONGLONG ullFraction;
  360. ULONG ulTmp;
  361. ullFraction = UInt32x32To64(ulXDstToSrcFracCeil, LeftClipDistance);
  362. ulTmp = ulXFracAccumulator;
  363. ulXFracAccumulator += (ULONG) (ullFraction);
  364. if (ulXFracAccumulator < ulTmp)
  365. XSrcStart++;
  366. XSrcStart += (ulXDstToSrcIntCeil * LeftClipDistance)
  367. + (ULONG) (ullFraction >> 32);
  368. }
  369. }
  370. //
  371. // Now clip Dst in Y, and/or calc src clipping effect on dst
  372. //
  373. // adjust top and bottom edges if needed, record
  374. // distance adjusted for fixing the src
  375. //
  376. if (YDstStart < prclClip->top)
  377. {
  378. YDstStart = prclClip->top;
  379. }
  380. if (YDstEnd > prclClip->bottom)
  381. {
  382. YDstEnd = prclClip->bottom;
  383. }
  384. //
  385. // Check for totally clipped out destination:
  386. //
  387. if (YDstEnd <= YDstStart)
  388. {
  389. return(TRUE);
  390. }
  391. TopClipDistance = YDstStart - prclDst->top;
  392. {
  393. ULONG ulTempInt;
  394. ULONG ulTempFrac;
  395. //
  396. // Calculate displacement for .5 in destination and add:
  397. //
  398. ulTempFrac = (ulYDstToSrcFracCeil >> 1) | (ulYDstToSrcIntCeil << 31);
  399. ulTempInt = ulYDstToSrcIntCeil >> 1;
  400. YSrcStart += (LONG)ulTempInt;
  401. ulYFracAccumulator = ulTempFrac;
  402. if (TopClipDistance != 0)
  403. {
  404. ULONGLONG ullFraction;
  405. ULONG ulTmp;
  406. ullFraction = UInt32x32To64(ulYDstToSrcFracCeil, TopClipDistance);
  407. ulTmp = ulYFracAccumulator;
  408. ulYFracAccumulator += (ULONG) (ullFraction);
  409. if (ulYFracAccumulator < ulTmp)
  410. YSrcStart++;
  411. YSrcStart += (ulYDstToSrcIntCeil * TopClipDistance)
  412. + (ULONG) (ullFraction >> 32);
  413. }
  414. }
  415. //
  416. // Warm up the hardware if doing an expanding stretch in 'y':
  417. //
  418. bStretch = (HeightDst > HeightSrc);
  419. if (bStretch)
  420. {
  421. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 4);
  422. //M64_OD(pjMmBase, CONTEXT_LOAD_CNTL, CONTEXT_LOAD_CmdLoad | ppdev->iDefContext );
  423. M64_OD(pjMmBase, SRC_OFF_PITCH, ppdev->ulScreenOffsetAndPitch);
  424. M64_OD(pjMmBase, DP_MIX, OVERPAINT << 16 );
  425. M64_OD(pjMmBase, DP_SRC, DP_SRC_Blit << 8 );
  426. M64_OD(pjMmBase, SRC_CNTL, SRC_CNTL_PatEna );
  427. }
  428. //
  429. // Fill out blt structure, then call format-specific stretch code
  430. //
  431. StrBlt.ppdev = ppdev;
  432. StrBlt.XDstEnd = XDstEnd;
  433. StrBlt.YDstStart = YDstStart;
  434. StrBlt.YDstCount = YDstEnd - YDstStart;
  435. if (StrBlt.YDstCount > 0)
  436. {
  437. //
  438. // Caclulate starting scan line address. Since the inner loop
  439. // routines are format dependent, they must add XDstStart/XSrcStart
  440. // to pjDstScan/pjSrcScan to get the actual starting pixel address.
  441. //
  442. StrBlt.pjSrcScan = (BYTE*) pvSrc + (YSrcStart * lDeltaSrc);
  443. StrBlt.pjDstScan = (BYTE*) pvDst + (YDstStart * lDeltaDst);
  444. StrBlt.lDeltaSrc = lDeltaSrc;
  445. StrBlt.XSrcStart = XSrcStart;
  446. StrBlt.XDstStart = XDstStart;
  447. StrBlt.lDeltaDst = lDeltaDst;
  448. StrBlt.ulXDstToSrcIntCeil = ulXDstToSrcIntCeil;
  449. StrBlt.ulXDstToSrcFracCeil = ulXDstToSrcFracCeil;
  450. StrBlt.ulYDstToSrcIntCeil = ulYDstToSrcIntCeil;
  451. StrBlt.ulYDstToSrcFracCeil = ulYDstToSrcFracCeil;
  452. StrBlt.ulXFracAccumulator = ulXFracAccumulator;
  453. StrBlt.ulYFracAccumulator = ulYFracAccumulator;
  454. if (ppdev->iBitmapFormat == BMF_8BPP)
  455. {
  456. if ((XDstEnd - XDstStart) < 7)
  457. pfnStr = vDirectStretch8Narrow;
  458. else
  459. pfnStr = vM64DirectStretch8;
  460. }
  461. else if (ppdev->iBitmapFormat == BMF_16BPP)
  462. {
  463. pfnStr = vM64DirectStretch16;
  464. }
  465. else
  466. {
  467. ASSERTDD(ppdev->iBitmapFormat == BMF_32BPP,
  468. "Only handle stretchs at 8, 16 and 32bpp");
  469. pfnStr = vM64DirectStretch32;
  470. }
  471. (*pfnStr)(&StrBlt);
  472. }
  473. return(TRUE);
  474. }
  475. BOOL bM32StretchDIB(
  476. PDEV* ppdev,
  477. VOID* pvDst,
  478. LONG lDeltaDst,
  479. RECTL* prclDst,
  480. VOID* pvSrc,
  481. LONG lDeltaSrc,
  482. RECTL* prclSrc,
  483. RECTL* prclClip)
  484. {
  485. STR_BLT StrBlt;
  486. ULONG ulXDstToSrcIntCeil;
  487. ULONG ulXDstToSrcFracCeil;
  488. ULONG ulYDstToSrcIntCeil;
  489. ULONG ulYDstToSrcFracCeil;
  490. ULONG ulXFracAccumulator;
  491. ULONG ulYFracAccumulator;
  492. LONG LeftClipDistance;
  493. LONG TopClipDistance;
  494. BOOL bStretch;
  495. BYTE* pjMmBase = ppdev->pjMmBase;
  496. union {
  497. LARGE_INTEGER large;
  498. ULONGLONG li;
  499. } liInit;
  500. PFN_DIRSTRETCH pfnStr;
  501. //
  502. // Calculate exclusive start and end points:
  503. //
  504. LONG WidthDst = prclDst->right - prclDst->left;
  505. LONG HeightDst = prclDst->bottom - prclDst->top;
  506. LONG WidthSrc = prclSrc->right - prclSrc->left;
  507. LONG HeightSrc = prclSrc->bottom - prclSrc->top;
  508. LONG XSrcStart = prclSrc->left;
  509. LONG XSrcEnd = prclSrc->right;
  510. LONG XDstStart = prclDst->left;
  511. LONG XDstEnd = prclDst->right;
  512. LONG YSrcStart = prclSrc->top;
  513. LONG YSrcEnd = prclSrc->bottom;
  514. LONG YDstStart = prclDst->top;
  515. LONG YDstEnd = prclDst->bottom;
  516. //
  517. // Validate parameters:
  518. //
  519. ASSERTDD(pvDst != (VOID*)NULL, "Bad destination bitmap pointer");
  520. ASSERTDD(pvSrc != (VOID*)NULL, "Bad source bitmap pointer");
  521. ASSERTDD(prclDst != (RECTL*)NULL, "Bad destination rectangle");
  522. ASSERTDD(prclSrc != (RECTL*)NULL, "Bad source rectangle");
  523. ASSERTDD((WidthDst > 0) && (HeightDst > 0) &&
  524. (WidthSrc > 0) && (HeightSrc > 0),
  525. "Can't do mirroring or empty rectangles here");
  526. ASSERTDD((WidthDst <= STRETCH_MAX_EXTENT) &&
  527. (HeightDst <= STRETCH_MAX_EXTENT) &&
  528. (WidthSrc <= STRETCH_MAX_EXTENT) &&
  529. (HeightSrc <= STRETCH_MAX_EXTENT), "Stretch exceeds limits");
  530. ASSERTDD(prclClip != NULL, "Bad clip rectangle");
  531. //
  532. // Calculate X Dst to Src mapping
  533. //
  534. //
  535. // dst->src = ( CEIL( (2k*WidthSrc)/WidthDst) ) / 2k
  536. //
  537. // = ( FLOOR( (2k*WidthSrc -1) / WidthDst) + 1) / 2k
  538. //
  539. // where 2k = 2 ^ 32
  540. //
  541. {
  542. ULONGLONG liWidthSrc;
  543. ULONGLONG liQuo;
  544. ULONG ulTemp;
  545. //
  546. // Work around a compiler bug dealing with the assignment
  547. // 'liHeightSrc = (((LONGLONG)HeightSrc) << 32) - 1':
  548. //
  549. liInit.large.LowPart = (ULONG) -1;
  550. liInit.large.HighPart = WidthSrc - 1;
  551. liWidthSrc = liInit.li;
  552. liQuo = liWidthSrc / (ULONGLONG) WidthDst;
  553. ulXDstToSrcIntCeil = (ULONG)(liQuo >> 32);
  554. ulXDstToSrcFracCeil = (ULONG)liQuo;
  555. //
  556. // Now add 1, use fake carry:
  557. //
  558. ulTemp = ulXDstToSrcFracCeil + 1;
  559. ulXDstToSrcIntCeil += (ulTemp < ulXDstToSrcFracCeil);
  560. ulXDstToSrcFracCeil = ulTemp;
  561. }
  562. //
  563. // Calculate Y Dst to Src mapping
  564. //
  565. //
  566. // dst->src = ( CEIL( (2k*HeightSrc)/HeightDst) ) / 2k
  567. //
  568. // = ( FLOOR( (2k*HeightSrc -1) / HeightDst) + 1) / 2k
  569. //
  570. // where 2k = 2 ^ 32
  571. //
  572. {
  573. ULONGLONG liHeightSrc;
  574. ULONGLONG liQuo;
  575. ULONG ulTemp;
  576. //
  577. // Work around a compiler bug dealing with the assignment
  578. // 'liHeightSrc = (((LONGLONG)HeightSrc) << 32) - 1':
  579. //
  580. liInit.large.LowPart = (ULONG) -1;
  581. liInit.large.HighPart = HeightSrc - 1;
  582. liHeightSrc = liInit.li;
  583. liQuo = liHeightSrc / (ULONGLONG) HeightDst;
  584. ulYDstToSrcIntCeil = (ULONG)(liQuo >> 32);
  585. ulYDstToSrcFracCeil = (ULONG)liQuo;
  586. //
  587. // Now add 1, use fake carry:
  588. //
  589. ulTemp = ulYDstToSrcFracCeil + 1;
  590. ulYDstToSrcIntCeil += (ulTemp < ulYDstToSrcFracCeil);
  591. ulYDstToSrcFracCeil = ulTemp;
  592. }
  593. //
  594. // Now clip Dst in X, and/or calc src clipping effect on dst
  595. //
  596. // adjust left and right edges if needed, record
  597. // distance adjusted for fixing the src
  598. //
  599. if (XDstStart < prclClip->left)
  600. {
  601. XDstStart = prclClip->left;
  602. }
  603. if (XDstEnd > prclClip->right)
  604. {
  605. XDstEnd = prclClip->right;
  606. }
  607. //
  608. // Check for totally clipped out destination:
  609. //
  610. if (XDstEnd <= XDstStart)
  611. {
  612. return(TRUE);
  613. }
  614. LeftClipDistance = XDstStart - prclDst->left;
  615. {
  616. ULONG ulTempInt;
  617. ULONG ulTempFrac;
  618. //
  619. // Calculate displacement for .5 in destination and add:
  620. //
  621. ulTempFrac = (ulXDstToSrcFracCeil >> 1) | (ulXDstToSrcIntCeil << 31);
  622. ulTempInt = (ulXDstToSrcIntCeil >> 1);
  623. XSrcStart += ulTempInt;
  624. ulXFracAccumulator = ulTempFrac;
  625. if (LeftClipDistance != 0)
  626. {
  627. ULONGLONG ullFraction;
  628. ULONG ulTmp;
  629. ullFraction = UInt32x32To64(ulXDstToSrcFracCeil, LeftClipDistance);
  630. ulTmp = ulXFracAccumulator;
  631. ulXFracAccumulator += (ULONG) (ullFraction);
  632. if (ulXFracAccumulator < ulTmp)
  633. XSrcStart++;
  634. XSrcStart += (ulXDstToSrcIntCeil * LeftClipDistance)
  635. + (ULONG) (ullFraction >> 32);
  636. }
  637. }
  638. //
  639. // Now clip Dst in Y, and/or calc src clipping effect on dst
  640. //
  641. // adjust top and bottom edges if needed, record
  642. // distance adjusted for fixing the src
  643. //
  644. if (YDstStart < prclClip->top)
  645. {
  646. YDstStart = prclClip->top;
  647. }
  648. if (YDstEnd > prclClip->bottom)
  649. {
  650. YDstEnd = prclClip->bottom;
  651. }
  652. //
  653. // Check for totally clipped out destination:
  654. //
  655. if (YDstEnd <= YDstStart)
  656. {
  657. return(TRUE);
  658. }
  659. TopClipDistance = YDstStart - prclDst->top;
  660. {
  661. ULONG ulTempInt;
  662. ULONG ulTempFrac;
  663. //
  664. // Calculate displacement for .5 in destination and add:
  665. //
  666. ulTempFrac = (ulYDstToSrcFracCeil >> 1) | (ulYDstToSrcIntCeil << 31);
  667. ulTempInt = ulYDstToSrcIntCeil >> 1;
  668. YSrcStart += (LONG)ulTempInt;
  669. ulYFracAccumulator = ulTempFrac;
  670. if (TopClipDistance != 0)
  671. {
  672. ULONGLONG ullFraction;
  673. ULONG ulTmp;
  674. ullFraction = UInt32x32To64(ulYDstToSrcFracCeil, TopClipDistance);
  675. ulTmp = ulYFracAccumulator;
  676. ulYFracAccumulator += (ULONG) (ullFraction);
  677. if (ulYFracAccumulator < ulTmp)
  678. YSrcStart++;
  679. YSrcStart += (ulYDstToSrcIntCeil * TopClipDistance)
  680. + (ULONG) (ullFraction >> 32);
  681. }
  682. }
  683. //
  684. // Warm up the hardware if doing an expanding stretch in 'y':
  685. //
  686. bStretch = (HeightDst > HeightSrc);
  687. if (bStretch)
  688. {
  689. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 3);
  690. M32_OW(pjMmBase, DP_CONFIG, 0x6011 );
  691. M32_OW(pjMmBase, ALU_FG_FN, OVERPAINT );
  692. M32_OW(pjMmBase, SRC_Y_DIR, 1 );
  693. }
  694. //
  695. // Fill out blt structure, then call format-specific stretch code
  696. //
  697. StrBlt.ppdev = ppdev;
  698. StrBlt.XDstEnd = XDstEnd;
  699. StrBlt.YDstStart = YDstStart;
  700. StrBlt.YDstCount = YDstEnd - YDstStart;
  701. if (StrBlt.YDstCount > 0)
  702. {
  703. //
  704. // Caclulate starting scan line address. Since the inner loop
  705. // routines are format dependent, they must add XDstStart/XSrcStart
  706. // to pjDstScan/pjSrcScan to get the actual starting pixel address.
  707. //
  708. StrBlt.pjSrcScan = (BYTE*) pvSrc + (YSrcStart * lDeltaSrc);
  709. StrBlt.pjDstScan = (BYTE*) pvDst + (YDstStart * lDeltaDst);
  710. StrBlt.lDeltaSrc = lDeltaSrc;
  711. StrBlt.XSrcStart = XSrcStart;
  712. StrBlt.XDstStart = XDstStart;
  713. StrBlt.lDeltaDst = lDeltaDst;
  714. StrBlt.ulXDstToSrcIntCeil = ulXDstToSrcIntCeil;
  715. StrBlt.ulXDstToSrcFracCeil = ulXDstToSrcFracCeil;
  716. StrBlt.ulYDstToSrcIntCeil = ulYDstToSrcIntCeil;
  717. StrBlt.ulYDstToSrcFracCeil = ulYDstToSrcFracCeil;
  718. StrBlt.ulXFracAccumulator = ulXFracAccumulator;
  719. StrBlt.ulYFracAccumulator = ulYFracAccumulator;
  720. if (ppdev->iBitmapFormat == BMF_8BPP)
  721. {
  722. if ((XDstEnd - XDstStart) < 7)
  723. pfnStr = vDirectStretch8Narrow;
  724. else
  725. pfnStr = vM32DirectStretch8;
  726. }
  727. else if (ppdev->iBitmapFormat == BMF_16BPP)
  728. {
  729. pfnStr = vM32DirectStretch16;
  730. }
  731. else
  732. {
  733. return FALSE; // should never come here.
  734. }
  735. (*pfnStr)(&StrBlt);
  736. }
  737. return(TRUE);
  738. }
  739. BOOL bI32StretchDIB(
  740. PDEV* ppdev,
  741. VOID* pvDst,
  742. LONG lDeltaDst,
  743. RECTL* prclDst,
  744. VOID* pvSrc,
  745. LONG lDeltaSrc,
  746. RECTL* prclSrc,
  747. RECTL* prclClip)
  748. {
  749. STR_BLT StrBlt;
  750. ULONG ulXDstToSrcIntCeil;
  751. ULONG ulXDstToSrcFracCeil;
  752. ULONG ulYDstToSrcIntCeil;
  753. ULONG ulYDstToSrcFracCeil;
  754. ULONG ulXFracAccumulator;
  755. ULONG ulYFracAccumulator;
  756. LONG LeftClipDistance;
  757. LONG TopClipDistance;
  758. BOOL bStretch;
  759. BYTE* pjIoBase = ppdev->pjIoBase;
  760. union {
  761. LARGE_INTEGER large;
  762. ULONGLONG li;
  763. } liInit;
  764. PFN_DIRSTRETCH pfnStr;
  765. //
  766. // Calculate exclusive start and end points:
  767. //
  768. LONG WidthDst = prclDst->right - prclDst->left;
  769. LONG HeightDst = prclDst->bottom - prclDst->top;
  770. LONG WidthSrc = prclSrc->right - prclSrc->left;
  771. LONG HeightSrc = prclSrc->bottom - prclSrc->top;
  772. LONG XSrcStart = prclSrc->left;
  773. LONG XSrcEnd = prclSrc->right;
  774. LONG XDstStart = prclDst->left;
  775. LONG XDstEnd = prclDst->right;
  776. LONG YSrcStart = prclSrc->top;
  777. LONG YSrcEnd = prclSrc->bottom;
  778. LONG YDstStart = prclDst->top;
  779. LONG YDstEnd = prclDst->bottom;
  780. //
  781. // Validate parameters:
  782. //
  783. ASSERTDD(pvDst != (VOID*)NULL, "Bad destination bitmap pointer");
  784. ASSERTDD(pvSrc != (VOID*)NULL, "Bad source bitmap pointer");
  785. ASSERTDD(prclDst != (RECTL*)NULL, "Bad destination rectangle");
  786. ASSERTDD(prclSrc != (RECTL*)NULL, "Bad source rectangle");
  787. ASSERTDD((WidthDst > 0) && (HeightDst > 0) &&
  788. (WidthSrc > 0) && (HeightSrc > 0),
  789. "Can't do mirroring or empty rectangles here");
  790. ASSERTDD((WidthDst <= STRETCH_MAX_EXTENT) &&
  791. (HeightDst <= STRETCH_MAX_EXTENT) &&
  792. (WidthSrc <= STRETCH_MAX_EXTENT) &&
  793. (HeightSrc <= STRETCH_MAX_EXTENT), "Stretch exceeds limits");
  794. ASSERTDD(prclClip != NULL, "Bad clip rectangle");
  795. //
  796. // Calculate X Dst to Src mapping
  797. //
  798. //
  799. // dst->src = ( CEIL( (2k*WidthSrc)/WidthDst) ) / 2k
  800. //
  801. // = ( FLOOR( (2k*WidthSrc -1) / WidthDst) + 1) / 2k
  802. //
  803. // where 2k = 2 ^ 32
  804. //
  805. {
  806. ULONGLONG liWidthSrc;
  807. ULONGLONG liQuo;
  808. ULONG ulTemp;
  809. //
  810. // Work around a compiler bug dealing with the assignment
  811. // 'liHeightSrc = (((LONGLONG)HeightSrc) << 32) - 1':
  812. //
  813. liInit.large.LowPart = (ULONG) -1;
  814. liInit.large.HighPart = WidthSrc - 1;
  815. liWidthSrc = liInit.li;
  816. liQuo = liWidthSrc / (ULONGLONG) WidthDst;
  817. ulXDstToSrcIntCeil = (ULONG)(liQuo >> 32);
  818. ulXDstToSrcFracCeil = (ULONG)liQuo;
  819. //
  820. // Now add 1, use fake carry:
  821. //
  822. ulTemp = ulXDstToSrcFracCeil + 1;
  823. ulXDstToSrcIntCeil += (ulTemp < ulXDstToSrcFracCeil);
  824. ulXDstToSrcFracCeil = ulTemp;
  825. }
  826. //
  827. // Calculate Y Dst to Src mapping
  828. //
  829. //
  830. // dst->src = ( CEIL( (2k*HeightSrc)/HeightDst) ) / 2k
  831. //
  832. // = ( FLOOR( (2k*HeightSrc -1) / HeightDst) + 1) / 2k
  833. //
  834. // where 2k = 2 ^ 32
  835. //
  836. {
  837. ULONGLONG liHeightSrc;
  838. ULONGLONG liQuo;
  839. ULONG ulTemp;
  840. //
  841. // Work around a compiler bug dealing with the assignment
  842. // 'liHeightSrc = (((LONGLONG)HeightSrc) << 32) - 1':
  843. //
  844. liInit.large.LowPart = (ULONG) -1;
  845. liInit.large.HighPart = HeightSrc - 1;
  846. liHeightSrc = liInit.li;
  847. liQuo = liHeightSrc / (ULONGLONG) HeightDst;
  848. ulYDstToSrcIntCeil = (ULONG)(liQuo >> 32);
  849. ulYDstToSrcFracCeil = (ULONG)liQuo;
  850. //
  851. // Now add 1, use fake carry:
  852. //
  853. ulTemp = ulYDstToSrcFracCeil + 1;
  854. ulYDstToSrcIntCeil += (ulTemp < ulYDstToSrcFracCeil);
  855. ulYDstToSrcFracCeil = ulTemp;
  856. }
  857. //
  858. // Now clip Dst in X, and/or calc src clipping effect on dst
  859. //
  860. // adjust left and right edges if needed, record
  861. // distance adjusted for fixing the src
  862. //
  863. if (XDstStart < prclClip->left)
  864. {
  865. XDstStart = prclClip->left;
  866. }
  867. if (XDstEnd > prclClip->right)
  868. {
  869. XDstEnd = prclClip->right;
  870. }
  871. //
  872. // Check for totally clipped out destination:
  873. //
  874. if (XDstEnd <= XDstStart)
  875. {
  876. return(TRUE);
  877. }
  878. LeftClipDistance = XDstStart - prclDst->left;
  879. {
  880. ULONG ulTempInt;
  881. ULONG ulTempFrac;
  882. //
  883. // Calculate displacement for .5 in destination and add:
  884. //
  885. ulTempFrac = (ulXDstToSrcFracCeil >> 1) | (ulXDstToSrcIntCeil << 31);
  886. ulTempInt = (ulXDstToSrcIntCeil >> 1);
  887. XSrcStart += ulTempInt;
  888. ulXFracAccumulator = ulTempFrac;
  889. if (LeftClipDistance != 0)
  890. {
  891. ULONGLONG ullFraction;
  892. ULONG ulTmp;
  893. ullFraction = UInt32x32To64(ulXDstToSrcFracCeil, LeftClipDistance);
  894. ulTmp = ulXFracAccumulator;
  895. ulXFracAccumulator += (ULONG) (ullFraction);
  896. if (ulXFracAccumulator < ulTmp)
  897. XSrcStart++;
  898. XSrcStart += (ulXDstToSrcIntCeil * LeftClipDistance)
  899. + (ULONG) (ullFraction >> 32);
  900. }
  901. }
  902. //
  903. // Now clip Dst in Y, and/or calc src clipping effect on dst
  904. //
  905. // adjust top and bottom edges if needed, record
  906. // distance adjusted for fixing the src
  907. //
  908. if (YDstStart < prclClip->top)
  909. {
  910. YDstStart = prclClip->top;
  911. }
  912. if (YDstEnd > prclClip->bottom)
  913. {
  914. YDstEnd = prclClip->bottom;
  915. }
  916. //
  917. // Check for totally clipped out destination:
  918. //
  919. if (YDstEnd <= YDstStart)
  920. {
  921. return(TRUE);
  922. }
  923. TopClipDistance = YDstStart - prclDst->top;
  924. {
  925. ULONG ulTempInt;
  926. ULONG ulTempFrac;
  927. //
  928. // Calculate displacement for .5 in destination and add:
  929. //
  930. ulTempFrac = (ulYDstToSrcFracCeil >> 1) | (ulYDstToSrcIntCeil << 31);
  931. ulTempInt = ulYDstToSrcIntCeil >> 1;
  932. YSrcStart += (LONG)ulTempInt;
  933. ulYFracAccumulator = ulTempFrac;
  934. if (TopClipDistance != 0)
  935. {
  936. ULONGLONG ullFraction;
  937. ULONG ulTmp;
  938. ullFraction = UInt32x32To64(ulYDstToSrcFracCeil, TopClipDistance);
  939. ulTmp = ulYFracAccumulator;
  940. ulYFracAccumulator += (ULONG) (ullFraction);
  941. if (ulYFracAccumulator < ulTmp)
  942. YSrcStart++;
  943. YSrcStart += (ulYDstToSrcIntCeil * TopClipDistance)
  944. + (ULONG) (ullFraction >> 32);
  945. }
  946. }
  947. //
  948. // Warm up the hardware if doing an expanding stretch in 'y':
  949. //
  950. bStretch = (HeightDst > HeightSrc);
  951. if (bStretch)
  952. {
  953. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 3);
  954. I32_OW(pjIoBase, DP_CONFIG, 0x6011 );
  955. I32_OW(pjIoBase, ALU_FG_FN, OVERPAINT );
  956. I32_OW(pjIoBase, SRC_Y_DIR, 1 );
  957. }
  958. //
  959. // Fill out blt structure, then call format-specific stretch code
  960. //
  961. StrBlt.ppdev = ppdev;
  962. StrBlt.XDstEnd = XDstEnd;
  963. StrBlt.YDstStart = YDstStart;
  964. StrBlt.YDstCount = YDstEnd - YDstStart;
  965. if (StrBlt.YDstCount > 0)
  966. {
  967. //
  968. // Caclulate starting scan line address. Since the inner loop
  969. // routines are format dependent, they must add XDstStart/XSrcStart
  970. // to pjDstScan/pjSrcScan to get the actual starting pixel address.
  971. //
  972. StrBlt.pjSrcScan = (BYTE*) pvSrc + (YSrcStart * lDeltaSrc);
  973. StrBlt.pjDstScan = (BYTE*) pvDst + (YDstStart * lDeltaDst);
  974. StrBlt.lDeltaSrc = lDeltaSrc;
  975. StrBlt.XSrcStart = XSrcStart;
  976. StrBlt.XDstStart = XDstStart;
  977. StrBlt.lDeltaDst = lDeltaDst;
  978. StrBlt.ulXDstToSrcIntCeil = ulXDstToSrcIntCeil;
  979. StrBlt.ulXDstToSrcFracCeil = ulXDstToSrcFracCeil;
  980. StrBlt.ulYDstToSrcIntCeil = ulYDstToSrcIntCeil;
  981. StrBlt.ulYDstToSrcFracCeil = ulYDstToSrcFracCeil;
  982. StrBlt.ulXFracAccumulator = ulXFracAccumulator;
  983. StrBlt.ulYFracAccumulator = ulYFracAccumulator;
  984. if (ppdev->iBitmapFormat == BMF_8BPP)
  985. {
  986. if ((XDstEnd - XDstStart) < 7)
  987. pfnStr = vDirectStretch8Narrow;
  988. else
  989. pfnStr = vI32DirectStretch8;
  990. }
  991. else if (ppdev->iBitmapFormat == BMF_16BPP)
  992. {
  993. pfnStr = vI32DirectStretch16;
  994. }
  995. else
  996. {
  997. return FALSE; // should never come here.
  998. }
  999. (*pfnStr)(&StrBlt);
  1000. }
  1001. return(TRUE);
  1002. }
  1003. /******************************Public*Routine******************************\
  1004. * BOOL bBankedStretch
  1005. *
  1006. \**************************************************************************/
  1007. BOOL bBankedStretch(
  1008. PDEV* ppdev,
  1009. VOID* pvDst,
  1010. LONG lDeltaDst,
  1011. RECTL* prclDst,
  1012. VOID* pvSrc,
  1013. LONG lDeltaSrc,
  1014. RECTL* prclSrc,
  1015. RECTL* prclClip)
  1016. {
  1017. BANK bnk;
  1018. BOOL b;
  1019. RECTL rclDst;
  1020. b = TRUE;
  1021. if (bIntersect(prclDst, prclClip, &rclDst))
  1022. {
  1023. vBankStart(ppdev, &rclDst, NULL, &bnk);
  1024. do {
  1025. b &= ppdev->pfnStretchDIB(ppdev,
  1026. bnk.pso->pvScan0,
  1027. lDeltaDst,
  1028. prclDst,
  1029. pvSrc,
  1030. lDeltaSrc,
  1031. prclSrc,
  1032. &bnk.pco->rclBounds);
  1033. } while (bBankEnum(&bnk));
  1034. }
  1035. return(b);
  1036. }
  1037. /******************************Public*Routine******************************\
  1038. * BOOL DrvStretchBlt
  1039. *
  1040. \**************************************************************************/
  1041. #if defined(ALPHA)
  1042. #define DENSE(ppdev) (ppdev->FeatureFlags & EVN_DENSE_CAPABLE)
  1043. #else
  1044. #define DENSE(ppdev) (ppdev->iAperture != APERTURE_NONE)
  1045. #endif
  1046. BOOL DrvStretchBlt(
  1047. SURFOBJ* psoDst,
  1048. SURFOBJ* psoSrc,
  1049. SURFOBJ* psoMsk,
  1050. CLIPOBJ* pco,
  1051. XLATEOBJ* pxlo,
  1052. COLORADJUSTMENT* pca,
  1053. POINTL* pptlHTOrg,
  1054. RECTL* prclDst,
  1055. RECTL* prclSrc,
  1056. POINTL* pptlMsk,
  1057. ULONG iMode)
  1058. {
  1059. DSURF* pdsurfSrc;
  1060. DSURF* pdsurfDst;
  1061. PDEV* ppdev;
  1062. OH* poh;
  1063. // GDI guarantees us that for a StretchBlt the destination surface
  1064. // will always be a device surface, and not a DIB:
  1065. ppdev = (PDEV*) psoDst->dhpdev;
  1066. // It's quicker for GDI to do a StretchBlt when the source surface
  1067. // is not a device-managed surface, because then it can directly
  1068. // read the source bits without having to allocate a temporary
  1069. // buffer and call DrvCopyBits to get a copy that it can use.
  1070. if (psoSrc->iType == STYPE_DEVBITMAP)
  1071. {
  1072. pdsurfSrc = (DSURF*) psoSrc->dhsurf;
  1073. if (pdsurfSrc->dt == DT_SCREEN)
  1074. goto Punt_It;
  1075. ASSERTDD(pdsurfSrc->dt == DT_DIB, "Can only handle DIB DFBs here");
  1076. psoSrc = pdsurfSrc->pso;
  1077. }
  1078. pdsurfDst = (DSURF*) psoDst->dhsurf;
  1079. if (pdsurfDst->dt == DT_DIB)
  1080. {
  1081. // The destination was a device bitmap that we just converted
  1082. // to a DIB:
  1083. psoDst = pdsurfDst->pso;
  1084. goto Punt_It;
  1085. }
  1086. poh = pdsurfDst->poh;
  1087. ppdev->xOffset = poh->x;
  1088. ppdev->yOffset = poh->y;
  1089. // Our special-case StretchBlt code assumes a dense frame buffer
  1090. // space, so this code can't be executed when using sparse space
  1091. // on the Alpha. Note that since we don't read from the frame
  1092. // buffer, we can allow this to go through even when
  1093. // CAPS_NO_DIRECT_ACCESS is set on the PPC.
  1094. //
  1095. // Also, because of the VTA4 screen source FIFO problem, we punt
  1096. // stretch blits for the VTA4.
  1097. if (DENSE(ppdev) && !(ppdev->FeatureFlags & EVN_SDRAM_1M))
  1098. {
  1099. RECTL rclClip;
  1100. RECTL* prclClip;
  1101. ULONG cxDst;
  1102. ULONG cyDst;
  1103. ULONG cxSrc;
  1104. ULONG cySrc;
  1105. BOOL bMore;
  1106. CLIPENUM ce;
  1107. LONG c;
  1108. LONG i;
  1109. if ((psoSrc->iType == STYPE_BITMAP) &&
  1110. (psoMsk == NULL) &&
  1111. ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)) &&
  1112. ((psoSrc->iBitmapFormat == ppdev->iBitmapFormat)) &&
  1113. (ppdev->iBitmapFormat != BMF_24BPP))
  1114. {
  1115. cxDst = prclDst->right - prclDst->left;
  1116. cyDst = prclDst->bottom - prclDst->top;
  1117. cxSrc = prclSrc->right - prclSrc->left;
  1118. cySrc = prclSrc->bottom - prclSrc->top;
  1119. // Our 'bStretchDIB' routine requires that the stretch be
  1120. // non-inverting, within a certain size, to have no source
  1121. // clipping, and to have no empty rectangles (the latter is the
  1122. // reason for the '- 1' on the unsigned compare here):
  1123. if (((cxSrc - 1) < STRETCH_MAX_EXTENT) &&
  1124. ((cySrc - 1) < STRETCH_MAX_EXTENT) &&
  1125. ((cxDst - 1) < STRETCH_MAX_EXTENT) &&
  1126. ((cyDst - 1) < STRETCH_MAX_EXTENT) &&
  1127. (prclSrc->left >= 0) &&
  1128. (prclSrc->top >= 0) &&
  1129. (prclSrc->right <= psoSrc->sizlBitmap.cx) &&
  1130. (prclSrc->bottom <= psoSrc->sizlBitmap.cy))
  1131. {
  1132. // Our snazzy routine only does COLORONCOLOR. But for
  1133. // stretching blts, BLACKONWHITE and WHITEONBLACK are also
  1134. // equivalent to COLORONCOLOR:
  1135. if ((iMode == COLORONCOLOR) ||
  1136. ((iMode < COLORONCOLOR) && (cxSrc <= cxDst) && (cySrc <= cyDst)))
  1137. {
  1138. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  1139. {
  1140. rclClip.left = 0;
  1141. rclClip.top = 0;
  1142. rclClip.right = poh->cx;
  1143. rclClip.bottom = poh->cy; // Extents of surface
  1144. prclClip = &rclClip;
  1145. StretchSingleClipRect:
  1146. if (bBankedStretch(ppdev,
  1147. NULL,
  1148. ppdev->lDelta,
  1149. prclDst,
  1150. psoSrc->pvScan0,
  1151. psoSrc->lDelta,
  1152. prclSrc,
  1153. prclClip))
  1154. {
  1155. return(TRUE);
  1156. }
  1157. }
  1158. else if (pco->iDComplexity == DC_RECT)
  1159. {
  1160. prclClip = &pco->rclBounds;
  1161. goto StretchSingleClipRect;
  1162. }
  1163. else
  1164. {
  1165. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  1166. do {
  1167. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG*) &ce);
  1168. c = cIntersect(prclDst, ce.arcl, ce.c);
  1169. if (c != 0)
  1170. {
  1171. for (i = 0; i < c; i++)
  1172. {
  1173. if (!bBankedStretch(ppdev,
  1174. NULL,
  1175. ppdev->lDelta,
  1176. prclDst,
  1177. psoSrc->pvScan0,
  1178. psoSrc->lDelta,
  1179. prclSrc,
  1180. &ce.arcl[i]))
  1181. {
  1182. goto Punt_It;
  1183. }
  1184. }
  1185. }
  1186. } while (bMore);
  1187. return(TRUE);
  1188. }
  1189. }
  1190. }
  1191. }
  1192. }
  1193. Punt_It:
  1194. // GDI is nice enough to handle the cases where 'psoDst' and/or 'psoSrc'
  1195. // are device-managed surfaces, but it ain't gonna be fast...
  1196. return(EngStretchBlt(psoDst, psoSrc, psoMsk, pco, pxlo, pca, pptlHTOrg,
  1197. prclDst, prclSrc, pptlMsk, iMode));
  1198. }
  1199.