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.

840 lines
24 KiB

  1. /******************************Module*Header*******************************\
  2. *
  3. * *******************
  4. * * GDI SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: stretch.c
  8. *
  9. * Copyright (c) 1993-1998 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.h"
  12. #define STRETCH_MAX_EXTENT 32767
  13. typedef DWORDLONG ULONGLONG;
  14. /******************************Public*Routine******************************\
  15. *
  16. * Routine Name
  17. *
  18. * vDirectStretch8Narrow
  19. *
  20. * Routine Description:
  21. *
  22. * Stretch blt 8->8 when the width is 7 or less
  23. *
  24. * Arguments:
  25. *
  26. * pStrBlt - contains all params for blt
  27. *
  28. * Return Value:
  29. *
  30. * VOID
  31. *
  32. \**************************************************************************/
  33. VOID vDirectStretch8Narrow(
  34. STR_BLT* pStrBlt)
  35. {
  36. BYTE* pjSrc;
  37. BYTE* pjDstEnd;
  38. ULONG ulDst;
  39. ULONG xAccum;
  40. ULONG xTmp;
  41. ULONG yTmp;
  42. LONG xDst = pStrBlt->XDstStart;
  43. LONG xSrc = pStrBlt->XSrcStart;
  44. BYTE* pjSrcScan = pStrBlt->pjSrcScan + xSrc;
  45. BYTE* pjDst = pStrBlt->pjDstScan + xDst;
  46. LONG yCount = pStrBlt->YDstCount;
  47. LONG WidthX = pStrBlt->XDstEnd - xDst;
  48. ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
  49. ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
  50. ULONG yAccum = pStrBlt->ulYFracAccumulator;
  51. ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
  52. LONG lDstStride = pStrBlt->lDeltaDst - WidthX;
  53. ULONG yInt = 0;
  54. yInt = pStrBlt->lDeltaSrc * pStrBlt->ulYDstToSrcIntCeil;
  55. //
  56. // Narrow blt
  57. //
  58. do {
  59. ULONG yTmp = yAccum + yFrac;
  60. BYTE jSrc0;
  61. BYTE* pjDstEndNarrow = pjDst + WidthX;
  62. pjSrc = pjSrcScan;
  63. xAccum = pStrBlt->ulXFracAccumulator;
  64. do {
  65. jSrc0 = *pjSrc;
  66. xTmp = xAccum + xFrac;
  67. pjSrc = pjSrc + xInt;
  68. if (xTmp < xAccum)
  69. pjSrc++;
  70. *pjDst++ = jSrc0;
  71. xAccum = xTmp;
  72. } while (pjDst != pjDstEndNarrow);
  73. pjSrcScan += yInt;
  74. if (yTmp < yAccum)
  75. {
  76. pjSrcScan += pStrBlt->lDeltaSrc;
  77. }
  78. yAccum = yTmp;
  79. pjDst += lDstStride;
  80. } while (--yCount);
  81. }
  82. /******************************Public*Routine******************************\
  83. *
  84. * Routine Name
  85. *
  86. * vDirectStretch32
  87. *
  88. * Routine Description:
  89. *
  90. * Stretch blt 32->32
  91. *
  92. * Arguments:
  93. *
  94. * pStrBlt - contains all params for blt
  95. *
  96. * Return Value:
  97. *
  98. * VOID
  99. *
  100. \**************************************************************************/
  101. VOID vDirectStretch32(
  102. STR_BLT* pStrBlt)
  103. {
  104. BYTE* pjOldScan;
  105. ULONG* pulSrc;
  106. ULONG* pulDstEnd;
  107. ULONG ulDst;
  108. ULONG xAccum;
  109. ULONG xTmp;
  110. ULONG yTmp;
  111. LONG cyDuplicate;
  112. PDEV* ppdev = pStrBlt->ppdev;
  113. LONG xDst = pStrBlt->XDstStart;
  114. LONG xSrc = pStrBlt->XSrcStart;
  115. BYTE* pjSrcScan = pStrBlt->pjSrcScan + xSrc * 4;
  116. ULONG* pulDst = (ULONG*)(pStrBlt->pjDstScan) + xDst;
  117. LONG yDst = pStrBlt->YDstStart + ppdev->yOffset;
  118. LONG yCount = pStrBlt->YDstCount;
  119. LONG WidthX = pStrBlt->XDstEnd - xDst;
  120. ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
  121. ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
  122. ULONG yAccum = pStrBlt->ulYFracAccumulator;
  123. ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
  124. LONG lDstStride = pStrBlt->lDeltaDst - 4*WidthX;
  125. ULONG yInt = 0;
  126. //
  127. // if this is a shrinking blt, calc src scan line stride
  128. //
  129. if (pStrBlt->ulYDstToSrcIntCeil != 0)
  130. {
  131. yInt = pStrBlt->lDeltaSrc * pStrBlt->ulYDstToSrcIntCeil;
  132. }
  133. do {
  134. ULONG ulSrc;
  135. ULONG yTmp;
  136. pulSrc = (ULONG*) pjSrcScan;
  137. xAccum = pStrBlt->ulXFracAccumulator;
  138. //
  139. // a single src scan line is being written
  140. //
  141. pulDstEnd = pulDst + WidthX;
  142. while (pulDst != pulDstEnd)
  143. {
  144. ulSrc = *pulSrc;
  145. xTmp = xAccum + xFrac;
  146. pulSrc = pulSrc + xInt;
  147. if (xTmp < xAccum)
  148. pulSrc++;
  149. *(ULONG*)pulDst = ulSrc;
  150. pulDst++;
  151. xAccum = xTmp;
  152. }
  153. pjOldScan = pjSrcScan;
  154. pjSrcScan += yInt;
  155. yTmp = yAccum + yFrac;
  156. if (yTmp < yAccum)
  157. {
  158. pjSrcScan += pStrBlt->lDeltaSrc;
  159. }
  160. yAccum = yTmp;
  161. pulDst = (ULONG*) ((BYTE*) pulDst + lDstStride);
  162. yDst++;
  163. yCount--;
  164. if ((yCount != 0) && (pjSrcScan == pjOldScan))
  165. {
  166. // It's an expanding stretch in 'y'; the scan we just laid down
  167. // will be copied at least once using the hardware:
  168. cyDuplicate = 0;
  169. do {
  170. cyDuplicate++;
  171. pjSrcScan += yInt;
  172. yTmp = yAccum + yFrac;
  173. if (yTmp < yAccum)
  174. {
  175. pjSrcScan += pStrBlt->lDeltaSrc;
  176. }
  177. yAccum = yTmp;
  178. pulDst = (ULONG*) ((BYTE*) pulDst + pStrBlt->lDeltaDst);
  179. yCount--;
  180. } while ((yCount != 0) && (pjSrcScan == pjOldScan));
  181. // The scan is to be copied 'cyDuplicate' times using the
  182. // hardware. On the S3, we have to turn off frame-buffer
  183. // access before touching the accelerator registers:
  184. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_OFF);
  185. IO_FIFO_WAIT(ppdev, 4);
  186. IO_MIN_AXIS_PCNT(ppdev, cyDuplicate - 1);
  187. IO_ABS_DEST_Y(ppdev, yDst);
  188. IO_ABS_CUR_Y(ppdev, yDst - 1);
  189. IO_CMD(ppdev, (BITBLT | DRAW | DIR_TYPE_XY | WRITE |
  190. DRAWING_DIR_TBLRXM));
  191. yDst += cyDuplicate;
  192. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, ppdev->bankmOnOverlapped);
  193. }
  194. } while (yCount != 0);
  195. }
  196. /******************************Public*Routine******************************\
  197. *
  198. * Routine Description:
  199. *
  200. * StretchBlt using integer math. Must be from one surface to another
  201. * surface of the same format.
  202. *
  203. * Arguments:
  204. *
  205. * ppdev - PDEV for device
  206. * pvDst - Pointer to start of dst bitmap
  207. * lDeltaDst - Bytes from start of dst scan line to start of next
  208. * DstCx - Width of Dst Bitmap in pixels
  209. * DstCy - Height of Dst Bitmap in pixels
  210. * prclDst - Pointer to rectangle of Dst extents
  211. * pvSrc - Pointer to start of Src bitmap
  212. * lDeltaSrc - Bytes from start of Src scan line to start of next
  213. * SrcCx - Width of Src Bitmap in pixels
  214. * SrcCy - Height of Src Bitmap in pixels
  215. * prclSrc - Pointer to rectangle of Src extents
  216. * prclSClip - Clip Dest to this rect
  217. *
  218. * Return Value:
  219. *
  220. * Status
  221. *
  222. \**************************************************************************/
  223. BOOL bStretchDIB(
  224. PDEV* ppdev,
  225. VOID* pvDst,
  226. LONG lDeltaDst,
  227. RECTL* prclDst,
  228. VOID* pvSrc,
  229. LONG lDeltaSrc,
  230. RECTL* prclSrc,
  231. RECTL* prclClip)
  232. {
  233. STR_BLT StrBlt;
  234. ULONG XSrcToDstIntFloor;
  235. ULONG XSrcToDstFracFloor;
  236. ULONG ulXDstToSrcIntCeil;
  237. ULONG ulXDstToSrcFracCeil;
  238. ULONG YSrcToDstIntFloor;
  239. ULONG YSrcToDstFracFloor;
  240. ULONG ulYDstToSrcIntCeil;
  241. ULONG ulYDstToSrcFracCeil;
  242. LONG SrcIntScan;
  243. LONG DstDeltaScanEnd;
  244. ULONG ulXFracAccumulator;
  245. ULONG ulYFracAccumulator;
  246. LONG LeftClipDistance;
  247. LONG TopClipDistance;
  248. BOOL bStretch;
  249. union {
  250. LARGE_INTEGER large;
  251. ULONGLONG li;
  252. } liInit;
  253. PFN_DIRSTRETCH pfnStr;
  254. //
  255. // Calculate exclusive start and end points:
  256. //
  257. LONG WidthDst = prclDst->right - prclDst->left;
  258. LONG HeightDst = prclDst->bottom - prclDst->top;
  259. LONG WidthSrc = prclSrc->right - prclSrc->left;
  260. LONG HeightSrc = prclSrc->bottom - prclSrc->top;
  261. LONG XSrcStart = prclSrc->left;
  262. LONG XSrcEnd = prclSrc->right;
  263. LONG XDstStart = prclDst->left;
  264. LONG XDstEnd = prclDst->right;
  265. LONG YSrcStart = prclSrc->top;
  266. LONG YSrcEnd = prclSrc->bottom;
  267. LONG YDstStart = prclDst->top;
  268. LONG YDstEnd = prclDst->bottom;
  269. //
  270. // Validate parameters:
  271. //
  272. ASSERTDD(pvDst != (VOID*)NULL, "Bad destination bitmap pointer");
  273. ASSERTDD(pvSrc != (VOID*)NULL, "Bad source bitmap pointer");
  274. ASSERTDD(prclDst != (RECTL*)NULL, "Bad destination rectangle");
  275. ASSERTDD(prclSrc != (RECTL*)NULL, "Bad source rectangle");
  276. ASSERTDD((WidthDst > 0) && (HeightDst > 0) &&
  277. (WidthSrc > 0) && (HeightSrc > 0),
  278. "Can't do mirroring or empty rectangles here");
  279. ASSERTDD((WidthDst <= STRETCH_MAX_EXTENT) &&
  280. (HeightDst <= STRETCH_MAX_EXTENT) &&
  281. (WidthSrc <= STRETCH_MAX_EXTENT) &&
  282. (HeightSrc <= STRETCH_MAX_EXTENT), "Stretch exceeds limits");
  283. ASSERTDD(prclClip != NULL, "Bad clip rectangle");
  284. //
  285. // Calculate X Dst to Src mapping
  286. //
  287. //
  288. // dst->src = ( CEIL( (2k*WidthSrc)/WidthDst) ) / 2k
  289. //
  290. // = ( FLOOR( (2k*WidthSrc -1) / WidthDst) + 1) / 2k
  291. //
  292. // where 2k = 2 ^ 32
  293. //
  294. {
  295. ULONGLONG liWidthSrc;
  296. ULONGLONG liQuo;
  297. ULONG ulTemp;
  298. //
  299. // Work around a compiler bug dealing with the assignment
  300. // 'liHeightSrc = (((LONGLONG)HeightSrc) << 32) - 1':
  301. //
  302. liInit.large.LowPart = (ULONG) -1;
  303. liInit.large.HighPart = WidthSrc - 1;
  304. liWidthSrc = liInit.li;
  305. liQuo = liWidthSrc / (ULONGLONG) WidthDst;
  306. ulXDstToSrcIntCeil = (ULONG)(liQuo >> 32);
  307. ulXDstToSrcFracCeil = (ULONG)liQuo;
  308. //
  309. // Now add 1, use fake carry:
  310. //
  311. ulTemp = ulXDstToSrcFracCeil + 1;
  312. ulXDstToSrcIntCeil += (ulTemp < ulXDstToSrcFracCeil);
  313. ulXDstToSrcFracCeil = ulTemp;
  314. }
  315. //
  316. // Calculate Y Dst to Src mapping
  317. //
  318. //
  319. // dst->src = ( CEIL( (2k*HeightSrc)/HeightDst) ) / 2k
  320. //
  321. // = ( FLOOR( (2k*HeightSrc -1) / HeightDst) + 1) / 2k
  322. //
  323. // where 2k = 2 ^ 32
  324. //
  325. {
  326. ULONGLONG liHeightSrc;
  327. ULONGLONG liQuo;
  328. ULONG ulTemp;
  329. //
  330. // Work around a compiler bug dealing with the assignment
  331. // 'liHeightSrc = (((LONGLONG)HeightSrc) << 32) - 1':
  332. //
  333. liInit.large.LowPart = (ULONG) -1;
  334. liInit.large.HighPart = HeightSrc - 1;
  335. liHeightSrc = liInit.li;
  336. liQuo = liHeightSrc / (ULONGLONG) HeightDst;
  337. ulYDstToSrcIntCeil = (ULONG)(liQuo >> 32);
  338. ulYDstToSrcFracCeil = (ULONG)liQuo;
  339. //
  340. // Now add 1, use fake carry:
  341. //
  342. ulTemp = ulYDstToSrcFracCeil + 1;
  343. ulYDstToSrcIntCeil += (ulTemp < ulYDstToSrcFracCeil);
  344. ulYDstToSrcFracCeil = ulTemp;
  345. }
  346. //
  347. // Now clip Dst in X, and/or calc src clipping effect on dst
  348. //
  349. // adjust left and right edges if needed, record
  350. // distance adjusted for fixing the src
  351. //
  352. if (XDstStart < prclClip->left)
  353. {
  354. XDstStart = prclClip->left;
  355. }
  356. if (XDstEnd > prclClip->right)
  357. {
  358. XDstEnd = prclClip->right;
  359. }
  360. //
  361. // Check for totally clipped out destination:
  362. //
  363. if (XDstEnd <= XDstStart)
  364. {
  365. return(TRUE);
  366. }
  367. LeftClipDistance = XDstStart - prclDst->left;
  368. {
  369. ULONG ulTempInt;
  370. ULONG ulTempFrac;
  371. //
  372. // Calculate displacement for .5 in destination and add:
  373. //
  374. ulTempFrac = (ulXDstToSrcFracCeil >> 1) | (ulXDstToSrcIntCeil << 31);
  375. ulTempInt = (ulXDstToSrcIntCeil >> 1);
  376. XSrcStart += ulTempInt;
  377. ulXFracAccumulator = ulTempFrac;
  378. if (LeftClipDistance != 0)
  379. {
  380. ULONGLONG ullFraction;
  381. ULONG ulTmp;
  382. ullFraction = UInt32x32To64(ulXDstToSrcFracCeil, LeftClipDistance);
  383. ulTmp = ulXFracAccumulator;
  384. ulXFracAccumulator += (ULONG) (ullFraction);
  385. if (ulXFracAccumulator < ulTmp)
  386. XSrcStart++;
  387. XSrcStart += (ulXDstToSrcIntCeil * LeftClipDistance)
  388. + (ULONG) (ullFraction >> 32);
  389. }
  390. }
  391. //
  392. // Now clip Dst in Y, and/or calc src clipping effect on dst
  393. //
  394. // adjust top and bottom edges if needed, record
  395. // distance adjusted for fixing the src
  396. //
  397. if (YDstStart < prclClip->top)
  398. {
  399. YDstStart = prclClip->top;
  400. }
  401. if (YDstEnd > prclClip->bottom)
  402. {
  403. YDstEnd = prclClip->bottom;
  404. }
  405. //
  406. // Check for totally clipped out destination:
  407. //
  408. if (YDstEnd <= YDstStart)
  409. {
  410. return(TRUE);
  411. }
  412. TopClipDistance = YDstStart - prclDst->top;
  413. {
  414. ULONG ulTempInt;
  415. ULONG ulTempFrac;
  416. //
  417. // Calculate displacement for .5 in destination and add:
  418. //
  419. ulTempFrac = (ulYDstToSrcFracCeil >> 1) | (ulYDstToSrcIntCeil << 31);
  420. ulTempInt = ulYDstToSrcIntCeil >> 1;
  421. YSrcStart += (LONG)ulTempInt;
  422. ulYFracAccumulator = ulTempFrac;
  423. if (TopClipDistance != 0)
  424. {
  425. ULONGLONG ullFraction;
  426. ULONG ulTmp;
  427. ullFraction = UInt32x32To64(ulYDstToSrcFracCeil, TopClipDistance);
  428. ulTmp = ulYFracAccumulator;
  429. ulYFracAccumulator += (ULONG) (ullFraction);
  430. if (ulYFracAccumulator < ulTmp)
  431. YSrcStart++;
  432. YSrcStart += (ulYDstToSrcIntCeil * TopClipDistance)
  433. + (ULONG) (ullFraction >> 32);
  434. }
  435. }
  436. //
  437. // Warm up the hardware if doing an expanding stretch in 'y':
  438. //
  439. bStretch = (HeightDst > HeightSrc);
  440. if (bStretch)
  441. {
  442. LONG x;
  443. //
  444. // We'll be banging on the CRTC registers whenever we enable
  445. // and disable direct frame buffer access; we can't have the
  446. // cursor thread banging on them at the same. So we grab the
  447. // CRTC critical section for the duration of the StretchBlt.
  448. //
  449. // Note that this CRTC critical section problem and the bank
  450. // mode selection logic are rather S3 specific -- other video
  451. // cards shouldn't have to worry about this.
  452. //
  453. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  454. //
  455. // Set up the left and right blt edges, since they never change
  456. // during the StretchBlt
  457. //
  458. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_OFF);
  459. IO_FIFO_WAIT(ppdev, 5);
  460. IO_FRGD_MIX(ppdev, SRC_DISPLAY_MEMORY | OVERPAINT);
  461. IO_PIX_CNTL(ppdev, ALL_ONES);
  462. IO_CUR_X(ppdev, XDstStart);
  463. IO_DEST_X(ppdev, XDstStart);
  464. IO_MAJ_AXIS_PCNT(ppdev, XDstEnd - XDstStart - 1);
  465. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, ppdev->bankmOnOverlapped);
  466. }
  467. //
  468. // Fill out blt structure, then call format-specific stretch code
  469. //
  470. StrBlt.ppdev = ppdev;
  471. StrBlt.XDstEnd = XDstEnd;
  472. StrBlt.YDstStart = YDstStart;
  473. StrBlt.YDstCount = YDstEnd - YDstStart;
  474. if (StrBlt.YDstCount > 0)
  475. {
  476. //
  477. // Caclulate starting scan line address. Since the inner loop
  478. // routines are format dependent, they must add XDstStart/XSrcStart
  479. // to pjDstScan/pjSrcScan to get the actual starting pixel address.
  480. //
  481. StrBlt.pjSrcScan = (BYTE*) pvSrc + (YSrcStart * lDeltaSrc);
  482. StrBlt.pjDstScan = (BYTE*) pvDst + (YDstStart * lDeltaDst);
  483. StrBlt.lDeltaSrc = lDeltaSrc;
  484. StrBlt.XSrcStart = XSrcStart;
  485. StrBlt.XDstStart = XDstStart;
  486. StrBlt.lDeltaDst = lDeltaDst;
  487. StrBlt.ulXDstToSrcIntCeil = ulXDstToSrcIntCeil;
  488. StrBlt.ulXDstToSrcFracCeil = ulXDstToSrcFracCeil;
  489. StrBlt.ulYDstToSrcIntCeil = ulYDstToSrcIntCeil;
  490. StrBlt.ulYDstToSrcFracCeil = ulYDstToSrcFracCeil;
  491. StrBlt.ulXFracAccumulator = ulXFracAccumulator;
  492. StrBlt.ulYFracAccumulator = ulYFracAccumulator;
  493. if (ppdev->iBitmapFormat == BMF_8BPP)
  494. {
  495. if ((XDstEnd - XDstStart) < 7)
  496. pfnStr = vDirectStretch8Narrow;
  497. else
  498. pfnStr = vDirectStretch8;
  499. }
  500. else if (ppdev->iBitmapFormat == BMF_16BPP)
  501. {
  502. pfnStr = vDirectStretch16;
  503. }
  504. else
  505. {
  506. ASSERTDD(ppdev->iBitmapFormat == BMF_32BPP,
  507. "Only handle stretchs at 8, 16 and 32bpp");
  508. pfnStr = vDirectStretch32;
  509. }
  510. (*pfnStr)(&StrBlt);
  511. }
  512. if (bStretch)
  513. {
  514. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  515. }
  516. return(TRUE);
  517. }
  518. /******************************Public*Routine******************************\
  519. * BOOL bBankedStretch
  520. *
  521. \**************************************************************************/
  522. BOOL bBankedStretch(
  523. PDEV* ppdev,
  524. VOID* pvDst,
  525. LONG lDeltaDst,
  526. RECTL* prclDst,
  527. VOID* pvSrc,
  528. LONG lDeltaSrc,
  529. RECTL* prclSrc,
  530. RECTL* prclClip)
  531. {
  532. BANK bnk;
  533. BOOL b;
  534. RECTL rclDst;
  535. b = TRUE;
  536. if (bIntersect(prclDst, prclClip, &rclDst))
  537. {
  538. vBankStart(ppdev, &rclDst, NULL, &bnk);
  539. do {
  540. b &= bStretchDIB(ppdev,
  541. bnk.pso->pvScan0,
  542. lDeltaDst,
  543. prclDst,
  544. pvSrc,
  545. lDeltaSrc,
  546. prclSrc,
  547. &bnk.pco->rclBounds);
  548. } while (bBankEnum(&bnk));
  549. }
  550. return(b);
  551. }
  552. /******************************Public*Routine******************************\
  553. * BOOL DrvStretchBlt
  554. *
  555. \**************************************************************************/
  556. BOOL DrvStretchBlt(
  557. SURFOBJ* psoDst,
  558. SURFOBJ* psoSrc,
  559. SURFOBJ* psoMsk,
  560. CLIPOBJ* pco,
  561. XLATEOBJ* pxlo,
  562. COLORADJUSTMENT* pca,
  563. POINTL* pptlHTOrg,
  564. RECTL* prclDst,
  565. RECTL* prclSrc,
  566. POINTL* pptlMsk,
  567. ULONG iMode)
  568. {
  569. DSURF* pdsurfSrc;
  570. DSURF* pdsurfDst;
  571. PDEV* ppdev;
  572. // GDI guarantees us that for a StretchBlt the destination surface
  573. // will always be a device surface, and not a DIB:
  574. ppdev = (PDEV*) psoDst->dhpdev;
  575. // It's quicker for GDI to do a StretchBlt when the source surface
  576. // is not a device-managed surface, because then it can directly
  577. // read the source bits without having to allocate a temporary
  578. // buffer and call DrvCopyBits to get a copy that it can use.
  579. if (psoSrc->iType == STYPE_DEVBITMAP)
  580. {
  581. goto Punt_It;
  582. }
  583. pdsurfDst = (DSURF*) psoDst->dhsurf;
  584. ASSERTDD(!(pdsurfDst->dt & DT_DIB), "Didn't expect DT_DIB");
  585. ppdev->xOffset = pdsurfDst->x;
  586. ppdev->yOffset = pdsurfDst->y;
  587. // Our special-case StretchBlt code assumes a dense frame buffer
  588. // space, so this code can't be executed when using sparse space
  589. // on the Alpha. Note that since we don't read from the frame
  590. // buffer, we can allow this to go through even when
  591. // CAPS_NO_DIRECT_ACCESS is set on the PPC.
  592. if (DENSE(ppdev))
  593. {
  594. RECTL rclClip;
  595. RECTL* prclClip;
  596. ULONG cxDst;
  597. ULONG cyDst;
  598. ULONG cxSrc;
  599. ULONG cySrc;
  600. BOOL bMore;
  601. CLIPENUM ce;
  602. LONG c;
  603. LONG i;
  604. if ((psoSrc->iType == STYPE_BITMAP) &&
  605. (psoMsk == NULL) &&
  606. ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)) &&
  607. ((psoSrc->iBitmapFormat == ppdev->iBitmapFormat)) &&
  608. (ppdev->iBitmapFormat != BMF_24BPP))
  609. {
  610. cxDst = prclDst->right - prclDst->left;
  611. cyDst = prclDst->bottom - prclDst->top;
  612. cxSrc = prclSrc->right - prclSrc->left;
  613. cySrc = prclSrc->bottom - prclSrc->top;
  614. // Our 'bStretchDIB' routine requires that the stretch be
  615. // non-inverting, within a certain size, to have no source
  616. // clipping, and to have no empty rectangles (the latter is the
  617. // reason for the '- 1' on the unsigned compare here):
  618. if (((cxSrc - 1) < STRETCH_MAX_EXTENT) &&
  619. ((cySrc - 1) < STRETCH_MAX_EXTENT) &&
  620. ((cxDst - 1) < STRETCH_MAX_EXTENT) &&
  621. ((cyDst - 1) < STRETCH_MAX_EXTENT) &&
  622. (prclSrc->left >= 0) &&
  623. (prclSrc->top >= 0) &&
  624. (prclSrc->right <= psoSrc->sizlBitmap.cx) &&
  625. (prclSrc->bottom <= psoSrc->sizlBitmap.cy))
  626. {
  627. // Our snazzy routine only does COLORONCOLOR. But for
  628. // stretching blts, BLACKONWHITE and WHITEONBLACK are also
  629. // equivalent to COLORONCOLOR:
  630. if ((iMode == COLORONCOLOR) ||
  631. ((iMode < COLORONCOLOR) && (cxSrc <= cxDst) && (cySrc <= cyDst)))
  632. {
  633. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  634. {
  635. rclClip.left = LONG_MIN;
  636. rclClip.top = LONG_MIN;
  637. rclClip.right = LONG_MAX;
  638. rclClip.bottom = LONG_MAX;
  639. prclClip = &rclClip;
  640. StretchSingleClipRect:
  641. if (bBankedStretch(ppdev,
  642. NULL,
  643. ppdev->lDelta,
  644. prclDst,
  645. psoSrc->pvScan0,
  646. psoSrc->lDelta,
  647. prclSrc,
  648. prclClip))
  649. {
  650. return(TRUE);
  651. }
  652. }
  653. else if (pco->iDComplexity == DC_RECT)
  654. {
  655. prclClip = &pco->rclBounds;
  656. goto StretchSingleClipRect;
  657. }
  658. else
  659. {
  660. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  661. do {
  662. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG*) &ce);
  663. c = cIntersect(prclDst, ce.arcl, ce.c);
  664. if (c != 0)
  665. {
  666. for (i = 0; i < c; i++)
  667. {
  668. if (!bBankedStretch(ppdev,
  669. NULL,
  670. ppdev->lDelta,
  671. prclDst,
  672. psoSrc->pvScan0,
  673. psoSrc->lDelta,
  674. prclSrc,
  675. &ce.arcl[i]))
  676. {
  677. goto Punt_It;
  678. }
  679. }
  680. }
  681. } while (bMore);
  682. return(TRUE);
  683. }
  684. }
  685. }
  686. }
  687. }
  688. Punt_It:
  689. // GDI is nice enough to handle the cases where 'psoDst' and/or 'psoSrc'
  690. // are device-managed surfaces, but it ain't gonna be fast...
  691. return(EngStretchBlt(psoDst, psoSrc, psoMsk, pco, pxlo, pca, pptlHTOrg,
  692. prclDst, prclSrc, pptlMsk, iMode));
  693. }