aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/utils/SkTextureCompressor_Utils.h
blob: 9b115a29647b95525cf445db686a65d92f4849fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

#ifndef SkTextureCompressorUtils_DEFINED
#define SkTextureCompressorUtils_DEFINED

namespace SkTextureCompressor {

    // In some compression formats used for grayscale alpha, i.e. coverage masks, three
    // bit indices are used to represent each pixel. A compression scheme must therefore
    // quantize the full eight bits of grayscale to three bits. The simplest way to do
    // this is to take the top three bits of the grayscale value. However, this does not
    // provide an accurate quantization: 192 will be quantized to 219 instead of 185. In
    // our compression schemes, we let these three-bit indices represent the full range
    // of grayscale values, and so when we go from three bits to eight bits, we replicate
    // the three bits into the lower bits of the eight bit value. Below are two different
    // techniques that offer a quality versus speed tradeoff in terms of quantization.
#if 1
    // Divides each byte in the 32-bit argument by three.
    static inline uint32_t MultibyteDiv3(uint32_t x) {
        const uint32_t a = (x >> 2) & 0x3F3F3F3F;
        const uint32_t ar = (x & 0x03030303) << 4;

        const uint32_t b = (x >> 4) & 0x0F0F0F0F;
        const uint32_t br = (x & 0x0F0F0F0F) << 2;

        const uint32_t c = (x >> 6) & 0x03030303;
        const uint32_t cr = x & 0x3F3F3F3F;

        return a + b + c + (((ar + br + cr) >> 6) & 0x03030303);
    }

    // Takes a loaded 32-bit integer of four 8-bit greyscale values and returns their
    // quantization into 3-bit values, used by LATC and R11 EAC. Instead of taking the
    // top three bits, the function computes the best three-bit value such that its
    // reconstruction into an eight bit value via bit replication will yield the best
    // results. In a 32-bit integer taking the range of values from 0-255 we would add
    // 18 and divide by 36 (255 / 36 ~= 7). However, since we are working in constrained
    // 8-bit space, our algorithm is the following:
    // 1. Shift right by one to give room for overflow
    // 2. Add 9 (18/2)
    // 3. Divide by 18 (divide by two, then by three twice)
    static inline uint32_t ConvertToThreeBitIndex(uint32_t x) {
        x = (x >> 1) & 0x7F7F7F7F; // 1
        x = x + 0x09090909;        // 2

        // Need to divide by 18... so first divide by two
        x = (x >> 1) & 0x7F7F7F7F;

        // Now divide by three twice
        x = MultibyteDiv3(x);
        x = MultibyteDiv3(x);
        return x;
    }
#else
    // Moves the top three bits of each byte in the 32-bit argument to the least
    // significant bits of their respective byte.
    static inline uint32_t ConvertToThreeBitIndex(uint32_t x) {
        return (x >> 5) & 0x07070707;
    }
#endif
}

#endif // SkTextureCompressorUtils_DEFINED