diff options
author | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-07-22 17:18:18 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-07-22 17:18:18 +0000 |
commit | 9cfc83cc8ac2ee50a7ce889e65a707941f48bdea (patch) | |
tree | 879cd1f934857a2f296d5fe9c5dbf190af1f40af /src/core | |
parent | 35f02fb9c9f548656e1cb2cc66d3ed20006384f8 (diff) |
stop using bitmap-filter flags outside of paint itself, as a step towards really changing them into an enum
BUG=
Review URL: https://codereview.chromium.org/19825002
git-svn-id: http://skia.googlecode.com/svn/trunk@10240 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkBitmapFilter.cpp | 2 | ||||
-rw-r--r-- | src/core/SkBitmapProcState.cpp | 152 | ||||
-rw-r--r-- | src/core/SkBitmapProcState.h | 7 | ||||
-rw-r--r-- | src/core/SkBitmapProcState_matrixProcs.cpp | 4 | ||||
-rw-r--r-- | src/core/SkBitmapProcState_sample.h | 8 | ||||
-rw-r--r-- | src/core/SkBitmapProcState_shaderproc.h | 2 |
6 files changed, 97 insertions, 78 deletions
diff --git a/src/core/SkBitmapFilter.cpp b/src/core/SkBitmapFilter.cpp index 060400944f..c2f68d4879 100644 --- a/src/core/SkBitmapFilter.cpp +++ b/src/core/SkBitmapFilter.cpp @@ -101,7 +101,7 @@ SkBitmapFilter *SkBitmapFilter::Allocate() { SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseBitmapFilterProc() { - if (fFilterQuality != kHQ_BitmapFilter) { + if (fFilterLevel != SkPaint::kHigh_FilterLevel) { return NULL; } diff --git a/src/core/SkBitmapProcState.cpp b/src/core/SkBitmapProcState.cpp index ebb010fd0a..2298398bd5 100644 --- a/src/core/SkBitmapProcState.cpp +++ b/src/core/SkBitmapProcState.cpp @@ -91,13 +91,26 @@ static bool valid_for_filtering(unsigned dimension) { return (dimension & ~0x3FFF) == 0; } +static bool effective_matrix_scale_sqrd(const SkMatrix& mat) { + SkPoint v1, v2; + + v1.fX = mat.getScaleX(); + v1.fY = mat.getSkewY(); + + v2.fX = mat.getSkewX(); + v2.fY = mat.getScaleY(); + + return SkMaxScalar(v1.lengthSqd(), v2.lengthSqd()); +} + // TODO -- we may want to pass the clip into this function so we only scale // the portion of the image that we're going to need. This will complicate // the interface to the cache, but might be well worth it. void SkBitmapProcState::possiblyScaleImage() { - if (fFilterQuality != kHQ_BitmapFilter) { + if (fFilterLevel <= SkPaint::kLow_FilterLevel) { + // none or low (bilerp) does not need to look any further return; } @@ -125,7 +138,7 @@ void SkBitmapProcState::possiblyScaleImage() { // doing high quality scaling. If so, do the bitmap scale here and // remove the scaling component from the matrix. - if (fFilterQuality == kHQ_BitmapFilter && + if (SkPaint::kHigh_FilterLevel == fFilterLevel && fInvMatrix.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask) && fOrigBitmap.config() == SkBitmap::kARGB_8888_Config) { @@ -148,55 +161,73 @@ void SkBitmapProcState::possiblyScaleImage() { // no need for any further filtering; we just did it! - fFilterQuality = kNone_BitmapFilter; + fFilterLevel = SkPaint::kNone_FilterLevel; return; } - if (!fOrigBitmap.hasMipMap() && fFilterQuality != kNone_BitmapFilter) { - - // STEP 2: MIPMAP DOWNSAMPLE? - - // Check to see if the transformation matrix is scaling *down*. - // If so, automatically build mipmaps. - - SkPoint v1, v2; - - // conservatively estimate if the matrix is scaling down by seeing - // what its upper left 2x2 portion does to two unit vectors. + /* + * If we get here, the caller has requested either Med or High filter-level + * + * If High, then our special-case for scale-only did not take, and so we + * have to make a choice: + * 1. fall back on mipmaps + bilerp + * 2. fall back on scanline bicubic filter + * For now, we compute the "scale" value from the matrix, and have a + * threshold to decide when bicubic is better, and when mips are better. + * No doubt a fancier decision tree could be used uere. + * + * If Medium, then we just try to build a mipmap and select a level, + * setting the filter-level to kLow to signal that we just need bilerp + * to process the selected level. + */ - v1.fX = fInvMatrix.getScaleX(); - v1.fY = fInvMatrix.getSkewY(); + SkScalar scaleSqd = effective_matrix_scale_sqrd(fInvMatrix); + + if (SkPaint::kHigh_FilterLevel == fFilterLevel) { + // Set the limit at 0.25 for the CTM... if the CTM is scaling smaller + // than this, then the mipmaps quality may be greater (certainly faster) + // so we only keep High quality if the scale is greater than this. + // + // Since we're dealing with the inverse, we compare against its inverse. + const SkScalar bicubicLimit = SkFloatToScalar(4.0f); + const SkScalar bicubicLimitSqd = bicubicLimit * bicubicLimit; + if (scaleSqd < bicubicLimitSqd) { // use bicubic scanline + return; + } - v2.fX = fInvMatrix.getSkewX(); - v2.fY = fInvMatrix.getScaleY(); + // else set the filter-level to Medium, since we're scaling down and + // want to reqeust mipmaps + fFilterLevel = SkPaint::kMedium_FilterLevel; + } + + SkASSERT(SkPaint::kMedium_FilterLevel == fFilterLevel); - if (v1.fX * v1.fX + v1.fY * v1.fY > 1 || - v2.fX * v2.fX + v2.fY * v2.fY > 1) { + /** + * Medium quality means use a mipmap for down-scaling, and just bilper + * for upscaling. Since we're examining the inverse matrix, we look for + * a scale > 1 to indicate down scaling by the CTM. + */ + if (scaleSqd > SK_Scalar1) { + if (!fOrigBitmap.hasMipMap()) { fOrigBitmap.buildMipMap(); - - // Now that we've built the mipmaps and we know we're downsampling, - // downgrade to bilinear interpolation for the mip level. - - fFilterQuality = kBilerp_BitmapFilter; + // build may fail, so we need to check again } - } - - if (fOrigBitmap.hasMipMap()) { - - // STEP 3: We've got mipmaps, let's choose the closest level as our render - // source and adjust the matrix accordingly. - - int shift = fOrigBitmap.extractMipLevel(&fScaledBitmap, - SkScalarToFixed(fInvMatrix.getScaleX()), - SkScalarToFixed(fInvMatrix.getSkewY())); - - if (shift > 0) { - SkScalar scale = SkFixedToScalar(SK_Fixed1 >> shift); - fInvMatrix.postScale(scale, scale); - fBitmap = &fScaledBitmap; + if (fOrigBitmap.hasMipMap()) { + int shift = fOrigBitmap.extractMipLevel(&fScaledBitmap, + SkScalarToFixed(fInvMatrix.getScaleX()), + SkScalarToFixed(fInvMatrix.getSkewY())); + if (shift > 0) { + SkScalar scale = SkFixedToScalar(SK_Fixed1 >> shift); + fInvMatrix.postScale(scale, scale); + fBitmap = &fScaledBitmap; + } } } + + // Now that we've built the mipmaps (if applicable), we set the filter-level + // bilinear interpolation. + fFilterLevel = SkPaint::kLow_FilterLevel; } void SkBitmapProcState::endContext() { @@ -225,14 +256,7 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { // We may downgrade it later if we determine that we either don't need // or can't provide as high a quality filtering as the user requested. - fFilterQuality = kNone_BitmapFilter; - if (paint.isFilterBitmap()) { - if (paint.getFlags() & SkPaint::kHighQualityFilterBitmap_Flag) { - fFilterQuality = kHQ_BitmapFilter; - } else { - fFilterQuality = kBilerp_BitmapFilter; - } - } + fFilterLevel = paint.getFilterLevel(); #ifndef SK_IGNORE_IMAGE_PRESCALE // possiblyScaleImage will look to see if it can rescale the image as a @@ -284,7 +308,7 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; - if (kHQ_BitmapFilter == fFilterQuality) { + if (SkPaint::kHigh_FilterLevel == fFilterLevel) { // If this is still set, that means we wanted HQ sampling // but couldn't do it as a preprocess. Let's try to install // the scanline version of the HQ sampler. If that process fails, @@ -300,17 +324,17 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { fShaderProc32 = this->chooseBitmapFilterProc(); if (!fShaderProc32) { - fFilterQuality = kBilerp_BitmapFilter; + fFilterLevel = SkPaint::kLow_FilterLevel; } } - if (kBilerp_BitmapFilter == fFilterQuality) { + if (SkPaint::kLow_FilterLevel == fFilterLevel) { // Only try bilerp if the matrix is "interesting" and // the image has a suitable size. if (fInvType <= SkMatrix::kTranslate_Mask || - !valid_for_filtering(fBitmap->width() | fBitmap->height())) { - fFilterQuality = kNone_BitmapFilter; + !valid_for_filtering(fBitmap->width() | fBitmap->height())) { + fFilterLevel = SkPaint::kNone_FilterLevel; } } @@ -328,7 +352,7 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { // still set to HQ by the time we get here, then we must have installed // the shader proc above and can skip all this. - if (fFilterQuality < kHQ_BitmapFilter) { + if (fFilterLevel < SkPaint::kHigh_FilterLevel) { int index = 0; if (fAlphaScale < 256) { // note: this distinction is not used for D16 @@ -337,7 +361,7 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { index |= 2; } - if (fFilterQuality != kNone_BitmapFilter) { + if (fFilterLevel > SkPaint::kNone_FilterLevel) { index |= 4; } // bits 3,4,5 encoding the source bitmap format @@ -468,7 +492,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(SkBitmapProcState::kNone_BitmapFilter == s.fFilterQuality); + SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel); const int maxX = s.fBitmap->width() - 1; const int maxY = s.fBitmap->height() - 1; @@ -542,7 +566,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(SkBitmapProcState::kNone_BitmapFilter == s.fFilterQuality); + SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel); const int stopX = s.fBitmap->width(); const int stopY = s.fBitmap->height(); @@ -588,7 +612,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.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter) { + if (SkPaint::kNone_FilterLevel != s.fFilterLevel) { SkBitmapProcState::MatrixProc mproc = s.getMatrixProc(); uint32_t xy[2]; @@ -669,7 +693,7 @@ static void S32_D32_constX_shaderproc(const SkBitmapProcState& s, const SkPMColor* row0 = s.fBitmap->getAddr32(0, iY0); SkPMColor color; - if (s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter) { + if (SkPaint::kNone_FilterLevel != s.fFilterLevel) { const SkPMColor* row1 = s.fBitmap->getAddr32(0, iY1); if (s.fAlphaScale < 256) { @@ -725,7 +749,7 @@ SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() { static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; if (1 == fBitmap->width() && 0 == (fInvType & ~kMask)) { - if (kNone_BitmapFilter == fFilterQuality && + if (SkPaint::kNone_FilterLevel == fFilterLevel && fInvType <= SkMatrix::kTranslate_Mask && !this->setupForTranslate()) { return DoNothing_shaderproc; @@ -739,7 +763,7 @@ SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() { if (fInvType > SkMatrix::kTranslate_Mask) { return NULL; } - if (fFilterQuality != kNone_BitmapFilter) { + if (SkPaint::kNone_FilterLevel != fFilterLevel) { return NULL; } @@ -835,9 +859,9 @@ void SkBitmapProcState::DebugMatrixProc(const SkBitmapProcState& state, // scale -vs- affine // filter -vs- nofilter if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { - proc = state.fFilterQuality != kNone_BitmapFilter ? check_scale_filter : check_scale_nofilter; + proc = state.fFilterLevel != SkPaint::kNone_FilterLevel ? check_scale_filter : check_scale_nofilter; } else { - proc = state.fFilterQuality != kNone_BitmapFilter ? check_affine_filter : check_affine_nofilter; + proc = state.fFilterLevel != SkPaint::kNone_FilterLevel ? check_affine_filter : check_affine_nofilter; } proc(bitmapXY, count, state.fBitmap->width(), state.fBitmap->height()); } @@ -872,7 +896,7 @@ int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const { size >>= 2; } - if (fFilterQuality != kNone_BitmapFilter) { + if (fFilterLevel != SkPaint::kNone_FilterLevel) { size >>= 1; } diff --git a/src/core/SkBitmapProcState.h b/src/core/SkBitmapProcState.h index b4fae045f8..349194f3b4 100644 --- a/src/core/SkBitmapProcState.h +++ b/src/core/SkBitmapProcState.h @@ -89,12 +89,7 @@ struct SkBitmapProcState { uint8_t fInvType; // chooseProcs uint8_t fTileModeX; // CONSTRUCTOR uint8_t fTileModeY; // CONSTRUCTOR - - enum { - kNone_BitmapFilter, - kBilerp_BitmapFilter, - kHQ_BitmapFilter - } fFilterQuality; // chooseProcs + uint8_t fFilterLevel; // chooseProcs /** The shader will let us know when we can release some of our resources * like scaled bitmaps. diff --git a/src/core/SkBitmapProcState_matrixProcs.cpp b/src/core/SkBitmapProcState_matrixProcs.cpp index d3cd5504fb..a3d2b08665 100644 --- a/src/core/SkBitmapProcState_matrixProcs.cpp +++ b/src/core/SkBitmapProcState_matrixProcs.cpp @@ -472,7 +472,7 @@ SkBitmapProcState::chooseMatrixProc(bool trivial_matrix) { // test_int_tileprocs(); // check for our special case when there is no scale/affine/perspective if (trivial_matrix) { - SkASSERT(kNone_BitmapFilter == fFilterQuality); + SkASSERT(SkPaint::kNone_FilterLevel == fFilterLevel); fIntTileProcY = choose_int_tile_proc(fTileModeY); switch (fTileModeX) { case SkShader::kClamp_TileMode: @@ -485,7 +485,7 @@ SkBitmapProcState::chooseMatrixProc(bool trivial_matrix) { } int index = 0; - if (fFilterQuality != kNone_BitmapFilter) { + if (fFilterLevel != SkPaint::kNone_FilterLevel) { index = 1; } if (fInvType & SkMatrix::kPerspective_Mask) { diff --git a/src/core/SkBitmapProcState_sample.h b/src/core/SkBitmapProcState_sample.h index ac14b96278..5c5f199f25 100644 --- a/src/core/SkBitmapProcState_sample.h +++ b/src/core/SkBitmapProcState_sample.h @@ -42,7 +42,7 @@ void MAKENAME(_nofilter_DXDY)(const SkBitmapProcState& s, const uint32_t* SK_RESTRICT xy, int count, DSTTYPE* SK_RESTRICT colors) { SkASSERT(count > 0 && colors != NULL); - SkASSERT(SkBitmapProcState::kNone_BitmapFilter == s.fFilterQuality); + SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel); SkDEBUGCODE(CHECKSTATE(s);) #ifdef PREAMBLE @@ -85,7 +85,7 @@ void MAKENAME(_nofilter_DX)(const SkBitmapProcState& s, int count, DSTTYPE* SK_RESTRICT colors) { SkASSERT(count > 0 && colors != NULL); SkASSERT(s.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)); - SkASSERT(SkBitmapProcState::kNone_BitmapFilter == s.fFilterQuality); + SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel); SkDEBUGCODE(CHECKSTATE(s);) #ifdef PREAMBLE @@ -139,7 +139,7 @@ void MAKENAME(_filter_DX)(const SkBitmapProcState& s, const uint32_t* SK_RESTRICT xy, int count, DSTTYPE* SK_RESTRICT colors) { SkASSERT(count > 0 && colors != NULL); - SkASSERT(s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter); + SkASSERT(s.fFilterLevel != SkPaint::kNone_FilterLevel); SkDEBUGCODE(CHECKSTATE(s);) #ifdef PREAMBLE @@ -185,7 +185,7 @@ void MAKENAME(_filter_DXDY)(const SkBitmapProcState& s, const uint32_t* SK_RESTRICT xy, int count, DSTTYPE* SK_RESTRICT colors) { SkASSERT(count > 0 && colors != NULL); - SkASSERT(s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter); + SkASSERT(s.fFilterLevel != SkPaint::kNone_FilterLevel); SkDEBUGCODE(CHECKSTATE(s);) #ifdef PREAMBLE diff --git a/src/core/SkBitmapProcState_shaderproc.h b/src/core/SkBitmapProcState_shaderproc.h index d765b8e92d..0014b4a526 100644 --- a/src/core/SkBitmapProcState_shaderproc.h +++ b/src/core/SkBitmapProcState_shaderproc.h @@ -21,7 +21,7 @@ void SCALE_FILTER_NAME(const SkBitmapProcState& s, int x, int y, SkMatrix::kScale_Mask)) == 0); SkASSERT(s.fInvKy == 0); SkASSERT(count > 0 && colors != NULL); - SkASSERT(s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter); + SkASSERT(s.fFilterLevel != SkPaint::kNone_FilterLevel); SkDEBUGCODE(CHECKSTATE(s);) const unsigned maxX = s.fBitmap->width() - 1; |