| OLD | NEW |
| 1 // Copyright 2012 Google Inc. All Rights Reserved. | 1 // Copyright 2012 Google Inc. All Rights Reserved. |
| 2 // | 2 // |
| 3 // Use of this source code is governed by a BSD-style license | 3 // Use of this source code is governed by a BSD-style license |
| 4 // that can be found in the COPYING file in the root of the source | 4 // that can be found in the COPYING file in the root of the source |
| 5 // tree. An additional intellectual property rights grant can be found | 5 // tree. An additional intellectual property rights grant can be found |
| 6 // in the file PATENTS. All contributing project authors may | 6 // in the file PATENTS. All contributing project authors may |
| 7 // be found in the AUTHORS file in the root of the source tree. | 7 // be found in the AUTHORS file in the root of the source tree. |
| 8 // ----------------------------------------------------------------------------- | 8 // ----------------------------------------------------------------------------- |
| 9 // | 9 // |
| 10 // Image transforms and color space conversion methods for lossless decoder. | 10 // Image transforms and color space conversion methods for lossless decoder. |
| 11 // | 11 // |
| 12 // Authors: Vikas Arora (vikaas.arora@gmail.com) | 12 // Authors: Vikas Arora (vikaas.arora@gmail.com) |
| 13 // Jyrki Alakuijala (jyrki@google.com) | 13 // Jyrki Alakuijala (jyrki@google.com) |
| 14 // Urvang Joshi (urvang@google.com) | 14 // Urvang Joshi (urvang@google.com) |
| 15 | 15 |
| 16 #include "./dsp.h" | 16 #include "./dsp.h" |
| 17 | 17 |
| 18 #include <math.h> | 18 #include <math.h> |
| 19 #include <stdlib.h> | 19 #include <stdlib.h> |
| 20 #include "../dec/vp8li.h" | 20 #include "../dec/vp8li_dec.h" |
| 21 #include "../utils/endian_inl.h" | 21 #include "../utils/endian_inl_utils.h" |
| 22 #include "./lossless.h" | 22 #include "./lossless.h" |
| 23 #include "./lossless_common.h" |
| 23 | 24 |
| 24 #define MAX_DIFF_COST (1e30f) | 25 #define MAX_DIFF_COST (1e30f) |
| 25 | 26 |
| 26 //------------------------------------------------------------------------------ | 27 //------------------------------------------------------------------------------ |
| 27 // Image transforms. | 28 // Image transforms. |
| 28 | 29 |
| 29 // In-place sum of each component with mod 256. | |
| 30 static WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) { | |
| 31 *a = VP8LAddPixels(*a, b); | |
| 32 } | |
| 33 | |
| 34 static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) { | 30 static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) { |
| 35 return (((a0 ^ a1) & 0xfefefefeu) >> 1) + (a0 & a1); | 31 return (((a0 ^ a1) & 0xfefefefeu) >> 1) + (a0 & a1); |
| 36 } | 32 } |
| 37 | 33 |
| 38 static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) { | 34 static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) { |
| 39 return Average2(Average2(a0, a2), a1); | 35 return Average2(Average2(a0, a2), a1); |
| 40 } | 36 } |
| 41 | 37 |
| 42 static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, | 38 static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, |
| 43 uint32_t a2, uint32_t a3) { | 39 uint32_t a2, uint32_t a3) { |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 } | 160 } |
| 165 static uint32_t Predictor12(uint32_t left, const uint32_t* const top) { | 161 static uint32_t Predictor12(uint32_t left, const uint32_t* const top) { |
| 166 const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]); | 162 const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]); |
| 167 return pred; | 163 return pred; |
| 168 } | 164 } |
| 169 static uint32_t Predictor13(uint32_t left, const uint32_t* const top) { | 165 static uint32_t Predictor13(uint32_t left, const uint32_t* const top) { |
| 170 const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]); | 166 const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]); |
| 171 return pred; | 167 return pred; |
| 172 } | 168 } |
| 173 | 169 |
| 170 GENERATE_PREDICTOR_ADD(Predictor0, PredictorAdd0) |
| 171 static void PredictorAdd1(const uint32_t* in, const uint32_t* upper, |
| 172 int num_pixels, uint32_t* out) { |
| 173 int i; |
| 174 uint32_t left = out[-1]; |
| 175 for (i = 0; i < num_pixels; ++i) { |
| 176 out[i] = left = VP8LAddPixels(in[i], left); |
| 177 } |
| 178 (void)upper; |
| 179 } |
| 180 GENERATE_PREDICTOR_ADD(Predictor2, PredictorAdd2) |
| 181 GENERATE_PREDICTOR_ADD(Predictor3, PredictorAdd3) |
| 182 GENERATE_PREDICTOR_ADD(Predictor4, PredictorAdd4) |
| 183 GENERATE_PREDICTOR_ADD(Predictor5, PredictorAdd5) |
| 184 GENERATE_PREDICTOR_ADD(Predictor6, PredictorAdd6) |
| 185 GENERATE_PREDICTOR_ADD(Predictor7, PredictorAdd7) |
| 186 GENERATE_PREDICTOR_ADD(Predictor8, PredictorAdd8) |
| 187 GENERATE_PREDICTOR_ADD(Predictor9, PredictorAdd9) |
| 188 GENERATE_PREDICTOR_ADD(Predictor10, PredictorAdd10) |
| 189 GENERATE_PREDICTOR_ADD(Predictor11, PredictorAdd11) |
| 190 GENERATE_PREDICTOR_ADD(Predictor12, PredictorAdd12) |
| 191 GENERATE_PREDICTOR_ADD(Predictor13, PredictorAdd13) |
| 192 |
| 174 //------------------------------------------------------------------------------ | 193 //------------------------------------------------------------------------------ |
| 175 | 194 |
| 176 // Inverse prediction. | 195 // Inverse prediction. |
| 177 static void PredictorInverseTransform(const VP8LTransform* const transform, | 196 static void PredictorInverseTransform(const VP8LTransform* const transform, |
| 178 int y_start, int y_end, uint32_t* data) { | 197 int y_start, int y_end, |
| 198 const uint32_t* in, uint32_t* out) { |
| 179 const int width = transform->xsize_; | 199 const int width = transform->xsize_; |
| 180 if (y_start == 0) { // First Row follows the L (mode=1) mode. | 200 if (y_start == 0) { // First Row follows the L (mode=1) mode. |
| 181 int x; | 201 PredictorAdd0(in, NULL, 1, out); |
| 182 const uint32_t pred0 = Predictor0(data[-1], NULL); | 202 PredictorAdd1(in + 1, NULL, width - 1, out + 1); |
| 183 AddPixelsEq(data, pred0); | 203 in += width; |
| 184 for (x = 1; x < width; ++x) { | 204 out += width; |
| 185 const uint32_t pred1 = Predictor1(data[x - 1], NULL); | |
| 186 AddPixelsEq(data + x, pred1); | |
| 187 } | |
| 188 data += width; | |
| 189 ++y_start; | 205 ++y_start; |
| 190 } | 206 } |
| 191 | 207 |
| 192 { | 208 { |
| 193 int y = y_start; | 209 int y = y_start; |
| 194 const int tile_width = 1 << transform->bits_; | 210 const int tile_width = 1 << transform->bits_; |
| 195 const int mask = tile_width - 1; | 211 const int mask = tile_width - 1; |
| 196 const int safe_width = width & ~mask; | |
| 197 const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_); | 212 const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_); |
| 198 const uint32_t* pred_mode_base = | 213 const uint32_t* pred_mode_base = |
| 199 transform->data_ + (y >> transform->bits_) * tiles_per_row; | 214 transform->data_ + (y >> transform->bits_) * tiles_per_row; |
| 200 | 215 |
| 201 while (y < y_end) { | 216 while (y < y_end) { |
| 202 const uint32_t pred2 = Predictor2(data[-1], data - width); | |
| 203 const uint32_t* pred_mode_src = pred_mode_base; | 217 const uint32_t* pred_mode_src = pred_mode_base; |
| 204 VP8LPredictorFunc pred_func; | |
| 205 int x = 1; | 218 int x = 1; |
| 206 int t = 1; | |
| 207 // First pixel follows the T (mode=2) mode. | 219 // First pixel follows the T (mode=2) mode. |
| 208 AddPixelsEq(data, pred2); | 220 PredictorAdd2(in, out - width, 1, out); |
| 209 // .. the rest: | 221 // .. the rest: |
| 210 while (x < safe_width) { | 222 while (x < width) { |
| 211 pred_func = VP8LPredictors[((*pred_mode_src++) >> 8) & 0xf]; | 223 const VP8LPredictorAddSubFunc pred_func = |
| 212 for (; t < tile_width; ++t, ++x) { | 224 VP8LPredictorsAdd[((*pred_mode_src++) >> 8) & 0xf]; |
| 213 const uint32_t pred = pred_func(data[x - 1], data + x - width); | 225 int x_end = (x & ~mask) + tile_width; |
| 214 AddPixelsEq(data + x, pred); | 226 if (x_end > width) x_end = width; |
| 215 } | 227 pred_func(in + x, out + x - width, x_end - x, out + x); |
| 216 t = 0; | 228 x = x_end; |
| 217 } | 229 } |
| 218 if (x < width) { | 230 in += width; |
| 219 pred_func = VP8LPredictors[((*pred_mode_src++) >> 8) & 0xf]; | 231 out += width; |
| 220 for (; x < width; ++x) { | |
| 221 const uint32_t pred = pred_func(data[x - 1], data + x - width); | |
| 222 AddPixelsEq(data + x, pred); | |
| 223 } | |
| 224 } | |
| 225 data += width; | |
| 226 ++y; | 232 ++y; |
| 227 if ((y & mask) == 0) { // Use the same mask, since tiles are squares. | 233 if ((y & mask) == 0) { // Use the same mask, since tiles are squares. |
| 228 pred_mode_base += tiles_per_row; | 234 pred_mode_base += tiles_per_row; |
| 229 } | 235 } |
| 230 } | 236 } |
| 231 } | 237 } |
| 232 } | 238 } |
| 233 | 239 |
| 234 // Add green to blue and red channels (i.e. perform the inverse transform of | 240 // Add green to blue and red channels (i.e. perform the inverse transform of |
| 235 // 'subtract green'). | 241 // 'subtract green'). |
| 236 void VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels) { | 242 void VP8LAddGreenToBlueAndRed_C(const uint32_t* src, int num_pixels, |
| 243 uint32_t* dst) { |
| 237 int i; | 244 int i; |
| 238 for (i = 0; i < num_pixels; ++i) { | 245 for (i = 0; i < num_pixels; ++i) { |
| 239 const uint32_t argb = data[i]; | 246 const uint32_t argb = src[i]; |
| 240 const uint32_t green = ((argb >> 8) & 0xff); | 247 const uint32_t green = ((argb >> 8) & 0xff); |
| 241 uint32_t red_blue = (argb & 0x00ff00ffu); | 248 uint32_t red_blue = (argb & 0x00ff00ffu); |
| 242 red_blue += (green << 16) | green; | 249 red_blue += (green << 16) | green; |
| 243 red_blue &= 0x00ff00ffu; | 250 red_blue &= 0x00ff00ffu; |
| 244 data[i] = (argb & 0xff00ff00u) | red_blue; | 251 dst[i] = (argb & 0xff00ff00u) | red_blue; |
| 245 } | 252 } |
| 246 } | 253 } |
| 247 | 254 |
| 248 static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred, | 255 static WEBP_INLINE int ColorTransformDelta(int8_t color_pred, |
| 249 int8_t color) { | 256 int8_t color) { |
| 250 return (uint32_t)((int)(color_pred) * color) >> 5; | 257 return ((int)color_pred * color) >> 5; |
| 251 } | 258 } |
| 252 | 259 |
| 253 static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code, | 260 static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code, |
| 254 VP8LMultipliers* const m) { | 261 VP8LMultipliers* const m) { |
| 255 m->green_to_red_ = (color_code >> 0) & 0xff; | 262 m->green_to_red_ = (color_code >> 0) & 0xff; |
| 256 m->green_to_blue_ = (color_code >> 8) & 0xff; | 263 m->green_to_blue_ = (color_code >> 8) & 0xff; |
| 257 m->red_to_blue_ = (color_code >> 16) & 0xff; | 264 m->red_to_blue_ = (color_code >> 16) & 0xff; |
| 258 } | 265 } |
| 259 | 266 |
| 260 void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, uint32_t* data, | 267 void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, |
| 261 int num_pixels) { | 268 const uint32_t* src, int num_pixels, |
| 269 uint32_t* dst) { |
| 262 int i; | 270 int i; |
| 263 for (i = 0; i < num_pixels; ++i) { | 271 for (i = 0; i < num_pixels; ++i) { |
| 264 const uint32_t argb = data[i]; | 272 const uint32_t argb = src[i]; |
| 265 const uint32_t green = argb >> 8; | 273 const uint32_t green = argb >> 8; |
| 266 const uint32_t red = argb >> 16; | 274 const uint32_t red = argb >> 16; |
| 267 uint32_t new_red = red; | 275 int new_red = red; |
| 268 uint32_t new_blue = argb; | 276 int new_blue = argb; |
| 269 new_red += ColorTransformDelta(m->green_to_red_, green); | 277 new_red += ColorTransformDelta(m->green_to_red_, green); |
| 270 new_red &= 0xff; | 278 new_red &= 0xff; |
| 271 new_blue += ColorTransformDelta(m->green_to_blue_, green); | 279 new_blue += ColorTransformDelta(m->green_to_blue_, green); |
| 272 new_blue += ColorTransformDelta(m->red_to_blue_, new_red); | 280 new_blue += ColorTransformDelta(m->red_to_blue_, new_red); |
| 273 new_blue &= 0xff; | 281 new_blue &= 0xff; |
| 274 data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue); | 282 dst[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue); |
| 275 } | 283 } |
| 276 } | 284 } |
| 277 | 285 |
| 278 // Color space inverse transform. | 286 // Color space inverse transform. |
| 279 static void ColorSpaceInverseTransform(const VP8LTransform* const transform, | 287 static void ColorSpaceInverseTransform(const VP8LTransform* const transform, |
| 280 int y_start, int y_end, uint32_t* data) { | 288 int y_start, int y_end, |
| 289 const uint32_t* src, uint32_t* dst) { |
| 281 const int width = transform->xsize_; | 290 const int width = transform->xsize_; |
| 282 const int tile_width = 1 << transform->bits_; | 291 const int tile_width = 1 << transform->bits_; |
| 283 const int mask = tile_width - 1; | 292 const int mask = tile_width - 1; |
| 284 const int safe_width = width & ~mask; | 293 const int safe_width = width & ~mask; |
| 285 const int remaining_width = width - safe_width; | 294 const int remaining_width = width - safe_width; |
| 286 const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_); | 295 const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_); |
| 287 int y = y_start; | 296 int y = y_start; |
| 288 const uint32_t* pred_row = | 297 const uint32_t* pred_row = |
| 289 transform->data_ + (y >> transform->bits_) * tiles_per_row; | 298 transform->data_ + (y >> transform->bits_) * tiles_per_row; |
| 290 | 299 |
| 291 while (y < y_end) { | 300 while (y < y_end) { |
| 292 const uint32_t* pred = pred_row; | 301 const uint32_t* pred = pred_row; |
| 293 VP8LMultipliers m = { 0, 0, 0 }; | 302 VP8LMultipliers m = { 0, 0, 0 }; |
| 294 const uint32_t* const data_safe_end = data + safe_width; | 303 const uint32_t* const src_safe_end = src + safe_width; |
| 295 const uint32_t* const data_end = data + width; | 304 const uint32_t* const src_end = src + width; |
| 296 while (data < data_safe_end) { | 305 while (src < src_safe_end) { |
| 297 ColorCodeToMultipliers(*pred++, &m); | 306 ColorCodeToMultipliers(*pred++, &m); |
| 298 VP8LTransformColorInverse(&m, data, tile_width); | 307 VP8LTransformColorInverse(&m, src, tile_width, dst); |
| 299 data += tile_width; | 308 src += tile_width; |
| 309 dst += tile_width; |
| 300 } | 310 } |
| 301 if (data < data_end) { // Left-overs using C-version. | 311 if (src < src_end) { // Left-overs using C-version. |
| 302 ColorCodeToMultipliers(*pred++, &m); | 312 ColorCodeToMultipliers(*pred++, &m); |
| 303 VP8LTransformColorInverse(&m, data, remaining_width); | 313 VP8LTransformColorInverse(&m, src, remaining_width, dst); |
| 304 data += remaining_width; | 314 src += remaining_width; |
| 315 dst += remaining_width; |
| 305 } | 316 } |
| 306 ++y; | 317 ++y; |
| 307 if ((y & mask) == 0) pred_row += tiles_per_row; | 318 if ((y & mask) == 0) pred_row += tiles_per_row; |
| 308 } | 319 } |
| 309 } | 320 } |
| 310 | 321 |
| 311 // Separate out pixels packed together using pixel-bundling. | 322 // Separate out pixels packed together using pixel-bundling. |
| 312 // We define two methods for ARGB data (uint32_t) and alpha-only data (uint8_t). | 323 // We define two methods for ARGB data (uint32_t) and alpha-only data (uint8_t). |
| 313 #define COLOR_INDEX_INVERSE(FUNC_NAME, F_NAME, STATIC_DECL, TYPE, BIT_SUFFIX, \ | 324 #define COLOR_INDEX_INVERSE(FUNC_NAME, F_NAME, STATIC_DECL, TYPE, BIT_SUFFIX, \ |
| 314 GET_INDEX, GET_VALUE) \ | 325 GET_INDEX, GET_VALUE) \ |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 #undef COLOR_INDEX_INVERSE | 370 #undef COLOR_INDEX_INVERSE |
| 360 | 371 |
| 361 void VP8LInverseTransform(const VP8LTransform* const transform, | 372 void VP8LInverseTransform(const VP8LTransform* const transform, |
| 362 int row_start, int row_end, | 373 int row_start, int row_end, |
| 363 const uint32_t* const in, uint32_t* const out) { | 374 const uint32_t* const in, uint32_t* const out) { |
| 364 const int width = transform->xsize_; | 375 const int width = transform->xsize_; |
| 365 assert(row_start < row_end); | 376 assert(row_start < row_end); |
| 366 assert(row_end <= transform->ysize_); | 377 assert(row_end <= transform->ysize_); |
| 367 switch (transform->type_) { | 378 switch (transform->type_) { |
| 368 case SUBTRACT_GREEN: | 379 case SUBTRACT_GREEN: |
| 369 VP8LAddGreenToBlueAndRed(out, (row_end - row_start) * width); | 380 VP8LAddGreenToBlueAndRed(in, (row_end - row_start) * width, out); |
| 370 break; | 381 break; |
| 371 case PREDICTOR_TRANSFORM: | 382 case PREDICTOR_TRANSFORM: |
| 372 PredictorInverseTransform(transform, row_start, row_end, out); | 383 PredictorInverseTransform(transform, row_start, row_end, in, out); |
| 373 if (row_end != transform->ysize_) { | 384 if (row_end != transform->ysize_) { |
| 374 // The last predicted row in this iteration will be the top-pred row | 385 // The last predicted row in this iteration will be the top-pred row |
| 375 // for the first row in next iteration. | 386 // for the first row in next iteration. |
| 376 memcpy(out - width, out + (row_end - row_start - 1) * width, | 387 memcpy(out - width, out + (row_end - row_start - 1) * width, |
| 377 width * sizeof(*out)); | 388 width * sizeof(*out)); |
| 378 } | 389 } |
| 379 break; | 390 break; |
| 380 case CROSS_COLOR_TRANSFORM: | 391 case CROSS_COLOR_TRANSFORM: |
| 381 ColorSpaceInverseTransform(transform, row_start, row_end, out); | 392 ColorSpaceInverseTransform(transform, row_start, row_end, in, out); |
| 382 break; | 393 break; |
| 383 case COLOR_INDEXING_TRANSFORM: | 394 case COLOR_INDEXING_TRANSFORM: |
| 384 if (in == out && transform->bits_ > 0) { | 395 if (in == out && transform->bits_ > 0) { |
| 385 // Move packed pixels to the end of unpacked region, so that unpacking | 396 // Move packed pixels to the end of unpacked region, so that unpacking |
| 386 // can occur seamlessly. | 397 // can occur seamlessly. |
| 387 // Also, note that this is the only transform that applies on | 398 // Also, note that this is the only transform that applies on |
| 388 // the effective width of VP8LSubSampleSize(xsize_, bits_). All other | 399 // the effective width of VP8LSubSampleSize(xsize_, bits_). All other |
| 389 // transforms work on effective width of xsize_. | 400 // transforms work on effective width of xsize_. |
| 390 const int out_stride = (row_end - row_start) * width; | 401 const int out_stride = (row_end - row_start) * width; |
| 391 const int in_stride = (row_end - row_start) * | 402 const int in_stride = (row_end - row_start) * |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 548 case MODE_RGB_565: | 559 case MODE_RGB_565: |
| 549 VP8LConvertBGRAToRGB565(in_data, num_pixels, rgba); | 560 VP8LConvertBGRAToRGB565(in_data, num_pixels, rgba); |
| 550 break; | 561 break; |
| 551 default: | 562 default: |
| 552 assert(0); // Code flow should not reach here. | 563 assert(0); // Code flow should not reach here. |
| 553 } | 564 } |
| 554 } | 565 } |
| 555 | 566 |
| 556 //------------------------------------------------------------------------------ | 567 //------------------------------------------------------------------------------ |
| 557 | 568 |
| 558 VP8LProcessBlueAndRedFunc VP8LAddGreenToBlueAndRed; | 569 VP8LProcessDecBlueAndRedFunc VP8LAddGreenToBlueAndRed; |
| 570 VP8LPredictorAddSubFunc VP8LPredictorsAdd[16]; |
| 559 VP8LPredictorFunc VP8LPredictors[16]; | 571 VP8LPredictorFunc VP8LPredictors[16]; |
| 560 | 572 |
| 561 VP8LTransformColorFunc VP8LTransformColorInverse; | 573 // exposed plain-C implementations |
| 574 VP8LPredictorAddSubFunc VP8LPredictorsAdd_C[16]; |
| 575 VP8LPredictorFunc VP8LPredictors_C[16]; |
| 576 |
| 577 VP8LTransformColorInverseFunc VP8LTransformColorInverse; |
| 562 | 578 |
| 563 VP8LConvertFunc VP8LConvertBGRAToRGB; | 579 VP8LConvertFunc VP8LConvertBGRAToRGB; |
| 564 VP8LConvertFunc VP8LConvertBGRAToRGBA; | 580 VP8LConvertFunc VP8LConvertBGRAToRGBA; |
| 565 VP8LConvertFunc VP8LConvertBGRAToRGBA4444; | 581 VP8LConvertFunc VP8LConvertBGRAToRGBA4444; |
| 566 VP8LConvertFunc VP8LConvertBGRAToRGB565; | 582 VP8LConvertFunc VP8LConvertBGRAToRGB565; |
| 567 VP8LConvertFunc VP8LConvertBGRAToBGR; | 583 VP8LConvertFunc VP8LConvertBGRAToBGR; |
| 568 | 584 |
| 569 VP8LMapARGBFunc VP8LMapColor32b; | 585 VP8LMapARGBFunc VP8LMapColor32b; |
| 570 VP8LMapAlphaFunc VP8LMapColor8b; | 586 VP8LMapAlphaFunc VP8LMapColor8b; |
| 571 | 587 |
| 572 extern void VP8LDspInitSSE2(void); | 588 extern void VP8LDspInitSSE2(void); |
| 573 extern void VP8LDspInitNEON(void); | 589 extern void VP8LDspInitNEON(void); |
| 574 extern void VP8LDspInitMIPSdspR2(void); | 590 extern void VP8LDspInitMIPSdspR2(void); |
| 591 extern void VP8LDspInitMSA(void); |
| 575 | 592 |
| 576 static volatile VP8CPUInfo lossless_last_cpuinfo_used = | 593 static volatile VP8CPUInfo lossless_last_cpuinfo_used = |
| 577 (VP8CPUInfo)&lossless_last_cpuinfo_used; | 594 (VP8CPUInfo)&lossless_last_cpuinfo_used; |
| 578 | 595 |
| 596 #define COPY_PREDICTOR_ARRAY(IN, OUT) do { \ |
| 597 (OUT)[0] = IN##0; \ |
| 598 (OUT)[1] = IN##1; \ |
| 599 (OUT)[2] = IN##2; \ |
| 600 (OUT)[3] = IN##3; \ |
| 601 (OUT)[4] = IN##4; \ |
| 602 (OUT)[5] = IN##5; \ |
| 603 (OUT)[6] = IN##6; \ |
| 604 (OUT)[7] = IN##7; \ |
| 605 (OUT)[8] = IN##8; \ |
| 606 (OUT)[9] = IN##9; \ |
| 607 (OUT)[10] = IN##10; \ |
| 608 (OUT)[11] = IN##11; \ |
| 609 (OUT)[12] = IN##12; \ |
| 610 (OUT)[13] = IN##13; \ |
| 611 (OUT)[14] = IN##0; /* <- padding security sentinels*/ \ |
| 612 (OUT)[15] = IN##0; \ |
| 613 } while (0); |
| 614 |
| 579 WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInit(void) { | 615 WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInit(void) { |
| 580 if (lossless_last_cpuinfo_used == VP8GetCPUInfo) return; | 616 if (lossless_last_cpuinfo_used == VP8GetCPUInfo) return; |
| 581 | 617 |
| 582 VP8LPredictors[0] = Predictor0; | 618 COPY_PREDICTOR_ARRAY(Predictor, VP8LPredictors) |
| 583 VP8LPredictors[1] = Predictor1; | 619 COPY_PREDICTOR_ARRAY(Predictor, VP8LPredictors_C) |
| 584 VP8LPredictors[2] = Predictor2; | 620 COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd) |
| 585 VP8LPredictors[3] = Predictor3; | 621 COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd_C) |
| 586 VP8LPredictors[4] = Predictor4; | |
| 587 VP8LPredictors[5] = Predictor5; | |
| 588 VP8LPredictors[6] = Predictor6; | |
| 589 VP8LPredictors[7] = Predictor7; | |
| 590 VP8LPredictors[8] = Predictor8; | |
| 591 VP8LPredictors[9] = Predictor9; | |
| 592 VP8LPredictors[10] = Predictor10; | |
| 593 VP8LPredictors[11] = Predictor11; | |
| 594 VP8LPredictors[12] = Predictor12; | |
| 595 VP8LPredictors[13] = Predictor13; | |
| 596 VP8LPredictors[14] = Predictor0; // <- padding security sentinels | |
| 597 VP8LPredictors[15] = Predictor0; | |
| 598 | 622 |
| 599 VP8LAddGreenToBlueAndRed = VP8LAddGreenToBlueAndRed_C; | 623 VP8LAddGreenToBlueAndRed = VP8LAddGreenToBlueAndRed_C; |
| 600 | 624 |
| 601 VP8LTransformColorInverse = VP8LTransformColorInverse_C; | 625 VP8LTransformColorInverse = VP8LTransformColorInverse_C; |
| 602 | 626 |
| 603 VP8LConvertBGRAToRGB = VP8LConvertBGRAToRGB_C; | 627 VP8LConvertBGRAToRGB = VP8LConvertBGRAToRGB_C; |
| 604 VP8LConvertBGRAToRGBA = VP8LConvertBGRAToRGBA_C; | 628 VP8LConvertBGRAToRGBA = VP8LConvertBGRAToRGBA_C; |
| 605 VP8LConvertBGRAToRGBA4444 = VP8LConvertBGRAToRGBA4444_C; | 629 VP8LConvertBGRAToRGBA4444 = VP8LConvertBGRAToRGBA4444_C; |
| 606 VP8LConvertBGRAToRGB565 = VP8LConvertBGRAToRGB565_C; | 630 VP8LConvertBGRAToRGB565 = VP8LConvertBGRAToRGB565_C; |
| 607 VP8LConvertBGRAToBGR = VP8LConvertBGRAToBGR_C; | 631 VP8LConvertBGRAToBGR = VP8LConvertBGRAToBGR_C; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 619 #if defined(WEBP_USE_NEON) | 643 #if defined(WEBP_USE_NEON) |
| 620 if (VP8GetCPUInfo(kNEON)) { | 644 if (VP8GetCPUInfo(kNEON)) { |
| 621 VP8LDspInitNEON(); | 645 VP8LDspInitNEON(); |
| 622 } | 646 } |
| 623 #endif | 647 #endif |
| 624 #if defined(WEBP_USE_MIPS_DSP_R2) | 648 #if defined(WEBP_USE_MIPS_DSP_R2) |
| 625 if (VP8GetCPUInfo(kMIPSdspR2)) { | 649 if (VP8GetCPUInfo(kMIPSdspR2)) { |
| 626 VP8LDspInitMIPSdspR2(); | 650 VP8LDspInitMIPSdspR2(); |
| 627 } | 651 } |
| 628 #endif | 652 #endif |
| 653 #if defined(WEBP_USE_MSA) |
| 654 if (VP8GetCPUInfo(kMSA)) { |
| 655 VP8LDspInitMSA(); |
| 656 } |
| 657 #endif |
| 629 } | 658 } |
| 630 lossless_last_cpuinfo_used = VP8GetCPUInfo; | 659 lossless_last_cpuinfo_used = VP8GetCPUInfo; |
| 631 } | 660 } |
| 661 #undef COPY_PREDICTOR_ARRAY |
| 632 | 662 |
| 633 //------------------------------------------------------------------------------ | 663 //------------------------------------------------------------------------------ |
| OLD | NEW |