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.

1318 lines
43 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: bitblt.c
  3. *
  4. * Banked Frame Buffer bitblit
  5. *
  6. * Copyright (c) 1992 Microsoft Corporation
  7. *
  8. \**************************************************************************/
  9. #include "driver.h"
  10. /************************************************************************\
  11. * bIntersectRect
  12. *
  13. * Calculates the intersection between *prcSrc1 and *prcSrc2,
  14. * returning the resulting rect in *prcDst. Returns TRUE if
  15. * *prcSrc1 intersects *prcSrc2, FALSE otherwise. If there is no
  16. * intersection, an empty rect is returned in *prcDst.
  17. \************************************************************************/
  18. static const RECTL rclEmpty = { 0, 0, 0, 0 };
  19. BOOL bIntersectRect(
  20. PRECTL prcDst,
  21. PRECTL prcSrc1,
  22. PRECTL prcSrc2)
  23. {
  24. prcDst->left = max(prcSrc1->left, prcSrc2->left);
  25. prcDst->right = min(prcSrc1->right, prcSrc2->right);
  26. // check for empty rect
  27. if (prcDst->left < prcDst->right)
  28. {
  29. prcDst->top = max(prcSrc1->top, prcSrc2->top);
  30. prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom);
  31. // check for empty rect
  32. if (prcDst->top < prcDst->bottom)
  33. return(TRUE); // not empty
  34. }
  35. // empty rect
  36. *prcDst = rclEmpty;
  37. return(FALSE);
  38. }
  39. /******************************Public*Routine******************************\
  40. * BOOL bPuntScreenToScreenCopyBits(ppdev, pco, pxlo, prclDest, pptlSrc)
  41. *
  42. * Performs a screen-to-screen CopyBits entirely using an intermediate
  43. * temporary buffer and GDI.
  44. *
  45. * We found that on most machines it was faster to have the engine copy
  46. * the source to a buffer, then blit the buffer to the destination, than
  47. * to have optimized ASM code that copies a word at a time. The reason?
  48. * The engine does d-word moves, which are faster than word moves even
  49. * going over the bus to a 16 bit display device.
  50. *
  51. * We could also write optimized ASM code that does d-word moves, but the
  52. * win will be marginal, we're time constrained, we also need a routine
  53. * like this to handle complex clip objects and palette translates, and
  54. * most of the other times we can use planar copies for important things
  55. * like scrolls, anyways.
  56. *
  57. \**************************************************************************/
  58. BOOL bPuntScreenToScreenCopyBits(
  59. PPDEV ppdev,
  60. CLIPOBJ* pco,
  61. XLATEOBJ* pxlo,
  62. RECTL* prclDest,
  63. POINTL* pptlSrc)
  64. {
  65. RECTL rclDest;
  66. POINTL ptlSrc;
  67. BOOL b = TRUE;
  68. ULONG ulWidth;
  69. LONG ulBurstSize;
  70. LONG xLeft;
  71. LONG xRight;
  72. SURFOBJ* pso = ppdev->pSurfObj;
  73. SURFOBJ* psoTmp = ppdev->psoTmp;
  74. ULONG ulAlign;
  75. PVOID savedpvScan0 = psoTmp->pvScan0;
  76. LONG savedlDelta = psoTmp->lDelta;
  77. USHORT savedfjBitmap = psoTmp->fjBitmap;
  78. xLeft = prclDest->left;
  79. xRight = prclDest->right;
  80. if (pco && (pco->iDComplexity != DC_TRIVIAL))
  81. {
  82. xLeft = max(xLeft,pco->rclBounds.left);
  83. xRight = min(xRight,pco->rclBounds.right);
  84. }
  85. ulAlign = xLeft & 3;
  86. ulWidth = (((xRight + 3) & ~3) - (xLeft & ~3));
  87. ulBurstSize = min((GLOBAL_BUFFER_SIZE/ulWidth),(ULONG)(prclDest->bottom-prclDest->top));
  88. ASSERTVGA (ulBurstSize > 0, "VGA256: bPuntScreenToScreenBitBlt ulBurstSize <= 0\n");
  89. // set up pso to use stack memory
  90. psoTmp->pvScan0 = ppdev->pvTmpBuf;
  91. psoTmp->lDelta = ulWidth;
  92. psoTmp->fjBitmap |= BMF_TOPDOWN;
  93. if (prclDest->top < pptlSrc->y)
  94. {
  95. ////////////////////////////////////////////////////////////////
  96. // Do a top-to-bottom copy:
  97. ////////////////////////////////////////////////////////////////
  98. LONG ySrcBottom;
  99. LONG yDestBottom;
  100. LONG yDestTop = prclDest->top;
  101. LONG ySrcTop = pptlSrc->y;
  102. LONG ySrcLast = ySrcTop + (prclDest->bottom - prclDest->top);
  103. if (ySrcTop < ppdev->rcl1WindowClip.top ||
  104. ySrcTop >= ppdev->rcl1WindowClip.bottom)
  105. {
  106. ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop);
  107. }
  108. pso->pvScan0 = ppdev->pvBitmapStart;
  109. while (TRUE)
  110. {
  111. // Copy some scans into the temporary buffer:
  112. ySrcBottom = min(ySrcLast, ppdev->rcl1WindowClip.bottom);
  113. ySrcBottom = min(ySrcBottom,ySrcTop+ulBurstSize);
  114. ptlSrc.x = pptlSrc->x;
  115. ptlSrc.y = ySrcTop;
  116. rclDest.left = ulAlign; // make sure buffer is aligned to dst
  117. rclDest.top = 0;
  118. rclDest.right = xRight - xLeft + ulAlign;
  119. rclDest.bottom = ySrcBottom - ySrcTop;
  120. b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc);
  121. yDestBottom = yDestTop + rclDest.bottom;
  122. if (ppdev->rcl1WindowClip.top >= yDestBottom)
  123. {
  124. ppdev->pfnBankControl(ppdev, yDestBottom - 1, JustifyBottom);
  125. pso->pvScan0 = ppdev->pvBitmapStart;
  126. }
  127. while (TRUE)
  128. {
  129. // Copy the temporary buffer into one or more destination
  130. // banks:
  131. LONG yThisTop;
  132. LONG yThisBottom;
  133. LONG yOffset;
  134. yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom);
  135. yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top);
  136. yOffset = yThisTop - yDestTop;
  137. ptlSrc.x = ulAlign;
  138. ptlSrc.y = yOffset;
  139. rclDest.left = xLeft;
  140. rclDest.top = yThisTop;
  141. rclDest.right = xRight;
  142. rclDest.bottom = yThisBottom;
  143. b &= EngCopyBits(pso, psoTmp, pco, pxlo, &rclDest, &ptlSrc);
  144. if (yOffset == 0)
  145. break;
  146. if (ppdev->rcl1WindowClip.top >= yThisTop)
  147. {
  148. ppdev->pfnBankControl(ppdev, yThisTop - 1, JustifyBottom);
  149. pso->pvScan0 = ppdev->pvBitmapStart;
  150. }
  151. }
  152. if (ySrcBottom >= ySrcLast)
  153. break;
  154. yDestTop = yDestBottom;
  155. ySrcTop = ySrcBottom;
  156. if (ySrcTop >= ppdev->rcl1WindowClip.bottom)
  157. {
  158. ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop);
  159. pso->pvScan0 = ppdev->pvBitmapStart;
  160. }
  161. }
  162. }
  163. else
  164. {
  165. ////////////////////////////////////////////////////////////////
  166. // Do a bottom-to-top copy:
  167. ////////////////////////////////////////////////////////////////
  168. LONG ySrcTop;
  169. LONG yDestTop;
  170. LONG yDestBottom = prclDest->bottom;
  171. LONG ySrcFirst = pptlSrc->y;
  172. LONG ySrcBottom = ySrcFirst + (prclDest->bottom - prclDest->top);
  173. if (ySrcBottom <= ppdev->rcl1WindowClip.top ||
  174. ySrcBottom > ppdev->rcl1WindowClip.bottom)
  175. {
  176. ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom);
  177. }
  178. pso->pvScan0 = ppdev->pvBitmapStart;
  179. while (TRUE)
  180. {
  181. // Copy some scans into the temporary buffer:
  182. ySrcTop = max(ySrcFirst, ppdev->rcl1WindowClip.top);
  183. ySrcTop = max(ySrcTop,ySrcBottom-ulBurstSize);
  184. ptlSrc.x = pptlSrc->x;
  185. ptlSrc.y = ySrcTop;
  186. rclDest.left = ulAlign;
  187. rclDest.top = 0;
  188. rclDest.right = xRight - xLeft + ulAlign;
  189. rclDest.bottom = ySrcBottom - ySrcTop;
  190. b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc);
  191. yDestTop = yDestBottom - rclDest.bottom;
  192. if (ppdev->rcl1WindowClip.bottom <= yDestTop)
  193. {
  194. ppdev->pfnBankControl(ppdev, yDestTop, JustifyTop);
  195. pso->pvScan0 = ppdev->pvBitmapStart;
  196. }
  197. while (TRUE)
  198. {
  199. // Copy the temporary buffer into one or more destination
  200. // banks:
  201. LONG yThisTop;
  202. LONG yThisBottom;
  203. LONG yOffset;
  204. yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top);
  205. yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom);
  206. yOffset = yThisTop - yDestTop;
  207. ptlSrc.x = ulAlign;
  208. ptlSrc.y = yOffset;
  209. rclDest.left = xLeft;
  210. rclDest.top = yThisTop;
  211. rclDest.right = xRight;
  212. rclDest.bottom = yThisBottom;
  213. b &= EngCopyBits(pso, psoTmp, pco, pxlo, &rclDest, &ptlSrc);
  214. if (yThisBottom == yDestBottom)
  215. break;
  216. if (ppdev->rcl1WindowClip.bottom <= yThisBottom)
  217. {
  218. ppdev->pfnBankControl(ppdev, yThisBottom, JustifyTop);
  219. pso->pvScan0 = ppdev->pvBitmapStart;
  220. }
  221. }
  222. if (ySrcTop <= ySrcFirst)
  223. break;
  224. yDestBottom = yDestTop;
  225. ySrcBottom = ySrcTop;
  226. if (ppdev->rcl1WindowClip.top >= ySrcBottom)
  227. {
  228. ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom);
  229. pso->pvScan0 = ppdev->pvBitmapStart;
  230. }
  231. }
  232. }
  233. // restore initial values to pso
  234. ppdev->psoTmp->pvScan0 = savedpvScan0;
  235. ppdev->psoTmp->lDelta = savedlDelta;
  236. ppdev->psoTmp->fjBitmap = savedfjBitmap;
  237. return(b);
  238. }
  239. /******************************Public*Routine******************************\
  240. * BOOL bPuntScreenToScreenBitBlt(...)
  241. *
  242. * Performs a screen-to-screen BitBlt entirely using an intermediate temporary
  243. * buffer and GDI.
  244. *
  245. * This function is basically a clone of bPuntScreenToScreenCopyBits,
  246. * except that it can handle funky ROPs and stuff.
  247. \**************************************************************************/
  248. BOOL bPuntScreenToScreenBitBlt(
  249. PPDEV ppdev,
  250. SURFOBJ* psoMask,
  251. CLIPOBJ* pco,
  252. XLATEOBJ* pxlo,
  253. RECTL* prclDest,
  254. POINTL* pptlSrc,
  255. POINTL* pptlMask,
  256. BRUSHOBJ* pbo,
  257. POINTL* pptlBrush,
  258. ROP4 rop4)
  259. {
  260. RECTL rclDest; // Temporary destination rectangle
  261. POINTL ptlSrc; // Temporary source point
  262. POINTL ptlMask; // Temporary mask offset
  263. POINTL ptlMaskAdjust; // Adjustment for mask offset
  264. BOOL b = TRUE;
  265. ULONG ulWidth;
  266. LONG ulBurstSize;
  267. LONG xLeft;
  268. LONG xRight;
  269. SURFOBJ* pso = ppdev->pSurfObj;
  270. SURFOBJ* psoTmp = ppdev->psoTmp;
  271. ULONG ulAlign;
  272. PVOID savedpvScan0 = psoTmp->pvScan0;
  273. LONG savedlDelta = psoTmp->lDelta;
  274. USHORT savedfjBitmap = psoTmp->fjBitmap;
  275. xLeft = prclDest->left;
  276. xRight = prclDest->right;
  277. if (pco && (pco->iDComplexity != DC_TRIVIAL))
  278. {
  279. xLeft = max(xLeft,pco->rclBounds.left);
  280. xRight = min(xRight,pco->rclBounds.right);
  281. }
  282. if (psoMask != NULL)
  283. {
  284. ptlMaskAdjust.x = xLeft - pptlMask->x;
  285. ptlMaskAdjust.y = prclDest->top - pptlMask->y;
  286. }
  287. ulAlign = xLeft & 3;
  288. ulWidth = (((xRight + 3) & ~3) - (xLeft & ~3));
  289. ulBurstSize = min((GLOBAL_BUFFER_SIZE/ulWidth),(ULONG)(prclDest->bottom-prclDest->top));
  290. ASSERTVGA (ulBurstSize > 0, "bPuntScreenToScreenBitBlt ulBurstSize <= 0\n");
  291. // set up pso to use stack memory
  292. psoTmp->pvScan0 = ppdev->pvTmpBuf;
  293. psoTmp->lDelta = ulWidth;
  294. psoTmp->fjBitmap |= BMF_TOPDOWN;
  295. if (prclDest->top < pptlSrc->y)
  296. {
  297. ////////////////////////////////////////////////////////////////
  298. // Do a top-to-bottom copy:
  299. ////////////////////////////////////////////////////////////////
  300. LONG ySrcBottom;
  301. LONG yDestBottom;
  302. LONG yDestTop = prclDest->top;
  303. LONG ySrcTop = pptlSrc->y;
  304. LONG ySrcLast = ySrcTop + (prclDest->bottom - prclDest->top);
  305. if (ySrcTop < ppdev->rcl1WindowClip.top ||
  306. ySrcTop >= ppdev->rcl1WindowClip.bottom)
  307. {
  308. ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop);
  309. }
  310. pso->pvScan0 = ppdev->pvBitmapStart;
  311. while (TRUE)
  312. {
  313. // Copy some scans into the temporary buffer:
  314. ySrcBottom = min(ySrcLast, ppdev->rcl1WindowClip.bottom);
  315. ySrcBottom = min(ySrcBottom,ySrcTop+ulBurstSize);
  316. ptlSrc.x = pptlSrc->x;
  317. ptlSrc.y = ySrcTop;
  318. rclDest.left = ulAlign;
  319. rclDest.top = 0;
  320. rclDest.right = xRight - xLeft + ulAlign;
  321. rclDest.bottom = ySrcBottom - ySrcTop;
  322. b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc);
  323. yDestBottom = yDestTop + rclDest.bottom;
  324. if (ppdev->rcl1WindowClip.top >= yDestBottom)
  325. {
  326. ppdev->pfnBankControl(ppdev, yDestBottom - 1, JustifyBottom);
  327. pso->pvScan0 = ppdev->pvBitmapStart;
  328. }
  329. while (TRUE)
  330. {
  331. // Copy the temporary buffer into one or more destination
  332. // banks:
  333. LONG yThisTop;
  334. LONG yThisBottom;
  335. LONG yOffset;
  336. yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom);
  337. yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top);
  338. yOffset = yThisTop - yDestTop;
  339. ptlSrc.x = ulAlign;
  340. ptlSrc.y = yOffset;
  341. rclDest.left = xLeft;
  342. rclDest.top = yThisTop;
  343. rclDest.right = xRight;
  344. rclDest.bottom = yThisBottom;
  345. ptlMask.x = rclDest.left - ptlMaskAdjust.x;
  346. ptlMask.y = rclDest.top - ptlMaskAdjust.y;
  347. b &= EngBitBlt(pso, psoTmp, psoMask, pco, pxlo, &rclDest,
  348. &ptlSrc, &ptlMask, pbo, pptlBrush, rop4);
  349. if (yOffset == 0)
  350. break;
  351. if (ppdev->rcl1WindowClip.top >= yThisTop)
  352. {
  353. ppdev->pfnBankControl(ppdev, yThisTop - 1, JustifyBottom);
  354. pso->pvScan0 = ppdev->pvBitmapStart;
  355. }
  356. }
  357. if (ySrcBottom >= ySrcLast)
  358. break;
  359. yDestTop = yDestBottom;
  360. ySrcTop = ySrcBottom;
  361. if (ySrcTop >= ppdev->rcl1WindowClip.bottom)
  362. {
  363. ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop);
  364. pso->pvScan0 = ppdev->pvBitmapStart;
  365. }
  366. }
  367. }
  368. else
  369. {
  370. ////////////////////////////////////////////////////////////////
  371. // Do a bottom-to-top copy:
  372. ////////////////////////////////////////////////////////////////
  373. LONG ySrcTop;
  374. LONG yDestTop;
  375. LONG yDestBottom = prclDest->bottom;
  376. LONG ySrcFirst = pptlSrc->y;
  377. LONG ySrcBottom = ySrcFirst + (prclDest->bottom - prclDest->top);
  378. if (ySrcBottom <= ppdev->rcl1WindowClip.top ||
  379. ySrcBottom > ppdev->rcl1WindowClip.bottom)
  380. {
  381. ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom);
  382. }
  383. pso->pvScan0 = ppdev->pvBitmapStart;
  384. while (TRUE)
  385. {
  386. // Copy some scans into the temporary buffer:
  387. ySrcTop = max(ySrcFirst, ppdev->rcl1WindowClip.top);
  388. ySrcTop = max(ySrcTop,ySrcBottom-ulBurstSize);
  389. ptlSrc.x = pptlSrc->x;
  390. ptlSrc.y = ySrcTop;
  391. rclDest.left = ulAlign;
  392. rclDest.top = 0;
  393. rclDest.right = xRight - xLeft + ulAlign;
  394. rclDest.bottom = ySrcBottom - ySrcTop;
  395. b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc);
  396. yDestTop = yDestBottom - rclDest.bottom;
  397. if (ppdev->rcl1WindowClip.bottom <= yDestTop)
  398. {
  399. ppdev->pfnBankControl(ppdev, yDestTop, JustifyTop);
  400. pso->pvScan0 = ppdev->pvBitmapStart;
  401. }
  402. while (TRUE)
  403. {
  404. // Copy the temporary buffer into one or more destination
  405. // banks:
  406. LONG yThisTop;
  407. LONG yThisBottom;
  408. LONG yOffset;
  409. yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top);
  410. yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom);
  411. yOffset = yThisTop - yDestTop;
  412. ptlSrc.x = ulAlign;
  413. ptlSrc.y = yOffset;
  414. rclDest.left = xLeft;
  415. rclDest.top = yThisTop;
  416. rclDest.right = xRight;
  417. rclDest.bottom = yThisBottom;
  418. ptlMask.x = rclDest.left - ptlMaskAdjust.x;
  419. ptlMask.y = rclDest.top - ptlMaskAdjust.y;
  420. b &= EngBitBlt(pso, psoTmp, psoMask, pco, pxlo, &rclDest,
  421. &ptlSrc, &ptlMask, pbo, pptlBrush, rop4);
  422. if (yThisBottom == yDestBottom)
  423. break;
  424. if (ppdev->rcl1WindowClip.bottom <= yThisBottom)
  425. {
  426. ppdev->pfnBankControl(ppdev, yThisBottom, JustifyTop);
  427. pso->pvScan0 = ppdev->pvBitmapStart;
  428. }
  429. }
  430. if (ySrcTop <= ySrcFirst)
  431. break;
  432. yDestBottom = yDestTop;
  433. ySrcBottom = ySrcTop;
  434. if (ppdev->rcl1WindowClip.top >= ySrcBottom)
  435. {
  436. ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom);
  437. pso->pvScan0 = ppdev->pvBitmapStart;
  438. }
  439. }
  440. }
  441. // restore initial values to pso
  442. ppdev->psoTmp->pvScan0 = savedpvScan0;
  443. ppdev->psoTmp->lDelta = savedlDelta;
  444. ppdev->psoTmp->fjBitmap = savedfjBitmap;
  445. return(b);
  446. }
  447. /******************************Public*Data*********************************\
  448. * ROP to mix translation table
  449. *
  450. * Table to translate ternary raster ops to mixes (binary raster ops). Ternary
  451. * raster ops that can't be translated to mixes are translated to 0 (0 is not
  452. * a valid mix).
  453. *
  454. \**************************************************************************/
  455. UCHAR jRop3ToMix[256] = {
  456. R2_BLACK, 0, 0, 0, 0, R2_NOTMERGEPEN, 0, 0,
  457. 0, 0, R2_MASKNOTPEN, 0, 0, 0, 0, R2_NOTCOPYPEN,
  458. 0, 0, 0, 0, 0, 0, 0, 0,
  459. 0, 0, 0, 0, 0, 0, 0, 0,
  460. 0, 0, 0, 0, 0, 0, 0, 0,
  461. 0, 0, 0, 0, 0, 0, 0, 0,
  462. 0, 0, 0, 0, 0, 0, 0, 0,
  463. 0, 0, 0, 0, 0, 0, 0, 0,
  464. 0, 0, 0, 0, 0, 0, 0, 0,
  465. 0, 0, 0, 0, 0, 0, 0, 0,
  466. R2_MASKPENNOT, 0, 0, 0, 0, R2_NOT, 0, 0,
  467. 0, 0, R2_XORPEN, 0, 0, 0, 0, R2_NOTMASKPEN,
  468. 0, 0, 0, 0, 0, 0, 0, 0,
  469. 0, 0, 0, 0, 0, 0, 0, 0,
  470. 0, 0, 0, 0, 0, 0, 0, 0,
  471. 0, 0, 0, 0, 0, 0, 0, 0,
  472. 0, 0, 0, 0, 0, 0, 0, 0,
  473. 0, 0, 0, 0, 0, 0, 0, 0,
  474. 0, 0, 0, 0, 0, 0, 0, 0,
  475. 0, 0, 0, 0, 0, 0, 0, 0,
  476. R2_MASKPEN, 0, 0, 0, 0, R2_NOTXORPEN, 0, 0,
  477. 0, 0, R2_NOP, 0, 0, 0, 0, R2_MERGENOTPEN,
  478. 0, 0, 0, 0, 0, 0, 0, 0,
  479. 0, 0, 0, 0, 0, 0, 0, 0,
  480. 0, 0, 0, 0, 0, 0, 0, 0,
  481. 0, 0, 0, 0, 0, 0, 0, 0,
  482. 0, 0, 0, 0, 0, 0, 0, 0,
  483. 0, 0, 0, 0, 0, 0, 0, 0,
  484. 0, 0, 0, 0, 0, 0, 0, 0,
  485. 0, 0, 0, 0, 0, 0, 0, 0,
  486. R2_COPYPEN, 0, 0, 0, 0, R2_MERGEPENNOT, 0, 0,
  487. 0, 0, R2_MERGEPEN, 0, 0, 0, 0, R2_WHITE
  488. };
  489. /******************************Public*Routine******************************\
  490. * BOOL DrvBitBlt(psoDest, psoSrc, psoMask, pco, pxlo, prclDest, pptlSrc,
  491. * pptlMask, pbo, pptlBrush, rop4)
  492. *
  493. * This routine will handle any blit. Perhaps glacially, but it will be
  494. * handled.
  495. \**************************************************************************/
  496. BOOL DrvBitBlt(
  497. SURFOBJ* psoDest,
  498. SURFOBJ* psoSrc,
  499. SURFOBJ* psoMask,
  500. CLIPOBJ* pco,
  501. XLATEOBJ* pxlo,
  502. RECTL* prclDest,
  503. POINTL* pptlSrc,
  504. POINTL* pptlMask,
  505. BRUSHOBJ* pbo,
  506. POINTL* pptlBrush,
  507. ROP4 rop4)
  508. {
  509. BOOL b;
  510. POINTL ptlSrc;
  511. RECTL rclDest;
  512. PPDEV ppdev;
  513. SURFOBJ* pso;
  514. MIX mix; // Mix, when solid fill performed
  515. BYTE jClipping;
  516. RECTL rclTmp;
  517. POINTL ptlTmp;
  518. BBENUM bben; // Clip enumerator
  519. BOOL bMore; // Clip continuation flag
  520. POINTL ptlMask; // Temporary mask for engine call-backs
  521. POINTL ptlMaskAdjust; // Adjustment for mask
  522. INT iCopyDir;
  523. RBRUSH_COLOR rbc; // Pointer to RBRUSH or iSolidColor value
  524. PFNFILL pfnFill = vTrgBlt; // Pointer to appropriate fill routine
  525. // (solid color by default)
  526. DISPDBG((3, "DrvBitBlt: Entering."));
  527. // Set up the clipping type
  528. if (pco == (CLIPOBJ *) NULL) {
  529. // No CLIPOBJ provided, so we don't have to worry about clipping
  530. jClipping = DC_TRIVIAL;
  531. } else {
  532. // Use the CLIPOBJ-provided clipping
  533. jClipping = pco->iDComplexity;
  534. }
  535. // Handle solid fills to the VGA surface with special-case code if planar
  536. // mode is supported.
  537. // LATER handle non-planar also
  538. if (psoDest->iType == STYPE_DEVICE) {
  539. // Destination is the VGA surface
  540. // Masked cases must be handled differently
  541. if ((((PPDEV) psoDest->dhsurf)->fl & DRIVER_PLANAR_CAPABLE) &&
  542. ((rop4 & 0xFF) == ((rop4 >> 8) & 0xFF))) {
  543. // Special-case static code for no-mask cases
  544. // Calculate mix from ROP if possible (not possible if it's truly a
  545. // ternary rop or a real rop4, but we can treat all pure binary
  546. // rops as mixes rather than rop4s)
  547. mix = jRop3ToMix[rop4 & 0xFF];
  548. switch (mix) {
  549. case R2_MASKNOTPEN:
  550. case R2_NOTCOPYPEN:
  551. case R2_XORPEN:
  552. case R2_MASKPEN:
  553. case R2_NOTXORPEN:
  554. case R2_MERGENOTPEN:
  555. case R2_COPYPEN:
  556. case R2_MERGEPEN:
  557. case R2_NOTMERGEPEN:
  558. case R2_MASKPENNOT:
  559. case R2_NOTMASKPEN:
  560. case R2_MERGEPENNOT:
  561. // vTrgBlt can only handle solid color fills
  562. if (pbo->iSolidColor != 0xffffffff)
  563. {
  564. rbc.iSolidColor = pbo->iSolidColor;
  565. }
  566. else
  567. {
  568. rbc.prb = (RBRUSH*) pbo->pvRbrush;
  569. if (rbc.prb == NULL)
  570. {
  571. rbc.prb = (RBRUSH*) BRUSHOBJ_pvGetRbrush(pbo);
  572. if (rbc.prb == NULL)
  573. {
  574. // If we haven't realized the brush, punt the call
  575. // to the engine:
  576. break;
  577. }
  578. }
  579. if (!(rbc.prb->fl & RBRUSH_BLACKWHITE) &&
  580. (mix != R2_COPYPEN))
  581. {
  582. // Only black/white brushes can handle ROPs other
  583. // than COPYPEN:
  584. break;
  585. }
  586. if (rbc.prb->fl & RBRUSH_NCOLOR)
  587. pfnFill = vColorPat;
  588. else
  589. pfnFill = vMonoPat;
  590. }
  591. // Rops that are implicit solid colors
  592. case R2_NOT:
  593. case R2_WHITE:
  594. case R2_BLACK:
  595. // We can do a special-case solid fill
  596. switch(jClipping) {
  597. case DC_TRIVIAL:
  598. // Just fill the rectangle:
  599. (*pfnFill)((PPDEV) psoDest->dhsurf, 1,
  600. prclDest, mix, rbc, pptlBrush);
  601. break;
  602. case DC_RECT:
  603. // Clip the solid fill to the clip rectangle
  604. if (!bIntersectRect(&rclTmp, prclDest,
  605. &pco->rclBounds))
  606. return(TRUE);
  607. // Fill the clipped rectangle
  608. (*pfnFill)((PPDEV) psoDest->dhsurf, 1,
  609. &rclTmp, mix, rbc, pptlBrush);
  610. break;
  611. case DC_COMPLEX:
  612. ppdev = (PPDEV) psoDest->dhsurf;
  613. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
  614. CD_ANY, BB_RECT_LIMIT);
  615. do {
  616. bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben),
  617. (PVOID) &bben);
  618. if (bben.c > 0)
  619. {
  620. RECTL* prclEnd = &bben.arcl[bben.c];
  621. RECTL* prcl = &bben.arcl[0];
  622. do {
  623. bIntersectRect(prcl, prcl, prclDest);
  624. prcl++;
  625. } while (prcl < prclEnd);
  626. (*pfnFill)(ppdev, bben.c, bben.arcl,
  627. mix, rbc, pptlBrush);
  628. }
  629. } while(bMore);
  630. }
  631. case R2_NOP:
  632. return(TRUE);
  633. default:
  634. break;
  635. }
  636. }
  637. }
  638. // Get the correct surface object for the target and the source
  639. if (psoDest->iType == STYPE_DEVICE) {
  640. if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE)) {
  641. ////////////////////////////////////////////////////////////////
  642. // BitBlt screen-to-screen:
  643. ////////////////////////////////////////////////////////////////
  644. ppdev = (PPDEV) psoDest->dhsurf;
  645. // See if we can do a simple CopyBits:
  646. if (rop4 == 0x0000CCCC)
  647. {
  648. ppdev = (PPDEV) psoDest->dhsurf;
  649. // We can handle quadpixel-aligned screen-to-screen blts with
  650. // no translation:
  651. if ((((pptlSrc->x ^ prclDest->left) & 3) == 0) &&
  652. (ppdev->fl & DRIVER_PLANAR_CAPABLE) &&
  653. ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
  654. {
  655. switch(jClipping)
  656. {
  657. case DC_TRIVIAL:
  658. vPlanarCopyBits(ppdev, prclDest, pptlSrc);
  659. return(TRUE);
  660. case DC_RECT:
  661. // Clip the target rectangle to the clip rectangle:
  662. if (!bIntersectRect(&rclTmp, prclDest, &pco->rclBounds))
  663. {
  664. DISPDBG((0, "DrvBitBlt: Nothing to draw."));
  665. return(TRUE);
  666. }
  667. ptlTmp.x = pptlSrc->x + rclTmp.left - prclDest->left;
  668. ptlTmp.y = pptlSrc->y + rclTmp.top - prclDest->top;
  669. vPlanarCopyBits(ppdev, &rclTmp, &ptlTmp);
  670. return(TRUE);
  671. case DC_COMPLEX:
  672. if (pptlSrc->y >= prclDest->top)
  673. {
  674. if (pptlSrc->x >= prclDest->left)
  675. iCopyDir = CD_RIGHTDOWN;
  676. else
  677. iCopyDir = CD_LEFTDOWN;
  678. }
  679. else
  680. {
  681. if (pptlSrc->x >= prclDest->left)
  682. iCopyDir = CD_RIGHTUP;
  683. else
  684. iCopyDir = CD_LEFTUP;
  685. }
  686. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iCopyDir, 0);
  687. do {
  688. RECTL* prcl;
  689. RECTL* prclEnd;
  690. bMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(bben),
  691. (PVOID) &bben);
  692. prclEnd = &bben.arcl[bben.c];
  693. for (prcl = bben.arcl; prcl < prclEnd; prcl++)
  694. {
  695. if (bIntersectRect(prcl, prclDest, prcl))
  696. {
  697. ptlTmp.x = pptlSrc->x + prcl->left - prclDest->left;
  698. ptlTmp.y = pptlSrc->y + prcl->top - prclDest->top;
  699. vPlanarCopyBits(ppdev, prcl, &ptlTmp);
  700. }
  701. }
  702. } while (bMore);
  703. return(TRUE);
  704. }
  705. }
  706. // Can't handle in hardware, so punt:
  707. return(bPuntScreenToScreenCopyBits(ppdev,
  708. pco,
  709. pxlo,
  710. prclDest,
  711. pptlSrc));
  712. }
  713. // It's more complicated than a CopyBits, so punt it:
  714. return(bPuntScreenToScreenBitBlt(ppdev,
  715. psoMask,
  716. pco,
  717. pxlo,
  718. prclDest,
  719. pptlSrc,
  720. pptlMask,
  721. pbo,
  722. pptlBrush,
  723. rop4));
  724. }
  725. ////////////////////////////////////////////////////////////////
  726. // BitBlt to screen:
  727. ////////////////////////////////////////////////////////////////
  728. ppdev = (PPDEV) psoDest->dhsurf;
  729. if ((rop4 == 0x0000CCCC) &&
  730. (psoSrc->iBitmapFormat == BMF_8BPP) &&
  731. ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
  732. {
  733. // We have special code for the common 8bpp from memory to screen
  734. // with no ROPs:
  735. switch(jClipping)
  736. {
  737. case DC_TRIVIAL:
  738. vSrcCopy8bpp(ppdev, prclDest, pptlSrc,
  739. psoSrc->lDelta, psoSrc->pvScan0);
  740. return(TRUE);
  741. case DC_RECT:
  742. // Clip the blt to the clip rectangle
  743. if(bIntersectRect(&rclTmp, prclDest, &pco->rclBounds)){
  744. ptlTmp.x = pptlSrc->x + rclTmp.left - prclDest->left;
  745. ptlTmp.y = pptlSrc->y + rclTmp.top - prclDest->top;
  746. vSrcCopy8bpp(ppdev, &rclTmp, &ptlTmp,
  747. psoSrc->lDelta, psoSrc->pvScan0);
  748. }
  749. return(TRUE);
  750. case DC_COMPLEX:
  751. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
  752. CD_ANY, BB_RECT_LIMIT);
  753. do {
  754. bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben),
  755. (PVOID) &bben);
  756. if (bben.c > 0)
  757. {
  758. RECTL* prclEnd = &bben.arcl[bben.c];
  759. RECTL* prcl = &bben.arcl[0];
  760. do {
  761. if (bIntersectRect(prcl, prcl, prclDest)){
  762. ptlTmp.x = pptlSrc->x + prcl->left
  763. - prclDest->left;
  764. ptlTmp.y = pptlSrc->y + prcl->top
  765. - prclDest->top;
  766. vSrcCopy8bpp(ppdev, prcl, &ptlTmp,
  767. psoSrc->lDelta, psoSrc->pvScan0);
  768. }
  769. prcl++;
  770. } while (prcl < prclEnd);
  771. }
  772. } while(bMore);
  773. return(TRUE);
  774. }
  775. }
  776. // Punt the memory-to-screen call back to the engine:
  777. if (psoMask != NULL)
  778. {
  779. ptlMaskAdjust.x = prclDest->left - pptlMask->x;
  780. ptlMaskAdjust.y = prclDest->top - pptlMask->y;
  781. }
  782. pso = ppdev->pSurfObj;
  783. vBankStartBltDest(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest);
  784. do {
  785. ptlMask.x = rclDest.left - ptlMaskAdjust.x;
  786. ptlMask.y = rclDest.top - ptlMaskAdjust.y;
  787. b = EngBitBlt(pso,
  788. psoSrc,
  789. psoMask,
  790. pco,
  791. pxlo,
  792. &rclDest,
  793. &ptlSrc,
  794. &ptlMask,
  795. pbo,
  796. pptlBrush,
  797. rop4);
  798. } while (b && bBankEnumBltDest(ppdev, pso, pptlSrc, prclDest,
  799. &ptlSrc, &rclDest));
  800. return(b);
  801. }
  802. else if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE))
  803. {
  804. ////////////////////////////////////////////////////////////////
  805. // BitBlt from screen:
  806. ////////////////////////////////////////////////////////////////
  807. if (psoMask != NULL)
  808. {
  809. ptlMaskAdjust.x = prclDest->left - pptlMask->x;
  810. ptlMaskAdjust.y = prclDest->top - pptlMask->y;
  811. }
  812. ppdev = (PPDEV) psoSrc->dhsurf;
  813. pso = ppdev->pSurfObj;
  814. vBankStartBltSrc(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest);
  815. do {
  816. ptlMask.x = rclDest.left - ptlMaskAdjust.x;
  817. ptlMask.y = rclDest.top - ptlMaskAdjust.y;
  818. b = EngBitBlt(psoDest,
  819. pso,
  820. psoMask,
  821. pco,
  822. pxlo,
  823. &rclDest,
  824. &ptlSrc,
  825. &ptlMask,
  826. pbo,
  827. pptlBrush,
  828. rop4);
  829. } while (b && bBankEnumBltSrc(ppdev, pso, pptlSrc, prclDest,
  830. &ptlSrc, &rclDest));
  831. return(b);
  832. }
  833. RIP("Got a funky format?");
  834. return(FALSE);
  835. }
  836. /***************************************************************************\
  837. * DrvCopyBits
  838. \***************************************************************************/
  839. BOOL DrvCopyBits(
  840. SURFOBJ* psoDest,
  841. SURFOBJ* psoSrc,
  842. CLIPOBJ* pco,
  843. XLATEOBJ* pxlo,
  844. RECTL* prclDest,
  845. POINTL* pptlSrc)
  846. {
  847. BOOL b;
  848. POINTL ptlSrc;
  849. RECTL rclDest;
  850. PPDEV ppdev;
  851. SURFOBJ* pso;
  852. BBENUM bben;
  853. BOOL bMore;
  854. BYTE jClipping;
  855. POINTL ptlTmp;
  856. RECTL rclTmp;
  857. INT iCopyDir;
  858. // Get the correct surface object for the target and the source
  859. if (psoDest->iType == STYPE_DEVICE)
  860. {
  861. // We have to special case screen-to-screen operations:
  862. if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE))
  863. {
  864. ////////////////////////////////////////////////////////////////
  865. // CopyBits screen-to-screen:
  866. ////////////////////////////////////////////////////////////////
  867. ppdev = (PPDEV) psoDest->dhsurf;
  868. // We check to see if we can do a planar copy, because usually
  869. // it will be faster. But the hardware has to be capable of
  870. // doing it, and the source and destination must be 4-pel
  871. // aligned.
  872. if ((((pptlSrc->x ^ prclDest->left) & 3) == 0) &&
  873. (ppdev->fl & DRIVER_PLANAR_CAPABLE) &&
  874. ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
  875. {
  876. jClipping = (pco != NULL) ? pco->iDComplexity : DC_TRIVIAL;
  877. switch(jClipping)
  878. {
  879. case DC_TRIVIAL:
  880. vPlanarCopyBits(ppdev, prclDest, pptlSrc);
  881. return(TRUE);
  882. case DC_RECT:
  883. // Clip the target rectangle to the clip rectangle:
  884. if (!bIntersectRect(&rclTmp, prclDest, &pco->rclBounds))
  885. {
  886. DISPDBG((0, "DrvCopyBits: Nothing to draw."));
  887. return(TRUE);
  888. }
  889. ptlTmp.x = pptlSrc->x + rclTmp.left - prclDest->left;
  890. ptlTmp.y = pptlSrc->y + rclTmp.top - prclDest->top;
  891. vPlanarCopyBits(ppdev, &rclTmp, &ptlTmp);
  892. return(TRUE);
  893. case DC_COMPLEX:
  894. if (pptlSrc->y >= prclDest->top)
  895. {
  896. if (pptlSrc->x >= prclDest->left)
  897. iCopyDir = CD_RIGHTDOWN;
  898. else
  899. iCopyDir = CD_LEFTDOWN;
  900. }
  901. else
  902. {
  903. if (pptlSrc->x >= prclDest->left)
  904. iCopyDir = CD_RIGHTUP;
  905. else
  906. iCopyDir = CD_LEFTUP;
  907. }
  908. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iCopyDir, 0);
  909. do {
  910. RECTL* prcl;
  911. RECTL* prclEnd;
  912. bMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(bben),
  913. (PVOID) &bben);
  914. prclEnd = &bben.arcl[bben.c];
  915. for (prcl = bben.arcl; prcl < prclEnd; prcl++)
  916. {
  917. if (bIntersectRect(prcl, prclDest, prcl))
  918. {
  919. ptlTmp.x = pptlSrc->x + prcl->left - prclDest->left;
  920. ptlTmp.y = pptlSrc->y + prcl->top - prclDest->top;
  921. vPlanarCopyBits(ppdev, prcl, &ptlTmp);
  922. }
  923. }
  924. } while (bMore);
  925. return(TRUE);
  926. }
  927. }
  928. return(bPuntScreenToScreenCopyBits(ppdev,
  929. pco,
  930. pxlo,
  931. prclDest,
  932. pptlSrc));
  933. }
  934. ////////////////////////////////////////////////////////////////
  935. // CopyBits to screen:
  936. ////////////////////////////////////////////////////////////////
  937. ppdev = (PPDEV) psoDest->dhsurf;
  938. if ((psoSrc->iBitmapFormat == BMF_8BPP) &&
  939. ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
  940. {
  941. // We have special code for the common 8bpp from memory to screen
  942. // with no ROPs:
  943. jClipping = (pco != NULL) ? pco->iDComplexity : DC_TRIVIAL;
  944. switch(jClipping)
  945. {
  946. case DC_TRIVIAL:
  947. vSrcCopy8bpp(ppdev, prclDest, pptlSrc,
  948. psoSrc->lDelta, psoSrc->pvScan0);
  949. return(TRUE);
  950. case DC_RECT:
  951. // Clip the blt to the clip rectangle
  952. if( bIntersectRect(&rclTmp, prclDest, &pco->rclBounds)){
  953. ptlTmp.x = pptlSrc->x + rclTmp.left - prclDest->left;
  954. ptlTmp.y = pptlSrc->y + rclTmp.top - prclDest->top;
  955. vSrcCopy8bpp(ppdev, &rclTmp, &ptlTmp,
  956. psoSrc->lDelta, psoSrc->pvScan0);
  957. }
  958. return(TRUE);
  959. case DC_COMPLEX:
  960. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
  961. CD_ANY, BB_RECT_LIMIT);
  962. do {
  963. bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben),
  964. (PVOID) &bben);
  965. if (bben.c > 0)
  966. {
  967. RECTL* prclEnd = &bben.arcl[bben.c];
  968. RECTL* prcl = &bben.arcl[0];
  969. do {
  970. ASSERTVGA((prcl->bottom - prcl->top) > 0,
  971. "DrvCopyBits: enum rect height <= 0\n");
  972. ASSERTVGA((prcl->right - prcl->left) > 0,
  973. "DrvCopyBits: enum rect width <= 0\n");
  974. if(bIntersectRect(prcl, prcl, prclDest)){
  975. ptlTmp.x = pptlSrc->x + prcl->left
  976. - prclDest->left;
  977. ptlTmp.y = pptlSrc->y + prcl->top
  978. - prclDest->top;
  979. vSrcCopy8bpp(ppdev, prcl, &ptlTmp,
  980. psoSrc->lDelta, psoSrc->pvScan0);
  981. }
  982. prcl++;
  983. } while (prcl < prclEnd);
  984. }
  985. } while(bMore);
  986. return(TRUE);
  987. }
  988. }
  989. // Fall back to the engine:
  990. pso = ppdev->pSurfObj;
  991. vBankStartBltDest(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest);
  992. do {
  993. b = EngCopyBits(pso,
  994. psoSrc,
  995. pco,
  996. pxlo,
  997. &rclDest,
  998. &ptlSrc);
  999. } while (b && bBankEnumBltDest(ppdev, pso, pptlSrc, prclDest,
  1000. &ptlSrc, &rclDest));
  1001. return(b);
  1002. }
  1003. else if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE))
  1004. {
  1005. ////////////////////////////////////////////////////////////////
  1006. // CopyBits from screen:
  1007. ////////////////////////////////////////////////////////////////
  1008. ppdev = (PPDEV) psoSrc->dhsurf;
  1009. pso = ppdev->pSurfObj;
  1010. vBankStartBltSrc(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest);
  1011. do {
  1012. b = EngCopyBits(psoDest,
  1013. pso,
  1014. pco,
  1015. pxlo,
  1016. &rclDest,
  1017. &ptlSrc);
  1018. } while (b && bBankEnumBltSrc(ppdev, pso, pptlSrc, prclDest,
  1019. &ptlSrc, &rclDest));
  1020. return(b);
  1021. }
  1022. /* we should never be here */
  1023. return FALSE;
  1024. }
  1025.