Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(41)

Side by Side Diff: src/core/SkBitmapProcState.cpp

Issue 306013010: allow subpixel positioning w/ bitmap filtering Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: rebase Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkBitmapProcState.h ('k') | src/core/SkBitmapProcState_matrixProcs.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 }
OLDNEW
« no previous file with comments | « src/core/SkBitmapProcState.h ('k') | src/core/SkBitmapProcState_matrixProcs.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698