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.

1182 lines
37 KiB

  1. /*++
  2. Copyright (c) 1990-2003 Microsoft Corporation
  3. Module Name:
  4. ropblt.c
  5. Abstract:
  6. This module contains code to deal with ROP3 codes
  7. Author:
  8. 07-Jan-1994 Fri 11:04:09 created
  9. 27-Jan-1994 Thu 23:42:09 updated
  10. Bascially re-write the codes, make up our own ROP3 to ROP2s generator
  11. and mixer. Cloning the surface object as necessary, some of ROP4 to
  12. ROP2 (Rop3ToSDMix[]) are hand twiks so that it can handle the one
  13. which we can not handle before (ie. multiple destinaiton usage cases)
  14. 16-Mar-1994 Wed 11:21:45 updated
  15. Update the DoMix2() so the SRC aligned to the destination only if the
  16. source is not psoMask
  17. [Environment:]
  18. GDI Device Driver - Plotter.
  19. [Notes:]
  20. Revision History:
  21. --*/
  22. #include "precomp.h"
  23. #pragma hdrstop
  24. #define DBG_PLOTFILENAME DbgRopBlt
  25. #define DBG_DOMIX2 0x00000001
  26. #define DBG_CLONESO 0x00000002
  27. #define DBG_ROP3 0x00000004
  28. #define DBG_SPECIALROP 0x00000008
  29. DEFINE_DBGVAR(0);
  30. //****************************************************************************
  31. // All ROP3/2 Related Local defines, structures which are only used in this
  32. // file are located here
  33. //****************************************************************************
  34. #define MIX2_0 0x00
  35. #define MIX2_SoD_n 0x01
  36. #define MIX2_nS_aD 0x02
  37. #define MIX2_nS 0x03
  38. #define MIX2_nD_aS 0x04
  39. #define MIX2_nD 0x05
  40. #define MIX2_SxD 0x06
  41. #define MIX2_SaD_n 0x07
  42. #define MIX2_SaD 0x08
  43. #define MIX2_SxD_n 0x09
  44. #define MIX2_D 0x0A
  45. #define MIX2_nS_oD 0x0B
  46. #define MIX2_S 0x0C
  47. #define MIX2_nD_oS 0x0D
  48. #define MIX2_SoD 0x0E
  49. #define MIX2_1 0x0F
  50. #define MIX2_MASK 0x0F
  51. #define MIXSD_SRC_DST 0x00
  52. #define MIXSD_PAT_DST 0x10
  53. #define MIXSD_SRC_PAT 0x20
  54. #define MIXSD_TMP_DST 0x30
  55. #define MIXSD_MASK 0x30
  56. #define MIX2F_MUL_DST 0x80
  57. #define MIX2F_MUL_SRC 0x40
  58. #define MIX2F_NEED_TMP 0x20
  59. #define MIX2F_COUNT_MASK 0x03
  60. #define MAX_SD_MIXS 4
  61. #define SDMIX_SHIFT_COUNT 6
  62. #define GET_SDMIX_MIX2F(dw) (BYTE)((dw) >> 24)
  63. #define SET_SDMIX_MIX2F(dw,f) (dw)|=((DWORD)(f) << 24)
  64. #define GET_MIX2F_COUNT(f) (((f)&0x3)+1)
  65. #define SET_MIX2F_COUNT(f,c) (f=(BYTE)((((c)-1)&0x3)|((f)&~0x3)))
  66. //
  67. // DWORD SDMix Bits meaning
  68. //
  69. // Bit 0- 5:
  70. // 6-11:
  71. // 12-17:
  72. // 18-23: Each has 6 bits, lower 4 bits denote MIX2 operation code (one
  73. // of 16 MIX2_xxxx, and upper 2 bits is the MIXSD_xxxx which
  74. // indicate where the source/destination operands come from.
  75. //
  76. // Bit 24-25: 2 bits indicate the total MIX2_xxx operation codes minus 1,
  77. // 00=1, 01=2, 02=3, 03=4, maximum will be 4 Mix2 operations
  78. //
  79. // Bit 26: Not Used
  80. // Bit 27: Not Used
  81. // Bit 28: Not Used
  82. // Bit 29: Flag MIX2F_NEED_TMP to indicate a temporary surface object is
  83. // needed to stored the PAT/SRC Mix2 operations.
  84. // Bit 30: Flag MIX2F_MUL_SRC to indicate multiple source operations
  85. // are present in the Mix2s.
  86. // Bit 31: Flag MIX2F_MUL_DST to indicate multiple destination operations
  87. // are present in the Mix2s.
  88. //
  89. // The Rop3ToSDMix[] is a DWORD array. each DWORD (SDMix) is defined
  90. // above. The Rop3ToSDMix[] only list the first 128 of the ROP3 code, the other
  91. // 128 Rop3 codes (128-255) can be obtains by 'Rop3ToSDMix[Rop3 ^ 0xFF]' and
  92. // the result of the Rop3 must be complemented.
  93. //
  94. // Since all Rop3/Rop2 codes are symmetric, we can complement the Rop3/Rop2
  95. // result by complementing MIX2_xxxx (0->15, 1->14...,7->8).
  96. //
  97. // The [!x] in the Rop3ToSDMix[], indicates the following
  98. //
  99. // !: Indicates MIX2F_MUL_DST bit is set for the ROP
  100. // x: Is the total number of MIX2_xxx operations
  101. //
  102. const DWORD Rop3ToSDMix[128] = {
  103. { 0x00000000 }, // [ 1] 0-0x00: 0
  104. { 0x21000C6E }, // [ 2] 1-0x01: ~(D | (P | S))
  105. { 0x21000E21 }, // [ 2] 2-0x02: D & ~(P | S)
  106. { 0x0100044C }, // [ 2] 3-0x03: ~(P | S)
  107. { 0x01000211 }, // [ 2] 4-0x04: S & ~(D | P)
  108. { 0x00000011 }, // [ 1] 5-0x05: ~(D | P)
  109. { 0x01000449 }, // [ 2] 6-0x06: ~(P | ~(D ^ S))
  110. { 0x01000448 }, // [ 2] 7-0x07: ~(P | (D & S))
  111. { 0x01000212 }, // [ 2] 8-0x08: S & (D & ~P)
  112. { 0x01000446 }, // [ 2] 9-0x09: ~(P | (D ^ S))
  113. { 0x00000012 }, // [ 1] 10-0x0a: D & ~P
  114. { 0x01000444 }, // [ 2] 11-0x0b: ~(P | (S & ~D))
  115. { 0x0100048C }, // [ 2] 12-0x0c: S & ~P
  116. { 0x01000442 }, // [ 2] 13-0x0d: ~(P | (D & ~S))
  117. { 0x01000441 }, // [ 2] 14-0x0e: ~(P | ~(D | S))
  118. { 0x00000013 }, // [ 1] 15-0x0f: ~P
  119. { 0x01000601 }, // [ 2] 16-0x10: P & ~(D | S)
  120. { 0x00000001 }, // [ 1] 17-0x11: ~(D | S)
  121. { 0x01000059 }, // [ 2] 18-0x12: ~(S | ~(D ^ P))
  122. { 0x01000058 }, // [ 2] 19-0x13: ~(S | (D & P))
  123. { 0x21000C69 }, // [ 2] 20-0x14: ~(D | ~(P ^ S))
  124. { 0x21000C68 }, // [ 2] 21-0x15: ~(D | (P & S))
  125. { 0x63586E27 }, // [ 4] 22-0x16: P ^ (S ^ (D & ~(P & S)))
  126. { 0x63278986 }, // [ 4] 23-0x17: ~(S ^ ((S ^ P) & (D ^ S)))
  127. { 0x22038996 }, // [ 3] 24-0x18: (S ^ P) & (P ^ D)
  128. { 0x62009E27 }, // [ 3] 25-0x19: ~(S ^ (D & ~(P & S)))
  129. { 0x22016FA8 }, // [ 3] 26-0x1a: P ^ (D | (S & P))
  130. { 0x62009E26 }, // [ 3] 27-0x1b: ~(S ^ (D & (P ^ S)))
  131. { 0x02016398 }, // [ 3] 28-0x1c: P ^ (S | (D & P))
  132. // { 0x81000216 }, // [!2] 29-0x1d: ~(D ^ (S & (P ^ D)))
  133. { 0x6203990E }, // [ 3] 29-0x1d: ~((S & ~P) ^ (S | D))
  134. { 0x0100058E }, // [ 2] 30-0x1e: P ^ (D | S)
  135. { 0x010005CE }, // [ 2] 31-0x1f: ~(P & (D | S))
  136. { 0x21000E22 }, // [ 2] 32-0x20: D & (P & ~S)
  137. { 0x01000056 }, // [ 2] 33-0x21: ~(S | (D ^ P))
  138. { 0x00000002 }, // [ 1] 34-0x22: D & ~S
  139. { 0x01000054 }, // [ 2] 35-0x23: ~(S | (P & ~D))
  140. { 0x62038986 }, // [ 3] 36-0x24: (S ^ P) & (D ^ S)
  141. { 0x22019E27 }, // [ 3] 37-0x25: ~(P ^ (D & ~(S & P)))
  142. { 0x62006FA8 }, // [ 3] 38-0x26: S ^ (D | (P & S))
  143. { 0x22019E26 }, // [ 3] 39-0x27: ~(P ^ (D & (S ^ P)))
  144. { 0x21000E26 }, // [ 2] 40-0x28: D & (P ^ S)
  145. { 0x63646FA8 }, // [ 4] 41-0x29: ~(P ^ (S ^ (D | (P & S))))
  146. { 0x21000E27 }, // [ 2] 42-0x2a: D & ~(P & S)
  147. { 0x63278996 }, // [ 4] 43-0x2b: ~(S ^ ((S ^ P) & (P ^ D)))
  148. { 0x0200660E }, // [ 3] 44-0x2c: S ^ (P & (D | S))
  149. { 0x01000642 }, // [ 2] 45-0x2d: ~(P ^ (D & ~S))
  150. { 0x02016396 }, // [ 3] 46-0x2e: P ^ (S | (D ^ P))
  151. { 0x010005CD }, // [ 2] 47-0x2f: ~(P & (S | ~D))
  152. { 0x0100050C }, // [ 2] 48-0x30: P & ~S
  153. { 0x01000052 }, // [ 2] 49-0x31: ~(S | (D & ~P))
  154. { 0x62006FAE }, // [ 3] 50-0x32: S ^ (D | (P | S))
  155. { 0x00000003 }, // [ 1] 51-0x33: ~S
  156. { 0x02006788 }, // [ 3] 52-0x34: S ^ (P | (D & S))
  157. { 0x02006789 }, // [ 3] 53-0x35: S ^ (P | ~(D ^ S))
  158. { 0x0100019E }, // [ 2] 54-0x36: S ^ (D | P)
  159. { 0x010001DE }, // [ 2] 55-0x37: ~(S & (D | P))
  160. { 0x0201621E }, // [ 3] 56-0x38: P ^ (S & (D | P))
  161. { 0x01000252 }, // [ 2] 57-0x39: ~(S ^ (D & ~P))
  162. { 0x02006786 }, // [ 3] 58-0x3a: S ^ (P | (D ^ S))
  163. { 0x010001DD }, // [ 2] 59-0x3b: ~(S & (P | ~D))
  164. { 0x0100058C }, // [ 2] 60-0x3c: P ^ S
  165. { 0x02006781 }, // [ 3] 61-0x3d: S ^ (P | ~(D | S))
  166. { 0x02006782 }, // [ 3] 62-0x3e: S ^ (P | (D & ~S))
  167. { 0x010005CC }, // [ 2] 63-0x3f: ~(P & S)
  168. { 0x01000604 }, // [ 2] 64-0x40: P & (S & ~D)
  169. { 0x21000C66 }, // [ 2] 65-0x41: ~(D | (P ^ S))
  170. { 0x81000196 }, // [!2] 66-0x42: ~((S ^ D) & (P ^ D))
  171. { 0x02009607 }, // [ 3] 67-0x43: ~(S ^ (P & ~(D & S)))
  172. { 0x00000004 }, // [ 1] 68-0x44: S & ~D
  173. { 0x21000C62 }, // [ 2] 69-0x45: ~(D | (P & ~S))
  174. { 0x81000398 }, // [!2] 70-0x46: ~(D ^ (S | (P & D)))
  175. { 0x02019216 }, // [ 3] 71-0x47: ~(P ^ (S & (D ^ P)))
  176. { 0x01000216 }, // [ 2] 72-0x48: S & (D ^ P)
  177. { 0x82019398 }, // [!3] 73-0x49: ~(P ^ (D ^ (S | (P & D))))
  178. { 0x8100060E }, // [!2] 74-0x4a: ~(D ^ (P & (S | D)))
  179. { 0x01000644 }, // [ 2] 75-0x4b: ~(P ^ (S & ~D))
  180. { 0x01000217 }, // [ 2] 76-0x4c: S & ~(D & P)
  181. { 0x6327E986 }, // [ 4] 77-0x4d: ~(S ^ ((S ^ P) | (D ^ S)))
  182. { 0x22016FA6 }, // [ 3] 78-0x4e: P ^ (D | (S ^ P))
  183. { 0x010005CB }, // [ 2] 79-0x4f: ~(P & (D | ~S))
  184. { 0x00000014 }, // [ 1] 80-0x50: P & ~D
  185. { 0x21000C64 }, // [ 2] 81-0x51: ~(D | (S & ~P))
  186. { 0x81000788 }, // [!2] 82-0x52: ~(D ^ (P | (S & D)))
  187. { 0x02009606 }, // [ 3] 83-0x53: ~(S ^ (P & (D ^ S)))
  188. { 0x21000C61 }, // [ 2] 84-0x54: ~(D | ~(P | S))
  189. { 0x00000005 }, // [ 1] 85-0x55: ~D
  190. { 0x21000DAE }, // [ 2] 86-0x56: D ^ (P | S)
  191. { 0x21000DEE }, // [ 2] 87-0x57: ~(D & (P | S))
  192. { 0x22016E2E }, // [ 3] 88-0x58: P ^ (D & (S | P))
  193. { 0x21000E64 }, // [ 2] 89-0x59: ~(D ^ (S & ~P))
  194. { 0x00000016 }, // [ 1] 90-0x5a: D ^ P
  195. { 0x22016FA1 }, // [ 3] 91-0x5b: P ^ (D | ~(S | P))
  196. { 0x220385EE }, // [ 3] 92-0x5c: (S | P) & ~(P & D)
  197. // { 0x81000786 }, // [!2] 92-0x5c: ~(D ^ (P | (S ^ D)))
  198. { 0x21000DEB }, // [ 2] 93-0x5d: ~(D & (P | ~S))
  199. { 0x22016FA4 }, // [ 3] 94-0x5e: P ^ (D | (S & ~P))
  200. { 0x00000017 }, // [ 1] 95-0x5f: ~(D & P)
  201. { 0x01000606 }, // [ 2] 96-0x60: P & (D ^ S)
  202. { 0x82006788 }, // [!3] 97-0x61: ~(D ^ (S ^ (P | (D & S))))
  203. { 0x8100021E }, // [!2] 98-0x62: ~(D ^ (S & (P | D)))
  204. { 0x01000254 }, // [ 2] 99-0x63: ~(S ^ (P & ~D))
  205. { 0x62006E2E }, // [ 3] 100-0x64: S ^ (D & (P | S))
  206. { 0x21000E62 }, // [ 2] 101-0x65: ~(D ^ (P & ~S))
  207. { 0x00000006 }, // [ 1] 102-0x66: D ^ S
  208. { 0x62006FA1 }, // [ 3] 103-0x67: S ^ (D | ~(P | S))
  209. { 0x63646FA1 }, // [ 4] 104-0x68: ~(P ^ (S ^ (D | ~(P | S))))
  210. { 0x21000E66 }, // [ 2] 105-0x69: ~(D ^ (P ^ S))
  211. { 0x21000DA8 }, // [ 2] 106-0x6a: D ^ (P & S)
  212. { 0x63646E2E }, // [ 4] 107-0x6b: ~(P ^ (S ^ (D & (P | S))))
  213. { 0x01000198 }, // [ 2] 108-0x6c: S ^ (D & P)
  214. { 0x8201921E }, // [!3] 109-0x6d: ~(P ^ (D ^ (S & (P | D))))
  215. { 0x62006E2B }, // [ 3] 110-0x6e: S ^ (D & (P | ~S))
  216. { 0x010005C9 }, // [ 2] 111-0x6f: ~(P & ~(D ^ S))
  217. { 0x01000607 }, // [ 2] 112-0x70: P & ~(D & S)
  218. { 0x82009196 }, // [!3] 113-0x71: ~(S ^ ((S ^ D) & (P ^ D)))
  219. { 0x62006FA6 }, // [ 3] 114-0x72: S ^ (D | (P ^ S))
  220. { 0x010001DB }, // [ 2] 115-0x73: ~(S & (D | ~P))
  221. { 0x81000396 }, // [!2] 116-0x74: ~(D ^ (S | (P ^ D)))
  222. { 0x21000DED }, // [ 2] 117-0x75: ~(D & (S | ~P))
  223. { 0x62006FA2 }, // [ 3] 118-0x76: S ^ (D | (P & ~S))
  224. { 0x00000007 }, // [ 1] 119-0x77: ~(D & S)
  225. { 0x01000588 }, // [ 2] 120-0x78: P ^ (D & S)
  226. { 0x8200660E }, // [!3] 121-0x79: ~(D ^ (S ^ (P & (D | S))))
  227. { 0x22016E2D }, // [ 3] 122-0x7a: P ^ (D & (S | ~P))
  228. { 0x010001D9 }, // [ 2] 123-0x7b: ~(S & ~(D ^ P))
  229. { 0x0200660B }, // [ 3] 124-0x7c: S ^ (P & (D | ~S))
  230. { 0x21000DE9 }, // [ 2] 125-0x7d: ~(D & ~(P ^ S))
  231. { 0x6203E986 }, // [ 3] 126-0x7e: (S ^ P) | (D ^ S)
  232. { 0x21000DE8 } // [ 2] 127-0x7f: ~(D & (P & S))
  233. };
  234. extern const POINTL ptlZeroOrigin;
  235. //****************************************************************************
  236. // END OF LOCAL DEFINES/STRUCTURE
  237. //****************************************************************************
  238. BOOL
  239. CloneBitBltSURFOBJ(
  240. PPDEV pPDev,
  241. SURFOBJ *psoDst,
  242. SURFOBJ *psoSrc,
  243. SURFOBJ *psoMask,
  244. XLATEOBJ *pxlo,
  245. PRECTL prclDst,
  246. PRECTL prclSrc,
  247. PRECTL prclPat,
  248. BRUSHOBJ *pbo,
  249. PCLONESO pCloneSO,
  250. DWORD RopBG,
  251. DWORD RopFG
  252. )
  253. /*++
  254. Routine Description:
  255. This function will clone the source/pattern and/or create a temp
  256. source buffer if we need one
  257. Arguments:
  258. pPDev - Pointer to our PDEV
  259. psoDst - Pointer to our surfae obj
  260. psoSrc - Pointer to source surfae obj
  261. psoMask - Pointer to the mask surface object if neeed to be used as pat
  262. pxlo - translate object from source to destination
  263. prclDst - Pointer to the destination rectangle area for the bitblt
  264. prclSrc - Pointer to the source rectangle area
  265. prclPat - pointer to the pattern rectangle area
  266. pbo - Pointer to the pointer of brush object
  267. pCloneSO - Pointer to the CLONSO[3] which stored the clone result
  268. RopBG - Background rop3
  269. RopFG - Foreground rop3
  270. Return Value:
  271. BOOLEAN
  272. Author:
  273. 24-Jan-1994 Mon 15:58:27 created
  274. Revision History:
  275. --*/
  276. {
  277. DWORD Index;
  278. INT CompPat;
  279. BYTE Flags;
  280. //
  281. // Invert Rop3 if we are out of data range (128-255) and then invert
  282. // the final result (by inverting last Mix2 Rop2 code (0-15), all Rop3/Rop2
  283. // codes are symmetric.
  284. //
  285. if ((Index = RopBG) >= 0x80) {
  286. Index ^= 0xFF;
  287. }
  288. Flags = GET_SDMIX_MIX2F(Rop3ToSDMix[Index]);
  289. if ((Index = RopFG) >= 0x80) {
  290. Index ^= 0xFF;
  291. }
  292. Flags |= GET_SDMIX_MIX2F(Rop3ToSDMix[Index]);
  293. //
  294. // Clone the PATTERN if necessary.
  295. //
  296. if ((ROP3_NEED_PAT(RopFG)) ||
  297. (ROP3_NEED_PAT(RopBG))) {
  298. //
  299. // Only Clone the MASK/PATTERN if it is required
  300. //
  301. PLOTDBG(DBG_CLONESO, ("CloneBitBltSURFOBJ: NEED PATTERN "));
  302. if (psoMask) {
  303. PLOTDBG(DBG_CLONESO, ("CloneBitBltSURFOBJ: Use psoMask as pattern"));
  304. if (!(pCloneSO[CSI_PAT].pso =
  305. CloneMaskSURFOBJ(pPDev,
  306. psoMask,
  307. &pCloneSO[CSI_PAT].hBmp,
  308. prclPat))) {
  309. PLOTERR(("CloneBitBltSURFOBJ:: CloneMaskSURFOBJ(psoPat) failed"));
  310. return(FALSE);
  311. }
  312. } else {
  313. //
  314. // Firs get the DEVBRUSH out.
  315. //
  316. if (!(CompPat = (INT)GetColor(pPDev, pbo, NULL, NULL, RopBG))) {
  317. PLOTERR(("CloneBitBltSURFOBJ:: GetColor for DEVBRUSH failed"));
  318. return(FALSE);
  319. }
  320. //
  321. // If we do not have a device compatible pattern or if we have to
  322. // do a SRC/PAT memory operation then we need to clone the pattern
  323. //
  324. if ((CompPat < 0) || (Flags & MIX2F_NEED_TMP)) {
  325. if (!(pCloneSO[CSI_PAT].pso =
  326. CloneBrushSURFOBJ(pPDev,
  327. psoDst,
  328. &pCloneSO[CSI_PAT].hBmp,
  329. pbo))) {
  330. PLOTERR(("CloneBitBltSURFOBJ:: CloneBrushSURFOBJ(psoPat) failed"));
  331. return(FALSE);
  332. }
  333. prclPat->left =
  334. prclPat->top = 0;
  335. prclPat->right = pCloneSO[CSI_PAT].pso->sizlBitmap.cx;
  336. prclPat->bottom = pCloneSO[CSI_PAT].pso->sizlBitmap.cy;
  337. }
  338. }
  339. }
  340. //
  341. // Determine if we need to clone the source
  342. //
  343. if ((ROP3_NEED_SRC(RopFG) || ROP3_NEED_SRC(RopBG))) {
  344. if (IsHTCompatibleSurfObj(pPDev,
  345. psoSrc,
  346. pxlo,
  347. (Flags & MIX2F_NEED_TMP) ?
  348. 0 : (ISHTF_ALTFMT | ISHTF_DSTPRIM_OK))) {
  349. PLOTDBG(DBG_CLONESO,
  350. ("CloneBitBltSURFOBJ:: Compatible HT Format, SRC=%ld, DST=%ld [ALT=%ld]",
  351. psoSrc->iBitmapFormat,
  352. ((PDRVHTINFO)pPDev->pvDrvHTData)->HTBmpFormat,
  353. ((PDRVHTINFO)pPDev->pvDrvHTData)->AltBmpFormat));
  354. } else {
  355. PLOTDBG(DBG_CLONESO, ("CloneBitBltSURFOBJ:: CLONING SOURCE"));
  356. if (!(pCloneSO[CSI_SRC].pso =
  357. CloneSURFOBJToHT(pPDev,
  358. psoDst,
  359. psoSrc,
  360. pxlo,
  361. &pCloneSO[CSI_SRC].hBmp,
  362. prclDst,
  363. prclSrc))) {
  364. PLOTDBG(DBG_CLONESO, ("CloneBitBltSURFOBJ:: CLONE Source FAILED"));
  365. return(FALSE);
  366. }
  367. }
  368. }
  369. //
  370. // Create a TEMP SURFOBJ for SRC/PAT memory operation if it is required
  371. //
  372. if (Flags & MIX2F_NEED_TMP) {
  373. PLOTDBG(DBG_CLONESO, ("CloneBitbltSURFOBJ: CLONE SRC_TMP (%ld x %ld)",
  374. prclSrc->right - prclSrc->left,
  375. prclSrc->bottom - prclSrc->top));
  376. if (!(pCloneSO[CSI_TMP].pso =
  377. CreateBitmapSURFOBJ(pPDev,
  378. &pCloneSO[CSI_TMP].hBmp,
  379. prclSrc->right - prclSrc->left,
  380. prclSrc->bottom - prclSrc->top,
  381. HTBMPFORMAT(pPDev),
  382. NULL))) {
  383. PLOTDBG(DBG_CLONESO, ("CloneBitBltSURFOBJ:: CLONE SRC_TMP FAILED"));
  384. return(FALSE);
  385. }
  386. }
  387. return(TRUE);
  388. }
  389. BOOL
  390. DoSpecialRop3(
  391. SURFOBJ *psoDst,
  392. CLIPOBJ *pco,
  393. PRECTL prclDst,
  394. DWORD Rop3
  395. )
  396. /*++
  397. Routine Description:
  398. This function does a white or black fil
  399. Arguments:
  400. psoDst - The device surface must be DEVICE
  401. pco - Clipping object
  402. prclDst - RECTL area to be rop'ed
  403. Rop3 - a special Rop3, 0x00, 0xFF, 0x55, 0xAA
  404. Return Value:
  405. BOOLEAN
  406. Author:
  407. 15-Jan-1994 Sat 07:38:55 created
  408. Revision History:
  409. --*/
  410. {
  411. BRUSHOBJ bo;
  412. DEVBRUSH DevBrush;
  413. PLOTASSERT(1, "DoSpecialRop3: Passed psoDst (%08lx) != STYPE_DEVICE",
  414. psoDst->iType == STYPE_DEVICE, psoDst);
  415. PLOTDBG(DBG_SPECIALROP, ("DoSpecialROP[%04lx] (%ld, %ld)-(%ld, %ld)=%ld x %ld",
  416. Rop3,
  417. prclDst->left, prclDst->top,
  418. prclDst->right, prclDst->bottom,
  419. prclDst->right - prclDst->left,
  420. prclDst->bottom - prclDst->top));
  421. bo.iSolidColor = (DWORD)((Rop3) ? 0x000000000 : 0x00FFFFFF);
  422. bo.pvRbrush = (LPVOID)&DevBrush;
  423. ZeroMemory(&DevBrush, sizeof(DevBrush));
  424. if (!DoFill(psoDst, // psoDst
  425. NULL, // psoSrc
  426. pco, // pco
  427. NULL, // pxlo
  428. prclDst, // prclDst
  429. NULL, // prclSrc
  430. &bo, // pbo
  431. (PPOINTL)&ptlZeroOrigin, // pptlBrushOrg
  432. Rop3 | (Rop3 << 8))) { // Rop4
  433. PLOTERR(("DoSpecialRop3: Rop3=%08lx Failed!!!", Rop3));
  434. return(FALSE);
  435. }
  436. return(TRUE);
  437. }
  438. BOOL
  439. DoMix2(
  440. PPDEV pPDev,
  441. SURFOBJ *psoDst,
  442. SURFOBJ *psoSrc,
  443. CLIPOBJ *pco,
  444. XLATEOBJ *pxlo,
  445. PRECTL prclDst,
  446. PRECTL prclSrc,
  447. PPOINTL pptlSrcOrg,
  448. DWORD Mix2
  449. )
  450. /*++
  451. Routine Description:
  452. This function is responsible for doing a device copy of a bitmap
  453. with/without tiling and activating the proper Rop2
  454. Arguments:
  455. pPDev - Pointer to the PDEV
  456. psoDst - pointer to the destination surface object
  457. psoSrc - pointer to the source surface object
  458. pco - Pointer to the CLIPOBJ
  459. pxlo - the translate object from the source to the destination
  460. prclDst - the output destination rectangle area
  461. prclSrc - the source rectangle area
  462. pptlSrcOrg - brush origin for the source rectangle, if this is NULL then
  463. prclSrc will not have to be aligned on the destination
  464. Mix2 - a rop2 mode 0 - 0x0F
  465. Return Value:
  466. BOOLEAN
  467. Author:
  468. 08-Feb-1994 Tue 16:33:41 updated
  469. fixed ptlSrcOrg problem, we need to modulate with source size before
  470. it get used.
  471. 27-Jan-1994 Thu 23:45:46 updated
  472. Re-write so that it can handle the tiling more efficient.
  473. 13-Jan-1994 Sat 09:34:06 created
  474. Revision History:
  475. --*/
  476. {
  477. RECTL rclSrc;
  478. RECTL rclDst;
  479. POINTL ptlSrcOrg;
  480. LONG cxSrc;
  481. LONG cySrc;
  482. DWORD OHTFlags = 0;
  483. BOOL MemMix2;
  484. //
  485. // The final ROP is either a ROP3 or a ROP4 (no mask) and it is always
  486. // a rop2 operation which deals with the source and destination
  487. //
  488. // First make it into a Rop3 representation of Rop2 (Mix2)
  489. //
  490. PLOTASSERT(1, "DoMix2: Passed INVALID psoSrc (%08lx) = STYPE_DEVICE",
  491. (psoSrc) &&
  492. (psoSrc->iType != STYPE_DEVICE), psoSrc);
  493. PLOTASSERT(1, "DoMix2: Unexpected Mix2 = %u, SHOULD NOT BE HERE",
  494. (Mix2 != MIX2_0) && (Mix2 != MIX2_1) &&
  495. (Mix2 != MIX2_D) && (Mix2 != MIX2_nD), Mix2);
  496. Mix2 &= 0x0F;
  497. Mix2 |= (DWORD)(Mix2 << 4);
  498. switch (Mix2) {
  499. case 0x00: // 0
  500. case 0xFF: // 1
  501. case 0x55: // ~D
  502. DoSpecialRop3(psoDst, pco, prclDst, Mix2);
  503. case 0xAA: // D
  504. return(TRUE);
  505. }
  506. if (MemMix2 = (BOOL)(psoDst->iType != STYPE_DEVICE)) {
  507. //
  508. // Now make it into Rop4 representation of Rop2 (Mix2)
  509. //
  510. Mix2 |= (Mix2 << 8);
  511. } else {
  512. if (!IsHTCompatibleSurfObj(pPDev,
  513. psoSrc,
  514. pxlo,
  515. ((pxlo) ? ISHTF_ALTFMT : 0) |
  516. ISHTF_HTXB |
  517. ISHTF_DSTPRIM_OK)) {
  518. PLOTERR(("DoMix2: The psoSrc is not HT compatible format (%08lx",
  519. psoSrc->iBitmapFormat));
  520. return(FALSE);
  521. }
  522. }
  523. cxSrc = prclSrc->right - prclSrc->left;
  524. cySrc = prclSrc->bottom - prclSrc->top;
  525. if (pptlSrcOrg) {
  526. ptlSrcOrg = *pptlSrcOrg;
  527. if ((ptlSrcOrg.x = (LONG)(prclDst->left - ptlSrcOrg.x) % cxSrc) < 0) {
  528. ptlSrcOrg.x += cxSrc;
  529. }
  530. if ((ptlSrcOrg.y = (LONG)(prclDst->top - ptlSrcOrg.y) % cySrc) < 0) {
  531. ptlSrcOrg.y += cySrc;
  532. }
  533. PLOTDBG(DBG_DOMIX2, ("DoMix2: ORG ptlSrcOrg=(%ld, %ld) -> (%ld, %ld)",
  534. pptlSrcOrg->x, pptlSrcOrg->y, ptlSrcOrg.x, ptlSrcOrg.y));
  535. } else {
  536. ptlSrcOrg.x =
  537. ptlSrcOrg.y = 0;
  538. PLOTDBG(DBG_DOMIX2, ("DoMix2: >>> DO NOT NEED TO ALIGN SRC on DEST <<<"));
  539. }
  540. rclSrc.top = prclSrc->top + ptlSrcOrg.y;
  541. rclSrc.bottom = prclSrc->bottom;
  542. rclDst.top = prclDst->top;
  543. rclDst.bottom = rclDst.top + (rclSrc.bottom - rclSrc.top);
  544. PLOTDBG(DBG_DOMIX2, ("DoMix2: SrcFormat=%ld, DstFormat=%ld %hs",
  545. psoSrc->iBitmapFormat,
  546. psoDst->iBitmapFormat,
  547. (MemMix2) ? "[MemMix2]" : ""));
  548. PLOTDBG(DBG_DOMIX2, ("DoMix2: ORG: Dst=(%ld, %ld)-(%ld,%ld), Src=(%ld, %ld)-(%ld, %ld)",
  549. prclDst->left, prclDst->top,
  550. prclDst->right, prclDst->bottom,
  551. prclSrc->left, prclSrc->top,
  552. prclSrc->right, prclSrc->bottom));
  553. while (rclDst.top < prclDst->bottom) {
  554. //
  555. // check if the destination bottom is overhanging, clip it,
  556. //
  557. // NOTE: This could happen the first time.
  558. //
  559. if (rclDst.bottom > prclDst->bottom) {
  560. //
  561. // Clip the source/destination rectangle, because we may do
  562. // EngBitBlt() or OutputHTBitmap()
  563. //
  564. rclSrc.bottom -= (rclDst.bottom - prclDst->bottom);
  565. rclDst.bottom = prclDst->bottom;
  566. }
  567. rclSrc.left = prclSrc->left + ptlSrcOrg.x;
  568. rclSrc.right = prclSrc->right;
  569. rclDst.left = prclDst->left;
  570. rclDst.right = rclDst.left + (rclSrc.right - rclSrc.left);
  571. while (rclDst.left < prclDst->right) {
  572. //
  573. // check if the destination right edge is overhanging, clip it if
  574. // necessary.
  575. //
  576. // NOTE: This could happen the first time.
  577. //
  578. if (rclDst.right > prclDst->right) {
  579. //
  580. // Clip the source/destination rectangle, because we may do a
  581. // EngBitBlt() or OutputHTBitmap()
  582. //
  583. rclSrc.right -= (rclDst.right - prclDst->right);
  584. rclDst.right = prclDst->right;
  585. }
  586. PLOTDBG(DBG_DOMIX2, ("DoMix2: TILE: Dst=(%ld, %ld)-(%ld,%ld), Src=(%ld, %ld)-(%ld, %ld)",
  587. rclDst.left, rclDst.top, rclDst.right, rclDst.bottom,
  588. rclSrc.left, rclSrc.top, rclSrc.right, rclSrc.bottom));
  589. if (MemMix2) {
  590. //
  591. // In the memory version we don't have to worry about PCO so
  592. // just call EngBitBlt to do the work.
  593. //
  594. if (!(EngBitBlt(psoDst, // psoDst
  595. psoSrc, // psoSrc
  596. NULL, // psoMask
  597. pco, // pco
  598. NULL, // pxlo
  599. &rclDst, // prclDst
  600. (PPOINTL)&rclSrc, // pptlSrc
  601. NULL, // pptlMask
  602. NULL, // pbo
  603. (PPOINTL)&ptlZeroOrigin, // pptlBrushOrg
  604. Mix2))) {
  605. PLOTERR(("DoMix2: EngBitBlt(MemMix2=%04lx) Failed!!!",Mix2));
  606. return(FALSE);
  607. }
  608. } else {
  609. if (!OutputHTBitmap(pPDev,
  610. psoSrc,
  611. pco,
  612. (PPOINTL)&rclDst,
  613. &rclSrc,
  614. Mix2,
  615. &OHTFlags)) {
  616. PLOTERR(("DoMix2: OutputHTBitmap() Failed!!!"));
  617. return(FALSE);
  618. }
  619. }
  620. //
  621. // Reset <source left> to the original left margin and move the
  622. // destination right to the left for the next destination RECTL.
  623. //
  624. rclSrc.left = prclSrc->left;
  625. rclDst.left = rclDst.right;
  626. rclDst.right += cxSrc;
  627. }
  628. //
  629. // Reset <source top> to the original top margin and move the
  630. // destination bottom to the top, and set bottom for the next destination
  631. // RECTL.
  632. //
  633. rclSrc.top = prclSrc->top;
  634. rclDst.top = rclDst.bottom;
  635. rclDst.bottom += cySrc;
  636. }
  637. if (OHTFlags & OHTF_MASK) {
  638. OHTFlags |= OHTF_EXIT_TO_HPGL2;
  639. OutputHTBitmap(pPDev, psoSrc, NULL, NULL, NULL, 0xAA, &OHTFlags);
  640. }
  641. return(TRUE);
  642. }
  643. BOOL
  644. DoRop3(
  645. PPDEV pPDev,
  646. SURFOBJ *psoDst,
  647. SURFOBJ *psoSrc,
  648. SURFOBJ *psoPat,
  649. SURFOBJ *psoTmp,
  650. CLIPOBJ *pco,
  651. XLATEOBJ *pxlo,
  652. PRECTL prclDst,
  653. PRECTL prclSrc,
  654. PRECTL prclPat,
  655. PPOINTL pptlPatOrg,
  656. BRUSHOBJ *pbo,
  657. DWORD Rop3
  658. )
  659. /*++
  660. Routine Description:
  661. This function performs ROP3 operations (one at a time)
  662. Arguments:
  663. pPDev - Pointer to the PDEV
  664. psoDst - pointer to the destination surface object
  665. psoSrc - pointer to the source surface object
  666. psoPat - Pointer to the pattern surface object
  667. psoTmp - pointer to the temp buffer surface object
  668. pco - clip object
  669. prclDst - pointer to the destination rectangle
  670. prclSrc - pointer to the source rectangle
  671. prclPat - pointer to the pattern rectangle
  672. pptlPatOrg - Pointer to the brush origin, if this is NULL then its assumed
  673. the pattern's prclPat does not have to be aligned on the
  674. destination
  675. pbo - a Brush object if we need to call DoFill()
  676. Rop3 - a ROP3 to be performed
  677. Return Value:
  678. BOOL
  679. Author:
  680. 20-Jan-1994 Thu 02:36:00 created
  681. 27-Jan-1994 Thu 23:46:28 updated
  682. Re-write to take other parameter, also move the cloning surface objects
  683. to the caller (ie. DrvBitBlt())
  684. Revision History:
  685. --*/
  686. {
  687. RECTL rclTmp;
  688. DWORD SDMix;
  689. DWORD Mix2;
  690. BYTE Flags;
  691. UINT Count;
  692. BOOL InvertMix2;
  693. BOOL Ok;
  694. PLOTDBG(DBG_ROP3, ("DoRop3: Rop3=%08lx", Rop3));
  695. switch (Rop3 &= 0xFF) {
  696. case 0x00: // 0
  697. case 0xFF: // 1
  698. case 0x55: // ~D
  699. DoSpecialRop3(psoDst, pco, prclDst, Rop3);
  700. case 0xAA: // D
  701. //
  702. // This is NOP
  703. //
  704. return(TRUE);
  705. }
  706. //
  707. // Invert Rop3 if we are out of the data range (128-255) and then invert
  708. // the final result (by inverting last Mix2 Rop2 code (0-15), all Rop3/Rop2
  709. // codes are symmetric.
  710. //
  711. if (Rop3 >= 0x80) {
  712. InvertMix2 = TRUE;
  713. SDMix = (DWORD)Rop3ToSDMix[Rop3 ^ 0xFF];
  714. PLOTDBG(DBG_ROP3, ("DoRop3: Need Invert ROP"));
  715. } else {
  716. InvertMix2 = FALSE;
  717. SDMix = (DWORD)Rop3ToSDMix[Rop3];
  718. }
  719. if (psoTmp) {
  720. rclTmp.left =
  721. rclTmp.top = 0;
  722. rclTmp.right = psoTmp->sizlBitmap.cx;
  723. rclTmp.bottom = psoTmp->sizlBitmap.cy;
  724. }
  725. Flags = GET_SDMIX_MIX2F(SDMix);
  726. Count = (UINT)GET_MIX2F_COUNT(Flags);
  727. Ok = TRUE;
  728. PLOTDBG(DBG_ROP3, ("SDMix=%08lx, Flags=%02x, Count=%u", SDMix, Flags, Count));
  729. if (Flags & MIX2F_MUL_DST) {
  730. PLOTWARN(("DoRop3: *** Rop3=%08lx Has Multiple DEST, Mix2s NOT complete ***", Rop3));
  731. }
  732. while ((Ok) && (Count--)) {
  733. Mix2 = (DWORD)(SDMix & MIX2_MASK);
  734. if ((!Count) && (InvertMix2)) {
  735. PLOTDBG(DBG_ROP3, ("DoRop3: Invert Last MIX2 %02lx -> %02lx",
  736. Mix2, Mix2 ^ MIX2_MASK));
  737. Mix2 ^= MIX2_MASK;
  738. }
  739. PLOTDBG(DBG_ROP3, ("DoRop3: SD=%02lx, Mix2=%02lx",
  740. SDMix & MIXSD_MASK, Mix2));
  741. switch (SDMix & MIXSD_MASK) {
  742. case MIXSD_SRC_DST:
  743. PLOTASSERT(1, "DoRop3: MIXSD_SRC_DST but psoSrc = NULL, Rop3=%08lx",
  744. psoSrc, Rop3);
  745. Ok = DoMix2(pPDev,
  746. psoDst,
  747. psoSrc,
  748. pco,
  749. pxlo,
  750. prclDst,
  751. prclSrc,
  752. NULL,
  753. Mix2);
  754. break;
  755. case MIXSD_PAT_DST:
  756. if (psoPat) {
  757. Ok = DoMix2(pPDev,
  758. psoDst,
  759. psoPat,
  760. pco,
  761. NULL,
  762. prclDst,
  763. prclPat,
  764. pptlPatOrg,
  765. Mix2);
  766. } else {
  767. //
  768. // A compatible brush object is passed, use DoFill() to do
  769. // the actual work.
  770. //
  771. Mix2 += 1;
  772. Mix2 = MixToRop4(Mix2 | (Mix2 << 8));
  773. PLOTDBG(DBG_ROP3, ("DoRop3: DoFill[%04lx] (%ld, %ld)-(%ld, %ld)=%ld x %ld",
  774. Mix2, prclDst->left, prclDst->top,
  775. prclDst->right, prclDst->bottom,
  776. prclDst->right - prclDst->left,
  777. prclDst->bottom - prclDst->top));
  778. Ok = DoFill(psoDst, // psoDst
  779. NULL, // psoSrc
  780. pco, // pco
  781. NULL, // pxlo
  782. prclDst, // prclDst
  783. NULL, // prclSrc
  784. pbo, // pbo
  785. pptlPatOrg, // pptlBrushOrg
  786. Mix2); // Rop4
  787. }
  788. break;
  789. case MIXSD_SRC_PAT:
  790. PLOTASSERT(1, "DoRop3: MIXSD_SRC_PAT but psoSrc = NULL, Rop3=%08lx",
  791. psoSrc, Rop3);
  792. PLOTASSERT(1, "DoRop3: MIXSD_SRC_PAT but psoPat = NULL, Rop3=%08lx",
  793. psoPat, Rop3);
  794. PLOTASSERT(1, "DoRop3: MIXSD_SRC_PAT but psoTmp = NULL, Rop3=%08lx",
  795. psoTmp, Rop3);
  796. //
  797. // Firs tile the pattern onto the temp buffer then do SRC/DST
  798. // using SRCCOPY = MIX2_S
  799. //
  800. if (pptlPatOrg) {
  801. //
  802. // This is a real pattern we have to tile and align it onto the
  803. // desination, but since psoTmp is 0,0 - cx,cy we must alter
  804. // the pptlPatOrg to make it align correctly.
  805. //
  806. pptlPatOrg->x -= prclDst->left;
  807. pptlPatOrg->y -= prclDst->top;
  808. }
  809. Ok = DoMix2(pPDev,
  810. psoTmp,
  811. psoPat,
  812. NULL,
  813. NULL,
  814. &rclTmp,
  815. prclPat,
  816. pptlPatOrg,
  817. MIX2_S);
  818. if (pptlPatOrg) {
  819. pptlPatOrg->x += prclDst->left;
  820. pptlPatOrg->y += prclDst->top;
  821. }
  822. //
  823. // Now We will do the MIX2 operation between SRC and PAT
  824. //
  825. if (Ok) {
  826. Ok = DoMix2(pPDev,
  827. psoTmp,
  828. psoSrc,
  829. NULL,
  830. NULL,
  831. &rclTmp,
  832. prclSrc,
  833. NULL,
  834. Mix2);
  835. }
  836. break;
  837. case MIXSD_TMP_DST:
  838. PLOTASSERT(1, "DoRop3: MIXSD_TMP_DST but psoTmp = NULL, Rop3=%08lx",
  839. psoTmp, Rop3);
  840. //
  841. // Since we already aligned the pattern on the temp buffer
  842. // we can just do the mix2 without aligning it again.
  843. //
  844. Ok = DoMix2(pPDev,
  845. psoDst,
  846. psoTmp,
  847. pco,
  848. NULL,
  849. prclDst,
  850. &rclTmp,
  851. NULL,
  852. Mix2);
  853. break;
  854. }
  855. SDMix >>= SDMIX_SHIFT_COUNT;
  856. }
  857. if (!Ok) {
  858. PLOTERR(("DoRop3: FAILED in DoMix2() operations"));
  859. }
  860. return(Ok);
  861. }