Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(231)

Side by Side Diff: src/utils/SkTextureCompressor_ASTC.cpp

Issue 444103002: Revert of Initial ASTC decoder -- currently only supports 2D LDR decomrpession modes. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/utils/SkTextureCompressor_ASTC.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
OLDNEW
« no previous file with comments | « src/utils/SkTextureCompressor_ASTC.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698