Source code of Windows XP (NT5)
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.

1791 lines
63 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: bitblt.c
  3. *
  4. * Contains the high-level DrvBitBlt and DrvCopyBits functions. The low-
  5. * level stuff lives in the 'blt??.c' files.
  6. *
  7. * Note: Since we've implemented device-bitmaps, any surface that GDI passes
  8. * to us can have 3 values for its 'iType': STYPE_BITMAP, STYPE_DEVICE
  9. * or STYPE_DEVBITMAP. We filter device-bitmaps that we've stored
  10. * as DIBs fairly high in the code, so after we adjust its 'pptlSrc',
  11. * we can treat STYPE_DEVBITMAP surfaces the same as STYPE_DEVICE
  12. * surfaces (e.g., a blt from an off-screen device bitmap to the screen
  13. * gets treated as a normal screen-to-screen blt).
  14. *
  15. * Unfortunately, if we've created our primary surface as a device-
  16. * managed surface, it has an 'iType' of STYPE_BITMAP and not
  17. * STYPE_DEVICE. So throughout this code, we will determine if a
  18. * surface is one of ours by checking 'dhsurf' -- a NULL value means
  19. * that it's a GDI-created DIB, otherwise it's one of our surfaces and
  20. * 'dhsurf' points to our DSURF structure.
  21. *
  22. * Copyright (c) 1992-1996 Microsoft Corporation
  23. \**************************************************************************/
  24. #include "precomp.h"
  25. /******************************Public*Table********************************\
  26. * BYTE gajLeftMask[] and BYTE gajRightMask[]
  27. *
  28. * Edge tables for vXferScreenTo1bpp.
  29. \**************************************************************************/
  30. BYTE gajLeftMask[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
  31. BYTE gajRightMask[] = { 0xff, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
  32. /******************************Public*Routine******************************\
  33. * VOID vXferNativeSrccopy
  34. *
  35. * Does a SRCCOPY transfer of a bitmap to the screen using the frame
  36. * buffer, because on the Tseng chips it's faster than using the data
  37. * transfer register.
  38. *
  39. \**************************************************************************/
  40. VOID vXferNativeSrccopy( // Type FNXFER
  41. PDEV* ppdev,
  42. LONG c, // Count of rectangles, can't be zero
  43. RECTL* prcl, // List of destination rectangles, in relative
  44. // coordinates
  45. ULONG rop4, // Not used
  46. SURFOBJ* psoSrc, // Source surface
  47. POINTL* pptlSrc, // Original unclipped source point
  48. RECTL* prclDst, // Original unclipped destination rectangle
  49. XLATEOBJ* pxlo) // Not used
  50. {
  51. LONG xOffset;
  52. LONG yOffset;
  53. LONG dx;
  54. LONG dy;
  55. RECTL rclDst;
  56. POINTL ptlSrc;
  57. ASSERTDD((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL),
  58. "Can handle trivial xlate only");
  59. ASSERTDD(psoSrc->iBitmapFormat == ppdev->iBitmapFormat,
  60. "Source must be same colour depth as screen");
  61. ASSERTDD(c > 0, "Can't handle zero rectangles");
  62. ASSERTDD(rop4 == 0xcccc, "Must be a SRCCOPY rop");
  63. xOffset = ppdev->xOffset;
  64. yOffset = ppdev->yOffset;
  65. dx = pptlSrc->x - prclDst->left;
  66. dy = pptlSrc->y - prclDst->top; // Add to destination to get source
  67. while (TRUE)
  68. {
  69. ptlSrc.x = prcl->left + dx;
  70. ptlSrc.y = prcl->top + dy;
  71. // 'ppdev->pfnPutBits' takes only absolute coordinates, so add in the
  72. // off-screen bitmap offset here:
  73. rclDst.left = prcl->left + xOffset;
  74. rclDst.right = prcl->right + xOffset;
  75. rclDst.top = prcl->top + yOffset;
  76. rclDst.bottom = prcl->bottom + yOffset;
  77. ppdev->pfnPutBits(ppdev, psoSrc, &rclDst, &ptlSrc);
  78. if (--c == 0)
  79. return;
  80. prcl++;
  81. }
  82. }
  83. /******************************Public*Routine******************************\
  84. * VOID vXferScreenTo1bpp
  85. *
  86. * Performs a SRCCOPY transfer from the screen (when it's 8bpp) to a 1bpp
  87. * bitmap.
  88. *
  89. \**************************************************************************/
  90. #if defined(_X86_)
  91. VOID vXferScreenTo1bpp( // Type FNXFER
  92. PDEV* ppdev,
  93. LONG c, // Count of rectangles, can't be zero
  94. RECTL* prcl, // List of destination rectangles, in relative
  95. // coordinates
  96. ULONG ulHwMix, // Not used
  97. SURFOBJ* psoDst, // Destination surface
  98. POINTL* pptlSrc, // Original unclipped source point
  99. RECTL* prclDst, // Original unclipped destination rectangle
  100. XLATEOBJ* pxlo) // Provides colour-compressions information
  101. {
  102. LONG cBpp;
  103. VOID* pfnCompute;
  104. SURFOBJ soTmp;
  105. ULONG* pulXlate;
  106. ULONG ulForeColor;
  107. POINTL ptlSrc;
  108. RECTL rclTmp;
  109. BYTE* pjDst;
  110. BYTE jLeftMask;
  111. BYTE jRightMask;
  112. BYTE jNotLeftMask;
  113. BYTE jNotRightMask;
  114. LONG cjMiddle;
  115. LONG lDstDelta;
  116. LONG lSrcDelta;
  117. LONG cyTmpScans;
  118. LONG cyThis;
  119. LONG cyToGo;
  120. ASSERTDD(c > 0, "Can't handle zero rectangles");
  121. ASSERTDD(psoDst->iBitmapFormat == BMF_1BPP, "Only 1bpp destinations");
  122. ASSERTDD(TMP_BUFFER_SIZE >= (ppdev->cxMemory * ppdev->cBpp),
  123. "Temp buffer has to be larger than widest possible scan");
  124. // When the destination is a 1bpp bitmap, the foreground colour
  125. // maps to '1', and any other colour maps to '0'.
  126. if (ppdev->iBitmapFormat == BMF_8BPP)
  127. {
  128. // When the source is 8bpp or less, we find the forground colour
  129. // by searching the translate table for the only '1':
  130. pulXlate = pxlo->pulXlate;
  131. while (*pulXlate != 1)
  132. pulXlate++;
  133. ulForeColor = pulXlate - pxlo->pulXlate;
  134. }
  135. else
  136. {
  137. ASSERTDD((ppdev->iBitmapFormat == BMF_16BPP) ||
  138. (ppdev->iBitmapFormat == BMF_32BPP),
  139. "This routine only supports 8, 16 or 32bpp");
  140. // When the source has a depth greater than 8bpp, the foreground
  141. // colour will be the first entry in the translate table we get
  142. // from calling 'piVector':
  143. pulXlate = XLATEOBJ_piVector(pxlo);
  144. ulForeColor = 0;
  145. if (pulXlate != NULL) // This check isn't really needed...
  146. ulForeColor = pulXlate[0];
  147. }
  148. // We use the temporary buffer to keep a copy of the source
  149. // rectangle:
  150. soTmp.pvScan0 = ppdev->pvTmpBuffer;
  151. do {
  152. // ptlSrc points to the upper-left corner of the screen rectangle
  153. // for the current batch:
  154. ptlSrc.x = prcl->left + (pptlSrc->x - prclDst->left);
  155. ptlSrc.y = prcl->top + (pptlSrc->y - prclDst->top);
  156. // ppdev->pfnGetBits takes absolute coordinates for the source point:
  157. ptlSrc.x += ppdev->xOffset;
  158. ptlSrc.y += ppdev->yOffset;
  159. pjDst = (BYTE*) psoDst->pvScan0 + (prcl->top * psoDst->lDelta)
  160. + (prcl->left >> 3);
  161. cBpp = ppdev->cBpp;
  162. soTmp.lDelta = cBpp * (((prcl->right + 7L) & ~7L) - (prcl->left & ~7L));
  163. // Our temporary buffer, into which we read a copy of the source,
  164. // may be smaller than the source rectangle. In that case, we
  165. // process the source rectangle in batches.
  166. //
  167. // cyTmpScans is the number of scans we can do in each batch.
  168. // cyToGo is the total number of scans we have to do for this
  169. // rectangle.
  170. //
  171. // We take the buffer size less four so that the right edge case
  172. // can safely read one dword past the end:
  173. cyTmpScans = (TMP_BUFFER_SIZE - 4) / soTmp.lDelta;
  174. cyToGo = prcl->bottom - prcl->top;
  175. ASSERTDD(cyTmpScans > 0, "Buffer too small for largest possible scan");
  176. // Initialize variables that don't change within the batch loop:
  177. rclTmp.top = 0;
  178. rclTmp.left = prcl->left & 7L;
  179. rclTmp.right = (prcl->right - prcl->left) + rclTmp.left;
  180. // Note that we have to be careful with the right mask so that it
  181. // isn't zero. A right mask of zero would mean that we'd always be
  182. // touching one byte past the end of the scan (even though we
  183. // wouldn't actually be modifying that byte), and we must never
  184. // access memory past the end of the bitmap (because we can access
  185. // violate if the bitmap end is exactly page-aligned).
  186. jLeftMask = gajLeftMask[rclTmp.left & 7];
  187. jRightMask = gajRightMask[rclTmp.right & 7];
  188. cjMiddle = ((rclTmp.right - 1) >> 3) - (rclTmp.left >> 3) - 1;
  189. if (cjMiddle < 0)
  190. {
  191. // The blt starts and ends in the same byte:
  192. jLeftMask &= jRightMask;
  193. jRightMask = 0;
  194. cjMiddle = 0;
  195. }
  196. jNotLeftMask = ~jLeftMask;
  197. jNotRightMask = ~jRightMask;
  198. lDstDelta = psoDst->lDelta - cjMiddle - 2;
  199. // Delta from the end of the destination
  200. // to the start on the next scan, accounting
  201. // for 'left' and 'right' bytes
  202. lSrcDelta = soTmp.lDelta - cBpp * (8 * (cjMiddle + 2));
  203. // Compute source delta for special cases
  204. // like when cjMiddle gets bumped up to '0',
  205. // and to correct aligned cases
  206. do {
  207. // This is the loop that breaks the source rectangle into
  208. // manageable batches.
  209. cyThis = cyTmpScans;
  210. cyToGo -= cyThis;
  211. if (cyToGo < 0)
  212. cyThis += cyToGo;
  213. rclTmp.bottom = cyThis;
  214. ppdev->pfnGetBits(ppdev, &soTmp, &rclTmp, &ptlSrc);
  215. ptlSrc.y += cyThis; // Get ready for next batch loop
  216. _asm {
  217. mov eax,ulForeColor ;eax = foreground colour
  218. ;ebx = temporary storage
  219. ;ecx = count of middle dst bytes
  220. ;dl = destination byte accumulator
  221. ;dh = temporary storage
  222. mov esi,soTmp.pvScan0 ;esi = source pointer
  223. mov edi,pjDst ;edi = destination pointer
  224. ; Figure out the appropriate compute routine:
  225. mov ebx,cBpp
  226. mov pfnCompute,offset Compute_Destination_Byte_From_8bpp
  227. dec ebx
  228. jz short Do_Left_Byte
  229. mov pfnCompute,offset Compute_Destination_Byte_From_16bpp
  230. dec ebx
  231. jz short Do_Left_Byte
  232. mov pfnCompute,offset Compute_Destination_Byte_From_32bpp
  233. Do_Left_Byte:
  234. call pfnCompute
  235. and dl,jLeftMask
  236. mov dh,jNotLeftMask
  237. and dh,[edi]
  238. or dh,dl
  239. mov [edi],dh
  240. inc edi
  241. mov ecx,cjMiddle
  242. dec ecx
  243. jl short Do_Right_Byte
  244. Do_Middle_Bytes:
  245. call pfnCompute
  246. mov [edi],dl
  247. inc edi
  248. dec ecx
  249. jge short Do_Middle_Bytes
  250. Do_Right_Byte:
  251. call pfnCompute
  252. and dl,jRightMask
  253. mov dh,jNotRightMask
  254. and dh,[edi]
  255. or dh,dl
  256. mov [edi],dh
  257. inc edi
  258. add edi,lDstDelta
  259. add esi,lSrcDelta
  260. dec cyThis
  261. jnz short Do_Left_Byte
  262. mov pjDst,edi ;save for next batch
  263. jmp All_Done
  264. Compute_Destination_Byte_From_8bpp:
  265. mov bl,[esi]
  266. sub bl,al
  267. cmp bl,1
  268. adc dl,dl ;bit 0
  269. mov bl,[esi+1]
  270. sub bl,al
  271. cmp bl,1
  272. adc dl,dl ;bit 1
  273. mov bl,[esi+2]
  274. sub bl,al
  275. cmp bl,1
  276. adc dl,dl ;bit 2
  277. mov bl,[esi+3]
  278. sub bl,al
  279. cmp bl,1
  280. adc dl,dl ;bit 3
  281. mov bl,[esi+4]
  282. sub bl,al
  283. cmp bl,1
  284. adc dl,dl ;bit 4
  285. mov bl,[esi+5]
  286. sub bl,al
  287. cmp bl,1
  288. adc dl,dl ;bit 5
  289. mov bl,[esi+6]
  290. sub bl,al
  291. cmp bl,1
  292. adc dl,dl ;bit 6
  293. mov bl,[esi+7]
  294. sub bl,al
  295. cmp bl,1
  296. adc dl,dl ;bit 7
  297. add esi,8 ;advance the source
  298. ret
  299. Compute_Destination_Byte_From_16bpp:
  300. mov bx,[esi]
  301. sub bx,ax
  302. cmp bx,1
  303. adc dl,dl ;bit 0
  304. mov bx,[esi+2]
  305. sub bx,ax
  306. cmp bx,1
  307. adc dl,dl ;bit 1
  308. mov bx,[esi+4]
  309. sub bx,ax
  310. cmp bx,1
  311. adc dl,dl ;bit 2
  312. mov bx,[esi+6]
  313. sub bx,ax
  314. cmp bx,1
  315. adc dl,dl ;bit 3
  316. mov bx,[esi+8]
  317. sub bx,ax
  318. cmp bx,1
  319. adc dl,dl ;bit 4
  320. mov bx,[esi+10]
  321. sub bx,ax
  322. cmp bx,1
  323. adc dl,dl ;bit 5
  324. mov bx,[esi+12]
  325. sub bx,ax
  326. cmp bx,1
  327. adc dl,dl ;bit 6
  328. mov bx,[esi+14]
  329. sub bx,ax
  330. cmp bx,1
  331. adc dl,dl ;bit 7
  332. add esi,16 ;advance the source
  333. ret
  334. Compute_Destination_Byte_From_32bpp:
  335. mov ebx,[esi]
  336. sub ebx,eax
  337. cmp ebx,1
  338. adc dl,dl ;bit 0
  339. mov ebx,[esi+4]
  340. sub ebx,eax
  341. cmp ebx,1
  342. adc dl,dl ;bit 1
  343. mov ebx,[esi+8]
  344. sub ebx,eax
  345. cmp ebx,1
  346. adc dl,dl ;bit 2
  347. mov ebx,[esi+12]
  348. sub ebx,eax
  349. cmp ebx,1
  350. adc dl,dl ;bit 3
  351. mov ebx,[esi+16]
  352. sub ebx,eax
  353. cmp ebx,1
  354. adc dl,dl ;bit 4
  355. mov ebx,[esi+20]
  356. sub ebx,eax
  357. cmp ebx,1
  358. adc dl,dl ;bit 5
  359. mov ebx,[esi+24]
  360. sub ebx,eax
  361. cmp ebx,1
  362. adc dl,dl ;bit 6
  363. mov ebx,[esi+28]
  364. sub ebx,eax
  365. cmp ebx,1
  366. adc dl,dl ;bit 7
  367. add esi,32 ;advance the source
  368. ret
  369. All_Done:
  370. }
  371. } while (cyToGo > 0);
  372. prcl++;
  373. } while (--c != 0);
  374. }
  375. #endif // i386
  376. /******************************Public*Routine******************************\
  377. * BOOL bPuntBlt
  378. *
  379. * Has GDI do any drawing operations that we don't specifically handle
  380. * in the driver.
  381. *
  382. \**************************************************************************/
  383. BOOL bPuntBlt(
  384. SURFOBJ* psoDst,
  385. SURFOBJ* psoSrc,
  386. SURFOBJ* psoMsk,
  387. CLIPOBJ* pco,
  388. XLATEOBJ* pxlo,
  389. RECTL* prclDst,
  390. POINTL* pptlSrc,
  391. POINTL* pptlMsk,
  392. BRUSHOBJ* pbo,
  393. POINTL* pptlBrush,
  394. ROP4 rop4)
  395. {
  396. PDEV* ppdev;
  397. if (psoDst->iType != STYPE_BITMAP)
  398. ppdev = (PDEV*) psoDst->dhpdev;
  399. else
  400. ppdev = (PDEV*) psoSrc->dhpdev;
  401. #if DBG
  402. {
  403. //////////////////////////////////////////////////////////////////////
  404. // Diagnostics
  405. //
  406. // Since calling the engine to do any drawing can be rather painful,
  407. // particularly when the source is an off-screen DFB (since GDI will
  408. // have to allocate a DIB and call us to make a temporary copy before
  409. // it can even start drawing), we'll try to avoid it as much as
  410. // possible.
  411. //
  412. // Here we simply spew out information describing the blt whenever
  413. // this routine gets called (checked builds only, of course):
  414. ULONG ulClip;
  415. ulClip = (pco == NULL) ? DC_TRIVIAL : pco->iDComplexity;
  416. DISPDBG((4, ">> Punt << Dst format: %li Dst type: %li Clip: %li Rop: %lx",
  417. psoDst->iBitmapFormat, psoDst->iType, ulClip, rop4));
  418. if (psoSrc != NULL)
  419. {
  420. DISPDBG((4, " << Src format: %li Src type: %li",
  421. psoSrc->iBitmapFormat, psoSrc->iType));
  422. if (psoSrc->iBitmapFormat == BMF_1BPP)
  423. {
  424. DISPDBG((4, " << Foreground: %lx Background: %lx",
  425. pxlo->pulXlate[1], pxlo->pulXlate[0]));
  426. }
  427. }
  428. if ((pxlo != NULL) && !(pxlo->flXlate & XO_TRIVIAL) && (psoSrc != NULL))
  429. {
  430. if (((psoSrc->dhsurf == NULL) &&
  431. (psoSrc->iBitmapFormat != ppdev->iBitmapFormat)) ||
  432. ((psoDst->dhsurf == NULL) &&
  433. (psoDst->iBitmapFormat != ppdev->iBitmapFormat)))
  434. {
  435. // Don't bother printing the 'xlate' message when the source
  436. // is a different bitmap format from the destination -- in
  437. // those cases we know there always has to be a translate.
  438. }
  439. else
  440. {
  441. DISPDBG((4, " << With xlate"));
  442. }
  443. }
  444. // If the rop4 requires a pattern, and it's a non-solid brush...
  445. if (((((rop4 >> 4) ^ (rop4)) & 0x0f0f) != 0) &&
  446. (pbo->iSolidColor == -1))
  447. {
  448. if (pbo->pvRbrush == NULL)
  449. DISPDBG((4, " << With brush -- Not created"));
  450. else
  451. DISPDBG((4, " << With brush -- Created Ok"));
  452. }
  453. }
  454. #endif
  455. if (DIRECT_ACCESS(ppdev))
  456. {
  457. //////////////////////////////////////////////////////////////////////
  458. // Banked Framebuffer bPuntBlt
  459. //
  460. // This section of code handles a PuntBlt when GDI can directly draw
  461. // on the framebuffer, but the drawing has to be done in banks:
  462. BANK bnk;
  463. BOOL b;
  464. HSURF hsurfTmp;
  465. SURFOBJ* psoTmp;
  466. SIZEL sizl;
  467. POINTL ptlSrc;
  468. RECTL rclTmp;
  469. RECTL rclDst;
  470. if (ppdev->bAutoBanking)
  471. {
  472. DSURF* pdsurfDst;
  473. DSURF* pdsurfSrc;
  474. OH* pohSrc;
  475. OH* pohDst;
  476. if (psoDst->dhsurf != NULL)
  477. {
  478. pdsurfDst = (DSURF*) psoDst->dhsurf;
  479. psoDst = ppdev->psoPunt;
  480. psoDst->pvScan0 = pdsurfDst->poh->pvScan0;
  481. psoDst->lDelta = ppdev->lDelta;
  482. if (psoSrc != NULL)
  483. {
  484. pdsurfSrc = (DSURF*) psoSrc->dhsurf;
  485. if ((pdsurfSrc != NULL) &&
  486. (pdsurfSrc != pdsurfDst))
  487. {
  488. // If we're doing a BitBlt between different off-screen
  489. // surfaces, we have to be sure to give GDI different
  490. // surfaces, otherwise it may get confused when it has
  491. // to do screen-to-screen blts with a translate...
  492. pohSrc = pdsurfSrc->poh;
  493. pohDst = pdsurfDst->poh;
  494. psoSrc = ppdev->psoPunt2;
  495. psoSrc->pvScan0 = pohSrc->pvScan0;
  496. psoSrc->lDelta = ppdev->lDelta;
  497. // Undo the source pointer adjustment we did earlier:
  498. ptlSrc.x = pptlSrc->x + (pohDst->x - pohSrc->x);
  499. ptlSrc.y = pptlSrc->y + (pohDst->y - pohSrc->y);
  500. pptlSrc = &ptlSrc;
  501. }
  502. }
  503. }
  504. else
  505. {
  506. ppdev = (PDEV*) psoSrc->dhpdev;
  507. pdsurfSrc = (DSURF*) psoSrc->dhsurf;
  508. psoSrc = ppdev->psoPunt;
  509. psoSrc->pvScan0 = pdsurfSrc->poh->pvScan0;
  510. psoSrc->lDelta = ppdev->lDelta;
  511. }
  512. ppdev->pfnBankSelectMode(ppdev, BANK_ON);
  513. return(EngBitBlt(psoDst, psoSrc, psoMsk, pco, pxlo, prclDst, pptlSrc,
  514. pptlMsk, pbo, pptlBrush, rop4));
  515. }
  516. // We copy the original destination rectangle, and use that in every
  517. // GDI call-back instead of the original because sometimes GDI is
  518. // sneaky and points 'prclDst' to '&pco->rclBounds'. Because we
  519. // modify 'rclBounds', that would affect 'prclDst', which we don't
  520. // want to happen:
  521. rclDst = *prclDst;
  522. if ((psoSrc == NULL) || (psoSrc->iType == STYPE_BITMAP))
  523. {
  524. ASSERTDD(psoDst->iType != STYPE_BITMAP,
  525. "Dest should be the screen when given a DIB source");
  526. // Do a memory-to-screen blt:
  527. vBankStart(ppdev, &rclDst, pco, &bnk);
  528. b = TRUE;
  529. do {
  530. b &= EngBitBlt(bnk.pso, psoSrc, psoMsk, bnk.pco, pxlo,
  531. &rclDst, pptlSrc, pptlMsk, pbo, pptlBrush,
  532. rop4);
  533. } while (bBankEnum(&bnk));
  534. }
  535. else
  536. {
  537. b = FALSE; // Assume failure
  538. // The screen is the source (it may be the destination too...)
  539. ptlSrc.x = pptlSrc->x + ppdev->xOffset;
  540. ptlSrc.y = pptlSrc->y + ppdev->yOffset;
  541. if ((pco != NULL) && (pco->iDComplexity != DC_TRIVIAL))
  542. {
  543. // We have to intersect the destination rectangle with
  544. // the clip bounds if there is one (consider the case
  545. // where the app asked to blt a really, really big
  546. // rectangle from the screen -- prclDst would be really,
  547. // really big but pco->rclBounds would be the actual
  548. // area of interest):
  549. rclDst.left = max(rclDst.left, pco->rclBounds.left);
  550. rclDst.top = max(rclDst.top, pco->rclBounds.top);
  551. rclDst.right = min(rclDst.right, pco->rclBounds.right);
  552. rclDst.bottom = min(rclDst.bottom, pco->rclBounds.bottom);
  553. // Correspondingly, we have to offset the source point:
  554. ptlSrc.x += (rclDst.left - prclDst->left);
  555. ptlSrc.y += (rclDst.top - prclDst->top);
  556. }
  557. // We're now either going to do a screen-to-screen or screen-to-DIB
  558. // blt. In either case, we're going to create a temporary copy of
  559. // the source. (Why do we do this when GDI could do it for us?
  560. // GDI would create a temporary copy of the DIB for every bank
  561. // call-back!)
  562. sizl.cx = rclDst.right - rclDst.left;
  563. sizl.cy = rclDst.bottom - rclDst.top;
  564. // Don't forget to convert from relative to absolute coordinates
  565. // on the source! (vBankStart takes care of that for the
  566. // destination.)
  567. rclTmp.right = sizl.cx;
  568. rclTmp.bottom = sizl.cy;
  569. rclTmp.left = 0;
  570. rclTmp.top = 0;
  571. // GDI does guarantee us that the blt extents have already been
  572. // clipped to the surface boundaries (we don't have to worry
  573. // here about trying to read where there isn't video memory).
  574. // Let's just assert to make sure:
  575. ASSERTDD((ptlSrc.x >= 0) &&
  576. (ptlSrc.y >= 0) &&
  577. (ptlSrc.x + sizl.cx <= ppdev->cxMemory) &&
  578. (ptlSrc.y + sizl.cy <= ppdev->cyMemory),
  579. "Source rectangle out of bounds!");
  580. hsurfTmp = (HSURF) EngCreateBitmap(sizl,
  581. 0, // Let GDI choose ulWidth
  582. ppdev->iBitmapFormat,
  583. 0, // Don't need any options
  584. NULL);// Let GDI allocate
  585. if (hsurfTmp != 0)
  586. {
  587. psoTmp = EngLockSurface(hsurfTmp);
  588. if (psoTmp != NULL)
  589. {
  590. ppdev->pfnGetBits(ppdev, psoTmp, &rclTmp, &ptlSrc);
  591. if (psoDst->iType == STYPE_BITMAP)
  592. {
  593. // It was a Screen-to-DIB blt; now it's a DIB-to-DIB
  594. // blt. Note that the source point is (0, 0) in our
  595. // temporary surface:
  596. b = EngBitBlt(psoDst, psoTmp, psoMsk, pco, pxlo,
  597. &rclDst, (POINTL*) &rclTmp, pptlMsk,
  598. pbo, pptlBrush, rop4);
  599. }
  600. else
  601. {
  602. // It was a Screen-to-Screen blt; now it's a DIB-to-
  603. // screen blt. Note that the source point is (0, 0)
  604. // in our temporary surface:
  605. vBankStart(ppdev, &rclDst, pco, &bnk);
  606. b = TRUE;
  607. do {
  608. b &= EngBitBlt(bnk.pso, psoTmp, psoMsk, bnk.pco,
  609. pxlo, &rclDst, (POINTL*) &rclTmp,
  610. pptlMsk, pbo, pptlBrush, rop4);
  611. } while (bBankEnum(&bnk));
  612. }
  613. EngUnlockSurface(psoTmp);
  614. }
  615. EngDeleteSurface(hsurfTmp);
  616. }
  617. }
  618. return(b);
  619. }
  620. #if !defined(_X86_)
  621. else
  622. {
  623. //////////////////////////////////////////////////////////////////////
  624. // Really Slow bPuntBlt
  625. //
  626. // Here we handle a PuntBlt when GDI can't draw directly on the
  627. // framebuffer (as on the Alpha, which can't do it because of its
  628. // 32 bit bus). If you thought the banked version was slow, just
  629. // look at this one. Guaranteed, there will be at least one bitmap
  630. // allocation and extra copy involved; there could be two if it's a
  631. // screen-to-screen operation.
  632. POINTL ptlSrc;
  633. RECTL rclDst;
  634. SIZEL sizl;
  635. BOOL bSrcIsScreen;
  636. HSURF hsurfSrc;
  637. RECTL rclTmp;
  638. BOOL b;
  639. LONG lDelta;
  640. BYTE* pjBits;
  641. BYTE* pjScan0;
  642. HSURF hsurfDst;
  643. RECTL rclScreen;
  644. b = FALSE; // For error cases, assume we'll fail
  645. rclDst = *prclDst;
  646. if (pptlSrc != NULL)
  647. ptlSrc = *pptlSrc;
  648. if ((pco != NULL) && (pco->iDComplexity != DC_TRIVIAL))
  649. {
  650. // We have to intersect the destination rectangle with
  651. // the clip bounds if there is one (consider the case
  652. // where the app asked to blt a really, really big
  653. // rectangle from the screen -- prclDst would be really,
  654. // really big but pco->rclBounds would be the actual
  655. // area of interest):
  656. rclDst.left = max(rclDst.left, pco->rclBounds.left);
  657. rclDst.top = max(rclDst.top, pco->rclBounds.top);
  658. rclDst.right = min(rclDst.right, pco->rclBounds.right);
  659. rclDst.bottom = min(rclDst.bottom, pco->rclBounds.bottom);
  660. ptlSrc.x += (rclDst.left - prclDst->left);
  661. ptlSrc.y += (rclDst.top - prclDst->top);
  662. }
  663. sizl.cx = rclDst.right - rclDst.left;
  664. sizl.cy = rclDst.bottom - rclDst.top;
  665. // We only need to make a copy from the screen if the source is
  666. // the screen, and the source is involved in the rop. Note that
  667. // we have to check the rop before dereferencing 'psoSrc'
  668. // (because 'psoSrc' may be NULL if the source isn't involved):
  669. bSrcIsScreen = (((((rop4 >> 2) ^ (rop4)) & 0x3333) != 0) &&
  670. (psoSrc->iType != STYPE_BITMAP));
  671. if (bSrcIsScreen)
  672. {
  673. // We need to create a copy of the source rectangle:
  674. hsurfSrc = (HSURF) EngCreateBitmap(sizl, 0, ppdev->iBitmapFormat,
  675. 0, NULL);
  676. if (hsurfSrc == 0)
  677. goto Error_0;
  678. psoSrc = EngLockSurface(hsurfSrc);
  679. if (psoSrc == NULL)
  680. goto Error_1;
  681. rclTmp.left = 0;
  682. rclTmp.top = 0;
  683. rclTmp.right = sizl.cx;
  684. rclTmp.bottom = sizl.cy;
  685. // ppdev->pfnGetBits takes absolute coordinates for the source point:
  686. ptlSrc.x += ppdev->xOffset;
  687. ptlSrc.y += ppdev->yOffset;
  688. ppdev->pfnGetBits(ppdev, psoSrc, &rclTmp, &ptlSrc);
  689. // The source will now come from (0, 0) of our temporary source
  690. // surface:
  691. ptlSrc.x = 0;
  692. ptlSrc.y = 0;
  693. }
  694. if (psoDst->iType == STYPE_BITMAP)
  695. {
  696. b = EngBitBlt(psoDst, psoSrc, psoMsk, pco, pxlo, &rclDst, &ptlSrc,
  697. pptlMsk, pbo, pptlBrush, rop4);
  698. }
  699. else
  700. {
  701. // We need to create a temporary work buffer. We have to do
  702. // some fudging with the offsets so that the upper-left corner
  703. // of the (relative coordinates) clip object bounds passed to
  704. // GDI will be transformed to the upper-left corner of our
  705. // temporary bitmap.
  706. // The alignment doesn't have to be as tight as this at 16bpp
  707. // and 32bpp, but it won't hurt:
  708. lDelta = ppdev->cBpp * (((rclDst.right + 3) & ~3L) -
  709. ((rclDst.left) & ~3L));
  710. // We're actually only allocating a bitmap that is 'sizl.cx' x
  711. // 'sizl.cy' in size:
  712. pjBits = EngAllocMem(0, lDelta * sizl.cy, ALLOC_TAG);
  713. if (pjBits == NULL)
  714. goto Error_2;
  715. // We now adjust the surface's 'pvScan0' so that when GDI thinks
  716. // it's writing to pixel (rclDst.top, rclDst.left), it will
  717. // actually be writing to the upper-left pixel of our temporary
  718. // bitmap:
  719. pjScan0 = pjBits - (rclDst.top * lDelta)
  720. - (ppdev->cBpp * (rclDst.left & ~3L));
  721. ASSERTDD((((ULONG_PTR) pjScan0) & 3) == 0,
  722. "pvScan0 must be dword aligned!");
  723. // The checked build of GDI sometimes checks on blts that
  724. // prclDst->right <= pso->sizl.cx, so we lie to it about
  725. // the size of our bitmap:
  726. sizl.cx = rclDst.right;
  727. sizl.cy = rclDst.bottom;
  728. hsurfDst = (HSURF) EngCreateBitmap(
  729. sizl, // Bitmap covers rectangle
  730. lDelta, // Use this delta
  731. ppdev->iBitmapFormat, // Same colour depth
  732. BMF_TOPDOWN, // Must have a positive delta
  733. pjScan0); // Where (0, 0) would be
  734. if ((hsurfDst == 0) ||
  735. (!EngAssociateSurface(hsurfDst, ppdev->hdevEng, 0)))
  736. goto Error_3;
  737. psoDst = EngLockSurface(hsurfDst);
  738. if (psoDst == NULL)
  739. goto Error_4;
  740. // Make sure that the rectangle we Get/Put from/to the screen
  741. // is in absolute coordinates:
  742. rclScreen.left = rclDst.left + ppdev->xOffset;
  743. rclScreen.right = rclDst.right + ppdev->xOffset;
  744. rclScreen.top = rclDst.top + ppdev->yOffset;
  745. rclScreen.bottom = rclDst.bottom + ppdev->yOffset;
  746. // It would be nice to get a copy of the destination rectangle
  747. // only when the ROP involves the destination (or when the source
  748. // is an RLE), but we can't do that. If the brush is truly NULL,
  749. // GDI will immediately return TRUE from EngBitBlt, without
  750. // modifying the temporary bitmap -- and we would proceed to
  751. // copy the uninitialized temporary bitmap back to the screen.
  752. ppdev->pfnGetBits(ppdev, psoDst, &rclDst, (POINTL*) &rclScreen);
  753. b = EngBitBlt(psoDst, psoSrc, psoMsk, pco, pxlo, &rclDst, &ptlSrc,
  754. pptlMsk, pbo, pptlBrush, rop4);
  755. ppdev->pfnPutBits(ppdev, psoDst, &rclScreen, (POINTL*) &rclDst);
  756. EngUnlockSurface(psoDst);
  757. Error_4:
  758. EngDeleteSurface(hsurfDst);
  759. Error_3:
  760. EngFreeMem(pjBits);
  761. }
  762. Error_2:
  763. if (bSrcIsScreen)
  764. {
  765. EngUnlockSurface(psoSrc);
  766. Error_1:
  767. EngDeleteSurface(hsurfSrc);
  768. }
  769. Error_0:
  770. return(b);
  771. }
  772. #endif
  773. }
  774. /******************************Public*Routine******************************\
  775. * BOOL DrvBitBlt
  776. *
  777. * Implements the workhorse routine of a display driver.
  778. *
  779. \**************************************************************************/
  780. BOOL DrvBitBlt(
  781. SURFOBJ* psoDst,
  782. SURFOBJ* psoSrc,
  783. SURFOBJ* psoMsk,
  784. CLIPOBJ* pco,
  785. XLATEOBJ* pxlo,
  786. RECTL* prclDst,
  787. POINTL* pptlSrc,
  788. POINTL* pptlMsk,
  789. BRUSHOBJ* pbo,
  790. POINTL* pptlBrush,
  791. ROP4 rop4)
  792. {
  793. PDEV* ppdev;
  794. DSURF* pdsurfDst;
  795. DSURF* pdsurfSrc;
  796. POINTL ptlSrc;
  797. BYTE jClip;
  798. OH* poh;
  799. BOOL bMore;
  800. CLIPENUM ce;
  801. LONG c;
  802. RECTL rcl;
  803. BYTE rop3;
  804. FNFILL* pfnFill;
  805. RBRUSH_COLOR rbc; // Realized brush or solid colour
  806. FNXFER* pfnXfer;
  807. ULONG iSrcBitmapFormat;
  808. ULONG iDir;
  809. BOOL bRet;
  810. XLATECOLORS xlc;
  811. XLATEOBJ xlo;
  812. bRet = TRUE; // Assume success
  813. pdsurfDst = (DSURF*) psoDst->dhsurf; // May be NULL
  814. if (psoSrc == NULL)
  815. {
  816. ///////////////////////////////////////////////////////////////////
  817. // Fills
  818. ///////////////////////////////////////////////////////////////////
  819. // Fills are this function's "raison d'etre", so we handle them
  820. // as quickly as possible:
  821. ASSERTDD(pdsurfDst != NULL,
  822. "Expect only device destinations when no source");
  823. if (pdsurfDst->dt == DT_SCREEN)
  824. {
  825. ppdev = (PDEV*) psoDst->dhpdev;
  826. poh = pdsurfDst->poh;
  827. ppdev->xOffset = poh->x;
  828. ppdev->yOffset = poh->y;
  829. ppdev->xyOffset = poh->xy;
  830. // Make sure it doesn't involve a mask (i.e., it's really a
  831. // Rop3):
  832. rop3 = (BYTE) rop4;
  833. if ((BYTE) (rop4 >> 8) == rop3)
  834. {
  835. // Since 'psoSrc' is NULL, the rop3 had better not indicate
  836. // that we need a source.
  837. ASSERTDD((((rop4 >> 2) ^ (rop4)) & 0x33) == 0,
  838. "Need source but GDI gave us a NULL 'psoSrc'");
  839. // Fill_It:
  840. pfnFill = ppdev->pfnFillSolid; // Default to solid fill
  841. if ((((rop3 >> 4) ^ (rop3)) & 0xf) != 0)
  842. {
  843. // The rop says that a pattern is truly required
  844. // (blackness, for instance, doesn't need one):
  845. rbc.iSolidColor = pbo->iSolidColor;
  846. if (rbc.iSolidColor == -1)
  847. {
  848. if (ppdev->cBpp > 2)
  849. {
  850. // [HWBUG]
  851. goto Punt_It;
  852. }
  853. // Try and realize the pattern brush; by doing
  854. // this call-back, GDI will eventually call us
  855. // again through DrvRealizeBrush:
  856. rbc.prb = pbo->pvRbrush;
  857. if (rbc.prb == NULL)
  858. {
  859. rbc.prb = BRUSHOBJ_pvGetRbrush(pbo);
  860. if (rbc.prb == NULL)
  861. {
  862. // If we couldn't realize the brush, punt
  863. // the call (it may have been a non 8x8
  864. // brush or something, which we can't be
  865. // bothered to handle, so let GDI do the
  866. // drawing):
  867. goto Punt_It;
  868. }
  869. }
  870. pfnFill = ppdev->pfnFillPat;
  871. }
  872. }
  873. // Note that these 2 'if's are more efficient than
  874. // a switch statement:
  875. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  876. {
  877. pfnFill(ppdev, 1, prclDst, rop4, rbc, pptlBrush);
  878. goto All_Done;
  879. }
  880. else if (pco->iDComplexity == DC_RECT)
  881. {
  882. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  883. pfnFill(ppdev, 1, &rcl, rop4, rbc, pptlBrush);
  884. goto All_Done;
  885. }
  886. else
  887. {
  888. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  889. do {
  890. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG*) &ce);
  891. c = cIntersect(prclDst, ce.arcl, ce.c);
  892. if (c != 0)
  893. pfnFill(ppdev, c, ce.arcl, rop4, rbc, pptlBrush);
  894. } while (bMore);
  895. goto All_Done;
  896. }
  897. }
  898. }
  899. }
  900. jClip = (pco == NULL) ? DC_TRIVIAL : pco->iDComplexity;
  901. if ((psoSrc != NULL) && (psoSrc->dhsurf != NULL))
  902. {
  903. pdsurfSrc = (DSURF*) psoSrc->dhsurf;
  904. if (pdsurfSrc->dt == DT_DIB)
  905. {
  906. // Here we consider putting a DIB DFB back into off-screen
  907. // memory. If there's a translate, it's probably not worth
  908. // moving since we won't be able to use the hardware to do
  909. // the blt (a similar argument could be made for weird rops
  910. // and stuff that we'll only end up having GDI simulate, but
  911. // those should happen infrequently enough that I don't care).
  912. if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))
  913. {
  914. ppdev = (PDEV*) psoSrc->dhpdev;
  915. // See 'DrvCopyBits' for some more comments on how this
  916. // moving-it-back-into-off-screen-memory thing works:
  917. if (pdsurfSrc->iUniq == ppdev->iHeapUniq)
  918. {
  919. if (--pdsurfSrc->cBlt == 0)
  920. {
  921. if (bMoveDibToOffscreenDfbIfRoom(ppdev, pdsurfSrc))
  922. goto Continue_It;
  923. }
  924. }
  925. else
  926. {
  927. // Some space was freed up in off-screen memory,
  928. // so reset the counter for this DFB:
  929. pdsurfSrc->iUniq = ppdev->iHeapUniq;
  930. pdsurfSrc->cBlt = HEAP_COUNT_DOWN;
  931. }
  932. }
  933. psoSrc = pdsurfSrc->pso;
  934. // Handle the case where the source is a DIB DFB and the
  935. // destination is a regular bitmap:
  936. if (psoDst->dhsurf == NULL)
  937. goto EngBitBlt_It;
  938. }
  939. }
  940. Continue_It:
  941. if (pdsurfDst != NULL)
  942. {
  943. if (pdsurfDst->dt == DT_DIB)
  944. {
  945. psoDst = pdsurfDst->pso;
  946. // If the destination is a DIB, we can only handle this
  947. // call if the source is not a DIB:
  948. if ((psoSrc == NULL) || (psoSrc->dhsurf == NULL))
  949. goto EngBitBlt_It;
  950. }
  951. }
  952. // At this point, we know that either the source or the destination is
  953. // not a DIB. Check for a DFB to screen, DFB to DFB, or screen to DFB
  954. // case:
  955. if ((psoSrc != NULL) &&
  956. (psoDst->dhsurf != NULL) &&
  957. (psoSrc->dhsurf != NULL))
  958. {
  959. pdsurfSrc = (DSURF*) psoSrc->dhsurf;
  960. pdsurfDst = (DSURF*) psoDst->dhsurf;
  961. ASSERTDD(pdsurfSrc->dt == DT_SCREEN, "Expected screen source");
  962. ASSERTDD(pdsurfDst->dt == DT_SCREEN, "Expected screen destination");
  963. ptlSrc.x = pptlSrc->x - (pdsurfDst->poh->x - pdsurfSrc->poh->x);
  964. ptlSrc.y = pptlSrc->y - (pdsurfDst->poh->y - pdsurfSrc->poh->y);
  965. pptlSrc = &ptlSrc;
  966. }
  967. if (psoDst->dhsurf != NULL)
  968. {
  969. pdsurfDst = (DSURF*) psoDst->dhsurf;
  970. ppdev = (PDEV*) psoDst->dhpdev;
  971. ppdev->xOffset = pdsurfDst->poh->x;
  972. ppdev->yOffset = pdsurfDst->poh->y;
  973. ppdev->xyOffset = pdsurfDst->poh->xy;
  974. }
  975. else
  976. {
  977. pdsurfSrc = (DSURF*) psoSrc->dhsurf;
  978. ppdev = (PDEV*) psoSrc->dhpdev;
  979. ppdev->xOffset = pdsurfSrc->poh->x;
  980. ppdev->yOffset = pdsurfSrc->poh->y;
  981. ppdev->xyOffset = pdsurfSrc->poh->xy;
  982. }
  983. if (((rop4 >> 8) & 0xff) == (rop4 & 0xff))
  984. {
  985. // Since we've already handled the cases where the ROP4 is really
  986. // a ROP3 and no source is required, we can assert...
  987. ASSERTDD((psoSrc != NULL) && (pptlSrc != NULL),
  988. "Expected no-source case to already have been handled");
  989. ///////////////////////////////////////////////////////////////////
  990. // Bitmap transfers
  991. ///////////////////////////////////////////////////////////////////
  992. // Since the foreground and background ROPs are the same, we
  993. // don't have to worry about no stinking masks (it's a simple
  994. // Rop3).
  995. rop3 = (BYTE) rop4; // Make it into a Rop3 (we keep the rop4
  996. // around in case we decide to punt)
  997. if (psoDst->dhsurf != NULL)
  998. {
  999. // The destination is the screen:
  1000. if ((rop3 >> 4) == (rop3 & 0xf))
  1001. {
  1002. // The ROP3 doesn't require a pattern:
  1003. if (psoSrc->dhsurf == NULL)
  1004. {
  1005. //////////////////////////////////////////////////
  1006. // DIB-to-screen blt
  1007. iSrcBitmapFormat = psoSrc->iBitmapFormat;
  1008. if (iSrcBitmapFormat == BMF_1BPP)
  1009. {
  1010. pfnXfer = ppdev->pfnXfer1bpp;
  1011. goto Xfer_It;
  1012. }
  1013. else if ((iSrcBitmapFormat == ppdev->iBitmapFormat) &&
  1014. ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
  1015. {
  1016. if ((rop3 & 0xf) != 0xc)
  1017. {
  1018. pfnXfer = ppdev->pfnXferNative;
  1019. }
  1020. else
  1021. {
  1022. // Plain SRCCOPY blts will be somewhat faster
  1023. // if we go through the memory aperture:
  1024. pfnXfer = vXferNativeSrccopy;
  1025. }
  1026. goto Xfer_It;
  1027. }
  1028. else if ((iSrcBitmapFormat == BMF_4BPP) &&
  1029. (ppdev->iBitmapFormat == BMF_8BPP))
  1030. {
  1031. // !!!
  1032. // pfnXfer = ppdev->pfnXfer4bpp;
  1033. // goto Xfer_It;
  1034. }
  1035. }
  1036. else // psoSrc->dhsurf != NULL
  1037. {
  1038. if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))
  1039. {
  1040. //////////////////////////////////////////////////
  1041. // Screen-to-screen blt with no translate
  1042. if (jClip == DC_TRIVIAL)
  1043. {
  1044. (ppdev->pfnCopyBlt)(ppdev, 1, prclDst, rop4,
  1045. pptlSrc, prclDst);
  1046. goto All_Done;
  1047. }
  1048. else if (jClip == DC_RECT)
  1049. {
  1050. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  1051. {
  1052. (ppdev->pfnCopyBlt)(ppdev, 1, &rcl, rop4,
  1053. pptlSrc, prclDst);
  1054. }
  1055. goto All_Done;
  1056. }
  1057. else
  1058. {
  1059. // Don't forget that we'll have to draw the
  1060. // rectangles in the correct direction:
  1061. if (pptlSrc->y >= prclDst->top)
  1062. {
  1063. if (pptlSrc->x >= prclDst->left)
  1064. iDir = CD_RIGHTDOWN;
  1065. else
  1066. iDir = CD_LEFTDOWN;
  1067. }
  1068. else
  1069. {
  1070. if (pptlSrc->x >= prclDst->left)
  1071. iDir = CD_RIGHTUP;
  1072. else
  1073. iDir = CD_LEFTUP;
  1074. }
  1075. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
  1076. iDir, 0);
  1077. do {
  1078. bMore = CLIPOBJ_bEnum(pco, sizeof(ce),
  1079. (ULONG*) &ce);
  1080. c = cIntersect(prclDst, ce.arcl, ce.c);
  1081. if (c != 0)
  1082. {
  1083. (ppdev->pfnCopyBlt)(ppdev, c, ce.arcl,
  1084. rop4, pptlSrc, prclDst);
  1085. }
  1086. } while (bMore);
  1087. goto All_Done;
  1088. }
  1089. }
  1090. }
  1091. }
  1092. else if (psoSrc->iBitmapFormat == BMF_1BPP)
  1093. {
  1094. if ( 0 && // !!!
  1095. (rop4 == 0xE2E2) &&
  1096. (pbo->iSolidColor != 0xffffffff) &&
  1097. //pxlo must be non NULL since the rop is E2E2
  1098. (pxlo->pulXlate[0] == 0) &&
  1099. (pxlo->pulXlate[1] == (ULONG)((1 << (ppdev->cBpp * 8)) - 1)))
  1100. {
  1101. //
  1102. // A BitBlt with the rop E2E2 (DSPDxax), a monochrome
  1103. // source, a foreground color of white, and a background
  1104. // color of black is equivalent to a monochrome expansion
  1105. // with transparency. All ones in the source expand to
  1106. // the brush color, and all zeros in the source expand to
  1107. // the destination color.
  1108. //
  1109. xlo.pulXlate = (ULONG*) &xlc;
  1110. xlc.iForeColor = pbo->iSolidColor;
  1111. xlc.iBackColor = 0;
  1112. pxlo = &xlo;
  1113. rop4 = 0xccaa;
  1114. pfnXfer = ppdev->pfnXfer1bpp;
  1115. goto Xfer_It;
  1116. }
  1117. }
  1118. }
  1119. else
  1120. {
  1121. #if defined(_X86_)
  1122. {
  1123. // We special case screen to monochrome blts because they
  1124. // happen fairly often. We only handle SRCCOPY rops and
  1125. // monochrome destinations (to handle a true 1bpp DIB
  1126. // destination, we would have to do near-colour searches
  1127. // on every colour; as it is, the foreground colour gets
  1128. // mapped to '1', and everything else gets mapped to '0'):
  1129. if ((psoDst->iBitmapFormat == BMF_1BPP) &&
  1130. (rop3 == 0xcc) &&
  1131. (pxlo->flXlate & XO_TO_MONO) &&
  1132. (ppdev->iBitmapFormat != BMF_24BPP))
  1133. {
  1134. pfnXfer = vXferScreenTo1bpp;
  1135. psoSrc = psoDst; // A misnomer, I admit
  1136. goto Xfer_It;
  1137. }
  1138. }
  1139. #endif // i386
  1140. }
  1141. }
  1142. #if 0
  1143. // [WORK] - Implement transparent brushes and then uncomment this block
  1144. // and the Fill_It label above.
  1145. else if ((psoMsk == NULL) &&
  1146. (rop4 & 0xff00) == (0xaa00) &&
  1147. ((((rop4 >> 2) ^ (rop4)) & 0x33) == 0))
  1148. {
  1149. // The only time GDI will ask us to do a true rop4 using the brush
  1150. // mask is when the brush is 1bpp, and the background rop is AA
  1151. // (meaning it's a NOP):
  1152. rop3 = (BYTE) rop4;
  1153. goto Fill_It;
  1154. }
  1155. #endif
  1156. // Just fall through to Punt_It...
  1157. Punt_It:
  1158. bRet = bPuntBlt(psoDst,
  1159. psoSrc,
  1160. psoMsk,
  1161. pco,
  1162. pxlo,
  1163. prclDst,
  1164. pptlSrc,
  1165. pptlMsk,
  1166. pbo,
  1167. pptlBrush,
  1168. rop4);
  1169. goto All_Done;
  1170. //////////////////////////////////////////////////////////////////////
  1171. // Common bitmap transfer
  1172. Xfer_It:
  1173. if (jClip == DC_TRIVIAL)
  1174. {
  1175. pfnXfer(ppdev, 1, prclDst, rop4, psoSrc, pptlSrc, prclDst, pxlo);
  1176. goto All_Done;
  1177. }
  1178. else if (jClip == DC_RECT)
  1179. {
  1180. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  1181. pfnXfer(ppdev, 1, &rcl, rop4, psoSrc, pptlSrc, prclDst, pxlo);
  1182. goto All_Done;
  1183. }
  1184. else
  1185. {
  1186. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
  1187. CD_ANY, 0);
  1188. do {
  1189. bMore = CLIPOBJ_bEnum(pco, sizeof(ce),
  1190. (ULONG*) &ce);
  1191. c = cIntersect(prclDst, ce.arcl, ce.c);
  1192. if (c != 0)
  1193. {
  1194. pfnXfer(ppdev, c, ce.arcl, rop4, psoSrc,
  1195. pptlSrc, prclDst, pxlo);
  1196. }
  1197. } while (bMore);
  1198. goto All_Done;
  1199. }
  1200. ////////////////////////////////////////////////////////////////////////
  1201. // Common DIB blt
  1202. EngBitBlt_It:
  1203. // Our driver doesn't handle any blt's between two DIBs. Normally
  1204. // a driver doesn't have to worry about this, but we do because
  1205. // we have DFBs that may get moved from off-screen memory to a DIB,
  1206. // where we have GDI do all the drawing. GDI does DIB drawing at
  1207. // a reasonable speed (unless one of the surfaces is a device-
  1208. // managed surface...)
  1209. //
  1210. // If either the source or destination surface in an EngBitBlt
  1211. // call-back is a device-managed surface (meaning it's not a DIB
  1212. // that GDI can draw with), GDI will automatically allocate memory
  1213. // and call the driver's DrvCopyBits routine to create a DIB copy
  1214. // that it can use. So this means that this could handle all 'punts',
  1215. // and we could conceivably get rid of bPuntBlt. But this would have
  1216. // a bad performance impact because of the extra memory allocations
  1217. // and bitmap copies -- you really don't want to do this unless you
  1218. // have to (or your surface was created such that GDI can draw
  1219. // directly onto it) -- I've been burned by this because it's not
  1220. // obvious that the performance impact is so bad.
  1221. //
  1222. // That being said, we only call EngBitBlt when all the surfaces
  1223. // are DIBs:
  1224. bRet = EngBitBlt(psoDst, psoSrc, psoMsk, pco, pxlo, prclDst,
  1225. pptlSrc, pptlMsk, pbo, pptlBrush, rop4);
  1226. All_Done:
  1227. return(bRet);
  1228. }
  1229. /******************************Public*Routine******************************\
  1230. * BOOL DrvCopyBits
  1231. *
  1232. * Do fast bitmap copies.
  1233. *
  1234. * Note that GDI will (usually) automatically adjust the blt extents to
  1235. * adjust for any rectangular clipping, so we'll rarely see DC_RECT
  1236. * clipping in this routine (and as such, we don't bother special casing
  1237. * it).
  1238. *
  1239. * I'm not sure if the performance benefit from this routine is actually
  1240. * worth the increase in code size, since SRCCOPY BitBlts are hardly the
  1241. * most common drawing operation we'll get. But what the heck.
  1242. *
  1243. * It's faster to do straight SRCCOPY bitblt's through the memory
  1244. * aperture than to use the data transfer register; as such, this
  1245. * routine is the logical place to put this special case.
  1246. *
  1247. \**************************************************************************/
  1248. BOOL DrvCopyBits(
  1249. SURFOBJ* psoDst,
  1250. SURFOBJ* psoSrc,
  1251. CLIPOBJ* pco,
  1252. XLATEOBJ* pxlo,
  1253. RECTL* prclDst,
  1254. POINTL* pptlSrc)
  1255. {
  1256. PDEV* ppdev;
  1257. DSURF* pdsurfSrc;
  1258. DSURF* pdsurfDst;
  1259. RECTL rcl;
  1260. POINTL ptl;
  1261. OH* pohSrc;
  1262. OH* pohDst;
  1263. // DrvCopyBits is a fast-path for SRCCOPY blts. But it can still be
  1264. // pretty complicated: there can be translates, clipping, RLEs,
  1265. // bitmaps that aren't the same format as the screen, plus
  1266. // screen-to-screen, DIB-to-screen or screen-to-DIB operations,
  1267. // not to mention DFBs (device format bitmaps).
  1268. //
  1269. // Rather than making this routine almost as big as DrvBitBlt, I'll
  1270. // handle here only the speed-critical cases, and punt the rest to
  1271. // our DrvBitBlt routine.
  1272. //
  1273. // We'll try to handle anything that doesn't involve clipping:
  1274. if (((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL)) &&
  1275. ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
  1276. {
  1277. if (psoDst->dhsurf != NULL)
  1278. {
  1279. // We know the destination is either a DFB or the screen:
  1280. ppdev = (PDEV*) psoDst->dhpdev;
  1281. pdsurfDst = (DSURF*) psoDst->dhsurf;
  1282. // See if the source is a plain DIB:
  1283. if (psoSrc->dhsurf != NULL)
  1284. {
  1285. pdsurfSrc = (DSURF*) psoSrc->dhsurf;
  1286. // Make sure the destination is really the screen or an
  1287. // off-screen DFB (i.e., not a DFB that we've converted
  1288. // to a DIB):
  1289. if (pdsurfDst->dt == DT_SCREEN)
  1290. {
  1291. ASSERTDD(psoSrc->dhsurf != NULL, "Can't be a DIB");
  1292. if (pdsurfSrc->dt == DT_SCREEN)
  1293. {
  1294. Screen_To_Screen:
  1295. //////////////////////////////////////////////////////
  1296. // Screen-to-screen
  1297. ASSERTDD((psoSrc->dhsurf != NULL) &&
  1298. (pdsurfSrc->dt == DT_SCREEN) &&
  1299. (psoDst->dhsurf != NULL) &&
  1300. (pdsurfDst->dt == DT_SCREEN),
  1301. "Should be a screen-to-screen case");
  1302. // pfnCopyBlt takes relative coordinates (relative
  1303. // to the destination surface, that is), so we have
  1304. // to change the start point to be relative to the
  1305. // destination surface too:
  1306. pohSrc = pdsurfSrc->poh;
  1307. pohDst = pdsurfDst->poh;
  1308. ptl.x = pptlSrc->x - (pohDst->x - pohSrc->x);
  1309. ptl.y = pptlSrc->y - (pohDst->y - pohSrc->y);
  1310. ppdev->xOffset = pohDst->x;
  1311. ppdev->yOffset = pohDst->y;
  1312. ppdev->xyOffset = pohDst->xy;
  1313. (ppdev->pfnCopyBlt)(ppdev, 1, prclDst, 0xcccc, &ptl,
  1314. prclDst);
  1315. return(TRUE);
  1316. }
  1317. else // (pdsurfSrc->dt != DT_SCREEN)
  1318. {
  1319. // Ah ha, the source is a DFB that's really a DIB.
  1320. ASSERTDD(psoDst->dhsurf != NULL,
  1321. "Destination can't be a DIB here");
  1322. /////////////////////////////////////////////////////
  1323. // Put It Back Into Off-screen?
  1324. //
  1325. // We take this opportunity to decide if we want to
  1326. // put the DIB back into off-screen memory. This is
  1327. // a pretty good place to do it because we have to
  1328. // copy the bits to some portion of the screen,
  1329. // anyway. So we would incur only an extra screen-to-
  1330. // screen blt at this time, much of which will be
  1331. // over-lapped with the CPU.
  1332. //
  1333. // The simple approach we have taken is to move a DIB
  1334. // back into off-screen memory only if there's already
  1335. // room -- we won't throw stuff out to make space
  1336. // (because it's tough to know what ones to throw out,
  1337. // and it's easy to get into thrashing scenarios).
  1338. //
  1339. // Because it takes some time to see if there's room
  1340. // in off-screen memory, we only check one in
  1341. // HEAP_COUNT_DOWN times if there's room. To bias
  1342. // in favour of bitmaps that are often blt, the
  1343. // counters are reset every time any space is freed
  1344. // up in off-screen memory. We also don't bother
  1345. // checking if no space has been freed since the
  1346. // last time we checked for this DIB.
  1347. if (pdsurfSrc->iUniq == ppdev->iHeapUniq)
  1348. {
  1349. if (--pdsurfSrc->cBlt == 0)
  1350. {
  1351. if (bMoveDibToOffscreenDfbIfRoom(ppdev,
  1352. pdsurfSrc))
  1353. goto Screen_To_Screen;
  1354. }
  1355. }
  1356. else
  1357. {
  1358. // Some space was freed up in off-screen memory,
  1359. // so reset the counter for this DFB:
  1360. pdsurfSrc->iUniq = ppdev->iHeapUniq;
  1361. pdsurfSrc->cBlt = HEAP_COUNT_DOWN;
  1362. }
  1363. // Since the destination is definitely the screen,
  1364. // we don't have to worry about creating a DIB to
  1365. // DIB copy case (for which we would have to call
  1366. // EngCopyBits):
  1367. psoSrc = pdsurfSrc->pso;
  1368. goto DIB_To_Screen;
  1369. }
  1370. }
  1371. else // (pdsurfDst->dt != DT_SCREEN)
  1372. {
  1373. // Because the source is not a DIB, we don't have to
  1374. // worry about creating a DIB to DIB case here (although
  1375. // we'll have to check later to see if the source is
  1376. // really a DIB that's masquerading as a DFB...)
  1377. ASSERTDD(psoSrc->dhsurf != NULL,
  1378. "Source can't be a DIB here");
  1379. psoDst = pdsurfDst->pso;
  1380. goto Screen_To_DIB;
  1381. }
  1382. }
  1383. else if (psoSrc->iBitmapFormat == ppdev->iBitmapFormat)
  1384. {
  1385. // Make sure the destination is really the screen:
  1386. if (pdsurfDst->dt == DT_SCREEN)
  1387. {
  1388. DIB_To_Screen:
  1389. //////////////////////////////////////////////////////
  1390. // DIB-to-screen
  1391. ASSERTDD((psoDst->dhsurf != NULL) &&
  1392. (pdsurfDst->dt == DT_SCREEN) &&
  1393. (psoSrc->dhsurf == NULL) &&
  1394. (psoSrc->iBitmapFormat == ppdev->iBitmapFormat),
  1395. "Should be a DIB-to-screen case");
  1396. // ppdev->pfnPutBits takes absolute screen coordinates, so
  1397. // we have to muck with the destination rectangle:
  1398. pohDst = pdsurfDst->poh;
  1399. rcl.left = prclDst->left + pohDst->x;
  1400. rcl.right = prclDst->right + pohDst->x;
  1401. rcl.top = prclDst->top + pohDst->y;
  1402. rcl.bottom = prclDst->bottom + pohDst->y;
  1403. // We use the memory aperture to do the transfer,
  1404. // because that is supposed to be faster for SRCCOPY
  1405. // blts than using the data-transfer register:
  1406. ppdev->pfnPutBits(ppdev, psoSrc, &rcl, pptlSrc);
  1407. return(TRUE);
  1408. }
  1409. }
  1410. }
  1411. else // (psoDst->dhsurf == NULL)
  1412. {
  1413. Screen_To_DIB:
  1414. pdsurfSrc = (DSURF*) psoSrc->dhsurf;
  1415. ppdev = (PDEV*) psoSrc->dhpdev;
  1416. if (psoDst->iBitmapFormat == ppdev->iBitmapFormat)
  1417. {
  1418. if (pdsurfSrc->dt == DT_SCREEN)
  1419. {
  1420. //////////////////////////////////////////////////////
  1421. // Screen-to-DIB
  1422. ASSERTDD((psoSrc->dhsurf != NULL) &&
  1423. (pdsurfSrc->dt == DT_SCREEN) &&
  1424. (psoDst->dhsurf == NULL) &&
  1425. (psoDst->iBitmapFormat == ppdev->iBitmapFormat),
  1426. "Should be a screen-to-DIB case");
  1427. // ppdev->pfnGetBits takes absolute screen coordinates, so we have
  1428. // to muck with the source point:
  1429. pohSrc = pdsurfSrc->poh;
  1430. ptl.x = pptlSrc->x + pohSrc->x;
  1431. ptl.y = pptlSrc->y + pohSrc->y;
  1432. ppdev->pfnGetBits(ppdev, psoDst, prclDst, &ptl);
  1433. return(TRUE);
  1434. }
  1435. else
  1436. {
  1437. // The source is a DFB that's really a DIB. Since we
  1438. // know that the destination is a DIB, we've got a DIB
  1439. // to DIB operation, and should call EngCopyBits:
  1440. psoSrc = pdsurfSrc->pso;
  1441. goto EngCopyBits_It;
  1442. }
  1443. }
  1444. }
  1445. }
  1446. // We can't call DrvBitBlt if we've accidentally converted both
  1447. // surfaces to DIBs, because it isn't equipped to handle it:
  1448. ASSERTDD((psoSrc->dhsurf != NULL) ||
  1449. (psoDst->dhsurf != NULL),
  1450. "Accidentally converted both surfaces to DIBs");
  1451. /////////////////////////////////////////////////////////////////
  1452. // A DrvCopyBits is after all just a simplified DrvBitBlt:
  1453. return(DrvBitBlt(psoDst, psoSrc, NULL, pco, pxlo, prclDst, pptlSrc, NULL,
  1454. NULL, NULL, 0x0000CCCC));
  1455. EngCopyBits_It:
  1456. ASSERTDD((psoDst->dhsurf == NULL) &&
  1457. (psoSrc->dhsurf == NULL),
  1458. "Both surfaces should be DIBs to call EngCopyBits");
  1459. return(EngCopyBits(psoDst, psoSrc, pco, pxlo, prclDst, pptlSrc));
  1460. }