Chromium Code Reviews| Index: src/core/SkBitmapProcState.cpp |
| diff --git a/src/core/SkBitmapProcState.cpp b/src/core/SkBitmapProcState.cpp |
| index a2c7f990c2d9b19fe5ee238de9eae68757a62c3b..d769aa7db05d514971435fb6fa9b36a3316ec66e 100644 |
| --- a/src/core/SkBitmapProcState.cpp |
| +++ b/src/core/SkBitmapProcState.cpp |
| @@ -90,6 +90,10 @@ static bool valid_for_filtering(unsigned dimension) { |
| return (dimension & ~0x3FFF) == 0; |
| } |
| +void SkBitmapProcState::endContext() { |
| + SkDELETE(fBitmapFilter); |
| +} |
| + |
| bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { |
| if (fOrigBitmap.width() == 0 || fOrigBitmap.height() == 0) { |
| return false; |
| @@ -109,8 +113,58 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { |
| } |
| fBitmap = &fOrigBitmap; |
| - if (fOrigBitmap.hasMipMap()) { |
| - int shift = fOrigBitmap.extractMipLevel(&fMipBitmap, |
| + |
| + // Check to see if the transformation matrix is scaling up, and if |
| + // the matrix is simple, and if the paint has high quality scaling |
| + // turned on. If so, do the bitmap scale here and remove the scaling component from the matrix. |
| + |
| + uint32_t hqUpsampleMask = SkPaint::kFilterBitmap_Flag |
| + | SkPaint::kHighQualityFilterBitmap_Flag |
| + ; |
| + if (inv.getType() == (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask) && |
| + (inv.getScaleX() < 1 || inv.getScaleY() < 1) && |
| + ((paint.getFlags() & hqUpsampleMask) == hqUpsampleMask) && |
| + fOrigBitmap.config() == SkBitmap::kARGB_8888_Config) { |
| + |
| + // All the criteria are met; let's make a new bitmap. |
| + fScaledBitmap.setConfig(SkBitmap::kARGB_8888_Config, fOrigBitmap.width() / inv.getScaleX(), fOrigBitmap.height() / inv.getScaleY()); |
|
reed1
2013/07/11 15:43:42
nit: line-wrap
reed1
2013/07/11 15:49:08
grrrr, this is tricky, since we have one predicate
humper
2013/07/11 16:03:03
Done.
|
| + fScaledBitmap.allocPixels(); |
| + fOrigBitmap.scale(&fScaledBitmap); |
| + fBitmap = &fScaledBitmap; |
| + |
| + // Now get rid of the scale factor from the matrix |
| + |
| + if (m != &fUnitInvMatrix) { |
| + fUnitInvMatrix = *m; |
| + m = &fUnitInvMatrix; |
| + } |
| + |
| + // set the inv matrix type to translate-only; this should have |
| + // the side-effect of disabling bitmap filtering also. |
| + |
| + fUnitInvMatrix.setTranslate( 1/m->getScaleX() * m->getTranslateX(), 1/m->getScaleY() * m->getTranslateY() ); |
|
reed1
2013/07/11 15:43:42
nit: line-wrap
humper
2013/07/11 16:03:03
Done.
|
| + } else if (!fBitmap->hasMipMap()) { |
| + // Check to see if the transformation matrix is scaling *down*. |
| + // If so, automatically build mipmaps |
| + |
| + SkPoint v1, v2; |
| + |
| + // guess if the matrix is scaling down by seeing what it does to two unit vectors. |
| + |
| + v1.fX = inv.getScaleX(); |
| + v1.fY = inv.getSkewY(); |
| + |
| + v2.fX = inv.getSkewX(); |
| + v2.fY = inv.getScaleY(); |
| + |
| + if (v1.fX * v1.fX + v1.fY * v1.fY > 1 || |
| + v2.fX * v2.fX + v2.fY * v2.fY > 1) { |
| + fBitmap->buildMipMap(); |
| + } |
| + } |
| + |
| + if (fBitmap->hasMipMap()) { |
| + int shift = fBitmap->extractMipLevel(&fMipBitmap, |
| SkScalarToFixed(m->getScaleX()), |
| SkScalarToFixed(m->getSkewY())); |
| @@ -156,20 +210,42 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { |
| fInvKyFractionalInt = SkScalarToFractionalInt(m->getSkewY()); |
| fAlphaScale = SkAlpha255To256(paint.getAlpha()); |
| + |
| + fShaderProc32 = NULL; |
| + fShaderProc16 = NULL; |
| + fSampleProc32 = NULL; |
| + fSampleProc16 = NULL; |
| // pick-up filtering from the paint, but only if the matrix is |
| // more complex than identity/translate (i.e. no need to pay the cost |
| // of filtering if we're not scaled etc.). |
| // note: we explicitly check inv, since m might be scaled due to unitinv |
| // trickery, but we don't want to see that for this test |
| - fDoFilter = paint.isFilterBitmap() && |
| - (fInvType > SkMatrix::kTranslate_Mask && |
| - valid_for_filtering(fBitmap->width() | fBitmap->height())); |
| - |
| - fShaderProc32 = NULL; |
| - fShaderProc16 = NULL; |
| - fSampleProc32 = NULL; |
| - fSampleProc16 = NULL; |
| + |
| + fFilterQuality = kNone_BitmapFilter; |
| + |
| + if (paint.isFilterBitmap()) { |
| + if ((paint.getFlags() & hqUpsampleMask) == hqUpsampleMask) { |
| + // The paint wants high quality sampling, so let's try to do it. |
| + fFilterQuality = kHQ_BitmapFilter; |
| + fShaderProc32 = this->chooseBitmapFilterProc(); |
| + } |
| + |
| + if (!fShaderProc32) { |
| + // if no shader proc is set, either the caller didn't ask |
| + // for high quality filtering (so we didn't try at all), |
| + // or our attempt to install an HQ sampler failed. |
| + // Attempt to use bilerp in either case. |
| + |
| + // Only install bilerp if the matrix is "interesting" and |
| + // the image has a suitable size. |
| + |
| + if (fInvType > SkMatrix::kTranslate_Mask && |
|
reed1
2013/07/11 15:43:42
Shouldn't we perform this (not scaled enough to ju
reed1
2013/07/11 15:49:08
Ah, I see that you are *re*calling this logic afte
humper
2013/07/11 16:03:03
the valid_for_filtering function actually checks t
|
| + valid_for_filtering(fBitmap->width() | fBitmap->height())) { |
| + fFilterQuality = kBilerp_BitmapFilter; |
| + } |
| + } |
| + } |
| fMatrixProc = this->chooseMatrixProc(trivial_matrix); |
| if (NULL == fMatrixProc) { |
| @@ -185,7 +261,7 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { |
| if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { |
| index |= 2; |
| } |
| - if (fDoFilter) { |
| + if (fFilterQuality != kNone_BitmapFilter) { |
| index |= 4; |
| } |
| // bits 3,4,5 encoding the source bitmap format |
| @@ -302,10 +378,6 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { |
| fShaderProc32 = this->chooseShaderProc32(); |
| } |
| - if (NULL == fShaderProc32) { |
| - fShaderProc32 = this->chooseBitmapFilterProc(paint); |
| - } |
| - |
| // see if our platform has any accelerated overrides |
| this->platformProcs(); |
| @@ -319,7 +391,7 @@ static void Clamp_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, |
| SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); |
| SkASSERT(s.fInvKy == 0); |
| SkASSERT(count > 0 && colors != NULL); |
| - SkASSERT(!s.fDoFilter); |
| + SkASSERT(s.fFilterQuality == kNone_BitmapFilter); |
| const int maxX = s.fBitmap->width() - 1; |
| const int maxY = s.fBitmap->height() - 1; |
| @@ -393,7 +465,7 @@ static void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, |
| SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); |
| SkASSERT(s.fInvKy == 0); |
| SkASSERT(count > 0 && colors != NULL); |
| - SkASSERT(!s.fDoFilter); |
| + SkASSERT(s.fFilterQuality == kNone_BitmapFilter); |
|
reed1
2013/07/11 15:43:42
nit: skia likes to place the literal on the left (
|
| const int stopX = s.fBitmap->width(); |
| const int stopY = s.fBitmap->height(); |
| @@ -439,7 +511,7 @@ static void S32_D32_constX_shaderproc(const SkBitmapProcState& s, |
| int iY1 SK_INIT_TO_AVOID_WARNING; |
| int iSubY SK_INIT_TO_AVOID_WARNING; |
| - if (s.fDoFilter) { |
| + if (s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter) { |
| SkBitmapProcState::MatrixProc mproc = s.getMatrixProc(); |
| uint32_t xy[2]; |
| @@ -520,7 +592,7 @@ static void S32_D32_constX_shaderproc(const SkBitmapProcState& s, |
| const SkPMColor* row0 = s.fBitmap->getAddr32(0, iY0); |
| SkPMColor color; |
| - if (s.fDoFilter) { |
| + if (s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter) { |
| const SkPMColor* row1 = s.fBitmap->getAddr32(0, iY1); |
| if (s.fAlphaScale < 256) { |
| @@ -576,7 +648,9 @@ SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() { |
| static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; |
| if (1 == fBitmap->width() && 0 == (fInvType & ~kMask)) { |
| - if (!fDoFilter && fInvType <= SkMatrix::kTranslate_Mask && !this->setupForTranslate()) { |
| + if (fFilterQuality == kNone_BitmapFilter && |
| + fInvType <= SkMatrix::kTranslate_Mask && |
| + !this->setupForTranslate()) { |
| return DoNothing_shaderproc; |
| } |
| return S32_D32_constX_shaderproc; |
| @@ -588,7 +662,7 @@ SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() { |
| if (fInvType > SkMatrix::kTranslate_Mask) { |
| return NULL; |
| } |
| - if (fDoFilter) { |
| + if (fFilterQuality != kNone_BitmapFilter) { |
| return NULL; |
| } |
| @@ -684,9 +758,9 @@ void SkBitmapProcState::DebugMatrixProc(const SkBitmapProcState& state, |
| // scale -vs- affine |
| // filter -vs- nofilter |
| if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { |
| - proc = state.fDoFilter ? check_scale_filter : check_scale_nofilter; |
| + proc = state.fFilterQuality != kNone_BitmapFilter ? check_scale_filter : check_scale_nofilter; |
| } else { |
| - proc = state.fDoFilter ? check_affine_filter : check_affine_nofilter; |
| + proc = state.fFilterQuality != kNone_BitmapFilter ? check_affine_filter : check_affine_nofilter; |
| } |
| proc(bitmapXY, count, state.fBitmap->width(), state.fBitmap->height()); |
| } |
| @@ -721,7 +795,7 @@ int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const { |
| size >>= 2; |
| } |
| - if (fDoFilter) { |
| + if (fFilterQuality != kNone_BitmapFilter) { |
| size >>= 1; |
| } |