| 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 |