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 |