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 | 10 |
10 #include "SkBlitter.h" | 11 #include "SkBlitter.h" |
11 #include "SkEndian.h" | 12 #include "SkEndian.h" |
12 | 13 |
13 // This table contains the weight values for each texel. This is used in determi
ning | 14 // This table contains the weight values for each texel. This is used in determi
ning |
14 // how to convert a 12x12 grid of alpha values into a 6x5 grid of index values.
Since | 15 // how to convert a 12x12 grid of alpha values into a 6x5 grid of index values.
Since |
15 // we have a 6x5 grid, that gives 30 values that we have to compute. For each in
dex, | 16 // we have a 6x5 grid, that gives 30 values that we have to compute. For each in
dex, |
16 // we store up to 20 different triplets of values. In order the triplets are: | 17 // we store up to 20 different triplets of values. In order the triplets are: |
17 // weight, texel-x, texel-y | 18 // weight, texel-x, texel-y |
18 // The weight value corresponds to the amount that this index contributes to the
final | 19 // The weight value corresponds to the amount that this index contributes to the
final |
(...skipping 106 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, | 126 { 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, | 127 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 | 128 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, | 129 { 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, | 130 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 | 131 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0} // n = 20 |
131 }; | 132 }; |
132 | 133 |
133 // Returns the alpha value of a texel at position (x, y) from src. | 134 // 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). | 135 // (x, y) are assumed to be in the range [0, 12). |
135 static inline uint8_t get_alpha(const uint8_t *src, int rowBytes, int x, int y)
{ | 136 inline uint8_t GetAlpha(const uint8_t *src, int rowBytes, int x, int y) { |
136 SkASSERT(x >= 0 && x < 12); | 137 SkASSERT(x >= 0 && x < 12); |
137 SkASSERT(y >= 0 && y < 12); | 138 SkASSERT(y >= 0 && y < 12); |
138 SkASSERT(rowBytes >= 12); | 139 SkASSERT(rowBytes >= 12); |
139 return *(src + y*rowBytes + x); | 140 return *(src + y*rowBytes + x); |
140 } | 141 } |
141 | 142 |
| 143 inline uint8_t GetAlphaTranspose(const uint8_t *src, int rowBytes, int x, int y)
{ |
| 144 return GetAlpha(src, rowBytes, y, x); |
| 145 } |
| 146 |
142 // Output the 16 bytes stored in top and bottom and advance the pointer. The byt
es | 147 // 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 | 148 // are stored as the integers are represented in memory, so they should be swapp
ed |
144 // if necessary. | 149 // if necessary. |
145 static inline void send_packing(uint8_t** dst, const uint64_t top, const uint64_
t bottom) { | 150 static inline void send_packing(uint8_t** dst, const uint64_t top, const uint64_
t bottom) { |
146 uint64_t* dst64 = reinterpret_cast<uint64_t*>(*dst); | 151 uint64_t* dst64 = reinterpret_cast<uint64_t*>(*dst); |
147 dst64[0] = top; | 152 dst64[0] = top; |
148 dst64[1] = bottom; | 153 dst64[1] = bottom; |
149 *dst += 16; | 154 *dst += 16; |
150 } | 155 } |
151 | 156 |
152 // Compresses an ASTC block, by looking up the proper contributions from | 157 // Compresses an ASTC block, by looking up the proper contributions from |
153 // k6x5To12x12Table and computing an index from the associated values. | 158 // k6x5To12x12Table and computing an index from the associated values. |
| 159 typedef uint8_t (*GetAlphaProc)(const uint8_t* src, int rowBytes, int x, int y); |
| 160 |
| 161 template<GetAlphaProc getAlphaProc> |
154 static void compress_a8_astc_block(uint8_t** dst, const uint8_t* src, int rowByt
es) { | 162 static void compress_a8_astc_block(uint8_t** dst, const uint8_t* src, int rowByt
es) { |
155 // Check for single color | 163 // Check for single color |
156 bool constant = true; | 164 bool constant = true; |
157 const uint32_t firstInt = *(reinterpret_cast<const uint32_t*>(src)); | 165 const uint32_t firstInt = *(reinterpret_cast<const uint32_t*>(src)); |
158 for (int i = 0; i < 12; ++i) { | 166 for (int i = 0; i < 12; ++i) { |
159 const uint32_t *rowInt = reinterpret_cast<const uint32_t *>(src + i*rowB
ytes); | 167 const uint32_t *rowInt = reinterpret_cast<const uint32_t *>(src + i*rowB
ytes); |
160 constant = constant && (rowInt[0] == firstInt); | 168 constant = constant && (rowInt[0] == firstInt); |
161 constant = constant && (rowInt[1] == firstInt); | 169 constant = constant && (rowInt[1] == firstInt); |
162 constant = constant && (rowInt[2] == firstInt); | 170 constant = constant && (rowInt[2] == firstInt); |
163 } | 171 } |
(...skipping 15 matching lines...) Expand all Loading... |
179 uint8_t indices[30]; // 6x5 index grid | 187 uint8_t indices[30]; // 6x5 index grid |
180 for (int idx = 0; idx < 30; ++idx) { | 188 for (int idx = 0; idx < 30; ++idx) { |
181 int weightTot = 0; | 189 int weightTot = 0; |
182 int alphaTot = 0; | 190 int alphaTot = 0; |
183 for (int w = 0; w < 20; ++w) { | 191 for (int w = 0; w < 20; ++w) { |
184 const int8_t weight = k6x5To12x12Table[idx][w*3]; | 192 const int8_t weight = k6x5To12x12Table[idx][w*3]; |
185 if (weight > 0) { | 193 if (weight > 0) { |
186 const int x = k6x5To12x12Table[idx][w*3 + 1]; | 194 const int x = k6x5To12x12Table[idx][w*3 + 1]; |
187 const int y = k6x5To12x12Table[idx][w*3 + 2]; | 195 const int y = k6x5To12x12Table[idx][w*3 + 2]; |
188 weightTot += weight; | 196 weightTot += weight; |
189 alphaTot += weight * get_alpha(src, rowBytes, x, y); | 197 alphaTot += weight * getAlphaProc(src, rowBytes, x, y); |
190 } else { | 198 } else { |
191 // In our table, not every entry has 20 weights, and all | 199 // In our table, not every entry has 20 weights, and all |
192 // of them are nonzero. Once we hit a negative weight, we | 200 // of them are nonzero. Once we hit a negative weight, we |
193 // know that all of the other weights are not valid either. | 201 // know that all of the other weights are not valid either. |
194 break; | 202 break; |
195 } | 203 } |
196 } | 204 } |
197 | 205 |
198 indices[idx] = (alphaTot / weightTot) >> 5; | 206 indices[idx] = (alphaTot / weightTot) >> 5; |
199 } | 207 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 // Reverse each 3-bit index since indices are read in reverse order... | 249 // Reverse each 3-bit index since indices are read in reverse order... |
242 uint64_t t = (bottom ^ (bottom >> 2)) & 0x2492492492492492ULL; | 250 uint64_t t = (bottom ^ (bottom >> 2)) & 0x2492492492492492ULL; |
243 bottom = bottom ^ t ^ (t << 2); | 251 bottom = bottom ^ t ^ (t << 2); |
244 | 252 |
245 t = (top ^ (top >> 2)) & 0x0924924000000000ULL; | 253 t = (top ^ (top >> 2)) & 0x0924924000000000ULL; |
246 top = top ^ t ^ (t << 2); | 254 top = top ^ t ^ (t << 2); |
247 | 255 |
248 send_packing(dst, SkEndian_SwapLE64(top), SkEndian_SwapLE64(bottom)); | 256 send_packing(dst, SkEndian_SwapLE64(top), SkEndian_SwapLE64(bottom)); |
249 } | 257 } |
250 | 258 |
| 259 inline void compress_a8_astc_block_vertical(uint8_t* dst, const uint8_t* src) { |
| 260 compress_a8_astc_block<GetAlphaTranspose>(&dst, src, 12); |
| 261 } |
| 262 |
251 //////////////////////////////////////////////////////////////////////////////// | 263 //////////////////////////////////////////////////////////////////////////////// |
252 | 264 |
253 namespace SkTextureCompressor { | 265 namespace SkTextureCompressor { |
254 | 266 |
255 bool CompressA8To12x12ASTC(uint8_t* dst, const uint8_t* src, int width, int heig
ht, int rowBytes) { | 267 bool CompressA8To12x12ASTC(uint8_t* dst, const uint8_t* src, int width, int heig
ht, int rowBytes) { |
256 if (width < 0 || ((width % 12) != 0) || height < 0 || ((height % 12) != 0))
{ | 268 if (width < 0 || ((width % 12) != 0) || height < 0 || ((height % 12) != 0))
{ |
257 return false; | 269 return false; |
258 } | 270 } |
259 | 271 |
260 uint8_t** dstPtr = &dst; | 272 uint8_t** dstPtr = &dst; |
261 for (int y = 0; y < height; y+=12) { | 273 for (int y = 0; y < height; y+=12) { |
262 for (int x = 0; x < width; x+=12) { | 274 for (int x = 0; x < width; x+=12) { |
263 compress_a8_astc_block(dstPtr, src + y*rowBytes + x, rowBytes); | 275 compress_a8_astc_block<GetAlpha>(dstPtr, src + y*rowBytes + x, rowBy
tes); |
264 } | 276 } |
265 } | 277 } |
266 | 278 |
267 return true; | 279 return true; |
268 } | 280 } |
269 | 281 |
270 SkBlitter* CreateASTCBlitter(int width, int height, void* outputBuffer) { | 282 SkBlitter* CreateASTCBlitter(int width, int height, void* outputBuffer) { |
271 // TODO (krajcevski) | 283 return new |
272 return NULL; | 284 SkTCompressedAlphaBlitter<12, 16, compress_a8_astc_block_vertical> |
| 285 (width, height, outputBuffer); |
273 } | 286 } |
274 | 287 |
275 } // SkTextureCompressor | 288 } // SkTextureCompressor |
OLD | NEW |