BC6Decoder.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  1. using Ryujinx.Graphics.Texture.Utils;
  2. using System;
  3. using System.Runtime.InteropServices;
  4. namespace Ryujinx.Graphics.Texture
  5. {
  6. static class BC6Decoder
  7. {
  8. private const int HalfOne = 0x3C00;
  9. public static void Decode(Span<byte> output, ReadOnlySpan<byte> data, int width, int height, bool signed)
  10. {
  11. ReadOnlySpan<Block> blocks = MemoryMarshal.Cast<byte, Block>(data);
  12. Span<ulong> output64 = MemoryMarshal.Cast<byte, ulong>(output);
  13. int wInBlocks = (width + 3) / 4;
  14. int hInBlocks = (height + 3) / 4;
  15. for (int y = 0; y < hInBlocks; y++)
  16. {
  17. int y2 = y * 4;
  18. int bh = Math.Min(4, height - y2);
  19. for (int x = 0; x < wInBlocks; x++)
  20. {
  21. int x2 = x * 4;
  22. int bw = Math.Min(4, width - x2);
  23. DecodeBlock(blocks[y * wInBlocks + x], output64.Slice(y2 * width + x2), bw, bh, width, signed);
  24. }
  25. }
  26. }
  27. private static void DecodeBlock(Block block, Span<ulong> output, int w, int h, int width, bool signed)
  28. {
  29. int mode = (int)(block.Low & 3);
  30. if ((mode & 2) != 0)
  31. {
  32. mode = (int)(block.Low & 0x1f);
  33. }
  34. Span<RgbaColor32> endPoints = stackalloc RgbaColor32[4];
  35. int subsetCount = DecodeEndPoints(ref block, endPoints, mode, signed);
  36. if (subsetCount == 0)
  37. {
  38. // Mode is invalid, the spec mandates that hardware fills the block with
  39. // a opaque black color.
  40. for (int ty = 0; ty < h; ty++)
  41. {
  42. int baseOffs = ty * width;
  43. for (int tx = 0; tx < w; tx++)
  44. {
  45. output[baseOffs + tx] = (ulong)HalfOne << 48;
  46. }
  47. }
  48. return;
  49. }
  50. int partition;
  51. int indexBitCount;
  52. ulong indices;
  53. if (subsetCount > 1)
  54. {
  55. partition = (int)((block.High >> 13) & 0x1F);
  56. indexBitCount = 3;
  57. int fixUpIndex = BC67Tables.FixUpIndices[subsetCount - 1][partition][1] * 3;
  58. ulong lowMask = (ulong.MaxValue >> (65 - fixUpIndex)) << 3;
  59. ulong highMask = ulong.MaxValue << (fixUpIndex + 3);
  60. indices = ((block.High >> 16) & highMask) | ((block.High >> 17) & lowMask) | ((block.High >> 18) & 3);
  61. }
  62. else
  63. {
  64. partition = 0;
  65. indexBitCount = 4;
  66. indices = (block.High & ~0xFUL) | ((block.High >> 1) & 7);
  67. }
  68. ulong indexMask = (1UL << indexBitCount) - 1;
  69. for (int ty = 0; ty < h; ty++)
  70. {
  71. int baseOffs = ty * width;
  72. for (int tx = 0; tx < w; tx++)
  73. {
  74. int offs = baseOffs + tx;
  75. int index = (int)(indices & indexMask);
  76. int endPointBase = BC67Tables.PartitionTable[subsetCount - 1][partition][ty * 4 + tx] << 1;
  77. RgbaColor32 color1 = endPoints[endPointBase];
  78. RgbaColor32 color2 = endPoints[endPointBase + 1];
  79. RgbaColor32 color = BC67Utils.Interpolate(color1, color2, index, indexBitCount);
  80. output[offs] =
  81. (ulong)FinishUnquantize(color.R, signed) |
  82. ((ulong)FinishUnquantize(color.G, signed) << 16) |
  83. ((ulong)FinishUnquantize(color.B, signed) << 32) |
  84. ((ulong)HalfOne << 48);
  85. indices >>= indexBitCount;
  86. }
  87. }
  88. }
  89. private static int DecodeEndPoints(ref Block block, Span<RgbaColor32> endPoints, int mode, bool signed)
  90. {
  91. ulong low = block.Low;
  92. ulong high = block.High;
  93. int r0 = 0, g0 = 0, b0 = 0, r1 = 0, g1 = 0, b1 = 0, r2 = 0, g2 = 0, b2 = 0, r3 = 0, g3 = 0, b3 = 0;
  94. int subsetCount;
  95. switch (mode)
  96. {
  97. case 0:
  98. r0 = (int)(low >> 5) & 0x3FF;
  99. g0 = (int)(low >> 15) & 0x3FF;
  100. b0 = (int)(low >> 25) & 0x3FF;
  101. if (signed)
  102. {
  103. r0 = SignExtend(r0, 10);
  104. g0 = SignExtend(g0, 10);
  105. b0 = SignExtend(b0, 10);
  106. }
  107. r1 = r0 + SignExtend((int)(low >> 35), 5);
  108. g1 = g0 + SignExtend((int)(low >> 45), 5);
  109. b1 = b0 + SignExtend((int)(low >> 55), 5);
  110. r2 = r0 + SignExtend((int)(high >> 1), 5);
  111. g2 = g0 + SignExtend((int)(((low << 2) & 0x10) | ((low >> 41) & 0xF)), 5);
  112. b2 = b0 + SignExtend((int)(((low << 1) & 0x10) | ((high << 3) & 0x08) | (low >> 61)), 5);
  113. r3 = r0 + SignExtend((int)(high >> 7), 5);
  114. g3 = g0 + SignExtend((int)(((low >> 36) & 0x10) | ((low >> 51) & 0xF)), 5);
  115. b3 = b0 + SignExtend((int)(
  116. ((low) & 0x10) |
  117. ((high >> 9) & 0x08) |
  118. ((high >> 4) & 0x04) |
  119. ((low >> 59) & 0x02) |
  120. ((low >> 50) & 0x01)), 5);
  121. r0 = Unquantize(r0, 10, signed);
  122. g0 = Unquantize(g0, 10, signed);
  123. b0 = Unquantize(b0, 10, signed);
  124. r1 = Unquantize(r1 & 0x3FF, 10, signed);
  125. g1 = Unquantize(g1 & 0x3FF, 10, signed);
  126. b1 = Unquantize(b1 & 0x3FF, 10, signed);
  127. r2 = Unquantize(r2 & 0x3FF, 10, signed);
  128. g2 = Unquantize(g2 & 0x3FF, 10, signed);
  129. b2 = Unquantize(b2 & 0x3FF, 10, signed);
  130. r3 = Unquantize(r3 & 0x3FF, 10, signed);
  131. g3 = Unquantize(g3 & 0x3FF, 10, signed);
  132. b3 = Unquantize(b3 & 0x3FF, 10, signed);
  133. subsetCount = 2;
  134. break;
  135. case 1:
  136. r0 = (int)(low >> 5) & 0x7F;
  137. g0 = (int)(low >> 15) & 0x7F;
  138. b0 = (int)(low >> 25) & 0x7F;
  139. if (signed)
  140. {
  141. r0 = SignExtend(r0, 7);
  142. g0 = SignExtend(g0, 7);
  143. b0 = SignExtend(b0, 7);
  144. }
  145. r1 = r0 + SignExtend((int)(low >> 35), 6);
  146. g1 = g0 + SignExtend((int)(low >> 45), 6);
  147. b1 = b0 + SignExtend((int)(low >> 55), 6);
  148. r2 = r0 + SignExtend((int)(high >> 1), 6);
  149. g2 = g0 + SignExtend((int)(((low << 3) & 0x20) | ((low >> 20) & 0x10) | ((low >> 41) & 0x0F)), 6);
  150. b2 = b0 + SignExtend((int)(
  151. ((low >> 17) & 0x20) |
  152. ((low >> 10) & 0x10) |
  153. ((high << 3) & 0x08) |
  154. (low >> 61)), 6);
  155. r3 = r0 + SignExtend((int)(high >> 7), 6);
  156. g3 = g0 + SignExtend((int)(((low << 1) & 0x30) | ((low >> 51) & 0xF)), 6);
  157. b3 = b0 + SignExtend((int)(
  158. ((low >> 28) & 0x20) |
  159. ((low >> 30) & 0x10) |
  160. ((low >> 29) & 0x08) |
  161. ((low >> 21) & 0x04) |
  162. ((low >> 12) & 0x03)), 6);
  163. r0 = Unquantize(r0, 7, signed);
  164. g0 = Unquantize(g0, 7, signed);
  165. b0 = Unquantize(b0, 7, signed);
  166. r1 = Unquantize(r1 & 0x7F, 7, signed);
  167. g1 = Unquantize(g1 & 0x7F, 7, signed);
  168. b1 = Unquantize(b1 & 0x7F, 7, signed);
  169. r2 = Unquantize(r2 & 0x7F, 7, signed);
  170. g2 = Unquantize(g2 & 0x7F, 7, signed);
  171. b2 = Unquantize(b2 & 0x7F, 7, signed);
  172. r3 = Unquantize(r3 & 0x7F, 7, signed);
  173. g3 = Unquantize(g3 & 0x7F, 7, signed);
  174. b3 = Unquantize(b3 & 0x7F, 7, signed);
  175. subsetCount = 2;
  176. break;
  177. case 2:
  178. r0 = (int)(((low >> 30) & 0x400) | ((low >> 5) & 0x3FF));
  179. g0 = (int)(((low >> 39) & 0x400) | ((low >> 15) & 0x3FF));
  180. b0 = (int)(((low >> 49) & 0x400) | ((low >> 25) & 0x3FF));
  181. if (signed)
  182. {
  183. r0 = SignExtend(r0, 11);
  184. g0 = SignExtend(g0, 11);
  185. b0 = SignExtend(b0, 11);
  186. }
  187. r1 = r0 + SignExtend((int)(low >> 35), 5);
  188. g1 = g0 + SignExtend((int)(low >> 45), 4);
  189. b1 = b0 + SignExtend((int)(low >> 55), 4);
  190. r2 = r0 + SignExtend((int)(high >> 1), 5);
  191. g2 = g0 + SignExtend((int)(low >> 41), 4);
  192. b2 = b0 + SignExtend((int)(((high << 3) & 8) | (low >> 61)), 4);
  193. r3 = r0 + SignExtend((int)(high >> 7), 5);
  194. g3 = g0 + SignExtend((int)(low >> 51), 4);
  195. b3 = b0 + SignExtend((int)(
  196. ((high >> 9) & 8) |
  197. ((high >> 4) & 4) |
  198. ((low >> 59) & 2) |
  199. ((low >> 50) & 1)), 4);
  200. r0 = Unquantize(r0, 11, signed);
  201. g0 = Unquantize(g0, 11, signed);
  202. b0 = Unquantize(b0, 11, signed);
  203. r1 = Unquantize(r1 & 0x7FF, 11, signed);
  204. g1 = Unquantize(g1 & 0x7FF, 11, signed);
  205. b1 = Unquantize(b1 & 0x7FF, 11, signed);
  206. r2 = Unquantize(r2 & 0x7FF, 11, signed);
  207. g2 = Unquantize(g2 & 0x7FF, 11, signed);
  208. b2 = Unquantize(b2 & 0x7FF, 11, signed);
  209. r3 = Unquantize(r3 & 0x7FF, 11, signed);
  210. g3 = Unquantize(g3 & 0x7FF, 11, signed);
  211. b3 = Unquantize(b3 & 0x7FF, 11, signed);
  212. subsetCount = 2;
  213. break;
  214. case 3:
  215. r0 = (int)(low >> 5) & 0x3FF;
  216. g0 = (int)(low >> 15) & 0x3FF;
  217. b0 = (int)(low >> 25) & 0x3FF;
  218. r1 = (int)(low >> 35) & 0x3FF;
  219. g1 = (int)(low >> 45) & 0x3FF;
  220. b1 = (int)(((high << 9) & 0x200) | (low >> 55));
  221. if (signed)
  222. {
  223. r0 = SignExtend(r0, 10);
  224. g0 = SignExtend(g0, 10);
  225. b0 = SignExtend(b0, 10);
  226. r1 = SignExtend(r1, 10);
  227. g1 = SignExtend(g1, 10);
  228. b1 = SignExtend(b1, 10);
  229. }
  230. r0 = Unquantize(r0, 10, signed);
  231. g0 = Unquantize(g0, 10, signed);
  232. b0 = Unquantize(b0, 10, signed);
  233. r1 = Unquantize(r1, 10, signed);
  234. g1 = Unquantize(g1, 10, signed);
  235. b1 = Unquantize(b1, 10, signed);
  236. subsetCount = 1;
  237. break;
  238. case 6:
  239. r0 = (int)(((low >> 29) & 0x400) | ((low >> 5) & 0x3FF));
  240. g0 = (int)(((low >> 40) & 0x400) | ((low >> 15) & 0x3FF));
  241. b0 = (int)(((low >> 49) & 0x400) | ((low >> 25) & 0x3FF));
  242. if (signed)
  243. {
  244. r0 = SignExtend(r0, 11);
  245. g0 = SignExtend(g0, 11);
  246. b0 = SignExtend(b0, 11);
  247. }
  248. r1 = r0 + SignExtend((int)(low >> 35), 4);
  249. g1 = g0 + SignExtend((int)(low >> 45), 5);
  250. b1 = b0 + SignExtend((int)(low >> 55), 4);
  251. r2 = r0 + SignExtend((int)(high >> 1), 4);
  252. g2 = g0 + SignExtend((int)(((high >> 7) & 0x10) | ((low >> 41) & 0x0F)), 5);
  253. b2 = b0 + SignExtend((int)(((high << 3) & 0x08) | ((low >> 61))), 4);
  254. r3 = r0 + SignExtend((int)(high >> 7), 4);
  255. g3 = g0 + SignExtend((int)(((low >> 36) & 0x10) | ((low >> 51) & 0x0F)), 5);
  256. b3 = b0 + SignExtend((int)(
  257. ((high >> 9) & 8) |
  258. ((high >> 4) & 4) |
  259. ((low >> 59) & 2) |
  260. ((high >> 5) & 1)), 4);
  261. r0 = Unquantize(r0, 11, signed);
  262. g0 = Unquantize(g0, 11, signed);
  263. b0 = Unquantize(b0, 11, signed);
  264. r1 = Unquantize(r1 & 0x7FF, 11, signed);
  265. g1 = Unquantize(g1 & 0x7FF, 11, signed);
  266. b1 = Unquantize(b1 & 0x7FF, 11, signed);
  267. r2 = Unquantize(r2 & 0x7FF, 11, signed);
  268. g2 = Unquantize(g2 & 0x7FF, 11, signed);
  269. b2 = Unquantize(b2 & 0x7FF, 11, signed);
  270. r3 = Unquantize(r3 & 0x7FF, 11, signed);
  271. g3 = Unquantize(g3 & 0x7FF, 11, signed);
  272. b3 = Unquantize(b3 & 0x7FF, 11, signed);
  273. subsetCount = 2;
  274. break;
  275. case 7:
  276. r0 = (int)(((low >> 34) & 0x400) | ((low >> 5) & 0x3FF));
  277. g0 = (int)(((low >> 44) & 0x400) | ((low >> 15) & 0x3FF));
  278. b0 = (int)(((high << 10) & 0x400) | ((low >> 25) & 0x3FF));
  279. if (signed)
  280. {
  281. r0 = SignExtend(r0, 11);
  282. g0 = SignExtend(g0, 11);
  283. b0 = SignExtend(b0, 11);
  284. }
  285. r1 = (r0 + SignExtend((int)(low >> 35), 9)) & 0x7FF;
  286. g1 = (g0 + SignExtend((int)(low >> 45), 9)) & 0x7FF;
  287. b1 = (b0 + SignExtend((int)(low >> 55), 9)) & 0x7FF;
  288. r0 = Unquantize(r0, 11, signed);
  289. g0 = Unquantize(g0, 11, signed);
  290. b0 = Unquantize(b0, 11, signed);
  291. r1 = Unquantize(r1, 11, signed);
  292. g1 = Unquantize(g1, 11, signed);
  293. b1 = Unquantize(b1, 11, signed);
  294. subsetCount = 1;
  295. break;
  296. case 10:
  297. r0 = (int)(((low >> 29) & 0x400) | ((low >> 5) & 0x3FF));
  298. g0 = (int)(((low >> 39) & 0x400) | ((low >> 15) & 0x3FF));
  299. b0 = (int)(((low >> 50) & 0x400) | ((low >> 25) & 0x3FF));
  300. if (signed)
  301. {
  302. r0 = SignExtend(r0, 11);
  303. g0 = SignExtend(g0, 11);
  304. b0 = SignExtend(b0, 11);
  305. }
  306. r1 = r0 + SignExtend((int)(low >> 35), 4);
  307. g1 = g0 + SignExtend((int)(low >> 45), 4);
  308. b1 = b0 + SignExtend((int)(low >> 55), 5);
  309. r2 = r0 + SignExtend((int)(high >> 1), 4);
  310. g2 = g0 + SignExtend((int)(low >> 41), 4);
  311. b2 = b0 + SignExtend((int)(((low >> 36) & 0x10) | ((high << 3) & 8) | (low >> 61)), 5);
  312. r3 = r0 + SignExtend((int)(high >> 7), 4);
  313. g3 = g0 + SignExtend((int)(low >> 51), 4);
  314. b3 = b0 + SignExtend((int)(
  315. ((high >> 7) & 0x10) |
  316. ((high >> 9) & 0x08) |
  317. ((high >> 4) & 0x06) |
  318. ((low >> 50) & 0x01)), 5);
  319. r0 = Unquantize(r0, 11, signed);
  320. g0 = Unquantize(g0, 11, signed);
  321. b0 = Unquantize(b0, 11, signed);
  322. r1 = Unquantize(r1 & 0x7FF, 11, signed);
  323. g1 = Unquantize(g1 & 0x7FF, 11, signed);
  324. b1 = Unquantize(b1 & 0x7FF, 11, signed);
  325. r2 = Unquantize(r2 & 0x7FF, 11, signed);
  326. g2 = Unquantize(g2 & 0x7FF, 11, signed);
  327. b2 = Unquantize(b2 & 0x7FF, 11, signed);
  328. r3 = Unquantize(r3 & 0x7FF, 11, signed);
  329. g3 = Unquantize(g3 & 0x7FF, 11, signed);
  330. b3 = Unquantize(b3 & 0x7FF, 11, signed);
  331. subsetCount = 2;
  332. break;
  333. case 11:
  334. r0 = (int)(((low >> 32) & 0x800) | ((low >> 34) & 0x400) | ((low >> 5) & 0x3FF));
  335. g0 = (int)(((low >> 42) & 0x800) | ((low >> 44) & 0x400) | ((low >> 15) & 0x3FF));
  336. b0 = (int)(((low >> 52) & 0x800) | ((high << 10) & 0x400) | ((low >> 25) & 0x3FF));
  337. if (signed)
  338. {
  339. r0 = SignExtend(r0, 12);
  340. g0 = SignExtend(g0, 12);
  341. b0 = SignExtend(b0, 12);
  342. }
  343. r1 = (r0 + SignExtend((int)(low >> 35), 8)) & 0xFFF;
  344. g1 = (g0 + SignExtend((int)(low >> 45), 8)) & 0xFFF;
  345. b1 = (b0 + SignExtend((int)(low >> 55), 8)) & 0xFFF;
  346. r0 = Unquantize(r0, 12, signed);
  347. g0 = Unquantize(g0, 12, signed);
  348. b0 = Unquantize(b0, 12, signed);
  349. r1 = Unquantize(r1, 12, signed);
  350. g1 = Unquantize(g1, 12, signed);
  351. b1 = Unquantize(b1, 12, signed);
  352. subsetCount = 1;
  353. break;
  354. case 14:
  355. r0 = (int)(low >> 5) & 0x1FF;
  356. g0 = (int)(low >> 15) & 0x1FF;
  357. b0 = (int)(low >> 25) & 0x1FF;
  358. if (signed)
  359. {
  360. r0 = SignExtend(r0, 9);
  361. g0 = SignExtend(g0, 9);
  362. b0 = SignExtend(b0, 9);
  363. }
  364. r1 = r0 + SignExtend((int)(low >> 35), 5);
  365. g1 = g0 + SignExtend((int)(low >> 45), 5);
  366. b1 = b0 + SignExtend((int)(low >> 55), 5);
  367. r2 = r0 + SignExtend((int)(high >> 1), 5);
  368. g2 = g0 + SignExtend((int)(((low >> 20) & 0x10) | ((low >> 41) & 0xF)), 5);
  369. b2 = b0 + SignExtend((int)(((low >> 10) & 0x10) | ((high << 3) & 8) | (low >> 61)), 5);
  370. r3 = r0 + SignExtend((int)(high >> 7), 5);
  371. g3 = g0 + SignExtend((int)(((low >> 36) & 0x10) | ((low >> 51) & 0xF)), 5);
  372. b3 = b0 + SignExtend((int)(
  373. ((low >> 30) & 0x10) |
  374. ((high >> 9) & 0x08) |
  375. ((high >> 4) & 0x04) |
  376. ((low >> 59) & 0x02) |
  377. ((low >> 50) & 0x01)), 5);
  378. r0 = Unquantize(r0, 9, signed);
  379. g0 = Unquantize(g0, 9, signed);
  380. b0 = Unquantize(b0, 9, signed);
  381. r1 = Unquantize(r1 & 0x1FF, 9, signed);
  382. g1 = Unquantize(g1 & 0x1FF, 9, signed);
  383. b1 = Unquantize(b1 & 0x1FF, 9, signed);
  384. r2 = Unquantize(r2 & 0x1FF, 9, signed);
  385. g2 = Unquantize(g2 & 0x1FF, 9, signed);
  386. b2 = Unquantize(b2 & 0x1FF, 9, signed);
  387. r3 = Unquantize(r3 & 0x1FF, 9, signed);
  388. g3 = Unquantize(g3 & 0x1FF, 9, signed);
  389. b3 = Unquantize(b3 & 0x1FF, 9, signed);
  390. subsetCount = 2;
  391. break;
  392. case 15:
  393. r0 = (BitReverse6((int)(low >> 39) & 0x3F) << 10) | ((int)(low >> 5) & 0x3FF);
  394. g0 = (BitReverse6((int)(low >> 49) & 0x3F) << 10) | ((int)(low >> 15) & 0x3FF);
  395. b0 = ((BitReverse6((int)(low >> 59)) | (int)(high & 1)) << 10) | ((int)(low >> 25) & 0x3FF);
  396. if (signed)
  397. {
  398. r0 = SignExtend(r0, 16);
  399. g0 = SignExtend(g0, 16);
  400. b0 = SignExtend(b0, 16);
  401. }
  402. r1 = (r0 + SignExtend((int)(low >> 35), 4)) & 0xFFFF;
  403. g1 = (g0 + SignExtend((int)(low >> 45), 4)) & 0xFFFF;
  404. b1 = (b0 + SignExtend((int)(low >> 55), 4)) & 0xFFFF;
  405. subsetCount = 1;
  406. break;
  407. case 18:
  408. r0 = (int)(low >> 5) & 0xFF;
  409. g0 = (int)(low >> 15) & 0xFF;
  410. b0 = (int)(low >> 25) & 0xFF;
  411. if (signed)
  412. {
  413. r0 = SignExtend(r0, 8);
  414. g0 = SignExtend(g0, 8);
  415. b0 = SignExtend(b0, 8);
  416. }
  417. r1 = r0 + SignExtend((int)(low >> 35), 6);
  418. g1 = g0 + SignExtend((int)(low >> 45), 5);
  419. b1 = b0 + SignExtend((int)(low >> 55), 5);
  420. r2 = r0 + SignExtend((int)(high >> 1), 6);
  421. g2 = g0 + SignExtend((int)(((low >> 20) & 0x10) | ((low >> 41) & 0xF)), 5);
  422. b2 = b0 + SignExtend((int)(((low >> 10) & 0x10) | ((high << 3) & 8) | (low >> 61)), 5);
  423. r3 = r0 + SignExtend((int)(high >> 7), 6);
  424. g3 = g0 + SignExtend((int)(((low >> 9) & 0x10) | ((low >> 51) & 0xF)), 5);
  425. b3 = b0 + SignExtend((int)(
  426. ((low >> 30) & 0x18) |
  427. ((low >> 21) & 0x04) |
  428. ((low >> 59) & 0x02) |
  429. ((low >> 50) & 0x01)), 5);
  430. r0 = Unquantize(r0, 8, signed);
  431. g0 = Unquantize(g0, 8, signed);
  432. b0 = Unquantize(b0, 8, signed);
  433. r1 = Unquantize(r1 & 0xFF, 8, signed);
  434. g1 = Unquantize(g1 & 0xFF, 8, signed);
  435. b1 = Unquantize(b1 & 0xFF, 8, signed);
  436. r2 = Unquantize(r2 & 0xFF, 8, signed);
  437. g2 = Unquantize(g2 & 0xFF, 8, signed);
  438. b2 = Unquantize(b2 & 0xFF, 8, signed);
  439. r3 = Unquantize(r3 & 0xFF, 8, signed);
  440. g3 = Unquantize(g3 & 0xFF, 8, signed);
  441. b3 = Unquantize(b3 & 0xFF, 8, signed);
  442. subsetCount = 2;
  443. break;
  444. case 22:
  445. r0 = (int)(low >> 5) & 0xFF;
  446. g0 = (int)(low >> 15) & 0xFF;
  447. b0 = (int)(low >> 25) & 0xFF;
  448. if (signed)
  449. {
  450. r0 = SignExtend(r0, 8);
  451. g0 = SignExtend(g0, 8);
  452. b0 = SignExtend(b0, 8);
  453. }
  454. r1 = r0 + SignExtend((int)(low >> 35), 5);
  455. g1 = g0 + SignExtend((int)(low >> 45), 6);
  456. b1 = b0 + SignExtend((int)(low >> 55), 5);
  457. r2 = r0 + SignExtend((int)(high >> 1), 5);
  458. g2 = g0 + SignExtend((int)(((low >> 18) & 0x20) | ((low >> 20) & 0x10) | ((low >> 41) & 0xF)), 6);
  459. b2 = b0 + SignExtend((int)(((low >> 10) & 0x10) | ((high << 3) & 0x08) | (low >> 61)), 5);
  460. r3 = r0 + SignExtend((int)(high >> 7), 5);
  461. g3 = g0 + SignExtend((int)(((low >> 28) & 0x20) | ((low >> 36) & 0x10) | ((low >> 51) & 0x0F)), 6);
  462. b3 = b0 + SignExtend((int)(
  463. ((low >> 30) & 0x10) |
  464. ((high >> 9) & 0x08) |
  465. ((high >> 4) & 0x04) |
  466. ((low >> 59) & 0x02) |
  467. ((low >> 13) & 0x01)), 5);
  468. r0 = Unquantize(r0, 8, signed);
  469. g0 = Unquantize(g0, 8, signed);
  470. b0 = Unquantize(b0, 8, signed);
  471. r1 = Unquantize(r1 & 0xFF, 8, signed);
  472. g1 = Unquantize(g1 & 0xFF, 8, signed);
  473. b1 = Unquantize(b1 & 0xFF, 8, signed);
  474. r2 = Unquantize(r2 & 0xFF, 8, signed);
  475. g2 = Unquantize(g2 & 0xFF, 8, signed);
  476. b2 = Unquantize(b2 & 0xFF, 8, signed);
  477. r3 = Unquantize(r3 & 0xFF, 8, signed);
  478. g3 = Unquantize(g3 & 0xFF, 8, signed);
  479. b3 = Unquantize(b3 & 0xFF, 8, signed);
  480. subsetCount = 2;
  481. break;
  482. case 26:
  483. r0 = (int)(low >> 5) & 0xFF;
  484. g0 = (int)(low >> 15) & 0xFF;
  485. b0 = (int)(low >> 25) & 0xFF;
  486. if (signed)
  487. {
  488. r0 = SignExtend(r0, 8);
  489. g0 = SignExtend(g0, 8);
  490. b0 = SignExtend(b0, 8);
  491. }
  492. r1 = r0 + SignExtend((int)(low >> 35), 5);
  493. g1 = g0 + SignExtend((int)(low >> 45), 5);
  494. b1 = b0 + SignExtend((int)(low >> 55), 6);
  495. r2 = r0 + SignExtend((int)(high >> 1), 5);
  496. g2 = g0 + SignExtend((int)(((low >> 20) & 0x10) | ((low >> 41) & 0xF)), 5);
  497. b2 = b0 + SignExtend((int)(
  498. ((low >> 18) & 0x20) |
  499. ((low >> 10) & 0x10) |
  500. ((high << 3) & 0x08) |
  501. (low >> 61)), 6);
  502. r3 = r0 + SignExtend((int)(high >> 7), 5);
  503. g3 = g0 + SignExtend((int)(((low >> 36) & 0x10) | ((low >> 51) & 0xF)), 5);
  504. b3 = b0 + SignExtend((int)(
  505. ((low >> 28) & 0x20) |
  506. ((low >> 30) & 0x10) |
  507. ((high >> 9) & 0x08) |
  508. ((high >> 4) & 0x04) |
  509. ((low >> 12) & 0x02) |
  510. ((low >> 50) & 0x01)), 6);
  511. r0 = Unquantize(r0, 8, signed);
  512. g0 = Unquantize(g0, 8, signed);
  513. b0 = Unquantize(b0, 8, signed);
  514. r1 = Unquantize(r1 & 0xFF, 8, signed);
  515. g1 = Unquantize(g1 & 0xFF, 8, signed);
  516. b1 = Unquantize(b1 & 0xFF, 8, signed);
  517. r2 = Unquantize(r2 & 0xFF, 8, signed);
  518. g2 = Unquantize(g2 & 0xFF, 8, signed);
  519. b2 = Unquantize(b2 & 0xFF, 8, signed);
  520. r3 = Unquantize(r3 & 0xFF, 8, signed);
  521. g3 = Unquantize(g3 & 0xFF, 8, signed);
  522. b3 = Unquantize(b3 & 0xFF, 8, signed);
  523. subsetCount = 2;
  524. break;
  525. case 30:
  526. r0 = (int)(low >> 5) & 0x3F;
  527. g0 = (int)(low >> 15) & 0x3F;
  528. b0 = (int)(low >> 25) & 0x3F;
  529. r1 = (int)(low >> 35) & 0x3F;
  530. g1 = (int)(low >> 45) & 0x3F;
  531. b1 = (int)(low >> 55) & 0x3F;
  532. r2 = (int)(high >> 1) & 0x3F;
  533. g2 = (int)(((low >> 16) & 0x20) | ((low >> 20) & 0x10) | ((low >> 41) & 0xF));
  534. b2 = (int)(((low >> 17) & 0x20) | ((low >> 10) & 0x10) | ((high << 3) & 0x08) | (low >> 61));
  535. r3 = (int)(high >> 7) & 0x3F;
  536. g3 = (int)(((low >> 26) & 0x20) | ((low >> 7) & 0x10) | ((low >> 51) & 0xF));
  537. b3 = (int)(
  538. ((low >> 28) & 0x20) |
  539. ((low >> 30) & 0x10) |
  540. ((low >> 29) & 0x08) |
  541. ((low >> 21) & 0x04) |
  542. ((low >> 12) & 0x03));
  543. if (signed)
  544. {
  545. r0 = SignExtend(r0, 6);
  546. g0 = SignExtend(g0, 6);
  547. b0 = SignExtend(b0, 6);
  548. r1 = SignExtend(r1, 6);
  549. g1 = SignExtend(g1, 6);
  550. b1 = SignExtend(b1, 6);
  551. r2 = SignExtend(r2, 6);
  552. g2 = SignExtend(g2, 6);
  553. b2 = SignExtend(b2, 6);
  554. r3 = SignExtend(r3, 6);
  555. g3 = SignExtend(g3, 6);
  556. b3 = SignExtend(b3, 6);
  557. }
  558. r0 = Unquantize(r0, 6, signed);
  559. g0 = Unquantize(g0, 6, signed);
  560. b0 = Unquantize(b0, 6, signed);
  561. r1 = Unquantize(r1, 6, signed);
  562. g1 = Unquantize(g1, 6, signed);
  563. b1 = Unquantize(b1, 6, signed);
  564. r2 = Unquantize(r2, 6, signed);
  565. g2 = Unquantize(g2, 6, signed);
  566. b2 = Unquantize(b2, 6, signed);
  567. r3 = Unquantize(r3, 6, signed);
  568. g3 = Unquantize(g3, 6, signed);
  569. b3 = Unquantize(b3, 6, signed);
  570. subsetCount = 2;
  571. break;
  572. default:
  573. subsetCount = 0;
  574. break;
  575. }
  576. if (subsetCount > 0)
  577. {
  578. endPoints[0] = new RgbaColor32(r0, g0, b0, HalfOne);
  579. endPoints[1] = new RgbaColor32(r1, g1, b1, HalfOne);
  580. if (subsetCount > 1)
  581. {
  582. endPoints[2] = new RgbaColor32(r2, g2, b2, HalfOne);
  583. endPoints[3] = new RgbaColor32(r3, g3, b3, HalfOne);
  584. }
  585. }
  586. return subsetCount;
  587. }
  588. private static int SignExtend(int value, int bits)
  589. {
  590. int shift = 32 - bits;
  591. return (value << shift) >> shift;
  592. }
  593. private static int Unquantize(int value, int bits, bool signed)
  594. {
  595. if (signed)
  596. {
  597. if (bits >= 16)
  598. {
  599. return value;
  600. }
  601. else
  602. {
  603. bool sign = value < 0;
  604. if (sign)
  605. {
  606. value = -value;
  607. }
  608. if (value == 0)
  609. {
  610. return value;
  611. }
  612. else if (value >= ((1 << (bits - 1)) - 1))
  613. {
  614. value = 0x7FFF;
  615. }
  616. else
  617. {
  618. value = ((value << 15) + 0x4000) >> (bits - 1);
  619. }
  620. if (sign)
  621. {
  622. value = -value;
  623. }
  624. }
  625. }
  626. else
  627. {
  628. if (bits >= 15 || value == 0)
  629. {
  630. return value;
  631. }
  632. else if (value == ((1 << bits) - 1))
  633. {
  634. return 0xFFFF;
  635. }
  636. else
  637. {
  638. return ((value << 16) + 0x8000) >> bits;
  639. }
  640. }
  641. return value;
  642. }
  643. private static ushort FinishUnquantize(int value, bool signed)
  644. {
  645. if (signed)
  646. {
  647. value = value < 0 ? -((-value * 31) >> 5) : (value * 31) >> 5;
  648. int sign = 0;
  649. if (value < 0)
  650. {
  651. sign = 0x8000;
  652. value = -value;
  653. }
  654. return (ushort)(sign | value);
  655. }
  656. else
  657. {
  658. return (ushort)((value * 31) >> 6);
  659. }
  660. }
  661. private static int BitReverse6(int value)
  662. {
  663. value = ((value >> 1) & 0x55) | ((value << 1) & 0xaa);
  664. value = ((value >> 2) & 0x33) | ((value << 2) & 0xcc);
  665. value = ((value >> 4) & 0x0f) | ((value << 4) & 0xf0);
  666. return value >> 2;
  667. }
  668. }
  669. }