1 /* 2 * Copyright 2014 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 9 #include "SkBitmapProcState.h" 10 #include "SkBitmapScaler.h" 11 #include "SkColorPriv.h" 12 #include "SkPaint.h" 13 #include "SkUtils.h" 14 15 static void SI8_D16_nofilter_DX_mips_dsp(const SkBitmapProcState& s, 16 const uint32_t* SK_RESTRICT xy, 17 int count, uint16_t* SK_RESTRICT colors) { 18 SkASSERT(count > 0 && colors != NULL); 19 SkASSERT(s.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)); 20 SkASSERT(kNone_SkFilterQuality == s.fFilterLevel); 21 const uint16_t* SK_RESTRICT table = s.fBitmap->getColorTable()->read16BitCache(); 22 const uint8_t* SK_RESTRICT srcAddr = (const uint8_t*)s.fBitmap->getPixels(); 23 SkASSERT((unsigned)xy[0] < (unsigned)s.fBitmap->height()); 24 srcAddr = (const uint8_t*)((const char*)srcAddr + xy[0] * s.fBitmap->rowBytes()); 25 uint8_t src; 26 27 if (1 == s.fBitmap->width()) { 28 src = srcAddr[0]; 29 uint16_t dstValue = table[src]; 30 sk_memset16(colors, dstValue, count); 31 } else { 32 int count8; 33 const uint16_t* SK_RESTRICT xx = (const uint16_t*)(xy + 1); 34 35 __asm__ volatile ( 36 ".set push \n\t" 37 ".set noreorder \n\t" 38 ".set noat \n\t" 39 "sra %[count8], %[count], 3 \n\t" 40 "beqz %[count8], 3f \n\t" 41 " addiu %[count8], %[count8], -1 \n\t" 42 "1: \n\t" 43 "beqz %[count8], 2f \n\t" 44 " addiu %[count8], %[count8], -1 \n\t" 45 "pref 0, 16(%[xx]) \n\t" 46 "lhu $t0, 0(%[xx]) \n\t" 47 "lhu $t1, 2(%[xx]) \n\t" 48 "lhu $t2, 4(%[xx]) \n\t" 49 "lhu $t3, 6(%[xx]) \n\t" 50 "lhu $t4, 8(%[xx]) \n\t" 51 "lhu $t5, 10(%[xx]) \n\t" 52 "lhu $t6, 12(%[xx]) \n\t" 53 "lhu $t7, 14(%[xx]) \n\t" 54 "pref 0, 8(%[srcAddr]) \n\t" 55 "lbux $t0, $t0(%[srcAddr]) \n\t" 56 "lbux $t1, $t1(%[srcAddr]) \n\t" 57 "lbux $t2, $t2(%[srcAddr]) \n\t" 58 "lbux $t3, $t3(%[srcAddr]) \n\t" 59 "lbux $t4, $t4(%[srcAddr]) \n\t" 60 "lbux $t5, $t5(%[srcAddr]) \n\t" 61 "lbux $t6, $t6(%[srcAddr]) \n\t" 62 "lbux $t7, $t7(%[srcAddr]) \n\t" 63 "addu $t0, $t0, $t0 \n\t" 64 "addu $t1, $t1, $t1 \n\t" 65 "addu $t2, $t2, $t2 \n\t" 66 "addu $t3, $t3, $t3 \n\t" 67 "addu $t4, $t4, $t4 \n\t" 68 "addu $t5, $t5, $t5 \n\t" 69 "addu $t6, $t6, $t6 \n\t" 70 "addu $t7, $t7, $t7 \n\t" 71 "pref 0, 16(%[table]) \n\t" 72 "lhx $t0, $t0(%[table]) \n\t" 73 "lhx $t1, $t1(%[table]) \n\t" 74 "lhx $t2, $t2(%[table]) \n\t" 75 "lhx $t3, $t3(%[table]) \n\t" 76 "lhx $t4, $t4(%[table]) \n\t" 77 "lhx $t5, $t5(%[table]) \n\t" 78 "lhx $t6, $t6(%[table]) \n\t" 79 "lhx $t7, $t7(%[table]) \n\t" 80 "sh $t0, 0(%[colors]) \n\t" 81 "sh $t1, 2(%[colors]) \n\t" 82 "sh $t2, 4(%[colors]) \n\t" 83 "sh $t3, 6(%[colors]) \n\t" 84 "sh $t4, 8(%[colors]) \n\t" 85 "sh $t5, 10(%[colors]) \n\t" 86 "sh $t6, 12(%[colors]) \n\t" 87 "sh $t7, 14(%[colors]) \n\t" 88 "addiu %[xx], %[xx], 16 \n\t" 89 "bgtz %[count8], 1b \n\t" 90 " addiu %[colors], %[colors], 16 \n\t" 91 "2: \n\t" 92 "lhu $t0, 0(%[xx]) \n\t" 93 "lhu $t1, 2(%[xx]) \n\t" 94 "lhu $t2, 4(%[xx]) \n\t" 95 "lhu $t3, 6(%[xx]) \n\t" 96 "lhu $t4, 8(%[xx]) \n\t" 97 "lhu $t5, 10(%[xx]) \n\t" 98 "lhu $t6, 12(%[xx]) \n\t" 99 "lhu $t7, 14(%[xx]) \n\t" 100 "lbux $t0, $t0(%[srcAddr]) \n\t" 101 "lbux $t1, $t1(%[srcAddr]) \n\t" 102 "lbux $t2, $t2(%[srcAddr]) \n\t" 103 "lbux $t3, $t3(%[srcAddr]) \n\t" 104 "lbux $t4, $t4(%[srcAddr]) \n\t" 105 "lbux $t5, $t5(%[srcAddr]) \n\t" 106 "lbux $t6, $t6(%[srcAddr]) \n\t" 107 "lbux $t7, $t7(%[srcAddr]) \n\t" 108 "addu $t0, $t0, $t0 \n\t" 109 "addu $t1, $t1, $t1 \n\t" 110 "addu $t2, $t2, $t2 \n\t" 111 "addu $t3, $t3, $t3 \n\t" 112 "addu $t4, $t4, $t4 \n\t" 113 "addu $t5, $t5, $t5 \n\t" 114 "addu $t6, $t6, $t6 \n\t" 115 "addu $t7, $t7, $t7 \n\t" 116 "lhx $t0, $t0(%[table]) \n\t" 117 "lhx $t1, $t1(%[table]) \n\t" 118 "lhx $t2, $t2(%[table]) \n\t" 119 "lhx $t3, $t3(%[table]) \n\t" 120 "lhx $t4, $t4(%[table]) \n\t" 121 "lhx $t5, $t5(%[table]) \n\t" 122 "lhx $t6, $t6(%[table]) \n\t" 123 "lhx $t7, $t7(%[table]) \n\t" 124 "sh $t0, 0(%[colors]) \n\t" 125 "sh $t1, 2(%[colors]) \n\t" 126 "sh $t2, 4(%[colors]) \n\t" 127 "sh $t3, 6(%[colors]) \n\t" 128 "sh $t4, 8(%[colors]) \n\t" 129 "sh $t5, 10(%[colors]) \n\t" 130 "sh $t6, 12(%[colors]) \n\t" 131 "sh $t7, 14(%[colors]) \n\t" 132 "addiu %[xx], %[xx], 16 \n\t" 133 "addiu %[colors], %[colors], 16 \n\t" 134 "3: \n\t" 135 ".set pop \n\t" 136 : [xx]"+r"(xx), [count8]"=&r"(count8), [colors]"+r"(colors) 137 : [table]"r"(table), [srcAddr]"r"(srcAddr), [count]"r"(count) 138 : "memory","t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7" 139 ); 140 141 for (int i = (count & 7); i > 0; --i) { 142 src = srcAddr[*xx++]; *colors++ = table[src]; 143 } 144 } 145 } 146 147 static void SI8_opaque_D32_nofilter_DX_mips_dsp(const SkBitmapProcState& s, 148 const uint32_t* SK_RESTRICT xy, 149 int count, SkPMColor* SK_RESTRICT colors) { 150 SkASSERT(count > 0 && colors != NULL); 151 SkASSERT(s.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)); 152 SkASSERT(kNone_SkFilterQuality == s.fFilterLevel); 153 const SkPMColor* SK_RESTRICT table = s.fBitmap->getColorTable()->readColors(); 154 const uint8_t* SK_RESTRICT srcAddr = (const uint8_t*)s.fBitmap->getPixels(); 155 srcAddr = (const uint8_t*)((const char*)srcAddr + xy[0] * s.fBitmap->rowBytes()); 156 157 if (1 == s.fBitmap->width()) { 158 uint8_t src = srcAddr[0]; 159 SkPMColor dstValue = table[src]; 160 sk_memset32(colors, dstValue, count); 161 } else { 162 const uint16_t* xx = (const uint16_t*)(xy + 1); 163 int s0, s1, s2, s3, s4, s5, s6, s7; 164 __asm__ volatile ( 165 ".set push \n\t" 166 ".set noreorder \n\t" 167 ".set noat \n\t" 168 "srl $t8, %[count], 4 \n\t" 169 "beqz $t8, 3f \n\t" 170 " nop \n\t" 171 "1: \n\t" 172 "addiu $t8, $t8, -1 \n\t" 173 "beqz $t8, 2f \n\t" 174 " addiu %[count], %[count], -16 \n\t" 175 "pref 0, 32(%[xx]) \n\t" 176 "lhu $t0, 0(%[xx]) \n\t" 177 "lhu $t1, 2(%[xx]) \n\t" 178 "lhu $t2, 4(%[xx]) \n\t" 179 "lhu $t3, 6(%[xx]) \n\t" 180 "lhu $t4, 8(%[xx]) \n\t" 181 "lhu $t5, 10(%[xx]) \n\t" 182 "lhu $t6, 12(%[xx]) \n\t" 183 "lhu $t7, 14(%[xx]) \n\t" 184 "lhu %[s0], 16(%[xx]) \n\t" 185 "lhu %[s1], 18(%[xx]) \n\t" 186 "lhu %[s2], 20(%[xx]) \n\t" 187 "lhu %[s3], 22(%[xx]) \n\t" 188 "lhu %[s4], 24(%[xx]) \n\t" 189 "lhu %[s5], 26(%[xx]) \n\t" 190 "lhu %[s6], 28(%[xx]) \n\t" 191 "lhu %[s7], 30(%[xx]) \n\t" 192 "lbux $t0, $t0(%[srcAddr]) \n\t" 193 "lbux $t1, $t1(%[srcAddr]) \n\t" 194 "lbux $t2, $t2(%[srcAddr]) \n\t" 195 "lbux $t3, $t3(%[srcAddr]) \n\t" 196 "lbux $t4, $t4(%[srcAddr]) \n\t" 197 "lbux $t5, $t5(%[srcAddr]) \n\t" 198 "lbux $t6, $t6(%[srcAddr]) \n\t" 199 "lbux $t7, $t7(%[srcAddr]) \n\t" 200 "lbux %[s0], %[s0](%[srcAddr]) \n\t" 201 "lbux %[s1], %[s1](%[srcAddr]) \n\t" 202 "lbux %[s2], %[s2](%[srcAddr]) \n\t" 203 "lbux %[s3], %[s3](%[srcAddr]) \n\t" 204 "lbux %[s4], %[s4](%[srcAddr]) \n\t" 205 "lbux %[s5], %[s5](%[srcAddr]) \n\t" 206 "lbux %[s6], %[s6](%[srcAddr]) \n\t" 207 "lbux %[s7], %[s7](%[srcAddr]) \n\t" 208 "sll $t0, $t0, 2 \n\t" 209 "sll $t1, $t1, 2 \n\t" 210 "sll $t2, $t2, 2 \n\t" 211 "sll $t3, $t3, 2 \n\t" 212 "sll $t4, $t4, 2 \n\t" 213 "sll $t5, $t5, 2 \n\t" 214 "sll $t6, $t6, 2 \n\t" 215 "sll $t7, $t7, 2 \n\t" 216 "sll %[s0], %[s0], 2 \n\t" 217 "sll %[s1], %[s1], 2 \n\t" 218 "sll %[s2], %[s2], 2 \n\t" 219 "sll %[s3], %[s3], 2 \n\t" 220 "sll %[s4], %[s4], 2 \n\t" 221 "sll %[s5], %[s5], 2 \n\t" 222 "sll %[s6], %[s6], 2 \n\t" 223 "sll %[s7], %[s7], 2 \n\t" 224 "pref 0, 64(%[table]) \n\t" 225 "lwx $t0, $t0(%[table]) \n\t" 226 "lwx $t1, $t1(%[table]) \n\t" 227 "lwx $t2, $t2(%[table]) \n\t" 228 "lwx $t3, $t3(%[table]) \n\t" 229 "lwx $t4, $t4(%[table]) \n\t" 230 "lwx $t5, $t5(%[table]) \n\t" 231 "lwx $t6, $t6(%[table]) \n\t" 232 "lwx $t7, $t7(%[table]) \n\t" 233 "lwx %[s0], %[s0](%[table]) \n\t" 234 "lwx %[s1], %[s1](%[table]) \n\t" 235 "lwx %[s2], %[s2](%[table]) \n\t" 236 "lwx %[s3], %[s3](%[table]) \n\t" 237 "lwx %[s4], %[s4](%[table]) \n\t" 238 "lwx %[s5], %[s5](%[table]) \n\t" 239 "lwx %[s6], %[s6](%[table]) \n\t" 240 "lwx %[s7], %[s7](%[table]) \n\t" 241 "pref 30, 64(%[colors]) \n\t" 242 "sw $t0, 0(%[colors]) \n\t" 243 "sw $t1, 4(%[colors]) \n\t" 244 "sw $t2, 8(%[colors]) \n\t" 245 "sw $t3, 12(%[colors]) \n\t" 246 "sw $t4, 16(%[colors]) \n\t" 247 "sw $t5, 20(%[colors]) \n\t" 248 "sw $t6, 24(%[colors]) \n\t" 249 "sw $t7, 28(%[colors]) \n\t" 250 "sw %[s0], 32(%[colors]) \n\t" 251 "sw %[s1], 36(%[colors]) \n\t" 252 "sw %[s2], 40(%[colors]) \n\t" 253 "sw %[s3], 44(%[colors]) \n\t" 254 "sw %[s4], 48(%[colors]) \n\t" 255 "sw %[s5], 52(%[colors]) \n\t" 256 "sw %[s6], 56(%[colors]) \n\t" 257 "sw %[s7], 60(%[colors]) \n\t" 258 "addiu %[xx], %[xx], 32 \n\t" 259 "b 1b \n\t" 260 " addiu %[colors], %[colors], 64 \n\t" 261 "2: \n\t" 262 "lhu $t0, 0(%[xx]) \n\t" 263 "lhu $t1, 2(%[xx]) \n\t" 264 "lhu $t2, 4(%[xx]) \n\t" 265 "lhu $t3, 6(%[xx]) \n\t" 266 "lhu $t4, 8(%[xx]) \n\t" 267 "lhu $t5, 10(%[xx]) \n\t" 268 "lhu $t6, 12(%[xx]) \n\t" 269 "lhu $t7, 14(%[xx]) \n\t" 270 "lhu %[s0], 16(%[xx]) \n\t" 271 "lhu %[s1], 18(%[xx]) \n\t" 272 "lhu %[s2], 20(%[xx]) \n\t" 273 "lhu %[s3], 22(%[xx]) \n\t" 274 "lhu %[s4], 24(%[xx]) \n\t" 275 "lhu %[s5], 26(%[xx]) \n\t" 276 "lhu %[s6], 28(%[xx]) \n\t" 277 "lhu %[s7], 30(%[xx]) \n\t" 278 "lbux $t0, $t0(%[srcAddr]) \n\t" 279 "lbux $t1, $t1(%[srcAddr]) \n\t" 280 "lbux $t2, $t2(%[srcAddr]) \n\t" 281 "lbux $t3, $t3(%[srcAddr]) \n\t" 282 "lbux $t4, $t4(%[srcAddr]) \n\t" 283 "lbux $t5, $t5(%[srcAddr]) \n\t" 284 "lbux $t6, $t6(%[srcAddr]) \n\t" 285 "lbux $t7, $t7(%[srcAddr]) \n\t" 286 "lbux %[s0], %[s0](%[srcAddr]) \n\t" 287 "lbux %[s1], %[s1](%[srcAddr]) \n\t" 288 "lbux %[s2], %[s2](%[srcAddr]) \n\t" 289 "lbux %[s3], %[s3](%[srcAddr]) \n\t" 290 "lbux %[s4], %[s4](%[srcAddr]) \n\t" 291 "lbux %[s5], %[s5](%[srcAddr]) \n\t" 292 "lbux %[s6], %[s6](%[srcAddr]) \n\t" 293 "lbux %[s7], %[s7](%[srcAddr]) \n\t" 294 "sll $t0, $t0, 2 \n\t" 295 "sll $t1, $t1, 2 \n\t" 296 "sll $t2, $t2, 2 \n\t" 297 "sll $t3, $t3, 2 \n\t" 298 "sll $t4, $t4, 2 \n\t" 299 "sll $t5, $t5, 2 \n\t" 300 "sll $t6, $t6, 2 \n\t" 301 "sll $t7, $t7, 2 \n\t" 302 "sll %[s0], %[s0], 2 \n\t" 303 "sll %[s1], %[s1], 2 \n\t" 304 "sll %[s2], %[s2], 2 \n\t" 305 "sll %[s3], %[s3], 2 \n\t" 306 "sll %[s4], %[s4], 2 \n\t" 307 "sll %[s5], %[s5], 2 \n\t" 308 "sll %[s6], %[s6], 2 \n\t" 309 "sll %[s7], %[s7], 2 \n\t" 310 "lwx $t0, $t0(%[table]) \n\t" 311 "lwx $t1, $t1(%[table]) \n\t" 312 "lwx $t2, $t2(%[table]) \n\t" 313 "lwx $t3, $t3(%[table]) \n\t" 314 "lwx $t4, $t4(%[table]) \n\t" 315 "lwx $t5, $t5(%[table]) \n\t" 316 "lwx $t6, $t6(%[table]) \n\t" 317 "lwx $t7, $t7(%[table]) \n\t" 318 "lwx %[s0], %[s0](%[table]) \n\t" 319 "lwx %[s1], %[s1](%[table]) \n\t" 320 "lwx %[s2], %[s2](%[table]) \n\t" 321 "lwx %[s3], %[s3](%[table]) \n\t" 322 "lwx %[s4], %[s4](%[table]) \n\t" 323 "lwx %[s5], %[s5](%[table]) \n\t" 324 "lwx %[s6], %[s6](%[table]) \n\t" 325 "lwx %[s7], %[s7](%[table]) \n\t" 326 "sw $t0, 0(%[colors]) \n\t" 327 "sw $t1, 4(%[colors]) \n\t" 328 "sw $t2, 8(%[colors]) \n\t" 329 "sw $t3, 12(%[colors]) \n\t" 330 "sw $t4, 16(%[colors]) \n\t" 331 "sw $t5, 20(%[colors]) \n\t" 332 "sw $t6, 24(%[colors]) \n\t" 333 "sw $t7, 28(%[colors]) \n\t" 334 "sw %[s0], 32(%[colors]) \n\t" 335 "sw %[s1], 36(%[colors]) \n\t" 336 "sw %[s2], 40(%[colors]) \n\t" 337 "sw %[s3], 44(%[colors]) \n\t" 338 "sw %[s4], 48(%[colors]) \n\t" 339 "sw %[s5], 52(%[colors]) \n\t" 340 "sw %[s6], 56(%[colors]) \n\t" 341 "sw %[s7], 60(%[colors]) \n\t" 342 "addiu %[xx], %[xx], 32 \n\t" 343 "beqz %[count], 4f \n\t" 344 " addiu %[colors], %[colors], 64 \n\t" 345 "3: \n\t" 346 "addiu %[count], %[count], -1 \n\t" 347 "lhu $t0, 0(%[xx]) \n\t" 348 "lbux $t1, $t0(%[srcAddr]) \n\t" 349 "sll $t1, $t1, 2 \n\t" 350 "lwx $t2, $t1(%[table]) \n\t" 351 "sw $t2, 0(%[colors]) \n\t" 352 "addiu %[xx], %[xx], 2 \n\t" 353 "bnez %[count], 3b \n\t" 354 " addiu %[colors], %[colors], 4 \n\t" 355 "4: \n\t" 356 ".set pop \n\t" 357 : [xx]"+r"(xx), [count]"+r"(count), [colors]"+r"(colors), 358 [s0]"=&r"(s0), [s1]"=&r"(s1), [s2]"=&r"(s2), [s3]"=&r"(s3), 359 [s4]"=&r"(s4), [s5]"=&r"(s5), [s6]"=&r"(s6), [s7]"=&r"(s7) 360 : [table]"r"(table), [srcAddr]"r"(srcAddr) 361 : "memory", "t0", "t1", "t2", "t3", 362 "t4", "t5", "t6", "t7", "t8" 363 ); 364 } 365 } 366 367 /* If we replace a sampleproc, then we null-out the associated shaderproc, 368 otherwise the shader won't even look at the matrix/sampler 369 */ 370 371 void SkBitmapProcState::platformProcs() { 372 bool isOpaque = 256 == fAlphaScale; 373 bool justDx = false; 374 375 if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { 376 justDx = true; 377 } 378 379 switch (fBitmap->colorType()) { 380 case kIndex_8_SkColorType: 381 if (justDx && kNone_SkFilterQuality == fFilterLevel) { 382 fSampleProc16 = SI8_D16_nofilter_DX_mips_dsp; 383 fShaderProc16 = NULL; 384 if (isOpaque) { 385 fSampleProc32 = SI8_opaque_D32_nofilter_DX_mips_dsp; 386 fShaderProc32 = NULL; 387 } 388 } 389 break; 390 default: 391 break; 392 } 393 } 394 395 void SkBitmapScaler::PlatformConvolutionProcs(SkConvolutionProcs*) {} 396