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