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.

2477 lines
79 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: drawstream.cxx
  3. *
  4. * All code related to handling draw streams except for multi-mon and
  5. * sprite layer hooking.
  6. *
  7. * Created: 3-21-2001
  8. * Author: Barton House [bhouse]
  9. *
  10. * Copyright (c) 1990-2001 Microsoft Corporation
  11. \**************************************************************************/
  12. #include "precomp.hxx"
  13. #if defined(USE_NINEGRID_STATIC)
  14. HSEMAPHORE gNineGridSem = 0;
  15. #endif
  16. /******************************Private*************************************\
  17. * Nine Grid Code Follows
  18. *
  19. * A bunch of nine grid structures and code follow below. This code
  20. * will be cleaned up and moved to its own file shortly.
  21. *
  22. * History:
  23. *
  24. * 3-18-2001 bhouse Created it
  25. *
  26. \**************************************************************************/
  27. typedef struct _DNGSTRETCH
  28. {
  29. ULONG xStart;
  30. ULONG xAccum;
  31. ULONG xFrac;
  32. ULONG xInt;
  33. ULONG ulDestWidth;
  34. ULONG ulSrcWidth;
  35. int left;
  36. int right;
  37. } DNGSTRETCH;
  38. typedef struct _DNGINTERNALDATA
  39. {
  40. int cxClipMin;
  41. int cxClipMax;
  42. ULONG* pvDestBits;
  43. LONG lDestDelta;
  44. int iDestWidth;
  45. int iClipWidth;
  46. ULONG* pvSrcBits;
  47. LONG lSrcDelta;
  48. int iSrcWidth;
  49. int iSrcBufWidth;
  50. int cxLeftWidth;
  51. int xMinLeft;
  52. int xMaxLeft;
  53. int cxRightWidth;
  54. int xMinRight;
  55. int xMaxRight;
  56. int cxMiddleWidth;
  57. int cxNewMiddleWidth;
  58. int xMinMiddle;
  59. int xMaxMiddle;
  60. // Variable for shrunken corners and sides
  61. BOOL fShowMiddle;
  62. DNGSTRETCH stretchLeft;
  63. DNGSTRETCH stretchRight;
  64. int cxNewLeftWidth;
  65. int cxNewRightWidth;
  66. BOOL fTileMode;
  67. // Specific to non-tile mode (i.e. stretch mode)
  68. DNGSTRETCH stretchMiddle;
  69. LONG lBufWidth;
  70. } DNGINTERNALDATA;
  71. static inline void DNG_StretchRow(ULONG* pvDestBits, ULONG* pvSrcBits, DNGSTRETCH * ps)
  72. {
  73. ULONG* pvTemp = pvDestBits + ps->left;
  74. ULONG* pvSentinel = pvDestBits + ps->right;
  75. ULONG xInt = ps->xInt;
  76. ULONG xFrac = ps->xFrac;
  77. ULONG xTmp;
  78. ULONG xAccum = ps->xAccum;
  79. ULONG * pulSrc = pvSrcBits + ps->xStart;
  80. ULONG ulSrc;
  81. while (pvTemp != pvSentinel)
  82. {
  83. ulSrc = *pulSrc;
  84. xTmp = xAccum + xFrac;
  85. pulSrc = pulSrc + xInt + (xTmp < xAccum);
  86. *pvTemp = ulSrc;
  87. pvTemp++;
  88. xAccum = xTmp;
  89. }
  90. }
  91. static inline void DNG_InitStretch(DNGSTRETCH* pStretch, ULONG ulDestWidth, ULONG ulSrcWidth, int left, int right)
  92. {
  93. pStretch->right = right;
  94. pStretch->left = left;
  95. ULONGLONG dx = ((((ULONGLONG) ulSrcWidth << 32) - 1) / (ULONGLONG) ulDestWidth) + 1;
  96. ULONGLONG x = (((ULONGLONG) ulSrcWidth << 32) / (ULONGLONG) ulDestWidth) >> 1;
  97. ULONG xInt = pStretch->xInt = (ULONG) (dx >> 32);
  98. ULONG xFrac = pStretch->xFrac = (ULONG) (dx & 0xFFFFFFFF);
  99. ULONG xAccum = (ULONG) (x & 0xFFFFFFFF);
  100. ULONG xStart = (ULONG) (x >> 32);
  101. if (left <= 5)
  102. {
  103. ULONG xTmp;
  104. for (int i = 0; i < left; i++)
  105. {
  106. xTmp = xAccum + xFrac;
  107. xStart = xStart + xInt + (xTmp < xAccum);
  108. xAccum = xTmp;
  109. }
  110. }
  111. else
  112. {
  113. ULONGLONG xTmp = ((ULONGLONG) xFrac * (ULONGLONG) left) + (ULONGLONG) xAccum;
  114. xStart = xStart + (xInt * left) + (ULONG) (xTmp >> 32);
  115. xAccum = (ULONG) xTmp;
  116. }
  117. pStretch->xStart = xStart;
  118. pStretch->xAccum = xAccum;
  119. }
  120. static inline void DNG_DrawRow(DNGINTERNALDATA* pdng)
  121. {
  122. ULONG* pvDestLoc = pdng->pvDestBits;
  123. ULONG* pvSrcLoc = pdng->pvSrcBits;
  124. // Left
  125. if (pdng->cxClipMin < pdng->cxNewLeftWidth)
  126. {
  127. if (pdng->cxLeftWidth == pdng->cxNewLeftWidth)
  128. {
  129. RtlCopyMemory(pvDestLoc + pdng->xMinLeft, pvSrcLoc + pdng->xMinLeft, (pdng->xMaxLeft - pdng->xMinLeft) * sizeof(ULONG));
  130. }
  131. else
  132. {
  133. DNG_StretchRow(pvDestLoc, pvSrcLoc, &pdng->stretchLeft);
  134. }
  135. }
  136. pvDestLoc += pdng->cxNewLeftWidth;
  137. pvSrcLoc += pdng->cxLeftWidth;
  138. // Middle
  139. if (pdng->fShowMiddle)
  140. {
  141. if (pdng->xMinMiddle < pdng->xMaxMiddle)
  142. {
  143. if (pdng->fTileMode)
  144. {
  145. ULONG* pvTempSrc = pvSrcLoc;
  146. ULONG* pvTempDest = pvDestLoc;
  147. // Fill in Top Tile
  148. int xMin = pdng->xMinMiddle;
  149. int xDiff = xMin - pdng->cxLeftWidth;
  150. pvDestLoc += xDiff;
  151. int iTileSize = pdng->cxMiddleWidth - (xDiff % pdng->cxMiddleWidth);
  152. pvSrcLoc += xDiff % pdng->cxMiddleWidth;
  153. int xMax = pdng->xMaxMiddle;
  154. for (int x = xMin; x < xMax; x++, pvDestLoc++ , pvSrcLoc++)
  155. {
  156. *pvDestLoc = *pvSrcLoc;
  157. iTileSize--;
  158. if (iTileSize == 0)
  159. {
  160. iTileSize = pdng->cxMiddleWidth;
  161. pvSrcLoc -= iTileSize;
  162. }
  163. }
  164. pvDestLoc = pvTempDest;
  165. pvSrcLoc = pvTempSrc;
  166. }
  167. else
  168. {
  169. DNG_StretchRow(pvDestLoc, pvSrcLoc, &pdng->stretchMiddle);
  170. }
  171. }
  172. pvDestLoc += pdng->cxNewMiddleWidth;
  173. }
  174. pvSrcLoc += pdng->cxMiddleWidth;
  175. // Right
  176. if (pdng->cxClipMax > (pdng->iDestWidth - pdng->cxNewRightWidth))
  177. {
  178. if (pdng->cxRightWidth == pdng->cxNewRightWidth)
  179. {
  180. RtlCopyMemory(pvDestLoc + pdng->xMinRight, pvSrcLoc + pdng->xMinRight, (pdng->xMaxRight - pdng->xMinRight) * sizeof(ULONG));
  181. }
  182. else
  183. {
  184. DNG_StretchRow(pvDestLoc, pvSrcLoc, &pdng->stretchRight);
  185. }
  186. }
  187. }
  188. static inline void DNG_StretchCol(DNGINTERNALDATA* pdng, DNGSTRETCH * ps)
  189. {
  190. ULONG* pvOldDestBits = pdng->pvDestBits;
  191. ULONG* pvOldSrcBits = pdng->pvSrcBits;
  192. ULONG* pvTemp = pdng->pvDestBits - (pdng->lDestDelta * ps->left);
  193. ULONG* pvSentinel = pdng->pvDestBits - (pdng->lDestDelta * ps->right);
  194. ULONG xInt = ps->xInt;
  195. ULONG xFrac = ps->xFrac;
  196. ULONG xTmp;
  197. ULONG xAccum = ps->xAccum;
  198. ULONG * pulSrc = pdng->pvSrcBits - (LONG)(pdng->lSrcDelta * ps->xStart); // Note the LONG cast so we get correct pointer arithmetic on WIN64.
  199. ULONG xDelta = 1; // force stretch on first scan
  200. while (pvTemp != pvSentinel)
  201. {
  202. if (xDelta != 0)
  203. {
  204. pdng->pvDestBits = pvTemp;
  205. pdng->pvSrcBits = pulSrc;
  206. DNG_DrawRow(pdng);
  207. }
  208. else
  209. {
  210. RtlCopyMemory(pvTemp + pdng->cxClipMin, pvTemp + pdng->cxClipMin + pdng->lDestDelta, pdng->iClipWidth * sizeof(ULONG));
  211. }
  212. xTmp = xAccum + xFrac;
  213. xDelta = (xInt + (xTmp < xAccum));
  214. pulSrc = pulSrc - (LONG)(pdng->lSrcDelta * xDelta); // Note LONG cast
  215. pvTemp -= pdng->lDestDelta;
  216. xAccum = xTmp;
  217. }
  218. pdng->pvDestBits = pvOldDestBits;
  219. pdng->pvSrcBits = pvOldSrcBits;
  220. }
  221. static void RenderNineGridInternal(
  222. SURFOBJ *psoScratch,
  223. SURFOBJ *psoSrc,
  224. RECTL *prclClip,
  225. RECTL *prclDst,
  226. RECTL *prclSrc,
  227. DS_NINEGRIDINFO *ngi,
  228. PDRAWSTREAMINFO pdsi,
  229. BOOL bMirror)
  230. {
  231. RECTL rcDest = *prclDst;
  232. RECTL rcClip = *prclClip;
  233. ULONG* pvDestBits = NULL;
  234. int iDestWidth = rcDest.right - rcDest.left;
  235. int iDestHeight = rcDest.bottom - rcDest.top;
  236. int iClipWidth = rcClip.right - rcClip.left;
  237. int iClipHeight = rcClip.bottom - rcClip.top;
  238. LONG lBufWidth = psoScratch->sizlBitmap.cx;
  239. LONG lBufHeight = psoScratch->sizlBitmap.cy;
  240. DNGINTERNALDATA dng;
  241. // The code below assumes that the source and scratch is 32bpp
  242. ASSERTGDI(psoSrc->iBitmapFormat == BMF_32BPP, "RenderNineGridInternal: source not 32bpp");
  243. ASSERTGDI(psoScratch->iBitmapFormat == BMF_32BPP, "RenderNineGridInternal: scratch not 32bpp");
  244. // The code below assumes that both source and scratch are bottom up
  245. // ASSERTGDI(psoSrc->lDelta < 0, "RenderNineGridInternal: source is not bottom up");
  246. // ASSERTGDI(psoScratch->lDelta < 0, "RenderNineGridInternal: scratch is not bottom up");
  247. dng.lBufWidth = lBufWidth;
  248. LONG lDestDelta = psoScratch->lDelta / (LONG)(sizeof(ULONG));
  249. dng.lDestDelta = lDestDelta;
  250. LONG lSrcDelta = psoSrc->lDelta / (LONG)(sizeof(ULONG));
  251. dng.lSrcDelta = lSrcDelta;
  252. dng.cxClipMin = rcClip.left - rcDest.left;
  253. dng.cxClipMax = rcClip.right - rcDest.left;
  254. int cyClipMin = rcClip.top - rcDest.top;
  255. int cyClipMax = rcClip.bottom - rcDest.top;
  256. // pvScan0 points to the pixel addressed at (cxClipMin, cyClipMin)
  257. // pvDestBits points to the pixel addressed at (0, iDestHeight - 1)
  258. pvDestBits = (ULONG *) psoScratch->pvScan0;
  259. pvDestBits += (iDestHeight - 1 - cyClipMin) * lDestDelta;
  260. pvDestBits -= dng.cxClipMin;
  261. int cxImage = rcClip.right - rcClip.left;
  262. int cyImage = rcClip.bottom - rcClip.top;
  263. LONG lSrcBufWidth = psoSrc->sizlBitmap.cx;
  264. LONG lSrcWidth = prclSrc->right - prclSrc->left;
  265. LONG lSrcHeight = prclSrc->bottom - prclSrc->top;
  266. ULONG * lSrcBits = (ULONG *) psoSrc->pvScan0 + (lSrcDelta * prclSrc->top) + prclSrc->left;
  267. lSrcBits += (lSrcDelta * (prclSrc->bottom - prclSrc->top - 1));
  268. // ULONG * lSrcBits = (ULONG *) psoSrc->pvScan0 + (lSrcDelta * (psoSrc->sizlBitmap.cy - 1));
  269. if (ngi->flFlags & DSDNG_TRUESIZE)
  270. {
  271. ULONG* pvDestLoc = pvDestBits - ((iDestHeight - 1) * lDestDelta);
  272. ULONG* pvSrcLoc = lSrcBits - ((lSrcHeight - 1) * lSrcDelta);
  273. int yMin = cyClipMin;
  274. pvDestLoc += yMin * lDestDelta;
  275. pvSrcLoc += yMin * lSrcDelta;
  276. int yMax = min(lSrcHeight, cyClipMax);
  277. int xMin = dng.cxClipMin;
  278. int xMax = min(lSrcWidth, dng.cxClipMax);
  279. if (xMax > xMin)
  280. {
  281. for (int y = yMin; y < yMax; y++, pvDestLoc += lDestDelta, pvSrcLoc += lSrcDelta)
  282. {
  283. RtlCopyMemory(pvDestLoc + xMin, pvSrcLoc + xMin, (xMax - xMin) * 4);
  284. }
  285. }
  286. cxImage = xMax - xMin;
  287. cyImage = yMax - yMin;
  288. }
  289. else
  290. {
  291. // Setup data
  292. dng.iDestWidth = iDestWidth;
  293. dng.iClipWidth = iClipWidth;
  294. dng.iSrcWidth = lSrcWidth;
  295. dng.iSrcBufWidth = lSrcBufWidth;
  296. dng.cxLeftWidth = ngi->ulLeftWidth;
  297. dng.cxRightWidth = ngi->ulRightWidth;
  298. dng.fTileMode = (ngi->flFlags & DSDNG_TILE);
  299. // Calculate clip stuff
  300. // Pre-calc corner stretching variables
  301. dng.fShowMiddle = ((iDestWidth - dng.cxLeftWidth - dng.cxRightWidth > 0) && (lSrcWidth - dng.cxLeftWidth - dng.cxRightWidth > 0));
  302. if (!dng.fShowMiddle)
  303. {
  304. dng.cxNewLeftWidth = (dng.cxLeftWidth + dng.cxRightWidth == 0) ? 0 : (dng.cxLeftWidth * dng.iDestWidth) / (dng.cxLeftWidth + dng.cxRightWidth);
  305. dng.cxNewRightWidth = dng.iDestWidth - dng.cxNewLeftWidth;
  306. }
  307. else
  308. {
  309. dng.cxNewLeftWidth = dng.cxLeftWidth;
  310. dng.cxNewRightWidth = dng.cxRightWidth;
  311. }
  312. // Pre-calc Left side variables
  313. dng.xMinLeft = dng.cxClipMin;
  314. dng.xMaxLeft = min(dng.cxNewLeftWidth, dng.cxClipMax);
  315. if (!dng.fShowMiddle && dng.cxNewLeftWidth)
  316. {
  317. DNG_InitStretch(&dng.stretchLeft, dng.cxNewLeftWidth, dng.cxLeftWidth, dng.xMinLeft, dng.xMaxLeft);
  318. }
  319. // Pre-calc Horizontal Middle Variables
  320. dng.cxMiddleWidth = dng.iSrcWidth - dng.cxLeftWidth - dng.cxRightWidth;
  321. dng.cxNewMiddleWidth = dng.iDestWidth - dng.cxNewLeftWidth - dng.cxNewRightWidth;
  322. dng.xMinMiddle = max(dng.cxNewLeftWidth, dng.cxClipMin);
  323. dng.xMaxMiddle = min(dng.cxNewLeftWidth + dng.cxNewMiddleWidth, dng.cxClipMax);
  324. if (dng.fShowMiddle)
  325. {
  326. DNG_InitStretch(&dng.stretchMiddle, dng.cxNewMiddleWidth, dng.cxMiddleWidth, dng.xMinMiddle - dng.cxNewLeftWidth, dng.xMaxMiddle - dng.cxNewLeftWidth);
  327. }
  328. // Pre-calc Right side variables
  329. dng.xMinRight = max(dng.iDestWidth - dng.cxNewRightWidth, dng.cxClipMin) - dng.cxNewLeftWidth - dng.cxNewMiddleWidth;
  330. dng.xMaxRight = min(dng.iDestWidth, dng.cxClipMax) - dng.cxNewLeftWidth - dng.cxNewMiddleWidth;
  331. if (!dng.fShowMiddle && dng.cxNewRightWidth)
  332. {
  333. DNG_InitStretch(&dng.stretchRight, dng.cxNewRightWidth, dng.cxRightWidth, dng.xMinRight, dng.xMaxRight);
  334. }
  335. BOOL fShowVertMiddle = ((iDestHeight - ngi->ulTopHeight - ngi->ulBottomHeight > 0) && (lSrcHeight - ngi->ulTopHeight - ngi->ulBottomHeight > 0));
  336. int cyTopHeight = ngi->ulTopHeight;
  337. int cyBottomHeight = ngi->ulBottomHeight;
  338. int cyNewTopHeight;
  339. int cyNewBottomHeight;
  340. if (!fShowVertMiddle)
  341. {
  342. cyNewTopHeight = (cyTopHeight + cyBottomHeight == 0) ? 0 : (cyTopHeight * iDestHeight) / (cyTopHeight + cyBottomHeight);
  343. cyNewBottomHeight = iDestHeight - cyNewTopHeight;
  344. }
  345. else
  346. {
  347. cyNewTopHeight = cyTopHeight;
  348. cyNewBottomHeight = cyBottomHeight;
  349. }
  350. // Draw Bottom
  351. // Draw the scan line from (iDestHeight - cyNewBottomHeight) to less than iDestHeight, in screen coordinates
  352. int yMin = max(iDestHeight - cyNewBottomHeight, cyClipMin);
  353. int yMax = min(iDestHeight, cyClipMax);
  354. if (cyClipMax > iDestHeight - cyNewBottomHeight)
  355. {
  356. dng.pvDestBits = pvDestBits;
  357. dng.pvSrcBits = lSrcBits;
  358. if (cyBottomHeight == cyNewBottomHeight)
  359. {
  360. int yDiff = yMin - (iDestHeight - cyNewBottomHeight);
  361. dng.pvDestBits -= (cyBottomHeight - 1 - yDiff) * lDestDelta;
  362. dng.pvSrcBits -= (cyBottomHeight - 1 - yDiff) * lSrcDelta;
  363. for (int y = yMin; y < yMax; y++, dng.pvDestBits += lDestDelta, dng.pvSrcBits += lSrcDelta)
  364. {
  365. DNG_DrawRow(&dng);
  366. }
  367. }
  368. else if (cyNewBottomHeight > 0)
  369. {
  370. DNGSTRETCH stretch;
  371. DNG_InitStretch(&stretch, cyNewBottomHeight, cyBottomHeight, cyNewBottomHeight - (yMax - iDestHeight + cyNewBottomHeight), cyNewBottomHeight - (yMin - iDestHeight + cyNewBottomHeight));
  372. DNG_StretchCol(&dng, &stretch);
  373. }
  374. }
  375. // Draw Middle
  376. // Draw the scan line from cyNewTopHeight to less than (iDestHeight - cyNewBottomHeight), in screen coordinates
  377. int cySrcTileSize = lSrcHeight - ngi->ulTopHeight - ngi->ulBottomHeight;
  378. int cyDestTileSize = iDestHeight - ngi->ulTopHeight - ngi->ulBottomHeight;
  379. if (fShowVertMiddle && (cySrcTileSize>0) && (cyDestTileSize>0) && (cyClipMin < iDestHeight - cyNewBottomHeight) && (cyClipMax > cyNewTopHeight))
  380. {
  381. dng.pvDestBits = pvDestBits - ngi->ulBottomHeight * lDestDelta;
  382. dng.pvSrcBits = lSrcBits - ngi->ulBottomHeight * lSrcDelta;
  383. int yMin = max(cyTopHeight, cyClipMin);
  384. if (dng.fTileMode)
  385. {
  386. // Start off tile
  387. dng.pvDestBits -= (cyDestTileSize - 1) * lDestDelta;
  388. dng.pvSrcBits -= (cySrcTileSize - 1) * lSrcDelta;
  389. int yDiff = yMin - cyTopHeight;
  390. dng.pvDestBits += yDiff * lDestDelta;
  391. int yOffset = (yDiff % cySrcTileSize);
  392. dng.pvSrcBits += yOffset * dng.lSrcDelta;
  393. int iTileOffset = cySrcTileSize - yOffset;
  394. int yMax = min(yMin + min(cySrcTileSize, cyDestTileSize), min(iDestHeight - cyBottomHeight, cyClipMax));
  395. for (int y = yMin; y < yMax; y++, dng.pvDestBits += lDestDelta, dng.pvSrcBits += lSrcDelta)
  396. {
  397. DNG_DrawRow(&dng);
  398. iTileOffset--;
  399. if (iTileOffset == 0)
  400. {
  401. iTileOffset = cySrcTileSize;
  402. dng.pvSrcBits -= lSrcDelta * cySrcTileSize;
  403. }
  404. }
  405. // Repeat tile pattern
  406. dng.pvSrcBits = dng.pvDestBits - (lDestDelta * cySrcTileSize);
  407. yMin = yMax;
  408. yMax = min(iDestHeight - cyBottomHeight, cyClipMax);
  409. for (int y = yMin; y < yMax; y++, dng.pvDestBits += lDestDelta, dng.pvSrcBits += lDestDelta)
  410. {
  411. RtlCopyMemory(dng.pvDestBits + dng.cxClipMin, dng.pvSrcBits + dng.cxClipMin, dng.iClipWidth * sizeof(ULONG));
  412. }
  413. }
  414. else
  415. {
  416. int yMax = min(iDestHeight - cyBottomHeight, cyClipMax);
  417. DNGSTRETCH stretch;
  418. DNG_InitStretch(&stretch, cyDestTileSize, cySrcTileSize, cyDestTileSize - (yMax - cyTopHeight), cyDestTileSize - (yMin - cyTopHeight));
  419. // Convert from screen coords to DIB coords
  420. DNG_StretchCol(&dng, &stretch);
  421. }
  422. }
  423. // Draw Top
  424. // Draw the scan line from 0 to less than cyNewTopHeight, in screen coordinates
  425. yMin = cyClipMin;
  426. yMax = min(cyNewTopHeight, cyClipMax);
  427. if (cyClipMin < cyNewTopHeight)
  428. {
  429. dng.pvDestBits = pvDestBits - (iDestHeight - cyNewTopHeight) * lDestDelta;
  430. dng.pvSrcBits = lSrcBits - (lSrcHeight - ngi->ulTopHeight) * lSrcDelta;
  431. if (cyTopHeight == cyNewTopHeight)
  432. {
  433. dng.pvDestBits -= (cyTopHeight - 1 - yMin) * lDestDelta;
  434. dng.pvSrcBits -= (cyTopHeight - 1 - yMin) * lSrcDelta;
  435. for (int y = yMin; y < yMax; y++, dng.pvDestBits += lDestDelta, dng.pvSrcBits += lSrcDelta)
  436. {
  437. DNG_DrawRow(&dng);
  438. }
  439. }
  440. else if (cyNewTopHeight > 0)
  441. {
  442. DNGSTRETCH stretch;
  443. DNG_InitStretch(&stretch, cyNewTopHeight, cyTopHeight, cyNewTopHeight - yMax, cyNewTopHeight - yMin);
  444. DNG_StretchCol(&dng, &stretch);
  445. }
  446. }
  447. }
  448. if (bMirror)
  449. {
  450. // Flip the buffer
  451. for (int y = 0; y < iClipHeight; y++)
  452. {
  453. ULONG* pvLeftBits = (ULONG *) psoScratch->pvScan0 + (y * lDestDelta);
  454. ULONG* pvRightBits = pvLeftBits + iClipWidth - 1;
  455. for (int x = 0; x < (iClipWidth / 2); x++)
  456. {
  457. ULONG ulTemp = *pvLeftBits;
  458. *pvLeftBits = *pvRightBits;
  459. *pvRightBits = ulTemp;
  460. pvLeftBits++;
  461. pvRightBits--;
  462. }
  463. }
  464. }
  465. }
  466. static void RenderNineGrid(
  467. SURFOBJ *psoDst,
  468. SURFOBJ *psoSrc,
  469. SURFOBJ *psoScratch,
  470. CLIPOBJ *pco,
  471. RECTL *prclClip,
  472. XLATEOBJ *pxlo,
  473. RECTL *prclDst,
  474. RECTL *prclSrc,
  475. DS_NINEGRIDINFO *ngi,
  476. PDRAWSTREAMINFO pdsi,
  477. BOOL bMirror)
  478. {
  479. PSURFACE pSurfSrc = SURFOBJ_TO_SURFACE(psoSrc);
  480. PSURFACE pSurfDst = SURFOBJ_TO_SURFACE(psoDst);
  481. PDEVOBJ pdoSrc(pSurfSrc->hdev());
  482. PDEVOBJ pdoDst(pSurfDst->hdev());
  483. XLATE * pxl = (XLATE *) pxlo;
  484. SIZEL sizlScratch;
  485. // only mirror the contents if we need to
  486. bMirror = bMirror && (ngi->flFlags & DSDNG_MUSTFLIP);
  487. // render nine grid into scratch
  488. ERECTL erclClip = *prclClip;
  489. if(bMirror)
  490. {
  491. // We need to remap the clip to ensure we generate the right flipped bits
  492. erclClip.right = prclDst->right - (prclClip->left - prclDst->left);
  493. erclClip.left = prclDst->right - (prclClip->right - prclDst->left);
  494. }
  495. RenderNineGridInternal(psoScratch, psoSrc, &erclClip, prclDst, prclSrc, ngi, pdsi, bMirror);
  496. // copy scratch to destination
  497. LONG lClipWidth = prclClip->right - prclClip->left;
  498. LONG lClipHeight = prclClip->bottom - prclClip->top;
  499. ERECTL erclScratch(0, 0, lClipWidth, lClipHeight);
  500. if(ngi->flFlags & DSDNG_PERPIXELALPHA)
  501. {
  502. EBLENDOBJ eBlendObj;
  503. eBlendObj.BlendFunction.AlphaFormat = AC_SRC_ALPHA;
  504. eBlendObj.BlendFunction.BlendFlags = 0;
  505. eBlendObj.BlendFunction.SourceConstantAlpha = 255;
  506. eBlendObj.BlendFunction.BlendOp = AC_SRC_OVER;
  507. eBlendObj.pxlo32ToDst = pdsi->pxloBGRAToDst;
  508. eBlendObj.pxloDstTo32 = pdsi->pxloDstToBGRA;
  509. eBlendObj.pxloSrcTo32 = pdsi->pxloSrcToBGRA;
  510. PPFNDIRECT(psoDst, AlphaBlend)(psoDst, psoScratch, pco, pxlo, prclClip, &erclScratch, &eBlendObj);
  511. }
  512. else if(ngi->flFlags & DSDNG_TRANSPARENT)
  513. {
  514. PPFNDIRECT(psoDst, TransparentBlt)(psoDst, psoScratch, pco, pxlo, prclClip, &erclScratch, ngi->crTransparent, 0);
  515. }
  516. else
  517. {
  518. PPFNDIRECT(psoDst, CopyBits)(psoDst, psoScratch, pco, pxlo, prclClip, &gptlZero);
  519. }
  520. }
  521. /******************************Private*Routine******************************\
  522. * xxEngNineGrid
  523. *
  524. * This stuff will be moved to EngNineGrid
  525. *
  526. *
  527. * History:
  528. *
  529. * 3-18-2001 bhouse Created it
  530. *
  531. \**************************************************************************/
  532. static int xxEngNineGrid(
  533. SURFOBJ *psoDst,
  534. SURFOBJ *psoSrc,
  535. CLIPOBJ *pco,
  536. XLATEOBJ *pxlo,
  537. RECTL * prclDst,
  538. RECTL * prclSrc,
  539. DS_NINEGRIDINFO *ngi,
  540. PDRAWSTREAMINFO pdsi)
  541. {
  542. BOOL bRet = FALSE;
  543. PSURFACE pSurfSrc = SURFOBJ_TO_SURFACE(psoSrc);
  544. PSURFACE pSurfDst = SURFOBJ_TO_SURFACE(psoDst);
  545. PDEVOBJ pdoSrc(pSurfSrc->hdev());
  546. PDEVOBJ pdoDst(pSurfDst->hdev());
  547. XLATE * pxl = (XLATE *) pxlo;
  548. ERECTL erclDst = *prclDst;
  549. BOOL bMirror = (erclDst.left > erclDst.right);
  550. if(bMirror)
  551. {
  552. LONG lRight = erclDst.left;
  553. erclDst.left = erclDst.right;
  554. erclDst.right = lRight;
  555. }
  556. // NOTE: TRUESIZE is a hack. The caller should do this reduction
  557. // and pass us an appropriate destination.
  558. // TODO: Talk with Justin Mann about changing his behavior in how
  559. // he calls us here. We should add assertions that the
  560. // destination dimensions never exceeds the source dimensions and
  561. // modify GdiDrawStream callers to pass appropriate data.
  562. if(ngi->flFlags & DSDNG_TRUESIZE)
  563. {
  564. LONG lSrcWidth = prclSrc->right - prclSrc->left;
  565. LONG lSrcHeight = prclSrc->bottom - prclSrc->top;
  566. // reduce destination to source size
  567. if((erclDst.right - erclDst.left) > lSrcWidth)
  568. {
  569. if(bMirror)
  570. erclDst.left = erclDst.right - lSrcWidth;
  571. else
  572. erclDst.right = erclDst.left + lSrcWidth;
  573. }
  574. if((erclDst.bottom - erclDst.top) > lSrcHeight)
  575. {
  576. if(bMirror)
  577. erclDst.top = erclDst.bottom - lSrcHeight;
  578. else
  579. erclDst.bottom = erclDst.top + lSrcHeight;
  580. }
  581. }
  582. SIZEL sizlScratch;
  583. ERECTL erclClip = erclDst;
  584. // For now, we only support 32bpp sources
  585. ASSERTGDI(psoSrc->iBitmapFormat == BMF_32BPP, "EngNineGrid: source not 32bpp");
  586. if(pco != (CLIPOBJ *) NULL && pco->iDComplexity != DC_TRIVIAL)
  587. {
  588. erclClip *= pco->rclBounds;
  589. }
  590. BOOL bClipOk = erclClip.left >= 0 &&
  591. erclClip.top >= 0 &&
  592. erclClip.right <= psoDst->sizlBitmap.cx &&
  593. erclClip.bottom <= psoDst->sizlBitmap.cy;
  594. ASSERTGDI(bClipOk, "EngNineGrid: bad clip");
  595. if(!erclClip.bEmpty() && bClipOk)
  596. {
  597. LONG lClipWidth = erclClip.right - erclClip.left;
  598. LONG lClipHeight = erclClip.bottom - erclClip.top;
  599. ASSERTGDI(lClipWidth > 0, "RenderNineGrid: clip width <= 0");
  600. ASSERTGDI(lClipHeight > 0, "RenderNineGrid: clip height <= 0");
  601. #define SCRATCH_WIDTH (256)
  602. #define SCRATCH_HEIGHT (64)
  603. #if defined(USE_NINEGRID_STATIC)
  604. SEMOBJ hsem(gNineGridSem);
  605. static HSURF hsurfScratch = NULL;
  606. if(hsurfScratch == NULL)
  607. {
  608. DEVBITMAPINFO dbmi;
  609. SURFMEM surfScratch;
  610. XEPALOBJ palScratch(pSurfSrc->ppal());
  611. if(!palScratch.bValid())
  612. {
  613. WARNING("xxEngNineGrid: palScratch is not valid");
  614. goto exit;
  615. }
  616. dbmi.cxBitmap = SCRATCH_WIDTH;
  617. dbmi.cyBitmap = SCRATCH_HEIGHT;
  618. dbmi.iFormat = pSurfSrc->iFormat();
  619. dbmi.fl = 0;
  620. dbmi.hpal = palScratch.hpal();
  621. if(!surfScratch.bCreateDIB(&dbmi, (VOID*) NULL))
  622. {
  623. WARNING("xxEngNineGrid: could not create surfScratch");
  624. goto exit;
  625. }
  626. surfScratch.vKeepIt();
  627. surfScratch.vSetPID(OBJECT_OWNER_PUBLIC);
  628. // Ensure that the scratch surface is not cached by driver
  629. surfScratch.ps->iUniq(0);
  630. hsurfScratch = surfScratch.ps->hsurf();
  631. }
  632. SURFREFAPI surfScratch(hsurfScratch);
  633. if(!surfScratch.bValid())
  634. {
  635. WARNING("xxEngNineGrid: SURFREFAPI(surfScratch) failed");
  636. goto exit;
  637. }
  638. SURFOBJ * psoScratch = surfScratch.pSurfobj();
  639. #else
  640. SURFACE *pSurfScratch;
  641. SURFMEM dimoScratch;
  642. {
  643. DEVBITMAPINFO dbmi;
  644. XEPALOBJ palScratch(pSurfSrc->ppal());
  645. if(!palScratch.bValid())
  646. {
  647. WARINING("xxEngNineGrid: palScratch is not valid\n");
  648. goto exit;
  649. }
  650. dbmi.cxBitmap = SCRATCH_WIDTH;
  651. dbmi.cyBitmap = SCRATCH_HEIGHT;
  652. dbmi.iFormat = pSurfSrc->iFormat();
  653. dbmi.fl = 0;
  654. dbmi.hpal = palScratch.hpal();
  655. if(!dimoScratch.bCreateDIB(&dbmi, (VOID*) NULL))
  656. {
  657. WARINING("xxEngNineGrid: could not create surfScratch\n");
  658. goto exit;
  659. }
  660. pSurfScratch = dimoScratch.ps;
  661. }
  662. SURFOBJ *psoScratch = pSurfScratch->pSurfobj();
  663. #endif
  664. if(lClipWidth > SCRATCH_WIDTH || lClipHeight > SCRATCH_HEIGHT)
  665. {
  666. LONG lBufWidth = SCRATCH_WIDTH;
  667. LONG lBufHeight = SCRATCH_HEIGHT;
  668. LONG lReducedClipTop = erclClip.top;
  669. while(lReducedClipTop < erclClip.bottom)
  670. {
  671. LONG lReducedClipBottom = lReducedClipTop + lBufHeight;
  672. if(lReducedClipBottom > erclClip.bottom)
  673. lReducedClipBottom = erclClip.bottom;
  674. LONG lReducedClipLeft = erclClip.left;
  675. while(lReducedClipLeft < erclClip.right)
  676. {
  677. LONG lReducedClipRight = lReducedClipLeft + lBufWidth;
  678. if(lReducedClipRight > erclClip.right)
  679. lReducedClipRight = erclClip.right;
  680. ERECTL erclReducedClip(lReducedClipLeft, lReducedClipTop,
  681. lReducedClipRight, lReducedClipBottom);
  682. RenderNineGrid(psoDst,
  683. psoSrc,
  684. psoScratch,
  685. pco,
  686. &erclReducedClip,
  687. pxlo,
  688. &erclDst,
  689. prclSrc,
  690. ngi,
  691. pdsi,
  692. bMirror);
  693. lReducedClipLeft += lBufWidth;
  694. }
  695. lReducedClipTop += lBufHeight;
  696. }
  697. }
  698. else
  699. {
  700. RenderNineGrid(psoDst, psoSrc, psoScratch, pco, &erclClip, pxlo, &erclDst, prclSrc, ngi, pdsi, bMirror);
  701. }
  702. }
  703. bRet = TRUE;
  704. exit:
  705. return bRet;
  706. }
  707. /******************************Private*Routine******************************\
  708. * EngNineGrid
  709. *
  710. * Purpose: Draws a nine grid.
  711. *
  712. * Description:
  713. *
  714. * <fill in details>
  715. *
  716. * History:
  717. *
  718. * 3-18-2001 bhouse Created it
  719. *
  720. \**************************************************************************/
  721. BOOL EngNineGrid(
  722. SURFOBJ *psoDst,
  723. SURFOBJ *psoSrc,
  724. CLIPOBJ *pco,
  725. XLATEOBJ *pxlo,
  726. PRECTL prclDst,
  727. PRECTL prclSrc,
  728. PNINEGRID png,
  729. BLENDOBJ* pBlendObj,
  730. PVOID pvReserved)
  731. {
  732. DRAWSTREAMINFO dsi;
  733. EBLENDOBJ *peBlendObj = (EBLENDOBJ*)pBlendObj;
  734. //
  735. // The source surface of EngNineGrid should always be a
  736. // GDI managed (memory) one.
  737. //
  738. if (psoSrc->iType != STYPE_BITMAP || psoSrc->iBitmapFormat != BMF_32BPP)
  739. {
  740. WARNING("EngNineGrid: psoSrc is not STYPE_BITMAP or not 32 Bpp");
  741. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  742. return FALSE;
  743. }
  744. dsi.bCalledFromBitBlt = FALSE;
  745. dsi.dss.blendFunction = pBlendObj->BlendFunction;
  746. dsi.dss.crColorKey = png->crTransparent;
  747. dsi.dss.ptlSrcOrigin.x = 0;
  748. dsi.dss.ptlSrcOrigin.y = 0;
  749. dsi.pptlDstOffset = &gptlZero;
  750. dsi.pvStream = NULL;
  751. dsi.ulStreamLength = 0;
  752. dsi.pxloBGRAToDst = peBlendObj->pxlo32ToDst;
  753. dsi.pxloDstToBGRA = peBlendObj->pxloDstTo32;
  754. dsi.pxloSrcToBGRA = peBlendObj->pxloSrcTo32;
  755. return xxEngNineGrid(psoDst, psoSrc, pco, pxlo, prclDst, prclSrc, (DS_NINEGRIDINFO *) png, &dsi);
  756. }
  757. #if 0
  758. // code to convert nine grid to blt commands
  759. LONG lSrcLeftWidth = cmd->ngi.ulLeftWidth;
  760. LONG lSrcRightWidth = cmd->ngi.ulRightWidth;
  761. LONG lSrcTopHeight = cmd->ngi.ulLeftWidth;
  762. LONG lSrcBottomHeight = cmd->ngi.ulRightWidth;
  763. LONG lDstLeftWidth = lSrcLeftWidth;
  764. LONG lDstRightWidth = lSrcRightWidth;
  765. LONG lDstTopHeight = lSrcTopHeight;
  766. LONG lDstBottomHeight = lSrcBottomHeight;
  767. LONG lDstWidth = erclDst.right - erclDst.left;
  768. BOOL bDrawMiddle;
  769. BOOL bMirror = (lDstWidth < 0);
  770. if(bMirror)
  771. {
  772. // horizontal mirror
  773. lDstLeftWidth = -lDstLeftWidth;
  774. lDstRightWidth = -lDstRightWidth;
  775. bDrawMiddle = (lDstWidth < lDstLeftWidth + lDstRightWidth);
  776. }
  777. else
  778. {
  779. bDrawMiddle = (lDstWidth > lDstLeftWidth + lDstRightWidth);
  780. }
  781. if(!bDrawMiddle && (lDstWidth != (lDstLeftWidth + lDstRightWidth)))
  782. {
  783. if((lDstLeftWidth + lDstRightWidth) == 0)
  784. continue; // this should never happen, we can probably remove
  785. lDstLeftWidth = lDstLeftWidth * lDstWidth / (lDstLeftWidth + lDstRightWidth);
  786. lDstRightWidth = lDstWidth - lDstLeftWidth;
  787. }
  788. DS_BLT cmdBlts[9];
  789. DS_BLT *cmdBlt = cmdBlts;
  790. if(cmd->ngi.flFlags & DSDNG_TRUESIZE)
  791. {
  792. // left top
  793. cmdBlt->ulCmdID = DS_BLTID;
  794. cmdBlt->flFlags = 0;
  795. if(cmd->ngi.flFlags & DSDNG_PERPIXELALPHA) cmdBlt->flFlags |= DSBLT_ALPHABLEND;
  796. else if(cmd->ngi.flFlags & DSDNG_TRANSPARENT) cmdBlt->flFlags |= DSBLT_TRANSPARENT;
  797. LONG lDstHeight = erclDst.bottom - erclDst.top;
  798. LONG lSrcWidth = cmd->rclSrc.right - cmd->rclSrc.left;
  799. LONG lSrcHeight = cmd->rclSrc.bottom - cmd->rclSrc.top;
  800. LONG lWidth;
  801. if(bMirror)
  802. {
  803. lWidth = (-lSrcWidth > lDstWidth ? -lSrcWidth : lDstWidth);
  804. }
  805. else
  806. {
  807. lWidth = (lSrcWidth < lDstWidth ? lSrcWidth : lDstWidth);
  808. }
  809. LONG lHeight = (lSrcHeight < lDstHeight ? lSrcHeight : lDstHeight);
  810. cmdBlt->rclDst.left = erclDst.left;
  811. cmdBlt->rclDst.top = erclDst.top;
  812. cmdBlt->rclDst.right = erclDst.left + lWidth;
  813. cmdBlt->rclDst.bottom = erclDst.top + lHeight;
  814. cmdBlt->rclSrc.left = cmd->rclSrc.left;
  815. cmdBlt->rclSrc.top = cmd->rclSrc.top;
  816. cmdBlt->rclSrc.right = cmd->rclSrc.left + lWidth;
  817. cmdBlt->rclSrc.bottom = cmd->rclSrc.top + lHeight;
  818. cmd++;
  819. }
  820. else
  821. {
  822. // left top
  823. cmdBlt->ulCmdID = DS_BLTID;
  824. cmdBlt->flFlags = 0;
  825. if(cmd->ngi.flFlags & DSDNG_TILE) cmdBlt->flFlags |= DSBLT_HTILE | DSBLT_VTILE;
  826. if(cmd->ngi.flFlags & DSDNG_PERPIXELALPHA) cmdBlt->flFlags |= DSBLT_ALPHABLEND;
  827. else if(cmd->ngi.flFlags & DSDNG_TRANSPARENT) cmdBlt->flFlags |= DSBLT_TRANSPARENT;
  828. cmdBlt->rclDst.left = erclDst.left;
  829. cmdBlt->rclDst.top = erclDst.top;
  830. cmdBlt->rclDst.right = erclDst.left + lDstLeftWidth;
  831. cmdBlt->rclDst.bottom = erclDst.top + lDstTopHeight;
  832. cmdBlt->rclSrc.left = cmd->rclSrc.left;
  833. cmdBlt->rclSrc.top = cmd->rclSrc.top;
  834. cmdBlt->rclSrc.right = cmd->rclSrc.left + lSrcLeftWidth;
  835. cmdBlt->rclSrc.bottom = cmd->rclSrc.top + lSrcTopHeight;
  836. // middle top
  837. cmdBlt++;
  838. *cmdBlt = cmdBlt[-1];
  839. cmdBlt->rclDst.left = cmdBlt->rclDst.right;
  840. cmdBlt->rclDst.right = erclDst.right - lDstRightWidth;
  841. cmdBlt->rclSrc.left = cmdBlt->rclSrc.right;
  842. cmdBlt->rclSrc.right = cmd->rclSrc.right - lSrcRightWidth;
  843. // right top
  844. cmdBlt++;
  845. *cmdBlt = cmdBlt[-1];
  846. cmdBlt->rclDst.left = cmdBlt->rclDst.right;
  847. cmdBlt->rclDst.right = erclDst.right;
  848. cmdBlt->rclSrc.left = cmdBlt->rclSrc.right;
  849. cmdBlt->rclSrc.right = cmd->rclSrc.right;
  850. // left middle
  851. cmdBlt++;
  852. *cmdBlt = cmdBlt[-1];
  853. cmdBlt->rclDst.left = erclDst.left;
  854. cmdBlt->rclDst.top = erclDst.top + lDstTopHeight;
  855. cmdBlt->rclDst.right = erclDst.left + lDstLeftWidth;
  856. cmdBlt->rclDst.bottom = erclDst.bottom - lDstBottomHeight;
  857. cmdBlt->rclSrc.left = cmd->rclSrc.left;
  858. cmdBlt->rclSrc.top = cmd->rclSrc.top + lSrcTopHeight;
  859. cmdBlt->rclSrc.right = cmd->rclSrc.left + lSrcLeftWidth;
  860. cmdBlt->rclSrc.bottom = cmd->rclSrc.bottom - lSrcBottomHeight;
  861. // middle middle
  862. if(bDrawMiddle)
  863. {
  864. cmdBlt++;
  865. *cmdBlt = cmdBlt[-1];
  866. cmdBlt->rclDst.left = cmdBlt->rclDst.right;
  867. cmdBlt->rclDst.right = erclDst.right - lDstRightWidth;
  868. cmdBlt->rclSrc.left = cmdBlt->rclSrc.right;
  869. cmdBlt->rclSrc.right = cmd->rclSrc.right - lSrcRightWidth;
  870. }
  871. // right middle
  872. cmdBlt++;
  873. *cmdBlt = cmdBlt[-1];
  874. cmdBlt->rclDst.left = erclDst.right - lDstRightWidth;
  875. cmdBlt->rclDst.right = erclDst.right;
  876. cmdBlt->rclSrc.left = cmd->rclSrc.right - lSrcRightWidth;
  877. cmdBlt->rclSrc.right = cmd->rclSrc.right;
  878. // left bottom
  879. cmdBlt++;
  880. *cmdBlt = cmdBlt[-1];
  881. cmdBlt->rclDst.left = erclDst.left;
  882. cmdBlt->rclDst.top = erclDst.bottom - lDstBottomHeight;
  883. cmdBlt->rclDst.right = erclDst.left + lDstLeftWidth;
  884. cmdBlt->rclDst.bottom = erclDst.bottom;
  885. cmdBlt->rclSrc.left = cmd->rclSrc.left;
  886. cmdBlt->rclSrc.top = cmd->rclSrc.bottom - lSrcBottomHeight;
  887. cmdBlt->rclSrc.right = cmd->rclSrc.left + lSrcLeftWidth;
  888. cmdBlt->rclSrc.bottom = cmd->rclSrc.bottom;
  889. // middle bottom
  890. cmdBlt++;
  891. *cmdBlt = cmdBlt[-1];
  892. cmdBlt->rclDst.left = cmdBlt->rclDst.right;
  893. cmdBlt->rclDst.right = erclDst.right - lDstRightWidth;
  894. cmdBlt->rclSrc.left = cmdBlt->rclSrc.right;
  895. cmdBlt->rclSrc.right = cmd->rclSrc.right - lSrcRightWidth;
  896. // right bottom
  897. cmdBlt++;
  898. *cmdBlt = cmdBlt[-1];
  899. cmdBlt->rclDst.left = cmdBlt->rclDst.right;
  900. cmdBlt->rclDst.right = erclDst.right;
  901. cmdBlt->rclSrc.left = cmdBlt->rclSrc.right;
  902. cmdBlt->rclSrc.right = cmd->rclSrc.right;
  903. cmdBlt++;
  904. }
  905. COLORREF crSave = pdss->crColorKey;
  906. BLENDFUNCTION bfxSave = pdss->blendFunction;
  907. pdss->blendFunction.AlphaFormat = AC_SRC_ALPHA;
  908. pdss->blendFunction.BlendFlags = 0;
  909. pdss->blendFunction.SourceConstantAlpha = 255;
  910. pdss->blendFunction.BlendOp = AC_SRC_OVER;
  911. // It is safe to go direct from here ... the source can't be a sprite
  912. // and the destination has already been taken care of (we have to
  913. // go through the sprite layer for the dest to get this far).
  914. bRet = (*PPFNDRVENG(psoDst, DrawStream))(psoDst, psoSrc, pco, pxlo, prclDstClip, &gptlZero,
  915. (ULONG) ((BYTE*) cmdBlt - (BYTE*) cmdBlts), cmdBlts, pdss);
  916. pdss->crColorKey = crSave;
  917. pdss->blendFunction = bfxSave;
  918. #endif
  919. #if DS_ENABLE_BLT
  920. int EngTileBits(
  921. SURFOBJ *psoDst,
  922. SURFOBJ *psoSrc,
  923. CLIPOBJ *pco,
  924. XLATEOBJ *pxlo,
  925. RECTL * prclDst,
  926. RECTL * prclSrc,
  927. POINTL * tileOrigin)
  928. {
  929. int iRet = TRUE;
  930. if(tileOrigin->x != 0 || tileOrigin->y != 0)
  931. return FALSE;
  932. PSURFACE pSurfSrc = SURFOBJ_TO_SURFACE(psoSrc);
  933. PSURFACE pSurfDst = SURFOBJ_TO_SURFACE(psoDst);
  934. PDEVOBJ pdoSrc(pSurfSrc->hdev());
  935. PDEVOBJ pdoDst(pSurfDst->hdev());
  936. XLATE * pxl = (XLATE *) pxlo;
  937. // TODO bhouse
  938. // we should handle all of the clipping cases
  939. // in the fast copy.
  940. LONG tileWidth = prclSrc->right - prclSrc->left;
  941. LONG tileHeight = prclSrc->bottom - prclSrc->top;
  942. if(tileWidth <= 0 || tileHeight <= 0)
  943. return FALSE;
  944. PFN_DrvCopyBits pfnCopyBits;
  945. // TODO: create a new dest if DC_RECT and adjust tileOrigin
  946. if((pSurfSrc->iType() == STYPE_BITMAP && !(pSurfSrc->fjBitmap() & BMF_NOTSYSMEM)) &&
  947. (pSurfDst->iType() == STYPE_BITMAP && !(pSurfDst->fjBitmap() & BMF_NOTSYSMEM)) &&
  948. pxl->bIsIdentity() &&
  949. (pco == NULL || pco->iDComplexity == DC_TRIVIAL) &&
  950. pSurfSrc->iFormat() >= BMF_8BPP &&
  951. pSurfSrc->iFormat() <= BMF_32BPP)
  952. {
  953. // tile it by hand nice and fast
  954. // TODO bhouse
  955. // Easy optimization here, we don't need to sync
  956. // every time ... seems wastefull as heck
  957. pdoSrc.vSync(psoDst,NULL,0);
  958. pdoDst.vSync(psoSrc,NULL,0);
  959. ULONG ulBytesPerPixel = (pSurfSrc->iFormat() - BMF_8BPP) + 1;
  960. ULONG ulTileWidthBytes = tileWidth * ulBytesPerPixel;
  961. ULONG ulDstWidthBytes = (prclDst->right - prclDst->left) * ulBytesPerPixel;
  962. PBYTE pbSrcStart = (PBYTE) pSurfSrc->pvScan0() +
  963. (prclSrc->top * pSurfSrc->lDelta()) +
  964. (prclSrc->left * ulBytesPerPixel);
  965. PBYTE pbSrcEnd = (PBYTE) pSurfSrc->pvScan0() +
  966. (prclSrc->bottom * pSurfSrc->lDelta()) +
  967. (prclSrc->left * ulBytesPerPixel);
  968. PBYTE pbDst = (PBYTE) pSurfDst->pvScan0() +
  969. (prclDst->top * pSurfDst->lDelta()) +
  970. (prclDst->left * ulBytesPerPixel);
  971. PBYTE pbDstEnd = (PBYTE) pSurfDst->pvScan0() +
  972. (prclDst->bottom * pSurfDst->lDelta()) +
  973. (prclDst->left * ulBytesPerPixel);
  974. PBYTE pbSrc = pbSrcStart;
  975. while(pbDst != pbDstEnd)
  976. {
  977. PBYTE pbDstLineEnd = pbDst + ulDstWidthBytes;
  978. PBYTE pbDstLine = pbDst;
  979. while(pbDstLine < pbDstLineEnd)
  980. {
  981. ULONG ulCopyBytes = (ULONG)(pbDstLineEnd - pbDstLine);
  982. if(ulCopyBytes > ulTileWidthBytes)
  983. ulCopyBytes = ulTileWidthBytes;
  984. RtlCopyMemory(pbDstLine, pbSrc, ulCopyBytes);
  985. pbDstLine += ulCopyBytes;
  986. }
  987. pbSrc += pSurfSrc->lDelta();
  988. if(pbSrc == pbSrcEnd)
  989. pbSrc = pbSrcStart;
  990. pbDst += pSurfDst->lDelta();
  991. }
  992. return TRUE;
  993. }
  994. // else if(pSurfDst->iType() == STYPE_BITMAP)
  995. // pfnCopyBits = EngCopyBits;
  996. else
  997. pfnCopyBits = PPFNGET(pdoDst,CopyBits,pSurfDst->flags());
  998. // brain dead method
  999. LONG y = prclDst->top;
  1000. LONG yEnd = prclDst->bottom;
  1001. LONG xEnd = prclDst->right;
  1002. RECTL dstRect;
  1003. while(y < yEnd)
  1004. {
  1005. LONG dy = yEnd - y;
  1006. if(dy > tileHeight) dy = tileHeight;
  1007. LONG x = prclDst->left;
  1008. while(x < xEnd)
  1009. {
  1010. LONG dx = xEnd - x;
  1011. if(dx > tileWidth) dx = tileWidth;
  1012. dstRect.left = x;
  1013. dstRect.top = y;
  1014. dstRect.right = x + dx;
  1015. dstRect.bottom = y + dy;
  1016. // TODO bhouse
  1017. // Lame clipping has to be fixed
  1018. if(pco == NULL || pco->iDComplexity == DC_TRIVIAL || bIntersect(&pco->rclBounds, &dstRect))
  1019. if(!(*pfnCopyBits)(psoDst, psoSrc, pco, pxlo, &dstRect, (POINTL*) prclSrc))
  1020. return FALSE;
  1021. x += dx;
  1022. }
  1023. y += dy;
  1024. }
  1025. return TRUE;
  1026. }
  1027. int EngTransparentTile(
  1028. SURFOBJ *psoDst,
  1029. SURFOBJ *psoSrc,
  1030. CLIPOBJ *pco,
  1031. XLATEOBJ *pxlo,
  1032. RECTL * prclDst,
  1033. RECTL * prclSrc,
  1034. POINTL * tileOrigin,
  1035. COLORREF crTransparentColor
  1036. )
  1037. {
  1038. int iRet = TRUE;
  1039. if(tileOrigin->x != 0 || tileOrigin->y != 0)
  1040. return FALSE;
  1041. PSURFACE pSurfSrc = SURFOBJ_TO_SURFACE(psoSrc);
  1042. PSURFACE pSurfDst = SURFOBJ_TO_SURFACE(psoDst);
  1043. PDEVOBJ pdoSrc(pSurfSrc->hdev());
  1044. PDEVOBJ pdoDst(pSurfDst->hdev());
  1045. XLATE * pxl = (XLATE *) pxlo;
  1046. // TODO bhouse
  1047. // we should handle all of the clipping cases
  1048. // in the fast copy.
  1049. LONG tileWidth = prclSrc->right - prclSrc->left;
  1050. LONG tileHeight = prclSrc->bottom - prclSrc->top;
  1051. if(tileWidth <= 0 || tileHeight <= 0)
  1052. return FALSE;
  1053. PFN_DrvTransparentBlt pfnTransparentBlt;
  1054. // if(pSurfDst->iType() == STYPE_BITMAP)
  1055. // pfnTransparentBlt = EngTransparentBlt;
  1056. // else
  1057. pfnTransparentBlt = PPFNGET(pdoDst,TransparentBlt,pSurfDst->flags());
  1058. // brain dead method
  1059. ERECTL dstRect;
  1060. ERECTL srcRect;
  1061. LONG y = prclDst->top;
  1062. LONG yEnd = prclDst->bottom;
  1063. LONG xEnd = prclDst->right;
  1064. srcRect.left = prclSrc->left;
  1065. srcRect.top = prclSrc->top;
  1066. while(y < yEnd)
  1067. {
  1068. LONG dy = yEnd - y;
  1069. if(dy > tileHeight) dy = tileHeight;
  1070. LONG x = prclDst->left;
  1071. dstRect.top = y;
  1072. dstRect.bottom = y + dy;
  1073. srcRect.bottom = srcRect.top + dy;
  1074. while(x < xEnd)
  1075. {
  1076. LONG dx = xEnd - x;
  1077. if(dx > tileWidth) dx = tileWidth;
  1078. dstRect.left = x;
  1079. dstRect.right = x + dx;
  1080. srcRect.right = srcRect.left + dx;
  1081. // TODO bhouse
  1082. // Lame clipping has to be fixed
  1083. if(pco == NULL || pco->iDComplexity == DC_TRIVIAL || bIntersect(&pco->rclBounds, &dstRect))
  1084. if(!(*pfnTransparentBlt)(psoDst, psoSrc, pco, pxlo, &dstRect, &srcRect, crTransparentColor, FALSE))
  1085. return FALSE;
  1086. x += dx;
  1087. }
  1088. y += dy;
  1089. }
  1090. return TRUE;
  1091. }
  1092. int EngAlphaTile(
  1093. SURFOBJ *psoDst,
  1094. SURFOBJ *psoSrc,
  1095. CLIPOBJ *pco,
  1096. XLATEOBJ *pxlo,
  1097. RECTL * prclDst,
  1098. RECTL * prclSrc,
  1099. POINTL * tileOrigin,
  1100. BLENDOBJ *pBlendObj
  1101. )
  1102. {
  1103. int iRet = TRUE;
  1104. if(tileOrigin->x != 0 || tileOrigin->y != 0)
  1105. return FALSE;
  1106. PSURFACE pSurfSrc = SURFOBJ_TO_SURFACE(psoSrc);
  1107. PSURFACE pSurfDst = SURFOBJ_TO_SURFACE(psoDst);
  1108. PDEVOBJ pdoSrc(pSurfSrc->hdev());
  1109. PDEVOBJ pdoDst(pSurfDst->hdev());
  1110. XLATE * pxl = (XLATE *) pxlo;
  1111. // TODO bhouse
  1112. // we should handle all of the clipping cases
  1113. // in the fast copy.
  1114. LONG tileWidth = prclSrc->right - prclSrc->left;
  1115. LONG tileHeight = prclSrc->bottom - prclSrc->top;
  1116. if(tileWidth <= 0 || tileHeight <= 0)
  1117. return FALSE;
  1118. PFN_DrvAlphaBlend pfnAlphaBlend;
  1119. // if(pSurfDst->iType() == STYPE_BITMAP)
  1120. // pfnAlphaBlend = EngAlphaBlend;
  1121. // else
  1122. pfnAlphaBlend = PPFNGET(pdoDst,AlphaBlend,pSurfDst->flags());
  1123. // brain dead method
  1124. LONG y = prclDst->top;
  1125. LONG yEnd = prclDst->bottom;
  1126. LONG xEnd = prclDst->right;
  1127. RECTL dstRect;
  1128. RECTL srcRect;
  1129. while(y < yEnd)
  1130. {
  1131. LONG dy = yEnd - y;
  1132. if(dy > tileHeight) dy = tileHeight;
  1133. LONG x = prclDst->left;
  1134. while(x < xEnd)
  1135. {
  1136. LONG dx = xEnd - x;
  1137. if(dx > tileWidth) dx = tileWidth;
  1138. dstRect.left = x;
  1139. dstRect.top = y;
  1140. dstRect.right = x + dx;
  1141. dstRect.bottom = y + dy;
  1142. srcRect.left = prclSrc->left;
  1143. srcRect.top = prclSrc->top;
  1144. srcRect.right = srcRect.left + dx;
  1145. srcRect.bottom = srcRect.top + dy;
  1146. // TODO bhouse
  1147. // Lame clipping has to be fixed
  1148. if(pco == NULL || pco->iDComplexity == DC_TRIVIAL || bIntersect(&pco->rclBounds, &dstRect))
  1149. if(!(*pfnAlphaBlend)(psoDst, psoSrc, pco, pxlo, &dstRect, &srcRect, pBlendObj ))
  1150. return FALSE;
  1151. x += dx;
  1152. }
  1153. y += dy;
  1154. }
  1155. return TRUE;
  1156. }
  1157. int EngDrawStreamBlt(
  1158. SURFOBJ *psoDst,
  1159. SURFOBJ *psoSrc,
  1160. CLIPOBJ *pco,
  1161. XLATEOBJ *pxlo,
  1162. RECTL * prclDst,
  1163. RECTL * prclSrc,
  1164. FLONG flFlags,
  1165. PDRAWSTREAMINFO pdsi)
  1166. {
  1167. int iRet = TRUE;
  1168. ERECTL erclDst = *prclDst;
  1169. BOOL bMirror = (erclDst.left > erclDst.right);
  1170. if(bMirror)
  1171. {
  1172. LONG lRight = erclDst.left;
  1173. erclDst.left = erclDst.right;
  1174. erclDst.right = lRight;
  1175. }
  1176. if(pco != NULL && pco->iDComplexity != DC_TRIVIAL && !bIntersect(&pco->rclBounds, &erclDst))
  1177. return TRUE;
  1178. PSURFACE pSurfDst = SURFOBJ_TO_SURFACE(psoDst);
  1179. PDEVOBJ pdoDst(pSurfDst->hdev());
  1180. FLONG flTile = (flFlags & (DSBLT_VTILE | DSBLT_HTILE));
  1181. if(flTile && flTile != (DSBLT_VTILE | DSBLT_HTILE))
  1182. {
  1183. // TODO: handle the case where we are tiling in one
  1184. // direction and stretching in the other
  1185. return TRUE;
  1186. }
  1187. if(flFlags & DSBLT_ALPHABLEND)
  1188. {
  1189. EBLENDOBJ eBlendObj;
  1190. eBlendObj.BlendFunction = pdsi->dss.blendFunction;
  1191. eBlendObj.pxlo32ToDst = pdsi->pxloBGRAToDst;
  1192. eBlendObj.pxloDstTo32 = pdsi->pxloDstToBGRA;
  1193. eBlendObj.pxloSrcTo32 = pdsi->pxloSrcToBGRA;
  1194. if(flTile)
  1195. {
  1196. iRet = EngAlphaTile(psoDst, psoSrc, pco, pxlo, &erclDst,
  1197. prclSrc, &gptlZero, (BLENDOBJ*) &eBlendObj);
  1198. }
  1199. else
  1200. {
  1201. iRet = (*PPFNGET(pdoDst,AlphaBlend,pSurfDst->flags()))(psoDst, psoSrc, pco, pxlo, &erclDst, prclSrc, &eBlendObj);
  1202. }
  1203. }
  1204. else if(flFlags & DSBLT_TRANSPARENT)
  1205. {
  1206. if(flTile)
  1207. {
  1208. iRet = EngTransparentTile(psoDst, psoSrc, pco, pxlo, &erclDst,
  1209. prclSrc, &gptlZero, pdsi->dss.crColorKey);
  1210. }
  1211. else
  1212. {
  1213. iRet = (*PPFNGET(pdoDst, TransparentBlt, pSurfDst->flags()))(psoDst, psoSrc, pco, pxlo,
  1214. &erclDst, prclSrc,
  1215. pdsi->dss.crColorKey,
  1216. FALSE);
  1217. }
  1218. }
  1219. else
  1220. {
  1221. if(flTile)
  1222. {
  1223. iRet = EngTileBits(psoDst, psoSrc, pco, pxlo, &erclDst,
  1224. prclSrc, &gptlZero);
  1225. }
  1226. else
  1227. {
  1228. iRet = (*PPFNGET(pdoDst, StretchBlt, pSurfDst->flags()))(psoDst, psoSrc, NULL, pco, pxlo,
  1229. NULL, NULL,
  1230. &erclDst, prclSrc,
  1231. NULL,
  1232. COLORONCOLOR);
  1233. }
  1234. }
  1235. return iRet;
  1236. }
  1237. #endif
  1238. /******************************Private*Routine******************************\
  1239. * EngDrawStream
  1240. *
  1241. * Purpose: Draws a graphics stream
  1242. *
  1243. * Description:
  1244. *
  1245. * Parses the graphics stream rendering each command as approprite.
  1246. *
  1247. * History:
  1248. *
  1249. * 3-18-2001 bhouse Created it
  1250. *
  1251. \**************************************************************************/
  1252. BOOL
  1253. EngDrawStream(
  1254. SURFOBJ *psoDst,
  1255. SURFOBJ *psoSrc,
  1256. CLIPOBJ *pco,
  1257. XLATEOBJ *pxlo,
  1258. PRECTL prclDstClip,
  1259. PPOINTL pptlDstOffset,
  1260. ULONG cjIn,
  1261. PVOID pvIn,
  1262. DSSTATE *pdss
  1263. )
  1264. {
  1265. BOOL bRet = TRUE;
  1266. PDRAWSTREAMINFO pdsi = (PDRAWSTREAMINFO) pdss;
  1267. ASSERTGDI(psoDst != NULL, "ERROR EngDrawStream: No Dst. Object\n");
  1268. ASSERTGDI(psoSrc != NULL, "ERROR EngDrawStream: No Src. Object\n");
  1269. ASSERTGDI(prclDstClip != (PRECTL) NULL, "ERROR EngDrawStream: No Target Bounds Rect.\n");
  1270. ASSERTGDI(prclDstClip->left < prclDstClip->right, "ERROR EngCopyBits0\n");
  1271. ASSERTGDI(prclDstClip->top < prclDstClip->bottom, "ERROR EngCopyBits1\n");
  1272. PSURFACE pSurfDst = SURFOBJ_TO_SURFACE(psoDst);
  1273. PSURFACE pSurfSrc = SURFOBJ_TO_SURFACE(psoSrc);
  1274. PDEVOBJ pdoDst(pSurfDst->hdev());
  1275. ASSERTGDI(pSurfDst->iFormat() != BMF_JPEG,
  1276. "ERROR EngCopyBits: dst BMF_JPEG\n");
  1277. ASSERTGDI(pSurfDst->iFormat() != BMF_PNG,
  1278. "ERROR EngCopyBits: dst BMF_PNG\n");
  1279. ASSERTGDI(pSurfSrc->iFormat() != BMF_JPEG,
  1280. "ERROR EngCopyBits: src BMF_JPEG\n");
  1281. ASSERTGDI(pSurfSrc->iFormat() != BMF_PNG,
  1282. "ERROR EngCopyBits: src BMF_PNG\n");
  1283. ULONG * pul = (ULONG *) pvIn;
  1284. while(cjIn >= sizeof(ULONG))
  1285. {
  1286. ULONG command = *pul;
  1287. HDC hdcTarget;
  1288. HDC hdcSource;
  1289. ULONG commandSize;
  1290. switch(command)
  1291. {
  1292. case DS_NINEGRIDID:
  1293. {
  1294. // TODO: ensure that the destination rect is within bounds
  1295. DS_NINEGRID * cmd = (DS_NINEGRID *) pul;
  1296. commandSize = sizeof(*cmd);
  1297. if(cjIn < commandSize) goto exit;
  1298. ERECTL erclDst(cmd->rclDst);
  1299. erclDst += *pptlDstOffset;
  1300. // Note, we are going directly to the driver or to EngNineGrid
  1301. // without going back through sprite or multimon layer. This is
  1302. // ok because we will have already gone through those layers to
  1303. // get here and the source can not be a primary surface.
  1304. PFN_DrvNineGrid pfn = pSurfDst->pfnNineGrid();
  1305. if( psoDst->dhpdev == NULL || !(pdoDst.flGraphicsCaps2() & GCAPS2_REMOTEDRIVER))
  1306. pfn = EngNineGrid;
  1307. // TODO: have the eBlendObj be part of DRAWSTREAMINFO
  1308. EBLENDOBJ eBlendObj;
  1309. eBlendObj.BlendFunction.AlphaFormat = AC_SRC_ALPHA;
  1310. eBlendObj.BlendFunction.BlendFlags = 0;
  1311. eBlendObj.BlendFunction.SourceConstantAlpha = 255;
  1312. eBlendObj.BlendFunction.BlendOp = AC_SRC_OVER;
  1313. eBlendObj.pxlo32ToDst = pdsi->pxloBGRAToDst;
  1314. eBlendObj.pxloDstTo32 = pdsi->pxloDstToBGRA;
  1315. eBlendObj.pxloSrcTo32 = pdsi->pxloSrcToBGRA;
  1316. bRet = (*pfn)(psoDst, psoSrc, pco, pxlo, &erclDst, &cmd->rclSrc, (PNINEGRID) &cmd->ngi, &eBlendObj, NULL);
  1317. }
  1318. break;
  1319. #if DS_ENABLE_BLT
  1320. case DS_BLTID:
  1321. {
  1322. // TODO: ensure that the destination rect is within bounds
  1323. DS_BLT * cmd = (DS_BLT *) pul;
  1324. commandSize = sizeof(*cmd);
  1325. if(cjIn < commandSize) goto exit;
  1326. ERECTL erclDst(cmd->rclDst);
  1327. erclDst += *pptlDstOffset;
  1328. if(!EngDrawStreamBlt(psoDst, psoSrc, pco, pxlo, &erclDst,
  1329. &cmd->rclSrc, cmd->flFlags, pdsi))
  1330. goto exit;
  1331. }
  1332. break;
  1333. case DS_SETCOLORKEYID:
  1334. {
  1335. // TODO: ensure that the destination rect is within bounds
  1336. DS_SETCOLORKEY * cmd = (DS_SETCOLORKEY *) pul;
  1337. commandSize = sizeof(*cmd);
  1338. if(cjIn < commandSize) goto exit;
  1339. pdsi->dss.crColorKey = cmd->crColorKey;
  1340. }
  1341. break;
  1342. case DS_SETBLENDID:
  1343. {
  1344. // TODO: ensure that the destination rect is within bounds
  1345. DS_SETBLEND * cmd = (DS_SETBLEND *) pul;
  1346. commandSize = sizeof(*cmd);
  1347. if(cjIn < commandSize) goto exit;
  1348. pdsi->dss.blendFunction = cmd->blendFunction;
  1349. }
  1350. break;
  1351. #endif
  1352. default:
  1353. goto exit;
  1354. }
  1355. cjIn -= commandSize;
  1356. pul += commandSize / 4;
  1357. }
  1358. exit:
  1359. return bRet;
  1360. }
  1361. /******************************Private*Routine******************************\
  1362. *
  1363. * NtGdiDrawStreamInternal
  1364. *
  1365. * Draws the given graphics stream to the given destination using
  1366. * the given source for any stream commands which require a source.
  1367. *
  1368. * History:
  1369. * 3-18-2001 bhouse Created it
  1370. *
  1371. \**************************************************************************/
  1372. BOOL
  1373. NtGdiDrawStreamInternal(
  1374. XDCOBJ& dcoDst,
  1375. EXFORMOBJ& xoDst,
  1376. SURFACE* pSurfSrc,
  1377. XLATEOBJ * pxlo,
  1378. RECTL* prclDstClip,
  1379. RECTL* prclDstBounds,
  1380. LONG cjIn,
  1381. LPSTR pvIn,
  1382. PDRAWSTREAMINFO pdsi
  1383. )
  1384. {
  1385. BOOL bReturn = FALSE;
  1386. ASSERTGDI(dcoDst.bValid(), "NtGdiDrawStrea: invalide destination DC\n");
  1387. ASSERTGDI(pSurfSrc != NULL, "NtGdiDrawStream: null source surface\n");
  1388. ERECTL erclDstClip(*prclDstClip);
  1389. ERECTL erclDstBounds(*prclDstBounds);
  1390. EPOINTL eptlDstOffset(0,0);
  1391. if(dcoDst.bDisplay() && !dcoDst.bRedirection() && !UserScreenAccessCheck())
  1392. {
  1393. //WARNING("NtGdiDrawStreamInternal: Screen Access Check Failed\n");
  1394. SAVE_ERROR_CODE(ERROR_ACCESS_DENIED);
  1395. goto exit;
  1396. }
  1397. if(xoDst.bRotation())
  1398. {
  1399. WARNING("NtGdiDrawStreamInternal: destination has rotational transform");
  1400. goto exit;
  1401. }
  1402. if(xoDst.bTranslationsOnly())
  1403. {
  1404. xoDst.bXform(eptlDstOffset);
  1405. }
  1406. else
  1407. {
  1408. // walk the stream applying transform
  1409. ULONG *pul = (ULONG *) pvIn;
  1410. ULONG *pulEnd = (ULONG*) ((BYTE*) pul + cjIn);
  1411. while(pul < pulEnd)
  1412. {
  1413. switch(*pul)
  1414. {
  1415. case DS_NINEGRIDID:
  1416. {
  1417. DS_NINEGRID * cmd = (DS_NINEGRID *) pul;
  1418. xoDst.bXform(*(ERECTL*)&cmd->rclDst);
  1419. pul = (ULONG*) (cmd+1);
  1420. }
  1421. break;
  1422. default:
  1423. WARNING("NtGdiDrawStreamInternal: unrecognized draw stream command");
  1424. goto exit;
  1425. }
  1426. }
  1427. }
  1428. xoDst.bXform(erclDstBounds);
  1429. erclDstBounds.vOrder();
  1430. if(erclDstClip.bEmpty())
  1431. {
  1432. WARNING("NtGdiDrawStreamInternal: destination clip is empty");
  1433. goto exit;
  1434. }
  1435. //
  1436. // Check pSurfDst, this may be an info DC or a memory DC with default bitmap.
  1437. //
  1438. SURFACE *pSurfDst = dcoDst.pSurface();
  1439. //
  1440. // Set up the brush if necessary.
  1441. //
  1442. EBRUSHOBJ *pbo = NULL;
  1443. //
  1444. // With a fixed DC origin we can change the destination to SCREEN coordinates.
  1445. //
  1446. eptlDstOffset += dcoDst.eptlOrigin();
  1447. erclDstClip += dcoDst.eptlOrigin();
  1448. //
  1449. // This is a pretty gnarly expression to save a return in here.
  1450. // Basically pco can be NULL if the rect is completely in the
  1451. // cached rect in the DC or if we set up a clip object that isn't empty.
  1452. //
  1453. ECLIPOBJ *pco = NULL;
  1454. BOOL bForce = !erclDstClip.bContain(erclDstBounds);
  1455. if (((erclDstBounds.left >= dcoDst.prclClip()->left) &&
  1456. (erclDstBounds.right <= dcoDst.prclClip()->right) &&
  1457. (erclDstBounds.top >= dcoDst.prclClip()->top) &&
  1458. (erclDstBounds.bottom <= dcoDst.prclClip()->bottom) &&
  1459. (!bForce)) ||
  1460. (pco = dcoDst.pco(),
  1461. pco->vSetup(dcoDst.prgnEffRao(), erclDstClip, (bForce ? CLIP_FORCE : CLIP_NOFORCE)),
  1462. erclDstClip = pco->erclExclude(),
  1463. (!erclDstClip.bEmpty())))
  1464. {
  1465. //
  1466. // Inc the target surface uniqueness
  1467. //
  1468. INC_SURF_UNIQ(pSurfDst);
  1469. PFN_DrvDrawStream pfn = pSurfDst->pfnDrawStream();
  1470. //
  1471. // Only call through draw stream layer for primary pdev surfaces
  1472. // and Meta DEVBITMAPS.
  1473. // This will allows us to call through sprite layer and multi-mon
  1474. // layer for the primary and Meta DEVBITMAPS only.
  1475. // Device drivers currently are not allowed to hook draw stream.
  1476. // NOTE: we have run out of hook flags. We will need to extend the
  1477. // hook flag mechanism to support additional DDI. This check
  1478. // is a hack to avoid calling through the sprite and multi-mon
  1479. // layers. (Normally, the hook flags would be set correctly
  1480. // to do the right thing).
  1481. PDEVOBJ pdoDst(pSurfDst->hdev());
  1482. BOOL bDstMetaDriver = (dcoDst.bSynchronizeAccess() && pdoDst.bValid() && pdoDst.bMetaDriver());
  1483. if(!pSurfDst->bPDEVSurface() && !(bDstMetaDriver && pSurfDst->iType() == STYPE_DEVBITMAP))
  1484. pfn = EngDrawStream;
  1485. bReturn = (*pfn) (
  1486. pSurfDst->pSurfobj(),
  1487. pSurfSrc->pSurfobj(),
  1488. pco,
  1489. pxlo,
  1490. &erclDstClip,
  1491. &eptlDstOffset,
  1492. cjIn,
  1493. pvIn,
  1494. (DSSTATE*) pdsi);
  1495. }
  1496. else
  1497. {
  1498. bReturn = TRUE;
  1499. }
  1500. exit:
  1501. return(bReturn);
  1502. }
  1503. BOOL gGreDrawStream = TRUE;
  1504. BOOL gDrawClipped = FALSE;
  1505. /******************************Private*Routine******************************\
  1506. *
  1507. * GreDrawStream
  1508. *
  1509. * Draws a graphics stream. hdcDst is the primary output device is more
  1510. * then one target is set within the stream.
  1511. *
  1512. * History:
  1513. * 3-18-2001 bhouse Created it
  1514. *
  1515. \**************************************************************************/
  1516. BOOL GreDrawStream(
  1517. HDC hdcDst,
  1518. ULONG cjIn,
  1519. PVOID pvIn
  1520. )
  1521. {
  1522. XDCOBJ dcoDst;
  1523. XDCOBJ dcoSrc;
  1524. SURFREFDC soSrc;
  1525. BOOL bRet = FALSE;
  1526. EXFORMOBJ xoSrc;
  1527. EXFORMOBJ xoDst;
  1528. DEVLOCKBLTOBJ dloSrc;
  1529. DEVLOCKBLTOBJ dloDst;
  1530. SURFACE * pSurfDst;
  1531. SURFACE * pSurfSrc = NULL;
  1532. XEPALOBJ palSrcDC;
  1533. XLATEOBJ * pxlo;
  1534. XEPALOBJ palDst;
  1535. XEPALOBJ palDstDC;
  1536. XEPALOBJ palSrc;
  1537. XEPALOBJ palRGB(gppalRGB);
  1538. EXLATEOBJ xlo;
  1539. ERECTL erclDstClip;
  1540. BOOL bAlphaBlendPresent = FALSE;
  1541. PVOID pvPrimStart = NULL;
  1542. DRAWSTREAMINFO dsi;
  1543. ERECTL erclDstBounds;
  1544. BOOL bFoundTrg = FALSE;
  1545. dloSrc.vInit();
  1546. dloDst.vInit();
  1547. if(!gGreDrawStream)
  1548. {
  1549. WARNING("GreDrawStream: gGreDrawStream == 0");
  1550. goto exit;
  1551. }
  1552. if(cjIn < sizeof(ULONG))
  1553. {
  1554. WARNING("GreDrawStream: cjIn < sizeof(ULONG)");
  1555. goto exit;
  1556. }
  1557. ULONG * pul = (ULONG *) pvIn;
  1558. if(*pul++ != 'DrwS')
  1559. {
  1560. WARNING("GreDrawStream: did not find DrwS magic number");
  1561. goto exit;
  1562. }
  1563. cjIn -= sizeof(ULONG);
  1564. while(cjIn >= sizeof(ULONG))
  1565. {
  1566. ULONG command = *pul;
  1567. HDC hdcTarget;
  1568. HDC hdcSource;
  1569. ULONG commandSize;
  1570. switch(command)
  1571. {
  1572. case DS_SETTARGETID: // set target
  1573. {
  1574. if(pvPrimStart != NULL) goto drawStream;
  1575. dloDst.vUnLock();
  1576. dcoDst.vUnlock();
  1577. soSrc.vUnlock();
  1578. DS_SETTARGET * cmd = (DS_SETTARGET *) pul;
  1579. commandSize = sizeof(*cmd);
  1580. if(cjIn < commandSize)
  1581. {
  1582. WARNING("GreDrawStream: cjIn < commandSize");
  1583. goto exit;
  1584. }
  1585. if((HDC) LongToHandle((LONG)(cmd->hdc)) != hdcDst)
  1586. {
  1587. WARNING("GreDrawStream: cmd->hdc != hdcDst");
  1588. goto exit;
  1589. }
  1590. dcoDst.vLock((HDC) LongToHandle((LONG)(cmd->hdc)));
  1591. if(!dcoDst.bValid())
  1592. {
  1593. WARNING("GreDrawStream: !dcoDst.bValid()");
  1594. goto exit;
  1595. }
  1596. if(dcoDst.bStockBitmap())
  1597. {
  1598. WARNING("GreDrawStream: dcoDst has Stock bitmap selected");
  1599. goto exit;
  1600. }
  1601. if(!dloDst.bLock(dcoDst))
  1602. {
  1603. WARNING("GreDrawStream: Could not lock dcoDst");
  1604. goto exit;
  1605. }
  1606. xoDst.vQuickInit(dcoDst, WORLD_TO_DEVICE);
  1607. if(xoDst.bRotation())
  1608. {
  1609. WARNING("GreDrawStream: dcoDst has a rotation transform");
  1610. goto exit;
  1611. }
  1612. erclDstClip = cmd->rclDstClip;
  1613. xoDst.bXform(erclDstClip);
  1614. erclDstClip.vOrder();
  1615. if (dcoDst.fjAccum())
  1616. dcoDst.vAccumulate(erclDstClip);
  1617. pSurfDst = dcoDst.pSurface();
  1618. if (pSurfDst == NULL)
  1619. {
  1620. //WARNING("GreDrawStream: dcoDst has NULL pSurface\n");
  1621. goto exit;
  1622. }
  1623. palDst.ppalSet(pSurfDst->ppal());
  1624. palDstDC.ppalSet(dcoDst.ppal());
  1625. // we don't support monochrome destinations
  1626. if(palSrc.bIsMonochrome())
  1627. {
  1628. WARNING("GreDrawStream: palSrc.bIsMonochrome()");
  1629. goto exit;
  1630. }
  1631. bFoundTrg = TRUE;
  1632. }
  1633. break;
  1634. case DS_SETSOURCEID: // set source
  1635. {
  1636. if(pvPrimStart != NULL) goto drawStream;
  1637. dloSrc.vUnLock();
  1638. dcoSrc.vUnlock();
  1639. soSrc.vUnlock();
  1640. pSurfSrc = NULL;
  1641. DS_SETSOURCE * cmd = (DS_SETSOURCE *) pul;
  1642. commandSize = sizeof(*cmd);
  1643. if(cjIn < commandSize || !bFoundTrg)
  1644. {
  1645. WARNING("GreDrawStream: cjIn < commandSize || !bFoundTrg");
  1646. goto exit;
  1647. }
  1648. #if 0
  1649. // Old code to to allow source to be from HDC
  1650. // We might want to support this in the future (source from
  1651. // HDC)
  1652. dcoSrc.vLock(cmd->hdc);
  1653. if(!dcoSrc.bValid())
  1654. {
  1655. WARNING("GreDrawStream: source is invalid");
  1656. goto exit;
  1657. }
  1658. xoSrc.vQuickInit(dcoSrc, WORLD_TO_DEVICE);
  1659. if(!xoSrc.bIdentity())
  1660. {
  1661. WARNING("GreDrawStream: source transform is not identity");
  1662. goto exit;
  1663. }
  1664. if(!dloSrc.bLock(dcoSrc))
  1665. goto exit;
  1666. pSurfSrc = dcoSrc.pSurface();
  1667. ASSERTGDI(pSurfSrc != NULL, "GreDrawSteam: unexpected NULL source in valid DC\n");
  1668. // source must be different then target
  1669. if (pSurfSrc == pSurfDst)
  1670. goto exit;
  1671. if (!(pSurfSrc->bReadable() && (dcoDst.bDisplay() ? UserScreenAccessCheck() : TRUE)) &&
  1672. !((dcoSrc.bDisplay()) && ((dcoDst.bDisplay()) || UserScreenAccessCheck() )) )
  1673. {
  1674. WARNING("GreDrawStream: faild screena access check");
  1675. goto exit;
  1676. }
  1677. palSrcDC.ppalSet(dcoSrc.ppal());
  1678. #endif
  1679. soSrc.vLock((HSURF) ULongToHandle(cmd->hbm));
  1680. if(!soSrc.bValid())
  1681. {
  1682. WARNING("GreDrawStream: source is invalid");
  1683. goto exit;
  1684. }
  1685. pSurfSrc = soSrc.ps;
  1686. palSrcDC.ppalSet(ppalDefault);
  1687. palSrc.ppalSet(pSurfSrc->ppal());
  1688. if(!palSrc.bValid())
  1689. {
  1690. WARNING("GreDrawStream: source must have an associated palette");
  1691. goto exit;
  1692. }
  1693. if(palSrc.bIsMonochrome())
  1694. {
  1695. WARNING("GreDrawStream: monochrome sources are not supported");
  1696. goto exit;
  1697. }
  1698. // source must be different then target and 32bpp for now
  1699. if (pSurfSrc == pSurfDst || (pSurfSrc->iFormat() != BMF_32BPP))
  1700. {
  1701. WARNING("GreDrawStream: source and destination surfaces must differ or the source is not 32 Bpp");
  1702. goto exit;
  1703. }
  1704. //
  1705. // No ICM with BitBlt(), so pass NULL color transform to XLATEOBJ
  1706. //
  1707. if(!xlo.bInitXlateObj(NULL, // hColorTransform
  1708. dcoDst.pdc->lIcmMode(), // ICM mode
  1709. palSrc,
  1710. palDst,
  1711. palSrcDC,
  1712. palDstDC,
  1713. dcoDst.pdc->crTextClr(),
  1714. dcoDst.pdc->crBackClr(),
  1715. 0))
  1716. {
  1717. WARNING("GreDrawStream: unable to initialize source to destination xlo");
  1718. goto exit;
  1719. }
  1720. pxlo = xlo.pxlo();
  1721. }
  1722. break;
  1723. case DS_NINEGRIDID:
  1724. {
  1725. commandSize = sizeof(DS_NINEGRID);
  1726. DS_NINEGRID * cmd = (DS_NINEGRID *) pul;
  1727. // validate nine grid
  1728. #define DSDNG_MASK 0x007F // move to wingdip.h
  1729. if(cmd->ngi.flFlags & ~DSDNG_MASK)
  1730. {
  1731. WARNING("GreDrawStream: unrecognized nine grid flags set");
  1732. goto exit;
  1733. }
  1734. if(pSurfSrc == NULL)
  1735. {
  1736. WARNING("GreDrawStream: source not set before nine grid command");
  1737. goto exit;
  1738. }
  1739. if(cmd->rclSrc.left < 0 || cmd->rclSrc.top < 0 ||
  1740. cmd->rclSrc.right > pSurfSrc->sizl().cx ||
  1741. cmd->rclSrc.bottom > pSurfSrc->sizl().cy)
  1742. {
  1743. WARNING("GreDrawStream: nine grid rclSrc not within bounds of source");
  1744. goto exit;
  1745. }
  1746. LONG lSrcWidth = cmd->rclSrc.right - cmd->rclSrc.left;
  1747. LONG lSrcHeight = cmd->rclSrc.bottom - cmd->rclSrc.top;
  1748. if(lSrcWidth <= 0 || lSrcHeight <= 0)
  1749. {
  1750. WARNING("GreDrawStream: nine grid rclSrc is not well ordered");
  1751. goto exit;
  1752. }
  1753. if(!(cmd->ngi.flFlags & DSDNG_TRUESIZE))
  1754. {
  1755. // NOTE: we have to check individual first then sum due to possible
  1756. // numerical overflows that could occur in the sum that might
  1757. // not be detected otherwise.
  1758. if(cmd->ngi.ulLeftWidth < 0 ||
  1759. cmd->ngi.ulRightWidth < 0 ||
  1760. cmd->ngi.ulTopHeight < 0 ||
  1761. cmd->ngi.ulBottomHeight < 0 ||
  1762. cmd->ngi.ulLeftWidth > lSrcWidth ||
  1763. cmd->ngi.ulRightWidth > lSrcWidth ||
  1764. cmd->ngi.ulTopHeight > lSrcHeight ||
  1765. cmd->ngi.ulBottomHeight > lSrcHeight ||
  1766. cmd->ngi.ulLeftWidth + cmd->ngi.ulRightWidth > lSrcWidth ||
  1767. cmd->ngi.ulTopHeight + cmd->ngi.ulBottomHeight > lSrcHeight)
  1768. {
  1769. WARNING("GreDrawStream: nine grid width is greater then rclSrc width or are negative");
  1770. goto exit;
  1771. }
  1772. }
  1773. if((cmd->ngi.flFlags & (DSDNG_TRANSPARENT | DSDNG_PERPIXELALPHA)) == (DSDNG_TRANSPARENT | DSDNG_PERPIXELALPHA))
  1774. {
  1775. WARNING("GreDrawStream: nine grid attempt to set both transparency and per pixel alpha");
  1776. goto exit;
  1777. }
  1778. if(cmd->ngi.flFlags & DSDNG_TRANSPARENT)
  1779. cmd->ngi.crTransparent = ulGetNearestIndexFromColorref(
  1780. palSrc,
  1781. palSrcDC,
  1782. cmd->ngi.crTransparent,
  1783. SE_DO_SEARCH_EXACT_FIRST
  1784. );
  1785. else if(cmd->ngi.flFlags & DSDNG_PERPIXELALPHA)
  1786. {
  1787. bAlphaBlendPresent = TRUE;
  1788. }
  1789. if(pvPrimStart == NULL)
  1790. {
  1791. pvPrimStart = (PVOID) pul;
  1792. erclDstBounds = cmd->rclDst;
  1793. }
  1794. else
  1795. erclDstBounds += cmd->rclDst;
  1796. }
  1797. break;
  1798. #if 0
  1799. case DS_BLTID:
  1800. {
  1801. commandSize = sizeof(DS_BLT);
  1802. DS_BLT * cmd = (DS_BLT *) pul;
  1803. if(cmd->flFlags & DSBLT_ALPHABLEND)
  1804. {
  1805. bAlphaBlendPresent = TRUE;
  1806. }
  1807. if(pvPrimStart == NULL)
  1808. {
  1809. pvPrimStart = (PVOID) pul;
  1810. erclDstBounds = cmd->rclDst;
  1811. }
  1812. else
  1813. erclDstBounds += cmd->rclDst;
  1814. }
  1815. break;
  1816. case DS_SETCOLORKEYID:
  1817. {
  1818. commandSize = sizeof(DS_SETCOLORKEY);
  1819. if(pvPrimStart == NULL) pvPrimStart = (PVOID) pul;
  1820. DS_SETCOLORKEY * cmd = (DS_SETCOLORKEY *) pul;
  1821. cmd->crColorKey = ulGetNearestIndexFromColorref(
  1822. palSrc,
  1823. palSrcDC,
  1824. cmd->crColorKey,
  1825. SE_DO_SEARCH_EXACT_FIRST
  1826. );
  1827. }
  1828. break;
  1829. case DS_SETBLENDID:
  1830. {
  1831. commandSize = sizeof(DS_SETBLEND);
  1832. if(pvPrimStart == NULL) pvPrimStart = (PVOID) pul;
  1833. DS_SETBLEND * cmd = (DS_SETBLEND *) pul;
  1834. }
  1835. break;
  1836. #endif
  1837. default:
  1838. goto exit;
  1839. }
  1840. cjIn -= commandSize;
  1841. pul += commandSize / 4;
  1842. if(cjIn == 0)
  1843. {
  1844. drawStream:
  1845. if(pvPrimStart != NULL && dcoDst.bValid() && pSurfSrc != NULL)
  1846. {
  1847. EXLATEOBJ xloSrcToBGRA;
  1848. EXLATEOBJ xloDstToBGRA;
  1849. EXLATEOBJ xloBGRAToDst;
  1850. dsi.dss.ulSize = sizeof(DRAWSTREAMINFO);
  1851. dsi.dss.crColorKey = 0;
  1852. dsi.dss.blendFunction.AlphaFormat = AC_SRC_ALPHA;
  1853. dsi.dss.blendFunction.BlendFlags = 0;
  1854. dsi.dss.blendFunction.SourceConstantAlpha = 255;
  1855. dsi.dss.blendFunction.BlendOp = AC_SRC_OVER;
  1856. dsi.bCalledFromBitBlt = FALSE;
  1857. dsi.dss.ptlSrcOrigin.x = 0;
  1858. dsi.dss.ptlSrcOrigin.y = 0;
  1859. if(bAlphaBlendPresent)
  1860. {
  1861. if(!xloSrcToBGRA.bInitXlateObj(
  1862. NULL,
  1863. DC_ICM_OFF,
  1864. palSrc,
  1865. palRGB,
  1866. palSrcDC,
  1867. palSrcDC,
  1868. 0,
  1869. 0,
  1870. 0
  1871. ))
  1872. {
  1873. WARNING("GreDrawStream: unable to initialize xloSrcToBGRA");
  1874. goto exit;
  1875. }
  1876. dsi.pxloSrcToBGRA = xloSrcToBGRA.pxlo();
  1877. if(!xloDstToBGRA.bInitXlateObj(
  1878. NULL,
  1879. DC_ICM_OFF,
  1880. palDst,
  1881. palRGB,
  1882. palDstDC,
  1883. palDstDC,
  1884. 0,
  1885. 0,
  1886. 0
  1887. ))
  1888. {
  1889. WARNING("GreDrawStream: unable to initialize xloDstToBGRA");
  1890. goto exit;
  1891. }
  1892. dsi.pxloDstToBGRA = xloDstToBGRA.pxlo();
  1893. if(!xloBGRAToDst.bInitXlateObj(
  1894. NULL,
  1895. DC_ICM_OFF,
  1896. palRGB,
  1897. palDst,
  1898. palDstDC,
  1899. palDstDC,
  1900. 0,
  1901. 0,
  1902. 0
  1903. ))
  1904. {
  1905. WARNING("GreDrawStream: unable to initialize xloBGRAToDst");
  1906. goto exit;
  1907. }
  1908. dsi.pxloBGRAToDst = xloBGRAToDst.pxlo();
  1909. }
  1910. else
  1911. {
  1912. dsi.pxloBGRAToDst = NULL;
  1913. dsi.pxloDstToBGRA = NULL;
  1914. dsi.pxloSrcToBGRA = NULL;
  1915. }
  1916. if(!NtGdiDrawStreamInternal(dcoDst, xoDst, pSurfSrc, pxlo,
  1917. (RECTL*) &erclDstClip,
  1918. (RECTL*) &erclDstBounds,
  1919. (LONG)((PBYTE) pul - (PBYTE) pvPrimStart),
  1920. (LPSTR) pvPrimStart,
  1921. &dsi))
  1922. {
  1923. //WARNING("GreDrawStream: NtGdiDrawStreamInternal failed\n");
  1924. goto exit;
  1925. }
  1926. pvPrimStart = NULL;
  1927. bAlphaBlendPresent = FALSE;
  1928. }
  1929. else
  1930. {
  1931. WARNING("GreDrawStream: !(pvPrimStart != NULL && dcoDst.bValid() && pSurfSrc != NULL)");
  1932. }
  1933. }
  1934. }
  1935. bRet = TRUE;
  1936. exit:
  1937. dcoDst.vUnlock();
  1938. dcoSrc.vUnlock();
  1939. return bRet;
  1940. }