OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkTextureCompressor_ASTC.h" | 8 #include "SkTextureCompressor_ASTC.h" |
9 #include "SkTextureCompressor_Blitter.h" | 9 #include "SkTextureCompressor_Blitter.h" |
10 | 10 |
11 #include "SkBlitter.h" | 11 #include "SkBlitter.h" |
12 #include "SkEndian.h" | 12 #include "SkEndian.h" |
| 13 #include "SkMath.h" |
13 | 14 |
14 // This table contains the weight values for each texel. This is used in determi
ning | 15 // This table contains the weight values for each texel. This is used in determi
ning |
15 // how to convert a 12x12 grid of alpha values into a 6x5 grid of index values.
Since | 16 // how to convert a 12x12 grid of alpha values into a 6x5 grid of index values.
Since |
16 // we have a 6x5 grid, that gives 30 values that we have to compute. For each in
dex, | 17 // we have a 6x5 grid, that gives 30 values that we have to compute. For each in
dex, |
17 // we store up to 20 different triplets of values. In order the triplets are: | 18 // we store up to 20 different triplets of values. In order the triplets are: |
18 // weight, texel-x, texel-y | 19 // weight, texel-x, texel-y |
19 // The weight value corresponds to the amount that this index contributes to the
final | 20 // The weight value corresponds to the amount that this index contributes to the
final |
20 // index value of the given texel. Hence, we need to reconstruct the 6x5 index g
rid | 21 // index value of the given texel. Hence, we need to reconstruct the 6x5 index g
rid |
21 // from their relative contribution to the 12x12 texel grid. | 22 // from their relative contribution to the 12x12 texel grid. |
22 // | 23 // |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 top = top ^ t ^ (t << 2); | 255 top = top ^ t ^ (t << 2); |
255 | 256 |
256 send_packing(dst, SkEndian_SwapLE64(top), SkEndian_SwapLE64(bottom)); | 257 send_packing(dst, SkEndian_SwapLE64(top), SkEndian_SwapLE64(bottom)); |
257 } | 258 } |
258 | 259 |
259 inline void CompressA8ASTCBlockVertical(uint8_t* dst, const uint8_t* src) { | 260 inline void CompressA8ASTCBlockVertical(uint8_t* dst, const uint8_t* src) { |
260 compress_a8_astc_block<GetAlphaTranspose>(&dst, src, 12); | 261 compress_a8_astc_block<GetAlphaTranspose>(&dst, src, 12); |
261 } | 262 } |
262 | 263 |
263 //////////////////////////////////////////////////////////////////////////////// | 264 //////////////////////////////////////////////////////////////////////////////// |
| 265 // |
| 266 // ASTC Decoder |
| 267 // |
| 268 // Full details available in the spec: |
| 269 // http://www.khronos.org/registry/gles/extensions/OES/OES_texture_compression_a
stc.txt |
| 270 // |
| 271 //////////////////////////////////////////////////////////////////////////////// |
| 272 |
| 273 // Enable this to assert whenever a decoded block has invalid ASTC values. Other
wise, |
| 274 // each invalid block will result in a disgusting magenta color. |
| 275 #define ASSERT_ASTC_DECODE_ERROR 0 |
| 276 |
| 277 // Reverse 64-bit integer taken from TAOCP 4a, although it's better |
| 278 // documented at this site: |
| 279 // http://matthewarcus.wordpress.com/2012/11/18/reversing-a-64-bit-word/ |
| 280 |
| 281 template <typename T, T m, int k> |
| 282 static inline T swap_bits(T p) { |
| 283 T q = ((p>>k)^p) & m; |
| 284 return p^q^(q<<k); |
| 285 } |
| 286 |
| 287 static inline uint64_t reverse64(uint64_t n) { |
| 288 static const uint64_t m0 = 0x5555555555555555LLU; |
| 289 static const uint64_t m1 = 0x0300c0303030c303LLU; |
| 290 static const uint64_t m2 = 0x00c0300c03f0003fLLU; |
| 291 static const uint64_t m3 = 0x00000ffc00003fffLLU; |
| 292 n = ((n>>1)&m0) | (n&m0)<<1; |
| 293 n = swap_bits<uint64_t, m1, 4>(n); |
| 294 n = swap_bits<uint64_t, m2, 8>(n); |
| 295 n = swap_bits<uint64_t, m3, 20>(n); |
| 296 n = (n >> 34) | (n << 30); |
| 297 return n; |
| 298 } |
| 299 |
| 300 // An ASTC block is 128 bits. We represent it as two 64-bit integers in order |
| 301 // to efficiently operate on the block using bitwise operations. |
| 302 struct ASTCBlock { |
| 303 uint64_t fLow; |
| 304 uint64_t fHigh; |
| 305 |
| 306 // Reverses the bits of an ASTC block, making the LSB of the |
| 307 // 128 bit block the MSB. |
| 308 inline void reverse() { |
| 309 const uint64_t newLow = reverse64(this->fHigh); |
| 310 this->fHigh = reverse64(this->fLow); |
| 311 this->fLow = newLow; |
| 312 } |
| 313 }; |
| 314 |
| 315 // Writes the given color to every pixel in the block. This is used by void-exte
nt |
| 316 // blocks (a special constant-color encoding of a block) and by the error functi
on. |
| 317 static inline void write_constant_color(uint8_t* dst, int blockDimX, int blockDi
mY, |
| 318 int dstRowBytes, SkColor color) { |
| 319 for (int y = 0; y < blockDimY; ++y) { |
| 320 SkColor *dstColors = reinterpret_cast<SkColor*>(dst); |
| 321 for (int x = 0; x < blockDimX; ++x) { |
| 322 dstColors[x] = color; |
| 323 } |
| 324 dst += dstRowBytes; |
| 325 } |
| 326 } |
| 327 |
| 328 // Sets the entire block to the ASTC "error" color, a disgusting magenta |
| 329 // that's not supposed to appear in natural images. |
| 330 static inline void write_error_color(uint8_t* dst, int blockDimX, int blockDimY, |
| 331 int dstRowBytes) { |
| 332 static const SkColor kASTCErrorColor = SkColorSetRGB(0xFF, 0, 0xFF); |
| 333 |
| 334 #if ASSERT_ASTC_DECODE_ERROR |
| 335 SkDEBUGFAIL("ASTC decoding error!\n"); |
| 336 #endif |
| 337 |
| 338 write_constant_color(dst, blockDimX, blockDimY, dstRowBytes, kASTCErrorColor
); |
| 339 } |
| 340 |
| 341 // Reads up to 64 bits of the ASTC block starting from bit |
| 342 // 'from' and going up to but not including bit 'to'. 'from' starts |
| 343 // counting from the LSB, counting up to the MSB. Returns -1 on |
| 344 // error. |
| 345 static uint64_t read_astc_bits(const ASTCBlock &block, int from, int to) { |
| 346 SkASSERT(0 <= from && from <= 128); |
| 347 SkASSERT(0 <= to && to <= 128); |
| 348 |
| 349 const int nBits = to - from; |
| 350 if (0 == nBits) { |
| 351 return 0; |
| 352 } |
| 353 |
| 354 if (nBits < 0 || 64 <= nBits) { |
| 355 SkDEBUGFAIL("ASTC -- shouldn't read more than 64 bits"); |
| 356 return -1; |
| 357 } |
| 358 |
| 359 // Remember, the 'to' bit isn't read. |
| 360 uint64_t result = 0; |
| 361 if (to <= 64) { |
| 362 // All desired bits are in the low 64-bits. |
| 363 result = (block.fLow >> from) & ((1ULL << nBits) - 1); |
| 364 } else if (from >= 64) { |
| 365 // All desired bits are in the high 64-bits. |
| 366 result = (block.fHigh >> (from - 64)) & ((1ULL << nBits) - 1); |
| 367 } else { |
| 368 // from < 64 && to > 64 |
| 369 SkASSERT(nBits > (64 - from)); |
| 370 const int nLow = 64 - from; |
| 371 const int nHigh = nBits - nLow; |
| 372 result = |
| 373 ((block.fLow >> from) & ((1ULL << nLow) - 1)) | |
| 374 ((block.fHigh & ((1ULL << nHigh) - 1)) << nLow); |
| 375 } |
| 376 |
| 377 return result; |
| 378 } |
| 379 |
| 380 // Returns the number of bits needed to represent a number |
| 381 // in the given power-of-two range (excluding the power of two itself). |
| 382 static inline int bits_for_range(int x) { |
| 383 SkASSERT(SkIsPow2(x)); |
| 384 SkASSERT(0 != x); |
| 385 // Since we know it's a power of two, there should only be one bit set, |
| 386 // meaning the number of trailing zeros is 31 minus the number of leading |
| 387 // zeros. |
| 388 return 31 - SkCLZ(x); |
| 389 } |
| 390 |
| 391 // Clamps an integer to the range [0, 255] |
| 392 static inline int clamp_byte(int x) { |
| 393 return SkClampMax(x, 255); |
| 394 } |
| 395 |
| 396 // Helper function defined in the ASTC spec, section C.2.14 |
| 397 // It transfers a few bits of precision from one value to another. |
| 398 static inline void bit_transfer_signed(int *a, int *b) { |
| 399 *b >>= 1; |
| 400 *b |= *a & 0x80; |
| 401 *a >>= 1; |
| 402 *a &= 0x3F; |
| 403 if ( (*a & 0x20) != 0 ) { |
| 404 *a -= 0x40; |
| 405 } |
| 406 } |
| 407 |
| 408 // Helper function defined in the ASTC spec, section C.2.14 |
| 409 // It uses the value in the blue channel to tint the red and green |
| 410 static inline SkColor blue_contract(int a, int r, int g, int b) { |
| 411 return SkColorSetARGB(a, (r + b) >> 1, (g + b) >> 1, b); |
| 412 } |
| 413 |
| 414 // Helper function that decodes two colors from eight values. If isRGB is true, |
| 415 // then the pointer 'v' contains six values and the last two are considered to b
e |
| 416 // 0xFF. If isRGB is false, then all eight values come from the pointer 'v'. Thi
s |
| 417 // corresponds to the decode procedure for the following endpoint modes: |
| 418 // kLDR_RGB_Direct_ColorEndpointMode |
| 419 // kLDR_RGBA_Direct_ColorEndpointMode |
| 420 static inline void decode_rgba_direct(const int *v, SkColor *endpoints, bool isR
GB) { |
| 421 |
| 422 int v6 = 0xFF; |
| 423 int v7 = 0xFF; |
| 424 if (!isRGB) { |
| 425 v6 = v[6]; |
| 426 v7 = v[7]; |
| 427 } |
| 428 |
| 429 const int s0 = v[0] + v[2] + v[4]; |
| 430 const int s1 = v[1] + v[3] + v[5]; |
| 431 |
| 432 if (s1 >= s0) { |
| 433 endpoints[0] = SkColorSetARGB(v6, v[0], v[2], v[4]); |
| 434 endpoints[1] = SkColorSetARGB(v7, v[1], v[3], v[5]); |
| 435 } else { |
| 436 endpoints[0] = blue_contract(v7, v[1], v[3], v[5]); |
| 437 endpoints[1] = blue_contract(v6, v[0], v[2], v[4]); |
| 438 } |
| 439 } |
| 440 |
| 441 // Helper function that decodes two colors from six values. If isRGB is true, |
| 442 // then the pointer 'v' contains four values and the last two are considered to
be |
| 443 // 0xFF. If isRGB is false, then all six values come from the pointer 'v'. This |
| 444 // corresponds to the decode procedure for the following endpoint modes: |
| 445 // kLDR_RGB_BaseScale_ColorEndpointMode |
| 446 // kLDR_RGB_BaseScaleWithAlpha_ColorEndpointMode |
| 447 static inline void decode_rgba_basescale(const int *v, SkColor *endpoints, bool
isRGB) { |
| 448 |
| 449 int v4 = 0xFF; |
| 450 int v5 = 0xFF; |
| 451 if (!isRGB) { |
| 452 v4 = v[4]; |
| 453 v5 = v[5]; |
| 454 } |
| 455 |
| 456 endpoints[0] = SkColorSetARGB(v4, |
| 457 (v[0]*v[3]) >> 8, |
| 458 (v[1]*v[3]) >> 8, |
| 459 (v[2]*v[3]) >> 8); |
| 460 endpoints[1] = SkColorSetARGB(v5, v[0], v[1], v[2]); |
| 461 } |
| 462 |
| 463 // Helper function that decodes two colors from eight values. If isRGB is true, |
| 464 // then the pointer 'v' contains six values and the last two are considered to b
e |
| 465 // 0xFF. If isRGB is false, then all eight values come from the pointer 'v'. Thi
s |
| 466 // corresponds to the decode procedure for the following endpoint modes: |
| 467 // kLDR_RGB_BaseOffset_ColorEndpointMode |
| 468 // kLDR_RGBA_BaseOffset_ColorEndpointMode |
| 469 // |
| 470 // If isRGB is true, then treat this as if v6 and v7 are meant to encode full al
pha values. |
| 471 static inline void decode_rgba_baseoffset(const int *v, SkColor *endpoints, bool
isRGB) { |
| 472 int v0 = v[0]; |
| 473 int v1 = v[1]; |
| 474 int v2 = v[2]; |
| 475 int v3 = v[3]; |
| 476 int v4 = v[4]; |
| 477 int v5 = v[5]; |
| 478 int v6 = isRGB ? 0xFF : v[6]; |
| 479 // The 0 is here because this is an offset, not a direct value |
| 480 int v7 = isRGB ? 0 : v[7]; |
| 481 |
| 482 bit_transfer_signed(&v1, &v0); |
| 483 bit_transfer_signed(&v3, &v2); |
| 484 bit_transfer_signed(&v5, &v4); |
| 485 if (!isRGB) { |
| 486 bit_transfer_signed(&v7, &v6); |
| 487 } |
| 488 |
| 489 int c[2][4]; |
| 490 if ((v1 + v3 + v5) >= 0) { |
| 491 c[0][0] = v6; |
| 492 c[0][1] = v0; |
| 493 c[0][2] = v2; |
| 494 c[0][3] = v4; |
| 495 |
| 496 c[1][0] = v6 + v7; |
| 497 c[1][1] = v0 + v1; |
| 498 c[1][2] = v2 + v3; |
| 499 c[1][3] = v4 + v5; |
| 500 } else { |
| 501 c[0][0] = v6 + v7; |
| 502 c[0][1] = (v0 + v1 + v4 + v5) >> 1; |
| 503 c[0][2] = (v2 + v3 + v4 + v5) >> 1; |
| 504 c[0][3] = v4 + v5; |
| 505 |
| 506 c[1][0] = v6; |
| 507 c[1][1] = (v0 + v4) >> 1; |
| 508 c[1][2] = (v2 + v4) >> 1; |
| 509 c[1][3] = v4; |
| 510 } |
| 511 |
| 512 endpoints[0] = SkColorSetARGB(clamp_byte(c[0][0]), |
| 513 clamp_byte(c[0][1]), |
| 514 clamp_byte(c[0][2]), |
| 515 clamp_byte(c[0][3])); |
| 516 |
| 517 endpoints[1] = SkColorSetARGB(clamp_byte(c[1][0]), |
| 518 clamp_byte(c[1][1]), |
| 519 clamp_byte(c[1][2]), |
| 520 clamp_byte(c[1][3])); |
| 521 } |
| 522 |
| 523 |
| 524 // A helper class used to decode bit values from standard integer values. |
| 525 // We can't use this class with ASTCBlock because then it would need to |
| 526 // handle multi-value ranges, and it's non-trivial to lookup a range of bits |
| 527 // that splits across two different ints. |
| 528 template <typename T> |
| 529 class SkTBits { |
| 530 public: |
| 531 SkTBits(const T val) : fVal(val) { } |
| 532 |
| 533 // Returns the bit at the given position |
| 534 T operator [](const int idx) const { |
| 535 return (fVal >> idx) & 1; |
| 536 } |
| 537 |
| 538 // Returns the bits in the given range, inclusive |
| 539 T operator ()(const int end, const int start) const { |
| 540 SkASSERT(end >= start); |
| 541 return (fVal >> start) & ((1ULL << ((end - start) + 1)) - 1); |
| 542 } |
| 543 |
| 544 private: |
| 545 const T fVal; |
| 546 }; |
| 547 |
| 548 // This algorithm matches the trit block decoding in the spec (Table C.2.14) |
| 549 static void decode_trit_block(int* dst, int nBits, const uint64_t &block) { |
| 550 |
| 551 SkTBits<uint64_t> blockBits(block); |
| 552 |
| 553 // According to the spec, a trit block, which contains five values, |
| 554 // has the following layout: |
| 555 // |
| 556 // 27 26 25 24 23 22 21 20 19 18 17 16 |
| 557 // ----------------------------------------------- |
| 558 // |T7 | m4 |T6 T5 | m3 |T4 | |
| 559 // ----------------------------------------------- |
| 560 // |
| 561 // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 |
| 562 // -------------------------------------------------------------- |
| 563 // | m2 |T3 T2 | m1 |T1 T0 | m0 | |
| 564 // -------------------------------------------------------------- |
| 565 // |
| 566 // Where the m's are variable width depending on the number of bits used |
| 567 // to encode the values (anywhere from 0 to 6). Since 3^5 = 243, the extra |
| 568 // byte labeled T (whose bits are interleaved where 0 is the LSB and 7 is |
| 569 // the MSB), contains five trit values. To decode the trit values, the spec |
| 570 // says that we need to follow the following algorithm: |
| 571 // |
| 572 // if T[4:2] = 111 |
| 573 // C = { T[7:5], T[1:0] }; t4 = t3 = 2 |
| 574 // else |
| 575 // C = T[4:0] |
| 576 // |
| 577 // if T[6:5] = 11 |
| 578 // t4 = 2; t3 = T[7] |
| 579 // else |
| 580 // t4 = T[7]; t3 = T[6:5] |
| 581 // |
| 582 // if C[1:0] = 11 |
| 583 // t2 = 2; t1 = C[4]; t0 = { C[3], C[2]&~C[3] } |
| 584 // else if C[3:2] = 11 |
| 585 // t2 = 2; t1 = 2; t0 = C[1:0] |
| 586 // else |
| 587 // t2 = C[4]; t1 = C[3:2]; t0 = { C[1], C[0]&~C[1] } |
| 588 // |
| 589 // The following C++ code is meant to mirror this layout and algorithm as |
| 590 // closely as possible. |
| 591 |
| 592 int m[5]; |
| 593 if (0 == nBits) { |
| 594 memset(m, 0, sizeof(m)); |
| 595 } else { |
| 596 SkASSERT(nBits < 8); |
| 597 m[0] = static_cast<int>(blockBits(nBits - 1, 0)); |
| 598 m[1] = static_cast<int>(blockBits(2*nBits - 1 + 2, nBits + 2)); |
| 599 m[2] = static_cast<int>(blockBits(3*nBits - 1 + 4, 2*nBits + 4)); |
| 600 m[3] = static_cast<int>(blockBits(4*nBits - 1 + 5, 3*nBits + 5)); |
| 601 m[4] = static_cast<int>(blockBits(5*nBits - 1 + 7, 4*nBits + 7)); |
| 602 } |
| 603 |
| 604 int T = |
| 605 static_cast<int>(blockBits(nBits + 1, nBits)) | |
| 606 (static_cast<int>(blockBits(2*nBits + 2 + 1, 2*nBits + 2)) << 2) | |
| 607 (static_cast<int>(blockBits[3*nBits + 4] << 4)) | |
| 608 (static_cast<int>(blockBits(4*nBits + 5 + 1, 4*nBits + 5)) << 5) | |
| 609 (static_cast<int>(blockBits[5*nBits + 7] << 7)); |
| 610 |
| 611 int t[5]; |
| 612 |
| 613 int C; |
| 614 SkTBits<int> Tbits(T); |
| 615 if (0x7 == Tbits(4, 2)) { |
| 616 C = (Tbits(7, 5) << 2) | Tbits(1, 0); |
| 617 t[3] = t[4] = 2; |
| 618 } else { |
| 619 C = Tbits(4, 0); |
| 620 if (Tbits(6, 5) == 0x3) { |
| 621 t[4] = 2; t[3] = Tbits[7]; |
| 622 } else { |
| 623 t[4] = Tbits[7]; t[3] = Tbits(6, 5); |
| 624 } |
| 625 } |
| 626 |
| 627 SkTBits<int> Cbits(C); |
| 628 if (Cbits(1, 0) == 0x3) { |
| 629 t[2] = 2; |
| 630 t[1] = Cbits[4]; |
| 631 t[0] = (Cbits[3] << 1) | (Cbits[2] & (0x1 & ~(Cbits[3]))); |
| 632 } else if (Cbits(3, 2) == 0x3) { |
| 633 t[2] = 2; |
| 634 t[1] = 2; |
| 635 t[0] = Cbits(1, 0); |
| 636 } else { |
| 637 t[2] = Cbits[4]; |
| 638 t[1] = Cbits(3, 2); |
| 639 t[0] = (Cbits[1] << 1) | (Cbits[0] & (0x1 & ~(Cbits[1]))); |
| 640 } |
| 641 |
| 642 #ifdef SK_DEBUG |
| 643 // Make sure all of the decoded values have a trit less than three |
| 644 // and a bit value within the range of the allocated bits. |
| 645 for (int i = 0; i < 5; ++i) { |
| 646 SkASSERT(t[i] < 3); |
| 647 SkASSERT(m[i] < (1 << nBits)); |
| 648 } |
| 649 #endif |
| 650 |
| 651 for (int i = 0; i < 5; ++i) { |
| 652 *dst = (t[i] << nBits) + m[i]; |
| 653 ++dst; |
| 654 } |
| 655 } |
| 656 |
| 657 // This algorithm matches the quint block decoding in the spec (Table C.2.15) |
| 658 static void decode_quint_block(int* dst, int nBits, const uint64_t &block) { |
| 659 SkTBits<uint64_t> blockBits(block); |
| 660 |
| 661 // According to the spec, a quint block, which contains three values, |
| 662 // has the following layout: |
| 663 // |
| 664 // |
| 665 // 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 |
| 666 // ------------------------------------------------------------------------
-- |
| 667 // |Q6 Q5 | m2 |Q4 Q3 | m1 |Q2 Q1 Q0 | m0
| |
| 668 // ------------------------------------------------------------------------
-- |
| 669 // |
| 670 // Where the m's are variable width depending on the number of bits used |
| 671 // to encode the values (anywhere from 0 to 4). Since 5^3 = 125, the extra |
| 672 // 7-bit value labeled Q (whose bits are interleaved where 0 is the LSB and
6 is |
| 673 // the MSB), contains three quint values. To decode the quint values, the sp
ec |
| 674 // says that we need to follow the following algorithm: |
| 675 // |
| 676 // if Q[2:1] = 11 and Q[6:5] = 00 |
| 677 // q2 = { Q[0], Q[4]&~Q[0], Q[3]&~Q[0] }; q1 = q0 = 4 |
| 678 // else |
| 679 // if Q[2:1] = 11 |
| 680 // q2 = 4; C = { Q[4:3], ~Q[6:5], Q[0] } |
| 681 // else |
| 682 // q2 = T[6:5]; C = Q[4:0] |
| 683 // |
| 684 // if C[2:0] = 101 |
| 685 // q1 = 4; q0 = C[4:3] |
| 686 // else |
| 687 // q1 = C[4:3]; q0 = C[2:0] |
| 688 // |
| 689 // The following C++ code is meant to mirror this layout and algorithm as |
| 690 // closely as possible. |
| 691 |
| 692 int m[3]; |
| 693 if (0 == nBits) { |
| 694 memset(m, 0, sizeof(m)); |
| 695 } else { |
| 696 SkASSERT(nBits < 8); |
| 697 m[0] = static_cast<int>(blockBits(nBits - 1, 0)); |
| 698 m[1] = static_cast<int>(blockBits(2*nBits - 1 + 3, nBits + 3)); |
| 699 m[2] = static_cast<int>(blockBits(3*nBits - 1 + 5, 2*nBits + 5)); |
| 700 } |
| 701 |
| 702 int Q = |
| 703 static_cast<int>(blockBits(nBits + 2, nBits)) | |
| 704 (static_cast<int>(blockBits(2*nBits + 3 + 1, 2*nBits + 3)) << 3) | |
| 705 (static_cast<int>(blockBits(3*nBits + 5 + 1, 3*nBits + 5)) << 5); |
| 706 |
| 707 int q[3]; |
| 708 SkTBits<int> Qbits(Q); // quantum? |
| 709 |
| 710 if (Qbits(2, 1) == 0x3 && Qbits(6, 5) == 0) { |
| 711 const int notBitZero = (0x1 & ~(Qbits[0])); |
| 712 q[2] = (Qbits[0] << 2) | ((Qbits[4] & notBitZero) << 1) | (Qbits[3] & no
tBitZero); |
| 713 q[1] = 4; |
| 714 q[0] = 4; |
| 715 } else { |
| 716 int C; |
| 717 if (Qbits(2, 1) == 0x3) { |
| 718 q[2] = 4; |
| 719 C = (Qbits(4, 3) << 3) | ((0x3 & ~(Qbits(6, 5))) << 1) | Qbits[0]; |
| 720 } else { |
| 721 q[2] = Qbits(6, 5); |
| 722 C = Qbits(4, 0); |
| 723 } |
| 724 |
| 725 SkTBits<int> Cbits(C); |
| 726 if (Cbits(2, 0) == 0x5) { |
| 727 q[1] = 4; |
| 728 q[0] = Cbits(4, 3); |
| 729 } else { |
| 730 q[1] = Cbits(4, 3); |
| 731 q[0] = Cbits(2, 0); |
| 732 } |
| 733 } |
| 734 |
| 735 #ifdef SK_DEBUG |
| 736 for (int i = 0; i < 3; ++i) { |
| 737 SkASSERT(q[i] < 5); |
| 738 SkASSERT(m[i] < (1 << nBits)); |
| 739 } |
| 740 #endif |
| 741 |
| 742 for (int i = 0; i < 3; ++i) { |
| 743 *dst = (q[i] << nBits) + m[i]; |
| 744 ++dst; |
| 745 } |
| 746 } |
| 747 |
| 748 // Function that decodes a sequence of integers stored as an ISE (Integer |
| 749 // Sequence Encoding) bit stream. The full details of this function are outlined |
| 750 // in section C.2.12 of the ASTC spec. A brief overview is as follows: |
| 751 // |
| 752 // - Each integer in the sequence is bounded by a specific range r. |
| 753 // - The range of each value determines the way the bit stream is interpreted, |
| 754 // - If the range is a power of two, then the sequence is a sequence of bits |
| 755 // - If the range is of the form 3*2^n, then the sequence is stored as a |
| 756 // sequence of blocks, each block contains 5 trits and 5 bit sequences, which |
| 757 // decodes into 5 values. |
| 758 // - Similarly, if the range is of the form 5*2^n, then the sequence is stored a
s a |
| 759 // sequence of blocks, each block contains 3 quints and 3 bit sequences, which |
| 760 // decodes into 3 values. |
| 761 static bool decode_integer_sequence( |
| 762 int* dst, // The array holding the destination bits |
| 763 int dstSize, // The maximum size of the array |
| 764 int nVals, // The number of values that we'd like to decode |
| 765 const ASTCBlock &block, // The block that we're decoding from |
| 766 int startBit, // The bit from which we're going to do the readin
g |
| 767 int endBit, // The bit at which we stop reading (not inclusive
) |
| 768 bool bReadForward, // If true, then read LSB -> MSB, else read MSB ->
LSB |
| 769 int nBits, // The number of bits representing this encoding |
| 770 int nTrits, // The number of trits representing this encoding |
| 771 int nQuints // The number of quints representing this encoding |
| 772 ) { |
| 773 // If we want more values than we have, then fail. |
| 774 if (nVals > dstSize) { |
| 775 return false; |
| 776 } |
| 777 |
| 778 ASTCBlock src = block; |
| 779 |
| 780 if (!bReadForward) { |
| 781 src.reverse(); |
| 782 startBit = 128 - startBit; |
| 783 endBit = 128 - endBit; |
| 784 } |
| 785 |
| 786 while (nVals > 0) { |
| 787 |
| 788 if (nTrits > 0) { |
| 789 SkASSERT(0 == nQuints); |
| 790 |
| 791 int endBlockBit = startBit + 8 + 5*nBits; |
| 792 if (endBlockBit > endBit) { |
| 793 endBlockBit = endBit; |
| 794 } |
| 795 |
| 796 decode_trit_block(dst, nBits, read_astc_bits(src, startBit, endBlock
Bit)); |
| 797 dst += 5; |
| 798 nVals -= 5; |
| 799 startBit = endBlockBit; |
| 800 |
| 801 } else if (nQuints > 0) { |
| 802 SkASSERT(0 == nTrits); |
| 803 |
| 804 int endBlockBit = startBit + 7 + 3*nBits; |
| 805 if (endBlockBit > endBit) { |
| 806 endBlockBit = endBit; |
| 807 } |
| 808 |
| 809 decode_quint_block(dst, nBits, read_astc_bits(src, startBit, endBloc
kBit)); |
| 810 dst += 3; |
| 811 nVals -= 3; |
| 812 startBit = endBlockBit; |
| 813 |
| 814 } else { |
| 815 // Just read the bits, but don't read more than we have... |
| 816 int endValBit = startBit + nBits; |
| 817 if (endValBit > endBit) { |
| 818 endValBit = endBit; |
| 819 } |
| 820 |
| 821 SkASSERT(endValBit - startBit < 31); |
| 822 *dst = static_cast<int>(read_astc_bits(src, startBit, endValBit)); |
| 823 ++dst; |
| 824 --nVals; |
| 825 startBit = endValBit; |
| 826 } |
| 827 } |
| 828 |
| 829 return true; |
| 830 } |
| 831 |
| 832 // Helper function that unquantizes some (seemingly random) generated |
| 833 // numbers... meant to match the ASTC hardware. This function is used |
| 834 // to unquantize both colors (Table C.2.16) and weights (Table C.2.26) |
| 835 static inline int unquantize_value(unsigned mask, int A, int B, int C, int D) { |
| 836 int T = D * C + B; |
| 837 T = T ^ A; |
| 838 T = (A & mask) | (T >> 2); |
| 839 SkASSERT(T < 256); |
| 840 return T; |
| 841 } |
| 842 |
| 843 // Helper function to replicate the bits in x that represents an oldPrec |
| 844 // precision integer into a prec precision integer. For example: |
| 845 // 255 == replicate_bits(7, 3, 8); |
| 846 static inline int replicate_bits(int x, int oldPrec, int prec) { |
| 847 while (oldPrec < prec) { |
| 848 const int toShift = SkMin32(prec-oldPrec, oldPrec); |
| 849 x = (x << toShift) | (x >> (oldPrec - toShift)); |
| 850 oldPrec += toShift; |
| 851 } |
| 852 |
| 853 // Make sure that no bits are set outside the desired precision. |
| 854 SkASSERT((-(1 << prec) & x) == 0); |
| 855 return x; |
| 856 } |
| 857 |
| 858 // Returns the unquantized value of a color that's represented only as |
| 859 // a set of bits. |
| 860 static inline int unquantize_bits_color(int val, int nBits) { |
| 861 return replicate_bits(val, nBits, 8); |
| 862 } |
| 863 |
| 864 // Returns the unquantized value of a color that's represented as a |
| 865 // trit followed by nBits bits. This algorithm follows the sequence |
| 866 // defined in section C.2.13 of the ASTC spec. |
| 867 static inline int unquantize_trit_color(int val, int nBits) { |
| 868 SkASSERT(nBits > 0); |
| 869 SkASSERT(nBits < 7); |
| 870 |
| 871 const int D = (val >> nBits) & 0x3; |
| 872 SkASSERT(D < 3); |
| 873 |
| 874 const int A = -(val & 0x1) & 0x1FF; |
| 875 |
| 876 static const int Cvals[6] = { 204, 93, 44, 22, 11, 5 }; |
| 877 const int C = Cvals[nBits - 1]; |
| 878 |
| 879 int B = 0; |
| 880 const SkTBits<int> valBits(val); |
| 881 switch (nBits) { |
| 882 case 1: |
| 883 B = 0; |
| 884 break; |
| 885 |
| 886 case 2: { |
| 887 const int b = valBits[1]; |
| 888 B = (b << 1) | (b << 2) | (b << 4) | (b << 8); |
| 889 } |
| 890 break; |
| 891 |
| 892 case 3: { |
| 893 const int cb = valBits(2, 1); |
| 894 B = cb | (cb << 2) | (cb << 7); |
| 895 } |
| 896 break; |
| 897 |
| 898 case 4: { |
| 899 const int dcb = valBits(3, 1); |
| 900 B = dcb | (dcb << 6); |
| 901 } |
| 902 break; |
| 903 |
| 904 case 5: { |
| 905 const int edcb = valBits(4, 1); |
| 906 B = (edcb << 5) | (edcb >> 2); |
| 907 } |
| 908 break; |
| 909 |
| 910 case 6: { |
| 911 const int fedcb = valBits(5, 1); |
| 912 B = (fedcb << 4) | (fedcb >> 4); |
| 913 } |
| 914 break; |
| 915 } |
| 916 |
| 917 return unquantize_value(0x80, A, B, C, D); |
| 918 } |
| 919 |
| 920 // Returns the unquantized value of a color that's represented as a |
| 921 // quint followed by nBits bits. This algorithm follows the sequence |
| 922 // defined in section C.2.13 of the ASTC spec. |
| 923 static inline int unquantize_quint_color(int val, int nBits) { |
| 924 const int D = (val >> nBits) & 0x7; |
| 925 SkASSERT(D < 5); |
| 926 |
| 927 const int A = -(val & 0x1) & 0x1FF; |
| 928 |
| 929 static const int Cvals[5] = { 113, 54, 26, 13, 6 }; |
| 930 SkASSERT(nBits > 0); |
| 931 SkASSERT(nBits < 6); |
| 932 |
| 933 const int C = Cvals[nBits - 1]; |
| 934 |
| 935 int B = 0; |
| 936 const SkTBits<int> valBits(val); |
| 937 switch (nBits) { |
| 938 case 1: |
| 939 B = 0; |
| 940 break; |
| 941 |
| 942 case 2: { |
| 943 const int b = valBits[1]; |
| 944 B = (b << 2) | (b << 3) | (b << 8); |
| 945 } |
| 946 break; |
| 947 |
| 948 case 3: { |
| 949 const int cb = valBits(2, 1); |
| 950 B = (cb >> 1) | (cb << 1) | (cb << 7); |
| 951 } |
| 952 break; |
| 953 |
| 954 case 4: { |
| 955 const int dcb = valBits(3, 1); |
| 956 B = (dcb >> 1) | (dcb << 6); |
| 957 } |
| 958 break; |
| 959 |
| 960 case 5: { |
| 961 const int edcb = valBits(4, 1); |
| 962 B = (edcb << 5) | (edcb >> 3); |
| 963 } |
| 964 break; |
| 965 } |
| 966 |
| 967 return unquantize_value(0x80, A, B, C, D); |
| 968 } |
| 969 |
| 970 // This algorithm takes a list of integers, stored in vals, and unquantizes them |
| 971 // in place. This follows the algorithm laid out in section C.2.13 of the ASTC s
pec. |
| 972 static void unquantize_colors(int *vals, int nVals, int nBits, int nTrits, int n
Quints) { |
| 973 for (int i = 0; i < nVals; ++i) { |
| 974 if (nTrits > 0) { |
| 975 SkASSERT(nQuints == 0); |
| 976 vals[i] = unquantize_trit_color(vals[i], nBits); |
| 977 } else if (nQuints > 0) { |
| 978 SkASSERT(nTrits == 0); |
| 979 vals[i] = unquantize_quint_color(vals[i], nBits); |
| 980 } else { |
| 981 SkASSERT(nQuints == 0 && nTrits == 0); |
| 982 vals[i] = unquantize_bits_color(vals[i], nBits); |
| 983 } |
| 984 } |
| 985 } |
| 986 |
| 987 // Returns an interpolated value between c0 and c1 based on the weight. This |
| 988 // follows the algorithm laid out in section C.2.19 of the ASTC spec. |
| 989 static int interpolate_channel(int c0, int c1, int weight) { |
| 990 SkASSERT(0 <= c0 && c0 < 256); |
| 991 SkASSERT(0 <= c1 && c1 < 256); |
| 992 |
| 993 c0 = (c0 << 8) | c0; |
| 994 c1 = (c1 << 8) | c1; |
| 995 |
| 996 const int result = ((c0*(64 - weight) + c1*weight + 32) / 64) >> 8; |
| 997 |
| 998 if (result > 255) { |
| 999 return 255; |
| 1000 } |
| 1001 |
| 1002 SkASSERT(result >= 0); |
| 1003 return result; |
| 1004 } |
| 1005 |
| 1006 // Returns an interpolated color between the two endpoints based on the weight. |
| 1007 static SkColor interpolate_endpoints(const SkColor endpoints[2], int weight) { |
| 1008 return SkColorSetARGB( |
| 1009 interpolate_channel(SkColorGetA(endpoints[0]), SkColorGetA(endpoints[1])
, weight), |
| 1010 interpolate_channel(SkColorGetR(endpoints[0]), SkColorGetR(endpoints[1])
, weight), |
| 1011 interpolate_channel(SkColorGetG(endpoints[0]), SkColorGetG(endpoints[1])
, weight), |
| 1012 interpolate_channel(SkColorGetB(endpoints[0]), SkColorGetB(endpoints[1])
, weight)); |
| 1013 } |
| 1014 |
| 1015 // Returns an interpolated color between the two endpoints based on the weight. |
| 1016 // It uses separate weights for the channel depending on the value of the 'plane
' |
| 1017 // variable. By default, all channels will use weight 0, and the value of plane |
| 1018 // means that weight1 will be used for: |
| 1019 // 0: red |
| 1020 // 1: green |
| 1021 // 2: blue |
| 1022 // 3: alpha |
| 1023 static SkColor interpolate_dual_endpoints( |
| 1024 const SkColor endpoints[2], int weight0, int weight1, int plane) { |
| 1025 int a = interpolate_channel(SkColorGetA(endpoints[0]), SkColorGetA(endpoints
[1]), weight0); |
| 1026 int r = interpolate_channel(SkColorGetR(endpoints[0]), SkColorGetR(endpoints
[1]), weight0); |
| 1027 int g = interpolate_channel(SkColorGetG(endpoints[0]), SkColorGetG(endpoints
[1]), weight0); |
| 1028 int b = interpolate_channel(SkColorGetB(endpoints[0]), SkColorGetB(endpoints
[1]), weight0); |
| 1029 |
| 1030 switch (plane) { |
| 1031 |
| 1032 case 0: |
| 1033 r = interpolate_channel( |
| 1034 SkColorGetR(endpoints[0]), SkColorGetR(endpoints[1]), weight1); |
| 1035 break; |
| 1036 |
| 1037 case 1: |
| 1038 g = interpolate_channel( |
| 1039 SkColorGetG(endpoints[0]), SkColorGetG(endpoints[1]), weight1); |
| 1040 break; |
| 1041 |
| 1042 case 2: |
| 1043 b = interpolate_channel( |
| 1044 SkColorGetB(endpoints[0]), SkColorGetB(endpoints[1]), weight1); |
| 1045 break; |
| 1046 |
| 1047 case 3: |
| 1048 a = interpolate_channel( |
| 1049 SkColorGetA(endpoints[0]), SkColorGetA(endpoints[1]), weight1); |
| 1050 break; |
| 1051 |
| 1052 default: |
| 1053 SkDEBUGFAIL("Plane should be 0-3"); |
| 1054 break; |
| 1055 } |
| 1056 |
| 1057 return SkColorSetARGB(a, r, g, b); |
| 1058 } |
| 1059 |
| 1060 // A struct of decoded values that we use to carry around information |
| 1061 // about the block. dimX and dimY are the dimension in texels of the block, |
| 1062 // for which there is only a limited subset of valid values: |
| 1063 // |
| 1064 // 4x4, 5x4, 5x5, 6x5, 6x6, 8x5, 8x6, 8x8, 10x5, 10x6, 10x8, 10x10, 12x10, 12x12 |
| 1065 |
| 1066 struct ASTCDecompressionData { |
| 1067 ASTCDecompressionData(int dimX, int dimY) : fDimX(dimX), fDimY(dimY) { } |
| 1068 const int fDimX; // the X dimension of the decompressed block |
| 1069 const int fDimY; // the Y dimension of the decompressed block |
| 1070 ASTCBlock fBlock; // the block data |
| 1071 int fBlockMode; // the block header that contains the block mode. |
| 1072 |
| 1073 bool fDualPlaneEnabled; // is this block compressing dual weight planes? |
| 1074 int fDualPlane; // the independent plane in dual plane mode. |
| 1075 |
| 1076 bool fVoidExtent; // is this block a single color? |
| 1077 bool fError; // does this block have an error encoding? |
| 1078 |
| 1079 int fWeightDimX; // the x dimension of the weight grid |
| 1080 int fWeightDimY; // the y dimension of the weight grid |
| 1081 |
| 1082 int fWeightBits; // the number of bits used for each weight value |
| 1083 int fWeightTrits; // the number of trits used for each weight value |
| 1084 int fWeightQuints; // the number of quints used for each weight value |
| 1085 |
| 1086 int fPartCount; // the number of partitions in this block |
| 1087 int fPartIndex; // the partition index: only relevant if fPartCount
> 0 |
| 1088 |
| 1089 // CEM values can be anything in the range 0-15, and each corresponds to a d
ifferent |
| 1090 // mode that represents the color data. We only support LDR modes. |
| 1091 enum ColorEndpointMode { |
| 1092 kLDR_Luminance_Direct_ColorEndpointMode = 0, |
| 1093 kLDR_Luminance_BaseOffset_ColorEndpointMode = 1, |
| 1094 kHDR_Luminance_LargeRange_ColorEndpointMode = 2, |
| 1095 kHDR_Luminance_SmallRange_ColorEndpointMode = 3, |
| 1096 kLDR_LuminanceAlpha_Direct_ColorEndpointMode = 4, |
| 1097 kLDR_LuminanceAlpha_BaseOffset_ColorEndpointMode = 5, |
| 1098 kLDR_RGB_BaseScale_ColorEndpointMode = 6, |
| 1099 kHDR_RGB_BaseScale_ColorEndpointMode = 7, |
| 1100 kLDR_RGB_Direct_ColorEndpointMode = 8, |
| 1101 kLDR_RGB_BaseOffset_ColorEndpointMode = 9, |
| 1102 kLDR_RGB_BaseScaleWithAlpha_ColorEndpointMode = 10, |
| 1103 kHDR_RGB_ColorEndpointMode = 11, |
| 1104 kLDR_RGBA_Direct_ColorEndpointMode = 12, |
| 1105 kLDR_RGBA_BaseOffset_ColorEndpointMode = 13, |
| 1106 kHDR_RGB_LDRAlpha_ColorEndpointMode = 14, |
| 1107 kHDR_RGB_HDRAlpha_ColorEndpointMode = 15 |
| 1108 }; |
| 1109 static const int kMaxColorEndpointModes = 16; |
| 1110 |
| 1111 // the color endpoint modes for this block. |
| 1112 static const int kMaxPartitions = 4; |
| 1113 ColorEndpointMode fCEM[kMaxPartitions]; |
| 1114 |
| 1115 int fColorStartBit; // The bit position of the first bit of the color da
ta |
| 1116 int fColorEndBit; // The bit position of the last *possible* bit of th
e color data |
| 1117 |
| 1118 // Returns the number of partitions for this block. |
| 1119 int numPartitions() const { |
| 1120 return fPartCount; |
| 1121 } |
| 1122 |
| 1123 // Returns the total number of weight values that are stored in this block |
| 1124 int numWeights() const { |
| 1125 return fWeightDimX * fWeightDimY * (fDualPlaneEnabled ? 2 : 1); |
| 1126 } |
| 1127 |
| 1128 #ifdef SK_DEBUG |
| 1129 // Returns the maximum value that any weight can take. We really only use |
| 1130 // this function for debugging. |
| 1131 int maxWeightValue() const { |
| 1132 int maxVal = (1 << fWeightBits); |
| 1133 if (fWeightTrits > 0) { |
| 1134 SkASSERT(0 == fWeightQuints); |
| 1135 maxVal *= 3; |
| 1136 } else if (fWeightQuints > 0) { |
| 1137 SkASSERT(0 == fWeightTrits); |
| 1138 maxVal *= 5; |
| 1139 } |
| 1140 return maxVal - 1; |
| 1141 } |
| 1142 #endif |
| 1143 |
| 1144 // The number of bits needed to represent the texel weight data. This |
| 1145 // comes from the 'data size determination' section of the ASTC spec (C.2.22
) |
| 1146 int numWeightBits() const { |
| 1147 const int nWeights = this->numWeights(); |
| 1148 return |
| 1149 ((nWeights*8*fWeightTrits + 4) / 5) + |
| 1150 ((nWeights*7*fWeightQuints + 2) / 3) + |
| 1151 (nWeights*fWeightBits); |
| 1152 } |
| 1153 |
| 1154 // Returns the number of color values stored in this block. The number of |
| 1155 // values stored is directly a function of the color endpoint modes. |
| 1156 int numColorValues() const { |
| 1157 int numValues = 0; |
| 1158 for (int i = 0; i < this->numPartitions(); ++i) { |
| 1159 int cemInt = static_cast<int>(fCEM[i]); |
| 1160 numValues += ((cemInt >> 2) + 1) * 2; |
| 1161 } |
| 1162 |
| 1163 return numValues; |
| 1164 } |
| 1165 |
| 1166 // Figures out the number of bits available for color values, and fills |
| 1167 // in the maximum encoding that will fit the number of color values that |
| 1168 // we need. Returns false on error. (See section C.2.22 of the spec) |
| 1169 bool getColorValueEncoding(int *nBits, int *nTrits, int *nQuints) const { |
| 1170 if (NULL == nBits || NULL == nTrits || NULL == nQuints) { |
| 1171 return false; |
| 1172 } |
| 1173 |
| 1174 const int nColorVals = this->numColorValues(); |
| 1175 if (nColorVals <= 0) { |
| 1176 return false; |
| 1177 } |
| 1178 |
| 1179 const int colorBits = fColorEndBit - fColorStartBit; |
| 1180 SkASSERT(colorBits > 0); |
| 1181 |
| 1182 // This is the minimum amount of accuracy required by the spec. |
| 1183 if (colorBits < ((13 * nColorVals + 4) / 5)) { |
| 1184 return false; |
| 1185 } |
| 1186 |
| 1187 // Values can be represented as at most 8-bit values. |
| 1188 // !SPEED! place this in a lookup table based on colorBits and nColorVal
s |
| 1189 for (int i = 255; i > 0; --i) { |
| 1190 int range = i + 1; |
| 1191 int bits = 0, trits = 0, quints = 0; |
| 1192 bool valid = false; |
| 1193 if (SkIsPow2(range)) { |
| 1194 bits = bits_for_range(range); |
| 1195 valid = true; |
| 1196 } else if ((range % 3) == 0 && SkIsPow2(range/3)) { |
| 1197 trits = 1; |
| 1198 bits = bits_for_range(range/3); |
| 1199 valid = true; |
| 1200 } else if ((range % 5) == 0 && SkIsPow2(range/5)) { |
| 1201 quints = 1; |
| 1202 bits = bits_for_range(range/5); |
| 1203 valid = true; |
| 1204 } |
| 1205 |
| 1206 if (valid) { |
| 1207 const int actualColorBits = |
| 1208 ((nColorVals*8*trits + 4) / 5) + |
| 1209 ((nColorVals*7*quints + 2) / 3) + |
| 1210 (nColorVals*bits); |
| 1211 if (actualColorBits <= colorBits) { |
| 1212 *nTrits = trits; |
| 1213 *nQuints = quints; |
| 1214 *nBits = bits; |
| 1215 return true; |
| 1216 } |
| 1217 } |
| 1218 } |
| 1219 |
| 1220 return false; |
| 1221 } |
| 1222 |
| 1223 // Converts the sequence of color values into endpoints. The algorithm here |
| 1224 // corresponds to the values determined by section C.2.14 of the ASTC spec |
| 1225 void colorEndpoints(SkColor endpoints[4][2], const int* colorValues) const { |
| 1226 for (int i = 0; i < this->numPartitions(); ++i) { |
| 1227 switch (fCEM[i]) { |
| 1228 case kLDR_Luminance_Direct_ColorEndpointMode: { |
| 1229 const int* v = colorValues; |
| 1230 endpoints[i][0] = SkColorSetARGB(0xFF, v[0], v[0], v[0]); |
| 1231 endpoints[i][1] = SkColorSetARGB(0xFF, v[1], v[1], v[1]); |
| 1232 |
| 1233 colorValues += 2; |
| 1234 } |
| 1235 break; |
| 1236 |
| 1237 case kLDR_Luminance_BaseOffset_ColorEndpointMode: { |
| 1238 const int* v = colorValues; |
| 1239 const int L0 = (v[0] >> 2) | (v[1] & 0xC0); |
| 1240 const int L1 = clamp_byte(L0 + (v[1] & 0x3F)); |
| 1241 |
| 1242 endpoints[i][0] = SkColorSetARGB(0xFF, L0, L0, L0); |
| 1243 endpoints[i][1] = SkColorSetARGB(0xFF, L1, L1, L1); |
| 1244 |
| 1245 colorValues += 2; |
| 1246 } |
| 1247 break; |
| 1248 |
| 1249 case kLDR_LuminanceAlpha_Direct_ColorEndpointMode: { |
| 1250 const int* v = colorValues; |
| 1251 |
| 1252 endpoints[i][0] = SkColorSetARGB(v[2], v[0], v[0], v[0]); |
| 1253 endpoints[i][1] = SkColorSetARGB(v[3], v[1], v[1], v[1]); |
| 1254 |
| 1255 colorValues += 4; |
| 1256 } |
| 1257 break; |
| 1258 |
| 1259 case kLDR_LuminanceAlpha_BaseOffset_ColorEndpointMode: { |
| 1260 int v0 = colorValues[0]; |
| 1261 int v1 = colorValues[1]; |
| 1262 int v2 = colorValues[2]; |
| 1263 int v3 = colorValues[3]; |
| 1264 |
| 1265 bit_transfer_signed(&v1, &v0); |
| 1266 bit_transfer_signed(&v3, &v2); |
| 1267 |
| 1268 endpoints[i][0] = SkColorSetARGB(v2, v0, v0, v0); |
| 1269 endpoints[i][1] = SkColorSetARGB( |
| 1270 clamp_byte(v3+v2), |
| 1271 clamp_byte(v1+v0), |
| 1272 clamp_byte(v1+v0), |
| 1273 clamp_byte(v1+v0)); |
| 1274 |
| 1275 colorValues += 4; |
| 1276 } |
| 1277 break; |
| 1278 |
| 1279 case kLDR_RGB_BaseScale_ColorEndpointMode: { |
| 1280 decode_rgba_basescale(colorValues, endpoints[i], true); |
| 1281 colorValues += 4; |
| 1282 } |
| 1283 break; |
| 1284 |
| 1285 case kLDR_RGB_Direct_ColorEndpointMode: { |
| 1286 decode_rgba_direct(colorValues, endpoints[i], true); |
| 1287 colorValues += 6; |
| 1288 } |
| 1289 break; |
| 1290 |
| 1291 case kLDR_RGB_BaseOffset_ColorEndpointMode: { |
| 1292 decode_rgba_baseoffset(colorValues, endpoints[i], true); |
| 1293 colorValues += 6; |
| 1294 } |
| 1295 break; |
| 1296 |
| 1297 case kLDR_RGB_BaseScaleWithAlpha_ColorEndpointMode: { |
| 1298 decode_rgba_basescale(colorValues, endpoints[i], false); |
| 1299 colorValues += 6; |
| 1300 } |
| 1301 break; |
| 1302 |
| 1303 case kLDR_RGBA_Direct_ColorEndpointMode: { |
| 1304 decode_rgba_direct(colorValues, endpoints[i], false); |
| 1305 colorValues += 8; |
| 1306 } |
| 1307 break; |
| 1308 |
| 1309 case kLDR_RGBA_BaseOffset_ColorEndpointMode: { |
| 1310 decode_rgba_baseoffset(colorValues, endpoints[i], false); |
| 1311 colorValues += 8; |
| 1312 } |
| 1313 break; |
| 1314 |
| 1315 default: |
| 1316 SkDEBUGFAIL("HDR mode unsupported! This should be caught soo
ner."); |
| 1317 break; |
| 1318 } |
| 1319 } |
| 1320 } |
| 1321 |
| 1322 // Follows the procedure from section C.2.17 of the ASTC specification |
| 1323 int unquantizeWeight(int x) const { |
| 1324 SkASSERT(x <= this->maxWeightValue()); |
| 1325 |
| 1326 const int D = (x >> fWeightBits) & 0x7; |
| 1327 const int A = -(x & 0x1) & 0x7F; |
| 1328 |
| 1329 SkTBits<int> xbits(x); |
| 1330 |
| 1331 int T = 0; |
| 1332 if (fWeightTrits > 0) { |
| 1333 SkASSERT(0 == fWeightQuints); |
| 1334 switch (fWeightBits) { |
| 1335 case 0: { |
| 1336 // x is a single trit |
| 1337 SkASSERT(x < 3); |
| 1338 |
| 1339 static const int kUnquantizationTable[3] = { 0, 32, 63 }; |
| 1340 T = kUnquantizationTable[x]; |
| 1341 } |
| 1342 break; |
| 1343 |
| 1344 case 1: { |
| 1345 const int B = 0; |
| 1346 const int C = 50; |
| 1347 T = unquantize_value(0x20, A, B, C, D); |
| 1348 } |
| 1349 break; |
| 1350 |
| 1351 case 2: { |
| 1352 const int b = xbits[1]; |
| 1353 const int B = b | (b << 2) | (b << 6); |
| 1354 const int C = 23; |
| 1355 T = unquantize_value(0x20, A, B, C, D); |
| 1356 } |
| 1357 break; |
| 1358 |
| 1359 case 3: { |
| 1360 const int cb = xbits(2, 1); |
| 1361 const int B = cb | (cb << 5); |
| 1362 const int C = 11; |
| 1363 T = unquantize_value(0x20, A, B, C, D); |
| 1364 } |
| 1365 break; |
| 1366 |
| 1367 default: |
| 1368 SkDEBUGFAIL("Too many bits for trit encoding"); |
| 1369 break; |
| 1370 } |
| 1371 |
| 1372 } else if (fWeightQuints > 0) { |
| 1373 SkASSERT(0 == fWeightTrits); |
| 1374 switch (fWeightBits) { |
| 1375 case 0: { |
| 1376 // x is a single quint |
| 1377 SkASSERT(x < 5); |
| 1378 |
| 1379 static const int kUnquantizationTable[5] = { 0, 16, 32, 47,
63 }; |
| 1380 T = kUnquantizationTable[x]; |
| 1381 } |
| 1382 break; |
| 1383 |
| 1384 case 1: { |
| 1385 const int B = 0; |
| 1386 const int C = 28; |
| 1387 T = unquantize_value(0x20, A, B, C, D); |
| 1388 } |
| 1389 break; |
| 1390 |
| 1391 case 2: { |
| 1392 const int b = xbits[1]; |
| 1393 const int B = (b << 1) | (b << 6); |
| 1394 const int C = 13; |
| 1395 T = unquantize_value(0x20, A, B, C, D); |
| 1396 } |
| 1397 break; |
| 1398 |
| 1399 default: |
| 1400 SkDEBUGFAIL("Too many bits for quint encoding"); |
| 1401 break; |
| 1402 } |
| 1403 } else { |
| 1404 SkASSERT(0 == fWeightTrits); |
| 1405 SkASSERT(0 == fWeightQuints); |
| 1406 |
| 1407 T = replicate_bits(x, fWeightBits, 6); |
| 1408 } |
| 1409 |
| 1410 // This should bring the value within [0, 63].. |
| 1411 SkASSERT(T <= 63); |
| 1412 |
| 1413 if (T > 32) { |
| 1414 T += 1; |
| 1415 } |
| 1416 |
| 1417 SkASSERT(T <= 64); |
| 1418 |
| 1419 return T; |
| 1420 } |
| 1421 |
| 1422 // Returns the weight at the associated index. If the index is out of bounds
, it |
| 1423 // returns zero. It also chooses the weight appropriately based on the given
dual |
| 1424 // plane. |
| 1425 int getWeight(const int* unquantizedWeights, int idx, bool dualPlane) const
{ |
| 1426 const int maxIdx = (fDualPlaneEnabled ? 2 : 1) * fWeightDimX * fWeightDi
mY - 1; |
| 1427 if (fDualPlaneEnabled) { |
| 1428 const int effectiveIdx = 2*idx + (dualPlane ? 1 : 0); |
| 1429 if (effectiveIdx > maxIdx) { |
| 1430 return 0; |
| 1431 } |
| 1432 return unquantizedWeights[effectiveIdx]; |
| 1433 } |
| 1434 |
| 1435 SkASSERT(!dualPlane); |
| 1436 |
| 1437 if (idx > maxIdx) { |
| 1438 return 0; |
| 1439 } else { |
| 1440 return unquantizedWeights[idx]; |
| 1441 } |
| 1442 } |
| 1443 |
| 1444 // This computes the effective weight at location (s, t) of the block. This |
| 1445 // weight is computed by sampling the texel weight grid (it's usually not 1-
1), and |
| 1446 // then applying a bilerp. The algorithm outlined here follows the algorithm |
| 1447 // defined in section C.2.18 of the ASTC spec. |
| 1448 int infillWeight(const int* unquantizedValues, int s, int t, bool dualPlane)
const { |
| 1449 const int Ds = (1024 + fDimX/2) / (fDimX - 1); |
| 1450 const int Dt = (1024 + fDimY/2) / (fDimY - 1); |
| 1451 |
| 1452 const int cs = Ds * s; |
| 1453 const int ct = Dt * t; |
| 1454 |
| 1455 const int gs = (cs*(fWeightDimX - 1) + 32) >> 6; |
| 1456 const int gt = (ct*(fWeightDimY - 1) + 32) >> 6; |
| 1457 |
| 1458 const int js = gs >> 4; |
| 1459 const int jt = gt >> 4; |
| 1460 |
| 1461 const int fs = gs & 0xF; |
| 1462 const int ft = gt & 0xF; |
| 1463 |
| 1464 const int idx = js + jt*fWeightDimX; |
| 1465 const int p00 = this->getWeight(unquantizedValues, idx, dualPlane); |
| 1466 const int p01 = this->getWeight(unquantizedValues, idx + 1, dualPlane); |
| 1467 const int p10 = this->getWeight(unquantizedValues, idx + fWeightDimX, du
alPlane); |
| 1468 const int p11 = this->getWeight(unquantizedValues, idx + fWeightDimX + 1
, dualPlane); |
| 1469 |
| 1470 const int w11 = (fs*ft + 8) >> 4; |
| 1471 const int w10 = ft - w11; |
| 1472 const int w01 = fs - w11; |
| 1473 const int w00 = 16 - fs - ft + w11; |
| 1474 |
| 1475 const int weight = (p00*w00 + p01*w01 + p10*w10 + p11*w11 + 8) >> 4; |
| 1476 SkASSERT(weight <= 64); |
| 1477 return weight; |
| 1478 } |
| 1479 |
| 1480 // Unquantizes the decoded texel weights as described in section C.2.17 of |
| 1481 // the ASTC specification. Additionally, it populates texelWeights with |
| 1482 // the expanded weight grid, which is computed according to section C.2.18 |
| 1483 void texelWeights(int texelWeights[2][12][12], const int* texelValues) const
{ |
| 1484 // Unquantized texel weights... |
| 1485 int unquantizedValues[144*2]; // 12x12 blocks with dual plane decoding..
. |
| 1486 SkASSERT(this->numWeights() <= 144*2); |
| 1487 |
| 1488 // Unquantize the weights and cache them |
| 1489 for (int j = 0; j < this->numWeights(); ++j) { |
| 1490 unquantizedValues[j] = this->unquantizeWeight(texelValues[j]); |
| 1491 } |
| 1492 |
| 1493 // Do weight infill... |
| 1494 for (int y = 0; y < fDimY; ++y) { |
| 1495 for (int x = 0; x < fDimX; ++x) { |
| 1496 texelWeights[0][x][y] = this->infillWeight(unquantizedValues, x,
y, false); |
| 1497 if (fDualPlaneEnabled) { |
| 1498 texelWeights[1][x][y] = this->infillWeight(unquantizedValues
, x, y, true); |
| 1499 } |
| 1500 } |
| 1501 } |
| 1502 } |
| 1503 |
| 1504 // Returns the partition for the texel located at position (x, y). |
| 1505 // Adapted from C.2.21 of the ASTC specification |
| 1506 int getPartition(int x, int y) const { |
| 1507 const int partitionCount = this->numPartitions(); |
| 1508 int seed = fPartIndex; |
| 1509 if ((fDimX * fDimY) < 31) { |
| 1510 x <<= 1; |
| 1511 y <<= 1; |
| 1512 } |
| 1513 |
| 1514 seed += (partitionCount - 1) * 1024; |
| 1515 |
| 1516 uint32_t p = seed; |
| 1517 p ^= p >> 15; p -= p << 17; p += p << 7; p += p << 4; |
| 1518 p ^= p >> 5; p += p << 16; p ^= p >> 7; p ^= p >> 3; |
| 1519 p ^= p << 6; p ^= p >> 17; |
| 1520 |
| 1521 uint32_t rnum = p; |
| 1522 uint8_t seed1 = rnum & 0xF; |
| 1523 uint8_t seed2 = (rnum >> 4) & 0xF; |
| 1524 uint8_t seed3 = (rnum >> 8) & 0xF; |
| 1525 uint8_t seed4 = (rnum >> 12) & 0xF; |
| 1526 uint8_t seed5 = (rnum >> 16) & 0xF; |
| 1527 uint8_t seed6 = (rnum >> 20) & 0xF; |
| 1528 uint8_t seed7 = (rnum >> 24) & 0xF; |
| 1529 uint8_t seed8 = (rnum >> 28) & 0xF; |
| 1530 uint8_t seed9 = (rnum >> 18) & 0xF; |
| 1531 uint8_t seed10 = (rnum >> 22) & 0xF; |
| 1532 uint8_t seed11 = (rnum >> 26) & 0xF; |
| 1533 uint8_t seed12 = ((rnum >> 30) | (rnum << 2)) & 0xF; |
| 1534 |
| 1535 seed1 *= seed1; seed2 *= seed2; |
| 1536 seed3 *= seed3; seed4 *= seed4; |
| 1537 seed5 *= seed5; seed6 *= seed6; |
| 1538 seed7 *= seed7; seed8 *= seed8; |
| 1539 seed9 *= seed9; seed10 *= seed10; |
| 1540 seed11 *= seed11; seed12 *= seed12; |
| 1541 |
| 1542 int sh1, sh2, sh3; |
| 1543 if (0 != (seed & 1)) { |
| 1544 sh1 = (0 != (seed & 2))? 4 : 5; |
| 1545 sh2 = (partitionCount == 3)? 6 : 5; |
| 1546 } else { |
| 1547 sh1 = (partitionCount==3)? 6 : 5; |
| 1548 sh2 = (0 != (seed & 2))? 4 : 5; |
| 1549 } |
| 1550 sh3 = (0 != (seed & 0x10))? sh1 : sh2; |
| 1551 |
| 1552 seed1 >>= sh1; seed2 >>= sh2; seed3 >>= sh1; seed4 >>= sh2; |
| 1553 seed5 >>= sh1; seed6 >>= sh2; seed7 >>= sh1; seed8 >>= sh2; |
| 1554 seed9 >>= sh3; seed10 >>= sh3; seed11 >>= sh3; seed12 >>= sh3; |
| 1555 |
| 1556 const int z = 0; |
| 1557 int a = seed1*x + seed2*y + seed11*z + (rnum >> 14); |
| 1558 int b = seed3*x + seed4*y + seed12*z + (rnum >> 10); |
| 1559 int c = seed5*x + seed6*y + seed9 *z + (rnum >> 6); |
| 1560 int d = seed7*x + seed8*y + seed10*z + (rnum >> 2); |
| 1561 |
| 1562 a &= 0x3F; |
| 1563 b &= 0x3F; |
| 1564 c &= 0x3F; |
| 1565 d &= 0x3F; |
| 1566 |
| 1567 if (partitionCount < 4) { |
| 1568 d = 0; |
| 1569 } |
| 1570 |
| 1571 if (partitionCount < 3) { |
| 1572 c = 0; |
| 1573 } |
| 1574 |
| 1575 if (a >= b && a >= c && a >= d) { |
| 1576 return 0; |
| 1577 } else if (b >= c && b >= d) { |
| 1578 return 1; |
| 1579 } else if (c >= d) { |
| 1580 return 2; |
| 1581 } else { |
| 1582 return 3; |
| 1583 } |
| 1584 } |
| 1585 |
| 1586 // Performs the proper interpolation of the texel based on the |
| 1587 // endpoints and weights. |
| 1588 SkColor getTexel(const SkColor endpoints[4][2], |
| 1589 const int weights[2][12][12], |
| 1590 int x, int y) const { |
| 1591 int part = 0; |
| 1592 if (this->numPartitions() > 1) { |
| 1593 part = this->getPartition(x, y); |
| 1594 } |
| 1595 |
| 1596 SkColor result; |
| 1597 if (fDualPlaneEnabled) { |
| 1598 result = interpolate_dual_endpoints( |
| 1599 endpoints[part], weights[0][x][y], weights[1][x][y], fDualPlane)
; |
| 1600 } else { |
| 1601 result = interpolate_endpoints(endpoints[part], weights[0][x][y]); |
| 1602 } |
| 1603 |
| 1604 #if 1 |
| 1605 // !FIXME! if we're writing directly to a bitmap, then we don't need |
| 1606 // to swap the red and blue channels, but since we're usually being used |
| 1607 // by the SkImageDecoder_astc module, the results are expected to be in
RGBA. |
| 1608 result = SkColorSetARGB( |
| 1609 SkColorGetA(result), SkColorGetB(result), SkColorGetG(result), SkCol
orGetR(result)); |
| 1610 #endif |
| 1611 |
| 1612 return result; |
| 1613 } |
| 1614 |
| 1615 void decode() { |
| 1616 // First decode the block mode. |
| 1617 this->decodeBlockMode(); |
| 1618 |
| 1619 // Now we can decode the partition information. |
| 1620 fPartIndex = static_cast<int>(read_astc_bits(fBlock, 11, 23)); |
| 1621 fPartCount = (fPartIndex & 0x3) + 1; |
| 1622 fPartIndex >>= 2; |
| 1623 |
| 1624 // This is illegal |
| 1625 if (fDualPlaneEnabled && this->numPartitions() == 4) { |
| 1626 fError = true; |
| 1627 return; |
| 1628 } |
| 1629 |
| 1630 // Based on the partition info, we can decode the color information. |
| 1631 this->decodeColorData(); |
| 1632 } |
| 1633 |
| 1634 // Decodes the dual plane based on the given bit location. The final |
| 1635 // location, if the dual plane is enabled, is also the end of our color data
. |
| 1636 // This function is only meant to be used from this->decodeColorData() |
| 1637 void decodeDualPlane(int bitLoc) { |
| 1638 if (fDualPlaneEnabled) { |
| 1639 fDualPlane = static_cast<int>(read_astc_bits(fBlock, bitLoc - 2, bit
Loc)); |
| 1640 fColorEndBit = bitLoc - 2; |
| 1641 } else { |
| 1642 fColorEndBit = bitLoc; |
| 1643 } |
| 1644 } |
| 1645 |
| 1646 // Decodes the color information based on the ASTC spec. |
| 1647 void decodeColorData() { |
| 1648 |
| 1649 // By default, the last color bit is at the end of the texel weights |
| 1650 const int lastWeight = 128 - this->numWeightBits(); |
| 1651 |
| 1652 // If we have a dual plane then it will be at this location, too. |
| 1653 int dualPlaneBitLoc = lastWeight; |
| 1654 |
| 1655 // If there's only one partition, then our job is (relatively) easy. |
| 1656 if (this->numPartitions() == 1) { |
| 1657 fCEM[0] = static_cast<ColorEndpointMode>(read_astc_bits(fBlock, 13,
17)); |
| 1658 fColorStartBit = 17; |
| 1659 |
| 1660 // Handle dual plane mode... |
| 1661 this->decodeDualPlane(dualPlaneBitLoc); |
| 1662 |
| 1663 return; |
| 1664 } |
| 1665 |
| 1666 // If we have more than one partition, then we need to make |
| 1667 // room for the partition index. |
| 1668 fColorStartBit = 29; |
| 1669 |
| 1670 // Read the base CEM. If it's zero, then we have no additional |
| 1671 // CEM data and the endpoints for each partition share the same CEM. |
| 1672 const int baseCEM = static_cast<int>(read_astc_bits(fBlock, 23, 25)); |
| 1673 if (0 == baseCEM) { |
| 1674 |
| 1675 const ColorEndpointMode sameCEM = |
| 1676 static_cast<ColorEndpointMode>(read_astc_bits(fBlock, 25, 29)); |
| 1677 |
| 1678 for (int i = 0; i < kMaxPartitions; ++i) { |
| 1679 fCEM[i] = sameCEM; |
| 1680 } |
| 1681 |
| 1682 // Handle dual plane mode... |
| 1683 this->decodeDualPlane(dualPlaneBitLoc); |
| 1684 |
| 1685 return; |
| 1686 } |
| 1687 |
| 1688 // Move the dual plane selector bits down based on how many |
| 1689 // partitions the block contains. |
| 1690 switch (this->numPartitions()) { |
| 1691 case 2: |
| 1692 dualPlaneBitLoc -= 2; |
| 1693 break; |
| 1694 |
| 1695 case 3: |
| 1696 dualPlaneBitLoc -= 5; |
| 1697 break; |
| 1698 |
| 1699 case 4: |
| 1700 dualPlaneBitLoc -= 8; |
| 1701 break; |
| 1702 |
| 1703 default: |
| 1704 SkDEBUGFAIL("Internal ASTC decoding error."); |
| 1705 break; |
| 1706 } |
| 1707 |
| 1708 // The rest of the CEM config will be between the dual plane bit selecto
r |
| 1709 // and the texel weight grid. |
| 1710 const int lowCEM = static_cast<int>(read_astc_bits(fBlock, 23, 29)); |
| 1711 SkASSERT(lastWeight - dualPlaneBitLoc > 31); |
| 1712 int fullCEM = static_cast<int>(read_astc_bits(fBlock, dualPlaneBitLoc, l
astWeight)); |
| 1713 |
| 1714 // Attach the config at the end of the weight grid to the CEM values |
| 1715 // in the beginning of the block. |
| 1716 fullCEM = (fullCEM << 6) | lowCEM; |
| 1717 |
| 1718 // Ignore the two least significant bits, since those are our baseCEM ab
ove. |
| 1719 fullCEM = fullCEM >> 2; |
| 1720 |
| 1721 int C[kMaxPartitions]; // Next, decode C and M from the spec (Table C.2.
12) |
| 1722 for (int i = 0; i < this->numPartitions(); ++i) { |
| 1723 C[i] = fullCEM & 1; |
| 1724 fullCEM = fullCEM >> 1; |
| 1725 } |
| 1726 |
| 1727 int M[kMaxPartitions]; |
| 1728 for (int i = 0; i < this->numPartitions(); ++i) { |
| 1729 M[i] = fullCEM & 0x3; |
| 1730 fullCEM = fullCEM >> 2; |
| 1731 } |
| 1732 |
| 1733 // Construct our CEMs.. |
| 1734 SkASSERT(baseCEM > 0); |
| 1735 for (int i = 0; i < this->numPartitions(); ++i) { |
| 1736 int cem = (baseCEM - 1) * 4; |
| 1737 cem += (0 == C[i])? 0 : 4; |
| 1738 cem += M[i]; |
| 1739 |
| 1740 SkASSERT(cem < 16); |
| 1741 fCEM[i] = static_cast<ColorEndpointMode>(cem); |
| 1742 } |
| 1743 |
| 1744 // Finally, if we have dual plane mode, then read the plane selector. |
| 1745 this->decodeDualPlane(dualPlaneBitLoc); |
| 1746 } |
| 1747 |
| 1748 // Decodes the block mode. This function determines whether or not we use |
| 1749 // dual plane encoding, the size of the texel weight grid, and the number of |
| 1750 // bits, trits and quints that are used to encode it. For more information, |
| 1751 // see section C.2.10 of the ASTC spec. |
| 1752 // |
| 1753 // For 2D blocks, the Block Mode field is laid out as follows: |
| 1754 // |
| 1755 // ------------------------------------------------------------------------- |
| 1756 // 10 9 8 7 6 5 4 3 2 1 0 Width Height Notes |
| 1757 // ------------------------------------------------------------------------- |
| 1758 // D H B A R0 0 0 R2 R1 B+4 A+2 |
| 1759 // D H B A R0 0 1 R2 R1 B+8 A+2 |
| 1760 // D H B A R0 1 0 R2 R1 A+2 B+8 |
| 1761 // D H 0 B A R0 1 1 R2 R1 A+2 B+6 |
| 1762 // D H 1 B A R0 1 1 R2 R1 B+2 A+2 |
| 1763 // D H 0 0 A R0 R2 R1 0 0 12 A+2 |
| 1764 // D H 0 1 A R0 R2 R1 0 0 A+2 12 |
| 1765 // D H 1 1 0 0 R0 R2 R1 0 0 6 10 |
| 1766 // D H 1 1 0 1 R0 R2 R1 0 0 10 6 |
| 1767 // B 1 0 A R0 R2 R1 0 0 A+6 B+6 D=0, H=0 |
| 1768 // x x 1 1 1 1 1 1 1 0 0 - - Void-extent |
| 1769 // x x 1 1 1 x x x x 0 0 - - Reserved* |
| 1770 // x x x x x x x 0 0 0 0 - - Reserved |
| 1771 // ------------------------------------------------------------------------- |
| 1772 // |
| 1773 // D - dual plane enabled |
| 1774 // H, R - used to determine the number of bits/trits/quints in texel weight
encoding |
| 1775 // R is a three bit value whose LSB is R0 and MSB is R1 |
| 1776 // Width, Height - dimensions of the texel weight grid (determined by A and
B) |
| 1777 |
| 1778 void decodeBlockMode() { |
| 1779 const int blockMode = static_cast<int>(read_astc_bits(fBlock, 0, 11)); |
| 1780 |
| 1781 // Check for special void extent encoding |
| 1782 fVoidExtent = (blockMode & 0x1FF) == 0x1FC; |
| 1783 |
| 1784 // Check for reserved block modes |
| 1785 fError = ((blockMode & 0x1C3) == 0x1C0) || ((blockMode & 0xF) == 0); |
| 1786 |
| 1787 // Neither reserved nor void-extent, decode as usual |
| 1788 // This code corresponds to table C.2.8 of the ASTC spec |
| 1789 bool highPrecision = false; |
| 1790 int R = 0; |
| 1791 if ((blockMode & 0x3) == 0) { |
| 1792 R = ((0xC & blockMode) >> 1) | ((0x10 & blockMode) >> 4); |
| 1793 const int bitsSevenAndEight = (blockMode & 0x180) >> 7; |
| 1794 SkASSERT(0 <= bitsSevenAndEight && bitsSevenAndEight < 4); |
| 1795 |
| 1796 const int A = (blockMode >> 5) & 0x3; |
| 1797 const int B = (blockMode >> 9) & 0x3; |
| 1798 |
| 1799 fDualPlaneEnabled = (blockMode >> 10) & 0x1; |
| 1800 highPrecision = (blockMode >> 9) & 0x1; |
| 1801 |
| 1802 switch (bitsSevenAndEight) { |
| 1803 default: |
| 1804 case 0: |
| 1805 fWeightDimX = 12; |
| 1806 fWeightDimY = A + 2; |
| 1807 break; |
| 1808 |
| 1809 case 1: |
| 1810 fWeightDimX = A + 2; |
| 1811 fWeightDimY = 12; |
| 1812 break; |
| 1813 |
| 1814 case 2: |
| 1815 fWeightDimX = A + 6; |
| 1816 fWeightDimY = B + 6; |
| 1817 fDualPlaneEnabled = false; |
| 1818 highPrecision = false; |
| 1819 break; |
| 1820 |
| 1821 case 3: |
| 1822 if (0 == A) { |
| 1823 fWeightDimX = 6; |
| 1824 fWeightDimY = 10; |
| 1825 } else { |
| 1826 fWeightDimX = 10; |
| 1827 fWeightDimY = 6; |
| 1828 } |
| 1829 break; |
| 1830 } |
| 1831 } else { // (blockMode & 0x3) != 0 |
| 1832 R = ((blockMode & 0x3) << 1) | ((blockMode & 0x10) >> 4); |
| 1833 |
| 1834 const int bitsTwoAndThree = (blockMode >> 2) & 0x3; |
| 1835 SkASSERT(0 <= bitsTwoAndThree && bitsTwoAndThree < 4); |
| 1836 |
| 1837 const int A = (blockMode >> 5) & 0x3; |
| 1838 const int B = (blockMode >> 7) & 0x3; |
| 1839 |
| 1840 fDualPlaneEnabled = (blockMode >> 10) & 0x1; |
| 1841 highPrecision = (blockMode >> 9) & 0x1; |
| 1842 |
| 1843 switch (bitsTwoAndThree) { |
| 1844 case 0: |
| 1845 fWeightDimX = B + 4; |
| 1846 fWeightDimY = A + 2; |
| 1847 break; |
| 1848 case 1: |
| 1849 fWeightDimX = B + 8; |
| 1850 fWeightDimY = A + 2; |
| 1851 break; |
| 1852 case 2: |
| 1853 fWeightDimX = A + 2; |
| 1854 fWeightDimY = B + 8; |
| 1855 break; |
| 1856 case 3: |
| 1857 if ((B & 0x2) == 0) { |
| 1858 fWeightDimX = A + 2; |
| 1859 fWeightDimY = (B & 1) + 6; |
| 1860 } else { |
| 1861 fWeightDimX = (B & 1) + 2; |
| 1862 fWeightDimY = A + 2; |
| 1863 } |
| 1864 break; |
| 1865 } |
| 1866 } |
| 1867 |
| 1868 // We should have set the values of R and highPrecision |
| 1869 // from decoding the block mode, these are used to determine |
| 1870 // the proper dimensions of our weight grid. |
| 1871 if ((R & 0x6) == 0) { |
| 1872 fError = true; |
| 1873 } else { |
| 1874 static const int kBitAllocationTable[2][6][3] = { |
| 1875 { |
| 1876 { 1, 0, 0 }, |
| 1877 { 0, 1, 0 }, |
| 1878 { 2, 0, 0 }, |
| 1879 { 0, 0, 1 }, |
| 1880 { 1, 1, 0 }, |
| 1881 { 3, 0, 0 } |
| 1882 }, |
| 1883 { |
| 1884 { 1, 0, 1 }, |
| 1885 { 2, 1, 0 }, |
| 1886 { 4, 0, 0 }, |
| 1887 { 2, 0, 1 }, |
| 1888 { 3, 1, 0 }, |
| 1889 { 5, 0, 0 } |
| 1890 } |
| 1891 }; |
| 1892 |
| 1893 fWeightBits = kBitAllocationTable[highPrecision][R - 2][0]; |
| 1894 fWeightTrits = kBitAllocationTable[highPrecision][R - 2][1]; |
| 1895 fWeightQuints = kBitAllocationTable[highPrecision][R - 2][2]; |
| 1896 } |
| 1897 } |
| 1898 }; |
| 1899 |
| 1900 // Reads an ASTC block from the given pointer. |
| 1901 static inline void read_astc_block(ASTCDecompressionData *dst, const uint8_t* sr
c) { |
| 1902 const uint64_t* qword = reinterpret_cast<const uint64_t*>(src); |
| 1903 dst->fBlock.fLow = SkEndian_SwapLE64(qword[0]); |
| 1904 dst->fBlock.fHigh = SkEndian_SwapLE64(qword[1]); |
| 1905 dst->decode(); |
| 1906 } |
| 1907 |
| 1908 // Take a known void-extent block, and write out the values as a constant color. |
| 1909 static void decompress_void_extent(uint8_t* dst, int dstRowBytes, |
| 1910 const ASTCDecompressionData &data) { |
| 1911 // The top 64 bits contain 4 16-bit RGBA values. |
| 1912 int a = (static_cast<int>(read_astc_bits(data.fBlock, 112, 128)) + 255) >> 8
; |
| 1913 int b = (static_cast<int>(read_astc_bits(data.fBlock, 96, 112)) + 255) >> 8; |
| 1914 int g = (static_cast<int>(read_astc_bits(data.fBlock, 80, 96)) + 255) >> 8; |
| 1915 int r = (static_cast<int>(read_astc_bits(data.fBlock, 64, 80)) + 255) >> 8; |
| 1916 |
| 1917 write_constant_color(dst, data.fDimX, data.fDimY, dstRowBytes, SkColorSetARG
B(a, r, g, b)); |
| 1918 } |
| 1919 |
| 1920 // Decompresses a single ASTC block. It's assumed that data.fDimX and data.fDimY
are |
| 1921 // set and that the block has already been decoded (i.e. data.decode() has been
called) |
| 1922 static void decompress_astc_block(uint8_t* dst, int dstRowBytes, |
| 1923 const ASTCDecompressionData &data) { |
| 1924 if (data.fError) { |
| 1925 write_error_color(dst, data.fDimX, data.fDimY, dstRowBytes); |
| 1926 return; |
| 1927 } |
| 1928 |
| 1929 if (data.fVoidExtent) { |
| 1930 decompress_void_extent(dst, dstRowBytes, data); |
| 1931 return; |
| 1932 } |
| 1933 |
| 1934 // According to the spec, any more than 64 values is illegal. (C.2.24) |
| 1935 static const int kMaxTexelValues = 64; |
| 1936 |
| 1937 // Decode the texel weights. |
| 1938 int texelValues[kMaxTexelValues]; |
| 1939 bool success = decode_integer_sequence( |
| 1940 texelValues, kMaxTexelValues, data.numWeights(), |
| 1941 // texel data goes to the end of the 128 bit block. |
| 1942 data.fBlock, 128, 128 - data.numWeightBits(), false, |
| 1943 data.fWeightBits, data.fWeightTrits, data.fWeightQuints); |
| 1944 |
| 1945 if (!success) { |
| 1946 write_error_color(dst, data.fDimX, data.fDimY, dstRowBytes); |
| 1947 return; |
| 1948 } |
| 1949 |
| 1950 // Decode the color endpoints |
| 1951 int colorBits, colorTrits, colorQuints; |
| 1952 if (!data.getColorValueEncoding(&colorBits, &colorTrits, &colorQuints)) { |
| 1953 write_error_color(dst, data.fDimX, data.fDimY, dstRowBytes); |
| 1954 return; |
| 1955 } |
| 1956 |
| 1957 // According to the spec, any more than 18 color values is illegal. (C.2.24) |
| 1958 static const int kMaxColorValues = 18; |
| 1959 |
| 1960 int colorValues[kMaxColorValues]; |
| 1961 success = decode_integer_sequence( |
| 1962 colorValues, kMaxColorValues, data.numColorValues(), |
| 1963 data.fBlock, data.fColorStartBit, data.fColorEndBit, true, |
| 1964 colorBits, colorTrits, colorQuints); |
| 1965 |
| 1966 if (!success) { |
| 1967 write_error_color(dst, data.fDimX, data.fDimY, dstRowBytes); |
| 1968 return; |
| 1969 } |
| 1970 |
| 1971 // Unquantize the color values after they've been decoded. |
| 1972 unquantize_colors(colorValues, data.numColorValues(), colorBits, colorTrits,
colorQuints); |
| 1973 |
| 1974 // Decode the colors into the appropriate endpoints. |
| 1975 SkColor endpoints[4][2]; |
| 1976 data.colorEndpoints(endpoints, colorValues); |
| 1977 |
| 1978 // Do texel infill and decode the texel values. |
| 1979 int texelWeights[2][12][12]; |
| 1980 data.texelWeights(texelWeights, texelValues); |
| 1981 |
| 1982 // Write the texels by interpolating them based on the information |
| 1983 // stored in the block. |
| 1984 dst += data.fDimY * dstRowBytes; |
| 1985 for (int y = 0; y < data.fDimY; ++y) { |
| 1986 dst -= dstRowBytes; |
| 1987 SkColor* colorPtr = reinterpret_cast<SkColor*>(dst); |
| 1988 for (int x = 0; x < data.fDimX; ++x) { |
| 1989 colorPtr[x] = data.getTexel(endpoints, texelWeights, x, y); |
| 1990 } |
| 1991 } |
| 1992 } |
| 1993 |
| 1994 //////////////////////////////////////////////////////////////////////////////// |
264 | 1995 |
265 namespace SkTextureCompressor { | 1996 namespace SkTextureCompressor { |
266 | 1997 |
267 bool CompressA8To12x12ASTC(uint8_t* dst, const uint8_t* src, int width, int heig
ht, int rowBytes) { | 1998 bool CompressA8To12x12ASTC(uint8_t* dst, const uint8_t* src, |
| 1999 int width, int height, int rowBytes) { |
268 if (width < 0 || ((width % 12) != 0) || height < 0 || ((height % 12) != 0))
{ | 2000 if (width < 0 || ((width % 12) != 0) || height < 0 || ((height % 12) != 0))
{ |
269 return false; | 2001 return false; |
270 } | 2002 } |
271 | 2003 |
272 uint8_t** dstPtr = &dst; | 2004 uint8_t** dstPtr = &dst; |
273 for (int y = 0; y < height; y += 12) { | 2005 for (int y = 0; y < height; y += 12) { |
274 for (int x = 0; x < width; x += 12) { | 2006 for (int x = 0; x < width; x += 12) { |
275 compress_a8_astc_block<GetAlpha>(dstPtr, src + y*rowBytes + x, rowBy
tes); | 2007 compress_a8_astc_block<GetAlpha>(dstPtr, src + y*rowBytes + x, rowBy
tes); |
276 } | 2008 } |
277 } | 2009 } |
278 | 2010 |
279 return true; | 2011 return true; |
280 } | 2012 } |
281 | 2013 |
282 SkBlitter* CreateASTCBlitter(int width, int height, void* outputBuffer) { | 2014 SkBlitter* CreateASTCBlitter(int width, int height, void* outputBuffer) { |
283 return new | 2015 return new |
284 SkTCompressedAlphaBlitter<12, 16, CompressA8ASTCBlockVertical> | 2016 SkTCompressedAlphaBlitter<12, 16, CompressA8ASTCBlockVertical> |
285 (width, height, outputBuffer); | 2017 (width, height, outputBuffer); |
286 } | 2018 } |
287 | 2019 |
| 2020 void DecompressASTC(uint8_t* dst, int dstRowBytes, const uint8_t* src, |
| 2021 int width, int height, int blockDimX, int blockDimY) { |
| 2022 // ASTC is encoded in what they call "raster order", so that the first |
| 2023 // block is the bottom-left block in the image, and the first pixel |
| 2024 // is the bottom-left pixel of the image |
| 2025 dst += height * dstRowBytes; |
| 2026 |
| 2027 ASTCDecompressionData data(blockDimX, blockDimY); |
| 2028 for (int y = 0; y < height; y += blockDimY) { |
| 2029 dst -= blockDimY * dstRowBytes; |
| 2030 SkColor *colorPtr = reinterpret_cast<SkColor*>(dst); |
| 2031 for (int x = 0; x < width; x += blockDimX) { |
| 2032 read_astc_block(&data, src); |
| 2033 decompress_astc_block(reinterpret_cast<uint8_t*>(colorPtr + x), dstR
owBytes, data); |
| 2034 |
| 2035 // ASTC encoded blocks are 16 bytes (128 bits) large. |
| 2036 src += 16; |
| 2037 } |
| 2038 } |
| 2039 } |
| 2040 |
288 } // SkTextureCompressor | 2041 } // SkTextureCompressor |
OLD | NEW |