Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1476 lines
52 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. * !!! Change note about 'iType'
  8. *
  9. * Note: Since we've implemented device-bitmaps, any surface that GDI passes
  10. * to us can have 3 values for its 'iType': STYPE_BITMAP, STYPE_DEVICE
  11. * or STYPE_DEVBITMAP. We filter device-bitmaps that we've stored
  12. * as DIBs fairly high in the code, so after we adjust its 'pptlSrc',
  13. * we can treat STYPE_DEVBITMAP surfaces the same as STYPE_DEVICE
  14. * surfaces (e.g., a blt from an off-screen device bitmap to the screen
  15. * gets treated as a normal screen-to-screen blt). So throughout
  16. * this code, we will compare a surface's 'iType' to STYPE_BITMAP:
  17. * if it's equal, we've got a true DIB, and if it's unequal, we have
  18. * a screen-to-screen operation.
  19. *
  20. * Copyright (c) 1992-1995 Microsoft Corporation
  21. \**************************************************************************/
  22. #include "precomp.h"
  23. #define gbdPunt FALSE // global boolean define punt all BitBlt calls
  24. /******************************Public*Table********************************\
  25. * BYTE gajLeftMask[] and BYTE gajRightMask[]
  26. *
  27. * Edge tables for vXferScreenTo1bpp.
  28. \**************************************************************************/
  29. BYTE gajLeftMask[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
  30. BYTE gajRightMask[] = { 0xff, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
  31. /******************************Public*Routine******************************\
  32. * VOID vXferNativeSrccopy
  33. *
  34. * Does a SRCCOPY transfer of a bitmap to the screen using the frame
  35. * buffer, because on the ATI it's faster than using the data transfer
  36. * register.
  37. *
  38. \**************************************************************************/
  39. VOID vXferNativeSrccopy( // Type FNXFER
  40. PDEV* ppdev,
  41. LONG c, // Count of rectangles, can't be zero
  42. RECTL* prcl, // List of destination rectangles, in relative
  43. // coordinates
  44. ULONG rop4, // Not used
  45. SURFOBJ* psoSrc, // Source surface
  46. POINTL* pptlSrc, // Original unclipped source point
  47. RECTL* prclDst, // Original unclipped destination rectangle
  48. XLATEOBJ* pxlo) // Not used
  49. {
  50. LONG xOffset;
  51. LONG yOffset;
  52. LONG dx;
  53. LONG dy;
  54. RECTL rclDst;
  55. POINTL ptlSrc;
  56. ASSERTDD((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL),
  57. "Can handle trivial xlate only");
  58. ASSERTDD(psoSrc->iBitmapFormat == ppdev->iBitmapFormat,
  59. "Source must be same colour depth as screen");
  60. ASSERTDD(c > 0, "Can't handle zero rectangles");
  61. ASSERTDD(rop4 == 0xcccc, "Must be a SRCCOPY rop");
  62. xOffset = ppdev->xOffset;
  63. yOffset = ppdev->yOffset;
  64. dx = pptlSrc->x - prclDst->left;
  65. dy = pptlSrc->y - prclDst->top; // Add to destination to get source
  66. while (TRUE)
  67. {
  68. ptlSrc.x = prcl->left + dx;
  69. ptlSrc.y = prcl->top + dy;
  70. // 'pfnPutBits' takes only absolute coordinates, so add in the
  71. // off-screen bitmap offset here:
  72. rclDst.left = prcl->left + xOffset;
  73. rclDst.right = prcl->right + xOffset;
  74. rclDst.top = prcl->top + yOffset;
  75. rclDst.bottom = prcl->bottom + yOffset;
  76. ppdev->pfnPutBits(ppdev, psoSrc, &rclDst, &ptlSrc);
  77. if (--c == 0)
  78. return;
  79. prcl++;
  80. }
  81. }
  82. /******************************Public*Routine******************************\
  83. * VOID vXferScreenTo1bpp
  84. *
  85. * Performs a SRCCOPY transfer from the screen (when it's 8bpp) to a 1bpp
  86. * bitmap.
  87. *
  88. \**************************************************************************/
  89. #if defined(_X86_)
  90. VOID vXferScreenTo1bpp( // Type FNXFER
  91. PDEV* ppdev,
  92. LONG c, // Count of rectangles, can't be zero
  93. RECTL* prcl, // List of destination rectangles, in relative
  94. // coordinates
  95. ULONG ulHwMix, // Not used
  96. SURFOBJ* psoDst, // Destination surface
  97. POINTL* pptlSrc, // Original unclipped source point
  98. RECTL* prclDst, // Original unclipped destination rectangle
  99. XLATEOBJ* pxlo) // Provides colour-compressions information
  100. {
  101. LONG cjPelSize;
  102. VOID* pfnCompute;
  103. SURFOBJ soTmp;
  104. ULONG* pulXlate;
  105. ULONG ulForeColor;
  106. POINTL ptlSrc;
  107. RECTL rclTmp;
  108. BYTE* pjDst;
  109. BYTE jLeftMask;
  110. BYTE jRightMask;
  111. BYTE jNotLeftMask;
  112. BYTE jNotRightMask;
  113. LONG cjMiddle;
  114. LONG lDstDelta;
  115. LONG lSrcDelta;
  116. LONG cyTmpScans;
  117. LONG cyThis;
  118. LONG cyToGo;
  119. ASSERTDD(c > 0, "Can't handle zero rectangles");
  120. ASSERTDD(psoDst->iBitmapFormat == BMF_1BPP, "Only 1bpp destinations");
  121. ASSERTDD(TMP_BUFFER_SIZE >= (ppdev->cxMemory * ppdev->cjPelSize),
  122. "Temp buffer has to be larger than widest possible scan");
  123. // When the destination is a 1bpp bitmap, the foreground colour
  124. // maps to '1', and any other colour maps to '0'.
  125. if (ppdev->iBitmapFormat == BMF_8BPP)
  126. {
  127. // When the source is 8bpp or less, we find the forground colour
  128. // by searching the translate table for the only '1':
  129. pulXlate = pxlo->pulXlate;
  130. while (*pulXlate != 1)
  131. pulXlate++;
  132. ulForeColor = pulXlate - pxlo->pulXlate;
  133. }
  134. else
  135. {
  136. ASSERTDD((ppdev->iBitmapFormat == BMF_16BPP) ||
  137. (ppdev->iBitmapFormat == BMF_32BPP),
  138. "This routine only supports 8, 16 or 32bpp");
  139. // When the source has a depth greater than 8bpp, the foreground
  140. // colour will be the first entry in the translate table we get
  141. // from calling 'piVector':
  142. pulXlate = XLATEOBJ_piVector(pxlo);
  143. ulForeColor = 0;
  144. if (pulXlate != NULL) // This check isn't really needed...
  145. ulForeColor = pulXlate[0];
  146. }
  147. // We use the temporary buffer to keep a copy of the source
  148. // rectangle:
  149. soTmp.pvScan0 = ppdev->pvTmpBuffer;
  150. do {
  151. // ptlSrc points to the upper-left corner of the screen rectangle
  152. // for the current batch:
  153. ptlSrc.x = prcl->left + (pptlSrc->x - prclDst->left);
  154. ptlSrc.y = prcl->top + (pptlSrc->y - prclDst->top);
  155. // pfnGetBits takes absolute coordinates for the source point:
  156. ptlSrc.x += ppdev->xOffset;
  157. ptlSrc.y += ppdev->yOffset;
  158. pjDst = (BYTE*) psoDst->pvScan0 + (prcl->top * psoDst->lDelta)
  159. + (prcl->left >> 3);
  160. cjPelSize = ppdev->cjPelSize;
  161. soTmp.lDelta = (((prcl->right + 7L) & ~7L) - (prcl->left & ~7L))
  162. * cjPelSize;
  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 - ((8 * (cjMiddle + 2)) * cjPelSize);
  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,cjPelSize
  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. PDEV* dbg_ppdev;
  416. if (psoDst->dhpdev != NULL)
  417. dbg_ppdev = (PDEV*) psoDst->dhpdev;
  418. else
  419. dbg_ppdev = (PDEV*) psoSrc->dhpdev;
  420. ulClip = (pco == NULL) ? DC_TRIVIAL : pco->iDComplexity;
  421. DISPDBG((15, ">> Punt << Dst format: %li Dst type: %li Clip: %li Rop: %lx",
  422. psoDst->iBitmapFormat, psoDst->iType, ulClip, rop4));
  423. if (psoSrc != NULL)
  424. {
  425. DISPDBG((15, " << Src format: %li Src type: %li",
  426. psoSrc->iBitmapFormat, psoSrc->iType));
  427. if (psoSrc->iBitmapFormat == BMF_1BPP)
  428. {
  429. DISPDBG((15, " << Foreground: %lx Background: %lx",
  430. pxlo->pulXlate[1], pxlo->pulXlate[0]));
  431. }
  432. }
  433. if ((pxlo != NULL) && !(pxlo->flXlate & XO_TRIVIAL) && (psoSrc != NULL))
  434. {
  435. if (((psoSrc->dhsurf == NULL) &&
  436. (psoSrc->iBitmapFormat != dbg_ppdev->iBitmapFormat)) ||
  437. ((psoDst->dhsurf == NULL) &&
  438. (psoDst->iBitmapFormat != dbg_ppdev->iBitmapFormat)))
  439. {
  440. // Don't bother printing the 'xlate' message when the source
  441. // is a different bitmap format from the destination -- in
  442. // those cases we know there always has to be a translate.
  443. }
  444. else
  445. {
  446. DISPDBG((15, " << With xlate"));
  447. }
  448. }
  449. // If the rop4 requires a pattern, and it's a non-solid brush...
  450. if (((((rop4 >> 4) ^ (rop4)) & 0x0f0f) != 0) &&
  451. (pbo->iSolidColor == -1))
  452. {
  453. if (pbo->pvRbrush == NULL)
  454. DISPDBG((15, " << With brush -- Not created"));
  455. else
  456. DISPDBG((15, " << With brush -- Created Ok"));
  457. }
  458. }
  459. #endif
  460. if (DIRECT_ACCESS(ppdev))
  461. {
  462. //////////////////////////////////////////////////////////////////////
  463. // Banked Framebuffer bPuntBlt
  464. //
  465. // This section of code handles a PuntBlt when GDI can directly draw
  466. // on the framebuffer, but the drawing has to be done in banks:
  467. BANK bnk;
  468. BOOL b;
  469. HSURF hsurfTmp;
  470. SURFOBJ* psoTmp;
  471. SIZEL sizl;
  472. POINTL ptlSrc;
  473. RECTL rclTmp;
  474. RECTL rclDst;
  475. // We copy the original destination rectangle, and use that in every
  476. // GDI call-back instead of the original because sometimes GDI is
  477. // sneaky and points 'prclDst' to '&pco->rclBounds'. Because we
  478. // modify 'rclBounds', that would affect 'prclDst', which we don't
  479. // want to happen:
  480. rclDst = *prclDst;
  481. if ((psoSrc == NULL) || (psoSrc->iType == STYPE_BITMAP))
  482. {
  483. ASSERTDD(psoDst->iType != STYPE_BITMAP,
  484. "Dest should be the screen when given a DIB source");
  485. // Do a memory-to-screen blt:
  486. vBankStart(ppdev, &rclDst, pco, &bnk);
  487. b = TRUE;
  488. do {
  489. b &= EngBitBlt(bnk.pso, psoSrc, psoMsk, bnk.pco, pxlo,
  490. &rclDst, pptlSrc, pptlMsk, pbo, pptlBrush,
  491. rop4);
  492. } while (bBankEnum(&bnk));
  493. }
  494. else
  495. {
  496. b = FALSE; // Assume failure
  497. // The screen is the source (it may be the destination too...)
  498. ptlSrc.x = pptlSrc->x + ppdev->xOffset;
  499. ptlSrc.y = pptlSrc->y + ppdev->yOffset;
  500. if ((pco != NULL) && (pco->iDComplexity != DC_TRIVIAL))
  501. {
  502. // We have to intersect the destination rectangle with
  503. // the clip bounds if there is one (consider the case
  504. // where the app asked to blt a really, really big
  505. // rectangle from the screen -- prclDst would be really,
  506. // really big but pco->rclBounds would be the actual
  507. // area of interest):
  508. rclDst.left = max(rclDst.left, pco->rclBounds.left);
  509. rclDst.top = max(rclDst.top, pco->rclBounds.top);
  510. rclDst.right = min(rclDst.right, pco->rclBounds.right);
  511. rclDst.bottom = min(rclDst.bottom, pco->rclBounds.bottom);
  512. // Correspondingly, we have to offset the source point:
  513. ptlSrc.x += (rclDst.left - prclDst->left);
  514. ptlSrc.y += (rclDst.top - prclDst->top);
  515. }
  516. // We're now either going to do a screen-to-screen or screen-to-DIB
  517. // blt. In either case, we're going to create a temporary copy of
  518. // the source. (Why do we do this when GDI could do it for us?
  519. // GDI would create a temporary copy of the DIB for every bank
  520. // call-back!)
  521. sizl.cx = rclDst.right - rclDst.left;
  522. sizl.cy = rclDst.bottom - rclDst.top;
  523. // Don't forget to convert from relative to absolute coordinates
  524. // on the source! (vBankStart takes care of that for the
  525. // destination.)
  526. rclTmp.right = sizl.cx;
  527. rclTmp.bottom = sizl.cy;
  528. rclTmp.left = 0;
  529. rclTmp.top = 0;
  530. // GDI does guarantee us that the blt extents have already been
  531. // clipped to the surface boundaries (we don't have to worry
  532. // here about trying to read where there isn't video memory).
  533. // Let's just assert to make sure:
  534. ASSERTDD((ptlSrc.x >= 0) &&
  535. (ptlSrc.y >= 0) &&
  536. (ptlSrc.x + sizl.cx <= ppdev->cxMemory) &&
  537. (ptlSrc.y + sizl.cy <= ppdev->cyMemory),
  538. "Source rectangle out of bounds!");
  539. hsurfTmp = (HSURF) EngCreateBitmap(sizl,
  540. 0, // Let GDI choose ulWidth
  541. ppdev->iBitmapFormat,
  542. 0, // Don't need any options
  543. NULL);// Let GDI allocate
  544. if (hsurfTmp != 0)
  545. {
  546. psoTmp = EngLockSurface(hsurfTmp);
  547. if (psoTmp != NULL)
  548. {
  549. ppdev->pfnGetBits(ppdev, psoTmp, &rclTmp, &ptlSrc);
  550. if (psoDst->iType == STYPE_BITMAP)
  551. {
  552. // It was a Screen-to-DIB blt; now it's a DIB-to-DIB
  553. // blt. Note that the source point is (0, 0) in our
  554. // temporary surface:
  555. b = EngBitBlt(psoDst, psoTmp, psoMsk, pco, pxlo,
  556. &rclDst, (POINTL*) &rclTmp, pptlMsk,
  557. pbo, pptlBrush, rop4);
  558. }
  559. else
  560. {
  561. // It was a Screen-to-Screen blt; now it's a DIB-to-
  562. // screen blt. Note that the source point is (0, 0)
  563. // in our temporary surface:
  564. vBankStart(ppdev, &rclDst, pco, &bnk);
  565. b = TRUE;
  566. do {
  567. b &= EngBitBlt(bnk.pso, psoTmp, psoMsk, bnk.pco,
  568. pxlo, &rclDst, (POINTL*) &rclTmp,
  569. pptlMsk, pbo, pptlBrush, rop4);
  570. } while (bBankEnum(&bnk));
  571. }
  572. EngUnlockSurface(psoTmp);
  573. }
  574. EngDeleteSurface(hsurfTmp);
  575. }
  576. }
  577. return(b);
  578. }
  579. else
  580. {
  581. //////////////////////////////////////////////////////////////////////
  582. // Really Slow bPuntBlt
  583. //
  584. // Here we handle a PuntBlt when GDI can't draw directly on the
  585. // framebuffer (as on the Alpha, which can't do it because of its
  586. // 32 bit bus). If you thought the banked version was slow, just
  587. // look at this one. Guaranteed, there will be at least one bitmap
  588. // allocation and extra copy involved; there could be two if it's a
  589. // screen-to-screen operation.
  590. POINTL ptlSrc;
  591. RECTL rclDst;
  592. SIZEL sizl;
  593. BOOL bSrcIsScreen;
  594. HSURF hsurfSrc;
  595. RECTL rclTmp;
  596. BOOL b;
  597. LONG lDelta;
  598. BYTE* pjBits;
  599. BYTE* pjScan0;
  600. HSURF hsurfDst;
  601. RECTL rclScreen;
  602. b = FALSE; // For error cases, assume we'll fail
  603. rclDst = *prclDst;
  604. if (pptlSrc != NULL)
  605. ptlSrc = *pptlSrc;
  606. if ((pco != NULL) && (pco->iDComplexity != DC_TRIVIAL))
  607. {
  608. // We have to intersect the destination rectangle with
  609. // the clip bounds if there is one (consider the case
  610. // where the app asked to blt a really, really big
  611. // rectangle from the screen -- prclDst would be really,
  612. // really big but pco->rclBounds would be the actual
  613. // area of interest):
  614. rclDst.left = max(rclDst.left, pco->rclBounds.left);
  615. rclDst.top = max(rclDst.top, pco->rclBounds.top);
  616. rclDst.right = min(rclDst.right, pco->rclBounds.right);
  617. rclDst.bottom = min(rclDst.bottom, pco->rclBounds.bottom);
  618. ptlSrc.x += (rclDst.left - prclDst->left);
  619. ptlSrc.y += (rclDst.top - prclDst->top);
  620. }
  621. sizl.cx = rclDst.right - rclDst.left;
  622. sizl.cy = rclDst.bottom - rclDst.top;
  623. // We only need to make a copy from the screen if the source is
  624. // the screen, and the source is involved in the rop. Note that
  625. // we have to check the rop before dereferencing 'psoSrc'
  626. // (because 'psoSrc' may be NULL if the source isn't involved):
  627. bSrcIsScreen = (((((rop4 >> 2) ^ (rop4)) & 0x3333) != 0) &&
  628. (psoSrc->iType != STYPE_BITMAP));
  629. if (bSrcIsScreen)
  630. {
  631. // We need to create a copy of the source rectangle:
  632. hsurfSrc = (HSURF) EngCreateBitmap(sizl, 0, ppdev->iBitmapFormat,
  633. 0, NULL);
  634. if (hsurfSrc == 0)
  635. goto Error_0;
  636. psoSrc = EngLockSurface(hsurfSrc);
  637. if (psoSrc == NULL)
  638. goto Error_1;
  639. rclTmp.left = 0;
  640. rclTmp.top = 0;
  641. rclTmp.right = sizl.cx;
  642. rclTmp.bottom = sizl.cy;
  643. // pfnGetBits takes absolute coordinates for the source point:
  644. ptlSrc.x += ppdev->xOffset;
  645. ptlSrc.y += ppdev->yOffset;
  646. ppdev->pfnGetBits(ppdev, psoSrc, &rclTmp, &ptlSrc);
  647. // The source will now come from (0, 0) of our temporary source
  648. // surface:
  649. ptlSrc.x = 0;
  650. ptlSrc.y = 0;
  651. }
  652. if (psoDst->iType == STYPE_BITMAP)
  653. {
  654. b = EngBitBlt(psoDst, psoSrc, psoMsk, pco, pxlo, &rclDst, &ptlSrc,
  655. pptlMsk, pbo, pptlBrush, rop4);
  656. }
  657. else
  658. {
  659. // We need to create a temporary work buffer. We have to do
  660. // some fudging with the offsets so that the upper-left corner
  661. // of the (relative coordinates) clip object bounds passed to
  662. // GDI will be transformed to the upper-left corner of our
  663. // temporary bitmap.
  664. // The alignment doesn't have to be as tight as this at 16bpp
  665. // and 32bpp, but it won't hurt:
  666. lDelta = (((rclDst.right + 3) & ~3L) - (rclDst.left & ~3L))
  667. * ppdev->cjPelSize;
  668. // We're actually only allocating a bitmap that is 'sizl.cx' x
  669. // 'sizl.cy' in size:
  670. pjBits = AtiAllocMem(LMEM_FIXED, 0, lDelta * sizl.cy);
  671. if (pjBits == NULL)
  672. goto Error_2;
  673. // We now adjust the surface's 'pvScan0' so that when GDI thinks
  674. // it's writing to pixel (rclDst.top, rclDst.left), it will
  675. // actually be writing to the upper-left pixel of our temporary
  676. // bitmap:
  677. pjScan0 = pjBits - (rclDst.top * lDelta)
  678. - ((rclDst.left & ~3L) * ppdev->cjPelSize);
  679. ASSERTDD((((ULONG_PTR) pjScan0) & 3) == 0,
  680. "pvScan0 must be dword aligned!");
  681. // The checked build of GDI sometimes checks on blts that
  682. // prclDst->right <= pso->sizl.cx, so we lie to it about
  683. // the size of our bitmap:
  684. sizl.cx = rclDst.right;
  685. sizl.cy = rclDst.bottom;
  686. hsurfDst = (HSURF) EngCreateBitmap(
  687. sizl, // Bitmap covers rectangle
  688. lDelta, // Use this delta
  689. ppdev->iBitmapFormat, // Same colour depth
  690. BMF_TOPDOWN, // Must have a positive delta
  691. pjScan0); // Where (0, 0) would be
  692. if ((hsurfDst == 0) ||
  693. (!EngAssociateSurface(hsurfDst, ppdev->hdevEng, 0)))
  694. goto Error_3;
  695. psoDst = EngLockSurface(hsurfDst);
  696. if (psoDst == NULL)
  697. goto Error_4;
  698. // Make sure that the rectangle we Get/Put from/to the screen
  699. // is in absolute coordinates:
  700. rclScreen.left = rclDst.left + ppdev->xOffset;
  701. rclScreen.right = rclDst.right + ppdev->xOffset;
  702. rclScreen.top = rclDst.top + ppdev->yOffset;
  703. rclScreen.bottom = rclDst.bottom + ppdev->yOffset;
  704. // It would be nice to get a copy of the destination rectangle
  705. // only when the ROP involves the destination (or when the source
  706. // is an RLE), but we can't do that. If the brush is truly NULL,
  707. // GDI will immediately return TRUE from EngBitBlt, without
  708. // modifying the temporary bitmap -- and we would proceed to
  709. // copy the uninitialized temporary bitmap back to the screen.
  710. ppdev->pfnGetBits(ppdev, psoDst, &rclDst, (POINTL*) &rclScreen);
  711. b = EngBitBlt(psoDst, psoSrc, psoMsk, pco, pxlo, &rclDst, &ptlSrc,
  712. pptlMsk, pbo, pptlBrush, rop4);
  713. ppdev->pfnPutBits(ppdev, psoDst, &rclScreen, (POINTL*) &rclDst);
  714. EngUnlockSurface(psoDst);
  715. Error_4:
  716. EngDeleteSurface(hsurfDst);
  717. Error_3:
  718. AtiFreeMem(pjBits);
  719. }
  720. Error_2:
  721. if (bSrcIsScreen)
  722. {
  723. EngUnlockSurface(psoSrc);
  724. Error_1:
  725. EngDeleteSurface(hsurfSrc);
  726. }
  727. Error_0:
  728. return(b);
  729. }
  730. }
  731. /******************************Public*Routine******************************\
  732. * BOOL DrvBitBlt
  733. *
  734. * Implements the workhorse routine of a display driver.
  735. *
  736. \**************************************************************************/
  737. BOOL DrvBitBlt(
  738. SURFOBJ* psoDst,
  739. SURFOBJ* psoSrc,
  740. SURFOBJ* psoMsk,
  741. CLIPOBJ* pco,
  742. XLATEOBJ* pxlo,
  743. RECTL* prclDst,
  744. POINTL* pptlSrc,
  745. POINTL* pptlMsk,
  746. BRUSHOBJ* pbo,
  747. POINTL* pptlBrush,
  748. ROP4 rop4)
  749. {
  750. PDEV* ppdev;
  751. DSURF* pdsurfDst;
  752. DSURF* pdsurfSrc;
  753. POINTL ptlSrc;
  754. BYTE jClip;
  755. OH* poh;
  756. BOOL bMore;
  757. CLIPENUM ce;
  758. LONG c;
  759. RECTL rcl;
  760. BYTE rop3;
  761. FNFILL* pfnFill;
  762. RBRUSH_COLOR rbc; // Realized brush or solid colour
  763. FNXFER* pfnXfer;
  764. ULONG iSrcBitmapFormat;
  765. ULONG iDir;
  766. BOOL bRet;
  767. bRet = TRUE; // Assume success
  768. pdsurfDst = (DSURF*) psoDst->dhsurf; // May be NULL
  769. if ((psoSrc == NULL) && (gbdPunt == FALSE))
  770. {
  771. ///////////////////////////////////////////////////////////////////
  772. // Fills
  773. ///////////////////////////////////////////////////////////////////
  774. // Fills are this function's "raison d'etre", so we handle them
  775. // as quickly as possible:
  776. ASSERTDD(pdsurfDst != NULL,
  777. "Expect only device destinations when no source");
  778. if (pdsurfDst->dt == DT_SCREEN)
  779. {
  780. ppdev = (PDEV*) psoDst->dhpdev;
  781. poh = pdsurfDst->poh;
  782. ppdev->xOffset = poh->x;
  783. ppdev->yOffset = poh->y;
  784. // Make sure it doesn't involve a mask (i.e., it's really a
  785. // Rop3):
  786. rop3 = (BYTE) rop4;
  787. if ((BYTE) (rop4 >> 8) == rop3)
  788. {
  789. // Since 'psoSrc' is NULL, the rop3 had better not indicate
  790. // that we need a source.
  791. ASSERTDD((((rop4 >> 2) ^ (rop4)) & 0x33) == 0,
  792. "Need source but GDI gave us a NULL 'psoSrc'");
  793. Fill_It:
  794. pfnFill = ppdev->pfnFillSolid; // Default to solid fill
  795. if ((((rop3 >> 4) ^ (rop3)) & 0xf) != 0)
  796. {
  797. // The rop says that a pattern is truly required
  798. // (blackness, for instance, doesn't need one):
  799. rbc.iSolidColor = pbo->iSolidColor;
  800. if (rbc.iSolidColor == -1)
  801. {
  802. // Try and realize the pattern brush; by doing
  803. // this call-back, GDI will eventually call us
  804. // again through DrvRealizeBrush:
  805. rbc.prb = pbo->pvRbrush;
  806. if (rbc.prb == NULL)
  807. {
  808. rbc.prb = BRUSHOBJ_pvGetRbrush(pbo);
  809. if (rbc.prb == NULL)
  810. {
  811. // If we couldn't realize the brush, punt
  812. // the call (it may have been a non 8x8
  813. // brush or something, which we can't be
  814. // bothered to handle, so let GDI do the
  815. // drawing):
  816. goto Punt_It;
  817. }
  818. }
  819. pfnFill = rbc.prb->pfnFillPat;
  820. if ((ppdev->FeatureFlags & EVN_SDRAM_1M) &&
  821. (pfnFill == vM64FillPatColor || pfnFill == vM64FillPatColor24))
  822. {
  823. // The VTA4 can't handle color patterns correctly!!
  824. goto Punt_It;
  825. }
  826. }
  827. }
  828. // Note that these 2 'if's are more efficient than
  829. // a switch statement:
  830. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  831. {
  832. pfnFill(ppdev, 1, prclDst, rop4, rbc, pptlBrush);
  833. goto All_Done;
  834. }
  835. else if (pco->iDComplexity == DC_RECT)
  836. {
  837. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  838. pfnFill(ppdev, 1, &rcl, rop4, rbc, pptlBrush);
  839. goto All_Done;
  840. }
  841. else
  842. {
  843. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  844. do {
  845. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG*) &ce);
  846. c = cIntersect(prclDst, ce.arcl, ce.c);
  847. if (c != 0)
  848. pfnFill(ppdev, c, ce.arcl, rop4, rbc, pptlBrush);
  849. } while (bMore);
  850. goto All_Done;
  851. }
  852. }
  853. }
  854. }
  855. jClip = (pco == NULL) ? DC_TRIVIAL : pco->iDComplexity;
  856. if ((psoSrc != NULL) && (psoSrc->dhsurf != NULL))
  857. {
  858. pdsurfSrc = (DSURF*) psoSrc->dhsurf;
  859. if (pdsurfSrc->dt == DT_DIB)
  860. {
  861. // Here we consider putting a DIB DFB back into off-screen
  862. // memory. If there's a translate, it's probably not worth
  863. // moving since we won't be able to use the hardware to do
  864. // the blt (a similar argument could be made for weird rops
  865. // and stuff that we'll only end up having GDI simulate, but
  866. // those should happen infrequently enough that I don't care).
  867. if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))
  868. {
  869. ppdev = (PDEV*) psoSrc->dhpdev;
  870. // See 'DrvCopyBits' for some more comments on how this
  871. // moving-it-back-into-off-screen-memory thing works:
  872. if (pdsurfSrc->iUniq == ppdev->iHeapUniq)
  873. {
  874. if (--pdsurfSrc->cBlt == 0)
  875. {
  876. if (bMoveDibToOffscreenDfbIfRoom(ppdev, pdsurfSrc))
  877. goto Continue_It;
  878. }
  879. }
  880. else
  881. {
  882. // Some space was freed up in off-screen memory,
  883. // so reset the counter for this DFB:
  884. pdsurfSrc->iUniq = ppdev->iHeapUniq;
  885. pdsurfSrc->cBlt = HEAP_COUNT_DOWN;
  886. }
  887. }
  888. psoSrc = pdsurfSrc->pso;
  889. // Handle the case where the source is a DIB DFB and the
  890. // destination is a regular bitmap:
  891. if (psoDst->dhsurf == NULL)
  892. goto EngBitBlt_It;
  893. }
  894. }
  895. Continue_It:
  896. if (pdsurfDst != NULL)
  897. {
  898. if (pdsurfDst->dt == DT_DIB)
  899. {
  900. psoDst = pdsurfDst->pso;
  901. // If the destination is a DIB, we can only handle this
  902. // call if the source is not a DIB:
  903. if ((psoSrc == NULL) || (psoSrc->dhsurf == NULL))
  904. goto EngBitBlt_It;
  905. }
  906. }
  907. // At this point, we know that either the source or the destination is
  908. // not a DIB. Check for a DFB to screen, DFB to DFB, or screen to DFB
  909. // case:
  910. if ((psoSrc != NULL) &&
  911. (psoDst->dhsurf != NULL) &&
  912. (psoSrc->dhsurf != NULL))
  913. {
  914. pdsurfSrc = (DSURF*) psoSrc->dhsurf;
  915. pdsurfDst = (DSURF*) psoDst->dhsurf;
  916. ASSERTDD(pdsurfSrc->dt == DT_SCREEN, "Expected screen source");
  917. ASSERTDD(pdsurfDst->dt == DT_SCREEN, "Expected screen destination");
  918. ptlSrc.x = pptlSrc->x - (pdsurfDst->poh->x - pdsurfSrc->poh->x);
  919. ptlSrc.y = pptlSrc->y - (pdsurfDst->poh->y - pdsurfSrc->poh->y);
  920. pptlSrc = &ptlSrc;
  921. }
  922. if (psoDst->dhsurf != NULL)
  923. {
  924. pdsurfDst = (DSURF*) psoDst->dhsurf;
  925. ppdev = (PDEV*) psoDst->dhpdev;
  926. ppdev->xOffset = pdsurfDst->poh->x;
  927. ppdev->yOffset = pdsurfDst->poh->y;
  928. }
  929. else
  930. {
  931. DSURF * pTmpdsurfSrc = (DSURF*) psoSrc->dhsurf;
  932. ppdev = (PDEV*) psoSrc->dhpdev;
  933. if (!pTmpdsurfSrc) {
  934. DISPDBG((0, "bad surf in psoSrc:%x, from %x\n", psoSrc, pdsurfSrc));
  935. }
  936. ppdev->xOffset = pTmpdsurfSrc->poh->x;
  937. ppdev->yOffset = pTmpdsurfSrc->poh->y;
  938. }
  939. if (gbdPunt)
  940. {
  941. goto Punt_It;
  942. }
  943. if (((rop4 >> 8) & 0xff) == (rop4 & 0xff))
  944. {
  945. // Since we've already handled the cases where the ROP4 is really
  946. // a ROP3 and no source is required, we can assert...
  947. ASSERTDD((psoSrc != NULL) && (pptlSrc != NULL),
  948. "Expected no-source case to already have been handled");
  949. ///////////////////////////////////////////////////////////////////
  950. // Bitmap transfers
  951. ///////////////////////////////////////////////////////////////////
  952. // Since the foreground and background ROPs are the same, we
  953. // don't have to worry about no stinking masks (it's a simple
  954. // Rop3).
  955. rop3 = (BYTE) rop4; // Make it into a Rop3 (we keep the rop4
  956. // around in case we decide to punt)
  957. if (psoDst->dhsurf != NULL)
  958. {
  959. // The destination is the screen:
  960. if ((rop3 >> 4) == (rop3 & 0xf))
  961. {
  962. // The ROP3 doesn't require a pattern:
  963. if (psoSrc->dhsurf == NULL)
  964. {
  965. //////////////////////////////////////////////////
  966. // DIB-to-screen blt
  967. iSrcBitmapFormat = psoSrc->iBitmapFormat;
  968. if (iSrcBitmapFormat == BMF_1BPP)
  969. {
  970. //RKE: do this when we have time
  971. if (ppdev->iBitmapFormat == BMF_24BPP)
  972. goto Punt_It;
  973. pfnXfer = ppdev->pfnXfer1bpp;
  974. goto Xfer_It;
  975. }
  976. else if ((iSrcBitmapFormat == ppdev->iBitmapFormat) &&
  977. ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
  978. {
  979. if ((rop3 & 0xf) != 0xc)
  980. {
  981. pfnXfer = ppdev->pfnXferNative;
  982. }
  983. else
  984. {
  985. // Plain SRCCOPY blts will be somewhat faster on
  986. // the ATI if we go through the memory aperture:
  987. pfnXfer = vXferNativeSrccopy;
  988. }
  989. goto Xfer_It;
  990. }
  991. else if (ppdev->iBitmapFormat != BMF_24BPP)
  992. {
  993. // I can't be bothered to write 4bpp or 8bpp
  994. // expansion code when running at 24bpp:
  995. if (iSrcBitmapFormat == BMF_4BPP)
  996. {
  997. pfnXfer = ppdev->pfnXfer4bpp;
  998. goto Xfer_It;
  999. }
  1000. else if (iSrcBitmapFormat == BMF_8BPP)
  1001. {
  1002. pfnXfer = ppdev->pfnXfer8bpp;
  1003. goto Xfer_It;
  1004. }
  1005. }
  1006. }
  1007. else // psoSrc->dhsurf != NULL
  1008. {
  1009. if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))
  1010. {
  1011. //////////////////////////////////////////////////
  1012. // Screen-to-screen blt with no translate
  1013. if (jClip == DC_TRIVIAL)
  1014. {
  1015. (ppdev->pfnCopyBlt)(ppdev, 1, prclDst, rop4,
  1016. pptlSrc, prclDst);
  1017. goto All_Done;
  1018. }
  1019. else if (jClip == DC_RECT)
  1020. {
  1021. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  1022. {
  1023. (ppdev->pfnCopyBlt)(ppdev, 1, &rcl, rop4,
  1024. pptlSrc, prclDst);
  1025. }
  1026. goto All_Done;
  1027. }
  1028. else
  1029. {
  1030. // Don't forget that we'll have to draw the
  1031. // rectangles in the correct direction:
  1032. if (pptlSrc->y >= prclDst->top)
  1033. {
  1034. if (pptlSrc->x >= prclDst->left)
  1035. iDir = CD_RIGHTDOWN;
  1036. else
  1037. iDir = CD_LEFTDOWN;
  1038. }
  1039. else
  1040. {
  1041. if (pptlSrc->x >= prclDst->left)
  1042. iDir = CD_RIGHTUP;
  1043. else
  1044. iDir = CD_LEFTUP;
  1045. }
  1046. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
  1047. iDir, 0);
  1048. do {
  1049. bMore = CLIPOBJ_bEnum(pco, sizeof(ce),
  1050. (ULONG*) &ce);
  1051. c = cIntersect(prclDst, ce.arcl, ce.c);
  1052. if (c != 0)
  1053. {
  1054. (ppdev->pfnCopyBlt)(ppdev, c, ce.arcl,
  1055. rop4, pptlSrc, prclDst);
  1056. }
  1057. } while (bMore);
  1058. goto All_Done;
  1059. }
  1060. }
  1061. }
  1062. }
  1063. }
  1064. else
  1065. {
  1066. #if defined(_X86_)
  1067. {
  1068. // We special case screen to monochrome blts because they
  1069. // happen fairly often. We only handle SRCCOPY rops and
  1070. // monochrome destinations (to handle a true 1bpp DIB
  1071. // destination, we would have to do near-colour searches
  1072. // on every colour; as it is, the foreground colour gets
  1073. // mapped to '1', and everything else gets mapped to '0'):
  1074. if ((psoDst->iBitmapFormat == BMF_1BPP) &&
  1075. (rop3 == 0xcc) &&
  1076. (pxlo->flXlate & XO_TO_MONO) &&
  1077. (ppdev->iBitmapFormat != BMF_24BPP))
  1078. {
  1079. pfnXfer = vXferScreenTo1bpp;
  1080. psoSrc = psoDst; // A misnomer, I admit
  1081. goto Xfer_It;
  1082. }
  1083. }
  1084. #endif // i386
  1085. }
  1086. }
  1087. else if ((psoMsk == NULL) && (rop4 == 0xaacc))
  1088. {
  1089. // The only time GDI will ask us to do a true rop4 using the brush
  1090. // mask is when the brush is 1bpp, and the background rop is AA
  1091. // (meaning it's a NOP):
  1092. if (ppdev->flCaps & CAPS_MONOCHROME_PATTERNS)
  1093. {
  1094. // We only handle these if our ATI has hardware monochrome
  1095. // pattern capabilities:
  1096. rop3 = (BYTE) rop4;
  1097. goto Fill_It;
  1098. }
  1099. }
  1100. // Just fall through to Punt_It...
  1101. Punt_It:
  1102. bRet = bPuntBlt(psoDst,
  1103. psoSrc,
  1104. psoMsk,
  1105. pco,
  1106. pxlo,
  1107. prclDst,
  1108. pptlSrc,
  1109. pptlMsk,
  1110. pbo,
  1111. pptlBrush,
  1112. rop4);
  1113. goto All_Done;
  1114. //////////////////////////////////////////////////////////////////////
  1115. // Common bitmap transfer
  1116. Xfer_It:
  1117. if (jClip == DC_TRIVIAL)
  1118. {
  1119. pfnXfer(ppdev, 1, prclDst, rop4, psoSrc, pptlSrc, prclDst, pxlo);
  1120. goto All_Done;
  1121. }
  1122. else if (jClip == DC_RECT)
  1123. {
  1124. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  1125. pfnXfer(ppdev, 1, &rcl, rop4, psoSrc, pptlSrc, prclDst, pxlo);
  1126. goto All_Done;
  1127. }
  1128. else
  1129. {
  1130. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
  1131. CD_ANY, 0);
  1132. do {
  1133. bMore = CLIPOBJ_bEnum(pco, sizeof(ce),
  1134. (ULONG*) &ce);
  1135. c = cIntersect(prclDst, ce.arcl, ce.c);
  1136. if (c != 0)
  1137. {
  1138. pfnXfer(ppdev, c, ce.arcl, rop4, psoSrc,
  1139. pptlSrc, prclDst, pxlo);
  1140. }
  1141. } while (bMore);
  1142. goto All_Done;
  1143. }
  1144. ////////////////////////////////////////////////////////////////////////
  1145. // Common DIB blt
  1146. EngBitBlt_It:
  1147. // Our driver doesn't handle any blt's between two DIBs. Normally
  1148. // a driver doesn't have to worry about this, but we do because
  1149. // we have DFBs that may get moved from off-screen memory to a DIB,
  1150. // where we have GDI do all the drawing. GDI does DIB drawing at
  1151. // a reasonable speed (unless one of the surfaces is a device-
  1152. // managed surface...)
  1153. //
  1154. // If either the source or destination surface in an EngBitBlt
  1155. // call-back is a device-managed surface (meaning it's not a DIB
  1156. // that GDI can draw with), GDI will automatically allocate memory
  1157. // and call the driver's DrvCopyBits routine to create a DIB copy
  1158. // that it can use. So this means that this could handle all 'punts',
  1159. // and we could conceivably get rid of bPuntBlt. But this would have
  1160. // a bad performance impact because of the extra memory allocations
  1161. // and bitmap copies -- you really don't want to do this unless you
  1162. // have to (or your surface was created such that GDI can draw
  1163. // directly onto it) -- I've been burned by this because it's not
  1164. // obvious that the performance impact is so bad.
  1165. //
  1166. // That being said, we only call EngBitBlt when all the surfaces
  1167. // are DIBs:
  1168. bRet = EngBitBlt(psoDst, psoSrc, psoMsk, pco, pxlo, prclDst,
  1169. pptlSrc, pptlMsk, pbo, pptlBrush, rop4);
  1170. All_Done:
  1171. return(bRet);
  1172. }
  1173. /******************************Public*Routine******************************\
  1174. * BOOL DrvCopyBits
  1175. *
  1176. * Do fast bitmap copies.
  1177. *
  1178. * Note that GDI will (usually) automatically adjust the blt extents to
  1179. * adjust for any rectangular clipping, so we'll rarely see DC_RECT
  1180. * clipping in this routine (and as such, we don't bother special casing
  1181. * it).
  1182. *
  1183. * I'm not sure if the performance benefit from this routine is actually
  1184. * worth the increase in code size, since SRCCOPY BitBlts are hardly the
  1185. * most common drawing operation we'll get. But what the heck.
  1186. *
  1187. * On the ATI it's faster to do straight SRCCOPY bitblt's through the
  1188. * memory aperture than to use the data transfer register; as such, this
  1189. * routine is the logical place to put this special case.
  1190. *
  1191. \**************************************************************************/
  1192. BOOL DrvCopyBits(
  1193. SURFOBJ* psoDst,
  1194. SURFOBJ* psoSrc,
  1195. CLIPOBJ* pco,
  1196. XLATEOBJ* pxlo,
  1197. RECTL* prclDst,
  1198. POINTL* pptlSrc)
  1199. {
  1200. return(DrvBitBlt(psoDst, psoSrc, NULL, pco, pxlo, prclDst, pptlSrc, NULL,
  1201. NULL, NULL, 0xcccc));
  1202. }