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.

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