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.

2339 lines
87 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 'bltio.c'.
  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). So throughout
  14. * this code, we will compare a surface's 'iType' to STYPE_BITMAP:
  15. * if it's equal, we've got a true DIB, and if it's unequal, we have
  16. * a screen-to-screen operation.
  17. *
  18. * Copyright (c) 1992-1994 Microsoft Corporation
  19. *
  20. \**************************************************************************/
  21. #include "precomp.h"
  22. #if !GDI_BANKING || DBG
  23. // This table is big, so include it only when we need it...
  24. /******************************Public*Data*********************************\
  25. * ROP3 translation table
  26. *
  27. * Translates the usual ternary rop into A-vector notation. Each bit in
  28. * this new notation corresponds to a term in a polynomial translation of
  29. * the rop.
  30. *
  31. * Rop(D,S,P) = a + a D + a S + a P + a DS + a DP + a SP + a DSP
  32. * 0 d s p ds dp sp dsp
  33. *
  34. \**************************************************************************/
  35. BYTE gajRop3[] =
  36. {
  37. 0x00, 0xff, 0xb2, 0x4d, 0xd4, 0x2b, 0x66, 0x99,
  38. 0x90, 0x6f, 0x22, 0xdd, 0x44, 0xbb, 0xf6, 0x09,
  39. 0xe8, 0x17, 0x5a, 0xa5, 0x3c, 0xc3, 0x8e, 0x71,
  40. 0x78, 0x87, 0xca, 0x35, 0xac, 0x53, 0x1e, 0xe1,
  41. 0xa0, 0x5f, 0x12, 0xed, 0x74, 0x8b, 0xc6, 0x39,
  42. 0x30, 0xcf, 0x82, 0x7d, 0xe4, 0x1b, 0x56, 0xa9,
  43. 0x48, 0xb7, 0xfa, 0x05, 0x9c, 0x63, 0x2e, 0xd1,
  44. 0xd8, 0x27, 0x6a, 0x95, 0x0c, 0xf3, 0xbe, 0x41,
  45. 0xc0, 0x3f, 0x72, 0x8d, 0x14, 0xeb, 0xa6, 0x59,
  46. 0x50, 0xaf, 0xe2, 0x1d, 0x84, 0x7b, 0x36, 0xc9,
  47. 0x28, 0xd7, 0x9a, 0x65, 0xfc, 0x03, 0x4e, 0xb1,
  48. 0xb8, 0x47, 0x0a, 0xf5, 0x6c, 0x93, 0xde, 0x21,
  49. 0x60, 0x9f, 0xd2, 0x2d, 0xb4, 0x4b, 0x06, 0xf9,
  50. 0xf0, 0x0f, 0x42, 0xbd, 0x24, 0xdb, 0x96, 0x69,
  51. 0x88, 0x77, 0x3a, 0xc5, 0x5c, 0xa3, 0xee, 0x11,
  52. 0x18, 0xe7, 0xaa, 0x55, 0xcc, 0x33, 0x7e, 0x81,
  53. 0x80, 0x7f, 0x32, 0xcd, 0x54, 0xab, 0xe6, 0x19,
  54. 0x10, 0xef, 0xa2, 0x5d, 0xc4, 0x3b, 0x76, 0x89,
  55. 0x68, 0x97, 0xda, 0x25, 0xbc, 0x43, 0x0e, 0xf1,
  56. 0xf8, 0x07, 0x4a, 0xb5, 0x2c, 0xd3, 0x9e, 0x61,
  57. 0x20, 0xdf, 0x92, 0x6d, 0xf4, 0x0b, 0x46, 0xb9,
  58. 0xb0, 0x4f, 0x02, 0xfd, 0x64, 0x9b, 0xd6, 0x29,
  59. 0xc8, 0x37, 0x7a, 0x85, 0x1c, 0xe3, 0xae, 0x51,
  60. 0x58, 0xa7, 0xea, 0x15, 0x8c, 0x73, 0x3e, 0xc1,
  61. 0x40, 0xbf, 0xf2, 0x0d, 0x94, 0x6b, 0x26, 0xd9,
  62. 0xd0, 0x2f, 0x62, 0x9d, 0x04, 0xfb, 0xb6, 0x49,
  63. 0xa8, 0x57, 0x1a, 0xe5, 0x7c, 0x83, 0xce, 0x31,
  64. 0x38, 0xc7, 0x8a, 0x75, 0xec, 0x13, 0x5e, 0xa1,
  65. 0xe0, 0x1f, 0x52, 0xad, 0x34, 0xcb, 0x86, 0x79,
  66. 0x70, 0x8f, 0xc2, 0x3d, 0xa4, 0x5b, 0x16, 0xe9,
  67. 0x08, 0xf7, 0xba, 0x45, 0xdc, 0x23, 0x6e, 0x91,
  68. 0x98, 0x67, 0x2a, 0xd5, 0x4c, 0xb3, 0xfe, 0x01
  69. };
  70. BYTE gaRop3FromMix[] =
  71. {
  72. 0xFF, // R2_WHITE - Allow rop = gaRop3FromMix[mix & 0x0F]
  73. 0x00, // R2_BLACK
  74. 0x05, // R2_NOTMERGEPEN
  75. 0x0A, // R2_MASKNOTPEN
  76. 0x0F, // R2_NOTCOPYPEN
  77. 0x50, // R2_MASKPENNOT
  78. 0x55, // R2_NOT
  79. 0x5A, // R2_XORPEN
  80. 0x5F, // R2_NOTMASKPEN
  81. 0xA0, // R2_MASKPEN
  82. 0xA5, // R2_NOTXORPEN
  83. 0xAA, // R2_NOP
  84. 0xAF, // R2_MERGENOTPEN
  85. 0xF0, // R2_COPYPEN
  86. 0xF5, // R2_MERGEPENNOT
  87. 0xFA, // R2_MERGEPEN
  88. 0xFF // R2_WHITE - Allow rop = gaRop3FromMix[mix & 0xFF]
  89. };
  90. #define AVEC_NOT 0x01
  91. #define AVEC_D 0x02
  92. #define AVEC_S 0x04
  93. #define AVEC_P 0x08
  94. #define AVEC_DS 0x10
  95. #define AVEC_DP 0x20
  96. #define AVEC_SP 0x40
  97. #define AVEC_DSP 0x80
  98. #define AVEC_NEED_SOURCE (AVEC_S | AVEC_DS | AVEC_SP | AVEC_DSP)
  99. #define AVEC_NEED_PATTERN (AVEC_P | AVEC_DP | AVEC_SP | AVEC_DSP)
  100. #define AVEC_NEED_DEST (AVEC_D | AVEC_DS | AVEC_DP | AVEC_DSP)
  101. #endif // GDI_BANKING
  102. /******************************Public*Table********************************\
  103. * BYTE gaulHwMixFromRop2[]
  104. *
  105. * Table to convert from a Source and Destination Rop2 to the hardware's
  106. * mix.
  107. \**************************************************************************/
  108. ULONG gaulHwMixFromRop2[] = {
  109. LOGICAL_0, // 00 -- 0 BLACKNESS
  110. NOT_SCREEN_AND_NOT_NEW, // 11 -- DSon NOTSRCERASE
  111. SCREEN_AND_NOT_NEW, // 22 -- DSna
  112. NOT_NEW, // 33 -- Sn NOSRCCOPY
  113. NOT_SCREEN_AND_NEW, // 44 -- SDna SRCERASE
  114. NOT_SCREEN, // 55 -- Dn DSTINVERT
  115. SCREEN_XOR_NEW, // 66 -- DSx SRCINVERT
  116. NOT_SCREEN_OR_NOT_NEW, // 77 -- DSan
  117. SCREEN_AND_NEW, // 88 -- DSa SRCAND
  118. NOT_SCREEN_XOR_NEW, // 99 -- DSxn
  119. LEAVE_ALONE, // AA -- D
  120. SCREEN_OR_NOT_NEW, // BB -- DSno MERGEPAINT
  121. OVERPAINT, // CC -- S SRCCOPY
  122. NOT_SCREEN_OR_NEW, // DD -- SDno
  123. SCREEN_OR_NEW, // EE -- DSo SRCPAINT
  124. LOGICAL_1 // FF -- 1 WHITENESS
  125. };
  126. /******************************Public*Table********************************\
  127. * BYTE gajHwMixFromMix[]
  128. *
  129. * Table to convert from a GDI mix value to the hardware's mix.
  130. *
  131. * Ordered so that the mix may be calculated from gajHwMixFromMix[mix & 0xf]
  132. * or gajHwMixFromMix[mix & 0xff].
  133. \**************************************************************************/
  134. BYTE gajHwMixFromMix[] = {
  135. LOGICAL_1, // 0 -- 1
  136. LOGICAL_0, // 1 -- 0
  137. NOT_SCREEN_AND_NOT_NEW, // 2 -- DPon
  138. SCREEN_AND_NOT_NEW, // 3 -- DPna
  139. NOT_NEW, // 4 -- Pn
  140. NOT_SCREEN_AND_NEW, // 5 -- PDna
  141. NOT_SCREEN, // 6 -- Dn
  142. SCREEN_XOR_NEW, // 7 -- DPx
  143. NOT_SCREEN_OR_NOT_NEW, // 8 -- DPan
  144. SCREEN_AND_NEW, // 9 -- DPa
  145. NOT_SCREEN_XOR_NEW, // 10 -- DPxn
  146. LEAVE_ALONE, // 11 -- D
  147. SCREEN_OR_NOT_NEW, // 12 -- DPno
  148. OVERPAINT, // 13 -- P
  149. NOT_SCREEN_OR_NEW, // 14 -- PDno
  150. SCREEN_OR_NEW, // 15 -- DPo
  151. LOGICAL_1 // 16 -- 1
  152. };
  153. /******************************Public*Table********************************\
  154. * BYTE gajLeftMask[] and BYTE gajRightMask[]
  155. *
  156. * Edge tables for vXferScreenTo1bpp.
  157. \**************************************************************************/
  158. BYTE gajLeftMask[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
  159. BYTE gajRightMask[] = { 0xff, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
  160. /******************************Public*Routine******************************\
  161. * BOOL bIntersect
  162. *
  163. * If 'prcl1' and 'prcl2' intersect, has a return value of TRUE and returns
  164. * the intersection in 'prclResult'. If they don't intersect, has a return
  165. * value of FALSE, and 'prclResult' is undefined.
  166. *
  167. \**************************************************************************/
  168. BOOL bIntersect(
  169. RECTL* prcl1,
  170. RECTL* prcl2,
  171. RECTL* prclResult)
  172. {
  173. prclResult->left = max(prcl1->left, prcl2->left);
  174. prclResult->right = min(prcl1->right, prcl2->right);
  175. if (prclResult->left < prclResult->right)
  176. {
  177. prclResult->top = max(prcl1->top, prcl2->top);
  178. prclResult->bottom = min(prcl1->bottom, prcl2->bottom);
  179. if (prclResult->top < prclResult->bottom)
  180. {
  181. return(TRUE);
  182. }
  183. }
  184. return(FALSE);
  185. }
  186. /******************************Public*Routine******************************\
  187. * LONG cIntersect
  188. *
  189. * This routine takes a list of rectangles from 'prclIn' and clips them
  190. * in-place to the rectangle 'prclClip'. The input rectangles don't
  191. * have to intersect 'prclClip'; the return value will reflect the
  192. * number of input rectangles that did intersect, and the intersecting
  193. * rectangles will be densely packed.
  194. *
  195. \**************************************************************************/
  196. LONG cIntersect(
  197. RECTL* prclClip,
  198. RECTL* prclIn, // List of rectangles
  199. LONG c) // Can be zero
  200. {
  201. LONG cIntersections;
  202. RECTL* prclOut;
  203. cIntersections = 0;
  204. prclOut = prclIn;
  205. for (; c != 0; prclIn++, c--)
  206. {
  207. prclOut->left = max(prclIn->left, prclClip->left);
  208. prclOut->right = min(prclIn->right, prclClip->right);
  209. if (prclOut->left < prclOut->right)
  210. {
  211. prclOut->top = max(prclIn->top, prclClip->top);
  212. prclOut->bottom = min(prclIn->bottom, prclClip->bottom);
  213. if (prclOut->top < prclOut->bottom)
  214. {
  215. prclOut++;
  216. cIntersections++;
  217. }
  218. }
  219. }
  220. return(cIntersections);
  221. }
  222. /******************************Public*Routine******************************\
  223. * VOID vXferScreenTo1bpp
  224. *
  225. * Performs a SRCCOPY transfer from the screen (when it's 8bpp) to a 1bpp
  226. * bitmap.
  227. *
  228. \**************************************************************************/
  229. #if defined(i386)
  230. VOID vXferScreenTo1bpp( // Type FNXFER
  231. PDEV* ppdev,
  232. LONG c, // Count of rectangles, can't be zero
  233. RECTL* prcl, // List of destination rectangles, in relative
  234. // coordinates
  235. ULONG ulHwForeMix, // Not used
  236. ULONG ulHwBackMix, // Not used
  237. SURFOBJ* psoDst, // Destination surface
  238. POINTL* pptlSrc, // Original unclipped source point
  239. RECTL* prclDst, // Original unclipped destination rectangle
  240. XLATEOBJ* pxlo) // Provides colour-compressions information
  241. {
  242. LONG cPelSize;
  243. VOID* pfnCompute;
  244. SURFOBJ soTmp;
  245. ULONG* pulXlate;
  246. ULONG ulForeColor;
  247. POINTL ptlSrc;
  248. RECTL rclTmp;
  249. BYTE* pjDst;
  250. BYTE jLeftMask;
  251. BYTE jRightMask;
  252. BYTE jNotLeftMask;
  253. BYTE jNotRightMask;
  254. LONG cjMiddle;
  255. LONG lDstDelta;
  256. LONG lSrcDelta;
  257. LONG cyTmpScans;
  258. LONG cyThis;
  259. LONG cyToGo;
  260. ASSERTDD(c > 0, "Can't handle zero rectangles");
  261. ASSERTDD(psoDst->iBitmapFormat == BMF_1BPP, "Only 1bpp destinations");
  262. ASSERTDD(TMP_BUFFER_SIZE >= (ppdev->cxMemory << ppdev->cPelSize),
  263. "Temp buffer has to be larger than widest possible scan");
  264. // When the destination is a 1bpp bitmap, the foreground colour
  265. // maps to '1', and any other colour maps to '0'.
  266. if (ppdev->iBitmapFormat == BMF_8BPP)
  267. {
  268. // When the source is 8bpp or less, we find the forground colour
  269. // by searching the translate table for the only '1':
  270. pulXlate = pxlo->pulXlate;
  271. while (*pulXlate != 1)
  272. pulXlate++;
  273. ulForeColor = pulXlate - pxlo->pulXlate;
  274. }
  275. else
  276. {
  277. ASSERTDD((ppdev->iBitmapFormat == BMF_16BPP) ||
  278. (ppdev->iBitmapFormat == BMF_32BPP),
  279. "This routine only supports 8, 16 or 32bpp");
  280. // When the source has a depth greater than 8bpp, the foreground
  281. // colour will be the first entry in the translate table we get
  282. // from calling 'piVector':
  283. pulXlate = XLATEOBJ_piVector(pxlo);
  284. ulForeColor = 0;
  285. if (pulXlate != NULL) // This check isn't really needed...
  286. ulForeColor = pulXlate[0];
  287. }
  288. // We use the temporary buffer to keep a copy of the source
  289. // rectangle:
  290. soTmp.pvScan0 = ppdev->pvTmpBuffer;
  291. do {
  292. // ptlSrc points to the upper-left corner of the screen rectangle
  293. // for the current batch:
  294. ptlSrc.x = prcl->left + (pptlSrc->x - prclDst->left);
  295. ptlSrc.y = prcl->top + (pptlSrc->y - prclDst->top);
  296. // vGetBits takes absolute coordinates for the source point:
  297. ptlSrc.x += ppdev->xOffset;
  298. ptlSrc.y += ppdev->yOffset;
  299. pjDst = (BYTE*) psoDst->pvScan0 + (prcl->top * psoDst->lDelta)
  300. + (prcl->left >> 3);
  301. cPelSize = ppdev->cPelSize;
  302. soTmp.lDelta = (((prcl->right + 7L) & ~7L) - (prcl->left & ~7L))
  303. << cPelSize;
  304. // Our temporary buffer, into which we read a copy of the source,
  305. // may be smaller than the source rectangle. In that case, we
  306. // process the source rectangle in batches.
  307. //
  308. // cyTmpScans is the number of scans we can do in each batch.
  309. // cyToGo is the total number of scans we have to do for this
  310. // rectangle.
  311. //
  312. // We take the buffer size less four so that the right edge case
  313. // can safely read one dword past the end:
  314. cyTmpScans = (TMP_BUFFER_SIZE - 4) / soTmp.lDelta;
  315. cyToGo = prcl->bottom - prcl->top;
  316. ASSERTDD(cyTmpScans > 0, "Buffer too small for largest possible scan");
  317. // Initialize variables that don't change within the batch loop:
  318. rclTmp.top = 0;
  319. rclTmp.left = prcl->left & 7L;
  320. rclTmp.right = (prcl->right - prcl->left) + rclTmp.left;
  321. // Note that we have to be careful with the right mask so that it
  322. // isn't zero. A right mask of zero would mean that we'd always be
  323. // touching one byte past the end of the scan (even though we
  324. // wouldn't actually be modifying that byte), and we must never
  325. // access memory past the end of the bitmap (because we can access
  326. // violate if the bitmap end is exactly page-aligned).
  327. jLeftMask = gajLeftMask[rclTmp.left & 7];
  328. jRightMask = gajRightMask[rclTmp.right & 7];
  329. cjMiddle = ((rclTmp.right - 1) >> 3) - (rclTmp.left >> 3) - 1;
  330. if (cjMiddle < 0)
  331. {
  332. // The blt starts and ends in the same byte:
  333. jLeftMask &= jRightMask;
  334. jRightMask = 0;
  335. cjMiddle = 0;
  336. }
  337. jNotLeftMask = ~jLeftMask;
  338. jNotRightMask = ~jRightMask;
  339. lDstDelta = psoDst->lDelta - cjMiddle - 2;
  340. // Delta from the end of the destination
  341. // to the start on the next scan, accounting
  342. // for 'left' and 'right' bytes
  343. lSrcDelta = soTmp.lDelta - ((8 * (cjMiddle + 2)) << cPelSize);
  344. // Compute source delta for special cases
  345. // like when cjMiddle gets bumped up to '0',
  346. // and to correct aligned cases
  347. do {
  348. // This is the loop that breaks the source rectangle into
  349. // manageable batches.
  350. cyThis = cyTmpScans;
  351. cyToGo -= cyThis;
  352. if (cyToGo < 0)
  353. cyThis += cyToGo;
  354. rclTmp.bottom = cyThis;
  355. vGetBits(ppdev, &soTmp, &rclTmp, &ptlSrc);
  356. ptlSrc.y += cyThis; // Get ready for next batch loop
  357. _asm {
  358. mov eax,ulForeColor ;eax = foreground colour
  359. ;ebx = temporary storage
  360. ;ecx = count of middle dst bytes
  361. ;dl = destination byte accumulator
  362. ;dh = temporary storage
  363. mov esi,soTmp.pvScan0 ;esi = source pointer
  364. mov edi,pjDst ;edi = destination pointer
  365. ; Figure out the appropriate compute routine:
  366. mov ebx,cPelSize
  367. mov pfnCompute,offset Compute_Destination_Byte_From_8bpp
  368. dec ebx
  369. jl short Do_Left_Byte
  370. mov pfnCompute,offset Compute_Destination_Byte_From_16bpp
  371. dec ebx
  372. jl short Do_Left_Byte
  373. mov pfnCompute,offset Compute_Destination_Byte_From_32bpp
  374. Do_Left_Byte:
  375. call pfnCompute
  376. and dl,jLeftMask
  377. mov dh,jNotLeftMask
  378. and dh,[edi]
  379. or dh,dl
  380. mov [edi],dh
  381. inc edi
  382. mov ecx,cjMiddle
  383. dec ecx
  384. jl short Do_Right_Byte
  385. Do_Middle_Bytes:
  386. call pfnCompute
  387. mov [edi],dl
  388. inc edi
  389. dec ecx
  390. jge short Do_Middle_Bytes
  391. Do_Right_Byte:
  392. call pfnCompute
  393. and dl,jRightMask
  394. mov dh,jNotRightMask
  395. and dh,[edi]
  396. or dh,dl
  397. mov [edi],dh
  398. inc edi
  399. add edi,lDstDelta
  400. add esi,lSrcDelta
  401. dec cyThis
  402. jnz short Do_Left_Byte
  403. mov pjDst,edi ;save for next batch
  404. jmp All_Done
  405. Compute_Destination_Byte_From_8bpp:
  406. mov bl,[esi]
  407. sub bl,al
  408. cmp bl,1
  409. adc dl,dl ;bit 0
  410. mov bl,[esi+1]
  411. sub bl,al
  412. cmp bl,1
  413. adc dl,dl ;bit 1
  414. mov bl,[esi+2]
  415. sub bl,al
  416. cmp bl,1
  417. adc dl,dl ;bit 2
  418. mov bl,[esi+3]
  419. sub bl,al
  420. cmp bl,1
  421. adc dl,dl ;bit 3
  422. mov bl,[esi+4]
  423. sub bl,al
  424. cmp bl,1
  425. adc dl,dl ;bit 4
  426. mov bl,[esi+5]
  427. sub bl,al
  428. cmp bl,1
  429. adc dl,dl ;bit 5
  430. mov bl,[esi+6]
  431. sub bl,al
  432. cmp bl,1
  433. adc dl,dl ;bit 6
  434. mov bl,[esi+7]
  435. sub bl,al
  436. cmp bl,1
  437. adc dl,dl ;bit 7
  438. add esi,8 ;advance the source
  439. ret
  440. Compute_Destination_Byte_From_16bpp:
  441. mov bx,[esi]
  442. sub bx,ax
  443. cmp bx,1
  444. adc dl,dl ;bit 0
  445. mov bx,[esi+2]
  446. sub bx,ax
  447. cmp bx,1
  448. adc dl,dl ;bit 1
  449. mov bx,[esi+4]
  450. sub bx,ax
  451. cmp bx,1
  452. adc dl,dl ;bit 2
  453. mov bx,[esi+6]
  454. sub bx,ax
  455. cmp bx,1
  456. adc dl,dl ;bit 3
  457. mov bx,[esi+8]
  458. sub bx,ax
  459. cmp bx,1
  460. adc dl,dl ;bit 4
  461. mov bx,[esi+10]
  462. sub bx,ax
  463. cmp bx,1
  464. adc dl,dl ;bit 5
  465. mov bx,[esi+12]
  466. sub bx,ax
  467. cmp bx,1
  468. adc dl,dl ;bit 6
  469. mov bx,[esi+14]
  470. sub bx,ax
  471. cmp bx,1
  472. adc dl,dl ;bit 7
  473. add esi,16 ;advance the source
  474. ret
  475. Compute_Destination_Byte_From_32bpp:
  476. mov ebx,[esi]
  477. sub ebx,eax
  478. cmp ebx,1
  479. adc dl,dl ;bit 0
  480. mov ebx,[esi+4]
  481. sub ebx,eax
  482. cmp ebx,1
  483. adc dl,dl ;bit 1
  484. mov ebx,[esi+8]
  485. sub ebx,eax
  486. cmp ebx,1
  487. adc dl,dl ;bit 2
  488. mov ebx,[esi+12]
  489. sub ebx,eax
  490. cmp ebx,1
  491. adc dl,dl ;bit 3
  492. mov ebx,[esi+16]
  493. sub ebx,eax
  494. cmp ebx,1
  495. adc dl,dl ;bit 4
  496. mov ebx,[esi+20]
  497. sub ebx,eax
  498. cmp ebx,1
  499. adc dl,dl ;bit 5
  500. mov ebx,[esi+24]
  501. sub ebx,eax
  502. cmp ebx,1
  503. adc dl,dl ;bit 6
  504. mov ebx,[esi+28]
  505. sub ebx,eax
  506. cmp ebx,1
  507. adc dl,dl ;bit 7
  508. add esi,32 ;advance the source
  509. ret
  510. All_Done:
  511. }
  512. } while (cyToGo > 0);
  513. prcl++;
  514. } while (--c != 0);
  515. }
  516. #endif // i386
  517. /******************************Public*Routine******************************\
  518. * VOID vMaskRopB8orE2
  519. *
  520. * Performs a 'b8' or 'e2' rop3 when the source is 1bpp or the same colour
  521. * depth as the display with no translate (can be either a DIB or off-screen
  522. * DFB). Uses the hardware in three passes.
  523. *
  524. \**************************************************************************/
  525. VOID vMaskRopB8orE2( // Type FNMASK
  526. PDEV* ppdev,
  527. LONG c, // Can't be zero
  528. RECTL* prcl, // List of destination rectangles, in relative
  529. // coordinates
  530. ULONG ulHwForeMix, // SCREEN_AND_NEW if rop b8,
  531. // SCREEN_AND_NOT_NEW if rop e2
  532. ULONG ulHwBackMix, // Not used
  533. SURFOBJ* psoMsk, // Not used
  534. POINTL* pptlMsk, // Not used
  535. SURFOBJ* psoSrc, // Source surface of blt (1bpp or native)
  536. POINTL* pptlSrc, // Original unclipped source point
  537. RECTL* prclDst, // Original unclipped destination rectangle
  538. ULONG iSolidColor, // Colour, 0xffffffff is pattern should be used
  539. RBRUSH* prb, // Pointer to our brush realization, if needed
  540. POINTL* pptlBrush, // Pattern alignment if needed
  541. XLATEOBJ* pxlo) // Translation data if needed
  542. {
  543. FNFILL* pfnFill;
  544. FNXFER* pfnXfer;
  545. RBRUSH_COLOR rbc;
  546. ASSERTDD((psoSrc->iType == STYPE_BITMAP) || !OVERLAP(prclDst, pptlSrc),
  547. "Can't overlap on screen-to-screen operations!");
  548. ASSERTDD((psoSrc->iBitmapFormat == BMF_1BPP) ||
  549. (pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL),
  550. "Can handle xlates only on 1bpp transfers");
  551. ASSERTDD((psoSrc->iBitmapFormat == BMF_1BPP) ||
  552. (psoSrc->iType != STYPE_BITMAP) ||
  553. (psoSrc->iBitmapFormat == ppdev->iBitmapFormat),
  554. "Can handle only 1bpp or native sources");
  555. ASSERTDD((ulHwForeMix == SCREEN_AND_NOT_NEW) ||
  556. (ulHwForeMix == SCREEN_AND_NEW),
  557. "Unexpected mix");
  558. if (iSolidColor != -1)
  559. {
  560. pfnFill = ppdev->pfnFillSolid;
  561. rbc.iSolidColor = iSolidColor;
  562. }
  563. else
  564. {
  565. pfnFill = ppdev->pfnFillPat;
  566. rbc.prb = prb;
  567. }
  568. // 'b8' is 'DSDPxax', and that's exactly what we do:
  569. pfnFill(ppdev, c, prcl, SCREEN_XOR_NEW, SCREEN_XOR_NEW, rbc, pptlBrush);
  570. if (psoSrc->iType != STYPE_BITMAP)
  571. ppdev->pfnCopyBlt(ppdev, c, prcl, ulHwForeMix, pptlSrc, prclDst);
  572. else
  573. {
  574. if (psoSrc->iBitmapFormat == BMF_1BPP)
  575. pfnXfer = ppdev->pfnXfer1bpp;
  576. else
  577. pfnXfer = ppdev->pfnXferNative;
  578. pfnXfer(ppdev, c, prcl, ulHwForeMix, ulHwForeMix, psoSrc, pptlSrc,
  579. prclDst, pxlo);
  580. }
  581. pfnFill(ppdev, c, prcl, SCREEN_XOR_NEW, SCREEN_XOR_NEW, rbc, pptlBrush);
  582. }
  583. /******************************Public*Routine******************************\
  584. * VOID vMaskRop69or96
  585. *
  586. * Performs a '69' or '96' rop3 when the source is 1bpp or the same colour
  587. * depth as the display with no translate (can be either a DIB or off-screen
  588. * DFB). Uses the hardware in two passes.
  589. *
  590. \**************************************************************************/
  591. VOID vMaskRop69or96( // Type FNMASK
  592. PDEV* ppdev,
  593. LONG c, // Can't be zero
  594. RECTL* prcl, // List of destination rectangles, in relative
  595. // coordinates
  596. ULONG ulHwForeMix, // NOT_SCREEN_XOR_NEW if rop 69,
  597. // SCREEN_XOR_NEW if rop 96
  598. ULONG ulHwBackMix, // Not used
  599. SURFOBJ* psoMsk, // Not used
  600. POINTL* pptlMsk, // Not used
  601. SURFOBJ* psoSrc, // Source surface of blt (1bpp or native)
  602. POINTL* pptlSrc, // Original unclipped source point
  603. RECTL* prclDst, // Original unclipped destination rectangle
  604. ULONG iSolidColor, // Colour, 0xffffffff is pattern should be used
  605. RBRUSH* prb, // Pointer to our brush realization, if needed
  606. POINTL* pptlBrush, // Pattern alignment if needed
  607. XLATEOBJ* pxlo) // Translation data if needed
  608. {
  609. FNFILL* pfnFill;
  610. FNXFER* pfnXfer;
  611. RBRUSH_COLOR rbc;
  612. ASSERTDD((psoSrc->iType == STYPE_BITMAP) || !OVERLAP(prclDst, pptlSrc),
  613. "Can't overlap on screen-to-screen operations!");
  614. ASSERTDD((psoSrc->iBitmapFormat == BMF_1BPP) ||
  615. (pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL),
  616. "Can handle xlates only on 1bpp transfers");
  617. ASSERTDD((psoSrc->iBitmapFormat == BMF_1BPP) ||
  618. (psoSrc->iType != STYPE_BITMAP) ||
  619. (psoSrc->iBitmapFormat == ppdev->iBitmapFormat),
  620. "Can handle only 1bpp or native sources");
  621. ASSERTDD((ulHwForeMix == NOT_SCREEN_XOR_NEW) ||
  622. (ulHwForeMix == SCREEN_XOR_NEW),
  623. "Unexpected mix");
  624. if (iSolidColor != -1)
  625. {
  626. pfnFill = ppdev->pfnFillSolid;
  627. rbc.iSolidColor = iSolidColor;
  628. }
  629. else
  630. {
  631. pfnFill = ppdev->pfnFillPat;
  632. rbc.prb = prb;
  633. }
  634. // '69' is 'PDSxxn', and that is exactly what we do:
  635. if (psoSrc->iType != STYPE_BITMAP)
  636. ppdev->pfnCopyBlt(ppdev, c, prcl, SCREEN_XOR_NEW, pptlSrc, prclDst);
  637. else
  638. {
  639. if (psoSrc->iBitmapFormat == BMF_1BPP)
  640. pfnXfer = ppdev->pfnXfer1bpp;
  641. else
  642. pfnXfer = ppdev->pfnXferNative;
  643. pfnXfer(ppdev, c, prcl, SCREEN_XOR_NEW, SCREEN_XOR_NEW, psoSrc, pptlSrc,
  644. prclDst, pxlo);
  645. }
  646. // XOR is commutative, but we do the bitmap transfer first so that
  647. // we don't have to sit around waiting for the patblt to finish:
  648. pfnFill(ppdev, c, prcl, ulHwForeMix, ulHwForeMix, rbc, pptlBrush);
  649. }
  650. /******************************Public*Routine******************************\
  651. * VOID vMaskRopAACCorCCAA
  652. *
  653. * Performs an 'AACC' or 'CCAA' simple MaskBlt in three passes using the
  654. * hardware when the source is in off-screen memory.
  655. *
  656. \**************************************************************************/
  657. VOID vMaskRopAACCorCCAA( // Type FNMASK
  658. PDEV* ppdev,
  659. LONG c, // Can't be zero
  660. RECTL* prcl, // Array of relative coordinates destination
  661. // rectangles
  662. ULONG ulHwForeMix, // Foreground mix
  663. ULONG ulHwBackMix, // Background mix
  664. SURFOBJ* psoMsk, // Mask surface
  665. POINTL* pptlMsk, // Original unclipped mask source point
  666. SURFOBJ* psoSrc, // Not used
  667. POINTL* pptlSrc, // Original unclipped source point
  668. RECTL* prclDst, // Original unclipped destination rectangle
  669. ULONG iSolidColor, // Not used
  670. RBRUSH* prb, // Not used
  671. POINTL* pptlBrush, // Not used
  672. XLATEOBJ* pxlo) // Not used
  673. {
  674. XLATEOBJ xlo;
  675. XLATECOLORS xlc;
  676. ASSERTDD(c > 0, "Can't handle zero rectangles");
  677. ASSERTDD(pptlMsk != NULL, "Can't have a NULL pptlmask");
  678. ASSERTDD(psoMsk->iBitmapFormat == BMF_1BPP, "Can only be a 1bpp mask");
  679. ASSERTDD(!OVERLAP(prclDst, pptlSrc), "Source and dest can't overlap!");
  680. ASSERTDD((ulHwForeMix == SCREEN_AND_NEW) ||
  681. (ulHwForeMix == SCREEN_AND_NOT_NEW),
  682. "Unexpected mix");
  683. // Fake up a translate:
  684. xlc.iForeColor = (ULONG) -1;
  685. xlc.iBackColor = 0;
  686. xlo.pulXlate = (ULONG*) &xlc;
  687. // First XOR the source, then AND the mask, then XOR the source again:
  688. ppdev->pfnCopyBlt(ppdev, c, prcl, SCREEN_XOR_NEW, pptlSrc, prclDst);
  689. ppdev->pfnXfer1bpp(ppdev, c, prcl, ulHwForeMix, ulHwForeMix, psoMsk,
  690. pptlMsk, prclDst, &xlo);
  691. ppdev->pfnCopyBlt(ppdev, c, prcl, SCREEN_XOR_NEW, pptlSrc, prclDst);
  692. }
  693. /******************************Public*Routine******************************\
  694. * BOOL bPuntBlt
  695. *
  696. * Has GDI do any drawing operations that we don't specifically handle
  697. * in the driver.
  698. *
  699. \**************************************************************************/
  700. BOOL bPuntBlt(
  701. SURFOBJ* psoDst,
  702. SURFOBJ* psoSrc,
  703. SURFOBJ* psoMsk,
  704. CLIPOBJ* pco,
  705. XLATEOBJ* pxlo,
  706. RECTL* prclDst,
  707. POINTL* pptlSrc,
  708. POINTL* pptlMsk,
  709. BRUSHOBJ* pbo,
  710. POINTL* pptlBrush,
  711. ROP4 rop4)
  712. {
  713. #if DBG
  714. {
  715. //////////////////////////////////////////////////////////////////////
  716. // Diagnostics
  717. //
  718. // Since calling the engine to do any drawing can be rather painful,
  719. // particularly when the source is an off-screen DFB (since GDI will
  720. // have to allocate a DIB and call us to make a temporary copy before
  721. // it can even start drawing), we'll try to avoid it as much as
  722. // possible.
  723. //
  724. // Here we simply spew out information describing the blt whenever
  725. // this routine gets called (checked builds only, of course):
  726. ULONG ulClip;
  727. PDEV* ppdev;
  728. ULONG ulAvec;
  729. if (psoDst->iType != STYPE_BITMAP)
  730. ppdev = (PDEV*) psoDst->dhpdev;
  731. else
  732. ppdev = (PDEV*) psoSrc->dhpdev;
  733. ulClip = (pco == NULL) ? DC_TRIVIAL : pco->iDComplexity;
  734. DISPDBG((1, ">> Punt << Dst format: %li Dst type: %li Clip: %li Rop: %lx",
  735. psoDst->iBitmapFormat, psoDst->iType, ulClip, rop4));
  736. if (psoSrc != NULL)
  737. DISPDBG((1, " << Src format: %li Src type: %li",
  738. psoSrc->iBitmapFormat, psoSrc->iType));
  739. if ((pxlo != NULL) && !(pxlo->flXlate & XO_TRIVIAL) && (psoSrc != NULL))
  740. {
  741. if (((psoSrc->iType == STYPE_BITMAP) &&
  742. (psoSrc->iBitmapFormat != ppdev->iBitmapFormat)) ||
  743. ((psoDst->iType == STYPE_BITMAP) &&
  744. (psoDst->iBitmapFormat != ppdev->iBitmapFormat)))
  745. {
  746. // Don't bother printing the 'xlate' message when the source
  747. // is a different bitmap format from the destination -- in
  748. // those cases we know there always has to be a translate.
  749. }
  750. else
  751. {
  752. DISPDBG((1, " << With xlate"));
  753. }
  754. }
  755. // The high 2 bytes of rop4 is not guaranteed to be zero. So in order
  756. // to get the low 8 bits as index, we have to &ffff before do >>
  757. ulAvec = gajRop3[rop4 & 0xff] | gajRop3[(rop4 & 0xffff) >> 8];
  758. if ((ulAvec & AVEC_NEED_PATTERN) && (pbo->iSolidColor == -1))
  759. {
  760. if (pbo->pvRbrush == NULL)
  761. DISPDBG((1, " << With brush -- Not created"));
  762. else
  763. DISPDBG((1, " << With brush -- Created Ok"));
  764. }
  765. }
  766. #endif
  767. #if GDI_BANKING
  768. {
  769. //////////////////////////////////////////////////////////////////////
  770. // Banked Framebuffer bPuntBlt
  771. //
  772. // This section of code handles a PuntBlt when GDI can directly draw
  773. // on the framebuffer, but the drawing has to be done in banks:
  774. BANK bnk;
  775. PDEV* ppdev;
  776. BOOL b;
  777. HSURF hsurfTmp;
  778. SURFOBJ* psoTmp;
  779. SIZEL sizl;
  780. POINTL ptlSrc;
  781. RECTL rclTmp;
  782. RECTL rclDst;
  783. // We copy the original destination rectangle, and use that in every
  784. // GDI call-back instead of the original because sometimes GDI is
  785. // sneaky and points 'prclDst' to '&pco->rclBounds'. Because we
  786. // modify 'rclBounds', that would affect 'prclDst', which we don't
  787. // want to happen:
  788. rclDst = *prclDst;
  789. if ((psoSrc == NULL) || (psoSrc->iType == STYPE_BITMAP))
  790. {
  791. ASSERTDD(psoDst->iType != STYPE_BITMAP,
  792. "Dest should be the screen when given a DIB source");
  793. // Do a memory-to-screen blt:
  794. ppdev = (PDEV*) psoDst->dhpdev;
  795. vBankStart(ppdev, &rclDst, pco, &bnk);
  796. b = TRUE;
  797. do {
  798. b &= EngBitBlt(bnk.pso, psoSrc, psoMsk, bnk.pco, pxlo,
  799. &rclDst, pptlSrc, pptlMsk, pbo, pptlBrush,
  800. rop4);
  801. } while (bBankEnum(&bnk));
  802. }
  803. else
  804. {
  805. // The screen is the source (it may be the destination too...)
  806. ppdev = (PDEV*) psoSrc->dhpdev;
  807. ptlSrc.x = pptlSrc->x + ppdev->xOffset;
  808. ptlSrc.y = pptlSrc->y + ppdev->yOffset;
  809. if ((pco != NULL) && (pco->iDComplexity != DC_TRIVIAL))
  810. {
  811. // We have to intersect the destination rectangle with
  812. // the clip bounds if there is one (consider the case
  813. // where the app asked to blt a really, really big
  814. // rectangle from the screen -- prclDst would be really,
  815. // really big but pco->rclBounds would be the actual
  816. // area of interest):
  817. rclDst.left = max(rclDst.left, pco->rclBounds.left);
  818. rclDst.top = max(rclDst.top, pco->rclBounds.top);
  819. rclDst.right = min(rclDst.right, pco->rclBounds.right);
  820. rclDst.bottom = min(rclDst.bottom, pco->rclBounds.bottom);
  821. // Correspondingly, we have to offset the source point:
  822. ptlSrc.x += (rclDst.left - prclDst->left);
  823. ptlSrc.y += (rclDst.top - prclDst->top);
  824. }
  825. // We're now either going to do a screen-to-screen or screen-to-DIB
  826. // blt. In either case, we're going to create a temporary copy of
  827. // the source. (Why do we do this when GDI could do it for us?
  828. // GDI would create a temporary copy of the DIB for every bank
  829. // call-back!)
  830. sizl.cx = rclDst.right - rclDst.left;
  831. sizl.cy = rclDst.bottom - rclDst.top;
  832. // Don't forget to convert from relative to absolute coordinates
  833. // on the source! (vBankStart takes care of that for the
  834. // destination.)
  835. rclTmp.right = sizl.cx;
  836. rclTmp.bottom = sizl.cy;
  837. rclTmp.left = 0;
  838. rclTmp.top = 0;
  839. // GDI does guarantee us that the blt extents have already been
  840. // clipped to the surface boundaries (we don't have to worry
  841. // here about trying to read where there isn't video memory).
  842. // Let's just assert to make sure:
  843. ASSERTDD((ptlSrc.x >= 0) &&
  844. (ptlSrc.y >= 0) &&
  845. (ptlSrc.x + sizl.cx <= ppdev->cxMemory) &&
  846. (ptlSrc.y + sizl.cy <= ppdev->cyMemory),
  847. "Source rectangle out of bounds!");
  848. hsurfTmp = (HSURF) EngCreateBitmap(sizl,
  849. 0, // Let GDI choose ulWidth
  850. ppdev->iBitmapFormat,
  851. 0, // Don't need any options
  852. NULL);// Let GDI allocate
  853. if (hsurfTmp != 0)
  854. {
  855. psoTmp = EngLockSurface(hsurfTmp);
  856. if (psoTmp != NULL)
  857. {
  858. vGetBits(ppdev, psoTmp, &rclTmp, &ptlSrc);
  859. if (psoDst->iType == STYPE_BITMAP)
  860. {
  861. // It was a Screen-to-DIB blt; now it's a DIB-to-DIB
  862. // blt. Note that the source point is (0, 0) in our
  863. // temporary surface:
  864. b = EngBitBlt(psoDst, psoTmp, psoMsk, pco, pxlo,
  865. &rclDst, (POINTL*) &rclTmp, pptlMsk,
  866. pbo, pptlBrush, rop4);
  867. }
  868. else
  869. {
  870. // It was a Screen-to-Screen blt; now it's a DIB-to-
  871. // screen blt. Note that the source point is (0, 0)
  872. // in our temporary surface:
  873. vBankStart(ppdev, &rclDst, pco, &bnk);
  874. b = TRUE;
  875. do {
  876. b &= EngBitBlt(bnk.pso, psoTmp, psoMsk, bnk.pco,
  877. pxlo, &rclDst, (POINTL*) &rclTmp,
  878. pptlMsk, pbo, pptlBrush, rop4);
  879. } while (bBankEnum(&bnk));
  880. }
  881. EngUnlockSurface(psoTmp);
  882. }
  883. EngDeleteSurface(hsurfTmp);
  884. }
  885. }
  886. return(b);
  887. }
  888. #else
  889. {
  890. //////////////////////////////////////////////////////////////////////
  891. // Really Slow bPuntBlt
  892. //
  893. // Here we handle a PuntBlt when GDI can't draw directly on the
  894. // framebuffer (as on the Alpha, which can't do it because of its
  895. // 32 bit bus). If you thought the banked version was slow, just
  896. // look at this one. Guaranteed, there will be at least one bitmap
  897. // allocation and extra copy involved; there could be two if it's a
  898. // screen-to-screen operation.
  899. PDEV* ppdev;
  900. POINTL ptlSrc;
  901. RECTL rclDst;
  902. SIZEL sizl;
  903. ULONG ulAvec;
  904. BOOL bSrcIsScreen;
  905. HSURF hsurfSrc;
  906. RECTL rclTmp;
  907. BOOL b;
  908. LONG lDelta;
  909. BYTE* pjBits;
  910. BYTE* pjScan0;
  911. HSURF hsurfDst;
  912. RECTL rclScreen;
  913. b = FALSE; // Fore error cases, assume we'll fail
  914. rclDst = *prclDst;
  915. if (pptlSrc != NULL)
  916. ptlSrc = *pptlSrc;
  917. if ((pco != NULL) && (pco->iDComplexity != DC_TRIVIAL))
  918. {
  919. // We have to intersect the destination rectangle with
  920. // the clip bounds if there is one (consider the case
  921. // where the app asked to blt a really, really big
  922. // rectangle from the screen -- prclDst would be really,
  923. // really big but pco->rclBounds would be the actual
  924. // area of interest):
  925. rclDst.left = max(rclDst.left, pco->rclBounds.left);
  926. rclDst.top = max(rclDst.top, pco->rclBounds.top);
  927. rclDst.right = min(rclDst.right, pco->rclBounds.right);
  928. rclDst.bottom = min(rclDst.bottom, pco->rclBounds.bottom);
  929. ptlSrc.x += (rclDst.left - prclDst->left);
  930. ptlSrc.y += (rclDst.top - prclDst->top);
  931. }
  932. sizl.cx = rclDst.right - rclDst.left;
  933. sizl.cy = rclDst.bottom - rclDst.top;
  934. // The high 2 bytes of rop4 is not guaranteed to be zero. So in order
  935. // to get the low 8 bits as index, we have to &ffff before do >>
  936. ulAvec = gajRop3[rop4 & 0xff] | gajRop3[(rop4 & 0xffff) >> 8];
  937. bSrcIsScreen = ((ulAvec & AVEC_NEED_SOURCE) &&
  938. (psoSrc->iType != STYPE_BITMAP));
  939. if (bSrcIsScreen)
  940. {
  941. ppdev = (PDEV*) psoSrc->dhpdev;
  942. // We need to create a copy of the source rectangle:
  943. hsurfSrc = (HSURF) EngCreateBitmap(sizl, 0, ppdev->iBitmapFormat,
  944. 0, NULL);
  945. if (hsurfSrc == 0)
  946. goto Error_0;
  947. psoSrc = EngLockSurface(hsurfSrc);
  948. if (psoSrc == NULL)
  949. goto Error_1;
  950. rclTmp.left = 0;
  951. rclTmp.top = 0;
  952. rclTmp.right = sizl.cx;
  953. rclTmp.bottom = sizl.cy;
  954. // vGetBits takes absolute coordinates for the source point:
  955. ptlSrc.x += ppdev->xOffset;
  956. ptlSrc.y += ppdev->yOffset;
  957. vGetBits(ppdev, psoSrc, &rclTmp, &ptlSrc);
  958. // The source will now come from (0, 0) of our temporary source
  959. // surface:
  960. ptlSrc.x = 0;
  961. ptlSrc.y = 0;
  962. }
  963. if (psoDst->iType == STYPE_BITMAP)
  964. {
  965. b = EngBitBlt(psoDst, psoSrc, psoMsk, pco, pxlo, &rclDst, &ptlSrc,
  966. pptlMsk, pbo, pptlBrush, rop4);
  967. }
  968. else
  969. {
  970. ppdev = (PDEV*) psoDst->dhpdev;
  971. // We need to create a temporary work buffer. We have to do
  972. // some fudging with the offsets so that the upper-left corner
  973. // of the (relative coordinates) clip object bounds passed to
  974. // GDI will be transformed to the upper-left corner of our
  975. // temporary bitmap.
  976. // The alignment doesn't have to be as tight as this at 16bpp
  977. // and 32bpp, but it won't hurt:
  978. lDelta = (((rclDst.right + 3) & ~3L) - (rclDst.left & ~3L))
  979. << ppdev->cPelSize;
  980. // We're actually only allocating a bitmap that is 'sizl.cx' x
  981. // 'sizl.cy' in size:
  982. pjBits = EngAllocMem(0, lDelta * sizl.cy, ALLOC_TAG);
  983. if (pjBits == NULL)
  984. goto Error_2;
  985. // We now adjust the surface's 'pvScan0' so that when GDI thinks
  986. // it's writing to pixel (rclDst.top, rclDst.left), it will
  987. // actually be writing to the upper-left pixel of our temporary
  988. // bitmap:
  989. pjScan0 = pjBits - (rclDst.top * lDelta)
  990. - ((rclDst.left & ~3L) << ppdev->cPelSize);
  991. ASSERTDD((((ULONG) pjScan0) & 3) == 0,
  992. "pvScan0 must be dword aligned!");
  993. // The checked build of GDI sometimes checks on blts that
  994. // prclDst->right <= pso->sizl.cx, so we lie to it about
  995. // the size of our bitmap:
  996. sizl.cx = rclDst.right;
  997. sizl.cy = rclDst.bottom;
  998. hsurfDst = (HSURF) EngCreateBitmap(
  999. sizl, // Bitmap covers rectangle
  1000. lDelta, // Use this delta
  1001. ppdev->iBitmapFormat, // Same colour depth
  1002. BMF_TOPDOWN, // Must have a positive delta
  1003. pjScan0); // Where (0, 0) would be
  1004. if ((hsurfDst == 0) ||
  1005. (!EngAssociateSurface(hsurfDst, ppdev->hdevEng, 0)))
  1006. goto Error_3;
  1007. psoDst = EngLockSurface(hsurfDst);
  1008. if (psoDst == NULL)
  1009. goto Error_4;
  1010. // Make sure that the rectangle we Get/Put from/to the screen
  1011. // is in absolute coordinates:
  1012. rclScreen.left = rclDst.left + ppdev->xOffset;
  1013. rclScreen.right = rclDst.right + ppdev->xOffset;
  1014. rclScreen.top = rclDst.top + ppdev->yOffset;
  1015. rclScreen.bottom = rclDst.bottom + ppdev->yOffset;
  1016. // It would be nice to get a copy of the destination rectangle
  1017. // only when the ROP involves the destination (or when the source
  1018. // is an RLE), but we can't do that. If the brush is truly NULL,
  1019. // GDI will immediately return TRUE from EngBitBlt, without
  1020. // modifying the temporary bitmap -- and we would proceed to
  1021. // copy the uninitialized temporary bitmap back to the screen.
  1022. vGetBits(ppdev, psoDst, &rclDst, (POINTL*) &rclScreen);
  1023. b = EngBitBlt(psoDst, psoSrc, psoMsk, pco, pxlo, &rclDst, &ptlSrc,
  1024. pptlMsk, pbo, pptlBrush, rop4);
  1025. vPutBits(ppdev, psoDst, &rclScreen, (POINTL*) &rclDst);
  1026. EngUnlockSurface(psoDst);
  1027. Error_4:
  1028. EngDeleteSurface(hsurfDst);
  1029. Error_3:
  1030. EngFreeMem(pjBits);
  1031. }
  1032. Error_2:
  1033. if (bSrcIsScreen)
  1034. {
  1035. EngUnlockSurface(psoSrc);
  1036. Error_1:
  1037. EngDeleteSurface(hsurfSrc);
  1038. }
  1039. Error_0:
  1040. return(b);
  1041. }
  1042. #endif
  1043. }
  1044. /******************************Public*Routine******************************\
  1045. * BOOL DrvBitBlt
  1046. *
  1047. * Implements the workhorse routine of a display driver.
  1048. *
  1049. \**************************************************************************/
  1050. BOOL DrvBitBlt(
  1051. SURFOBJ* psoDst,
  1052. SURFOBJ* psoSrc,
  1053. SURFOBJ* psoMsk,
  1054. CLIPOBJ* pco,
  1055. XLATEOBJ* pxlo,
  1056. RECTL* prclDst,
  1057. POINTL* pptlSrc,
  1058. POINTL* pptlMsk,
  1059. BRUSHOBJ* pbo,
  1060. POINTL* pptlBrush,
  1061. ROP4 rop4)
  1062. {
  1063. PDEV* ppdev;
  1064. DSURF* pdsurfDst;
  1065. DSURF* pdsurfSrc;
  1066. POINTL ptlSrc;
  1067. BYTE jClip;
  1068. BOOL bMore;
  1069. ULONG ulHwForeMix;
  1070. ULONG ulHwBackMix;
  1071. CLIPENUM ce;
  1072. LONG c;
  1073. RECTL rcl;
  1074. ULONG rop2;
  1075. ULONG rop3;
  1076. FNFILL* pfnFill;
  1077. FNMASK* pfnMask;
  1078. RBRUSH_COLOR rbc; // Realized brush or solid colour
  1079. ULONG iSolidColor;
  1080. RBRUSH* prb;
  1081. XLATECOLORS xlc;
  1082. XLATEOBJ xlo;
  1083. ULONG* pulXlate;
  1084. ULONG ulTmp;
  1085. FNXFER* pfnXfer;
  1086. ULONG iSrcBitmapFormat;
  1087. ULONG iDir;
  1088. jClip = (pco == NULL) ? DC_TRIVIAL : pco->iDComplexity;
  1089. if (psoSrc == NULL)
  1090. {
  1091. ///////////////////////////////////////////////////////////////////
  1092. // Fills
  1093. ///////////////////////////////////////////////////////////////////
  1094. // Fills are this function's "raison d'etre" (which is French
  1095. // for "purple armadillo"), so we handle them as quickly as
  1096. // possible:
  1097. pdsurfDst = (DSURF*) psoDst->dhsurf;
  1098. ASSERTDD((psoDst->iType == STYPE_DEVICE) ||
  1099. (psoDst->iType == STYPE_DEVBITMAP),
  1100. "Expect only device destinations when no source");
  1101. if (pdsurfDst->dt == DT_SCREEN)
  1102. {
  1103. ppdev = (PDEV*) psoDst->dhpdev;
  1104. ppdev->xOffset = pdsurfDst->poh->x;
  1105. ppdev->yOffset = pdsurfDst->poh->y;
  1106. // Make sure it doesn't involve a mask (i.e., it's really a
  1107. // Rop3):
  1108. if ((rop4 >> 8) == (rop4 & 0xff))
  1109. {
  1110. rop2 = (BYTE) (rop4 & 0xff);
  1111. // We now want to see if we can convert this Rop3 to a Rop2
  1112. // between the Destination and the Pattern. We could do
  1113. // a byte look-up on 'Rop3', but that would involve a
  1114. // 1/4 Kbyte table which sort of big. So we twiddle
  1115. // the bits of the Rop3 to get a Rop2.
  1116. if ((((rop2 >> 2) ^ (rop2)) & 0x33) == 0)
  1117. {
  1118. // The ROP3 doesn't require a source...
  1119. rop2 >>= 2;
  1120. rop2 &= 0xf; // Effectively rop2 between Dest and Pattern
  1121. // Admittedly, we're doing a lookup here to convert the
  1122. // rop2 to the hardware mix, but it's only 16 entries
  1123. // long:
  1124. ulHwForeMix = gaulHwMixFromRop2[rop2];
  1125. ulHwBackMix = ulHwForeMix;
  1126. ppdev->bRealizeTransparent = FALSE;
  1127. // The nice thing about the mix values for this hardware
  1128. // is that they are ordered so that values 0 through 3
  1129. // are the ones that don't require a source. So we can
  1130. // do a simple logical-and operation on the hardware mix
  1131. // to see if we need to get a brush:
  1132. // NOTE: The following check depends on the actual ordering
  1133. // of the mix values for the hardware! If your mixes
  1134. // are ordered differently, you may have to make this
  1135. // into a 16-case switch statement on (rop2 + 1),
  1136. // comparing it to each of the R2_ rops declared in
  1137. // windows.h.
  1138. Fill_It:
  1139. pfnFill = ppdev->pfnFillSolid;
  1140. if (ulHwForeMix & MIX_NEEDSPATTERN)
  1141. {
  1142. rbc.iSolidColor = pbo->iSolidColor;
  1143. if (rbc.iSolidColor == -1)
  1144. {
  1145. // Try and realize the pattern brush; by doing
  1146. // this call-back, GDI will eventually call us
  1147. // again through DrvRealizeBrush:
  1148. rbc.prb = pbo->pvRbrush;
  1149. if (rbc.prb == NULL)
  1150. {
  1151. rbc.prb = BRUSHOBJ_pvGetRbrush(pbo);
  1152. if (rbc.prb == NULL)
  1153. {
  1154. // If we couldn't realize the brush, punt
  1155. // the call (it may have been a non 8x8
  1156. // brush or something, which we can't be
  1157. // bothered to handle, so let GDI do the
  1158. // drawing):
  1159. goto Punt_It;
  1160. }
  1161. }
  1162. pfnFill = ppdev->pfnFillPat;
  1163. }
  1164. }
  1165. // Note that these 2 'if's are more efficient than
  1166. // a switch statement:
  1167. if (jClip == DC_TRIVIAL)
  1168. {
  1169. pfnFill(ppdev, 1, prclDst, ulHwForeMix, ulHwBackMix,
  1170. rbc, pptlBrush);
  1171. goto All_Done;
  1172. }
  1173. else if (jClip == DC_RECT)
  1174. {
  1175. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  1176. pfnFill(ppdev, 1, &rcl, ulHwForeMix, ulHwBackMix,
  1177. rbc, pptlBrush);
  1178. goto All_Done;
  1179. }
  1180. else
  1181. {
  1182. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
  1183. CD_ANY, 0);
  1184. do {
  1185. bMore = CLIPOBJ_bEnum(pco, sizeof(ce),
  1186. (ULONG*) &ce);
  1187. c = cIntersect(prclDst, ce.arcl, ce.c);
  1188. if (c != 0)
  1189. pfnFill(ppdev, c, ce.arcl, ulHwForeMix,
  1190. ulHwBackMix, rbc, pptlBrush);
  1191. } while (bMore);
  1192. goto All_Done;
  1193. }
  1194. }
  1195. }
  1196. }
  1197. }
  1198. if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVBITMAP))
  1199. {
  1200. pdsurfSrc = (DSURF*) psoSrc->dhsurf;
  1201. if (pdsurfSrc->dt == DT_DIB)
  1202. {
  1203. // Here we consider putting a DIB DFB back into off-screen
  1204. // memory. If there's a translate, it's probably not worth
  1205. // moving since we won't be able to use the hardware to do
  1206. // the blt (a similar argument could be made for weird rops
  1207. // and stuff that we'll only end up having GDI simulate, but
  1208. // those should happen infrequently enough that I don't care).
  1209. if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))
  1210. {
  1211. ppdev = (PDEV*) psoSrc->dhpdev;
  1212. // See 'DrvCopyBits' for some more comments on how this
  1213. // moving-it-back-into-off-screen-memory thing works:
  1214. if (pdsurfSrc->iUniq == ppdev->iHeapUniq)
  1215. {
  1216. if (--pdsurfSrc->cBlt == 0)
  1217. {
  1218. if (bMoveDibToOffscreenDfbIfRoom(ppdev, pdsurfSrc))
  1219. goto Continue_It;
  1220. }
  1221. }
  1222. else
  1223. {
  1224. // Some space was freed up in off-screen memory,
  1225. // so reset the counter for this DFB:
  1226. pdsurfSrc->iUniq = ppdev->iHeapUniq;
  1227. pdsurfSrc->cBlt = HEAP_COUNT_DOWN;
  1228. }
  1229. }
  1230. psoSrc = pdsurfSrc->pso;
  1231. // Handle the case where the source is a DIB DFB and the
  1232. // destination is a regular bitmap:
  1233. if (psoDst->iType == STYPE_BITMAP)
  1234. goto EngBitBlt_It;
  1235. }
  1236. }
  1237. Continue_It:
  1238. if (psoDst->iType == STYPE_DEVBITMAP)
  1239. {
  1240. pdsurfDst = (DSURF*) psoDst->dhsurf;
  1241. if (pdsurfDst->dt == DT_DIB)
  1242. {
  1243. psoDst = pdsurfDst->pso;
  1244. // If the destination is a DIB, we can only handle this
  1245. // call if the source is not a DIB:
  1246. if ((psoSrc == NULL) || (psoSrc->iType == STYPE_BITMAP))
  1247. goto EngBitBlt_It;
  1248. }
  1249. }
  1250. // At this point, we know that either the source or the destination is
  1251. // not a DIB. Check for a DFB to screen, DFB to DFB, or screen to DFB
  1252. // case:
  1253. if ((psoSrc != NULL) &&
  1254. (psoDst->iType != STYPE_BITMAP) &&
  1255. (psoSrc->iType != STYPE_BITMAP))
  1256. {
  1257. pdsurfSrc = (DSURF*) psoSrc->dhsurf;
  1258. pdsurfDst = (DSURF*) psoDst->dhsurf;
  1259. ASSERTDD(pdsurfSrc->dt == DT_SCREEN, "Expected screen source");
  1260. ASSERTDD(pdsurfDst->dt == DT_SCREEN, "Expected screen destination");
  1261. ptlSrc.x = pptlSrc->x - (pdsurfDst->poh->x - pdsurfSrc->poh->x);
  1262. ptlSrc.y = pptlSrc->y - (pdsurfDst->poh->y - pdsurfSrc->poh->y);
  1263. pptlSrc = &ptlSrc;
  1264. psoSrc = psoDst;
  1265. }
  1266. if (psoDst->iType != STYPE_BITMAP)
  1267. {
  1268. pdsurfDst = (DSURF*) psoDst->dhsurf;
  1269. ppdev = (PDEV*) psoDst->dhpdev;
  1270. ppdev->xOffset = pdsurfDst->poh->x;
  1271. ppdev->yOffset = pdsurfDst->poh->y;
  1272. }
  1273. else
  1274. {
  1275. pdsurfSrc = (DSURF*) psoSrc->dhsurf;
  1276. ppdev = (PDEV*) psoSrc->dhpdev;
  1277. ppdev->xOffset = pdsurfSrc->poh->x;
  1278. ppdev->yOffset = pdsurfSrc->poh->y;
  1279. }
  1280. if ((rop4 >> 8) == (rop4 & 0xff))
  1281. {
  1282. // Since we've already handled the cases where the ROP4 is really
  1283. // a ROP3 and no source is required, we can assert...
  1284. ASSERTDD((psoSrc != NULL) && (pptlSrc != NULL),
  1285. "Expected no-source case to already have been handled");
  1286. ///////////////////////////////////////////////////////////////////
  1287. // Bitmap transfers
  1288. ///////////////////////////////////////////////////////////////////
  1289. // Since the foreground and background ROPs are the same, we
  1290. // don't have to worry about no stinking masks (it's a simple
  1291. // Rop3).
  1292. rop3 = (rop4 & 0xff); // Make it into a Rop3 (we keep the rop4
  1293. // around in case we decide to punt)
  1294. if (psoDst->iType != STYPE_BITMAP)
  1295. {
  1296. // The destination is the screen:
  1297. if ((rop3 >> 4) == (rop3 & 0xf))
  1298. {
  1299. // The ROP3 doesn't require a pattern:
  1300. rop2 = rop3 & 0xf; // Make it into a Rop2
  1301. if (psoSrc->iType == STYPE_BITMAP)
  1302. {
  1303. //////////////////////////////////////////////////
  1304. // DIB-to-screen blt
  1305. // This section handles 1bpp, 4bpp and 8bpp sources.
  1306. // 1bpp should have 'ulHwForeMix' and 'ulHwBackMix' the
  1307. // same values, and 4bpp and 8bpp ignore 'ulHwBackMix'.
  1308. ulHwForeMix = gaulHwMixFromRop2[rop2];
  1309. ulHwBackMix = ulHwForeMix;
  1310. iSrcBitmapFormat = psoSrc->iBitmapFormat;
  1311. if (iSrcBitmapFormat == BMF_1BPP)
  1312. {
  1313. pfnXfer = ppdev->pfnXfer1bpp;
  1314. goto Xfer_It;
  1315. }
  1316. else if ((iSrcBitmapFormat == ppdev->iBitmapFormat) &&
  1317. ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
  1318. {
  1319. // Plain SRCCOPY blts will be somewhat faster on the S3
  1320. // if we go through the memory aperture, but
  1321. // DrvCopyBits should take care of that case, so we
  1322. // won't bother checking for it here.
  1323. pfnXfer = ppdev->pfnXferNative;
  1324. goto Xfer_It;
  1325. }
  1326. else if ((iSrcBitmapFormat == BMF_4BPP) &&
  1327. (ppdev->iBitmapFormat == BMF_8BPP))
  1328. {
  1329. pfnXfer = ppdev->pfnXfer4bpp;
  1330. goto Xfer_It;
  1331. }
  1332. }
  1333. else // psoSrc->iType != STYPE_BITMAP
  1334. {
  1335. if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))
  1336. {
  1337. //////////////////////////////////////////////////
  1338. // Screen-to-screen blt with no translate
  1339. ulHwForeMix = gaulHwMixFromRop2[rop2];
  1340. if (jClip == DC_TRIVIAL)
  1341. {
  1342. (ppdev->pfnCopyBlt)(ppdev, 1, prclDst, ulHwForeMix,
  1343. pptlSrc, prclDst);
  1344. goto All_Done;
  1345. }
  1346. else if (jClip == DC_RECT)
  1347. {
  1348. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  1349. {
  1350. (ppdev->pfnCopyBlt)(ppdev, 1, &rcl, ulHwForeMix,
  1351. pptlSrc, prclDst);
  1352. }
  1353. goto All_Done;
  1354. }
  1355. else
  1356. {
  1357. // Don't forget that we'll have to draw the
  1358. // rectangles in the correct direction:
  1359. if (pptlSrc->y >= prclDst->top)
  1360. {
  1361. if (pptlSrc->x >= prclDst->left)
  1362. iDir = CD_RIGHTDOWN;
  1363. else
  1364. iDir = CD_LEFTDOWN;
  1365. }
  1366. else
  1367. {
  1368. if (pptlSrc->x >= prclDst->left)
  1369. iDir = CD_RIGHTUP;
  1370. else
  1371. iDir = CD_LEFTUP;
  1372. }
  1373. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
  1374. iDir, 0);
  1375. do {
  1376. bMore = CLIPOBJ_bEnum(pco, sizeof(ce),
  1377. (ULONG*) &ce);
  1378. c = cIntersect(prclDst, ce.arcl, ce.c);
  1379. if (c != 0)
  1380. {
  1381. (ppdev->pfnCopyBlt)(ppdev, c, ce.arcl,
  1382. ulHwForeMix, pptlSrc, prclDst);
  1383. }
  1384. } while (bMore);
  1385. goto All_Done;
  1386. }
  1387. }
  1388. }
  1389. }
  1390. else if (psoSrc->iBitmapFormat == BMF_1BPP)
  1391. {
  1392. pulXlate = pxlo->pulXlate;
  1393. if (((pulXlate[0] == 0) && (pulXlate[1] == ppdev->ulWhite)) ||
  1394. ((pulXlate[1] == 0) && (pulXlate[0] == ppdev->ulWhite)))
  1395. {
  1396. // When the brush is solid, and the bitmap colours are
  1397. // black and white, we can handle any rop3 by converting
  1398. // it to a monochrome blt with separate foreground and
  1399. // background mixes.
  1400. //
  1401. // (Note that with the S3 801/805/928/964, we could handle
  1402. // patterns too, using the same trick we use in MaskCopy.
  1403. // This only works for black and white source bitmaps,
  1404. // which is the most common call, but unfortunately a
  1405. // certain program which benchmarks these rops messed up
  1406. // and gives non-black and white colours. Since I'll
  1407. // handle those cases using multiple passes, I won't
  1408. // bother to implement this special trick.)
  1409. ulHwForeMix = gaulHwMixFromRop2[((rop3 >> 4) & 0xC) |
  1410. ((rop3 >> 2) & 0x3)];
  1411. ulHwBackMix = gaulHwMixFromRop2[((rop3 >> 2) & 0xC) |
  1412. ((rop3 ) & 0x3)];
  1413. pptlMsk = pptlSrc;
  1414. psoMsk = psoSrc;
  1415. if (pulXlate[1] == 0)
  1416. {
  1417. ulTmp = ulHwForeMix;
  1418. ulHwForeMix = ulHwBackMix;
  1419. ulHwBackMix = ulTmp;
  1420. }
  1421. // Fall through if the brush isn't solid:
  1422. if ( (((ulHwForeMix | ulHwBackMix) & MIX_NEEDSPATTERN) == 0)
  1423. ||(pbo->iSolidColor != -1) )
  1424. {
  1425. goto Handle_Fill_Mask;
  1426. }
  1427. }
  1428. }
  1429. // Here we special case some often used rop3's that we can
  1430. // do in two or three passes using the hardware.
  1431. //
  1432. // We only handle 1bpp sources, or sources that are the same
  1433. // pixel depth as the screen (either a bitmap or an off-screen
  1434. // DFB) with no xlate:
  1435. if ((psoSrc->iBitmapFormat == BMF_1BPP) ||
  1436. (((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)) &&
  1437. ((psoSrc->iType != STYPE_BITMAP) ||
  1438. (psoSrc->iBitmapFormat == ppdev->iBitmapFormat))))
  1439. {
  1440. if ((psoSrc->iType != STYPE_BITMAP) &&
  1441. (OVERLAP(prclDst, pptlSrc)))
  1442. {
  1443. // We don't handle overlapping rectangles on a
  1444. // screen-to-screen operation:
  1445. goto Punt_It;
  1446. }
  1447. if (rop3 == 0xb8)
  1448. {
  1449. ulHwForeMix = SCREEN_AND_NEW;
  1450. pfnMask = vMaskRopB8orE2;
  1451. }
  1452. else if (rop3 == 0xe2)
  1453. {
  1454. ulHwForeMix = SCREEN_AND_NOT_NEW;
  1455. pfnMask = vMaskRopB8orE2;
  1456. }
  1457. else if (rop3 == 0x69)
  1458. {
  1459. ulHwForeMix = NOT_SCREEN_XOR_NEW;
  1460. pfnMask = vMaskRop69or96;
  1461. }
  1462. else if (rop3 == 0x96)
  1463. {
  1464. ulHwForeMix = SCREEN_XOR_NEW;
  1465. pfnMask = vMaskRop69or96;
  1466. }
  1467. else
  1468. {
  1469. goto Punt_It;
  1470. }
  1471. // All the rop3's that we've special cased need a pattern,
  1472. // so it's safe to realize a brush:
  1473. iSolidColor = pbo->iSolidColor;
  1474. if (iSolidColor == -1)
  1475. {
  1476. prb = pbo->pvRbrush;
  1477. if (prb == NULL)
  1478. {
  1479. ppdev->bRealizeTransparent = FALSE;
  1480. prb = BRUSHOBJ_pvGetRbrush(pbo);
  1481. if (prb == NULL)
  1482. goto Punt_It;
  1483. }
  1484. }
  1485. goto Mask_It;
  1486. }
  1487. }
  1488. else
  1489. {
  1490. #if defined(i386)
  1491. {
  1492. // We special case screen to monochrome blts because they
  1493. // happen fairly often. We only handle SRCCOPY rops and
  1494. // monochrome destinations (to handle a true 1bpp DIB
  1495. // destination, we would have to do near-colour searches
  1496. // on every colour; as it is, the foreground colour gets
  1497. // mapped to '1', and everything else gets mapped to '0'):
  1498. if ((psoDst->iBitmapFormat == BMF_1BPP) &&
  1499. (rop3 == 0xcc) &&
  1500. (pxlo->flXlate & XO_TO_MONO))
  1501. {
  1502. pfnXfer = vXferScreenTo1bpp;
  1503. psoSrc = psoDst; // A misnomer, I admit
  1504. goto Xfer_It;
  1505. }
  1506. }
  1507. #endif // i386
  1508. }
  1509. }
  1510. // We're going to handle some true ROP4s, where there's a foreground
  1511. // ROP3 and a background ROP3 associated with the 1bpp mask.
  1512. else if (psoMsk != NULL)
  1513. {
  1514. // At this point, we've made sure that we have a true ROP4.
  1515. // This is important because we're about to dereference the
  1516. // mask. I'll assert to make sure that I haven't inadvertently
  1517. // broken the logic for this:
  1518. ASSERTDD((rop4 & 0xff) != (rop4 >> 8), "This handles true ROP4's only");
  1519. ///////////////////////////////////////////////////////////////////
  1520. // True ROP4's
  1521. ///////////////////////////////////////////////////////////////////
  1522. // Handle ROP4 where no source is required for either Rop3:
  1523. if ((((rop4 >> 2) ^ (rop4)) & 0x3333) == 0)
  1524. {
  1525. ulHwForeMix = gaulHwMixFromRop2[(rop4 >> 2) & 0xf];
  1526. ulHwBackMix = gaulHwMixFromRop2[(rop4 >> 10) & 0xf];
  1527. Handle_Fill_Mask:
  1528. pfnXfer = ppdev->pfnXfer1bpp;
  1529. if ((ulHwForeMix & MIX_NEEDSPATTERN) ||
  1530. (ulHwBackMix & MIX_NEEDSPATTERN))
  1531. {
  1532. // Fake up a 1bpp XLATEOBJ (note that we should only
  1533. // dereference 'pbo' when it's required by the mix):
  1534. xlc.iForeColor = pbo->iSolidColor;
  1535. xlc.iBackColor = xlc.iForeColor;
  1536. if (xlc.iForeColor == -1)
  1537. goto Punt_It; // We don't handle non-solid brushes
  1538. }
  1539. // Note that when neither the foreground nor the background mix
  1540. // requires a source, the colours in 'xlc' are allowed to be
  1541. // garbage.
  1542. xlo.pulXlate = (ULONG*) &xlc;
  1543. pxlo = &xlo;
  1544. psoSrc = psoMsk;
  1545. pptlSrc = pptlMsk;
  1546. goto Xfer_It;
  1547. }
  1548. else if ((((rop4 >> 4) ^ (rop4)) & 0x0f0f) == 0) // No pattern required
  1549. {
  1550. // We're about to dereference 'psoSrc' and 'pptlSrc' --
  1551. // since we already handled the case where neither ROP3
  1552. // required the source, the ROP4 must require a source,
  1553. // so we're safe.
  1554. ASSERTDD((psoSrc != NULL) && (pptlSrc != NULL),
  1555. "No source case should already have been handled!");
  1556. // The operation has to be screen-to-screen, and the rectangles
  1557. // cannot overlap:
  1558. if ((psoSrc->iType != STYPE_BITMAP) &&
  1559. (psoDst->iType != STYPE_BITMAP) &&
  1560. ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)) &&
  1561. !OVERLAP(prclDst, pptlSrc))
  1562. {
  1563. if (ppdev->flCaps & CAPS_MASKBLT_CAPABLE)
  1564. {
  1565. ulHwForeMix = gaulHwMixFromRop2[rop4 & 0xf];
  1566. ulHwBackMix = gaulHwMixFromRop2[(rop4 >> 8) & 0xf];
  1567. pfnMask = ppdev->pfnMaskCopy;
  1568. goto Mask_It;
  1569. }
  1570. else
  1571. {
  1572. // We don't have hardware capabilities for doing it in
  1573. // one pass, but we can still do it in three passes
  1574. // using the hardware if it's a standard MaskBlt rop:
  1575. if (rop4 == 0xccaa)
  1576. ulHwForeMix = SCREEN_AND_NEW;
  1577. else if (rop4 == 0xaacc)
  1578. ulHwForeMix = SCREEN_AND_NOT_NEW;
  1579. else
  1580. goto Punt_It;
  1581. pfnMask = vMaskRopAACCorCCAA;
  1582. goto Mask_It;
  1583. }
  1584. }
  1585. }
  1586. }
  1587. else if ((rop4 & 0xff00) == (0xaa00) &&
  1588. ((((rop4 >> 2) ^ (rop4)) & 0x33) == 0))
  1589. {
  1590. // The only time GDI will ask us to do a true rop4 using the brush
  1591. // mask is when the brush is 1bpp, and the background rop is AA
  1592. // (meaning it's a NOP):
  1593. ASSERTDD(psoMsk == NULL, "This should be the NULL mask case");
  1594. ulHwForeMix = gaulHwMixFromRop2[(rop4 >> 2) & 0xf];
  1595. ulHwBackMix = LEAVE_ALONE;
  1596. ppdev->bRealizeTransparent = TRUE;
  1597. goto Fill_It;
  1598. }
  1599. // Just fall through to Punt_It...
  1600. Punt_It:
  1601. return(bPuntBlt(psoDst,
  1602. psoSrc,
  1603. psoMsk,
  1604. pco,
  1605. pxlo,
  1606. prclDst,
  1607. pptlSrc,
  1608. pptlMsk,
  1609. pbo,
  1610. pptlBrush,
  1611. rop4));
  1612. //////////////////////////////////////////////////////////////////////
  1613. // Common bitmap transfer
  1614. Xfer_It:
  1615. if (jClip == DC_TRIVIAL)
  1616. {
  1617. pfnXfer(ppdev, 1, prclDst, ulHwForeMix, ulHwBackMix, psoSrc, pptlSrc,
  1618. prclDst, pxlo);
  1619. goto All_Done;
  1620. }
  1621. else if (jClip == DC_RECT)
  1622. {
  1623. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  1624. pfnXfer(ppdev, 1, &rcl, ulHwForeMix, ulHwBackMix, psoSrc, pptlSrc,
  1625. prclDst, pxlo);
  1626. goto All_Done;
  1627. }
  1628. else
  1629. {
  1630. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
  1631. CD_ANY, 0);
  1632. do {
  1633. bMore = CLIPOBJ_bEnum(pco, sizeof(ce),
  1634. (ULONG*) &ce);
  1635. c = cIntersect(prclDst, ce.arcl, ce.c);
  1636. if (c != 0)
  1637. {
  1638. pfnXfer(ppdev, c, ce.arcl, ulHwForeMix, ulHwBackMix, psoSrc,
  1639. pptlSrc, prclDst, pxlo);
  1640. }
  1641. } while (bMore);
  1642. goto All_Done;
  1643. }
  1644. //////////////////////////////////////////////////////////////////////
  1645. // Common masked blt
  1646. Mask_It:
  1647. if (jClip == DC_TRIVIAL)
  1648. {
  1649. pfnMask(ppdev, 1, prclDst, ulHwForeMix, ulHwBackMix,
  1650. psoMsk, pptlMsk, psoSrc, pptlSrc, prclDst,
  1651. iSolidColor, prb, pptlBrush, pxlo);
  1652. goto All_Done;
  1653. }
  1654. else if (jClip == DC_RECT)
  1655. {
  1656. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  1657. pfnMask(ppdev, 1, &rcl, ulHwForeMix, ulHwBackMix,
  1658. psoMsk, pptlMsk, psoSrc, pptlSrc, prclDst,
  1659. iSolidColor, prb, pptlBrush, pxlo);
  1660. goto All_Done;
  1661. }
  1662. else
  1663. {
  1664. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
  1665. CD_ANY, 0);
  1666. do {
  1667. bMore = CLIPOBJ_bEnum(pco, sizeof(ce),
  1668. (ULONG*) &ce);
  1669. c = cIntersect(prclDst, ce.arcl, ce.c);
  1670. if (c != 0)
  1671. {
  1672. pfnMask(ppdev, c, ce.arcl, ulHwForeMix, ulHwBackMix,
  1673. psoMsk, pptlMsk, psoSrc, pptlSrc, prclDst,
  1674. iSolidColor, prb, pptlBrush, pxlo);
  1675. }
  1676. } while (bMore);
  1677. goto All_Done;
  1678. }
  1679. ////////////////////////////////////////////////////////////////////////
  1680. // Common DIB blt
  1681. EngBitBlt_It:
  1682. // Our driver doesn't handle any blt's between two DIBs. Normally
  1683. // a driver doesn't have to worry about this, but we do because
  1684. // we have DFBs that may get moved from off-screen memory to a DIB,
  1685. // where we have GDI do all the drawing. GDI does DIB drawing at
  1686. // a reasonable speed (unless one of the surfaces is a device-
  1687. // managed surface...)
  1688. //
  1689. // If either the source or destination surface in an EngBitBlt
  1690. // call-back is a device-managed surface (meaning it's not a DIB
  1691. // that GDI can draw with), GDI will automatically allocate memory
  1692. // and call the driver's DrvCopyBits routine to create a DIB copy
  1693. // that it can use. So this means that this could handle all 'punts',
  1694. // and we could conceivably get rid of bPuntBlt. But this would have
  1695. // a bad performance impact because of the extra memory allocations
  1696. // and bitmap copies -- you really don't want to do this unless you
  1697. // have to (or your surface was created such that GDI can draw
  1698. // directly onto it) -- I've been burned by this because it's not
  1699. // obvious that the performance impact is so bad.
  1700. //
  1701. // That being said, we only call EngBitBlt when all the surfaces
  1702. // are DIBs:
  1703. return(EngBitBlt(psoDst, psoSrc, psoMsk, pco, pxlo, prclDst,
  1704. pptlSrc, pptlMsk, pbo, pptlBrush, rop4));
  1705. All_Done:
  1706. return(TRUE);
  1707. }
  1708. /******************************Public*Routine******************************\
  1709. * BOOL DrvCopyBits
  1710. *
  1711. * Do fast bitmap copies.
  1712. *
  1713. * Note that GDI will (usually) automatically adjust the blt extents to
  1714. * adjust for any rectangular clipping, so we'll rarely see DC_RECT
  1715. * clipping in this routine (and as such, we don't bother special casing
  1716. * it).
  1717. *
  1718. * I'm not sure if the performance benefit from this routine is actually
  1719. * worth the increase in code size, since SRCCOPY BitBlts are hardly the
  1720. * most common drawing operation we'll get. But what the heck.
  1721. *
  1722. * On the S3 it's faster to do straight SRCCOPY bitblt's through the
  1723. * memory aperture than to use the data transfer register; as such, this
  1724. * routine is the logical place to put this special case.
  1725. *
  1726. \**************************************************************************/
  1727. BOOL DrvCopyBits(
  1728. SURFOBJ* psoDst,
  1729. SURFOBJ* psoSrc,
  1730. CLIPOBJ* pco,
  1731. XLATEOBJ* pxlo,
  1732. RECTL* prclDst,
  1733. POINTL* pptlSrc)
  1734. {
  1735. PDEV* ppdev;
  1736. DSURF* pdsurfSrc;
  1737. DSURF* pdsurfDst;
  1738. RECTL rcl;
  1739. POINTL ptl;
  1740. OH* pohSrc;
  1741. OH* pohDst;
  1742. // DrvCopyBits is a fast-path for SRCCOPY blts. But it can still be
  1743. // pretty complicated: there can be translates, clipping, RLEs,
  1744. // bitmaps that aren't the same format as the screen, plus
  1745. // screen-to-screen, DIB-to-screen or screen-to-DIB operations,
  1746. // not to mention DFBs (device format bitmaps).
  1747. //
  1748. // Rather than making this routine almost as big as DrvBitBlt, I'll
  1749. // handle here only the speed-critical cases, and punt the rest to
  1750. // our DrvBitBlt routine.
  1751. //
  1752. // We'll try to handle anything that doesn't involve clipping:
  1753. if (((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL)) &&
  1754. ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
  1755. {
  1756. if (psoDst->iType != STYPE_BITMAP)
  1757. {
  1758. // We know the destination is either a DFB or the screen:
  1759. ppdev = (PDEV*) psoDst->dhpdev;
  1760. pdsurfDst = (DSURF*) psoDst->dhsurf;
  1761. // See if the source is a plain DIB:
  1762. if (psoSrc->iType != STYPE_BITMAP)
  1763. {
  1764. pdsurfSrc = (DSURF*) psoSrc->dhsurf;
  1765. // Make sure the destination is really the screen or an
  1766. // off-screen DFB (i.e., not a DFB that we've converted
  1767. // to a DIB):
  1768. if (pdsurfDst->dt == DT_SCREEN)
  1769. {
  1770. ASSERTDD(psoSrc->iType != STYPE_BITMAP, "Can't be a DIB");
  1771. if (pdsurfSrc->dt == DT_SCREEN)
  1772. {
  1773. Screen_To_Screen:
  1774. //////////////////////////////////////////////////////
  1775. // Screen-to-screen
  1776. ASSERTDD((psoSrc->iType != STYPE_BITMAP) &&
  1777. (pdsurfSrc->dt == DT_SCREEN) &&
  1778. (psoDst->iType != STYPE_BITMAP) &&
  1779. (pdsurfDst->dt == DT_SCREEN),
  1780. "Should be a screen-to-screen case");
  1781. // pfnCopyBlt takes relative coordinates (relative
  1782. // to the destination surface, that is), so we have
  1783. // to change the start point to be relative to the
  1784. // destination surface too:
  1785. pohSrc = pdsurfSrc->poh;
  1786. pohDst = pdsurfDst->poh;
  1787. ptl.x = pptlSrc->x - (pohDst->x - pohSrc->x);
  1788. ptl.y = pptlSrc->y - (pohDst->y - pohSrc->y);
  1789. ppdev->xOffset = pohDst->x;
  1790. ppdev->yOffset = pohDst->y;
  1791. (ppdev->pfnCopyBlt)(ppdev, 1, prclDst, OVERPAINT, &ptl,
  1792. prclDst);
  1793. return(TRUE);
  1794. }
  1795. else // (pdsurfSrc->dt != DT_SCREEN)
  1796. {
  1797. // Ah ha, the source is a DFB that's really a DIB.
  1798. ASSERTDD(psoDst->iType != STYPE_BITMAP,
  1799. "Destination can't be a DIB here");
  1800. /////////////////////////////////////////////////////
  1801. // Put It Back Into Off-screen?
  1802. //
  1803. // We take this opportunity to decide if we want to
  1804. // put the DIB back into off-screen memory. This is
  1805. // a pretty good place to do it because we have to
  1806. // copy the bits to some portion of the screen,
  1807. // anyway. So we would incur only an extra screen-to-
  1808. // screen blt at this time, much of which will be
  1809. // over-lapped with the CPU.
  1810. //
  1811. // The simple approach we have taken is to move a DIB
  1812. // back into off-screen memory only if there's already
  1813. // room -- we won't throw stuff out to make space
  1814. // (because it's tough to know what ones to throw out,
  1815. // and it's easy to get into thrashing scenarios).
  1816. //
  1817. // Because it takes some time to see if there's room
  1818. // in off-screen memory, we only check one in
  1819. // HEAP_COUNT_DOWN times if there's room. To bias
  1820. // in favour of bitmaps that are often blt, the
  1821. // counters are reset every time any space is freed
  1822. // up in off-screen memory. We also don't bother
  1823. // checking if no space has been freed since the
  1824. // last time we checked for this DIB.
  1825. if (pdsurfSrc->iUniq == ppdev->iHeapUniq)
  1826. {
  1827. if (--pdsurfSrc->cBlt == 0)
  1828. {
  1829. if (bMoveDibToOffscreenDfbIfRoom(ppdev,
  1830. pdsurfSrc))
  1831. goto Screen_To_Screen;
  1832. }
  1833. }
  1834. else
  1835. {
  1836. // Some space was freed up in off-screen memory,
  1837. // so reset the counter for this DFB:
  1838. pdsurfSrc->iUniq = ppdev->iHeapUniq;
  1839. pdsurfSrc->cBlt = HEAP_COUNT_DOWN;
  1840. }
  1841. // Since the destination is definitely the screen,
  1842. // we don't have to worry about creating a DIB to
  1843. // DIB copy case (for which we would have to call
  1844. // EngCopyBits):
  1845. psoSrc = pdsurfSrc->pso;
  1846. goto DIB_To_Screen;
  1847. }
  1848. }
  1849. else // (pdsurfDst->dt != DT_SCREEN)
  1850. {
  1851. // Because the source is not a DIB, we don't have to
  1852. // worry about creating a DIB to DIB case here (although
  1853. // we'll have to check later to see if the source is
  1854. // really a DIB that's masquerading as a DFB...)
  1855. ASSERTDD(psoSrc->iType != STYPE_BITMAP,
  1856. "Source can't be a DIB here");
  1857. psoDst = pdsurfDst->pso;
  1858. goto Screen_To_DIB;
  1859. }
  1860. }
  1861. else if (psoSrc->iBitmapFormat == ppdev->iBitmapFormat)
  1862. {
  1863. // Make sure the destination is really the screen:
  1864. if (pdsurfDst->dt == DT_SCREEN)
  1865. {
  1866. DIB_To_Screen:
  1867. //////////////////////////////////////////////////////
  1868. // DIB-to-screen
  1869. ASSERTDD((psoDst->iType != STYPE_BITMAP) &&
  1870. (pdsurfDst->dt == DT_SCREEN) &&
  1871. (psoSrc->iType == STYPE_BITMAP) &&
  1872. (psoSrc->iBitmapFormat == ppdev->iBitmapFormat),
  1873. "Should be a DIB-to-screen case");
  1874. // vPutBits takes absolute screen coordinates, so
  1875. // we have to muck with the destination rectangle:
  1876. pohDst = pdsurfDst->poh;
  1877. rcl.left = prclDst->left + pohDst->x;
  1878. rcl.right = prclDst->right + pohDst->x;
  1879. rcl.top = prclDst->top + pohDst->y;
  1880. rcl.bottom = prclDst->bottom + pohDst->y;
  1881. // We use the memory aperture to do the transfer,
  1882. // because that is supposed to be faster for SRCCOPY
  1883. // blts than using the data-transfer register:
  1884. vPutBits(ppdev, psoSrc, &rcl, pptlSrc);
  1885. return(TRUE);
  1886. }
  1887. }
  1888. }
  1889. else // (psoDst->iType == STYPE_BITMAP)
  1890. {
  1891. Screen_To_DIB:
  1892. pdsurfSrc = (DSURF*) psoSrc->dhsurf;
  1893. ppdev = (PDEV*) psoSrc->dhpdev;
  1894. if (psoDst->iBitmapFormat == ppdev->iBitmapFormat)
  1895. {
  1896. if (pdsurfSrc->dt == DT_SCREEN)
  1897. {
  1898. //////////////////////////////////////////////////////
  1899. // Screen-to-DIB
  1900. ASSERTDD((psoSrc->iType != STYPE_BITMAP) &&
  1901. (pdsurfSrc->dt == DT_SCREEN) &&
  1902. (psoDst->iType == STYPE_BITMAP) &&
  1903. (psoDst->iBitmapFormat == ppdev->iBitmapFormat),
  1904. "Should be a screen-to-DIB case");
  1905. // vGetBits takes absolute screen coordinates, so we have
  1906. // to muck with the source point:
  1907. pohSrc = pdsurfSrc->poh;
  1908. ptl.x = pptlSrc->x + pohSrc->x;
  1909. ptl.y = pptlSrc->y + pohSrc->y;
  1910. vGetBits(ppdev, psoDst, prclDst, &ptl);
  1911. return(TRUE);
  1912. }
  1913. else
  1914. {
  1915. // The source is a DFB that's really a DIB. Since we
  1916. // know that the destination is a DIB, we've got a DIB
  1917. // to DIB operation, and should call EngCopyBits:
  1918. psoSrc = pdsurfSrc->pso;
  1919. goto EngCopyBits_It;
  1920. }
  1921. }
  1922. }
  1923. }
  1924. // We can't call DrvBitBlt if we've accidentally converted both
  1925. // surfaces to DIBs, because it isn't equipped to handle it:
  1926. ASSERTDD((psoSrc->iType != STYPE_BITMAP) ||
  1927. (psoDst->iType != STYPE_BITMAP),
  1928. "Accidentally converted both surfaces to DIBs");
  1929. /////////////////////////////////////////////////////////////////
  1930. // A DrvCopyBits is after all just a simplified DrvBitBlt:
  1931. return(DrvBitBlt(psoDst, psoSrc, NULL, pco, pxlo, prclDst, pptlSrc, NULL,
  1932. NULL, NULL, 0x0000CCCC));
  1933. EngCopyBits_It:
  1934. ASSERTDD((psoDst->iType == STYPE_BITMAP) &&
  1935. (psoSrc->iType == STYPE_BITMAP),
  1936. "Both surfaces should be DIBs to call EngCopyBits");
  1937. return(EngCopyBits(psoDst, psoSrc, pco, pxlo, prclDst, pptlSrc));
  1938. }