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.

692 lines
26 KiB

  1. /******************************Module*Header***********************************\
  2. *
  3. * *******************
  4. * * GDI SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: stretch.c
  8. *
  9. * Contains all the stretch blt functions.
  10. *
  11. * Copyright (C) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
  12. * Copyright (C) 1995-1999 Microsoft Corporation. All rights reserved.
  13. ******************************************************************************/
  14. #include "precomp.h"
  15. #include "gdi.h"
  16. #include "directx.h"
  17. #include "clip.h"
  18. //
  19. // Maximal clip rectangle for trivial stretch clipping
  20. //
  21. // Note: SCISSOR_MAX is defined as 2047 because this is
  22. // the maximum clip size P2 can handle.
  23. // It is OK to set this maximum clip size since no device
  24. // bitmap will be bigger than 2047. This is the limitation
  25. // of P2 hardware. See DrvCreateDeviceBitmap() for more
  26. // detail
  27. //
  28. RECTL grclStretchClipMax = { 0, 0, SCISSOR_MAX, SCISSOR_MAX };
  29. //-----------------------------------------------------------------------------
  30. //
  31. // DWORD dwGetPixelSize()
  32. //
  33. // This routine converts current bitmap format to Permedia pixel size
  34. //
  35. //-----------------------------------------------------------------------------
  36. DWORD
  37. dwGetPixelSize(ULONG ulBitmapFormat,
  38. DWORD* pdwFormatBits,
  39. DWORD* pdwFormatExtention)
  40. {
  41. DWORD dwPixelSize;
  42. switch ( ulBitmapFormat )
  43. {
  44. case BMF_8BPP:
  45. dwPixelSize = 0;
  46. *pdwFormatBits = PERMEDIA_8BIT_PALETTEINDEX;
  47. *pdwFormatExtention = PERMEDIA_8BIT_PALETTEINDEX_EXTENSION;
  48. break;
  49. case BMF_16BPP:
  50. dwPixelSize = 1;
  51. *pdwFormatBits = PERMEDIA_565_RGB;
  52. *pdwFormatExtention = PERMEDIA_565_RGB_EXTENSION;
  53. break;
  54. case BMF_32BPP:
  55. dwPixelSize = 2;
  56. *pdwFormatBits = PERMEDIA_888_RGB;
  57. *pdwFormatExtention = PERMEDIA_888_RGB_EXTENSION;
  58. break;
  59. default:
  60. dwPixelSize = -1;
  61. }
  62. return dwPixelSize;
  63. }// dwGetPixelSize()
  64. //-----------------------------------------------------------------------------
  65. //
  66. // DWORD bStretchInit()
  67. //
  68. // This routine initializes all the registers needed for doing a stretch blt
  69. //
  70. //-----------------------------------------------------------------------------
  71. BOOL
  72. bStretchInit(SURFOBJ* psoDst,
  73. SURFOBJ* psoSrc)
  74. {
  75. Surf* pSurfDst = (Surf*)psoDst->dhsurf;
  76. Surf* pSurfSrc = (Surf*)psoSrc->dhsurf;
  77. DWORD dwDstPixelSize;
  78. DWORD dwDstFormatBits;
  79. DWORD dwDstFormatExtention;
  80. DWORD dwSrcPixelSize;
  81. DWORD dwSrcFormatBits;
  82. DWORD dwSrcFormatExtention;
  83. PDev* ppdev = (PDev*)psoDst->dhpdev;
  84. ULONG* pBuffer;
  85. DBG_GDI((6, "bStretchInit called"));
  86. ASSERTDD(pSurfSrc, "Not valid private surface in source");
  87. ASSERTDD(pSurfDst, "Not valid private surface in destination");
  88. dwDstPixelSize = dwGetPixelSize(psoDst->iBitmapFormat,
  89. &dwDstFormatBits,
  90. &dwDstFormatExtention);
  91. if ( dwDstPixelSize == -1 )
  92. {
  93. DBG_GDI((1, "bStretchBlt return FALSE because of wrong DstPixel Size"));
  94. //
  95. // Unsupported bitmap format, return false
  96. //
  97. return FALSE;
  98. }
  99. InputBufferReserve(ppdev, 26, &pBuffer);
  100. if ( dwDstPixelSize != __PERMEDIA_8BITPIXEL)
  101. {
  102. pBuffer[0] = __Permedia2TagDitherMode;
  103. pBuffer[1] = (COLOR_MODE << PM_DITHERMODE_COLORORDER) // RGB color order
  104. |(dwDstFormatBits << PM_DITHERMODE_COLORFORMAT)
  105. |(dwDstFormatExtention << PM_DITHERMODE_COLORFORMATEXTENSION)
  106. |(1 << PM_DITHERMODE_ENABLE);
  107. }
  108. else
  109. {
  110. pBuffer[0] = __Permedia2TagDitherMode;
  111. pBuffer[1] = __PERMEDIA_DISABLE;
  112. }
  113. pBuffer[2] = __Permedia2TagFBWindowBase;
  114. pBuffer[3] = pSurfDst->ulPixOffset;
  115. //
  116. // Set no read of source.
  117. //
  118. pBuffer[4] = __Permedia2TagFBReadMode;
  119. pBuffer[5] = PM_FBREADMODE_PARTIAL(pSurfDst->ulPackedPP);
  120. pBuffer[6] = __Permedia2TagLogicalOpMode;
  121. pBuffer[7] = __PERMEDIA_DISABLE;
  122. pBuffer[8] = __Permedia2TagTextureBaseAddress;
  123. pBuffer[9] = pSurfSrc->ulPixOffset;
  124. pBuffer[10] = __Permedia2TagTextureAddressMode;
  125. pBuffer[11] = 1 << PM_TEXADDRESSMODE_ENABLE;
  126. pBuffer[12] = __Permedia2TagTextureColorMode;
  127. pBuffer[13] = (1 << PM_TEXCOLORMODE_ENABLE)
  128. | (0 << 4) // RGB
  129. | (_P2_TEXTURE_COPY << PM_TEXCOLORMODE_APPLICATION);
  130. //
  131. // Note: we have to turn off BiLinear filtering here, even for stretch
  132. // because GDI doesn't do it. Otherwise, we will fail during the
  133. // comparison
  134. //
  135. pBuffer[14] = __Permedia2TagTextureReadMode;
  136. pBuffer[15] = PM_TEXREADMODE_ENABLE(__PERMEDIA_ENABLE)
  137. | PM_TEXREADMODE_FILTER(__PERMEDIA_DISABLE)
  138. | PM_TEXREADMODE_WIDTH(11)
  139. | PM_TEXREADMODE_HEIGHT(11);
  140. dwSrcPixelSize = dwGetPixelSize(psoSrc->iBitmapFormat,
  141. &dwSrcFormatBits,
  142. &dwSrcFormatExtention);
  143. if ( dwSrcPixelSize == -1 )
  144. {
  145. DBG_GDI((1, "bStretchBlt return FALSE because of wrong SrcPixel Size"));
  146. //
  147. // Unsupported bitmap format, return false
  148. //
  149. return FALSE;
  150. }
  151. pBuffer[16] = __Permedia2TagTextureDataFormat;
  152. pBuffer[17] = (dwSrcFormatBits << PM_TEXDATAFORMAT_FORMAT)
  153. | (dwSrcFormatExtention << PM_TEXDATAFORMAT_FORMATEXTENSION)
  154. | (COLOR_MODE << PM_TEXDATAFORMAT_COLORORDER);
  155. pBuffer[18] = __Permedia2TagTextureMapFormat;
  156. pBuffer[19] = pSurfSrc->ulPackedPP
  157. |(dwSrcPixelSize << PM_TEXMAPFORMAT_TEXELSIZE);
  158. pBuffer[20] = __Permedia2TagScissorMode;
  159. pBuffer[21] = SCREEN_SCISSOR_DEFAULT
  160. | USER_SCISSOR_ENABLE;
  161. pBuffer[22] = __Permedia2TagdSdyDom;
  162. pBuffer[23] = 0;
  163. pBuffer[24] = __Permedia2TagdTdx;
  164. pBuffer[25] = 0;
  165. pBuffer += 26;
  166. InputBufferCommit(ppdev, pBuffer);
  167. DBG_GDI((6, "bStretchInit return TRUE"));
  168. return TRUE;
  169. }// bStretchInit()
  170. //-----------------------------------------------------------------------------
  171. //
  172. // DWORD bStretchReset()
  173. //
  174. // This routine resets all the registers changed during stretch blt
  175. //
  176. //-----------------------------------------------------------------------------
  177. void
  178. vStretchReset(PDev* ppdev)
  179. {
  180. ULONG* pBuffer;
  181. DBG_GDI((6, "vStretchReset called"));
  182. InputBufferReserve(ppdev, 12, &pBuffer);
  183. //
  184. // Restore the default settings
  185. //
  186. pBuffer[0] = __Permedia2TagScissorMode;
  187. pBuffer[1] = SCREEN_SCISSOR_DEFAULT;
  188. pBuffer[2] = __Permedia2TagDitherMode;
  189. pBuffer[3] = __PERMEDIA_DISABLE;
  190. pBuffer[4] = __Permedia2TagTextureAddressMode;
  191. pBuffer[5] = __PERMEDIA_DISABLE;
  192. pBuffer[6] = __Permedia2TagTextureColorMode;
  193. pBuffer[7] = __PERMEDIA_DISABLE;
  194. pBuffer[8] = __Permedia2TagTextureReadMode;
  195. pBuffer[9] = __PERMEDIA_DISABLE;
  196. pBuffer[10] = __Permedia2TagdY;
  197. pBuffer[11] = INTtoFIXED(1);
  198. pBuffer += 12;
  199. InputBufferCommit(ppdev, pBuffer);
  200. DBG_GDI((6, "vStretchReset done"));
  201. return;
  202. }// vStretchReset()
  203. //-----------------------------------------------------------------------------
  204. //
  205. // VOID vStretchBlt()
  206. //
  207. // This routine does the stretch blt work through the texture engine
  208. //
  209. //-----------------------------------------------------------------------------
  210. VOID
  211. vStretchBlt(SURFOBJ* psoDst,
  212. SURFOBJ* psoSrc,
  213. RECTL* rDest,
  214. RECTL* rSrc,
  215. RECTL* prclClip)
  216. {
  217. Surf* pSurfDst = (Surf*)psoDst->dhsurf;
  218. Surf* pSurfSrc = (Surf*)psoSrc->dhsurf;
  219. LONG lXScale;
  220. LONG lYScale;
  221. DWORD dwDestWidth = rDest->right - rDest->left;
  222. DWORD dwDestHeight = rDest->bottom - rDest->top;
  223. DWORD dwSourceWidth = rSrc->right - rSrc->left;
  224. DWORD dwSourceHeight = rSrc->bottom - rSrc->top;
  225. DWORD dwRenderDirection;
  226. DWORD dwDstPixelSize;
  227. DWORD dwDstFormatBits;
  228. DWORD dwDstFormatExtention;
  229. DWORD dwSrcPixelSize;
  230. DWORD dwSrcFormatBits;
  231. DWORD dwSrcFormatExtention;
  232. ULONG* pBuffer;
  233. PDev* ppdev = (PDev*)psoDst->dhpdev;
  234. DBG_GDI((6, "vStretchBlt called"));
  235. DBG_GDI((6, "prclClip (left, right, top, bottom)=(%d, %d, %d,%d)",
  236. prclClip->left, prclClip->right, prclClip->top, prclClip->bottom));
  237. DBG_GDI((6, "rSrc (left, right, top, bottom=(%d, %d, %d,%d)",rSrc->left,
  238. rSrc->right, rSrc->top, rSrc->bottom));
  239. DBG_GDI((6, "rDest (left, right, top, bottom)=(%d, %d, %d,%d)",rDest->left,
  240. rDest->right, rDest->top, rDest->bottom));
  241. ASSERTDD(prclClip != NULL, "Wrong clippng rectangle");
  242. //
  243. // Note: the scale factor register value: dsDx, dTdyDom's interger part
  244. // starts at bit 20. So we need to "<< 20" here
  245. //
  246. lXScale = (dwSourceWidth << 20) / dwDestWidth;
  247. lYScale = (dwSourceHeight << 20) / dwDestHeight;
  248. // lXScale = (((dwSourceWidth << 18) - 1) / dwDestWidth) << 2;
  249. // lYScale = (((dwSourceHeight << 18) - 1) / dwDestHeight) << 2;
  250. DBG_GDI((6, "lXScale=0x%x, lYScale=0x%x", lXScale, lYScale));
  251. DBG_GDI((6, "dwSourceWidth=%d, dwDestWidth=%d",
  252. dwSourceWidth, dwDestWidth));
  253. DBG_GDI((6, "dwSourceHeight=%d, dwDestHeight=%d",
  254. dwSourceHeight, dwDestHeight));
  255. InputBufferReserve(ppdev, 24, &pBuffer);
  256. pBuffer[0] = __Permedia2TagScissorMinXY;
  257. pBuffer[1] = ((prclClip->left)<< SCISSOR_XOFFSET)
  258. |((prclClip->top)<< SCISSOR_YOFFSET);
  259. pBuffer[2] = __Permedia2TagScissorMaxXY;
  260. pBuffer[3] = ((prclClip->right)<< SCISSOR_XOFFSET)
  261. |((prclClip->bottom)<< SCISSOR_YOFFSET);
  262. //
  263. // We need to be carefull with overlapping rectangles
  264. //
  265. if ( (pSurfSrc->ulPixOffset) != (pSurfDst->ulPixOffset) )
  266. {
  267. //
  268. // Src and dst are differnt surface
  269. //
  270. dwRenderDirection = 1;
  271. }
  272. else
  273. {
  274. //
  275. // Src and dst are the same surface
  276. // We will set dwRenderDirection=1 if the src is lower or righter
  277. // than the dst, that is, if it is bottom-up or right-left, we set
  278. // dwRenderDirection=1, otherwise it = 0
  279. //
  280. if ( rSrc->top < rDest->top )
  281. {
  282. dwRenderDirection = 0;
  283. }
  284. else if ( rSrc->top > rDest->top )
  285. {
  286. dwRenderDirection = 1;
  287. }
  288. else if ( rSrc->left < rDest->left )
  289. {
  290. dwRenderDirection = 0;
  291. }
  292. else
  293. {
  294. dwRenderDirection = 1;
  295. }
  296. }// src and dst are different
  297. DBG_GDI((6, "dwRenderDirection=%d", dwRenderDirection));
  298. //
  299. // Render the rectangle
  300. //
  301. if ( dwRenderDirection )
  302. {
  303. pBuffer[4] = __Permedia2TagSStart;
  304. pBuffer[5] = (rSrc->left << 20) + ((lXScale >> 1) & 0xfffffffc);
  305. pBuffer[6] = __Permedia2TagTStart;
  306. pBuffer[7] = (rSrc->top << 20) + ((lYScale >> 1) & 0xfffffffc);
  307. pBuffer[8] = __Permedia2TagdSdx;
  308. pBuffer[9] = lXScale;
  309. pBuffer[10] = __Permedia2TagdTdyDom;
  310. pBuffer[11] = lYScale;
  311. pBuffer[12] = __Permedia2TagStartXDom;
  312. pBuffer[13] = INTtoFIXED(rDest->left);
  313. pBuffer[14] = __Permedia2TagStartXSub;
  314. pBuffer[15] = INTtoFIXED(rDest->right);
  315. pBuffer[16] = __Permedia2TagStartY;
  316. pBuffer[17] = INTtoFIXED(rDest->top);
  317. pBuffer[18] = __Permedia2TagdY;
  318. pBuffer[19] = INTtoFIXED(1);
  319. pBuffer[20] = __Permedia2TagCount;
  320. pBuffer[21] = rDest->bottom - rDest->top;
  321. pBuffer[22] = __Permedia2TagRender;
  322. pBuffer[23] = __RENDER_TRAPEZOID_PRIMITIVE
  323. | __RENDER_TEXTURED_PRIMITIVE;
  324. }
  325. else
  326. {
  327. //
  328. // Render right to left, bottom to top
  329. //
  330. pBuffer[4] = __Permedia2TagSStart;
  331. pBuffer[5] = (rSrc->right << 20) + ((lXScale >> 1)& 0xfffffffc);
  332. pBuffer[6] = __Permedia2TagTStart;
  333. pBuffer[7] = (rSrc->bottom << 20) - ((lYScale >> 1)& 0xfffffffc);
  334. lXScale = -lXScale;
  335. lYScale = -lYScale;
  336. pBuffer[8] = __Permedia2TagdSdx;
  337. pBuffer[9] = lXScale;
  338. pBuffer[10] = __Permedia2TagdTdyDom;
  339. pBuffer[11] = lYScale;
  340. pBuffer[12] = __Permedia2TagStartXDom;
  341. pBuffer[13] = INTtoFIXED(rDest->right);
  342. pBuffer[14] = __Permedia2TagStartXSub;
  343. pBuffer[15] = INTtoFIXED(rDest->left);
  344. pBuffer[16] = __Permedia2TagStartY;
  345. pBuffer[17] = INTtoFIXED(rDest->bottom - 1);
  346. pBuffer[18] = __Permedia2TagdY;
  347. pBuffer[19] = (DWORD)INTtoFIXED(-1);
  348. pBuffer[20] = __Permedia2TagCount;
  349. pBuffer[21] = rDest->bottom - rDest->top;
  350. pBuffer[22] = __Permedia2TagRender;
  351. pBuffer[23] = __RENDER_TRAPEZOID_PRIMITIVE
  352. | __RENDER_TEXTURED_PRIMITIVE;
  353. }
  354. pBuffer += 24;
  355. InputBufferCommit(ppdev, pBuffer);
  356. DBG_GDI((6, "vStretchBlt done"));
  357. return;
  358. }// vStretchBlt()
  359. //-----------------------------Public*Routine----------------------------------
  360. //
  361. // BOOL DrvStretchBlt
  362. //
  363. // DrvStretchBlt provides stretching bit-block transfer capabilities between any
  364. // combination of device-managed and GDI-managed surfaces. This function enables
  365. // the device driver to write to GDI bitmaps, especially when the driver can do
  366. // halftoning. This function allows the same halftoning algorithm to be applied
  367. // to GDI bitmaps and device surfaces.
  368. //
  369. // Parameters
  370. // psoDest-----Points to a SURFOBJ that identifies the surface on which to draw
  371. // psoSrc------Points to a SURFOBJ that defines the source for the bit-block
  372. // transfer operation.
  373. // psoMask-----This optional parameter points to a surface that provides a mask
  374. // for the source. The mask is defined by a logic map, which is a
  375. // bitmap with 1 bit per pixel.
  376. // The mask limits the area of the source that is copied. If this
  377. // parameter is specified, it has an implicit rop4 of 0xCCAA,
  378. // meaning the source should be copied wherever the mask is one,
  379. // but the destination should be left alone wherever the mask is
  380. // zero.
  381. //
  382. // When this parameter is null there is an implicit rop4 of 0xCCCC,
  383. // which means that the source should be copied everywhere in the
  384. // source rectangle.
  385. //
  386. // The mask will always be large enough to contain the relevant
  387. // source; tiling is unnecessary.
  388. // pco---------Points to a CLIPOBJ that limits the area to be modified in the
  389. // destination. GDI services are provided to enumerate the clip
  390. // region as a set of rectangles.
  391. // Whenever possible, GDI simplifies the clipping involved.
  392. // However, unlike DrvBitBlt, DrvStretchBlt can be called with a
  393. // single clipping rectangle. This prevents rounding errors in
  394. // clipping the output.
  395. // pxlo--------Points to a XLATEOBJ that specifies how color indices are to be
  396. // translated between the source and target surfaces.
  397. // The XLATEOBJ can also be queried to find the RGB color for any
  398. // source index. A high quality stretching bit-block transfer will
  399. // need to interpolate colors in some cases.
  400. // pca---------Points to a COLORADJUSTMENT structure that defines the color
  401. // adjustment values to be applied to the source bitmap before
  402. // stretching the bits. (See the Platform SDK.)
  403. // pptlHTOrg---Specifies the origin of the halftone brush. Device drivers that
  404. // use halftone brushes should align the upper left pixel of the
  405. // brush's pattern with this point on the device surface.
  406. // prclDest----Points to a RECTL structure that defines the area to be modified
  407. // in the coordinate system of the destination surface. This
  408. // rectangle is defined by two points that are not necessarily well
  409. // ordered, meaning the coordinates of the second point are not
  410. // necessarily larger than those of the first point. The rectangle
  411. // they describe does not include the lower and right edges. This
  412. // function is never called with an empty destination rectangle.
  413. //
  414. // DrvStretchBlt can do inversions of x and y when the destination
  415. // rectangle is not well ordered.
  416. // prclSrc-----Points to a RECTL that defines the area that will be copied in
  417. // the coordinate system of the source surface. The rectangle is
  418. // defined by two points, and will map onto the rectangle defined
  419. // by prclDest. The points of the source rectangle are well ordered
  420. // This function is never given an empty source rectangle.
  421. //
  422. // The mapping is defined by prclSrc and prclDest. The points
  423. // specified in prclDest and prclSrc lie on integer coordinates,
  424. // which correspond to pixel centers. A rectangle defined by two
  425. // such points is considered to be a geometric rectangle with two
  426. // vertices whose coordinates are the given points, but with 0.5
  427. // subtracted from each coordinate. (POINTL structures should be
  428. // considered a shorthand notation for specifying these fractional
  429. // coordinate vertices.)
  430. //
  431. // The edges of any rectangle never intersect a pixel, but go
  432. // around a set of pixels. The pixels inside the rectangle are
  433. // those expected for a "bottom-right exclusive" rectangle.
  434. // DrvStretchBlt will map the geometric source rectangle exactly
  435. // onto the geometric destination rectangle.
  436. // pptlMask----Points to a POINTL structure that specifies which pixel in the
  437. // given mask corresponds to the upper left pixel in the source
  438. // rectangle. Ignore this parameter if no mask is specified.
  439. // iMode-------Specifies how source pixels are combined to get output pixels.
  440. // The HALFTONE mode is slower than the other modes, but produces
  441. // higher quality images.
  442. // Value Meaning
  443. // WHITEONBLACK On a shrinking bit-block transfer, pixels
  444. // should be combined with a Boolean OR
  445. // operation. On a stretching bit-block
  446. // transfer, pixels should be replicated.
  447. // BLACKONWHITE On a shrinking bit-block transfer, pixels
  448. // should be combined with a Boolean AND
  449. // operation. On a stretching bit-block
  450. // transfer, pixels should be replicated.
  451. // COLORONCOLOR On a shrinking bit-block transfer, enough
  452. // pixels should be ignored so that pixels
  453. // don't need to be combined. On a stretching
  454. // bit-block transfer, pixels should be
  455. // replicated.
  456. // HALFTONE The driver can use groups of pixels in the
  457. // output surface to best approximate the color
  458. // or gray level of the input.
  459. //
  460. // Return Value
  461. // The return value is TRUE if the function is successful. Otherwise, it is
  462. // FALSE, and an error code is logged.
  463. //
  464. // Comments
  465. // This function can be provided to handle only certain forms of stretching,
  466. // such as by integer multiples. If the driver has hooked the call and is asked
  467. // to perform an operation it does not support, the driver should forward the
  468. // data to EngStretchBlt for GDI to handle.
  469. //
  470. // If the driver wants GDI to handle halftoning, and wants to ensure the proper
  471. // iMode value, the driver can hook DrvStretchBlt, set iMode to HALFTONE, and
  472. // call back to GDI with EngStretchBlt with the set iMode value.
  473. //
  474. // DrvStretchBlt is optional for display drivers.
  475. //
  476. //-----------------------------------------------------------------------------
  477. BOOL
  478. DrvStretchBlt(SURFOBJ* psoDst,
  479. SURFOBJ* psoSrc,
  480. SURFOBJ* psoMsk,
  481. CLIPOBJ* pco,
  482. XLATEOBJ* pxlo,
  483. COLORADJUSTMENT* pca,
  484. POINTL* pptlHTOrg,
  485. RECTL* prclDst,
  486. RECTL* prclSrc,
  487. POINTL* pptlMsk,
  488. ULONG iMode)
  489. {
  490. Surf* pSurfSrc = (Surf*)psoSrc->dhsurf;
  491. Surf* pSurfDst = (Surf*)psoDst->dhsurf;
  492. PDev* ppdev = (PDev*)psoDst->dhpdev;
  493. BYTE iDComplexity;
  494. RECTL* prclClip;
  495. ULONG cxDst;
  496. ULONG cyDst;
  497. ULONG cxSrc;
  498. ULONG cySrc;
  499. BOOL bMore;
  500. ClipEnum ceInfo;
  501. LONG lNumOfIntersections;
  502. LONG i;
  503. DBG_GDI((6, "DrvStretchBlt called with iMode = %d", iMode));
  504. if (iMode != COLORONCOLOR)
  505. {
  506. DBG_GDI((6, "Punt because iMode != COLORONCOLOR"));
  507. goto Punt_It;
  508. }
  509. vCheckGdiContext(ppdev);
  510. //
  511. // GDI guarantees us that for a StretchBlt the destination surface
  512. // will always be in video memory, not in system memory
  513. //
  514. ASSERTDD(pSurfDst->flags & SF_VM, "Dest surface is not in video memory");
  515. //
  516. // If the source is not a driver created surface or currently not sit
  517. // in the video memory, we just punt it back because GDI doing it will
  518. // be faster
  519. //
  520. if ( (!pSurfSrc) || (pSurfSrc->flags & SF_SM) )
  521. {
  522. DBG_GDI((6, "Punt because source = 0x%x or in sys memory", pSurfSrc));
  523. goto Punt_It;
  524. }
  525. //
  526. // We don't do the stretch blt if the mask is not NULL or the translate is
  527. // not trivial. We also don't do it if the source and current screen has
  528. // different color depth
  529. //
  530. if ( (psoMsk == NULL)
  531. &&((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))
  532. &&((psoSrc->iBitmapFormat == ppdev->iBitmapFormat)) )
  533. {
  534. cxDst = prclDst->right - prclDst->left;
  535. cyDst = prclDst->bottom - prclDst->top;
  536. cxSrc = prclSrc->right - prclSrc->left;
  537. cySrc = prclSrc->bottom - prclSrc->top;
  538. //
  539. // Our 'vStretchDIB' routine requires that the stretch be
  540. // non-inverting, within a certain size, to have no source
  541. // clipping, and to have no empty rectangles (the latter is the
  542. // reason for the '- 1' on the unsigned compare here):
  543. //
  544. if ( ((cxSrc - 1) < STRETCH_MAX_EXTENT)
  545. &&((cySrc - 1) < STRETCH_MAX_EXTENT)
  546. &&((cxDst - 1) < STRETCH_MAX_EXTENT)
  547. &&((cyDst - 1) < STRETCH_MAX_EXTENT)
  548. &&(prclSrc->left >= 0)
  549. &&(prclSrc->top >= 0)
  550. &&(prclSrc->right <= psoSrc->sizlBitmap.cx)
  551. &&(prclSrc->bottom <= psoSrc->sizlBitmap.cy))
  552. {
  553. if ( !bStretchInit(psoDst, psoSrc) )
  554. {
  555. goto Punt_It;
  556. }
  557. iDComplexity = (pco == NULL) ? DC_TRIVIAL : pco->iDComplexity;
  558. if ( (iDComplexity == DC_TRIVIAL) || (iDComplexity == DC_RECT) )
  559. {
  560. if (iDComplexity == DC_TRIVIAL) {
  561. DBG_GDI((7, "Trivial clipping"));
  562. // If there is no clipping, we just set the clipping area
  563. // as the maximum
  564. prclClip = &grclStretchClipMax;
  565. ASSERTDD(((prclClip->right >= prclDst->right) &&
  566. (prclClip->bottom >= prclDst->bottom)), "Dest surface is larger than P2 can handle");
  567. }
  568. else
  569. {
  570. DBG_GDI((7, "DC_RECT clipping"));
  571. prclClip = &pco->rclBounds;
  572. }
  573. vStretchBlt(psoDst,
  574. psoSrc,
  575. prclDst,
  576. prclSrc,
  577. prclClip);
  578. }
  579. else
  580. {
  581. DBG_GDI((7, "Complex clipping"));
  582. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  583. //
  584. // Enumerate all the clip rectangles
  585. //
  586. do
  587. {
  588. //
  589. // Get one clip rectangle
  590. //
  591. bMore = CLIPOBJ_bEnum(pco, sizeof(ceInfo),
  592. (ULONG*)&ceInfo);
  593. //
  594. // Get the intersect region with the dest rectangle
  595. //
  596. lNumOfIntersections = cIntersect(prclDst, ceInfo.arcl,
  597. ceInfo.c);
  598. //
  599. // If there is clipping, then we do stretch region
  600. // by region
  601. //
  602. if ( lNumOfIntersections != 0 )
  603. {
  604. for ( i = 0; i < lNumOfIntersections; ++i )
  605. {
  606. vStretchBlt(psoDst,
  607. psoSrc,
  608. prclDst,
  609. prclSrc,
  610. &ceInfo.arcl[i]);
  611. }
  612. }
  613. } while (bMore);
  614. }// Non-DC rect clipping
  615. DBG_GDI((6, "DrvStretchBlt return TRUE"));
  616. // Cleanup stretch settings
  617. vStretchReset(ppdev);
  618. InputBufferFlush(ppdev);
  619. return TRUE;
  620. }// source/dest withnin range
  621. }// No mask, trivial xlate, same BMP format
  622. Punt_It:
  623. DBG_GDI((6, "DrvStretchBlt punt"));
  624. return(EngStretchBlt(psoDst, psoSrc, psoMsk, pco, pxlo, pca,
  625. pptlHTOrg, prclDst, prclSrc, pptlMsk, iMode));
  626. }// DrvStretchBlt()