1 // Copyright 2016 Google Inc. All Rights Reserved. 2 // 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 5 // tree. An additional intellectual property rights grant can be found 6 // in the file PATENTS. All contributing project authors may 7 // be found in the AUTHORS file in the root of the source tree. 8 // ----------------------------------------------------------------------------- 9 // 10 // MSA variant of Image transform methods for lossless encoder. 11 // 12 // Authors: Prashant Patil (Prashant.Patil (at) imgtec.com) 13 14 #include "src/dsp/dsp.h" 15 16 #if defined(WEBP_USE_MSA) 17 18 #include "src/dsp/lossless.h" 19 #include "src/dsp/msa_macro.h" 20 21 #define TRANSFORM_COLOR_8(src0, src1, dst0, dst1, c0, c1, mask0, mask1) do { \ 22 v8i16 g0, g1, t0, t1, t2, t3; \ 23 v4i32 t4, t5; \ 24 VSHF_B2_SH(src0, src0, src1, src1, mask0, mask0, g0, g1); \ 25 DOTP_SB2_SH(g0, g1, c0, c0, t0, t1); \ 26 SRAI_H2_SH(t0, t1, 5); \ 27 t0 = __msa_subv_h((v8i16)src0, t0); \ 28 t1 = __msa_subv_h((v8i16)src1, t1); \ 29 t4 = __msa_srli_w((v4i32)src0, 16); \ 30 t5 = __msa_srli_w((v4i32)src1, 16); \ 31 DOTP_SB2_SH(t4, t5, c1, c1, t2, t3); \ 32 SRAI_H2_SH(t2, t3, 5); \ 33 SUB2(t0, t2, t1, t3, t0, t1); \ 34 VSHF_B2_UB(src0, t0, src1, t1, mask1, mask1, dst0, dst1); \ 35 } while (0) 36 37 #define TRANSFORM_COLOR_4(src, dst, c0, c1, mask0, mask1) do { \ 38 const v16i8 g0 = VSHF_SB(src, src, mask0); \ 39 v8i16 t0 = __msa_dotp_s_h(c0, g0); \ 40 v8i16 t1; \ 41 v4i32 t2; \ 42 t0 = SRAI_H(t0, 5); \ 43 t0 = __msa_subv_h((v8i16)src, t0); \ 44 t2 = __msa_srli_w((v4i32)src, 16); \ 45 t1 = __msa_dotp_s_h(c1, (v16i8)t2); \ 46 t1 = SRAI_H(t1, 5); \ 47 t0 = t0 - t1; \ 48 dst = VSHF_UB(src, t0, mask1); \ 49 } while (0) 50 51 static void TransformColor_MSA(const VP8LMultipliers* const m, uint32_t* data, 52 int num_pixels) { 53 v16u8 src0, dst0; 54 const v16i8 g2br = (v16i8)__msa_fill_w(m->green_to_blue_ | 55 (m->green_to_red_ << 16)); 56 const v16i8 r2b = (v16i8)__msa_fill_w(m->red_to_blue_); 57 const v16u8 mask0 = { 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 58 13, 255, 13, 255 }; 59 const v16u8 mask1 = { 16, 1, 18, 3, 20, 5, 22, 7, 24, 9, 26, 11, 60 28, 13, 30, 15 }; 61 62 while (num_pixels >= 8) { 63 v16u8 src1, dst1; 64 LD_UB2(data, 4, src0, src1); 65 TRANSFORM_COLOR_8(src0, src1, dst0, dst1, g2br, r2b, mask0, mask1); 66 ST_UB2(dst0, dst1, data, 4); 67 data += 8; 68 num_pixels -= 8; 69 } 70 if (num_pixels > 0) { 71 if (num_pixels >= 4) { 72 src0 = LD_UB(data); 73 TRANSFORM_COLOR_4(src0, dst0, g2br, r2b, mask0, mask1); 74 ST_UB(dst0, data); 75 data += 4; 76 num_pixels -= 4; 77 } 78 if (num_pixels > 0) { 79 src0 = LD_UB(data); 80 TRANSFORM_COLOR_4(src0, dst0, g2br, r2b, mask0, mask1); 81 if (num_pixels == 3) { 82 const uint64_t pix_d = __msa_copy_s_d((v2i64)dst0, 0); 83 const uint32_t pix_w = __msa_copy_s_w((v4i32)dst0, 2); 84 SD(pix_d, data + 0); 85 SW(pix_w, data + 2); 86 } else if (num_pixels == 2) { 87 const uint64_t pix_d = __msa_copy_s_d((v2i64)dst0, 0); 88 SD(pix_d, data); 89 } else { 90 const uint32_t pix_w = __msa_copy_s_w((v4i32)dst0, 0); 91 SW(pix_w, data); 92 } 93 } 94 } 95 } 96 97 static void SubtractGreenFromBlueAndRed_MSA(uint32_t* argb_data, 98 int num_pixels) { 99 int i; 100 uint8_t* ptemp_data = (uint8_t*)argb_data; 101 v16u8 src0, dst0, tmp0; 102 const v16u8 mask = { 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 103 13, 255, 13, 255 }; 104 105 while (num_pixels >= 8) { 106 v16u8 src1, dst1, tmp1; 107 LD_UB2(ptemp_data, 16, src0, src1); 108 VSHF_B2_UB(src0, src1, src1, src0, mask, mask, tmp0, tmp1); 109 SUB2(src0, tmp0, src1, tmp1, dst0, dst1); 110 ST_UB2(dst0, dst1, ptemp_data, 16); 111 ptemp_data += 8 * 4; 112 num_pixels -= 8; 113 } 114 if (num_pixels > 0) { 115 if (num_pixels >= 4) { 116 src0 = LD_UB(ptemp_data); 117 tmp0 = VSHF_UB(src0, src0, mask); 118 dst0 = src0 - tmp0; 119 ST_UB(dst0, ptemp_data); 120 ptemp_data += 4 * 4; 121 num_pixels -= 4; 122 } 123 for (i = 0; i < num_pixels; i++) { 124 const uint8_t b = ptemp_data[0]; 125 const uint8_t g = ptemp_data[1]; 126 const uint8_t r = ptemp_data[2]; 127 ptemp_data[0] = (b - g) & 0xff; 128 ptemp_data[2] = (r - g) & 0xff; 129 ptemp_data += 4; 130 } 131 } 132 } 133 134 //------------------------------------------------------------------------------ 135 // Entry point 136 137 extern void VP8LEncDspInitMSA(void); 138 139 WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMSA(void) { 140 VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_MSA; 141 VP8LTransformColor = TransformColor_MSA; 142 } 143 144 #else // !WEBP_USE_MSA 145 146 WEBP_DSP_INIT_STUB(VP8LEncDspInitMSA) 147 148 #endif // WEBP_USE_MSA 149