| 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 |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 // Pack indices... The ASTC block layout is fairly complicated. An extensive | 210 // Pack indices... The ASTC block layout is fairly complicated. An extensive |
| 211 // description can be found here: | 211 // description can be found here: |
| 212 // https://www.opengl.org/registry/specs/KHR/texture_compression_astc_hdr.tx
t | 212 // https://www.opengl.org/registry/specs/KHR/texture_compression_astc_hdr.tx
t |
| 213 // | 213 // |
| 214 // Here is a summary of the options that we've chosen: | 214 // Here is a summary of the options that we've chosen: |
| 215 // 1. Block mode: 0b00101110011 | 215 // 1. Block mode: 0b00101110011 |
| 216 // - 6x5 texel grid | 216 // - 6x5 texel grid |
| 217 // - Single plane | 217 // - Single plane |
| 218 // - Low-precision index values | 218 // - Low-precision index values |
| 219 // - Index range 0-7 (three bits per index) | 219 // - Index range 0-7 (three bits per index) |
| 220 // 2. Partitions: 0b00 | 220 // 2. Partitions: 0b00 |
| 221 // - One partition | 221 // - One partition |
| 222 // 3. Color Endpoint Mode: 0b0000 | 222 // 3. Color Endpoint Mode: 0b0000 |
| 223 // - Direct luminance -- e0=(v0,v0,v0,0xFF); e1=(v1,v1,v1,0xFF); | 223 // - Direct luminance -- e0=(v0,v0,v0,0xFF); e1=(v1,v1,v1,0xFF); |
| 224 // 4. 8-bit endpoints: | 224 // 4. 8-bit endpoints: |
| 225 // v0 = 0, v1 = 255 | 225 // v0 = 0, v1 = 255 |
| 226 // | 226 // |
| 227 // The rest of the block contains the 30 index values from before, which | 227 // The rest of the block contains the 30 index values from before, which |
| 228 // are currently stored in the indices variable. | 228 // are currently stored in the indices variable. |
| 229 | 229 |
| 230 uint64_t top = 0x0000000001FE000173ULL; | 230 uint64_t top = 0x0000000001FE000173ULL; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 | 263 |
| 264 //////////////////////////////////////////////////////////////////////////////// | 264 //////////////////////////////////////////////////////////////////////////////// |
| 265 // | 265 // |
| 266 // ASTC Decoder | 266 // ASTC Decoder |
| 267 // | 267 // |
| 268 // Full details available in the spec: | 268 // Full details available in the spec: |
| 269 // http://www.khronos.org/registry/gles/extensions/OES/OES_texture_compression_a
stc.txt | 269 // http://www.khronos.org/registry/gles/extensions/OES/OES_texture_compression_a
stc.txt |
| 270 // | 270 // |
| 271 //////////////////////////////////////////////////////////////////////////////// | 271 //////////////////////////////////////////////////////////////////////////////// |
| 272 | 272 |
| 273 // Enable this to assert whenever a decoded block has invalid ASTC values. Other
wise, | 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. | 274 // each invalid block will result in a disgusting magenta color. |
| 275 #define ASSERT_ASTC_DECODE_ERROR 0 | 275 #define ASSERT_ASTC_DECODE_ERROR 0 |
| 276 | 276 |
| 277 // Reverse 64-bit integer taken from TAOCP 4a, although it's better | 277 // Reverse 64-bit integer taken from TAOCP 4a, although it's better |
| 278 // documented at this site: | 278 // documented at this site: |
| 279 // http://matthewarcus.wordpress.com/2012/11/18/reversing-a-64-bit-word/ | 279 // http://matthewarcus.wordpress.com/2012/11/18/reversing-a-64-bit-word/ |
| 280 | 280 |
| 281 template <typename T, T m, int k> | 281 template <typename T, T m, int k> |
| 282 static inline T swap_bits(T p) { | 282 static inline T swap_bits(T p) { |
| 283 T q = ((p>>k)^p) & m; | 283 T q = ((p>>k)^p) & m; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 // All desired bits are in the low 64-bits. | 362 // All desired bits are in the low 64-bits. |
| 363 result = (block.fLow >> from) & ((1ULL << nBits) - 1); | 363 result = (block.fLow >> from) & ((1ULL << nBits) - 1); |
| 364 } else if (from >= 64) { | 364 } else if (from >= 64) { |
| 365 // All desired bits are in the high 64-bits. | 365 // All desired bits are in the high 64-bits. |
| 366 result = (block.fHigh >> (from - 64)) & ((1ULL << nBits) - 1); | 366 result = (block.fHigh >> (from - 64)) & ((1ULL << nBits) - 1); |
| 367 } else { | 367 } else { |
| 368 // from < 64 && to > 64 | 368 // from < 64 && to > 64 |
| 369 SkASSERT(nBits > (64 - from)); | 369 SkASSERT(nBits > (64 - from)); |
| 370 const int nLow = 64 - from; | 370 const int nLow = 64 - from; |
| 371 const int nHigh = nBits - nLow; | 371 const int nHigh = nBits - nLow; |
| 372 result = | 372 result = |
| 373 ((block.fLow >> from) & ((1ULL << nLow) - 1)) | | 373 ((block.fLow >> from) & ((1ULL << nLow) - 1)) | |
| 374 ((block.fHigh & ((1ULL << nHigh) - 1)) << nLow); | 374 ((block.fHigh & ((1ULL << nHigh) - 1)) << nLow); |
| 375 } | 375 } |
| 376 | 376 |
| 377 return result; | 377 return result; |
| 378 } | 378 } |
| 379 | 379 |
| 380 // Returns the number of bits needed to represent a number | 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). | 381 // in the given power-of-two range (excluding the power of two itself). |
| 382 static inline int bits_for_range(int x) { | 382 static inline int bits_for_range(int x) { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 445 // kLDR_RGB_BaseScale_ColorEndpointMode | 445 // kLDR_RGB_BaseScale_ColorEndpointMode |
| 446 // kLDR_RGB_BaseScaleWithAlpha_ColorEndpointMode | 446 // kLDR_RGB_BaseScaleWithAlpha_ColorEndpointMode |
| 447 static inline void decode_rgba_basescale(const int *v, SkColor *endpoints, bool
isRGB) { | 447 static inline void decode_rgba_basescale(const int *v, SkColor *endpoints, bool
isRGB) { |
| 448 | 448 |
| 449 int v4 = 0xFF; | 449 int v4 = 0xFF; |
| 450 int v5 = 0xFF; | 450 int v5 = 0xFF; |
| 451 if (!isRGB) { | 451 if (!isRGB) { |
| 452 v4 = v[4]; | 452 v4 = v[4]; |
| 453 v5 = v[5]; | 453 v5 = v[5]; |
| 454 } | 454 } |
| 455 | 455 |
| 456 endpoints[0] = SkColorSetARGB(v4, | 456 endpoints[0] = SkColorSetARGB(v4, |
| 457 (v[0]*v[3]) >> 8, | 457 (v[0]*v[3]) >> 8, |
| 458 (v[1]*v[3]) >> 8, | 458 (v[1]*v[3]) >> 8, |
| 459 (v[2]*v[3]) >> 8); | 459 (v[2]*v[3]) >> 8); |
| 460 endpoints[1] = SkColorSetARGB(v5, v[0], v[1], v[2]); | 460 endpoints[1] = SkColorSetARGB(v5, v[0], v[1], v[2]); |
| 461 } | 461 } |
| 462 | 462 |
| 463 // Helper function that decodes two colors from eight values. If isRGB is true, | 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 | 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 | 465 // 0xFF. If isRGB is false, then all eight values come from the pointer 'v'. Thi
s |
| (...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1249 | 1249 |
| 1250 endpoints[i][0] = SkColorSetARGB(0xFF, L0, L0, L0); | 1250 endpoints[i][0] = SkColorSetARGB(0xFF, L0, L0, L0); |
| 1251 endpoints[i][1] = SkColorSetARGB(0xFF, L1, L1, L1); | 1251 endpoints[i][1] = SkColorSetARGB(0xFF, L1, L1, L1); |
| 1252 | 1252 |
| 1253 colorValues += 2; | 1253 colorValues += 2; |
| 1254 } | 1254 } |
| 1255 break; | 1255 break; |
| 1256 | 1256 |
| 1257 case kLDR_LuminanceAlpha_Direct_ColorEndpointMode: { | 1257 case kLDR_LuminanceAlpha_Direct_ColorEndpointMode: { |
| 1258 const int* v = colorValues; | 1258 const int* v = colorValues; |
| 1259 | 1259 |
| 1260 endpoints[i][0] = SkColorSetARGB(v[2], v[0], v[0], v[0]); | 1260 endpoints[i][0] = SkColorSetARGB(v[2], v[0], v[0], v[0]); |
| 1261 endpoints[i][1] = SkColorSetARGB(v[3], v[1], v[1], v[1]); | 1261 endpoints[i][1] = SkColorSetARGB(v[3], v[1], v[1], v[1]); |
| 1262 | 1262 |
| 1263 colorValues += 4; | 1263 colorValues += 4; |
| 1264 } | 1264 } |
| 1265 break; | 1265 break; |
| 1266 | 1266 |
| 1267 case kLDR_LuminanceAlpha_BaseOffset_ColorEndpointMode: { | 1267 case kLDR_LuminanceAlpha_BaseOffset_ColorEndpointMode: { |
| 1268 int v0 = colorValues[0]; | 1268 int v0 = colorValues[0]; |
| 1269 int v1 = colorValues[1]; | 1269 int v1 = colorValues[1]; |
| 1270 int v2 = colorValues[2]; | 1270 int v2 = colorValues[2]; |
| 1271 int v3 = colorValues[3]; | 1271 int v3 = colorValues[3]; |
| 1272 | 1272 |
| 1273 bit_transfer_signed(&v1, &v0); | 1273 bit_transfer_signed(&v1, &v0); |
| 1274 bit_transfer_signed(&v3, &v2); | 1274 bit_transfer_signed(&v3, &v2); |
| 1275 | 1275 |
| 1276 endpoints[i][0] = SkColorSetARGB(v2, v0, v0, v0); | 1276 endpoints[i][0] = SkColorSetARGB(v2, v0, v0, v0); |
| 1277 endpoints[i][1] = SkColorSetARGB( | 1277 endpoints[i][1] = SkColorSetARGB( |
| 1278 clamp_byte(v3+v2), | 1278 clamp_byte(v3+v2), |
| 1279 clamp_byte(v1+v0), | 1279 clamp_byte(v1+v0), |
| 1280 clamp_byte(v1+v0), | 1280 clamp_byte(v1+v0), |
| 1281 clamp_byte(v1+v0)); | 1281 clamp_byte(v1+v0)); |
| 1282 | 1282 |
| 1283 colorValues += 4; | 1283 colorValues += 4; |
| 1284 } | 1284 } |
| 1285 break; | 1285 break; |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1662 | 1662 |
| 1663 // If there's only one partition, then our job is (relatively) easy. | 1663 // If there's only one partition, then our job is (relatively) easy. |
| 1664 if (this->numPartitions() == 1) { | 1664 if (this->numPartitions() == 1) { |
| 1665 fCEM[0] = static_cast<ColorEndpointMode>(read_astc_bits(fBlock, 13,
17)); | 1665 fCEM[0] = static_cast<ColorEndpointMode>(read_astc_bits(fBlock, 13,
17)); |
| 1666 fColorStartBit = 17; | 1666 fColorStartBit = 17; |
| 1667 | 1667 |
| 1668 // Handle dual plane mode... | 1668 // Handle dual plane mode... |
| 1669 this->decodeDualPlane(dualPlaneBitLoc); | 1669 this->decodeDualPlane(dualPlaneBitLoc); |
| 1670 | 1670 |
| 1671 return; | 1671 return; |
| 1672 } | 1672 } |
| 1673 | 1673 |
| 1674 // If we have more than one partition, then we need to make | 1674 // If we have more than one partition, then we need to make |
| 1675 // room for the partition index. | 1675 // room for the partition index. |
| 1676 fColorStartBit = 29; | 1676 fColorStartBit = 29; |
| 1677 | 1677 |
| 1678 // Read the base CEM. If it's zero, then we have no additional | 1678 // Read the base CEM. If it's zero, then we have no additional |
| 1679 // CEM data and the endpoints for each partition share the same CEM. | 1679 // CEM data and the endpoints for each partition share the same CEM. |
| 1680 const int baseCEM = static_cast<int>(read_astc_bits(fBlock, 23, 25)); | 1680 const int baseCEM = static_cast<int>(read_astc_bits(fBlock, 23, 25)); |
| 1681 if (0 == baseCEM) { | 1681 if (0 == baseCEM) { |
| 1682 | 1682 |
| 1683 const ColorEndpointMode sameCEM = | 1683 const ColorEndpointMode sameCEM = |
| 1684 static_cast<ColorEndpointMode>(read_astc_bits(fBlock, 25, 29)); | 1684 static_cast<ColorEndpointMode>(read_astc_bits(fBlock, 25, 29)); |
| 1685 | 1685 |
| 1686 for (int i = 0; i < kMaxPartitions; ++i) { | 1686 for (int i = 0; i < kMaxPartitions; ++i) { |
| 1687 fCEM[i] = sameCEM; | 1687 fCEM[i] = sameCEM; |
| 1688 } | 1688 } |
| 1689 | 1689 |
| 1690 // Handle dual plane mode... | 1690 // Handle dual plane mode... |
| 1691 this->decodeDualPlane(dualPlaneBitLoc); | 1691 this->decodeDualPlane(dualPlaneBitLoc); |
| 1692 | 1692 |
| 1693 return; | 1693 return; |
| 1694 } | 1694 } |
| 1695 | 1695 |
| 1696 // Move the dual plane selector bits down based on how many | 1696 // Move the dual plane selector bits down based on how many |
| 1697 // partitions the block contains. | 1697 // partitions the block contains. |
| 1698 switch (this->numPartitions()) { | 1698 switch (this->numPartitions()) { |
| 1699 case 2: | 1699 case 2: |
| 1700 dualPlaneBitLoc -= 2; | 1700 dualPlaneBitLoc -= 2; |
| 1701 break; | 1701 break; |
| 1702 | 1702 |
| 1703 case 3: | 1703 case 3: |
| 1704 dualPlaneBitLoc -= 5; | 1704 dualPlaneBitLoc -= 5; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1749 SkASSERT(cem < 16); | 1749 SkASSERT(cem < 16); |
| 1750 fCEM[i] = static_cast<ColorEndpointMode>(cem); | 1750 fCEM[i] = static_cast<ColorEndpointMode>(cem); |
| 1751 } | 1751 } |
| 1752 | 1752 |
| 1753 // Finally, if we have dual plane mode, then read the plane selector. | 1753 // Finally, if we have dual plane mode, then read the plane selector. |
| 1754 this->decodeDualPlane(dualPlaneBitLoc); | 1754 this->decodeDualPlane(dualPlaneBitLoc); |
| 1755 } | 1755 } |
| 1756 | 1756 |
| 1757 // Decodes the block mode. This function determines whether or not we use | 1757 // Decodes the block mode. This function determines whether or not we use |
| 1758 // dual plane encoding, the size of the texel weight grid, and the number of | 1758 // dual plane encoding, the size of the texel weight grid, and the number of |
| 1759 // bits, trits and quints that are used to encode it. For more information, | 1759 // bits, trits and quints that are used to encode it. For more information, |
| 1760 // see section C.2.10 of the ASTC spec. | 1760 // see section C.2.10 of the ASTC spec. |
| 1761 // | 1761 // |
| 1762 // For 2D blocks, the Block Mode field is laid out as follows: | 1762 // For 2D blocks, the Block Mode field is laid out as follows: |
| 1763 // | 1763 // |
| 1764 // ------------------------------------------------------------------------- | 1764 // ------------------------------------------------------------------------- |
| 1765 // 10 9 8 7 6 5 4 3 2 1 0 Width Height Notes | 1765 // 10 9 8 7 6 5 4 3 2 1 0 Width Height Notes |
| 1766 // ------------------------------------------------------------------------- | 1766 // ------------------------------------------------------------------------- |
| 1767 // D H B A R0 0 0 R2 R1 B+4 A+2 | 1767 // D H B A R0 0 0 R2 R1 B+4 A+2 |
| 1768 // D H B A R0 0 1 R2 R1 B+8 A+2 | 1768 // D H B A R0 0 1 R2 R1 B+8 A+2 |
| 1769 // D H B A R0 1 0 R2 R1 A+2 B+8 | 1769 // D H B A R0 1 0 R2 R1 A+2 B+8 |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2092 read_astc_block(&data, src); | 2092 read_astc_block(&data, src); |
| 2093 decompress_astc_block(reinterpret_cast<uint8_t*>(colorPtr + x), dstR
owBytes, data); | 2093 decompress_astc_block(reinterpret_cast<uint8_t*>(colorPtr + x), dstR
owBytes, data); |
| 2094 | 2094 |
| 2095 // ASTC encoded blocks are 16 bytes (128 bits) large. | 2095 // ASTC encoded blocks are 16 bytes (128 bits) large. |
| 2096 src += 16; | 2096 src += 16; |
| 2097 } | 2097 } |
| 2098 } | 2098 } |
| 2099 } | 2099 } |
| 2100 | 2100 |
| 2101 } // SkTextureCompressor | 2101 } // SkTextureCompressor |
| OLD | NEW |