OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 #include "SkBitmapProcState.h" | 8 #include "SkBitmapProcState.h" |
9 #include "SkColorPriv.h" | 9 #include "SkColorPriv.h" |
10 #include "SkFilterProc.h" | 10 #include "SkFilterProc.h" |
11 #include "SkPaint.h" | 11 #include "SkPaint.h" |
12 #include "SkShader.h" // for tilemodes | 12 #include "SkShader.h" // for tilemodes |
13 #include "SkUtilsArm.h" | 13 #include "SkUtilsArm.h" |
14 #include "SkBitmapScaler.h" | 14 #include "SkBitmapScaler.h" |
| 15 #include "SkMatrixUtils.h" |
15 #include "SkMipMap.h" | 16 #include "SkMipMap.h" |
16 #include "SkPixelRef.h" | 17 #include "SkPixelRef.h" |
17 #include "SkScaledImageCache.h" | 18 #include "SkScaledImageCache.h" |
18 #include "SkImageEncoder.h" | 19 #include "SkImageEncoder.h" |
19 | 20 |
| 21 static int paintfilter_to_subpixelbits(SkPaint::FilterLevel level) { |
| 22 const int gBits[] = { 0, 4, 4, 4, }; |
| 23 return gBits[level]; |
| 24 } |
| 25 |
20 #if !SK_ARM_NEON_IS_NONE | 26 #if !SK_ARM_NEON_IS_NONE |
21 // These are defined in src/opts/SkBitmapProcState_arm_neon.cpp | 27 // These are defined in src/opts/SkBitmapProcState_arm_neon.cpp |
22 extern const SkBitmapProcState::SampleProc16 gSkBitmapProcStateSample16_neon[]; | 28 extern const SkBitmapProcState::SampleProc16 gSkBitmapProcStateSample16_neon[]; |
23 extern const SkBitmapProcState::SampleProc32 gSkBitmapProcStateSample32_neon[]; | 29 extern const SkBitmapProcState::SampleProc32 gSkBitmapProcStateSample32_neon[]; |
24 extern void S16_D16_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, i
nt, uint16_t*); | 30 extern void S16_D16_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, i
nt, uint16_t*); |
25 extern void Clamp_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, i
nt, int, uint16_t*, int); | 31 extern void Clamp_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, i
nt, int, uint16_t*, int); |
26 extern void Repeat_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&,
int, int, uint16_t*, int); | 32 extern void Repeat_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&,
int, int, uint16_t*, int); |
27 extern void SI8_opaque_D32_filter_DX_neon(const SkBitmapProcState&, const uint3
2_t*, int, SkPMColor*); | 33 extern void SI8_opaque_D32_filter_DX_neon(const SkBitmapProcState&, const uint3
2_t*, int, SkPMColor*); |
28 extern void SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&,
int, int, uint32_t*, int); | 34 extern void SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&,
int, int, uint32_t*, int); |
29 extern void Clamp_SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcSt
ate&, int, int, uint32_t*, int); | 35 extern void Clamp_SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcSt
ate&, int, int, uint32_t*, int); |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 return true; | 373 return true; |
368 } | 374 } |
369 | 375 |
370 SkBitmapProcState::~SkBitmapProcState() { | 376 SkBitmapProcState::~SkBitmapProcState() { |
371 if (fScaledCacheID) { | 377 if (fScaledCacheID) { |
372 SkScaledImageCache::Unlock(fScaledCacheID); | 378 SkScaledImageCache::Unlock(fScaledCacheID); |
373 } | 379 } |
374 SkDELETE(fBitmapFilter); | 380 SkDELETE(fBitmapFilter); |
375 } | 381 } |
376 | 382 |
| 383 bool SkBitmapProcState::isInverseTrivial() const { |
| 384 unsigned bits = paintfilter_to_subpixelbits((SkPaint::FilterLevel)fFilterLev
el); |
| 385 return SkTreatAsSprite(fInvMatrix, fBitmap->width(), fBitmap->height(), bits
); |
| 386 } |
| 387 |
377 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { | 388 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { |
378 SkASSERT(fOrigBitmap.width() && fOrigBitmap.height()); | 389 SkASSERT(fOrigBitmap.width() && fOrigBitmap.height()); |
| 390 SkASSERT(NULL == fScaledCacheID); |
379 | 391 |
380 fBitmap = NULL; | |
381 fInvMatrix = inv; | 392 fInvMatrix = inv; |
382 fFilterLevel = paint.getFilterLevel(); | 393 fFilterLevel = paint.getFilterLevel(); |
| 394 fBitmap = &fOrigBitmap; |
383 | 395 |
384 SkASSERT(NULL == fScaledCacheID); | 396 bool trivialMX = this->isInverseTrivial(); |
| 397 if (trivialMX) { |
| 398 fFilterLevel = SkPaint::kNone_FilterLevel; |
| 399 } |
| 400 |
| 401 // Reset to null for possiblyScaleImage() |
| 402 fBitmap = NULL; |
385 | 403 |
386 // possiblyScaleImage will look to see if it can rescale the image as a | 404 // possiblyScaleImage will look to see if it can rescale the image as a |
387 // preprocess; either by scaling up to the target size, or by selecting | 405 // preprocess; either by scaling up to the target size, or by selecting |
388 // a nearby mipmap level. If it does, it will adjust the working | 406 // a nearby mipmap level. If it does, it will adjust the working |
389 // matrix as well as the working bitmap. It may also adjust the filter | 407 // matrix as well as the working bitmap. It may also adjust the filter |
390 // quality to avoid re-filtering an already perfectly scaled image. | 408 // quality to avoid re-filtering an already perfectly scaled image. |
391 if (!this->possiblyScaleImage()) { | 409 if (!this->possiblyScaleImage()) { |
392 if (!this->lockBaseBitmap()) { | 410 if (!this->lockBaseBitmap()) { |
393 return false; | 411 return false; |
394 } | 412 } |
395 } | 413 } |
396 // The above logic should have always assigned fBitmap, but in case it | 414 // The above logic should have always assigned fBitmap, but in case it |
397 // didn't, we check for that now... | 415 // didn't, we check for that now... |
398 // TODO(dominikg): Ask humper@ if we can just use an SkASSERT(fBitmap)? | 416 // TODO(dominikg): Ask humper@ if we can just use an SkASSERT(fBitmap)? |
399 if (NULL == fBitmap) { | 417 if (NULL == fBitmap) { |
400 return false; | 418 return false; |
401 } | 419 } |
402 | 420 |
403 // If we are "still" kMedium_FilterLevel, then the request was not fulfilled
by possiblyScale, | 421 // If we are "still" kMedium_FilterLevel, then the request was not fulfilled
by possiblyScale, |
404 // so we downgrade to kLow (so the rest of the sniffing code can assume that
) | 422 // so we downgrade to kLow (so the rest of the sniffing code can assume that
) |
405 if (SkPaint::kMedium_FilterLevel == fFilterLevel) { | 423 if (SkPaint::kMedium_FilterLevel == fFilterLevel) { |
406 fFilterLevel = SkPaint::kLow_FilterLevel; | 424 fFilterLevel = SkPaint::kLow_FilterLevel; |
407 } | 425 } |
408 | 426 |
409 bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) ==
0; | 427 trivialMX = this->isInverseTrivial(); |
| 428 if (trivialMX) { |
| 429 fFilterLevel = SkPaint::kNone_FilterLevel; |
| 430 } |
| 431 |
410 bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && | 432 bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && |
411 SkShader::kClamp_TileMode == fTileModeY; | 433 SkShader::kClamp_TileMode == fTileModeY; |
412 | 434 |
413 if (!(clampClamp || trivialMatrix)) { | 435 if (!(clampClamp || trivialMX)) { |
414 fInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); | 436 fInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); |
415 } | 437 } |
416 | 438 |
417 // Now that all possible changes to the matrix have taken place, check | 439 // Now that all possible changes to the matrix have taken place, check |
418 // to see if we're really close to a no-scale matrix. If so, explicitly | 440 // to see if we're really close to a no-scale matrix. If so, explicitly |
419 // set it to be so. Subsequent code may inspect this matrix to choose | 441 // set it to be so. Subsequent code may inspect this matrix to choose |
420 // a faster path in this case. | 442 // a faster path in this case. |
421 | 443 |
422 // This code will only execute if the matrix has some scale component; | 444 // This code will only execute if the matrix has some scale component; |
423 // if it's already pure translate then we won't do this inversion. | 445 // if it's already pure translate then we won't do this inversion. |
424 | 446 |
425 if (matrix_only_scale_translate(fInvMatrix)) { | 447 // if (matrix_only_scale_translate(fInvMatrix)) { |
| 448 if (trivialMX) { |
426 SkMatrix forward; | 449 SkMatrix forward; |
427 if (fInvMatrix.invert(&forward)) { | 450 if (fInvMatrix.invert(&forward)) { |
428 if (clampClamp ? just_trans_clamp(forward, *fBitmap) | 451 if (clampClamp ? just_trans_clamp(forward, *fBitmap) |
429 : just_trans_general(forward)) { | 452 : just_trans_general(forward)) { |
430 SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX()); | 453 SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX()); |
431 SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY()); | 454 SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY()); |
432 fInvMatrix.setTranslate(tx, ty); | 455 fInvMatrix.setTranslate(tx, ty); |
433 } | 456 } |
434 } | 457 } |
435 } | 458 } |
436 | 459 |
| 460 if (trivialMX && (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask)) { |
| 461 // SkDebugf("sfsd\n"); |
| 462 } |
| 463 |
437 fInvProc = fInvMatrix.getMapXYProc(); | 464 fInvProc = fInvMatrix.getMapXYProc(); |
438 fInvType = fInvMatrix.getType(); | 465 fInvType = fInvMatrix.getType(); |
439 fInvSx = SkScalarToFixed(fInvMatrix.getScaleX()); | 466 fInvSx = SkScalarToFixed(fInvMatrix.getScaleX()); |
440 fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix.getScaleX()); | 467 fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix.getScaleX()); |
441 fInvKy = SkScalarToFixed(fInvMatrix.getSkewY()); | 468 fInvKy = SkScalarToFixed(fInvMatrix.getSkewY()); |
442 fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix.getSkewY()); | 469 fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix.getSkewY()); |
443 | 470 |
444 fAlphaScale = SkAlpha255To256(paint.getAlpha()); | 471 fAlphaScale = SkAlpha255To256(paint.getAlpha()); |
445 | 472 |
446 fShaderProc32 = NULL; | 473 fShaderProc32 = NULL; |
447 fShaderProc16 = NULL; | 474 fShaderProc16 = NULL; |
448 fSampleProc32 = NULL; | 475 fSampleProc32 = NULL; |
449 fSampleProc16 = NULL; | 476 fSampleProc16 = NULL; |
450 | 477 |
451 // recompute the triviality of the matrix here because we may have | |
452 // changed it! | |
453 | |
454 trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; | |
455 | |
456 if (SkPaint::kHigh_FilterLevel == fFilterLevel) { | 478 if (SkPaint::kHigh_FilterLevel == fFilterLevel) { |
457 // If this is still set, that means we wanted HQ sampling | 479 // If this is still set, that means we wanted HQ sampling |
458 // but couldn't do it as a preprocess. Let's try to install | 480 // but couldn't do it as a preprocess. Let's try to install |
459 // the scanline version of the HQ sampler. If that process fails, | 481 // the scanline version of the HQ sampler. If that process fails, |
460 // downgrade to bilerp. | 482 // downgrade to bilerp. |
461 | 483 |
462 // NOTE: Might need to be careful here in the future when we want | 484 // NOTE: Might need to be careful here in the future when we want |
463 // to have the platform proc have a shot at this; it's possible that | 485 // to have the platform proc have a shot at this; it's possible that |
464 // the chooseBitmapFilterProc will fail to install a shader but a | 486 // the chooseBitmapFilterProc will fail to install a shader but a |
465 // platform-specific one might succeed, so it might be premature here | 487 // platform-specific one might succeed, so it might be premature here |
466 // to fall back to bilerp. This needs thought. | 488 // to fall back to bilerp. This needs thought. |
467 | 489 |
468 if (!this->setBitmapFilterProcs()) { | 490 if (!this->setBitmapFilterProcs()) { |
469 fFilterLevel = SkPaint::kLow_FilterLevel; | 491 fFilterLevel = SkPaint::kLow_FilterLevel; |
470 } | 492 } |
471 } | 493 } |
472 | 494 |
473 if (SkPaint::kLow_FilterLevel == fFilterLevel) { | |
474 // Only try bilerp if the matrix is "interesting" and | |
475 // the image has a suitable size. | |
476 | |
477 if (fInvType <= SkMatrix::kTranslate_Mask || | |
478 !valid_for_filtering(fBitmap->width() | fBitmap->height())) { | |
479 fFilterLevel = SkPaint::kNone_FilterLevel; | |
480 } | |
481 } | |
482 | |
483 // At this point, we know exactly what kind of sampling the per-scanline | 495 // At this point, we know exactly what kind of sampling the per-scanline |
484 // shader will perform. | 496 // shader will perform. |
485 | 497 |
486 fMatrixProc = this->chooseMatrixProc(trivialMatrix); | 498 fMatrixProc = this->chooseMatrixProc(trivialMX); |
487 // TODO(dominikg): SkASSERT(fMatrixProc) instead? chooseMatrixProc never ret
urns NULL. | 499 // TODO(dominikg): SkASSERT(fMatrixProc) instead? chooseMatrixProc never ret
urns NULL. |
488 if (NULL == fMatrixProc) { | 500 if (NULL == fMatrixProc) { |
489 return false; | 501 return false; |
490 } | 502 } |
491 | 503 |
492 /////////////////////////////////////////////////////////////////////// | 504 /////////////////////////////////////////////////////////////////////// |
493 | 505 |
494 // No need to do this if we're doing HQ sampling; if filter quality is | 506 // No need to do this if we're doing HQ sampling; if filter quality is |
495 // still set to HQ by the time we get here, then we must have installed | 507 // still set to HQ by the time we get here, then we must have installed |
496 // the shader procs above and can skip all this. | 508 // the shader procs above and can skip all this. |
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1039 } else { | 1051 } else { |
1040 size >>= 2; | 1052 size >>= 2; |
1041 } | 1053 } |
1042 | 1054 |
1043 if (fFilterLevel != SkPaint::kNone_FilterLevel) { | 1055 if (fFilterLevel != SkPaint::kNone_FilterLevel) { |
1044 size >>= 1; | 1056 size >>= 1; |
1045 } | 1057 } |
1046 | 1058 |
1047 return size; | 1059 return size; |
1048 } | 1060 } |
OLD | NEW |