pavel | 47eedcc | 2014-10-23 13:18:50 -0700 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 2014 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
| 7 | |
| 8 | #ifndef SkTextureCompressorUtils_DEFINED |
| 9 | #define SkTextureCompressorUtils_DEFINED |
| 10 | |
| 11 | namespace SkTextureCompressor { |
| 12 | |
| 13 | // In some compression formats used for grayscale alpha, i.e. coverage masks, three |
| 14 | // bit indices are used to represent each pixel. A compression scheme must therefore |
| 15 | // quantize the full eight bits of grayscale to three bits. The simplest way to do |
| 16 | // this is to take the top three bits of the grayscale value. However, this does not |
| 17 | // provide an accurate quantization: 192 will be quantized to 219 instead of 185. In |
| 18 | // our compression schemes, we let these three-bit indices represent the full range |
| 19 | // of grayscale values, and so when we go from three bits to eight bits, we replicate |
| 20 | // the three bits into the lower bits of the eight bit value. Below are two different |
| 21 | // techniques that offer a quality versus speed tradeoff in terms of quantization. |
| 22 | #if 1 |
| 23 | // Divides each byte in the 32-bit argument by three. |
| 24 | static inline uint32_t MultibyteDiv3(uint32_t x) { |
| 25 | const uint32_t a = (x >> 2) & 0x3F3F3F3F; |
| 26 | const uint32_t ar = (x & 0x03030303) << 4; |
| 27 | |
| 28 | const uint32_t b = (x >> 4) & 0x0F0F0F0F; |
| 29 | const uint32_t br = (x & 0x0F0F0F0F) << 2; |
| 30 | |
| 31 | const uint32_t c = (x >> 6) & 0x03030303; |
| 32 | const uint32_t cr = x & 0x3F3F3F3F; |
| 33 | |
| 34 | return a + b + c + (((ar + br + cr) >> 6) & 0x03030303); |
| 35 | } |
| 36 | |
| 37 | // Takes a loaded 32-bit integer of four 8-bit greyscale values and returns their |
| 38 | // quantization into 3-bit values, used by LATC and R11 EAC. Instead of taking the |
| 39 | // top three bits, the function computes the best three-bit value such that its |
| 40 | // reconstruction into an eight bit value via bit replication will yield the best |
| 41 | // results. In a 32-bit integer taking the range of values from 0-255 we would add |
| 42 | // 18 and divide by 36 (255 / 36 ~= 7). However, since we are working in constrained |
| 43 | // 8-bit space, our algorithm is the following: |
| 44 | // 1. Shift right by one to give room for overflow |
| 45 | // 2. Add 9 (18/2) |
| 46 | // 3. Divide by 18 (divide by two, then by three twice) |
| 47 | static inline uint32_t ConvertToThreeBitIndex(uint32_t x) { |
| 48 | x = (x >> 1) & 0x7F7F7F7F; // 1 |
| 49 | x = x + 0x09090909; // 2 |
| 50 | |
| 51 | // Need to divide by 18... so first divide by two |
| 52 | x = (x >> 1) & 0x7F7F7F7F; |
| 53 | |
| 54 | // Now divide by three twice |
| 55 | x = MultibyteDiv3(x); |
| 56 | x = MultibyteDiv3(x); |
| 57 | return x; |
| 58 | } |
| 59 | #else |
| 60 | // Moves the top three bits of each byte in the 32-bit argument to the least |
| 61 | // significant bits of their respective byte. |
| 62 | static inline uint32_t ConvertToThreeBitIndex(uint32_t x) { |
| 63 | return (x >> 5) & 0x07070707; |
| 64 | } |
| 65 | #endif |
| 66 | } |
| 67 | |
| 68 | #endif // SkTextureCompressorUtils_DEFINED |