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.

3927 lines
134 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * *******************
  4. * * GDI SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: bitblt.c
  8. *
  9. * Note: Since we've implemented device-bitmaps, any surface that GDI passes
  10. * to us can have 3 values for its 'iType': STYPE_BITMAP, STYPE_DEVICE
  11. * or STYPE_DEVBITMAP. We filter device-bitmaps that we've stored
  12. * as DIBs fairly high in the code, so after we adjust its 'pptlSrc',
  13. * we can treat STYPE_DEVBITMAP surfaces the same as STYPE_DEVICE
  14. * surfaces (e.g., a blt from an off-screen device bitmap to the screen
  15. * gets treated as a normal screen-to-screen blt). So throughout
  16. * this code, we will compare a surface's 'iType' to STYPE_BITMAP:
  17. * if it's equal, we've got a true DIB, and if it's unequal, we have
  18. * a screen-to-screen operation.
  19. *
  20. * Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
  21. * Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
  22. \*****************************************************************************/
  23. #include "precomp.h"
  24. #include "glint.h"
  25. /************************************************************************\
  26. *
  27. * decompose all rops into GLINT logic ops if the dest is the screen.
  28. * Sometimes we do this in a few stages. The following defines mimic
  29. * the definitions found in the ROP3 table in the books. The idea
  30. * is to minimize errors in constructing the ropTable array below by
  31. * allowing me to copy the reverse Polish notation more or less in
  32. * tact.
  33. *
  34. \**************************************************************************/
  35. #define unset __GLINT_LOGICOP_CLEAR
  36. #define P __GLINT_LOGICOP_COPY
  37. #define S P
  38. #define DPna __GLINT_LOGICOP_AND_INVERTED
  39. #define DSna DPna
  40. #define DPa __GLINT_LOGICOP_AND
  41. #define DSa DPa
  42. #define PDa DPa
  43. #define SDa DPa
  44. #define PDna __GLINT_LOGICOP_AND_REVERSE
  45. #define SDna PDna
  46. #define DPno __GLINT_LOGICOP_OR_INVERT
  47. #define DSno DPno
  48. #define DPo __GLINT_LOGICOP_OR
  49. #define DSo DPo
  50. #define PDo DPo
  51. #define SDo DPo
  52. #define PDno __GLINT_LOGICOP_OR_REVERSE
  53. #define SDno PDno
  54. #define D __GLINT_LOGICOP_NOOP
  55. #define Dn __GLINT_LOGICOP_INVERT
  56. #define Pn __GLINT_LOGICOP_COPY_INVERT
  57. #define Sn Pn
  58. #define DPan __GLINT_LOGICOP_NAND
  59. #define DSan DPan
  60. #define PDan DPan
  61. #define SDan DPan
  62. #define DPon __GLINT_LOGICOP_NOR
  63. #define DSon DPon
  64. #define PDon DPon
  65. #define SDon DPon
  66. #define DPxn __GLINT_LOGICOP_EQUIV
  67. #define DSxn DPxn
  68. #define PDxn DPxn
  69. #define SDxn DPxn
  70. #define DPx __GLINT_LOGICOP_XOR
  71. #define DSx DPx
  72. #define PDx DPx
  73. #define SDx DPx
  74. #define set __GLINT_LOGICOP_SET
  75. /************************************************************************\
  76. *
  77. * if we have to first combine the source and pattern before downloading
  78. * to GLINT we use the engine to do it using EngBitBlt. So these are the
  79. * chosen rop3s which combine the source with the pattern. We blt into
  80. * a temporary bitmap and use this to download.
  81. *
  82. \**************************************************************************/
  83. #define SPa 0x30
  84. #define PSa SPa
  85. #define SPan 0x3F
  86. #define PSan SPan
  87. #define SPna 0x0C
  88. #define PSna 0x30
  89. #define SPo 0xFC
  90. #define PSo SPo
  91. #define SPon 0x03
  92. #define PSon SPon
  93. #define SPno 0xCF
  94. #define PSno 0xF3
  95. #define SPx 0x3C
  96. #define PSx SPx
  97. #define SPxn 0xC3
  98. #define PSxn SPxn
  99. #define SPnx SPxn
  100. #define PSnx SPxn
  101. /************************************************************************\
  102. *
  103. * we set up a junp table for the different rop3's. Each entry contains
  104. * a category and a set of 1, 2 or 3 GLINT logic ops. In the main blt
  105. * routine we switch on the category to figure out what routine to call.
  106. * We pass the GLINT logic op straight in without having to do any further
  107. * conversion. By keeping each entry in the table down to 4 bytes it
  108. * takes up 1K of data. That's not too much. The benefit is that in each
  109. * routine we call we don't have to do any checking to see whether the
  110. * rop really needs pattern or source. I've done some pre-processing on
  111. * some of the rops to decompose them into forms which allow us to use
  112. * the hardware in a series of steps. e.g. pattern fill followed by
  113. * source download. If anything doesn't fit into a defined category then
  114. * we go back to the engine.
  115. *
  116. \**************************************************************************/
  117. // categories
  118. #define SOLID_FILL_1_BLT 0 // must be 0
  119. #define PAT_FILL_1_BLT 1 // must be 1
  120. #define SRC_FILL_1_BLT 2 // must be 2
  121. #define PAT_SRC_2_BLT 3 // PatSrcPatBlt
  122. #define PAT_SRC_PAT_3_BLT 4 // PatSrcPatBlt
  123. #define SRC_PAT_2_BLT 5 // SrcPatSrcBlt
  124. #define SRC_PAT_SRC_3_BLT 6 // SrcPatSrcBlt
  125. #define ENG_DOWNLOAD_2_BLT 7 // EngBitBlt for now
  126. #define ENGINE_BITBLT 8 // EngBitBlt always
  127. // adding new entries here may double the table size.
  128. typedef struct _rop_table {
  129. UCHAR func_index;
  130. UCHAR logicop[3];
  131. } RopTableRec, *RopTablePtr;
  132. RopTableRec ropTable[] = {
  133. /* 00 */ { SOLID_FILL_1_BLT, unset },
  134. /* 01 */ { SRC_PAT_2_BLT, SDo, DPon, },
  135. /* 02 */ { SRC_PAT_2_BLT, DSna, DPna },
  136. /* 03 */ { SRC_PAT_2_BLT, S, PDon, },
  137. /* 04 */ { SRC_PAT_2_BLT, SDna, DPna, },
  138. /* 05 */ { PAT_FILL_1_BLT, DPon, },
  139. /* 06 */ { SRC_PAT_2_BLT, DSxn, PDon, },
  140. /* 07 */ { SRC_PAT_2_BLT, DSa, PDon, },
  141. /* 08 */ { SRC_PAT_2_BLT, DSa, DPna, },
  142. /* 09 */ { SRC_PAT_2_BLT, DSx, PDon, },
  143. /* 0A */ { PAT_FILL_1_BLT, DPna, },
  144. /* 0B */ { SRC_PAT_2_BLT, SDna, PDon, },
  145. /* 0C */ { SRC_PAT_2_BLT, S, DPna, },
  146. /* 0D */ { SRC_PAT_2_BLT, DSna, PDon, },
  147. /* 0E */ { SRC_PAT_2_BLT, DSon, PDon, },
  148. /* 0F */ { PAT_FILL_1_BLT, Pn, },
  149. /* 10 */ { SRC_PAT_2_BLT, DSon, PDa, },
  150. /* 11 */ { SRC_FILL_1_BLT, DSon, },
  151. /* 12 */ { PAT_SRC_2_BLT, DPxn, SDon, },
  152. /* 13 */ { PAT_SRC_2_BLT, DPa, SDon, },
  153. /* 14 */ { ENG_DOWNLOAD_2_BLT, PSx, SDno, },
  154. /* 15 */ { ENG_DOWNLOAD_2_BLT, PSa, DSon, },
  155. /* 16 */ { ENGINE_BITBLT, },
  156. /* 17 */ { ENGINE_BITBLT, },
  157. /* 18 */ { ENGINE_BITBLT, },
  158. /* 19 */ { ENGINE_BITBLT, },
  159. /* 1A */ { ENGINE_BITBLT, },
  160. /* 1B */ { ENGINE_BITBLT, },
  161. /* 1C */ { PAT_SRC_PAT_3_BLT, DPa, SDo, PDx, },
  162. /* 1D */ { ENGINE_BITBLT, },
  163. /* 1E */ { SRC_PAT_2_BLT, DSo, PDx, },
  164. /* 1F */ { SRC_PAT_2_BLT, DSo, PDan, },
  165. /* 20 */ { SRC_PAT_2_BLT, DSna, PDa, },
  166. /* 21 */ { PAT_SRC_2_BLT, DPx, SDon, },
  167. /* 22 */ { SRC_FILL_1_BLT, DSna, },
  168. /* 23 */ { PAT_SRC_2_BLT, PDna, SDon, },
  169. /* 24 */ { ENGINE_BITBLT, },
  170. /* 25 */ { ENGINE_BITBLT, },
  171. /* 26 */ { ENGINE_BITBLT, },
  172. /* 27 */ { ENGINE_BITBLT, },
  173. /* 28 */ { ENG_DOWNLOAD_2_BLT, PSx, DSa, },
  174. /* 29 */ { ENGINE_BITBLT, },
  175. /* 2A */ { ENG_DOWNLOAD_2_BLT, PSa, DSna, },
  176. /* 2B */ { ENGINE_BITBLT, },
  177. /* 2C */ { SRC_PAT_SRC_3_BLT, DSo, PDa, SDx, },
  178. /* 2D */ { SRC_PAT_2_BLT, SDno, PDx, },
  179. /* 2E */ { PAT_SRC_PAT_3_BLT, DPx, SDo, PDx, },
  180. /* 2F */ { SRC_PAT_2_BLT, SDno, PDan, },
  181. /* 30 */ { SRC_PAT_2_BLT, S, PDna, },
  182. /* 31 */ { PAT_SRC_2_BLT, DPna, SDon, },
  183. /* 32 */ { SRC_PAT_SRC_3_BLT, SDo, PDo, SDx },
  184. /* 33 */ { SRC_FILL_1_BLT, Sn, },
  185. /* 34 */ { SRC_PAT_SRC_3_BLT, DSa, PDo, SDx, },
  186. /* 35 */ { SRC_PAT_SRC_3_BLT, DSxn, PDo, SDx, },
  187. /* 36 */ { PAT_SRC_2_BLT, DPo, SDx, },
  188. /* 37 */ { PAT_SRC_2_BLT, DPo, SDan, },
  189. /* 38 */ { PAT_SRC_PAT_3_BLT, DPo, SDa, PDx, },
  190. /* 39 */ { PAT_SRC_2_BLT, PDno, SDx, },
  191. /* 3A */ { SRC_PAT_SRC_3_BLT, DSx, PDo, SDx, },
  192. /* 3B */ { PAT_SRC_2_BLT, PDno, SDan, },
  193. /* 3C */ { SRC_PAT_2_BLT, S, PDx, },
  194. /* 3D */ { SRC_PAT_SRC_3_BLT, DSon, PDo, SDx, },
  195. /* 3E */ { SRC_PAT_SRC_3_BLT, DSna, PDo, SDx, },
  196. /* 3F */ { SRC_PAT_2_BLT, S, PDan, },
  197. /* 40 */ { SRC_PAT_2_BLT, SDna, PDa, },
  198. /* 41 */ { ENG_DOWNLOAD_2_BLT, PSx, DSon, },
  199. /* 42 */ { ENGINE_BITBLT, },
  200. /* 43 */ { SRC_PAT_SRC_3_BLT, DSan, PDa, SDxn, },
  201. /* 44 */ { SRC_FILL_1_BLT, SDna, },
  202. /* 45 */ { ENG_DOWNLOAD_2_BLT, PSna, DSon, },
  203. /* 46 */ { ENGINE_BITBLT, },
  204. /* 47 */ { PAT_SRC_PAT_3_BLT, DPx, SDa, PDxn, },
  205. /* 48 */ { PAT_SRC_2_BLT, DPx, SDa, },
  206. /* 49 */ { ENGINE_BITBLT, },
  207. /* 4A */ { ENGINE_BITBLT, },
  208. /* 4B */ { SRC_PAT_2_BLT, DSno, PDx, },
  209. /* 4C */ { PAT_SRC_2_BLT, DPan, SDa, },
  210. /* 4D */ { ENGINE_BITBLT, },
  211. /* 4E */ { ENGINE_BITBLT, },
  212. /* 4F */ { SRC_PAT_2_BLT, DSno, PDan, },
  213. /* 50 */ { PAT_FILL_1_BLT, PDna, },
  214. /* 51 */ { ENG_DOWNLOAD_2_BLT, SPna, DSon, },
  215. /* 52 */ { ENGINE_BITBLT, },
  216. /* 53 */ { SRC_PAT_SRC_3_BLT, DSx, PDa, SDxn, },
  217. /* 54 */ { ENG_DOWNLOAD_2_BLT, PSo, SDna, },
  218. /* 55 */ { SOLID_FILL_1_BLT, Dn, },
  219. /* 56 */ { ENG_DOWNLOAD_2_BLT, PSo, DSx, },
  220. /* 57 */ { ENG_DOWNLOAD_2_BLT, PSo, DSan, },
  221. /* 58 */ { ENGINE_BITBLT, },
  222. /* 59 */ { ENG_DOWNLOAD_2_BLT, PSno, DSx, },
  223. /* 5A */ { PAT_FILL_1_BLT, DPx, },
  224. /* 5B */ { ENGINE_BITBLT, },
  225. /* 5C */ { ENGINE_BITBLT, },
  226. /* 5D */ { ENG_DOWNLOAD_2_BLT, PSno, DSan, },
  227. /* 5E */ { ENGINE_BITBLT, },
  228. /* 5F */ { PAT_FILL_1_BLT, DPan, },
  229. /* 60 */ { SRC_PAT_2_BLT, DSx, PDa, },
  230. /* 61 */ { ENGINE_BITBLT, },
  231. /* 62 */ { ENGINE_BITBLT, },
  232. /* 63 */ { PAT_SRC_2_BLT, DPno, SDx, },
  233. /* 64 */ { ENGINE_BITBLT, },
  234. /* 65 */ { ENG_DOWNLOAD_2_BLT, SPno, DSx, },
  235. /* 66 */ { SRC_FILL_1_BLT, DSx, },
  236. /* 67 */ { ENGINE_BITBLT, },
  237. /* 68 */ { ENGINE_BITBLT, },
  238. /* 69 */ { SRC_PAT_2_BLT, DSx, PDxn, },
  239. /* 6A */ { ENG_DOWNLOAD_2_BLT, PSa, DSx, },
  240. /* 6B */ { ENGINE_BITBLT, },
  241. /* 6C */ { PAT_SRC_2_BLT, DPa, SDx, },
  242. /* 6D */ { ENGINE_BITBLT, },
  243. /* 6E */ { ENGINE_BITBLT, },
  244. /* 6F */ { SRC_PAT_2_BLT, DSxn, PDan, },
  245. /* 70 */ { SRC_PAT_2_BLT, DSan, PDa, },
  246. /* 71 */ { ENGINE_BITBLT, },
  247. /* 72 */ { ENGINE_BITBLT, },
  248. /* 73 */ { PAT_SRC_2_BLT, DPno, SDan, },
  249. /* 74 */ { ENGINE_BITBLT, },
  250. /* 75 */ { ENG_DOWNLOAD_2_BLT, SPno, DSan, },
  251. /* 76 */ { ENGINE_BITBLT, },
  252. /* 77 */ { SRC_FILL_1_BLT, DSan, },
  253. /* 78 */ { SRC_PAT_2_BLT, DSa, PDx, },
  254. /* 79 */ { ENGINE_BITBLT, },
  255. /* 7A */ { ENGINE_BITBLT, },
  256. /* 7B */ { PAT_SRC_2_BLT, DPxn, SDan, },
  257. /* 7C */ { SRC_PAT_SRC_3_BLT, DSno, PDa, SDx, },
  258. /* 7D */ { ENG_DOWNLOAD_2_BLT, PSxn, DSan, },
  259. /* 7E */ { ENGINE_BITBLT, },
  260. /* 7F */ { ENG_DOWNLOAD_2_BLT, PSa, DSan, },
  261. /* 80 */ { ENG_DOWNLOAD_2_BLT, PSa, DSa, },
  262. /* 81 */ { ENGINE_BITBLT, },
  263. /* 82 */ { ENG_DOWNLOAD_2_BLT, PSx, DSna, },
  264. /* 83 */ { SRC_PAT_SRC_3_BLT, DSno, PDa, SDxn, },
  265. /* 84 */ { PAT_SRC_2_BLT, DPxn, SDa, },
  266. /* 85 */ { ENGINE_BITBLT, },
  267. /* 86 */ { ENGINE_BITBLT, },
  268. /* 87 */ { SRC_PAT_2_BLT, DSa, PDxn, },
  269. /* 88 */ { SRC_FILL_1_BLT, DSa, },
  270. /* 89 */ { ENGINE_BITBLT, },
  271. /* 8A */ { ENG_DOWNLOAD_2_BLT, SPno, DSa, },
  272. /* 8B */ { ENGINE_BITBLT, },
  273. /* 8C */ { PAT_SRC_2_BLT, DPno, SDa, },
  274. /* 8D */ { ENGINE_BITBLT, },
  275. /* 8E */ { ENGINE_BITBLT, },
  276. /* 8F */ { SRC_PAT_2_BLT, DSan, PDan, },
  277. /* 90 */ { SRC_PAT_2_BLT, DSxn, PDa, },
  278. /* 91 */ { ENGINE_BITBLT, },
  279. /* 92 */ { ENGINE_BITBLT, },
  280. /* 93 */ { PAT_SRC_2_BLT, PDa, SDxn, },
  281. /* 94 */ { ENGINE_BITBLT, },
  282. /* 95 */ { ENG_DOWNLOAD_2_BLT, PSa, DSxn, },
  283. /* 96 */ { SRC_PAT_2_BLT, DSx, PDx, }, /* DPSxx == PDSxx */
  284. /* 97 */ { ENGINE_BITBLT, },
  285. /* 98 */ { ENGINE_BITBLT, },
  286. /* 99 */ { SRC_FILL_1_BLT, DSxn, },
  287. /* 9A */ { ENG_DOWNLOAD_2_BLT, PSna, DSx, },
  288. /* 9B */ { ENGINE_BITBLT, },
  289. /* 9C */ { PAT_SRC_2_BLT, PDna, SDx, },
  290. /* 9D */ { ENGINE_BITBLT, },
  291. /* 9E */ { ENGINE_BITBLT, },
  292. /* 9F */ { SRC_PAT_2_BLT, DSx, PDan, },
  293. /* A0 */ { PAT_FILL_1_BLT, DPa, },
  294. /* A1 */ { ENGINE_BITBLT, },
  295. /* A2 */ { ENG_DOWNLOAD_2_BLT, PSno, DSa, },
  296. /* A3 */ { ENGINE_BITBLT, },
  297. /* A4 */ { ENGINE_BITBLT, },
  298. /* A5 */ { PAT_FILL_1_BLT, PDxn, },
  299. /* A6 */ { ENG_DOWNLOAD_2_BLT, SPna, DSx, },
  300. /* A7 */ { ENGINE_BITBLT, },
  301. /* A8 */ { ENG_DOWNLOAD_2_BLT, PSo, DSa, },
  302. /* A9 */ { ENG_DOWNLOAD_2_BLT, PSo, DSxn, },
  303. /* AA */ { SOLID_FILL_1_BLT, D },
  304. /* AB */ { ENG_DOWNLOAD_2_BLT, PSo, DSno, },
  305. /* AC */ { SRC_PAT_SRC_3_BLT, DSx, PDa, SDx, },
  306. /* AD */ { ENGINE_BITBLT, },
  307. /* AE */ { ENG_DOWNLOAD_2_BLT, SPna, DSo, },
  308. /* AF */ { PAT_FILL_1_BLT, DPno, },
  309. /* B0 */ { SRC_PAT_2_BLT, DSno, PDa, },
  310. /* B1 */ { ENGINE_BITBLT, },
  311. /* B2 */ { ENGINE_BITBLT, },
  312. /* B3 */ { PAT_SRC_2_BLT, DPan, SDan, },
  313. /* B4 */ { SRC_PAT_2_BLT, SDna, PDx, },
  314. /* B5 */ { ENGINE_BITBLT, },
  315. /* B6 */ { ENGINE_BITBLT, },
  316. /* B7 */ { PAT_SRC_2_BLT, DPx, SDan, },
  317. /* B8 */ { PAT_SRC_PAT_3_BLT, DPx, SDa, PDx, },
  318. /* B9 */ { ENGINE_BITBLT, },
  319. /* BA */ { ENG_DOWNLOAD_2_BLT, PSna, DSo, },
  320. /* BB */ { SRC_FILL_1_BLT, DSno, },
  321. /* BC */ { SRC_PAT_SRC_3_BLT, DSan, PDa, SDx, },
  322. /* BD */ { ENGINE_BITBLT, },
  323. /* BE */ { ENG_DOWNLOAD_2_BLT, PSx, DSo, },
  324. /* BF */ { ENG_DOWNLOAD_2_BLT, PSa, DSno, },
  325. /* C0 */ { SRC_PAT_2_BLT, S, PDa, },
  326. /* C1 */ { ENGINE_BITBLT, },
  327. /* C2 */ { ENGINE_BITBLT, },
  328. /* C3 */ { SRC_PAT_2_BLT, S, PDxn, },
  329. /* C4 */ { PAT_SRC_2_BLT, PDno, SDa, },
  330. /* C5 */ { SRC_PAT_SRC_3_BLT, DSx, PDo, SDxn, },
  331. /* C6 */ { PAT_SRC_2_BLT, DPna, SDx, },
  332. /* C7 */ { PAT_SRC_PAT_3_BLT, DPo, SDa, PDxn, },
  333. /* C8 */ { PAT_SRC_2_BLT, DPo, SDa, },
  334. /* C9 */ { PAT_SRC_2_BLT, PDo, SDxn, },
  335. /* CA */ { ENGINE_BITBLT, },
  336. /* CB */ { SRC_PAT_SRC_3_BLT, DSa, PDo, SDxn, },
  337. /* CC */ { SRC_FILL_1_BLT, S, },
  338. /* CD */ { PAT_SRC_2_BLT, DPon, SDo, },
  339. /* CE */ { PAT_SRC_2_BLT, DPna, SDo, },
  340. /* CF */ { SRC_PAT_2_BLT, S, DPno, },
  341. /* D0 */ { SRC_PAT_2_BLT, SDno, PDa, },
  342. /* D1 */ { PAT_SRC_PAT_3_BLT, DPx, SDo, PDxn, },
  343. /* D2 */ { SRC_PAT_2_BLT, DSna, PDx, },
  344. /* D3 */ { SRC_PAT_SRC_3_BLT, DSo, PDa, SDxn, },
  345. /* D4 */ { ENGINE_BITBLT, },
  346. /* D5 */ { ENG_DOWNLOAD_2_BLT, PSan, DSan, },
  347. /* D6 */ { ENGINE_BITBLT, },
  348. /* D7 */ { ENG_DOWNLOAD_2_BLT, PSx, DSan, },
  349. /* D8 */ { ENGINE_BITBLT, },
  350. /* D9 */ { ENGINE_BITBLT, },
  351. /* DA */ { ENGINE_BITBLT, },
  352. /* DB */ { ENGINE_BITBLT, },
  353. /* DC */ { PAT_SRC_2_BLT, PDna, SDo, },
  354. /* DD */ { SRC_FILL_1_BLT, SDno, },
  355. /* DE */ { PAT_SRC_2_BLT, DPx, SDo, },
  356. /* DF */ { ENG_DOWNLOAD_2_BLT, DPan, SDo, },
  357. /* E0 */ { SRC_PAT_2_BLT, DSo, PDa, },
  358. /* E1 */ { SRC_PAT_2_BLT, DSo, PDxn, },
  359. /* E2 */ { ENGINE_BITBLT, }, /* DSPDxax : XXX S3 special cases this */
  360. /* E3 */ { PAT_SRC_PAT_3_BLT, DPa, SDo, PDxn, },
  361. /* E4 */ { ENGINE_BITBLT, },
  362. /* E5 */ { ENGINE_BITBLT, },
  363. /* E6 */ { ENGINE_BITBLT, },
  364. /* E7 */ { ENGINE_BITBLT, },
  365. /* E8 */ { ENGINE_BITBLT, },
  366. /* E9 */ { ENGINE_BITBLT, },
  367. /* EA */ { ENG_DOWNLOAD_2_BLT, PSa, DSo, },
  368. /* EB */ { ENG_DOWNLOAD_2_BLT, PSx, DSno, },
  369. /* EC */ { PAT_SRC_2_BLT, DPa, SDo, },
  370. /* ED */ { PAT_SRC_2_BLT, DPxn, SDo, },
  371. /* EE */ { SRC_FILL_1_BLT, DSo, },
  372. /* EF */ { SRC_PAT_2_BLT, SDo, DPno },
  373. /* F0 */ { PAT_FILL_1_BLT, P, },
  374. /* F1 */ { SRC_PAT_2_BLT, DSon, PDo, },
  375. /* F2 */ { SRC_PAT_2_BLT, DSna, PDo, },
  376. /* F3 */ { SRC_PAT_2_BLT, S, PDno, },
  377. /* F4 */ { SRC_PAT_2_BLT, SDna, PDo, },
  378. /* F5 */ { PAT_FILL_1_BLT, PDno, },
  379. /* F6 */ { SRC_PAT_2_BLT, DSx, PDo, },
  380. /* F7 */ { SRC_PAT_2_BLT, DSan, PDo, },
  381. /* F8 */ { SRC_PAT_2_BLT, DSa, PDo, },
  382. /* F9 */ { SRC_PAT_2_BLT, DSxn, PDo, },
  383. /* FA */ { PAT_FILL_1_BLT, DPo, },
  384. /* FB */ { SRC_PAT_2_BLT, DSno, PDo, },
  385. /* FC */ { SRC_PAT_2_BLT, S, PDo, },
  386. /* FD */ { SRC_PAT_2_BLT, SDno, PDo, },
  387. /* FE */ { ENG_DOWNLOAD_2_BLT, PSo, DSo, },
  388. /* FF */ { SOLID_FILL_1_BLT, set, },
  389. };
  390. // table to determine which logicops need read dest turned on in FBReadMode
  391. DWORD LogicopReadDest[] = {
  392. 0, /* 00 */
  393. __FB_READ_DESTINATION, /* 01 */
  394. __FB_READ_DESTINATION, /* 02 */
  395. 0, /* 03 */
  396. __FB_READ_DESTINATION, /* 04 */
  397. __FB_READ_DESTINATION, /* 05 */
  398. __FB_READ_DESTINATION, /* 06 */
  399. __FB_READ_DESTINATION, /* 07 */
  400. __FB_READ_DESTINATION, /* 08 */
  401. __FB_READ_DESTINATION, /* 09 */
  402. __FB_READ_DESTINATION, /* 10 */
  403. __FB_READ_DESTINATION, /* 11 */
  404. 0, /* 12 */
  405. __FB_READ_DESTINATION, /* 13 */
  406. __FB_READ_DESTINATION, /* 14 */
  407. 0, /* 15 */
  408. };
  409. // translate a ROP2 into a GLINT logicop. Note, ROP2's start at 1 so
  410. // entry 0 is not used.
  411. DWORD GlintLogicOpsFromR2[] = {
  412. 0, /* rop2's start at 1 */
  413. __GLINT_LOGICOP_CLEAR, /* 0 1 */
  414. __GLINT_LOGICOP_NOR, /* DPon 2 */
  415. __GLINT_LOGICOP_AND_INVERTED, /* DPna 3 */
  416. __GLINT_LOGICOP_COPY_INVERT, /* Pn 4 */
  417. __GLINT_LOGICOP_AND_REVERSE, /* PDna 5 */
  418. __GLINT_LOGICOP_INVERT, /* Dn 6 */
  419. __GLINT_LOGICOP_XOR, /* DPx 7 */
  420. __GLINT_LOGICOP_NAND, /* DPan 8 */
  421. __GLINT_LOGICOP_AND, /* DPa 9 */
  422. __GLINT_LOGICOP_EQUIV, /* DPxn 10 */
  423. __GLINT_LOGICOP_NOOP, /* D 11 */
  424. __GLINT_LOGICOP_OR_INVERT, /* DPno 12 */
  425. __GLINT_LOGICOP_COPY, /* P 13 */
  426. __GLINT_LOGICOP_OR_REVERSE, /* PDno 14 */
  427. __GLINT_LOGICOP_OR, /* DPo 15 */
  428. __GLINT_LOGICOP_SET, /* 1 16 */
  429. };
  430. BOOL
  431. PatternFillRect(PPDEV, RECTL *, CLIPOBJ *, BRUSHOBJ *,
  432. POINTL *, ULONG, ULONG);
  433. BOOL
  434. SourceFillRect(PPDEV, RECTL *, CLIPOBJ *, SURFOBJ *, XLATEOBJ *,
  435. POINTL *, ULONG, ULONG);
  436. BOOL
  437. PatSrcPatBlt(PPDEV, SURFOBJ*, CLIPOBJ*, XLATEOBJ*, RECTL*,
  438. POINTL*, BRUSHOBJ*, POINTL*, RopTablePtr);
  439. BOOL
  440. SrcPatSrcBlt(PPDEV, SURFOBJ*, CLIPOBJ*, XLATEOBJ*, RECTL*,
  441. POINTL*, BRUSHOBJ*, POINTL*, RopTablePtr);
  442. BOOL
  443. MaskCopyBlt(PPDEV, RECTL*, CLIPOBJ*, SURFOBJ*, SURFOBJ*, POINTL*,
  444. POINTL*, ULONG, ULONG);
  445. BOOL
  446. bUploadRect(PPDEV, CLIPOBJ *, SURFOBJ *, SURFOBJ *, POINTL *, RECTL *);
  447. BOOL bUploadBlt(
  448. PPDEV,
  449. SURFOBJ *,
  450. SURFOBJ *,
  451. SURFOBJ *,
  452. CLIPOBJ *,
  453. XLATEOBJ *,
  454. RECTL *,
  455. POINTL *,
  456. POINTL *,
  457. BRUSHOBJ *,
  458. POINTL *,
  459. ROP4);
  460. #if defined(_X86_)
  461. // Mono upload functions
  462. BOOL DoScreenToMono(
  463. PDEV* ppdev,
  464. RECTL *prclDst,
  465. CLIPOBJ *pco,
  466. SURFOBJ* psoSrc, // Source surface
  467. SURFOBJ* psoDst, // Destination surface
  468. POINTL* pptlSrc, // Original unclipped source point
  469. XLATEOBJ* pxlo); // Provides colour-compressions information
  470. VOID vXferScreenTo1bpp(
  471. PDEV* ppdev,
  472. LONG c, // Count of rectangles, can't be zero
  473. RECTL* prcl, // List of destination rectangles, in
  474. // relative coordinates
  475. ULONG ulHwMix, // Not used
  476. SURFOBJ* psoSrc, // Source surface
  477. SURFOBJ* psoDst, // Destination surface
  478. POINTL* pptlSrc, // Original unclipped source point
  479. RECTL* prclDst, // Original unclipped destination rectangle
  480. XLATEOBJ* pxlo); // Provides colour-compressions information
  481. #endif // defined(_X86_)
  482. /******************************Public*Routine******************************\
  483. * BOOL bIntersect
  484. *
  485. * If 'prcl1' and 'prcl2' intersect, has a return value of TRUE and returns
  486. * the intersection in 'prclResult'. If they don't intersect, has a return
  487. * value of FALSE, and 'prclResult' is undefined.
  488. *
  489. \**************************************************************************/
  490. BOOL bIntersect(
  491. RECTL* prcl1,
  492. RECTL* prcl2,
  493. RECTL* prclResult)
  494. {
  495. prclResult->left = max(prcl1->left, prcl2->left);
  496. prclResult->right = min(prcl1->right, prcl2->right);
  497. if (prclResult->left < prclResult->right)
  498. {
  499. prclResult->top = max(prcl1->top, prcl2->top);
  500. prclResult->bottom = min(prcl1->bottom, prcl2->bottom);
  501. if (prclResult->top < prclResult->bottom)
  502. {
  503. return(TRUE);
  504. }
  505. }
  506. return(FALSE);
  507. }
  508. /******************************Public*Routine******************************\
  509. * LONG cIntersect
  510. *
  511. * This routine takes a list of rectangles from 'prclIn' and clips them
  512. * in-place to the rectangle 'prclClip'. The input rectangles don't
  513. * have to intersect 'prclClip'; the return value will reflect the
  514. * number of input rectangles that did intersect, and the intersecting
  515. * rectangles will be densely packed.
  516. *
  517. \**************************************************************************/
  518. LONG cIntersect(
  519. RECTL* prclClip,
  520. RECTL* prclIn, // List of rectangles
  521. LONG c) // Can be zero
  522. {
  523. LONG cIntersections;
  524. RECTL* prclOut;
  525. cIntersections = 0;
  526. prclOut = prclIn;
  527. for (; c != 0; prclIn++, c--)
  528. {
  529. prclOut->left = max(prclIn->left, prclClip->left);
  530. prclOut->right = min(prclIn->right, prclClip->right);
  531. if (prclOut->left < prclOut->right)
  532. {
  533. prclOut->top = max(prclIn->top, prclClip->top);
  534. prclOut->bottom = min(prclIn->bottom, prclClip->bottom);
  535. if (prclOut->top < prclOut->bottom)
  536. {
  537. prclOut++;
  538. cIntersections++;
  539. }
  540. }
  541. }
  542. return(cIntersections);
  543. }
  544. /******************************Public*Routine******************************\
  545. * VOID vGlintChangeFBDepth
  546. *
  547. * Change the GLINT packing mode for different depths. We use this to speed
  548. * up rendering for 8 and 16 bpp where we can process up to 4 pixels at a
  549. * time.
  550. *
  551. \**************************************************************************/
  552. VOID vGlintChangeFBDepth(
  553. PPDEV ppdev,
  554. ULONG cPelSize)
  555. {
  556. ULONG cFlags;
  557. GLINT_DECL;
  558. DISPDBG((DBGLVL, "setting current pixel depth to %d",
  559. (cPelSize == 0) ? 8 : (cPelSize == 1) ? 16 : 32));
  560. glintInfo->FBReadMode = glintInfo->packing[cPelSize].readMode;
  561. glintInfo->currentPelSize = cPelSize;
  562. // Toggle the FBReadMode cache flag
  563. DISPDBG((DBGLVL, "setting FBReadMode to 0x%08x", glintInfo->FBReadMode));
  564. cFlags = CHECK_CACHEFLAGS (ppdev, 0xFFFFFFFF);
  565. SET_CACHEFLAGS (ppdev, (cFlags & ~cFlagFBReadDefault));
  566. // set FX pixel depth
  567. // 0 - 8 bits, 1 - 16 bits and 2 - 32 bits.
  568. DISPDBG((DBGLVL, "Changing FBDepth for PERMEDIA"));
  569. WAIT_GLINT_FIFO(1);
  570. LD_GLINT_FIFO(__PermediaTagFBReadPixel, cPelSize);
  571. }
  572. /******************************Public*Routine******************************\
  573. * BOOL DrvBitBlt
  574. *
  575. * Implements the workhorse routine of a display driver.
  576. *
  577. \**************************************************************************/
  578. BOOL DrvBitBlt(
  579. SURFOBJ *psoDst,
  580. SURFOBJ *psoSrc,
  581. SURFOBJ *psoMsk,
  582. CLIPOBJ *pco,
  583. XLATEOBJ *pxlo,
  584. RECTL *prclDst,
  585. POINTL *pptlSrc,
  586. POINTL *pptlMsk,
  587. BRUSHOBJ *pbo,
  588. POINTL *pptlBrush,
  589. ROP4 rop4)
  590. {
  591. BOOL bRet;
  592. PPDEV ppdev;
  593. DSURF *pdsurfDst;
  594. DSURF *pdsurfSrc;
  595. UCHAR funcIndexFore;
  596. UCHAR funcIndexBack;
  597. XLATECOLORS xlc;
  598. XLATEOBJ xlo;
  599. RopTablePtr pTableFore;
  600. RopTablePtr pTableBack;
  601. HSURF hsurfSrcBitmap, hsurfDstBitmap;
  602. SURFOBJ *psoSrcBitmap, *psoDstBitmap;
  603. SURFOBJ *psoSrcOrig = psoSrc, *psoDstOrig = psoDst;
  604. GLINT_DECL_VARS;
  605. // We need to remove the pointer, but we dont know which surface is valid
  606. // (if either).
  607. if ((psoDst->iType != STYPE_BITMAP) &&
  608. (((DSURF *)(psoDst->dhsurf))->dt & DT_SCREEN))
  609. {
  610. ppdev = (PDEV *)psoDst->dhpdev;
  611. REMOVE_SWPOINTER(psoDst);
  612. }
  613. else if (psoSrc &&
  614. (psoSrc->iType != STYPE_BITMAP) &&
  615. (((DSURF *)(psoSrc->dhsurf))->dt & DT_SCREEN))
  616. {
  617. ppdev = (PDEV *)psoSrc->dhpdev;
  618. REMOVE_SWPOINTER(psoSrc);
  619. }
  620. // GDI will never give us a Rop4 with the bits in the high-word set
  621. // (so that we can check if it's actually a Rop3 via the expression
  622. // (rop4 >> 8) == (rop4 & 0xff))
  623. ASSERTDD((rop4 >> 16) == 0, "Didn't expect a rop4 with high bits set");
  624. #if !defined(_WIN64) && WNT_DDRAW
  625. // Touch the source surface 1st and then the destination surface
  626. vSurfUsed(psoSrc);
  627. vSurfUsed(psoDst);
  628. #endif
  629. pdsurfDst = (DSURF *)psoDst->dhsurf;
  630. if (psoSrc == NULL)
  631. {
  632. ///////////////////////////////////////////////////////////////////
  633. // Fills
  634. ///////////////////////////////////////////////////////////////////
  635. // Fills are this function's "raison d'etre", so we handle them
  636. // as quickly as possible:
  637. ASSERTDD(pdsurfDst != NULL,
  638. "Expect only device destinations when no source");
  639. if (pdsurfDst->dt & DT_SCREEN)
  640. {
  641. OH* poh;
  642. BOOL bMore;
  643. CLIPENUM ce;
  644. LONG c;
  645. RECTL rcl;
  646. BYTE rop3;
  647. GFNFILL* pfnFill;
  648. RBRUSH_COLOR rbc; // Realized brush or solid colour
  649. DWORD fgLogicop;
  650. DWORD bgLogicop;
  651. ppdev = (PDEV*) psoDst->dhpdev;
  652. GLINT_DECL_INIT;
  653. poh = pdsurfDst->poh;
  654. SETUP_PPDEV_OFFSETS(ppdev, pdsurfDst);
  655. VALIDATE_DD_CONTEXT;
  656. // Make sure it doesn't involve a mask (i.e., it's really a
  657. // Rop3):
  658. rop3 = (BYTE) rop4;
  659. if ((BYTE) (rop4 >> 8) == rop3)
  660. {
  661. // Since 'psoSrc' is NULL, the rop3 had better not indicate
  662. // that we need a source.
  663. ASSERTDD((((rop4 >> 2) ^ (rop4)) & 0x33) == 0,
  664. "Need source but GDI gave us a NULL 'psoSrc'");
  665. pfnFill = ppdev->pgfnFillSolid; // Default to solid fill
  666. pTableFore = &ropTable[rop4 & 0xff];
  667. pTableBack = &ropTable[rop4 >> 8];
  668. fgLogicop = pTableFore->logicop[0];
  669. if ((((rop3 >> 4) ^ (rop3)) & 0xf) != 0)
  670. {
  671. // The rop says that a pattern is truly required
  672. // (blackness, for instance, doesn't need one):
  673. rbc.iSolidColor = pbo->iSolidColor;
  674. if (rbc.iSolidColor == -1)
  675. {
  676. // Try and realize the pattern brush; by doing
  677. // this call-back, GDI will eventually call us
  678. // again through DrvRealizeBrush:
  679. rbc.prb = pbo->pvRbrush;
  680. if (rbc.prb == NULL)
  681. {
  682. rbc.prb = BRUSHOBJ_pvGetRbrush(pbo);
  683. if (rbc.prb == NULL)
  684. {
  685. // If we couldn't realize the brush, punt
  686. // the call (it may have been a non 8x8
  687. // brush or something, which we can't be
  688. // bothered to handle, so let GDI do the
  689. // drawing):
  690. DISPDBG((WRNLVL, "DrvBitBlt: BRUSHOBJ_pvGetRbrush"
  691. "failed.calling engine_blt"));
  692. GLINT_DECL_INIT;
  693. goto engine_blt;
  694. }
  695. }
  696. if (rbc.prb->fl & RBRUSH_2COLOR)
  697. {
  698. DISPDBG((DBGLVL, "monochrome brush"));
  699. pfnFill = ppdev->pgfnFillPatMono;
  700. }
  701. else
  702. {
  703. DISPDBG((DBGLVL, "colored brush"));
  704. pfnFill = ppdev->pgfnFillPatColor;
  705. }
  706. bgLogicop = pTableBack->logicop[0];
  707. }
  708. }
  709. else
  710. {
  711. // Turn some logicops into solid block fills. We get here
  712. // only for rops 0, 55, AA and FF.
  713. if ((fgLogicop == __GLINT_LOGICOP_SET) ||
  714. (fgLogicop == __GLINT_LOGICOP_CLEAR))
  715. {
  716. rbc.iSolidColor = 0xffffff; // does any depth
  717. if (fgLogicop == __GLINT_LOGICOP_CLEAR)
  718. {
  719. rbc.iSolidColor = 0;
  720. }
  721. fgLogicop = __GLINT_LOGICOP_COPY;
  722. }
  723. else if (fgLogicop == __GLINT_LOGICOP_NOOP)
  724. {
  725. return(TRUE); // DST logicop is a noop
  726. }
  727. }
  728. // Note that these 2 'if's are more efficient than
  729. // a switch statement:
  730. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  731. {
  732. pfnFill(ppdev, 1, prclDst, fgLogicop, bgLogicop,
  733. rbc, pptlBrush);
  734. return TRUE;
  735. }
  736. else if (pco->iDComplexity == DC_RECT)
  737. {
  738. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  739. {
  740. pfnFill(ppdev, 1, &rcl, fgLogicop, bgLogicop,
  741. rbc, pptlBrush);
  742. }
  743. return TRUE;
  744. }
  745. else
  746. {
  747. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  748. do {
  749. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG*) &ce);
  750. c = cIntersect(prclDst, ce.arcl, ce.c);
  751. if (c != 0)
  752. {
  753. pfnFill(ppdev, c, ce.arcl, fgLogicop, bgLogicop,
  754. rbc, pptlBrush);
  755. }
  756. } while (bMore);
  757. return TRUE;
  758. }
  759. }
  760. }
  761. }
  762. #if defined(_X86_)
  763. if ((pxlo != NULL) &&
  764. (pxlo->flXlate & XO_TO_MONO) &&
  765. (psoSrc != NULL) && (pptlSrc != NULL) &&
  766. (psoDst != NULL) && (psoDst->dhsurf == NULL) &&
  767. (psoDst->iBitmapFormat == BMF_1BPP))
  768. {
  769. BYTE rop3 = (BYTE) rop4; // Make rop4 into a Rop3
  770. ppdev = (PDEV*) psoSrc->dhpdev;
  771. pdsurfSrc = (DSURF *)psoSrc->dhsurf;
  772. GLINT_DECL_INIT;
  773. VALIDATE_DD_CONTEXT;
  774. if ((ppdev->iBitmapFormat != BMF_24BPP) &&
  775. (((rop4 >> 8) & 0xff) == (rop4 & 0xff)) &&
  776. (psoSrc->iType != STYPE_BITMAP) &&
  777. (pdsurfSrc->dt & DT_SCREEN) &&
  778. (rop3 == 0xcc))
  779. {
  780. // We special case screen to monochrome blts because they
  781. // happen fairly often. We only handle SRCCOPY rops and
  782. // monochrome destinations (to handle a true 1bpp DIB
  783. // destination, we would have to do near-colour searches
  784. // on every colour; as it is, the foreground colour gets
  785. // mapped to '1', and everything else gets mapped to '0'):
  786. SETUP_PPDEV_OFFSETS(ppdev, pdsurfSrc);
  787. ASSERTDD (pdsurfSrc->poh->cy >= psoSrc->sizlBitmap.cy ||
  788. pdsurfSrc->poh->cx >= psoSrc->sizlBitmap.cx,
  789. "DrvBitBlt: Got a BAD screen-to-mono size");
  790. DISPDBG((DBGLVL, "DrvBitBlt: Screen-to-mono, size poh(%d,%d)",
  791. pdsurfSrc->poh->cx, pdsurfSrc->poh->cy));
  792. if (DoScreenToMono (ppdev, prclDst, pco, psoSrc,
  793. psoDst, pptlSrc, pxlo))
  794. return (TRUE);
  795. }
  796. }
  797. #endif // defined(_X86_)
  798. // pdsurfDst is valid only if iType != BITMAP so be careful with the ordering
  799. //
  800. if ((psoDst->iType == STYPE_BITMAP) || ((pdsurfDst->dt & DT_SCREEN) == 0))
  801. {
  802. // Destination is either a bitmap or an ex offscreen bitmap
  803. DISPDBG((DBGLVL, "dst is a bitmap or a DIB"));
  804. if (psoSrc)
  805. {
  806. DISPDBG((DBGLVL, "we have a src"));
  807. pdsurfSrc = (DSURF *)psoSrc->dhsurf;
  808. if ((psoSrc->iType != STYPE_BITMAP) &&
  809. (pdsurfSrc->dt & DT_SCREEN))
  810. {
  811. ppdev = (PPDEV)psoSrc->dhpdev;
  812. GLINT_DECL_INIT;
  813. SETUP_PPDEV_OFFSETS(ppdev, pdsurfSrc);
  814. // if we are ex offscreen, get the DIB pointer.
  815. if (psoDst->iType != STYPE_BITMAP)
  816. {
  817. psoDst = pdsurfDst->pso;
  818. }
  819. VALIDATE_DD_CONTEXT;
  820. DISPDBG((DBGLVL, "uploading from the screen"));
  821. if (bUploadBlt(ppdev, psoDst, psoSrc, psoMsk, pco, pxlo, prclDst,
  822. pptlSrc, pptlMsk, pbo, pptlBrush, rop4))
  823. {
  824. return (TRUE);
  825. }
  826. // If for some reason the upload failed go and do it.
  827. DISPDBG((WRNLVL, "DrvBitBlt: bUploadBlt "
  828. "failed.calling engine_blt"));
  829. goto engine_blt;
  830. }
  831. }
  832. DISPDBG((DBGLVL, "falling through to engine_blt"));
  833. if (psoDst->iType != STYPE_BITMAP)
  834. {
  835. // Destination is an Ex Offscreen Bitmap
  836. ppdev = (PPDEV)psoDst->dhpdev;
  837. GLINT_DECL_INIT;
  838. DISPDBG((DBGLVL, "DrvBitBlt: ex offscreen "
  839. "bitmap.calling engine_blt"));
  840. goto engine_blt;
  841. }
  842. else
  843. {
  844. // Destination is a Memory Bitmap. We shouldnt ever get here.
  845. DISPDBG((DBGLVL, "DrvBitBlt: memory bitmap!!."
  846. "calling simple_engine_blt"));
  847. goto simple_engine_blt;
  848. }
  849. }
  850. ppdev = (PPDEV)psoDst->dhpdev;
  851. GLINT_DECL_INIT;
  852. VALIDATE_DD_CONTEXT;
  853. SETUP_PPDEV_OFFSETS(ppdev, pdsurfDst);
  854. // pick out the rop table entries for the foreground and background mixes.
  855. // if we get the same entry for both then we have a rop3.
  856. //
  857. pTableFore = &ropTable[rop4 & 0xff];
  858. pTableBack = &ropTable[rop4 >> 8];
  859. funcIndexFore = pTableFore->func_index;
  860. // handle rop3 pattern fills where no source is needed
  861. //
  862. if ((psoSrc == NULL) && (pTableFore == pTableBack))
  863. {
  864. // really a rop3. no mask required
  865. // solid or pattern fills
  866. if (funcIndexFore <= PAT_FILL_1_BLT)
  867. {
  868. BRUSHOBJ tmpBrush;
  869. BRUSHOBJ *pboTmp;
  870. ULONG logicop;
  871. pboTmp = pbo;
  872. logicop = pTableFore->logicop[0];
  873. // handle the 4 logicops that don't use src or pattern by turning
  874. // them into optimized solid fills.
  875. //
  876. if (funcIndexFore == SOLID_FILL_1_BLT)
  877. {
  878. if ((logicop == __GLINT_LOGICOP_SET) ||
  879. (logicop == __GLINT_LOGICOP_CLEAR))
  880. {
  881. // as solid fills we can make use of hardware block fills
  882. tmpBrush.iSolidColor = 0xffffff; // does any depth
  883. if (logicop == __GLINT_LOGICOP_CLEAR)
  884. {
  885. tmpBrush.iSolidColor = 0;
  886. }
  887. logicop = __GLINT_LOGICOP_COPY;
  888. pboTmp = &tmpBrush;
  889. }
  890. else if (logicop == __GLINT_LOGICOP_INVERT)
  891. {
  892. pboTmp = NULL; // forces a solid fill
  893. }
  894. else
  895. {
  896. return(TRUE); // DST logicop is a noop
  897. }
  898. }
  899. // as fills are performance critical it may be wise to make this
  900. // code inline as in the sample driver. But for the moment, I'll
  901. // leave it as a function call.
  902. //
  903. if (PatternFillRect(ppdev, prclDst, pco, pboTmp, pptlBrush,
  904. logicop, logicop))
  905. {
  906. return(TRUE);
  907. }
  908. DISPDBG((DBGLVL, "DrvBitBlt: PatternFillRect "
  909. "failed.calling engine_blt"));
  910. goto engine_blt;
  911. }
  912. }
  913. // this code is important in that it resets psoSrc to be a real DIB surface
  914. // if src is a DFB converted to a DIB. SourceFillRect() depends on this
  915. // having been done.
  916. //
  917. if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVBITMAP))
  918. {
  919. pdsurfSrc = (DSURF *)psoSrc->dhsurf;
  920. if (pdsurfSrc->dt & DT_DIB)
  921. {
  922. // Here we consider putting a DIB DFB back into off-screen
  923. // memory. If there's a translate, it's probably not worth
  924. // moving since we won't be able to use the hardware to do
  925. // the blt (a similar argument could be made for weird rops
  926. // and stuff that we'll only end up having GDI simulate, but
  927. // those should happen infrequently enough that I don't care).
  928. if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))
  929. {
  930. // See 'DrvCopyBits' for some more comments on how this
  931. // moving-it-back-into-off-screen-memory thing works:
  932. if (pdsurfSrc->iUniq == ppdev->iHeapUniq)
  933. {
  934. if (--pdsurfSrc->cBlt == 0)
  935. {
  936. if (bMoveDibToOffscreenDfbIfRoom(ppdev, pdsurfSrc))
  937. {
  938. goto Continue_It;
  939. }
  940. }
  941. }
  942. else
  943. {
  944. // Some space was freed up in off-screen memory,
  945. // so reset the counter for this DFB:
  946. pdsurfSrc->iUniq = ppdev->iHeapUniq;
  947. pdsurfSrc->cBlt = HEAP_COUNT_DOWN;
  948. }
  949. }
  950. // pick out the DIB surface that we defined for the DFB when it
  951. // was created (as our VRAM is linear we always have this).
  952. //
  953. psoSrc = pdsurfSrc->pso;
  954. }
  955. }
  956. Continue_It:
  957. // we are now interested in rop3s involving a source
  958. //
  959. if (pTableFore == pTableBack)
  960. {
  961. if (funcIndexFore == SRC_FILL_1_BLT)
  962. {
  963. if (SourceFillRect(ppdev, prclDst, pco, psoSrc, pxlo,
  964. pptlSrc, pTableFore->logicop[0], pTableFore->logicop[0]))
  965. {
  966. return(TRUE);
  967. }
  968. DISPDBG((DBGLVL, "DrvBitBlt: SourceFillRect"
  969. " failed.calling engine_blt"));
  970. goto engine_blt;
  971. }
  972. // handle miscellaneous other rop3s. Most of these are done in
  973. // multiple passes of the hardware.
  974. //
  975. switch (funcIndexFore)
  976. {
  977. case PAT_SRC_2_BLT:
  978. case PAT_SRC_PAT_3_BLT:
  979. DISPDBG((DBGLVL, "PAT_SRC_PAT_BLT, rop 0x%x",
  980. pTableFore - ropTable));
  981. if (PatSrcPatBlt(ppdev, psoSrc, pco, pxlo, prclDst,pptlSrc,
  982. pbo, pptlBrush, pTableFore))
  983. {
  984. return(TRUE);
  985. }
  986. break;
  987. case SRC_PAT_2_BLT:
  988. case SRC_PAT_SRC_3_BLT:
  989. DISPDBG((DBGLVL, "SRC_PAT_SRC_BLT, rop 0x%x",
  990. pTableFore - ropTable));
  991. if (SrcPatSrcBlt(ppdev, psoSrc, pco, pxlo, prclDst,pptlSrc,
  992. pbo, pptlBrush, pTableFore))
  993. {
  994. return(TRUE);
  995. }
  996. break;
  997. case ENG_DOWNLOAD_2_BLT:
  998. DISPDBG((DBGLVL, "ENG_DOWNLOAD_2_BLT, rop 0x%x",
  999. pTableFore - ropTable));
  1000. break;
  1001. case ENGINE_BITBLT:
  1002. DISPDBG((DBGLVL, "ENGINE_BITBLT, rop 0x%x",
  1003. pTableFore - ropTable));
  1004. break;
  1005. default:
  1006. break;
  1007. }
  1008. DISPDBG((WRNLVL, "DrvBitBlt: Unhandled rop3.calling engine_blt"));
  1009. goto engine_blt;
  1010. }
  1011. // ROP4
  1012. // we get here if the mix is a true rop4.
  1013. // unlike the above we only handle a few well chosen rop4s.
  1014. // do later.
  1015. DISPDBG((DBGLVL, "got a true rop4 0x%x", rop4));
  1016. funcIndexBack = pTableBack->func_index;
  1017. if (psoMsk != NULL)
  1018. {
  1019. // At this point, we've made sure that we have a true ROP4.
  1020. // This is important because we're about to dereference the
  1021. // mask. I'll assert to make sure that I haven't inadvertently
  1022. // broken the logic for this:
  1023. ASSERTDD((rop4 & 0xff) != (rop4 >> 8), "This handles true ROP4's only");
  1024. ///////////////////////////////////////////////////////////////////
  1025. // True ROP4's
  1026. ///////////////////////////////////////////////////////////////////
  1027. // Handle ROP4 where no source is required for either Rop3:
  1028. // In this case we handle it by using the mask as a 1bpp
  1029. // source image and we download it. The foreground and
  1030. // background colors are taken from a solid brush.
  1031. if ((funcIndexFore | funcIndexBack) <= PAT_FILL_1_BLT)
  1032. {
  1033. if ((funcIndexFore | funcIndexBack) == PAT_FILL_1_BLT)
  1034. {
  1035. // Fake up a 1bpp XLATEOBJ (note that we should only
  1036. // dereference 'pbo' when it's required by the mix):
  1037. xlc.iForeColor = pbo->iSolidColor;
  1038. xlc.iBackColor = xlc.iForeColor;
  1039. if (xlc.iForeColor == -1)
  1040. {
  1041. DISPDBG((WRNLVL, "1bpp fake xlate rejected"
  1042. " as brush not solid"));
  1043. goto engine_blt; // We don't handle non-solid brushes
  1044. }
  1045. }
  1046. // Note that when neither the foreground nor the background mix
  1047. // requires a source, the colours in 'xlc' are allowed to be
  1048. // garbage.
  1049. xlo.pulXlate = (ULONG*) &xlc;
  1050. pxlo = &xlo;
  1051. psoSrc = psoMsk;
  1052. pptlSrc = pptlMsk;
  1053. DISPDBG((DBGLVL, "calling SourceFillRect for rop4 (fg %d, bg %d)",
  1054. pTableFore->logicop[0], pTableBack->logicop[0]));
  1055. if (SourceFillRect(ppdev, prclDst, pco, psoSrc, pxlo,
  1056. pptlSrc, pTableFore->logicop[0], pTableBack->logicop[0]))
  1057. {
  1058. return(TRUE);
  1059. }
  1060. DISPDBG((WRNLVL, "DrvBitBlt: SourceFillRect (2) "
  1061. "failed.calling engine_blt"));
  1062. goto engine_blt;
  1063. } // No pattern required
  1064. else if ((funcIndexFore | funcIndexBack) == SRC_FILL_1_BLT)
  1065. {
  1066. // We're about to dereference 'psoSrc' and 'pptlSrc' --
  1067. // since we already handled the case where neither ROP3
  1068. // required the source, the ROP4 must require a source,
  1069. // so we're safe.
  1070. ASSERTDD((psoSrc != NULL) && (pptlSrc != NULL),
  1071. "No source case should already have been handled!");
  1072. // The operation has to be screen-to-screen, and the rectangles
  1073. // cannot overlap:
  1074. if ((psoSrc->iType != STYPE_BITMAP) &&
  1075. (psoDst->iType != STYPE_BITMAP) &&
  1076. ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)) &&
  1077. !OVERLAP(prclDst, pptlSrc))
  1078. {
  1079. DISPDBG((DBGLVL, "calling MskCopyBlt for rop 4 (fg %d, bg %d)",
  1080. pTableFore->logicop[0], pTableBack->logicop[0]));
  1081. //@@BEGIN_DDKSPLIT
  1082. // TMM: 060897: Removed this for WHQL tests
  1083. //if (MaskCopyBlt(ppdev, prclDst, pco, psoSrc, psoMsk,
  1084. // pptlSrc, pptlMsk,
  1085. // pTableFore->logicop[0],
  1086. // pTableBack->logicop[0]))
  1087. // return(TRUE);
  1088. //@@END_DDKSPLIT
  1089. DISPDBG((WRNLVL, "DrvBitBlt: MaskCopyBlt "
  1090. "failed.calling engine_blt"));
  1091. goto engine_blt;
  1092. }
  1093. }
  1094. DISPDBG((DBGLVL, "rejected rop4 0x%x with mask", rop4));
  1095. }
  1096. else if ((pTableBack->logicop[0] == __GLINT_LOGICOP_NOOP) &&
  1097. (funcIndexFore <= PAT_FILL_1_BLT))
  1098. {
  1099. // The only time GDI will ask us to do a true rop4 using the brush
  1100. // mask is when the brush is 1bpp, and the background rop is AA
  1101. // (meaning it's a NOP).
  1102. DISPDBG((DBGLVL, "calling PatternFillRect for rop4 (fg %d, bg %d)",
  1103. pTableFore->logicop[0], pTableBack->logicop[0]));
  1104. if (PatternFillRect(ppdev, prclDst, pco, pbo, pptlBrush,
  1105. pTableFore->logicop[0], pTableBack->logicop[0]))
  1106. {
  1107. return(TRUE);
  1108. }
  1109. // fall through to engine_blt ...
  1110. }
  1111. DISPDBG((DBGLVL, "fell through to engine_blt"));
  1112. engine_blt:
  1113. if (glintInfo->GdiCantAccessFramebuffer)
  1114. {
  1115. // We require the original pointers to decide if we are talking to
  1116. // the screen or not.
  1117. psoSrc = psoSrcOrig;
  1118. psoDst = psoDstOrig;
  1119. hsurfSrcBitmap = (HSURF)NULL;
  1120. hsurfDstBitmap = (HSURF)NULL;
  1121. psoSrcBitmap = (SURFOBJ*)NULL;
  1122. psoDstBitmap = (SURFOBJ*)NULL;
  1123. // if source is the screen then pick out the bitmap surface
  1124. if (psoSrc && (psoSrc->iType != STYPE_BITMAP))
  1125. {
  1126. ppdev = (PPDEV)psoSrc->dhpdev;
  1127. pdsurfSrc = (DSURF *)psoSrc->dhsurf;
  1128. psoSrc = pdsurfSrc->pso;
  1129. if (pdsurfSrc->dt & DT_SCREEN)
  1130. {
  1131. RECTL rclTmp;
  1132. DISPDBG((DBGLVL, "Replacing src screen with bitmap Uploading"));
  1133. // We need to upload the area from the screen and use bitmaps
  1134. // to perform the operation
  1135. hsurfSrcBitmap = (HSURF) EngCreateBitmap(psoSrc->sizlBitmap, 0,
  1136. psoSrc->iBitmapFormat, 0, NULL);
  1137. if (hsurfSrcBitmap == NULL)
  1138. {
  1139. goto drvBitBltFailed;
  1140. }
  1141. if ((psoSrcBitmap = EngLockSurface(hsurfSrcBitmap)) == NULL)
  1142. {
  1143. goto drvBitBltFailed;
  1144. }
  1145. rclTmp.left = pptlSrc->x;
  1146. rclTmp.right = pptlSrc->x + prclDst->right - prclDst->left;
  1147. rclTmp.top = pptlSrc->y;
  1148. rclTmp.bottom = pptlSrc->y + prclDst->bottom - prclDst->top;
  1149. GLINT_DECL_INIT;
  1150. SETUP_PPDEV_OFFSETS(ppdev, pdsurfSrc);
  1151. VALIDATE_DD_CONTEXT;
  1152. // Call our function to perform image upload to tmp surface
  1153. if (!bUploadRect(ppdev, NULL, psoSrc, psoSrcBitmap,
  1154. pptlSrc, &rclTmp))
  1155. {
  1156. goto drvBitBltFailed;
  1157. }
  1158. psoSrc = psoSrcBitmap;
  1159. }
  1160. }
  1161. // if target is on screen then pick out the screen DIB surface
  1162. if (psoDst->iType != STYPE_BITMAP)
  1163. {
  1164. ppdev = (PPDEV)psoDst->dhpdev;
  1165. pdsurfDst = (DSURF *)psoDst->dhsurf;
  1166. psoDst = pdsurfDst->pso;
  1167. if (pdsurfDst->dt & DT_SCREEN)
  1168. {
  1169. POINTL ptlTmp;
  1170. DISPDBG((DBGLVL, "Replacing dst screen with bitmap Uploading"));
  1171. // We need to upload the area from the screen and use bitmaps
  1172. // to perform the operation
  1173. hsurfDstBitmap = (HSURF) EngCreateBitmap(psoDst->sizlBitmap, 0,
  1174. psoDst->iBitmapFormat, 0, NULL);
  1175. if (hsurfDstBitmap == NULL)
  1176. {
  1177. goto drvBitBltFailed;
  1178. }
  1179. if ((psoDstBitmap = EngLockSurface(hsurfDstBitmap)) == NULL)
  1180. {
  1181. goto drvBitBltFailed;
  1182. }
  1183. ptlTmp.x = prclDst->left;
  1184. ptlTmp.y = prclDst->top;
  1185. GLINT_DECL_INIT;
  1186. SETUP_PPDEV_OFFSETS(ppdev, pdsurfDst);
  1187. VALIDATE_DD_CONTEXT;
  1188. // Call our function to perform image upload to tmp surface
  1189. if (!bUploadRect(ppdev, pco, psoDst, psoDstBitmap,
  1190. &ptlTmp, prclDst))
  1191. {
  1192. goto drvBitBltFailed;
  1193. }
  1194. psoDst = psoDstBitmap;
  1195. }
  1196. }
  1197. #if DBG
  1198. if (psoDstBitmap)
  1199. {
  1200. DISPDBG((DBGLVL, "DrvBitBlt dest DIB, psoDst = 0x%08x:", psoDst));
  1201. DISPDBG((DBGLVL, "\tsize: %d x %d",
  1202. psoDst->sizlBitmap.cx,
  1203. psoDst->sizlBitmap.cy));
  1204. DISPDBG((DBGLVL, "\tcjBits = %d", psoDst->cjBits));
  1205. DISPDBG((DBGLVL, "\tpvBits = 0x%08x", psoDst->pvBits));
  1206. DISPDBG((DBGLVL, "\tpvScan0 = 0x%08x", psoDst->pvScan0));
  1207. DISPDBG((DBGLVL, "\tlDelta = %d", psoDst->lDelta));
  1208. DISPDBG((DBGLVL, "\tiBitmapFormat = %d", psoDst->iBitmapFormat));
  1209. DISPDBG((DBGLVL, "\tfjBitmap = %d", psoDst->fjBitmap));
  1210. }
  1211. if (psoSrcBitmap)
  1212. {
  1213. DISPDBG((DBGLVL, "DrvBitBlt source DIB, psoSrc = 0x%08x:", psoSrc));
  1214. DISPDBG((DBGLVL, "psoSrc != NULL"));
  1215. DISPDBG((DBGLVL, "\tsize: %d x %d",
  1216. psoSrc->sizlBitmap.cx, psoSrc->sizlBitmap.cy));
  1217. DISPDBG((DBGLVL, "\tcjBits = %d", psoSrc->cjBits));
  1218. DISPDBG((DBGLVL, "\tpvBits = 0x%08x", psoSrc->pvBits));
  1219. DISPDBG((DBGLVL, "\tpvScan0 = 0x%08x", psoSrc->pvScan0));
  1220. DISPDBG((DBGLVL, "\tlDelta = %d", psoSrc->lDelta));
  1221. DISPDBG((DBGLVL, "\tiBitmapFormat = %d", psoSrc->iBitmapFormat));
  1222. DISPDBG((DBGLVL, "\tfjBitmap = %d", psoSrc->fjBitmap));
  1223. }
  1224. #endif
  1225. DISPDBG((DBGLVL, "About to pass to GDI"));
  1226. if (pco && (pco->iDComplexity == DC_COMPLEX))
  1227. {
  1228. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  1229. }
  1230. // get GDI to do the blt
  1231. bRet = EngBitBlt(psoDst,
  1232. psoSrc,
  1233. psoMsk,
  1234. pco,
  1235. pxlo,
  1236. prclDst,
  1237. pptlSrc,
  1238. pptlMsk,
  1239. pbo,
  1240. pptlBrush,
  1241. rop4);
  1242. // if we need the nibbles replicated within each color component we must
  1243. // do it now since GDI will have destroyed one half of each byte.
  1244. if (psoDstBitmap)
  1245. {
  1246. POINTL ptlTmp;
  1247. // We need to upload the destination to the screen now.
  1248. ptlTmp.x = prclDst->left;
  1249. ptlTmp.y = prclDst->top;
  1250. DISPDBG((DBGLVL, "downloading Now"));
  1251. // We assume the dest upload was performed last,
  1252. // so the offsets will still be correct.
  1253. if (!SourceFillRect(ppdev, prclDst, pco, psoDstBitmap, NULL, &ptlTmp,
  1254. __GLINT_LOGICOP_COPY, __GLINT_LOGICOP_COPY))
  1255. {
  1256. goto drvBitBltFailed;
  1257. }
  1258. DISPDBG((DBGLVL, "downloading Done 0x%x 0x%x",
  1259. psoDstBitmap, hsurfDstBitmap));
  1260. // Now we can discard the destination bitmap too.
  1261. EngUnlockSurface(psoDstBitmap);
  1262. EngDeleteSurface(hsurfDstBitmap);
  1263. DISPDBG((DBGLVL, "Surface deleted"));
  1264. }
  1265. if (psoSrcBitmap)
  1266. {
  1267. // We can just discard the src bitmap if it was created.
  1268. EngUnlockSurface(psoSrcBitmap);
  1269. EngDeleteSurface(hsurfSrcBitmap);
  1270. }
  1271. DISPDBG((DBGLVL, "returning %d", bRet));
  1272. return(bRet);
  1273. drvBitBltFailed:
  1274. DISPDBG((WRNLVL, "drvBitBltFailed"));
  1275. if (psoSrcBitmap)
  1276. {
  1277. EngUnlockSurface(psoSrcBitmap);
  1278. }
  1279. if (hsurfSrcBitmap)
  1280. {
  1281. EngDeleteSurface(hsurfSrcBitmap);
  1282. }
  1283. if (psoDstBitmap)
  1284. {
  1285. EngUnlockSurface(psoDstBitmap);
  1286. }
  1287. if (hsurfDstBitmap)
  1288. {
  1289. EngDeleteSurface(hsurfDstBitmap);
  1290. }
  1291. return(FALSE);
  1292. }
  1293. simple_engine_blt:
  1294. // if target is on screen then pick out the screen DIB surface
  1295. if (psoDst->iType != STYPE_BITMAP)
  1296. {
  1297. ppdev = (PPDEV)psoDst->dhpdev;
  1298. pdsurfDst = (DSURF *)psoDst->dhsurf;
  1299. psoDst = pdsurfDst->pso;
  1300. }
  1301. // if source is the screen then pick out the bitmap surface
  1302. if (psoSrc && (psoSrc->iType != STYPE_BITMAP))
  1303. {
  1304. ppdev = (PPDEV)psoSrc->dhpdev;
  1305. pdsurfSrc = (DSURF *)psoSrc->dhsurf;
  1306. psoSrc = pdsurfSrc->pso;
  1307. }
  1308. // get GDI to do the blt
  1309. bRet = EngBitBlt(psoDst,
  1310. psoSrc,
  1311. psoMsk,
  1312. pco,
  1313. pxlo,
  1314. prclDst,
  1315. pptlSrc,
  1316. pptlMsk,
  1317. pbo,
  1318. pptlBrush,
  1319. rop4);
  1320. return(bRet);
  1321. }
  1322. /******************************Public*Routine******************************\
  1323. * BOOL PatternFillRect
  1324. *
  1325. * Fill a set of rectangles with either a solid color or a pattern. The pattern
  1326. * can be either monochrome or colored. If pbo is null then we are using a
  1327. * logicop which doesn't require a source. In this case we can set color to
  1328. * be anything we want in the low level routine. If pbo is not null then it
  1329. * can indicate either a solid color or a mono or colored pattern.
  1330. *
  1331. * Returns:
  1332. *
  1333. * True if we handled the fill, False if we want GDI to do it.
  1334. *
  1335. \**************************************************************************/
  1336. BOOL PatternFillRect(
  1337. PPDEV ppdev,
  1338. RECTL *prclDst,
  1339. CLIPOBJ *pco,
  1340. BRUSHOBJ *pbo,
  1341. POINTL *pptlBrush,
  1342. DWORD fgLogicop,
  1343. DWORD bgLogicop)
  1344. {
  1345. BYTE jClip;
  1346. BOOL bMore;
  1347. RBRUSH *prb;
  1348. RBRUSH_COLOR rbc;
  1349. CLIPENUM ce;
  1350. RECTL rcl;
  1351. LONG c;
  1352. GFNFILL *fillFn;
  1353. // if pbo is null then the caller will have ensured that the logic op
  1354. // doesn't need a source so we can do a solid fill. In that case rbc
  1355. // is irrelevant.
  1356. //
  1357. if ((pbo == NULL) || ((rbc.iSolidColor = pbo->iSolidColor) != -1))
  1358. {
  1359. DISPDBG((DBGLVL, "got a solid brush with color 0x%x "
  1360. "(fgrop %d, bgrop %d)",
  1361. rbc.iSolidColor, fgLogicop, bgLogicop));
  1362. fillFn = ppdev->pgfnFillSolid;
  1363. }
  1364. else
  1365. {
  1366. DISPDBG((DBGLVL, "Got a real patterned brush. pbo = 0x%x", pbo));
  1367. // got ourselves a real pattern so check it's realized
  1368. if ((prb = pbo->pvRbrush) == NULL)
  1369. {
  1370. DISPDBG((DBGLVL, "calling BRUSHOBJ_pvGetRbrush"));
  1371. prb = BRUSHOBJ_pvGetRbrush(pbo);
  1372. DISPDBG((DBGLVL, "BRUSHOBJ_pvGetRbrush returned 0x%x", prb));
  1373. if (prb == NULL)
  1374. {
  1375. return FALSE; // let the engine do it
  1376. }
  1377. }
  1378. if (prb->fl & RBRUSH_2COLOR)
  1379. {
  1380. DISPDBG((DBGLVL, "monochrome brush"));
  1381. fillFn = ppdev->pgfnFillPatMono;
  1382. }
  1383. else
  1384. {
  1385. DISPDBG((DBGLVL, "colored brush"));
  1386. fillFn = ppdev->pgfnFillPatColor;
  1387. }
  1388. rbc.prb = prb;
  1389. }
  1390. jClip = (pco == NULL) ? DC_TRIVIAL : pco->iDComplexity;
  1391. if (jClip == DC_TRIVIAL)
  1392. {
  1393. DISPDBG((DBGLVL, "trivial clip"));
  1394. (*fillFn)(ppdev, 1, prclDst, fgLogicop, bgLogicop, rbc, pptlBrush);
  1395. }
  1396. else if (jClip == DC_RECT)
  1397. {
  1398. DISPDBG((DBGLVL, "rect clip"));
  1399. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  1400. {
  1401. (*fillFn)(ppdev, 1, &rcl, fgLogicop, bgLogicop, rbc, pptlBrush);
  1402. }
  1403. }
  1404. else
  1405. {
  1406. DISPDBG((DBGLVL, "complex clip"));
  1407. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  1408. do {
  1409. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG *)&ce);
  1410. c = cIntersect(prclDst, ce.arcl, ce.c);
  1411. if (c != 0)
  1412. {
  1413. (*fillFn)(ppdev, c, ce.arcl, fgLogicop,
  1414. bgLogicop, rbc, pptlBrush);
  1415. }
  1416. } while (bMore);
  1417. }
  1418. return(TRUE);
  1419. }
  1420. /******************************Public*Routine******************************\
  1421. * BOOL SourceFillRect
  1422. *
  1423. * Fill a set of rectangles by downloading data from the source bitmap. This
  1424. * handles both memory-to-screen and screen-to-screen.
  1425. *
  1426. * Returns:
  1427. *
  1428. * True if we handled the fill, False if we want GDI to do it.
  1429. *
  1430. \**************************************************************************/
  1431. BOOL SourceFillRect(
  1432. PPDEV ppdev,
  1433. RECTL *prclDst,
  1434. CLIPOBJ *pco,
  1435. SURFOBJ *psoSrc,
  1436. XLATEOBJ *pxlo,
  1437. POINTL *pptlSrc,
  1438. ULONG fgLogicop,
  1439. ULONG bgLogicop)
  1440. {
  1441. BYTE jClip;
  1442. BOOL bMore;
  1443. CLIPENUM ce;
  1444. RECTL rcl;
  1445. LONG c;
  1446. GFNXFER *fillFn;
  1447. ULONG iSrcBitmapFormat;
  1448. DSURF *pdsurfSrc;
  1449. POINTL ptlSrc;
  1450. ULONG iDir;
  1451. GlintDataPtr glintInfo = (GlintDataPtr)(ppdev->glintInfo);
  1452. DISPDBG((DBGLVL, "SourceFillRect called"));
  1453. // we don't get into this routine unless dst is the screen
  1454. // if psoSrc was originally a DFB converted to a DIB, it must have been
  1455. // re-assigned to the DIV surface before calling this function.
  1456. jClip = (pco == NULL) ? DC_TRIVIAL : pco->iDComplexity;
  1457. if (psoSrc->iType != STYPE_BITMAP)
  1458. {
  1459. // screen to screen
  1460. pdsurfSrc = (DSURF*) psoSrc->dhsurf;
  1461. ASSERTDD(pdsurfSrc->dt & DT_SCREEN, "Expected screen source");
  1462. SETUP_PPDEV_SRC_OFFSETS(ppdev, pdsurfSrc);
  1463. ptlSrc.x = pptlSrc->x - (ppdev->xOffset - pdsurfSrc->poh->x);
  1464. ptlSrc.y = pptlSrc->y;
  1465. pptlSrc = &ptlSrc;
  1466. if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))
  1467. {
  1468. //////////////////////////////////////////////////
  1469. // Screen-to-screen blt with no translate
  1470. if (jClip == DC_TRIVIAL)
  1471. {
  1472. DISPDBG((DBGLVL, "trivial clip calling ppdev->pgfnCopyBlt"));
  1473. (*ppdev->pgfnCopyBlt)(ppdev, prclDst, 1, fgLogicop, pptlSrc,
  1474. prclDst);
  1475. }
  1476. else if (jClip == DC_RECT)
  1477. {
  1478. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  1479. {
  1480. DISPDBG((DBGLVL, "rect clip calling ppdev->pgfnCopyBlt"));
  1481. (*ppdev->pgfnCopyBlt)(ppdev, &rcl, 1, fgLogicop, pptlSrc,
  1482. prclDst);
  1483. }
  1484. }
  1485. else
  1486. {
  1487. // Don't forget that we'll have to draw the
  1488. // rectangles in the correct direction:
  1489. if (pptlSrc->y >= prclDst->top)
  1490. {
  1491. if (pptlSrc->x >= prclDst->left)
  1492. iDir = CD_RIGHTDOWN;
  1493. else
  1494. iDir = CD_LEFTDOWN;
  1495. }
  1496. else
  1497. {
  1498. if (pptlSrc->x >= prclDst->left)
  1499. iDir = CD_RIGHTUP;
  1500. else
  1501. iDir = CD_LEFTUP;
  1502. }
  1503. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
  1504. iDir, 0);
  1505. do {
  1506. bMore = CLIPOBJ_bEnum(pco, sizeof(ce),
  1507. (ULONG*) &ce);
  1508. c = cIntersect(prclDst, ce.arcl, ce.c);
  1509. if (c != 0)
  1510. {
  1511. DISPDBG((DBGLVL, "complex clip calling "
  1512. "ppdev->pgfnCopyBlt"));
  1513. (*ppdev->pgfnCopyBlt)(ppdev,
  1514. ce.arcl,
  1515. c,
  1516. fgLogicop,
  1517. pptlSrc,
  1518. prclDst);
  1519. }
  1520. } while (bMore);
  1521. }
  1522. return TRUE;
  1523. }
  1524. }
  1525. else // (psoSrc->iType == STYPE_BITMAP)
  1526. {
  1527. // Image download
  1528. // here we can use a set of function pointers to handle the
  1529. // different cases. At the end loop through the cliprects
  1530. // calling the given function.
  1531. iSrcBitmapFormat = psoSrc->iBitmapFormat;
  1532. if (iSrcBitmapFormat == BMF_1BPP)
  1533. {
  1534. // do 1bpp download
  1535. fillFn = ppdev->pgfnXfer1bpp;
  1536. }
  1537. else if ((iSrcBitmapFormat == ppdev->iBitmapFormat) &&
  1538. ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
  1539. {
  1540. // native depth image download
  1541. fillFn = ppdev->pgfnXferImage;
  1542. }
  1543. else if (iSrcBitmapFormat == BMF_4BPP)
  1544. {
  1545. // 4 to 8,16,32 image download
  1546. DISPDBG((DBGLVL, "4bpp source download."));
  1547. fillFn = ppdev->pgfnXfer4bpp;
  1548. }
  1549. else if (iSrcBitmapFormat == BMF_8BPP)
  1550. {
  1551. // 8 to 8,16,32 image download
  1552. DISPDBG((DBGLVL, "8bpp source download."));
  1553. fillFn = ppdev->pgfnXfer8bpp;
  1554. }
  1555. else
  1556. {
  1557. DISPDBG((DBGLVL, "source has format %d, Punting to GDI",
  1558. iSrcBitmapFormat));
  1559. goto ReturnFalse;
  1560. }
  1561. if (jClip == DC_TRIVIAL)
  1562. {
  1563. DISPDBG((DBGLVL, "trivial clip image download"));
  1564. (*fillFn)(ppdev, prclDst, 1, fgLogicop, bgLogicop, psoSrc,
  1565. pptlSrc, prclDst, pxlo);
  1566. }
  1567. else if (jClip == DC_RECT)
  1568. {
  1569. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  1570. {
  1571. DISPDBG((DBGLVL, "rect clip image download"));
  1572. (*fillFn)(ppdev, &rcl, 1, fgLogicop, bgLogicop, psoSrc,
  1573. pptlSrc, prclDst, pxlo);
  1574. }
  1575. }
  1576. else
  1577. {
  1578. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  1579. do {
  1580. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG *)&ce);
  1581. c = cIntersect(prclDst, ce.arcl, ce.c);
  1582. if (c != 0)
  1583. {
  1584. DISPDBG((DBGLVL, "complex clip image download"));
  1585. (*fillFn)(ppdev, ce.arcl, c, fgLogicop, bgLogicop, psoSrc,
  1586. pptlSrc, prclDst, pxlo);
  1587. }
  1588. } while (bMore);
  1589. }
  1590. return TRUE;
  1591. }
  1592. ReturnFalse:
  1593. #if DBG
  1594. DISPDBG((WRNLVL, "SourceFillRect returning false"));
  1595. if ((pxlo != NULL) && !(pxlo->flXlate & XO_TRIVIAL))
  1596. DISPDBG((WRNLVL, "due to non-trivial xlate"));
  1597. #endif
  1598. return FALSE;
  1599. }
  1600. /******************************Public*Routine******************************\
  1601. * BOOL MaskCopyBlt
  1602. *
  1603. * We do a screen-to-screen blt through a mask. The source surface must not
  1604. * be a bitmap.
  1605. *
  1606. * Returns:
  1607. *
  1608. * True if we handled the copy, False if we want GDI to do it.
  1609. *
  1610. \**************************************************************************/
  1611. BOOL MaskCopyBlt(
  1612. PPDEV ppdev,
  1613. RECTL* prclDst,
  1614. CLIPOBJ* pco,
  1615. SURFOBJ* psoSrc,
  1616. SURFOBJ* psoMsk,
  1617. POINTL* pptlSrc,
  1618. POINTL* pptlMsk,
  1619. ULONG fgLogicop,
  1620. ULONG bgLogicop)
  1621. {
  1622. BYTE jClip;
  1623. BOOL bMore;
  1624. CLIPENUM ce;
  1625. RECTL rcl;
  1626. LONG c;
  1627. DSURF *pdsurfSrc;
  1628. POINTL ptlSrc;
  1629. DISPDBG((DBGLVL, "MaskCopyBlt called"));
  1630. if (psoSrc != NULL)
  1631. {
  1632. pdsurfSrc = (DSURF*) psoSrc->dhsurf;
  1633. ASSERTDD(pdsurfSrc->dt & DT_SCREEN, "Expected screen source");
  1634. ptlSrc.x = pptlSrc->x - (ppdev->xOffset - pdsurfSrc->poh->x);
  1635. ptlSrc.y = pptlSrc->y + pdsurfSrc->poh->y;
  1636. pptlSrc = &ptlSrc;
  1637. }
  1638. jClip = (pco == NULL) ? DC_TRIVIAL : pco->iDComplexity;
  1639. if (jClip == DC_TRIVIAL)
  1640. {
  1641. DISPDBG((DBGLVL, "trivial clip"));
  1642. (*ppdev->pgfnMaskCopyBlt)(ppdev, prclDst, 1, psoMsk, pptlMsk,
  1643. fgLogicop, bgLogicop, pptlSrc, prclDst);
  1644. }
  1645. else if (jClip == DC_RECT)
  1646. {
  1647. DISPDBG((DBGLVL, "rect clip"));
  1648. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  1649. {
  1650. (*ppdev->pgfnMaskCopyBlt)(ppdev, &rcl, 1, psoMsk, pptlMsk,
  1651. fgLogicop, bgLogicop, pptlSrc, prclDst);
  1652. }
  1653. }
  1654. else
  1655. {
  1656. DISPDBG((DBGLVL, "complex clip"));
  1657. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  1658. do {
  1659. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG *)&ce);
  1660. c = cIntersect(prclDst, ce.arcl, ce.c);
  1661. if (c != 0)
  1662. {
  1663. (*ppdev->pgfnMaskCopyBlt)(ppdev, ce.arcl, c, psoMsk, pptlMsk,
  1664. fgLogicop, bgLogicop, pptlSrc, prclDst);
  1665. }
  1666. } while (bMore);
  1667. }
  1668. return(TRUE);
  1669. }
  1670. /******************************Public*Routine******************************\
  1671. * BOOL PatSrcPatBlt
  1672. *
  1673. * Function to perform a rop3 by combining pattern and source fills. Does a
  1674. * pattern fill followed by a source fill. Optionally, it does a further
  1675. * pattern fill. Each fill has a separate logicop given in pLogicop.
  1676. *
  1677. * Returns:
  1678. *
  1679. * True if we handled the blt, False if we want GDI to do it.
  1680. *
  1681. \**************************************************************************/
  1682. BOOL PatSrcPatBlt(
  1683. PPDEV ppdev,
  1684. SURFOBJ *psoSrc,
  1685. CLIPOBJ *pco,
  1686. XLATEOBJ *pxlo,
  1687. RECTL *prclDst,
  1688. POINTL *pptlSrc,
  1689. BRUSHOBJ *pbo,
  1690. POINTL *pptlBrush,
  1691. RopTablePtr pTable)
  1692. {
  1693. ULONG iSrcBitmapFormat;
  1694. BOOL bRet;
  1695. DISPDBG((DBGLVL, "PatSrcPatBlt called"));
  1696. // ensure that all calls will pass before we do any rendering. The pattern
  1697. // fills will only fail if we can't realize the brush and that will be
  1698. // detected on the first call. So we only have to ensure that the source
  1699. // download will work since by the time we call the function we will
  1700. // already have done the first pattern fill and it's too late to back out.
  1701. DISPDBG((DBGLVL, "source is of type %s, depth %s",
  1702. (psoSrc->iType == STYPE_DEVBITMAP) ? "DEVBITMAP" :
  1703. (psoSrc->iType == STYPE_BITMAP) ? "BITMAP" : "SCREEN",
  1704. (psoSrc->iBitmapFormat == BMF_1BPP) ? "1" :
  1705. (psoSrc->iBitmapFormat == ppdev->iBitmapFormat) ? "native" :
  1706. "not supported"
  1707. ));
  1708. // if both source and destination are the screen, we cannot handle this
  1709. // if they overlap since we may destroy the source when we do the first
  1710. // pattern fill.
  1711. //
  1712. if ((psoSrc->iType != STYPE_BITMAP) && (OVERLAP(prclDst, pptlSrc)))
  1713. {
  1714. DISPDBG((DBGLVL, "screen src and dst overlap"));
  1715. return(FALSE);
  1716. }
  1717. if (psoSrc->iType == STYPE_BITMAP)
  1718. {
  1719. iSrcBitmapFormat = psoSrc->iBitmapFormat;
  1720. if ((iSrcBitmapFormat == BMF_1BPP) ||
  1721. ((iSrcBitmapFormat == ppdev->iBitmapFormat) &&
  1722. ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))))
  1723. {
  1724. goto Continue_It;
  1725. }
  1726. DISPDBG((DBGLVL, "failed due to bad source bitmap format"));
  1727. return(FALSE);
  1728. }
  1729. //@@BEGIN_DDKSPLIT
  1730. // else (psoSrc->iType != STYPE_BITMAP)
  1731. //@@END_DDKSPLIT
  1732. if ((pxlo != NULL) && !(pxlo->flXlate & XO_TRIVIAL))
  1733. {
  1734. DISPDBG((DBGLVL, "failed due to xlate with non-DIB source"));
  1735. return(FALSE);
  1736. }
  1737. Continue_It:
  1738. // as part of the B8 rop3 we are sometimes asked to xor with 0. As this is
  1739. // a noop I'll trap it.
  1740. //
  1741. if ((pbo->iSolidColor != 0) || (pTable->logicop[0] != __GLINT_LOGICOP_XOR))
  1742. {
  1743. // do the first pattern fill. It can only fail if a brush realize fails
  1744. //
  1745. DISPDBG((DBGLVL, "calling pattern fill function, rop %d",
  1746. pTable->logicop[0]));
  1747. if (!PatternFillRect(ppdev,
  1748. prclDst,
  1749. pco,
  1750. pbo,
  1751. pptlBrush,
  1752. pTable->logicop[0],
  1753. pTable->logicop[0]))
  1754. {
  1755. return(FALSE);
  1756. }
  1757. }
  1758. else
  1759. {
  1760. DISPDBG((DBGLVL, "ignoring xor with solid color 0"));
  1761. }
  1762. // download the source. We've already ensured that the call won't fail
  1763. DISPDBG((DBGLVL, "downloading source bitmap, rop %d",
  1764. pTable->logicop[1]));
  1765. bRet = SourceFillRect(ppdev,
  1766. prclDst,
  1767. pco,
  1768. psoSrc,
  1769. pxlo,
  1770. pptlSrc,
  1771. pTable->logicop[1],
  1772. pTable->logicop[1]);
  1773. ASSERTDD(bRet == TRUE, "PatSrcPatBlt: SourceFillRect returned FALSE");
  1774. if ((pTable->func_index == PAT_SRC_PAT_3_BLT) &&
  1775. ((pbo->iSolidColor != 0) || (pTable->logicop[2] != __GLINT_LOGICOP_XOR)))
  1776. {
  1777. // fill with the pattern again. This won't fail because the first
  1778. // pattern fill succeeded.
  1779. DISPDBG((DBGLVL, "calling pattern fill function, rop %d",
  1780. pTable->logicop[2]));
  1781. bRet = PatternFillRect(ppdev,
  1782. prclDst,
  1783. pco,
  1784. pbo,
  1785. pptlBrush,
  1786. pTable->logicop[2],
  1787. pTable->logicop[2]);
  1788. ASSERTDD(bRet == TRUE,
  1789. "PatSrcPatBlt: second PatterFillRect returned FALSE");
  1790. }
  1791. #if DBG
  1792. else if (pTable->func_index == PAT_SRC_PAT_3_BLT)
  1793. {
  1794. DISPDBG((DBGLVL, "ignoring xor with solid color 0"));
  1795. }
  1796. #endif
  1797. DISPDBG((DBGLVL, "PatSrcPatBlt returning true"));
  1798. return(TRUE);
  1799. }
  1800. /******************************Public*Routine******************************\
  1801. * BOOL SrcPatSrcBlt
  1802. *
  1803. * Function to perform a rop3 by combining pattern and source fills. Does a
  1804. * source fill followed by a pattern fill. Optionally, it does a further
  1805. * source fill. Each fill has a separate logicop given in pLogicop.
  1806. *
  1807. * Returns:
  1808. *
  1809. * True if we handled the blt, False if we want GDI to do it.
  1810. *
  1811. \**************************************************************************/
  1812. BOOL SrcPatSrcBlt(
  1813. PPDEV ppdev,
  1814. SURFOBJ *psoSrc,
  1815. CLIPOBJ *pco,
  1816. XLATEOBJ *pxlo,
  1817. RECTL *prclDst,
  1818. POINTL *pptlSrc,
  1819. BRUSHOBJ *pbo,
  1820. POINTL *pptlBrush,
  1821. RopTablePtr pTable)
  1822. {
  1823. RBRUSH *prb;
  1824. BOOL bRet;
  1825. DISPDBG((DBGLVL, "SrcPatSrc called"));
  1826. // if both source and destination are the screen, we cannot handle it
  1827. // if they overlap since we may destroy the source with the first two
  1828. // operations before we get to the third one. If we're only a
  1829. // SRC_PAT_2_BLT then we're OK; SourceFillRect will handle
  1830. // the copy direction of the source fill properly.
  1831. //
  1832. if ((psoSrc->iType != STYPE_BITMAP) &&
  1833. (pTable->func_index == SRC_PAT_SRC_3_BLT) &&
  1834. (OVERLAP(prclDst, pptlSrc)))
  1835. {
  1836. return(FALSE);
  1837. }
  1838. // we must ensure that the pattern fill will succeed. It can only fail if
  1839. // we can't realize the brush so do it now.
  1840. //
  1841. if ((pbo != NULL) && (pbo->iSolidColor == -1))
  1842. {
  1843. if ((prb = pbo->pvRbrush) == NULL)
  1844. {
  1845. prb = BRUSHOBJ_pvGetRbrush(pbo);
  1846. if (prb == NULL)
  1847. {
  1848. return FALSE; // let the engine do it
  1849. }
  1850. }
  1851. }
  1852. // do the first source download. If it succeeds we know the second one
  1853. // will also work. If it fails we simply let the engine do it and we
  1854. // haven't upset anything (except we may have realized the brush without
  1855. // needing to).
  1856. //
  1857. DISPDBG((DBGLVL, "downloading source bitmap, rop %d",
  1858. pTable->logicop[0]));
  1859. if (!SourceFillRect(ppdev,
  1860. prclDst,
  1861. pco,
  1862. psoSrc,
  1863. pxlo,
  1864. pptlSrc,
  1865. pTable->logicop[0],
  1866. pTable->logicop[0]))
  1867. {
  1868. return(FALSE);
  1869. }
  1870. // fill with the pattern again. We've already ensured this will work.
  1871. DISPDBG((DBGLVL, "calling pattern fill function, rop %d",
  1872. pTable->logicop[1]));
  1873. bRet = PatternFillRect(ppdev,
  1874. prclDst,
  1875. pco,
  1876. pbo,
  1877. pptlBrush,
  1878. pTable->logicop[1],
  1879. pTable->logicop[1]);
  1880. ASSERTDD(bRet == TRUE, "SrcPatSrcBlt: PatternFillRect returned FALSE");
  1881. if (pTable->func_index == SRC_PAT_SRC_3_BLT)
  1882. {
  1883. // download the source again with the final logic op
  1884. DISPDBG((DBGLVL, "downloading source bitmap, rop %d",
  1885. pTable->logicop[2]));
  1886. bRet = SourceFillRect(ppdev,
  1887. prclDst,
  1888. pco,
  1889. psoSrc,
  1890. pxlo,
  1891. pptlSrc,
  1892. pTable->logicop[2],
  1893. pTable->logicop[2]);
  1894. ASSERTDD(bRet == TRUE,
  1895. "SrcPatSrcBlt: second SourceFillRect returned FALSE");
  1896. }
  1897. DISPDBG((DBGLVL, "SrcPatSrcBlt returning true"));
  1898. return(TRUE);
  1899. }
  1900. /******************************Public*Routine******************************\
  1901. * BOOL bUploadRect
  1902. *
  1903. * upload a rectangular area. clip to a given CLIPOBJ
  1904. *
  1905. * Returns:
  1906. *
  1907. * True if we handled the blt, otherwise False.
  1908. *
  1909. \**************************************************************************/
  1910. BOOL bUploadRect(
  1911. PPDEV ppdev,
  1912. CLIPOBJ *pco,
  1913. SURFOBJ *psoSrc,
  1914. SURFOBJ *psoDst,
  1915. POINTL *pptlSrc,
  1916. RECTL *prclDst)
  1917. {
  1918. BYTE jClip;
  1919. BOOL bMore;
  1920. CLIPENUM ce;
  1921. RECTL rcl;
  1922. LONG c;
  1923. // Perform the clipping and pass to a
  1924. // function to upload a list of rectangles.
  1925. DISPDBG((DBGLVL, "UploadRect called. Src %d %d To "
  1926. "dst (%d %d) --> (%d %d)",
  1927. pptlSrc->x, pptlSrc->y,
  1928. prclDst->left, prclDst->top,
  1929. prclDst->right, prclDst->bottom));
  1930. jClip = (pco == NULL) ? DC_TRIVIAL : pco->iDComplexity;
  1931. if (jClip == DC_TRIVIAL)
  1932. {
  1933. DISPDBG((DBGLVL, "trivial clip"));
  1934. ppdev->pgfnUpload(ppdev, 1, prclDst, psoDst, pptlSrc, prclDst);
  1935. }
  1936. else if (jClip == DC_RECT)
  1937. {
  1938. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  1939. {
  1940. DISPDBG((DBGLVL, "rect clip"));
  1941. ppdev->pgfnUpload(ppdev, 1, &rcl, psoDst, pptlSrc, prclDst);
  1942. }
  1943. }
  1944. else
  1945. {
  1946. DISPDBG((DBGLVL, "complex clip"));
  1947. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  1948. do {
  1949. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG *)&ce);
  1950. c = cIntersect(prclDst, ce.arcl, ce.c);
  1951. if (c != 0)
  1952. {
  1953. ppdev->pgfnUpload(ppdev, c, ce.arcl, psoDst, pptlSrc, prclDst);
  1954. }
  1955. } while (bMore);
  1956. }
  1957. return(TRUE);
  1958. }
  1959. /******************************Public*Routine******************************\
  1960. * BOOL bUploadBlt
  1961. *
  1962. * Returns:
  1963. *
  1964. * True if we handled the blt, otherwise False.
  1965. *
  1966. \**************************************************************************/
  1967. BOOL bUploadBlt(
  1968. PPDEV ppdev,
  1969. SURFOBJ *psoDst,
  1970. SURFOBJ *psoSrc,
  1971. SURFOBJ *psoMsk,
  1972. CLIPOBJ *pco,
  1973. XLATEOBJ *pxlo,
  1974. RECTL *prclDst,
  1975. POINTL *pptlSrc,
  1976. POINTL *pptlMsk,
  1977. BRUSHOBJ *pbo,
  1978. POINTL *pptlBrush,
  1979. ROP4 rop4)
  1980. {
  1981. BOOL bRet;
  1982. DISPDBG((DBGLVL, "bUploadBlt called"));
  1983. if ((rop4 == 0xCCCC) &&
  1984. ((pxlo == NULL) || pxlo->flXlate & XO_TRIVIAL) &&
  1985. (psoDst->iBitmapFormat == ppdev->iBitmapFormat))
  1986. {
  1987. // We have no raster op to worry about, and no translations to perform.
  1988. // All we need to do is upload the data from GLINT and put it in the
  1989. // destination. Practically, most image uploads should be of this type.
  1990. return(bUploadRect(ppdev, pco, psoSrc, psoDst, pptlSrc, prclDst));
  1991. }
  1992. else
  1993. {
  1994. HSURF hsurfTmp;
  1995. SURFOBJ* psoTmp;
  1996. SIZEL sizl;
  1997. POINTL ptlTmp;
  1998. RECTL rclTmp;
  1999. // We cant upload directly to the destination, so we create a
  2000. // temporary bitmap, upload to this bitmap, then call EngBitBlt
  2001. // to do the hard work of the translation or raster op.
  2002. // Source point in tmp:
  2003. ptlTmp.x = 0;
  2004. ptlTmp.y = 0;
  2005. // Dest Area in tmp
  2006. rclTmp.left = 0;
  2007. rclTmp.top = 0;
  2008. rclTmp.right = prclDst->right - prclDst->left;
  2009. rclTmp.bottom = prclDst->bottom - prclDst->top;
  2010. // Work out size of tmp bitmap. We know left and top are zero.
  2011. sizl.cx = rclTmp.right;
  2012. sizl.cy = rclTmp.bottom;
  2013. // Create the bitmap
  2014. hsurfTmp = (HSURF) EngCreateBitmap(sizl, 0, ppdev->iBitmapFormat,
  2015. 0, NULL);
  2016. if (hsurfTmp == NULL)
  2017. {
  2018. return(FALSE);
  2019. }
  2020. if ((psoTmp = EngLockSurface(hsurfTmp)) == NULL)
  2021. {
  2022. EngDeleteSurface(hsurfTmp);
  2023. return(FALSE);
  2024. }
  2025. // Call our function to perform image upload to tmp surface
  2026. bRet = bUploadRect(ppdev, NULL, psoSrc, psoTmp, pptlSrc, &rclTmp);
  2027. // Call GDI to blt from tmp surface to destination,
  2028. // doing all the work for us
  2029. if (bRet)
  2030. {
  2031. bRet = EngBitBlt(psoDst, psoTmp, psoMsk, pco, pxlo, prclDst,
  2032. &ptlTmp, pptlMsk, pbo, pptlBrush, rop4);
  2033. }
  2034. // Remove tmp surface
  2035. EngUnlockSurface(psoTmp);
  2036. EngDeleteSurface(hsurfTmp);
  2037. return(bRet);
  2038. }
  2039. }
  2040. /******************************Public*Routine******************************\
  2041. * BOOL DrvCopyBits
  2042. *
  2043. * Do fast bitmap copies.
  2044. *
  2045. * Note that GDI will (usually) automatically adjust the blt extents to
  2046. * adjust for any rectangular clipping, so we'll rarely see DC_RECT
  2047. * clipping in this routine (and as such, we don't bother special casing
  2048. * it).
  2049. *
  2050. * I'm not sure if the performance benefit from this routine is actually
  2051. * worth the increase in code size, since SRCCOPY BitBlts are hardly the
  2052. * most common drawing operation we'll get. But what the heck.
  2053. *
  2054. * On the S3 it's faster to do straight SRCCOPY bitblt's through the
  2055. * memory aperture than to use the data transfer register; as such, this
  2056. * routine is the logical place to put this special case.
  2057. *
  2058. \**************************************************************************/
  2059. BOOL DrvCopyBits(
  2060. SURFOBJ* psoDst,
  2061. SURFOBJ* psoSrc,
  2062. CLIPOBJ* pco,
  2063. XLATEOBJ* pxlo,
  2064. RECTL* prclDst,
  2065. POINTL* pptlSrc)
  2066. {
  2067. PDEV* ppdev;
  2068. DSURF* pdsurfSrc;
  2069. DSURF* pdsurfDst;
  2070. POINTL ptl;
  2071. RECTL rcl;
  2072. OH* pohSrc;
  2073. OH* pohDst;
  2074. CLIPENUM ce;
  2075. int cClipRects;
  2076. BOOL bMore, bRet, bCopyDone = FALSE;
  2077. GLINT_DECL_VARS;
  2078. DISPDBG((DBGLVL, "DrvCopyBits called"));
  2079. // We need to remove the pointer, but we dont know which surface is valid
  2080. // (if either).
  2081. if ((psoDst->iType != STYPE_BITMAP) &&
  2082. (((DSURF *)(psoDst->dhsurf))->dt & DT_SCREEN))
  2083. {
  2084. ppdev = (PDEV *)psoDst->dhpdev;
  2085. REMOVE_SWPOINTER(psoDst);
  2086. }
  2087. else if ((psoSrc->iType != STYPE_BITMAP) &&
  2088. (((DSURF *)(psoSrc->dhsurf))->dt & DT_SCREEN))
  2089. {
  2090. ppdev = (PDEV *)psoSrc->dhpdev;
  2091. REMOVE_SWPOINTER(psoSrc);
  2092. }
  2093. #if 0
  2094. else
  2095. {
  2096. // we shouldn't ever fall here, but we have this just as safeguard code
  2097. return EngCopyBits(psoDst, psoSrc, pco, pxlo, prclDst, pptlSrc);
  2098. }
  2099. #endif
  2100. #if !defined(_WIN64) && WNT_DDRAW
  2101. // Touch the source surface 1st and then the destination surface
  2102. vSurfUsed(psoSrc);
  2103. vSurfUsed(psoDst);
  2104. #endif
  2105. // Faster route to calling screen-to-screen BLT. The order in the if() is
  2106. // very important to avoid null pointers.
  2107. pdsurfDst = (DSURF*)psoDst->dhsurf;
  2108. pdsurfSrc = (DSURF*)psoSrc->dhsurf;
  2109. if ((psoDst->iType != STYPE_BITMAP) &&
  2110. (pdsurfDst->dt & DT_SCREEN) &&
  2111. psoSrc &&
  2112. (psoSrc->iType != STYPE_BITMAP) &&
  2113. (pdsurfSrc->dt & DT_SCREEN) &&
  2114. ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL)) &&
  2115. ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
  2116. {
  2117. pohSrc = pdsurfSrc->poh;
  2118. pohDst = pdsurfDst->poh;
  2119. ptl.x = pptlSrc->x - (pohDst->x - pohSrc->x);
  2120. ptl.y = pptlSrc->y;
  2121. ppdev = (PDEV*) psoDst->dhpdev;
  2122. GLINT_DECL_INIT;
  2123. VALIDATE_DD_CONTEXT;
  2124. SETUP_PPDEV_SRC_AND_DST_OFFSETS(ppdev, pdsurfSrc, pdsurfDst);
  2125. (*ppdev->pgfnCopyBltCopyROP)(ppdev, prclDst, 1, __GLINT_LOGICOP_COPY,
  2126. &ptl, prclDst);
  2127. return(TRUE);
  2128. }
  2129. if ((psoDst->iType != STYPE_BITMAP) &&
  2130. psoSrc &&
  2131. (psoSrc->iType == STYPE_BITMAP))
  2132. {
  2133. // straight DIB->screen download with translate: see if
  2134. // we special-case it
  2135. ppdev = (PDEV*)psoDst->dhpdev;
  2136. if (((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)) &&
  2137. (psoSrc->iBitmapFormat == psoDst->iBitmapFormat) &&
  2138. ppdev->pgfnCopyXferImage)
  2139. {
  2140. // native depth download
  2141. pdsurfDst = (DSURF*)psoDst->dhsurf;
  2142. // only accelerate when downloading to the framebuffer
  2143. if (pdsurfDst->dt & DT_SCREEN)
  2144. {
  2145. GLINT_DECL_INIT;
  2146. VALIDATE_DD_CONTEXT;
  2147. pohDst = pdsurfDst->poh;
  2148. SETUP_PPDEV_OFFSETS(ppdev, pdsurfDst);
  2149. if(pco == NULL || pco->iDComplexity == DC_TRIVIAL)
  2150. {
  2151. ppdev->pgfnCopyXferImage(ppdev, psoSrc, pptlSrc, prclDst,
  2152. prclDst, 1);
  2153. }
  2154. else if(pco->iDComplexity == DC_RECT)
  2155. {
  2156. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  2157. {
  2158. ppdev->pgfnCopyXferImage(ppdev, psoSrc, pptlSrc,
  2159. prclDst, &rcl, 1);
  2160. }
  2161. }
  2162. else //(pco->iDComplexity == DC_COMPLEX)
  2163. {
  2164. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  2165. do
  2166. {
  2167. bMore = CLIPOBJ_bEnum(pco, sizeof ce, (ULONG *)&ce);
  2168. cClipRects = cIntersect(prclDst, ce.arcl, ce.c);
  2169. if(cClipRects)
  2170. {
  2171. ppdev->pgfnCopyXferImage(ppdev, psoSrc, pptlSrc,
  2172. prclDst, ce.arcl,
  2173. cClipRects);
  2174. }
  2175. }
  2176. while(bMore);
  2177. }
  2178. return(TRUE);
  2179. }
  2180. }
  2181. else if (((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)) &&
  2182. (psoSrc->iBitmapFormat == BMF_24BPP) &&
  2183. ppdev->pgfnCopyXfer24bpp)
  2184. {
  2185. pdsurfDst = (DSURF*)psoDst->dhsurf;
  2186. // only accelerate when downloading to the framebuffer
  2187. if (pdsurfDst->dt & DT_SCREEN)
  2188. {
  2189. GLINT_DECL_INIT;
  2190. VALIDATE_DD_CONTEXT;
  2191. pohDst = pdsurfDst->poh;
  2192. SETUP_PPDEV_OFFSETS(ppdev, pdsurfDst);
  2193. if(pco == NULL || pco->iDComplexity == DC_TRIVIAL)
  2194. {
  2195. ppdev->pgfnCopyXfer24bpp(ppdev, psoSrc, pptlSrc, prclDst,
  2196. prclDst, 1);
  2197. }
  2198. else if(pco->iDComplexity == DC_RECT)
  2199. {
  2200. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  2201. {
  2202. ppdev->pgfnCopyXfer24bpp(ppdev, psoSrc, pptlSrc,
  2203. prclDst, &rcl, 1);
  2204. }
  2205. }
  2206. else // (pco->iDComplexity == DC_COMPLEX)
  2207. {
  2208. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  2209. do {
  2210. bMore = CLIPOBJ_bEnum(pco, sizeof ce, (ULONG *)&ce);
  2211. cClipRects = cIntersect(prclDst, ce.arcl, ce.c);
  2212. if(cClipRects)
  2213. {
  2214. ppdev->pgfnCopyXfer24bpp(ppdev, psoSrc, pptlSrc,
  2215. prclDst, ce.arcl,
  2216. cClipRects);
  2217. }
  2218. } while(bMore);
  2219. }
  2220. return(TRUE);
  2221. }
  2222. }
  2223. else if (pxlo && (pxlo->flXlate & XO_TABLE) &&
  2224. (psoSrc->iBitmapFormat == BMF_8BPP) &&
  2225. (pxlo->cEntries == 256) && ppdev->pgfnCopyXfer8bpp)
  2226. {
  2227. pdsurfDst = (DSURF*)psoDst->dhsurf;
  2228. if (pdsurfDst->dt & DT_SCREEN)
  2229. {
  2230. BOOL bRenderLargeBitmap;
  2231. GLINT_DECL_INIT;
  2232. VALIDATE_DD_CONTEXT;
  2233. pohDst = pdsurfDst->poh;
  2234. SETUP_PPDEV_OFFSETS(ppdev, pdsurfDst);
  2235. bRenderLargeBitmap = (ppdev->pgfnCopyXfer8bppLge != NULL);
  2236. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  2237. {
  2238. if(bRenderLargeBitmap)
  2239. {
  2240. ppdev->pgfnCopyXfer8bppLge(ppdev, psoSrc, pptlSrc,
  2241. prclDst, prclDst, 1, pxlo);
  2242. }
  2243. else
  2244. {
  2245. ppdev->pgfnCopyXfer8bpp(ppdev, psoSrc, pptlSrc, prclDst,
  2246. prclDst, 1, pxlo);
  2247. }
  2248. }
  2249. else if (pco->iDComplexity == DC_RECT)
  2250. {
  2251. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  2252. {
  2253. if(bRenderLargeBitmap)
  2254. {
  2255. ppdev->pgfnCopyXfer8bppLge(ppdev, psoSrc, pptlSrc,
  2256. prclDst, &rcl, 1, pxlo);
  2257. }
  2258. else
  2259. {
  2260. ppdev->pgfnCopyXfer8bpp(ppdev, psoSrc, pptlSrc,
  2261. prclDst, &rcl, 1, pxlo);
  2262. }
  2263. }
  2264. }
  2265. else // (pco->iDComplexity == DC_COMPLEX)
  2266. {
  2267. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  2268. do {
  2269. bMore = CLIPOBJ_bEnum(pco, sizeof ce, (ULONG *)&ce);
  2270. cClipRects = cIntersect(prclDst, ce.arcl, ce.c);
  2271. if(cClipRects)
  2272. {
  2273. if(bRenderLargeBitmap)
  2274. {
  2275. ppdev->pgfnCopyXfer8bppLge(ppdev, psoSrc,
  2276. pptlSrc, prclDst,
  2277. ce.arcl, cClipRects,
  2278. pxlo);
  2279. }
  2280. else
  2281. {
  2282. ppdev->pgfnCopyXfer8bpp(ppdev, psoSrc, pptlSrc,
  2283. prclDst, ce.arcl,
  2284. cClipRects, pxlo);
  2285. }
  2286. }
  2287. } while(bMore);
  2288. }
  2289. return(TRUE);
  2290. }
  2291. }
  2292. else if (pxlo && (pxlo->flXlate & XO_TABLE) &&
  2293. (psoSrc->iBitmapFormat == BMF_4BPP) &&
  2294. (pxlo->cEntries == 16) && ppdev->pgfnCopyXfer4bpp)
  2295. {
  2296. pdsurfDst = (DSURF*)psoDst->dhsurf;
  2297. if (pdsurfDst->dt & DT_SCREEN)
  2298. {
  2299. GLINT_DECL_INIT;
  2300. VALIDATE_DD_CONTEXT;
  2301. pohDst = pdsurfDst->poh;
  2302. SETUP_PPDEV_OFFSETS(ppdev, pdsurfDst);
  2303. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  2304. {
  2305. ppdev->pgfnCopyXfer4bpp(ppdev, psoSrc, pptlSrc, prclDst,
  2306. prclDst, 1, pxlo);
  2307. }
  2308. else if (pco->iDComplexity == DC_RECT)
  2309. {
  2310. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  2311. {
  2312. ppdev->pgfnCopyXfer4bpp(ppdev, psoSrc, pptlSrc,
  2313. prclDst, &rcl, 1, pxlo);
  2314. }
  2315. }
  2316. else // (pco->iDComplexity == DC_COMPLEX)
  2317. {
  2318. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  2319. do {
  2320. bMore = CLIPOBJ_bEnum(pco, sizeof ce, (ULONG *)&ce);
  2321. cClipRects = cIntersect(prclDst, ce.arcl, ce.c);
  2322. if(cClipRects)
  2323. {
  2324. ppdev->pgfnCopyXfer4bpp(ppdev, psoSrc, pptlSrc,
  2325. prclDst, ce.arcl,
  2326. cClipRects, pxlo);
  2327. }
  2328. }
  2329. while(bMore);
  2330. }
  2331. return(TRUE);
  2332. }
  2333. }
  2334. //@@BEGIN_DDKSPLIT
  2335. #if DBG && 0
  2336. else if (psoSrc->iBitmapFormat != BMF_1BPP)
  2337. {
  2338. SIZEL sizl;
  2339. int cEntries = pxlo == 0 ? 0 : pxlo->cEntries;
  2340. int flXlate = pxlo == 0 ? 0 : pxlo->flXlate;
  2341. int iDComplexity = pco == 0 ? 0 : pco->iDComplexity;
  2342. sizl.cx = prclDst->right - prclDst->left;
  2343. sizl.cy = prclDst->bottom - prclDst->top;
  2344. DISPDBG((ERRLVL, "DrvCopyBits() unhandled copy download "
  2345. "bmf(%xh) pxlo(%p, cEntries=%03xh flXlate=%xh) "
  2346. "pco(%p, iDComplexity=%02xh), cxcy(%03xh,%03xh)",
  2347. psoSrc->iBitmapFormat, pxlo, cEntries, flXlate,
  2348. pco, iDComplexity, sizl.cx, sizl.cy));
  2349. }
  2350. #endif
  2351. //@@END_DDKSPLIT
  2352. }
  2353. // DrvCopyBits is a fast-path for SRCCOPY blts. But it can still be
  2354. // pretty complicated: there can be translates, clipping, RLEs,
  2355. // bitmaps that aren't the same format as the screen, plus
  2356. // screen-to-screen, DIB-to-screen or screen-to-DIB operations,
  2357. // not to mention DFBs (device format bitmaps).
  2358. //
  2359. // Rather than making this routine almost as big as DrvBitBlt, I'll
  2360. // handle here only the speed-critical cases, and punt the rest to
  2361. // our DrvBitBlt routine.
  2362. //
  2363. // We'll try to handle anything that doesn't involve clipping:
  2364. if (((pco) && (pco->iDComplexity != DC_TRIVIAL)) ||
  2365. ((pxlo) && (! (pxlo->flXlate & XO_TRIVIAL))))
  2366. {
  2367. /////////////////////////////////////////////////////////////////
  2368. // A DrvCopyBits is after all just a simplified DrvBitBlt:
  2369. DISPDBG((DBGLVL, "DrvCopyBits fell through to DrvBitBlt"));
  2370. return(DrvBitBlt(psoDst, psoSrc, NULL, pco, pxlo, prclDst, pptlSrc,
  2371. NULL, NULL, NULL, 0x0000CCCC));
  2372. }
  2373. //@@BEGIN_DDKSPLIT
  2374. // Screen to screen case has already been handled at the very beginning.
  2375. //@@END_DDKSPLIT
  2376. DISPDBG((DBGLVL, "trivial clip and xlate"));
  2377. if ((psoDst->iType != STYPE_BITMAP) && (pdsurfDst->dt & DT_SCREEN))
  2378. {
  2379. // We know the destination is either a DFB or the screen:
  2380. DISPDBG((DBGLVL, "Destination is not a bitmap"));
  2381. GLINT_DECL_INIT;
  2382. VALIDATE_DD_CONTEXT;
  2383. // See if the source is a plain DIB:
  2384. ASSERTDD(((psoSrc->iType == STYPE_BITMAP) || (pdsurfSrc->dt & DT_DIB)),
  2385. "Screen-to-screen case should have been handled");
  2386. //@@BEGIN_DDKSPLIT
  2387. // Ah ha, the source is a DFB that's really a DIB.
  2388. //@@END_DDKSPLIT
  2389. if (psoSrc->iBitmapFormat == ppdev->iBitmapFormat)
  2390. {
  2391. if (pdsurfSrc) {
  2392. DISPDBG((DBGLVL, "source is DFB that's really a DIB"));
  2393. psoSrc = pdsurfSrc->pso;
  2394. ppdev = pdsurfSrc->ppdev;
  2395. }
  2396. //////////////////////////////////////////////////////
  2397. // DIB-to-screen
  2398. ASSERTDD((psoDst->iType != STYPE_BITMAP) &&
  2399. (pdsurfDst->dt & DT_SCREEN) &&
  2400. (psoSrc->iType == STYPE_BITMAP) &&
  2401. (psoSrc->iBitmapFormat == ppdev->iBitmapFormat),
  2402. "Should be a DIB-to-screen case");
  2403. SETUP_PPDEV_OFFSETS(ppdev, pdsurfDst);
  2404. DISPDBG((DBGLVL, "doing DIB-to-screen transfer"));
  2405. (*ppdev->pgfnXferImage)(ppdev,
  2406. prclDst,
  2407. 1,
  2408. __GLINT_LOGICOP_COPY,
  2409. __GLINT_LOGICOP_COPY,
  2410. psoSrc,
  2411. pptlSrc,
  2412. prclDst,
  2413. NULL);
  2414. bRet = TRUE;
  2415. bCopyDone = TRUE;
  2416. }
  2417. }
  2418. else // The destination is a DIB
  2419. {
  2420. DISPDBG((DBGLVL, "Destination is a bitmap"));
  2421. if (pdsurfDst)
  2422. {
  2423. psoDst = pdsurfDst->pso;
  2424. }
  2425. if (pdsurfSrc)
  2426. {
  2427. ppdev = pdsurfSrc->ppdev;
  2428. }
  2429. if ((ppdev != NULL) &&
  2430. (psoDst->iBitmapFormat == ppdev->iBitmapFormat) &&
  2431. (psoSrc->iType != STYPE_BITMAP) &&
  2432. (pdsurfSrc->dt & DT_SCREEN))
  2433. {
  2434. VOID pxrxMemUpload (PDEV*, LONG, RECTL*, SURFOBJ*, POINTL*, RECTL*);
  2435. GLINT_DECL_INIT;
  2436. SETUP_PPDEV_OFFSETS(ppdev, pdsurfSrc);
  2437. // Perform the upload.
  2438. VALIDATE_DD_CONTEXT;
  2439. DISPDBG((DBGLVL, "doing Screen-to-DIB image upload"));
  2440. //(*ppdev->pgfnUpload)
  2441. pxrxMemUpload
  2442. (ppdev, 1, prclDst, psoDst,
  2443. pptlSrc, prclDst);
  2444. bRet = TRUE;
  2445. bCopyDone = TRUE;
  2446. }
  2447. }
  2448. //@@BEGIN_DDKSPLIT
  2449. // NB: we must never get here if the dest is actually the screen (ie. if
  2450. // pdsurfDst->dt & DT_SCREEN and we've changed psoDst to the bypass
  2451. // bitmap). This is because we don't handle nibble replication here which
  2452. // we must do if GDI ever draws directly to the framebuffer. We don't SYNC
  2453. // here because we may be doing a true DIB-to-DIB. We do a SYNC if
  2454. // necessary before jumping here. Currently this happens only if the src
  2455. // is a DFB.
  2456. //
  2457. //@@END_DDKSPLIT
  2458. if (! bCopyDone)
  2459. {
  2460. if (pdsurfDst)
  2461. {
  2462. psoDst = pdsurfDst->pso;
  2463. }
  2464. if (pdsurfSrc)
  2465. {
  2466. psoSrc = pdsurfSrc->pso;
  2467. }
  2468. ASSERTDD((psoDst->iType == STYPE_BITMAP) &&
  2469. (psoSrc->iType == STYPE_BITMAP),
  2470. "Both surfaces should be DIBs to call EngCopyBits");
  2471. DISPDBG((DBGLVL, "DrvCopyBits fell through to EngCopyBits"));
  2472. bRet = EngCopyBits(psoDst, psoSrc, pco, pxlo, prclDst, pptlSrc);
  2473. }
  2474. /////////////////////////////////////////////////////
  2475. // Put It Back Into Off-screen?
  2476. //
  2477. // We take this opportunity to decide if we want to
  2478. // put the DIB back into off-screen memory. This is
  2479. // a pretty good place to do it because we have to
  2480. // copy the bits to some portion of the screen,
  2481. // anyway. So we would incur only an extra screen-to-
  2482. // screen blt at this time, much of which will be
  2483. // over-lapped with the CPU.
  2484. //
  2485. // The simple approach we have taken is to move a DIB
  2486. // back into off-screen memory only if there's already
  2487. // room -- we won't throw stuff out to make space
  2488. // (because it's tough to know what ones to throw out,
  2489. // and it's easy to get into thrashing scenarios).
  2490. //
  2491. // Because it takes some time to see if there's room
  2492. // in off-screen memory, we only check one in
  2493. // HEAP_COUNT_DOWN times if there's room. To bias
  2494. // in favour of bitmaps that are often blt, the
  2495. // counters are reset every time any space is freed
  2496. // up in off-screen memory. We also don't bother
  2497. // checking if no space has been freed since the
  2498. // last time we checked for this DIB.
  2499. if ((! pdsurfSrc) || (pdsurfSrc->dt & DT_SCREEN))
  2500. {
  2501. return (bRet);
  2502. }
  2503. if (pdsurfSrc->iUniq == ppdev->iHeapUniq)
  2504. {
  2505. if (--pdsurfSrc->cBlt == 0)
  2506. {
  2507. DISPDBG((DBGLVL, "putting src back "
  2508. "into off-screen"));
  2509. // Failure is safe here
  2510. bMoveDibToOffscreenDfbIfRoom(ppdev, pdsurfSrc);
  2511. }
  2512. }
  2513. else
  2514. {
  2515. // Some space was freed up in off-screen memory,
  2516. // so reset the counter for this DFB:
  2517. pdsurfSrc->iUniq = ppdev->iHeapUniq;
  2518. pdsurfSrc->cBlt = HEAP_COUNT_DOWN;
  2519. }
  2520. return (bRet);
  2521. }
  2522. #if defined(_X86_)
  2523. /******************************Public*Table********************************\
  2524. * BYTE gajLeftMask[] and BYTE gajRightMask[]
  2525. *
  2526. * Edge tables for vXferScreenTo1bpp.
  2527. \**************************************************************************/
  2528. BYTE gajLeftMask[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
  2529. BYTE gajRightMask[] = { 0xff, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
  2530. /******************************Public*Routine******************************\
  2531. * VOID DoScreenToMono
  2532. *
  2533. * This function works out the clip list and then calls vXferScreenTo1bpp()
  2534. * to do ye hard work.
  2535. *
  2536. \**************************************************************************/
  2537. BOOL DoScreenToMono(
  2538. PDEV* ppdev,
  2539. RECTL *prclDst,
  2540. CLIPOBJ *pco,
  2541. SURFOBJ* psoSrc, // Source surface
  2542. SURFOBJ* psoDst, // Destination surface
  2543. POINTL* pptlSrc, // Original unclipped source point
  2544. XLATEOBJ* pxlo) // Provides colour-compressions information
  2545. {
  2546. RECTL rcl;
  2547. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  2548. {
  2549. DISPDBG((DBGLVL, "DoScreenToMono: Trivial clipping"));
  2550. vXferScreenTo1bpp(ppdev, 1, prclDst, 0, psoSrc,
  2551. psoDst, pptlSrc, prclDst, pxlo);
  2552. }
  2553. else if (pco->iDComplexity == DC_RECT)
  2554. {
  2555. DISPDBG((DBGLVL, "DoScreenToMono: rect clipping"));
  2556. if (bIntersect(prclDst, &pco->rclBounds, &rcl))
  2557. {
  2558. vXferScreenTo1bpp(ppdev, 1, &rcl, 0, psoSrc,
  2559. psoDst, pptlSrc, prclDst, pxlo);
  2560. }
  2561. }
  2562. else // (pco->iDComplexity == DC_COMPLEX)
  2563. {
  2564. CLIPENUM ce;
  2565. int cClipRects;
  2566. BOOL bMore;
  2567. DISPDBG((DBGLVL, "DoScreenToMono: complex clipping"));
  2568. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  2569. do {
  2570. bMore = CLIPOBJ_bEnum(pco, sizeof ce, (ULONG *)&ce);
  2571. cClipRects = cIntersect(prclDst, ce.arcl, ce.c);
  2572. if(cClipRects)
  2573. {
  2574. vXferScreenTo1bpp (ppdev, cClipRects, ce.arcl, 0, psoSrc,
  2575. psoDst, pptlSrc, prclDst, pxlo);
  2576. }
  2577. } while(bMore);
  2578. }
  2579. return(TRUE);
  2580. }
  2581. /******************************Public*Routine******************************\
  2582. * VOID vXferScreenTo1bpp
  2583. *
  2584. * Performs a SRCCOPY transfer from the screen (when it's 8bpp) to a 1bpp
  2585. * bitmap.
  2586. *
  2587. \**************************************************************************/
  2588. VOID vXferScreenTo1bpp( // Type FNXFER
  2589. PDEV* ppdev,
  2590. LONG c, // Count of rectangles, can't be zero
  2591. RECTL* prcl, // List of destination rectangles, in relative
  2592. // coordinates
  2593. ULONG ulHwMix, // Not used
  2594. SURFOBJ* psoSrc, // Source surface
  2595. SURFOBJ* psoDst, // Destination surface
  2596. POINTL* pptlSrc, // Original unclipped source point
  2597. RECTL* prclDst, // Original unclipped destination rectangle
  2598. XLATEOBJ* pxlo) // Provides colour-compressions information
  2599. {
  2600. LONG cjPelSize;
  2601. VOID* pfnCompute;
  2602. SURFOBJ soTmp;
  2603. ULONG* pulXlate;
  2604. ULONG ulForeColor;
  2605. RECTL rclTmp;
  2606. BYTE* pjDst;
  2607. BYTE jLeftMask;
  2608. BYTE jRightMask;
  2609. BYTE jNotLeftMask;
  2610. BYTE jNotRightMask;
  2611. LONG cjMiddle;
  2612. LONG lDstDelta;
  2613. LONG lSrcDelta;
  2614. LONG cyTmpScans;
  2615. LONG cyThis;
  2616. LONG cyToGo;
  2617. ASSERTDD(c > 0, "Can't handle zero rectangles");
  2618. ASSERTDD(psoDst->iBitmapFormat == BMF_1BPP, "Only 1bpp destinations");
  2619. ASSERTDD(TMP_BUFFER_SIZE >= (ppdev->cxMemory * ppdev->cjPelSize),
  2620. "Temp buffer has to be larger than widest possible scan");
  2621. soTmp = *psoSrc;
  2622. // When the destination is a 1bpp bitmap, the foreground colour
  2623. // maps to '1', and any other colour maps to '0'.
  2624. if (ppdev->iBitmapFormat == BMF_8BPP)
  2625. {
  2626. // When the source is 8bpp or less, we find the forground colour
  2627. // by searching the translate table for the only '1':
  2628. pulXlate = pxlo->pulXlate;
  2629. while (*pulXlate != 1)
  2630. {
  2631. pulXlate++;
  2632. }
  2633. ulForeColor = pulXlate - pxlo->pulXlate;
  2634. }
  2635. else
  2636. {
  2637. ASSERTDD((ppdev->iBitmapFormat == BMF_16BPP) ||
  2638. (ppdev->iBitmapFormat == BMF_32BPP),
  2639. "This routine only supports 8, 16 or 32bpp");
  2640. // When the source has a depth greater than 8bpp, the foreground
  2641. // colour will be the first entry in the translate table we get
  2642. // from calling 'piVector':
  2643. pulXlate = XLATEOBJ_piVector(pxlo);
  2644. ulForeColor = 0;
  2645. if (pulXlate != NULL) // This check isn't really needed...
  2646. {
  2647. ulForeColor = pulXlate[0];
  2648. }
  2649. }
  2650. // We use the temporary buffer to keep a copy of the source
  2651. // rectangle:
  2652. soTmp.pvScan0 = ppdev->pvTmpBuffer;
  2653. do {
  2654. pjDst = (BYTE*) psoDst->pvScan0 + (prcl->top * psoDst->lDelta)
  2655. + (prcl->left >> 3);
  2656. cjPelSize = ppdev->cjPelSize;
  2657. soTmp.lDelta = (((prcl->right + 7L) & ~7L) - (prcl->left & ~7L))
  2658. * cjPelSize;
  2659. // Our temporary buffer, into which we read a copy of the source,
  2660. // may be smaller than the source rectangle. In that case, we
  2661. // process the source rectangle in batches.
  2662. //
  2663. // cyTmpScans is the number of scans we can do in each batch.
  2664. // cyToGo is the total number of scans we have to do for this
  2665. // rectangle.
  2666. //
  2667. // We take the buffer size less four so that the right edge case
  2668. // can safely read one dword past the end:
  2669. cyTmpScans = (TMP_BUFFER_SIZE - 4) / soTmp.lDelta;
  2670. cyToGo = prcl->bottom - prcl->top;
  2671. ASSERTDD(cyTmpScans > 0, "Buffer too small for largest possible scan");
  2672. // Initialize variables that don't change within the batch loop:
  2673. rclTmp.top = 0;
  2674. rclTmp.left = prcl->left & 7L;
  2675. rclTmp.right = (prcl->right - prcl->left) + rclTmp.left;
  2676. // Note that we have to be careful with the right mask so that it
  2677. // isn't zero. A right mask of zero would mean that we'd always be
  2678. // touching one byte past the end of the scan (even though we
  2679. // wouldn't actually be modifying that byte), and we must never
  2680. // access memory past the end of the bitmap (because we can access
  2681. // violate if the bitmap end is exactly page-aligned).
  2682. jLeftMask = gajLeftMask[rclTmp.left & 7];
  2683. jRightMask = gajRightMask[rclTmp.right & 7];
  2684. cjMiddle = ((rclTmp.right - 1) >> 3) - (rclTmp.left >> 3) - 1;
  2685. if (cjMiddle < 0)
  2686. {
  2687. // The blt starts and ends in the same byte:
  2688. jLeftMask &= jRightMask;
  2689. jRightMask = 0;
  2690. cjMiddle = 0;
  2691. }
  2692. jNotLeftMask = ~jLeftMask;
  2693. jNotRightMask = ~jRightMask;
  2694. lDstDelta = psoDst->lDelta - cjMiddle - 2;
  2695. // Delta from the end of the destination
  2696. // to the start on the next scan, accounting
  2697. // for 'left' and 'right' bytes
  2698. lSrcDelta = soTmp.lDelta - ((8 * (cjMiddle + 2)) * cjPelSize);
  2699. // Compute source delta for special cases
  2700. // like when cjMiddle gets bumped up to '0',
  2701. // and to correct aligned cases
  2702. do {
  2703. // This is the loop that breaks the source rectangle into
  2704. // manageable batches.
  2705. cyThis = cyTmpScans;
  2706. if( cyToGo < cyThis )
  2707. {
  2708. cyThis = cyToGo;
  2709. }
  2710. cyToGo -= cyThis;
  2711. rclTmp.bottom = cyThis;
  2712. ppdev->pgfnUpload( ppdev, 1, &rclTmp, &soTmp, pptlSrc, &rclTmp );
  2713. pptlSrc->y += cyThis;
  2714. _asm {
  2715. mov eax,ulForeColor ;eax = foreground colour
  2716. ;ebx = temporary storage
  2717. ;ecx = count of middle dst bytes
  2718. ;dl = destination byte accumulator
  2719. ;dh = temporary storage
  2720. mov esi,soTmp.pvScan0 ;esi = source pointer
  2721. mov edi,pjDst ;edi = destination pointer
  2722. ; Figure out the appropriate compute routine:
  2723. mov ebx,cjPelSize
  2724. mov pfnCompute,offset Compute_Destination_Byte_From_8bpp
  2725. dec ebx
  2726. jz short Do_Left_Byte
  2727. mov pfnCompute,offset Compute_Destination_Byte_From_16bpp
  2728. dec ebx
  2729. jz short Do_Left_Byte
  2730. mov pfnCompute,offset Compute_Destination_Byte_From_32bpp
  2731. Do_Left_Byte:
  2732. call pfnCompute
  2733. and dl,jLeftMask
  2734. mov dh,jNotLeftMask
  2735. and dh,[edi]
  2736. or dh,dl
  2737. mov [edi],dh
  2738. inc edi
  2739. mov ecx,cjMiddle
  2740. dec ecx
  2741. jl short Do_Right_Byte
  2742. Do_Middle_Bytes:
  2743. call pfnCompute
  2744. mov [edi],dl
  2745. inc edi
  2746. dec ecx
  2747. jge short Do_Middle_Bytes
  2748. Do_Right_Byte:
  2749. call pfnCompute
  2750. and dl,jRightMask
  2751. mov dh,jNotRightMask
  2752. and dh,[edi]
  2753. or dh,dl
  2754. mov [edi],dh
  2755. inc edi
  2756. add edi,lDstDelta
  2757. add esi,lSrcDelta
  2758. dec cyThis
  2759. jnz short Do_Left_Byte
  2760. mov pjDst,edi ;save for next batch
  2761. jmp All_Done
  2762. Compute_Destination_Byte_From_8bpp:
  2763. mov bl,[esi]
  2764. sub bl,al
  2765. cmp bl,1
  2766. adc dl,dl ;bit 0
  2767. mov bl,[esi+1]
  2768. sub bl,al
  2769. cmp bl,1
  2770. adc dl,dl ;bit 1
  2771. mov bl,[esi+2]
  2772. sub bl,al
  2773. cmp bl,1
  2774. adc dl,dl ;bit 2
  2775. mov bl,[esi+3]
  2776. sub bl,al
  2777. cmp bl,1
  2778. adc dl,dl ;bit 3
  2779. mov bl,[esi+4]
  2780. sub bl,al
  2781. cmp bl,1
  2782. adc dl,dl ;bit 4
  2783. mov bl,[esi+5]
  2784. sub bl,al
  2785. cmp bl,1
  2786. adc dl,dl ;bit 5
  2787. mov bl,[esi+6]
  2788. sub bl,al
  2789. cmp bl,1
  2790. adc dl,dl ;bit 6
  2791. mov bl,[esi+7]
  2792. sub bl,al
  2793. cmp bl,1
  2794. adc dl,dl ;bit 7
  2795. add esi,8 ;advance the source
  2796. ret
  2797. Compute_Destination_Byte_From_16bpp:
  2798. mov bx,[esi]
  2799. sub bx,ax
  2800. cmp bx,1
  2801. adc dl,dl ;bit 0
  2802. mov bx,[esi+2]
  2803. sub bx,ax
  2804. cmp bx,1
  2805. adc dl,dl ;bit 1
  2806. mov bx,[esi+4]
  2807. sub bx,ax
  2808. cmp bx,1
  2809. adc dl,dl ;bit 2
  2810. mov bx,[esi+6]
  2811. sub bx,ax
  2812. cmp bx,1
  2813. adc dl,dl ;bit 3
  2814. mov bx,[esi+8]
  2815. sub bx,ax
  2816. cmp bx,1
  2817. adc dl,dl ;bit 4
  2818. mov bx,[esi+10]
  2819. sub bx,ax
  2820. cmp bx,1
  2821. adc dl,dl ;bit 5
  2822. mov bx,[esi+12]
  2823. sub bx,ax
  2824. cmp bx,1
  2825. adc dl,dl ;bit 6
  2826. mov bx,[esi+14]
  2827. sub bx,ax
  2828. cmp bx,1
  2829. adc dl,dl ;bit 7
  2830. add esi,16 ;advance the source
  2831. ret
  2832. Compute_Destination_Byte_From_32bpp:
  2833. mov ebx,[esi]
  2834. sub ebx,eax
  2835. cmp ebx,1
  2836. adc dl,dl ;bit 0
  2837. mov ebx,[esi+4]
  2838. sub ebx,eax
  2839. cmp ebx,1
  2840. adc dl,dl ;bit 1
  2841. mov ebx,[esi+8]
  2842. sub ebx,eax
  2843. cmp ebx,1
  2844. adc dl,dl ;bit 2
  2845. mov ebx,[esi+12]
  2846. sub ebx,eax
  2847. cmp ebx,1
  2848. adc dl,dl ;bit 3
  2849. mov ebx,[esi+16]
  2850. sub ebx,eax
  2851. cmp ebx,1
  2852. adc dl,dl ;bit 4
  2853. mov ebx,[esi+20]
  2854. sub ebx,eax
  2855. cmp ebx,1
  2856. adc dl,dl ;bit 5
  2857. mov ebx,[esi+24]
  2858. sub ebx,eax
  2859. cmp ebx,1
  2860. adc dl,dl ;bit 6
  2861. mov ebx,[esi+28]
  2862. sub ebx,eax
  2863. cmp ebx,1
  2864. adc dl,dl ;bit 7
  2865. add esi,32 ;advance the source
  2866. ret
  2867. All_Done:
  2868. }
  2869. } while (cyToGo > 0);
  2870. prcl++;
  2871. } while (--c != 0);
  2872. }
  2873. #endif // defined(_X86_)
  2874. #if (_WIN32_WINNT >= 0x500)
  2875. //*****************************************************************************
  2876. // FUNC: DrvGradientFill
  2877. // ARGS: psoDst (I) - destination surface
  2878. // pco (I) - destination clipping
  2879. // pxlo (I) - color translation for pVertex
  2880. // pVertex (I) - array of trivertex (x,y,color) coordinates
  2881. // nVertex (I) - size of pVertex
  2882. // pMesh (I) - array of GRADIENT_RECT or GRADIENT_TRIANGLE structures
  2883. // that define the connectivity of pVertex points
  2884. // nMesh (I) - size of pMesh
  2885. // prclExtents (I) - the bounding rectangle
  2886. // pptlDitherOrg (I) - unused
  2887. // ulMode (I) - specifies the fill type (rectangular or triangular)and
  2888. // direction
  2889. // RETN: TRUE if successful
  2890. //-----------------------------------------------------------------------------
  2891. // Performs a Gouraud-shaded fill for an array of rectangles or triangles.
  2892. // Rectangles can be horizontally or vertically shaded (i.e. we only step the
  2893. // color DDA in one direction).
  2894. //*****************************************************************************
  2895. BOOL DrvGradientFill(
  2896. SURFOBJ *psoDst,
  2897. CLIPOBJ *pco,
  2898. XLATEOBJ *pxlo,
  2899. TRIVERTEX *pVertex,
  2900. ULONG nVertex,
  2901. PVOID pMesh,
  2902. ULONG nMesh,
  2903. RECTL *prclExtents,
  2904. POINTL *pptlDitherOrg,
  2905. ULONG ulMode)
  2906. {
  2907. SURFOBJ *psoDstOrig = psoDst; // destination surface DIB
  2908. PDEV *ppdev;
  2909. DSURF *pdsurf;
  2910. OH *poh;
  2911. SURFOBJ *psoDIBDst;
  2912. BOOL bSuccess = FALSE;
  2913. GLINT_DECL_VARS;
  2914. DISPDBG((DBGLVL, "DrvGradientFill entered"));
  2915. ppdev = (PDEV *)psoDst->dhpdev;
  2916. pdsurf = (DSURF *)psoDst->dhsurf;
  2917. GLINT_DECL_INIT;
  2918. if(ppdev->pgfnGradientFillRect == NULL)
  2919. {
  2920. // we don't accelerate this function
  2921. goto punt;
  2922. }
  2923. if(psoDst->iType == STYPE_BITMAP)
  2924. {
  2925. DISPDBG((4, "DrvGradientFill: destination is a DIB - "
  2926. "punt back to GDI"));
  2927. goto punt;
  2928. }
  2929. if((pdsurf->dt & DT_SCREEN) == 0)
  2930. {
  2931. DISPDBG((DBGLVL, "DrvGradientFill: destination is a DFB "
  2932. "now in host memory - punt back to GDI"));
  2933. goto punt;
  2934. }
  2935. if(ulMode == GRADIENT_FILL_TRIANGLE)
  2936. {
  2937. DISPDBG((DBGLVL, "DrvGradientFill: don't support triangular fills"));
  2938. goto punt;
  2939. }
  2940. //@@BEGIN_DDKSPLIT
  2941. /* ignore pxlo: source is always in 16:16:16:16 format
  2942. if(pxlo->iDstType)
  2943. {
  2944. // xlate object is valid
  2945. if((pxlo != NULL) && !(pxlo->flXlate & XO_TRIVIAL))
  2946. {
  2947. DISPDBG((DBGLVL, "DrvGradientFill: "
  2948. "don't support color translation"));
  2949. goto punt;
  2950. }
  2951. }
  2952. */
  2953. //@@END_DDKSPLIT
  2954. VALIDATE_DD_CONTEXT;
  2955. poh = pdsurf->poh;
  2956. SETUP_PPDEV_OFFSETS(ppdev, pdsurf);
  2957. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  2958. {
  2959. DISPDBG((DBGLVL, "DrvGradientFill: trivial clipping"));
  2960. bSuccess = ppdev->pgfnGradientFillRect(ppdev,
  2961. pVertex,
  2962. nVertex,
  2963. (GRADIENT_RECT *)pMesh,
  2964. nMesh,
  2965. ulMode,
  2966. prclExtents,
  2967. 1);
  2968. }
  2969. else if (pco->iDComplexity == DC_RECT)
  2970. {
  2971. RECTL rcl;
  2972. DISPDBG((DBGLVL, "DrvGradientFill: rectangular clipping"));
  2973. bSuccess = !bIntersect(prclExtents, &pco->rclBounds, &rcl);
  2974. if(!bSuccess)
  2975. {
  2976. bSuccess = ppdev->pgfnGradientFillRect(ppdev,
  2977. pVertex,
  2978. nVertex,
  2979. (GRADIENT_RECT *)pMesh,
  2980. nMesh,
  2981. ulMode,
  2982. &rcl,
  2983. 1);
  2984. }
  2985. }
  2986. else
  2987. {
  2988. CLIPENUM ce;
  2989. LONG crcl;
  2990. BOOL bMore;
  2991. DISPDBG((DBGLVL, "DrvGradientFill: complex clipping"));
  2992. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  2993. do {
  2994. bMore = CLIPOBJ_bEnum(pco, sizeof ce, (ULONG *)&ce);
  2995. crcl = cIntersect(prclExtents, ce.arcl, ce.c);
  2996. if(crcl)
  2997. {
  2998. bSuccess = ppdev->pgfnGradientFillRect(ppdev,
  2999. pVertex,
  3000. nVertex,
  3001. (GRADIENT_RECT *)pMesh,
  3002. nMesh,
  3003. ulMode,
  3004. ce.arcl,
  3005. crcl);
  3006. }
  3007. } while(bMore && bSuccess);
  3008. }
  3009. DISPDBG((DBGLVL, "DrvGradientFill done, bSuccess = %d", bSuccess));
  3010. if(bSuccess)
  3011. {
  3012. return(bSuccess);
  3013. }
  3014. punt:
  3015. DISPDBG((DBGLVL, "DrvGradientFill: calling EngGradientFill"));
  3016. if(psoDstOrig->iType != STYPE_BITMAP)
  3017. {
  3018. if(!glintInfo->GdiCantAccessFramebuffer)
  3019. {
  3020. psoDstOrig = pdsurf->pso;
  3021. }
  3022. }
  3023. bSuccess = EngGradientFill(psoDstOrig,
  3024. pco,
  3025. pxlo,
  3026. pVertex,
  3027. nVertex,
  3028. pMesh,
  3029. nMesh,
  3030. prclExtents,
  3031. pptlDitherOrg,
  3032. ulMode);
  3033. return(bSuccess);
  3034. }
  3035. //*****************************************************************************
  3036. // FUNC: DrvTransparentBlt
  3037. // ARGS: psoDst (I) - destination surface
  3038. // psoSrc (I) - sources surface
  3039. // pco (I) - destination clipping
  3040. // pxlo (I) - color translation from source to destination
  3041. // prclDst (I) - destination rectangle
  3042. // prclSrc (I) - source rectangle
  3043. // iTransColor (I) - transparent color
  3044. // RETN: TRUE if successful
  3045. //-----------------------------------------------------------------------------
  3046. // Performs a chroma-keyed COPY blt. Source and Destination are guaranteed not
  3047. // to overlap.
  3048. //*****************************************************************************
  3049. BOOL DrvTransparentBlt(
  3050. SURFOBJ *psoDst,
  3051. SURFOBJ *psoSrc,
  3052. CLIPOBJ *pco,
  3053. XLATEOBJ *pxlo,
  3054. RECTL *prclDst,
  3055. RECTL *prclSrc,
  3056. ULONG iTransColor,
  3057. ULONG ulReserved)
  3058. {
  3059. SURFOBJ *psoDstOrig = psoDst;
  3060. SURFOBJ *psoSrcOrig = psoSrc;
  3061. PDEV *ppdev;
  3062. DSURF *pdsurfSrc, *pdsurfDst;
  3063. OH *pohSrc, *pohDst;
  3064. ULONG cxSrc, cySrc, cxDst, cyDst;
  3065. POINTL ptlSrc;
  3066. BOOL bSuccess = FALSE;
  3067. GLINT_DECL_VARS;
  3068. DISPDBG((DBGLVL, "DrvTransparentBlt entered"));
  3069. if ((psoSrc->iType == STYPE_BITMAP) &&
  3070. (psoDst->iType == STYPE_BITMAP))
  3071. {
  3072. // we can't obtain any valid ppdev from this
  3073. goto punt_error;
  3074. }
  3075. if (psoSrc->iType != STYPE_BITMAP)
  3076. {
  3077. pdsurfSrc = (DSURF *)psoSrc->dhsurf;
  3078. ppdev = (PDEV *)psoSrc->dhpdev;
  3079. }
  3080. if (psoDst->iType != STYPE_BITMAP)
  3081. {
  3082. pdsurfDst = (DSURF *)psoDst->dhsurf;
  3083. ppdev = (PDEV *)psoDst->dhpdev;
  3084. }
  3085. GLINT_DECL_INIT;
  3086. if (ppdev->pgfnTransparentBlt == NULL)
  3087. {
  3088. // we don't accelerate this function
  3089. goto punt;
  3090. }
  3091. if (psoSrc->iType == STYPE_BITMAP)
  3092. {
  3093. DISPDBG((DBGLVL, "DrvTransparentBlt: don't support downloads"));
  3094. goto punt;
  3095. }
  3096. if (psoDst->iType == STYPE_BITMAP)
  3097. {
  3098. DISPDBG((DBGLVL, "DrvTransparentBlt: don't support uploads"));
  3099. goto punt;
  3100. }
  3101. if (pxlo && !(pxlo->flXlate & XO_TRIVIAL))
  3102. {
  3103. DISPDBG((DBGLVL, "DrvTransparentBlt: don't support xlates"));
  3104. goto punt;
  3105. }
  3106. // screen-to-screen blt
  3107. // ensure both surfaces are in the framebuffer
  3108. if((pdsurfSrc->dt & DT_SCREEN) == 0)
  3109. {
  3110. DISPDBG((DBGLVL, "DrvTransparentBlt: source is a DFB now "
  3111. "in host memory - punt back to GDI"));
  3112. goto punt;
  3113. }
  3114. if((pdsurfDst->dt & DT_SCREEN) == 0)
  3115. {
  3116. DISPDBG((DBGLVL, "DrvTransparentBlt: destination is a DFB "
  3117. "now in host memory - punt back to GDI"));
  3118. goto punt;
  3119. }
  3120. cxSrc = prclSrc->right - prclSrc->left;
  3121. cySrc = prclSrc->bottom - prclSrc->top;
  3122. cxDst = prclDst->right - prclDst->left;
  3123. cyDst = prclDst->bottom - prclDst->top;
  3124. if ((cxSrc != cxDst) || (cySrc != cyDst))
  3125. {
  3126. DISPDBG((DBGLVL, "DrvTransparentBlt: only support 1:1 blts "
  3127. "cxySrc(%d,%d) cxyDst(%d,%d)",
  3128. cxSrc, cySrc, cxDst, cyDst));
  3129. goto punt;
  3130. }
  3131. GLINT_DECL_INIT;
  3132. VALIDATE_DD_CONTEXT;
  3133. // destination surface base offset plus x offset from that
  3134. pohDst = pdsurfDst->poh;
  3135. pohSrc = pdsurfSrc->poh;
  3136. SETUP_PPDEV_SRC_AND_DST_OFFSETS(ppdev, pdsurfSrc, pdsurfDst);
  3137. ptlSrc.x = prclSrc->left + pohSrc->x;
  3138. ptlSrc.y = prclSrc->top;
  3139. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  3140. {
  3141. DISPDBG((DBGLVL, "DrvTransparentBlt: trivial clipping"));
  3142. bSuccess = ppdev->pgfnTransparentBlt(ppdev, prclDst, &ptlSrc,
  3143. iTransColor, prclDst, 1);
  3144. }
  3145. else if (pco->iDComplexity == DC_RECT)
  3146. {
  3147. RECTL rcl;
  3148. DISPDBG((DBGLVL, "DrvTransparentBlt: rectangular clipping"));
  3149. bSuccess = !bIntersect(prclDst, &pco->rclBounds, &rcl);
  3150. if (!bSuccess)
  3151. {
  3152. bSuccess = ppdev->pgfnTransparentBlt(ppdev, prclDst, &ptlSrc,
  3153. iTransColor, &rcl, 1);
  3154. }
  3155. }
  3156. else
  3157. {
  3158. CLIPENUM ce;
  3159. LONG crcl;
  3160. BOOL bMore;
  3161. DISPDBG((DBGLVL, "DrvTransparentBlt: complex clipping"));
  3162. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  3163. do {
  3164. bMore = CLIPOBJ_bEnum(pco, sizeof ce, (ULONG *)&ce);
  3165. crcl = cIntersect(prclDst, ce.arcl, ce.c);
  3166. if(crcl)
  3167. {
  3168. bSuccess = ppdev->pgfnTransparentBlt(ppdev,prclDst, &ptlSrc,
  3169. iTransColor, ce.arcl,
  3170. crcl);
  3171. }
  3172. } while(bMore && bSuccess);
  3173. }
  3174. DISPDBG((DBGLVL, "DrvTransparentBlt done, bSuccess = %d", bSuccess));
  3175. if(bSuccess)
  3176. {
  3177. return(bSuccess);
  3178. }
  3179. punt:
  3180. DISPDBG((DBGLVL, "DrvTransparentBlt: calling EngTransparentBlt"));
  3181. if(psoDstOrig->iType != STYPE_BITMAP)
  3182. {
  3183. if(!glintInfo->GdiCantAccessFramebuffer)
  3184. psoDstOrig = pdsurfDst->pso;
  3185. }
  3186. if(psoSrcOrig->iType != STYPE_BITMAP)
  3187. {
  3188. if(!glintInfo->GdiCantAccessFramebuffer)
  3189. psoSrcOrig = pdsurfSrc->pso;
  3190. }
  3191. punt_error:
  3192. bSuccess = EngTransparentBlt(psoDstOrig,
  3193. psoSrcOrig,
  3194. pco,
  3195. pxlo,
  3196. prclDst,
  3197. prclSrc,
  3198. iTransColor,
  3199. ulReserved);
  3200. return(bSuccess);
  3201. }
  3202. //*****************************************************************************
  3203. // FUNC: DrvAlphaBlend
  3204. // ARGS: psoDst (I) - destination surface
  3205. // psoSrc (I) - sources surface
  3206. // pco (I) - destination clipping
  3207. // pxlo (I) - color translation from source to destination
  3208. // prclDst (I) - destination rectangle
  3209. // prclSrc (I) - source rectangle
  3210. // pBlendObj (I) - specifies the type of alpha blending
  3211. // RETN: TRUE if successful
  3212. //-----------------------------------------------------------------------------
  3213. // Performs a blt with alpha blending. There are three types of blend
  3214. // operation:-
  3215. // 1.) Source has constant alpha. Each destination color component is
  3216. // calculated using the common blend function:-
  3217. // dC = sC.cA + dC(1 - cA)
  3218. // 2.) Source has per pixel alpha. The source is guaranteed to be 32 bits and
  3219. // to have been premultiplied with its alpha. Each destination color
  3220. // component is calculated using the premult blend function:-
  3221. // dC = sC + dC(1 - sA)
  3222. // 3.) Source has per pixel alpha and constant alpha. The source is guaranteed
  3223. // to be 32 bits and to have been premultiplied with its alpha. The
  3224. // calculation is in two stages, first we calculate the transient value of
  3225. // each component by multiplying the source with the constant alpha:-
  3226. // tC = sC * cA
  3227. // Next, we blend the destination with the premultiplied transient value:-
  3228. // dC = tC + dC(1 - tA)
  3229. //
  3230. // dC = destination component, sC = source component, tC = transient component
  3231. // cA = constant alpha, sA = source alpha, tA = transient alpha
  3232. //*****************************************************************************
  3233. BOOL DrvAlphaBlend(
  3234. SURFOBJ *psoDst,
  3235. SURFOBJ *psoSrc,
  3236. CLIPOBJ *pco,
  3237. XLATEOBJ *pxlo,
  3238. RECTL *prclDst,
  3239. RECTL *prclSrc,
  3240. BLENDOBJ *pBlendObj)
  3241. {
  3242. SURFOBJ *psoDstOrig = psoDst;
  3243. SURFOBJ *psoSrcOrig = psoSrc;
  3244. PDEV *ppdev;
  3245. DSURF *pdsurfDst, *pdsurfSrc;
  3246. OH *pohDst, *pohSrc;
  3247. ULONG cxSrc, cySrc, cxDst, cyDst;
  3248. POINTL ptlSrc;
  3249. CLIPENUM ce;
  3250. BOOL bMore;
  3251. LONG crcl;
  3252. BOOL bSuccess = FALSE;
  3253. GLINT_DECL_VARS;
  3254. DISPDBG((DBGLVL, "DrvAlphaBlend entered"));
  3255. if ((psoSrc->iType == STYPE_BITMAP) &&
  3256. (psoDst->iType == STYPE_BITMAP))
  3257. {
  3258. // we can't obtain any valid ppdev from this
  3259. goto punt_error;
  3260. }
  3261. if (psoSrc->iType != STYPE_BITMAP)
  3262. {
  3263. pdsurfSrc = (DSURF *)psoSrc->dhsurf;
  3264. ppdev = (PDEV *)psoSrc->dhpdev;
  3265. }
  3266. if (psoDst->iType != STYPE_BITMAP)
  3267. {
  3268. pdsurfDst = (DSURF *)psoDst->dhsurf;
  3269. ppdev = (PDEV *)psoDst->dhpdev;
  3270. }
  3271. GLINT_DECL_INIT;
  3272. if (ppdev->pgfnAlphaBlend == NULL)
  3273. {
  3274. // we don't accelerate this function
  3275. goto punt;
  3276. }
  3277. if (psoSrc->iType == STYPE_BITMAP)
  3278. {
  3279. DISPDBG((DBGLVL, "DrvAlphaBlend: don't support downloads"));
  3280. goto punt;
  3281. }
  3282. if (psoDst->iType == STYPE_BITMAP)
  3283. {
  3284. DISPDBG((DBGLVL, "DrvAlphaBlend: don't support uploads"));
  3285. goto punt;
  3286. }
  3287. if (pxlo && !(pxlo->flXlate & XO_TRIVIAL))
  3288. {
  3289. DISPDBG((DBGLVL, "DrvAlphaBlend: don't support xlates"));
  3290. goto punt;
  3291. }
  3292. // screen-to-screen blt
  3293. // ensure both surfaces are in the framebuffer
  3294. if((pdsurfSrc->dt & DT_SCREEN) == 0)
  3295. {
  3296. DISPDBG((DBGLVL, "DrvAlphaBlend: source is a DFB now in host memory "
  3297. "- punt back to GDI"));
  3298. goto punt;
  3299. }
  3300. if((pdsurfDst->dt & DT_SCREEN) == 0)
  3301. {
  3302. DISPDBG((DBGLVL, "DrvAlphaBlend: destination is a DFB now in host "
  3303. "memory - punt back to GDI"));
  3304. goto punt;
  3305. }
  3306. cxSrc = prclSrc->right - prclSrc->left;
  3307. cySrc = prclSrc->bottom - prclSrc->top;
  3308. cxDst = prclDst->right - prclDst->left;
  3309. cyDst = prclDst->bottom - prclDst->top;
  3310. if((cxSrc != cxDst) || (cySrc != cyDst))
  3311. {
  3312. DISPDBG((DBGLVL, "DrvAlphaBlend: only support 1:1 blts "
  3313. "cxySrc(%d,%d) cxyDst(%d,%d)",
  3314. cxSrc, cySrc, cxDst, cyDst));
  3315. goto punt;
  3316. }
  3317. GLINT_DECL_INIT;
  3318. VALIDATE_DD_CONTEXT;
  3319. // destination surface base offset plus x offset from that
  3320. pohDst = pdsurfDst->poh;
  3321. pohSrc = pdsurfSrc->poh;
  3322. SETUP_PPDEV_SRC_AND_DST_OFFSETS(ppdev, pdsurfSrc, pdsurfDst);
  3323. ptlSrc.x = prclSrc->left + pohSrc->x;
  3324. ptlSrc.y = prclSrc->top;
  3325. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  3326. {
  3327. DISPDBG((DBGLVL, "DrvAlphaBlend: trivial clipping"));
  3328. bSuccess = ppdev->pgfnAlphaBlend(ppdev, prclDst, &ptlSrc, pBlendObj,
  3329. prclDst, 1);
  3330. }
  3331. else if (pco->iDComplexity == DC_RECT)
  3332. {
  3333. RECTL rcl;
  3334. DISPDBG((DBGLVL, "DrvAlphaBlend: rectangular clipping"));
  3335. bSuccess = !bIntersect(prclDst, &pco->rclBounds, &rcl);
  3336. if (!bSuccess)
  3337. {
  3338. bSuccess = ppdev->pgfnAlphaBlend(ppdev, prclDst, &ptlSrc,
  3339. pBlendObj, &rcl, 1);
  3340. }
  3341. }
  3342. else
  3343. {
  3344. DISPDBG((DBGLVL, "DrvAlphaBlend: complex clipping"));
  3345. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  3346. do {
  3347. bMore = CLIPOBJ_bEnum(pco, sizeof ce, (ULONG *)&ce);
  3348. crcl = cIntersect(prclDst, ce.arcl, ce.c);
  3349. if(crcl)
  3350. {
  3351. bSuccess = ppdev->pgfnAlphaBlend(ppdev,prclDst, &ptlSrc,
  3352. pBlendObj, ce.arcl, crcl);
  3353. }
  3354. } while(bMore && bSuccess);
  3355. }
  3356. DISPDBG((DBGLVL, "DrvAlphaBlend done, bSuccess = %d", bSuccess));
  3357. if (bSuccess)
  3358. {
  3359. return(bSuccess);
  3360. }
  3361. punt:
  3362. DISPDBG((DBGLVL, "DrvAlphaBlend: calling EngAlphaBlend"));
  3363. if (psoDstOrig->iType != STYPE_BITMAP)
  3364. {
  3365. if (!glintInfo->GdiCantAccessFramebuffer)
  3366. psoDstOrig = pdsurfDst->pso;
  3367. }
  3368. if (psoSrcOrig->iType != STYPE_BITMAP)
  3369. {
  3370. if (!glintInfo->GdiCantAccessFramebuffer)
  3371. psoSrcOrig = pdsurfSrc->pso;
  3372. }
  3373. punt_error:
  3374. bSuccess = EngAlphaBlend(psoDstOrig,
  3375. psoSrcOrig,
  3376. pco,
  3377. pxlo,
  3378. prclDst,
  3379. prclSrc,
  3380. pBlendObj);
  3381. return(bSuccess);
  3382. }
  3383. #endif //(_WIN32_WINNT >= 0x500)