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 | 9 |
10 #include "SkBlitter.h" | 10 #include "SkBlitter.h" |
(...skipping 19 matching lines...) Expand all Loading... |
30 // if weight >= 0: | 30 // if weight >= 0: |
31 // total-weight += weight; | 31 // total-weight += weight; |
32 // total-alpha += weight * alphas[texel-x][texel-y]; | 32 // total-alpha += weight * alphas[texel-x][texel-y]; |
33 // | 33 // |
34 // total-alpha /= total-weight; | 34 // total-alpha /= total-weight; |
35 // index = top three bits of total-alpha | 35 // index = top three bits of total-alpha |
36 // | 36 // |
37 // If the associated index does not contribute to 20 different texels (e.g. it's
in | 37 // If the associated index does not contribute to 20 different texels (e.g. it's
in |
38 // a corner), then the extra texels are stored with -1's in the table. | 38 // a corner), then the extra texels are stored with -1's in the table. |
39 | 39 |
40 static const int k6x5To12x12Table[30][60] = { | 40 static const int8_t k6x5To12x12Table[30][60] = { |
41 { 16, 0, 0, 9, 1, 0, 1, 2, 0, 10, 0, 1, 6, 1, 1, 1, 2, 1, 4, 0, 2, 2, | 41 { 16, 0, 0, 9, 1, 0, 1, 2, 0, 10, 0, 1, 6, 1, 1, 1, 2, 1, 4, 0, 2, 2, |
42 1, 2, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, | 42 1, 2, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, |
43 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0}, // n = 20 | 43 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0}, // n = 20 |
44 { 7, 1, 0, 15, 2, 0, 10, 3, 0, 3, 4, 0, 4, 1, 1, 9, 2, 1, 6, 3, 1, 2, | 44 { 7, 1, 0, 15, 2, 0, 10, 3, 0, 3, 4, 0, 4, 1, 1, 9, 2, 1, 6, 3, 1, 2, |
45 4, 1, 2, 1, 2, 4, 2, 2, 3, 3, 2, 1, 4, 2, -1, 0, 0, -1, 0, 0, -1, 0, | 45 4, 1, 2, 1, 2, 4, 2, 2, 3, 3, 2, 1, 4, 2, -1, 0, 0, -1, 0, 0, -1, 0, |
46 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0}, // n = 20 | 46 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0}, // n = 20 |
47 { 6, 3, 0, 13, 4, 0, 12, 5, 0, 4, 6, 0, 4, 3, 1, 8, 4, 1, 8, 5, 1, 3, | 47 { 6, 3, 0, 13, 4, 0, 12, 5, 0, 4, 6, 0, 4, 3, 1, 8, 4, 1, 8, 5, 1, 3, |
48 6, 1, 1, 3, 2, 3, 4, 2, 3, 5, 2, 1, 6, 2, -1, 0, 0, -1, 0, 0, -1, 0, | 48 6, 1, 1, 3, 2, 3, 4, 2, 3, 5, 2, 1, 6, 2, -1, 0, 0, -1, 0, 0, -1, 0, |
49 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0}, // n = 20 | 49 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0}, // n = 20 |
50 { 4, 5, 0, 12, 6, 0, 13, 7, 0, 6, 8, 0, 2, 5, 1, 7, 6, 1, 8, 7, 1, 4, | 50 { 4, 5, 0, 12, 6, 0, 13, 7, 0, 6, 8, 0, 2, 5, 1, 7, 6, 1, 8, 7, 1, 4, |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 { 1, 7, 9, 3, 8, 9, 4, 9, 9, 2, 10, 9, 2, 7, 10, 6, 8, 10, 9, 9, 10, 4, | 125 { 1, 7, 9, 3, 8, 9, 4, 9, 9, 2, 10, 9, 2, 7, 10, 6, 8, 10, 9, 9, 10, 4, |
126 10, 10, 3, 7, 11, 10, 8, 11, 15, 9, 11, 7, 10, 11, -1, 0, 0, -1, 0, 0, -1, 0, | 126 10, 10, 3, 7, 11, 10, 8, 11, 15, 9, 11, 7, 10, 11, -1, 0, 0, -1, 0, 0, -1, 0, |
127 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0}, // n = 20 | 127 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0}, // n = 20 |
128 { 2, 10, 9, 4, 11, 9, 1, 9, 10, 6, 10, 10, 10, 11, 10, 1, 9, 11, 9, 10, 11, 16, | 128 { 2, 10, 9, 4, 11, 9, 1, 9, 10, 6, 10, 10, 10, 11, 10, 1, 9, 11, 9, 10, 11, 16, |
129 11, 11, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, | 129 11, 11, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, |
130 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0} // n = 20 | 130 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0} // n = 20 |
131 }; | 131 }; |
132 | 132 |
133 // Returns the alpha value of a texel at position (x, y) from src. | 133 // Returns the alpha value of a texel at position (x, y) from src. |
134 // (x, y) are assumed to be in the range [0, 12). | 134 // (x, y) are assumed to be in the range [0, 12). |
135 uint8_t get_alpha(const uint8_t *src, int rowBytes, int x, int y) { | 135 static inline uint8_t get_alpha(const uint8_t *src, int rowBytes, int x, int y)
{ |
136 SkASSERT(x >= 0 && x < 12); | 136 SkASSERT(x >= 0 && x < 12); |
137 SkASSERT(y >= 0 && y < 12); | 137 SkASSERT(y >= 0 && y < 12); |
138 SkASSERT(rowBytes >= 12); | 138 SkASSERT(rowBytes >= 12); |
139 return *(src + y*rowBytes + x); | 139 return *(src + y*rowBytes + x); |
140 } | 140 } |
141 | 141 |
142 // Output the 16 bytes stored in top and bottom and advance the pointer. The byt
es | 142 // Output the 16 bytes stored in top and bottom and advance the pointer. The byt
es |
143 // are stored as the integers are represented in memory, so they should be swapp
ed | 143 // are stored as the integers are represented in memory, so they should be swapp
ed |
144 // if necessary. | 144 // if necessary. |
145 static inline void send_packing(uint8_t** dst, const uint64_t top, const uint64_
t bottom) { | 145 static inline void send_packing(uint8_t** dst, const uint64_t top, const uint64_
t bottom) { |
(...skipping 27 matching lines...) Expand all Loading... |
173 // v0 = 255, v1 = 0, so everything will be opaque. | 173 // v0 = 255, v1 = 0, so everything will be opaque. |
174 send_packing(dst, SkTEndian_SwapLE64(0x000000000001FE0173ULL), 0); | 174 send_packing(dst, SkTEndian_SwapLE64(0x000000000001FE0173ULL), 0); |
175 return; | 175 return; |
176 } | 176 } |
177 } | 177 } |
178 | 178 |
179 uint8_t indices[30]; // 6x5 index grid | 179 uint8_t indices[30]; // 6x5 index grid |
180 for (int idx = 0; idx < 30; ++idx) { | 180 for (int idx = 0; idx < 30; ++idx) { |
181 int weightTot = 0; | 181 int weightTot = 0; |
182 int alphaTot = 0; | 182 int alphaTot = 0; |
183 | |
184 for (int w = 0; w < 20; ++w) { | 183 for (int w = 0; w < 20; ++w) { |
185 const int weight = k6x5To12x12Table[idx][w*3]; | 184 const int8_t weight = k6x5To12x12Table[idx][w*3]; |
186 if (weight > 0) { | 185 if (weight > 0) { |
187 const int x = k6x5To12x12Table[idx][w*3 + 1]; | 186 const int x = k6x5To12x12Table[idx][w*3 + 1]; |
188 const int y = k6x5To12x12Table[idx][w*3 + 2]; | 187 const int y = k6x5To12x12Table[idx][w*3 + 2]; |
189 weightTot += weight; | 188 weightTot += weight; |
190 alphaTot += weight * get_alpha(src, rowBytes, x, y); | 189 alphaTot += weight * get_alpha(src, rowBytes, x, y); |
| 190 } else { |
| 191 // In our table, not every entry has 20 weights, and all |
| 192 // of them are nonzero. Once we hit a negative weight, we |
| 193 // know that all of the other weights are not valid either. |
| 194 break; |
191 } | 195 } |
192 } | 196 } |
193 | 197 |
194 indices[idx] = (alphaTot + (weightTot/2)) / weightTot; | 198 indices[idx] = (alphaTot / weightTot) >> 5; |
195 } | 199 } |
196 | 200 |
197 // Pack indices... The ASTC block layout is fairly complicated. An extensive | 201 // Pack indices... The ASTC block layout is fairly complicated. An extensive |
198 // description can be found here: | 202 // description can be found here: |
199 // https://www.opengl.org/registry/specs/KHR/texture_compression_astc_hdr.tx
t | 203 // https://www.opengl.org/registry/specs/KHR/texture_compression_astc_hdr.tx
t |
200 // | 204 // |
201 // Here is a summary of the options that we've chosen: | 205 // Here is a summary of the options that we've chosen: |
202 // 1. Block mode: 0b00101110011 | 206 // 1. Block mode: 0b00101110011 |
203 // - 6x5 texel grid | 207 // - 6x5 texel grid |
204 // - Single plane | 208 // - Single plane |
205 // - Low-precision index values | 209 // - Low-precision index values |
206 // - Index range 0-7 (three bits per index) | 210 // - Index range 0-7 (three bits per index) |
207 // 2. Partitions: 0b00 | 211 // 2. Partitions: 0b00 |
208 // - One partition | 212 // - One partition |
209 // 3. Color Endpoint Mode: 0b0000 | 213 // 3. Color Endpoint Mode: 0b0000 |
210 // - Direct luminance -- e0=(v0,v0,v0,0xFF); e1=(v1,v1,v1,0xFF); | 214 // - Direct luminance -- e0=(v0,v0,v0,0xFF); e1=(v1,v1,v1,0xFF); |
211 // 4. 8-bit endpoints: | 215 // 4. 8-bit endpoints: |
212 // v0 = 0, v1 = 255 | 216 // v0 = 0, v1 = 255 |
213 // | 217 // |
214 // The rest of the block contains the 30 index values from before, which | 218 // The rest of the block contains the 30 index values from before, which |
215 // are currently stored in the indices variable. | 219 // are currently stored in the indices variable. |
216 | 220 |
217 uint64_t top = 0x0000000001FE000173ULL; | 221 uint64_t top = 0x0000000001FE000173ULL; |
218 uint64_t bottom = 0; | 222 uint64_t bottom = 0; |
219 | 223 |
220 for (int idx = 0; idx <= 20; ++idx) { | 224 for (int idx = 0; idx <= 20; ++idx) { |
221 const uint8_t index = (indices[idx] & 0xE0) >> 5; | 225 const uint8_t index = indices[idx]; |
222 bottom |= static_cast<uint64_t>(index) << (61-(idx*3)); | 226 bottom |= static_cast<uint64_t>(index) << (61-(idx*3)); |
223 } | 227 } |
224 | 228 |
225 // index 21 straddles top and bottom | 229 // index 21 straddles top and bottom |
226 { | 230 { |
227 const uint8_t index = (indices[21] & 0xE0) >> 5; | 231 const uint8_t index = indices[21]; |
228 bottom |= index & 1; | 232 bottom |= index & 1; |
229 top |= static_cast<uint64_t>((index >> 2) | (index & 2)) << 62; | 233 top |= static_cast<uint64_t>((index >> 2) | (index & 2)) << 62; |
230 } | 234 } |
231 | 235 |
232 for (int idx = 22; idx < 30; ++idx) { | 236 for (int idx = 22; idx < 30; ++idx) { |
233 const uint8_t index = (indices[idx] & 0xE0) >> 5; | 237 const uint8_t index = indices[idx]; |
234 top |= static_cast<uint64_t>(index) << (59-(idx-22)*3); | 238 top |= static_cast<uint64_t>(index) << (59-(idx-22)*3); |
235 } | 239 } |
236 | 240 |
237 // Reverse each 3-bit index since indices are read in reverse order... | 241 // Reverse each 3-bit index since indices are read in reverse order... |
238 uint64_t t = (bottom ^ (bottom >> 2)) & 0x2492492492492492ULL; | 242 uint64_t t = (bottom ^ (bottom >> 2)) & 0x2492492492492492ULL; |
239 bottom = bottom ^ t ^ (t << 2); | 243 bottom = bottom ^ t ^ (t << 2); |
240 | 244 |
241 t = (top ^ (top >> 2)) & 0x0924924000000000ULL; | 245 t = (top ^ (top >> 2)) & 0x0924924000000000ULL; |
242 top = top ^ t ^ (t << 2); | 246 top = top ^ t ^ (t << 2); |
243 | 247 |
(...skipping 18 matching lines...) Expand all Loading... |
262 | 266 |
263 return true; | 267 return true; |
264 } | 268 } |
265 | 269 |
266 SkBlitter* CreateASTCBlitter(int width, int height, void* outputBuffer) { | 270 SkBlitter* CreateASTCBlitter(int width, int height, void* outputBuffer) { |
267 // TODO (krajcevski) | 271 // TODO (krajcevski) |
268 return NULL; | 272 return NULL; |
269 } | 273 } |
270 | 274 |
271 } // SkTextureCompressor | 275 } // SkTextureCompressor |
OLD | NEW |