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" | |
14 | 13 |
15 // This table contains the weight values for each texel. This is used in determi
ning | 14 // This table contains the weight values for each texel. This is used in determi
ning |
16 // how to convert a 12x12 grid of alpha values into a 6x5 grid of index values.
Since | 15 // how to convert a 12x12 grid of alpha values into a 6x5 grid of index values.
Since |
17 // we have a 6x5 grid, that gives 30 values that we have to compute. For each in
dex, | 16 // we have a 6x5 grid, that gives 30 values that we have to compute. For each in
dex, |
18 // we store up to 20 different triplets of values. In order the triplets are: | 17 // we store up to 20 different triplets of values. In order the triplets are: |
19 // weight, texel-x, texel-y | 18 // weight, texel-x, texel-y |
20 // The weight value corresponds to the amount that this index contributes to the
final | 19 // The weight value corresponds to the amount that this index contributes to the
final |
21 // index value of the given texel. Hence, we need to reconstruct the 6x5 index g
rid | 20 // index value of the given texel. Hence, we need to reconstruct the 6x5 index g
rid |
22 // from their relative contribution to the 12x12 texel grid. | 21 // from their relative contribution to the 12x12 texel grid. |
23 // | 22 // |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 top = top ^ t ^ (t << 2); | 254 top = top ^ t ^ (t << 2); |
256 | 255 |
257 send_packing(dst, SkEndian_SwapLE64(top), SkEndian_SwapLE64(bottom)); | 256 send_packing(dst, SkEndian_SwapLE64(top), SkEndian_SwapLE64(bottom)); |
258 } | 257 } |
259 | 258 |
260 inline void CompressA8ASTCBlockVertical(uint8_t* dst, const uint8_t* src) { | 259 inline void CompressA8ASTCBlockVertical(uint8_t* dst, const uint8_t* src) { |
261 compress_a8_astc_block<GetAlphaTranspose>(&dst, src, 12); | 260 compress_a8_astc_block<GetAlphaTranspose>(&dst, src, 12); |
262 } | 261 } |
263 | 262 |
264 //////////////////////////////////////////////////////////////////////////////// | 263 //////////////////////////////////////////////////////////////////////////////// |
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 #if 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 #if 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 //////////////////////////////////////////////////////////////////////////////// | |
1995 | 264 |
1996 namespace SkTextureCompressor { | 265 namespace SkTextureCompressor { |
1997 | 266 |
1998 bool CompressA8To12x12ASTC(uint8_t* dst, const uint8_t* src, | 267 bool CompressA8To12x12ASTC(uint8_t* dst, const uint8_t* src, int width, int heig
ht, int rowBytes) { |
1999 int width, int height, int rowBytes) { | |
2000 if (width < 0 || ((width % 12) != 0) || height < 0 || ((height % 12) != 0))
{ | 268 if (width < 0 || ((width % 12) != 0) || height < 0 || ((height % 12) != 0))
{ |
2001 return false; | 269 return false; |
2002 } | 270 } |
2003 | 271 |
2004 uint8_t** dstPtr = &dst; | 272 uint8_t** dstPtr = &dst; |
2005 for (int y = 0; y < height; y += 12) { | 273 for (int y = 0; y < height; y += 12) { |
2006 for (int x = 0; x < width; x += 12) { | 274 for (int x = 0; x < width; x += 12) { |
2007 compress_a8_astc_block<GetAlpha>(dstPtr, src + y*rowBytes + x, rowBy
tes); | 275 compress_a8_astc_block<GetAlpha>(dstPtr, src + y*rowBytes + x, rowBy
tes); |
2008 } | 276 } |
2009 } | 277 } |
2010 | 278 |
2011 return true; | 279 return true; |
2012 } | 280 } |
2013 | 281 |
2014 SkBlitter* CreateASTCBlitter(int width, int height, void* outputBuffer) { | 282 SkBlitter* CreateASTCBlitter(int width, int height, void* outputBuffer) { |
2015 return new | 283 return new |
2016 SkTCompressedAlphaBlitter<12, 16, CompressA8ASTCBlockVertical> | 284 SkTCompressedAlphaBlitter<12, 16, CompressA8ASTCBlockVertical> |
2017 (width, height, outputBuffer); | 285 (width, height, outputBuffer); |
2018 } | 286 } |
2019 | 287 |
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 | |
2041 } // SkTextureCompressor | 288 } // SkTextureCompressor |
OLD | NEW |