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 15static 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(SkPaint::kNone_FilterLevel == s.fFilterLevel); 21 const uint16_t* SK_RESTRICT table = s.fBitmap->getColorTable()->lock16BitCache(); 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 s.fBitmap->getColorTable()->unlock16BitCache(); 146} 147 148static void SI8_opaque_D32_nofilter_DX_mips_dsp(const SkBitmapProcState& s, 149 const uint32_t* SK_RESTRICT xy, 150 int count, SkPMColor* SK_RESTRICT colors) { 151 SkASSERT(count > 0 && colors != NULL); 152 SkASSERT(s.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)); 153 SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel); 154 const SkPMColor* SK_RESTRICT table = s.fBitmap->getColorTable()->lockColors(); 155 const uint8_t* SK_RESTRICT srcAddr = (const uint8_t*)s.fBitmap->getPixels(); 156 srcAddr = (const uint8_t*)((const char*)srcAddr + xy[0] * s.fBitmap->rowBytes()); 157 158 if (1 == s.fBitmap->width()) { 159 uint8_t src = srcAddr[0]; 160 SkPMColor dstValue = table[src]; 161 sk_memset32(colors, dstValue, count); 162 } else { 163 const uint16_t* xx = (const uint16_t*)(xy + 1); 164 int s0, s1, s2, s3, s4, s5, s6, s7; 165 __asm__ volatile ( 166 ".set push \n\t" 167 ".set noreorder \n\t" 168 ".set noat \n\t" 169 "srl $t8, %[count], 4 \n\t" 170 "beqz $t8, 3f \n\t" 171 " nop \n\t" 172 "1: \n\t" 173 "addiu $t8, $t8, -1 \n\t" 174 "beqz $t8, 2f \n\t" 175 " addiu %[count], %[count], -16 \n\t" 176 "pref 0, 32(%[xx]) \n\t" 177 "lhu $t0, 0(%[xx]) \n\t" 178 "lhu $t1, 2(%[xx]) \n\t" 179 "lhu $t2, 4(%[xx]) \n\t" 180 "lhu $t3, 6(%[xx]) \n\t" 181 "lhu $t4, 8(%[xx]) \n\t" 182 "lhu $t5, 10(%[xx]) \n\t" 183 "lhu $t6, 12(%[xx]) \n\t" 184 "lhu $t7, 14(%[xx]) \n\t" 185 "lhu %[s0], 16(%[xx]) \n\t" 186 "lhu %[s1], 18(%[xx]) \n\t" 187 "lhu %[s2], 20(%[xx]) \n\t" 188 "lhu %[s3], 22(%[xx]) \n\t" 189 "lhu %[s4], 24(%[xx]) \n\t" 190 "lhu %[s5], 26(%[xx]) \n\t" 191 "lhu %[s6], 28(%[xx]) \n\t" 192 "lhu %[s7], 30(%[xx]) \n\t" 193 "lbux $t0, $t0(%[srcAddr]) \n\t" 194 "lbux $t1, $t1(%[srcAddr]) \n\t" 195 "lbux $t2, $t2(%[srcAddr]) \n\t" 196 "lbux $t3, $t3(%[srcAddr]) \n\t" 197 "lbux $t4, $t4(%[srcAddr]) \n\t" 198 "lbux $t5, $t5(%[srcAddr]) \n\t" 199 "lbux $t6, $t6(%[srcAddr]) \n\t" 200 "lbux $t7, $t7(%[srcAddr]) \n\t" 201 "lbux %[s0], %[s0](%[srcAddr]) \n\t" 202 "lbux %[s1], %[s1](%[srcAddr]) \n\t" 203 "lbux %[s2], %[s2](%[srcAddr]) \n\t" 204 "lbux %[s3], %[s3](%[srcAddr]) \n\t" 205 "lbux %[s4], %[s4](%[srcAddr]) \n\t" 206 "lbux %[s5], %[s5](%[srcAddr]) \n\t" 207 "lbux %[s6], %[s6](%[srcAddr]) \n\t" 208 "lbux %[s7], %[s7](%[srcAddr]) \n\t" 209 "sll $t0, $t0, 2 \n\t" 210 "sll $t1, $t1, 2 \n\t" 211 "sll $t2, $t2, 2 \n\t" 212 "sll $t3, $t3, 2 \n\t" 213 "sll $t4, $t4, 2 \n\t" 214 "sll $t5, $t5, 2 \n\t" 215 "sll $t6, $t6, 2 \n\t" 216 "sll $t7, $t7, 2 \n\t" 217 "sll %[s0], %[s0], 2 \n\t" 218 "sll %[s1], %[s1], 2 \n\t" 219 "sll %[s2], %[s2], 2 \n\t" 220 "sll %[s3], %[s3], 2 \n\t" 221 "sll %[s4], %[s4], 2 \n\t" 222 "sll %[s5], %[s5], 2 \n\t" 223 "sll %[s6], %[s6], 2 \n\t" 224 "sll %[s7], %[s7], 2 \n\t" 225 "pref 0, 64(%[table]) \n\t" 226 "lwx $t0, $t0(%[table]) \n\t" 227 "lwx $t1, $t1(%[table]) \n\t" 228 "lwx $t2, $t2(%[table]) \n\t" 229 "lwx $t3, $t3(%[table]) \n\t" 230 "lwx $t4, $t4(%[table]) \n\t" 231 "lwx $t5, $t5(%[table]) \n\t" 232 "lwx $t6, $t6(%[table]) \n\t" 233 "lwx $t7, $t7(%[table]) \n\t" 234 "lwx %[s0], %[s0](%[table]) \n\t" 235 "lwx %[s1], %[s1](%[table]) \n\t" 236 "lwx %[s2], %[s2](%[table]) \n\t" 237 "lwx %[s3], %[s3](%[table]) \n\t" 238 "lwx %[s4], %[s4](%[table]) \n\t" 239 "lwx %[s5], %[s5](%[table]) \n\t" 240 "lwx %[s6], %[s6](%[table]) \n\t" 241 "lwx %[s7], %[s7](%[table]) \n\t" 242 "pref 30, 64(%[colors]) \n\t" 243 "sw $t0, 0(%[colors]) \n\t" 244 "sw $t1, 4(%[colors]) \n\t" 245 "sw $t2, 8(%[colors]) \n\t" 246 "sw $t3, 12(%[colors]) \n\t" 247 "sw $t4, 16(%[colors]) \n\t" 248 "sw $t5, 20(%[colors]) \n\t" 249 "sw $t6, 24(%[colors]) \n\t" 250 "sw $t7, 28(%[colors]) \n\t" 251 "sw %[s0], 32(%[colors]) \n\t" 252 "sw %[s1], 36(%[colors]) \n\t" 253 "sw %[s2], 40(%[colors]) \n\t" 254 "sw %[s3], 44(%[colors]) \n\t" 255 "sw %[s4], 48(%[colors]) \n\t" 256 "sw %[s5], 52(%[colors]) \n\t" 257 "sw %[s6], 56(%[colors]) \n\t" 258 "sw %[s7], 60(%[colors]) \n\t" 259 "addiu %[xx], %[xx], 32 \n\t" 260 "b 1b \n\t" 261 " addiu %[colors], %[colors], 64 \n\t" 262 "2: \n\t" 263 "lhu $t0, 0(%[xx]) \n\t" 264 "lhu $t1, 2(%[xx]) \n\t" 265 "lhu $t2, 4(%[xx]) \n\t" 266 "lhu $t3, 6(%[xx]) \n\t" 267 "lhu $t4, 8(%[xx]) \n\t" 268 "lhu $t5, 10(%[xx]) \n\t" 269 "lhu $t6, 12(%[xx]) \n\t" 270 "lhu $t7, 14(%[xx]) \n\t" 271 "lhu %[s0], 16(%[xx]) \n\t" 272 "lhu %[s1], 18(%[xx]) \n\t" 273 "lhu %[s2], 20(%[xx]) \n\t" 274 "lhu %[s3], 22(%[xx]) \n\t" 275 "lhu %[s4], 24(%[xx]) \n\t" 276 "lhu %[s5], 26(%[xx]) \n\t" 277 "lhu %[s6], 28(%[xx]) \n\t" 278 "lhu %[s7], 30(%[xx]) \n\t" 279 "lbux $t0, $t0(%[srcAddr]) \n\t" 280 "lbux $t1, $t1(%[srcAddr]) \n\t" 281 "lbux $t2, $t2(%[srcAddr]) \n\t" 282 "lbux $t3, $t3(%[srcAddr]) \n\t" 283 "lbux $t4, $t4(%[srcAddr]) \n\t" 284 "lbux $t5, $t5(%[srcAddr]) \n\t" 285 "lbux $t6, $t6(%[srcAddr]) \n\t" 286 "lbux $t7, $t7(%[srcAddr]) \n\t" 287 "lbux %[s0], %[s0](%[srcAddr]) \n\t" 288 "lbux %[s1], %[s1](%[srcAddr]) \n\t" 289 "lbux %[s2], %[s2](%[srcAddr]) \n\t" 290 "lbux %[s3], %[s3](%[srcAddr]) \n\t" 291 "lbux %[s4], %[s4](%[srcAddr]) \n\t" 292 "lbux %[s5], %[s5](%[srcAddr]) \n\t" 293 "lbux %[s6], %[s6](%[srcAddr]) \n\t" 294 "lbux %[s7], %[s7](%[srcAddr]) \n\t" 295 "sll $t0, $t0, 2 \n\t" 296 "sll $t1, $t1, 2 \n\t" 297 "sll $t2, $t2, 2 \n\t" 298 "sll $t3, $t3, 2 \n\t" 299 "sll $t4, $t4, 2 \n\t" 300 "sll $t5, $t5, 2 \n\t" 301 "sll $t6, $t6, 2 \n\t" 302 "sll $t7, $t7, 2 \n\t" 303 "sll %[s0], %[s0], 2 \n\t" 304 "sll %[s1], %[s1], 2 \n\t" 305 "sll %[s2], %[s2], 2 \n\t" 306 "sll %[s3], %[s3], 2 \n\t" 307 "sll %[s4], %[s4], 2 \n\t" 308 "sll %[s5], %[s5], 2 \n\t" 309 "sll %[s6], %[s6], 2 \n\t" 310 "sll %[s7], %[s7], 2 \n\t" 311 "lwx $t0, $t0(%[table]) \n\t" 312 "lwx $t1, $t1(%[table]) \n\t" 313 "lwx $t2, $t2(%[table]) \n\t" 314 "lwx $t3, $t3(%[table]) \n\t" 315 "lwx $t4, $t4(%[table]) \n\t" 316 "lwx $t5, $t5(%[table]) \n\t" 317 "lwx $t6, $t6(%[table]) \n\t" 318 "lwx $t7, $t7(%[table]) \n\t" 319 "lwx %[s0], %[s0](%[table]) \n\t" 320 "lwx %[s1], %[s1](%[table]) \n\t" 321 "lwx %[s2], %[s2](%[table]) \n\t" 322 "lwx %[s3], %[s3](%[table]) \n\t" 323 "lwx %[s4], %[s4](%[table]) \n\t" 324 "lwx %[s5], %[s5](%[table]) \n\t" 325 "lwx %[s6], %[s6](%[table]) \n\t" 326 "lwx %[s7], %[s7](%[table]) \n\t" 327 "sw $t0, 0(%[colors]) \n\t" 328 "sw $t1, 4(%[colors]) \n\t" 329 "sw $t2, 8(%[colors]) \n\t" 330 "sw $t3, 12(%[colors]) \n\t" 331 "sw $t4, 16(%[colors]) \n\t" 332 "sw $t5, 20(%[colors]) \n\t" 333 "sw $t6, 24(%[colors]) \n\t" 334 "sw $t7, 28(%[colors]) \n\t" 335 "sw %[s0], 32(%[colors]) \n\t" 336 "sw %[s1], 36(%[colors]) \n\t" 337 "sw %[s2], 40(%[colors]) \n\t" 338 "sw %[s3], 44(%[colors]) \n\t" 339 "sw %[s4], 48(%[colors]) \n\t" 340 "sw %[s5], 52(%[colors]) \n\t" 341 "sw %[s6], 56(%[colors]) \n\t" 342 "sw %[s7], 60(%[colors]) \n\t" 343 "addiu %[xx], %[xx], 32 \n\t" 344 "beqz %[count], 4f \n\t" 345 " addiu %[colors], %[colors], 64 \n\t" 346 "3: \n\t" 347 "addiu %[count], %[count], -1 \n\t" 348 "lhu $t0, 0(%[xx]) \n\t" 349 "lbux $t1, $t0(%[srcAddr]) \n\t" 350 "sll $t1, $t1, 2 \n\t" 351 "lwx $t2, $t1(%[table]) \n\t" 352 "sw $t2, 0(%[colors]) \n\t" 353 "addiu %[xx], %[xx], 2 \n\t" 354 "bnez %[count], 3b \n\t" 355 " addiu %[colors], %[colors], 4 \n\t" 356 "4: \n\t" 357 ".set pop \n\t" 358 : [xx]"+r"(xx), [count]"+r"(count), [colors]"+r"(colors), 359 [s0]"=&r"(s0), [s1]"=&r"(s1), [s2]"=&r"(s2), [s3]"=&r"(s3), 360 [s4]"=&r"(s4), [s5]"=&r"(s5), [s6]"=&r"(s6), [s7]"=&r"(s7) 361 : [table]"r"(table), [srcAddr]"r"(srcAddr) 362 : "memory", "t0", "t1", "t2", "t3", 363 "t4", "t5", "t6", "t7", "t8" 364 ); 365 } 366 s.fBitmap->getColorTable()->unlockColors(); 367} 368 369/* If we replace a sampleproc, then we null-out the associated shaderproc, 370 otherwise the shader won't even look at the matrix/sampler 371 */ 372 373void SkBitmapProcState::platformProcs() { 374 bool isOpaque = 256 == fAlphaScale; 375 bool justDx = false; 376 377 if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { 378 justDx = true; 379 } 380 381 switch (fBitmap->colorType()) { 382 case kIndex_8_SkColorType: 383 if (justDx && SkPaint::kNone_FilterLevel == fFilterLevel) { 384 fSampleProc16 = SI8_D16_nofilter_DX_mips_dsp; 385 fShaderProc16 = NULL; 386 if (isOpaque) { 387 fSampleProc32 = SI8_opaque_D32_nofilter_DX_mips_dsp; 388 fShaderProc32 = NULL; 389 } 390 } 391 break; 392 default: 393 break; 394 } 395} 396 397void SkBitmapScaler::PlatformConvolutionProcs(SkConvolutionProcs*) {} 398