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.

928 lines
30 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. SURFOBJ* pso = ppdev->pSurfObj;
  69. SURFOBJ* psoTmp = ppdev->psoTmp;
  70. if (prclDest->top < pptlSrc->y)
  71. {
  72. ////////////////////////////////////////////////////////////////
  73. // Do a top-to-bottom copy:
  74. ////////////////////////////////////////////////////////////////
  75. LONG ySrcBottom;
  76. LONG yDestBottom;
  77. LONG yDestTop = prclDest->top;
  78. LONG ySrcTop = pptlSrc->y;
  79. LONG ySrcLast = ySrcTop + (prclDest->bottom - prclDest->top);
  80. if (ySrcTop < ppdev->rcl1WindowClip.top ||
  81. ySrcTop >= ppdev->rcl1WindowClip.bottom)
  82. {
  83. ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop);
  84. }
  85. pso->pvScan0 = ppdev->pvBitmapStart;
  86. while (TRUE)
  87. {
  88. // Copy an entire source bank into the temporary buffer:
  89. ySrcBottom = min(ySrcLast, ppdev->rcl1WindowClip.bottom);
  90. ptlSrc.x = pptlSrc->x;
  91. ptlSrc.y = ySrcTop;
  92. rclDest.left = prclDest->left;
  93. rclDest.top = 0;
  94. rclDest.right = prclDest->right;
  95. rclDest.bottom = ySrcBottom - ySrcTop;
  96. b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc);
  97. yDestBottom = yDestTop + rclDest.bottom;
  98. if (ppdev->rcl1WindowClip.top >= yDestBottom)
  99. {
  100. ppdev->pfnBankControl(ppdev, yDestBottom - 1, JustifyBottom);
  101. pso->pvScan0 = ppdev->pvBitmapStart;
  102. }
  103. while (TRUE)
  104. {
  105. // Copy the temporary buffer into one or more destination
  106. // banks:
  107. LONG yThisTop;
  108. LONG yThisBottom;
  109. LONG yOffset;
  110. yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom);
  111. yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top);
  112. yOffset = yThisTop - yDestTop;
  113. ptlSrc.x = prclDest->left;
  114. ptlSrc.y = yOffset;
  115. rclDest.left = prclDest->left;
  116. rclDest.top = yThisTop;
  117. rclDest.right = prclDest->right;
  118. rclDest.bottom = yThisBottom;
  119. b &= EngCopyBits(pso, psoTmp, pco, pxlo, &rclDest, &ptlSrc);
  120. if (yOffset == 0)
  121. break;
  122. ppdev->pfnBankControl(ppdev, yThisTop - 1, JustifyBottom);
  123. pso->pvScan0 = ppdev->pvBitmapStart;
  124. }
  125. if (ySrcBottom >= ySrcLast)
  126. break;
  127. yDestTop = yDestBottom;
  128. ySrcTop = ySrcBottom;
  129. ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop);
  130. pso->pvScan0 = ppdev->pvBitmapStart;
  131. }
  132. }
  133. else
  134. {
  135. ////////////////////////////////////////////////////////////////
  136. // Do a bottom-to-top copy:
  137. ////////////////////////////////////////////////////////////////
  138. LONG ySrcTop;
  139. LONG yDestTop;
  140. LONG yDestBottom = prclDest->bottom;
  141. LONG ySrcFirst = pptlSrc->y;
  142. LONG ySrcBottom = ySrcFirst + (prclDest->bottom - prclDest->top);
  143. if (ySrcBottom <= ppdev->rcl1WindowClip.top ||
  144. ySrcBottom > ppdev->rcl1WindowClip.bottom)
  145. {
  146. ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom);
  147. }
  148. pso->pvScan0 = ppdev->pvBitmapStart;
  149. while (TRUE)
  150. {
  151. // Copy an entire source bank into the temporary buffer:
  152. ySrcTop = max(ySrcFirst, ppdev->rcl1WindowClip.top);
  153. ptlSrc.x = pptlSrc->x;
  154. ptlSrc.y = ySrcTop;
  155. rclDest.left = prclDest->left;
  156. rclDest.top = 0;
  157. rclDest.right = prclDest->right;
  158. rclDest.bottom = ySrcBottom - ySrcTop;
  159. b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc);
  160. yDestTop = yDestBottom - rclDest.bottom;
  161. if (ppdev->rcl1WindowClip.bottom <= yDestTop)
  162. {
  163. ppdev->pfnBankControl(ppdev, yDestTop, JustifyTop);
  164. pso->pvScan0 = ppdev->pvBitmapStart;
  165. }
  166. while (TRUE)
  167. {
  168. // Copy the temporary buffer into one or more destination
  169. // banks:
  170. LONG yThisTop;
  171. LONG yThisBottom;
  172. LONG yOffset;
  173. yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top);
  174. yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom);
  175. yOffset = yThisTop - yDestTop;
  176. ptlSrc.x = prclDest->left;
  177. ptlSrc.y = yOffset;
  178. rclDest.left = prclDest->left;
  179. rclDest.top = yThisTop;
  180. rclDest.right = prclDest->right;
  181. rclDest.bottom = yThisBottom;
  182. b &= EngCopyBits(pso, psoTmp, pco, pxlo, &rclDest, &ptlSrc);
  183. if (yThisBottom == yDestBottom)
  184. break;
  185. ppdev->pfnBankControl(ppdev, yThisBottom, JustifyTop);
  186. pso->pvScan0 = ppdev->pvBitmapStart;
  187. }
  188. if (ySrcTop <= ySrcFirst)
  189. break;
  190. yDestBottom = yDestTop;
  191. ySrcBottom = ySrcTop;
  192. ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom);
  193. pso->pvScan0 = ppdev->pvBitmapStart;
  194. }
  195. }
  196. return(b);
  197. }
  198. /******************************Public*Routine******************************\
  199. * BOOL bPuntScreenToScreenBitBlt(...)
  200. *
  201. * Performs a screen-to-screen BitBlt entirely using an intermediate temporary
  202. * buffer and GDI.
  203. *
  204. * This function is basically a clone of bPuntScreenToScreenCopyBits,
  205. * except that it can handle funky ROPs and stuff.
  206. \**************************************************************************/
  207. BOOL bPuntScreenToScreenBitBlt(
  208. PPDEV ppdev,
  209. SURFOBJ* psoMask,
  210. CLIPOBJ* pco,
  211. XLATEOBJ* pxlo,
  212. RECTL* prclDest,
  213. POINTL* pptlSrc,
  214. POINTL* pptlMask,
  215. BRUSHOBJ* pbo,
  216. POINTL* pptlBrush,
  217. ROP4 rop4)
  218. {
  219. RECTL rclDest; // Temporary destination rectangle
  220. POINTL ptlSrc; // Temporary source point
  221. POINTL ptlMask; // Temporary mask offset
  222. POINTL ptlMaskAdjust; // Adjustment for mask offset
  223. BOOL b = TRUE;
  224. SURFOBJ* pso = ppdev->pSurfObj;
  225. SURFOBJ* psoTmp = ppdev->psoTmp;
  226. if (psoMask != NULL)
  227. {
  228. ptlMaskAdjust.x = prclDest->left - pptlMask->x;
  229. ptlMaskAdjust.y = prclDest->top - pptlMask->y;
  230. }
  231. if (prclDest->top < pptlSrc->y)
  232. {
  233. ////////////////////////////////////////////////////////////////
  234. // Do a top-to-bottom copy:
  235. ////////////////////////////////////////////////////////////////
  236. LONG ySrcBottom;
  237. LONG yDestBottom;
  238. LONG yDestTop = prclDest->top;
  239. LONG ySrcTop = pptlSrc->y;
  240. LONG ySrcLast = ySrcTop + (prclDest->bottom - prclDest->top);
  241. if (ySrcTop < ppdev->rcl1WindowClip.top ||
  242. ySrcTop >= ppdev->rcl1WindowClip.bottom)
  243. {
  244. ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop);
  245. }
  246. pso->pvScan0 = ppdev->pvBitmapStart;
  247. while (TRUE)
  248. {
  249. // Copy an entire source bank into the temporary buffer:
  250. ySrcBottom = min(ySrcLast, ppdev->rcl1WindowClip.bottom);
  251. ptlSrc.x = pptlSrc->x;
  252. ptlSrc.y = ySrcTop;
  253. rclDest.left = prclDest->left;
  254. rclDest.top = 0;
  255. rclDest.right = prclDest->right;
  256. rclDest.bottom = ySrcBottom - ySrcTop;
  257. b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc);
  258. yDestBottom = yDestTop + rclDest.bottom;
  259. if (ppdev->rcl1WindowClip.top >= yDestBottom)
  260. {
  261. ppdev->pfnBankControl(ppdev, yDestBottom - 1, JustifyBottom);
  262. pso->pvScan0 = ppdev->pvBitmapStart;
  263. }
  264. while (TRUE)
  265. {
  266. // Copy the temporary buffer into one or more destination
  267. // banks:
  268. LONG yThisTop;
  269. LONG yThisBottom;
  270. LONG yOffset;
  271. yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom);
  272. yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top);
  273. yOffset = yThisTop - yDestTop;
  274. ptlSrc.x = prclDest->left;
  275. ptlSrc.y = yOffset;
  276. rclDest.left = prclDest->left;
  277. rclDest.top = yThisTop;
  278. rclDest.right = prclDest->right;
  279. rclDest.bottom = yThisBottom;
  280. ptlMask.x = rclDest.left - ptlMaskAdjust.x;
  281. ptlMask.y = rclDest.top - ptlMaskAdjust.y;
  282. b &= EngBitBlt(pso, psoTmp, psoMask, pco, pxlo, &rclDest,
  283. &ptlSrc, &ptlMask, pbo, pptlBrush, rop4);
  284. if (yOffset == 0)
  285. break;
  286. ppdev->pfnBankControl(ppdev, yThisTop - 1, JustifyBottom);
  287. pso->pvScan0 = ppdev->pvBitmapStart;
  288. }
  289. if (ySrcBottom >= ySrcLast)
  290. break;
  291. yDestTop = yDestBottom;
  292. ySrcTop = ySrcBottom;
  293. ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop);
  294. pso->pvScan0 = ppdev->pvBitmapStart;
  295. }
  296. }
  297. else
  298. {
  299. ////////////////////////////////////////////////////////////////
  300. // Do a bottom-to-top copy:
  301. ////////////////////////////////////////////////////////////////
  302. LONG ySrcTop;
  303. LONG yDestTop;
  304. LONG yDestBottom = prclDest->bottom;
  305. LONG ySrcFirst = pptlSrc->y;
  306. LONG ySrcBottom = ySrcFirst + (prclDest->bottom - prclDest->top);
  307. if (ySrcBottom <= ppdev->rcl1WindowClip.top ||
  308. ySrcBottom > ppdev->rcl1WindowClip.bottom)
  309. {
  310. ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom);
  311. }
  312. pso->pvScan0 = ppdev->pvBitmapStart;
  313. while (TRUE)
  314. {
  315. // Copy an entire source bank into the temporary buffer:
  316. ySrcTop = max(ySrcFirst, ppdev->rcl1WindowClip.top);
  317. ptlSrc.x = pptlSrc->x;
  318. ptlSrc.y = ySrcTop;
  319. rclDest.left = prclDest->left;
  320. rclDest.top = 0;
  321. rclDest.right = prclDest->right;
  322. rclDest.bottom = ySrcBottom - ySrcTop;
  323. b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc);
  324. yDestTop = yDestBottom - rclDest.bottom;
  325. if (ppdev->rcl1WindowClip.bottom <= yDestTop)
  326. {
  327. ppdev->pfnBankControl(ppdev, yDestTop, JustifyTop);
  328. pso->pvScan0 = ppdev->pvBitmapStart;
  329. }
  330. while (TRUE)
  331. {
  332. // Copy the temporary buffer into one or more destination
  333. // banks:
  334. LONG yThisTop;
  335. LONG yThisBottom;
  336. LONG yOffset;
  337. yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top);
  338. yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom);
  339. yOffset = yThisTop - yDestTop;
  340. ptlSrc.x = prclDest->left;
  341. ptlSrc.y = yOffset;
  342. rclDest.left = prclDest->left;
  343. rclDest.top = yThisTop;
  344. rclDest.right = prclDest->right;
  345. rclDest.bottom = yThisBottom;
  346. ptlMask.x = rclDest.left - ptlMaskAdjust.x;
  347. ptlMask.y = rclDest.top - ptlMaskAdjust.y;
  348. b &= EngBitBlt(pso, psoTmp, psoMask, pco, pxlo, &rclDest,
  349. &ptlSrc, &ptlMask, pbo, pptlBrush, rop4);
  350. if (yThisBottom == yDestBottom)
  351. break;
  352. ppdev->pfnBankControl(ppdev, yThisBottom, JustifyTop);
  353. pso->pvScan0 = ppdev->pvBitmapStart;
  354. }
  355. if (ySrcTop <= ySrcFirst)
  356. break;
  357. yDestBottom = yDestTop;
  358. ySrcBottom = ySrcTop;
  359. ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom);
  360. pso->pvScan0 = ppdev->pvBitmapStart;
  361. }
  362. }
  363. return(b);
  364. }
  365. /******************************Public*Data*********************************\
  366. * ROP to mix translation table
  367. *
  368. * Table to translate ternary raster ops to mixes (binary raster ops). Ternary
  369. * raster ops that can't be translated to mixes are translated to 0 (0 is not
  370. * a valid mix).
  371. *
  372. \**************************************************************************/
  373. UCHAR jRop3ToMix[256] = {
  374. R2_BLACK, 0, 0, 0, 0, R2_NOTMERGEPEN, 0, 0,
  375. 0, 0, R2_MASKNOTPEN, 0, 0, 0, 0, R2_NOTCOPYPEN,
  376. 0, 0, 0, 0, 0, 0, 0, 0,
  377. 0, 0, 0, 0, 0, 0, 0, 0,
  378. 0, 0, 0, 0, 0, 0, 0, 0,
  379. 0, 0, 0, 0, 0, 0, 0, 0,
  380. 0, 0, 0, 0, 0, 0, 0, 0,
  381. 0, 0, 0, 0, 0, 0, 0, 0,
  382. 0, 0, 0, 0, 0, 0, 0, 0,
  383. 0, 0, 0, 0, 0, 0, 0, 0,
  384. R2_MASKPENNOT, 0, 0, 0, 0, R2_NOT, 0, 0,
  385. 0, 0, R2_XORPEN, 0, 0, 0, 0, R2_NOTMASKPEN,
  386. 0, 0, 0, 0, 0, 0, 0, 0,
  387. 0, 0, 0, 0, 0, 0, 0, 0,
  388. 0, 0, 0, 0, 0, 0, 0, 0,
  389. 0, 0, 0, 0, 0, 0, 0, 0,
  390. 0, 0, 0, 0, 0, 0, 0, 0,
  391. 0, 0, 0, 0, 0, 0, 0, 0,
  392. 0, 0, 0, 0, 0, 0, 0, 0,
  393. 0, 0, 0, 0, 0, 0, 0, 0,
  394. R2_MASKPEN, 0, 0, 0, 0, R2_NOTXORPEN, 0, 0,
  395. 0, 0, R2_NOP, 0, 0, 0, 0, R2_MERGENOTPEN,
  396. 0, 0, 0, 0, 0, 0, 0, 0,
  397. 0, 0, 0, 0, 0, 0, 0, 0,
  398. 0, 0, 0, 0, 0, 0, 0, 0,
  399. 0, 0, 0, 0, 0, 0, 0, 0,
  400. 0, 0, 0, 0, 0, 0, 0, 0,
  401. 0, 0, 0, 0, 0, 0, 0, 0,
  402. 0, 0, 0, 0, 0, 0, 0, 0,
  403. 0, 0, 0, 0, 0, 0, 0, 0,
  404. R2_COPYPEN, 0, 0, 0, 0, R2_MERGEPENNOT, 0, 0,
  405. 0, 0, R2_MERGEPEN, 0, 0, 0, 0, R2_WHITE
  406. };
  407. /******************************Public*Routine******************************\
  408. * BOOL DrvBitBlt(psoDest, psoSrc, psoMask, pco, pxlo, prclDest, pptlSrc,
  409. * pptlMask, pbo, pptlBrush, rop4)
  410. *
  411. * This routine will handle any blit. Perhaps glacially, but it will be
  412. * handled.
  413. \**************************************************************************/
  414. BOOL DrvBitBlt(
  415. SURFOBJ* psoDest,
  416. SURFOBJ* psoSrc,
  417. SURFOBJ* psoMask,
  418. CLIPOBJ* pco,
  419. XLATEOBJ* pxlo,
  420. RECTL* prclDest,
  421. POINTL* pptlSrc,
  422. POINTL* pptlMask,
  423. BRUSHOBJ* pbo,
  424. POINTL* pptlBrush,
  425. ROP4 rop4)
  426. {
  427. BOOL b;
  428. POINTL ptlSrc;
  429. RECTL rclDest;
  430. PPDEV ppdev;
  431. SURFOBJ* pso;
  432. BYTE jClipping;
  433. RECTL rclTmp;
  434. POINTL ptlTmp;
  435. BBENUM bben; // Clip enumerator
  436. BOOL bMore; // Clip continuation flag
  437. POINTL ptlMask; // Temporary mask for engine call-backs
  438. POINTL ptlMaskAdjust; // Adjustment for mask
  439. INT iCopyDir;
  440. // Set up the clipping type
  441. if (pco == (CLIPOBJ *) NULL) {
  442. // No CLIPOBJ provided, so we don't have to worry about clipping
  443. jClipping = DC_TRIVIAL;
  444. } else {
  445. // Use the CLIPOBJ-provided clipping
  446. jClipping = pco->iDComplexity;
  447. }
  448. // Get the correct surface object for the target and the source
  449. if (psoDest->iType == STYPE_DEVICE) {
  450. if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE)) {
  451. ////////////////////////////////////////////////////////////////
  452. // BitBlt screen-to-screen:
  453. ////////////////////////////////////////////////////////////////
  454. ppdev = (PPDEV) psoDest->dhsurf;
  455. // See if we can do a simple CopyBits:
  456. if (rop4 == 0x0000CCCC)
  457. {
  458. ppdev = (PPDEV) psoDest->dhsurf;
  459. // We can handle quadpixel-aligned screen-to-screen blts with
  460. // no translation:
  461. if ((((pptlSrc->x ^ prclDest->left) & 1) == 0) &&
  462. (ppdev->fl & DRIVER_PLANAR_CAPABLE) &&
  463. ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
  464. {
  465. switch(jClipping)
  466. {
  467. case DC_TRIVIAL:
  468. vPlanarCopyBits(ppdev, prclDest, pptlSrc);
  469. return(TRUE);
  470. case DC_RECT:
  471. // Clip the target rectangle to the clip rectangle:
  472. if (!bIntersectRect(&rclTmp, prclDest, &pco->rclBounds))
  473. {
  474. DISPDBG((0, "DrvBitBlt: Nothing to draw."));
  475. return(TRUE);
  476. }
  477. ptlTmp.x = pptlSrc->x + rclTmp.left - prclDest->left;
  478. ptlTmp.y = pptlSrc->y + rclTmp.top - prclDest->top;
  479. vPlanarCopyBits(ppdev, &rclTmp, &ptlTmp);
  480. return(TRUE);
  481. case DC_COMPLEX:
  482. if (pptlSrc->y >= prclDest->top)
  483. {
  484. if (pptlSrc->x >= prclDest->left)
  485. iCopyDir = CD_RIGHTDOWN;
  486. else
  487. iCopyDir = CD_LEFTDOWN;
  488. }
  489. else
  490. {
  491. if (pptlSrc->x >= prclDest->left)
  492. iCopyDir = CD_RIGHTUP;
  493. else
  494. iCopyDir = CD_LEFTUP;
  495. }
  496. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iCopyDir, 0);
  497. do {
  498. RECTL* prcl;
  499. RECTL* prclEnd;
  500. bMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(bben),
  501. (PVOID) &bben);
  502. prclEnd = &bben.arcl[bben.c];
  503. for (prcl = bben.arcl; prcl < prclEnd; prcl++)
  504. {
  505. if (bIntersectRect(prcl, prclDest, prcl))
  506. {
  507. ptlTmp.x = pptlSrc->x + prcl->left - prclDest->left;
  508. ptlTmp.y = pptlSrc->y + prcl->top - prclDest->top;
  509. vPlanarCopyBits(ppdev, prcl, &ptlTmp);
  510. }
  511. }
  512. } while (bMore);
  513. return(TRUE);
  514. }
  515. }
  516. // Can't handle in hardware, so punt:
  517. return(bPuntScreenToScreenCopyBits(ppdev,
  518. pco,
  519. pxlo,
  520. prclDest,
  521. pptlSrc));
  522. }
  523. // It's more complicated than a CopyBits, so punt it:
  524. return(bPuntScreenToScreenBitBlt(ppdev,
  525. psoMask,
  526. pco,
  527. pxlo,
  528. prclDest,
  529. pptlSrc,
  530. pptlMask,
  531. pbo,
  532. pptlBrush,
  533. rop4));
  534. }
  535. ////////////////////////////////////////////////////////////////
  536. // BitBlt to screen:
  537. ////////////////////////////////////////////////////////////////
  538. ppdev = (PPDEV) psoDest->dhsurf;
  539. // Punt the memory-to-screen call back to the engine:
  540. if (psoMask != NULL)
  541. {
  542. ptlMaskAdjust.x = prclDest->left - pptlMask->x;
  543. ptlMaskAdjust.y = prclDest->top - pptlMask->y;
  544. }
  545. pso = ppdev->pSurfObj;
  546. vBankStartBltDest(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest);
  547. do {
  548. ptlMask.x = rclDest.left - ptlMaskAdjust.x;
  549. ptlMask.y = rclDest.top - ptlMaskAdjust.y;
  550. b = EngBitBlt(pso,
  551. psoSrc,
  552. psoMask,
  553. pco,
  554. pxlo,
  555. &rclDest,
  556. &ptlSrc,
  557. &ptlMask,
  558. pbo,
  559. pptlBrush,
  560. rop4);
  561. } while (b && bBankEnumBltDest(ppdev, pso, pptlSrc, prclDest,
  562. &ptlSrc, &rclDest));
  563. return(b);
  564. }
  565. else if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE))
  566. {
  567. ////////////////////////////////////////////////////////////////
  568. // BitBlt from screen:
  569. ////////////////////////////////////////////////////////////////
  570. if (psoMask != NULL)
  571. {
  572. ptlMaskAdjust.x = prclDest->left - pptlMask->x;
  573. ptlMaskAdjust.y = prclDest->top - pptlMask->y;
  574. }
  575. ppdev = (PPDEV) psoSrc->dhsurf;
  576. pso = ppdev->pSurfObj;
  577. vBankStartBltSrc(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest);
  578. do {
  579. ptlMask.x = rclDest.left - ptlMaskAdjust.x;
  580. ptlMask.y = rclDest.top - ptlMaskAdjust.y;
  581. b = EngBitBlt(psoDest,
  582. pso,
  583. psoMask,
  584. pco,
  585. pxlo,
  586. &rclDest,
  587. &ptlSrc,
  588. &ptlMask,
  589. pbo,
  590. pptlBrush,
  591. rop4);
  592. } while (b && bBankEnumBltSrc(ppdev, pso, pptlSrc, prclDest,
  593. &ptlSrc, &rclDest));
  594. return(b);
  595. }
  596. RIP("Got a funky format?");
  597. return(FALSE);
  598. }
  599. /***************************************************************************\
  600. * DrvCopyBits
  601. \***************************************************************************/
  602. BOOL DrvCopyBits(
  603. SURFOBJ* psoDest,
  604. SURFOBJ* psoSrc,
  605. CLIPOBJ* pco,
  606. XLATEOBJ* pxlo,
  607. RECTL* prclDest,
  608. POINTL* pptlSrc)
  609. {
  610. BOOL b;
  611. POINTL ptlSrc;
  612. RECTL rclDest;
  613. PPDEV ppdev;
  614. SURFOBJ* pso;
  615. BBENUM bben;
  616. BOOL bMore;
  617. BYTE jClipping;
  618. POINTL ptlTmp;
  619. RECTL rclTmp;
  620. INT iCopyDir;
  621. // Get the correct surface object for the target and the source
  622. if (psoDest->iType == STYPE_DEVICE)
  623. {
  624. // We have to special case screen-to-screen operations:
  625. if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE))
  626. {
  627. ////////////////////////////////////////////////////////////////
  628. // CopyBits screen-to-screen:
  629. ////////////////////////////////////////////////////////////////
  630. ppdev = (PPDEV) psoDest->dhsurf;
  631. // We check to see if we can do a planar copy, because usually
  632. // it will be faster. But the hardware has to be capable of
  633. // doing it, and the source and destination must be 4-pel
  634. // aligned.
  635. if ((((pptlSrc->x ^ prclDest->left) & 1) == 0) &&
  636. (ppdev->fl & DRIVER_PLANAR_CAPABLE) &&
  637. ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
  638. {
  639. jClipping = (pco != NULL) ? pco->iDComplexity : DC_TRIVIAL;
  640. switch(jClipping)
  641. {
  642. case DC_TRIVIAL:
  643. vPlanarCopyBits(ppdev, prclDest, pptlSrc);
  644. return(TRUE);
  645. case DC_RECT:
  646. // Clip the target rectangle to the clip rectangle:
  647. if (!bIntersectRect(&rclTmp, prclDest, &pco->rclBounds))
  648. {
  649. DISPDBG((0, "DrvCopyBits: Nothing to draw."));
  650. return(TRUE);
  651. }
  652. ptlTmp.x = pptlSrc->x + rclTmp.left - prclDest->left;
  653. ptlTmp.y = pptlSrc->y + rclTmp.top - prclDest->top;
  654. vPlanarCopyBits(ppdev, &rclTmp, &ptlTmp);
  655. return(TRUE);
  656. case DC_COMPLEX:
  657. if (pptlSrc->y >= prclDest->top)
  658. {
  659. if (pptlSrc->x >= prclDest->left)
  660. iCopyDir = CD_RIGHTDOWN;
  661. else
  662. iCopyDir = CD_LEFTDOWN;
  663. }
  664. else
  665. {
  666. if (pptlSrc->x >= prclDest->left)
  667. iCopyDir = CD_RIGHTUP;
  668. else
  669. iCopyDir = CD_LEFTUP;
  670. }
  671. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iCopyDir, 0);
  672. do {
  673. RECTL* prcl;
  674. RECTL* prclEnd;
  675. bMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(bben),
  676. (PVOID) &bben);
  677. prclEnd = &bben.arcl[bben.c];
  678. for (prcl = bben.arcl; prcl < prclEnd; prcl++)
  679. {
  680. if (bIntersectRect(prcl, prclDest, prcl))
  681. {
  682. ptlTmp.x = pptlSrc->x + prcl->left - prclDest->left;
  683. ptlTmp.y = pptlSrc->y + prcl->top - prclDest->top;
  684. vPlanarCopyBits(ppdev, prcl, &ptlTmp);
  685. }
  686. }
  687. } while (bMore);
  688. return(TRUE);
  689. }
  690. }
  691. return(bPuntScreenToScreenCopyBits(ppdev,
  692. pco,
  693. pxlo,
  694. prclDest,
  695. pptlSrc));
  696. }
  697. ppdev = (PPDEV) psoDest->dhsurf;
  698. // Fall back to the engine:
  699. pso = ppdev->pSurfObj;
  700. vBankStartBltDest(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest);
  701. do {
  702. b = EngCopyBits(pso,
  703. psoSrc,
  704. pco,
  705. pxlo,
  706. &rclDest,
  707. &ptlSrc);
  708. } while (b && bBankEnumBltDest(ppdev, pso, pptlSrc, prclDest,
  709. &ptlSrc, &rclDest));
  710. return(b);
  711. }
  712. else if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE))
  713. {
  714. ////////////////////////////////////////////////////////////////
  715. // CopyBits from screen:
  716. ////////////////////////////////////////////////////////////////
  717. ppdev = (PPDEV) psoSrc->dhsurf;
  718. pso = ppdev->pSurfObj;
  719. vBankStartBltSrc(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest);
  720. do {
  721. b = EngCopyBits(psoDest,
  722. pso,
  723. pco,
  724. pxlo,
  725. &rclDest,
  726. &ptlSrc);
  727. } while (b && bBankEnumBltSrc(ppdev, pso, pptlSrc, prclDest,
  728. &ptlSrc, &rclDest));
  729. return(b);
  730. }
  731. /* we should never be here */
  732. return FALSE;
  733. }