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.

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