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.

529 lines
11 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1999-2000 Microsoft Corporation
  4. *
  5. * Module name:
  6. *
  7. * The "WriteRMW" scan operation.
  8. *
  9. * Abstract:
  10. *
  11. * See Gdiplus\Specs\ScanOperation.doc for an overview.
  12. *
  13. * This module implements scan operations for writing to the final destination
  14. * when we've done the 'RMW optimization' (see SOReadRMW.cpp).
  15. *
  16. * We use ReadRMW in some cases when we do a SrcOver alpha-blend operation.
  17. * When a pixel to be blended has 0 alpha, this means that the destination
  18. * pixel will be unchanged. The ReadRMW operation skips reading the pixel,
  19. * so the WriteRMW operation must skip writing to it (to avoid writing
  20. * garbage).
  21. *
  22. * Revision History:
  23. *
  24. * 12/10/1999 agodfrey
  25. * Created it.
  26. *
  27. \**************************************************************************/
  28. #include "precomp.hpp"
  29. // SHOULDCOPY* returns FALSE if the specified alpha value is
  30. // completely transparent.
  31. #define SHOULDCOPY_sRGB(x) ((x) != 0)
  32. #define SHOULDCOPY_sRGB64(x) ((x) != 0)
  33. // Helper macros for declaring 'alpha', a pointer to the
  34. // first alpha component in the blending scan.
  35. #define DECLARE_ALPHA_sRGB \
  36. const BYTE *alpha = \
  37. static_cast<const BYTE *>(otherParams->BlendingScan) + 3;
  38. #define DECLARE_ALPHA_sRGB64 \
  39. const INT16 *alpha = \
  40. static_cast<const INT16 *>(otherParams->BlendingScan) + 3;
  41. /**************************************************************************\
  42. *
  43. * Operation Description:
  44. *
  45. * ReadRMW: Copy all pixels where the corresponding pixel in
  46. * otherParams->BlendingScan is not completely transparent
  47. * (i.e. alpha is not 0.)
  48. *
  49. * Arguments:
  50. *
  51. * dst - The destination scan
  52. * src - The source scan
  53. * count - The length of the scan, in pixels
  54. * otherParams - Additional data (we use BlendingScan).
  55. *
  56. * Return Value:
  57. *
  58. * None
  59. *
  60. * History:
  61. *
  62. * 12/10/1999 agodfrey
  63. * Created it.
  64. *
  65. \**************************************************************************/
  66. // 8bpp, for sRGB
  67. VOID FASTCALL
  68. ScanOperation::WriteRMW_8_sRGB(
  69. VOID *dst,
  70. const VOID *src,
  71. INT count,
  72. const OtherParams *otherParams
  73. )
  74. {
  75. DEFINE_POINTERS(BYTE, BYTE)
  76. DECLARE_ALPHA_sRGB
  77. // We want to get dword alignment for our copies, so handle the
  78. // initial partial dword, if there is one:
  79. INT align = (INT) ((-((LONG_PTR) d)) & 0x3);
  80. align = min(count, align);
  81. count -= align;
  82. while (align)
  83. {
  84. if (SHOULDCOPY_sRGB(*alpha))
  85. {
  86. *d = *s;
  87. }
  88. d++;
  89. s++;
  90. alpha += 4;
  91. align--;
  92. }
  93. // Now go through the aligned dword loop:
  94. while (count >= 4)
  95. {
  96. ASSERT((((ULONG_PTR) d) & 0x3) == 0);
  97. int mask = 0;
  98. if (SHOULDCOPY_sRGB(*alpha))
  99. {
  100. mask = 1;
  101. }
  102. if (SHOULDCOPY_sRGB(*(alpha+4)))
  103. {
  104. mask |= 2;
  105. }
  106. if (SHOULDCOPY_sRGB(*(alpha+8)))
  107. {
  108. mask |= 4;
  109. }
  110. if (SHOULDCOPY_sRGB(*(alpha+12)))
  111. {
  112. mask |= 8;
  113. }
  114. if (mask == 15)
  115. {
  116. // Do a dword write.
  117. *((UINT32*) d) = *((UNALIGNED UINT32*) s);
  118. }
  119. else
  120. {
  121. int idx = 0;
  122. while (mask)
  123. {
  124. if (mask & 1)
  125. {
  126. *(d + idx) = *(s + idx);
  127. }
  128. idx ++;
  129. mask >>= 1;
  130. }
  131. }
  132. d += 4;
  133. s += 4;
  134. alpha += 16;
  135. count -= 4;
  136. }
  137. // Handle the last few pixels:
  138. while (count)
  139. {
  140. if (SHOULDCOPY_sRGB(*alpha))
  141. {
  142. *d = *s;
  143. }
  144. d++;
  145. s++;
  146. alpha += 4;
  147. count--;
  148. }
  149. }
  150. // 8bpp, for sRGB64
  151. VOID FASTCALL
  152. ScanOperation::WriteRMW_8_sRGB64(
  153. VOID *dst,
  154. const VOID *src,
  155. INT count,
  156. const OtherParams *otherParams
  157. )
  158. {
  159. DEFINE_POINTERS(BYTE, BYTE)
  160. DECLARE_ALPHA_sRGB64
  161. // We want to get dword alignment for our copies, so handle the
  162. // initial partial dword, if there is one:
  163. INT align = (INT) ((-((LONG_PTR) d)) & 0x3);
  164. align = min(count, align);
  165. count -= align;
  166. while (align)
  167. {
  168. if (SHOULDCOPY_sRGB64(*alpha))
  169. {
  170. *d = *s;
  171. }
  172. d++;
  173. s++;
  174. alpha += 4;
  175. align--;
  176. }
  177. // Now go through the aligned dword loop:
  178. while (count >= 4)
  179. {
  180. ASSERT((((ULONG_PTR) d) & 0x3) == 0);
  181. int mask = 0;
  182. if (SHOULDCOPY_sRGB64(*alpha))
  183. {
  184. mask = 1;
  185. }
  186. if (SHOULDCOPY_sRGB64(*(alpha+4)))
  187. {
  188. mask |= 2;
  189. }
  190. if (SHOULDCOPY_sRGB64(*(alpha+8)))
  191. {
  192. mask |= 4;
  193. }
  194. if (SHOULDCOPY_sRGB64(*(alpha+12)))
  195. {
  196. mask |= 8;
  197. }
  198. if (mask == 15)
  199. {
  200. // Do a dword write.
  201. *((UINT32*) d) = *((UNALIGNED UINT32*) s);
  202. }
  203. else
  204. {
  205. int idx = 0;
  206. while (mask)
  207. {
  208. if (mask & 1)
  209. {
  210. *(d + idx) = *(s + idx);
  211. }
  212. idx ++;
  213. mask >>= 1;
  214. }
  215. }
  216. d += 4;
  217. s += 4;
  218. alpha += 16;
  219. count -= 4;
  220. }
  221. // Handle the last few pixels:
  222. while (count)
  223. {
  224. if (SHOULDCOPY_sRGB64(*alpha))
  225. {
  226. *d = *s;
  227. }
  228. d++;
  229. s++;
  230. alpha += 4;
  231. count--;
  232. }
  233. }
  234. // 16bpp, for sRGB
  235. VOID FASTCALL
  236. ScanOperation::WriteRMW_16_sRGB(
  237. VOID *dst,
  238. const VOID *src,
  239. INT count,
  240. const OtherParams *otherParams
  241. )
  242. {
  243. DEFINE_POINTERS(UINT16, UINT16)
  244. DECLARE_ALPHA_sRGB
  245. // We want to get dword alignment for our copies, so handle the
  246. // initial partial dword, if there is one:
  247. if (((ULONG_PTR) d) & 0x2)
  248. {
  249. if (SHOULDCOPY_sRGB(*alpha))
  250. {
  251. *(d) = *(s);
  252. }
  253. d++;
  254. s++;
  255. alpha += 4;
  256. count--;
  257. }
  258. // Now go through the aligned dword loop:
  259. while ((count -= 2) >= 0)
  260. {
  261. if (SHOULDCOPY_sRGB(*alpha))
  262. {
  263. if (SHOULDCOPY_sRGB(*(alpha + 4)))
  264. {
  265. // Both pixels have partial alpha, so do a dword read:
  266. *((UINT32*) d) = *((UNALIGNED UINT32*) s);
  267. }
  268. else
  269. {
  270. // Only the first pixel has partial alpha, so do a word read:
  271. *(d) = *(s);
  272. }
  273. }
  274. else if (SHOULDCOPY_sRGB(*(alpha + 4)))
  275. {
  276. // Only the second pixel has partial alpha, so do a word read:
  277. *(d + 1) = *(s + 1);
  278. }
  279. d += 2;
  280. s += 2;
  281. alpha += 8;
  282. }
  283. // Handle the end alignment:
  284. if (count & 1)
  285. {
  286. if (SHOULDCOPY_sRGB(*alpha))
  287. {
  288. *(d) = *(s);
  289. }
  290. }
  291. }
  292. // 16bpp, for sRGB64
  293. VOID FASTCALL
  294. ScanOperation::WriteRMW_16_sRGB64(
  295. VOID *dst,
  296. const VOID *src,
  297. INT count,
  298. const OtherParams *otherParams
  299. )
  300. {
  301. DEFINE_POINTERS(UINT16, UINT16)
  302. DECLARE_ALPHA_sRGB64
  303. // We want to get dword alignment for our copies, so handle the
  304. // initial partial dword, if there is one:
  305. if (((ULONG_PTR) d) & 0x2)
  306. {
  307. if (SHOULDCOPY_sRGB64(*alpha))
  308. {
  309. *(d) = *(s);
  310. }
  311. d++;
  312. s++;
  313. alpha += 4;
  314. count--;
  315. }
  316. // Now go through the aligned dword loop:
  317. while ((count -= 2) >= 0)
  318. {
  319. if (SHOULDCOPY_sRGB64(*alpha))
  320. {
  321. if (SHOULDCOPY_sRGB64(*(alpha + 4)))
  322. {
  323. // Both pixels have partial alpha, so do a dword read:
  324. *((UINT32*) d) = *((UNALIGNED UINT32*) s);
  325. }
  326. else
  327. {
  328. // Only the first pixel has partial alpha, so do a word read:
  329. *(d) = *(s);
  330. }
  331. }
  332. else if (SHOULDCOPY_sRGB64(*(alpha + 4)))
  333. {
  334. // Only the second pixel has partial alpha, so do a word read:
  335. *(d + 1) = *(s + 1);
  336. }
  337. d += 2;
  338. s += 2;
  339. alpha += 8;
  340. }
  341. // Handle the end alignment:
  342. if (count & 1)
  343. {
  344. if (SHOULDCOPY_sRGB64(*alpha))
  345. {
  346. *(d) = *(s);
  347. }
  348. }
  349. }
  350. // 24bpp, for sRGB
  351. VOID FASTCALL
  352. ScanOperation::WriteRMW_24_sRGB(
  353. VOID *dst,
  354. const VOID *src,
  355. INT count,
  356. const OtherParams *otherParams
  357. )
  358. {
  359. DEFINE_POINTERS(BYTE, BYTE)
  360. DECLARE_ALPHA_sRGB
  361. ASSERT(count>0);
  362. do {
  363. if (SHOULDCOPY_sRGB(*alpha))
  364. {
  365. // Doing byte per byte writes are much faster than finding
  366. // runs and doing DWORD copies.
  367. *(d) = *(s);
  368. *(d + 1) = *(s + 1);
  369. *(d + 2) = *(s + 2);
  370. }
  371. d += 3;
  372. s += 3;
  373. alpha += 4;
  374. } while (--count != 0);
  375. }
  376. // 24bpp, for sRGB64
  377. VOID FASTCALL
  378. ScanOperation::WriteRMW_24_sRGB64(
  379. VOID *dst,
  380. const VOID *src,
  381. INT count,
  382. const OtherParams *otherParams
  383. )
  384. {
  385. DEFINE_POINTERS(BYTE, BYTE)
  386. DECLARE_ALPHA_sRGB64
  387. ASSERT(count>0);
  388. do {
  389. if (SHOULDCOPY_sRGB64(*alpha))
  390. {
  391. // Doing byte per byte writes are much faster than finding
  392. // runs and doing DWORD copies.
  393. *(d) = *(s);
  394. *(d + 1) = *(s + 1);
  395. *(d + 2) = *(s + 2);
  396. }
  397. d += 3;
  398. s += 3;
  399. alpha += 4;
  400. } while (--count != 0);
  401. }
  402. // 32bpp, for sRGB
  403. VOID FASTCALL
  404. ScanOperation::WriteRMW_32_sRGB(
  405. VOID *dst,
  406. const VOID *src,
  407. INT count,
  408. const OtherParams *otherParams
  409. )
  410. {
  411. DEFINE_POINTERS(UINT32, UINT32)
  412. DECLARE_ALPHA_sRGB
  413. while (count--)
  414. {
  415. if (SHOULDCOPY_sRGB(*alpha))
  416. {
  417. *d = *s;
  418. }
  419. d++;
  420. s++;
  421. alpha += 4;
  422. }
  423. }
  424. // 32bpp, for sRGB64
  425. VOID FASTCALL
  426. ScanOperation::WriteRMW_32_sRGB64(
  427. VOID *dst,
  428. const VOID *src,
  429. INT count,
  430. const OtherParams *otherParams
  431. )
  432. {
  433. DEFINE_POINTERS(UINT32, UINT32)
  434. DECLARE_ALPHA_sRGB64
  435. while (count--)
  436. {
  437. if (SHOULDCOPY_sRGB64(*alpha))
  438. {
  439. *d = *s;
  440. }
  441. d++;
  442. s++;
  443. alpha += 4;
  444. }
  445. }